@@ -52,6 +52,12 @@ type KeyspaceMetadata struct {
52
52
UserTypes map [string ]* UserTypeMetadata
53
53
}
54
54
55
+ // schema metadata for a virtual keyspace
56
+ type VirtualKeyspaceMetadata struct {
57
+ Name string
58
+ Tables map [string ]* VirtualTableMetadata
59
+ }
60
+
55
61
// schema metadata for a table (a.k.a. column family)
56
62
type TableMetadata struct {
57
63
Keyspace string
@@ -68,6 +74,13 @@ type TableMetadata struct {
68
74
OrderedColumns []string
69
75
}
70
76
77
+ type VirtualTableMetadata struct {
78
+ Keyspace string
79
+ Name string
80
+ Comment string
81
+ Columns map [string ]* VirtualColumnMetadata
82
+ }
83
+
71
84
// schema metadata for a column
72
85
type ColumnMetadata struct {
73
86
Keyspace string
@@ -82,6 +95,15 @@ type ColumnMetadata struct {
82
95
Index ColumnIndexMetadata
83
96
}
84
97
98
+ type VirtualColumnMetadata struct {
99
+ Keyspace string
100
+ Table string
101
+ Name string
102
+ ClusteringOrder string
103
+ Kind ColumnKind
104
+ Type TypeInfo
105
+ }
106
+
85
107
// FunctionMetadata holds metadata for function constructs
86
108
type FunctionMetadata struct {
87
109
Keyspace string
@@ -240,6 +262,13 @@ type schemaDescriber struct {
240
262
cache map [string ]* KeyspaceMetadata
241
263
}
242
264
265
+ // queries the cluster for schema information for a virtual keyspace
266
+ type virtualSchemaDescriber struct {
267
+ session * Session
268
+ mu sync.Mutex
269
+ cache map [string ]* VirtualKeyspaceMetadata
270
+ }
271
+
243
272
// creates a session bound schema describer which will query and cache
244
273
// keyspace metadata
245
274
func newSchemaDescriber (session * Session ) * schemaDescriber {
@@ -249,6 +278,15 @@ func newSchemaDescriber(session *Session) *schemaDescriber {
249
278
}
250
279
}
251
280
281
+ // creates a session bound schema describer which will query and cache
282
+ // virtual keyspace metadata
283
+ func newVirtualSchemaDescriber (session * Session ) * virtualSchemaDescriber {
284
+ return & virtualSchemaDescriber {
285
+ session : session ,
286
+ cache : map [string ]* VirtualKeyspaceMetadata {},
287
+ }
288
+ }
289
+
252
290
// returns the cached KeyspaceMetadata held by the describer for the named
253
291
// keyspace.
254
292
func (s * schemaDescriber ) getSchema (keyspaceName string ) (* KeyspaceMetadata , error ) {
@@ -269,6 +307,23 @@ func (s *schemaDescriber) getSchema(keyspaceName string) (*KeyspaceMetadata, err
269
307
return metadata , nil
270
308
}
271
309
310
+ // returns the cached VirtualKeyspaceMetadata held by the describer for the named
311
+ // keyspace.
312
+ func (s * virtualSchemaDescriber ) getSchema (keyspaceName string ) (* VirtualKeyspaceMetadata , error ) {
313
+ s .mu .Lock ()
314
+ defer s .mu .Unlock ()
315
+ metadata , found := s .cache [keyspaceName ]
316
+ if ! found {
317
+ err := s .refreshSchema (keyspaceName )
318
+ if err != nil {
319
+ return nil , err
320
+ }
321
+ metadata = s .cache [keyspaceName ]
322
+ }
323
+
324
+ return metadata , nil
325
+ }
326
+
272
327
// clears the already cached keyspace metadata
273
328
func (s * schemaDescriber ) clearSchema (keyspaceName string ) {
274
329
s .mu .Lock ()
@@ -323,6 +378,42 @@ func (s *schemaDescriber) refreshSchema(keyspaceName string) error {
323
378
return nil
324
379
}
325
380
381
+ // forcibly updates the current VirtualKeyspaceMetadata held by the virtual schema describer
382
+ // for a given named keyspace.
383
+ func (s * virtualSchemaDescriber ) refreshSchema (keyspaceName string ) error {
384
+ var wg sync.WaitGroup
385
+ var tables []VirtualTableMetadata
386
+ var columns []VirtualColumnMetadata
387
+ var err error
388
+
389
+ wg .Add (2 )
390
+ go func () {
391
+ defer wg .Done ()
392
+ tables , err = getVirtualTableMetadata (s .session , keyspaceName )
393
+ if err != nil {
394
+ return
395
+ }
396
+ }()
397
+ go func () {
398
+ defer wg .Done ()
399
+ columns , err = getVirtualColumnMetadata (s .session , keyspaceName )
400
+ if err != nil {
401
+ return
402
+ }
403
+ }()
404
+ wg .Wait ()
405
+ if err != nil {
406
+ return err
407
+ }
408
+
409
+ keyspaceMetadata := & VirtualKeyspaceMetadata {Name : keyspaceName }
410
+ compileVirtualMetadata (keyspaceMetadata , tables , columns )
411
+
412
+ s .cache [keyspaceName ] = keyspaceMetadata
413
+
414
+ return nil
415
+ }
416
+
326
417
// "compiles" derived information about keyspace, table, and column metadata
327
418
// for a keyspace from the basic queried metadata objects returned by
328
419
// getKeyspaceMetadata, getTableMetadata, and getColumnMetadata respectively;
@@ -417,6 +508,33 @@ func compileMetadata(
417
508
}
418
509
}
419
510
511
+ // "compiles" derived information about virtual keyspace, table, and column metadata
512
+ // for a keyspace from the basic queried metadata objects returned by
513
+ // getVirtualTableMetadata, and getVirtualColumnMetadata respectively;
514
+ // Links the metadata objects together.
515
+ func compileVirtualMetadata (
516
+ keyspace * VirtualKeyspaceMetadata ,
517
+ tables []VirtualTableMetadata ,
518
+ columns []VirtualColumnMetadata ,
519
+ ) {
520
+ keyspace .Tables = make (map [string ]* VirtualTableMetadata )
521
+ for i := range tables {
522
+ tables [i ].Columns = make (map [string ]* VirtualColumnMetadata )
523
+
524
+ keyspace .Tables [tables [i ].Name ] = & tables [i ]
525
+ }
526
+
527
+ for i := range columns {
528
+ col := & columns [i ]
529
+ table , ok := keyspace .Tables [col .Table ]
530
+ if ! ok {
531
+ continue
532
+ }
533
+
534
+ table .Columns [col .Name ] = col
535
+ }
536
+ }
537
+
420
538
// Compiles derived information from TableMetadata which have had
421
539
// ColumnMetadata added already. V1 protocol does not return as much
422
540
// column metadata as V2+ (because V1 doesn't support the "type" column in the
@@ -760,6 +878,28 @@ func getTableMetadata(session *Session, keyspaceName string) ([]TableMetadata, e
760
878
return tables , nil
761
879
}
762
880
881
+ // query for only the table metadata in the specified keyspace from system_virtual_schema.tables
882
+ func getVirtualTableMetadata (s * Session , keyspaceName string ) ([]VirtualTableMetadata , error ) {
883
+ const stmt = `
884
+ SELECT
885
+ table_name,
886
+ comment
887
+ FROM system_virtual_schema.tables
888
+ WHERE keyspace_name = ?`
889
+
890
+ tables := []VirtualTableMetadata {}
891
+ table := VirtualTableMetadata {Keyspace : keyspaceName }
892
+
893
+ iter := s .control .query (stmt , keyspaceName )
894
+
895
+ for iter .Scan (& table .Name , & table .Comment ) {
896
+ tables = append (tables , table )
897
+ table = VirtualTableMetadata {Keyspace : keyspaceName }
898
+ }
899
+
900
+ return tables , nil
901
+ }
902
+
763
903
func (s * Session ) scanColumnMetadataV1 (keyspace string ) ([]ColumnMetadata , error ) {
764
904
// V1 does not support the type column, and all returned rows are
765
905
// of kind "regular".
@@ -947,6 +1087,47 @@ func getColumnMetadata(session *Session, keyspaceName string) ([]ColumnMetadata,
947
1087
return columns , nil
948
1088
}
949
1089
1090
+ // query for only the column metadata in the specified keyspace from system_virtual_schema.columns
1091
+ func getVirtualColumnMetadata (s * Session , keyspaceName string ) ([]VirtualColumnMetadata , error ) {
1092
+ const stmt = `
1093
+ SELECT
1094
+ table_name,
1095
+ column_name,
1096
+ clustering_order,
1097
+ kind,
1098
+ type
1099
+ FROM system_virtual_schema.columns
1100
+ WHERE keyspace_name = ?`
1101
+
1102
+ var columns []VirtualColumnMetadata
1103
+
1104
+ rows := s .control .query (stmt , keyspaceName ).Scanner ()
1105
+ for rows .Next () {
1106
+ var (
1107
+ column = VirtualColumnMetadata {Keyspace : keyspaceName }
1108
+ columnType string
1109
+ )
1110
+
1111
+ err := rows .Scan (
1112
+ & column .Table ,
1113
+ & column .Name ,
1114
+ & column .ClusteringOrder ,
1115
+ & column .Kind ,
1116
+ & columnType ,
1117
+ )
1118
+
1119
+ if err != nil {
1120
+ return nil , err
1121
+ }
1122
+
1123
+ column .Type = getCassandraType (columnType , s .logger )
1124
+
1125
+ columns = append (columns , column )
1126
+ }
1127
+
1128
+ return columns , nil
1129
+ }
1130
+
950
1131
func getTypeInfo (t string , logger StdLogger ) TypeInfo {
951
1132
if strings .HasPrefix (t , apacheCassandraTypePrefix ) {
952
1133
t = apacheToCassandraType (t )
0 commit comments