Fix some bogosities in pg_dump's foreign-table support.
authorTom Lane <tgl@sss.pgh.pa.us>
Mon, 28 Nov 2011 17:51:41 +0000 (12:51 -0500)
committerTom Lane <tgl@sss.pgh.pa.us>
Mon, 28 Nov 2011 17:51:41 +0000 (12:51 -0500)
The server name for a foreign table was not quoted at need, as per report
from Ronan Dunklau.  Also, queries related to FDW options were inadequately
schema-qualified in places where the search path isn't just pg_catalog, and
were inconsistently formatted everywhere, and we didn't always check that
we got the expected number of rows from them.

src/bin/pg_dump/pg_dump.c

index ec932e4063f02c48c99f2ff80f536bddb810a449..916939cf936484ae1a3911b1b0cf96370044a19a 100644 (file)
@@ -5667,11 +5667,11 @@ getTableAttrs(TableInfo *tblinfo, int numTables)
                        "array_to_string(a.attoptions, ', ') AS attoptions, "
                              "CASE WHEN a.attcollation <> t.typcollation "
                            "THEN a.attcollation ELSE 0 END AS attcollation, "
-                 "array_to_string(ARRAY("
-                 "  SELECT quote_ident(option_name) || ' ' || "
-                 "         quote_literal(option_value) "
-                 "  FROM pg_options_to_table(attfdwoptions)), ', ') "
-                 " AS attfdwoptions "
+                             "pg_catalog.array_to_string(ARRAY("
+                             "SELECT pg_catalog.quote_ident(option_name) || "
+                             "' ' || pg_catalog.quote_literal(option_value) "
+                             "FROM pg_catalog.pg_options_to_table(attfdwoptions)"
+                             "), ', ') AS attfdwoptions "
             "FROM pg_catalog.pg_attribute a LEFT JOIN pg_catalog.pg_type t "
                              "ON a.atttypid = t.oid "
                              "WHERE a.attrelid = '%u'::pg_catalog.oid "
@@ -6485,9 +6485,10 @@ getForeignDataWrappers(int *numForeignDataWrappers)
                          "fdwhandler::pg_catalog.regproc, "
                          "fdwvalidator::pg_catalog.regproc, fdwacl, "
                          "array_to_string(ARRAY("
-                         "     SELECT quote_ident(option_name) || ' ' || "
-                         "            quote_literal(option_value) "
-                         "     FROM pg_options_to_table(fdwoptions)), ', ') AS fdwoptions "
+                         "SELECT quote_ident(option_name) || ' ' || "
+                         "quote_literal(option_value) "
+                         "FROM pg_options_to_table(fdwoptions)"
+                         "), ', ') AS fdwoptions "
                          "FROM pg_foreign_data_wrapper",
                          username_subquery);
    }
@@ -6498,9 +6499,10 @@ getForeignDataWrappers(int *numForeignDataWrappers)
                          "'-' AS fdwhandler, "
                          "fdwvalidator::pg_catalog.regproc, fdwacl, "
                          "array_to_string(ARRAY("
-                         "     SELECT quote_ident(option_name) || ' ' || "
-                         "            quote_literal(option_value) "
-                         "     FROM pg_options_to_table(fdwoptions)), ', ') AS fdwoptions "
+                         "SELECT quote_ident(option_name) || ' ' || "
+                         "quote_literal(option_value) "
+                         "FROM pg_options_to_table(fdwoptions)"
+                         "), ', ') AS fdwoptions "
                          "FROM pg_foreign_data_wrapper",
                          username_subquery);
    }
@@ -6586,9 +6588,10 @@ getForeignServers(int *numForeignServers)
                      "(%s srvowner) AS rolname, "
                      "srvfdw, srvtype, srvversion, srvacl,"
                      "array_to_string(ARRAY("
-        "      SELECT quote_ident(option_name) || ' ' || "
-        "             quote_literal(option_value) "
-      "        FROM pg_options_to_table(srvoptions)), ', ') AS srvoptions "
+                     "SELECT quote_ident(option_name) || ' ' || "
+                     "quote_literal(option_value) "
+                     "FROM pg_options_to_table(srvoptions)"
+                     "), ', ') AS srvoptions "
                      "FROM pg_foreign_server",
                      username_subquery);
 
@@ -11650,9 +11653,13 @@ dumpUserMappings(Archive *fout,
 
    appendPQExpBuffer(query,
                      "SELECT usename, "
-                     "array_to_string(ARRAY(SELECT quote_ident(option_name) || ' ' || quote_literal(option_value) FROM pg_options_to_table(umoptions)), ', ') AS umoptions\n"
+                     "array_to_string(ARRAY("
+                     "SELECT quote_ident(option_name) || ' ' || "
+                     "quote_literal(option_value) "
+                     "FROM pg_options_to_table(umoptions)"
+                     "), ', ') AS umoptions "
                      "FROM pg_user_mappings "
-                     "WHERE srvid = %u",
+                     "WHERE srvid = '%u'",
                      catalogId.oid);
 
    res = PQexec(g_conn, query->data);
@@ -12212,12 +12219,12 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
    int         numParents;
    TableInfo **parents;
    int         actual_atts;    /* number of attrs in this CREATE statment */
-   char       *reltypename;
+   const char *reltypename;
    char       *storage;
+   char       *srvname;
+   char       *ftoptions;
    int         j,
                k;
-   char       *srvname;
-   char       *ftoptions = NULL;
 
    /* Make sure we are in proper schema */
    selectSourceSchema(tbinfo->dobj.namespace->dobj.name);
@@ -12303,15 +12310,25 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
 
            /* retrieve name of foreign server and generic options */
            appendPQExpBuffer(query,
-                             "SELECT fs.srvname, array_to_string(ARRAY("
-               "   SELECT quote_ident(option_name) || ' ' || "
-               "          quote_literal(option_value)"
-              "   FROM pg_options_to_table(ftoptions)), ', ') AS ftoptions "
-                       "FROM pg_foreign_table ft JOIN pg_foreign_server fs "
-                             " ON (fs.oid = ft.ftserver) "
-                           "WHERE ft.ftrelid = %u", tbinfo->dobj.catId.oid);
+                             "SELECT fs.srvname, "
+                             "pg_catalog.array_to_string(ARRAY("
+                             "SELECT pg_catalog.quote_ident(option_name) || "
+                             "' ' || pg_catalog.quote_literal(option_value) "
+                             "FROM pg_catalog.pg_options_to_table(ftoptions)"
+                             "), ', ') AS ftoptions "
+                             "FROM pg_catalog.pg_foreign_table ft "
+                             "JOIN pg_catalog.pg_foreign_server fs "
+                             "ON (fs.oid = ft.ftserver) "
+                             "WHERE ft.ftrelid = '%u'",
+                             tbinfo->dobj.catId.oid);
            res = PQexec(g_conn, query->data);
            check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
+           if (PQntuples(res) != 1)
+           {
+               write_msg(NULL, "query returned %d foreign server entries for foreign table \"%s\"\n",
+                         PQntuples(res), tbinfo->dobj.name);
+               exit_nicely();
+           }
            i_srvname = PQfnumber(res, "srvname");
            i_ftoptions = PQfnumber(res, "ftoptions");
            srvname = pg_strdup(PQgetvalue(res, 0, i_srvname));
@@ -12502,7 +12519,7 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
        }
 
        if (tbinfo->relkind == RELKIND_FOREIGN_TABLE)
-           appendPQExpBuffer(q, "\nSERVER %s", srvname);
+           appendPQExpBuffer(q, "\nSERVER %s", fmtId(srvname));
 
        if ((tbinfo->reloptions && strlen(tbinfo->reloptions) > 0) ||
          (tbinfo->toast_reloptions && strlen(tbinfo->toast_reloptions) > 0))