|
2 | 2 | *
|
3 | 3 | * Utility routines for SQL dumping
|
4 | 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/ ... |
5 | 6 | *
|
6 | 7 | *
|
7 | 8 | * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
|
8 | 9 | * Portions Copyright (c) 1994, Regents of the University of California
|
9 | 10 | *
|
10 |
| - * $PostgreSQL: pgsql/src/bin/pg_dump/dumputils.c,v 1.32 2006/10/04 00:30:05 momjian Exp $ |
| 11 | + * $PostgreSQL: pgsql/src/bin/pg_dump/dumputils.c,v 1.33 2006/10/09 23:30:33 tgl Exp $ |
11 | 12 | *
|
12 | 13 | *-------------------------------------------------------------------------
|
13 | 14 | */
|
14 |
| - |
15 | 15 | #include"postgres_fe.h"
|
16 | 16 |
|
| 17 | +#include<ctype.h> |
| 18 | + |
17 | 19 | #include"dumputils.h"
|
18 | 20 |
|
19 | 21 | #include"parser/keywords.h"
|
@@ -570,6 +572,8 @@ parseAclItem(const char *item, const char *type, const char *name,
|
570 | 572 | char*pos;
|
571 | 573 |
|
572 | 574 | buf=strdup(item);
|
| 575 | +if (!buf) |
| 576 | +return false; |
573 | 577 |
|
574 | 578 | /* user or group name is string up to = */
|
575 | 579 | eqpos=copyAclUserName(grantee,buf);
|
@@ -726,3 +730,200 @@ AddAcl(PQExpBuffer aclbuf, const char *keyword)
|
726 | 730 | appendPQExpBufferChar(aclbuf,',');
|
727 | 731 | appendPQExpBuffer(aclbuf,"%s",keyword);
|
728 | 732 | }
|
| 733 | + |
| 734 | + |
| 735 | +/* |
| 736 | + * processSQLNamePattern |
| 737 | + * |
| 738 | + * Scan a wildcard-pattern string and generate appropriate WHERE clauses |
| 739 | + * to limit the set of objects returned. The WHERE clauses are appended |
| 740 | + * to the already-partially-constructed query in buf. |
| 741 | + * |
| 742 | + * conn: connection query will be sent to (consulted for escaping rules). |
| 743 | + * buf: output parameter. |
| 744 | + * pattern: user-specified pattern option, or NULL if none ("*" is implied). |
| 745 | + * have_where: true if caller already emitted "WHERE" (clauses will be ANDed |
| 746 | + * onto the existing WHERE clause). |
| 747 | + * force_escape: always quote regexp special characters, even outside |
| 748 | + * double quotes (else they are quoted only between double quotes). |
| 749 | + * schemavar: name of query variable to match against a schema-name pattern. |
| 750 | + * Can be NULL if no schema. |
| 751 | + * namevar: name of query variable to match against an object-name pattern. |
| 752 | + * altnamevar: NULL, or name of an alternate variable to match against name. |
| 753 | + * visibilityrule: clause to use if we want to restrict to visible objects |
| 754 | + * (for example, "pg_catalog.pg_table_is_visible(p.oid)").Can be NULL. |
| 755 | + * |
| 756 | + * Formatting note: the text already present in buf should end with a newline. |
| 757 | + * The appended text, if any, will end with one too. |
| 758 | + */ |
| 759 | +void |
| 760 | +processSQLNamePattern(PGconn*conn,PQExpBufferbuf,constchar*pattern, |
| 761 | +boolhave_where,boolforce_escape, |
| 762 | +constchar*schemavar,constchar*namevar, |
| 763 | +constchar*altnamevar,constchar*visibilityrule) |
| 764 | +{ |
| 765 | +PQExpBufferDataschemabuf; |
| 766 | +PQExpBufferDatanamebuf; |
| 767 | +intencoding=PQclientEncoding(conn); |
| 768 | +boolinquotes; |
| 769 | +constchar*cp; |
| 770 | +inti; |
| 771 | + |
| 772 | +#defineWHEREAND() \ |
| 773 | +(appendPQExpBufferStr(buf, have_where ? " AND " : "WHERE "), have_where = true) |
| 774 | + |
| 775 | +if (pattern==NULL) |
| 776 | +{ |
| 777 | +/* Default: select all visible objects */ |
| 778 | +if (visibilityrule) |
| 779 | +{ |
| 780 | +WHEREAND(); |
| 781 | +appendPQExpBuffer(buf,"%s\n",visibilityrule); |
| 782 | +} |
| 783 | +return; |
| 784 | +} |
| 785 | + |
| 786 | +initPQExpBuffer(&schemabuf); |
| 787 | +initPQExpBuffer(&namebuf); |
| 788 | + |
| 789 | +/* |
| 790 | + * Parse the pattern, converting quotes and lower-casing unquoted letters. |
| 791 | + * Also, adjust shell-style wildcard characters into regexp notation. |
| 792 | + * |
| 793 | + * We surround the pattern with "^(...)$" to force it to match the whole |
| 794 | + * string, as per SQL practice. We have to have parens in case the string |
| 795 | + * contains "|", else the "^" and "$" will be bound into the first and |
| 796 | + * last alternatives which is not what we want. |
| 797 | + * |
| 798 | + * Note: the result of this pass is the actual regexp pattern(s) we want to |
| 799 | + * execute. Quoting/escaping into SQL literal format will be done below |
| 800 | + * using appendStringLiteralConn(). |
| 801 | + */ |
| 802 | +appendPQExpBufferStr(&namebuf,"^("); |
| 803 | + |
| 804 | +inquotes= false; |
| 805 | +cp=pattern; |
| 806 | + |
| 807 | +while (*cp) |
| 808 | +{ |
| 809 | +charch=*cp; |
| 810 | + |
| 811 | +if (ch=='"') |
| 812 | +{ |
| 813 | +if (inquotes&&cp[1]=='"') |
| 814 | +{ |
| 815 | +/* emit one quote, stay in inquotes mode */ |
| 816 | +appendPQExpBufferChar(&namebuf,'"'); |
| 817 | +cp++; |
| 818 | +} |
| 819 | +else |
| 820 | +inquotes= !inquotes; |
| 821 | +cp++; |
| 822 | +} |
| 823 | +elseif (!inquotes&&isupper((unsignedchar)ch)) |
| 824 | +{ |
| 825 | +appendPQExpBufferChar(&namebuf, |
| 826 | +pg_tolower((unsignedchar)ch)); |
| 827 | +cp++; |
| 828 | +} |
| 829 | +elseif (!inquotes&&ch=='*') |
| 830 | +{ |
| 831 | +appendPQExpBufferStr(&namebuf,".*"); |
| 832 | +cp++; |
| 833 | +} |
| 834 | +elseif (!inquotes&&ch=='?') |
| 835 | +{ |
| 836 | +appendPQExpBufferChar(&namebuf,'.'); |
| 837 | +cp++; |
| 838 | +} |
| 839 | +elseif (!inquotes&&ch=='.') |
| 840 | +{ |
| 841 | +/* Found schema/name separator, move current pattern to schema */ |
| 842 | +resetPQExpBuffer(&schemabuf); |
| 843 | +appendPQExpBufferStr(&schemabuf,namebuf.data); |
| 844 | +resetPQExpBuffer(&namebuf); |
| 845 | +appendPQExpBufferStr(&namebuf,"^("); |
| 846 | +cp++; |
| 847 | +} |
| 848 | +else |
| 849 | +{ |
| 850 | +/* |
| 851 | + * Ordinary data character, transfer to pattern |
| 852 | + * |
| 853 | + * Inside double quotes, or at all times if force_escape is true, |
| 854 | + * quote regexp special characters with a backslash to avoid |
| 855 | + * regexp errors. Outside quotes, however, let them pass through |
| 856 | + * as-is; this lets knowledgeable users build regexp expressions |
| 857 | + * that are more powerful than shell-style patterns. |
| 858 | + */ |
| 859 | +if ((inquotes||force_escape)&& |
| 860 | +strchr("|*+?()[]{}.^$\\",ch)) |
| 861 | +appendPQExpBufferChar(&namebuf,'\\'); |
| 862 | +i=PQmblen(cp,encoding); |
| 863 | +while (i--&&*cp) |
| 864 | +{ |
| 865 | +appendPQExpBufferChar(&namebuf,*cp); |
| 866 | +cp++; |
| 867 | +} |
| 868 | +} |
| 869 | +} |
| 870 | + |
| 871 | +/* |
| 872 | + * Now decide what we need to emit. Note there will be a leading "^(" |
| 873 | + * in the patterns in any case. |
| 874 | + */ |
| 875 | +if (namebuf.len>2) |
| 876 | +{ |
| 877 | +/* We have a name pattern, so constrain the namevar(s) */ |
| 878 | + |
| 879 | +appendPQExpBufferStr(&namebuf,")$"); |
| 880 | +/* Optimize away a "*" pattern */ |
| 881 | +if (strcmp(namebuf.data,"^(.*)$")!=0) |
| 882 | +{ |
| 883 | +WHEREAND(); |
| 884 | +if (altnamevar) |
| 885 | +{ |
| 886 | +appendPQExpBuffer(buf,"(%s ~ ",namevar); |
| 887 | +appendStringLiteralConn(buf,namebuf.data,conn); |
| 888 | +appendPQExpBuffer(buf,"\n OR %s ~ ",altnamevar); |
| 889 | +appendStringLiteralConn(buf,namebuf.data,conn); |
| 890 | +appendPQExpBufferStr(buf,")\n"); |
| 891 | +} |
| 892 | +else |
| 893 | +{ |
| 894 | +appendPQExpBuffer(buf,"%s ~ ",namevar); |
| 895 | +appendStringLiteralConn(buf,namebuf.data,conn); |
| 896 | +appendPQExpBufferChar(buf,'\n'); |
| 897 | +} |
| 898 | +} |
| 899 | +} |
| 900 | + |
| 901 | +if (schemabuf.len>2) |
| 902 | +{ |
| 903 | +/* We have a schema pattern, so constrain the schemavar */ |
| 904 | + |
| 905 | +appendPQExpBufferStr(&schemabuf,")$"); |
| 906 | +/* Optimize away a "*" pattern */ |
| 907 | +if (strcmp(schemabuf.data,"^(.*)$")!=0&&schemavar) |
| 908 | +{ |
| 909 | +WHEREAND(); |
| 910 | +appendPQExpBuffer(buf,"%s ~ ",schemavar); |
| 911 | +appendStringLiteralConn(buf,schemabuf.data,conn); |
| 912 | +appendPQExpBufferChar(buf,'\n'); |
| 913 | +} |
| 914 | +} |
| 915 | +else |
| 916 | +{ |
| 917 | +/* No schema pattern given, so select only visible objects */ |
| 918 | +if (visibilityrule) |
| 919 | +{ |
| 920 | +WHEREAND(); |
| 921 | +appendPQExpBuffer(buf,"%s\n",visibilityrule); |
| 922 | +} |
| 923 | +} |
| 924 | + |
| 925 | +termPQExpBuffer(&schemabuf); |
| 926 | +termPQExpBuffer(&namebuf); |
| 927 | + |
| 928 | +#undef WHEREAND |
| 929 | +} |