diff --git a/backup/predata_relations.go b/backup/predata_relations.go index 8f42a8a2..ead394ab 100644 --- a/backup/predata_relations.go +++ b/backup/predata_relations.go @@ -444,8 +444,12 @@ func PrintCreateViewStatement(metadataFile *utils.FileWithByteCount, objToc *toc if !view.IsMaterialized { metadataFile.MustPrintf("\n\nCREATE VIEW %s%s AS %s\n", view.FQN(), view.Options, view.Definition.String) } else { - metadataFile.MustPrintf("\n\nCREATE MATERIALIZED VIEW %s%s%s AS %s\nWITH NO DATA\n%s;\n", - view.FQN(), view.Options, tablespaceClause, view.Definition.String[:len(view.Definition.String)-1], view.DistPolicy.Policy) + accessMethodClause := "" + if view.AccessMethodName != "" { + accessMethodClause = fmt.Sprintf(" USING %s", view.AccessMethodName) + } + metadataFile.MustPrintf("\n\nCREATE MATERIALIZED VIEW %s%s%s%s AS %s\nWITH NO DATA\n%s;\n", + view.FQN(), accessMethodClause, view.Options, tablespaceClause, view.Definition.String[:len(view.Definition.String)-1], view.DistPolicy.Policy) } section, entry := view.GetMetadataEntry() tier := globalTierMap[view.GetUniqueID()] diff --git a/backup/queries_relations.go b/backup/queries_relations.go index ed16db98..34652a84 100644 --- a/backup/queries_relations.go +++ b/backup/queries_relations.go @@ -344,16 +344,17 @@ func GetSequenceDefinition(connectionPool *dbconn.DBConn, seqName string) Sequen } type View struct { - Oid uint32 - Schema string - Name string - Options string - Definition sql.NullString - Tablespace string - IsMaterialized bool - DistPolicy DistPolicy - NeedsDummy bool - ColumnDefs []ColumnDefinition + Oid uint32 + Schema string + Name string + Options string + Definition sql.NullString + Tablespace string + IsMaterialized bool + DistPolicy DistPolicy + NeedsDummy bool + ColumnDefs []ColumnDefinition + AccessMethodName string } func (v View) GetMetadataEntry() (string, toc.MetadataEntry) { @@ -412,7 +413,7 @@ func GetAllViews(connectionPool *dbconn.DBConn) []View { // Materialized views were introduced in GPDB 7 and backported to GPDB 6.2. // Reloptions and tablespace added to pg_class in GPDB 6 - atLeast6Query := fmt.Sprintf(` + version6Query := fmt.Sprintf(` SELECT c.oid AS oid, quote_ident(n.nspname) AS schema, @@ -428,11 +429,31 @@ func GetAllViews(connectionPool *dbconn.DBConn) []View { AND %s AND %s`, relationAndSchemaFilterClause(), ExtensionFilterClause("c")) + atLeast7Query := fmt.Sprintf(` + SELECT + c.oid AS oid, + quote_ident(n.nspname) AS schema, + quote_ident(c.relname) AS name, + pg_get_viewdef(c.oid) AS definition, + coalesce(' WITH (' || array_to_string(c.reloptions, ', ') || ')', '') AS options, + coalesce(quote_ident(t.spcname), '') AS tablespace, + c.relkind='m' AS ismaterialized, + coalesce(quote_ident(am.amname), '') AS accessmethodname + FROM pg_class c + LEFT JOIN pg_namespace n ON n.oid = c.relnamespace + LEFT JOIN pg_tablespace t ON t.oid = c.reltablespace + LEFT JOIN pg_am am ON am.oid = c.relam + WHERE c.relkind IN ('m', 'v') + AND %s + AND %s`, relationAndSchemaFilterClause(), ExtensionFilterClause("c")) + query := "" if connectionPool.Version.IsGPDB() && connectionPool.Version.Before("6") { query = before6Query + } else if connectionPool.Version.IsGPDB() && connectionPool.Version.Is("6") { + query = version6Query } else { - query = atLeast6Query + query = atLeast7Query } results := make([]View, 0) diff --git a/integration/predata_relations_create_test.go b/integration/predata_relations_create_test.go index 3d825f11..5a92c391 100644 --- a/integration/predata_relations_create_test.go +++ b/integration/predata_relations_create_test.go @@ -576,6 +576,9 @@ SET SUBPARTITION TEMPLATE ` + ` }) It("creates a view with privileges, owner, security label, and comment", func() { 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)"}} + if (connectionPool.Version.IsGPDB() && connectionPool.Version.AtLeast("7")) || connectionPool.Version.IsCBDB() { + view.AccessMethodName = "heap" + } viewMetadata := testutils.DefaultMetadata(toc.OBJ_MATERIALIZED_VIEW, true, true, true, includeSecurityLabels) backup.PrintCreateViewStatement(backupfile, tocfile, view, viewMetadata) @@ -594,7 +597,9 @@ SET SUBPARTITION TEMPLATE ` + ` }) It("creates a materialized view with options", func() { 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)"}} - + if (connectionPool.Version.IsGPDB() && connectionPool.Version.AtLeast("7")) || connectionPool.Version.IsCBDB() { + view.AccessMethodName = "heap" + } backup.PrintCreateViewStatement(backupfile, tocfile, view, backup.ObjectMetadata{}) testhelper.AssertQueryRuns(connectionPool, buffer.String()) diff --git a/integration/predata_relations_queries_test.go b/integration/predata_relations_queries_test.go index af97c5c9..a0fc446e 100644 --- a/integration/predata_relations_queries_test.go +++ b/integration/predata_relations_queries_test.go @@ -512,6 +512,9 @@ PARTITION BY LIST (gender) results := backup.GetAllViews(connectionPool) 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)"}} + if (connectionPool.Version.IsGPDB() && connectionPool.Version.AtLeast("7")) || connectionPool.Version.IsCBDB() { + materialView.AccessMethodName = "heap" + } materialView.Oid = testutils.OidFromObjectName(connectionPool, "public", "simplematerialview", backup.TYPE_RELATION) Expect(results).To(HaveLen(1)) @@ -526,7 +529,9 @@ PARTITION BY LIST (gender) results := backup.GetAllViews(connectionPool) 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)"}} - + if (connectionPool.Version.IsGPDB() && connectionPool.Version.AtLeast("7")) || connectionPool.Version.IsCBDB() { + materialView.AccessMethodName = "heap" + } materialView.Oid = testutils.OidFromObjectName(connectionPool, "public", "simplematerialview", backup.TYPE_RELATION) Expect(results).To(HaveLen(1)) structmatcher.ExpectStructsToMatchExcluding(&materialView, &results[0], "ColumnDefs", "DistPolicy.Oid") @@ -542,7 +547,9 @@ PARTITION BY LIST (gender) results := backup.GetAllViews(connectionPool) 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)"}} - + if (connectionPool.Version.IsGPDB() && connectionPool.Version.AtLeast("7")) || connectionPool.Version.IsCBDB() { + materialView.AccessMethodName = "heap" + } Expect(results).To(HaveLen(1)) structmatcher.ExpectStructsToMatchExcluding(&materialView, &results[0], "Oid", "ColumnDefs", "DistPolicy.Oid") })