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 + -
显示快捷键?