Skip to content

Commit cc320a7

Browse files
committed
Support for pg_dump to dump tables in cluster order if a clustered index is defined on the table, a little hacked in with how the data is passed around and how the order is pulled out of the db. The latter is the only semi-problematic part as you might be able to generate (very odd) table column names that would break the regex used there which would cause the sql query to be invalid and therefore not dump data for that table. But as long as you don't name an clustered column/function something like "foo ) WHERE" or the like should be ok.
Pulled from REL9_1_2_P and fixed some merge conflicts Conflicts: src/bin/pg_dump/pg_dump.c
1 parent 73c1227 commit cc320a7

File tree

2 files changed

+45
-4
lines changed

2 files changed

+45
-4
lines changed

src/bin/pg_dump/pg_dump.c

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ static const CatalogId nilCatalogId = {0, 0};
133133
static int binary_upgrade = 0;
134134
static int disable_dollar_quoting = 0;
135135
static int dump_inserts = 0;
136+
static int cluster_order = 0;
136137
static int column_inserts = 0;
137138
static int no_security_labels = 0;
138139
static int no_unlogged_table_data = 0;
@@ -336,6 +337,7 @@ main(int argc, char **argv)
336337
*/
337338
{"attribute-inserts", no_argument, &column_inserts, 1},
338339
{"binary-upgrade", no_argument, &binary_upgrade, 1},
340+
{"cluster-order", no_argument, &cluster_order, 1},
339341
{"column-inserts", no_argument, &column_inserts, 1},
340342
{"disable-dollar-quoting", no_argument, &disable_dollar_quoting, 1},
341343
{"disable-triggers", no_argument, &disable_triggers, 1},
@@ -848,6 +850,7 @@ help(const char *progname)
848850
printf(_(" -T, --exclude-table=TABLE do NOT dump the named table(s)\n"));
849851
printf(_(" -x, --no-privileges do not dump privileges (grant/revoke)\n"));
850852
printf(_(" --binary-upgrade for use by upgrade utilities only\n"));
853+
printf(_(" --cluster-order dump table data in clustered index order (>= 8.2)\n"));
851854
printf(_(" --column-inserts dump data as INSERT commands with column names\n"));
852855
printf(_(" --disable-dollar-quoting disable dollar quoting, use SQL standard quoting\n"));
853856
printf(_(" --disable-triggers disable triggers during data-only restore\n"));
@@ -1296,7 +1299,7 @@ dumpTableData_copy(Archive *fout, void *dcontext)
12961299
classname),
12971300
column_list);
12981301
}
1299-
else if (tdinfo->filtercond)
1302+
else if (tdinfo->filtercond || tbinfo->ordercond)
13001303
{
13011304
/* Note: this syntax is only supported in 8.2 and up */
13021305
appendPQExpBufferStr(q, "COPY (SELECT ");
@@ -1308,11 +1311,15 @@ dumpTableData_copy(Archive *fout, void *dcontext)
13081311
}
13091312
else
13101313
appendPQExpBufferStr(q, "* ");
1311-
appendPQExpBuffer(q, "FROM %s %s) TO stdout;",
1314+
appendPQExpBuffer(q, "FROM %s ",
13121315
fmtQualifiedId(fout,
13131316
tbinfo->dobj.namespace->dobj.name,
1314-
classname),
1315-
tdinfo->filtercond);
1317+
classname));
1318+
if (tdinfo->filtercond)
1319+
appendPQExpBuffer(q, "%s ", tdinfo->filtercond);
1320+
if (tbinfo->ordercond)
1321+
appendPQExpBuffer(q, "%s", tbinfo->ordercond);
1322+
appendPQExpBuffer(q, ") TO stdout;");
13161323
}
13171324
else
13181325
{
@@ -1456,6 +1463,8 @@ dumpTableData_insert(Archive *fout, void *dcontext)
14561463
}
14571464
if (tdinfo->filtercond)
14581465
appendPQExpBuffer(q, " %s", tdinfo->filtercond);
1466+
if (tbinfo->ordercond)
1467+
appendPQExpBuffer(q, " %s", tbinfo->ordercond);
14591468

14601469
ExecuteSqlStatement(fout, q->data);
14611470

@@ -4473,6 +4482,7 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
44734482
i_oid,
44744483
i_indexname,
44754484
i_indexdef,
4485+
i_indexdeforderclause,
44764486
i_indnkeys,
44774487
i_indkey,
44784488
i_indisclustered,
@@ -4528,6 +4538,14 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
45284538
"SELECT t.tableoid, t.oid, "
45294539
"t.relname AS indexname, "
45304540
"pg_catalog.pg_get_indexdef(i.indexrelid) AS indexdef, "
4541+
/*
4542+
* FIXME - regex is not the best way to to do this, but
4543+
* indexdef is consistent enough that it should work
4544+
* Any missing corner cases worth worrying about?
4545+
* A column named "foo ) WITH" would be problematic...
4546+
* but would need a parser to cover all possible cases
4547+
*/
4548+
"CASE WHEN i.indisclustered THEN 'ORDER BY ' || regexp_replace(pg_catalog.pg_get_indexdef(i.indexrelid), E'^CREATE (UNIQUE )?INDEX (CONCURRENTLY )?.* ON .* USING [^\\\\(]*\\\\((.*?)\\\\)($| WITH .*| WHERE .*| TABLESPACE .*)', E'\\\\3') ELSE NULL END AS indexdeforderclause, "
45314549
"t.relnatts AS indnkeys, "
45324550
"i.indkey, i.indisclustered, "
45334551
"c.contype, c.conname, "
@@ -4554,6 +4572,14 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
45544572
"SELECT t.tableoid, t.oid, "
45554573
"t.relname AS indexname, "
45564574
"pg_catalog.pg_get_indexdef(i.indexrelid) AS indexdef, "
4575+
/*
4576+
* FIXME - regex is not the best way to to do this, but
4577+
* indexdef is consistent enough that it should work
4578+
* Any missing corner cases worth worrying about?
4579+
* A column named "foo ) WITH" would be problematic...
4580+
* but would need a parser to cover all possible cases
4581+
*/
4582+
"CASE WHEN i.indisclustered THEN 'ORDER BY ' || regexp_replace(pg_catalog.pg_get_indexdef(i.indexrelid), E'^CREATE (UNIQUE )?INDEX (CONCURRENTLY )?.* ON .* USING [^\\\\(]*\\\\((.*?)\\\\)($| WITH .*| WHERE .*| TABLESPACE .*)', E'\\\\3') ELSE NULL END AS indexdeforderclause, "
45574583
"t.relnatts AS indnkeys, "
45584584
"i.indkey, i.indisclustered, "
45594585
"c.contype, c.conname, "
@@ -4583,6 +4609,7 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
45834609
"SELECT t.tableoid, t.oid, "
45844610
"t.relname AS indexname, "
45854611
"pg_catalog.pg_get_indexdef(i.indexrelid) AS indexdef, "
4612+
"NULL AS indexdeforderclause, "
45864613
"t.relnatts AS indnkeys, "
45874614
"i.indkey, i.indisclustered, "
45884615
"c.contype, c.conname, "
@@ -4611,6 +4638,7 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
46114638
"SELECT t.tableoid, t.oid, "
46124639
"t.relname AS indexname, "
46134640
"pg_catalog.pg_get_indexdef(i.indexrelid) AS indexdef, "
4641+
"NULL AS indexdeforderclause, "
46144642
"t.relnatts AS indnkeys, "
46154643
"i.indkey, i.indisclustered, "
46164644
"c.contype, c.conname, "
@@ -4639,6 +4667,7 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
46394667
"SELECT t.tableoid, t.oid, "
46404668
"t.relname AS indexname, "
46414669
"pg_get_indexdef(i.indexrelid) AS indexdef, "
4670+
"NULL AS indexdeforderclause, "
46424671
"t.relnatts AS indnkeys, "
46434672
"i.indkey, false AS indisclustered, "
46444673
"CASE WHEN i.indisprimary THEN 'p'::char "
@@ -4665,6 +4694,7 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
46654694
"t.oid, "
46664695
"t.relname AS indexname, "
46674696
"pg_get_indexdef(i.indexrelid) AS indexdef, "
4697+
"NULL AS indexdeforderclause, "
46684698
"t.relnatts AS indnkeys, "
46694699
"i.indkey, false AS indisclustered, "
46704700
"CASE WHEN i.indisprimary THEN 'p'::char "
@@ -4692,6 +4722,7 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
46924722
i_oid = PQfnumber(res, "oid");
46934723
i_indexname = PQfnumber(res, "indexname");
46944724
i_indexdef = PQfnumber(res, "indexdef");
4725+
i_indexdeforderclause = PQfnumber(res, "indexdeforderclause");
46954726
i_indnkeys = PQfnumber(res, "indnkeys");
46964727
i_indkey = PQfnumber(res, "indkey");
46974728
i_indisclustered = PQfnumber(res, "indisclustered");
@@ -4779,6 +4810,15 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
47794810
/* Plain secondary index */
47804811
indxinfo[j].indexconstraint = 0;
47814812
}
4813+
4814+
/*
4815+
* propogate table order clause if clustered index for this
4816+
* table and --cluster-order is specified
4817+
*/
4818+
if (cluster_order && fout->remoteVersion >= 80200 &&
4819+
indxinfo[j].indisclustered && !tbinfo->ordercond &&
4820+
PQgetvalue(res, j, i_indexdeforderclause))
4821+
tbinfo->ordercond = strdup(PQgetvalue(res, j, i_indexdeforderclause));
47824822
}
47834823

47844824
PQclear(res);

src/bin/pg_dump/pg_dump.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,7 @@ typedef struct _tableInfo
291291
int numParents; /* number of (immediate) parent tables */
292292
struct _tableInfo **parents; /* TableInfos of immediate parents */
293293
struct _tableDataInfo *dataObj; /* TableDataInfo, if dumping its data */
294+
char *ordercond; /* ORDER condition to order dumped rows, should prob. be in dataObj, but we find it out from the indexes before that's created (though arguably should do it's own query since that's the only way to support --data-only with --cluster-order) */
294295
} TableInfo;
295296

296297
typedef struct _attrDefInfo

0 commit comments

Comments
 (0)