diff options
Diffstat (limited to 'src/bin/pg_dump/pg_dump.c')
-rw-r--r-- | src/bin/pg_dump/pg_dump.c | 390 |
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 |