Bladeren bron

add metadata for views (#1225)

Jaume Marhuenda 6 jaren geleden
bovenliggende
commit
2a689301c5
5 gewijzigde bestanden met toevoegingen van 124 en 5 verwijderingen
  1. 45 0
      cassandra_test.go
  2. 11 0
      common_test.go
  3. 2 2
      conn_test.go
  4. 64 1
      metadata.go
  5. 2 2
      metadata_test.go

+ 45 - 0
cassandra_test.go

@@ -2149,6 +2149,45 @@ func TestGetColumnMetadata(t *testing.T) {
 	}
 }
 
+func TestViewMetadata(t *testing.T) {
+	session := createSession(t)
+	defer session.Close()
+	createViews(t, session)
+
+	views, err := getViewsMetadata(session, "gocql_test")
+	if err != nil {
+		t.Fatalf("failed to query view metadata with err: %v", err)
+	}
+	if views == nil {
+		t.Fatal("failed to query view metadata, nil returned")
+	}
+
+	if len(views) != 1 {
+		t.Fatal("expected one view")
+	}
+
+	textType := TypeText
+	if flagCassVersion.Before(3, 0, 0) {
+		textType = TypeVarchar
+	}
+
+	expectedView := ViewMetadata{
+		Keyspace:   "gocql_test",
+		Name:       "basicview",
+		FieldNames: []string{"birthday", "nationality", "weight", "height"},
+		FieldTypes: []TypeInfo{
+			NativeType{typ: TypeTimestamp},
+			NativeType{typ: textType},
+			NativeType{typ: textType},
+			NativeType{typ: textType},
+		},
+	}
+
+	if !reflect.DeepEqual(views[0], expectedView) {
+		t.Fatalf("view is %+v, but expected %+v", views[0], expectedView)
+	}
+}
+
 func TestAggregateMetadata(t *testing.T) {
 	session := createSession(t)
 	defer session.Close()
@@ -2278,6 +2317,7 @@ func TestKeyspaceMetadata(t *testing.T) {
 		t.Fatalf("failed to create table with error '%v'", err)
 	}
 	createAggregate(t, session)
+	createViews(t, session)
 
 	if err := session.Query("CREATE INDEX index_metadata ON test_metadata ( third_id )").Exec(); err != nil {
 		t.Fatalf("failed to create index with err: %v", err)
@@ -2343,6 +2383,11 @@ func TestKeyspaceMetadata(t *testing.T) {
 	if aggregate.StateFunc.Name != "avgstate" {
 		t.Fatalf("expected state function %s, but got %s", "avgstate", aggregate.StateFunc.Name)
 	}
+
+	_, found = keyspaceMetadata.Views["basicview"]
+	if !found {
+		t.Fatal("failed to find the view in metadata")
+	}
 }
 
 // Integration test of the routing key calculation

+ 11 - 0
common_test.go

@@ -170,6 +170,17 @@ func createTestSession() *Session {
 	return session
 }
 
+func createViews(t *testing.T, session *Session) {
+	if err := session.Query(`
+		CREATE TYPE IF NOT EXISTS gocql_test.basicView (
+		birthday timestamp,
+		nationality text,
+		weight text,
+		height text);	`).Exec(); err != nil {
+		t.Fatalf("failed to create view with err: %v", err)
+	}
+}
+
 func createFunctions(t *testing.T, session *Session) {
 	if err := session.Query(`
 		CREATE OR REPLACE FUNCTION gocql_test.avgState ( state tuple<int,bigint>, val int )

+ 2 - 2
conn_test.go

@@ -46,8 +46,8 @@ func TestApprove(t *testing.T) {
 
 func TestJoinHostPort(t *testing.T) {
 	tests := map[string]string{
-		"127.0.0.1:0": JoinHostPort("127.0.0.1", 0),
-		"127.0.0.1:1": JoinHostPort("127.0.0.1:1", 9142),
+		"127.0.0.1:0":                                 JoinHostPort("127.0.0.1", 0),
+		"127.0.0.1:1":                                 JoinHostPort("127.0.0.1:1", 9142),
 		"[2001:0db8:85a3:0000:0000:8a2e:0370:7334]:0": JoinHostPort("2001:0db8:85a3:0000:0000:8a2e:0370:7334", 0),
 		"[2001:0db8:85a3:0000:0000:8a2e:0370:7334]:1": JoinHostPort("[2001:0db8:85a3:0000:0000:8a2e:0370:7334]:1", 9142),
 	}

+ 64 - 1
metadata.go

@@ -22,6 +22,7 @@ type KeyspaceMetadata struct {
 	Tables          map[string]*TableMetadata
 	Functions       map[string]*FunctionMetadata
 	Aggregates      map[string]*AggregateMetadata
+	Views           map[string]*ViewMetadata
 }
 
 // schema metadata for a table (a.k.a. column family)
@@ -81,6 +82,14 @@ type AggregateMetadata struct {
 	finalFunc string
 }
 
+// ViewMetadata holds the metadata for views.
+type ViewMetadata struct {
+	Keyspace   string
+	Name       string
+	FieldNames []string
+	FieldTypes []TypeInfo
+}
+
 // the ordering of the column with regard to its comparator
 type ColumnOrder bool
 
@@ -233,9 +242,13 @@ func (s *schemaDescriber) refreshSchema(keyspaceName string) error {
 	if err != nil {
 		return err
 	}
+	views, err := getViewsMetadata(s.session, keyspaceName)
+	if err != nil {
+		return err
+	}
 
 	// organize the schema data
-	compileMetadata(s.session.cfg.ProtoVersion, keyspace, tables, columns, functions, aggregates)
+	compileMetadata(s.session.cfg.ProtoVersion, keyspace, tables, columns, functions, aggregates, views)
 
 	// update the cache
 	s.cache[keyspaceName] = keyspace
@@ -255,6 +268,7 @@ func compileMetadata(
 	columns []ColumnMetadata,
 	functions []FunctionMetadata,
 	aggregates []AggregateMetadata,
+	views []ViewMetadata,
 ) {
 	keyspace.Tables = make(map[string]*TableMetadata)
 	for i := range tables {
@@ -272,6 +286,10 @@ func compileMetadata(
 		aggregate.StateFunc = *keyspace.Functions[aggregate.stateFunc]
 		keyspace.Aggregates[aggregate.Name] = &aggregate
 	}
+	keyspace.Views = make(map[string]*ViewMetadata, len(views))
+	for i := range views {
+		keyspace.Views[views[i].Name] = &views[i]
+	}
 
 	// add columns from the schema data
 	for i := range columns {
@@ -849,6 +867,51 @@ func getTypeInfo(t string) TypeInfo {
 	return getCassandraType(t)
 }
 
+func getViewsMetadata(session *Session, keyspaceName string) ([]ViewMetadata, error) {
+	if session.cfg.ProtoVersion == protoVersion1 {
+		return nil, nil
+	}
+	var tableName string
+	if session.useSystemSchema {
+		tableName = "system_schema.types"
+	} else {
+		tableName = "system.schema_usertypes"
+	}
+	stmt := fmt.Sprintf(`
+		SELECT
+			type_name,
+			field_names,
+			field_types
+		FROM %s
+		WHERE keyspace_name = ?`, tableName)
+
+	var views []ViewMetadata
+
+	rows := session.control.query(stmt, keyspaceName).Scanner()
+	for rows.Next() {
+		view := ViewMetadata{Keyspace: keyspaceName}
+		var argumentTypes []string
+		err := rows.Scan(&view.Name,
+			&view.FieldNames,
+			&argumentTypes,
+		)
+		if err != nil {
+			return nil, err
+		}
+		view.FieldTypes = make([]TypeInfo, len(argumentTypes))
+		for i, argumentType := range argumentTypes {
+			view.FieldTypes[i] = getTypeInfo(argumentType)
+		}
+		views = append(views, view)
+	}
+
+	if err := rows.Err(); err != nil {
+		return nil, err
+	}
+
+	return views, nil
+}
+
 func getFunctionsMetadata(session *Session, keyspaceName string) ([]FunctionMetadata, error) {
 	if session.cfg.ProtoVersion == protoVersion1 {
 		return nil, nil

+ 2 - 2
metadata_test.go

@@ -94,7 +94,7 @@ func TestCompileMetadata(t *testing.T) {
 		{Keyspace: "V1Keyspace", Table: "peers", Kind: ColumnRegular, Name: "schema_version", ComponentIndex: 0, Validator: "org.apache.cassandra.db.marshal.UUIDType"},
 		{Keyspace: "V1Keyspace", Table: "peers", Kind: ColumnRegular, Name: "tokens", ComponentIndex: 0, Validator: "org.apache.cassandra.db.marshal.SetType(org.apache.cassandra.db.marshal.UTF8Type)"},
 	}
-	compileMetadata(1, keyspace, tables, columns, nil, nil)
+	compileMetadata(1, keyspace, tables, columns, nil, nil, nil)
 	assertKeyspaceMetadata(
 		t,
 		keyspace,
@@ -375,7 +375,7 @@ func TestCompileMetadata(t *testing.T) {
 			Validator: "org.apache.cassandra.db.marshal.UTF8Type",
 		},
 	}
-	compileMetadata(2, keyspace, tables, columns, nil, nil)
+	compileMetadata(2, keyspace, tables, columns, nil, nil, nil)
 	assertKeyspaceMetadata(
 		t,
 		keyspace,