Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 811af97

Browse files
committed
Don't overwrite scan key in systable_beginscan()
When systable_beginscan() and systable_beginscan_ordered() choose an index scan, they remap the attribute numbers in the passed-in scan keys to the attribute numbers of the index, and then write those remapped attribute numbers back into the scan key passed by the caller. This second part is surprising and gratuitous. It means that a scan key cannot safely be used more than once (but it might sometimes work, depending on circumstances). Also, there is no value in providing these remapped attribute numbers back to the caller, since they can't do anything with that. Fix that by making a copy of the scan keys passed by the caller and make the modifications there. Also, some code that had to work around the previous situation is simplified. Discussion: https://www.postgresql.org/message-id/flat/f8c739d9-f48d-4187-b214-df3391ba41ab@eisentraut.org
1 parent 00c76cf commit 811af97

File tree

3 files changed

+40
-33
lines changed

3 files changed

+40
-33
lines changed

src/backend/access/index/genam.c

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -372,7 +372,7 @@ index_compute_xid_horizon_for_tuples(Relation irel,
372372
* nkeys, key: scan keys
373373
*
374374
* The attribute numbers in the scan key should be set for the heap case.
375-
* If we choose to index, we reset them to 1..n to reference the index
375+
* If we choose to index, we convert them to 1..n to reference the index
376376
* columns. Note this means there must be one scankey qualification per
377377
* index column! This is checked by the Asserts in the normal, index-using
378378
* case, but won't be checked if the heapscan path is taken.
@@ -420,17 +420,22 @@ systable_beginscan(Relation heapRelation,
420420
if (irel)
421421
{
422422
int i;
423+
ScanKey idxkey;
423424

424-
/* Change attribute numbers to be index column numbers. */
425+
idxkey = palloc_array(ScanKeyData, nkeys);
426+
427+
/* Convert attribute numbers to be index column numbers. */
425428
for (i = 0; i < nkeys; i++)
426429
{
427430
int j;
428431

432+
memcpy(&idxkey[i], &key[i], sizeof(ScanKeyData));
433+
429434
for (j = 0; j < IndexRelationGetNumberOfAttributes(irel); j++)
430435
{
431436
if (key[i].sk_attno == irel->rd_index->indkey.values[j])
432437
{
433-
key[i].sk_attno = j + 1;
438+
idxkey[i].sk_attno = j + 1;
434439
break;
435440
}
436441
}
@@ -440,7 +445,7 @@ systable_beginscan(Relation heapRelation,
440445

441446
sysscan->iscan = index_beginscan(heapRelation, irel,
442447
snapshot, nkeys, 0);
443-
index_rescan(sysscan->iscan, key, nkeys, NULL, 0);
448+
index_rescan(sysscan->iscan, idxkey, nkeys, NULL, 0);
444449
sysscan->scan = NULL;
445450
}
446451
else
@@ -648,6 +653,7 @@ systable_beginscan_ordered(Relation heapRelation,
648653
{
649654
SysScanDesc sysscan;
650655
int i;
656+
ScanKey idxkey;
651657

652658
/* REINDEX can probably be a hard error here ... */
653659
if (ReindexIsProcessingIndex(RelationGetRelid(indexRelation)))
@@ -679,16 +685,20 @@ systable_beginscan_ordered(Relation heapRelation,
679685
sysscan->snapshot = NULL;
680686
}
681687

682-
/* Change attribute numbers to be index column numbers. */
688+
idxkey = palloc_array(ScanKeyData, nkeys);
689+
690+
/* Convert attribute numbers to be index column numbers. */
683691
for (i = 0; i < nkeys; i++)
684692
{
685693
int j;
686694

695+
memcpy(&idxkey[i], &key[i], sizeof(ScanKeyData));
696+
687697
for (j = 0; j < IndexRelationGetNumberOfAttributes(indexRelation); j++)
688698
{
689699
if (key[i].sk_attno == indexRelation->rd_index->indkey.values[j])
690700
{
691-
key[i].sk_attno = j + 1;
701+
idxkey[i].sk_attno = j + 1;
692702
break;
693703
}
694704
}
@@ -698,7 +708,7 @@ systable_beginscan_ordered(Relation heapRelation,
698708

699709
sysscan->iscan = index_beginscan(heapRelation, indexRelation,
700710
snapshot, nkeys, 0);
701-
index_rescan(sysscan->iscan, key, nkeys, NULL, 0);
711+
index_rescan(sysscan->iscan, idxkey, nkeys, NULL, 0);
702712
sysscan->scan = NULL;
703713

704714
return sysscan;

src/backend/utils/cache/catcache.c

Lines changed: 20 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1468,19 +1468,18 @@ SearchCatCacheMiss(CatCache *cache,
14681468
*/
14691469
relation = table_open(cache->cc_reloid, AccessShareLock);
14701470

1471+
/*
1472+
* Ok, need to make a lookup in the relation, copy the scankey and fill
1473+
* out any per-call fields.
1474+
*/
1475+
memcpy(cur_skey, cache->cc_skey, sizeof(ScanKeyData) * nkeys);
1476+
cur_skey[0].sk_argument = v1;
1477+
cur_skey[1].sk_argument = v2;
1478+
cur_skey[2].sk_argument = v3;
1479+
cur_skey[3].sk_argument = v4;
1480+
14711481
do
14721482
{
1473-
/*
1474-
* Ok, need to make a lookup in the relation, copy the scankey and
1475-
* fill out any per-call fields. (We must re-do this when retrying,
1476-
* because systable_beginscan scribbles on the scankey.)
1477-
*/
1478-
memcpy(cur_skey, cache->cc_skey, sizeof(ScanKeyData) * nkeys);
1479-
cur_skey[0].sk_argument = v1;
1480-
cur_skey[1].sk_argument = v2;
1481-
cur_skey[2].sk_argument = v3;
1482-
cur_skey[3].sk_argument = v4;
1483-
14841483
scandesc = systable_beginscan(relation,
14851484
cache->cc_indexoid,
14861485
IndexScanOK(cache),
@@ -1788,19 +1787,18 @@ SearchCatCacheList(CatCache *cache,
17881787

17891788
relation = table_open(cache->cc_reloid, AccessShareLock);
17901789

1790+
/*
1791+
* Ok, need to make a lookup in the relation, copy the scankey and
1792+
* fill out any per-call fields.
1793+
*/
1794+
memcpy(cur_skey, cache->cc_skey, sizeof(ScanKeyData) * cache->cc_nkeys);
1795+
cur_skey[0].sk_argument = v1;
1796+
cur_skey[1].sk_argument = v2;
1797+
cur_skey[2].sk_argument = v3;
1798+
cur_skey[3].sk_argument = v4;
1799+
17911800
do
17921801
{
1793-
/*
1794-
* Ok, need to make a lookup in the relation, copy the scankey and
1795-
* fill out any per-call fields. (We must re-do this when
1796-
* retrying, because systable_beginscan scribbles on the scankey.)
1797-
*/
1798-
memcpy(cur_skey, cache->cc_skey, sizeof(ScanKeyData) * cache->cc_nkeys);
1799-
cur_skey[0].sk_argument = v1;
1800-
cur_skey[1].sk_argument = v2;
1801-
cur_skey[2].sk_argument = v3;
1802-
cur_skey[3].sk_argument = v4;
1803-
18041802
scandesc = systable_beginscan(relation,
18051803
cache->cc_indexoid,
18061804
IndexScanOK(cache),

src/backend/utils/cache/relfilenumbermap.c

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,6 @@ RelidByRelfilenumber(Oid reltablespace, RelFileNumber relfilenumber)
141141
SysScanDesc scandesc;
142142
Relation relation;
143143
HeapTuple ntp;
144-
ScanKeyData skey[2];
145144
Oid relid;
146145

147146
if (RelfilenumberMapHash == NULL)
@@ -181,6 +180,8 @@ RelidByRelfilenumber(Oid reltablespace, RelFileNumber relfilenumber)
181180
}
182181
else
183182
{
183+
ScanKeyData skey[2];
184+
184185
/*
185186
* Not a shared table, could either be a plain relation or a
186187
* non-shared, nailed one, like e.g. pg_class.
@@ -189,10 +190,8 @@ RelidByRelfilenumber(Oid reltablespace, RelFileNumber relfilenumber)
189190
/* check for plain relations by looking in pg_class */
190191
relation = table_open(RelationRelationId, AccessShareLock);
191192

192-
/* copy scankey to local copy, it will be modified during the scan */
193+
/* copy scankey to local copy and set scan arguments */
193194
memcpy(skey, relfilenumber_skey, sizeof(skey));
194-
195-
/* set scan arguments */
196195
skey[0].sk_argument = ObjectIdGetDatum(reltablespace);
197196
skey[1].sk_argument = ObjectIdGetDatum(relfilenumber);
198197

0 commit comments

Comments
 (0)