From 45b315efd83553871e8e966c1c03441b5601a306 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Thu, 7 Feb 2013 18:22:38 -0500 Subject: [PATCH] Fix erroneous range-union logic for varlena types in contrib/btree_gist. gbt_var_bin_union() failed to do the right thing when the existing range needed to be widened at both ends rather than just one end. This could result in an invalid index in which keys that are present would not be found by searches, because the searches would not think they need to descend to the relevant leaf pages. This error affected all the varlena datatypes supported by btree_gist (text, bytea, bit, numeric). Per investigation of a trouble report from Tomas Vondra. (There is also an issue in gbt_var_penalty(), but that should only result in inefficiency not wrong answers. I'm committing this separately so that we have a git state in which it can be tested that bad penalty results don't produce invalid indexes.) Back-patch to all supported branches. --- contrib/btree_gist/btree_utils_var.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/contrib/btree_gist/btree_utils_var.c b/contrib/btree_gist/btree_utils_var.c index 916706d8a47..10138b1f42b 100644 --- a/contrib/btree_gist/btree_utils_var.c +++ b/contrib/btree_gist/btree_utils_var.c @@ -233,14 +233,13 @@ gbt_var_node_truncate(const GBT_VARKEY *node, int32 cpf_length, const gbtree_vin void gbt_var_bin_union(Datum *u, GBT_VARKEY *e, const gbtree_vinfo *tinfo) { - - GBT_VARKEY *nk = NULL; - GBT_VARKEY *tmp = NULL; - GBT_VARKEY_R nr; GBT_VARKEY_R eo = gbt_var_key_readable(e); + GBT_VARKEY_R nr; if (eo.lower == eo.upper) /* leaf */ { + GBT_VARKEY *tmp; + tmp = gbt_var_leaf2node(e, tinfo); if (tmp != e) eo = gbt_var_key_readable(tmp); @@ -248,25 +247,26 @@ gbt_var_bin_union(Datum *u, GBT_VARKEY *e, const gbtree_vinfo *tinfo) if (DatumGetPointer(*u)) { - GBT_VARKEY_R ro = gbt_var_key_readable((GBT_VARKEY *) DatumGetPointer(*u)); + bool update = false; + + nr.lower = ro.lower; + nr.upper = ro.upper; if ((*tinfo->f_cmp) ((bytea *) ro.lower, (bytea *) eo.lower) > 0) { nr.lower = eo.lower; - nr.upper = ro.upper; - nk = gbt_var_key_copy(&nr, TRUE); + update = true; } if ((*tinfo->f_cmp) ((bytea *) ro.upper, (bytea *) eo.upper) < 0) { nr.upper = eo.upper; - nr.lower = ro.lower; - nk = gbt_var_key_copy(&nr, TRUE); + update = true; } - if (nk) - *u = PointerGetDatum(nk); + if (update) + *u = PointerGetDatum(gbt_var_key_copy(&nr, TRUE)); } else {