summaryrefslogtreecommitdiff
path: root/src/backend/access/hash/hashutil.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2016-06-24 16:57:36 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2016-06-24 16:57:36 -0400
commit07f69137b15e594edfaec29f73efa86aa442902c (patch)
treee21f49019b64157b8d82b946ddca7a942ed9e09a /src/backend/access/hash/hashutil.c
parentb4e6123bf604ed316b03629b881fbf67edcb9725 (diff)
Fix building of large (bigger than shared_buffers) hash indexes.
When the index is predicted to need more than NBuffers buckets, CREATE INDEX attempts to sort the index entries by hash key before insertion, so as to reduce thrashing. This code path got broken by commit 9f03ca915196dfc8, which overlooked that _hash_form_tuple() is not just an alias for index_form_tuple(). The index got built anyway, but with garbage data, so that searches for pre-existing tuples always failed. Fix by refactoring to separate construction of the indexable data from calling index_form_tuple(). Per bug #14210 from Daniel Newman. Back-patch to 9.5 where the bug was introduced. Report: <20160623162507.17237.39471@wrigleys.postgresql.org>
Diffstat (limited to 'src/backend/access/hash/hashutil.c')
-rw-r--r--src/backend/access/hash/hashutil.c44
1 files changed, 27 insertions, 17 deletions
diff --git a/src/backend/access/hash/hashutil.c b/src/backend/access/hash/hashutil.c
index 3d662164749..9f8fcc96a3b 100644
--- a/src/backend/access/hash/hashutil.c
+++ b/src/backend/access/hash/hashutil.c
@@ -248,27 +248,37 @@ _hash_get_indextuple_hashkey(IndexTuple itup)
}
/*
- * _hash_form_tuple - form an index tuple containing hash code only
+ * _hash_convert_tuple - convert raw index data to hash key
+ *
+ * Inputs: values and isnull arrays for the user data column(s)
+ * Outputs: values and isnull arrays for the index tuple, suitable for
+ * passing to index_form_tuple().
+ *
+ * Returns true if successful, false if not (because there are null values).
+ * On a false result, the given data need not be indexed.
+ *
+ * Note: callers know that the index-column arrays are always of length 1.
+ * In principle, there could be more than one input column, though we do not
+ * currently support that.
*/
-IndexTuple
-_hash_form_tuple(Relation index, Datum *values, bool *isnull)
+bool
+_hash_convert_tuple(Relation index,
+ Datum *user_values, bool *user_isnull,
+ Datum *index_values, bool *index_isnull)
{
- IndexTuple itup;
uint32 hashkey;
- Datum hashkeydatum;
- TupleDesc hashdesc;
- if (isnull[0])
- hashkeydatum = (Datum) 0;
- else
- {
- hashkey = _hash_datum2hashkey(index, values[0]);
- hashkeydatum = UInt32GetDatum(hashkey);
- }
- hashdesc = RelationGetDescr(index);
- Assert(hashdesc->natts == 1);
- itup = index_form_tuple(hashdesc, &hashkeydatum, isnull);
- return itup;
+ /*
+ * We do not insert null values into hash indexes. This is okay because
+ * the only supported search operator is '=', and we assume it is strict.
+ */
+ if (user_isnull[0])
+ return false;
+
+ hashkey = _hash_datum2hashkey(index, user_values[0]);
+ index_values[0] = UInt32GetDatum(hashkey);
+ index_isnull[0] = false;
+ return true;
}
/*