aboutsummaryrefslogtreecommitdiff
path: root/src/bin/pg_dump/pg_dump.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/bin/pg_dump/pg_dump.c')
-rw-r--r--src/bin/pg_dump/pg_dump.c390
1 files changed, 389 insertions, 1 deletions
diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index 04758761d4e..ae7233dbf83 100644
--- a/src/bin/pg_dump/pg_dump.c
+++ b/src/bin/pg_dump/pg_dump.c
@@ -12,7 +12,7 @@
* by PostgreSQL
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.508 2008/12/18 18:20:34 tgl Exp $
+ * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.509 2008/12/19 16:25:18 petere Exp $
*
*-------------------------------------------------------------------------
*/
@@ -158,6 +158,11 @@ static void dumpTSParser(Archive *fout, TSParserInfo *prsinfo);
static void dumpTSDictionary(Archive *fout, TSDictInfo *dictinfo);
static void dumpTSTemplate(Archive *fout, TSTemplateInfo *tmplinfo);
static void dumpTSConfig(Archive *fout, TSConfigInfo *cfginfo);
+static void dumpForeignDataWrapper(Archive *fout, FdwInfo *fdwinfo);
+static void dumpForeignServer(Archive *fout, ForeignServerInfo *srvinfo);
+static void dumpUserMappings(Archive *fout, const char *target,
+ const char *servername, const char *namespace,
+ const char *owner, CatalogId catalogId, DumpId dumpId);
static void dumpACL(Archive *fout, CatalogId objCatId, DumpId objDumpId,
const char *type, const char *name,
@@ -5269,6 +5274,165 @@ getTSConfigurations(int *numTSConfigs)
return cfginfo;
}
+/*
+ * getForeignDataWrappers:
+ * read all foreign-data wrappers in the system catalogs and return
+ * them in the FdwInfo* structure
+ *
+ * numForeignDataWrappers is set to the number of fdws read in
+ */
+FdwInfo *
+getForeignDataWrappers(int *numForeignDataWrappers)
+{
+ PGresult *res;
+ int ntups;
+ int i;
+ PQExpBuffer query = createPQExpBuffer();
+ FdwInfo *fdwinfo;
+ int i_oid;
+ int i_fdwname;
+ int i_rolname;
+ int i_fdwlibrary;
+ int i_fdwacl;
+ int i_fdwoptions;
+
+ /* Before 8.4, there are no foreign-data wrappers */
+ if (g_fout->remoteVersion < 80400)
+ {
+ *numForeignDataWrappers = 0;
+ return NULL;
+ }
+
+ /* Make sure we are in proper schema */
+ selectSourceSchema("pg_catalog");
+
+ appendPQExpBuffer(query, "SELECT oid, fdwname, "
+ "(%s fdwowner) as rolname, fdwlibrary, fdwacl,"
+ "array_to_string(ARRAY(select option_name || ' ' || quote_literal(option_value) from pg_options_to_table(fdwoptions)), ', ') AS fdwoptions "
+ "FROM pg_foreign_data_wrapper",
+ username_subquery);
+
+ res = PQexec(g_conn, query->data);
+ check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
+
+ ntups = PQntuples(res);
+ *numForeignDataWrappers = ntups;
+
+ fdwinfo = (FdwInfo *) malloc(ntups * sizeof(FdwInfo));
+
+ i_oid = PQfnumber(res, "oid");
+ i_fdwname = PQfnumber(res, "fdwname");
+ i_rolname = PQfnumber(res, "rolname");
+ i_fdwlibrary = PQfnumber(res, "fdwlibrary");
+ i_fdwacl = PQfnumber(res, "fdwacl");
+ i_fdwoptions = PQfnumber(res, "fdwoptions");
+
+ for (i = 0; i < ntups; i++)
+ {
+ fdwinfo[i].dobj.objType = DO_FDW;
+ fdwinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
+ AssignDumpId(&fdwinfo[i].dobj);
+ fdwinfo[i].dobj.name = strdup(PQgetvalue(res, i, i_fdwname));
+ fdwinfo[i].dobj.namespace = NULL;
+ fdwinfo[i].rolname = strdup(PQgetvalue(res, i, i_rolname));
+ fdwinfo[i].fdwlibrary = strdup(PQgetvalue(res, i, i_fdwlibrary));
+ fdwinfo[i].fdwoptions = strdup(PQgetvalue(res, i, i_fdwoptions));
+ fdwinfo[i].fdwacl = strdup(PQgetvalue(res, i, i_fdwacl));
+
+
+ /* Decide whether we want to dump it */
+ selectDumpableObject(&(fdwinfo[i].dobj));
+ }
+
+ PQclear(res);
+
+ destroyPQExpBuffer(query);
+
+ return fdwinfo;
+}
+
+/*
+ * getForeignServers:
+ * read all foreign servers in the system catalogs and return
+ * them in the ForeignServerInfo * structure
+ *
+ * numForeignServers is set to the number of servers read in
+ */
+ForeignServerInfo *
+getForeignServers(int *numForeignServers)
+{
+ PGresult *res;
+ int ntups;
+ int i;
+ PQExpBuffer query = createPQExpBuffer();
+ ForeignServerInfo *srvinfo;
+ int i_oid;
+ int i_srvname;
+ int i_rolname;
+ int i_srvfdw;
+ int i_srvtype;
+ int i_srvversion;
+ int i_srvacl;
+ int i_srvoptions;
+
+ /* Before 8.4, there are no foreign servers */
+ if (g_fout->remoteVersion < 80400)
+ {
+ *numForeignServers = 0;
+ return NULL;
+ }
+
+ /* Make sure we are in proper schema */
+ selectSourceSchema("pg_catalog");
+
+ appendPQExpBuffer(query, "SELECT oid, srvname, "
+ "(%s srvowner) as rolname, "
+ "srvfdw, srvtype, srvversion, srvacl,"
+ "array_to_string(ARRAY(select option_name || ' ' || quote_literal(option_value) from pg_options_to_table(srvoptions)), ', ') as srvoptions "
+ "FROM pg_foreign_server",
+ username_subquery);
+
+ res = PQexec(g_conn, query->data);
+ check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
+
+ ntups = PQntuples(res);
+ *numForeignServers = ntups;
+
+ srvinfo = (ForeignServerInfo *) malloc(ntups * sizeof(ForeignServerInfo));
+
+ i_oid = PQfnumber(res, "oid");
+ i_srvname = PQfnumber(res, "srvname");
+ i_rolname = PQfnumber(res, "rolname");
+ i_srvfdw = PQfnumber(res, "srvfdw");
+ i_srvtype = PQfnumber(res, "srvtype");
+ i_srvversion = PQfnumber(res, "srvversion");
+ i_srvacl = PQfnumber(res, "srvacl");
+ i_srvoptions = PQfnumber(res, "srvoptions");
+
+ for (i = 0; i < ntups; i++)
+ {
+ srvinfo[i].dobj.objType = DO_FOREIGN_SERVER;
+ srvinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
+ AssignDumpId(&srvinfo[i].dobj);
+ srvinfo[i].dobj.name = strdup(PQgetvalue(res, i, i_srvname));
+ srvinfo[i].dobj.namespace = NULL;
+ srvinfo[i].rolname = strdup(PQgetvalue(res, i, i_rolname));
+ srvinfo[i].srvfdw = atooid(PQgetvalue(res, i, i_srvfdw));
+ srvinfo[i].srvtype = strdup(PQgetvalue(res, i, i_srvtype));
+ srvinfo[i].srvversion = strdup(PQgetvalue(res, i, i_srvversion));
+ srvinfo[i].srvoptions = strdup(PQgetvalue(res, i, i_srvoptions));
+ srvinfo[i].srvacl = strdup(PQgetvalue(res, i, i_srvacl));
+
+ /* Decide whether we want to dump it */
+ selectDumpableObject(&(srvinfo[i].dobj));
+ }
+
+ PQclear(res);
+
+ destroyPQExpBuffer(query);
+
+ return srvinfo;
+}
/*
* dumpComment --
@@ -5671,6 +5835,12 @@ dumpDumpableObject(Archive *fout, DumpableObject *dobj)
case DO_TSCONFIG:
dumpTSConfig(fout, (TSConfigInfo *) dobj);
break;
+ case DO_FDW:
+ dumpForeignDataWrapper(fout, (FdwInfo *) dobj);
+ break;
+ case DO_FOREIGN_SERVER:
+ dumpForeignServer(fout, (ForeignServerInfo *) dobj);
+ break;
case DO_BLOBS:
ArchiveEntry(fout, dobj->catId, dobj->dumpId,
dobj->name, NULL, NULL, "",
@@ -8977,6 +9147,224 @@ dumpTSConfig(Archive *fout, TSConfigInfo *cfginfo)
destroyPQExpBuffer(query);
}
+/*
+ * dumpForeignDataWrapper
+ * write out a single foreign-data wrapper definition
+ */
+static void
+dumpForeignDataWrapper(Archive *fout, FdwInfo *fdwinfo)
+{
+ PQExpBuffer q;
+ PQExpBuffer delq;
+ char *namecopy;
+
+ /* Skip if not to be dumped */
+ if (!fdwinfo->dobj.dump || dataOnly)
+ return;
+
+ q = createPQExpBuffer();
+ delq = createPQExpBuffer();
+
+ appendPQExpBuffer(q, "CREATE FOREIGN DATA WRAPPER %s LIBRARY '%s' LANGUAGE C",
+ fmtId(fdwinfo->dobj.name), fdwinfo->fdwlibrary);
+ if (fdwinfo->fdwoptions && strlen(fdwinfo->fdwoptions) > 0)
+ appendPQExpBuffer(q, " OPTIONS (%s)", fdwinfo->fdwoptions);
+
+ appendPQExpBuffer(q, ";\n");
+
+ appendPQExpBuffer(delq, "DROP FOREIGN DATA WRAPPER %s;\n",
+ fmtId(fdwinfo->dobj.name));
+
+ ArchiveEntry(fout, fdwinfo->dobj.catId, fdwinfo->dobj.dumpId,
+ fdwinfo->dobj.name,
+ NULL,
+ NULL,
+ fdwinfo->rolname,
+ false, "FOREIGN DATA WRAPPER", q->data, delq->data, NULL,
+ fdwinfo->dobj.dependencies, fdwinfo->dobj.nDeps,
+ NULL, NULL);
+
+ /* Handle the ACL */
+ namecopy = strdup(fmtId(fdwinfo->dobj.name));
+ dumpACL(fout, fdwinfo->dobj.catId, fdwinfo->dobj.dumpId,
+ "FOREIGN DATA WRAPPER",
+ namecopy, fdwinfo->dobj.name,
+ NULL, fdwinfo->rolname,
+ fdwinfo->fdwacl);
+ free(namecopy);
+
+ destroyPQExpBuffer(q);
+ destroyPQExpBuffer(delq);
+}
+
+/*
+ * dumpForeignServer
+ * write out a foreign server definition
+ */
+static void
+dumpForeignServer(Archive *fout, ForeignServerInfo *srvinfo)
+{
+ PQExpBuffer q;
+ PQExpBuffer delq;
+ PQExpBuffer query;
+ PGresult *res;
+ int ntups;
+ char *namecopy;
+ char *fdwname;
+
+ /* Skip if not to be dumped */
+ if (!srvinfo->dobj.dump || dataOnly)
+ return;
+
+ q = createPQExpBuffer();
+ delq = createPQExpBuffer();
+ query = createPQExpBuffer();
+
+ /* look up the foreign-data wrapper */
+ appendPQExpBuffer(query, "SELECT fdwname "
+ "FROM pg_foreign_data_wrapper w "
+ "WHERE w.oid = '%u'",
+ srvinfo->srvfdw);
+ res = PQexec(g_conn, query->data);
+ check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
+ ntups = PQntuples(res);
+ if (ntups != 1)
+ {
+ write_msg(NULL, "query returned %d rows instead of one: %s\n",
+ ntups, query->data);
+ exit_nicely();
+ }
+ fdwname = PQgetvalue(res, 0, 0);
+
+ appendPQExpBuffer(q, "CREATE SERVER %s", fmtId(srvinfo->dobj.name));
+ if (srvinfo->srvtype && strlen(srvinfo->srvtype) > 0)
+ appendPQExpBuffer(q, " TYPE '%s'", srvinfo->srvtype);
+ if (srvinfo->srvversion && strlen(srvinfo->srvversion) > 0)
+ appendPQExpBuffer(q, " VERSION '%s'", srvinfo->srvversion);
+
+ appendPQExpBuffer(q, " FOREIGN DATA WRAPPER ");
+ appendPQExpBuffer(q, "%s", fmtId(fdwname));
+
+ if (srvinfo->srvoptions && strlen(srvinfo->srvoptions) > 0)
+ appendPQExpBuffer(q, " OPTIONS (%s)", srvinfo->srvoptions);
+
+ appendPQExpBuffer(q, ";\n");
+
+ appendPQExpBuffer(delq, "DROP SERVER %s;\n",
+ fmtId(srvinfo->dobj.name));
+
+ ArchiveEntry(fout, srvinfo->dobj.catId, srvinfo->dobj.dumpId,
+ srvinfo->dobj.name,
+ NULL,
+ NULL,
+ srvinfo->rolname,
+ false, "SERVER", q->data, delq->data, NULL,
+ srvinfo->dobj.dependencies, srvinfo->dobj.nDeps,
+ NULL, NULL);
+
+ /* Handle the ACL */
+ namecopy = strdup(fmtId(srvinfo->dobj.name));
+ dumpACL(fout, srvinfo->dobj.catId, srvinfo->dobj.dumpId,
+ "SERVER",
+ namecopy, srvinfo->dobj.name,
+ NULL, srvinfo->rolname,
+ srvinfo->srvacl);
+ free(namecopy);
+
+ /* Dump user mappings */
+ resetPQExpBuffer(q);
+ appendPQExpBuffer(q, "SERVER %s", fmtId(srvinfo->dobj.name));
+ dumpUserMappings(fout, q->data,
+ srvinfo->dobj.name, NULL,
+ srvinfo->rolname,
+ srvinfo->dobj.catId, srvinfo->dobj.dumpId);
+
+ destroyPQExpBuffer(q);
+ destroyPQExpBuffer(delq);
+}
+
+/*
+ * dumpUserMappings
+ *
+ * This routine is used to dump any user mappings associated with the
+ * server handed to this routine. Should be called after ArchiveEntry()
+ * for the server.
+ */
+static void
+dumpUserMappings(Archive *fout, const char *target,
+ const char *servername, const char *namespace,
+ const char *owner,
+ CatalogId catalogId, DumpId dumpId)
+{
+ PQExpBuffer q;
+ PQExpBuffer delq;
+ PQExpBuffer query;
+ PQExpBuffer tag;
+ PGresult *res;
+ int ntups;
+ int i_umuser;
+ int i_umoptions;
+ int i;
+
+ q = createPQExpBuffer();
+ tag = createPQExpBuffer();
+ delq = createPQExpBuffer();
+ query = createPQExpBuffer();
+
+ appendPQExpBuffer(query,
+ "SELECT (%s umuser) AS umuser, "
+ "array_to_string(ARRAY(SELECT option_name || ' ' || quote_literal(option_value) FROM pg_options_to_table(umoptions)), ', ') AS umoptions\n"
+ "FROM pg_user_mapping WHERE umserver=%u",
+ username_subquery,
+ catalogId.oid);
+
+ res = PQexec(g_conn, query->data);
+ check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
+
+ ntups = PQntuples(res);
+ i_umuser = PQfnumber(res, "umuser");
+ i_umoptions = PQfnumber(res, "umoptions");
+
+ for (i = 0; i < ntups; i++)
+ {
+ char *umuser;
+ char *umoptions;
+
+ umuser = PQgetvalue(res, i, i_umuser);
+ umoptions = PQgetvalue(res, i, i_umoptions);
+
+ resetPQExpBuffer(q);
+ appendPQExpBuffer(q, "CREATE USER MAPPING FOR %s", fmtId(umuser));
+ appendPQExpBuffer(q, " SERVER %s", fmtId(servername));
+
+ if (umoptions && strlen(umoptions) > 0)
+ appendPQExpBuffer(q, " OPTIONS (%s)", umoptions);
+
+ appendPQExpBuffer(q, ";\n");
+
+ resetPQExpBuffer(delq);
+ appendPQExpBuffer(delq, "DROP USER MAPPING FOR %s SERVER %s;\n", fmtId(umuser), fmtId(servername));
+
+ resetPQExpBuffer(tag);
+ appendPQExpBuffer(tag, "USER MAPPING %s %s", fmtId(umuser), target);
+
+ ArchiveEntry(fout, nilCatalogId, createDumpId(),
+ tag->data,
+ namespace,
+ NULL,
+ owner, false,
+ "USER MAPPING", q->data,
+ delq->data, NULL,
+ &dumpId, 1,
+ NULL, NULL);
+ }
+
+ PQclear(res);
+
+ destroyPQExpBuffer(query);
+ destroyPQExpBuffer(delq);
+ destroyPQExpBuffer(q);
+}
/*----------
* Write out grant/revoke information