@@ -32,6 +32,8 @@ pub struct CassTableMeta {
32
32
pub columns_metadata : HashMap < String , CassColumnMeta > ,
33
33
pub partition_keys : Vec < String > ,
34
34
pub clustering_keys : Vec < String > ,
35
+ /// Non-key columns sorted alphabetically by name.
36
+ pub non_key_sorted_columns : Vec < String > ,
35
37
pub views : HashMap < String , Arc < CassMaterializedViewMeta > > ,
36
38
}
37
39
@@ -81,11 +83,25 @@ pub fn create_table_metadata(table_name: &str, table_metadata: &Table) -> CassTa
81
83
columns_metadata. insert ( column_name. clone ( ) , cass_column_meta) ;
82
84
} ) ;
83
85
86
+ let mut non_key_sorted_columns = columns_metadata
87
+ . iter ( )
88
+ . filter ( |( _, column) | {
89
+ !matches ! (
90
+ column. column_kind,
91
+ CassColumnType :: CASS_COLUMN_TYPE_PARTITION_KEY
92
+ | CassColumnType :: CASS_COLUMN_TYPE_CLUSTERING_KEY ,
93
+ )
94
+ } )
95
+ . map ( |( name, _column) | name. to_owned ( ) )
96
+ . collect :: < Vec < _ > > ( ) ;
97
+ non_key_sorted_columns. sort_unstable ( ) ;
98
+
84
99
CassTableMeta {
85
100
name : table_name. to_owned ( ) ,
86
101
columns_metadata,
87
102
partition_keys : table_metadata. partition_key . clone ( ) ,
88
103
clustering_keys : table_metadata. clustering_key . clone ( ) ,
104
+ non_key_sorted_columns,
89
105
views : HashMap :: new ( ) ,
90
106
}
91
107
}
@@ -209,6 +225,59 @@ pub unsafe extern "C" fn cass_table_meta_column_count(table_meta: *const CassTab
209
225
table_meta. columns_metadata . len ( ) as size_t
210
226
}
211
227
228
+ #[ no_mangle]
229
+ pub unsafe extern "C" fn cass_table_meta_column (
230
+ table_meta : * const CassTableMeta ,
231
+ index : size_t ,
232
+ ) -> * const CassColumnMeta {
233
+ // The order of columns in cpp-driver (and in DESCRIBE TABLE in cqlsh):
234
+ // 1. partition keys sorted by position <- this is guaranteed by rust-driver.
235
+ // Table::partition_keys is a Vector of pk names, sorted by position.
236
+ // 2. clustering keys sorted by position <- this is guaranteed by rust-driver (same reasoning as above).
237
+ // 3. remaining columns in alphabetical order <- this is something we need to guarantee.
238
+ //
239
+ // Example:
240
+ // CREATE TABLE t
241
+ // (
242
+ // i int, f int, g int STATIC, b int, c int STATIC, a int, d int, j int, h int,
243
+ // PRIMARY KEY( (d, a, j), h, i )
244
+ // );
245
+ //
246
+ // The order should be: d, a, j, h, i, b, c, f, g
247
+ // First pks by position: d, a, j
248
+ // Then cks by position: h, i
249
+ // Then remaining columns alphabetically: b, c, f, g
250
+
251
+ let table_meta = RefFFI :: as_ref ( table_meta) ;
252
+ let index = index as usize ;
253
+
254
+ // Check if the index lands in partition keys. If so, simply return the corresponding column.
255
+ if let Some ( pk_name) = table_meta. partition_keys . get ( index) {
256
+ // unwrap: partition key must exist in columns_metadata. This is ensured by rust-driver.
257
+ return RefFFI :: as_ptr ( table_meta. columns_metadata . get ( pk_name) . unwrap ( ) ) ;
258
+ }
259
+
260
+ // Update the index to search in clustering keys
261
+ let index = index - table_meta. partition_keys . len ( ) ;
262
+
263
+ // Check if the index lands in clustering keys. If so, simply return the corresponding column.
264
+ if let Some ( ck_name) = table_meta. clustering_keys . get ( index) {
265
+ // unwrap: clustering key must exist in columns_metadata. This is ensured by rust-driver.
266
+ return RefFFI :: as_ptr ( table_meta. columns_metadata . get ( ck_name) . unwrap ( ) ) ;
267
+ }
268
+
269
+ // Update the index to search in remaining columns
270
+ let index = index - table_meta. clustering_keys . len ( ) ;
271
+
272
+ table_meta
273
+ . non_key_sorted_columns
274
+ . get ( index)
275
+ . map_or ( std:: ptr:: null ( ) , |column_name| {
276
+ // unwrap: We guarantee that column_name exists in columns_metadata. See `create_table_metadata`.
277
+ RefFFI :: as_ptr ( table_meta. columns_metadata . get ( column_name) . unwrap ( ) )
278
+ } )
279
+ }
280
+
212
281
#[ no_mangle]
213
282
pub unsafe extern "C" fn cass_table_meta_partition_key (
214
283
table_meta : * const CassTableMeta ,
0 commit comments