diff --git a/cassandra_test.go b/cassandra_test.go index a9a5e0463..e53df1d05 100644 --- a/cassandra_test.go +++ b/cassandra_test.go @@ -1752,10 +1752,10 @@ func TestGetColumnMetadata(t *testing.T) { if column.Keyspace != "gocql_test" { t.Errorf("Expected column %s keyspace name to be 'gocql_test', but it was '%s'", column.Name, column.Keyspace) } - if column.Kind == "" { + if column.Kind == ColumnUnkownKind { t.Errorf("Expected column %s kind to be set, but it was empty", column.Name) } - if session.cfg.ProtoVersion == 1 && column.Kind != "regular" { + if session.cfg.ProtoVersion == 1 && column.Kind != ColumnRegular { t.Errorf("Expected column %s kind to be set to 'regular' for proto V1 but it was '%s'", column.Name, column.Kind) } if column.Validator == "" { @@ -1778,8 +1778,8 @@ func TestGetColumnMetadata(t *testing.T) { t.Fatalf("Expected to find column 'third_id' metadata but there was only %v", testColumns) } - if thirdID.Kind != REGULAR { - t.Errorf("Expected %s column kind to be '%s' but it was '%s'", thirdID.Name, REGULAR, thirdID.Kind) + if thirdID.Kind != ColumnRegular { + t.Errorf("Expected %s column kind to be '%s' but it was '%s'", thirdID.Name, ColumnRegular, thirdID.Kind) } if thirdID.Index.Name != "index_column_metadata" { @@ -1802,14 +1802,14 @@ func TestGetColumnMetadata(t *testing.T) { t.Fatalf("Expected to find column 'third_id' metadata but there was only %v", testColumns) } - if firstID.Kind != PARTITION_KEY { - t.Errorf("Expected %s column kind to be '%s' but it was '%s'", firstID.Name, PARTITION_KEY, firstID.Kind) + if firstID.Kind != ColumnPartitionKey { + t.Errorf("Expected %s column kind to be '%s' but it was '%s'", firstID.Name, ColumnPartitionKey, firstID.Kind) } - if secondID.Kind != CLUSTERING_KEY { - t.Errorf("Expected %s column kind to be '%s' but it was '%s'", secondID.Name, CLUSTERING_KEY, secondID.Kind) + if secondID.Kind != ColumnClusteringKey { + t.Errorf("Expected %s column kind to be '%s' but it was '%s'", secondID.Name, ColumnClusteringKey, secondID.Kind) } - if thirdID.Kind != REGULAR { - t.Errorf("Expected %s column kind to be '%s' but it was '%s'", thirdID.Name, REGULAR, thirdID.Kind) + if thirdID.Kind != ColumnRegular { + t.Errorf("Expected %s column kind to be '%s' but it was '%s'", thirdID.Name, ColumnRegular, thirdID.Kind) } if thirdID.Index.Name != "index_column_metadata" { diff --git a/metadata.go b/metadata.go index 1c85881c2..345c391bb 100644 --- a/metadata.go +++ b/metadata.go @@ -45,7 +45,7 @@ type ColumnMetadata struct { Table string Name string ComponentIndex int - Kind string + Kind ColumnKind Validator string Type TypeInfo ClusteringOrder string @@ -67,14 +67,60 @@ type ColumnIndexMetadata struct { Options map[string]interface{} } -// Column kind values +type ColumnKind int + const ( - PARTITION_KEY = "partition_key" - CLUSTERING_KEY = "clustering_key" - REGULAR = "regular" - COMPACT_VALUE = "compact_value" + ColumnUnkownKind ColumnKind = iota + ColumnPartitionKey + ColumnClusteringKey + ColumnRegular + ColumnCompact ) +func (c ColumnKind) String() string { + switch c { + case ColumnPartitionKey: + return "partition_key" + case ColumnClusteringKey: + return "clustering_key" + case ColumnRegular: + return "regular" + case ColumnCompact: + return "compact" + default: + return fmt.Sprintf("unkown_column_%d", c) + } +} + +func (c *ColumnKind) UnmarshalCQL(typ TypeInfo, p []byte) error { + if typ.Type() != TypeVarchar { + return unmarshalErrorf("unable to marshall %s into ColumnKind, expected Varchar", typ) + } + + kind, err := columnKindFromSchema(string(p)) + if err != nil { + return err + } + *c = kind + + return nil +} + +func columnKindFromSchema(kind string) (ColumnKind, error) { + switch kind { + case "partition_key": + return ColumnPartitionKey, nil + case "clustering_key", "clustering": + return ColumnClusteringKey, nil + case "regular": + return ColumnRegular, nil + case "compact_value": + return ColumnCompact, nil + default: + return -1, fmt.Errorf("unknown column kind: %q", kind) + } +} + // default alias values const ( DEFAULT_KEY_ALIAS = "key" @@ -243,7 +289,7 @@ func compileV1Metadata(tables []TableMetadata) { Table: table.Name, Name: alias, Type: keyValidatorParsed.types[i], - Kind: PARTITION_KEY, + Kind: ColumnPartitionKey, ComponentIndex: i, } @@ -288,7 +334,7 @@ func compileV1Metadata(tables []TableMetadata) { Name: alias, Type: comparatorParsed.types[i], Order: order, - Kind: CLUSTERING_KEY, + Kind: ColumnClusteringKey, ComponentIndex: i, } @@ -308,7 +354,7 @@ func compileV1Metadata(tables []TableMetadata) { Table: table.Name, Name: alias, Type: defaultValidatorParsed.types[0], - Kind: REGULAR, + Kind: ColumnRegular, } table.Columns[alias] = column } @@ -320,22 +366,22 @@ func compileV2Metadata(tables []TableMetadata) { for i := range tables { table := &tables[i] - clusteringColumnCount := componentColumnCountOfType(table.Columns, CLUSTERING_KEY) + clusteringColumnCount := componentColumnCountOfType(table.Columns, ColumnClusteringKey) table.ClusteringColumns = make([]*ColumnMetadata, clusteringColumnCount) if table.KeyValidator != "" { keyValidatorParsed := parseType(table.KeyValidator) table.PartitionKey = make([]*ColumnMetadata, len(keyValidatorParsed.types)) } else { // Cassandra 3.x+ - partitionKeyCount := componentColumnCountOfType(table.Columns, PARTITION_KEY) + partitionKeyCount := componentColumnCountOfType(table.Columns, ColumnPartitionKey) table.PartitionKey = make([]*ColumnMetadata, partitionKeyCount) } for _, columnName := range table.OrderedColumns { column := table.Columns[columnName] - if column.Kind == PARTITION_KEY { + if column.Kind == ColumnPartitionKey { table.PartitionKey[column.ComponentIndex] = column - } else if column.Kind == CLUSTERING_KEY { + } else if column.Kind == ColumnClusteringKey { table.ClusteringColumns[column.ComponentIndex] = column } } @@ -343,7 +389,7 @@ func compileV2Metadata(tables []TableMetadata) { } // returns the count of coluns with the given "kind" value. -func componentColumnCountOfType(columns map[string]*ColumnMetadata, kind string) int { +func componentColumnCountOfType(columns map[string]*ColumnMetadata, kind ColumnKind) int { maxComponentIndex := -1 for _, column := range columns { if column.Kind == kind && column.ComponentIndex > maxComponentIndex { @@ -570,7 +616,7 @@ func getColumnMetadata( indexOptionsJSON *[]byte, ) bool { // all columns returned by V1 are regular - column.Kind = REGULAR + column.Kind = ColumnRegular return iter.Scan( &column.Table, &column.Name, diff --git a/metadata_test.go b/metadata_test.go index 9e48401f0..cc4631acc 100644 --- a/metadata_test.go +++ b/metadata_test.go @@ -86,13 +86,13 @@ func TestCompileMetadata(t *testing.T) { } columns := []ColumnMetadata{ // Here are the regular columns from the peers table for testing regular columns - {Keyspace: "V1Keyspace", Table: "peers", Kind: REGULAR, Name: "data_center", ComponentIndex: 0, Validator: "org.apache.cassandra.db.marshal.UTF8Type"}, - {Keyspace: "V1Keyspace", Table: "peers", Kind: REGULAR, Name: "host_id", ComponentIndex: 0, Validator: "org.apache.cassandra.db.marshal.UUIDType"}, - {Keyspace: "V1Keyspace", Table: "peers", Kind: REGULAR, Name: "rack", ComponentIndex: 0, Validator: "org.apache.cassandra.db.marshal.UTF8Type"}, - {Keyspace: "V1Keyspace", Table: "peers", Kind: REGULAR, Name: "release_version", ComponentIndex: 0, Validator: "org.apache.cassandra.db.marshal.UTF8Type"}, - {Keyspace: "V1Keyspace", Table: "peers", Kind: REGULAR, Name: "rpc_address", ComponentIndex: 0, Validator: "org.apache.cassandra.db.marshal.InetAddressType"}, - {Keyspace: "V1Keyspace", Table: "peers", Kind: REGULAR, Name: "schema_version", ComponentIndex: 0, Validator: "org.apache.cassandra.db.marshal.UUIDType"}, - {Keyspace: "V1Keyspace", Table: "peers", Kind: REGULAR, Name: "tokens", ComponentIndex: 0, Validator: "org.apache.cassandra.db.marshal.SetType(org.apache.cassandra.db.marshal.UTF8Type)"}, + {Keyspace: "V1Keyspace", Table: "peers", Kind: ColumnRegular, Name: "data_center", ComponentIndex: 0, Validator: "org.apache.cassandra.db.marshal.UTF8Type"}, + {Keyspace: "V1Keyspace", Table: "peers", Kind: ColumnRegular, Name: "host_id", ComponentIndex: 0, Validator: "org.apache.cassandra.db.marshal.UUIDType"}, + {Keyspace: "V1Keyspace", Table: "peers", Kind: ColumnRegular, Name: "rack", ComponentIndex: 0, Validator: "org.apache.cassandra.db.marshal.UTF8Type"}, + {Keyspace: "V1Keyspace", Table: "peers", Kind: ColumnRegular, Name: "release_version", ComponentIndex: 0, Validator: "org.apache.cassandra.db.marshal.UTF8Type"}, + {Keyspace: "V1Keyspace", Table: "peers", Kind: ColumnRegular, Name: "rpc_address", ComponentIndex: 0, Validator: "org.apache.cassandra.db.marshal.InetAddressType"}, + {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) assertKeyspaceMetadata( @@ -113,7 +113,7 @@ func TestCompileMetadata(t *testing.T) { "key": { Name: "key", Type: NativeType{typ: TypeBlob}, - Kind: PARTITION_KEY, + Kind: ColumnPartitionKey, }, }, }, @@ -140,24 +140,24 @@ func TestCompileMetadata(t *testing.T) { "target_id": { Name: "target_id", Type: NativeType{typ: TypeUUID}, - Kind: PARTITION_KEY, + Kind: ColumnPartitionKey, }, "hint_id": { Name: "hint_id", Type: NativeType{typ: TypeTimeUUID}, Order: ASC, - Kind: CLUSTERING_KEY, + Kind: ColumnClusteringKey, }, "message_version": { Name: "message_version", Type: NativeType{typ: TypeInt}, Order: ASC, - Kind: CLUSTERING_KEY, + Kind: ColumnClusteringKey, }, "mutation": { Name: "mutation", Type: NativeType{typ: TypeBlob}, - Kind: REGULAR, + Kind: ColumnRegular, }, }, }, @@ -173,15 +173,15 @@ func TestCompileMetadata(t *testing.T) { "peer": { Name: "peer", Type: NativeType{typ: TypeInet}, - Kind: PARTITION_KEY, - }, - "data_center": {Keyspace: "V1Keyspace", Table: "peers", Kind: REGULAR, Name: "data_center", ComponentIndex: 0, Validator: "org.apache.cassandra.db.marshal.UTF8Type", Type: NativeType{typ: TypeVarchar}}, - "host_id": {Keyspace: "V1Keyspace", Table: "peers", Kind: REGULAR, Name: "host_id", ComponentIndex: 0, Validator: "org.apache.cassandra.db.marshal.UUIDType", Type: NativeType{typ: TypeUUID}}, - "rack": {Keyspace: "V1Keyspace", Table: "peers", Kind: REGULAR, Name: "rack", ComponentIndex: 0, Validator: "org.apache.cassandra.db.marshal.UTF8Type", Type: NativeType{typ: TypeVarchar}}, - "release_version": {Keyspace: "V1Keyspace", Table: "peers", Kind: REGULAR, Name: "release_version", ComponentIndex: 0, Validator: "org.apache.cassandra.db.marshal.UTF8Type", Type: NativeType{typ: TypeVarchar}}, - "rpc_address": {Keyspace: "V1Keyspace", Table: "peers", Kind: REGULAR, Name: "rpc_address", ComponentIndex: 0, Validator: "org.apache.cassandra.db.marshal.InetAddressType", Type: NativeType{typ: TypeInet}}, - "schema_version": {Keyspace: "V1Keyspace", Table: "peers", Kind: REGULAR, Name: "schema_version", ComponentIndex: 0, Validator: "org.apache.cassandra.db.marshal.UUIDType", Type: NativeType{typ: TypeUUID}}, - "tokens": {Keyspace: "V1Keyspace", Table: "peers", Kind: REGULAR, Name: "tokens", ComponentIndex: 0, Validator: "org.apache.cassandra.db.marshal.SetType(org.apache.cassandra.db.marshal.UTF8Type)", Type: CollectionType{NativeType: NativeType{typ: TypeSet}}}, + Kind: ColumnPartitionKey, + }, + "data_center": {Keyspace: "V1Keyspace", Table: "peers", Kind: ColumnRegular, Name: "data_center", ComponentIndex: 0, Validator: "org.apache.cassandra.db.marshal.UTF8Type", Type: NativeType{typ: TypeVarchar}}, + "host_id": {Keyspace: "V1Keyspace", Table: "peers", Kind: ColumnRegular, Name: "host_id", ComponentIndex: 0, Validator: "org.apache.cassandra.db.marshal.UUIDType", Type: NativeType{typ: TypeUUID}}, + "rack": {Keyspace: "V1Keyspace", Table: "peers", Kind: ColumnRegular, Name: "rack", ComponentIndex: 0, Validator: "org.apache.cassandra.db.marshal.UTF8Type", Type: NativeType{typ: TypeVarchar}}, + "release_version": {Keyspace: "V1Keyspace", Table: "peers", Kind: ColumnRegular, Name: "release_version", ComponentIndex: 0, Validator: "org.apache.cassandra.db.marshal.UTF8Type", Type: NativeType{typ: TypeVarchar}}, + "rpc_address": {Keyspace: "V1Keyspace", Table: "peers", Kind: ColumnRegular, Name: "rpc_address", ComponentIndex: 0, Validator: "org.apache.cassandra.db.marshal.InetAddressType", Type: NativeType{typ: TypeInet}}, + "schema_version": {Keyspace: "V1Keyspace", Table: "peers", Kind: ColumnRegular, Name: "schema_version", ComponentIndex: 0, Validator: "org.apache.cassandra.db.marshal.UUIDType", Type: NativeType{typ: TypeUUID}}, + "tokens": {Keyspace: "V1Keyspace", Table: "peers", Kind: ColumnRegular, Name: "tokens", ComponentIndex: 0, Validator: "org.apache.cassandra.db.marshal.SetType(org.apache.cassandra.db.marshal.UTF8Type)", Type: CollectionType{NativeType: NativeType{typ: TypeSet}}}, }, }, "IndexInfo": { @@ -202,18 +202,18 @@ func TestCompileMetadata(t *testing.T) { "table_name": { Name: "table_name", Type: NativeType{typ: TypeVarchar}, - Kind: PARTITION_KEY, + Kind: ColumnPartitionKey, }, "index_name": { Name: "index_name", Type: NativeType{typ: TypeVarchar}, Order: DESC, - Kind: CLUSTERING_KEY, + Kind: ColumnClusteringKey, }, "value": { Name: "value", Type: NativeType{typ: TypeBlob}, - Kind: REGULAR, + Kind: ColumnRegular, }, }, }, @@ -235,12 +235,12 @@ func TestCompileMetadata(t *testing.T) { "title": { Name: "title", Type: NativeType{typ: TypeVarchar}, - Kind: PARTITION_KEY, + Kind: ColumnPartitionKey, }, "revid": { Name: "revid", Type: NativeType{typ: TypeTimeUUID}, - Kind: CLUSTERING_KEY, + Kind: ColumnClusteringKey, }, }, }, @@ -276,35 +276,35 @@ func TestCompileMetadata(t *testing.T) { "key": { Name: "key", Type: NativeType{typ: TypeUUID}, - Kind: PARTITION_KEY, + Kind: ColumnPartitionKey, }, "key2": { Name: "key2", Type: NativeType{typ: TypeUUID}, - Kind: PARTITION_KEY, + Kind: ColumnPartitionKey, }, "column": { Name: "column", Type: NativeType{typ: TypeInt}, Order: ASC, - Kind: CLUSTERING_KEY, + Kind: ColumnClusteringKey, }, "column2": { Name: "column2", Type: NativeType{typ: TypeInt}, Order: ASC, - Kind: CLUSTERING_KEY, + Kind: ColumnClusteringKey, }, "column3": { Name: "column3", Type: NativeType{typ: TypeInt}, Order: ASC, - Kind: CLUSTERING_KEY, + Kind: ColumnClusteringKey, }, "value": { Name: "value", Type: NativeType{typ: TypeBlob}, - Kind: REGULAR, + Kind: ColumnRegular, }, }, }, @@ -331,7 +331,7 @@ func TestCompileMetadata(t *testing.T) { Keyspace: "V2Keyspace", Table: "Table1", Name: "KEY1", - Kind: PARTITION_KEY, + Kind: ColumnPartitionKey, ComponentIndex: 0, Validator: "org.apache.cassandra.db.marshal.UTF8Type", }, @@ -339,7 +339,7 @@ func TestCompileMetadata(t *testing.T) { Keyspace: "V2Keyspace", Table: "Table1", Name: "Key1", - Kind: PARTITION_KEY, + Kind: ColumnPartitionKey, ComponentIndex: 0, Validator: "org.apache.cassandra.db.marshal.UTF8Type", }, @@ -347,7 +347,7 @@ func TestCompileMetadata(t *testing.T) { Keyspace: "V2Keyspace", Table: "Table2", Name: "Column1", - Kind: PARTITION_KEY, + Kind: ColumnPartitionKey, ComponentIndex: 0, Validator: "org.apache.cassandra.db.marshal.UTF8Type", }, @@ -355,7 +355,7 @@ func TestCompileMetadata(t *testing.T) { Keyspace: "V2Keyspace", Table: "Table2", Name: "Column2", - Kind: CLUSTERING_KEY, + Kind: ColumnClusteringKey, ComponentIndex: 0, Validator: "org.apache.cassandra.db.marshal.UTF8Type", }, @@ -363,7 +363,7 @@ func TestCompileMetadata(t *testing.T) { Keyspace: "V2Keyspace", Table: "Table2", Name: "Column3", - Kind: CLUSTERING_KEY, + Kind: ColumnClusteringKey, ComponentIndex: 1, Validator: "org.apache.cassandra.db.marshal.ReversedType(org.apache.cassandra.db.marshal.UTF8Type)", }, @@ -371,7 +371,7 @@ func TestCompileMetadata(t *testing.T) { Keyspace: "V2Keyspace", Table: "Table2", Name: "Column4", - Kind: REGULAR, + Kind: ColumnRegular, Validator: "org.apache.cassandra.db.marshal.UTF8Type", }, } @@ -394,12 +394,12 @@ func TestCompileMetadata(t *testing.T) { "KEY1": { Name: "KEY1", Type: NativeType{typ: TypeVarchar}, - Kind: PARTITION_KEY, + Kind: ColumnPartitionKey, }, "Key1": { Name: "Key1", Type: NativeType{typ: TypeVarchar}, - Kind: PARTITION_KEY, + Kind: ColumnPartitionKey, }, }, }, @@ -426,24 +426,24 @@ func TestCompileMetadata(t *testing.T) { "Column1": { Name: "Column1", Type: NativeType{typ: TypeVarchar}, - Kind: PARTITION_KEY, + Kind: ColumnPartitionKey, }, "Column2": { Name: "Column2", Type: NativeType{typ: TypeVarchar}, Order: ASC, - Kind: CLUSTERING_KEY, + Kind: ColumnClusteringKey, }, "Column3": { Name: "Column3", Type: NativeType{typ: TypeVarchar}, Order: DESC, - Kind: CLUSTERING_KEY, + Kind: ColumnClusteringKey, }, "Column4": { Name: "Column4", Type: NativeType{typ: TypeVarchar}, - Kind: REGULAR, + Kind: ColumnRegular, }, }, }, @@ -486,8 +486,8 @@ func assertKeyspaceMetadata(t *testing.T, actual, expected *KeyspaceMetadata) { if i != at.PartitionKey[i].ComponentIndex { t.Errorf("Expected %s.Tables[%s].PartitionKey[%d].ComponentIndex to be %v but was %v", expected.Name, keyT, i, i, at.PartitionKey[i].ComponentIndex) } - if PARTITION_KEY != at.PartitionKey[i].Kind { - t.Errorf("Expected %s.Tables[%s].PartitionKey[%d].Kind to be '%v' but was '%v'", expected.Name, keyT, i, PARTITION_KEY, at.PartitionKey[i].Kind) + if ColumnPartitionKey != at.PartitionKey[i].Kind { + t.Errorf("Expected %s.Tables[%s].PartitionKey[%d].Kind to be '%v' but was '%v'", expected.Name, keyT, i, ColumnPartitionKey, at.PartitionKey[i].Kind) } } } @@ -516,8 +516,8 @@ func assertKeyspaceMetadata(t *testing.T, actual, expected *KeyspaceMetadata) { if et.ClusteringColumns[i].Order != at.ClusteringColumns[i].Order { t.Errorf("Expected %s.Tables[%s].ClusteringColumns[%d].Order to be %v but was %v", expected.Name, keyT, i, et.ClusteringColumns[i].Order, at.ClusteringColumns[i].Order) } - if CLUSTERING_KEY != at.ClusteringColumns[i].Kind { - t.Errorf("Expected %s.Tables[%s].ClusteringColumns[%d].Kind to be '%v' but was '%v'", expected.Name, keyT, i, CLUSTERING_KEY, at.ClusteringColumns[i].Kind) + if ColumnClusteringKey != at.ClusteringColumns[i].Kind { + t.Errorf("Expected %s.Tables[%s].ClusteringColumns[%d].Kind to be '%v' but was '%v'", expected.Name, keyT, i, ColumnClusteringKey, at.ClusteringColumns[i].Kind) } } }