oracle_compat.c

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

C
1,498
字号
	{		ptr2 = ptr2start;		while (ptr2 <= end2)		{			if (*ptr == *ptr2)				break;			++ptr2;		}		if (ptr2 > end2)			break;		ptr++;		m--;	}	while (m > 0)	{		ptr2 = ptr2start;		while (ptr2 <= end2)		{			if (*end == *ptr2)				break;			++ptr2;		}		if (ptr2 > end2)			break;		end--;		m--;	}	ret = (bytea *) palloc(VARHDRSZ + m);	SET_VARSIZE(ret, VARHDRSZ + m);	memcpy(VARDATA(ret), ptr, m);	PG_RETURN_BYTEA_P(ret);}/******************************************************************** * * ltrim * * Syntax: * *	 text ltrim(text string, text set) * * Purpose: * *	 Returns string with initial characters removed up to the first *	 character not in set. * ********************************************************************/Datumltrim(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, false);	PG_RETURN_TEXT_P(ret);}/******************************************************************** * * ltrim1 --- ltrim with set fixed as ' ' * ********************************************************************/Datumltrim1(PG_FUNCTION_ARGS){	text	   *string = PG_GETARG_TEXT_PP(0);	text	   *ret;	ret = dotrim(VARDATA_ANY(string), VARSIZE_ANY_EXHDR(string),				 " ", 1,				 true, false);	PG_RETURN_TEXT_P(ret);}/******************************************************************** * * rtrim * * Syntax: * *	 text rtrim(text string, text set) * * Purpose: * *	 Returns string with final characters removed after the last *	 character not in set. * ********************************************************************/Datumrtrim(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),				 false, true);	PG_RETURN_TEXT_P(ret);}/******************************************************************** * * rtrim1 --- rtrim with set fixed as ' ' * ********************************************************************/Datumrtrim1(PG_FUNCTION_ARGS){	text	   *string = PG_GETARG_TEXT_PP(0);	text	   *ret;	ret = dotrim(VARDATA_ANY(string), VARSIZE_ANY_EXHDR(string),				 " ", 1,				 false, true);	PG_RETURN_TEXT_P(ret);}/******************************************************************** * * translate * * Syntax: * *	 text translate(text string, text from, text to) * * Purpose: * *	 Returns string after replacing all occurrences of characters in from *	 with the corresponding character in to.  If from is longer than to, *	 occurrences of the extra characters in from are deleted. *	 Improved by Edwin Ramirez <ramirez@doc.mssm.edu>. * ********************************************************************/Datumtranslate(PG_FUNCTION_ARGS){	text	   *string = PG_GETARG_TEXT_PP(0);	text	   *from = PG_GETARG_TEXT_PP(1);	text	   *to = PG_GETARG_TEXT_PP(2);	text	   *result;	char	   *from_ptr,			   *to_ptr;	char	   *source,			   *target;	int			m,				fromlen,				tolen,				retlen,				i;	int			worst_len;	int			len;	int			source_len;	int			from_index;	m = VARSIZE_ANY_EXHDR(string);	if (m <= 0)		PG_RETURN_TEXT_P(string);	source = VARDATA_ANY(string);	fromlen = VARSIZE_ANY_EXHDR(from);	from_ptr = VARDATA_ANY(from);	tolen = VARSIZE_ANY_EXHDR(to);	to_ptr = VARDATA_ANY(to);	/*	 * The worst-case expansion is to substitute a max-length character for a	 * single-byte character at each position of the string.	 */	worst_len = pg_database_encoding_max_length() * m;	/* check for integer overflow */	if (worst_len / pg_database_encoding_max_length() != m)		ereport(ERROR,				(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),				 errmsg("requested length too large")));	result = (text *) palloc(worst_len + VARHDRSZ);	target = VARDATA(result);	retlen = 0;	while (m > 0)	{		source_len = pg_mblen(source);		from_index = 0;		for (i = 0; i < fromlen; i += len)		{			len = pg_mblen(&from_ptr[i]);			if (len == source_len &&				memcmp(source, &from_ptr[i], len) == 0)				break;			from_index++;		}		if (i < fromlen)		{			/* substitute */			char	   *p = to_ptr;			for (i = 0; i < from_index; i++)			{				p += pg_mblen(p);				if (p >= (to_ptr + tolen))					break;			}			if (p < (to_ptr + tolen))			{				len = pg_mblen(p);				memcpy(target, p, len);				target += len;				retlen += len;			}		}		else		{			/* no match, so copy */			memcpy(target, source, source_len);			target += source_len;			retlen += source_len;		}		source += source_len;		m -= source_len;	}	SET_VARSIZE(result, retlen + VARHDRSZ);	/*	 * The function result is probably much bigger than needed, if we're using	 * a multibyte encoding, but it's not worth reallocating it; the result	 * probably won't live long anyway.	 */	PG_RETURN_TEXT_P(result);}/******************************************************************** * * ascii * * Syntax: * *	 int ascii(text string) * * Purpose: * *	 Returns the decimal representation of the first character from *	 string. *	 If the string is empty we return 0. *	 If the database encoding is UTF8, we return the Unicode codepoint. *	 If the database encoding is any other multi-byte encoding, we *	 return the value of the first byte if it is an ASCII character *	 (range 1 .. 127), or raise an error. *	 For all other encodings we return the value of the first byte, *	 (range 1..255). * ********************************************************************/Datumascii(PG_FUNCTION_ARGS){	text	   *string = PG_GETARG_TEXT_PP(0);	int			encoding = GetDatabaseEncoding();	unsigned char *data;	if (VARSIZE_ANY_EXHDR(string) <= 0)		PG_RETURN_INT32(0);	data = (unsigned char *) VARDATA_ANY(string);	if (encoding == PG_UTF8 && *data > 127)	{		/* return the code point for Unicode */		int			result = 0,					tbytes = 0,					i;		if (*data >= 0xF0)		{			result = *data & 0x07;			tbytes = 3;		}		else if (*data >= 0xE0)		{			result = *data & 0x0F;			tbytes = 2;		}		else		{			Assert(*data > 0xC0);			result = *data & 0x1f;			tbytes = 1;		}		Assert(tbytes > 0);		for (i = 1; i <= tbytes; i++)		{			Assert((data[i] & 0xC0) == 0x80);			result = (result << 6) + (data[i] & 0x3f);		}		PG_RETURN_INT32(result);	}	else	{		if (pg_encoding_max_length(encoding) > 1 && *data > 127)			ereport(ERROR,					(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),					 errmsg("requested character too large")));		PG_RETURN_INT32((int32) *data);	}}/******************************************************************** * * chr * * Syntax: * *	 text chr(int val) * * Purpose: * *	Returns the character having the binary equivalent to val. * * For UTF8 we treat the argumwent as a Unicode code point. * For other multi-byte encodings we raise an error for arguments * outside the strict ASCII range (1..127). * * It's important that we don't ever return a value that is not valid * in the database encoding, so that this doesn't become a way for * invalid data to enter the database. * ********************************************************************/Datumchr			(PG_FUNCTION_ARGS){	uint32		cvalue = PG_GETARG_UINT32(0);	text	   *result;	int			encoding = GetDatabaseEncoding();	if (encoding == PG_UTF8 && cvalue > 127)	{		/* for Unicode we treat the argument as a code point */		int			bytes;		char	   *wch;		/* We only allow valid Unicode code points */		if (cvalue > 0x001fffff)			ereport(ERROR,					(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),					 errmsg("requested character too large for encoding: %d",							cvalue)));		if (cvalue > 0xffff)			bytes = 4;		else if (cvalue > 0x07ff)			bytes = 3;		else			bytes = 2;		result = (text *) palloc(VARHDRSZ + bytes);		SET_VARSIZE(result, VARHDRSZ + bytes);		wch = VARDATA(result);		if (bytes == 2)		{			wch[0] = 0xC0 | ((cvalue >> 6) & 0x1F);			wch[1] = 0x80 | (cvalue & 0x3F);;		}		else if (bytes == 3)		{			wch[0] = 0xE0 | ((cvalue >> 12) & 0x0F);			wch[1] = 0x80 | ((cvalue >> 6) & 0x3F);			wch[2] = 0x80 | (cvalue & 0x3F);		}		else		{			wch[0] = 0xF0 | ((cvalue >> 18) & 0x07);			wch[1] = 0x80 | ((cvalue >> 12) & 0x3F);			wch[2] = 0x80 | ((cvalue >> 6) & 0x3F);			wch[3] = 0x80 | (cvalue & 0x3F);		}	}	else	{		bool		is_mb;		/*		 * Error out on arguments that make no sense or that we can't validly		 * represent in the encoding.		 */		if (cvalue == 0)			ereport(ERROR,					(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),					 errmsg("null character not permitted")));		is_mb = pg_encoding_max_length(encoding) > 1;		if ((is_mb && (cvalue > 127)) || (!is_mb && (cvalue > 255)))			ereport(ERROR,					(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),					 errmsg("requested character too large for encoding: %d",							cvalue)));		result = (text *) palloc(VARHDRSZ + 1);		SET_VARSIZE(result, VARHDRSZ + 1);		*VARDATA(result) = (char) cvalue;	}	PG_RETURN_TEXT_P(result);}/******************************************************************** * * repeat * * Syntax: * *	 text repeat(text string, int val) * * Purpose: * *	Repeat string by val. * ********************************************************************/Datumrepeat(PG_FUNCTION_ARGS){	text	   *string = PG_GETARG_TEXT_PP(0);	int32		count = PG_GETARG_INT32(1);	text	   *result;	int			slen,				tlen;	int			i;	char	   *cp,			   *sp;	if (count < 0)		count = 0;	slen = VARSIZE_ANY_EXHDR(string);	tlen = VARHDRSZ + (count * slen);	/* Check for integer overflow */	if (slen != 0 && count != 0)	{		int			check = count * slen;		int			check2 = check + VARHDRSZ;		if ((check / slen) != count || check2 <= check)			ereport(ERROR,					(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),					 errmsg("requested length too large")));	}	result = (text *) palloc(tlen);	SET_VARSIZE(result, tlen);	cp = VARDATA(result);	sp = VARDATA_ANY(string);	for (i = 0; i < count; i++)	{		memcpy(cp, sp, slen);		cp += slen;	}	PG_RETURN_TEXT_P(result);}

⌨️ 快捷键说明

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