diff options
Diffstat (limited to 'src/bin/psql/describe.c')
-rw-r--r-- | src/bin/psql/describe.c | 504 |
1 files changed, 336 insertions, 168 deletions
diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c index 583817b0cc6..4369f2235b4 100644 --- a/src/bin/psql/describe.c +++ b/src/bin/psql/describe.c @@ -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;"); @@ -5893,6 +5986,59 @@ listOneExtensionContents(const char *extname, const char *oid) } /* + * 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" |