varlena.c

来自「PostgreSQL7.4.6 for Linux」· C语言 代码 · 共 2,310 行 · 第 1/4 页

C
2,310
字号
	PG_RETURN_BOOL(result > 0);}Datumtext_pattern_ne(PG_FUNCTION_ARGS){	text	   *arg1 = PG_GETARG_TEXT_P(0);	text	   *arg2 = PG_GETARG_TEXT_P(1);	int			result;	if (VARSIZE(arg1) != VARSIZE(arg2))		result = 1;	else		result = internal_text_pattern_compare(arg1, arg2);	PG_FREE_IF_COPY(arg1, 0);	PG_FREE_IF_COPY(arg2, 1);	PG_RETURN_BOOL(result != 0);}Datumbttext_pattern_cmp(PG_FUNCTION_ARGS){	text	   *arg1 = PG_GETARG_TEXT_P(0);	text	   *arg2 = PG_GETARG_TEXT_P(1);	int			result;	result = internal_text_pattern_compare(arg1, arg2);	PG_FREE_IF_COPY(arg1, 0);	PG_FREE_IF_COPY(arg2, 1);	PG_RETURN_INT32(result);}/*------------------------------------------------------------- * byteaoctetlen * * get the number of bytes contained in an instance of type 'bytea' *------------------------------------------------------------- */Datumbyteaoctetlen(PG_FUNCTION_ARGS){	PG_RETURN_INT32(toast_raw_datum_size(PG_GETARG_DATUM(0)) - VARHDRSZ);}/* * byteacat - *	  takes two bytea* and returns a bytea* that is the concatenation of *	  the two. * * Cloned from textcat and modified as required. */Datumbyteacat(PG_FUNCTION_ARGS){	bytea	   *t1 = PG_GETARG_BYTEA_P(0);	bytea	   *t2 = PG_GETARG_BYTEA_P(1);	int			len1,				len2,				len;	bytea	   *result;	char	   *ptr;	len1 = (VARSIZE(t1) - VARHDRSZ);	if (len1 < 0)		len1 = 0;	len2 = (VARSIZE(t2) - VARHDRSZ);	if (len2 < 0)		len2 = 0;	len = len1 + len2 + VARHDRSZ;	result = (bytea *) palloc(len);	/* Set size of result string... */	VARATT_SIZEP(result) = len;	/* Fill data field of result string... */	ptr = VARDATA(result);	if (len1 > 0)		memcpy(ptr, VARDATA(t1), len1);	if (len2 > 0)		memcpy(ptr + len1, VARDATA(t2), len2);	PG_RETURN_BYTEA_P(result);}#define PG_STR_GET_BYTEA(str_) \	DatumGetByteaP(DirectFunctionCall1(byteain, CStringGetDatum(str_)))/* * bytea_substr() * Return a substring starting at the specified position. * Cloned from text_substr and modified as required. * * Input: *	- string *	- starting position (is one-based) *	- string length (optional) * * If the starting position is zero or less, then return from the start of the string * adjusting the length to be consistent with the "negative start" per SQL92. * If the length is less than zero, an ERROR is thrown. If no third argument * (length) is provided, the length to the end of the string is assumed. */Datumbytea_substr(PG_FUNCTION_ARGS){	int			S = PG_GETARG_INT32(1); /* start position */	int			S1;				/* adjusted start position */	int			L1;				/* adjusted substring length */	S1 = Max(S, 1);	if (fcinfo->nargs == 2)	{		/*		 * Not passed a length - PG_GETARG_BYTEA_P_SLICE() grabs		 * everything to the end of the string if we pass it a negative		 * value for length.		 */		L1 = -1;	}	else	{		/* end position */		int			E = S + PG_GETARG_INT32(2);		/*		 * A negative value for L is the only way for the end position to		 * be before the start. SQL99 says to throw an error.		 */		if (E < S)			ereport(ERROR,					(errcode(ERRCODE_SUBSTRING_ERROR),					 errmsg("negative substring length not allowed")));		/*		 * A zero or negative value for the end position can happen if the		 * start was negative or one. SQL99 says to return a zero-length		 * string.		 */		if (E < 1)			PG_RETURN_BYTEA_P(PG_STR_GET_BYTEA(""));		L1 = E - S1;	}	/*	 * If the start position is past the end of the string, SQL99 says to	 * return a zero-length string -- PG_GETARG_TEXT_P_SLICE() will do	 * that for us. Convert to zero-based starting position	 */	PG_RETURN_BYTEA_P(PG_GETARG_BYTEA_P_SLICE(0, S1 - 1, L1));}/* * bytea_substr_no_len - *	  Wrapper to avoid opr_sanity failure due to *	  one function accepting a different number of args. */Datumbytea_substr_no_len(PG_FUNCTION_ARGS){	return bytea_substr(fcinfo);}/* * byteapos - *	  Return the position of the specified substring. *	  Implements the SQL92 POSITION() function. * Cloned from textpos and modified as required. */Datumbyteapos(PG_FUNCTION_ARGS){	bytea	   *t1 = PG_GETARG_BYTEA_P(0);	bytea	   *t2 = PG_GETARG_BYTEA_P(1);	int			pos;	int			px,				p;	int			len1,				len2;	char	   *p1,			   *p2;	if (VARSIZE(t2) <= VARHDRSZ)		PG_RETURN_INT32(1);		/* result for empty pattern */	len1 = (VARSIZE(t1) - VARHDRSZ);	len2 = (VARSIZE(t2) - VARHDRSZ);	p1 = VARDATA(t1);	p2 = VARDATA(t2);	pos = 0;	px = (len1 - len2);	for (p = 0; p <= px; p++)	{		if ((*p2 == *p1) && (memcmp(p1, p2, len2) == 0))		{			pos = p + 1;			break;		};		p1++;	};	PG_RETURN_INT32(pos);}/*------------------------------------------------------------- * byteaGetByte * * this routine treats "bytea" as an array of bytes. * It returns the Nth byte (a number between 0 and 255). *------------------------------------------------------------- */DatumbyteaGetByte(PG_FUNCTION_ARGS){	bytea	   *v = PG_GETARG_BYTEA_P(0);	int32		n = PG_GETARG_INT32(1);	int			len;	int			byte;	len = VARSIZE(v) - VARHDRSZ;	if (n < 0 || n >= len)		ereport(ERROR,				(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),				 errmsg("index %d out of valid range, 0..%d",						n, len - 1)));	byte = ((unsigned char *) VARDATA(v))[n];	PG_RETURN_INT32(byte);}/*------------------------------------------------------------- * byteaGetBit * * This routine treats a "bytea" type like an array of bits. * It returns the value of the Nth bit (0 or 1). * *------------------------------------------------------------- */DatumbyteaGetBit(PG_FUNCTION_ARGS){	bytea	   *v = PG_GETARG_BYTEA_P(0);	int32		n = PG_GETARG_INT32(1);	int			byteNo,				bitNo;	int			len;	int			byte;	len = VARSIZE(v) - VARHDRSZ;	if (n < 0 || n >= len * 8)		ereport(ERROR,				(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),				 errmsg("index %d out of valid range, 0..%d",						n, len * 8 - 1)));	byteNo = n / 8;	bitNo = n % 8;	byte = ((unsigned char *) VARDATA(v))[byteNo];	if (byte & (1 << bitNo))		PG_RETURN_INT32(1);	else		PG_RETURN_INT32(0);}/*------------------------------------------------------------- * byteaSetByte * * Given an instance of type 'bytea' creates a new one with * the Nth byte set to the given value. * *------------------------------------------------------------- */DatumbyteaSetByte(PG_FUNCTION_ARGS){	bytea	   *v = PG_GETARG_BYTEA_P(0);	int32		n = PG_GETARG_INT32(1);	int32		newByte = PG_GETARG_INT32(2);	int			len;	bytea	   *res;	len = VARSIZE(v) - VARHDRSZ;	if (n < 0 || n >= len)		ereport(ERROR,				(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),				 errmsg("index %d out of valid range, 0..%d",						n, len - 1)));	/*	 * Make a copy of the original varlena.	 */	res = (bytea *) palloc(VARSIZE(v));	memcpy((char *) res, (char *) v, VARSIZE(v));	/*	 * Now set the byte.	 */	((unsigned char *) VARDATA(res))[n] = newByte;	PG_RETURN_BYTEA_P(res);}/*------------------------------------------------------------- * byteaSetBit * * Given an instance of type 'bytea' creates a new one with * the Nth bit set to the given value. * *------------------------------------------------------------- */DatumbyteaSetBit(PG_FUNCTION_ARGS){	bytea	   *v = PG_GETARG_BYTEA_P(0);	int32		n = PG_GETARG_INT32(1);	int32		newBit = PG_GETARG_INT32(2);	bytea	   *res;	int			len;	int			oldByte,				newByte;	int			byteNo,				bitNo;	len = VARSIZE(v) - VARHDRSZ;	if (n < 0 || n >= len * 8)		ereport(ERROR,				(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),				 errmsg("index %d out of valid range, 0..%d",						n, len * 8 - 1)));	byteNo = n / 8;	bitNo = n % 8;	/*	 * sanity check!	 */	if (newBit != 0 && newBit != 1)		ereport(ERROR,				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),				 errmsg("new bit must be 0 or 1")));	/*	 * Make a copy of the original varlena.	 */	res = (bytea *) palloc(VARSIZE(v));	memcpy((char *) res, (char *) v, VARSIZE(v));	/*	 * Update the byte.	 */	oldByte = ((unsigned char *) VARDATA(res))[byteNo];	if (newBit == 0)		newByte = oldByte & (~(1 << bitNo));	else		newByte = oldByte | (1 << bitNo);	((unsigned char *) VARDATA(res))[byteNo] = newByte;	PG_RETURN_BYTEA_P(res);}/* text_name() * Converts a text type to a Name type. */Datumtext_name(PG_FUNCTION_ARGS){	text	   *s = PG_GETARG_TEXT_P(0);	Name		result;	int			len;	len = VARSIZE(s) - VARHDRSZ;	/* Truncate oversize input */	if (len >= NAMEDATALEN)		len = NAMEDATALEN - 1;#ifdef STRINGDEBUG	printf("text- convert string length %d (%d) ->%d\n",		   VARSIZE(s) - VARHDRSZ, VARSIZE(s), len);#endif	result = (Name) palloc(NAMEDATALEN);	memcpy(NameStr(*result), VARDATA(s), len);	/* 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, const char *caller){	char	   *rawname;	List	   *result = NIL;	List	   *namelist;	List	   *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);	freeList(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 freeList() 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 */

⌨️ 快捷键说明

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