varchar.c

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

C
713
字号
#ifdef NOT_USED	Oid			typelem = PG_GETARG_OID(1);#endif	int32		atttypmod = PG_GETARG_INT32(2);	VarChar    *result;	size_t		len,				maxlen;	/* verify encoding */	len = strlen(s);	pg_verifymbstr(s, len, false);	maxlen = atttypmod - VARHDRSZ;	if (atttypmod >= (int32) VARHDRSZ && len > maxlen)	{		/* Verify that extra characters are spaces, and clip them off */		size_t		mbmaxlen = pg_mbcharcliplen(s, len, maxlen);		if (strspn(s + mbmaxlen, " ") == len - mbmaxlen)			len = mbmaxlen;		else			ereport(ERROR,					(errcode(ERRCODE_STRING_DATA_LENGTH_MISMATCH),				  errmsg("value too long for type character varying(%d)",						 (int) maxlen)));	}	result = palloc(len + VARHDRSZ);	VARATT_SIZEP(result) = len + VARHDRSZ;	memcpy(VARDATA(result), s, len);	PG_RETURN_VARCHAR_P(result);}/* * Convert a VARCHAR value to a C string. */Datumvarcharout(PG_FUNCTION_ARGS){	VarChar    *s = PG_GETARG_VARCHAR_P(0);	char	   *result;	int32		len;	/* copy and add null term */	len = VARSIZE(s) - VARHDRSZ;	result = palloc(len + 1);	memcpy(result, VARDATA(s), len);	result[len] = '\0';	PG_RETURN_CSTRING(result);}/* *		varcharrecv			- converts external binary format to varchar */Datumvarcharrecv(PG_FUNCTION_ARGS){	/* Exactly the same as textrecv, so share code */	return textrecv(fcinfo);}/* *		varcharsend			- converts varchar to binary format */Datumvarcharsend(PG_FUNCTION_ARGS){	/* Exactly the same as textsend, so share code */	return textsend(fcinfo);}/* * Converts a VARCHAR type to the specified size. * * maxlen is the typmod, ie, declared length plus VARHDRSZ bytes. * isExplicit is true if this is for an explicit cast to varchar(N). * * Truncation rules: for an explicit cast, silently truncate to the given * length; for an implicit cast, raise error unless extra characters are * all spaces.	(This is sort-of per SQL: the spec would actually have us * raise a "completion condition" for the explicit cast case, but Postgres * hasn't got such a concept.) */Datumvarchar(PG_FUNCTION_ARGS){	VarChar    *source = PG_GETARG_VARCHAR_P(0);	int32		maxlen = PG_GETARG_INT32(1);	bool		isExplicit = PG_GETARG_BOOL(2);	VarChar    *result;	int32		len;	size_t		maxmblen;	int			i;	len = VARSIZE(source);	/* No work if typmod is invalid or supplied data fits it already */	if (maxlen < (int32) VARHDRSZ || len <= maxlen)		PG_RETURN_VARCHAR_P(source);	/* only reach here if string is too long... */	/* truncate multibyte string preserving multibyte boundary */	maxmblen = pg_mbcharcliplen(VARDATA(source), len - VARHDRSZ,								maxlen - VARHDRSZ);	if (!isExplicit)	{		for (i = maxmblen; i < len - VARHDRSZ; i++)			if (*(VARDATA(source) + i) != ' ')				ereport(ERROR,						(errcode(ERRCODE_STRING_DATA_LENGTH_MISMATCH),				  errmsg("value too long for type character varying(%d)",						 maxlen - VARHDRSZ)));	}	len = maxmblen + VARHDRSZ;	result = palloc(len);	VARATT_SIZEP(result) = len;	memcpy(VARDATA(result), VARDATA(source), len - VARHDRSZ);	PG_RETURN_VARCHAR_P(result);}/***************************************************************************** * Exported functions *****************************************************************************//* "True" length (not counting trailing blanks) of a BpChar */static intbcTruelen(BpChar *arg){	char	   *s = VARDATA(arg);	int			i;	int			len;	len = VARSIZE(arg) - VARHDRSZ;	for (i = len - 1; i >= 0; i--)	{		if (s[i] != ' ')			break;	}	return i + 1;}Datumbpcharlen(PG_FUNCTION_ARGS){	BpChar	   *arg = PG_GETARG_BPCHAR_P(0);	/* optimization for single byte encoding */	if (pg_database_encoding_max_length() <= 1)		PG_RETURN_INT32(VARSIZE(arg) - VARHDRSZ);	PG_RETURN_INT32(			  pg_mbstrlen_with_len(VARDATA(arg), VARSIZE(arg) - VARHDRSZ)		);}Datumbpcharoctetlen(PG_FUNCTION_ARGS){	BpChar	   *arg = PG_GETARG_BPCHAR_P(0);	PG_RETURN_INT32(VARSIZE(arg) - VARHDRSZ);}/***************************************************************************** *	Comparison Functions used for bpchar * * 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. *****************************************************************************/Datumbpchareq(PG_FUNCTION_ARGS){	BpChar	   *arg1 = PG_GETARG_BPCHAR_P(0);	BpChar	   *arg2 = PG_GETARG_BPCHAR_P(1);	int			len1,				len2;	bool		result;	len1 = bcTruelen(arg1);	len2 = bcTruelen(arg2);	/* fast path for different-length inputs */	if (len1 != len2)		result = false;	else		result = (varstr_cmp(VARDATA(arg1), len1, VARDATA(arg2), len2) == 0);	PG_FREE_IF_COPY(arg1, 0);	PG_FREE_IF_COPY(arg2, 1);	PG_RETURN_BOOL(result);}Datumbpcharne(PG_FUNCTION_ARGS){	BpChar	   *arg1 = PG_GETARG_BPCHAR_P(0);	BpChar	   *arg2 = PG_GETARG_BPCHAR_P(1);	int			len1,				len2;	bool		result;	len1 = bcTruelen(arg1);	len2 = bcTruelen(arg2);	/* fast path for different-length inputs */	if (len1 != len2)		result = true;	else		result = (varstr_cmp(VARDATA(arg1), len1, VARDATA(arg2), len2) != 0);	PG_FREE_IF_COPY(arg1, 0);	PG_FREE_IF_COPY(arg2, 1);	PG_RETURN_BOOL(result);}Datumbpcharlt(PG_FUNCTION_ARGS){	BpChar	   *arg1 = PG_GETARG_BPCHAR_P(0);	BpChar	   *arg2 = PG_GETARG_BPCHAR_P(1);	int			len1,				len2;	int			cmp;	len1 = bcTruelen(arg1);	len2 = bcTruelen(arg2);	cmp = varstr_cmp(VARDATA(arg1), len1, VARDATA(arg2), len2);	PG_FREE_IF_COPY(arg1, 0);	PG_FREE_IF_COPY(arg2, 1);	PG_RETURN_BOOL(cmp < 0);}Datumbpcharle(PG_FUNCTION_ARGS){	BpChar	   *arg1 = PG_GETARG_BPCHAR_P(0);	BpChar	   *arg2 = PG_GETARG_BPCHAR_P(1);	int			len1,				len2;	int			cmp;	len1 = bcTruelen(arg1);	len2 = bcTruelen(arg2);	cmp = varstr_cmp(VARDATA(arg1), len1, VARDATA(arg2), len2);	PG_FREE_IF_COPY(arg1, 0);	PG_FREE_IF_COPY(arg2, 1);	PG_RETURN_BOOL(cmp <= 0);}Datumbpchargt(PG_FUNCTION_ARGS){	BpChar	   *arg1 = PG_GETARG_BPCHAR_P(0);	BpChar	   *arg2 = PG_GETARG_BPCHAR_P(1);	int			len1,				len2;	int			cmp;	len1 = bcTruelen(arg1);	len2 = bcTruelen(arg2);	cmp = varstr_cmp(VARDATA(arg1), len1, VARDATA(arg2), len2);	PG_FREE_IF_COPY(arg1, 0);	PG_FREE_IF_COPY(arg2, 1);	PG_RETURN_BOOL(cmp > 0);}Datumbpcharge(PG_FUNCTION_ARGS){	BpChar	   *arg1 = PG_GETARG_BPCHAR_P(0);	BpChar	   *arg2 = PG_GETARG_BPCHAR_P(1);	int			len1,				len2;	int			cmp;	len1 = bcTruelen(arg1);	len2 = bcTruelen(arg2);	cmp = varstr_cmp(VARDATA(arg1), len1, VARDATA(arg2), len2);	PG_FREE_IF_COPY(arg1, 0);	PG_FREE_IF_COPY(arg2, 1);	PG_RETURN_BOOL(cmp >= 0);}Datumbpcharcmp(PG_FUNCTION_ARGS){	BpChar	   *arg1 = PG_GETARG_BPCHAR_P(0);	BpChar	   *arg2 = PG_GETARG_BPCHAR_P(1);	int			len1,				len2;	int			cmp;	len1 = bcTruelen(arg1);	len2 = bcTruelen(arg2);	cmp = varstr_cmp(VARDATA(arg1), len1, VARDATA(arg2), len2);	PG_FREE_IF_COPY(arg1, 0);	PG_FREE_IF_COPY(arg2, 1);	PG_RETURN_INT32(cmp);}/* * bpchar needs a specialized hash function because we want to ignore * trailing blanks in comparisons. * * XXX is there any need for locale-specific behavior here? */Datumhashbpchar(PG_FUNCTION_ARGS){	BpChar	   *key = PG_GETARG_BPCHAR_P(0);	char	   *keydata;	int			keylen;	Datum		result;	keydata = VARDATA(key);	keylen = bcTruelen(key);	result = hash_any((unsigned char *) keydata, keylen);	/* Avoid leaking memory for toasted inputs */	PG_FREE_IF_COPY(key, 0);	return result;}

⌨️ 快捷键说明

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