Commit 12f6eadf authored by Tom Lane's avatar Tom Lane

Fix incorrect logic for excluding range constructor functions in pg_dump.

Faulty AND/OR nesting in the WHERE clause of getFuncs' SQL query led to
dumping range constructor functions if they are part of an extension
and we're in binary-upgrade mode.  Actually, we don't want to dump them
separately even then, since CREATE TYPE AS RANGE will create the range's
constructor functions regardless.  Per report from Andrew Dunstan.

It looks like this mistake was introduced by me, in commit b985d487, in
perhaps-overzealous refactoring to reduce code duplication.  I'm suitably
embarrassed.

Report: <34854939-02d7-f591-5677-ce2994104599@dunslane.net>
parent 959ea7fa
...@@ -4952,20 +4952,23 @@ getFuncs(Archive *fout, int *numFuncs) ...@@ -4952,20 +4952,23 @@ getFuncs(Archive *fout, int *numFuncs)
selectSourceSchema(fout, "pg_catalog"); selectSourceSchema(fout, "pg_catalog");
/* /*
* Find all interesting functions. We include functions in pg_catalog, if * Find all interesting functions. This is a bit complicated:
* they have an ACL different from what we set at initdb time (which is
* saved in pg_init_privs for us to perform this check). There may also
* be functions which are members of extensions which we must dump if we
* are in binary upgrade mode (we'll mark those functions as to-be-dumped
* when we check if the extension is to-be-dumped and we're in binary
* upgrade mode).
* *
* Also, in 9.2 and up, exclude functions that are internally dependent on * 1. Always exclude aggregates; those are handled elsewhere.
* something else, since presumably those will be created as a result of *
* creating the something else. This currently only acts to suppress * 2. Always exclude functions that are internally dependent on something
* constructor functions for range types. Note that this is OK only * else, since presumably those will be created as a result of creating
* because the constructors don't have any dependencies the range type * the something else. This currently acts only to suppress constructor
* doesn't have; otherwise we might not get creation ordering correct. * functions for range types (so we only need it in 9.2 and up). Note
* this is OK only because the constructors don't have any dependencies
* the range type doesn't have; otherwise we might not get creation
* ordering correct.
*
* 3. Otherwise, we normally exclude functions in pg_catalog. However, if
* they're members of extensions and we are in binary-upgrade mode then
* include them, since we want to dump extension members individually in
* that mode. Also, in 9.6 and up, include functions in pg_catalog if
* they have an ACL different from what's shown in pg_init_privs.
*/ */
if (fout->remoteVersion >= 90600) if (fout->remoteVersion >= 90600)
{ {
...@@ -4992,14 +4995,14 @@ getFuncs(Archive *fout, int *numFuncs) ...@@ -4992,14 +4995,14 @@ getFuncs(Archive *fout, int *numFuncs)
"(p.oid = pip.objoid " "(p.oid = pip.objoid "
"AND pip.classoid = 'pg_proc'::regclass " "AND pip.classoid = 'pg_proc'::regclass "
"AND pip.objsubid = 0) " "AND pip.objsubid = 0) "
"WHERE NOT proisagg " "WHERE NOT proisagg"
"AND NOT EXISTS (SELECT 1 FROM pg_depend " "\n AND NOT EXISTS (SELECT 1 FROM pg_depend "
"WHERE classid = 'pg_proc'::regclass AND " "WHERE classid = 'pg_proc'::regclass AND "
"objid = p.oid AND deptype = 'i') AND (" "objid = p.oid AND deptype = 'i')"
"pronamespace != " "\n AND ("
"\n pronamespace != "
"(SELECT oid FROM pg_namespace " "(SELECT oid FROM pg_namespace "
"WHERE nspname = 'pg_catalog') OR " "WHERE nspname = 'pg_catalog')",
"p.proacl IS DISTINCT FROM pip.initprivs",
acl_subquery->data, acl_subquery->data,
racl_subquery->data, racl_subquery->data,
initacl_subquery->data, initacl_subquery->data,
...@@ -5012,6 +5015,8 @@ getFuncs(Archive *fout, int *numFuncs) ...@@ -5012,6 +5015,8 @@ getFuncs(Archive *fout, int *numFuncs)
"objid = p.oid AND " "objid = p.oid AND "
"refclassid = 'pg_extension'::regclass AND " "refclassid = 'pg_extension'::regclass AND "
"deptype = 'e')"); "deptype = 'e')");
appendPQExpBufferStr(query,
"\n OR p.proacl IS DISTINCT FROM pip.initprivs");
appendPQExpBufferChar(query, ')'); appendPQExpBufferChar(query, ')');
destroyPQExpBuffer(acl_subquery); destroyPQExpBuffer(acl_subquery);
...@@ -5029,16 +5034,18 @@ getFuncs(Archive *fout, int *numFuncs) ...@@ -5029,16 +5034,18 @@ getFuncs(Archive *fout, int *numFuncs)
"pronamespace, " "pronamespace, "
"(%s proowner) AS rolname " "(%s proowner) AS rolname "
"FROM pg_proc p " "FROM pg_proc p "
"WHERE NOT proisagg AND (" "WHERE NOT proisagg",
"pronamespace != "
"(SELECT oid FROM pg_namespace "
"WHERE nspname = 'pg_catalog')",
username_subquery); username_subquery);
if (fout->remoteVersion >= 90200) if (fout->remoteVersion >= 90200)
appendPQExpBufferStr(query, appendPQExpBufferStr(query,
"\n AND NOT EXISTS (SELECT 1 FROM pg_depend " "\n AND NOT EXISTS (SELECT 1 FROM pg_depend "
"WHERE classid = 'pg_proc'::regclass AND " "WHERE classid = 'pg_proc'::regclass AND "
"objid = p.oid AND deptype = 'i')"); "objid = p.oid AND deptype = 'i')");
appendPQExpBufferStr(query,
"\n AND ("
"\n pronamespace != "
"(SELECT oid FROM pg_namespace "
"WHERE nspname = 'pg_catalog')");
if (dopt->binary_upgrade && fout->remoteVersion >= 90100) if (dopt->binary_upgrade && fout->remoteVersion >= 90100)
appendPQExpBufferStr(query, appendPQExpBufferStr(query,
"\n OR EXISTS(SELECT 1 FROM pg_depend WHERE " "\n OR EXISTS(SELECT 1 FROM pg_depend WHERE "
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment