hctl->accesses++;
#endif
+ /*
+ * If inserting, check if it is time to split a bucket.
+ *
+ * NOTE: failure to expand table is not a fatal error, it just means we
+ * have to run at higher fill factor than we wanted. However, if we're
+ * using the palloc allocator then it will throw error anyway on
+ * out-of-memory, so we must do this before modifying the table.
+ */
+ if (action == HASH_ENTER || action == HASH_ENTER_NULL)
+ {
+ /*
+ * Can't split if running in partitioned mode, nor if frozen, nor if
+ * table is the subject of any active hash_seq_search scans. Strange
+ * order of these tests is to try to check cheaper conditions first.
+ */
+ if (!IS_PARTITIONED(hctl) && !hashp->frozen &&
+ hctl->nentries / (long) (hctl->max_bucket + 1) >= hctl->ffactor &&
+ !has_seq_scans(hashp))
+ (void) expand_table(hashp);
+ }
+
/*
* Do the initial lookup
*/
currBucket->hashvalue = hashvalue;
hashp->keycopy(ELEMENTKEY(currBucket), keyPtr, keysize);
- /* caller is expected to fill the data field on return */
-
/*
- * Check if it is time to split a bucket. Can't split if running
- * in partitioned mode, nor if table is the subject of any active
- * hash_seq_search scans. Strange order of these tests is to try
- * to check cheaper conditions first.
+ * Caller is expected to fill the data field on return. DO NOT
+ * insert any code that could possibly throw error here, as doing
+ * so would leave the table entry incomplete and hence corrupt the
+ * caller's data structure.
*/
- if (!IS_PARTITIONED(hctl) &&
- hctl->nentries / (long) (hctl->max_bucket + 1) >= hctl->ffactor &&
- !has_seq_scans(hashp))
- {
- /*
- * NOTE: failure to expand table is not a fatal error, it just
- * means we have to run at higher fill factor than we wanted.
- */
- expand_table(hashp);
- }
return (void *) ELEMENTKEY(currBucket);
}