1 /*-------------------------------------------------------------------------
3 * Utility routines for SQL dumping
4 * Basically this is stuff that is useful in both pg_dump and pg_dumpall.
5 * Lately it's also being used by psql and bin/scripts/ ...
8 * Portions Copyright (c) 1996-2012, PostgreSQL Global Development Group
9 * Portions Copyright (c) 1994, Regents of the University of California
11 * src/bin/pg_dump/dumputils.c
13 *-------------------------------------------------------------------------
15 #include "postgres_fe.h"
19 #include "dumputils.h"
20 #include "pg_backup.h"
22 #include "parser/keywords.h"
25 /* Globals exported by this file */
26 int quote_all_identifiers = 0;
27 const char *progname = NULL;
30 #define supports_grant_options(version) ((version) >= 70400)
32 static bool parseAclItem(const char *item, const char *type,
33 const char *name, const char *subname, int remoteVersion,
34 PQExpBuffer grantee, PQExpBuffer grantor,
35 PQExpBuffer privs, PQExpBuffer privswgo);
36 static char *copyAclUserName(PQExpBuffer output, char *input);
37 static void AddAcl(PQExpBuffer aclbuf, const char *keyword,
41 static bool parallel_init_done = false;
42 static DWORD tls_index;
46 init_parallel_dump_utils(void)
49 if (!parallel_init_done)
51 tls_index = TlsAlloc();
52 parallel_init_done = true;
58 * Quotes input string if it's not a legitimate SQL identifier as-is.
60 * Note that the returned string must be used before calling fmtId again,
61 * since we re-use the same return buffer each time. Non-reentrant but
62 * reduces memory leakage. (On Windows the memory leakage will be one buffer
63 * per thread, which is at least better than one per call).
66 fmtId(const char *rawid)
69 * The Tls code goes awry if we use a static var, so we provide for both
70 * static and auto, and omit any use of the static var when using Tls.
72 static PQExpBuffer s_id_return = NULL;
73 PQExpBuffer id_return;
76 bool need_quotes = false;
79 if (parallel_init_done)
80 id_return = (PQExpBuffer) TlsGetValue(tls_index); /* 0 when not set */
82 id_return = s_id_return;
84 id_return = s_id_return;
87 if (id_return) /* first time through? */
89 /* same buffer, just wipe contents */
90 resetPQExpBuffer(id_return);
95 id_return = createPQExpBuffer();
97 if (parallel_init_done)
98 TlsSetValue(tls_index, id_return);
100 s_id_return = id_return;
102 s_id_return = id_return;
108 * These checks need to match the identifier production in scan.l. Don't
111 if (quote_all_identifiers)
113 /* slightly different rules for first character */
114 else if (!((rawid[0] >= 'a' && rawid[0] <= 'z') || rawid[0] == '_'))
118 /* otherwise check the entire string */
119 for (cp = rawid; *cp; cp++)
121 if (!((*cp >= 'a' && *cp <= 'z')
122 || (*cp >= '0' && *cp <= '9')
134 * Check for keyword. We quote keywords except for unreserved ones.
135 * (In some cases we could avoid quoting a col_name or type_func_name
136 * keyword, but it seems much harder than it's worth to tell that.)
138 * Note: ScanKeywordLookup() does case-insensitive comparison, but
139 * that's fine, since we already know we have all-lower-case.
141 const ScanKeyword *keyword = ScanKeywordLookup(rawid,
145 if (keyword != NULL && keyword->category != UNRESERVED_KEYWORD)
151 /* no quoting needed */
152 appendPQExpBufferStr(id_return, rawid);
156 appendPQExpBufferChar(id_return, '\"');
157 for (cp = rawid; *cp; cp++)
160 * Did we find a double-quote in the string? Then make this a
161 * double double-quote per SQL99. Before, we put in a
162 * backslash/double-quote pair. - thomas 2000-08-05
165 appendPQExpBufferChar(id_return, '\"');
166 appendPQExpBufferChar(id_return, *cp);
168 appendPQExpBufferChar(id_return, '\"');
171 return id_return->data;
176 * Convert a string value to an SQL string literal and append it to
177 * the given buffer. We assume the specified client_encoding and
178 * standard_conforming_strings settings.
180 * This is essentially equivalent to libpq's PQescapeStringInternal,
181 * except for the output buffer structure. We need it in situations
182 * where we do not have a PGconn available. Where we do,
183 * appendStringLiteralConn is a better choice.
186 appendStringLiteral(PQExpBuffer buf, const char *str,
187 int encoding, bool std_strings)
189 size_t length = strlen(str);
190 const char *source = str;
193 if (!enlargePQExpBuffer(buf, 2 * length + 2))
196 target = buf->data + buf->len;
199 while (*source != '\0')
205 /* Fast path for plain ASCII */
206 if (!IS_HIGHBIT_SET(c))
208 /* Apply quoting if needed */
209 if (SQL_STR_DOUBLE(c, !std_strings))
211 /* Copy the character */
217 /* Slow path for possible multibyte characters */
218 len = PQmblen(source, encoding);
220 /* Copy the character */
221 for (i = 0; i < len; i++)
225 *target++ = *source++;
229 * If we hit premature end of string (ie, incomplete multibyte
230 * character), try to pad out to the correct length with spaces. We
231 * may not be able to pad completely, but we will always be able to
232 * insert at least one pad space (since we'd not have quoted a
233 * multibyte character). This should be enough to make a string that
234 * the server will error out on.
238 char *stop = buf->data + buf->maxlen - 2;
250 /* Write the terminating quote and NUL character. */
254 buf->len = target - buf->data;
259 * Convert a string value to an SQL string literal and append it to
260 * the given buffer. Encoding and string syntax rules are as indicated
261 * by current settings of the PGconn.
264 appendStringLiteralConn(PQExpBuffer buf, const char *str, PGconn *conn)
266 size_t length = strlen(str);
269 * XXX This is a kluge to silence escape_string_warning in our utility
270 * programs. It should go away someday.
272 if (strchr(str, '\\') != NULL && PQserverVersion(conn) >= 80100)
274 /* ensure we are not adjacent to an identifier */
275 if (buf->len > 0 && buf->data[buf->len - 1] != ' ')
276 appendPQExpBufferChar(buf, ' ');
277 appendPQExpBufferChar(buf, ESCAPE_STRING_SYNTAX);
278 appendStringLiteral(buf, str, PQclientEncoding(conn), false);
283 if (!enlargePQExpBuffer(buf, 2 * length + 2))
285 appendPQExpBufferChar(buf, '\'');
286 buf->len += PQescapeStringConn(conn, buf->data + buf->len,
288 appendPQExpBufferChar(buf, '\'');
293 * Convert a string value to a dollar quoted literal and append it to
294 * the given buffer. If the dqprefix parameter is not NULL then the
295 * dollar quote delimiter will begin with that (after the opening $).
297 * No escaping is done at all on str, in compliance with the rules
298 * for parsing dollar quoted strings. Also, we need not worry about
302 appendStringLiteralDQ(PQExpBuffer buf, const char *str, const char *dqprefix)
304 static const char suffixes[] = "_XXXXXXX";
306 PQExpBuffer delimBuf = createPQExpBuffer();
308 /* start with $ + dqprefix if not NULL */
309 appendPQExpBufferChar(delimBuf, '$');
311 appendPQExpBufferStr(delimBuf, dqprefix);
314 * Make sure we choose a delimiter which (without the trailing $) is not
315 * present in the string being quoted. We don't check with the trailing $
316 * because a string ending in $foo must not be quoted with $foo$.
318 while (strstr(str, delimBuf->data) != NULL)
320 appendPQExpBufferChar(delimBuf, suffixes[nextchar++]);
321 nextchar %= sizeof(suffixes) - 1;
325 appendPQExpBufferChar(delimBuf, '$');
327 /* quote it and we are all done */
328 appendPQExpBufferStr(buf, delimBuf->data);
329 appendPQExpBufferStr(buf, str);
330 appendPQExpBufferStr(buf, delimBuf->data);
332 destroyPQExpBuffer(delimBuf);
337 * Convert a bytea value (presented as raw bytes) to an SQL string literal
338 * and append it to the given buffer. We assume the specified
339 * standard_conforming_strings setting.
341 * This is needed in situations where we do not have a PGconn available.
342 * Where we do, PQescapeByteaConn is a better choice.
345 appendByteaLiteral(PQExpBuffer buf, const unsigned char *str, size_t length,
348 const unsigned char *source = str;
351 static const char hextbl[] = "0123456789abcdef";
354 * This implementation is hard-wired to produce hex-format output. We do
355 * not know the server version the output will be loaded into, so making
356 * an intelligent format choice is impossible. It might be better to
357 * always use the old escaped format.
359 if (!enlargePQExpBuffer(buf, 2 * length + 5))
362 target = buf->data + buf->len;
371 unsigned char c = *source++;
373 *target++ = hextbl[(c >> 4) & 0xF];
374 *target++ = hextbl[c & 0xF];
377 /* Write the terminating quote and NUL character. */
381 buf->len = target - buf->data;
386 * Convert backend's version string into a number.
389 parse_version(const char *versionString)
396 cnt = sscanf(versionString, "%d.%d.%d", &vmaj, &vmin, &vrev);
404 return (100 * vmaj + vmin) * 100 + vrev;
409 * Deconstruct the text representation of a 1-dimensional Postgres array
410 * into individual items.
412 * On success, returns true and sets *itemarray and *nitems to describe
413 * an array of individual strings. On parse failure, returns false;
414 * *itemarray may exist or be NULL.
416 * NOTE: free'ing itemarray is sufficient to deallocate the working storage.
419 parsePGArray(const char *atext, char ***itemarray, int *nitems)
427 * We expect input in the form of "{item,item,item}" where any item is
428 * either raw data, or surrounded by double quotes (in which case embedded
429 * characters including backslashes and quotes are backslashed).
431 * We build the result as an array of pointers followed by the actual
432 * string data, all in one malloc block for convenience of deallocation.
433 * The worst-case storage need is not more than one pointer and one
434 * character for each input character (consider "{,,,,,,,,,,}").
438 inputlen = strlen(atext);
439 if (inputlen < 2 || atext[0] != '{' || atext[inputlen - 1] != '}')
440 return false; /* bad input */
441 items = (char **) malloc(inputlen * (sizeof(char *) + sizeof(char)));
443 return false; /* out of memory */
445 strings = (char *) (items + inputlen);
447 atext++; /* advance over initial '{' */
449 while (*atext != '}')
452 return false; /* premature end of string */
453 items[curitem] = strings;
454 while (*atext != '}' && *atext != ',')
457 return false; /* premature end of string */
459 *strings++ = *atext++; /* copy unquoted data */
462 /* process quoted substring */
464 while (*atext != '"')
467 return false; /* premature end of string */
472 return false; /* premature end of string */
474 *strings++ = *atext++; /* copy quoted data */
484 if (atext[1] != '\0')
485 return false; /* bogus syntax (embedded '}') */
492 * Build GRANT/REVOKE command(s) for an object.
494 * name: the object name, in the form to use in the commands (already quoted)
495 * subname: the sub-object name, if any (already quoted); NULL if none
496 * type: the object type (as seen in GRANT command: must be one of
497 * TABLE, SEQUENCE, FUNCTION, LANGUAGE, SCHEMA, DATABASE, TABLESPACE,
498 * FOREIGN DATA WRAPPER, SERVER, or LARGE OBJECT)
499 * acls: the ACL string fetched from the database
500 * owner: username of object owner (will be passed through fmtId); can be
501 * NULL or empty string to indicate "no owner known"
502 * prefix: string to prefix to each generated command; typically empty
503 * remoteVersion: version of database
505 * Returns TRUE if okay, FALSE if could not parse the acl string.
506 * The resulting commands (if any) are appended to the contents of 'sql'.
508 * Note: when processing a default ACL, prefix is "ALTER DEFAULT PRIVILEGES "
509 * or something similar, and name is an empty string.
511 * Note: beware of passing a fmtId() result directly as 'name' or 'subname',
512 * since this routine uses fmtId() internally.
515 buildACLCommands(const char *name, const char *subname,
516 const char *type, const char *acls, const char *owner,
517 const char *prefix, int remoteVersion,
527 PQExpBuffer firstsql,
529 bool found_owner_privs = false;
531 if (strlen(acls) == 0)
532 return true; /* object has default permissions */
534 /* treat empty-string owner same as NULL */
535 if (owner && *owner == '\0')
538 if (!parsePGArray(acls, &aclitems, &naclitems))
545 grantee = createPQExpBuffer();
546 grantor = createPQExpBuffer();
547 privs = createPQExpBuffer();
548 privswgo = createPQExpBuffer();
551 * At the end, these two will be pasted together to form the result. But
552 * the owner privileges need to go before the other ones to keep the
553 * dependencies valid. In recent versions this is normally the case, but
554 * in old versions they come after the PUBLIC privileges and that results
555 * in problems if we need to run REVOKE on the owner privileges.
557 firstsql = createPQExpBuffer();
558 secondsql = createPQExpBuffer();
561 * Always start with REVOKE ALL FROM PUBLIC, so that we don't have to
562 * wire-in knowledge about the default public privileges for different
565 appendPQExpBuffer(firstsql, "%sREVOKE ALL", prefix);
567 appendPQExpBuffer(firstsql, "(%s)", subname);
568 appendPQExpBuffer(firstsql, " ON %s %s FROM PUBLIC;\n", type, name);
571 * We still need some hacking though to cover the case where new default
572 * public privileges are added in new versions: the REVOKE ALL will revoke
573 * them, leading to behavior different from what the old version had,
574 * which is generally not what's wanted. So add back default privs if the
575 * source database is too old to have had that particular priv.
577 if (remoteVersion < 80200 && strcmp(type, "DATABASE") == 0)
579 /* database CONNECT priv didn't exist before 8.2 */
580 appendPQExpBuffer(firstsql, "%sGRANT CONNECT ON %s %s TO PUBLIC;\n",
584 /* Scan individual ACL items */
585 for (i = 0; i < naclitems; i++)
587 if (!parseAclItem(aclitems[i], type, name, subname, remoteVersion,
588 grantee, grantor, privs, privswgo))
591 if (grantor->len == 0 && owner)
592 printfPQExpBuffer(grantor, "%s", owner);
594 if (privs->len > 0 || privswgo->len > 0)
597 && strcmp(grantee->data, owner) == 0
598 && strcmp(grantor->data, owner) == 0)
600 found_owner_privs = true;
603 * For the owner, the default privilege level is ALL WITH
604 * GRANT OPTION (only ALL prior to 7.4).
606 if (supports_grant_options(remoteVersion)
607 ? strcmp(privswgo->data, "ALL") != 0
608 : strcmp(privs->data, "ALL") != 0)
610 appendPQExpBuffer(firstsql, "%sREVOKE ALL", prefix);
612 appendPQExpBuffer(firstsql, "(%s)", subname);
613 appendPQExpBuffer(firstsql, " ON %s %s FROM %s;\n",
614 type, name, fmtId(grantee->data));
616 appendPQExpBuffer(firstsql,
617 "%sGRANT %s ON %s %s TO %s;\n",
618 prefix, privs->data, type, name,
619 fmtId(grantee->data));
620 if (privswgo->len > 0)
621 appendPQExpBuffer(firstsql,
622 "%sGRANT %s ON %s %s TO %s WITH GRANT OPTION;\n",
623 prefix, privswgo->data, type, name,
624 fmtId(grantee->data));
630 * Otherwise can assume we are starting from no privs.
633 && (!owner || strcmp(owner, grantor->data) != 0))
634 appendPQExpBuffer(secondsql, "SET SESSION AUTHORIZATION %s;\n",
635 fmtId(grantor->data));
639 appendPQExpBuffer(secondsql, "%sGRANT %s ON %s %s TO ",
640 prefix, privs->data, type, name);
641 if (grantee->len == 0)
642 appendPQExpBuffer(secondsql, "PUBLIC;\n");
643 else if (strncmp(grantee->data, "group ",
644 strlen("group ")) == 0)
645 appendPQExpBuffer(secondsql, "GROUP %s;\n",
646 fmtId(grantee->data + strlen("group ")));
648 appendPQExpBuffer(secondsql, "%s;\n", fmtId(grantee->data));
650 if (privswgo->len > 0)
652 appendPQExpBuffer(secondsql, "%sGRANT %s ON %s %s TO ",
653 prefix, privswgo->data, type, name);
654 if (grantee->len == 0)
655 appendPQExpBuffer(secondsql, "PUBLIC");
656 else if (strncmp(grantee->data, "group ",
657 strlen("group ")) == 0)
658 appendPQExpBuffer(secondsql, "GROUP %s",
659 fmtId(grantee->data + strlen("group ")));
661 appendPQExpBuffer(secondsql, "%s", fmtId(grantee->data));
662 appendPQExpBuffer(secondsql, " WITH GRANT OPTION;\n");
666 && (!owner || strcmp(owner, grantor->data) != 0))
667 appendPQExpBuffer(secondsql, "RESET SESSION AUTHORIZATION;\n");
673 * If we didn't find any owner privs, the owner must have revoked 'em all
675 if (!found_owner_privs && owner)
677 appendPQExpBuffer(firstsql, "%sREVOKE ALL", prefix);
679 appendPQExpBuffer(firstsql, "(%s)", subname);
680 appendPQExpBuffer(firstsql, " ON %s %s FROM %s;\n",
681 type, name, fmtId(owner));
684 destroyPQExpBuffer(grantee);
685 destroyPQExpBuffer(grantor);
686 destroyPQExpBuffer(privs);
687 destroyPQExpBuffer(privswgo);
689 appendPQExpBuffer(sql, "%s%s", firstsql->data, secondsql->data);
690 destroyPQExpBuffer(firstsql);
691 destroyPQExpBuffer(secondsql);
699 * Build ALTER DEFAULT PRIVILEGES command(s) for single pg_default_acl entry.
701 * type: the object type (TABLES, FUNCTIONS, etc)
702 * nspname: schema name, or NULL for global default privileges
703 * acls: the ACL string fetched from the database
704 * owner: username of privileges owner (will be passed through fmtId)
705 * remoteVersion: version of database
707 * Returns TRUE if okay, FALSE if could not parse the acl string.
708 * The resulting commands (if any) are appended to the contents of 'sql'.
711 buildDefaultACLCommands(const char *type, const char *nspname,
712 const char *acls, const char *owner,
719 prefix = createPQExpBuffer();
722 * We incorporate the target role directly into the command, rather than
723 * playing around with SET ROLE or anything like that. This is so that a
724 * permissions error leads to nothing happening, rather than changing
725 * default privileges for the wrong user.
727 appendPQExpBuffer(prefix, "ALTER DEFAULT PRIVILEGES FOR ROLE %s ",
730 appendPQExpBuffer(prefix, "IN SCHEMA %s ", fmtId(nspname));
732 result = buildACLCommands("", NULL,
734 prefix->data, remoteVersion,
737 destroyPQExpBuffer(prefix);
743 * This will parse an aclitem string, having the general form
744 * username=privilegecodes/grantor
746 * group groupname=privilegecodes/grantor
747 * (the /grantor part will not be present if pre-7.4 database).
749 * The returned grantee string will be the dequoted username or groupname
750 * (preceded with "group " in the latter case). The returned grantor is
751 * the dequoted grantor name or empty. Privilege characters are decoded
752 * and split between privileges with grant option (privswgo) and without
755 * Note: for cross-version compatibility, it's important to use ALL when
759 parseAclItem(const char *item, const char *type,
760 const char *name, const char *subname, int remoteVersion,
761 PQExpBuffer grantee, PQExpBuffer grantor,
762 PQExpBuffer privs, PQExpBuffer privswgo)
765 bool all_with_go = true;
766 bool all_without_go = true;
775 /* user or group name is string up to = */
776 eqpos = copyAclUserName(grantee, buf);
780 /* grantor may be listed after / */
781 slpos = strchr(eqpos + 1, '/');
785 slpos = copyAclUserName(grantor, slpos);
790 resetPQExpBuffer(grantor);
792 /* privilege codes */
793 #define CONVERT_PRIV(code, keywd) \
795 if ((pos = strchr(eqpos + 1, code))) \
797 if (*(pos + 1) == '*') \
799 AddAcl(privswgo, keywd, subname); \
800 all_without_go = false; \
804 AddAcl(privs, keywd, subname); \
805 all_with_go = false; \
809 all_with_go = all_without_go = false; \
812 resetPQExpBuffer(privs);
813 resetPQExpBuffer(privswgo);
815 if (strcmp(type, "TABLE") == 0 || strcmp(type, "SEQUENCE") == 0 ||
816 strcmp(type, "TABLES") == 0 || strcmp(type, "SEQUENCES") == 0)
818 CONVERT_PRIV('r', "SELECT");
820 if (strcmp(type, "SEQUENCE") == 0 ||
821 strcmp(type, "SEQUENCES") == 0)
823 CONVERT_PRIV('U', "USAGE");
827 CONVERT_PRIV('a', "INSERT");
828 if (remoteVersion >= 70200)
829 CONVERT_PRIV('x', "REFERENCES");
830 /* rest are not applicable to columns */
833 if (remoteVersion >= 70200)
835 CONVERT_PRIV('d', "DELETE");
836 CONVERT_PRIV('t', "TRIGGER");
838 if (remoteVersion >= 80400)
839 CONVERT_PRIV('D', "TRUNCATE");
844 if (remoteVersion >= 70200 ||
845 strcmp(type, "SEQUENCE") == 0 ||
846 strcmp(type, "SEQUENCES") == 0)
847 CONVERT_PRIV('w', "UPDATE");
849 /* 7.0 and 7.1 have a simpler worldview */
850 CONVERT_PRIV('w', "UPDATE,DELETE");
852 else if (strcmp(type, "FUNCTION") == 0 ||
853 strcmp(type, "FUNCTIONS") == 0)
854 CONVERT_PRIV('X', "EXECUTE");
855 else if (strcmp(type, "LANGUAGE") == 0)
856 CONVERT_PRIV('U', "USAGE");
857 else if (strcmp(type, "SCHEMA") == 0)
859 CONVERT_PRIV('C', "CREATE");
860 CONVERT_PRIV('U', "USAGE");
862 else if (strcmp(type, "DATABASE") == 0)
864 CONVERT_PRIV('C', "CREATE");
865 CONVERT_PRIV('c', "CONNECT");
866 CONVERT_PRIV('T', "TEMPORARY");
868 else if (strcmp(type, "TABLESPACE") == 0)
869 CONVERT_PRIV('C', "CREATE");
870 else if (strcmp(type, "FOREIGN DATA WRAPPER") == 0)
871 CONVERT_PRIV('U', "USAGE");
872 else if (strcmp(type, "FOREIGN SERVER") == 0)
873 CONVERT_PRIV('U', "USAGE");
874 else if (strcmp(type, "FOREIGN TABLE") == 0)
875 CONVERT_PRIV('r', "SELECT");
876 else if (strcmp(type, "LARGE OBJECT") == 0)
878 CONVERT_PRIV('r', "SELECT");
879 CONVERT_PRIV('w', "UPDATE");
888 resetPQExpBuffer(privs);
889 printfPQExpBuffer(privswgo, "ALL");
891 appendPQExpBuffer(privswgo, "(%s)", subname);
893 else if (all_without_go)
895 resetPQExpBuffer(privswgo);
896 printfPQExpBuffer(privs, "ALL");
898 appendPQExpBuffer(privs, "(%s)", subname);
907 * Transfer a user or group name starting at *input into the output buffer,
908 * dequoting if needed. Returns a pointer to just past the input name.
909 * The name is taken to end at an unquoted '=' or end of string.
912 copyAclUserName(PQExpBuffer output, char *input)
914 resetPQExpBuffer(output);
916 while (*input && *input != '=')
919 * If user name isn't quoted, then just add it to the output buffer
922 appendPQExpBufferChar(output, *input++);
925 /* Otherwise, it's a quoted username */
927 /* Loop until we come across an unescaped quote */
928 while (!(*input == '"' && *(input + 1) != '"'))
931 return input; /* really a syntax error... */
934 * Quoting convention is to escape " as "". Keep this code in
935 * sync with putid() in backend's acl.c.
937 if (*input == '"' && *(input + 1) == '"')
939 appendPQExpBufferChar(output, *input++);
948 * Append a privilege keyword to a keyword list, inserting comma if needed.
951 AddAcl(PQExpBuffer aclbuf, const char *keyword, const char *subname)
954 appendPQExpBufferChar(aclbuf, ',');
955 appendPQExpBuffer(aclbuf, "%s", keyword);
957 appendPQExpBuffer(aclbuf, "(%s)", subname);
962 * processSQLNamePattern
964 * Scan a wildcard-pattern string and generate appropriate WHERE clauses
965 * to limit the set of objects returned. The WHERE clauses are appended
966 * to the already-partially-constructed query in buf. Returns whether
967 * any clause was added.
969 * conn: connection query will be sent to (consulted for escaping rules).
970 * buf: output parameter.
971 * pattern: user-specified pattern option, or NULL if none ("*" is implied).
972 * have_where: true if caller already emitted "WHERE" (clauses will be ANDed
973 * onto the existing WHERE clause).
974 * force_escape: always quote regexp special characters, even outside
975 * double quotes (else they are quoted only between double quotes).
976 * schemavar: name of query variable to match against a schema-name pattern.
977 * Can be NULL if no schema.
978 * namevar: name of query variable to match against an object-name pattern.
979 * altnamevar: NULL, or name of an alternative variable to match against name.
980 * visibilityrule: clause to use if we want to restrict to visible objects
981 * (for example, "pg_catalog.pg_table_is_visible(p.oid)"). Can be NULL.
983 * Formatting note: the text already present in buf should end with a newline.
984 * The appended text, if any, will end with one too.
987 processSQLNamePattern(PGconn *conn, PQExpBuffer buf, const char *pattern,
988 bool have_where, bool force_escape,
989 const char *schemavar, const char *namevar,
990 const char *altnamevar, const char *visibilityrule)
992 PQExpBufferData schemabuf;
993 PQExpBufferData namebuf;
994 int encoding = PQclientEncoding(conn);
998 bool added_clause = false;
1000 #define WHEREAND() \
1001 (appendPQExpBufferStr(buf, have_where ? " AND " : "WHERE "), \
1002 have_where = true, added_clause = true)
1004 if (pattern == NULL)
1006 /* Default: select all visible objects */
1010 appendPQExpBuffer(buf, "%s\n", visibilityrule);
1012 return added_clause;
1015 initPQExpBuffer(&schemabuf);
1016 initPQExpBuffer(&namebuf);
1019 * Parse the pattern, converting quotes and lower-casing unquoted letters.
1020 * Also, adjust shell-style wildcard characters into regexp notation.
1022 * We surround the pattern with "^(...)$" to force it to match the whole
1023 * string, as per SQL practice. We have to have parens in case the string
1024 * contains "|", else the "^" and "$" will be bound into the first and
1025 * last alternatives which is not what we want.
1027 * Note: the result of this pass is the actual regexp pattern(s) we want
1028 * to execute. Quoting/escaping into SQL literal format will be done
1029 * below using appendStringLiteralConn().
1031 appendPQExpBufferStr(&namebuf, "^(");
1042 if (inquotes && cp[1] == '"')
1044 /* emit one quote, stay in inquotes mode */
1045 appendPQExpBufferChar(&namebuf, '"');
1049 inquotes = !inquotes;
1052 else if (!inquotes && isupper((unsigned char) ch))
1054 appendPQExpBufferChar(&namebuf,
1055 pg_tolower((unsigned char) ch));
1058 else if (!inquotes && ch == '*')
1060 appendPQExpBufferStr(&namebuf, ".*");
1063 else if (!inquotes && ch == '?')
1065 appendPQExpBufferChar(&namebuf, '.');
1068 else if (!inquotes && ch == '.')
1070 /* Found schema/name separator, move current pattern to schema */
1071 resetPQExpBuffer(&schemabuf);
1072 appendPQExpBufferStr(&schemabuf, namebuf.data);
1073 resetPQExpBuffer(&namebuf);
1074 appendPQExpBufferStr(&namebuf, "^(");
1080 * Dollar is always quoted, whether inside quotes or not. The
1081 * reason is that it's allowed in SQL identifiers, so there's a
1082 * significant use-case for treating it literally, while because
1083 * we anchor the pattern automatically there is no use-case for
1084 * having it possess its regexp meaning.
1086 appendPQExpBufferStr(&namebuf, "\\$");
1092 * Ordinary data character, transfer to pattern
1094 * Inside double quotes, or at all times if force_escape is true,
1095 * quote regexp special characters with a backslash to avoid
1096 * regexp errors. Outside quotes, however, let them pass through
1097 * as-is; this lets knowledgeable users build regexp expressions
1098 * that are more powerful than shell-style patterns.
1100 if ((inquotes || force_escape) &&
1101 strchr("|*+?()[]{}.^$\\", ch))
1102 appendPQExpBufferChar(&namebuf, '\\');
1103 i = PQmblen(cp, encoding);
1106 appendPQExpBufferChar(&namebuf, *cp);
1113 * Now decide what we need to emit. Note there will be a leading "^(" in
1114 * the patterns in any case.
1116 if (namebuf.len > 2)
1118 /* We have a name pattern, so constrain the namevar(s) */
1120 appendPQExpBufferStr(&namebuf, ")$");
1121 /* Optimize away a "*" pattern */
1122 if (strcmp(namebuf.data, "^(.*)$") != 0)
1127 appendPQExpBuffer(buf, "(%s ~ ", namevar);
1128 appendStringLiteralConn(buf, namebuf.data, conn);
1129 appendPQExpBuffer(buf, "\n OR %s ~ ", altnamevar);
1130 appendStringLiteralConn(buf, namebuf.data, conn);
1131 appendPQExpBufferStr(buf, ")\n");
1135 appendPQExpBuffer(buf, "%s ~ ", namevar);
1136 appendStringLiteralConn(buf, namebuf.data, conn);
1137 appendPQExpBufferChar(buf, '\n');
1142 if (schemabuf.len > 2)
1144 /* We have a schema pattern, so constrain the schemavar */
1146 appendPQExpBufferStr(&schemabuf, ")$");
1147 /* Optimize away a "*" pattern */
1148 if (strcmp(schemabuf.data, "^(.*)$") != 0 && schemavar)
1151 appendPQExpBuffer(buf, "%s ~ ", schemavar);
1152 appendStringLiteralConn(buf, schemabuf.data, conn);
1153 appendPQExpBufferChar(buf, '\n');
1158 /* No schema pattern given, so select only visible objects */
1162 appendPQExpBuffer(buf, "%s\n", visibilityrule);
1166 termPQExpBuffer(&schemabuf);
1167 termPQExpBuffer(&namebuf);
1169 return added_clause;
1174 * buildShSecLabelQuery
1176 * Build a query to retrieve security labels for a shared object.
1179 buildShSecLabelQuery(PGconn *conn, const char *catalog_name, uint32 objectId,
1182 appendPQExpBuffer(sql,
1183 "SELECT provider, label FROM pg_catalog.pg_shseclabel "
1184 "WHERE classoid = '%s'::pg_catalog.regclass AND "
1185 "objoid = %u", catalog_name, objectId);
1191 * Format security label data retrieved by the query generated in
1192 * buildShSecLabelQuery.
1195 emitShSecLabels(PGconn *conn, PGresult *res, PQExpBuffer buffer,
1196 const char *target, const char *objname)
1200 for (i = 0; i < PQntuples(res); i++)
1202 char *provider = PQgetvalue(res, i, 0);
1203 char *label = PQgetvalue(res, i, 1);
1205 /* must use fmtId result before calling it again */
1206 appendPQExpBuffer(buffer,
1207 "SECURITY LABEL FOR %s ON %s",
1208 fmtId(provider), target);
1209 appendPQExpBuffer(buffer,
1212 appendStringLiteralConn(buffer, label, conn);
1213 appendPQExpBuffer(buffer, ";\n");
1219 * Write a printf-style message to stderr.
1221 * The program name is prepended, if "progname" has been set.
1222 * Also, if modulename isn't NULL, that's included too.
1223 * Note that we'll try to translate the modulename and the fmt string.
1226 write_msg(const char *modulename, const char *fmt,...)
1231 vwrite_msg(modulename, fmt, ap);
1236 * As write_msg, but pass a va_list not variable arguments.
1239 vwrite_msg(const char *modulename, const char *fmt, va_list ap)
1244 fprintf(stderr, "%s: [%s] ", progname, _(modulename));
1246 fprintf(stderr, "%s: ", progname);
1248 vfprintf(stderr, _(fmt), ap);
1253 * Fail and die, with a message to stderr. Parameters as for write_msg.
1256 exit_horribly(const char *modulename, const char *fmt,...)
1261 vwrite_msg(modulename, fmt, ap);
1268 * Set the bitmask in dumpSections according to the first argument.
1269 * dumpSections is initialised as DUMP_UNSECTIONED by pg_dump and
1270 * pg_restore so they can know if this has even been called.
1274 set_section (const char *arg, int *dumpSections)
1276 /* if this is the first, clear all the bits */
1277 if (*dumpSections == DUMP_UNSECTIONED)
1280 if (strcmp(arg,"pre-data") == 0)
1281 *dumpSections |= DUMP_PRE_DATA;
1282 else if (strcmp(arg,"data") == 0)
1283 *dumpSections |= DUMP_DATA;
1284 else if (strcmp(arg,"post-data") == 0)
1285 *dumpSections |= DUMP_POST_DATA;
1288 fprintf(stderr, _("%s: unknown section name \"%s\")\n"),
1290 fprintf(stderr, _("Try \"%s --help\" for more information.\n"),