📄 varchar.c
字号:
} len = mbmaxlen; } result = (VarChar *) palloc(len + VARHDRSZ); VARATT_SIZEP(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_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){ 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_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_RIGHT_TRUNCATION), 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); 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(arg), len); PG_RETURN_INT32(len);}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); /* * 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(arg1), VARDATA(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_P(0); BpChar *arg2 = PG_GETARG_BPCHAR_P(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(arg1), VARDATA(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_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);}Datumbpchar_larger(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_RETURN_BPCHAR_P((cmp >= 0) ? arg1 : arg2);}Datumbpchar_smaller(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_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_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 + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -