Skip to content

Commit

Permalink
fix dependency handling for functions
Browse files Browse the repository at this point in the history
there are complex logic to handle object dependencies in GetDependencies
function. This logic starts from non-internal dependencies (e.g. with
namespaces) and enrich them by up to two levels of internal dependencies.
E.g. some function depends on composite type and this type depends
on a user table. But sometimes it's not enough, e.g. in case of
function argument is an array of user composite types. In this case
dependency chain is function-array_of_type-type-relation:

 classid  |     objid      |  refclassid  |   refobjid   | deptype
----------+----------------+--------------+--------------+---------
 pg_type  | some_table     | pg_class     | some_table   | i
 pg_type  | some_table[]   | pg_type      | some_table   | i
 pg_class | some_table     | pg_namespace | public       | n
 pg_proc  | dependant_func | pg_namespace | public       | n
 pg_proc  | dependant_func | pg_type      | some_table[] | n

This patch append handling for one more dependency level. I've
intentionally avoided recursive queries here because there are problems
with recursive query support in the old gpdb versions. This code part
has branches even for gpdb 4. Also, I couldn't reproduce longer chain of
internal dependencies.
  • Loading branch information
Stolb27 committed May 6, 2024
1 parent ab6aa74 commit 8c25531
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 2 deletions.
5 changes: 3 additions & 2 deletions backup/dependencies.go
Original file line number Diff line number Diff line change
Expand Up @@ -278,12 +278,13 @@ func GetDependencies(connectionPool *dbconn.DBConn, backupSet map[UniqueID]bool,
query := `SELECT
coalesce(id1.refclassid, d.classid) AS classid,
coalesce(id1.refobjid, d.objid) AS objid,
coalesce(id2.refclassid, d.refclassid) AS refclassid,
coalesce(id2.refobjid, d.refobjid) AS refobjid
coalesce(id3.refclassid, id2.refclassid, d.refclassid) AS refclassid,
coalesce(id3.refobjid, id2.refobjid, d.refobjid) AS refobjid
FROM pg_depend d
-- link implicit objects, using objid and refobjid, to the objects that created them
LEFT JOIN pg_depend id1 ON (d.objid = id1.objid and d.classid = id1.classid and id1.deptype='i')
LEFT JOIN pg_depend id2 ON (d.refobjid = id2.objid and d.refclassid = id2.classid and id2.deptype='i')
LEFT JOIN pg_depend id3 ON (id2.refobjid = id3.objid and id2.refclassid = id3.classid and id3.deptype='i')
WHERE d.classid != 0
AND d.deptype != 'i'
UNION
Expand Down
19 changes: 19 additions & 0 deletions integration/dependency_queries_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,25 @@ object-relational database management system');`)
Expect(functionDeps[funcEntry]).To(HaveKey(compositeEntry))
Expect(functionDeps[funcEntry]).To(HaveKey(baseEntry))
})
It("construct dependencies correctly for a function dependent on an array of relation row's type", func() {
testhelper.AssertQueryRuns(connectionPool, "CREATE TABLE public.some_table(a int, b int)")
defer testhelper.AssertQueryRuns(connectionPool, "DROP TABLE public.some_table CASCADE")
testhelper.AssertQueryRuns(connectionPool, "CREATE FUNCTION public.some_function(arg public.some_table[]) RETURNS int AS $$ SELECT 42; $$ LANGUAGE SQL;")
defer testhelper.AssertQueryRuns(connectionPool, "DROP FUNCTION public.some_function(arg public.some_table[]);")

functionOid := testutils.OidFromObjectName(connectionPool, "public", "some_function", backup.TYPE_FUNCTION)
funcEntry := backup.UniqueID{ClassID: backup.PG_PROC_OID, Oid: functionOid}
tableOid := testutils.OidFromObjectName(connectionPool, "public", "some_table", backup.TYPE_RELATION)
tableEntry := backup.UniqueID{ClassID: backup.PG_CLASS_OID, Oid: tableOid}
backupSet := map[backup.UniqueID]bool{funcEntry: true, tableEntry: true}
tables := make([]backup.Table, 0)

functionDeps := backup.GetDependencies(connectionPool, backupSet, tables)

Expect(functionDeps).To(HaveLen(1))
Expect(functionDeps[funcEntry]).To(HaveLen(1))
Expect(functionDeps[funcEntry]).To(HaveKey(tableEntry))
})
})
Describe("type dependencies", func() {
var (
Expand Down

0 comments on commit 8c25531

Please sign in to comment.