Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commite4fb8ff

Browse files
committed
Add a new column to pg_am to specify whether an index AM supports backward
scanning; GiST and GIN do not, and it seems like too much trouble to makethem do so. By teaching ExecSupportsBackwardScan() about this restriction,we ensure that the planner will protect a scroll cursor from the problemby adding a Materialize node.In passing, fix another longstanding bug in the same area: backwards scan ofa plan with set-returning functions in the targetlist did not work either,since the TupFromTlist expansion code pays no attention to direction (andhas no way to run a SRF backwards anyway). Again the fix is to makeExecSupportsBackwardScan check this restriction.Also adjust the index AM API specification to note that mark/restore supportis unnecessary if the AM can't produce ordered output.
1 parent2a64931 commite4fb8ff

File tree

5 files changed

+119
-42
lines changed

5 files changed

+119
-42
lines changed

‎doc/src/sgml/catalogs.sgml

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<!-- $PostgreSQL: pgsql/doc/src/sgml/catalogs.sgml,v 2.178 2008/10/06 13:59:37 tgl Exp $ -->
1+
<!-- $PostgreSQL: pgsql/doc/src/sgml/catalogs.sgml,v 2.179 2008/10/17 22:10:29 tgl Exp $ -->
22
<!--
33
Documentation of the system catalogs, directed toward PostgreSQL developers
44
-->
@@ -401,6 +401,13 @@
401401
<entry>Does the access method support ordered scans?</entry>
402402
</row>
403403

404+
<row>
405+
<entry><structfield>amcanbackward</structfield></entry>
406+
<entry><type>bool</type></entry>
407+
<entry></entry>
408+
<entry>Does the access method support backward scanning?</entry>
409+
</row>
410+
404411
<row>
405412
<entry><structfield>amcanunique</structfield></entry>
406413
<entry><type>bool</type></entry>

‎doc/src/sgml/indexam.sgml

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<!-- $PostgreSQL: pgsql/doc/src/sgml/indexam.sgml,v 2.27 2008/08/14 18:47:58 tgl Exp $ -->
1+
<!-- $PostgreSQL: pgsql/doc/src/sgml/indexam.sgml,v 2.28 2008/10/17 22:10:29 tgl Exp $ -->
22

33
<chapter id="indexam">
44
<title>Index Access Method Interface Definition</title>
@@ -474,15 +474,20 @@ amrestrpos (IndexScanDesc scan);
474474
normally would. (This will only occur for access
475475
methods that advertise they support ordered scans.) After the
476476
first call, <function>amgettuple</> must be prepared to advance the scan in
477-
either direction from the most recently returned entry.
477+
either direction from the most recently returned entry. (But if
478+
<structname>pg_am</>.<structfield>amcanbackward</> is false, all subsequent
479+
calls will have the same direction as the first one.)
478480
</para>
479481

480482
<para>
481-
The access method must support <quote>marking</> a position in a scan
482-
and later returning to the marked position. The same position might be
483-
restored multiple times. However, only one position need be remembered
484-
per scan; a new <function>ammarkpos</> call overrides the previously
485-
marked position.
483+
Access methods that support ordered scans must support <quote>marking</> a
484+
position in a scan and later returning to the marked position. The same
485+
position might be restored multiple times. However, only one position need
486+
be remembered per scan; a new <function>ammarkpos</> call overrides the
487+
previously marked position. An access method that does not support
488+
ordered scans should still provide mark and restore functions in
489+
<structname>pg_am</>, but it is sufficient to have them throw errors if
490+
called.
486491
</para>
487492

488493
<para>

‎src/backend/executor/execAmi.c

Lines changed: 68 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
77
* Portions Copyright (c) 1994, Regents of the University of California
88
*
9-
*$PostgreSQL: pgsql/src/backend/executor/execAmi.c,v 1.99 2008/10/04 21:56:53 tgl Exp $
9+
*$PostgreSQL: pgsql/src/backend/executor/execAmi.c,v 1.100 2008/10/17 22:10:29 tgl Exp $
1010
*
1111
*-------------------------------------------------------------------------
1212
*/
@@ -42,6 +42,12 @@
4242
#include"executor/nodeValuesscan.h"
4343
#include"executor/nodeCtescan.h"
4444
#include"executor/nodeWorktablescan.h"
45+
#include"nodes/nodeFuncs.h"
46+
#include"utils/syscache.h"
47+
48+
49+
staticboolTargetListSupportsBackwardScan(List*targetlist);
50+
staticboolIndexSupportsBackwardScan(Oidindexid);
4551

4652

4753
/*
@@ -390,7 +396,8 @@ ExecSupportsBackwardScan(Plan *node)
390396
{
391397
caseT_Result:
392398
if (outerPlan(node)!=NULL)
393-
returnExecSupportsBackwardScan(outerPlan(node));
399+
returnExecSupportsBackwardScan(outerPlan(node))&&
400+
TargetListSupportsBackwardScan(node->targetlist);
394401
else
395402
return false;
396403

@@ -403,29 +410,85 @@ ExecSupportsBackwardScan(Plan *node)
403410
if (!ExecSupportsBackwardScan((Plan*)lfirst(l)))
404411
return false;
405412
}
413+
/* need not check tlist because Append doesn't evaluate it */
406414
return true;
407415
}
408416

409417
caseT_SeqScan:
410-
caseT_IndexScan:
411418
caseT_TidScan:
412419
caseT_FunctionScan:
413420
caseT_ValuesScan:
414421
caseT_CteScan:
415422
caseT_WorkTableScan:
416-
return true;
423+
returnTargetListSupportsBackwardScan(node->targetlist);
424+
425+
caseT_IndexScan:
426+
returnIndexSupportsBackwardScan(((IndexScan*)node)->indexid)&&
427+
TargetListSupportsBackwardScan(node->targetlist);
417428

418429
caseT_SubqueryScan:
419-
returnExecSupportsBackwardScan(((SubqueryScan*)node)->subplan);
430+
returnExecSupportsBackwardScan(((SubqueryScan*)node)->subplan)&&
431+
TargetListSupportsBackwardScan(node->targetlist);
420432

421433
caseT_Material:
422434
caseT_Sort:
435+
/* these don't evaluate tlist */
423436
return true;
424437

425438
caseT_Limit:
439+
/* doesn't evaluate tlist */
426440
returnExecSupportsBackwardScan(outerPlan(node));
427441

428442
default:
429443
return false;
430444
}
431445
}
446+
447+
/*
448+
* If the tlist contains set-returning functions, we can't support backward
449+
* scan, because the TupFromTlist code is direction-ignorant.
450+
*/
451+
staticbool
452+
TargetListSupportsBackwardScan(List*targetlist)
453+
{
454+
if (expression_returns_set((Node*)targetlist))
455+
return false;
456+
return true;
457+
}
458+
459+
/*
460+
* An IndexScan node supports backward scan only if the index's AM does.
461+
*/
462+
staticbool
463+
IndexSupportsBackwardScan(Oidindexid)
464+
{
465+
boolresult;
466+
HeapTupleht_idxrel;
467+
HeapTupleht_am;
468+
Form_pg_classidxrelrec;
469+
Form_pg_amamrec;
470+
471+
/* Fetch the pg_class tuple of the index relation */
472+
ht_idxrel=SearchSysCache(RELOID,
473+
ObjectIdGetDatum(indexid),
474+
0,0,0);
475+
if (!HeapTupleIsValid(ht_idxrel))
476+
elog(ERROR,"cache lookup failed for relation %u",indexid);
477+
idxrelrec= (Form_pg_class)GETSTRUCT(ht_idxrel);
478+
479+
/* Fetch the pg_am tuple of the index' access method */
480+
ht_am=SearchSysCache(AMOID,
481+
ObjectIdGetDatum(idxrelrec->relam),
482+
0,0,0);
483+
if (!HeapTupleIsValid(ht_am))
484+
elog(ERROR,"cache lookup failed for access method %u",
485+
idxrelrec->relam);
486+
amrec= (Form_pg_am)GETSTRUCT(ht_am);
487+
488+
result=amrec->amcanbackward;
489+
490+
ReleaseSysCache(ht_idxrel);
491+
ReleaseSysCache(ht_am);
492+
493+
returnresult;
494+
}

‎src/include/catalog/catversion.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
3838
* Portions Copyright (c) 1994, Regents of the University of California
3939
*
40-
* $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.498 2008/10/14 17:12:33 tgl Exp $
40+
* $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.499 2008/10/17 22:10:30 tgl Exp $
4141
*
4242
*-------------------------------------------------------------------------
4343
*/
@@ -53,6 +53,6 @@
5353
*/
5454

5555
/*yyyymmddN */
56-
#defineCATALOG_VERSION_NO200810141
56+
#defineCATALOG_VERSION_NO200810171
5757

5858
#endif

‎src/include/catalog/pg_am.h

Lines changed: 29 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
99
* Portions Copyright (c) 1994, Regents of the University of California
1010
*
11-
* $PostgreSQL: pgsql/src/include/catalog/pg_am.h,v 1.58 2008/09/15 18:43:41 tgl Exp $
11+
* $PostgreSQL: pgsql/src/include/catalog/pg_am.h,v 1.59 2008/10/17 22:10:30 tgl Exp $
1212
*
1313
* NOTES
1414
*the genbki.sh script reads this file and generates .bki
@@ -41,6 +41,7 @@ CATALOG(pg_am,2601)
4141
int2amsupport;/* total number of support functions that this
4242
* AM uses */
4343
boolamcanorder;/* does AM support ordered scan results? */
44+
boolamcanbackward;/* does AM support backward scan? */
4445
boolamcanunique;/* does AM support UNIQUE indexes? */
4546
boolamcanmulticol;/* does AM support multi-column indexes? */
4647
boolamoptionalkey;/* can query omit key for the first column? */
@@ -75,48 +76,49 @@ typedef FormData_pg_am *Form_pg_am;
7576
*compiler constants for pg_am
7677
* ----------------
7778
*/
78-
#defineNatts_pg_am25
79+
#defineNatts_pg_am26
7980
#defineAnum_pg_am_amname1
8081
#defineAnum_pg_am_amstrategies2
8182
#defineAnum_pg_am_amsupport3
8283
#defineAnum_pg_am_amcanorder4
83-
#defineAnum_pg_am_amcanunique5
84-
#defineAnum_pg_am_amcanmulticol6
85-
#defineAnum_pg_am_amoptionalkey7
86-
#defineAnum_pg_am_amindexnulls8
87-
#defineAnum_pg_am_amsearchnulls9
88-
#defineAnum_pg_am_amstorage10
89-
#defineAnum_pg_am_amclusterable11
90-
#defineAnum_pg_am_amkeytype12
91-
#defineAnum_pg_am_aminsert13
92-
#defineAnum_pg_am_ambeginscan14
93-
#defineAnum_pg_am_amgettuple15
94-
#defineAnum_pg_am_amgetbitmap16
95-
#defineAnum_pg_am_amrescan17
96-
#defineAnum_pg_am_amendscan18
97-
#defineAnum_pg_am_ammarkpos19
98-
#defineAnum_pg_am_amrestrpos20
99-
#defineAnum_pg_am_ambuild21
100-
#defineAnum_pg_am_ambulkdelete22
101-
#defineAnum_pg_am_amvacuumcleanup23
102-
#defineAnum_pg_am_amcostestimate24
103-
#defineAnum_pg_am_amoptions25
84+
#defineAnum_pg_am_amcanbackward5
85+
#defineAnum_pg_am_amcanunique6
86+
#defineAnum_pg_am_amcanmulticol7
87+
#defineAnum_pg_am_amoptionalkey8
88+
#defineAnum_pg_am_amindexnulls9
89+
#defineAnum_pg_am_amsearchnulls10
90+
#defineAnum_pg_am_amstorage11
91+
#defineAnum_pg_am_amclusterable12
92+
#defineAnum_pg_am_amkeytype13
93+
#defineAnum_pg_am_aminsert14
94+
#defineAnum_pg_am_ambeginscan15
95+
#defineAnum_pg_am_amgettuple16
96+
#defineAnum_pg_am_amgetbitmap17
97+
#defineAnum_pg_am_amrescan18
98+
#defineAnum_pg_am_amendscan19
99+
#defineAnum_pg_am_ammarkpos20
100+
#defineAnum_pg_am_amrestrpos21
101+
#defineAnum_pg_am_ambuild22
102+
#defineAnum_pg_am_ambulkdelete23
103+
#defineAnum_pg_am_amvacuumcleanup24
104+
#defineAnum_pg_am_amcostestimate25
105+
#defineAnum_pg_am_amoptions26
104106

105107
/* ----------------
106108
*initial contents of pg_am
107109
* ----------------
108110
*/
109111

110-
DATA(insertOID=403 (btree51ttttttft0btinsertbtbeginscanbtgettuplebtgetbitmapbtrescanbtendscanbtmarkposbtrestrposbtbuildbtbulkdeletebtvacuumcleanupbtcostestimatebtoptions ));
112+
DATA(insertOID=403 (btree51tttttttft0btinsertbtbeginscanbtgettuplebtgetbitmapbtrescanbtendscanbtmarkposbtrestrposbtbuildbtbulkdeletebtvacuumcleanupbtcostestimatebtoptions ));
111113
DESCR("b-tree index access method");
112114
#defineBTREE_AM_OID 403
113-
DATA(insertOID=405 (hash11ffffffff23hashinserthashbeginscanhashgettuplehashgetbitmaphashrescanhashendscanhashmarkposhashrestrposhashbuildhashbulkdeletehashvacuumcleanuphashcostestimatehashoptions ));
115+
DATA(insertOID=405 (hash11ftfffffff23hashinserthashbeginscanhashgettuplehashgetbitmaphashrescanhashendscanhashmarkposhashrestrposhashbuildhashbulkdeletehashvacuumcleanuphashcostestimatehashoptions ));
114116
DESCR("hash index access method");
115117
#defineHASH_AM_OID 405
116-
DATA(insertOID=783 (gist07fftttttt0gistinsertgistbeginscangistgettuplegistgetbitmapgistrescangistendscangistmarkposgistrestrposgistbuildgistbulkdeletegistvacuumcleanupgistcostestimategistoptions ));
118+
DATA(insertOID=783 (gist07ffftttttt0gistinsertgistbeginscangistgettuplegistgetbitmapgistrescangistendscangistmarkposgistrestrposgistbuildgistbulkdeletegistvacuumcleanupgistcostestimategistoptions ));
117119
DESCR("GiST index access method");
118120
#defineGIST_AM_OID 783
119-
DATA(insertOID=2742 (gin05ffttfftf0gininsertginbeginscangingettuplegingetbitmapginrescanginendscanginmarkposginrestrposginbuildginbulkdeleteginvacuumcleanupgincostestimateginoptions ));
121+
DATA(insertOID=2742 (gin05fffttfftf0gininsertginbeginscangingettuplegingetbitmapginrescanginendscanginmarkposginrestrposginbuildginbulkdeleteginvacuumcleanupgincostestimateginoptions ));
120122
DESCR("GIN index access method");
121123
#defineGIN_AM_OID 2742
122124

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp