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

Commitda27c0a

Browse files
committed
Teach tid-scan code to make use of "ctid = ANY (array)" clauses, so that
"ctid IN (list)" will still work after we convert IN to ScalarArrayOpExpr.Make some minor efficiency improvements while at it, such as ensuring thatmultiple TIDs are fetched in physical heap order. And fix EXPLAIN so thatit shows what's really going on for a TID scan.
1 parenta66e2c8 commitda27c0a

File tree

15 files changed

+378
-147
lines changed

15 files changed

+378
-147
lines changed

‎src/backend/commands/explain.c

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1994-5, Regents of the University of California
88
*
99
* IDENTIFICATION
10-
* $PostgreSQL: pgsql/src/backend/commands/explain.c,v 1.140 2005/11/22 18:17:09 momjian Exp $
10+
* $PostgreSQL: pgsql/src/backend/commands/explain.c,v 1.141 2005/11/26 22:14:56 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -724,7 +724,6 @@ explain_outNode(StringInfo str,
724724
str,indent,es);
725725
/* FALL THRU */
726726
caseT_SeqScan:
727-
caseT_TidScan:
728727
caseT_SubqueryScan:
729728
caseT_FunctionScan:
730729
show_scan_qual(plan->qual,
@@ -733,6 +732,28 @@ explain_outNode(StringInfo str,
733732
outer_plan,
734733
str,indent,es);
735734
break;
735+
caseT_TidScan:
736+
{
737+
/*
738+
* The tidquals list has OR semantics, so be sure to show it
739+
* as an OR condition.
740+
*/
741+
List*tidquals= ((TidScan*)plan)->tidquals;
742+
743+
if (list_length(tidquals)>1)
744+
tidquals=list_make1(make_orclause(tidquals));
745+
show_scan_qual(tidquals,
746+
"TID Cond",
747+
((Scan*)plan)->scanrelid,
748+
outer_plan,
749+
str,indent,es);
750+
show_scan_qual(plan->qual,
751+
"Filter",
752+
((Scan*)plan)->scanrelid,
753+
outer_plan,
754+
str,indent,es);
755+
}
756+
break;
736757
caseT_NestLoop:
737758
show_upper_qual(((NestLoop*)plan)->join.joinqual,
738759
"Join Filter",

‎src/backend/executor/nodeTidscan.c

Lines changed: 163 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/executor/nodeTidscan.c,v 1.44 2005/11/25 04:24:48 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/executor/nodeTidscan.c,v 1.45 2005/11/26 22:14:56 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -24,54 +24,187 @@
2424
*/
2525
#include"postgres.h"
2626

27+
#include"access/heapam.h"
28+
#include"catalog/pg_type.h"
2729
#include"executor/execdebug.h"
2830
#include"executor/nodeTidscan.h"
29-
#include"access/heapam.h"
31+
#include"optimizer/clauses.h"
3032
#include"parser/parsetree.h"
33+
#include"utils/array.h"
3134

3235

36+
#defineIsCTIDVar(node) \
37+
((node) != NULL && \
38+
IsA((node), Var) && \
39+
((Var *) (node))->varattno == SelfItemPointerAttributeNumber && \
40+
((Var *) (node))->varlevelsup == 0)
41+
3342
staticvoidTidListCreate(TidScanState*tidstate);
43+
staticintitemptr_comparator(constvoid*a,constvoid*b);
3444
staticTupleTableSlot*TidNext(TidScanState*node);
3545

3646

3747
/*
3848
* Compute the list of TIDs to be visited, by evaluating the expressions
3949
* for them.
50+
*
51+
* (The result is actually an array, not a list.)
4052
*/
4153
staticvoid
4254
TidListCreate(TidScanState*tidstate)
4355
{
44-
List*evalList=tidstate->tss_tideval;
56+
List*evalList=tidstate->tss_tidquals;
4557
ExprContext*econtext=tidstate->ss.ps.ps_ExprContext;
4658
ItemPointerData*tidList;
47-
intnumTids=0;
59+
intnumAllocTids;
60+
intnumTids;
4861
ListCell*l;
4962

63+
/*
64+
* We initialize the array with enough slots for the case that all
65+
* quals are simple OpExprs. If there's any ScalarArrayOpExprs,
66+
* we may have to enlarge the array.
67+
*/
68+
numAllocTids=list_length(evalList);
5069
tidList= (ItemPointerData*)
51-
palloc(list_length(tidstate->tss_tideval)*sizeof(ItemPointerData));
70+
palloc(numAllocTids*sizeof(ItemPointerData));
71+
numTids=0;
5272

5373
foreach(l,evalList)
5474
{
75+
ExprState*exstate= (ExprState*)lfirst(l);
76+
Expr*expr=exstate->expr;
5577
ItemPointeritemptr;
5678
boolisNull;
5779

58-
itemptr= (ItemPointer)
59-
DatumGetPointer(ExecEvalExprSwitchContext(lfirst(l),
60-
econtext,
61-
&isNull,
62-
NULL));
63-
if (!isNull&&itemptr&&ItemPointerIsValid(itemptr))
80+
if (is_opclause(expr))
6481
{
65-
tidList[numTids]=*itemptr;
66-
numTids++;
82+
FuncExprState*fexstate= (FuncExprState*)exstate;
83+
Node*arg1;
84+
Node*arg2;
85+
86+
arg1=get_leftop(expr);
87+
arg2=get_rightop(expr);
88+
if (IsCTIDVar(arg1))
89+
exstate= (ExprState*)lsecond(fexstate->args);
90+
elseif (IsCTIDVar(arg2))
91+
exstate= (ExprState*)linitial(fexstate->args);
92+
else
93+
elog(ERROR,"could not identify CTID variable");
94+
95+
itemptr= (ItemPointer)
96+
DatumGetPointer(ExecEvalExprSwitchContext(exstate,
97+
econtext,
98+
&isNull,
99+
NULL));
100+
if (!isNull&&ItemPointerIsValid(itemptr))
101+
{
102+
if (numTids >=numAllocTids)
103+
{
104+
numAllocTids *=2;
105+
tidList= (ItemPointerData*)
106+
repalloc(tidList,
107+
numAllocTids*sizeof(ItemPointerData));
108+
}
109+
tidList[numTids++]=*itemptr;
110+
}
67111
}
112+
elseif (expr&&IsA(expr,ScalarArrayOpExpr))
113+
{
114+
ScalarArrayOpExprState*saexstate= (ScalarArrayOpExprState*)exstate;
115+
Datumarraydatum;
116+
ArrayType*itemarray;
117+
Datum*ipdatums;
118+
bool*ipnulls;
119+
intndatums;
120+
inti;
121+
122+
exstate= (ExprState*)lsecond(saexstate->fxprstate.args);
123+
arraydatum=ExecEvalExprSwitchContext(exstate,
124+
econtext,
125+
&isNull,
126+
NULL);
127+
if (isNull)
128+
continue;
129+
itemarray=DatumGetArrayTypeP(arraydatum);
130+
deconstruct_array(itemarray,
131+
TIDOID,SizeOfIptrData, false,'s',
132+
&ipdatums,&ipnulls,&ndatums);
133+
if (numTids+ndatums>numAllocTids)
134+
{
135+
numAllocTids=numTids+ndatums;
136+
tidList= (ItemPointerData*)
137+
repalloc(tidList,
138+
numAllocTids*sizeof(ItemPointerData));
139+
}
140+
for (i=0;i<ndatums;i++)
141+
{
142+
if (!ipnulls[i])
143+
{
144+
itemptr= (ItemPointer)DatumGetPointer(ipdatums[i]);
145+
if (ItemPointerIsValid(itemptr))
146+
tidList[numTids++]=*itemptr;
147+
}
148+
}
149+
pfree(ipdatums);
150+
pfree(ipnulls);
151+
}
152+
else
153+
elog(ERROR,"could not identify CTID expression");
154+
}
155+
156+
/*
157+
* Sort the array of TIDs into order, and eliminate duplicates.
158+
* Eliminating duplicates is necessary since we want OR semantics
159+
* across the list. Sorting makes it easier to detect duplicates,
160+
* and as a bonus ensures that we will visit the heap in the most
161+
* efficient way.
162+
*/
163+
if (numTids>1)
164+
{
165+
intlastTid;
166+
inti;
167+
168+
qsort((void*)tidList,numTids,sizeof(ItemPointerData),
169+
itemptr_comparator);
170+
lastTid=0;
171+
for (i=1;i<numTids;i++)
172+
{
173+
if (!ItemPointerEquals(&tidList[lastTid],&tidList[i]))
174+
tidList[++lastTid]=tidList[i];
175+
}
176+
numTids=lastTid+1;
68177
}
69178

70179
tidstate->tss_TidList=tidList;
71180
tidstate->tss_NumTids=numTids;
72181
tidstate->tss_TidPtr=-1;
73182
}
74183

184+
/*
185+
* qsort comparator for ItemPointerData items
186+
*/
187+
staticint
188+
itemptr_comparator(constvoid*a,constvoid*b)
189+
{
190+
constItemPointerData*ipa= (constItemPointerData*)a;
191+
constItemPointerData*ipb= (constItemPointerData*)b;
192+
BlockNumberba=ItemPointerGetBlockNumber(ipa);
193+
BlockNumberbb=ItemPointerGetBlockNumber(ipb);
194+
OffsetNumberoa=ItemPointerGetOffsetNumber(ipa);
195+
OffsetNumberob=ItemPointerGetOffsetNumber(ipb);
196+
197+
if (ba<bb)
198+
return-1;
199+
if (ba>bb)
200+
return1;
201+
if (oa<ob)
202+
return-1;
203+
if (oa>ob)
204+
return1;
205+
return0;
206+
}
207+
75208
/* ----------------------------------------------------------------
76209
*TidNext
77210
*
@@ -94,7 +227,6 @@ TidNext(TidScanState *node)
94227
ItemPointerData*tidList;
95228
intnumTids;
96229
boolbBackward;
97-
inttidNumber;
98230

99231
/*
100232
* extract necessary information from tid scan node
@@ -143,38 +275,35 @@ TidNext(TidScanState *node)
143275
tuple=&(node->tss_htup);
144276

145277
/*
146-
* ok, now that we have what we need, fetch an tid tuple. if scanning this
147-
* tid succeeded then return the appropriate heap tuple.. else return
148-
* NULL.
278+
* Initialize or advance scan position, depending on direction.
149279
*/
150280
bBackward=ScanDirectionIsBackward(direction);
151281
if (bBackward)
152282
{
153-
tidNumber=numTids-node->tss_TidPtr-1;
154-
if (tidNumber<0)
283+
if (node->tss_TidPtr<0)
155284
{
156-
tidNumber=0;
285+
/* initialize for backward scan */
157286
node->tss_TidPtr=numTids-1;
158287
}
288+
else
289+
node->tss_TidPtr--;
159290
}
160291
else
161292
{
162-
if ((tidNumber=node->tss_TidPtr)<0)
293+
if (node->tss_TidPtr<0)
163294
{
164-
tidNumber=0;
295+
/* initialize for forward scan */
165296
node->tss_TidPtr=0;
166297
}
298+
else
299+
node->tss_TidPtr++;
167300
}
168-
while (tidNumber<numTids)
169-
{
170-
boolslot_is_valid= false;
171301

302+
while (node->tss_TidPtr >=0&&node->tss_TidPtr<numTids)
303+
{
172304
tuple->t_self=tidList[node->tss_TidPtr];
173305
if (heap_fetch(heapRelation,snapshot,tuple,&buffer, false,NULL))
174306
{
175-
boolprev_matches= false;
176-
intprev_tid;
177-
178307
/*
179308
* store the scanned tuple in the scan tuple slot of the scan
180309
* state. Eventually we will only do this and not return a tuple.
@@ -193,31 +322,13 @@ TidNext(TidScanState *node)
193322
*/
194323
ReleaseBuffer(buffer);
195324

196-
/*
197-
* We must check to see if the current tuple would have been
198-
* matched by an earlier tid, so we don't double report it.
199-
*/
200-
for (prev_tid=0;prev_tid<node->tss_TidPtr;
201-
prev_tid++)
202-
{
203-
if (ItemPointerEquals(&tidList[prev_tid],&tuple->t_self))
204-
{
205-
prev_matches= true;
206-
break;
207-
}
208-
}
209-
if (!prev_matches)
210-
slot_is_valid= true;
211-
else
212-
ExecClearTuple(slot);
325+
returnslot;
213326
}
214-
tidNumber++;
327+
/* Bad TID or failed snapshot qual; try next */
215328
if (bBackward)
216329
node->tss_TidPtr--;
217330
else
218331
node->tss_TidPtr++;
219-
if (slot_is_valid)
220-
returnslot;
221332
}
222333

223334
/*
@@ -242,8 +353,7 @@ TidNext(TidScanState *node)
242353
*Initial States:
243354
* -- the relation indicated is opened for scanning so that the
244355
* "cursor" is positioned before the first qualifying tuple.
245-
* -- tidPtr points to the first tid.
246-
* -- state variable ruleFlag = nil.
356+
* -- tidPtr is -1.
247357
* ----------------------------------------------------------------
248358
*/
249359
TupleTableSlot*
@@ -362,7 +472,6 @@ TidScanState *
362472
ExecInitTidScan(TidScan*node,EState*estate)
363473
{
364474
TidScanState*tidstate;
365-
List*rangeTable;
366475
RangeTblEntry*rtentry;
367476
Oidrelid;
368477
Oidreloid;
@@ -392,8 +501,8 @@ ExecInitTidScan(TidScan *node, EState *estate)
392501
ExecInitExpr((Expr*)node->scan.plan.qual,
393502
(PlanState*)tidstate);
394503

395-
tidstate->tss_tideval= (List*)
396-
ExecInitExpr((Expr*)node->tideval,
504+
tidstate->tss_tidquals= (List*)
505+
ExecInitExpr((Expr*)node->tidquals,
397506
(PlanState*)tidstate);
398507

399508
#defineTIDSCAN_NSLOTS 2
@@ -411,19 +520,13 @@ ExecInitTidScan(TidScan *node, EState *estate)
411520
tidstate->tss_NumTids=0;
412521
tidstate->tss_TidPtr=-1;
413522

414-
/*
415-
* get the range table and direction information from the execution state
416-
* (these are needed to open the relations).
417-
*/
418-
rangeTable=estate->es_range_table;
419-
420523
/*
421524
* open the base relation
422525
*
423526
* We acquire AccessShareLock for the duration of the scan.
424527
*/
425528
relid=node->scan.scanrelid;
426-
rtentry=rt_fetch(relid,rangeTable);
529+
rtentry=rt_fetch(relid,estate->es_range_table);
427530
reloid=rtentry->relid;
428531

429532
currentRelation=heap_open(reloid,AccessShareLock);

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp