* Break apart TABLE[(COLUMNS)] of "spec". With the reset_val of search_path * in effect, have regclassin() interpret the TABLE portion. Append to "buf" * the qualified name of TABLE, followed by any (COLUMNS). Exit on failure. * We use this to interpret --table=foo under the search path psql would get, * in advance of "ANALYZE public.foo" under the always-secure search path. */
| 67 | * in advance of "ANALYZE public.foo" under the always-secure search path. |
| 68 | */ |
| 69 | void |
| 70 | appendQualifiedRelation(PQExpBuffer buf, const char *spec, |
| 71 | PGconn *conn, bool echo) |
| 72 | { |
| 73 | char *table; |
| 74 | const char *columns; |
| 75 | PQExpBufferData sql; |
| 76 | PGresult *res; |
| 77 | int ntups; |
| 78 | |
| 79 | splitTableColumnsSpec(spec, PQclientEncoding(conn), &table, &columns); |
| 80 | |
| 81 | /* |
| 82 | * Query must remain ABSOLUTELY devoid of unqualified names. This would |
| 83 | * be unnecessary given a regclassin() variant taking a search_path |
| 84 | * argument. |
| 85 | */ |
| 86 | initPQExpBuffer(&sql); |
| 87 | appendPQExpBufferStr(&sql, |
| 88 | "SELECT c.relname, ns.nspname\n" |
| 89 | " FROM pg_catalog.pg_class c," |
| 90 | " pg_catalog.pg_namespace ns\n" |
| 91 | " WHERE c.relnamespace OPERATOR(pg_catalog.=) ns.oid\n" |
| 92 | " AND c.oid OPERATOR(pg_catalog.=) "); |
| 93 | appendStringLiteralConn(&sql, table, conn); |
| 94 | appendPQExpBufferStr(&sql, "::pg_catalog.regclass;"); |
| 95 | |
| 96 | executeCommand(conn, "RESET search_path;", echo); |
| 97 | |
| 98 | /* |
| 99 | * One row is a typical result, as is a nonexistent relation ERROR. |
| 100 | * regclassin() unconditionally accepts all-digits input as an OID; if no |
| 101 | * relation has that OID; this query returns no rows. Catalog corruption |
| 102 | * might elicit other row counts. |
| 103 | */ |
| 104 | res = executeQuery(conn, sql.data, echo); |
| 105 | ntups = PQntuples(res); |
| 106 | if (ntups != 1) |
| 107 | { |
| 108 | pg_log_error(ngettext("query returned %d row instead of one: %s", |
| 109 | "query returned %d rows instead of one: %s", |
| 110 | ntups), |
| 111 | ntups, sql.data); |
| 112 | PQfinish(conn); |
| 113 | exit(1); |
| 114 | } |
| 115 | appendPQExpBufferStr(buf, |
| 116 | fmtQualifiedIdEnc(PQgetvalue(res, 0, 1), |
| 117 | PQgetvalue(res, 0, 0), |
| 118 | PQclientEncoding(conn))); |
| 119 | appendPQExpBufferStr(buf, columns); |
| 120 | PQclear(res); |
| 121 | termPQExpBuffer(&sql); |
| 122 | pg_free(table); |
| 123 | |
| 124 | PQclear(executeQuery(conn, ALWAYS_SECURE_SEARCH_PATH_SQL, echo)); |
| 125 | } |
| 126 |
no test coverage detected