Repository: gocql/gocql
Pull request #1525 (2021-01-25 15:11:13)

fix compileMetadata bug for materialized views
Fixes https://github.com/gocql/gocql/issues/1524 for materialised views

beltran: Thank you for reviewing, I've addressed the comments.

Patch:
diff --git a/metadata.go b/metadata.go
index e586dd4..226ce47 100644
--- a/metadata.go
+++ b/metadata.go
@@ -347,9 +347,9 @@ func compileMetadata(
 		keyspace.UserTypes[types[i].Name] = &types[i]
 	}
 	keyspace.MaterializedViews = make(map[string]*MaterializedViewMetadata, len(materializedViews))
-	for _, materializedView := range materializedViews {
-		materializedView.BaseTable = keyspace.Tables[materializedView.baseTableName]
-		keyspace.MaterializedViews[materializedView.Name] = &materializedView
+	for i, _ := range materializedViews {
+		materializedViews[i].BaseTable = keyspace.Tables[materializedViews[i].baseTableName]
+		keyspace.MaterializedViews[materializedViews[i].Name] = &materializedViews[i]
 	}
 
 	// add columns from the schema data


Test patch:
diff --git a/cassandra_test.go b/cassandra_test.go
index d06274b..ba2a880 100644
--- a/cassandra_test.go
+++ b/cassandra_test.go
@@ -2248,10 +2248,10 @@ func TestMaterializedViewMetadata(t *testing.T) {
 	if materializedViews == nil {
 		t.Fatal("failed to query view metadata, nil returned")
 	}
-	if len(materializedViews) != 1 {
-		t.Fatal("expected one view")
+	if len(materializedViews) != 2 {
+		t.Fatal("expected two views")
 	}
-	expectedView := MaterializedViewMetadata{
+	expectedView1 := MaterializedViewMetadata{
 		Keyspace:                "gocql_test",
 		Name:                    "view_view",
 		baseTableName:           "view_table",
@@ -2268,12 +2268,33 @@ func TestMaterializedViewMetadata(t *testing.T) {
 		IncludeAllColumns:       false, MaxIndexInterval: 2048, MemtableFlushPeriodInMs: 0, MinIndexInterval: 128, ReadRepairChance: 0,
 		SpeculativeRetry: "99PERCENTILE",
 	}
+	expectedView2 := MaterializedViewMetadata{
+		Keyspace:                "gocql_test",
+		Name:                    "view_view2",
+		baseTableName:           "view_table2",
+		BloomFilterFpChance:     0.01,
+		Caching:                 map[string]string{"keys": "ALL", "rows_per_partition": "NONE"},
+		Comment:                 "",
+		Compaction:              map[string]string{"class": "org.apache.cassandra.db.compaction.SizeTieredCompactionStrategy", "max_threshold": "32", "min_threshold": "4"},
+		Compression:             map[string]string{"chunk_length_in_kb": "64", "class": "org.apache.cassandra.io.compress.LZ4Compressor"},
+		CrcCheckChance:          1,
+		DcLocalReadRepairChance: 0.1,
+		DefaultTimeToLive:       0,
+		Extensions:              map[string]string{},
+		GcGraceSeconds:          864000,
+		IncludeAllColumns:       false, MaxIndexInterval: 2048, MemtableFlushPeriodInMs: 0, MinIndexInterval: 128, ReadRepairChance: 0,
+		SpeculativeRetry: "99PERCENTILE",
+	}
 
-	expectedView.BaseTableId = materializedViews[0].BaseTableId
-	expectedView.Id = materializedViews[0].Id
-
-	if !reflect.DeepEqual(materializedViews[0], expectedView) {
-		t.Fatalf("materialized view is %+v, but expected %+v", materializedViews[0], expectedView)
+	expectedView1.BaseTableId = materializedViews[0].BaseTableId
+	expectedView1.Id = materializedViews[0].Id
+	if !reflect.DeepEqual(materializedViews[0], expectedView1) {
+		t.Fatalf("materialized view is %+v, but expected %+v", materializedViews[0], expectedView1)
+	}
+	expectedView2.BaseTableId = materializedViews[1].BaseTableId
+	expectedView2.Id = materializedViews[1].Id
+	if !reflect.DeepEqual(materializedViews[1], expectedView2) {
+		t.Fatalf("materialized view is %+v, but expected %+v", materializedViews[1], expectedView2)
 	}
 }
 
@@ -2503,11 +2524,18 @@ func TestKeyspaceMetadata(t *testing.T) {
 	if flagCassVersion.Major >= 3 {
 		materializedView, found := keyspaceMetadata.MaterializedViews["view_view"]
 		if !found {
-			t.Fatal("failed to find the materialized view in metadata")
+			t.Fatal("failed to find materialized view view_view in metadata")
 		}
 		if materializedView.BaseTable.Name != "view_table" {
 			t.Fatalf("expected name: %s, materialized view base table name: %s", "view_table", materializedView.BaseTable.Name)
 		}
+		materializedView, found = keyspaceMetadata.MaterializedViews["view_view2"]
+		if !found {
+			t.Fatal("failed to find materialized view view_view2 in metadata")
+		}
+		if materializedView.BaseTable.Name != "view_table2" {
+			t.Fatalf("expected name: %s, materialized view base table name: %s", "view_table2", materializedView.BaseTable.Name)
+		}
 	}
 }
 
diff --git a/common_test.go b/common_test.go
index c7b912f..e751566 100644
--- a/common_test.go
+++ b/common_test.go
@@ -195,6 +195,13 @@ func createMaterializedViews(t *testing.T, session *Session) {
     		    PRIMARY KEY (userid));`).Exec(); err != nil {
 		t.Fatalf("failed to create materialized view with err: %v", err)
 	}
+	if err := session.Query(`CREATE TABLE IF NOT EXISTS gocql_test.view_table2 (
+		    userid text,
+		    year int,
+		    month int,
+    		    PRIMARY KEY (userid));`).Exec(); err != nil {
+		t.Fatalf("failed to create materialized view with err: %v", err)
+	}
 	if err := session.Query(`CREATE MATERIALIZED VIEW IF NOT EXISTS gocql_test.view_view AS
 		   SELECT year, month, userid
 		   FROM gocql_test.view_table
@@ -202,6 +209,13 @@ func createMaterializedViews(t *testing.T, session *Session) {
 		   PRIMARY KEY (userid, year);`).Exec(); err != nil {
 		t.Fatalf("failed to create materialized view with err: %v", err)
 	}
+	if err := session.Query(`CREATE MATERIALIZED VIEW IF NOT EXISTS gocql_test.view_view2 AS
+		   SELECT year, month, userid
+		   FROM gocql_test.view_table2
+		   WHERE year IS NOT NULL AND month IS NOT NULL AND userid IS NOT NULL
+		   PRIMARY KEY (userid, year);`).Exec(); err != nil {
+		t.Fatalf("failed to create materialized view with err: %v", err)
+	}
 }
 
 func createFunctions(t *testing.T, session *Session) {