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

📄 varchar.c

📁 postgresql8.3.4源码,开源数据库
💻 C
📖 第 1 页 / 共 2 页
字号:
/*------------------------------------------------------------------------- * * varchar.c *	  Functions for the built-in types char(n) and varchar(n). * * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION *	  $PostgreSQL: pgsql/src/backend/utils/adt/varchar.c,v 1.126 2008/01/01 19:45:53 momjian Exp $ * *------------------------------------------------------------------------- */#include "postgres.h"#include "access/hash.h"#include "access/tuptoaster.h"#include "libpq/pqformat.h"#include "utils/array.h"#include "utils/builtins.h"#include "mb/pg_wchar.h"/* common code for bpchartypmodin and varchartypmodin */static int32anychar_typmodin(ArrayType *ta, const char *typename){	int32		typmod;	int32	   *tl;	int			n;	tl = ArrayGetIntegerTypmods(ta, &n);	/*	 * we're not too tense about good error message here because grammar	 * shouldn't allow wrong number of modifiers for CHAR	 */	if (n != 1)		ereport(ERROR,				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),				 errmsg("invalid type modifier")));	if (*tl < 1)		ereport(ERROR,				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),				 errmsg("length for type %s must be at least 1", typename)));	if (*tl > MaxAttrSize)		ereport(ERROR,				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),				 errmsg("length for type %s cannot exceed %d",						typename, MaxAttrSize)));	/*	 * For largely historical reasons, the typmod is VARHDRSZ plus the number	 * of characters; there is enough client-side code that knows about that	 * that we'd better not change it.	 */	typmod = VARHDRSZ + *tl;	return typmod;}/* common code for bpchartypmodout and varchartypmodout */static char *anychar_typmodout(int32 typmod){	char	   *res = (char *) palloc(64);	if (typmod > VARHDRSZ)		snprintf(res, 64, "(%d)", (int) (typmod - VARHDRSZ));	else		*res = '\0';	return res;}/* * CHAR() and VARCHAR() types are part of the ANSI SQL standard. CHAR() * is for blank-padded string whose length is specified in CREATE TABLE. * VARCHAR is for storing string whose length is at most the length specified * at CREATE TABLE time. * * It's hard to implement these types because we cannot figure out * the length of the type from the type itself. I changed (hopefully all) the * fmgr calls that invoke input functions of a data type to supply the * length also. (eg. in INSERTs, we have the tupleDescriptor which contains * the length of the attributes and hence the exact length of the char() or * varchar(). We pass this to bpcharin() or varcharin().) In the case where * we cannot determine the length, we pass in -1 instead and the input * converter does not enforce any length check. * * We actually implement this as a varlena so that we don't have to pass in * the length for the comparison functions. (The difference between these * types and "text" is that we truncate and possibly blank-pad the string * at insertion time.) * *															  - ay 6/95 *//***************************************************************************** *	 bpchar - char()														 * *****************************************************************************//* * bpchar_input -- common guts of bpcharin and bpcharrecv * * s is the input text of length len (may not be null-terminated) * atttypmod is the typmod value to apply * * Note that atttypmod is measured in characters, which * is not necessarily the same as the number of bytes. * * If the input string is too long, raise an error, unless the extra * characters are spaces, in which case they're truncated.  (per SQL) */static BpChar *bpchar_input(const char *s, size_t len, int32 atttypmod){	BpChar	   *result;	char	   *r;	size_t		maxlen;	/* If typmod is -1 (or invalid), use the actual string length */	if (atttypmod < (int32) VARHDRSZ)		maxlen = len;	else	{		size_t		charlen;	/* number of CHARACTERS in the input */		maxlen = atttypmod - VARHDRSZ;		charlen = pg_mbstrlen_with_len(s, len);		if (charlen > maxlen)		{			/* Verify that extra characters are spaces, and clip them off */			size_t		mbmaxlen = pg_mbcharcliplen(s, len, maxlen);			size_t		j;			/*			 * at this point, len is the actual BYTE length of the input			 * string, maxlen is the max number of CHARACTERS allowed for this			 * bpchar type, mbmaxlen is the length in BYTES of those chars.			 */			for (j = mbmaxlen; j < len; j++)			{				if (s[j] != ' ')					ereport(ERROR,							(errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION),							 errmsg("value too long for type character(%d)",									(int) maxlen)));			}			/*			 * Now we set maxlen to the necessary byte length, not the number			 * of CHARACTERS!			 */			maxlen = len = mbmaxlen;		}		else		{			/*			 * Now we set maxlen to the necessary byte length, not the number			 * of CHARACTERS!			 */			maxlen = len + (maxlen - charlen);		}	}	result = (BpChar *) palloc(maxlen + VARHDRSZ);	SET_VARSIZE(result, maxlen + VARHDRSZ);	r = VARDATA(result);	memcpy(r, s, len);	/* blank pad the string if necessary */	if (maxlen > len)		memset(r + len, ' ', maxlen - len);	return result;}/* * Convert a C string to CHARACTER internal representation.  atttypmod * is the declared length of the type plus VARHDRSZ. */Datumbpcharin(PG_FUNCTION_ARGS){	char	   *s = PG_GETARG_CSTRING(0);#ifdef NOT_USED	Oid			typelem = PG_GETARG_OID(1);#endif	int32		atttypmod = PG_GETARG_INT32(2);	BpChar	   *result;	result = bpchar_input(s, strlen(s), atttypmod);	PG_RETURN_BPCHAR_P(result);}/* * Convert a CHARACTER value to a C string. */Datumbpcharout(PG_FUNCTION_ARGS){	BpChar	   *s = PG_GETARG_BPCHAR_PP(0);	char	   *result;	int			len;	/* copy and add null term */	len = VARSIZE_ANY_EXHDR(s);	result = (char *) palloc(len + 1);	memcpy(result, VARDATA_ANY(s), len);	result[len] = '\0';	PG_RETURN_CSTRING(result);}/* *		bpcharrecv			- converts external binary format to bpchar */Datumbpcharrecv(PG_FUNCTION_ARGS){	StringInfo	buf = (StringInfo) PG_GETARG_POINTER(0);#ifdef NOT_USED	Oid			typelem = PG_GETARG_OID(1);#endif	int32		atttypmod = PG_GETARG_INT32(2);	BpChar	   *result;	char	   *str;	int			nbytes;	str = pq_getmsgtext(buf, buf->len - buf->cursor, &nbytes);	result = bpchar_input(str, nbytes, atttypmod);	pfree(str);	PG_RETURN_BPCHAR_P(result);}/* *		bpcharsend			- converts bpchar to binary format */Datumbpcharsend(PG_FUNCTION_ARGS){	/* Exactly the same as textsend, so share code */	return textsend(fcinfo);}/* * Converts a CHARACTER 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 char(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.) */Datumbpchar(PG_FUNCTION_ARGS){	BpChar	   *source = PG_GETARG_BPCHAR_PP(0);	int32		maxlen = PG_GETARG_INT32(1);	bool		isExplicit = PG_GETARG_BOOL(2);	BpChar	   *result;	int32		len;	char	   *r;	char	   *s;	int			i;	int			charlen;		/* number of characters in the input string +								 * VARHDRSZ */	/* No work if typmod is invalid */	if (maxlen < (int32) VARHDRSZ)		PG_RETURN_BPCHAR_P(source);	maxlen -= VARHDRSZ;	len = VARSIZE_ANY_EXHDR(source);	s = VARDATA_ANY(source);	charlen = pg_mbstrlen_with_len(s, len);	/* No work if supplied data matches typmod already */	if (charlen == maxlen)		PG_RETURN_BPCHAR_P(source);	if (charlen > maxlen)	{		/* Verify that extra characters are spaces, and clip them off */		size_t		maxmblen;		maxmblen = pg_mbcharcliplen(s, len, maxlen);		if (!isExplicit)		{			for (i = maxmblen; i < len; i++)				if (s[i] != ' ')					ereport(ERROR,							(errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION),							 errmsg("value too long for type character(%d)",									maxlen)));		}		len = maxmblen;		/*		 * At this point, maxlen is the necessary byte length, not the number		 * of CHARACTERS!		 */		maxlen = len;	}	else	{		/*		 * At this point, maxlen is the necessary byte length, not the number		 * of CHARACTERS!		 */		maxlen = len + (maxlen - charlen);	}	Assert(maxlen >= len);	result = palloc(maxlen + VARHDRSZ);	SET_VARSIZE(result, maxlen + VARHDRSZ);	r = VARDATA(result);	memcpy(r, s, len);	/* blank pad the string if necessary */	if (maxlen > len)		memset(r + len, ' ', maxlen - len);	PG_RETURN_BPCHAR_P(result);}/* char_bpchar() * Convert char to bpchar(1). */Datumchar_bpchar(PG_FUNCTION_ARGS){	char		c = PG_GETARG_CHAR(0);	BpChar	   *result;	result = (BpChar *) palloc(VARHDRSZ + 1);	SET_VARSIZE(result, VARHDRSZ + 1);	*(VARDATA(result)) = c;	PG_RETURN_BPCHAR_P(result);}/* bpchar_name() * Converts a bpchar() type to a NameData type. */Datumbpchar_name(PG_FUNCTION_ARGS){	BpChar	   *s = PG_GETARG_BPCHAR_PP(0);	char	   *s_data;	Name		result;	int			len;	len = VARSIZE_ANY_EXHDR(s);	s_data = VARDATA_ANY(s);	/* Truncate to max length for a Name */	if (len >= NAMEDATALEN)		len = NAMEDATALEN - 1;	/* Remove trailing blanks */	while (len > 0)	{		if (s_data[len - 1] != ' ')			break;		len--;	}	result = (NameData *) palloc(NAMEDATALEN);	memcpy(NameStr(*result), s_data, len);	/* Now null pad to full length... */	while (len < NAMEDATALEN)	{		*(NameStr(*result) + len) = '\0';		len++;	}	PG_RETURN_NAME(result);}/* name_bpchar() * Converts a NameData type to a bpchar type. */Datumname_bpchar(PG_FUNCTION_ARGS){	Name		s = PG_GETARG_NAME(0);	BpChar	   *result;	int			len;	len = strlen(NameStr(*s));	result = (BpChar *) palloc(VARHDRSZ + len);	memcpy(VARDATA(result), NameStr(*s), len);	SET_VARSIZE(result, VARHDRSZ + len);	PG_RETURN_BPCHAR_P(result);}Datumbpchartypmodin(PG_FUNCTION_ARGS){	ArrayType  *ta = PG_GETARG_ARRAYTYPE_P(0);	PG_RETURN_INT32(anychar_typmodin(ta, "char"));}Datumbpchartypmodout(PG_FUNCTION_ARGS){	int32		typmod = PG_GETARG_INT32(0);	PG_RETURN_CSTRING(anychar_typmodout(typmod));}/***************************************************************************** *	 varchar - varchar(n) * * Note: varchar piggybacks on type text for most operations, and so has no * C-coded functions except for I/O and typmod checking. *****************************************************************************//* * varchar_input -- common guts of varcharin and varcharrecv * * s is the input text of length len (may not be null-terminated) * atttypmod is the typmod value to apply * * Note that atttypmod is measured in characters, which * is not necessarily the same as the number of bytes.

⌨️ 快捷键说明

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