varchar.c
来自「PostgreSQL7.4.6 for Linux」· C语言 代码 · 共 713 行 · 第 1/2 页
C
713 行
/*------------------------------------------------------------------------- * * varchar.c * Functions for the built-in types char(n) and varchar(n). * * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION * $Header: /cvsroot/pgsql/src/backend/utils/adt/varchar.c,v 1.102 2003/08/04 04:03:10 tgl Exp $ * *------------------------------------------------------------------------- */#include "postgres.h"#include "access/hash.h"#include "catalog/pg_type.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 string * must be null-terminated. * * 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() * *****************************************************************************//* * Convert a C string to CHARACTER internal representation. atttypmod * is the declared length of the type plus VARHDRSZ. * * If the C string is too long, raise an error, unless the extra * characters are spaces, in which case they're truncated. (per SQL) */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; char *r; size_t len, maxlen; int i; int charlen; /* number of charcters in the input string */ /* verify encoding */ len = strlen(s); pg_verifymbstr(s, len, false); charlen = pg_mbstrlen(s); /* If typmod is -1 (or invalid), use the actual string length */ if (atttypmod < (int32) VARHDRSZ) maxlen = charlen; else maxlen = atttypmod - VARHDRSZ; if (charlen > maxlen) { /* Verify that extra characters are spaces, and clip them off */ size_t mbmaxlen = pg_mbcharcliplen(s, len, maxlen); /* * 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. */ if (strspn(s + mbmaxlen, " ") == len - mbmaxlen) len = mbmaxlen; else ereport(ERROR, (errcode(ERRCODE_STRING_DATA_LENGTH_MISMATCH), errmsg("value too long for type character(%d)", (int) maxlen))); /* * XXX: at this point, maxlen is the necessary byte length, not * the number of CHARACTERS! */ maxlen = len; } else { /* * XXX: at this point, maxlen is the necessary byte length, not * the number of CHARACTERS! */ maxlen = len + (maxlen - charlen); } result = palloc(maxlen + VARHDRSZ); VARATT_SIZEP(result) = maxlen + VARHDRSZ; r = VARDATA(result); for (i = 0; i < len; i++) *r++ = *s++; /* blank pad the string if necessary */ for (; i < maxlen; i++) *r++ = ' '; 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){ /* Exactly the same as textrecv, so share code */ return textrecv(fcinfo);}/* * 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 charcters in the input string * + VARHDRSZ */ len = VARSIZE(source); charlen = pg_mbstrlen_with_len(VARDATA(source), len - VARHDRSZ) + VARHDRSZ; /* No work if typmod is invalid or supplied data matches it already */ if (maxlen < (int32) VARHDRSZ || 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_LENGTH_MISMATCH), 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); for (i = 0; i < len - VARHDRSZ; i++) *r++ = *s++; /* blank pad the string if necessary */ for (; i < maxlen - VARHDRSZ; i++) *r++ = ' '; 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. *****************************************************************************//* * Convert a C string to VARCHAR internal representation. atttypmod * is the declared length of the type plus VARHDRSZ. * * Note that atttypmod is regarded as the number of characters, which * is not necessarily the same as the number of bytes. * * If the C string is too long, raise an error, unless the extra characters * are spaces, in which case they're truncated. (per SQL) */Datumvarcharin(PG_FUNCTION_ARGS){ char *s = PG_GETARG_CSTRING(0);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?