diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2000-07-29 03:26:51 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2000-07-29 03:26:51 +0000 |
commit | 1ebe1da296419b07377058ffad0e75bb330de8d1 (patch) | |
tree | 1f67ea127b88b997c82e9e57ad139bece91c806c /src/backend/utils/adt/varchar.c | |
parent | 20f6a1e56268f490ac2ac436e199e411de430f51 (diff) | |
download | postgresql-1ebe1da296419b07377058ffad0e75bb330de8d1.tar.gz postgresql-1ebe1da296419b07377058ffad0e75bb330de8d1.zip |
bpchar, varchar, bytea, numeric are toastable --- if you initdb, which
I did not force. I marked numeric as compressable-but-not-move-off-able,
partly to test that storage mode and partly because I've got doubts
that numerics are large enough to need external storage.
Diffstat (limited to 'src/backend/utils/adt/varchar.c')
-rw-r--r-- | src/backend/utils/adt/varchar.c | 393 |
1 files changed, 213 insertions, 180 deletions
diff --git a/src/backend/utils/adt/varchar.c b/src/backend/utils/adt/varchar.c index 58b24f339e1..804ab8c5caa 100644 --- a/src/backend/utils/adt/varchar.c +++ b/src/backend/utils/adt/varchar.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/varchar.c,v 1.68 2000/07/07 21:12:50 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/varchar.c,v 1.69 2000/07/29 03:26:42 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -260,19 +260,20 @@ char_bpchar(PG_FUNCTION_ARGS) /* bpchar_name() * Converts a bpchar() type to a NameData type. */ -NameData * -bpchar_name(char *s) +Datum +bpchar_name(PG_FUNCTION_ARGS) { - NameData *result; + BpChar *s = PG_GETARG_BPCHAR_P(0); + Name result; int len; - if (s == NULL) - return NULL; - 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) != ' ') @@ -280,49 +281,36 @@ bpchar_name(char *s) len--; } -#ifdef STRINGDEBUG - printf("bpchar- convert string length %d (%d) ->%d\n", - VARSIZE(s) - VARHDRSZ, VARSIZE(s), len); -#endif - result = (NameData *) palloc(NAMEDATALEN); memcpy(NameStr(*result), VARDATA(s), len); - /* now null pad to full length... */ + /* Now null pad to full length... */ while (len < NAMEDATALEN) { *(NameStr(*result) + len) = '\0'; len++; } - return result; -} /* bpchar_name() */ + PG_RETURN_NAME(result); +} /* name_bpchar() * Converts a NameData type to a bpchar type. */ -char * -name_bpchar(NameData *s) +Datum +name_bpchar(PG_FUNCTION_ARGS) { - char *result; + Name s = PG_GETARG_NAME(0); + BpChar *result; int len; - if (s == NULL) - return NULL; - len = strlen(NameStr(*s)); - -#ifdef STRINGDEBUG - printf("bpchar- convert string length %d (%d) ->%d\n", - VARSIZE(s) - VARHDRSZ, VARSIZE(s), len); -#endif - - result = (char *) palloc(VARHDRSZ + len); + result = (BpChar *) palloc(VARHDRSZ + len); memcpy(VARDATA(result), NameStr(*s), len); VARATT_SIZEP(result) = len + VARHDRSZ; - return result; -} /* name_bpchar() */ + PG_RETURN_BPCHAR_P(result); +} /***************************************************************************** @@ -446,13 +434,9 @@ _varchar(PG_FUNCTION_ARGS) return array_map(&locfcinfo, VARCHAROID, VARCHAROID); } - -/***************************************************************************** - * Comparison Functions used for bpchar - *****************************************************************************/ - +/* "True" length (not counting trailing blanks) of a BpChar */ static int -bcTruelen(char *arg) +bcTruelen(BpChar *arg) { char *s = VARDATA(arg); int i; @@ -467,19 +451,16 @@ bcTruelen(char *arg) return i + 1; } -int32 -bpcharlen(char *arg) +Datum +bpcharlen(PG_FUNCTION_ARGS) { + BpChar *arg = PG_GETARG_BPCHAR_P(0); #ifdef MULTIBYTE unsigned char *s; int len, l, wl; -#endif - if (!PointerIsValid(arg)) - elog(ERROR, "Bad (null) char() external representation"); -#ifdef MULTIBYTE l = VARSIZE(arg) - VARHDRSZ; len = 0; s = VARDATA(arg); @@ -490,134 +471,160 @@ bpcharlen(char *arg) s += wl; len++; } - return (len); + PG_RETURN_INT32(len); #else - return (VARSIZE(arg) - VARHDRSZ); + PG_RETURN_INT32(VARSIZE(arg) - VARHDRSZ); #endif } -int32 -bpcharoctetlen(char *arg) +Datum +bpcharoctetlen(PG_FUNCTION_ARGS) { - if (!PointerIsValid(arg)) - elog(ERROR, "Bad (null) char() external representation"); + BpChar *arg = PG_GETARG_BPCHAR_P(0); - return (VARSIZE(arg) - VARHDRSZ); + PG_RETURN_INT32(VARSIZE(arg) - VARHDRSZ); } -bool -bpchareq(char *arg1, char *arg2) + +/***************************************************************************** + * 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. + *****************************************************************************/ + +Datum +bpchareq(PG_FUNCTION_ARGS) { + BpChar *arg1 = PG_GETARG_BPCHAR_P(0); + BpChar *arg2 = PG_GETARG_BPCHAR_P(1); int len1, len2; + bool result; - if (arg1 == NULL || arg2 == NULL) - return (bool) 0; len1 = bcTruelen(arg1); len2 = bcTruelen(arg2); if (len1 != len2) - return 0; + result = false; + else + result = (strncmp(VARDATA(arg1), VARDATA(arg2), len1) == 0); - return strncmp(VARDATA(arg1), VARDATA(arg2), len1) == 0; + PG_FREE_IF_COPY(arg1, 0); + PG_FREE_IF_COPY(arg2, 1); + + PG_RETURN_BOOL(result); } -bool -bpcharne(char *arg1, char *arg2) +Datum +bpcharne(PG_FUNCTION_ARGS) { + BpChar *arg1 = PG_GETARG_BPCHAR_P(0); + BpChar *arg2 = PG_GETARG_BPCHAR_P(1); int len1, len2; + bool result; - if (arg1 == NULL || arg2 == NULL) - return (bool) 0; len1 = bcTruelen(arg1); len2 = bcTruelen(arg2); if (len1 != len2) - return 1; + result = true; + else + result = (strncmp(VARDATA(arg1), VARDATA(arg2), len1) != 0); + + PG_FREE_IF_COPY(arg1, 0); + PG_FREE_IF_COPY(arg2, 1); - return strncmp(VARDATA(arg1), VARDATA(arg2), len1) != 0; + PG_RETURN_BOOL(result); } -bool -bpcharlt(char *arg1, char *arg2) +Datum +bpcharlt(PG_FUNCTION_ARGS) { + BpChar *arg1 = PG_GETARG_BPCHAR_P(0); + BpChar *arg2 = PG_GETARG_BPCHAR_P(1); int len1, len2; int cmp; - if (arg1 == NULL || arg2 == NULL) - return (bool) 0; len1 = bcTruelen(arg1); len2 = bcTruelen(arg2); cmp = varstr_cmp(VARDATA(arg1), len1, VARDATA(arg2), len2); - if (cmp == 0) - return len1 < len2; - else - return cmp < 0; + + PG_FREE_IF_COPY(arg1, 0); + PG_FREE_IF_COPY(arg2, 1); + + PG_RETURN_BOOL(cmp < 0); } -bool -bpcharle(char *arg1, char *arg2) +Datum +bpcharle(PG_FUNCTION_ARGS) { + BpChar *arg1 = PG_GETARG_BPCHAR_P(0); + BpChar *arg2 = PG_GETARG_BPCHAR_P(1); int len1, len2; int cmp; - if (arg1 == NULL || arg2 == NULL) - return (bool) 0; len1 = bcTruelen(arg1); len2 = bcTruelen(arg2); cmp = varstr_cmp(VARDATA(arg1), len1, VARDATA(arg2), len2); - if (0 == cmp) - return (bool) (len1 <= len2 ? 1 : 0); - else - return (bool) (cmp <= 0); + + PG_FREE_IF_COPY(arg1, 0); + PG_FREE_IF_COPY(arg2, 1); + + PG_RETURN_BOOL(cmp <= 0); } -bool -bpchargt(char *arg1, char *arg2) +Datum +bpchargt(PG_FUNCTION_ARGS) { + BpChar *arg1 = PG_GETARG_BPCHAR_P(0); + BpChar *arg2 = PG_GETARG_BPCHAR_P(1); int len1, len2; int cmp; - if (arg1 == NULL || arg2 == NULL) - return (bool) 0; len1 = bcTruelen(arg1); len2 = bcTruelen(arg2); cmp = varstr_cmp(VARDATA(arg1), len1, VARDATA(arg2), len2); - if (cmp == 0) - return len1 > len2; - else - return cmp > 0; + + PG_FREE_IF_COPY(arg1, 0); + PG_FREE_IF_COPY(arg2, 1); + + PG_RETURN_BOOL(cmp > 0); } -bool -bpcharge(char *arg1, char *arg2) +Datum +bpcharge(PG_FUNCTION_ARGS) { + BpChar *arg1 = PG_GETARG_BPCHAR_P(0); + BpChar *arg2 = PG_GETARG_BPCHAR_P(1); int len1, len2; int cmp; - if (arg1 == NULL || arg2 == NULL) - return (bool) 0; len1 = bcTruelen(arg1); len2 = bcTruelen(arg2); cmp = varstr_cmp(VARDATA(arg1), len1, VARDATA(arg2), len2); - if (0 == cmp) - return (bool) (len1 >= len2 ? 1 : 0); - else - return (bool) (cmp >= 0); + + PG_FREE_IF_COPY(arg1, 0); + PG_FREE_IF_COPY(arg2, 1); + + PG_RETURN_BOOL(cmp >= 0); } -int32 -bpcharcmp(char *arg1, char *arg2) +Datum +bpcharcmp(PG_FUNCTION_ARGS) { + BpChar *arg1 = PG_GETARG_BPCHAR_P(0); + BpChar *arg2 = PG_GETARG_BPCHAR_P(1); int len1, len2; int cmp; @@ -626,30 +633,46 @@ bpcharcmp(char *arg1, char *arg2) len2 = bcTruelen(arg2); cmp = varstr_cmp(VARDATA(arg1), len1, VARDATA(arg2), len2); - if ((0 == cmp) && (len1 != len2)) - return (int32) (len1 < len2 ? -1 : 1); - else - return cmp; + + 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. (varchar can use plain hashvarlena.) + */ +Datum +hashbpchar(PG_FUNCTION_ARGS) +{ + BpChar *key = PG_GETARG_BPCHAR_P(0); + char *keydata; + int keylen; + + keydata = VARDATA(key); + keylen = bcTruelen(key); + + return hash_any(keydata, keylen); +} + + /***************************************************************************** - * Comparison Functions used for varchar + * Functions used for varchar *****************************************************************************/ -int32 -varcharlen(char *arg) +Datum +varcharlen(PG_FUNCTION_ARGS) { + VarChar *arg = PG_GETARG_VARCHAR_P(0); #ifdef MULTIBYTE unsigned char *s; int len, l, wl; -#endif - if (!PointerIsValid(arg)) - elog(ERROR, "Bad (null) varchar() external representation"); - -#ifdef MULTIBYTE len = 0; s = VARDATA(arg); l = VARSIZE(arg) - VARHDRSZ; @@ -660,161 +683,171 @@ varcharlen(char *arg) s += wl; len++; } - return (len); + PG_RETURN_INT32(len); #else - return VARSIZE(arg) - VARHDRSZ; + PG_RETURN_INT32(VARSIZE(arg) - VARHDRSZ); #endif } -int32 -varcharoctetlen(char *arg) +Datum +varcharoctetlen(PG_FUNCTION_ARGS) { - if (!PointerIsValid(arg)) - elog(ERROR, "Bad (null) varchar() external representation"); - return VARSIZE(arg) - VARHDRSZ; + VarChar *arg = PG_GETARG_VARCHAR_P(0); + + PG_RETURN_INT32(VARSIZE(arg) - VARHDRSZ); } -bool -varchareq(char *arg1, char *arg2) + +/***************************************************************************** + * Comparison Functions used for varchar + * + * 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. + *****************************************************************************/ + +Datum +varchareq(PG_FUNCTION_ARGS) { + VarChar *arg1 = PG_GETARG_VARCHAR_P(0); + VarChar *arg2 = PG_GETARG_VARCHAR_P(1); int len1, len2; - - if (arg1 == NULL || arg2 == NULL) - return (bool) 0; + bool result; len1 = VARSIZE(arg1) - VARHDRSZ; len2 = VARSIZE(arg2) - VARHDRSZ; if (len1 != len2) - return 0; + result = false; + else + result = (strncmp(VARDATA(arg1), VARDATA(arg2), len1) == 0); - return strncmp(VARDATA(arg1), VARDATA(arg2), len1) == 0; + PG_FREE_IF_COPY(arg1, 0); + PG_FREE_IF_COPY(arg2, 1); + + PG_RETURN_BOOL(result); } -bool -varcharne(char *arg1, char *arg2) +Datum +varcharne(PG_FUNCTION_ARGS) { + VarChar *arg1 = PG_GETARG_VARCHAR_P(0); + VarChar *arg2 = PG_GETARG_VARCHAR_P(1); int len1, len2; + bool result; - if (arg1 == NULL || arg2 == NULL) - return (bool) 0; len1 = VARSIZE(arg1) - VARHDRSZ; len2 = VARSIZE(arg2) - VARHDRSZ; if (len1 != len2) - return 1; + result = true; + else + result = (strncmp(VARDATA(arg1), VARDATA(arg2), len1) != 0); + + PG_FREE_IF_COPY(arg1, 0); + PG_FREE_IF_COPY(arg2, 1); - return strncmp(VARDATA(arg1), VARDATA(arg2), len1) != 0; + PG_RETURN_BOOL(result); } -bool -varcharlt(char *arg1, char *arg2) +Datum +varcharlt(PG_FUNCTION_ARGS) { + VarChar *arg1 = PG_GETARG_VARCHAR_P(0); + VarChar *arg2 = PG_GETARG_VARCHAR_P(1); int len1, len2; int cmp; - if (arg1 == NULL || arg2 == NULL) - return (bool) 0; len1 = VARSIZE(arg1) - VARHDRSZ; len2 = VARSIZE(arg2) - VARHDRSZ; cmp = varstr_cmp(VARDATA(arg1), len1, VARDATA(arg2), len2); - if (cmp == 0) - return len1 < len2; - else - return cmp < 0; + + PG_FREE_IF_COPY(arg1, 0); + PG_FREE_IF_COPY(arg2, 1); + + PG_RETURN_BOOL(cmp < 0); } -bool -varcharle(char *arg1, char *arg2) +Datum +varcharle(PG_FUNCTION_ARGS) { + VarChar *arg1 = PG_GETARG_VARCHAR_P(0); + VarChar *arg2 = PG_GETARG_VARCHAR_P(1); int len1, len2; int cmp; - if (arg1 == NULL || arg2 == NULL) - return (bool) 0; len1 = VARSIZE(arg1) - VARHDRSZ; len2 = VARSIZE(arg2) - VARHDRSZ; cmp = varstr_cmp(VARDATA(arg1), len1, VARDATA(arg2), len2); - if (0 == cmp) - return (bool) (len1 <= len2 ? 1 : 0); - else - return (bool) (cmp <= 0); + + PG_FREE_IF_COPY(arg1, 0); + PG_FREE_IF_COPY(arg2, 1); + + PG_RETURN_BOOL(cmp <= 0); } -bool -varchargt(char *arg1, char *arg2) +Datum +varchargt(PG_FUNCTION_ARGS) { + VarChar *arg1 = PG_GETARG_VARCHAR_P(0); + VarChar *arg2 = PG_GETARG_VARCHAR_P(1); int len1, len2; int cmp; - if (arg1 == NULL || arg2 == NULL) - return (bool) 0; len1 = VARSIZE(arg1) - VARHDRSZ; len2 = VARSIZE(arg2) - VARHDRSZ; cmp = varstr_cmp(VARDATA(arg1), len1, VARDATA(arg2), len2); - if (cmp == 0) - return len1 > len2; - else - return cmp > 0; + + PG_FREE_IF_COPY(arg1, 0); + PG_FREE_IF_COPY(arg2, 1); + + PG_RETURN_BOOL(cmp > 0); } -bool -varcharge(char *arg1, char *arg2) +Datum +varcharge(PG_FUNCTION_ARGS) { + VarChar *arg1 = PG_GETARG_VARCHAR_P(0); + VarChar *arg2 = PG_GETARG_VARCHAR_P(1); int len1, len2; int cmp; - if (arg1 == NULL || arg2 == NULL) - return (bool) 0; len1 = VARSIZE(arg1) - VARHDRSZ; len2 = VARSIZE(arg2) - VARHDRSZ; cmp = varstr_cmp(VARDATA(arg1), len1, VARDATA(arg2), len2); - if (0 == cmp) - return (bool) (len1 >= len2 ? 1 : 0); - else - return (bool) (cmp >= 0); + PG_FREE_IF_COPY(arg1, 0); + PG_FREE_IF_COPY(arg2, 1); + + PG_RETURN_BOOL(cmp >= 0); } -int32 -varcharcmp(char *arg1, char *arg2) +Datum +varcharcmp(PG_FUNCTION_ARGS) { + VarChar *arg1 = PG_GETARG_VARCHAR_P(0); + VarChar *arg2 = PG_GETARG_VARCHAR_P(1); int len1, len2; int cmp; len1 = VARSIZE(arg1) - VARHDRSZ; len2 = VARSIZE(arg2) - VARHDRSZ; - cmp = varstr_cmp(VARDATA(arg1), len1, VARDATA(arg2), len2); - if ((0 == cmp) && (len1 != len2)) - return (int32) (len1 < len2 ? -1 : 1); - else - return (int32) (cmp); -} -/* - * bpchar needs a specialized hash function because we want to ignore - * trailing blanks in comparisons. (varchar can use plain hashvarlena.) - */ -Datum -hashbpchar(PG_FUNCTION_ARGS) -{ - BpChar *key = PG_GETARG_BPCHAR_P(0); - char *keydata; - int keylen; + cmp = varstr_cmp(VARDATA(arg1), len1, VARDATA(arg2), len2); - keydata = VARDATA(key); - keylen = bcTruelen((char *) key); + PG_FREE_IF_COPY(arg1, 0); + PG_FREE_IF_COPY(arg2, 1); - return hash_any(keydata, keylen); + PG_RETURN_INT32(cmp); } |