diff options
author | Peter Geoghegan <pg@bowt.ie> | 2019-03-20 09:30:57 -0700 |
---|---|---|
committer | Peter Geoghegan <pg@bowt.ie> | 2019-03-20 09:30:57 -0700 |
commit | e5adcb789d80ba565ccacb1ed4341a7c29085238 (patch) | |
tree | 3393597468587cf5906dea6a4ae41e0a01db9ca5 /src/backend/access/nbtree/nbtutils.c | |
parent | 550b9d26f80fa3048f2d5883f0779ed29465960a (diff) | |
download | postgresql-e5adcb789d80ba565ccacb1ed4341a7c29085238.tar.gz postgresql-e5adcb789d80ba565ccacb1ed4341a7c29085238.zip |
Refactor nbtree insertion scankeys.
Use dedicated struct to represent nbtree insertion scan keys. Having a
dedicated struct makes the difference between search type scankeys and
insertion scankeys a lot clearer, and simplifies the signature of
several related functions. This is based on a suggestion by Andrey
Lepikhov.
Streamline how unique index insertions cache binary search progress.
Cache the state of in-progress binary searches within _bt_check_unique()
for later instead of having callers avoid repeating the binary search in
an ad-hoc manner. This makes it easy to add a new optimization:
_bt_check_unique() now falls out of its loop immediately in the common
case where it's already clear that there couldn't possibly be a
duplicate.
The new _bt_check_unique() scheme makes it a lot easier to manage cached
binary search effort afterwards, from within _bt_findinsertloc(). This
is needed for the upcoming patch to make nbtree tuples unique by
treating heap TID as a final tiebreaker column. Unique key binary
searches need to restore lower and upper bounds. They cannot simply
continue to use the >= lower bound as the offset to insert at, because
the heap TID tiebreaker column must be used in comparisons for the
restored binary search (unlike the original _bt_check_unique() binary
search, where scankey's heap TID column must be omitted).
Author: Peter Geoghegan, Heikki Linnakangas
Reviewed-By: Heikki Linnakangas, Andrey Lepikhov
Discussion: https://postgr.es/m/CAH2-WzmE6AhUdk9NdWBf4K3HjWXZBX3+umC7mH7+WDrKcRtsOw@mail.gmail.com
Diffstat (limited to 'src/backend/access/nbtree/nbtutils.c')
-rw-r--r-- | src/backend/access/nbtree/nbtutils.c | 94 |
1 files changed, 26 insertions, 68 deletions
diff --git a/src/backend/access/nbtree/nbtutils.c b/src/backend/access/nbtree/nbtutils.c index 2c05fb5e451..0250e089a65 100644 --- a/src/backend/access/nbtree/nbtutils.c +++ b/src/backend/access/nbtree/nbtutils.c @@ -56,34 +56,37 @@ static bool _bt_check_rowcompare(ScanKey skey, * Build an insertion scan key that contains comparison data from itup * as well as comparator routines appropriate to the key datatypes. * - * The result is intended for use with _bt_compare(). + * Result is intended for use with _bt_compare(). Callers that don't + * need to fill out the insertion scankey arguments (e.g. they use an + * ad-hoc comparison routine) can pass a NULL index tuple. */ -ScanKey +BTScanInsert _bt_mkscankey(Relation rel, IndexTuple itup) { + BTScanInsert key; ScanKey skey; TupleDesc itupdesc; - int indnatts PG_USED_FOR_ASSERTS_ONLY; int indnkeyatts; int16 *indoption; + int tupnatts; int i; itupdesc = RelationGetDescr(rel); - indnatts = IndexRelationGetNumberOfAttributes(rel); indnkeyatts = IndexRelationGetNumberOfKeyAttributes(rel); indoption = rel->rd_indoption; + tupnatts = itup ? BTreeTupleGetNAtts(itup, rel) : 0; - Assert(indnkeyatts > 0); - Assert(indnkeyatts <= indnatts); - Assert(BTreeTupleGetNAtts(itup, rel) == indnatts || - BTreeTupleGetNAtts(itup, rel) == indnkeyatts); + Assert(tupnatts <= IndexRelationGetNumberOfAttributes(rel)); /* * We'll execute search using scan key constructed on key columns. Non-key * (INCLUDE index) columns are always omitted from scan keys. */ - skey = (ScanKey) palloc(indnkeyatts * sizeof(ScanKeyData)); - + key = palloc(offsetof(BTScanInsertData, scankeys) + + sizeof(ScanKeyData) * indnkeyatts); + key->nextkey = false; + key->keysz = Min(indnkeyatts, tupnatts); + skey = key->scankeys; for (i = 0; i < indnkeyatts; i++) { FmgrInfo *procinfo; @@ -96,56 +99,20 @@ _bt_mkscankey(Relation rel, IndexTuple itup) * comparison can be needed. */ procinfo = index_getprocinfo(rel, i + 1, BTORDER_PROC); - arg = index_getattr(itup, i + 1, itupdesc, &null); - flags = (null ? SK_ISNULL : 0) | (indoption[i] << SK_BT_INDOPTION_SHIFT); - ScanKeyEntryInitializeWithInfo(&skey[i], - flags, - (AttrNumber) (i + 1), - InvalidStrategy, - InvalidOid, - rel->rd_indcollation[i], - procinfo, - arg); - } - - return skey; -} - -/* - * _bt_mkscankey_nodata - * Build an insertion scan key that contains 3-way comparator routines - * appropriate to the key datatypes, but no comparison data. The - * comparison data ultimately used must match the key datatypes. - * - * The result cannot be used with _bt_compare(), unless comparison - * data is first stored into the key entries. Currently this - * routine is only called by nbtsort.c and tuplesort.c, which have - * their own comparison routines. - */ -ScanKey -_bt_mkscankey_nodata(Relation rel) -{ - ScanKey skey; - int indnkeyatts; - int16 *indoption; - int i; - - indnkeyatts = IndexRelationGetNumberOfKeyAttributes(rel); - indoption = rel->rd_indoption; - - skey = (ScanKey) palloc(indnkeyatts * sizeof(ScanKeyData)); - - for (i = 0; i < indnkeyatts; i++) - { - FmgrInfo *procinfo; - int flags; /* - * We can use the cached (default) support procs since no cross-type - * comparison can be needed. + * Key arguments built when caller provides no tuple are + * defensively represented as NULL values. They should never be + * used. */ - procinfo = index_getprocinfo(rel, i + 1, BTORDER_PROC); - flags = SK_ISNULL | (indoption[i] << SK_BT_INDOPTION_SHIFT); + if (i < tupnatts) + arg = index_getattr(itup, i + 1, itupdesc, &null); + else + { + arg = (Datum) 0; + null = true; + } + flags = (null ? SK_ISNULL : 0) | (indoption[i] << SK_BT_INDOPTION_SHIFT); ScanKeyEntryInitializeWithInfo(&skey[i], flags, (AttrNumber) (i + 1), @@ -153,19 +120,10 @@ _bt_mkscankey_nodata(Relation rel) InvalidOid, rel->rd_indcollation[i], procinfo, - (Datum) 0); + arg); } - return skey; -} - -/* - * free a scan key made by either _bt_mkscankey or _bt_mkscankey_nodata. - */ -void -_bt_freeskey(ScanKey skey) -{ - pfree(skey); + return key; } /* |