oracle_compat.c

来自「postgresql8.3.4源码,开源数据库」· C语言 代码 · 共 1,498 行 · 第 1/3 页

C
1,498
字号
		text	   *string = PG_GETARG_TEXT_PP(0);		text	   *result;		wchar_t    *workspace;		int			wasalnum = 0;		int			i;		workspace = texttowcs(string);		for (i = 0; workspace[i] != 0; i++)		{			if (wasalnum)				workspace[i] = towlower(workspace[i]);			else				workspace[i] = towupper(workspace[i]);			wasalnum = iswalnum(workspace[i]);		}		result = wcstotext(workspace, i);		pfree(workspace);		PG_RETURN_TEXT_P(result);	}	else#endif   /* USE_WIDE_UPPER_LOWER */	{		text	   *string = PG_GETARG_TEXT_P_COPY(0);		int			wasalnum = 0;		char	   *ptr;		int			m;		/*		 * Since we copied the string, we can scribble directly on the value		 */		ptr = VARDATA(string);		m = VARSIZE(string) - VARHDRSZ;		while (m-- > 0)		{			if (wasalnum)				*ptr = tolower((unsigned char) *ptr);			else				*ptr = toupper((unsigned char) *ptr);			wasalnum = isalnum((unsigned char) *ptr);			ptr++;		}		PG_RETURN_TEXT_P(string);	}}/******************************************************************** * * lpad * * Syntax: * *	 text lpad(text string1, int4 len, text string2) * * Purpose: * *	 Returns string1, left-padded to length len with the sequence of *	 characters in string2.  If len is less than the length of string1, *	 instead truncate (on the right) to len. * ********************************************************************/Datumlpad(PG_FUNCTION_ARGS){	text	   *string1 = PG_GETARG_TEXT_PP(0);	int32		len = PG_GETARG_INT32(1);	text	   *string2 = PG_GETARG_TEXT_PP(2);	text	   *ret;	char	   *ptr1,			   *ptr2,			   *ptr2start,			   *ptr2end,			   *ptr_ret;	int			m,				s1len,				s2len;	int			bytelen;	/* Negative len is silently taken as zero */	if (len < 0)		len = 0;	s1len = VARSIZE_ANY_EXHDR(string1);	if (s1len < 0)		s1len = 0;				/* shouldn't happen */	s2len = VARSIZE_ANY_EXHDR(string2);	if (s2len < 0)		s2len = 0;				/* shouldn't happen */	s1len = pg_mbstrlen_with_len(VARDATA_ANY(string1), s1len);	if (s1len > len)		s1len = len;			/* truncate string1 to len chars */	if (s2len <= 0)		len = s1len;			/* nothing to pad with, so don't pad */	bytelen = pg_database_encoding_max_length() * len;	/* check for integer overflow */	if (len != 0 && bytelen / pg_database_encoding_max_length() != len)		ereport(ERROR,				(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),				 errmsg("requested length too large")));	ret = (text *) palloc(VARHDRSZ + bytelen);	m = len - s1len;	ptr2 = ptr2start = VARDATA_ANY(string2);	ptr2end = ptr2 + s2len;	ptr_ret = VARDATA(ret);	while (m--)	{		int			mlen = pg_mblen(ptr2);		memcpy(ptr_ret, ptr2, mlen);		ptr_ret += mlen;		ptr2 += mlen;		if (ptr2 == ptr2end)	/* wrap around at end of s2 */			ptr2 = ptr2start;	}	ptr1 = VARDATA_ANY(string1);	while (s1len--)	{		int			mlen = pg_mblen(ptr1);		memcpy(ptr_ret, ptr1, mlen);		ptr_ret += mlen;		ptr1 += mlen;	}	SET_VARSIZE(ret, ptr_ret - (char *) ret);	PG_RETURN_TEXT_P(ret);}/******************************************************************** * * rpad * * Syntax: * *	 text rpad(text string1, int4 len, text string2) * * Purpose: * *	 Returns string1, right-padded to length len with the sequence of *	 characters in string2.  If len is less than the length of string1, *	 instead truncate (on the right) to len. * ********************************************************************/Datumrpad(PG_FUNCTION_ARGS){	text	   *string1 = PG_GETARG_TEXT_PP(0);	int32		len = PG_GETARG_INT32(1);	text	   *string2 = PG_GETARG_TEXT_PP(2);	text	   *ret;	char	   *ptr1,			   *ptr2,			   *ptr2start,			   *ptr2end,			   *ptr_ret;	int			m,				s1len,				s2len;	int			bytelen;	/* Negative len is silently taken as zero */	if (len < 0)		len = 0;	s1len = VARSIZE_ANY_EXHDR(string1);	if (s1len < 0)		s1len = 0;				/* shouldn't happen */	s2len = VARSIZE_ANY_EXHDR(string2);	if (s2len < 0)		s2len = 0;				/* shouldn't happen */	s1len = pg_mbstrlen_with_len(VARDATA_ANY(string1), s1len);	if (s1len > len)		s1len = len;			/* truncate string1 to len chars */	if (s2len <= 0)		len = s1len;			/* nothing to pad with, so don't pad */	bytelen = pg_database_encoding_max_length() * len;	/* Check for integer overflow */	if (len != 0 && bytelen / pg_database_encoding_max_length() != len)		ereport(ERROR,				(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),				 errmsg("requested length too large")));	ret = (text *) palloc(VARHDRSZ + bytelen);	m = len - s1len;	ptr1 = VARDATA_ANY(string1);	ptr_ret = VARDATA(ret);	while (s1len--)	{		int			mlen = pg_mblen(ptr1);		memcpy(ptr_ret, ptr1, mlen);		ptr_ret += mlen;		ptr1 += mlen;	}	ptr2 = ptr2start = VARDATA_ANY(string2);	ptr2end = ptr2 + s2len;	while (m--)	{		int			mlen = pg_mblen(ptr2);		memcpy(ptr_ret, ptr2, mlen);		ptr_ret += mlen;		ptr2 += mlen;		if (ptr2 == ptr2end)	/* wrap around at end of s2 */			ptr2 = ptr2start;	}	SET_VARSIZE(ret, ptr_ret - (char *) ret);	PG_RETURN_TEXT_P(ret);}/******************************************************************** * * btrim * * Syntax: * *	 text btrim(text string, text set) * * Purpose: * *	 Returns string with characters removed from the front and back *	 up to the first character not in set. * ********************************************************************/Datumbtrim(PG_FUNCTION_ARGS){	text	   *string = PG_GETARG_TEXT_PP(0);	text	   *set = PG_GETARG_TEXT_PP(1);	text	   *ret;	ret = dotrim(VARDATA_ANY(string), VARSIZE_ANY_EXHDR(string),				 VARDATA_ANY(set), VARSIZE_ANY_EXHDR(set),				 true, true);	PG_RETURN_TEXT_P(ret);}/******************************************************************** * * btrim1 --- btrim with set fixed as ' ' * ********************************************************************/Datumbtrim1(PG_FUNCTION_ARGS){	text	   *string = PG_GETARG_TEXT_PP(0);	text	   *ret;	ret = dotrim(VARDATA_ANY(string), VARSIZE_ANY_EXHDR(string),				 " ", 1,				 true, true);	PG_RETURN_TEXT_P(ret);}/* * Common implementation for btrim, ltrim, rtrim */static text *dotrim(const char *string, int stringlen,	   const char *set, int setlen,	   bool doltrim, bool dortrim){	text	   *result;	int			i;	/* Nothing to do if either string or set is empty */	if (stringlen > 0 && setlen > 0)	{		if (pg_database_encoding_max_length() > 1)		{			/*			 * In the multibyte-encoding case, build arrays of pointers to			 * character starts, so that we can avoid inefficient checks in			 * the inner loops.			 */			const char **stringchars;			const char **setchars;			int		   *stringmblen;			int		   *setmblen;			int			stringnchars;			int			setnchars;			int			resultndx;			int			resultnchars;			const char *p;			int			len;			int			mblen;			const char *str_pos;			int			str_len;			stringchars = (const char **) palloc(stringlen * sizeof(char *));			stringmblen = (int *) palloc(stringlen * sizeof(int));			stringnchars = 0;			p = string;			len = stringlen;			while (len > 0)			{				stringchars[stringnchars] = p;				stringmblen[stringnchars] = mblen = pg_mblen(p);				stringnchars++;				p += mblen;				len -= mblen;			}			setchars = (const char **) palloc(setlen * sizeof(char *));			setmblen = (int *) palloc(setlen * sizeof(int));			setnchars = 0;			p = set;			len = setlen;			while (len > 0)			{				setchars[setnchars] = p;				setmblen[setnchars] = mblen = pg_mblen(p);				setnchars++;				p += mblen;				len -= mblen;			}			resultndx = 0;		/* index in stringchars[] */			resultnchars = stringnchars;			if (doltrim)			{				while (resultnchars > 0)				{					str_pos = stringchars[resultndx];					str_len = stringmblen[resultndx];					for (i = 0; i < setnchars; i++)					{						if (str_len == setmblen[i] &&							memcmp(str_pos, setchars[i], str_len) == 0)							break;					}					if (i >= setnchars)						break;	/* no match here */					string += str_len;					stringlen -= str_len;					resultndx++;					resultnchars--;				}			}			if (dortrim)			{				while (resultnchars > 0)				{					str_pos = stringchars[resultndx + resultnchars - 1];					str_len = stringmblen[resultndx + resultnchars - 1];					for (i = 0; i < setnchars; i++)					{						if (str_len == setmblen[i] &&							memcmp(str_pos, setchars[i], str_len) == 0)							break;					}					if (i >= setnchars)						break;	/* no match here */					stringlen -= str_len;					resultnchars--;				}			}			pfree(stringchars);			pfree(stringmblen);			pfree(setchars);			pfree(setmblen);		}		else		{			/*			 * In the single-byte-encoding case, we don't need such overhead.			 */			if (doltrim)			{				while (stringlen > 0)				{					char		str_ch = *string;					for (i = 0; i < setlen; i++)					{						if (str_ch == set[i])							break;					}					if (i >= setlen)						break;	/* no match here */					string++;					stringlen--;				}			}			if (dortrim)			{				while (stringlen > 0)				{					char		str_ch = string[stringlen - 1];					for (i = 0; i < setlen; i++)					{						if (str_ch == set[i])							break;					}					if (i >= setlen)						break;	/* no match here */					stringlen--;				}			}		}	}	/* Return selected portion of string */	result = (text *) palloc(VARHDRSZ + stringlen);	SET_VARSIZE(result, VARHDRSZ + stringlen);	memcpy(VARDATA(result), string, stringlen);	return result;}/******************************************************************** * * byteatrim * * Syntax: * *	 bytea byteatrim(byta string, bytea set) * * Purpose: * *	 Returns string with characters removed from the front and back *	 up to the first character not in set. * * Cloned from btrim and modified as required. ********************************************************************/Datumbyteatrim(PG_FUNCTION_ARGS){	bytea	   *string = PG_GETARG_BYTEA_PP(0);	bytea	   *set = PG_GETARG_BYTEA_PP(1);	bytea	   *ret;	char	   *ptr,			   *end,			   *ptr2,			   *ptr2start,			   *end2;	int			m,				stringlen,				setlen;	stringlen = VARSIZE_ANY_EXHDR(string);	setlen = VARSIZE_ANY_EXHDR(set);	if (stringlen <= 0 || setlen <= 0)		PG_RETURN_BYTEA_P(string);	m = stringlen;	ptr = VARDATA_ANY(string);	end = ptr + stringlen - 1;	ptr2start = VARDATA_ANY(set);	end2 = ptr2start + setlen - 1;	while (m > 0)

⌨️ 快捷键说明

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