⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dumputils.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 2 页
字号:
/*------------------------------------------------------------------------- * * Utility routines for SQL dumping *	Basically this is stuff that is useful in both pg_dump and pg_dumpall. * * * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * $PostgreSQL: pgsql/src/bin/pg_dump/dumputils.c,v 1.20.2.1 2005/11/22 18:23:26 momjian Exp $ * *------------------------------------------------------------------------- */#include "postgres_fe.h"#include "dumputils.h"#include "parser/keywords.h"#define supports_grant_options(version) ((version) >= 70400)static bool parseAclItem(const char *item, const char *type, const char *name,			 int remoteVersion,			 PQExpBuffer grantee, PQExpBuffer grantor,			 PQExpBuffer privs, PQExpBuffer privswgo);static char *copyAclUserName(PQExpBuffer output, char *input);static void AddAcl(PQExpBuffer aclbuf, const char *keyword);/* *	Quotes input string if it's not a legitimate SQL identifier as-is. * *	Note that the returned string must be used before calling fmtId again, *	since we re-use the same return buffer each time.  Non-reentrant but *	avoids memory leakage. */const char *fmtId(const char *rawid){	static PQExpBuffer id_return = NULL;	const char *cp;	bool		need_quotes = false;	if (id_return)				/* first time through? */		resetPQExpBuffer(id_return);	else		id_return = createPQExpBuffer();	/*	 * These checks need to match the identifier production in scan.l. Don't	 * use islower() etc.	 */	if (ScanKeywordLookup(rawid))		need_quotes = true;	/* slightly different rules for first character */	else if (!((rawid[0] >= 'a' && rawid[0] <= 'z') || rawid[0] == '_'))		need_quotes = true;	else	{		/* otherwise check the entire string */		for (cp = rawid; *cp; cp++)		{			if (!((*cp >= 'a' && *cp <= 'z')				  || (*cp >= '0' && *cp <= '9')				  || (*cp == '_')))			{				need_quotes = true;				break;			}		}	}	if (!need_quotes)	{		/* no quoting needed */		appendPQExpBufferStr(id_return, rawid);	}	else	{		appendPQExpBufferChar(id_return, '\"');		for (cp = rawid; *cp; cp++)		{			/*			 * Did we find a double-quote in the string? Then make this a			 * double double-quote per SQL99. Before, we put in a			 * backslash/double-quote pair. - thomas 2000-08-05			 */			if (*cp == '\"')				appendPQExpBufferChar(id_return, '\"');			appendPQExpBufferChar(id_return, *cp);		}		appendPQExpBufferChar(id_return, '\"');	}	return id_return->data;}/* * Convert a string value to an SQL string literal and append it to * the given buffer. * * Special characters are escaped. Quote mark ' goes to '' per SQL * standard, other stuff goes to \ sequences.  If escapeAll is false, * whitespace characters are not escaped (tabs, newlines, etc.).  This * is appropriate for dump file output. */voidappendStringLiteral(PQExpBuffer buf, const char *str, bool escapeAll){	char		ch;	const char *p;	for (p = str; *p; p++)	{		ch = *p;		if (ch == '\\' ||			((unsigned char) ch < (unsigned char) ' ' &&			 (escapeAll ||			  (ch != '\t' && ch != '\n' && ch != '\v' &&			   ch != '\f' && ch != '\r'))))		{			appendPQExpBufferChar(buf, ESCAPE_STRING_SYNTAX);			break;		}	}	appendPQExpBufferChar(buf, '\'');	for (p = str; *p; p++)	{		ch = *p;		if (SQL_STR_DOUBLE(ch))		{			appendPQExpBufferChar(buf, ch);			appendPQExpBufferChar(buf, ch);		}		else if ((unsigned char) ch < (unsigned char) ' ' &&				 (escapeAll ||				  (ch != '\t' && ch != '\n' && ch != '\v' &&				   ch != '\f' && ch != '\r')))		{			/*			 * generate octal escape for control chars other than whitespace			 */			appendPQExpBufferChar(buf, '\\');			appendPQExpBufferChar(buf, ((ch >> 6) & 3) + '0');			appendPQExpBufferChar(buf, ((ch >> 3) & 7) + '0');			appendPQExpBufferChar(buf, (ch & 7) + '0');		}		else			appendPQExpBufferChar(buf, ch);	}	appendPQExpBufferChar(buf, '\'');}/* * Convert a string value to a dollar quoted literal and append it to * the given buffer. If the dqprefix parameter is not NULL then the * dollar quote delimiter will begin with that (after the opening $). * * No escaping is done at all on str, in compliance with the rules * for parsing dollar quoted strings. */voidappendStringLiteralDQ(PQExpBuffer buf, const char *str, const char *dqprefix){	static const char suffixes[] = "_XXXXXXX";	int			nextchar = 0;	PQExpBuffer delimBuf = createPQExpBuffer();	/* start with $ + dqprefix if not NULL */	appendPQExpBufferChar(delimBuf, '$');	if (dqprefix)		appendPQExpBufferStr(delimBuf, dqprefix);	/*	 * Make sure we choose a delimiter which (without the trailing $) is not	 * present in the string being quoted. We don't check with the trailing $	 * because a string ending in $foo must not be quoted with $foo$.	 */	while (strstr(str, delimBuf->data) != NULL)	{		appendPQExpBufferChar(delimBuf, suffixes[nextchar++]);		nextchar %= sizeof(suffixes) - 1;	}	/* add trailing $ */	appendPQExpBufferChar(delimBuf, '$');	/* quote it and we are all done */	appendPQExpBufferStr(buf, delimBuf->data);	appendPQExpBufferStr(buf, str);	appendPQExpBufferStr(buf, delimBuf->data);	destroyPQExpBuffer(delimBuf);}/* * Use dollar quoting if the string to be quoted contains ' or \, * otherwise use standard quoting. */voidappendStringLiteralDQOpt(PQExpBuffer buf, const char *str,						 bool escapeAll, const char *dqprefix){	if (strchr(str, '\'') == NULL && strchr(str, '\\') == NULL)		appendStringLiteral(buf, str, escapeAll);	else		appendStringLiteralDQ(buf, str, dqprefix);}/* * Convert backend's version string into a number. */intparse_version(const char *versionString){	int			cnt;	int			vmaj,				vmin,				vrev;	cnt = sscanf(versionString, "%d.%d.%d", &vmaj, &vmin, &vrev);	if (cnt < 2)		return -1;	if (cnt == 2)		vrev = 0;	return (100 * vmaj + vmin) * 100 + vrev;}/* * Deconstruct the text representation of a 1-dimensional Postgres array * into individual items. * * On success, returns true and sets *itemarray and *nitems to describe * an array of individual strings.	On parse failure, returns false; * *itemarray may exist or be NULL. * * NOTE: free'ing itemarray is sufficient to deallocate the working storage. */boolparsePGArray(const char *atext, char ***itemarray, int *nitems){	int			inputlen;	char	  **items;	char	   *strings;	int			curitem;	/*	 * We expect input in the form of "{item,item,item}" where any item is	 * either raw data, or surrounded by double quotes (in which case embedded	 * characters including backslashes and quotes are backslashed).	 *	 * We build the result as an array of pointers followed by the actual	 * string data, all in one malloc block for convenience of deallocation.	 * The worst-case storage need is not more than one pointer and one	 * character for each input character (consider "{,,,,,,,,,,}").	 */	*itemarray = NULL;	*nitems = 0;	inputlen = strlen(atext);	if (inputlen < 2 || atext[0] != '{' || atext[inputlen - 1] != '}')		return false;			/* bad input */	items = (char **) malloc(inputlen * (sizeof(char *) + sizeof(char)));	if (items == NULL)		return false;			/* out of memory */	*itemarray = items;	strings = (char *) (items + inputlen);	atext++;					/* advance over initial '{' */	curitem = 0;	while (*atext != '}')	{		if (*atext == '\0')			return false;		/* premature end of string */		items[curitem] = strings;		while (*atext != '}' && *atext != ',')		{			if (*atext == '\0')				return false;	/* premature end of string */			if (*atext != '"')				*strings++ = *atext++;	/* copy unquoted data */			else			{				/* process quoted substring */				atext++;				while (*atext != '"')				{					if (*atext == '\0')						return false;	/* premature end of string */					if (*atext == '\\')					{						atext++;						if (*atext == '\0')							return false;		/* premature end of string */					}					*strings++ = *atext++;		/* copy quoted data */				}				atext++;			}		}		*strings++ = '\0';		if (*atext == ',')			atext++;		curitem++;	}	if (atext[1] != '\0')		return false;			/* bogus syntax (embedded '}') */	*nitems = curitem;	return true;}/* * Build GRANT/REVOKE command(s) for an object. * *	name: the object name, in the form to use in the commands (already quoted) *	type: the object type (as seen in GRANT command: must be one of *		TABLE, FUNCTION, LANGUAGE, or SCHEMA, or DATABASE) *	acls: the ACL string fetched from the database *	owner: username of object owner (will be passed through fmtId), or NULL *	remoteVersion: version of database * * Returns TRUE if okay, FALSE if could not parse the acl string. * The resulting commands (if any) are appended to the contents of 'sql'. * * Note: beware of passing fmtId() result as 'name', since this routine

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -