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

📄 varlena.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 5 页
字号:
	/* now null pad to full length... */	while (len < NAMEDATALEN)	{		*(NameStr(*result) + len) = '\0';		len++;	}	PG_RETURN_NAME(result);}/* name_text() * Converts a Name type to a text type. */Datumname_text(PG_FUNCTION_ARGS){	Name		s = PG_GETARG_NAME(0);	text	   *result;	int			len;	len = strlen(NameStr(*s));#ifdef STRINGDEBUG	printf("text- convert string length %d (%d) ->%d\n",		   VARSIZE(s) - VARHDRSZ, VARSIZE(s), len);#endif	result = palloc(VARHDRSZ + len);	VARATT_SIZEP(result) = VARHDRSZ + len;	memcpy(VARDATA(result), NameStr(*s), len);	PG_RETURN_TEXT_P(result);}/* * textToQualifiedNameList - convert a text object to list of names * * This implements the input parsing needed by nextval() and other * functions that take a text parameter representing a qualified name. * We split the name at dots, downcase if not double-quoted, and * truncate names if they're too long. */List *textToQualifiedNameList(text *textval){	char	   *rawname;	List	   *result = NIL;	List	   *namelist;	ListCell   *l;	/* Convert to C string (handles possible detoasting). */	/* Note we rely on being able to modify rawname below. */	rawname = DatumGetCString(DirectFunctionCall1(textout,												  PointerGetDatum(textval)));	if (!SplitIdentifierString(rawname, '.', &namelist))		ereport(ERROR,				(errcode(ERRCODE_INVALID_NAME),				 errmsg("invalid name syntax")));	if (namelist == NIL)		ereport(ERROR,				(errcode(ERRCODE_INVALID_NAME),				 errmsg("invalid name syntax")));	foreach(l, namelist)	{		char	   *curname = (char *) lfirst(l);		result = lappend(result, makeString(pstrdup(curname)));	}	pfree(rawname);	list_free(namelist);	return result;}/* * SplitIdentifierString --- parse a string containing identifiers * * This is the guts of textToQualifiedNameList, and is exported for use in * other situations such as parsing GUC variables.	In the GUC case, it's * important to avoid memory leaks, so the API is designed to minimize the * amount of stuff that needs to be allocated and freed. * * Inputs: *	rawstring: the input string; must be overwritable!	On return, it's *			   been modified to contain the separated identifiers. *	separator: the separator punctuation expected between identifiers *			   (typically '.' or ',').	Whitespace may also appear around *			   identifiers. * Outputs: *	namelist: filled with a palloc'd list of pointers to identifiers within *			  rawstring.  Caller should list_free() this even on error return. * * Returns TRUE if okay, FALSE if there is a syntax error in the string. * * Note that an empty string is considered okay here, though not in * textToQualifiedNameList. */boolSplitIdentifierString(char *rawstring, char separator,					  List **namelist){	char	   *nextp = rawstring;	bool		done = false;	*namelist = NIL;	while (isspace((unsigned char) *nextp))		nextp++;				/* skip leading whitespace */	if (*nextp == '\0')		return true;			/* allow empty string */	/* At the top of the loop, we are at start of a new identifier. */	do	{		char	   *curname;		char	   *endp;		if (*nextp == '\"')		{			/* Quoted name --- collapse quote-quote pairs, no downcasing */			curname = nextp + 1;			for (;;)			{				endp = strchr(nextp + 1, '\"');				if (endp == NULL)					return false;		/* mismatched quotes */				if (endp[1] != '\"')					break;		/* found end of quoted name */				/* Collapse adjacent quotes into one quote, and look again */				memmove(endp, endp + 1, strlen(endp));				nextp = endp;			}			/* endp now points at the terminating quote */			nextp = endp + 1;		}		else		{			/* Unquoted name --- extends to separator or whitespace */			char	   *downname;			int			len;			curname = nextp;			while (*nextp && *nextp != separator &&				   !isspace((unsigned char) *nextp))				nextp++;			endp = nextp;			if (curname == nextp)				return false;	/* empty unquoted name not allowed */			/*			 * Downcase the identifier, using same code as main lexer does.			 *			 * XXX because we want to overwrite the input in-place, we cannot			 * support a downcasing transformation that increases the string			 * length.	This is not a problem given the current implementation			 * of downcase_truncate_identifier, but we'll probably have to do			 * something about this someday.			 */			len = endp - curname;			downname = downcase_truncate_identifier(curname, len, false);			Assert(strlen(downname) <= len);			strncpy(curname, downname, len);			pfree(downname);		}		while (isspace((unsigned char) *nextp))			nextp++;			/* skip trailing whitespace */		if (*nextp == separator)		{			nextp++;			while (isspace((unsigned char) *nextp))				nextp++;		/* skip leading whitespace for next */			/* we expect another name, so done remains false */		}		else if (*nextp == '\0')			done = true;		else			return false;		/* invalid syntax */		/* Now safe to overwrite separator with a null */		*endp = '\0';		/* Truncate name if it's overlength */		truncate_identifier(curname, strlen(curname), false);		/*		 * Finished isolating current name --- add it to list		 */		*namelist = lappend(*namelist, curname);		/* Loop back if we didn't reach end of string */	} while (!done);	return true;}/***************************************************************************** *	Comparison Functions used for bytea * * Note: btree indexes need these routines not to leak memory; therefore, * be careful to free working copies of toasted datums.  Most places don't * need to be so careful. *****************************************************************************/Datumbyteaeq(PG_FUNCTION_ARGS){	bytea	   *arg1 = PG_GETARG_BYTEA_P(0);	bytea	   *arg2 = PG_GETARG_BYTEA_P(1);	int			len1,				len2;	bool		result;	len1 = VARSIZE(arg1) - VARHDRSZ;	len2 = VARSIZE(arg2) - VARHDRSZ;	/* fast path for different-length inputs */	if (len1 != len2)		result = false;	else		result = (memcmp(VARDATA(arg1), VARDATA(arg2), len1) == 0);	PG_FREE_IF_COPY(arg1, 0);	PG_FREE_IF_COPY(arg2, 1);	PG_RETURN_BOOL(result);}Datumbyteane(PG_FUNCTION_ARGS){	bytea	   *arg1 = PG_GETARG_BYTEA_P(0);	bytea	   *arg2 = PG_GETARG_BYTEA_P(1);	int			len1,				len2;	bool		result;	len1 = VARSIZE(arg1) - VARHDRSZ;	len2 = VARSIZE(arg2) - VARHDRSZ;	/* fast path for different-length inputs */	if (len1 != len2)		result = true;	else		result = (memcmp(VARDATA(arg1), VARDATA(arg2), len1) != 0);	PG_FREE_IF_COPY(arg1, 0);	PG_FREE_IF_COPY(arg2, 1);	PG_RETURN_BOOL(result);}Datumbytealt(PG_FUNCTION_ARGS){	bytea	   *arg1 = PG_GETARG_BYTEA_P(0);	bytea	   *arg2 = PG_GETARG_BYTEA_P(1);	int			len1,				len2;	int			cmp;	len1 = VARSIZE(arg1) - VARHDRSZ;	len2 = VARSIZE(arg2) - VARHDRSZ;	cmp = memcmp(VARDATA(arg1), VARDATA(arg2), Min(len1, len2));	PG_FREE_IF_COPY(arg1, 0);	PG_FREE_IF_COPY(arg2, 1);	PG_RETURN_BOOL((cmp < 0) || ((cmp == 0) && (len1 < len2)));}Datumbyteale(PG_FUNCTION_ARGS){	bytea	   *arg1 = PG_GETARG_BYTEA_P(0);	bytea	   *arg2 = PG_GETARG_BYTEA_P(1);	int			len1,				len2;	int			cmp;	len1 = VARSIZE(arg1) - VARHDRSZ;	len2 = VARSIZE(arg2) - VARHDRSZ;	cmp = memcmp(VARDATA(arg1), VARDATA(arg2), Min(len1, len2));	PG_FREE_IF_COPY(arg1, 0);	PG_FREE_IF_COPY(arg2, 1);	PG_RETURN_BOOL((cmp < 0) || ((cmp == 0) && (len1 <= len2)));}Datumbyteagt(PG_FUNCTION_ARGS){	bytea	   *arg1 = PG_GETARG_BYTEA_P(0);	bytea	   *arg2 = PG_GETARG_BYTEA_P(1);	int			len1,				len2;	int			cmp;	len1 = VARSIZE(arg1) - VARHDRSZ;	len2 = VARSIZE(arg2) - VARHDRSZ;	cmp = memcmp(VARDATA(arg1), VARDATA(arg2), Min(len1, len2));	PG_FREE_IF_COPY(arg1, 0);	PG_FREE_IF_COPY(arg2, 1);	PG_RETURN_BOOL((cmp > 0) || ((cmp == 0) && (len1 > len2)));}Datumbyteage(PG_FUNCTION_ARGS){	bytea	   *arg1 = PG_GETARG_BYTEA_P(0);	bytea	   *arg2 = PG_GETARG_BYTEA_P(1);	int			len1,				len2;	int			cmp;	len1 = VARSIZE(arg1) - VARHDRSZ;	len2 = VARSIZE(arg2) - VARHDRSZ;	cmp = memcmp(VARDATA(arg1), VARDATA(arg2), Min(len1, len2));	PG_FREE_IF_COPY(arg1, 0);	PG_FREE_IF_COPY(arg2, 1);	PG_RETURN_BOOL((cmp > 0) || ((cmp == 0) && (len1 >= len2)));}Datumbyteacmp(PG_FUNCTION_ARGS){	bytea	   *arg1 = PG_GETARG_BYTEA_P(0);	bytea	   *arg2 = PG_GETARG_BYTEA_P(1);	int			len1,				len2;	int			cmp;	len1 = VARSIZE(arg1) - VARHDRSZ;	len2 = VARSIZE(arg2) - VARHDRSZ;	cmp = memcmp(VARDATA(arg1), VARDATA(arg2), Min(len1, len2));	if ((cmp == 0) && (len1 != len2))		cmp = (len1 < len2) ? -1 : 1;	PG_FREE_IF_COPY(arg1, 0);	PG_FREE_IF_COPY(arg2, 1);	PG_RETURN_INT32(cmp);}/* * appendStringInfoText * * Append a text to str. * Like appendStringInfoString(str, PG_TEXT_GET_STR(s)) but faster. */static voidappendStringInfoText(StringInfo str, const text *t){	appendBinaryStringInfo(str, VARDATA(t), VARSIZE(t) - VARHDRSZ);}/* * replace_text * replace all occurrences of 'old_sub_str' in 'orig_str' * with 'new_sub_str' to form 'new_str' * * returns 'orig_str' if 'old_sub_str' == '' or 'orig_str' == '' * otherwise returns 'new_str' */Datumreplace_text(PG_FUNCTION_ARGS){	text	   *src_text = PG_GETARG_TEXT_P(0);	text	   *from_sub_text = PG_GETARG_TEXT_P(1);	text	   *to_sub_text = PG_GETARG_TEXT_P(2);	int			src_text_len = TEXTLEN(src_text);	int			from_sub_text_len = TEXTLEN(from_sub_text);	text	   *left_text;	text	   *right_text;	text	   *buf_text;	text	   *ret_text;	int			curr_posn;	StringInfo	str;	if (src_text_len == 0 || from_sub_text_len == 0)		PG_RETURN_TEXT_P(src_text);	curr_posn = TEXTPOS(src_text, from_sub_text);	/* When the from_sub_text is not found, there is nothing to do. */	if (curr_posn == 0)		PG_RETURN_TEXT_P(src_text);	str = makeStringInfo();	buf_text = src_text;	while (curr_posn > 0)	{		left_text = text_substring(PointerGetDatum(buf_text),								   1, curr_posn - 1, false);		right_text = text_substring(PointerGetDatum(buf_text),									curr_posn + from_sub_text_len, -1, true);		appendStringInfoText(str, left_text);		appendStringInfoText(str, to_sub_text);		if (buf_text != src_text)			pfree(buf_text);		pfree(left_text);		buf_text = right_text;		curr_posn = TEXTPOS(buf_text, from_sub_text);	}	appendStringInfoText(str, buf_text);	if (buf_text != src_text)		pfree(buf_text);	ret_text = PG_STR_GET_TEXT(str->data);	pfree(str->data);	pfree(str);	PG_RETURN_TEXT_P(ret_text);}/* * check_replace_text_has_escape_char * * check whether replace_text contains escape char. */static boolcheck_replace_text_has_escape_char(const text *replace_text){	const char *p = VARDATA(replace_text);	const char *p_end = p + (VARSIZE(replace_text) - VARHDRSZ);	if (pg_database_encoding_max_length() == 1)	{		for (; p < p_end; p++)		{			if (*p == '\\')				return true;		}	}	else	{		for (; p < p_end; p += pg_mblen(p))		{			if (*p == '\\')				return true;		}	}	return false;}/* * appendStringInfoRegexpSubstr * * Append replace_text to str, substituting regexp back references for * \n escapes. */static voidappendStringInfoRegexpSubstr(StringInfo str, text *replace_text,							 regmatch_t *pmatch, text *src_text){	const char *p = VARDATA(replace_text);	const char *p_end = p + (VARSIZE(replace_text) - VARHDRSZ);	int			eml = pg_database_encoding_max_length();	for (;;)	{		const char *chunk_start = p;		int			so;		int			eo;		/* Find next escape char. */		if (eml == 1)		{			for (; p < p_end && *p != '\\'; p++)				 /* nothing */ ;		}		else		{			for (; p < p_end && *p != '\\'; p += pg_mblen(p))				 /* nothing */ ;		}		/* Copy the text we just scanned over, if any. */		if (p > chunk_start)			appendBinaryStringInfo(str, chunk_start, p - chunk_start);		/* Done if at end of string, else advance over escape char. */		if (p >= p_end)			break;		p++;		if (p >= p_end)		{			/* Escape at very end of input.  Treat same as unexpected char */			appendStringInfoChar(str, '\\');			break;		}		if (*p >= '1' && *p <= '9')		{			/* Use the back reference of regexp. */			int			idx = *p - '0';			so = pmatch[idx].rm_so;			eo = pmatch[idx].rm_eo;			p++;		}		else if (*p == '&')		{			/* Use the entire matched string. */			so = pmatch[0].rm_so;			eo = pmatch[0].rm_eo;			p++;		}		else if (*p == '\\')		{			/* \\ means transfer one \ to output. */			appendStringInfoChar(str, '\\');			p++;			continue;		}		else		{			/*			 * If escape char is not followed by any expected char, just treat			 * it as ordinary data to copy.  (XXX would it be better to throw			 * an error?)

⌨️ 快捷键说明

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