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

📄 varlena.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 5 页
字号:
										 * string */			L1 = -1;		else		{			/* end position */			int			E = S + length;			/*			 * 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)				return PG_STR_GET_TEXT("");			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		 */		return DatumGetTextPSlice(str, S1 - 1, L1);	}	else if (eml > 1)	{		/*		 * When encoding max length is > 1, we can't get LC without		 * detoasting, so we'll grab a conservatively large slice now and go		 * back later to do the right thing		 */		int32		slice_start;		int32		slice_size;		int32		slice_strlen;		text	   *slice;		int32		E1;		int32		i;		char	   *p;		char	   *s;		text	   *ret;		/*		 * if S is past the end of the string, the tuple toaster will return a		 * zero-length string to us		 */		S1 = Max(S, 1);		/*		 * We need to start at position zero because there is no way to know		 * in advance which byte offset corresponds to the supplied start		 * position.		 */		slice_start = 0;		if (length_not_specified)		/* special case - get length to end of										 * string */			slice_size = L1 = -1;		else		{			int			E = S + length;			/*			 * 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)				return PG_STR_GET_TEXT("");			/*			 * if E is past the end of the string, the tuple toaster will			 * truncate the length for us			 */			L1 = E - S1;			/*			 * Total slice size in bytes can't be any longer than the start			 * position plus substring length times the encoding max length.			 */			slice_size = (S1 + L1) * eml;		}		slice = DatumGetTextPSlice(str, slice_start, slice_size);		/* see if we got back an empty string */		if ((VARSIZE(slice) - VARHDRSZ) == 0)			return PG_STR_GET_TEXT("");		/* Now we can get the actual length of the slice in MB characters */		slice_strlen = pg_mbstrlen_with_len(VARDATA(slice), VARSIZE(slice) - VARHDRSZ);		/*		 * Check that the start position wasn't > slice_strlen. If so, SQL99		 * says to return a zero-length string.		 */		if (S1 > slice_strlen)			return PG_STR_GET_TEXT("");		/*		 * Adjust L1 and E1 now that we know the slice string length. Again		 * remember that S1 is one based, and slice_start is zero based.		 */		if (L1 > -1)			E1 = Min(S1 + L1, slice_start + 1 + slice_strlen);		else			E1 = slice_start + 1 + slice_strlen;		/*		 * Find the start position in the slice; remember S1 is not zero based		 */		p = VARDATA(slice);		for (i = 0; i < S1 - 1; i++)			p += pg_mblen(p);		/* hang onto a pointer to our start position */		s = p;		/*		 * Count the actual bytes used by the substring of the requested		 * length.		 */		for (i = S1; i < E1; i++)			p += pg_mblen(p);		ret = (text *) palloc(VARHDRSZ + (p - s));		VARATT_SIZEP(ret) = VARHDRSZ + (p - s);		memcpy(VARDATA(ret), s, (p - s));		return ret;	}	else		elog(ERROR, "invalid backend encoding: encoding max length < 1");	/* not reached: suppress compiler warning */	return NULL;}/* * textpos - *	  Return the position of the specified substring. *	  Implements the SQL92 POSITION() function. *	  Ref: A Guide To The SQL Standard, Date & Darwen, 1997 * - thomas 1997-07-27 */Datumtextpos(PG_FUNCTION_ARGS){	text	   *str = PG_GETARG_TEXT_P(0);	text	   *search_str = PG_GETARG_TEXT_P(1);	PG_RETURN_INT32(text_position(str, search_str, 1));}/* * text_position - *	Does the real work for textpos() * * Inputs: *		t1 - string to be searched *		t2 - pattern to match within t1 *		matchnum - number of the match to be found (1 is the first match) * Result: *		Character index of the first matched char, starting from 1, *		or 0 if no match. * *	This is broken out so it can be called directly by other string processing *	functions. */static int32text_position(text *t1, text *t2, int matchnum){	int			match = 0,				pos = 0,				p,				px,				len1,				len2;	if (matchnum <= 0)		return 0;				/* result for 0th match */	if (VARSIZE(t2) <= VARHDRSZ)		return 1;				/* result for empty pattern */	len1 = VARSIZE(t1) - VARHDRSZ;	len2 = VARSIZE(t2) - VARHDRSZ;	if (pg_database_encoding_max_length() == 1)	{		/* simple case - single byte encoding */		char	   *p1,				   *p2;		p1 = VARDATA(t1);		p2 = VARDATA(t2);		/* no use in searching str past point where search_str will fit */		px = (len1 - len2);		for (p = 0; p <= px; p++)		{			if ((*p1 == *p2) && (strncmp(p1, p2, len2) == 0))			{				if (++match == matchnum)				{					pos = p + 1;					break;				}			}			p1++;		}	}	else	{		/* not as simple - multibyte encoding */		pg_wchar   *p1,				   *p2,				   *ps1,				   *ps2;		ps1 = p1 = (pg_wchar *) palloc((len1 + 1) * sizeof(pg_wchar));		(void) pg_mb2wchar_with_len(VARDATA(t1), p1, len1);		len1 = pg_wchar_strlen(p1);		ps2 = p2 = (pg_wchar *) palloc((len2 + 1) * sizeof(pg_wchar));		(void) pg_mb2wchar_with_len(VARDATA(t2), p2, len2);		len2 = pg_wchar_strlen(p2);		/* no use in searching str past point where search_str will fit */		px = (len1 - len2);		for (p = 0; p <= px; p++)		{			if ((*p1 == *p2) && (pg_wchar_strncmp(p1, p2, len2) == 0))			{				if (++match == matchnum)				{					pos = p + 1;					break;				}			}			p1++;		}		pfree(ps1);		pfree(ps2);	}	return pos;}/* varstr_cmp() * Comparison function for text strings with given lengths. * Includes locale support, but must copy strings to temporary memory *	to allow null-termination for inputs to strcoll(). * Returns -1, 0 or 1 */intvarstr_cmp(char *arg1, int len1, char *arg2, int len2){	int			result;	/*	 * Unfortunately, there is no strncoll(), so in the non-C locale case we	 * have to do some memory copying.	This turns out to be significantly	 * slower, so we optimize the case where LC_COLLATE is C.  We also try to	 * optimize relatively-short strings by avoiding palloc/pfree overhead.	 */	if (lc_collate_is_c())	{		result = strncmp(arg1, arg2, Min(len1, len2));		if ((result == 0) && (len1 != len2))			result = (len1 < len2) ? -1 : 1;	}	else	{#define STACKBUFLEN		1024		char		a1buf[STACKBUFLEN];		char		a2buf[STACKBUFLEN];		char	   *a1p,				   *a2p;#ifdef WIN32		/* Win32 does not have UTF-8, so we need to map to UTF-16 */		if (GetDatabaseEncoding() == PG_UTF8)		{			int			a1len;			int			a2len;			int			r;			if (len1 >= STACKBUFLEN / 2)			{				a1len = len1 * 2 + 2;				a1p = palloc(a1len);			}			else			{				a1len = STACKBUFLEN;				a1p = a1buf;			}			if (len2 >= STACKBUFLEN / 2)			{				a2len = len2 * 2 + 2;				a2p = palloc(a2len);			}			else			{				a2len = STACKBUFLEN;				a2p = a2buf;			}			/* stupid Microsloth API does not work for zero-length input */			if (len1 == 0)				r = 0;			else			{				r = MultiByteToWideChar(CP_UTF8, 0, arg1, len1,										(LPWSTR) a1p, a1len / 2);				if (!r)					ereport(ERROR,					 (errmsg("could not convert string to UTF-16: error %lu",							 GetLastError())));			}			((LPWSTR) a1p)[r] = 0;			if (len2 == 0)				r = 0;			else			{				r = MultiByteToWideChar(CP_UTF8, 0, arg2, len2,										(LPWSTR) a2p, a2len / 2);				if (!r)					ereport(ERROR,					 (errmsg("could not convert string to UTF-16: error %lu",							 GetLastError())));			}			((LPWSTR) a2p)[r] = 0;			errno = 0;			result = wcscoll((LPWSTR) a1p, (LPWSTR) a2p);			if (result == 2147483647)	/* _NLSCMPERROR; missing from mingw										 * headers */				ereport(ERROR,						(errmsg("could not compare Unicode strings: %m")));			if (a1p != a1buf)				pfree(a1p);			if (a2p != a2buf)				pfree(a2p);			return result;		}#endif   /* WIN32 */		if (len1 >= STACKBUFLEN)			a1p = (char *) palloc(len1 + 1);		else			a1p = a1buf;		if (len2 >= STACKBUFLEN)			a2p = (char *) palloc(len2 + 1);		else			a2p = a2buf;		memcpy(a1p, arg1, len1);		a1p[len1] = '\0';		memcpy(a2p, arg2, len2);		a2p[len2] = '\0';		result = strcoll(a1p, a2p);		/*		 * In some locales strcoll() can claim that nonidentical strings are		 * equal.  Believing that would be bad news for a number of reasons,		 * so we follow Perl's lead and sort "equal" strings according to		 * strcmp().		 */		if (result == 0)			result = strcmp(a1p, a2p);		if (a1p != a1buf)			pfree(a1p);		if (a2p != a2buf)			pfree(a2p);	}	return result;}/* text_cmp() * Internal comparison function for text strings. * Returns -1, 0 or 1 */static inttext_cmp(text *arg1, text *arg2){	char	   *a1p,			   *a2p;	int			len1,				len2;	a1p = VARDATA(arg1);	a2p = VARDATA(arg2);	len1 = VARSIZE(arg1) - VARHDRSZ;	len2 = VARSIZE(arg2) - VARHDRSZ;	return varstr_cmp(a1p, len1, a2p, len2);}/* * Comparison functions for text strings. * * 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. */Datumtexteq(PG_FUNCTION_ARGS){	text	   *arg1 = PG_GETARG_TEXT_P(0);	text	   *arg2 = PG_GETARG_TEXT_P(1);	bool		result;	/*	 * Since we only care about equality or not-equality, we can avoid all	 * the expense of strcoll() here, and just do bitwise comparison.	 */	if (VARSIZE(arg1) != VARSIZE(arg2))		result = false;	else		result = (strncmp(VARDATA(arg1), VARDATA(arg2),						  VARSIZE(arg1) - VARHDRSZ) == 0);	PG_FREE_IF_COPY(arg1, 0);	PG_FREE_IF_COPY(arg2, 1);	PG_RETURN_BOOL(result);}Datumtextne(PG_FUNCTION_ARGS){	text	   *arg1 = PG_GETARG_TEXT_P(0);	text	   *arg2 = PG_GETARG_TEXT_P(1);	bool		result;	/*	 * Since we only care about equality or not-equality, we can avoid all	 * the expense of strcoll() here, and just do bitwise comparison.	 */	if (VARSIZE(arg1) != VARSIZE(arg2))		result = true;	else		result = (strncmp(VARDATA(arg1), VARDATA(arg2),						  VARSIZE(arg1) - VARHDRSZ) != 0);	PG_FREE_IF_COPY(arg1, 0);	PG_FREE_IF_COPY(arg2, 1);	PG_RETURN_BOOL(result);}Datumtext_lt(PG_FUNCTION_ARGS){	text	   *arg1 = PG_GETARG_TEXT_P(0);	text	   *arg2 = PG_GETARG_TEXT_P(1);	bool		result;	result = (text_cmp(arg1, arg2) < 0);	PG_FREE_IF_COPY(arg1, 0);	PG_FREE_IF_COPY(arg2, 1);	PG_RETURN_BOOL(result);}Datumtext_le(PG_FUNCTION_ARGS){	text	   *arg1 = PG_GETARG_TEXT_P(0);	text	   *arg2 = PG_GETARG_TEXT_P(1);	bool		result;	result = (text_cmp(arg1, arg2) <= 0);	PG_FREE_IF_COPY(arg1, 0);	PG_FREE_IF_COPY(arg2, 1);	PG_RETURN_BOOL(result);}Datumtext_gt(PG_FUNCTION_ARGS){	text	   *arg1 = PG_GETARG_TEXT_P(0);	text	   *arg2 = PG_GETARG_TEXT_P(1);	bool		result;	result = (text_cmp(arg1, arg2) > 0);	PG_FREE_IF_COPY(arg1, 0);	PG_FREE_IF_COPY(arg2, 1);	PG_RETURN_BOOL(result);}Datumtext_ge(PG_FUNCTION_ARGS){	text	   *arg1 = PG_GETARG_TEXT_P(0);	text	   *arg2 = PG_GETARG_TEXT_P(1);	bool		result;	result = (text_cmp(arg1, arg2) >= 0);	PG_FREE_IF_COPY(arg1, 0);	PG_FREE_IF_COPY(arg2, 1);	PG_RETURN_BOOL(result);}Datumbttextcmp(PG_FUNCTION_ARGS){	text	   *arg1 = PG_GETARG_TEXT_P(0);

⌨️ 快捷键说明

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