diff options
author | Teodor Sigaev <teodor@sigaev.ru> | 2005-07-01 13:44:56 +0000 |
---|---|---|
committer | Teodor Sigaev <teodor@sigaev.ru> | 2005-07-01 13:44:56 +0000 |
commit | ef770cbb6913cc4c816bb09acd7cb13f996281bd (patch) | |
tree | fe973e6aeb9c018d54ea6267f49d5d1b2d5d2f95 /contrib/btree_gist/btree_utils_var.c | |
parent | 8f6e8e8fed372a592f645d8900b6f456db82cc59 (diff) | |
download | postgresql-ef770cbb6913cc4c816bb09acd7cb13f996281bd.tar.gz postgresql-ef770cbb6913cc4c816bb09acd7cb13f996281bd.zip |
Fixes from Janko Richter <jankorichter@yahoo.de>
- Fix wrong index results on text, char, varchar for multibyte strings
- Fix some SIGFPE signals
- Add support for infinite timestamps
- Because of locale settings, btree_gist can not be a prefix index anymore (for text).
Each node holds now just the lower and upper boundary.
Diffstat (limited to 'contrib/btree_gist/btree_utils_var.c')
-rw-r--r-- | contrib/btree_gist/btree_utils_var.c | 162 |
1 files changed, 84 insertions, 78 deletions
diff --git a/contrib/btree_gist/btree_utils_var.c b/contrib/btree_gist/btree_utils_var.c index 720381428f2..8de39bb327b 100644 --- a/contrib/btree_gist/btree_utils_var.c +++ b/contrib/btree_gist/btree_utils_var.c @@ -1,6 +1,7 @@ #include "btree_gist.h" #include "utils/pg_locale.h" #include "btree_utils_var.h" +#include "utils/builtins.h" PG_FUNCTION_INFO_V1(gbt_var_decompress); Datum gbt_var_decompress(PG_FUNCTION_ARGS); @@ -90,69 +91,91 @@ gbt_var_leaf2node(GBT_VARKEY * leaf, const gbtree_vinfo * tinfo) static int32 gbt_var_node_cp_len(const GBT_VARKEY * node, const gbtree_vinfo * tinfo) { - int32 i; - int32 s = (tinfo->str) ? (1) : (0); - GBT_VARKEY_R r = gbt_var_key_readable(node); - int32 t1len = VARSIZE(r.lower) - VARHDRSZ - s; - int32 t2len = VARSIZE(r.upper) - VARHDRSZ - s; - int32 ml = Min(t1len, t2len); - char *p1 = VARDATA(r.lower), - *p2 = VARDATA(r.upper); + GBT_VARKEY_R r = gbt_var_key_readable(node); + int32 i = 0; + int32 l = 0; + int32 t1len = VARSIZE(r.lower) - VARHDRSZ ; + int32 t2len = VARSIZE(r.upper) - VARHDRSZ ; + int32 ml = Min(t1len, t2len); + + char *p1 = VARDATA(r.lower); + char *p2 = VARDATA(r.upper); - for (i = 0; i < ml; i++) + if ( ml == 0 ) + return 0; + + while ( i < ml ) { - if (*p1 != *p2) - return i; - p1++; - p2++; + if ( tinfo->eml > 1 && l == 0 ) + { + + if ( ( l = pg_mblen(p1) ) != pg_mblen(p2) ) + { + return i; + } + } + if (*p1 != *p2) + { + if( tinfo->eml > 1 ) + { + return (i-l+1); + } else { + return i; + } + } + + p1++; + p2++; + l--; + i++; } - return (ml); + return (ml); /* lower == upper */ } - /* - * returns true, if query matches prefix using common prefix + * returns true, if query matches prefix ( common prefix ) */ - static bool gbt_bytea_pf_match(const bytea *pf, const bytea *query, const gbtree_vinfo * tinfo) { - int k; - int32 s = (tinfo->str) ? (1) : (0); - bool out = FALSE; - int32 qlen = VARSIZE(query) - VARHDRSZ - s; - int32 nlen = VARSIZE(pf) - VARHDRSZ - s; + bool out = FALSE; + int32 k = 0; + int32 qlen = VARSIZE(query) - VARHDRSZ ; + int32 nlen = VARSIZE(pf) - VARHDRSZ ; if (nlen <= qlen) { - char *q = VARDATA(query); - char *n = VARDATA(pf); - - out = TRUE; - for (k = 0; k < nlen; k++) - { - if (*n != *q) - { - out = FALSE; - break; - } - if (k < (nlen - 1)) - { - q++; - n++; - } - } + char *q = VARDATA(query); + char *n = VARDATA(pf); + + if ( tinfo->eml > 1 ) + { + out = ( varstr_cmp(q, nlen, n, nlen) == 0 ); + } else { + out = TRUE; + for (k = 0; k < nlen; k++) + { + if (*n != *q) + { + out = FALSE; + break; + } + if (k < (nlen - 1)) + { + q++; + n++; + } + } + } } return out; } - - /* * returns true, if query matches node using common prefix */ @@ -161,44 +184,36 @@ static bool gbt_var_node_pf_match(const GBT_VARKEY_R * node, const bytea *query, const gbtree_vinfo * tinfo) { - return ( + return ( tinfo->trnc && ( gbt_bytea_pf_match(node->lower, query, tinfo) || gbt_bytea_pf_match(node->upper, query, tinfo) - ); + ) ); } /* * truncates / compresses the node key +* cpf_length .. common prefix length */ static GBT_VARKEY * -gbt_var_node_truncate(const GBT_VARKEY * node, int32 length, const gbtree_vinfo * tinfo) +gbt_var_node_truncate(const GBT_VARKEY * node, int32 cpf_length, const gbtree_vinfo * tinfo) { - - int32 s = (tinfo->str) ? (1) : (0); GBT_VARKEY *out = NULL; GBT_VARKEY_R r = gbt_var_key_readable(node); - int32 len1 = VARSIZE(r.lower) - VARHDRSZ; - int32 len2 = VARSIZE(r.upper) - VARHDRSZ; - int32 si = 0; + int32 len1 = VARSIZE(r.lower) - VARHDRSZ; + int32 len2 = VARSIZE(r.upper) - VARHDRSZ; + int32 si = 0; - if (tinfo->str) - length++; /* because of tailing '\0' */ + len1 = Min(len1,(cpf_length + 1)); + len2 = Min(len2,(cpf_length + 1)); - len1 = Min(len1, length); - len2 = Min(len2, length); si = 2 * VARHDRSZ + INTALIGN(VARHDRSZ + len1) + len2; out = (GBT_VARKEY *) palloc(si); out->vl_len = si; - memcpy((void *) &(((char *) out)[VARHDRSZ]), (void *) r.lower, len1 + VARHDRSZ - s); - memcpy((void *) &(((char *) out)[VARHDRSZ + INTALIGN(VARHDRSZ + len1)]), (void *) r.upper, len2 + VARHDRSZ - s); + memcpy((void *) &(((char *) out)[VARHDRSZ]), (void *) r.lower, len1 + VARHDRSZ ); + memcpy((void *) &(((char *) out)[VARHDRSZ + INTALIGN(VARHDRSZ + len1)]), (void *) r.upper, len2 + VARHDRSZ ); - if (tinfo->str) - { - ((char *) out)[VARHDRSZ + INTALIGN(VARHDRSZ + len1) - 1] = '\0'; - ((char *) out)[2 * VARHDRSZ + INTALIGN(VARHDRSZ + len1) + len2 - 1] = '\0'; - } *((int32 *) &(((char *) out)[VARHDRSZ])) = len1 + VARHDRSZ; *((int32 *) &(((char *) out)[VARHDRSZ + INTALIGN(VARHDRSZ + len1)])) = len2 + VARHDRSZ; @@ -356,7 +371,6 @@ gbt_var_penalty(float *res, const GISTENTRY *o, const GISTENTRY *n, const gbtree GBT_VARKEY_R ok, nk; GBT_VARKEY *tmp = NULL; - int32 s = (tinfo->str) ? (1) : (0); *res = 0.0; @@ -369,7 +383,7 @@ gbt_var_penalty(float *res, const GISTENTRY *o, const GISTENTRY *n, const gbtree } ok = gbt_var_key_readable(orge); - if ((VARSIZE(ok.lower) - VARHDRSZ) == s && (VARSIZE(ok.upper) - VARHDRSZ) == s) + if ((VARSIZE(ok.lower) - VARHDRSZ) == 0 && (VARSIZE(ok.upper) - VARHDRSZ) == 0) *res = 0.0; else if (!( ( @@ -396,22 +410,14 @@ gbt_var_penalty(float *res, const GISTENTRY *o, const GISTENTRY *n, const gbtree { GBT_VARKEY_R uk = gbt_var_key_readable((GBT_VARKEY *) DatumGetPointer(d)); - if (tinfo->str) - { - dres = (VARDATA(ok.lower)[ul] - VARDATA(uk.lower)[ul]) + - (VARDATA(uk.upper)[ul] - VARDATA(ok.upper)[ul]); - } - else - { - char tmp[4]; - - tmp[0] = ((VARSIZE(ok.lower) - VARHDRSZ) == ul) ? (CHAR_MIN) : (VARDATA(ok.lower)[ul]); - tmp[1] = ((VARSIZE(uk.lower) - VARHDRSZ) == ul) ? (CHAR_MIN) : (VARDATA(uk.lower)[ul]); - tmp[2] = ((VARSIZE(ok.upper) - VARHDRSZ) == ul) ? (CHAR_MIN) : (VARDATA(ok.upper)[ul]); - tmp[3] = ((VARSIZE(uk.upper) - VARHDRSZ) == ul) ? (CHAR_MIN) : (VARDATA(uk.upper)[ul]); - dres = (tmp[0] - tmp[1]) + - (tmp[3] - tmp[2]); - } + char tmp[4]; + + tmp[0] = ((VARSIZE(ok.lower) - VARHDRSZ) == ul) ? (CHAR_MIN) : (VARDATA(ok.lower)[ul]); + tmp[1] = ((VARSIZE(uk.lower) - VARHDRSZ) == ul) ? (CHAR_MIN) : (VARDATA(uk.lower)[ul]); + tmp[2] = ((VARSIZE(ok.upper) - VARHDRSZ) == ul) ? (CHAR_MIN) : (VARDATA(ok.upper)[ul]); + tmp[3] = ((VARSIZE(uk.upper) - VARHDRSZ) == ul) ? (CHAR_MIN) : (VARDATA(uk.upper)[ul]); + dres = (tmp[0] - tmp[1]) + + (tmp[3] - tmp[2]); dres /= 256.0; } |