Skip to content

Commit b60130e

Browse files
robertmumy-ship-it
authored andcommitted
fix(relations): Ensure materialized view access method is restored
On Cloudberry, Greenplum 7+, materialized views must be created with a specific access method (e.g., 'heap', 'ao_row') and associated storage options in the 'WITH' clause (e.g., 'compresstype=zstd'). The prior implementation did not back up the 'USING' clause. During restore, the database would default to another access method (e.g., 'heap') which might not support the view's storage options. This incompatibility caused the 'CREATE MATERIALIZED VIEW' command to fail validation. This commit corrects the failure by: - Updating the view query for Cloudberry, GPDB 7+ to fetch the access method. - Modifying DDL generation to include the 'USING' clause. - Updating integration tests to verify the fix. Fixes #61
1 parent 4648d84 commit b60130e

File tree

4 files changed

+54
-17
lines changed

4 files changed

+54
-17
lines changed

backup/predata_relations.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -444,8 +444,12 @@ func PrintCreateViewStatement(metadataFile *utils.FileWithByteCount, objToc *toc
444444
if !view.IsMaterialized {
445445
metadataFile.MustPrintf("\n\nCREATE VIEW %s%s AS %s\n", view.FQN(), view.Options, view.Definition.String)
446446
} else {
447-
metadataFile.MustPrintf("\n\nCREATE MATERIALIZED VIEW %s%s%s AS %s\nWITH NO DATA\n%s;\n",
448-
view.FQN(), view.Options, tablespaceClause, view.Definition.String[:len(view.Definition.String)-1], view.DistPolicy.Policy)
447+
accessMethodClause := ""
448+
if view.AccessMethodName != "" {
449+
accessMethodClause = fmt.Sprintf(" USING %s", view.AccessMethodName)
450+
}
451+
metadataFile.MustPrintf("\n\nCREATE MATERIALIZED VIEW %s%s%s%s AS %s\nWITH NO DATA\n%s;\n",
452+
view.FQN(), accessMethodClause, view.Options, tablespaceClause, view.Definition.String[:len(view.Definition.String)-1], view.DistPolicy.Policy)
449453
}
450454
section, entry := view.GetMetadataEntry()
451455
tier := globalTierMap[view.GetUniqueID()]

backup/queries_relations.go

Lines changed: 33 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -344,16 +344,17 @@ func GetSequenceDefinition(connectionPool *dbconn.DBConn, seqName string) Sequen
344344
}
345345

346346
type View struct {
347-
Oid uint32
348-
Schema string
349-
Name string
350-
Options string
351-
Definition sql.NullString
352-
Tablespace string
353-
IsMaterialized bool
354-
DistPolicy DistPolicy
355-
NeedsDummy bool
356-
ColumnDefs []ColumnDefinition
347+
Oid uint32
348+
Schema string
349+
Name string
350+
Options string
351+
Definition sql.NullString
352+
Tablespace string
353+
IsMaterialized bool
354+
DistPolicy DistPolicy
355+
NeedsDummy bool
356+
ColumnDefs []ColumnDefinition
357+
AccessMethodName string
357358
}
358359

359360
func (v View) GetMetadataEntry() (string, toc.MetadataEntry) {
@@ -412,7 +413,7 @@ func GetAllViews(connectionPool *dbconn.DBConn) []View {
412413

413414
// Materialized views were introduced in GPDB 7 and backported to GPDB 6.2.
414415
// Reloptions and tablespace added to pg_class in GPDB 6
415-
atLeast6Query := fmt.Sprintf(`
416+
version6Query := fmt.Sprintf(`
416417
SELECT
417418
c.oid AS oid,
418419
quote_ident(n.nspname) AS schema,
@@ -428,11 +429,31 @@ func GetAllViews(connectionPool *dbconn.DBConn) []View {
428429
AND %s
429430
AND %s`, relationAndSchemaFilterClause(), ExtensionFilterClause("c"))
430431

432+
atLeast7Query := fmt.Sprintf(`
433+
SELECT
434+
c.oid AS oid,
435+
quote_ident(n.nspname) AS schema,
436+
quote_ident(c.relname) AS name,
437+
pg_get_viewdef(c.oid) AS definition,
438+
coalesce(' WITH (' || array_to_string(c.reloptions, ', ') || ')', '') AS options,
439+
coalesce(quote_ident(t.spcname), '') AS tablespace,
440+
c.relkind='m' AS ismaterialized,
441+
coalesce(quote_ident(am.amname), '') AS accessmethodname
442+
FROM pg_class c
443+
LEFT JOIN pg_namespace n ON n.oid = c.relnamespace
444+
LEFT JOIN pg_tablespace t ON t.oid = c.reltablespace
445+
LEFT JOIN pg_am am ON am.oid = c.relam
446+
WHERE c.relkind IN ('m', 'v')
447+
AND %s
448+
AND %s`, relationAndSchemaFilterClause(), ExtensionFilterClause("c"))
449+
431450
query := ""
432451
if connectionPool.Version.IsGPDB() && connectionPool.Version.Before("6") {
433452
query = before6Query
453+
} else if connectionPool.Version.IsGPDB() && connectionPool.Version.Is("6") {
454+
query = version6Query
434455
} else {
435-
query = atLeast6Query
456+
query = atLeast7Query
436457
}
437458

438459
results := make([]View, 0)

integration/predata_relations_create_test.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -576,6 +576,9 @@ SET SUBPARTITION TEMPLATE ` + `
576576
})
577577
It("creates a view with privileges, owner, security label, and comment", func() {
578578
view := backup.View{Oid: 1, Schema: "public", Name: "simplemview", Definition: sql.NullString{String: " SELECT 1 AS a;", Valid: true}, IsMaterialized: true, DistPolicy: backup.DistPolicy{Policy: "DISTRIBUTED BY (a)"}}
579+
if (connectionPool.Version.IsGPDB() && connectionPool.Version.AtLeast("7")) || connectionPool.Version.IsCBDB() {
580+
view.AccessMethodName = "heap"
581+
}
579582
viewMetadata := testutils.DefaultMetadata(toc.OBJ_MATERIALIZED_VIEW, true, true, true, includeSecurityLabels)
580583

581584
backup.PrintCreateViewStatement(backupfile, tocfile, view, viewMetadata)
@@ -594,7 +597,9 @@ SET SUBPARTITION TEMPLATE ` + `
594597
})
595598
It("creates a materialized view with options", func() {
596599
view := backup.View{Oid: 1, Schema: "public", Name: "simplemview", Options: " WITH (fillfactor=10)", Definition: sql.NullString{String: " SELECT 1 AS a;", Valid: true}, IsMaterialized: true, DistPolicy: backup.DistPolicy{Policy: "DISTRIBUTED BY (a)"}}
597-
600+
if (connectionPool.Version.IsGPDB() && connectionPool.Version.AtLeast("7")) || connectionPool.Version.IsCBDB() {
601+
view.AccessMethodName = "heap"
602+
}
598603
backup.PrintCreateViewStatement(backupfile, tocfile, view, backup.ObjectMetadata{})
599604

600605
testhelper.AssertQueryRuns(connectionPool, buffer.String())

integration/predata_relations_queries_test.go

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -512,6 +512,9 @@ PARTITION BY LIST (gender)
512512

513513
results := backup.GetAllViews(connectionPool)
514514
materialView := backup.View{Oid: 1, Schema: "public", Name: "simplematerialview", Definition: sql.NullString{String: " SELECT 1 AS a;", Valid: true}, IsMaterialized: true, DistPolicy: backup.DistPolicy{Policy: "DISTRIBUTED BY (a)"}}
515+
if (connectionPool.Version.IsGPDB() && connectionPool.Version.AtLeast("7")) || connectionPool.Version.IsCBDB() {
516+
materialView.AccessMethodName = "heap"
517+
}
515518

516519
materialView.Oid = testutils.OidFromObjectName(connectionPool, "public", "simplematerialview", backup.TYPE_RELATION)
517520
Expect(results).To(HaveLen(1))
@@ -526,7 +529,9 @@ PARTITION BY LIST (gender)
526529

527530
results := backup.GetAllViews(connectionPool)
528531
materialView := backup.View{Oid: 1, Schema: "public", Name: "simplematerialview", Definition: sql.NullString{String: " SELECT 1 AS a;", Valid: true}, Options: " WITH (fillfactor=50, autovacuum_enabled=false)", IsMaterialized: true, DistPolicy: backup.DistPolicy{Policy: "DISTRIBUTED BY (a)"}}
529-
532+
if (connectionPool.Version.IsGPDB() && connectionPool.Version.AtLeast("7")) || connectionPool.Version.IsCBDB() {
533+
materialView.AccessMethodName = "heap"
534+
}
530535
materialView.Oid = testutils.OidFromObjectName(connectionPool, "public", "simplematerialview", backup.TYPE_RELATION)
531536
Expect(results).To(HaveLen(1))
532537
structmatcher.ExpectStructsToMatchExcluding(&materialView, &results[0], "ColumnDefs", "DistPolicy.Oid")
@@ -542,7 +547,9 @@ PARTITION BY LIST (gender)
542547

543548
results := backup.GetAllViews(connectionPool)
544549
materialView := backup.View{Oid: 1, Schema: "public", Name: "simplematerialview", Definition: sql.NullString{String: " SELECT 1 AS a;", Valid: true}, Tablespace: "test_tablespace", IsMaterialized: true, DistPolicy: backup.DistPolicy{Policy: "DISTRIBUTED BY (a)"}}
545-
550+
if (connectionPool.Version.IsGPDB() && connectionPool.Version.AtLeast("7")) || connectionPool.Version.IsCBDB() {
551+
materialView.AccessMethodName = "heap"
552+
}
546553
Expect(results).To(HaveLen(1))
547554
structmatcher.ExpectStructsToMatchExcluding(&materialView, &results[0], "Oid", "ColumnDefs", "DistPolicy.Oid")
548555
})

0 commit comments

Comments
 (0)