*
* Utility routines for SQL dumping
* Basically this is stuff that is useful in both pg_dump and pg_dumpall.
+ * Lately it's also being used by psql and bin/scripts/ ...
*
*
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/bin/pg_dump/dumputils.c,v 1.32 2006/10/04 00:30:05 momjian Exp $
+ * $PostgreSQL: pgsql/src/bin/pg_dump/dumputils.c,v 1.33 2006/10/09 23:30:33 tgl Exp $
*
*-------------------------------------------------------------------------
*/
-
#include "postgres_fe.h"
+#include <ctype.h>
+
#include "dumputils.h"
#include "parser/keywords.h"
char *pos;
buf = strdup(item);
+ if (!buf)
+ return false;
/* user or group name is string up to = */
eqpos = copyAclUserName(grantee, buf);
appendPQExpBufferChar(aclbuf, ',');
appendPQExpBuffer(aclbuf, "%s", keyword);
}
+
+
+/*
+ * processSQLNamePattern
+ *
+ * Scan a wildcard-pattern string and generate appropriate WHERE clauses
+ * to limit the set of objects returned. The WHERE clauses are appended
+ * to the already-partially-constructed query in buf.
+ *
+ * conn: connection query will be sent to (consulted for escaping rules).
+ * buf: output parameter.
+ * pattern: user-specified pattern option, or NULL if none ("*" is implied).
+ * have_where: true if caller already emitted "WHERE" (clauses will be ANDed
+ * onto the existing WHERE clause).
+ * force_escape: always quote regexp special characters, even outside
+ * double quotes (else they are quoted only between double quotes).
+ * schemavar: name of query variable to match against a schema-name pattern.
+ * Can be NULL if no schema.
+ * namevar: name of query variable to match against an object-name pattern.
+ * altnamevar: NULL, or name of an alternate 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.
+ *
+ * Formatting note: the text already present in buf should end with a newline.
+ * The appended text, if any, will end with one too.
+ */
+void
+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)
+{
+ PQExpBufferData schemabuf;
+ PQExpBufferData namebuf;
+ int encoding = PQclientEncoding(conn);
+ bool inquotes;
+ const char *cp;
+ int i;
+
+#define WHEREAND() \
+ (appendPQExpBufferStr(buf, have_where ? " AND " : "WHERE "), have_where = true)
+
+ if (pattern == NULL)
+ {
+ /* Default: select all visible objects */
+ if (visibilityrule)
+ {
+ WHEREAND();
+ appendPQExpBuffer(buf, "%s\n", visibilityrule);
+ }
+ return;
+ }
+
+ initPQExpBuffer(&schemabuf);
+ initPQExpBuffer(&namebuf);
+
+ /*
+ * Parse the pattern, converting quotes and lower-casing unquoted letters.
+ * Also, adjust shell-style wildcard characters into regexp notation.
+ *
+ * We surround the pattern with "^(...)$" to force it to match the whole
+ * string, as per SQL practice. We have to have parens in case the string
+ * contains "|", else the "^" and "$" will be bound into the first and
+ * last alternatives which is not what we want.
+ *
+ * Note: the result of this pass is the actual regexp pattern(s) we want to
+ * execute. Quoting/escaping into SQL literal format will be done below
+ * using appendStringLiteralConn().
+ */
+ appendPQExpBufferStr(&namebuf, "^(");
+
+ inquotes = false;
+ cp = pattern;
+
+ while (*cp)
+ {
+ char ch = *cp;
+
+ if (ch == '"')
+ {
+ if (inquotes && cp[1] == '"')
+ {
+ /* emit one quote, stay in inquotes mode */
+ appendPQExpBufferChar(&namebuf, '"');
+ cp++;
+ }
+ else
+ inquotes = !inquotes;
+ cp++;
+ }
+ else if (!inquotes && isupper((unsigned char) ch))
+ {
+ appendPQExpBufferChar(&namebuf,
+ pg_tolower((unsigned char) ch));
+ cp++;
+ }
+ else if (!inquotes && ch == '*')
+ {
+ appendPQExpBufferStr(&namebuf, ".*");
+ cp++;
+ }
+ else if (!inquotes && ch == '?')
+ {
+ appendPQExpBufferChar(&namebuf, '.');
+ cp++;
+ }
+ else if (!inquotes && ch == '.')
+ {
+ /* Found schema/name separator, move current pattern to schema */
+ resetPQExpBuffer(&schemabuf);
+ appendPQExpBufferStr(&schemabuf, namebuf.data);
+ resetPQExpBuffer(&namebuf);
+ appendPQExpBufferStr(&namebuf, "^(");
+ cp++;
+ }
+ else
+ {
+ /*
+ * Ordinary data character, transfer to pattern
+ *
+ * Inside double quotes, or at all times if force_escape is true,
+ * quote regexp special characters with a backslash to avoid
+ * regexp errors. Outside quotes, however, let them pass through
+ * as-is; this lets knowledgeable users build regexp expressions
+ * that are more powerful than shell-style patterns.
+ */
+ if ((inquotes || force_escape) &&
+ strchr("|*+?()[]{}.^$\\", ch))
+ appendPQExpBufferChar(&namebuf, '\\');
+ i = PQmblen(cp, encoding);
+ while (i-- && *cp)
+ {
+ appendPQExpBufferChar(&namebuf, *cp);
+ cp++;
+ }
+ }
+ }
+
+ /*
+ * Now decide what we need to emit. Note there will be a leading "^("
+ * in the patterns in any case.
+ */
+ if (namebuf.len > 2)
+ {
+ /* We have a name pattern, so constrain the namevar(s) */
+
+ appendPQExpBufferStr(&namebuf, ")$");
+ /* Optimize away a "*" pattern */
+ if (strcmp(namebuf.data, "^(.*)$") != 0)
+ {
+ WHEREAND();
+ if (altnamevar)
+ {
+ appendPQExpBuffer(buf, "(%s ~ ", namevar);
+ appendStringLiteralConn(buf, namebuf.data, conn);
+ appendPQExpBuffer(buf, "\n OR %s ~ ", altnamevar);
+ appendStringLiteralConn(buf, namebuf.data, conn);
+ appendPQExpBufferStr(buf, ")\n");
+ }
+ else
+ {
+ appendPQExpBuffer(buf, "%s ~ ", namevar);
+ appendStringLiteralConn(buf, namebuf.data, conn);
+ appendPQExpBufferChar(buf, '\n');
+ }
+ }
+ }
+
+ if (schemabuf.len > 2)
+ {
+ /* We have a schema pattern, so constrain the schemavar */
+
+ appendPQExpBufferStr(&schemabuf, ")$");
+ /* Optimize away a "*" pattern */
+ if (strcmp(schemabuf.data, "^(.*)$") != 0 && schemavar)
+ {
+ WHEREAND();
+ appendPQExpBuffer(buf, "%s ~ ", schemavar);
+ appendStringLiteralConn(buf, schemabuf.data, conn);
+ appendPQExpBufferChar(buf, '\n');
+ }
+ }
+ else
+ {
+ /* No schema pattern given, so select only visible objects */
+ if (visibilityrule)
+ {
+ WHEREAND();
+ appendPQExpBuffer(buf, "%s\n", visibilityrule);
+ }
+ }
+
+ termPQExpBuffer(&schemabuf);
+ termPQExpBuffer(&namebuf);
+
+#undef WHEREAND
+}
*
* Copyright (c) 2000-2006, PostgreSQL Global Development Group
*
- * $PostgreSQL: pgsql/src/bin/psql/describe.c,v 1.146 2006/10/07 22:21:38 tgl Exp $
+ * $PostgreSQL: pgsql/src/bin/psql/describe.c,v 1.147 2006/10/09 23:30:33 tgl Exp $
*/
#include "postgres_fe.h"
#include "describe.h"
const char *relationname,
const char *oid,
bool verbose);
-static void processNamePattern(PQExpBuffer buf, const char *pattern,
- bool have_where, bool force_escape,
- const char *schemavar, const char *namevar,
- const char *altnamevar, const char *visibilityrule);
-
static bool add_tablespace_footer(char relkind, Oid tablespace, char **footers,
int *count, PQExpBufferData buf, bool newline);
_("Schema"), _("Name"),
_("Argument data types"), _("Description"));
- processNamePattern(&buf, pattern, true, false,
- "n.nspname", "p.proname", NULL,
- "pg_catalog.pg_function_is_visible(p.oid)");
+ processSQLNamePattern(pset.db, &buf, pattern, true, false,
+ "n.nspname", "p.proname", NULL,
+ "pg_catalog.pg_function_is_visible(p.oid)");
appendPQExpBuffer(&buf, "ORDER BY 1, 2, 3;");
appendPQExpBuffer(&buf,
"\nFROM pg_catalog.pg_tablespace\n");
- processNamePattern(&buf, pattern, false, false,
- NULL, "spcname", NULL,
- NULL);
+ processSQLNamePattern(pset.db, &buf, pattern, false, false,
+ NULL, "spcname", NULL,
+ NULL);
appendPQExpBuffer(&buf, "ORDER BY 1;");
" OR p.proargtypes[0] <> 'pg_catalog.cstring'::pg_catalog.regtype)\n"
" AND NOT p.proisagg\n");
- processNamePattern(&buf, pattern, true, false,
- "n.nspname", "p.proname", NULL,
- "pg_catalog.pg_function_is_visible(p.oid)");
+ processSQLNamePattern(pset.db, &buf, pattern, true, false,
+ "n.nspname", "p.proname", NULL,
+ "pg_catalog.pg_function_is_visible(p.oid)");
appendPQExpBuffer(&buf, "ORDER BY 1, 2, 3, 4;");
appendPQExpBuffer(&buf, "AND t.typname !~ '^_'\n");
/* Match name pattern against either internal or external name */
- processNamePattern(&buf, pattern, true, false,
- "n.nspname", "t.typname",
- "pg_catalog.format_type(t.oid, NULL)",
- "pg_catalog.pg_type_is_visible(t.oid)");
+ processSQLNamePattern(pset.db, &buf, pattern, true, false,
+ "n.nspname", "t.typname",
+ "pg_catalog.format_type(t.oid, NULL)",
+ "pg_catalog.pg_type_is_visible(t.oid)");
appendPQExpBuffer(&buf, "ORDER BY 1, 2;");
_("Left arg type"), _("Right arg type"),
_("Result type"), _("Description"));
- processNamePattern(&buf, pattern, false, true,
- "n.nspname", "o.oprname", NULL,
- "pg_catalog.pg_operator_is_visible(o.oid)");
+ processSQLNamePattern(pset.db, &buf, pattern, false, true,
+ "n.nspname", "o.oprname", NULL,
+ "pg_catalog.pg_operator_is_visible(o.oid)");
appendPQExpBuffer(&buf, "ORDER BY 1, 2, 3, 4;");
* point of view. You can see 'em by explicit request though, eg with \z
* pg_catalog.*
*/
- processNamePattern(&buf, pattern, true, false,
- "n.nspname", "c.relname", NULL,
+ processSQLNamePattern(pset.db, &buf, pattern, true, false,
+ "n.nspname", "c.relname", NULL,
"n.nspname !~ '^pg_' AND pg_catalog.pg_table_is_visible(c.oid)");
appendPQExpBuffer(&buf, "ORDER BY 1, 2;");
" LEFT JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace\n"
" WHERE p.proisagg\n",
_("aggregate"));
- processNamePattern(&buf, pattern, true, false,
- "n.nspname", "p.proname", NULL,
- "pg_catalog.pg_function_is_visible(p.oid)");
+ processSQLNamePattern(pset.db, &buf, pattern, true, false,
+ "n.nspname", "p.proname", NULL,
+ "pg_catalog.pg_function_is_visible(p.oid)");
/* Function descriptions (except in/outs for datatypes) */
appendPQExpBuffer(&buf,
" OR p.proargtypes[0] <> 'pg_catalog.cstring'::pg_catalog.regtype)\n"
" AND NOT p.proisagg\n",
_("function"));
- processNamePattern(&buf, pattern, true, false,
- "n.nspname", "p.proname", NULL,
- "pg_catalog.pg_function_is_visible(p.oid)");
+ processSQLNamePattern(pset.db, &buf, pattern, true, false,
+ "n.nspname", "p.proname", NULL,
+ "pg_catalog.pg_function_is_visible(p.oid)");
/* Operator descriptions (only if operator has its own comment) */
appendPQExpBuffer(&buf,
" FROM pg_catalog.pg_operator o\n"
" LEFT JOIN pg_catalog.pg_namespace n ON n.oid = o.oprnamespace\n",
_("operator"));
- processNamePattern(&buf, pattern, false, false,
- "n.nspname", "o.oprname", NULL,
- "pg_catalog.pg_operator_is_visible(o.oid)");
+ processSQLNamePattern(pset.db, &buf, pattern, false, false,
+ "n.nspname", "o.oprname", NULL,
+ "pg_catalog.pg_operator_is_visible(o.oid)");
/* Type description */
appendPQExpBuffer(&buf,
" FROM pg_catalog.pg_type t\n"
" LEFT JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace\n",
_("data type"));
- processNamePattern(&buf, pattern, false, false,
- "n.nspname", "pg_catalog.format_type(t.oid, NULL)", NULL,
- "pg_catalog.pg_type_is_visible(t.oid)");
+ processSQLNamePattern(pset.db, &buf, pattern, false, false,
+ "n.nspname", "pg_catalog.format_type(t.oid, NULL)",
+ NULL,
+ "pg_catalog.pg_type_is_visible(t.oid)");
/* Relation (tables, views, indexes, sequences) descriptions */
appendPQExpBuffer(&buf,
" LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace\n"
" WHERE c.relkind IN ('r', 'v', 'i', 'S')\n",
_("table"), _("view"), _("index"), _("sequence"));
- processNamePattern(&buf, pattern, true, false,
- "n.nspname", "c.relname", NULL,
- "pg_catalog.pg_table_is_visible(c.oid)");
+ processSQLNamePattern(pset.db, &buf, pattern, true, false,
+ "n.nspname", "c.relname", NULL,
+ "pg_catalog.pg_table_is_visible(c.oid)");
/* Rule description (ignore rules for views) */
appendPQExpBuffer(&buf,
" WHERE r.rulename != '_RETURN'\n",
_("rule"));
/* XXX not sure what to do about visibility rule here? */
- processNamePattern(&buf, pattern, true, false,
- "n.nspname", "r.rulename", NULL,
- "pg_catalog.pg_table_is_visible(c.oid)");
+ processSQLNamePattern(pset.db, &buf, pattern, true, false,
+ "n.nspname", "r.rulename", NULL,
+ "pg_catalog.pg_table_is_visible(c.oid)");
/* Trigger description */
appendPQExpBuffer(&buf,
" LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace\n",
_("trigger"));
/* XXX not sure what to do about visibility rule here? */
- processNamePattern(&buf, pattern, false, false,
- "n.nspname", "t.tgname", NULL,
- "pg_catalog.pg_table_is_visible(c.oid)");
+ processSQLNamePattern(pset.db, &buf, pattern, false, false,
+ "n.nspname", "t.tgname", NULL,
+ "pg_catalog.pg_table_is_visible(c.oid)");
appendPQExpBuffer(&buf,
") AS tt\n"
"FROM pg_catalog.pg_class c\n"
" LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace\n");
- processNamePattern(&buf, pattern, false, false,
- "n.nspname", "c.relname", NULL,
- "pg_catalog.pg_table_is_visible(c.oid)");
+ processSQLNamePattern(pset.db, &buf, pattern, false, false,
+ "n.nspname", "c.relname", NULL,
+ "pg_catalog.pg_table_is_visible(c.oid)");
appendPQExpBuffer(&buf, "ORDER BY 2, 3;");
appendPQExpBuffer(&buf, "\nFROM pg_catalog.pg_roles r\n");
- processNamePattern(&buf, pattern, false, false,
- NULL, "r.rolname", NULL, NULL);
+ processSQLNamePattern(pset.db, &buf, pattern, false, false,
+ NULL, "r.rolname", NULL, NULL);
appendPQExpBuffer(&buf, "ORDER BY 1;");
else
appendPQExpBuffer(&buf, " AND n.nspname NOT IN ('pg_catalog', 'pg_toast')\n");
- processNamePattern(&buf, pattern, true, false,
- "n.nspname", "c.relname", NULL,
- "pg_catalog.pg_table_is_visible(c.oid)");
+ processSQLNamePattern(pset.db, &buf, pattern, true, false,
+ "n.nspname", "c.relname", NULL,
+ "pg_catalog.pg_table_is_visible(c.oid)");
appendPQExpBuffer(&buf, "ORDER BY 1,2;");
_("Modifier"),
_("Check"));
- processNamePattern(&buf, pattern, true, false,
- "n.nspname", "t.typname", NULL,
- "pg_catalog.pg_type_is_visible(t.oid)");
+ processSQLNamePattern(pset.db, &buf, pattern, true, false,
+ "n.nspname", "t.typname", NULL,
+ "pg_catalog.pg_type_is_visible(t.oid)");
appendPQExpBuffer(&buf, "ORDER BY 1, 2;");
_("no"),
_("Default?"));
- processNamePattern(&buf, pattern, true, false,
- "n.nspname", "c.conname", NULL,
- "pg_catalog.pg_conversion_is_visible(c.oid)");
+ processSQLNamePattern(pset.db, &buf, pattern, true, false,
+ "n.nspname", "c.conname", NULL,
+ "pg_catalog.pg_conversion_is_visible(c.oid)");
appendPQExpBuffer(&buf, "ORDER BY 1, 2;");
"WHERE (n.nspname !~ '^pg_temp_' OR\n"
" n.nspname = (pg_catalog.current_schemas(true))[1])\n"); /* temp schema is first */
- processNamePattern(&buf, pattern, true, false,
- NULL, "n.nspname", NULL,
- NULL);
+ processSQLNamePattern(pset.db, &buf, pattern, true, false,
+ NULL, "n.nspname", NULL,
+ NULL);
appendPQExpBuffer(&buf, "ORDER BY 1;");
PQclear(res);
return true;
}
-
-
-/*
- * processNamePattern
- *
- * Scan a wildcard-pattern option and generate appropriate WHERE clauses
- * to limit the set of objects returned. The WHERE clauses are appended
- * to buf.
- *
- * pattern: user-specified pattern option to a \d command, or NULL if none.
- * have_where: true if caller already emitted WHERE.
- * force_escape: always quote regexp special characters, even outside quotes.
- * schemavar: name of WHERE variable to match against a schema-name pattern.
- * Can be NULL if no schema.
- * namevar: name of WHERE variable to match against an object-name pattern.
- * altnamevar: NULL, or name of an alternate 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.
- */
-static void
-processNamePattern(PQExpBuffer buf, const char *pattern,
- bool have_where, bool force_escape,
- const char *schemavar, const char *namevar,
- const char *altnamevar, const char *visibilityrule)
-{
- PQExpBufferData schemabuf;
- PQExpBufferData namebuf;
- bool inquotes;
- const char *cp;
- int i;
-
-#define WHEREAND() \
- (appendPQExpBuffer(buf, have_where ? " AND " : "WHERE "), have_where = true)
-
- if (pattern == NULL)
- {
- /* Default: select all visible objects */
- if (visibilityrule)
- {
- WHEREAND();
- appendPQExpBuffer(buf, "%s\n", visibilityrule);
- }
- return;
- }
-
- initPQExpBuffer(&schemabuf);
- initPQExpBuffer(&namebuf);
-
- /*
- * Parse the pattern, converting quotes and lower-casing unquoted letters;
- * we assume this was NOT done by scan_option. Also, adjust shell-style
- * wildcard characters into regexp notation.
- *
- * Note: the result of this pass is the actual regexp pattern we want to
- * execute. Quoting/escaping it into a SQL literal will be done below.
- */
- appendPQExpBufferChar(&namebuf, '^');
-
- inquotes = false;
- cp = pattern;
-
- while (*cp)
- {
- char ch = *cp;
-
- if (ch == '"')
- {
- if (inquotes && cp[1] == '"')
- {
- /* emit one quote, stay in inquotes mode */
- appendPQExpBufferChar(&namebuf, '"');
- cp++;
- }
- else
- inquotes = !inquotes;
- cp++;
- }
- else if (!inquotes && isupper((unsigned char) ch))
- {
- appendPQExpBufferChar(&namebuf,
- pg_tolower((unsigned char) ch));
- cp++;
- }
- else if (!inquotes && ch == '*')
- {
- appendPQExpBuffer(&namebuf, ".*");
- cp++;
- }
- else if (!inquotes && ch == '?')
- {
- appendPQExpBufferChar(&namebuf, '.');
- cp++;
- }
- else if (!inquotes && ch == '.')
- {
- /* Found schema/name separator, move current pattern to schema */
- resetPQExpBuffer(&schemabuf);
- appendPQExpBufferStr(&schemabuf, namebuf.data);
- resetPQExpBuffer(&namebuf);
- appendPQExpBufferChar(&namebuf, '^');
- cp++;
- }
- else
- {
- /*
- * Ordinary data character, transfer to pattern
- *
- * Inside double quotes, or at all times if parsing an operator
- * name, quote regexp special characters with a backslash to avoid
- * regexp errors. Outside quotes, however, let them pass through
- * as-is; this lets knowledgeable users build regexp expressions
- * that are more powerful than shell-style patterns.
- */
- if ((inquotes || force_escape) &&
- strchr("|*+?()[]{}.^$\\", ch))
- appendPQExpBufferChar(&namebuf, '\\');
- i = PQmblen(cp, pset.encoding);
- while (i-- && *cp)
- {
- appendPQExpBufferChar(&namebuf, *cp);
- cp++;
- }
- }
- }
-
- /*
- * Now decide what we need to emit. Note there will be a leading '^' in
- * the patterns in any case.
- */
- if (namebuf.len > 1)
- {
- /* We have a name pattern, so constrain the namevar(s) */
-
- appendPQExpBufferChar(&namebuf, '$');
- /* Optimize away ".*$", and possibly the whole pattern */
- if (namebuf.len >= 4 &&
- strcmp(namebuf.data + (namebuf.len - 3), ".*$") == 0)
- {
- namebuf.len -= 3;
- namebuf.data[namebuf.len] = '\0';
- }
-
- if (namebuf.len > 1)
- {
- WHEREAND();
- if (altnamevar)
- {
- appendPQExpBuffer(buf, "(%s ~ ", namevar);
- appendStringLiteralConn(buf, namebuf.data, pset.db);
- appendPQExpBuffer(buf, "\n OR %s ~ ", altnamevar);
- appendStringLiteralConn(buf, namebuf.data, pset.db);
- appendPQExpBuffer(buf, ")\n");
- }
- else
- {
- appendPQExpBuffer(buf, "%s ~ ", namevar);
- appendStringLiteralConn(buf, namebuf.data, pset.db);
- appendPQExpBufferChar(buf, '\n');
- }
- }
- }
-
- if (schemabuf.len > 1)
- {
- /* We have a schema pattern, so constrain the schemavar */
-
- appendPQExpBufferChar(&schemabuf, '$');
- /* Optimize away ".*$", and possibly the whole pattern */
- if (schemabuf.len >= 4 &&
- strcmp(schemabuf.data + (schemabuf.len - 3), ".*$") == 0)
- {
- schemabuf.len -= 3;
- schemabuf.data[schemabuf.len] = '\0';
- }
-
- if (schemabuf.len > 1 && schemavar)
- {
- WHEREAND();
- appendPQExpBuffer(buf, "%s ~ ", schemavar);
- appendStringLiteralConn(buf, schemabuf.data, pset.db);
- appendPQExpBufferChar(buf, '\n');
- }
- }
- else
- {
- /* No schema pattern given, so select only visible objects */
- if (visibilityrule)
- {
- WHEREAND();
- appendPQExpBuffer(buf, "%s\n", visibilityrule);
- }
- }
-
- termPQExpBuffer(&schemabuf);
- termPQExpBuffer(&namebuf);
-
-#undef WHEREAND
-}