📄 varchar.c
字号:
* * 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))); } len = mbmaxlen; } result = (VarChar *) palloc(len + VARHDRSZ); SET_VARSIZE(result, len + VARHDRSZ); memcpy(VARDATA(result), s, len); return result;}/* * Convert a C string to VARCHAR internal representation. atttypmod * is the declared length of the type plus VARHDRSZ. */Datumvarcharin(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); VarChar *result; result = varchar_input(s, strlen(s), atttypmod); PG_RETURN_VARCHAR_P(result);}/* * Convert a VARCHAR value to a C string. */Datumvarcharout(PG_FUNCTION_ARGS){ VarChar *s = PG_GETARG_VARCHAR_PP(0); char *result; int32 len; /* copy and add null term */ len = VARSIZE_ANY_EXHDR(s); result = palloc(len + 1); memcpy(result, VARDATA_ANY(s), len); result[len] = '\0'; PG_RETURN_CSTRING(result);}/* * varcharrecv - converts external binary format to varchar */Datumvarcharrecv(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); VarChar *result; char *str; int nbytes; str = pq_getmsgtext(buf, buf->len - buf->cursor, &nbytes); result = varchar_input(str, nbytes, atttypmod); pfree(str); PG_RETURN_VARCHAR_P(result);}/* * 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_PP(0); int32 typmod = PG_GETARG_INT32(1); bool isExplicit = PG_GETARG_BOOL(2); VarChar *result; int32 len, maxlen; size_t maxmblen; int i; char *s_data; len = VARSIZE_ANY_EXHDR(source); s_data = VARDATA_ANY(source); maxlen = typmod - VARHDRSZ; /* No work if typmod is invalid or supplied data fits it already */ if (maxlen < 0 || len <= maxlen) PG_RETURN_VARCHAR_P(source); /* only reach here if string is too long... */ /* truncate multibyte string preserving multibyte boundary */ maxmblen = pg_mbcharcliplen(s_data, len, maxlen); if (!isExplicit) { for (i = maxmblen; i < len; i++) if (s_data[i] != ' ') ereport(ERROR, (errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION), errmsg("value too long for type character varying(%d)", maxlen))); } result = palloc(maxmblen + VARHDRSZ); SET_VARSIZE(result, maxmblen + VARHDRSZ); memcpy(VARDATA(result), s_data, maxmblen); PG_RETURN_VARCHAR_P(result);}Datumvarchartypmodin(PG_FUNCTION_ARGS){ ArrayType *ta = PG_GETARG_ARRAYTYPE_P(0); PG_RETURN_INT32(anychar_typmodin(ta, "varchar"));}Datumvarchartypmodout(PG_FUNCTION_ARGS){ int32 typmod = PG_GETARG_INT32(0); PG_RETURN_CSTRING(anychar_typmodout(typmod));}/***************************************************************************** * Exported functions *****************************************************************************//* "True" length (not counting trailing blanks) of a BpChar */static intbcTruelen(BpChar *arg){ char *s = VARDATA_ANY(arg); int i; int len; len = VARSIZE_ANY_EXHDR(arg); for (i = len - 1; i >= 0; i--) { if (s[i] != ' ') break; } return i + 1;}Datumbpcharlen(PG_FUNCTION_ARGS){ BpChar *arg = PG_GETARG_BPCHAR_PP(0); int len; /* get number of bytes, ignoring trailing spaces */ len = bcTruelen(arg); /* in multibyte encoding, convert to number of characters */ if (pg_database_encoding_max_length() != 1) len = pg_mbstrlen_with_len(VARDATA_ANY(arg), len); PG_RETURN_INT32(len);}Datumbpcharoctetlen(PG_FUNCTION_ARGS){ Datum arg = PG_GETARG_DATUM(0); /* We need not detoast the input at all */ PG_RETURN_INT32(toast_raw_datum_size(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_PP(0); BpChar *arg2 = PG_GETARG_BPCHAR_PP(1); int len1, len2; bool result; len1 = bcTruelen(arg1); len2 = bcTruelen(arg2); /* * Since we only care about equality or not-equality, we can avoid all the * expense of strcoll() here, and just do bitwise comparison. */ if (len1 != len2) result = false; else result = (strncmp(VARDATA_ANY(arg1), VARDATA_ANY(arg2), len1) == 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_PP(0); BpChar *arg2 = PG_GETARG_BPCHAR_PP(1); int len1, len2; bool result; len1 = bcTruelen(arg1); len2 = bcTruelen(arg2); /* * Since we only care about equality or not-equality, we can avoid all the * expense of strcoll() here, and just do bitwise comparison. */ if (len1 != len2) result = true; else result = (strncmp(VARDATA_ANY(arg1), VARDATA_ANY(arg2), len1) != 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_PP(0); BpChar *arg2 = PG_GETARG_BPCHAR_PP(1); int len1, len2; int cmp; len1 = bcTruelen(arg1); len2 = bcTruelen(arg2); cmp = varstr_cmp(VARDATA_ANY(arg1), len1, VARDATA_ANY(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_PP(0); BpChar *arg2 = PG_GETARG_BPCHAR_PP(1); int len1, len2; int cmp; len1 = bcTruelen(arg1); len2 = bcTruelen(arg2); cmp = varstr_cmp(VARDATA_ANY(arg1), len1, VARDATA_ANY(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_PP(0); BpChar *arg2 = PG_GETARG_BPCHAR_PP(1); int len1, len2; int cmp; len1 = bcTruelen(arg1); len2 = bcTruelen(arg2); cmp = varstr_cmp(VARDATA_ANY(arg1), len1, VARDATA_ANY(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_PP(0); BpChar *arg2 = PG_GETARG_BPCHAR_PP(1); int len1, len2; int cmp; len1 = bcTruelen(arg1); len2 = bcTruelen(arg2); cmp = varstr_cmp(VARDATA_ANY(arg1), len1, VARDATA_ANY(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_PP(0); BpChar *arg2 = PG_GETARG_BPCHAR_PP(1); int len1, len2; int cmp; len1 = bcTruelen(arg1); len2 = bcTruelen(arg2); cmp = varstr_cmp(VARDATA_ANY(arg1), len1, VARDATA_ANY(arg2), len2); PG_FREE_IF_COPY(arg1, 0); PG_FREE_IF_COPY(arg2, 1); PG_RETURN_INT32(cmp);}Datumbpchar_larger(PG_FUNCTION_ARGS){ BpChar *arg1 = PG_GETARG_BPCHAR_PP(0); BpChar *arg2 = PG_GETARG_BPCHAR_PP(1); int len1, len2; int cmp; len1 = bcTruelen(arg1); len2 = bcTruelen(arg2); cmp = varstr_cmp(VARDATA_ANY(arg1), len1, VARDATA_ANY(arg2), len2); PG_RETURN_BPCHAR_P((cmp >= 0) ? arg1 : arg2);}Datumbpchar_smaller(PG_FUNCTION_ARGS){ BpChar *arg1 = PG_GETARG_BPCHAR_PP(0); BpChar *arg2 = PG_GETARG_BPCHAR_PP(1); int len1, len2; int cmp; len1 = bcTruelen(arg1); len2 = bcTruelen(arg2); cmp = varstr_cmp(VARDATA_ANY(arg1), len1, VARDATA_ANY(arg2), len2); PG_RETURN_BPCHAR_P((cmp <= 0) ? arg1 : arg2);}/* * bpchar needs a specialized hash function because we want to ignore * trailing blanks in comparisons. * * Note: currently there is no need for locale-specific behavior here, * but if we ever change the semantics of bpchar comparison to trust * strcoll() completely, we'd need to do something different in non-C locales. */Datumhashbpchar(PG_FUNCTION_ARGS){ BpChar *key = PG_GETARG_BPCHAR_PP(0); char *keydata; int keylen; Datum result; keydata = VARDATA_ANY(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 + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -