mirror of
https://git.postgresql.org/git/postgresql.git
synced 2025-03-01 19:45:33 +08:00
Allow db.schema.table patterns, but complain about random garbage.
psql, pg_dump, and pg_amcheck share code to process object name
patterns like 'foo*.bar*' to match all tables with names starting in
'bar' that are in schemas starting with 'foo'. Before v14, any number
of extra name parts were silently ignored, so a command line '\d
foo.bar.baz.bletch.quux' was interpreted as '\d bletch.quux'. In v14,
as a result of commit 2c8726c4b0
, we
instead treated this as a request for table quux in a schema named
'foo.bar.baz.bletch'. That caused problems for people like Justin
Pryzby who were accustomed to copying strings of the form
db.schema.table from messages generated by PostgreSQL itself and using
them as arguments to \d.
Accordingly, revise things so that if an object name pattern contains
more parts than we're expecting, we throw an error, unless there's
exactly one extra part and it matches the current database name.
That way, thisdb.myschema.mytable is accepted as meaning just
myschema.mytable, but otherdb.myschema.mytable is an error, and so
is some.random.garbage.myschema.mytable.
Mark Dilger, per report from Justin Pryzby and discussion among
various people.
Discussion: https://www.postgresql.org/message-id/20211013165426.GD27491%40telsasoft.com
This commit is contained in:
parent
836af9756b
commit
d2d3547979
@ -3641,14 +3641,27 @@ select 1\; select 2\; select 3;
|
||||
</para>
|
||||
|
||||
<para>
|
||||
A pattern that contains a dot (<literal>.</literal>) is interpreted as a schema
|
||||
A relation pattern that contains a dot (<literal>.</literal>) is interpreted as a schema
|
||||
name pattern followed by an object name pattern. For example,
|
||||
<literal>\dt foo*.*bar*</literal> displays all tables whose table name
|
||||
includes <literal>bar</literal> that are in schemas whose schema name
|
||||
starts with <literal>foo</literal>. When no dot appears, then the pattern
|
||||
matches only objects that are visible in the current schema search path.
|
||||
Again, a dot within double quotes loses its special meaning and is matched
|
||||
literally.
|
||||
literally. A relation pattern that contains two dots (<literal>.</literal>)
|
||||
is interpreted as a database name followed by a schema name pattern followed
|
||||
by an object name pattern. The database name portion will not be treated as
|
||||
a pattern and must match the name of the currently connected database, else
|
||||
an error will be raised.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
A schema pattern that contains a dot (<literal>.</literal>) is interpreted
|
||||
as a database name followed by a schema name pattern. For example,
|
||||
<literal>\dn mydb.*foo*</literal> displays all schemas whose schema name
|
||||
includes <literal>foo</literal>. The database name portion will not be
|
||||
treated as a pattern and must match the name of the currently connected
|
||||
database, else an error will be raised.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
|
@ -1308,10 +1308,17 @@ static void
|
||||
append_database_pattern(PatternInfoArray *pia, const char *pattern, int encoding)
|
||||
{
|
||||
PQExpBufferData buf;
|
||||
int dotcnt;
|
||||
PatternInfo *info = extend_pattern_info_array(pia);
|
||||
|
||||
initPQExpBuffer(&buf);
|
||||
patternToSQLRegex(encoding, NULL, NULL, &buf, pattern, false);
|
||||
patternToSQLRegex(encoding, NULL, NULL, &buf, pattern, false, false,
|
||||
&dotcnt);
|
||||
if (dotcnt > 0)
|
||||
{
|
||||
pg_log_error("improper qualified name (too many dotted names): %s", pattern);
|
||||
exit(2);
|
||||
}
|
||||
info->pattern = pattern;
|
||||
info->db_regex = pstrdup(buf.data);
|
||||
|
||||
@ -1332,12 +1339,19 @@ append_schema_pattern(PatternInfoArray *pia, const char *pattern, int encoding)
|
||||
{
|
||||
PQExpBufferData dbbuf;
|
||||
PQExpBufferData nspbuf;
|
||||
int dotcnt;
|
||||
PatternInfo *info = extend_pattern_info_array(pia);
|
||||
|
||||
initPQExpBuffer(&dbbuf);
|
||||
initPQExpBuffer(&nspbuf);
|
||||
|
||||
patternToSQLRegex(encoding, NULL, &dbbuf, &nspbuf, pattern, false);
|
||||
patternToSQLRegex(encoding, NULL, &dbbuf, &nspbuf, pattern, false, false,
|
||||
&dotcnt);
|
||||
if (dotcnt > 1)
|
||||
{
|
||||
pg_log_error("improper qualified name (too many dotted names): %s", pattern);
|
||||
exit(2);
|
||||
}
|
||||
info->pattern = pattern;
|
||||
if (dbbuf.data[0])
|
||||
{
|
||||
@ -1369,13 +1383,20 @@ append_relation_pattern_helper(PatternInfoArray *pia, const char *pattern,
|
||||
PQExpBufferData dbbuf;
|
||||
PQExpBufferData nspbuf;
|
||||
PQExpBufferData relbuf;
|
||||
int dotcnt;
|
||||
PatternInfo *info = extend_pattern_info_array(pia);
|
||||
|
||||
initPQExpBuffer(&dbbuf);
|
||||
initPQExpBuffer(&nspbuf);
|
||||
initPQExpBuffer(&relbuf);
|
||||
|
||||
patternToSQLRegex(encoding, &dbbuf, &nspbuf, &relbuf, pattern, false);
|
||||
patternToSQLRegex(encoding, &dbbuf, &nspbuf, &relbuf, pattern, false,
|
||||
false, &dotcnt);
|
||||
if (dotcnt > 2)
|
||||
{
|
||||
pg_log_error("improper relation name (too many dotted names): %s", pattern);
|
||||
exit(2);
|
||||
}
|
||||
info->pattern = pattern;
|
||||
if (dbbuf.data[0])
|
||||
{
|
||||
|
@ -147,6 +147,100 @@ $node->command_checks_all(
|
||||
[qr/pg_amcheck: error: no heap tables to check matching "\."/],
|
||||
'checking table pattern "."');
|
||||
|
||||
# Check that a multipart database name is rejected
|
||||
$node->command_checks_all(
|
||||
[ 'pg_amcheck', '-d', 'localhost.postgres' ],
|
||||
2,
|
||||
[qr/^$/],
|
||||
[
|
||||
qr/pg_amcheck: error: improper qualified name \(too many dotted names\): localhost\.postgres/
|
||||
],
|
||||
'multipart database patterns are rejected'
|
||||
);
|
||||
|
||||
# Check that a three-part schema name is rejected
|
||||
$node->command_checks_all(
|
||||
[ 'pg_amcheck', '-s', 'localhost.postgres.pg_catalog' ],
|
||||
2,
|
||||
[qr/^$/],
|
||||
[
|
||||
qr/pg_amcheck: error: improper qualified name \(too many dotted names\): localhost\.postgres\.pg_catalog/
|
||||
],
|
||||
'three part schema patterns are rejected'
|
||||
);
|
||||
|
||||
# Check that a four-part table name is rejected
|
||||
$node->command_checks_all(
|
||||
[ 'pg_amcheck', '-t', 'localhost.postgres.pg_catalog.pg_class' ],
|
||||
2,
|
||||
[qr/^$/],
|
||||
[
|
||||
qr/pg_amcheck: error: improper relation name \(too many dotted names\): localhost\.postgres\.pg_catalog\.pg_class/
|
||||
],
|
||||
'four part table patterns are rejected'
|
||||
);
|
||||
|
||||
# Check that too many dotted names still draws an error under --no-strict-names
|
||||
# That flag means that it is ok for the object to be missing, not that it is ok
|
||||
# for the object name to be ungrammatical
|
||||
$node->command_checks_all(
|
||||
[ 'pg_amcheck', '--no-strict-names', '-t', 'this.is.a.really.long.dotted.string' ],
|
||||
2,
|
||||
[qr/^$/],
|
||||
[
|
||||
qr/pg_amcheck: error: improper relation name \(too many dotted names\): this\.is\.a\.really\.long\.dotted\.string/
|
||||
],
|
||||
'ungrammatical table names still draw errors under --no-strict-names'
|
||||
);
|
||||
$node->command_checks_all(
|
||||
[ 'pg_amcheck', '--no-strict-names', '-s', 'postgres.long.dotted.string' ],
|
||||
2,
|
||||
[qr/^$/],
|
||||
[
|
||||
qr/pg_amcheck: error: improper qualified name \(too many dotted names\): postgres\.long\.dotted\.string/
|
||||
],
|
||||
'ungrammatical schema names still draw errors under --no-strict-names'
|
||||
);
|
||||
$node->command_checks_all(
|
||||
[ 'pg_amcheck', '--no-strict-names', '-d', 'postgres.long.dotted.string' ],
|
||||
2,
|
||||
[qr/^$/],
|
||||
[
|
||||
qr/pg_amcheck: error: improper qualified name \(too many dotted names\): postgres\.long\.dotted\.string/
|
||||
],
|
||||
'ungrammatical database names still draw errors under --no-strict-names'
|
||||
);
|
||||
|
||||
# Likewise for exclusion patterns
|
||||
$node->command_checks_all(
|
||||
[ 'pg_amcheck', '--no-strict-names', '-T', 'a.b.c.d' ],
|
||||
2,
|
||||
[qr/^$/],
|
||||
[
|
||||
qr/pg_amcheck: error: improper relation name \(too many dotted names\): a\.b\.c\.d/
|
||||
],
|
||||
'ungrammatical table exclusions still draw errors under --no-strict-names'
|
||||
);
|
||||
$node->command_checks_all(
|
||||
[ 'pg_amcheck', '--no-strict-names', '-S', 'a.b.c' ],
|
||||
2,
|
||||
[qr/^$/],
|
||||
[
|
||||
qr/pg_amcheck: error: improper qualified name \(too many dotted names\): a\.b\.c/
|
||||
],
|
||||
'ungrammatical schema exclusions still draw errors under --no-strict-names'
|
||||
);
|
||||
$node->command_checks_all(
|
||||
[ 'pg_amcheck', '--no-strict-names', '-D', 'a.b' ],
|
||||
2,
|
||||
[qr/^$/],
|
||||
[
|
||||
qr/pg_amcheck: error: improper qualified name \(too many dotted names\): a\.b/
|
||||
],
|
||||
'ungrammatical database exclusions still draw errors under --no-strict-names'
|
||||
);
|
||||
|
||||
|
||||
#########################################
|
||||
# Test checking non-existent databases, schemas, tables, and indexes
|
||||
|
||||
@ -165,9 +259,7 @@ $node->command_checks_all(
|
||||
'-d', 'no*such*database',
|
||||
'-r', 'none.none',
|
||||
'-r', 'none.none.none',
|
||||
'-r', 'this.is.a.really.long.dotted.string',
|
||||
'-r', 'postgres.none.none',
|
||||
'-r', 'postgres.long.dotted.string',
|
||||
'-r', 'postgres.pg_catalog.none',
|
||||
'-r', 'postgres.none.pg_class',
|
||||
'-t', 'postgres.pg_catalog.pg_class', # This exists
|
||||
@ -186,15 +278,12 @@ $node->command_checks_all(
|
||||
qr/pg_amcheck: warning: no connectable databases to check matching "no\*such\*database"/,
|
||||
qr/pg_amcheck: warning: no relations to check matching "none\.none"/,
|
||||
qr/pg_amcheck: warning: no connectable databases to check matching "none\.none\.none"/,
|
||||
qr/pg_amcheck: warning: no connectable databases to check matching "this\.is\.a\.really\.long\.dotted\.string"/,
|
||||
qr/pg_amcheck: warning: no relations to check matching "postgres\.none\.none"/,
|
||||
qr/pg_amcheck: warning: no relations to check matching "postgres\.long\.dotted\.string"/,
|
||||
qr/pg_amcheck: warning: no relations to check matching "postgres\.pg_catalog\.none"/,
|
||||
qr/pg_amcheck: warning: no relations to check matching "postgres\.none\.pg_class"/,
|
||||
qr/pg_amcheck: warning: no connectable databases to check matching "no_such_database"/,
|
||||
qr/pg_amcheck: warning: no connectable databases to check matching "no\*such\*database"/,
|
||||
qr/pg_amcheck: warning: no connectable databases to check matching "none\.none\.none"/,
|
||||
qr/pg_amcheck: warning: no connectable databases to check matching "this\.is\.a\.really\.long\.dotted\.string"/,
|
||||
],
|
||||
'many unmatched patterns and one matched pattern under --no-strict-names'
|
||||
);
|
||||
|
@ -178,6 +178,9 @@ static void expand_table_name_patterns(Archive *fout,
|
||||
SimpleStringList *patterns,
|
||||
SimpleOidList *oids,
|
||||
bool strict_names);
|
||||
static void prohibit_crossdb_refs(PGconn *conn, const char *dbname,
|
||||
const char *pattern);
|
||||
|
||||
static NamespaceInfo *findNamespace(Oid nsoid);
|
||||
static void dumpTableData(Archive *fout, const TableDataInfo *tdinfo);
|
||||
static void refreshMatViewData(Archive *fout, const TableDataInfo *tdinfo);
|
||||
@ -1315,10 +1318,21 @@ expand_schema_name_patterns(Archive *fout,
|
||||
|
||||
for (cell = patterns->head; cell; cell = cell->next)
|
||||
{
|
||||
PQExpBufferData dbbuf;
|
||||
int dotcnt;
|
||||
|
||||
appendPQExpBufferStr(query,
|
||||
"SELECT oid FROM pg_catalog.pg_namespace n\n");
|
||||
initPQExpBuffer(&dbbuf);
|
||||
processSQLNamePattern(GetConnection(fout), query, cell->val, false,
|
||||
false, NULL, "n.nspname", NULL, NULL);
|
||||
false, NULL, "n.nspname", NULL, NULL, &dbbuf,
|
||||
&dotcnt);
|
||||
if (dotcnt > 1)
|
||||
pg_fatal("improper qualified name (too many dotted names): %s",
|
||||
cell->val);
|
||||
else if (dotcnt == 1)
|
||||
prohibit_crossdb_refs(GetConnection(fout), dbbuf.data, cell->val);
|
||||
termPQExpBuffer(&dbbuf);
|
||||
|
||||
res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
|
||||
if (strict_names && PQntuples(res) == 0)
|
||||
@ -1362,10 +1376,16 @@ expand_extension_name_patterns(Archive *fout,
|
||||
*/
|
||||
for (cell = patterns->head; cell; cell = cell->next)
|
||||
{
|
||||
int dotcnt;
|
||||
|
||||
appendPQExpBufferStr(query,
|
||||
"SELECT oid FROM pg_catalog.pg_extension e\n");
|
||||
processSQLNamePattern(GetConnection(fout), query, cell->val, false,
|
||||
false, NULL, "e.extname", NULL, NULL);
|
||||
false, NULL, "e.extname", NULL, NULL, NULL,
|
||||
&dotcnt);
|
||||
if (dotcnt > 0)
|
||||
pg_fatal("improper qualified name (too many dotted names): %s",
|
||||
cell->val);
|
||||
|
||||
res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
|
||||
if (strict_names && PQntuples(res) == 0)
|
||||
@ -1409,10 +1429,16 @@ expand_foreign_server_name_patterns(Archive *fout,
|
||||
|
||||
for (cell = patterns->head; cell; cell = cell->next)
|
||||
{
|
||||
int dotcnt;
|
||||
|
||||
appendPQExpBufferStr(query,
|
||||
"SELECT oid FROM pg_catalog.pg_foreign_server s\n");
|
||||
processSQLNamePattern(GetConnection(fout), query, cell->val, false,
|
||||
false, NULL, "s.srvname", NULL, NULL);
|
||||
false, NULL, "s.srvname", NULL, NULL, NULL,
|
||||
&dotcnt);
|
||||
if (dotcnt > 0)
|
||||
pg_fatal("improper qualified name (too many dotted names): %s",
|
||||
cell->val);
|
||||
|
||||
res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
|
||||
if (PQntuples(res) == 0)
|
||||
@ -1455,6 +1481,9 @@ expand_table_name_patterns(Archive *fout,
|
||||
|
||||
for (cell = patterns->head; cell; cell = cell->next)
|
||||
{
|
||||
PQExpBufferData dbbuf;
|
||||
int dotcnt;
|
||||
|
||||
/*
|
||||
* Query must remain ABSOLUTELY devoid of unqualified names. This
|
||||
* would be unnecessary given a pg_table_is_visible() variant taking a
|
||||
@ -1470,9 +1499,17 @@ expand_table_name_patterns(Archive *fout,
|
||||
RELKIND_RELATION, RELKIND_SEQUENCE, RELKIND_VIEW,
|
||||
RELKIND_MATVIEW, RELKIND_FOREIGN_TABLE,
|
||||
RELKIND_PARTITIONED_TABLE);
|
||||
initPQExpBuffer(&dbbuf);
|
||||
processSQLNamePattern(GetConnection(fout), query, cell->val, true,
|
||||
false, "n.nspname", "c.relname", NULL,
|
||||
"pg_catalog.pg_table_is_visible(c.oid)");
|
||||
"pg_catalog.pg_table_is_visible(c.oid)", &dbbuf,
|
||||
&dotcnt);
|
||||
if (dotcnt > 2)
|
||||
pg_fatal("improper relation name (too many dotted names): %s",
|
||||
cell->val);
|
||||
else if (dotcnt == 2)
|
||||
prohibit_crossdb_refs(GetConnection(fout), dbbuf.data, cell->val);
|
||||
termPQExpBuffer(&dbbuf);
|
||||
|
||||
ExecuteSqlStatement(fout, "RESET search_path");
|
||||
res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
|
||||
@ -1493,6 +1530,26 @@ expand_table_name_patterns(Archive *fout,
|
||||
destroyPQExpBuffer(query);
|
||||
}
|
||||
|
||||
/*
|
||||
* Verifies that the connected database name matches the given database name,
|
||||
* and if not, dies with an error about the given pattern.
|
||||
*
|
||||
* The 'dbname' argument should be a literal name parsed from 'pattern'.
|
||||
*/
|
||||
static void
|
||||
prohibit_crossdb_refs(PGconn *conn, const char *dbname, const char *pattern)
|
||||
{
|
||||
const char *db;
|
||||
|
||||
db = PQdb(conn);
|
||||
if (db == NULL)
|
||||
pg_fatal("You are currently not connected to a database.");
|
||||
|
||||
if (strcmp(db, dbname) != 0)
|
||||
pg_fatal("cross-database references are not implemented: %s",
|
||||
pattern);
|
||||
}
|
||||
|
||||
/*
|
||||
* checkExtensionMembership
|
||||
* Determine whether object is an extension member, and if so,
|
||||
|
@ -1269,10 +1269,21 @@ expand_dbname_patterns(PGconn *conn,
|
||||
|
||||
for (SimpleStringListCell *cell = patterns->head; cell; cell = cell->next)
|
||||
{
|
||||
int dotcnt;
|
||||
|
||||
appendPQExpBufferStr(query,
|
||||
"SELECT datname FROM pg_catalog.pg_database n\n");
|
||||
processSQLNamePattern(conn, query, cell->val, false,
|
||||
false, NULL, "datname", NULL, NULL);
|
||||
false, NULL, "datname", NULL, NULL, NULL,
|
||||
&dotcnt);
|
||||
|
||||
if (dotcnt > 0)
|
||||
{
|
||||
pg_log_error("improper qualified name (too many dotted names): %s",
|
||||
cell->val);
|
||||
PQfinish(conn);
|
||||
exit_nicely(1);
|
||||
}
|
||||
|
||||
res = executeQuery(conn, query->data);
|
||||
for (int i = 0; i < PQntuples(res); i++)
|
||||
|
@ -3973,6 +3973,113 @@ command_fails_like(
|
||||
qr/\Qpg_dump: error: no matching tables were found for pattern\E/,
|
||||
'no matching tables');
|
||||
|
||||
#########################################
|
||||
# Test invalid multipart database names
|
||||
|
||||
$node->command_fails_like(
|
||||
[ 'pg_dumpall', '--exclude-database', '.' ],
|
||||
qr/pg_dumpall: error: improper qualified name \(too many dotted names\): \./,
|
||||
'pg_dumpall: option --exclude-database rejects multipart pattern "."'
|
||||
);
|
||||
|
||||
$node->command_fails_like(
|
||||
[ 'pg_dumpall', '--exclude-database', '.*' ],
|
||||
qr/pg_dumpall: error: improper qualified name \(too many dotted names\): \.\*/,
|
||||
'pg_dumpall: option --exclude-database rejects multipart pattern ".*"'
|
||||
);
|
||||
|
||||
$node->command_fails_like(
|
||||
[ 'pg_dumpall', '--exclude-database', '*.*' ],
|
||||
qr/pg_dumpall: error: improper qualified name \(too many dotted names\): \*\.\*/,
|
||||
'pg_dumpall: option --exclude-database rejects multipart pattern "*.*"'
|
||||
);
|
||||
|
||||
$node->command_fails_like(
|
||||
[ 'pg_dumpall', '--exclude-database', 'myhost.mydb' ],
|
||||
qr/pg_dumpall: error: improper qualified name \(too many dotted names\): myhost\.mydb/,
|
||||
'pg_dumpall: option --exclude-database rejects multipart database names'
|
||||
);
|
||||
|
||||
#########################################
|
||||
# Test valid database exclusion patterns
|
||||
|
||||
$node->command_ok(
|
||||
[ 'pg_dumpall', '-p', "$port", '--exclude-database', '"myhost.mydb"' ],
|
||||
'pg_dumpall: option --exclude-database handles database names with embedded dots'
|
||||
);
|
||||
|
||||
$node->command_ok(
|
||||
[ 'pg_dumpall', '--exclude-database', '??*' ],
|
||||
'pg_dumpall: option --exclude-database handles database name patterns'
|
||||
);
|
||||
|
||||
|
||||
#########################################
|
||||
# Test invalid multipart schema names
|
||||
|
||||
$node->command_fails_like(
|
||||
[ 'pg_dump', '--schema', 'myhost.mydb.myschema' ],
|
||||
qr/pg_dump: error: improper qualified name \(too many dotted names\): myhost\.mydb\.myschema/,
|
||||
'pg_dump: option --schema rejects three-part schema names'
|
||||
);
|
||||
|
||||
$node->command_fails_like(
|
||||
[ 'pg_dump', '--schema', 'otherdb.myschema' ],
|
||||
qr/pg_dump: error: cross-database references are not implemented: otherdb\.myschema/,
|
||||
'pg_dump: option --schema rejects cross-database multipart schema names'
|
||||
);
|
||||
|
||||
$node->command_fails_like(
|
||||
[ 'pg_dump', '--schema', '.' ],
|
||||
qr/pg_dump: error: cross-database references are not implemented: \./,
|
||||
'pg_dump: option --schema rejects degenerate two-part schema name: "."'
|
||||
);
|
||||
|
||||
$node->command_fails_like(
|
||||
[ 'pg_dump', '--schema', '"some.other.db".myschema' ],
|
||||
qr/pg_dump: error: cross-database references are not implemented: "some\.other\.db"\.myschema/,
|
||||
'pg_dump: option --schema rejects cross-database multipart schema names with embedded dots'
|
||||
);
|
||||
|
||||
$node->command_fails_like(
|
||||
[ 'pg_dump', '--schema', '.*' ],
|
||||
qr/pg_dump: error: cross-database references are not implemented: \.\*/,
|
||||
'pg_dump: option --schema rejects degenerate two-part schema name: ".*"'
|
||||
);
|
||||
|
||||
$node->command_fails_like(
|
||||
[ 'pg_dump', '--schema', '..' ],
|
||||
qr/pg_dump: error: improper qualified name \(too many dotted names\): \.\./,
|
||||
'pg_dump: option --schema rejects degenerate three-part schema name: ".."'
|
||||
);
|
||||
|
||||
$node->command_fails_like(
|
||||
[ 'pg_dump', '--schema', '.*.*' ],
|
||||
qr/pg_dump: error: improper qualified name \(too many dotted names\): \.\*\.\*/,
|
||||
'pg_dump: option --schema rejects degenerate three-part schema pattern: ".*.*"'
|
||||
);
|
||||
|
||||
#########################################
|
||||
# Test invalid multipart relation names
|
||||
|
||||
$node->command_fails_like(
|
||||
[ 'pg_dump', '--table', 'myhost.mydb.myschema.mytable' ],
|
||||
qr/pg_dump: error: improper relation name \(too many dotted names\): myhost\.mydb\.myschema\.mytable/,
|
||||
'pg_dump: option --table rejects four-part table names'
|
||||
);
|
||||
|
||||
$node->command_fails_like(
|
||||
[ 'pg_dump', '--table', 'otherdb.pg_catalog.pg_class' ],
|
||||
qr/pg_dump: error: cross-database references are not implemented: otherdb\.pg_catalog\.pg_class/,
|
||||
'pg_dump: option --table rejects cross-database three part table names'
|
||||
);
|
||||
|
||||
command_fails_like(
|
||||
[ 'pg_dump', '-p', "$port", '--table', '"some.other.db".pg_catalog.pg_class' ],
|
||||
qr/pg_dump: error: cross-database references are not implemented: "some\.other\.db"\.pg_catalog\.pg_class/,
|
||||
'pg_dump: option --table rejects cross-database three part table names with embedded dots'
|
||||
);
|
||||
|
||||
#########################################
|
||||
# Run all runs
|
||||
|
||||
|
@ -46,6 +46,12 @@ static bool describeOneTSConfig(const char *oid, const char *nspname,
|
||||
const char *pnspname, const char *prsname);
|
||||
static void printACLColumn(PQExpBuffer buf, const char *colname);
|
||||
static bool listOneExtensionContents(const char *extname, const char *oid);
|
||||
static bool validateSQLNamePattern(PQExpBuffer buf, const char *pattern,
|
||||
bool have_where, bool force_escape,
|
||||
const char *schemavar, const char *namevar,
|
||||
const char *altnamevar,
|
||||
const char *visibilityrule,
|
||||
bool *added_clause, int maxparts);
|
||||
|
||||
|
||||
/*----------------
|
||||
@ -102,9 +108,11 @@ describeAggregates(const char *pattern, bool verbose, bool showSystem)
|
||||
appendPQExpBufferStr(&buf, " AND n.nspname <> 'pg_catalog'\n"
|
||||
" AND n.nspname <> 'information_schema'\n");
|
||||
|
||||
processSQLNamePattern(pset.db, &buf, pattern, true, false,
|
||||
"n.nspname", "p.proname", NULL,
|
||||
"pg_catalog.pg_function_is_visible(p.oid)");
|
||||
if (!validateSQLNamePattern(&buf, pattern, true, false,
|
||||
"n.nspname", "p.proname", NULL,
|
||||
"pg_catalog.pg_function_is_visible(p.oid)",
|
||||
NULL, 3))
|
||||
return false;
|
||||
|
||||
appendPQExpBufferStr(&buf, "ORDER BY 1, 2, 4;");
|
||||
|
||||
@ -170,9 +178,11 @@ describeAccessMethods(const char *pattern, bool verbose)
|
||||
appendPQExpBufferStr(&buf,
|
||||
"\nFROM pg_catalog.pg_am\n");
|
||||
|
||||
processSQLNamePattern(pset.db, &buf, pattern, false, false,
|
||||
NULL, "amname", NULL,
|
||||
NULL);
|
||||
if (!validateSQLNamePattern(&buf, pattern, false, false,
|
||||
NULL, "amname", NULL,
|
||||
NULL,
|
||||
NULL, 1))
|
||||
return false;
|
||||
|
||||
appendPQExpBufferStr(&buf, "ORDER BY 1;");
|
||||
|
||||
@ -230,9 +240,11 @@ describeTablespaces(const char *pattern, bool verbose)
|
||||
appendPQExpBufferStr(&buf,
|
||||
"\nFROM pg_catalog.pg_tablespace\n");
|
||||
|
||||
processSQLNamePattern(pset.db, &buf, pattern, false, false,
|
||||
NULL, "spcname", NULL,
|
||||
NULL);
|
||||
if (!validateSQLNamePattern(&buf, pattern, false, false,
|
||||
NULL, "spcname", NULL,
|
||||
NULL,
|
||||
NULL, 1))
|
||||
return false;
|
||||
|
||||
appendPQExpBufferStr(&buf, "ORDER BY 1;");
|
||||
|
||||
@ -518,9 +530,11 @@ describeFunctions(const char *functypes, const char *func_pattern,
|
||||
appendPQExpBufferStr(&buf, " )\n");
|
||||
}
|
||||
|
||||
processSQLNamePattern(pset.db, &buf, func_pattern, have_where, false,
|
||||
"n.nspname", "p.proname", NULL,
|
||||
"pg_catalog.pg_function_is_visible(p.oid)");
|
||||
if (!validateSQLNamePattern(&buf, func_pattern, have_where, false,
|
||||
"n.nspname", "p.proname", NULL,
|
||||
"pg_catalog.pg_function_is_visible(p.oid)",
|
||||
NULL, 3))
|
||||
return false;
|
||||
|
||||
for (int i = 0; i < num_arg_patterns; i++)
|
||||
{
|
||||
@ -542,10 +556,12 @@ describeFunctions(const char *functypes, const char *func_pattern,
|
||||
"pg_catalog.format_type(t%d.oid, NULL)", i);
|
||||
snprintf(tiv, sizeof(tiv),
|
||||
"pg_catalog.pg_type_is_visible(t%d.oid)", i);
|
||||
processSQLNamePattern(pset.db, &buf,
|
||||
map_typename_pattern(arg_patterns[i]),
|
||||
true, false,
|
||||
nspname, typname, ft, tiv);
|
||||
if (!validateSQLNamePattern(&buf,
|
||||
map_typename_pattern(arg_patterns[i]),
|
||||
true, false,
|
||||
nspname, typname, ft, tiv,
|
||||
NULL, 3))
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -660,11 +676,13 @@ describeTypes(const char *pattern, bool verbose, bool showSystem)
|
||||
" AND n.nspname <> 'information_schema'\n");
|
||||
|
||||
/* Match name pattern against either internal or external name */
|
||||
processSQLNamePattern(pset.db, &buf, map_typename_pattern(pattern),
|
||||
true, false,
|
||||
"n.nspname", "t.typname",
|
||||
"pg_catalog.format_type(t.oid, NULL)",
|
||||
"pg_catalog.pg_type_is_visible(t.oid)");
|
||||
if (!validateSQLNamePattern(&buf, map_typename_pattern(pattern),
|
||||
true, false,
|
||||
"n.nspname", "t.typname",
|
||||
"pg_catalog.format_type(t.oid, NULL)",
|
||||
"pg_catalog.pg_type_is_visible(t.oid)",
|
||||
NULL, 3))
|
||||
return false;
|
||||
|
||||
appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
|
||||
|
||||
@ -813,10 +831,12 @@ describeOperators(const char *oper_pattern,
|
||||
appendPQExpBufferStr(&buf, "WHERE n.nspname <> 'pg_catalog'\n"
|
||||
" AND n.nspname <> 'information_schema'\n");
|
||||
|
||||
processSQLNamePattern(pset.db, &buf, oper_pattern,
|
||||
!showSystem && !oper_pattern, true,
|
||||
"n.nspname", "o.oprname", NULL,
|
||||
"pg_catalog.pg_operator_is_visible(o.oid)");
|
||||
if (!validateSQLNamePattern(&buf, oper_pattern,
|
||||
!showSystem && !oper_pattern, true,
|
||||
"n.nspname", "o.oprname", NULL,
|
||||
"pg_catalog.pg_operator_is_visible(o.oid)",
|
||||
NULL, 3))
|
||||
return false;
|
||||
|
||||
if (num_arg_patterns == 1)
|
||||
appendPQExpBufferStr(&buf, " AND o.oprleft = 0\n");
|
||||
@ -841,10 +861,12 @@ describeOperators(const char *oper_pattern,
|
||||
"pg_catalog.format_type(t%d.oid, NULL)", i);
|
||||
snprintf(tiv, sizeof(tiv),
|
||||
"pg_catalog.pg_type_is_visible(t%d.oid)", i);
|
||||
processSQLNamePattern(pset.db, &buf,
|
||||
map_typename_pattern(arg_patterns[i]),
|
||||
true, false,
|
||||
nspname, typname, ft, tiv);
|
||||
if (!validateSQLNamePattern(&buf,
|
||||
map_typename_pattern(arg_patterns[i]),
|
||||
true, false,
|
||||
nspname, typname, ft, tiv,
|
||||
NULL, 3))
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -928,8 +950,10 @@ listAllDbs(const char *pattern, bool verbose)
|
||||
" JOIN pg_catalog.pg_tablespace t on d.dattablespace = t.oid\n");
|
||||
|
||||
if (pattern)
|
||||
processSQLNamePattern(pset.db, &buf, pattern, false, false,
|
||||
NULL, "d.datname", NULL, NULL);
|
||||
if (!validateSQLNamePattern(&buf, pattern, false, false,
|
||||
NULL, "d.datname", NULL, NULL,
|
||||
NULL, 1))
|
||||
return false;
|
||||
|
||||
appendPQExpBufferStr(&buf, "ORDER BY 1;");
|
||||
res = PSQLexec(buf.data);
|
||||
@ -1078,9 +1102,11 @@ permissionsList(const char *pattern)
|
||||
* point of view. You can see 'em by explicit request though, eg with \z
|
||||
* pg_catalog.*
|
||||
*/
|
||||
processSQLNamePattern(pset.db, &buf, pattern, true, false,
|
||||
"n.nspname", "c.relname", NULL,
|
||||
"n.nspname !~ '^pg_' AND pg_catalog.pg_table_is_visible(c.oid)");
|
||||
if (!validateSQLNamePattern(&buf, pattern, true, false,
|
||||
"n.nspname", "c.relname", NULL,
|
||||
"n.nspname !~ '^pg_' AND pg_catalog.pg_table_is_visible(c.oid)",
|
||||
NULL, 3))
|
||||
return false;
|
||||
|
||||
appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
|
||||
|
||||
@ -1145,11 +1171,13 @@ listDefaultACLs(const char *pattern)
|
||||
appendPQExpBufferStr(&buf, "\nFROM pg_catalog.pg_default_acl d\n"
|
||||
" LEFT JOIN pg_catalog.pg_namespace n ON n.oid = d.defaclnamespace\n");
|
||||
|
||||
processSQLNamePattern(pset.db, &buf, pattern, false, false,
|
||||
NULL,
|
||||
"n.nspname",
|
||||
"pg_catalog.pg_get_userbyid(d.defaclrole)",
|
||||
NULL);
|
||||
if (!validateSQLNamePattern(&buf, pattern, false, false,
|
||||
NULL,
|
||||
"n.nspname",
|
||||
"pg_catalog.pg_get_userbyid(d.defaclrole)",
|
||||
NULL,
|
||||
NULL, 3))
|
||||
return false;
|
||||
|
||||
appendPQExpBufferStr(&buf, "ORDER BY 1, 2, 3;");
|
||||
|
||||
@ -1221,9 +1249,11 @@ objectDescription(const char *pattern, bool showSystem)
|
||||
appendPQExpBufferStr(&buf, "WHERE n.nspname <> 'pg_catalog'\n"
|
||||
" AND n.nspname <> 'information_schema'\n");
|
||||
|
||||
processSQLNamePattern(pset.db, &buf, pattern, !showSystem && !pattern,
|
||||
false, "n.nspname", "pgc.conname", NULL,
|
||||
"pg_catalog.pg_table_is_visible(c.oid)");
|
||||
if (!validateSQLNamePattern(&buf, pattern, !showSystem && !pattern,
|
||||
false, "n.nspname", "pgc.conname", NULL,
|
||||
"pg_catalog.pg_table_is_visible(c.oid)",
|
||||
NULL, 3))
|
||||
return false;
|
||||
|
||||
/* Domain constraint descriptions */
|
||||
appendPQExpBuffer(&buf,
|
||||
@ -1243,9 +1273,11 @@ objectDescription(const char *pattern, bool showSystem)
|
||||
appendPQExpBufferStr(&buf, "WHERE n.nspname <> 'pg_catalog'\n"
|
||||
" AND n.nspname <> 'information_schema'\n");
|
||||
|
||||
processSQLNamePattern(pset.db, &buf, pattern, !showSystem && !pattern,
|
||||
false, "n.nspname", "pgc.conname", NULL,
|
||||
"pg_catalog.pg_type_is_visible(t.oid)");
|
||||
if (!validateSQLNamePattern(&buf, pattern, !showSystem && !pattern,
|
||||
false, "n.nspname", "pgc.conname", NULL,
|
||||
"pg_catalog.pg_type_is_visible(t.oid)",
|
||||
NULL, 3))
|
||||
return false;
|
||||
|
||||
/* Operator class descriptions */
|
||||
appendPQExpBuffer(&buf,
|
||||
@ -1265,9 +1297,11 @@ objectDescription(const char *pattern, bool showSystem)
|
||||
appendPQExpBufferStr(&buf, " AND n.nspname <> 'pg_catalog'\n"
|
||||
" AND n.nspname <> 'information_schema'\n");
|
||||
|
||||
processSQLNamePattern(pset.db, &buf, pattern, true, false,
|
||||
"n.nspname", "o.opcname", NULL,
|
||||
"pg_catalog.pg_opclass_is_visible(o.oid)");
|
||||
if (!validateSQLNamePattern(&buf, pattern, true, false,
|
||||
"n.nspname", "o.opcname", NULL,
|
||||
"pg_catalog.pg_opclass_is_visible(o.oid)",
|
||||
NULL, 3))
|
||||
return false;
|
||||
|
||||
/* Operator family descriptions */
|
||||
appendPQExpBuffer(&buf,
|
||||
@ -1287,9 +1321,11 @@ objectDescription(const char *pattern, bool showSystem)
|
||||
appendPQExpBufferStr(&buf, " AND n.nspname <> 'pg_catalog'\n"
|
||||
" AND n.nspname <> 'information_schema'\n");
|
||||
|
||||
processSQLNamePattern(pset.db, &buf, pattern, true, false,
|
||||
"n.nspname", "opf.opfname", NULL,
|
||||
"pg_catalog.pg_opfamily_is_visible(opf.oid)");
|
||||
if (!validateSQLNamePattern(&buf, pattern, true, false,
|
||||
"n.nspname", "opf.opfname", NULL,
|
||||
"pg_catalog.pg_opfamily_is_visible(opf.oid)",
|
||||
NULL, 3))
|
||||
return false;
|
||||
|
||||
/* Rule descriptions (ignore rules for views) */
|
||||
appendPQExpBuffer(&buf,
|
||||
@ -1308,9 +1344,11 @@ objectDescription(const char *pattern, bool showSystem)
|
||||
appendPQExpBufferStr(&buf, " AND n.nspname <> 'pg_catalog'\n"
|
||||
" AND n.nspname <> 'information_schema'\n");
|
||||
|
||||
processSQLNamePattern(pset.db, &buf, pattern, true, false,
|
||||
"n.nspname", "r.rulename", NULL,
|
||||
"pg_catalog.pg_table_is_visible(c.oid)");
|
||||
if (!validateSQLNamePattern(&buf, pattern, true, false,
|
||||
"n.nspname", "r.rulename", NULL,
|
||||
"pg_catalog.pg_table_is_visible(c.oid)",
|
||||
NULL, 3))
|
||||
return false;
|
||||
|
||||
/* Trigger descriptions */
|
||||
appendPQExpBuffer(&buf,
|
||||
@ -1328,9 +1366,11 @@ objectDescription(const char *pattern, bool showSystem)
|
||||
appendPQExpBufferStr(&buf, "WHERE n.nspname <> 'pg_catalog'\n"
|
||||
" AND n.nspname <> 'information_schema'\n");
|
||||
|
||||
processSQLNamePattern(pset.db, &buf, pattern, !showSystem && !pattern, false,
|
||||
"n.nspname", "t.tgname", NULL,
|
||||
"pg_catalog.pg_table_is_visible(c.oid)");
|
||||
if (!validateSQLNamePattern(&buf, pattern, !showSystem && !pattern, false,
|
||||
"n.nspname", "t.tgname", NULL,
|
||||
"pg_catalog.pg_table_is_visible(c.oid)",
|
||||
NULL, 3))
|
||||
return false;
|
||||
|
||||
appendPQExpBufferStr(&buf,
|
||||
") AS tt\n"
|
||||
@ -1384,9 +1424,11 @@ describeTableDetails(const char *pattern, bool verbose, bool showSystem)
|
||||
appendPQExpBufferStr(&buf, "WHERE n.nspname <> 'pg_catalog'\n"
|
||||
" AND n.nspname <> 'information_schema'\n");
|
||||
|
||||
processSQLNamePattern(pset.db, &buf, pattern, !showSystem && !pattern, false,
|
||||
"n.nspname", "c.relname", NULL,
|
||||
"pg_catalog.pg_table_is_visible(c.oid)");
|
||||
if (!validateSQLNamePattern(&buf, pattern, !showSystem && !pattern, false,
|
||||
"n.nspname", "c.relname", NULL,
|
||||
"pg_catalog.pg_table_is_visible(c.oid)",
|
||||
NULL, 3))
|
||||
return false;
|
||||
|
||||
appendPQExpBufferStr(&buf, "ORDER BY 2, 3;");
|
||||
|
||||
@ -3572,8 +3614,10 @@ describeRoles(const char *pattern, bool verbose, bool showSystem)
|
||||
if (!showSystem && !pattern)
|
||||
appendPQExpBufferStr(&buf, "WHERE r.rolname !~ '^pg_'\n");
|
||||
|
||||
processSQLNamePattern(pset.db, &buf, pattern, false, false,
|
||||
NULL, "r.rolname", NULL, NULL);
|
||||
if (!validateSQLNamePattern(&buf, pattern, false, false,
|
||||
NULL, "r.rolname", NULL, NULL,
|
||||
NULL, 1))
|
||||
return false;
|
||||
|
||||
appendPQExpBufferStr(&buf, "ORDER BY 1;");
|
||||
|
||||
@ -3696,10 +3740,13 @@ listDbRoleSettings(const char *pattern, const char *pattern2)
|
||||
gettext_noop("Role"),
|
||||
gettext_noop("Database"),
|
||||
gettext_noop("Settings"));
|
||||
havewhere = processSQLNamePattern(pset.db, &buf, pattern, false, false,
|
||||
NULL, "r.rolname", NULL, NULL);
|
||||
processSQLNamePattern(pset.db, &buf, pattern2, havewhere, false,
|
||||
NULL, "d.datname", NULL, NULL);
|
||||
if (!validateSQLNamePattern(&buf, pattern, false, false,
|
||||
NULL, "r.rolname", NULL, NULL, &havewhere, 1))
|
||||
return false;
|
||||
if (!validateSQLNamePattern(&buf, pattern2, havewhere, false,
|
||||
NULL, "d.datname", NULL, NULL,
|
||||
NULL, 1))
|
||||
return false;
|
||||
appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
|
||||
|
||||
res = PSQLexec(buf.data);
|
||||
@ -3892,9 +3939,11 @@ listTables(const char *tabtypes, const char *pattern, bool verbose, bool showSys
|
||||
" AND n.nspname !~ '^pg_toast'\n"
|
||||
" AND n.nspname <> 'information_schema'\n");
|
||||
|
||||
processSQLNamePattern(pset.db, &buf, pattern, true, false,
|
||||
"n.nspname", "c.relname", NULL,
|
||||
"pg_catalog.pg_table_is_visible(c.oid)");
|
||||
if (!validateSQLNamePattern(&buf, pattern, true, false,
|
||||
"n.nspname", "c.relname", NULL,
|
||||
"pg_catalog.pg_table_is_visible(c.oid)",
|
||||
NULL, 3))
|
||||
return false;
|
||||
|
||||
appendPQExpBufferStr(&buf, "ORDER BY 1,2;");
|
||||
|
||||
@ -4107,9 +4156,11 @@ listPartitionedTables(const char *reltypes, const char *pattern, bool verbose)
|
||||
" AND n.nspname !~ '^pg_toast'\n"
|
||||
" AND n.nspname <> 'information_schema'\n");
|
||||
|
||||
processSQLNamePattern(pset.db, &buf, pattern, true, false,
|
||||
"n.nspname", "c.relname", NULL,
|
||||
"pg_catalog.pg_table_is_visible(c.oid)");
|
||||
if (!validateSQLNamePattern(&buf, pattern, true, false,
|
||||
"n.nspname", "c.relname", NULL,
|
||||
"pg_catalog.pg_table_is_visible(c.oid)",
|
||||
NULL, 3))
|
||||
return false;
|
||||
|
||||
appendPQExpBuffer(&buf, "ORDER BY \"Schema\", %s%s\"Name\";",
|
||||
mixed_output ? "\"Type\" DESC, " : "",
|
||||
@ -4182,8 +4233,10 @@ listLanguages(const char *pattern, bool verbose, bool showSystem)
|
||||
gettext_noop("Description"));
|
||||
|
||||
if (pattern)
|
||||
processSQLNamePattern(pset.db, &buf, pattern, false, false,
|
||||
NULL, "l.lanname", NULL, NULL);
|
||||
if (!validateSQLNamePattern(&buf, pattern, false, false,
|
||||
NULL, "l.lanname", NULL, NULL,
|
||||
NULL, 2))
|
||||
return false;
|
||||
|
||||
if (!showSystem && !pattern)
|
||||
appendPQExpBufferStr(&buf, "WHERE l.lanplcallfoid != 0\n");
|
||||
@ -4265,9 +4318,11 @@ listDomains(const char *pattern, bool verbose, bool showSystem)
|
||||
appendPQExpBufferStr(&buf, " AND n.nspname <> 'pg_catalog'\n"
|
||||
" AND n.nspname <> 'information_schema'\n");
|
||||
|
||||
processSQLNamePattern(pset.db, &buf, pattern, true, false,
|
||||
"n.nspname", "t.typname", NULL,
|
||||
"pg_catalog.pg_type_is_visible(t.oid)");
|
||||
if (!validateSQLNamePattern(&buf, pattern, true, false,
|
||||
"n.nspname", "t.typname", NULL,
|
||||
"pg_catalog.pg_type_is_visible(t.oid)",
|
||||
NULL, 3))
|
||||
return false;
|
||||
|
||||
appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
|
||||
|
||||
@ -4339,9 +4394,11 @@ listConversions(const char *pattern, bool verbose, bool showSystem)
|
||||
appendPQExpBufferStr(&buf, " AND n.nspname <> 'pg_catalog'\n"
|
||||
" AND n.nspname <> 'information_schema'\n");
|
||||
|
||||
processSQLNamePattern(pset.db, &buf, pattern, true, false,
|
||||
"n.nspname", "c.conname", NULL,
|
||||
"pg_catalog.pg_conversion_is_visible(c.oid)");
|
||||
if (!validateSQLNamePattern(&buf, pattern, true, false,
|
||||
"n.nspname", "c.conname", NULL,
|
||||
"pg_catalog.pg_conversion_is_visible(c.oid)",
|
||||
NULL, 3))
|
||||
return false;
|
||||
|
||||
appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
|
||||
|
||||
@ -4406,7 +4463,7 @@ describeConfigurationParameters(const char *pattern, bool verbose,
|
||||
processSQLNamePattern(pset.db, &buf, pattern,
|
||||
false, false,
|
||||
NULL, "pg_catalog.lower(s.name)", NULL,
|
||||
NULL);
|
||||
NULL, NULL, NULL);
|
||||
else
|
||||
appendPQExpBufferStr(&buf, "WHERE s.source <> 'default' AND\n"
|
||||
" s.setting IS DISTINCT FROM s.boot_val\n");
|
||||
@ -4485,8 +4542,10 @@ listEventTriggers(const char *pattern, bool verbose)
|
||||
appendPQExpBufferStr(&buf,
|
||||
"\nFROM pg_catalog.pg_event_trigger e ");
|
||||
|
||||
processSQLNamePattern(pset.db, &buf, pattern, false, false,
|
||||
NULL, "evtname", NULL, NULL);
|
||||
if (!validateSQLNamePattern(&buf, pattern, false, false,
|
||||
NULL, "evtname", NULL, NULL,
|
||||
NULL, 1))
|
||||
return false;
|
||||
|
||||
appendPQExpBufferStr(&buf, "ORDER BY 1");
|
||||
|
||||
@ -4577,10 +4636,12 @@ listExtendedStats(const char *pattern)
|
||||
appendPQExpBufferStr(&buf,
|
||||
" \nFROM pg_catalog.pg_statistic_ext es \n");
|
||||
|
||||
processSQLNamePattern(pset.db, &buf, pattern,
|
||||
false, false,
|
||||
"es.stxnamespace::pg_catalog.regnamespace::pg_catalog.text", "es.stxname",
|
||||
NULL, "pg_catalog.pg_statistics_obj_is_visible(es.oid)");
|
||||
if (!validateSQLNamePattern(&buf, pattern,
|
||||
false, false,
|
||||
"es.stxnamespace::pg_catalog.regnamespace::pg_catalog.text", "es.stxname",
|
||||
NULL, "pg_catalog.pg_statistics_obj_is_visible(es.oid)",
|
||||
NULL, 3))
|
||||
return false;
|
||||
|
||||
appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
|
||||
|
||||
@ -4679,17 +4740,21 @@ listCasts(const char *pattern, bool verbose)
|
||||
* Match name pattern against either internal or external name of either
|
||||
* castsource or casttarget
|
||||
*/
|
||||
processSQLNamePattern(pset.db, &buf, pattern, true, false,
|
||||
"ns.nspname", "ts.typname",
|
||||
"pg_catalog.format_type(ts.oid, NULL)",
|
||||
"pg_catalog.pg_type_is_visible(ts.oid)");
|
||||
if (!validateSQLNamePattern(&buf, pattern, true, false,
|
||||
"ns.nspname", "ts.typname",
|
||||
"pg_catalog.format_type(ts.oid, NULL)",
|
||||
"pg_catalog.pg_type_is_visible(ts.oid)",
|
||||
NULL, 3))
|
||||
return false;
|
||||
|
||||
appendPQExpBufferStr(&buf, ") OR (true");
|
||||
|
||||
processSQLNamePattern(pset.db, &buf, pattern, true, false,
|
||||
"nt.nspname", "tt.typname",
|
||||
"pg_catalog.format_type(tt.oid, NULL)",
|
||||
"pg_catalog.pg_type_is_visible(tt.oid)");
|
||||
if (!validateSQLNamePattern(&buf, pattern, true, false,
|
||||
"nt.nspname", "tt.typname",
|
||||
"pg_catalog.format_type(tt.oid, NULL)",
|
||||
"pg_catalog.pg_type_is_visible(tt.oid)",
|
||||
NULL, 3))
|
||||
return false;
|
||||
|
||||
appendPQExpBufferStr(&buf, ") )\nORDER BY 1, 2;");
|
||||
|
||||
@ -4785,9 +4850,11 @@ listCollations(const char *pattern, bool verbose, bool showSystem)
|
||||
*/
|
||||
appendPQExpBufferStr(&buf, " AND c.collencoding IN (-1, pg_catalog.pg_char_to_encoding(pg_catalog.getdatabaseencoding()))\n");
|
||||
|
||||
processSQLNamePattern(pset.db, &buf, pattern, true, false,
|
||||
"n.nspname", "c.collname", NULL,
|
||||
"pg_catalog.pg_collation_is_visible(c.oid)");
|
||||
if (!validateSQLNamePattern(&buf, pattern, true, false,
|
||||
"n.nspname", "c.collname", NULL,
|
||||
"pg_catalog.pg_collation_is_visible(c.oid)",
|
||||
NULL, 3))
|
||||
return false;
|
||||
|
||||
appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
|
||||
|
||||
@ -4845,10 +4912,12 @@ listSchemas(const char *pattern, bool verbose, bool showSystem)
|
||||
appendPQExpBufferStr(&buf,
|
||||
"WHERE n.nspname !~ '^pg_' AND n.nspname <> 'information_schema'\n");
|
||||
|
||||
processSQLNamePattern(pset.db, &buf, pattern,
|
||||
!showSystem && !pattern, false,
|
||||
NULL, "n.nspname", NULL,
|
||||
NULL);
|
||||
if (!validateSQLNamePattern(&buf, pattern,
|
||||
!showSystem && !pattern, false,
|
||||
NULL, "n.nspname", NULL,
|
||||
NULL,
|
||||
NULL, 2))
|
||||
return false;
|
||||
|
||||
appendPQExpBufferStr(&buf, "ORDER BY 1;");
|
||||
|
||||
@ -4959,9 +5028,11 @@ listTSParsers(const char *pattern, bool verbose)
|
||||
gettext_noop("Description")
|
||||
);
|
||||
|
||||
processSQLNamePattern(pset.db, &buf, pattern, false, false,
|
||||
"n.nspname", "p.prsname", NULL,
|
||||
"pg_catalog.pg_ts_parser_is_visible(p.oid)");
|
||||
if (!validateSQLNamePattern(&buf, pattern, false, false,
|
||||
"n.nspname", "p.prsname", NULL,
|
||||
"pg_catalog.pg_ts_parser_is_visible(p.oid)",
|
||||
NULL, 3))
|
||||
return false;
|
||||
|
||||
appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
|
||||
|
||||
@ -5000,9 +5071,11 @@ listTSParsersVerbose(const char *pattern)
|
||||
"LEFT JOIN pg_catalog.pg_namespace n ON n.oid = p.prsnamespace\n"
|
||||
);
|
||||
|
||||
processSQLNamePattern(pset.db, &buf, pattern, false, false,
|
||||
"n.nspname", "p.prsname", NULL,
|
||||
"pg_catalog.pg_ts_parser_is_visible(p.oid)");
|
||||
if (!validateSQLNamePattern(&buf, pattern, false, false,
|
||||
"n.nspname", "p.prsname", NULL,
|
||||
"pg_catalog.pg_ts_parser_is_visible(p.oid)",
|
||||
NULL, 3))
|
||||
return false;
|
||||
|
||||
appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
|
||||
|
||||
@ -5207,9 +5280,11 @@ listTSDictionaries(const char *pattern, bool verbose)
|
||||
appendPQExpBufferStr(&buf, "FROM pg_catalog.pg_ts_dict d\n"
|
||||
"LEFT JOIN pg_catalog.pg_namespace n ON n.oid = d.dictnamespace\n");
|
||||
|
||||
processSQLNamePattern(pset.db, &buf, pattern, false, false,
|
||||
"n.nspname", "d.dictname", NULL,
|
||||
"pg_catalog.pg_ts_dict_is_visible(d.oid)");
|
||||
if (!validateSQLNamePattern(&buf, pattern, false, false,
|
||||
"n.nspname", "d.dictname", NULL,
|
||||
"pg_catalog.pg_ts_dict_is_visible(d.oid)",
|
||||
NULL, 3))
|
||||
return false;
|
||||
|
||||
appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
|
||||
|
||||
@ -5268,9 +5343,11 @@ listTSTemplates(const char *pattern, bool verbose)
|
||||
appendPQExpBufferStr(&buf, "FROM pg_catalog.pg_ts_template t\n"
|
||||
"LEFT JOIN pg_catalog.pg_namespace n ON n.oid = t.tmplnamespace\n");
|
||||
|
||||
processSQLNamePattern(pset.db, &buf, pattern, false, false,
|
||||
"n.nspname", "t.tmplname", NULL,
|
||||
"pg_catalog.pg_ts_template_is_visible(t.oid)");
|
||||
if (!validateSQLNamePattern(&buf, pattern, false, false,
|
||||
"n.nspname", "t.tmplname", NULL,
|
||||
"pg_catalog.pg_ts_template_is_visible(t.oid)",
|
||||
NULL, 3))
|
||||
return false;
|
||||
|
||||
appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
|
||||
|
||||
@ -5318,9 +5395,11 @@ listTSConfigs(const char *pattern, bool verbose)
|
||||
gettext_noop("Description")
|
||||
);
|
||||
|
||||
processSQLNamePattern(pset.db, &buf, pattern, false, false,
|
||||
"n.nspname", "c.cfgname", NULL,
|
||||
"pg_catalog.pg_ts_config_is_visible(c.oid)");
|
||||
if (!validateSQLNamePattern(&buf, pattern, false, false,
|
||||
"n.nspname", "c.cfgname", NULL,
|
||||
"pg_catalog.pg_ts_config_is_visible(c.oid)",
|
||||
NULL, 3))
|
||||
return false;
|
||||
|
||||
appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
|
||||
|
||||
@ -5360,9 +5439,11 @@ listTSConfigsVerbose(const char *pattern)
|
||||
"WHERE p.oid = c.cfgparser\n"
|
||||
);
|
||||
|
||||
processSQLNamePattern(pset.db, &buf, pattern, true, false,
|
||||
"n.nspname", "c.cfgname", NULL,
|
||||
"pg_catalog.pg_ts_config_is_visible(c.oid)");
|
||||
if (!validateSQLNamePattern(&buf, pattern, true, false,
|
||||
"n.nspname", "c.cfgname", NULL,
|
||||
"pg_catalog.pg_ts_config_is_visible(c.oid)",
|
||||
NULL, 3))
|
||||
return false;
|
||||
|
||||
appendPQExpBufferStr(&buf, "ORDER BY 3, 2;");
|
||||
|
||||
@ -5532,8 +5613,10 @@ listForeignDataWrappers(const char *pattern, bool verbose)
|
||||
" ON d.classoid = fdw.tableoid "
|
||||
"AND d.objoid = fdw.oid AND d.objsubid = 0\n");
|
||||
|
||||
processSQLNamePattern(pset.db, &buf, pattern, false, false,
|
||||
NULL, "fdwname", NULL, NULL);
|
||||
if (!validateSQLNamePattern(&buf, pattern, false, false,
|
||||
NULL, "fdwname", NULL, NULL,
|
||||
NULL, 1))
|
||||
return false;
|
||||
|
||||
appendPQExpBufferStr(&buf, "ORDER BY 1;");
|
||||
|
||||
@ -5604,8 +5687,10 @@ listForeignServers(const char *pattern, bool verbose)
|
||||
"ON d.classoid = s.tableoid AND d.objoid = s.oid "
|
||||
"AND d.objsubid = 0\n");
|
||||
|
||||
processSQLNamePattern(pset.db, &buf, pattern, false, false,
|
||||
NULL, "s.srvname", NULL, NULL);
|
||||
if (!validateSQLNamePattern(&buf, pattern, false, false,
|
||||
NULL, "s.srvname", NULL, NULL,
|
||||
NULL, 1))
|
||||
return false;
|
||||
|
||||
appendPQExpBufferStr(&buf, "ORDER BY 1;");
|
||||
|
||||
@ -5655,8 +5740,10 @@ listUserMappings(const char *pattern, bool verbose)
|
||||
|
||||
appendPQExpBufferStr(&buf, "\nFROM pg_catalog.pg_user_mappings um\n");
|
||||
|
||||
processSQLNamePattern(pset.db, &buf, pattern, false, false,
|
||||
NULL, "um.srvname", "um.usename", NULL);
|
||||
if (!validateSQLNamePattern(&buf, pattern, false, false,
|
||||
NULL, "um.srvname", "um.usename", NULL,
|
||||
NULL, 1))
|
||||
return false;
|
||||
|
||||
appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
|
||||
|
||||
@ -5722,9 +5809,11 @@ listForeignTables(const char *pattern, bool verbose)
|
||||
" ON d.classoid = c.tableoid AND "
|
||||
"d.objoid = c.oid AND d.objsubid = 0\n");
|
||||
|
||||
processSQLNamePattern(pset.db, &buf, pattern, false, false,
|
||||
"n.nspname", "c.relname", NULL,
|
||||
"pg_catalog.pg_table_is_visible(c.oid)");
|
||||
if (!validateSQLNamePattern(&buf, pattern, false, false,
|
||||
"n.nspname", "c.relname", NULL,
|
||||
"pg_catalog.pg_table_is_visible(c.oid)",
|
||||
NULL, 3))
|
||||
return false;
|
||||
|
||||
appendPQExpBufferStr(&buf, "ORDER BY 1, 2;");
|
||||
|
||||
@ -5768,10 +5857,12 @@ listExtensions(const char *pattern)
|
||||
gettext_noop("Schema"),
|
||||
gettext_noop("Description"));
|
||||
|
||||
processSQLNamePattern(pset.db, &buf, pattern,
|
||||
false, false,
|
||||
NULL, "e.extname", NULL,
|
||||
NULL);
|
||||
if (!validateSQLNamePattern(&buf, pattern,
|
||||
false, false,
|
||||
NULL, "e.extname", NULL,
|
||||
NULL,
|
||||
NULL, 1))
|
||||
return false;
|
||||
|
||||
appendPQExpBufferStr(&buf, "ORDER BY 1;");
|
||||
|
||||
@ -5807,10 +5898,12 @@ listExtensionContents(const char *pattern)
|
||||
"SELECT e.extname, e.oid\n"
|
||||
"FROM pg_catalog.pg_extension e\n");
|
||||
|
||||
processSQLNamePattern(pset.db, &buf, pattern,
|
||||
false, false,
|
||||
NULL, "e.extname", NULL,
|
||||
NULL);
|
||||
if (!validateSQLNamePattern(&buf, pattern,
|
||||
false, false,
|
||||
NULL, "e.extname", NULL,
|
||||
NULL,
|
||||
NULL, 1))
|
||||
return false;
|
||||
|
||||
appendPQExpBufferStr(&buf, "ORDER BY 1;");
|
||||
|
||||
@ -5892,6 +5985,59 @@ listOneExtensionContents(const char *extname, const char *oid)
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* validateSQLNamePattern
|
||||
*
|
||||
* Wrapper around string_utils's processSQLNamePattern which also checks the
|
||||
* pattern's validity. In addition to that function's parameters, takes a
|
||||
* 'maxparts' parameter specifying the maximum number of dotted names the
|
||||
* pattern is allowed to have, and a 'added_clause' parameter that returns by
|
||||
* reference whether a clause was added to 'buf'. Returns whether the pattern
|
||||
* passed validation, after logging any errors.
|
||||
*/
|
||||
static bool
|
||||
validateSQLNamePattern(PQExpBuffer buf, const char *pattern, bool have_where,
|
||||
bool force_escape, const char *schemavar,
|
||||
const char *namevar, const char *altnamevar,
|
||||
const char *visibilityrule, bool *added_clause,
|
||||
int maxparts)
|
||||
{
|
||||
PQExpBufferData dbbuf;
|
||||
int dotcnt;
|
||||
bool added;
|
||||
|
||||
initPQExpBuffer(&dbbuf);
|
||||
added = processSQLNamePattern(pset.db, buf, pattern, have_where, force_escape,
|
||||
schemavar, namevar, altnamevar,
|
||||
visibilityrule, &dbbuf, &dotcnt);
|
||||
if (added_clause != NULL)
|
||||
*added_clause = added;
|
||||
|
||||
if (dotcnt >= maxparts)
|
||||
{
|
||||
pg_log_error("improper qualified name (too many dotted names): %s",
|
||||
pattern);
|
||||
termPQExpBuffer(&dbbuf);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (maxparts > 1 && dotcnt == maxparts-1)
|
||||
{
|
||||
if (PQdb(pset.db) == NULL)
|
||||
{
|
||||
pg_log_error("You are currently not connected to a database.");
|
||||
return false;
|
||||
}
|
||||
if (strcmp(PQdb(pset.db), dbbuf.data) != 0)
|
||||
{
|
||||
pg_log_error("cross-database references are not implemented: %s",
|
||||
pattern);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* \dRp
|
||||
* Lists publications.
|
||||
@ -5943,9 +6089,11 @@ listPublications(const char *pattern)
|
||||
appendPQExpBufferStr(&buf,
|
||||
"\nFROM pg_catalog.pg_publication\n");
|
||||
|
||||
processSQLNamePattern(pset.db, &buf, pattern, false, false,
|
||||
NULL, "pubname", NULL,
|
||||
NULL);
|
||||
if (!validateSQLNamePattern(&buf, pattern, false, false,
|
||||
NULL, "pubname", NULL,
|
||||
NULL,
|
||||
NULL, 1))
|
||||
return false;
|
||||
|
||||
appendPQExpBufferStr(&buf, "ORDER BY 1;");
|
||||
|
||||
@ -6056,9 +6204,11 @@ describePublications(const char *pattern)
|
||||
appendPQExpBufferStr(&buf,
|
||||
"\nFROM pg_catalog.pg_publication\n");
|
||||
|
||||
processSQLNamePattern(pset.db, &buf, pattern, false, false,
|
||||
NULL, "pubname", NULL,
|
||||
NULL);
|
||||
if (!validateSQLNamePattern(&buf, pattern, false, false,
|
||||
NULL, "pubname", NULL,
|
||||
NULL,
|
||||
NULL, 1))
|
||||
return false;
|
||||
|
||||
appendPQExpBufferStr(&buf, "ORDER BY 2;");
|
||||
|
||||
@ -6266,9 +6416,11 @@ describeSubscriptions(const char *pattern, bool verbose)
|
||||
" FROM pg_catalog.pg_database\n"
|
||||
" WHERE datname = pg_catalog.current_database())");
|
||||
|
||||
processSQLNamePattern(pset.db, &buf, pattern, true, false,
|
||||
NULL, "subname", NULL,
|
||||
NULL);
|
||||
if (!validateSQLNamePattern(&buf, pattern, true, false,
|
||||
NULL, "subname", NULL,
|
||||
NULL,
|
||||
NULL, 1))
|
||||
return false;
|
||||
|
||||
appendPQExpBufferStr(&buf, "ORDER BY 1;");
|
||||
|
||||
@ -6369,15 +6521,19 @@ listOperatorClasses(const char *access_method_pattern,
|
||||
" LEFT JOIN pg_catalog.pg_namespace ofn ON ofn.oid = of.opfnamespace\n");
|
||||
|
||||
if (access_method_pattern)
|
||||
have_where = processSQLNamePattern(pset.db, &buf, access_method_pattern,
|
||||
false, false, NULL, "am.amname", NULL, NULL);
|
||||
if (!validateSQLNamePattern(&buf, access_method_pattern,
|
||||
false, false, NULL, "am.amname", NULL, NULL,
|
||||
&have_where, 1))
|
||||
return false;
|
||||
if (type_pattern)
|
||||
{
|
||||
/* Match type name pattern against either internal or external name */
|
||||
processSQLNamePattern(pset.db, &buf, type_pattern, have_where, false,
|
||||
"tn.nspname", "t.typname",
|
||||
"pg_catalog.format_type(t.oid, NULL)",
|
||||
"pg_catalog.pg_type_is_visible(t.oid)");
|
||||
if (!validateSQLNamePattern(&buf, type_pattern, have_where, false,
|
||||
"tn.nspname", "t.typname",
|
||||
"pg_catalog.format_type(t.oid, NULL)",
|
||||
"pg_catalog.pg_type_is_visible(t.oid)",
|
||||
NULL, 3))
|
||||
return false;
|
||||
}
|
||||
|
||||
appendPQExpBufferStr(&buf, "ORDER BY 1, 2, 4;");
|
||||
@ -6441,8 +6597,10 @@ listOperatorFamilies(const char *access_method_pattern,
|
||||
" LEFT JOIN pg_catalog.pg_namespace n ON n.oid = f.opfnamespace\n");
|
||||
|
||||
if (access_method_pattern)
|
||||
have_where = processSQLNamePattern(pset.db, &buf, access_method_pattern,
|
||||
false, false, NULL, "am.amname", NULL, NULL);
|
||||
if (!validateSQLNamePattern(&buf, access_method_pattern,
|
||||
false, false, NULL, "am.amname", NULL, NULL,
|
||||
&have_where, 1))
|
||||
return false;
|
||||
if (type_pattern)
|
||||
{
|
||||
appendPQExpBuffer(&buf,
|
||||
@ -6454,10 +6612,12 @@ listOperatorFamilies(const char *access_method_pattern,
|
||||
" WHERE oc.opcfamily = f.oid\n",
|
||||
have_where ? "AND" : "WHERE");
|
||||
/* Match type name pattern against either internal or external name */
|
||||
processSQLNamePattern(pset.db, &buf, type_pattern, true, false,
|
||||
"tn.nspname", "t.typname",
|
||||
"pg_catalog.format_type(t.oid, NULL)",
|
||||
"pg_catalog.pg_type_is_visible(t.oid)");
|
||||
if (!validateSQLNamePattern(&buf, type_pattern, true, false,
|
||||
"tn.nspname", "t.typname",
|
||||
"pg_catalog.format_type(t.oid, NULL)",
|
||||
"pg_catalog.pg_type_is_visible(t.oid)",
|
||||
NULL, 3))
|
||||
return false;
|
||||
appendPQExpBufferStr(&buf, " )\n");
|
||||
}
|
||||
|
||||
@ -6535,13 +6695,17 @@ listOpFamilyOperators(const char *access_method_pattern,
|
||||
" LEFT JOIN pg_catalog.pg_opfamily ofs ON ofs.oid = o.amopsortfamily\n");
|
||||
|
||||
if (access_method_pattern)
|
||||
have_where = processSQLNamePattern(pset.db, &buf, access_method_pattern,
|
||||
false, false, NULL, "am.amname",
|
||||
NULL, NULL);
|
||||
if (!validateSQLNamePattern(&buf, access_method_pattern,
|
||||
false, false, NULL, "am.amname",
|
||||
NULL, NULL,
|
||||
&have_where, 1))
|
||||
return false;
|
||||
|
||||
if (family_pattern)
|
||||
processSQLNamePattern(pset.db, &buf, family_pattern, have_where, false,
|
||||
"nsf.nspname", "of.opfname", NULL, NULL);
|
||||
if (!validateSQLNamePattern(&buf, family_pattern, have_where, false,
|
||||
"nsf.nspname", "of.opfname", NULL, NULL,
|
||||
NULL, 3))
|
||||
return false;
|
||||
|
||||
appendPQExpBufferStr(&buf, "ORDER BY 1, 2,\n"
|
||||
" o.amoplefttype = o.amoprighttype DESC,\n"
|
||||
@ -6619,12 +6783,16 @@ listOpFamilyFunctions(const char *access_method_pattern,
|
||||
" LEFT JOIN pg_catalog.pg_proc p ON ap.amproc = p.oid\n");
|
||||
|
||||
if (access_method_pattern)
|
||||
have_where = processSQLNamePattern(pset.db, &buf, access_method_pattern,
|
||||
false, false, NULL, "am.amname",
|
||||
NULL, NULL);
|
||||
if (!validateSQLNamePattern(&buf, access_method_pattern,
|
||||
false, false, NULL, "am.amname",
|
||||
NULL, NULL,
|
||||
&have_where, 1))
|
||||
return false;
|
||||
if (family_pattern)
|
||||
processSQLNamePattern(pset.db, &buf, family_pattern, have_where, false,
|
||||
"ns.nspname", "of.opfname", NULL, NULL);
|
||||
if (!validateSQLNamePattern(&buf, family_pattern, have_where, false,
|
||||
"ns.nspname", "of.opfname", NULL, NULL,
|
||||
NULL, 3))
|
||||
return false;
|
||||
|
||||
appendPQExpBufferStr(&buf, "ORDER BY 1, 2,\n"
|
||||
" ap.amproclefttype = ap.amprocrighttype DESC,\n"
|
||||
|
@ -882,6 +882,9 @@ appendReloptionsArray(PQExpBuffer buffer, const char *reloptions,
|
||||
* altnamevar: NULL, or name of an alternative variable to match against name.
|
||||
* visibilityrule: clause to use if we want to restrict to visible objects
|
||||
* (for example, "pg_catalog.pg_table_is_visible(p.oid)"). Can be NULL.
|
||||
* dbnamebuf: output parameter receiving the database name portion of the
|
||||
* pattern, if any. Can be NULL.
|
||||
* dotcnt: how many separators were parsed from the pattern, by reference.
|
||||
*
|
||||
* Formatting note: the text already present in buf should end with a newline.
|
||||
* The appended text, if any, will end with one too.
|
||||
@ -890,16 +893,21 @@ bool
|
||||
processSQLNamePattern(PGconn *conn, PQExpBuffer buf, const char *pattern,
|
||||
bool have_where, bool force_escape,
|
||||
const char *schemavar, const char *namevar,
|
||||
const char *altnamevar, const char *visibilityrule)
|
||||
const char *altnamevar, const char *visibilityrule,
|
||||
PQExpBuffer dbnamebuf, int *dotcnt)
|
||||
{
|
||||
PQExpBufferData schemabuf;
|
||||
PQExpBufferData namebuf;
|
||||
bool added_clause = false;
|
||||
int dcnt;
|
||||
|
||||
#define WHEREAND() \
|
||||
(appendPQExpBufferStr(buf, have_where ? " AND " : "WHERE "), \
|
||||
have_where = true, added_clause = true)
|
||||
|
||||
if (dotcnt == NULL)
|
||||
dotcnt = &dcnt;
|
||||
*dotcnt = 0;
|
||||
if (pattern == NULL)
|
||||
{
|
||||
/* Default: select all visible objects */
|
||||
@ -922,9 +930,11 @@ processSQLNamePattern(PGconn *conn, PQExpBuffer buf, const char *pattern,
|
||||
* If the caller provided a schemavar, we want to split the pattern on
|
||||
* ".", otherwise not.
|
||||
*/
|
||||
patternToSQLRegex(PQclientEncoding(conn), NULL,
|
||||
(schemavar ? &schemabuf : NULL), &namebuf,
|
||||
pattern, force_escape);
|
||||
patternToSQLRegex(PQclientEncoding(conn),
|
||||
(schemavar ? dbnamebuf : NULL),
|
||||
(schemavar ? &schemabuf : NULL),
|
||||
&namebuf,
|
||||
pattern, force_escape, true, dotcnt);
|
||||
|
||||
/*
|
||||
* Now decide what we need to emit. We may run under a hostile
|
||||
@ -937,7 +947,7 @@ processSQLNamePattern(PGconn *conn, PQExpBuffer buf, const char *pattern,
|
||||
* is >= v12 then we need to force it through explicit COLLATE clauses,
|
||||
* otherwise the "C" collation attached to "name" catalog columns wins.
|
||||
*/
|
||||
if (namebuf.len > 2)
|
||||
if (namevar && namebuf.len > 2)
|
||||
{
|
||||
/* We have a name pattern, so constrain the namevar(s) */
|
||||
|
||||
@ -971,7 +981,7 @@ processSQLNamePattern(PGconn *conn, PQExpBuffer buf, const char *pattern,
|
||||
}
|
||||
}
|
||||
|
||||
if (schemabuf.len > 2)
|
||||
if (schemavar && schemabuf.len > 2)
|
||||
{
|
||||
/* We have a schema pattern, so constrain the schemavar */
|
||||
|
||||
@ -1012,8 +1022,7 @@ processSQLNamePattern(PGconn *conn, PQExpBuffer buf, const char *pattern,
|
||||
* If the dbnamebuf and schemabuf arguments are non-NULL, and the pattern
|
||||
* contains two or more dbname/schema/name separators, we parse the portions of
|
||||
* the pattern prior to the first and second separators into dbnamebuf and
|
||||
* schemabuf, and the rest into namebuf. (Additional dots in the name portion
|
||||
* are not treated as special.)
|
||||
* schemabuf, and the rest into namebuf.
|
||||
*
|
||||
* If dbnamebuf is NULL and schemabuf is non-NULL, and the pattern contains at
|
||||
* least one separator, we parse the first portion into schemabuf and the rest
|
||||
@ -1021,24 +1030,49 @@ processSQLNamePattern(PGconn *conn, PQExpBuffer buf, const char *pattern,
|
||||
*
|
||||
* Otherwise, we parse all the pattern into namebuf.
|
||||
*
|
||||
* If the pattern contains more dotted parts than buffers to parse into, the
|
||||
* extra dots will be treated as literal characters and written into the
|
||||
* namebuf, though they will be counted. Callers should always check the value
|
||||
* returned by reference in dotcnt and handle this error case appropriately.
|
||||
*
|
||||
* We surround the regexps with "^(...)$" to force them to match whole strings,
|
||||
* as per SQL practice. We have to have parens in case strings contain "|",
|
||||
* else the "^" and "$" will be bound into the first and last alternatives
|
||||
* which is not what we want.
|
||||
* which is not what we want. Whether this is done for dbnamebuf is controlled
|
||||
* by the want_literal_dbname parameter.
|
||||
*
|
||||
* The regexps we parse into the buffers are appended to the data (if any)
|
||||
* already present. If we parse fewer fields than the number of buffers we
|
||||
* were given, the extra buffers are unaltered.
|
||||
*
|
||||
* encoding: the character encoding for the given pattern
|
||||
* dbnamebuf: output parameter receiving the database name portion of the
|
||||
* pattern, if any. Can be NULL.
|
||||
* schemabuf: output parameter receiving the schema name portion of the
|
||||
* pattern, if any. Can be NULL.
|
||||
* namebuf: output parameter receiving the database name portion of the
|
||||
* pattern, if any. Can be NULL.
|
||||
* pattern: user-specified pattern option, or NULL if none ("*" is implied).
|
||||
* force_escape: always quote regexp special characters, even outside
|
||||
* double quotes (else they are quoted only between double quotes).
|
||||
* want_literal_dbname: if true, regexp special characters within the database
|
||||
* name portion of the pattern will not be escaped, nor will the dbname be
|
||||
* converted into a regular expression.
|
||||
* dotcnt: output parameter receiving the number of separators parsed from the
|
||||
* pattern.
|
||||
*/
|
||||
void
|
||||
patternToSQLRegex(int encoding, PQExpBuffer dbnamebuf, PQExpBuffer schemabuf,
|
||||
PQExpBuffer namebuf, const char *pattern, bool force_escape)
|
||||
PQExpBuffer namebuf, const char *pattern, bool force_escape,
|
||||
bool want_literal_dbname, int *dotcnt)
|
||||
{
|
||||
PQExpBufferData buf[3];
|
||||
PQExpBufferData left_literal;
|
||||
PQExpBuffer curbuf;
|
||||
PQExpBuffer maxbuf;
|
||||
int i;
|
||||
bool inquotes;
|
||||
bool left;
|
||||
const char *cp;
|
||||
|
||||
Assert(pattern != NULL);
|
||||
@ -1046,7 +1080,9 @@ patternToSQLRegex(int encoding, PQExpBuffer dbnamebuf, PQExpBuffer schemabuf,
|
||||
|
||||
/* callers should never expect "dbname.relname" format */
|
||||
Assert(dbnamebuf == NULL || schemabuf != NULL);
|
||||
Assert(dotcnt != NULL);
|
||||
|
||||
*dotcnt = 0;
|
||||
inquotes = false;
|
||||
cp = pattern;
|
||||
|
||||
@ -1058,6 +1094,13 @@ patternToSQLRegex(int encoding, PQExpBuffer dbnamebuf, PQExpBuffer schemabuf,
|
||||
maxbuf = &buf[0];
|
||||
|
||||
curbuf = &buf[0];
|
||||
if (want_literal_dbname)
|
||||
{
|
||||
left = true;
|
||||
initPQExpBuffer(&left_literal);
|
||||
}
|
||||
else
|
||||
left = false;
|
||||
initPQExpBuffer(curbuf);
|
||||
appendPQExpBufferStr(curbuf, "^(");
|
||||
while (*cp)
|
||||
@ -1070,6 +1113,8 @@ patternToSQLRegex(int encoding, PQExpBuffer dbnamebuf, PQExpBuffer schemabuf,
|
||||
{
|
||||
/* emit one quote, stay in inquotes mode */
|
||||
appendPQExpBufferChar(curbuf, '"');
|
||||
if (left)
|
||||
appendPQExpBufferChar(&left_literal, '"');
|
||||
cp++;
|
||||
}
|
||||
else
|
||||
@ -1080,32 +1125,40 @@ patternToSQLRegex(int encoding, PQExpBuffer dbnamebuf, PQExpBuffer schemabuf,
|
||||
{
|
||||
appendPQExpBufferChar(curbuf,
|
||||
pg_tolower((unsigned char) ch));
|
||||
if (left)
|
||||
appendPQExpBufferChar(&left_literal,
|
||||
pg_tolower((unsigned char) ch));
|
||||
cp++;
|
||||
}
|
||||
else if (!inquotes && ch == '*')
|
||||
{
|
||||
appendPQExpBufferStr(curbuf, ".*");
|
||||
if (left)
|
||||
appendPQExpBufferChar(&left_literal, '*');
|
||||
cp++;
|
||||
}
|
||||
else if (!inquotes && ch == '?')
|
||||
{
|
||||
appendPQExpBufferChar(curbuf, '.');
|
||||
if (left)
|
||||
appendPQExpBufferChar(&left_literal, '?');
|
||||
cp++;
|
||||
}
|
||||
|
||||
/*
|
||||
* When we find a dbname/schema/name separator, we treat it specially
|
||||
* only if the caller requested more patterns to be parsed than we
|
||||
* have already parsed from the pattern. Otherwise, dot characters
|
||||
* are not special.
|
||||
*/
|
||||
else if (!inquotes && ch == '.' && curbuf < maxbuf)
|
||||
else if (!inquotes && ch == '.')
|
||||
{
|
||||
appendPQExpBufferStr(curbuf, ")$");
|
||||
curbuf++;
|
||||
initPQExpBuffer(curbuf);
|
||||
appendPQExpBufferStr(curbuf, "^(");
|
||||
cp++;
|
||||
left = false;
|
||||
if (dotcnt)
|
||||
(*dotcnt)++;
|
||||
if (curbuf < maxbuf)
|
||||
{
|
||||
appendPQExpBufferStr(curbuf, ")$");
|
||||
curbuf++;
|
||||
initPQExpBuffer(curbuf);
|
||||
appendPQExpBufferStr(curbuf, "^(");
|
||||
cp++;
|
||||
}
|
||||
else
|
||||
appendPQExpBufferChar(curbuf, *cp++);
|
||||
}
|
||||
else if (ch == '$')
|
||||
{
|
||||
@ -1117,6 +1170,8 @@ patternToSQLRegex(int encoding, PQExpBuffer dbnamebuf, PQExpBuffer schemabuf,
|
||||
* having it possess its regexp meaning.
|
||||
*/
|
||||
appendPQExpBufferStr(curbuf, "\\$");
|
||||
if (left)
|
||||
appendPQExpBufferChar(&left_literal, '$');
|
||||
cp++;
|
||||
}
|
||||
else
|
||||
@ -1141,25 +1196,35 @@ patternToSQLRegex(int encoding, PQExpBuffer dbnamebuf, PQExpBuffer schemabuf,
|
||||
appendPQExpBufferChar(curbuf, '\\');
|
||||
i = PQmblenBounded(cp, encoding);
|
||||
while (i--)
|
||||
{
|
||||
if (left)
|
||||
appendPQExpBufferChar(&left_literal, *cp);
|
||||
appendPQExpBufferChar(curbuf, *cp++);
|
||||
}
|
||||
}
|
||||
}
|
||||
appendPQExpBufferStr(curbuf, ")$");
|
||||
|
||||
appendPQExpBufferStr(namebuf, curbuf->data);
|
||||
termPQExpBuffer(curbuf);
|
||||
|
||||
if (curbuf > buf)
|
||||
if (namebuf)
|
||||
{
|
||||
appendPQExpBufferStr(namebuf, curbuf->data);
|
||||
termPQExpBuffer(curbuf);
|
||||
curbuf--;
|
||||
}
|
||||
|
||||
if (schemabuf && curbuf >= buf)
|
||||
{
|
||||
appendPQExpBufferStr(schemabuf, curbuf->data);
|
||||
termPQExpBuffer(curbuf);
|
||||
curbuf--;
|
||||
}
|
||||
|
||||
if (curbuf > buf)
|
||||
{
|
||||
curbuf--;
|
||||
if (dbnamebuf && curbuf >= buf)
|
||||
{
|
||||
if (want_literal_dbname)
|
||||
appendPQExpBufferStr(dbnamebuf, left_literal.data);
|
||||
else
|
||||
appendPQExpBufferStr(dbnamebuf, curbuf->data);
|
||||
termPQExpBuffer(curbuf);
|
||||
}
|
||||
termPQExpBuffer(curbuf);
|
||||
}
|
||||
}
|
||||
|
@ -55,10 +55,12 @@ extern bool processSQLNamePattern(PGconn *conn, PQExpBuffer buf,
|
||||
const char *pattern,
|
||||
bool have_where, bool force_escape,
|
||||
const char *schemavar, const char *namevar,
|
||||
const char *altnamevar, const char *visibilityrule);
|
||||
const char *altnamevar, const char *visibilityrule,
|
||||
PQExpBuffer dbnamebuf, int *dotcnt);
|
||||
|
||||
extern void patternToSQLRegex(int encoding, PQExpBuffer dbnamebuf,
|
||||
PQExpBuffer schemabuf, PQExpBuffer namebuf,
|
||||
const char *pattern, bool force_escape);
|
||||
const char *pattern, bool force_escape,
|
||||
bool want_literal_dbname, int *dotcnt);
|
||||
|
||||
#endif /* STRING_UTILS_H */
|
||||
|
@ -5549,3 +5549,807 @@ SELECT * FROM bla ORDER BY 1;
|
||||
# final ON_ERROR_ROLLBACK: off
|
||||
DROP TABLE bla;
|
||||
DROP FUNCTION psql_error;
|
||||
-- check describing invalid multipart names
|
||||
\dA regression.heap
|
||||
improper qualified name (too many dotted names): regression.heap
|
||||
\dA nonesuch.heap
|
||||
improper qualified name (too many dotted names): nonesuch.heap
|
||||
\dt host.regression.pg_catalog.pg_class
|
||||
improper qualified name (too many dotted names): host.regression.pg_catalog.pg_class
|
||||
\dt |.pg_catalog.pg_class
|
||||
cross-database references are not implemented: |.pg_catalog.pg_class
|
||||
\dt nonesuch.pg_catalog.pg_class
|
||||
cross-database references are not implemented: nonesuch.pg_catalog.pg_class
|
||||
\da host.regression.pg_catalog.sum
|
||||
improper qualified name (too many dotted names): host.regression.pg_catalog.sum
|
||||
\da +.pg_catalog.sum
|
||||
cross-database references are not implemented: +.pg_catalog.sum
|
||||
\da nonesuch.pg_catalog.sum
|
||||
cross-database references are not implemented: nonesuch.pg_catalog.sum
|
||||
\dAc nonesuch.brin
|
||||
improper qualified name (too many dotted names): nonesuch.brin
|
||||
\dAc regression.brin
|
||||
improper qualified name (too many dotted names): regression.brin
|
||||
\dAf nonesuch.brin
|
||||
improper qualified name (too many dotted names): nonesuch.brin
|
||||
\dAf regression.brin
|
||||
improper qualified name (too many dotted names): regression.brin
|
||||
\dAo nonesuch.brin
|
||||
improper qualified name (too many dotted names): nonesuch.brin
|
||||
\dAo regression.brin
|
||||
improper qualified name (too many dotted names): regression.brin
|
||||
\dAp nonesuch.brin
|
||||
improper qualified name (too many dotted names): nonesuch.brin
|
||||
\dAp regression.brin
|
||||
improper qualified name (too many dotted names): regression.brin
|
||||
\db nonesuch.pg_default
|
||||
improper qualified name (too many dotted names): nonesuch.pg_default
|
||||
\db regression.pg_default
|
||||
improper qualified name (too many dotted names): regression.pg_default
|
||||
\dc host.regression.public.conversion
|
||||
improper qualified name (too many dotted names): host.regression.public.conversion
|
||||
\dc (.public.conversion
|
||||
cross-database references are not implemented: (.public.conversion
|
||||
\dc nonesuch.public.conversion
|
||||
cross-database references are not implemented: nonesuch.public.conversion
|
||||
\dC host.regression.pg_catalog.int8
|
||||
improper qualified name (too many dotted names): host.regression.pg_catalog.int8
|
||||
\dC ).pg_catalog.int8
|
||||
cross-database references are not implemented: ).pg_catalog.int8
|
||||
\dC nonesuch.pg_catalog.int8
|
||||
cross-database references are not implemented: nonesuch.pg_catalog.int8
|
||||
\dd host.regression.pg_catalog.pg_class
|
||||
improper qualified name (too many dotted names): host.regression.pg_catalog.pg_class
|
||||
\dd [.pg_catalog.pg_class
|
||||
cross-database references are not implemented: [.pg_catalog.pg_class
|
||||
\dd nonesuch.pg_catalog.pg_class
|
||||
cross-database references are not implemented: nonesuch.pg_catalog.pg_class
|
||||
\dD host.regression.public.gtestdomain1
|
||||
improper qualified name (too many dotted names): host.regression.public.gtestdomain1
|
||||
\dD ].public.gtestdomain1
|
||||
cross-database references are not implemented: ].public.gtestdomain1
|
||||
\dD nonesuch.public.gtestdomain1
|
||||
cross-database references are not implemented: nonesuch.public.gtestdomain1
|
||||
\ddp host.regression.pg_catalog.pg_class
|
||||
improper qualified name (too many dotted names): host.regression.pg_catalog.pg_class
|
||||
\ddp {.pg_catalog.pg_class
|
||||
cross-database references are not implemented: {.pg_catalog.pg_class
|
||||
\ddp nonesuch.pg_catalog.pg_class
|
||||
cross-database references are not implemented: nonesuch.pg_catalog.pg_class
|
||||
\dE host.regression.public.ft
|
||||
improper qualified name (too many dotted names): host.regression.public.ft
|
||||
\dE }.public.ft
|
||||
cross-database references are not implemented: }.public.ft
|
||||
\dE nonesuch.public.ft
|
||||
cross-database references are not implemented: nonesuch.public.ft
|
||||
\di host.regression.public.tenk1_hundred
|
||||
improper qualified name (too many dotted names): host.regression.public.tenk1_hundred
|
||||
\di ..public.tenk1_hundred
|
||||
improper qualified name (too many dotted names): ..public.tenk1_hundred
|
||||
\di nonesuch.public.tenk1_hundred
|
||||
cross-database references are not implemented: nonesuch.public.tenk1_hundred
|
||||
\dm host.regression.public.mvtest_bb
|
||||
improper qualified name (too many dotted names): host.regression.public.mvtest_bb
|
||||
\dm ^.public.mvtest_bb
|
||||
cross-database references are not implemented: ^.public.mvtest_bb
|
||||
\dm nonesuch.public.mvtest_bb
|
||||
cross-database references are not implemented: nonesuch.public.mvtest_bb
|
||||
\ds host.regression.public.check_seq
|
||||
improper qualified name (too many dotted names): host.regression.public.check_seq
|
||||
\ds regression|mydb.public.check_seq
|
||||
cross-database references are not implemented: regression|mydb.public.check_seq
|
||||
\ds nonesuch.public.check_seq
|
||||
cross-database references are not implemented: nonesuch.public.check_seq
|
||||
\dt host.regression.public.b_star
|
||||
improper qualified name (too many dotted names): host.regression.public.b_star
|
||||
\dt regres+ion.public.b_star
|
||||
cross-database references are not implemented: regres+ion.public.b_star
|
||||
\dt nonesuch.public.b_star
|
||||
cross-database references are not implemented: nonesuch.public.b_star
|
||||
\dv host.regression.public.shoe
|
||||
improper qualified name (too many dotted names): host.regression.public.shoe
|
||||
\dv regress(ion).public.shoe
|
||||
cross-database references are not implemented: regress(ion).public.shoe
|
||||
\dv nonesuch.public.shoe
|
||||
cross-database references are not implemented: nonesuch.public.shoe
|
||||
\des nonesuch.server
|
||||
improper qualified name (too many dotted names): nonesuch.server
|
||||
\des regression.server
|
||||
improper qualified name (too many dotted names): regression.server
|
||||
\des nonesuch.server
|
||||
improper qualified name (too many dotted names): nonesuch.server
|
||||
\des regression.server
|
||||
improper qualified name (too many dotted names): regression.server
|
||||
\des nonesuch.username
|
||||
improper qualified name (too many dotted names): nonesuch.username
|
||||
\des regression.username
|
||||
improper qualified name (too many dotted names): regression.username
|
||||
\dew nonesuch.fdw
|
||||
improper qualified name (too many dotted names): nonesuch.fdw
|
||||
\dew regression.fdw
|
||||
improper qualified name (too many dotted names): regression.fdw
|
||||
\df host.regression.public.namelen
|
||||
improper qualified name (too many dotted names): host.regression.public.namelen
|
||||
\df regres[qrstuv]ion.public.namelen
|
||||
cross-database references are not implemented: regres[qrstuv]ion.public.namelen
|
||||
\df nonesuch.public.namelen
|
||||
cross-database references are not implemented: nonesuch.public.namelen
|
||||
\dF host.regression.pg_catalog.arabic
|
||||
improper qualified name (too many dotted names): host.regression.pg_catalog.arabic
|
||||
\dF regres{1,2}ion.pg_catalog.arabic
|
||||
cross-database references are not implemented: regres{1,2}ion.pg_catalog.arabic
|
||||
\dF nonesuch.pg_catalog.arabic
|
||||
cross-database references are not implemented: nonesuch.pg_catalog.arabic
|
||||
\dFd host.regression.pg_catalog.arabic_stem
|
||||
improper qualified name (too many dotted names): host.regression.pg_catalog.arabic_stem
|
||||
\dFd regres?ion.pg_catalog.arabic_stem
|
||||
cross-database references are not implemented: regres?ion.pg_catalog.arabic_stem
|
||||
\dFd nonesuch.pg_catalog.arabic_stem
|
||||
cross-database references are not implemented: nonesuch.pg_catalog.arabic_stem
|
||||
\dFp host.regression.pg_catalog.default
|
||||
improper qualified name (too many dotted names): host.regression.pg_catalog.default
|
||||
\dFp ^regression.pg_catalog.default
|
||||
cross-database references are not implemented: ^regression.pg_catalog.default
|
||||
\dFp nonesuch.pg_catalog.default
|
||||
cross-database references are not implemented: nonesuch.pg_catalog.default
|
||||
\dFt host.regression.pg_catalog.ispell
|
||||
improper qualified name (too many dotted names): host.regression.pg_catalog.ispell
|
||||
\dFt regression$.pg_catalog.ispell
|
||||
cross-database references are not implemented: regression$.pg_catalog.ispell
|
||||
\dFt nonesuch.pg_catalog.ispell
|
||||
cross-database references are not implemented: nonesuch.pg_catalog.ispell
|
||||
\dg nonesuch.pg_database_owner
|
||||
improper qualified name (too many dotted names): nonesuch.pg_database_owner
|
||||
\dg regression.pg_database_owner
|
||||
improper qualified name (too many dotted names): regression.pg_database_owner
|
||||
\dL host.regression.plpgsql
|
||||
improper qualified name (too many dotted names): host.regression.plpgsql
|
||||
\dL *.plpgsql
|
||||
cross-database references are not implemented: *.plpgsql
|
||||
\dL nonesuch.plpgsql
|
||||
cross-database references are not implemented: nonesuch.plpgsql
|
||||
\dn host.regression.public
|
||||
improper qualified name (too many dotted names): host.regression.public
|
||||
\dn """".public
|
||||
cross-database references are not implemented: """".public
|
||||
\dn nonesuch.public
|
||||
cross-database references are not implemented: nonesuch.public
|
||||
\do host.regression.public.!=-
|
||||
improper qualified name (too many dotted names): host.regression.public.!=-
|
||||
\do "regression|mydb".public.!=-
|
||||
cross-database references are not implemented: "regression|mydb".public.!=-
|
||||
\do nonesuch.public.!=-
|
||||
cross-database references are not implemented: nonesuch.public.!=-
|
||||
\dO host.regression.pg_catalog.POSIX
|
||||
improper qualified name (too many dotted names): host.regression.pg_catalog.POSIX
|
||||
\dO .pg_catalog.POSIX
|
||||
cross-database references are not implemented: .pg_catalog.POSIX
|
||||
\dO nonesuch.pg_catalog.POSIX
|
||||
cross-database references are not implemented: nonesuch.pg_catalog.POSIX
|
||||
\dp host.regression.public.a_star
|
||||
improper qualified name (too many dotted names): host.regression.public.a_star
|
||||
\dp "regres+ion".public.a_star
|
||||
cross-database references are not implemented: "regres+ion".public.a_star
|
||||
\dp nonesuch.public.a_star
|
||||
cross-database references are not implemented: nonesuch.public.a_star
|
||||
\dP host.regression.public.mlparted
|
||||
improper qualified name (too many dotted names): host.regression.public.mlparted
|
||||
\dP "regres(sion)".public.mlparted
|
||||
cross-database references are not implemented: "regres(sion)".public.mlparted
|
||||
\dP nonesuch.public.mlparted
|
||||
cross-database references are not implemented: nonesuch.public.mlparted
|
||||
\drds nonesuch.lc_messages
|
||||
improper qualified name (too many dotted names): nonesuch.lc_messages
|
||||
\drds regression.lc_messages
|
||||
improper qualified name (too many dotted names): regression.lc_messages
|
||||
\dRp public.mypub
|
||||
improper qualified name (too many dotted names): public.mypub
|
||||
\dRp regression.mypub
|
||||
improper qualified name (too many dotted names): regression.mypub
|
||||
\dRs public.mysub
|
||||
improper qualified name (too many dotted names): public.mysub
|
||||
\dRs regression.mysub
|
||||
improper qualified name (too many dotted names): regression.mysub
|
||||
\dT host.regression.public.widget
|
||||
improper qualified name (too many dotted names): host.regression.public.widget
|
||||
\dT "regression{1,2}".public.widget
|
||||
cross-database references are not implemented: "regression{1,2}".public.widget
|
||||
\dT nonesuch.public.widget
|
||||
cross-database references are not implemented: nonesuch.public.widget
|
||||
\dx regression.plpgsql
|
||||
improper qualified name (too many dotted names): regression.plpgsql
|
||||
\dx nonesuch.plpgsql
|
||||
improper qualified name (too many dotted names): nonesuch.plpgsql
|
||||
\dX host.regression.public.func_deps_stat
|
||||
improper qualified name (too many dotted names): host.regression.public.func_deps_stat
|
||||
\dX "^regression$".public.func_deps_stat
|
||||
cross-database references are not implemented: "^regression$".public.func_deps_stat
|
||||
\dX nonesuch.public.func_deps_stat
|
||||
cross-database references are not implemented: nonesuch.public.func_deps_stat
|
||||
\dy regression.myevt
|
||||
improper qualified name (too many dotted names): regression.myevt
|
||||
\dy nonesuch.myevt
|
||||
improper qualified name (too many dotted names): nonesuch.myevt
|
||||
-- check that dots within quoted name segments are not counted
|
||||
\dA "no.such.access.method"
|
||||
List of access methods
|
||||
Name | Type
|
||||
------+------
|
||||
(0 rows)
|
||||
|
||||
\dt "no.such.table.relation"
|
||||
List of relations
|
||||
Schema | Name | Type | Owner
|
||||
--------+------+------+-------
|
||||
(0 rows)
|
||||
|
||||
\da "no.such.aggregate.function"
|
||||
List of aggregate functions
|
||||
Schema | Name | Result data type | Argument data types | Description
|
||||
--------+------+------------------+---------------------+-------------
|
||||
(0 rows)
|
||||
|
||||
\dAc "no.such.operator.class"
|
||||
List of operator classes
|
||||
AM | Input type | Storage type | Operator class | Default?
|
||||
----+------------+--------------+----------------+----------
|
||||
(0 rows)
|
||||
|
||||
\dAf "no.such.operator.family"
|
||||
List of operator families
|
||||
AM | Operator family | Applicable types
|
||||
----+-----------------+------------------
|
||||
(0 rows)
|
||||
|
||||
\dAo "no.such.operator.of.operator.family"
|
||||
List of operators of operator families
|
||||
AM | Operator family | Operator | Strategy | Purpose
|
||||
----+-----------------+----------+----------+---------
|
||||
(0 rows)
|
||||
|
||||
\dAp "no.such.operator.support.function.of.operator.family"
|
||||
List of support functions of operator families
|
||||
AM | Operator family | Registered left type | Registered right type | Number | Function
|
||||
----+-----------------+----------------------+-----------------------+--------+----------
|
||||
(0 rows)
|
||||
|
||||
\db "no.such.tablespace"
|
||||
List of tablespaces
|
||||
Name | Owner | Location
|
||||
------+-------+----------
|
||||
(0 rows)
|
||||
|
||||
\dc "no.such.conversion"
|
||||
List of conversions
|
||||
Schema | Name | Source | Destination | Default?
|
||||
--------+------+--------+-------------+----------
|
||||
(0 rows)
|
||||
|
||||
\dC "no.such.cast"
|
||||
List of casts
|
||||
Source type | Target type | Function | Implicit?
|
||||
-------------+-------------+----------+-----------
|
||||
(0 rows)
|
||||
|
||||
\dd "no.such.object.description"
|
||||
Object descriptions
|
||||
Schema | Name | Object | Description
|
||||
--------+------+--------+-------------
|
||||
(0 rows)
|
||||
|
||||
\dD "no.such.domain"
|
||||
List of domains
|
||||
Schema | Name | Type | Collation | Nullable | Default | Check
|
||||
--------+------+------+-----------+----------+---------+-------
|
||||
(0 rows)
|
||||
|
||||
\ddp "no.such.default.access.privilege"
|
||||
Default access privileges
|
||||
Owner | Schema | Type | Access privileges
|
||||
-------+--------+------+-------------------
|
||||
(0 rows)
|
||||
|
||||
\di "no.such.index.relation"
|
||||
List of relations
|
||||
Schema | Name | Type | Owner | Table
|
||||
--------+------+------+-------+-------
|
||||
(0 rows)
|
||||
|
||||
\dm "no.such.materialized.view"
|
||||
List of relations
|
||||
Schema | Name | Type | Owner
|
||||
--------+------+------+-------
|
||||
(0 rows)
|
||||
|
||||
\ds "no.such.relation"
|
||||
List of relations
|
||||
Schema | Name | Type | Owner
|
||||
--------+------+------+-------
|
||||
(0 rows)
|
||||
|
||||
\dt "no.such.relation"
|
||||
List of relations
|
||||
Schema | Name | Type | Owner
|
||||
--------+------+------+-------
|
||||
(0 rows)
|
||||
|
||||
\dv "no.such.relation"
|
||||
List of relations
|
||||
Schema | Name | Type | Owner
|
||||
--------+------+------+-------
|
||||
(0 rows)
|
||||
|
||||
\des "no.such.foreign.server"
|
||||
List of foreign servers
|
||||
Name | Owner | Foreign-data wrapper
|
||||
------+-------+----------------------
|
||||
(0 rows)
|
||||
|
||||
\dew "no.such.foreign.data.wrapper"
|
||||
List of foreign-data wrappers
|
||||
Name | Owner | Handler | Validator
|
||||
------+-------+---------+-----------
|
||||
(0 rows)
|
||||
|
||||
\df "no.such.function"
|
||||
List of functions
|
||||
Schema | Name | Result data type | Argument data types | Type
|
||||
--------+------+------------------+---------------------+------
|
||||
(0 rows)
|
||||
|
||||
\dF "no.such.text.search.configuration"
|
||||
List of text search configurations
|
||||
Schema | Name | Description
|
||||
--------+------+-------------
|
||||
(0 rows)
|
||||
|
||||
\dFd "no.such.text.search.dictionary"
|
||||
List of text search dictionaries
|
||||
Schema | Name | Description
|
||||
--------+------+-------------
|
||||
(0 rows)
|
||||
|
||||
\dFp "no.such.text.search.parser"
|
||||
List of text search parsers
|
||||
Schema | Name | Description
|
||||
--------+------+-------------
|
||||
(0 rows)
|
||||
|
||||
\dFt "no.such.text.search.template"
|
||||
List of text search templates
|
||||
Schema | Name | Description
|
||||
--------+------+-------------
|
||||
(0 rows)
|
||||
|
||||
\dg "no.such.role"
|
||||
List of roles
|
||||
Role name | Attributes | Member of
|
||||
-----------+------------+-----------
|
||||
|
||||
\dL "no.such.language"
|
||||
List of languages
|
||||
Name | Owner | Trusted | Description
|
||||
------+-------+---------+-------------
|
||||
(0 rows)
|
||||
|
||||
\dn "no.such.schema"
|
||||
List of schemas
|
||||
Name | Owner
|
||||
------+-------
|
||||
(0 rows)
|
||||
|
||||
\do "no.such.operator"
|
||||
List of operators
|
||||
Schema | Name | Left arg type | Right arg type | Result type | Description
|
||||
--------+------+---------------+----------------+-------------+-------------
|
||||
(0 rows)
|
||||
|
||||
\dO "no.such.collation"
|
||||
List of collations
|
||||
Schema | Name | Collate | Ctype | ICU Locale | Provider | Deterministic?
|
||||
--------+------+---------+-------+------------+----------+----------------
|
||||
(0 rows)
|
||||
|
||||
\dp "no.such.access.privilege"
|
||||
Access privileges
|
||||
Schema | Name | Type | Access privileges | Column privileges | Policies
|
||||
--------+------+------+-------------------+-------------------+----------
|
||||
(0 rows)
|
||||
|
||||
\dP "no.such.partitioned.relation"
|
||||
List of partitioned relations
|
||||
Schema | Name | Owner | Type | Parent name | Table
|
||||
--------+------+-------+------+-------------+-------
|
||||
(0 rows)
|
||||
|
||||
\drds "no.such.setting"
|
||||
List of settings
|
||||
Role | Database | Settings
|
||||
------+----------+----------
|
||||
(0 rows)
|
||||
|
||||
\dRp "no.such.publication"
|
||||
List of publications
|
||||
Name | Owner | All tables | Inserts | Updates | Deletes | Truncates | Via root
|
||||
------+-------+------------+---------+---------+---------+-----------+----------
|
||||
(0 rows)
|
||||
|
||||
\dRs "no.such.subscription"
|
||||
List of subscriptions
|
||||
Name | Owner | Enabled | Publication
|
||||
------+-------+---------+-------------
|
||||
(0 rows)
|
||||
|
||||
\dT "no.such.data.type"
|
||||
List of data types
|
||||
Schema | Name | Description
|
||||
--------+------+-------------
|
||||
(0 rows)
|
||||
|
||||
\dx "no.such.installed.extension"
|
||||
List of installed extensions
|
||||
Name | Version | Schema | Description
|
||||
------+---------+--------+-------------
|
||||
(0 rows)
|
||||
|
||||
\dX "no.such.extended.statistics"
|
||||
List of extended statistics
|
||||
Schema | Name | Definition | Ndistinct | Dependencies | MCV
|
||||
--------+------+------------+-----------+--------------+-----
|
||||
(0 rows)
|
||||
|
||||
\dy "no.such.event.trigger"
|
||||
List of event triggers
|
||||
Name | Event | Owner | Enabled | Function | Tags
|
||||
------+-------+-------+---------+----------+------
|
||||
(0 rows)
|
||||
|
||||
-- again, but with dotted schema qualifications.
|
||||
\dA "no.such.schema"."no.such.access.method"
|
||||
improper qualified name (too many dotted names): "no.such.schema"."no.such.access.method"
|
||||
\dt "no.such.schema"."no.such.table.relation"
|
||||
List of relations
|
||||
Schema | Name | Type | Owner
|
||||
--------+------+------+-------
|
||||
(0 rows)
|
||||
|
||||
\da "no.such.schema"."no.such.aggregate.function"
|
||||
List of aggregate functions
|
||||
Schema | Name | Result data type | Argument data types | Description
|
||||
--------+------+------------------+---------------------+-------------
|
||||
(0 rows)
|
||||
|
||||
\dAc "no.such.schema"."no.such.operator.class"
|
||||
improper qualified name (too many dotted names): "no.such.schema"."no.such.operator.class"
|
||||
\dAf "no.such.schema"."no.such.operator.family"
|
||||
improper qualified name (too many dotted names): "no.such.schema"."no.such.operator.family"
|
||||
\dAo "no.such.schema"."no.such.operator.of.operator.family"
|
||||
improper qualified name (too many dotted names): "no.such.schema"."no.such.operator.of.operator.family"
|
||||
\dAp "no.such.schema"."no.such.operator.support.function.of.operator.family"
|
||||
improper qualified name (too many dotted names): "no.such.schema"."no.such.operator.support.function.of.operator.family"
|
||||
\db "no.such.schema"."no.such.tablespace"
|
||||
improper qualified name (too many dotted names): "no.such.schema"."no.such.tablespace"
|
||||
\dc "no.such.schema"."no.such.conversion"
|
||||
List of conversions
|
||||
Schema | Name | Source | Destination | Default?
|
||||
--------+------+--------+-------------+----------
|
||||
(0 rows)
|
||||
|
||||
\dC "no.such.schema"."no.such.cast"
|
||||
List of casts
|
||||
Source type | Target type | Function | Implicit?
|
||||
-------------+-------------+----------+-----------
|
||||
(0 rows)
|
||||
|
||||
\dd "no.such.schema"."no.such.object.description"
|
||||
Object descriptions
|
||||
Schema | Name | Object | Description
|
||||
--------+------+--------+-------------
|
||||
(0 rows)
|
||||
|
||||
\dD "no.such.schema"."no.such.domain"
|
||||
List of domains
|
||||
Schema | Name | Type | Collation | Nullable | Default | Check
|
||||
--------+------+------+-----------+----------+---------+-------
|
||||
(0 rows)
|
||||
|
||||
\ddp "no.such.schema"."no.such.default.access.privilege"
|
||||
Default access privileges
|
||||
Owner | Schema | Type | Access privileges
|
||||
-------+--------+------+-------------------
|
||||
(0 rows)
|
||||
|
||||
\di "no.such.schema"."no.such.index.relation"
|
||||
List of relations
|
||||
Schema | Name | Type | Owner | Table
|
||||
--------+------+------+-------+-------
|
||||
(0 rows)
|
||||
|
||||
\dm "no.such.schema"."no.such.materialized.view"
|
||||
List of relations
|
||||
Schema | Name | Type | Owner
|
||||
--------+------+------+-------
|
||||
(0 rows)
|
||||
|
||||
\ds "no.such.schema"."no.such.relation"
|
||||
List of relations
|
||||
Schema | Name | Type | Owner
|
||||
--------+------+------+-------
|
||||
(0 rows)
|
||||
|
||||
\dt "no.such.schema"."no.such.relation"
|
||||
List of relations
|
||||
Schema | Name | Type | Owner
|
||||
--------+------+------+-------
|
||||
(0 rows)
|
||||
|
||||
\dv "no.such.schema"."no.such.relation"
|
||||
List of relations
|
||||
Schema | Name | Type | Owner
|
||||
--------+------+------+-------
|
||||
(0 rows)
|
||||
|
||||
\des "no.such.schema"."no.such.foreign.server"
|
||||
improper qualified name (too many dotted names): "no.such.schema"."no.such.foreign.server"
|
||||
\dew "no.such.schema"."no.such.foreign.data.wrapper"
|
||||
improper qualified name (too many dotted names): "no.such.schema"."no.such.foreign.data.wrapper"
|
||||
\df "no.such.schema"."no.such.function"
|
||||
List of functions
|
||||
Schema | Name | Result data type | Argument data types | Type
|
||||
--------+------+------------------+---------------------+------
|
||||
(0 rows)
|
||||
|
||||
\dF "no.such.schema"."no.such.text.search.configuration"
|
||||
List of text search configurations
|
||||
Schema | Name | Description
|
||||
--------+------+-------------
|
||||
(0 rows)
|
||||
|
||||
\dFd "no.such.schema"."no.such.text.search.dictionary"
|
||||
List of text search dictionaries
|
||||
Schema | Name | Description
|
||||
--------+------+-------------
|
||||
(0 rows)
|
||||
|
||||
\dFp "no.such.schema"."no.such.text.search.parser"
|
||||
List of text search parsers
|
||||
Schema | Name | Description
|
||||
--------+------+-------------
|
||||
(0 rows)
|
||||
|
||||
\dFt "no.such.schema"."no.such.text.search.template"
|
||||
List of text search templates
|
||||
Schema | Name | Description
|
||||
--------+------+-------------
|
||||
(0 rows)
|
||||
|
||||
\dg "no.such.schema"."no.such.role"
|
||||
improper qualified name (too many dotted names): "no.such.schema"."no.such.role"
|
||||
\dL "no.such.schema"."no.such.language"
|
||||
cross-database references are not implemented: "no.such.schema"."no.such.language"
|
||||
\do "no.such.schema"."no.such.operator"
|
||||
List of operators
|
||||
Schema | Name | Left arg type | Right arg type | Result type | Description
|
||||
--------+------+---------------+----------------+-------------+-------------
|
||||
(0 rows)
|
||||
|
||||
\dO "no.such.schema"."no.such.collation"
|
||||
List of collations
|
||||
Schema | Name | Collate | Ctype | ICU Locale | Provider | Deterministic?
|
||||
--------+------+---------+-------+------------+----------+----------------
|
||||
(0 rows)
|
||||
|
||||
\dp "no.such.schema"."no.such.access.privilege"
|
||||
Access privileges
|
||||
Schema | Name | Type | Access privileges | Column privileges | Policies
|
||||
--------+------+------+-------------------+-------------------+----------
|
||||
(0 rows)
|
||||
|
||||
\dP "no.such.schema"."no.such.partitioned.relation"
|
||||
List of partitioned relations
|
||||
Schema | Name | Owner | Type | Parent name | Table
|
||||
--------+------+-------+------+-------------+-------
|
||||
(0 rows)
|
||||
|
||||
\drds "no.such.schema"."no.such.setting"
|
||||
improper qualified name (too many dotted names): "no.such.schema"."no.such.setting"
|
||||
\dRp "no.such.schema"."no.such.publication"
|
||||
improper qualified name (too many dotted names): "no.such.schema"."no.such.publication"
|
||||
\dRs "no.such.schema"."no.such.subscription"
|
||||
improper qualified name (too many dotted names): "no.such.schema"."no.such.subscription"
|
||||
\dT "no.such.schema"."no.such.data.type"
|
||||
List of data types
|
||||
Schema | Name | Description
|
||||
--------+------+-------------
|
||||
(0 rows)
|
||||
|
||||
\dx "no.such.schema"."no.such.installed.extension"
|
||||
improper qualified name (too many dotted names): "no.such.schema"."no.such.installed.extension"
|
||||
\dX "no.such.schema"."no.such.extended.statistics"
|
||||
List of extended statistics
|
||||
Schema | Name | Definition | Ndistinct | Dependencies | MCV
|
||||
--------+------+------------+-----------+--------------+-----
|
||||
(0 rows)
|
||||
|
||||
\dy "no.such.schema"."no.such.event.trigger"
|
||||
improper qualified name (too many dotted names): "no.such.schema"."no.such.event.trigger"
|
||||
-- again, but with current database and dotted schema qualifications.
|
||||
\dt regression."no.such.schema"."no.such.table.relation"
|
||||
List of relations
|
||||
Schema | Name | Type | Owner
|
||||
--------+------+------+-------
|
||||
(0 rows)
|
||||
|
||||
\da regression."no.such.schema"."no.such.aggregate.function"
|
||||
List of aggregate functions
|
||||
Schema | Name | Result data type | Argument data types | Description
|
||||
--------+------+------------------+---------------------+-------------
|
||||
(0 rows)
|
||||
|
||||
\dc regression."no.such.schema"."no.such.conversion"
|
||||
List of conversions
|
||||
Schema | Name | Source | Destination | Default?
|
||||
--------+------+--------+-------------+----------
|
||||
(0 rows)
|
||||
|
||||
\dC regression."no.such.schema"."no.such.cast"
|
||||
List of casts
|
||||
Source type | Target type | Function | Implicit?
|
||||
-------------+-------------+----------+-----------
|
||||
(0 rows)
|
||||
|
||||
\dd regression."no.such.schema"."no.such.object.description"
|
||||
Object descriptions
|
||||
Schema | Name | Object | Description
|
||||
--------+------+--------+-------------
|
||||
(0 rows)
|
||||
|
||||
\dD regression."no.such.schema"."no.such.domain"
|
||||
List of domains
|
||||
Schema | Name | Type | Collation | Nullable | Default | Check
|
||||
--------+------+------+-----------+----------+---------+-------
|
||||
(0 rows)
|
||||
|
||||
\di regression."no.such.schema"."no.such.index.relation"
|
||||
List of relations
|
||||
Schema | Name | Type | Owner | Table
|
||||
--------+------+------+-------+-------
|
||||
(0 rows)
|
||||
|
||||
\dm regression."no.such.schema"."no.such.materialized.view"
|
||||
List of relations
|
||||
Schema | Name | Type | Owner
|
||||
--------+------+------+-------
|
||||
(0 rows)
|
||||
|
||||
\ds regression."no.such.schema"."no.such.relation"
|
||||
List of relations
|
||||
Schema | Name | Type | Owner
|
||||
--------+------+------+-------
|
||||
(0 rows)
|
||||
|
||||
\dt regression."no.such.schema"."no.such.relation"
|
||||
List of relations
|
||||
Schema | Name | Type | Owner
|
||||
--------+------+------+-------
|
||||
(0 rows)
|
||||
|
||||
\dv regression."no.such.schema"."no.such.relation"
|
||||
List of relations
|
||||
Schema | Name | Type | Owner
|
||||
--------+------+------+-------
|
||||
(0 rows)
|
||||
|
||||
\df regression."no.such.schema"."no.such.function"
|
||||
List of functions
|
||||
Schema | Name | Result data type | Argument data types | Type
|
||||
--------+------+------------------+---------------------+------
|
||||
(0 rows)
|
||||
|
||||
\dF regression."no.such.schema"."no.such.text.search.configuration"
|
||||
List of text search configurations
|
||||
Schema | Name | Description
|
||||
--------+------+-------------
|
||||
(0 rows)
|
||||
|
||||
\dFd regression."no.such.schema"."no.such.text.search.dictionary"
|
||||
List of text search dictionaries
|
||||
Schema | Name | Description
|
||||
--------+------+-------------
|
||||
(0 rows)
|
||||
|
||||
\dFp regression."no.such.schema"."no.such.text.search.parser"
|
||||
List of text search parsers
|
||||
Schema | Name | Description
|
||||
--------+------+-------------
|
||||
(0 rows)
|
||||
|
||||
\dFt regression."no.such.schema"."no.such.text.search.template"
|
||||
List of text search templates
|
||||
Schema | Name | Description
|
||||
--------+------+-------------
|
||||
(0 rows)
|
||||
|
||||
\do regression."no.such.schema"."no.such.operator"
|
||||
List of operators
|
||||
Schema | Name | Left arg type | Right arg type | Result type | Description
|
||||
--------+------+---------------+----------------+-------------+-------------
|
||||
(0 rows)
|
||||
|
||||
\dO regression."no.such.schema"."no.such.collation"
|
||||
List of collations
|
||||
Schema | Name | Collate | Ctype | ICU Locale | Provider | Deterministic?
|
||||
--------+------+---------+-------+------------+----------+----------------
|
||||
(0 rows)
|
||||
|
||||
\dp regression."no.such.schema"."no.such.access.privilege"
|
||||
Access privileges
|
||||
Schema | Name | Type | Access privileges | Column privileges | Policies
|
||||
--------+------+------+-------------------+-------------------+----------
|
||||
(0 rows)
|
||||
|
||||
\dP regression."no.such.schema"."no.such.partitioned.relation"
|
||||
List of partitioned relations
|
||||
Schema | Name | Owner | Type | Parent name | Table
|
||||
--------+------+-------+------+-------------+-------
|
||||
(0 rows)
|
||||
|
||||
\dT regression."no.such.schema"."no.such.data.type"
|
||||
List of data types
|
||||
Schema | Name | Description
|
||||
--------+------+-------------
|
||||
(0 rows)
|
||||
|
||||
\dX regression."no.such.schema"."no.such.extended.statistics"
|
||||
List of extended statistics
|
||||
Schema | Name | Definition | Ndistinct | Dependencies | MCV
|
||||
--------+------+------------+-----------+--------------+-----
|
||||
(0 rows)
|
||||
|
||||
-- again, but with dotted database and dotted schema qualifications.
|
||||
\dt "no.such.database"."no.such.schema"."no.such.table.relation"
|
||||
cross-database references are not implemented: "no.such.database"."no.such.schema"."no.such.table.relation"
|
||||
\da "no.such.database"."no.such.schema"."no.such.aggregate.function"
|
||||
cross-database references are not implemented: "no.such.database"."no.such.schema"."no.such.aggregate.function"
|
||||
\dc "no.such.database"."no.such.schema"."no.such.conversion"
|
||||
cross-database references are not implemented: "no.such.database"."no.such.schema"."no.such.conversion"
|
||||
\dC "no.such.database"."no.such.schema"."no.such.cast"
|
||||
cross-database references are not implemented: "no.such.database"."no.such.schema"."no.such.cast"
|
||||
\dd "no.such.database"."no.such.schema"."no.such.object.description"
|
||||
cross-database references are not implemented: "no.such.database"."no.such.schema"."no.such.object.description"
|
||||
\dD "no.such.database"."no.such.schema"."no.such.domain"
|
||||
cross-database references are not implemented: "no.such.database"."no.such.schema"."no.such.domain"
|
||||
\ddp "no.such.database"."no.such.schema"."no.such.default.access.privilege"
|
||||
cross-database references are not implemented: "no.such.database"."no.such.schema"."no.such.default.access.privilege"
|
||||
\di "no.such.database"."no.such.schema"."no.such.index.relation"
|
||||
cross-database references are not implemented: "no.such.database"."no.such.schema"."no.such.index.relation"
|
||||
\dm "no.such.database"."no.such.schema"."no.such.materialized.view"
|
||||
cross-database references are not implemented: "no.such.database"."no.such.schema"."no.such.materialized.view"
|
||||
\ds "no.such.database"."no.such.schema"."no.such.relation"
|
||||
cross-database references are not implemented: "no.such.database"."no.such.schema"."no.such.relation"
|
||||
\dt "no.such.database"."no.such.schema"."no.such.relation"
|
||||
cross-database references are not implemented: "no.such.database"."no.such.schema"."no.such.relation"
|
||||
\dv "no.such.database"."no.such.schema"."no.such.relation"
|
||||
cross-database references are not implemented: "no.such.database"."no.such.schema"."no.such.relation"
|
||||
\df "no.such.database"."no.such.schema"."no.such.function"
|
||||
cross-database references are not implemented: "no.such.database"."no.such.schema"."no.such.function"
|
||||
\dF "no.such.database"."no.such.schema"."no.such.text.search.configuration"
|
||||
cross-database references are not implemented: "no.such.database"."no.such.schema"."no.such.text.search.configuration"
|
||||
\dFd "no.such.database"."no.such.schema"."no.such.text.search.dictionary"
|
||||
cross-database references are not implemented: "no.such.database"."no.such.schema"."no.such.text.search.dictionary"
|
||||
\dFp "no.such.database"."no.such.schema"."no.such.text.search.parser"
|
||||
cross-database references are not implemented: "no.such.database"."no.such.schema"."no.such.text.search.parser"
|
||||
\dFt "no.such.database"."no.such.schema"."no.such.text.search.template"
|
||||
cross-database references are not implemented: "no.such.database"."no.such.schema"."no.such.text.search.template"
|
||||
\do "no.such.database"."no.such.schema"."no.such.operator"
|
||||
cross-database references are not implemented: "no.such.database"."no.such.schema"."no.such.operator"
|
||||
\dO "no.such.database"."no.such.schema"."no.such.collation"
|
||||
cross-database references are not implemented: "no.such.database"."no.such.schema"."no.such.collation"
|
||||
\dp "no.such.database"."no.such.schema"."no.such.access.privilege"
|
||||
cross-database references are not implemented: "no.such.database"."no.such.schema"."no.such.access.privilege"
|
||||
\dP "no.such.database"."no.such.schema"."no.such.partitioned.relation"
|
||||
cross-database references are not implemented: "no.such.database"."no.such.schema"."no.such.partitioned.relation"
|
||||
\dT "no.such.database"."no.such.schema"."no.such.data.type"
|
||||
cross-database references are not implemented: "no.such.database"."no.such.schema"."no.such.data.type"
|
||||
\dX "no.such.database"."no.such.schema"."no.such.extended.statistics"
|
||||
cross-database references are not implemented: "no.such.database"."no.such.schema"."no.such.extended.statistics"
|
||||
|
@ -1463,3 +1463,245 @@ SELECT * FROM bla ORDER BY 1;
|
||||
\echo '# final ON_ERROR_ROLLBACK:' :ON_ERROR_ROLLBACK
|
||||
DROP TABLE bla;
|
||||
DROP FUNCTION psql_error;
|
||||
|
||||
-- check describing invalid multipart names
|
||||
\dA regression.heap
|
||||
\dA nonesuch.heap
|
||||
\dt host.regression.pg_catalog.pg_class
|
||||
\dt |.pg_catalog.pg_class
|
||||
\dt nonesuch.pg_catalog.pg_class
|
||||
\da host.regression.pg_catalog.sum
|
||||
\da +.pg_catalog.sum
|
||||
\da nonesuch.pg_catalog.sum
|
||||
\dAc nonesuch.brin
|
||||
\dAc regression.brin
|
||||
\dAf nonesuch.brin
|
||||
\dAf regression.brin
|
||||
\dAo nonesuch.brin
|
||||
\dAo regression.brin
|
||||
\dAp nonesuch.brin
|
||||
\dAp regression.brin
|
||||
\db nonesuch.pg_default
|
||||
\db regression.pg_default
|
||||
\dc host.regression.public.conversion
|
||||
\dc (.public.conversion
|
||||
\dc nonesuch.public.conversion
|
||||
\dC host.regression.pg_catalog.int8
|
||||
\dC ).pg_catalog.int8
|
||||
\dC nonesuch.pg_catalog.int8
|
||||
\dd host.regression.pg_catalog.pg_class
|
||||
\dd [.pg_catalog.pg_class
|
||||
\dd nonesuch.pg_catalog.pg_class
|
||||
\dD host.regression.public.gtestdomain1
|
||||
\dD ].public.gtestdomain1
|
||||
\dD nonesuch.public.gtestdomain1
|
||||
\ddp host.regression.pg_catalog.pg_class
|
||||
\ddp {.pg_catalog.pg_class
|
||||
\ddp nonesuch.pg_catalog.pg_class
|
||||
\dE host.regression.public.ft
|
||||
\dE }.public.ft
|
||||
\dE nonesuch.public.ft
|
||||
\di host.regression.public.tenk1_hundred
|
||||
\di ..public.tenk1_hundred
|
||||
\di nonesuch.public.tenk1_hundred
|
||||
\dm host.regression.public.mvtest_bb
|
||||
\dm ^.public.mvtest_bb
|
||||
\dm nonesuch.public.mvtest_bb
|
||||
\ds host.regression.public.check_seq
|
||||
\ds regression|mydb.public.check_seq
|
||||
\ds nonesuch.public.check_seq
|
||||
\dt host.regression.public.b_star
|
||||
\dt regres+ion.public.b_star
|
||||
\dt nonesuch.public.b_star
|
||||
\dv host.regression.public.shoe
|
||||
\dv regress(ion).public.shoe
|
||||
\dv nonesuch.public.shoe
|
||||
\des nonesuch.server
|
||||
\des regression.server
|
||||
\des nonesuch.server
|
||||
\des regression.server
|
||||
\des nonesuch.username
|
||||
\des regression.username
|
||||
\dew nonesuch.fdw
|
||||
\dew regression.fdw
|
||||
\df host.regression.public.namelen
|
||||
\df regres[qrstuv]ion.public.namelen
|
||||
\df nonesuch.public.namelen
|
||||
\dF host.regression.pg_catalog.arabic
|
||||
\dF regres{1,2}ion.pg_catalog.arabic
|
||||
\dF nonesuch.pg_catalog.arabic
|
||||
\dFd host.regression.pg_catalog.arabic_stem
|
||||
\dFd regres?ion.pg_catalog.arabic_stem
|
||||
\dFd nonesuch.pg_catalog.arabic_stem
|
||||
\dFp host.regression.pg_catalog.default
|
||||
\dFp ^regression.pg_catalog.default
|
||||
\dFp nonesuch.pg_catalog.default
|
||||
\dFt host.regression.pg_catalog.ispell
|
||||
\dFt regression$.pg_catalog.ispell
|
||||
\dFt nonesuch.pg_catalog.ispell
|
||||
\dg nonesuch.pg_database_owner
|
||||
\dg regression.pg_database_owner
|
||||
\dL host.regression.plpgsql
|
||||
\dL *.plpgsql
|
||||
\dL nonesuch.plpgsql
|
||||
\dn host.regression.public
|
||||
\dn """".public
|
||||
\dn nonesuch.public
|
||||
\do host.regression.public.!=-
|
||||
\do "regression|mydb".public.!=-
|
||||
\do nonesuch.public.!=-
|
||||
\dO host.regression.pg_catalog.POSIX
|
||||
\dO .pg_catalog.POSIX
|
||||
\dO nonesuch.pg_catalog.POSIX
|
||||
\dp host.regression.public.a_star
|
||||
\dp "regres+ion".public.a_star
|
||||
\dp nonesuch.public.a_star
|
||||
\dP host.regression.public.mlparted
|
||||
\dP "regres(sion)".public.mlparted
|
||||
\dP nonesuch.public.mlparted
|
||||
\drds nonesuch.lc_messages
|
||||
\drds regression.lc_messages
|
||||
\dRp public.mypub
|
||||
\dRp regression.mypub
|
||||
\dRs public.mysub
|
||||
\dRs regression.mysub
|
||||
\dT host.regression.public.widget
|
||||
\dT "regression{1,2}".public.widget
|
||||
\dT nonesuch.public.widget
|
||||
\dx regression.plpgsql
|
||||
\dx nonesuch.plpgsql
|
||||
\dX host.regression.public.func_deps_stat
|
||||
\dX "^regression$".public.func_deps_stat
|
||||
\dX nonesuch.public.func_deps_stat
|
||||
\dy regression.myevt
|
||||
\dy nonesuch.myevt
|
||||
|
||||
-- check that dots within quoted name segments are not counted
|
||||
\dA "no.such.access.method"
|
||||
\dt "no.such.table.relation"
|
||||
\da "no.such.aggregate.function"
|
||||
\dAc "no.such.operator.class"
|
||||
\dAf "no.such.operator.family"
|
||||
\dAo "no.such.operator.of.operator.family"
|
||||
\dAp "no.such.operator.support.function.of.operator.family"
|
||||
\db "no.such.tablespace"
|
||||
\dc "no.such.conversion"
|
||||
\dC "no.such.cast"
|
||||
\dd "no.such.object.description"
|
||||
\dD "no.such.domain"
|
||||
\ddp "no.such.default.access.privilege"
|
||||
\di "no.such.index.relation"
|
||||
\dm "no.such.materialized.view"
|
||||
\ds "no.such.relation"
|
||||
\dt "no.such.relation"
|
||||
\dv "no.such.relation"
|
||||
\des "no.such.foreign.server"
|
||||
\dew "no.such.foreign.data.wrapper"
|
||||
\df "no.such.function"
|
||||
\dF "no.such.text.search.configuration"
|
||||
\dFd "no.such.text.search.dictionary"
|
||||
\dFp "no.such.text.search.parser"
|
||||
\dFt "no.such.text.search.template"
|
||||
\dg "no.such.role"
|
||||
\dL "no.such.language"
|
||||
\dn "no.such.schema"
|
||||
\do "no.such.operator"
|
||||
\dO "no.such.collation"
|
||||
\dp "no.such.access.privilege"
|
||||
\dP "no.such.partitioned.relation"
|
||||
\drds "no.such.setting"
|
||||
\dRp "no.such.publication"
|
||||
\dRs "no.such.subscription"
|
||||
\dT "no.such.data.type"
|
||||
\dx "no.such.installed.extension"
|
||||
\dX "no.such.extended.statistics"
|
||||
\dy "no.such.event.trigger"
|
||||
|
||||
-- again, but with dotted schema qualifications.
|
||||
\dA "no.such.schema"."no.such.access.method"
|
||||
\dt "no.such.schema"."no.such.table.relation"
|
||||
\da "no.such.schema"."no.such.aggregate.function"
|
||||
\dAc "no.such.schema"."no.such.operator.class"
|
||||
\dAf "no.such.schema"."no.such.operator.family"
|
||||
\dAo "no.such.schema"."no.such.operator.of.operator.family"
|
||||
\dAp "no.such.schema"."no.such.operator.support.function.of.operator.family"
|
||||
\db "no.such.schema"."no.such.tablespace"
|
||||
\dc "no.such.schema"."no.such.conversion"
|
||||
\dC "no.such.schema"."no.such.cast"
|
||||
\dd "no.such.schema"."no.such.object.description"
|
||||
\dD "no.such.schema"."no.such.domain"
|
||||
\ddp "no.such.schema"."no.such.default.access.privilege"
|
||||
\di "no.such.schema"."no.such.index.relation"
|
||||
\dm "no.such.schema"."no.such.materialized.view"
|
||||
\ds "no.such.schema"."no.such.relation"
|
||||
\dt "no.such.schema"."no.such.relation"
|
||||
\dv "no.such.schema"."no.such.relation"
|
||||
\des "no.such.schema"."no.such.foreign.server"
|
||||
\dew "no.such.schema"."no.such.foreign.data.wrapper"
|
||||
\df "no.such.schema"."no.such.function"
|
||||
\dF "no.such.schema"."no.such.text.search.configuration"
|
||||
\dFd "no.such.schema"."no.such.text.search.dictionary"
|
||||
\dFp "no.such.schema"."no.such.text.search.parser"
|
||||
\dFt "no.such.schema"."no.such.text.search.template"
|
||||
\dg "no.such.schema"."no.such.role"
|
||||
\dL "no.such.schema"."no.such.language"
|
||||
\do "no.such.schema"."no.such.operator"
|
||||
\dO "no.such.schema"."no.such.collation"
|
||||
\dp "no.such.schema"."no.such.access.privilege"
|
||||
\dP "no.such.schema"."no.such.partitioned.relation"
|
||||
\drds "no.such.schema"."no.such.setting"
|
||||
\dRp "no.such.schema"."no.such.publication"
|
||||
\dRs "no.such.schema"."no.such.subscription"
|
||||
\dT "no.such.schema"."no.such.data.type"
|
||||
\dx "no.such.schema"."no.such.installed.extension"
|
||||
\dX "no.such.schema"."no.such.extended.statistics"
|
||||
\dy "no.such.schema"."no.such.event.trigger"
|
||||
|
||||
-- again, but with current database and dotted schema qualifications.
|
||||
\dt regression."no.such.schema"."no.such.table.relation"
|
||||
\da regression."no.such.schema"."no.such.aggregate.function"
|
||||
\dc regression."no.such.schema"."no.such.conversion"
|
||||
\dC regression."no.such.schema"."no.such.cast"
|
||||
\dd regression."no.such.schema"."no.such.object.description"
|
||||
\dD regression."no.such.schema"."no.such.domain"
|
||||
\di regression."no.such.schema"."no.such.index.relation"
|
||||
\dm regression."no.such.schema"."no.such.materialized.view"
|
||||
\ds regression."no.such.schema"."no.such.relation"
|
||||
\dt regression."no.such.schema"."no.such.relation"
|
||||
\dv regression."no.such.schema"."no.such.relation"
|
||||
\df regression."no.such.schema"."no.such.function"
|
||||
\dF regression."no.such.schema"."no.such.text.search.configuration"
|
||||
\dFd regression."no.such.schema"."no.such.text.search.dictionary"
|
||||
\dFp regression."no.such.schema"."no.such.text.search.parser"
|
||||
\dFt regression."no.such.schema"."no.such.text.search.template"
|
||||
\do regression."no.such.schema"."no.such.operator"
|
||||
\dO regression."no.such.schema"."no.such.collation"
|
||||
\dp regression."no.such.schema"."no.such.access.privilege"
|
||||
\dP regression."no.such.schema"."no.such.partitioned.relation"
|
||||
\dT regression."no.such.schema"."no.such.data.type"
|
||||
\dX regression."no.such.schema"."no.such.extended.statistics"
|
||||
|
||||
-- again, but with dotted database and dotted schema qualifications.
|
||||
\dt "no.such.database"."no.such.schema"."no.such.table.relation"
|
||||
\da "no.such.database"."no.such.schema"."no.such.aggregate.function"
|
||||
\dc "no.such.database"."no.such.schema"."no.such.conversion"
|
||||
\dC "no.such.database"."no.such.schema"."no.such.cast"
|
||||
\dd "no.such.database"."no.such.schema"."no.such.object.description"
|
||||
\dD "no.such.database"."no.such.schema"."no.such.domain"
|
||||
\ddp "no.such.database"."no.such.schema"."no.such.default.access.privilege"
|
||||
\di "no.such.database"."no.such.schema"."no.such.index.relation"
|
||||
\dm "no.such.database"."no.such.schema"."no.such.materialized.view"
|
||||
\ds "no.such.database"."no.such.schema"."no.such.relation"
|
||||
\dt "no.such.database"."no.such.schema"."no.such.relation"
|
||||
\dv "no.such.database"."no.such.schema"."no.such.relation"
|
||||
\df "no.such.database"."no.such.schema"."no.such.function"
|
||||
\dF "no.such.database"."no.such.schema"."no.such.text.search.configuration"
|
||||
\dFd "no.such.database"."no.such.schema"."no.such.text.search.dictionary"
|
||||
\dFp "no.such.database"."no.such.schema"."no.such.text.search.parser"
|
||||
\dFt "no.such.database"."no.such.schema"."no.such.text.search.template"
|
||||
\do "no.such.database"."no.such.schema"."no.such.operator"
|
||||
\dO "no.such.database"."no.such.schema"."no.such.collation"
|
||||
\dp "no.such.database"."no.such.schema"."no.such.access.privilege"
|
||||
\dP "no.such.database"."no.such.schema"."no.such.partitioned.relation"
|
||||
\dT "no.such.database"."no.such.schema"."no.such.data.type"
|
||||
\dX "no.such.database"."no.such.schema"."no.such.extended.statistics"
|
||||
|
Loading…
Reference in New Issue
Block a user