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

📄 varchar.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 2 页
字号:
/*------------------------------------------------------------------------- * * varchar.c *	  Functions for the built-in types char(n) and varchar(n). * * Portions Copyright (c) 1996-2005, 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.113.2.2 2006/05/21 20:05:48 tgl Exp $ * *------------------------------------------------------------------------- */#include "postgres.h"#include "access/hash.h"#include "catalog/pg_type.h"#include "lib/stringinfo.h"#include "libpq/pqformat.h"#include "miscadmin.h"#include "utils/array.h"#include "utils/builtins.h"#include "utils/fmgroids.h"#include "mb/pg_wchar.h"/* * 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);	VARATT_SIZEP(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_P(0);	char	   *result;	int			len;	/* copy and add null term */	len = VARSIZE(s) - VARHDRSZ;	result = (char *) palloc(len + 1);	memcpy(result, VARDATA(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_P(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);	len = VARSIZE(source);	charlen = pg_mbstrlen_with_len(VARDATA(source), len - VARHDRSZ) + VARHDRSZ;	/* 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(VARDATA(source), len - VARHDRSZ,									maxlen - VARHDRSZ) + VARHDRSZ;		if (!isExplicit)		{			for (i = maxmblen - VARHDRSZ; i < len - VARHDRSZ; i++)				if (*(VARDATA(source) + i) != ' ')					ereport(ERROR,							(errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION),							 errmsg("value too long for type character(%d)",									maxlen - VARHDRSZ)));		}		len = maxmblen;		/*		 * XXX: at this point, maxlen is the necessary byte length+VARHDRSZ,		 * not the number of CHARACTERS!		 */		maxlen = len;	}	else	{		/*		 * XXX: at this point, maxlen is the necessary byte length+VARHDRSZ,		 * not the number of CHARACTERS!		 */		maxlen = len + (maxlen - charlen);	}	s = VARDATA(source);	result = palloc(maxlen);	VARATT_SIZEP(result) = maxlen;	r = VARDATA(result);	memcpy(r, s, len - VARHDRSZ);	/* blank pad the string if necessary */	if (maxlen > len)		memset(r + len - VARHDRSZ, ' ', 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);	VARATT_SIZEP(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_P(0);	Name		result;	int			len;	len = VARSIZE(s) - VARHDRSZ;	/* Truncate to max length for a Name */	if (len >= NAMEDATALEN)		len = NAMEDATALEN - 1;	/* Remove trailing blanks */	while (len > 0)	{		if (*(VARDATA(s) + len - 1) != ' ')			break;		len--;	}	result = (NameData *) palloc(NAMEDATALEN);	memcpy(NameStr(*result), VARDATA(s), 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);	VARATT_SIZEP(result) = len + VARHDRSZ;	PG_RETURN_BPCHAR_P(result);}/***************************************************************************** *	 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. * * 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 VarChar *varchar_input(const char *s, size_t len, int32 atttypmod){	VarChar    *result;	size_t		maxlen;	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);		size_t		j;		for (j = mbmaxlen; j < len; j++)		{			if (s[j] != ' ')				ereport(ERROR,						(errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION),					  errmsg("value too long for type character varying(%d)",							 (int) maxlen)));

⌨️ 快捷键说明

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