diff options
author | Pavan Deolasee | 2017-04-18 06:57:06 +0000 |
---|---|---|
committer | Pavan Deolasee | 2017-05-05 04:59:34 +0000 |
commit | 69fba376ab646b51e9645b302bc28b2c02d6779a (patch) | |
tree | 6e26be6b15a83cf26239402d8fad9987fc191f1f | |
parent | 5e6562f0edc534d668639694590f2534fbb04a51 (diff) |
Allow pg_dump to dump from PostgreSQL databases.
The current implementation could only dump from XL database, which is not ideal
since we then need to use pg_dump/pg_dumpall from PG installation to dump PG
database. We now check whether the remote server is running XL or PG and then
acoordingly skip XL-specific dumps.
-rw-r--r-- | src/bin/pg_dump/pg_backup.h | 1 | ||||
-rw-r--r-- | src/bin/pg_dump/pg_backup_db.c | 20 | ||||
-rw-r--r-- | src/bin/pg_dump/pg_dump.c | 176 |
3 files changed, 121 insertions, 76 deletions
diff --git a/src/bin/pg_dump/pg_backup.h b/src/bin/pg_dump/pg_backup.h index 4afa92f5f6..82c3baa9f1 100644 --- a/src/bin/pg_dump/pg_backup.h +++ b/src/bin/pg_dump/pg_backup.h @@ -174,6 +174,7 @@ typedef struct Archive char *remoteVersionStr; /* server's version string */ int remoteVersion; /* same in numeric form */ bool isStandby; /* is server a standby node */ + bool isPostgresXL; /* is server a Postgres-XL node */ int minRemoteVersion; /* allowable range */ int maxRemoteVersion; diff --git a/src/bin/pg_dump/pg_backup_db.c b/src/bin/pg_dump/pg_backup_db.c index d2a3de3c5d..d7e776071b 100644 --- a/src/bin/pg_dump/pg_backup_db.c +++ b/src/bin/pg_dump/pg_backup_db.c @@ -73,6 +73,26 @@ _check_database_version(ArchiveHandle *AH) } else AH->public.isStandby = false; + + /* + * Check if we are connected to a Postgres-XL node. We do a pretty basic + * check for existence of pgxc_class table in pg_catalog schema. + * + * We don't think there will be a XC/XL database running anything older + * than 9.1. So only look for server versions great than that. + */ + if (remoteversion >= 90100) + { + res = ExecuteSqlQueryForSingleRow((Archive *) AH, "SELECT EXISTS " + "(SELECT 1 FROM pg_catalog.pg_class where relname = 'pgxc_class' " + "AND relnamespace = (SELECT oid FROM pg_namespace " + "WHERE nspname = 'pg_catalog'))"); + + AH->public.isPostgresXL = (strcmp(PQgetvalue(res, 0, 0), "t") == 0); + PQclear(res); + } + else + AH->public.isPostgresXL = false; } /* diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c index 83c2523408..03ed88732b 100644 --- a/src/bin/pg_dump/pg_dump.c +++ b/src/bin/pg_dump/pg_dump.c @@ -5294,9 +5294,7 @@ getTables(Archive *fout, int *numTables) "d.refobjsubid AS owning_col, " "(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, " #ifdef PGXC - "(SELECT pclocatortype from pgxc_class v where v.pcrelid = c.oid) AS pgxclocatortype," - "(SELECT pcattnum from pgxc_class v where v.pcrelid = c.oid) AS pgxcattnum," - "(SELECT string_agg(node_name,',') AS pgxc_node_names from pgxc_node n where n.oid in (select unnest(nodeoids) from pgxc_class v where v.pcrelid=c.oid) ) , " + "%s" #endif "array_remove(array_remove(c.reloptions,'check_option=local'),'check_option=cascaded') AS reloptions, " "CASE WHEN 'check_option=local' = ANY (c.reloptions) THEN 'LOCAL'::text " @@ -5395,6 +5393,11 @@ getTables(Archive *fout, int *numTables) "WHERE c.relkind in ('%c', '%c', '%c', '%c', '%c', '%c') " "ORDER BY c.oid", username_subquery, + fout->isPostgresXL + ? "(SELECT pclocatortype from pgxc_class v where v.pcrelid = c.oid) AS pgxclocatortype," + "(SELECT pcattnum from pgxc_class v where v.pcrelid = c.oid) AS pgxcattnum," + "(SELECT string_agg(node_name,',') AS pgxc_node_names from pgxc_node n where n.oid in (select unnest(nodeoids) from pgxc_class v where v.pcrelid=c.oid) ) , " + : "", RELKIND_SEQUENCE, RELKIND_RELATION, RELKIND_SEQUENCE, RELKIND_VIEW, RELKIND_COMPOSITE_TYPE, @@ -5427,9 +5430,7 @@ getTables(Archive *fout, int *numTables) "d.refobjsubid AS owning_col, " "(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, " #ifdef PGXC - "(SELECT pclocatortype from pgxc_class v where v.pcrelid = c.oid) AS pgxclocatortype," - "(SELECT pcattnum from pgxc_class v where v.pcrelid = c.oid) AS pgxcattnum," - "(SELECT string_agg(node_name,',') AS pgxc_node_names from pgxc_node n where n.oid in (select unnest(nodeoids) from pgxc_class v where v.pcrelid=c.oid) ) , " + "%s" #endif "array_remove(array_remove(c.reloptions,'check_option=local'),'check_option=cascaded') AS reloptions, " "CASE WHEN 'check_option=local' = ANY (c.reloptions) THEN 'LOCAL'::text " @@ -5446,6 +5447,11 @@ getTables(Archive *fout, int *numTables) "WHERE c.relkind in ('%c', '%c', '%c', '%c', '%c', '%c') " "ORDER BY c.oid", username_subquery, + fout->isPostgresXL + ? "(SELECT pclocatortype from pgxc_class v where v.pcrelid = c.oid) AS pgxclocatortype," + "(SELECT pcattnum from pgxc_class v where v.pcrelid = c.oid) AS pgxcattnum," + "(SELECT string_agg(node_name,',') AS pgxc_node_names from pgxc_node n where n.oid in (select unnest(nodeoids) from pgxc_class v where v.pcrelid=c.oid) ) , " + : "", RELKIND_SEQUENCE, RELKIND_RELATION, RELKIND_SEQUENCE, RELKIND_VIEW, RELKIND_COMPOSITE_TYPE, @@ -5478,9 +5484,7 @@ getTables(Archive *fout, int *numTables) "d.refobjsubid AS owning_col, " "(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, " #ifdef PGXC - "(SELECT pclocatortype from pgxc_class v where v.pcrelid = c.oid) AS pgxclocatortype," - "(SELECT pcattnum from pgxc_class v where v.pcrelid = c.oid) AS pgxcattnum," - "(SELECT string_agg(node_name,',') AS pgxc_node_names from pgxc_node n where n.oid in (select unnest(nodeoids) from pgxc_class v where v.pcrelid=c.oid) ) , " + "%s" #endif "array_remove(array_remove(c.reloptions,'check_option=local'),'check_option=cascaded') AS reloptions, " "CASE WHEN 'check_option=local' = ANY (c.reloptions) THEN 'LOCAL'::text " @@ -5497,6 +5501,11 @@ getTables(Archive *fout, int *numTables) "WHERE c.relkind in ('%c', '%c', '%c', '%c', '%c', '%c') " "ORDER BY c.oid", username_subquery, + fout->isPostgresXL + ? "(SELECT pclocatortype from pgxc_class v where v.pcrelid = c.oid) AS pgxclocatortype," + "(SELECT pcattnum from pgxc_class v where v.pcrelid = c.oid) AS pgxcattnum," + "(SELECT string_agg(node_name,',') AS pgxc_node_names from pgxc_node n where n.oid in (select unnest(nodeoids) from pgxc_class v where v.pcrelid=c.oid) ) , " + : "", RELKIND_SEQUENCE, RELKIND_RELATION, RELKIND_SEQUENCE, RELKIND_VIEW, RELKIND_COMPOSITE_TYPE, @@ -5529,9 +5538,7 @@ getTables(Archive *fout, int *numTables) "d.refobjsubid AS owning_col, " "(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, " #ifdef PGXC - "(SELECT pclocatortype from pgxc_class v where v.pcrelid = c.oid) AS pgxclocatortype," - "(SELECT pcattnum from pgxc_class v where v.pcrelid = c.oid) AS pgxcattnum," - "(SELECT string_agg(node_name,',') AS pgxc_node_names from pgxc_node n where n.oid in (select unnest(nodeoids) from pgxc_class v where v.pcrelid=c.oid) ) , " + "%s" #endif "c.reloptions AS reloptions, " "tc.reloptions AS toast_reloptions, " @@ -5546,6 +5553,11 @@ getTables(Archive *fout, int *numTables) "WHERE c.relkind in ('%c', '%c', '%c', '%c', '%c', '%c') " "ORDER BY c.oid", username_subquery, + fout->isPostgresXL + ? "(SELECT pclocatortype from pgxc_class v where v.pcrelid = c.oid) AS pgxclocatortype," + "(SELECT pcattnum from pgxc_class v where v.pcrelid = c.oid) AS pgxcattnum," + "(SELECT string_agg(node_name,',') AS pgxc_node_names from pgxc_node n where n.oid in (select unnest(nodeoids) from pgxc_class v where v.pcrelid=c.oid) ) , " + : "", RELKIND_SEQUENCE, RELKIND_RELATION, RELKIND_SEQUENCE, RELKIND_VIEW, RELKIND_COMPOSITE_TYPE, @@ -5915,9 +5927,12 @@ getTables(Archive *fout, int *numTables) i_owning_tab = PQfnumber(res, "owning_tab"); i_owning_col = PQfnumber(res, "owning_col"); #ifdef PGXC - i_pgxclocatortype = PQfnumber(res, "pgxclocatortype"); - i_pgxcattnum = PQfnumber(res, "pgxcattnum"); - i_pgxc_node_names = PQfnumber(res, "pgxc_node_names"); + if (fout->isPostgresXL) + { + i_pgxclocatortype = PQfnumber(res, "pgxclocatortype"); + i_pgxcattnum = PQfnumber(res, "pgxcattnum"); + i_pgxc_node_names = PQfnumber(res, "pgxc_node_names"); + } #endif i_reltablespace = PQfnumber(res, "reltablespace"); i_reloptions = PQfnumber(res, "reloptions"); @@ -5989,18 +6004,21 @@ getTables(Archive *fout, int *numTables) tblinfo[i].owning_col = atoi(PQgetvalue(res, i, i_owning_col)); } #ifdef PGXC - /* Not all the tables have pgxc locator Data */ - if (PQgetisnull(res, i, i_pgxclocatortype)) + if (fout->isPostgresXL) { - tblinfo[i].pgxclocatortype = 'E'; - tblinfo[i].pgxcattnum = 0; - } - else - { - tblinfo[i].pgxclocatortype = *(PQgetvalue(res, i, i_pgxclocatortype)); - tblinfo[i].pgxcattnum = atoi(PQgetvalue(res, i, i_pgxcattnum)); + /* Not all the tables have pgxc locator Data */ + if (PQgetisnull(res, i, i_pgxclocatortype)) + { + tblinfo[i].pgxclocatortype = 'E'; + tblinfo[i].pgxcattnum = 0; + } + else + { + tblinfo[i].pgxclocatortype = *(PQgetvalue(res, i, i_pgxclocatortype)); + tblinfo[i].pgxcattnum = atoi(PQgetvalue(res, i, i_pgxcattnum)); + } + tblinfo[i].pgxc_node_names = pg_strdup(PQgetvalue(res, i, i_pgxc_node_names)); } - tblinfo[i].pgxc_node_names = pg_strdup(PQgetvalue(res, i, i_pgxc_node_names)); #endif tblinfo[i].reltablespace = pg_strdup(PQgetvalue(res, i, i_reltablespace)); tblinfo[i].reloptions = pg_strdup(PQgetvalue(res, i, i_reloptions)); @@ -15534,39 +15552,42 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo) } #ifdef PGXC - /* Add the grammar extension linked to PGXC depending on data got from pgxc_class */ - if (tbinfo->pgxclocatortype != 'E') + if (fout->isPostgresXL) { - /* N: DISTRIBUTE BY ROUNDROBIN */ - if (tbinfo->pgxclocatortype == 'N') - { - appendPQExpBuffer(q, "\nDISTRIBUTE BY ROUNDROBIN"); - } - /* R: DISTRIBUTE BY REPLICATED */ - else if (tbinfo->pgxclocatortype == 'R') + /* Add the grammar extension linked to PGXC depending on data got from pgxc_class */ + if (tbinfo->pgxclocatortype != 'E') { - appendPQExpBuffer(q, "\nDISTRIBUTE BY REPLICATION"); - } - /* H: DISTRIBUTE BY HASH */ - else if (tbinfo->pgxclocatortype == 'H') - { - int hashkey = tbinfo->pgxcattnum; - appendPQExpBuffer(q, "\nDISTRIBUTE BY HASH (%s)", - fmtId(tbinfo->attnames[hashkey - 1])); + /* N: DISTRIBUTE BY ROUNDROBIN */ + if (tbinfo->pgxclocatortype == 'N') + { + appendPQExpBuffer(q, "\nDISTRIBUTE BY ROUNDROBIN"); + } + /* R: DISTRIBUTE BY REPLICATED */ + else if (tbinfo->pgxclocatortype == 'R') + { + appendPQExpBuffer(q, "\nDISTRIBUTE BY REPLICATION"); + } + /* H: DISTRIBUTE BY HASH */ + else if (tbinfo->pgxclocatortype == 'H') + { + int hashkey = tbinfo->pgxcattnum; + appendPQExpBuffer(q, "\nDISTRIBUTE BY HASH (%s)", + fmtId(tbinfo->attnames[hashkey - 1])); + } + else if (tbinfo->pgxclocatortype == 'M') + { + int hashkey = tbinfo->pgxcattnum; + appendPQExpBuffer(q, "\nDISTRIBUTE BY MODULO (%s)", + fmtId(tbinfo->attnames[hashkey - 1])); + } } - else if (tbinfo->pgxclocatortype == 'M') + if (include_nodes && + tbinfo->pgxc_node_names != NULL && + tbinfo->pgxc_node_names[0] != '\0') { - int hashkey = tbinfo->pgxcattnum; - appendPQExpBuffer(q, "\nDISTRIBUTE BY MODULO (%s)", - fmtId(tbinfo->attnames[hashkey - 1])); + appendPQExpBuffer(q, "\nTO NODE (%s)", tbinfo->pgxc_node_names); } } - if (include_nodes && - tbinfo->pgxc_node_names != NULL && - tbinfo->pgxc_node_names[0] != '\0') - { - appendPQExpBuffer(q, "\nTO NODE (%s)", tbinfo->pgxc_node_names); - } #endif /* Dump generic options if any */ if (ftoptions && ftoptions[0]) @@ -16664,32 +16685,35 @@ dumpSequenceData(Archive *fout, TableDataInfo *tdinfo) last = PQgetvalue(res, 0, 0); called = (strcmp(PQgetvalue(res, 0, 1), "t") == 0); #ifdef PGXC - /* - * In Postgres-XC it is possible that the current value of a - * sequence cached on each node is different as several sessions - * might use the sequence on different nodes. So what we do here - * to get a consistent dump is to get the next value of sequence. - * This insures that sequence value is unique as nextval is directly - * obtained from GTM. - */ - resetPQExpBuffer(query); - appendPQExpBufferStr(query, "SELECT pg_catalog.nextval("); - appendStringLiteralAH(query, fmtId(tbinfo->dobj.name), fout); - appendPQExpBuffer(query, ");\n"); - res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK); + if (fout->isPostgresXL) + { + /* + * In Postgres-XC it is possible that the current value of a + * sequence cached on each node is different as several sessions + * might use the sequence on different nodes. So what we do here + * to get a consistent dump is to get the next value of sequence. + * This insures that sequence value is unique as nextval is directly + * obtained from GTM. + */ + resetPQExpBuffer(query); + appendPQExpBufferStr(query, "SELECT pg_catalog.nextval("); + appendStringLiteralAH(query, fmtId(tbinfo->dobj.name), fout); + appendPQExpBuffer(query, ");\n"); + res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK); - if (PQntuples(res) != 1) - { - write_msg(NULL, ngettext("query to get nextval of sequence \"%s\" " - "returned %d rows (expected 1)\n", - "query to get nextval of sequence \"%s\" " - "returned %d rows (expected 1)\n", - PQntuples(res)), - tbinfo->dobj.name, PQntuples(res)); - exit_nicely(1); - } + if (PQntuples(res) != 1) + { + write_msg(NULL, ngettext("query to get nextval of sequence \"%s\" " + "returned %d rows (expected 1)\n", + "query to get nextval of sequence \"%s\" " + "returned %d rows (expected 1)\n", + PQntuples(res)), + tbinfo->dobj.name, PQntuples(res)); + exit_nicely(1); + } - last = PQgetvalue(res, 0, 0); + last = PQgetvalue(res, 0, 0); + } #endif resetPQExpBuffer(query); |