Commit 44c52881 authored by Stephen Frost's avatar Stephen Frost

Change the way pg_dump retrieves partitioning info

This gets rid of the code that issued separate queries to retrieve the
partitioning parent-child relationship, parent partition key, and child
partition bound information.  With this patch, the information is
retrieved instead using the queries issued from getTables() and
getInherits(), which is both more efficient than the previous approach
and doesn't require any new code.

Since the partitioning parent-child relationship is now retrieved with
the same old code that handles inheritance, partition attributes receive
a proper flagInhAttrs() treatment (that it didn't receive before), which
is needed so that the inherited NOT NULL constraints are not emitted if
we already emitted it for the parent.

Also, fix a bug in pg_dump's --binary-upgrade code, which caused pg_dump
to emit invalid command to attach a partition to its parent.

Author: Amit Langote, with some additional changes by me.
parent 5469e44f
...@@ -68,8 +68,6 @@ static int numextmembers; ...@@ -68,8 +68,6 @@ static int numextmembers;
static void flagInhTables(TableInfo *tbinfo, int numTables, static void flagInhTables(TableInfo *tbinfo, int numTables,
InhInfo *inhinfo, int numInherits); InhInfo *inhinfo, int numInherits);
static void flagPartitions(TableInfo *tblinfo, int numTables,
PartInfo *partinfo, int numPartitions);
static void flagInhAttrs(DumpOptions *dopt, TableInfo *tblinfo, int numTables); static void flagInhAttrs(DumpOptions *dopt, TableInfo *tblinfo, int numTables);
static DumpableObject **buildIndexArray(void *objArray, int numObjs, static DumpableObject **buildIndexArray(void *objArray, int numObjs,
Size objSize); Size objSize);
...@@ -77,8 +75,6 @@ static int DOCatalogIdCompare(const void *p1, const void *p2); ...@@ -77,8 +75,6 @@ static int DOCatalogIdCompare(const void *p1, const void *p2);
static int ExtensionMemberIdCompare(const void *p1, const void *p2); static int ExtensionMemberIdCompare(const void *p1, const void *p2);
static void findParentsByOid(TableInfo *self, static void findParentsByOid(TableInfo *self,
InhInfo *inhinfo, int numInherits); InhInfo *inhinfo, int numInherits);
static void findPartitionParentByOid(TableInfo *self, PartInfo *partinfo,
int numPartitions);
static int strInArray(const char *pattern, char **arr, int arr_size); static int strInArray(const char *pattern, char **arr, int arr_size);
...@@ -97,10 +93,8 @@ getSchemaData(Archive *fout, int *numTablesPtr) ...@@ -97,10 +93,8 @@ getSchemaData(Archive *fout, int *numTablesPtr)
NamespaceInfo *nspinfo; NamespaceInfo *nspinfo;
ExtensionInfo *extinfo; ExtensionInfo *extinfo;
InhInfo *inhinfo; InhInfo *inhinfo;
PartInfo *partinfo;
int numAggregates; int numAggregates;
int numInherits; int numInherits;
int numPartitions;
int numRules; int numRules;
int numProcLangs; int numProcLangs;
int numCasts; int numCasts;
...@@ -237,10 +231,6 @@ getSchemaData(Archive *fout, int *numTablesPtr) ...@@ -237,10 +231,6 @@ getSchemaData(Archive *fout, int *numTablesPtr)
write_msg(NULL, "reading table inheritance information\n"); write_msg(NULL, "reading table inheritance information\n");
inhinfo = getInherits(fout, &numInherits); inhinfo = getInherits(fout, &numInherits);
if (g_verbose)
write_msg(NULL, "reading partition information\n");
partinfo = getPartitions(fout, &numPartitions);
if (g_verbose) if (g_verbose)
write_msg(NULL, "reading event triggers\n"); write_msg(NULL, "reading event triggers\n");
getEventTriggers(fout, &numEventTriggers); getEventTriggers(fout, &numEventTriggers);
...@@ -255,11 +245,6 @@ getSchemaData(Archive *fout, int *numTablesPtr) ...@@ -255,11 +245,6 @@ getSchemaData(Archive *fout, int *numTablesPtr)
write_msg(NULL, "finding inheritance relationships\n"); write_msg(NULL, "finding inheritance relationships\n");
flagInhTables(tblinfo, numTables, inhinfo, numInherits); flagInhTables(tblinfo, numTables, inhinfo, numInherits);
/* Link tables to partition parents, mark parents as interesting */
if (g_verbose)
write_msg(NULL, "finding partition relationships\n");
flagPartitions(tblinfo, numTables, partinfo, numPartitions);
if (g_verbose) if (g_verbose)
write_msg(NULL, "reading column info for interesting tables\n"); write_msg(NULL, "reading column info for interesting tables\n");
getTableAttrs(fout, tblinfo, numTables); getTableAttrs(fout, tblinfo, numTables);
...@@ -292,10 +277,6 @@ getSchemaData(Archive *fout, int *numTablesPtr) ...@@ -292,10 +277,6 @@ getSchemaData(Archive *fout, int *numTablesPtr)
write_msg(NULL, "reading policies\n"); write_msg(NULL, "reading policies\n");
getPolicies(fout, tblinfo, numTables); getPolicies(fout, tblinfo, numTables);
if (g_verbose)
write_msg(NULL, "reading partition key information for interesting tables\n");
getTablePartitionKeyInfo(fout, tblinfo, numTables);
if (g_verbose) if (g_verbose)
write_msg(NULL, "reading publications\n"); write_msg(NULL, "reading publications\n");
getPublications(fout); getPublications(fout);
...@@ -354,43 +335,6 @@ flagInhTables(TableInfo *tblinfo, int numTables, ...@@ -354,43 +335,6 @@ flagInhTables(TableInfo *tblinfo, int numTables,
} }
} }
/* flagPartitions -
* Fill in parent link fields of every target table that is partition,
* and mark parents of partitions as interesting
*
* modifies tblinfo
*/
static void
flagPartitions(TableInfo *tblinfo, int numTables,
PartInfo *partinfo, int numPartitions)
{
int i;
for (i = 0; i < numTables; i++)
{
/* Some kinds are never partitions */
if (tblinfo[i].relkind == RELKIND_SEQUENCE ||
tblinfo[i].relkind == RELKIND_VIEW ||
tblinfo[i].relkind == RELKIND_MATVIEW)
continue;
/* Don't bother computing anything for non-target tables, either */
if (!tblinfo[i].dobj.dump)
continue;
/* Find the parent TableInfo and save */
findPartitionParentByOid(&tblinfo[i], partinfo, numPartitions);
/* Mark the parent as interesting for getTableAttrs */
if (tblinfo[i].partitionOf)
{
tblinfo[i].partitionOf->interesting = true;
addObjectDependency(&tblinfo[i].dobj,
tblinfo[i].partitionOf->dobj.dumpId);
}
}
}
/* flagInhAttrs - /* flagInhAttrs -
* for each dumpable table in tblinfo, flag its inherited attributes * for each dumpable table in tblinfo, flag its inherited attributes
* *
...@@ -991,40 +935,6 @@ findParentsByOid(TableInfo *self, ...@@ -991,40 +935,6 @@ findParentsByOid(TableInfo *self,
self->parents = NULL; self->parents = NULL;
} }
/*
* findPartitionParentByOid
* find a partition's parent in tblinfo[]
*/
static void
findPartitionParentByOid(TableInfo *self, PartInfo *partinfo,
int numPartitions)
{
Oid oid = self->dobj.catId.oid;
int i;
for (i = 0; i < numPartitions; i++)
{
if (partinfo[i].partrelid == oid)
{
TableInfo *parent;
parent = findTableByOid(partinfo[i].partparent);
if (parent == NULL)
{
write_msg(NULL, "failed sanity check, parent OID %u of table \"%s\" (OID %u) not found\n",
partinfo[i].partparent,
self->dobj.name,
oid);
exit_nicely(1);
}
self->partitionOf = parent;
/* While we're at it, also save the partdef */
self->partitiondef = partinfo[i].partdef;
}
}
}
/* /*
* parseOidArray * parseOidArray
* parse a string of numbers delimited by spaces into a character array * parse a string of numbers delimited by spaces into a character array
......
...@@ -5507,6 +5507,9 @@ getTables(Archive *fout, int *numTables) ...@@ -5507,6 +5507,9 @@ getTables(Archive *fout, int *numTables)
int i_relpages; int i_relpages;
int i_is_identity_sequence; int i_is_identity_sequence;
int i_changed_acl; int i_changed_acl;
int i_partkeydef;
int i_ispartition;
int i_partbound;
/* Make sure we are in proper schema */ /* Make sure we are in proper schema */
selectSourceSchema(fout, "pg_catalog"); selectSourceSchema(fout, "pg_catalog");
...@@ -5533,6 +5536,10 @@ getTables(Archive *fout, int *numTables) ...@@ -5533,6 +5536,10 @@ getTables(Archive *fout, int *numTables)
if (fout->remoteVersion >= 90600) if (fout->remoteVersion >= 90600)
{ {
char *partkeydef = "NULL";
char *ispartition = "false";
char *partbound = "NULL";
PQExpBuffer acl_subquery = createPQExpBuffer(); PQExpBuffer acl_subquery = createPQExpBuffer();
PQExpBuffer racl_subquery = createPQExpBuffer(); PQExpBuffer racl_subquery = createPQExpBuffer();
PQExpBuffer initacl_subquery = createPQExpBuffer(); PQExpBuffer initacl_subquery = createPQExpBuffer();
...@@ -5543,6 +5550,18 @@ getTables(Archive *fout, int *numTables) ...@@ -5543,6 +5550,18 @@ getTables(Archive *fout, int *numTables)
PQExpBuffer attinitacl_subquery = createPQExpBuffer(); PQExpBuffer attinitacl_subquery = createPQExpBuffer();
PQExpBuffer attinitracl_subquery = createPQExpBuffer(); PQExpBuffer attinitracl_subquery = createPQExpBuffer();
/*
* Collect the information about any partitioned tables, which were
* added in PG10.
*/
if (fout->remoteVersion >= 100000)
{
partkeydef = "pg_get_partkeydef(c.oid)";
ispartition = "c.relispartition";
partbound = "pg_get_expr(c.relpartbound, c.oid)";
}
/* /*
* Left join to pick up dependency info linking sequences to their * Left join to pick up dependency info linking sequences to their
* owning column, if any (note this dependency is AUTO as of 8.2) * owning column, if any (note this dependency is AUTO as of 8.2)
...@@ -5594,7 +5613,10 @@ getTables(Archive *fout, int *numTables) ...@@ -5594,7 +5613,10 @@ getTables(Archive *fout, int *numTables)
"OR %s IS NOT NULL " "OR %s IS NOT NULL "
"OR %s IS NOT NULL" "OR %s IS NOT NULL"
"))" "))"
"AS changed_acl " "AS changed_acl, "
"%s AS partkeydef, "
"%s AS ispartition, "
"%s AS partbound "
"FROM pg_class c " "FROM pg_class c "
"LEFT JOIN pg_depend d ON " "LEFT JOIN pg_depend d ON "
"(c.relkind = '%c' AND " "(c.relkind = '%c' AND "
...@@ -5618,6 +5640,9 @@ getTables(Archive *fout, int *numTables) ...@@ -5618,6 +5640,9 @@ getTables(Archive *fout, int *numTables)
attracl_subquery->data, attracl_subquery->data,
attinitacl_subquery->data, attinitacl_subquery->data,
attinitracl_subquery->data, attinitracl_subquery->data,
partkeydef,
ispartition,
partbound,
RELKIND_SEQUENCE, RELKIND_SEQUENCE,
RELKIND_RELATION, RELKIND_SEQUENCE, RELKIND_RELATION, RELKIND_SEQUENCE,
RELKIND_VIEW, RELKIND_COMPOSITE_TYPE, RELKIND_VIEW, RELKIND_COMPOSITE_TYPE,
...@@ -5663,7 +5688,10 @@ getTables(Archive *fout, int *numTables) ...@@ -5663,7 +5688,10 @@ getTables(Archive *fout, int *numTables)
"CASE WHEN 'check_option=local' = ANY (c.reloptions) THEN 'LOCAL'::text " "CASE WHEN 'check_option=local' = ANY (c.reloptions) THEN 'LOCAL'::text "
"WHEN 'check_option=cascaded' = ANY (c.reloptions) THEN 'CASCADED'::text ELSE NULL END AS checkoption, " "WHEN 'check_option=cascaded' = ANY (c.reloptions) THEN 'CASCADED'::text ELSE NULL END AS checkoption, "
"tc.reloptions AS toast_reloptions, " "tc.reloptions AS toast_reloptions, "
"NULL AS changed_acl " "NULL AS changed_acl, "
"NULL AS partkeydef, "
"false AS ispartition, "
"NULL AS partbound "
"FROM pg_class c " "FROM pg_class c "
"LEFT JOIN pg_depend d ON " "LEFT JOIN pg_depend d ON "
"(c.relkind = '%c' AND " "(c.relkind = '%c' AND "
...@@ -5709,7 +5737,10 @@ getTables(Archive *fout, int *numTables) ...@@ -5709,7 +5737,10 @@ getTables(Archive *fout, int *numTables)
"CASE WHEN 'check_option=local' = ANY (c.reloptions) THEN 'LOCAL'::text " "CASE WHEN 'check_option=local' = ANY (c.reloptions) THEN 'LOCAL'::text "
"WHEN 'check_option=cascaded' = ANY (c.reloptions) THEN 'CASCADED'::text ELSE NULL END AS checkoption, " "WHEN 'check_option=cascaded' = ANY (c.reloptions) THEN 'CASCADED'::text ELSE NULL END AS checkoption, "
"tc.reloptions AS toast_reloptions, " "tc.reloptions AS toast_reloptions, "
"NULL AS changed_acl " "NULL AS changed_acl, "
"NULL AS partkeydef, "
"false AS ispartition, "
"NULL AS partbound "
"FROM pg_class c " "FROM pg_class c "
"LEFT JOIN pg_depend d ON " "LEFT JOIN pg_depend d ON "
"(c.relkind = '%c' AND " "(c.relkind = '%c' AND "
...@@ -5755,7 +5786,10 @@ getTables(Archive *fout, int *numTables) ...@@ -5755,7 +5786,10 @@ getTables(Archive *fout, int *numTables)
"CASE WHEN 'check_option=local' = ANY (c.reloptions) THEN 'LOCAL'::text " "CASE WHEN 'check_option=local' = ANY (c.reloptions) THEN 'LOCAL'::text "
"WHEN 'check_option=cascaded' = ANY (c.reloptions) THEN 'CASCADED'::text ELSE NULL END AS checkoption, " "WHEN 'check_option=cascaded' = ANY (c.reloptions) THEN 'CASCADED'::text ELSE NULL END AS checkoption, "
"tc.reloptions AS toast_reloptions, " "tc.reloptions AS toast_reloptions, "
"NULL AS changed_acl " "NULL AS changed_acl, "
"NULL AS partkeydef, "
"false AS ispartition, "
"NULL AS partbound "
"FROM pg_class c " "FROM pg_class c "
"LEFT JOIN pg_depend d ON " "LEFT JOIN pg_depend d ON "
"(c.relkind = '%c' AND " "(c.relkind = '%c' AND "
...@@ -5799,7 +5833,10 @@ getTables(Archive *fout, int *numTables) ...@@ -5799,7 +5833,10 @@ getTables(Archive *fout, int *numTables)
"(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, " "(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, "
"c.reloptions AS reloptions, " "c.reloptions AS reloptions, "
"tc.reloptions AS toast_reloptions, " "tc.reloptions AS toast_reloptions, "
"NULL AS changed_acl " "NULL AS changed_acl, "
"NULL AS partkeydef, "
"false AS ispartition, "
"NULL AS partbound "
"FROM pg_class c " "FROM pg_class c "
"LEFT JOIN pg_depend d ON " "LEFT JOIN pg_depend d ON "
"(c.relkind = '%c' AND " "(c.relkind = '%c' AND "
...@@ -5843,7 +5880,10 @@ getTables(Archive *fout, int *numTables) ...@@ -5843,7 +5880,10 @@ getTables(Archive *fout, int *numTables)
"(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, " "(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, "
"c.reloptions AS reloptions, " "c.reloptions AS reloptions, "
"tc.reloptions AS toast_reloptions, " "tc.reloptions AS toast_reloptions, "
"NULL AS changed_acl " "NULL AS changed_acl, "
"NULL AS partkeydef, "
"false AS ispartition, "
"NULL AS partbound "
"FROM pg_class c " "FROM pg_class c "
"LEFT JOIN pg_depend d ON " "LEFT JOIN pg_depend d ON "
"(c.relkind = '%c' AND " "(c.relkind = '%c' AND "
...@@ -5886,7 +5926,10 @@ getTables(Archive *fout, int *numTables) ...@@ -5886,7 +5926,10 @@ getTables(Archive *fout, int *numTables)
"(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, " "(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, "
"c.reloptions AS reloptions, " "c.reloptions AS reloptions, "
"tc.reloptions AS toast_reloptions, " "tc.reloptions AS toast_reloptions, "
"NULL AS changed_acl " "NULL AS changed_acl, "
"NULL AS partkeydef, "
"false AS ispartition, "
"NULL AS partbound "
"FROM pg_class c " "FROM pg_class c "
"LEFT JOIN pg_depend d ON " "LEFT JOIN pg_depend d ON "
"(c.relkind = '%c' AND " "(c.relkind = '%c' AND "
...@@ -5929,7 +5972,10 @@ getTables(Archive *fout, int *numTables) ...@@ -5929,7 +5972,10 @@ getTables(Archive *fout, int *numTables)
"(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, " "(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, "
"c.reloptions AS reloptions, " "c.reloptions AS reloptions, "
"NULL AS toast_reloptions, " "NULL AS toast_reloptions, "
"NULL AS changed_acl " "NULL AS changed_acl, "
"NULL AS partkeydef, "
"false AS ispartition, "
"NULL AS partbound "
"FROM pg_class c " "FROM pg_class c "
"LEFT JOIN pg_depend d ON " "LEFT JOIN pg_depend d ON "
"(c.relkind = '%c' AND " "(c.relkind = '%c' AND "
...@@ -5971,7 +6017,10 @@ getTables(Archive *fout, int *numTables) ...@@ -5971,7 +6017,10 @@ getTables(Archive *fout, int *numTables)
"(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, " "(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, "
"NULL AS reloptions, " "NULL AS reloptions, "
"NULL AS toast_reloptions, " "NULL AS toast_reloptions, "
"NULL AS changed_acl " "NULL AS changed_acl, "
"NULL AS partkeydef, "
"false AS ispartition, "
"NULL AS partbound "
"FROM pg_class c " "FROM pg_class c "
"LEFT JOIN pg_depend d ON " "LEFT JOIN pg_depend d ON "
"(c.relkind = '%c' AND " "(c.relkind = '%c' AND "
...@@ -6038,6 +6087,9 @@ getTables(Archive *fout, int *numTables) ...@@ -6038,6 +6087,9 @@ getTables(Archive *fout, int *numTables)
i_reloftype = PQfnumber(res, "reloftype"); i_reloftype = PQfnumber(res, "reloftype");
i_is_identity_sequence = PQfnumber(res, "is_identity_sequence"); i_is_identity_sequence = PQfnumber(res, "is_identity_sequence");
i_changed_acl = PQfnumber(res, "changed_acl"); i_changed_acl = PQfnumber(res, "changed_acl");
i_partkeydef = PQfnumber(res, "partkeydef");
i_ispartition = PQfnumber(res, "ispartition");
i_partbound = PQfnumber(res, "partbound");
if (dopt->lockWaitTimeout) if (dopt->lockWaitTimeout)
{ {
...@@ -6140,6 +6192,11 @@ getTables(Archive *fout, int *numTables) ...@@ -6140,6 +6192,11 @@ getTables(Archive *fout, int *numTables)
tblinfo[i].is_identity_sequence = (i_is_identity_sequence >= 0 && tblinfo[i].is_identity_sequence = (i_is_identity_sequence >= 0 &&
strcmp(PQgetvalue(res, i, i_is_identity_sequence), "t") == 0); strcmp(PQgetvalue(res, i, i_is_identity_sequence), "t") == 0);
/* Partition key string or NULL */
tblinfo[i].partkeydef = pg_strdup(PQgetvalue(res, i, i_partkeydef));
tblinfo[i].ispartition = (strcmp(PQgetvalue(res, i, i_ispartition), "t") == 0);
tblinfo[i].partbound = pg_strdup(PQgetvalue(res, i, i_partbound));
/* /*
* Read-lock target tables to make sure they aren't DROPPED or altered * Read-lock target tables to make sure they aren't DROPPED or altered
* in schema before we get around to dumping them. * in schema before we get around to dumping them.
...@@ -6265,11 +6322,7 @@ getInherits(Archive *fout, int *numInherits) ...@@ -6265,11 +6322,7 @@ getInherits(Archive *fout, int *numInherits)
* we want more information about partitions than just the parent-child * we want more information about partitions than just the parent-child
* relationship. * relationship.
*/ */
appendPQExpBufferStr(query, appendPQExpBufferStr(query, "SELECT inhrelid, inhparent FROM pg_inherits");
"SELECT inhrelid, inhparent "
"FROM pg_inherits "
"WHERE inhparent NOT IN (SELECT oid FROM pg_class "
"WHERE relkind = " CppAsString2(RELKIND_PARTITIONED_TABLE) ")");
res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK); res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
...@@ -6295,72 +6348,6 @@ getInherits(Archive *fout, int *numInherits) ...@@ -6295,72 +6348,6 @@ getInherits(Archive *fout, int *numInherits)
return inhinfo; return inhinfo;
} }
/*
* getPartitions
* read all the partition inheritance and partition bound information
* from the system catalogs return them in the PartInfo* structure
*
* numPartitions is set to the number of pairs read in
*/
PartInfo *
getPartitions(Archive *fout, int *numPartitions)
{
PGresult *res;
int ntups;
int i;
PQExpBuffer query;
PartInfo *partinfo;
int i_partrelid;
int i_partparent;
int i_partbound;
/* Before version 10, there are no partitions */
if (fout->remoteVersion < 100000)
{
*numPartitions = 0;
return NULL;
}
query = createPQExpBuffer();
/* Make sure we are in proper schema */
selectSourceSchema(fout, "pg_catalog");
/* find the inheritance and boundary information about partitions */
appendPQExpBufferStr(query,
"SELECT inhrelid as partrelid, inhparent AS partparent,"
" pg_get_expr(relpartbound, inhrelid) AS partbound"
" FROM pg_class c, pg_inherits"
" WHERE c.oid = inhrelid AND c.relispartition");
res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
ntups = PQntuples(res);
*numPartitions = ntups;
partinfo = (PartInfo *) pg_malloc(ntups * sizeof(PartInfo));
i_partrelid = PQfnumber(res, "partrelid");
i_partparent = PQfnumber(res, "partparent");
i_partbound = PQfnumber(res, "partbound");
for (i = 0; i < ntups; i++)
{
partinfo[i].partrelid = atooid(PQgetvalue(res, i, i_partrelid));
partinfo[i].partparent = atooid(PQgetvalue(res, i, i_partparent));
partinfo[i].partdef = pg_strdup(PQgetvalue(res, i, i_partbound));
}
PQclear(res);
destroyPQExpBuffer(query);
return partinfo;
}
/* /*
* getIndexes * getIndexes
* get information about every index on a dumpable table * get information about every index on a dumpable table
...@@ -7729,49 +7716,6 @@ getTransforms(Archive *fout, int *numTransforms) ...@@ -7729,49 +7716,6 @@ getTransforms(Archive *fout, int *numTransforms)
return transforminfo; return transforminfo;
} }
/*
* getTablePartitionKeyInfo -
* for each interesting partitioned table, read information about its
* partition key
*
* modifies tblinfo
*/
void
getTablePartitionKeyInfo(Archive *fout, TableInfo *tblinfo, int numTables)
{
PQExpBuffer q;
int i;
PGresult *res;
/* No partitioned tables before 10 */
if (fout->remoteVersion < 100000)
return;
q = createPQExpBuffer();
for (i = 0; i < numTables; i++)
{
TableInfo *tbinfo = &(tblinfo[i]);
/* Only partitioned tables have partition key */
if (tbinfo->relkind != RELKIND_PARTITIONED_TABLE)
continue;
/* Don't bother computing anything for non-target tables, either */
if (!tbinfo->dobj.dump)
continue;
resetPQExpBuffer(q);
appendPQExpBuffer(q, "SELECT pg_catalog.pg_get_partkeydef('%u'::pg_catalog.oid)",
tbinfo->dobj.catId.oid);
res = ExecuteSqlQuery(fout, q->data, PGRES_TUPLES_OK);
Assert(PQntuples(res) == 1);
tbinfo->partkeydef = pg_strdup(PQgetvalue(res, 0, 0));
}
destroyPQExpBuffer(q);
}
/* /*
* getTableAttrs - * getTableAttrs -
* for each interesting table, read info about its attributes * for each interesting table, read info about its attributes
...@@ -15196,9 +15140,22 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo) ...@@ -15196,9 +15140,22 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
if (tbinfo->reloftype && !dopt->binary_upgrade) if (tbinfo->reloftype && !dopt->binary_upgrade)
appendPQExpBuffer(q, " OF %s", tbinfo->reloftype); appendPQExpBuffer(q, " OF %s", tbinfo->reloftype);
if (tbinfo->partitionOf && !dopt->binary_upgrade) /*
* If the table is a partition, dump it as such; except in the case
* of a binary upgrade, we dump the table normally and attach it to
* the parent afterward.
*/
if (tbinfo->ispartition && !dopt->binary_upgrade)
{ {
TableInfo *parentRel = tbinfo->partitionOf; TableInfo *parentRel = tbinfo->parents[0];
/*
* With partitions, unlike inheritance, there can only be one
* parent.
*/
if (tbinfo->numParents != 1)
exit_horribly(NULL, "invalid number of parents %d for table \"%s\"\n",
tbinfo->numParents, tbinfo->dobj.name);
appendPQExpBuffer(q, " PARTITION OF "); appendPQExpBuffer(q, " PARTITION OF ");
if (parentRel->dobj.namespace != tbinfo->dobj.namespace) if (parentRel->dobj.namespace != tbinfo->dobj.namespace)
...@@ -15239,7 +15196,7 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo) ...@@ -15239,7 +15196,7 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
* Skip column if fully defined by reloftype or the * Skip column if fully defined by reloftype or the
* partition parent. * partition parent.
*/ */
if ((tbinfo->reloftype || tbinfo->partitionOf) && if ((tbinfo->reloftype || tbinfo->ispartition) &&
!has_default && !has_notnull && !dopt->binary_upgrade) !has_default && !has_notnull && !dopt->binary_upgrade)
continue; continue;
...@@ -15276,7 +15233,7 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo) ...@@ -15276,7 +15233,7 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
* partition ('PARTITION OF'), since the type comes from * partition ('PARTITION OF'), since the type comes from
* the parent/partitioned table. * the parent/partitioned table.
*/ */
if (dopt->binary_upgrade || (!tbinfo->reloftype && !tbinfo->partitionOf)) if (dopt->binary_upgrade || (!tbinfo->reloftype && !tbinfo->ispartition))
{ {
appendPQExpBuffer(q, " %s", appendPQExpBuffer(q, " %s",
tbinfo->atttypnames[j]); tbinfo->atttypnames[j]);
...@@ -15330,7 +15287,7 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo) ...@@ -15330,7 +15287,7 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
if (actual_atts) if (actual_atts)
appendPQExpBufferStr(q, "\n)"); appendPQExpBufferStr(q, "\n)");
else if (!((tbinfo->reloftype || tbinfo->partitionOf) && else if (!((tbinfo->reloftype || tbinfo->ispartition) &&
!dopt->binary_upgrade)) !dopt->binary_upgrade))
{ {
/* /*
...@@ -15340,13 +15297,16 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo) ...@@ -15340,13 +15297,16 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
appendPQExpBufferStr(q, " (\n)"); appendPQExpBufferStr(q, " (\n)");
} }
if (tbinfo->partitiondef && !dopt->binary_upgrade) if (tbinfo->ispartition && !dopt->binary_upgrade)
{ {
appendPQExpBufferStr(q, "\n"); appendPQExpBufferStr(q, "\n");
appendPQExpBufferStr(q, tbinfo->partitiondef); appendPQExpBufferStr(q, tbinfo->partbound);
} }
if (numParents > 0 && !dopt->binary_upgrade) /* Emit the INHERITS clause, except if this is a partition. */
if (numParents > 0 &&
!tbinfo->ispartition &&
!dopt->binary_upgrade)
{ {
appendPQExpBufferStr(q, "\nINHERITS ("); appendPQExpBufferStr(q, "\nINHERITS (");
for (k = 0; k < numParents; k++) for (k = 0; k < numParents; k++)
...@@ -15492,18 +15452,38 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo) ...@@ -15492,18 +15452,38 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
if (numParents > 0) if (numParents > 0)
{ {
appendPQExpBufferStr(q, "\n-- For binary upgrade, set up inheritance this way.\n"); appendPQExpBufferStr(q, "\n-- For binary upgrade, set up inheritance and partitioning this way.\n");
for (k = 0; k < numParents; k++) for (k = 0; k < numParents; k++)
{ {
TableInfo *parentRel = parents[k]; TableInfo *parentRel = parents[k];
PQExpBuffer parentname = createPQExpBuffer();
appendPQExpBuffer(q, "ALTER TABLE ONLY %s INHERIT ", /* Schema-qualify the parent table, if necessary */
fmtId(tbinfo->dobj.name));
if (parentRel->dobj.namespace != tbinfo->dobj.namespace) if (parentRel->dobj.namespace != tbinfo->dobj.namespace)
appendPQExpBuffer(q, "%s.", appendPQExpBuffer(parentname, "%s.",
fmtId(parentRel->dobj.namespace->dobj.name)); fmtId(parentRel->dobj.namespace->dobj.name));
appendPQExpBuffer(q, "%s;\n",
appendPQExpBuffer(parentname, "%s",
fmtId(parentRel->dobj.name)); fmtId(parentRel->dobj.name));
/* In the partitioning case, we alter the parent */
if (tbinfo->ispartition)
appendPQExpBuffer(q,
"ALTER TABLE ONLY %s ATTACH PARTITION ",
parentname->data);
else
appendPQExpBuffer(q, "ALTER TABLE ONLY %s INHERIT ",
fmtId(tbinfo->dobj.name));
/* Partition needs specifying the bounds */
if (tbinfo->ispartition)
appendPQExpBuffer(q, "%s %s;\n",
fmtId(tbinfo->dobj.name),
tbinfo->partbound);
else
appendPQExpBuffer(q, "%s;\n", parentname->data);
destroyPQExpBuffer(parentname);
} }
} }
...@@ -15515,16 +15495,6 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo) ...@@ -15515,16 +15495,6 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
tbinfo->reloftype); tbinfo->reloftype);
} }
if (tbinfo->partitionOf)
{
appendPQExpBufferStr(q, "\n-- For binary upgrade, set up partitions this way.\n");
appendPQExpBuffer(q, "ALTER TABLE ONLY %s ",
fmtId(tbinfo->partitionOf->dobj.name));
appendPQExpBuffer(q, "ATTACH PARTITION %s %s;\n",
fmtId(tbinfo->dobj.name),
tbinfo->partitiondef);
}
appendPQExpBufferStr(q, "\n-- For binary upgrade, set heap's relfrozenxid and relminmxid\n"); appendPQExpBufferStr(q, "\n-- For binary upgrade, set heap's relfrozenxid and relminmxid\n");
appendPQExpBuffer(q, "UPDATE pg_catalog.pg_class\n" appendPQExpBuffer(q, "UPDATE pg_catalog.pg_class\n"
"SET relfrozenxid = '%u', relminmxid = '%u'\n" "SET relfrozenxid = '%u', relminmxid = '%u'\n"
......
...@@ -294,6 +294,7 @@ typedef struct _tableInfo ...@@ -294,6 +294,7 @@ typedef struct _tableInfo
bool interesting; /* true if need to collect more data */ bool interesting; /* true if need to collect more data */
bool dummy_view; /* view's real definition must be postponed */ bool dummy_view; /* view's real definition must be postponed */
bool postponed_def; /* matview must be postponed into post-data */ bool postponed_def; /* matview must be postponed into post-data */
bool ispartition; /* is table a partition? */
/* /*
* These fields are computed only if we decide the table is interesting * These fields are computed only if we decide the table is interesting
...@@ -319,6 +320,7 @@ typedef struct _tableInfo ...@@ -319,6 +320,7 @@ typedef struct _tableInfo
struct _attrDefInfo **attrdefs; /* DEFAULT expressions */ struct _attrDefInfo **attrdefs; /* DEFAULT expressions */
struct _constraintInfo *checkexprs; /* CHECK constraints */ struct _constraintInfo *checkexprs; /* CHECK constraints */
char *partkeydef; /* partition key definition */ char *partkeydef; /* partition key definition */
char *partbound; /* partition bound definition */
bool needs_override; /* has GENERATED ALWAYS AS IDENTITY */ bool needs_override; /* has GENERATED ALWAYS AS IDENTITY */
/* /*
...@@ -329,8 +331,6 @@ typedef struct _tableInfo ...@@ -329,8 +331,6 @@ typedef struct _tableInfo
struct _tableDataInfo *dataObj; /* TableDataInfo, if dumping its data */ struct _tableDataInfo *dataObj; /* TableDataInfo, if dumping its data */
int numTriggers; /* number of triggers for table */ int numTriggers; /* number of triggers for table */
struct _triggerInfo *triggers; /* array of TriggerInfo structs */ struct _triggerInfo *triggers; /* array of TriggerInfo structs */
struct _tableInfo *partitionOf; /* TableInfo for the partition parent */
char *partitiondef; /* partition key definition */
} TableInfo; } TableInfo;
typedef struct _attrDefInfo typedef struct _attrDefInfo
...@@ -476,15 +476,6 @@ typedef struct _inhInfo ...@@ -476,15 +476,6 @@ typedef struct _inhInfo
Oid inhparent; /* OID of its parent */ Oid inhparent; /* OID of its parent */
} InhInfo; } InhInfo;
/* PartInfo isn't a DumpableObject, just temporary state */
typedef struct _partInfo
{
Oid partrelid; /* OID of a partition */
Oid partparent; /* OID of its parent */
char *partdef; /* partition bound definition */
} PartInfo;
typedef struct _prsInfo typedef struct _prsInfo
{ {
DumpableObject dobj; DumpableObject dobj;
...@@ -691,7 +682,6 @@ extern ConvInfo *getConversions(Archive *fout, int *numConversions); ...@@ -691,7 +682,6 @@ extern ConvInfo *getConversions(Archive *fout, int *numConversions);
extern TableInfo *getTables(Archive *fout, int *numTables); extern TableInfo *getTables(Archive *fout, int *numTables);
extern void getOwnedSeqs(Archive *fout, TableInfo tblinfo[], int numTables); extern void getOwnedSeqs(Archive *fout, TableInfo tblinfo[], int numTables);
extern InhInfo *getInherits(Archive *fout, int *numInherits); extern InhInfo *getInherits(Archive *fout, int *numInherits);
extern PartInfo *getPartitions(Archive *fout, int *numPartitions);
extern void getIndexes(Archive *fout, TableInfo tblinfo[], int numTables); extern void getIndexes(Archive *fout, TableInfo tblinfo[], int numTables);
extern void getExtendedStatistics(Archive *fout, TableInfo tblinfo[], int numTables); extern void getExtendedStatistics(Archive *fout, TableInfo tblinfo[], int numTables);
extern void getConstraints(Archive *fout, TableInfo tblinfo[], int numTables); extern void getConstraints(Archive *fout, TableInfo tblinfo[], int numTables);
...@@ -717,7 +707,6 @@ extern void processExtensionTables(Archive *fout, ExtensionInfo extinfo[], ...@@ -717,7 +707,6 @@ extern void processExtensionTables(Archive *fout, ExtensionInfo extinfo[],
int numExtensions); int numExtensions);
extern EventTriggerInfo *getEventTriggers(Archive *fout, int *numEventTriggers); extern EventTriggerInfo *getEventTriggers(Archive *fout, int *numEventTriggers);
extern void getPolicies(Archive *fout, TableInfo tblinfo[], int numTables); extern void getPolicies(Archive *fout, TableInfo tblinfo[], int numTables);
extern void getTablePartitionKeyInfo(Archive *fout, TableInfo *tblinfo, int numTables);
extern void getPublications(Archive *fout); extern void getPublications(Archive *fout);
extern void getPublicationTables(Archive *fout, TableInfo tblinfo[], extern void getPublicationTables(Archive *fout, TableInfo tblinfo[],
int numTables); int numTables);
......
...@@ -1049,6 +1049,40 @@ my %tests = ( ...@@ -1049,6 +1049,40 @@ my %tests = (
section_post_data => 1, section_post_data => 1,
section_data => 1, }, }, section_data => 1, }, },
'ALTER TABLE ONLY dump_test.measurement ATTACH PARTITION measurement_y2006m2' => {
all_runs => 1,
regexp => qr/^
\QALTER TABLE ONLY dump_test.measurement ATTACH PARTITION measurement_y2006m2 \E
\QFOR VALUES FROM ('2006-02-01') TO ('2006-03-01');\E\n
/xm,
like => {
binary_upgrade => 1, },
unlike => {
clean => 1,
clean_if_exists => 1,
createdb => 1,
defaults => 1,
exclude_dump_test_schema => 1,
exclude_test_table => 1,
exclude_test_table_data => 1,
no_blobs => 1,
no_privs => 1,
no_owner => 1,
pg_dumpall_dbprivs => 1,
role => 1,
schema_only => 1,
section_pre_data => 1,
with_oids => 1,
only_dump_test_schema => 1,
only_dump_test_table => 1,
pg_dumpall_globals => 1,
pg_dumpall_globals_clean => 1,
section_post_data => 1,
test_schema_plus_blobs => 1,
column_inserts => 1,
data_only => 1,
section_data => 1, }, },
'ALTER TABLE test_table CLUSTER ON test_table_pkey' => { 'ALTER TABLE test_table CLUSTER ON test_table_pkey' => {
all_runs => 1, all_runs => 1,
catch_all => 'ALTER TABLE ... commands', catch_all => 'ALTER TABLE ... commands',
...@@ -4764,8 +4798,6 @@ qr/CREATE TRANSFORM FOR integer LANGUAGE sql \(FROM SQL WITH FUNCTION pg_catalog ...@@ -4764,8 +4798,6 @@ qr/CREATE TRANSFORM FOR integer LANGUAGE sql \(FROM SQL WITH FUNCTION pg_catalog
\Q--\E\n\n \Q--\E\n\n
\QCREATE TABLE measurement_y2006m2 PARTITION OF dump_test.measurement\E\n \QCREATE TABLE measurement_y2006m2 PARTITION OF dump_test.measurement\E\n
\QFOR VALUES FROM ('2006-02-01') TO ('2006-03-01');\E\n \QFOR VALUES FROM ('2006-02-01') TO ('2006-03-01');\E\n
\QALTER TABLE ONLY measurement_y2006m2 ALTER COLUMN city_id SET NOT NULL;\E\n
\QALTER TABLE ONLY measurement_y2006m2 ALTER COLUMN logdate SET NOT NULL;\E\n
/xm, /xm,
like => { like => {
clean => 1, clean => 1,
......
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