Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
P
Postgres FD Implementation
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Abuhujair Javed
Postgres FD Implementation
Commits
0a2e5cdf
Commit
0a2e5cdf
authored
Aug 01, 1998
by
Bruce Momjian
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Allow index use with OR clauses.
parent
0668aa88
Changes
9
Show whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
287 additions
and
316 deletions
+287
-316
src/backend/executor/execQual.c
src/backend/executor/execQual.c
+1
-3
src/backend/executor/nodeIndexscan.c
src/backend/executor/nodeIndexscan.c
+118
-107
src/backend/nodes/copyfuncs.c
src/backend/nodes/copyfuncs.c
+6
-6
src/backend/nodes/equalfuncs.c
src/backend/nodes/equalfuncs.c
+17
-1
src/backend/nodes/outfuncs.c
src/backend/nodes/outfuncs.c
+3
-3
src/backend/nodes/readfuncs.c
src/backend/nodes/readfuncs.c
+4
-4
src/backend/optimizer/path/clausesel.c
src/backend/optimizer/path/clausesel.c
+3
-14
src/backend/optimizer/path/indxpath.c
src/backend/optimizer/path/indxpath.c
+92
-127
src/backend/optimizer/path/orindxpath.c
src/backend/optimizer/path/orindxpath.c
+43
-51
No files found.
src/backend/executor/execQual.c
View file @
0a2e5cdf
...
@@ -7,7 +7,7 @@
...
@@ -7,7 +7,7 @@
*
*
*
*
* IDENTIFICATION
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.3
3 1998/06/15 19:28:19
momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.3
4 1998/08/01 22:12:02
momjian Exp $
*
*
*-------------------------------------------------------------------------
*-------------------------------------------------------------------------
*/
*/
...
@@ -1349,8 +1349,6 @@ ExecQual(List *qual, ExprContext *econtext)
...
@@ -1349,8 +1349,6 @@ ExecQual(List *qual, ExprContext *econtext)
foreach
(
clause
,
qual
)
foreach
(
clause
,
qual
)
{
{
result
=
ExecQualClause
((
Node
*
)
lfirst
(
clause
),
econtext
);
result
=
ExecQualClause
((
Node
*
)
lfirst
(
clause
),
econtext
);
if
(
result
==
true
)
if
(
result
==
true
)
break
;
break
;
...
...
src/backend/executor/nodeIndexscan.c
View file @
0a2e5cdf
...
@@ -7,7 +7,7 @@
...
@@ -7,7 +7,7 @@
*
*
*
*
* IDENTIFICATION
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/nodeIndexscan.c,v 1.
19 1998/07/27 19:37:57 vadim
Exp $
* $Header: /cvsroot/pgsql/src/backend/executor/nodeIndexscan.c,v 1.
20 1998/08/01 22:12:04 momjian
Exp $
*
*
*-------------------------------------------------------------------------
*-------------------------------------------------------------------------
*/
*/
...
@@ -87,7 +87,6 @@ IndexNext(IndexScan *node)
...
@@ -87,7 +87,6 @@ IndexNext(IndexScan *node)
IndexScanState
*
indexstate
;
IndexScanState
*
indexstate
;
ScanDirection
direction
;
ScanDirection
direction
;
Snapshot
snapshot
;
Snapshot
snapshot
;
int
indexPtr
;
IndexScanDescPtr
scanDescs
;
IndexScanDescPtr
scanDescs
;
IndexScanDesc
scandesc
;
IndexScanDesc
scandesc
;
Relation
heapRelation
;
Relation
heapRelation
;
...
@@ -95,6 +94,7 @@ IndexNext(IndexScan *node)
...
@@ -95,6 +94,7 @@ IndexNext(IndexScan *node)
HeapTuple
tuple
;
HeapTuple
tuple
;
TupleTableSlot
*
slot
;
TupleTableSlot
*
slot
;
Buffer
buffer
=
InvalidBuffer
;
Buffer
buffer
=
InvalidBuffer
;
int
numIndices
;
/* ----------------
/* ----------------
* extract necessary information from index scan node
* extract necessary information from index scan node
...
@@ -105,23 +105,20 @@ IndexNext(IndexScan *node)
...
@@ -105,23 +105,20 @@ IndexNext(IndexScan *node)
snapshot
=
estate
->
es_snapshot
;
snapshot
=
estate
->
es_snapshot
;
scanstate
=
node
->
scan
.
scanstate
;
scanstate
=
node
->
scan
.
scanstate
;
indexstate
=
node
->
indxstate
;
indexstate
=
node
->
indxstate
;
indexPtr
=
indexstate
->
iss_IndexPtr
;
scanDescs
=
indexstate
->
iss_ScanDescs
;
scanDescs
=
indexstate
->
iss_ScanDescs
;
scandesc
=
scanDescs
[
indexPtr
];
heapRelation
=
scanstate
->
css_currentRelation
;
heapRelation
=
scanstate
->
css_currentRelation
;
numIndices
=
indexstate
->
iss_NumIndices
;
slot
=
scanstate
->
css_ScanTupleSlot
;
slot
=
scanstate
->
css_ScanTupleSlot
;
/* ----------------
/* ----------------
* ok, now that we have what we need, fetch an index tuple.
* ok, now that we have what we need, fetch an index tuple.
* ----------------
*/
/* ----------------
* if scanning this index succeeded then return the
* if scanning this index succeeded then return the
* appropriate heap tuple.. else return NULL.
* appropriate heap tuple.. else return NULL.
* ----------------
* ----------------
*/
*/
while
(
indexstate
->
iss_IndexPtr
<
numIndices
)
{
scandesc
=
scanDescs
[
indexstate
->
iss_IndexPtr
];
while
((
result
=
index_getnext
(
scandesc
,
direction
))
!=
NULL
)
while
((
result
=
index_getnext
(
scandesc
,
direction
))
!=
NULL
)
{
{
tuple
=
heap_fetch
(
heapRelation
,
snapshot
,
tuple
=
heap_fetch
(
heapRelation
,
snapshot
,
...
@@ -131,6 +128,9 @@ IndexNext(IndexScan *node)
...
@@ -131,6 +128,9 @@ IndexNext(IndexScan *node)
if
(
tuple
!=
NULL
)
if
(
tuple
!=
NULL
)
{
{
bool
prev_matches
=
false
;
int
prev_index
;
/* ----------------
/* ----------------
* store the scanned tuple in the scan tuple slot of
* store the scanned tuple in the scan tuple slot of
* the scan state. Eventually we will only do this and not
* the scan state. Eventually we will only do this and not
...
@@ -144,15 +144,27 @@ IndexNext(IndexScan *node)
...
@@ -144,15 +144,27 @@ IndexNext(IndexScan *node)
buffer
,
/* buffer associated with tuple */
buffer
,
/* buffer associated with tuple */
false
);
/* don't pfree */
false
);
/* don't pfree */
return
slot
;
for
(
prev_index
=
0
;
prev_index
<
indexstate
->
iss_IndexPtr
;
prev_index
++
)
{
if
(
ExecQual
(
nth
(
prev_index
,
node
->
indxqual
),
scanstate
->
cstate
.
cs_ExprContext
))
{
prev_matches
=
true
;
break
;
}
}
}
if
(
!
prev_matches
)
return
slot
;
else
else
{
ExecClearTuple
(
slot
);
}
if
(
BufferIsValid
(
buffer
))
if
(
BufferIsValid
(
buffer
))
ReleaseBuffer
(
buffer
);
ReleaseBuffer
(
buffer
);
}
}
if
(
indexstate
->
iss_IndexPtr
<
numIndices
)
indexstate
->
iss_IndexPtr
++
;
}
}
/* ----------------
/* ----------------
* if we get here it means the index scan failed so we
* if we get here it means the index scan failed so we
* are at the end of the scan..
* are at the end of the scan..
...
@@ -218,7 +230,6 @@ ExecIndexReScan(IndexScan *node, ExprContext *exprCtxt, Plan *parent)
...
@@ -218,7 +230,6 @@ ExecIndexReScan(IndexScan *node, ExprContext *exprCtxt, Plan *parent)
int
i
;
int
i
;
Pointer
*
runtimeKeyInfo
;
Pointer
*
runtimeKeyInfo
;
int
indexPtr
;
int
*
numScanKeys
;
int
*
numScanKeys
;
List
*
indxqual
;
List
*
indxqual
;
List
*
qual
;
List
*
qual
;
...
@@ -238,31 +249,34 @@ ExecIndexReScan(IndexScan *node, ExprContext *exprCtxt, Plan *parent)
...
@@ -238,31 +249,34 @@ ExecIndexReScan(IndexScan *node, ExprContext *exprCtxt, Plan *parent)
numIndices
=
indexstate
->
iss_NumIndices
;
numIndices
=
indexstate
->
iss_NumIndices
;
scanDescs
=
indexstate
->
iss_ScanDescs
;
scanDescs
=
indexstate
->
iss_ScanDescs
;
scanKeys
=
indexstate
->
iss_ScanKeys
;
scanKeys
=
indexstate
->
iss_ScanKeys
;
runtimeKeyInfo
=
(
Pointer
*
)
indexstate
->
iss_RuntimeKeyInfo
;
runtimeKeyInfo
=
(
Pointer
*
)
indexstate
->
iss_RuntimeKeyInfo
;
if
(
runtimeKeyInfo
!=
NULL
)
{
/*
* get the index qualifications and recalculate the appropriate
* values
*/
indexPtr
=
indexstate
->
iss_IndexPtr
;
indxqual
=
node
->
indxqual
;
indxqual
=
node
->
indxqual
;
qual
=
nth
(
indexPtr
,
indxqual
);
numScanKeys
=
indexstate
->
iss_NumScanKeys
;
numScanKeys
=
indexstate
->
iss_NumScanKeys
;
n_keys
=
numScanKeys
[
indexPtr
];
indexstate
->
iss_IndexPtr
=
0
;
run_keys
=
(
int
*
)
runtimeKeyInfo
[
indexPtr
];
scan_keys
=
(
ScanKey
)
scanKeys
[
indexPtr
];
/* it's possible in subselects */
/* it's possible in subselects */
if
(
exprCtxt
==
NULL
)
if
(
exprCtxt
==
NULL
)
exprCtxt
=
node
->
scan
.
scanstate
->
cstate
.
cs_ExprContext
;
exprCtxt
=
node
->
scan
.
scanstate
->
cstate
.
cs_ExprContext
;
for
(
j
=
0
;
j
<
n_keys
;
j
++
)
if
(
exprCtxt
!=
NULL
)
node
->
scan
.
scanstate
->
cstate
.
cs_ExprContext
->
ecxt_outertuple
=
exprCtxt
->
ecxt_outertuple
;
/*
* get the index qualifications and recalculate the appropriate
* values
*/
for
(
i
=
0
;
i
<
numIndices
;
i
++
)
{
if
(
runtimeKeyInfo
&&
runtimeKeyInfo
[
i
]
!=
NULL
)
{
{
qual
=
nth
(
i
,
indxqual
);
n_keys
=
numScanKeys
[
i
];
run_keys
=
(
int
*
)
runtimeKeyInfo
[
i
];
scan_keys
=
(
ScanKey
)
scanKeys
[
i
];
for
(
j
=
0
;
j
<
n_keys
;
j
++
)
{
/*
/*
* If we have a run-time key, then extract the run-time
* If we have a run-time key, then extract the run-time
* expression and evaluate it with respect to the current
* expression and evaluate it with respect to the current
...
@@ -287,16 +301,6 @@ ExecIndexReScan(IndexScan *node, ExprContext *exprCtxt, Plan *parent)
...
@@ -287,16 +301,6 @@ ExecIndexReScan(IndexScan *node, ExprContext *exprCtxt, Plan *parent)
scan_keys
[
j
].
sk_flags
&=
~
SK_ISNULL
;
scan_keys
[
j
].
sk_flags
&=
~
SK_ISNULL
;
}
}
}
}
}
/*
* rescans all indices
*
* note: AMrescan assumes only one scan key. This may have to change if
* we ever decide to support multiple keys.
*/
for
(
i
=
0
;
i
<
numIndices
;
i
++
)
{
sdesc
=
scanDescs
[
i
];
sdesc
=
scanDescs
[
i
];
skey
=
scanKeys
[
i
];
skey
=
scanKeys
[
i
];
index_rescan
(
sdesc
,
direction
,
skey
);
index_rescan
(
sdesc
,
direction
,
skey
);
...
@@ -322,12 +326,15 @@ ExecEndIndexScan(IndexScan *node)
...
@@ -322,12 +326,15 @@ ExecEndIndexScan(IndexScan *node)
{
{
CommonScanState
*
scanstate
;
CommonScanState
*
scanstate
;
IndexScanState
*
indexstate
;
IndexScanState
*
indexstate
;
Pointer
*
runtimeKeyInfo
;
ScanKey
*
scanKeys
;
ScanKey
*
scanKeys
;
int
*
numScanKeys
;
int
numIndices
;
int
numIndices
;
int
i
;
int
i
;
scanstate
=
node
->
scan
.
scanstate
;
scanstate
=
node
->
scan
.
scanstate
;
indexstate
=
node
->
indxstate
;
indexstate
=
node
->
indxstate
;
runtimeKeyInfo
=
(
Pointer
*
)
indexstate
->
iss_RuntimeKeyInfo
;
/* ----------------
/* ----------------
* extract information from the node
* extract information from the node
...
@@ -335,6 +342,7 @@ ExecEndIndexScan(IndexScan *node)
...
@@ -335,6 +342,7 @@ ExecEndIndexScan(IndexScan *node)
*/
*/
numIndices
=
indexstate
->
iss_NumIndices
;
numIndices
=
indexstate
->
iss_NumIndices
;
scanKeys
=
indexstate
->
iss_ScanKeys
;
scanKeys
=
indexstate
->
iss_ScanKeys
;
numScanKeys
=
indexstate
->
iss_NumScanKeys
;
/* ----------------
/* ----------------
* Free the projection info and the scan attribute info
* Free the projection info and the scan attribute info
...
@@ -362,6 +370,23 @@ ExecEndIndexScan(IndexScan *node)
...
@@ -362,6 +370,23 @@ ExecEndIndexScan(IndexScan *node)
if
(
scanKeys
[
i
]
!=
NULL
)
if
(
scanKeys
[
i
]
!=
NULL
)
pfree
(
scanKeys
[
i
]);
pfree
(
scanKeys
[
i
]);
}
}
pfree
(
scanKeys
);
pfree
(
numScanKeys
);
if
(
runtimeKeyInfo
)
{
for
(
i
=
0
;
i
<
numIndices
;
i
++
)
{
List
*
qual
;
int
n_keys
;
qual
=
nth
(
i
,
indxqual
);
n_keys
=
length
(
qual
);
if
(
n_keys
>
0
)
pfree
(
runtimeKeyInfo
[
i
]);
}
pfree
(
runtimeKeyInfo
);
}
/* ----------------
/* ----------------
* clear out tuple table slots
* clear out tuple table slots
...
@@ -886,20 +911,7 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent)
...
@@ -886,20 +911,7 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent)
if
(
have_runtime_keys
)
if
(
have_runtime_keys
)
indexstate
->
iss_RuntimeKeyInfo
=
(
Pointer
)
runtimeKeyInfo
;
indexstate
->
iss_RuntimeKeyInfo
=
(
Pointer
)
runtimeKeyInfo
;
else
else
{
indexstate
->
iss_RuntimeKeyInfo
=
NULL
;
indexstate
->
iss_RuntimeKeyInfo
=
NULL
;
for
(
i
=
0
;
i
<
numIndices
;
i
++
)
{
List
*
qual
;
int
n_keys
;
qual
=
nth
(
i
,
indxqual
);
n_keys
=
length
(
qual
);
if
(
n_keys
>
0
)
pfree
(
runtimeKeyInfo
[
i
]);
}
pfree
(
runtimeKeyInfo
);
}
/* ----------------
/* ----------------
* get the range table and direction information
* get the range table and direction information
...
@@ -991,6 +1003,5 @@ int
...
@@ -991,6 +1003,5 @@ int
ExecCountSlotsIndexScan
(
IndexScan
*
node
)
ExecCountSlotsIndexScan
(
IndexScan
*
node
)
{
{
return
ExecCountSlotsNode
(
outerPlan
((
Plan
*
)
node
))
+
return
ExecCountSlotsNode
(
outerPlan
((
Plan
*
)
node
))
+
ExecCountSlotsNode
(
innerPlan
((
Plan
*
)
node
))
+
ExecCountSlotsNode
(
innerPlan
((
Plan
*
)
node
))
+
INDEXSCAN_NSLOTS
;
INDEXSCAN_NSLOTS
;
}
}
src/backend/nodes/copyfuncs.c
View file @
0a2e5cdf
/*-------------------------------------------------------------------------
/*-------------------------------------------------------------------------
*
*
* copyfuncs.c--
* copyfuncs.c--
* Copy functions for Postgres tree nodes.
* Copy functions for Postgres tree nodes.
...
@@ -7,7 +7,7 @@
...
@@ -7,7 +7,7 @@
*
*
*
*
* IDENTIFICATION
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.4
4 1998/07/18 04:22:2
5 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.4
5 1998/08/01 22:12:0
5 momjian Exp $
*
*
*-------------------------------------------------------------------------
*-------------------------------------------------------------------------
*/
*/
...
@@ -990,16 +990,16 @@ _copyArrayRef(ArrayRef *from)
...
@@ -990,16 +990,16 @@ _copyArrayRef(ArrayRef *from)
*/
*/
/* ----------------
/* ----------------
* _copyRel
* _copyRel
OptInfo
* ----------------
* ----------------
*/
*/
/*
/*
** when you change this, also make sure to fix up xfunc_copyRel in
** when you change this, also make sure to fix up xfunc_copyRel
OptInfo
in
** planner/path/xfunc.c accordingly!!!
** planner/path/xfunc.c accordingly!!!
** -- JMH, 8/2/93
** -- JMH, 8/2/93
*/
*/
static
RelOptInfo
*
static
RelOptInfo
*
_copyRel
(
RelOptInfo
*
from
)
_copyRel
OptInfo
(
RelOptInfo
*
from
)
{
{
RelOptInfo
*
newnode
=
makeNode
(
RelOptInfo
);
RelOptInfo
*
newnode
=
makeNode
(
RelOptInfo
);
int
i
,
int
i
,
...
@@ -1735,7 +1735,7 @@ copyObject(void *from)
...
@@ -1735,7 +1735,7 @@ copyObject(void *from)
* RELATION NODES
* RELATION NODES
*/
*/
case
T_RelOptInfo
:
case
T_RelOptInfo
:
retval
=
_copyRel
(
from
);
retval
=
_copyRel
OptInfo
(
from
);
break
;
break
;
case
T_Path
:
case
T_Path
:
retval
=
_copyPath
(
from
);
retval
=
_copyPath
(
from
);
...
...
src/backend/nodes/equalfuncs.c
View file @
0a2e5cdf
...
@@ -7,7 +7,7 @@
...
@@ -7,7 +7,7 @@
*
*
*
*
* IDENTIFICATION
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.1
6 1998/02/26 04:3
2:07 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.1
7 1998/08/01 22:1
2:07 momjian Exp $
*
*
*-------------------------------------------------------------------------
*-------------------------------------------------------------------------
*/
*/
...
@@ -302,6 +302,19 @@ _equalCInfo(CInfo *a, CInfo *b)
...
@@ -302,6 +302,19 @@ _equalCInfo(CInfo *a, CInfo *b)
(
b
->
indexids
)));
(
b
->
indexids
)));
}
}
/*
* RelOptInfo is a subclass of Node.
*/
static
bool
_equalRelOptInfo
(
RelOptInfo
*
a
,
RelOptInfo
*
b
)
{
Assert
(
IsA
(
a
,
RelOptInfo
));
Assert
(
IsA
(
b
,
RelOptInfo
));
return
(
equal
((
a
->
relids
),
(
b
->
relids
)));
}
static
bool
static
bool
_equalJoinMethod
(
JoinMethod
*
a
,
JoinMethod
*
b
)
_equalJoinMethod
(
JoinMethod
*
a
,
JoinMethod
*
b
)
{
{
...
@@ -663,6 +676,9 @@ equal(void *a, void *b)
...
@@ -663,6 +676,9 @@ equal(void *a, void *b)
case
T_CInfo
:
case
T_CInfo
:
retval
=
_equalCInfo
(
a
,
b
);
retval
=
_equalCInfo
(
a
,
b
);
break
;
break
;
case
T_RelOptInfo
:
retval
=
_equalRelOptInfo
(
a
,
b
);
break
;
case
T_JoinMethod
:
case
T_JoinMethod
:
retval
=
_equalJoinMethod
(
a
,
b
);
retval
=
_equalJoinMethod
(
a
,
b
);
break
;
break
;
...
...
src/backend/nodes/outfuncs.c
View file @
0a2e5cdf
...
@@ -7,7 +7,7 @@
...
@@ -7,7 +7,7 @@
*
*
*
*
* IDENTIFICATION
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.4
1 1998/07/18 04:22:26
momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.4
2 1998/08/01 22:12:08
momjian Exp $
*
*
* NOTES
* NOTES
* Every (plan) node in POSTGRES has an associated "out" routine which
* Every (plan) node in POSTGRES has an associated "out" routine which
...
@@ -990,7 +990,7 @@ _outEState(StringInfo str, EState *node)
...
@@ -990,7 +990,7 @@ _outEState(StringInfo str, EState *node)
* Stuff from relation.h
* Stuff from relation.h
*/
*/
static
void
static
void
_outRel
(
StringInfo
str
,
RelOptInfo
*
node
)
_outRel
OptInfo
(
StringInfo
str
,
RelOptInfo
*
node
)
{
{
char
buf
[
500
];
char
buf
[
500
];
...
@@ -1788,7 +1788,7 @@ _outNode(StringInfo str, void *obj)
...
@@ -1788,7 +1788,7 @@ _outNode(StringInfo str, void *obj)
_outEState
(
str
,
obj
);
_outEState
(
str
,
obj
);
break
;
break
;
case
T_RelOptInfo
:
case
T_RelOptInfo
:
_outRel
(
str
,
obj
);
_outRel
OptInfo
(
str
,
obj
);
break
;
break
;
case
T_TargetEntry
:
case
T_TargetEntry
:
_outTargetEntry
(
str
,
obj
);
_outTargetEntry
(
str
,
obj
);
...
...
src/backend/nodes/readfuncs.c
View file @
0a2e5cdf
...
@@ -7,7 +7,7 @@
...
@@ -7,7 +7,7 @@
*
*
*
*
* IDENTIFICATION
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v 1.3
3 1998/07/18 04:22:26
momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v 1.3
4 1998/08/01 22:12:09
momjian Exp $
*
*
* NOTES
* NOTES
* Most of the read functions for plan nodes are tested. (In fact, they
* Most of the read functions for plan nodes are tested. (In fact, they
...
@@ -1218,11 +1218,11 @@ _readEState()
...
@@ -1218,11 +1218,11 @@ _readEState()
*/
*/
/* ----------------
/* ----------------
* _readRel
* _readRel
OptInfo
* ----------------
* ----------------
*/
*/
static
RelOptInfo
*
static
RelOptInfo
*
_readRel
()
_readRel
OptInfo
()
{
{
RelOptInfo
*
local_node
;
RelOptInfo
*
local_node
;
char
*
token
;
char
*
token
;
...
@@ -1991,7 +1991,7 @@ parsePlanString(void)
...
@@ -1991,7 +1991,7 @@ parsePlanString(void)
else
if
(
!
strncmp
(
token
,
"ESTATE"
,
length
))
else
if
(
!
strncmp
(
token
,
"ESTATE"
,
length
))
return_value
=
_readEState
();
return_value
=
_readEState
();
else
if
(
!
strncmp
(
token
,
"RELOPTINFO"
,
length
))
else
if
(
!
strncmp
(
token
,
"RELOPTINFO"
,
length
))
return_value
=
_readRel
();
return_value
=
_readRel
OptInfo
();
else
if
(
!
strncmp
(
token
,
"TARGETENTRY"
,
length
))
else
if
(
!
strncmp
(
token
,
"TARGETENTRY"
,
length
))
return_value
=
_readTargetEntry
();
return_value
=
_readTargetEntry
();
else
if
(
!
strncmp
(
token
,
"RTE"
,
length
))
else
if
(
!
strncmp
(
token
,
"RTE"
,
length
))
...
...
src/backend/optimizer/path/clausesel.c
View file @
0a2e5cdf
...
@@ -7,7 +7,7 @@
...
@@ -7,7 +7,7 @@
*
*
*
*
* IDENTIFICATION
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/clausesel.c,v 1.
9 1998/07/18 04:22:30
momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/clausesel.c,v 1.
10 1998/08/01 22:12:11
momjian Exp $
*
*
*-------------------------------------------------------------------------
*-------------------------------------------------------------------------
*/
*/
...
@@ -159,19 +159,8 @@ set_rest_selec(Query *root, List *clauseinfo_list)
...
@@ -159,19 +159,8 @@ set_rest_selec(Query *root, List *clauseinfo_list)
Cost
Cost
compute_clause_selec
(
Query
*
root
,
Node
*
clause
,
List
*
or_selectivities
)
compute_clause_selec
(
Query
*
root
,
Node
*
clause
,
List
*
or_selectivities
)
{
{
if
(
!
is_opclause
(
clause
))
if
(
is_opclause
(
clause
))
{
return
compute_selec
(
root
,
lcons
(
clause
,
NIL
),
or_selectivities
);
/*
* if it's not an operator clause, then it is a boolean clause
* -jolly
*/
/*
* Boolean variables get a selectivity of 1/2.
*/
return
(
0
.
1
);
}
else
if
(
not_clause
(
clause
))
else
if
(
not_clause
(
clause
))
{
{
...
...
src/backend/optimizer/path/indxpath.c
View file @
0a2e5cdf
...
@@ -8,7 +8,7 @@
...
@@ -8,7 +8,7 @@
*
*
*
*
* IDENTIFICATION
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.
19 1998/07/31 15:10:40 vadim
Exp $
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.
20 1998/08/01 22:12:12 momjian
Exp $
*
*
*-------------------------------------------------------------------------
*-------------------------------------------------------------------------
*/
*/
...
@@ -21,6 +21,7 @@
...
@@ -21,6 +21,7 @@
#include "access/nbtree.h"
#include "access/nbtree.h"
#include "catalog/catname.h"
#include "catalog/catname.h"
#include "catalog/pg_amop.h"
#include "catalog/pg_amop.h"
#include "catalog/pg_type.h"
#include "executor/executor.h"
#include "executor/executor.h"
#include "fmgr.h"
#include "fmgr.h"
#include "nodes/makefuncs.h"
#include "nodes/makefuncs.h"
...
@@ -77,10 +78,7 @@ create_index_paths(Query *root, RelOptInfo *rel, RelOptInfo *index,
...
@@ -77,10 +78,7 @@ create_index_paths(Query *root, RelOptInfo *rel, RelOptInfo *index,
List
*
clausegroup_list
,
bool
join
);
List
*
clausegroup_list
,
bool
join
);
static
List
*
add_index_paths
(
List
*
indexpaths
,
List
*
new_indexpaths
);
static
List
*
add_index_paths
(
List
*
indexpaths
,
List
*
new_indexpaths
);
static
bool
function_index_operand
(
Expr
*
funcOpnd
,
RelOptInfo
*
rel
,
RelOptInfo
*
index
);
static
bool
function_index_operand
(
Expr
*
funcOpnd
,
RelOptInfo
*
rel
,
RelOptInfo
*
index
);
static
bool
SingleAttributeIndex
(
RelOptInfo
*
index
);
/* If Spyros can use a constant PRS2_BOOL_TYPEID, I can use this */
#define BOOL_TYPEID ((Oid) 16)
/*
/*
* find-index-paths--
* find-index-paths--
...
@@ -121,35 +119,25 @@ find_index_paths(Query *root,
...
@@ -121,35 +119,25 @@ find_index_paths(Query *root,
List
*
joinclausegroups
=
NIL
;
List
*
joinclausegroups
=
NIL
;
List
*
joinpaths
=
NIL
;
List
*
joinpaths
=
NIL
;
List
*
retval
=
NIL
;
List
*
retval
=
NIL
;
List
*
ilist
;
if
(
indices
==
NIL
)
foreach
(
ilist
,
indices
)
return
(
NULL
);
{
index
=
(
RelOptInfo
*
)
lfirst
(
ilist
);
index
=
(
RelOptInfo
*
)
lfirst
(
indices
);
retval
=
find_index_paths
(
root
,
rel
,
lnext
(
indices
),
clauseinfo_list
,
joininfo_list
);
/* If this is a partial index, return if it fails the predicate test */
/* If this is a partial index, return if it fails the predicate test */
if
(
index
->
indpred
!=
NIL
)
if
(
index
->
indpred
!=
NIL
)
if
(
!
pred_test
(
index
->
indpred
,
clauseinfo_list
,
joininfo_list
))
if
(
!
pred_test
(
index
->
indpred
,
clauseinfo_list
,
joininfo_list
))
return
retval
;
continue
;
/*
/*
* 1. If this index has only one key, try matching it against
* 1. Try matching the index against subclauses of an 'or' clause.
* subclauses of an 'or' clause. The fields of the clauseinfo nodes
* The fields of the clauseinfo nodes are marked with lists of the
* are marked with lists of the matching indices no path are actually
* matching indices. No path are actually created. We currently
* created.
* only look to match the first key. We don't find multi-key index
*
* cases where an AND matches the first key, and the OR matches the
* XXX NOTE: Currently btrees dos not support indices with > 1 key, so
* second key.
* the following test will always be true for now but we have decided
* not to support index-scans on disjunction . -- lp
*/
*/
if
(
SingleAttributeIndex
(
index
))
{
match_index_orclauses
(
rel
,
match_index_orclauses
(
rel
,
index
,
index
,
index
->
indexkeys
[
0
],
index
->
indexkeys
[
0
],
...
@@ -205,6 +193,7 @@ find_index_paths(Query *root,
...
@@ -205,6 +193,7 @@ find_index_paths(Query *root,
retval
=
add_index_paths
(
joinpaths
,
retval
);
retval
=
add_index_paths
(
joinpaths
,
retval
);
if
(
scanpaths
!=
NULL
)
if
(
scanpaths
!=
NULL
)
retval
=
add_index_paths
(
scanpaths
,
retval
);
retval
=
add_index_paths
(
scanpaths
,
retval
);
}
return
retval
;
return
retval
;
...
@@ -297,7 +286,7 @@ match_index_to_operand(int indexkey,
...
@@ -297,7 +286,7 @@ match_index_to_operand(int indexkey,
* (1) the operator within the subclause can be used with one
* (1) the operator within the subclause can be used with one
* of the index's operator classes, and
* of the index's operator classes, and
* (2) there is a usable key that matches the variable within a
* (2) there is a usable key that matches the variable within a
* s
arg
able clause.
* s
earch
able clause.
*
*
* 'or-clauses' are the remaining subclauses within the 'or' clause
* 'or-clauses' are the remaining subclauses within the 'or' clause
* 'other-matching-indices' is the list of information on other indices
* 'other-matching-indices' is the list of information on other indices
...
@@ -322,30 +311,31 @@ match_index_orclause(RelOptInfo *rel,
...
@@ -322,30 +311,31 @@ match_index_orclause(RelOptInfo *rel,
List
*
matched_indices
=
other_matching_indices
;
List
*
matched_indices
=
other_matching_indices
;
List
*
index_list
=
NIL
;
List
*
index_list
=
NIL
;
List
*
clist
;
List
*
clist
;
List
*
ind
;
if
(
!
matched_indices
)
matched_indices
=
lcons
(
NIL
,
NIL
);
for
(
clist
=
or_clauses
,
ind
=
matched_indices
;
foreach
(
clist
,
or_clauses
)
clist
;
clist
=
lnext
(
clist
),
ind
=
lnext
(
ind
))
{
{
clause
=
lfirst
(
clist
);
clause
=
lfirst
(
clist
);
if
(
is_opclause
(
clause
)
&&
if
(
is_opclause
(
clause
)
&&
op_class
(((
Oper
*
)
((
Expr
*
)
clause
)
->
oper
)
->
opno
,
op_class
(((
Oper
*
)
((
Expr
*
)
clause
)
->
oper
)
->
opno
,
xclass
,
index
->
relam
)
&&
xclass
,
index
->
relam
)
&&
match_index_to_operand
(
indexkey
,
((
match_index_to_operand
(
indexkey
,
(
Expr
*
)
get_leftop
((
Expr
*
)
clause
),
rel
,
index
)
&&
IsA
(
get_rightop
((
Expr
*
)
clause
),
Const
))
||
(
match_index_to_operand
(
indexkey
,
(
Expr
*
)
get_leftop
((
Expr
*
)
clause
),
(
Expr
*
)
get_leftop
((
Expr
*
)
clause
),
rel
,
rel
,
index
)
&&
index
)
&&
IsA
(
get_rightop
((
Expr
*
)
clause
),
Const
))
IsA
(
get_rightop
((
Expr
*
)
clause
),
Const
))
))
{
{
matched_indices
=
lcons
(
index
,
matched_indices
);
matched_indices
=
lcons
(
index
,
matched_indices
);
index_list
=
lappend
(
index_list
,
matched_indices
);
}
}
index_list
=
lappend
(
index_list
,
matched_indices
);
/* for the first index, we are creating the indexids list */
if
(
matched_indices
)
matched_indices
=
lnext
(
matched_indices
);
}
}
return
(
index_list
);
return
(
index_list
);
...
@@ -1061,7 +1051,7 @@ clause_pred_clause_test(Expr *predicate, Node *clause)
...
@@ -1061,7 +1051,7 @@ clause_pred_clause_test(Expr *predicate, Node *clause)
*/
*/
test_oper
=
makeOper
(
test_op
,
/* opno */
test_oper
=
makeOper
(
test_op
,
/* opno */
InvalidOid
,
/* opid */
InvalidOid
,
/* opid */
BOOL
_TYPE
ID
,
/* opresulttype */
BOOL
O
ID
,
/* opresulttype */
0
,
/* opsize */
0
,
/* opsize */
NULL
);
/* op_fcache */
NULL
);
/* op_fcache */
replace_opid
(
test_oper
);
replace_opid
(
test_oper
);
...
@@ -1176,7 +1166,8 @@ extract_restrict_clauses(List *clausegroup)
...
@@ -1176,7 +1166,8 @@ extract_restrict_clauses(List *clausegroup)
*
*
*/
*/
static
List
*
static
List
*
index_innerjoin
(
Query
*
root
,
RelOptInfo
*
rel
,
List
*
clausegroup_list
,
RelOptInfo
*
index
)
index_innerjoin
(
Query
*
root
,
RelOptInfo
*
rel
,
List
*
clausegroup_list
,
RelOptInfo
*
index
)
{
{
List
*
clausegroup
=
NIL
;
List
*
clausegroup
=
NIL
;
List
*
cg_list
=
NIL
;
List
*
cg_list
=
NIL
;
...
@@ -1366,29 +1357,3 @@ function_index_operand(Expr *funcOpnd, RelOptInfo *rel, RelOptInfo *index)
...
@@ -1366,29 +1357,3 @@ function_index_operand(Expr *funcOpnd, RelOptInfo *rel, RelOptInfo *index)
return
true
;
return
true
;
}
}
static
bool
SingleAttributeIndex
(
RelOptInfo
*
index
)
{
/*
* return false for now as I don't know if we support index scans on
* disjunction and the code doesn't work
*/
return
(
false
);
#if 0
/*
* Non-functional indices.
*/
if (index->indproc == InvalidOid)
return (index->indexkeys[0] != 0 &&
index->indexkeys[1] == 0);
/*
* We have a functional index which is a single attr index
*/
return true;
#endif
}
src/backend/optimizer/path/orindxpath.c
View file @
0a2e5cdf
...
@@ -7,7 +7,7 @@
...
@@ -7,7 +7,7 @@
*
*
*
*
* IDENTIFICATION
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/orindxpath.c,v 1.
7 1998/07/18 04:22:3
3 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/orindxpath.c,v 1.
8 1998/08/01 22:12:1
3 momjian Exp $
*
*
*-------------------------------------------------------------------------
*-------------------------------------------------------------------------
*/
*/
...
@@ -55,10 +55,11 @@ create_or_index_paths(Query *root,
...
@@ -55,10 +55,11 @@ create_or_index_paths(Query *root,
RelOptInfo
*
rel
,
List
*
clauses
)
RelOptInfo
*
rel
,
List
*
clauses
)
{
{
List
*
t_list
=
NIL
;
List
*
t_list
=
NIL
;
List
*
clist
;
if
(
clauses
!=
NIL
)
foreach
(
clist
,
clauses
)
{
{
CInfo
*
clausenode
=
(
CInfo
*
)
(
lfirst
(
cl
auses
));
CInfo
*
clausenode
=
(
CInfo
*
)
(
lfirst
(
cl
ist
));
/*
/*
* Check to see if this clause is an 'or' clause, and, if so,
* Check to see if this clause is an 'or' clause, and, if so,
...
@@ -77,8 +78,11 @@ create_or_index_paths(Query *root,
...
@@ -77,8 +78,11 @@ create_or_index_paths(Query *root,
index_list
=
clausenode
->
indexids
;
index_list
=
clausenode
->
indexids
;
foreach
(
temp
,
index_list
)
foreach
(
temp
,
index_list
)
{
{
if
(
!
temp
)
if
(
!
lfirst
(
temp
))
{
index_flag
=
false
;
index_flag
=
false
;
break
;
}
}
}
if
(
index_flag
)
if
(
index_flag
)
{
/* used to be a lisp every function */
{
/* used to be a lisp every function */
...
@@ -100,8 +104,7 @@ create_or_index_paths(Query *root,
...
@@ -100,8 +104,7 @@ create_or_index_paths(Query *root,
pathnode
->
path
.
pathtype
=
T_IndexScan
;
pathnode
->
path
.
pathtype
=
T_IndexScan
;
pathnode
->
path
.
parent
=
rel
;
pathnode
->
path
.
parent
=
rel
;
pathnode
->
indexqual
=
pathnode
->
indexqual
=
lcons
(
clausenode
,
NIL
);
lcons
(
clausenode
,
NIL
);
pathnode
->
indexid
=
indexids
;
pathnode
->
indexid
=
indexids
;
pathnode
->
path
.
path_cost
=
cost
;
pathnode
->
path
.
path_cost
=
cost
;
...
@@ -110,9 +113,8 @@ create_or_index_paths(Query *root,
...
@@ -110,9 +113,8 @@ create_or_index_paths(Query *root,
* processing -- JMH, 7/7/92
* processing -- JMH, 7/7/92
*/
*/
pathnode
->
path
.
locclauseinfo
=
pathnode
->
path
.
locclauseinfo
=
set_difference
(
clauses
,
set_difference
(
copyObject
((
Node
*
)
rel
->
clauseinfo
),
copyObject
((
Node
*
)
lcons
(
clausenode
,
NIL
));
rel
->
clauseinfo
));
#if 0 /* fix xfunc */
#if 0 /* fix xfunc */
/* add in cost for expensive functions! -- JMH, 7/7/92 */
/* add in cost for expensive functions! -- JMH, 7/7/92 */
...
@@ -123,12 +125,8 @@ create_or_index_paths(Query *root,
...
@@ -123,12 +125,8 @@ create_or_index_paths(Query *root,
}
}
#endif
#endif
clausenode
->
selectivity
=
(
Cost
)
floatVal
(
selecs
);
clausenode
->
selectivity
=
(
Cost
)
floatVal
(
selecs
);
t_list
=
t_list
=
lappend
(
t_list
,
pathnode
);
lcons
(
pathnode
,
create_or_index_paths
(
root
,
rel
,
lnext
(
clauses
)));
}
}
else
t_list
=
create_or_index_paths
(
root
,
rel
,
lnext
(
clauses
));
}
}
}
}
...
@@ -167,32 +165,28 @@ best_or_subclause_indices(Query *root,
...
@@ -167,32 +165,28 @@ best_or_subclause_indices(Query *root,
Cost
*
cost
,
/* return value */
Cost
*
cost
,
/* return value */
List
**
selecs
)
/* return value */
List
**
selecs
)
/* return value */
{
{
if
(
subclauses
==
NIL
)
List
*
slist
;
{
*
indexids
=
nreverse
(
examined_indexids
);
foreach
(
slist
,
subclauses
)
*
cost
=
subcost
;
*
selecs
=
nreverse
(
selectivities
);
}
else
{
{
int
best_indexid
;
int
best_indexid
;
Cost
best_cost
;
Cost
best_cost
;
Cost
best_selec
;
Cost
best_selec
;
best_or_subclause_index
(
root
,
rel
,
lfirst
(
s
ubclauses
),
lfirst
(
indices
),
best_or_subclause_index
(
root
,
rel
,
lfirst
(
s
list
),
lfirst
(
indices
),
&
best_indexid
,
&
best_cost
,
&
best_selec
);
&
best_indexid
,
&
best_cost
,
&
best_selec
);
best_or_subclause_indices
(
root
,
examined_indexids
=
lappendi
(
examined_indexids
,
best_indexid
);
rel
,
subcost
+=
best_cost
;
lnext
(
subclauses
),
selectivities
=
lappend
(
selectivities
,
makeFloat
(
best_selec
));
lnext
(
indices
),
lconsi
(
best_indexid
,
examined_indexids
),
indices
=
lnext
(
indices
);
subcost
+
best_cost
,
lcons
(
makeFloat
(
best_selec
),
selectivities
),
indexids
,
cost
,
selecs
);
}
}
*
indexids
=
examined_indexids
;
*
cost
=
subcost
;
*
selecs
=
selectivities
;
return
;
return
;
}
}
...
@@ -219,20 +213,21 @@ best_or_subclause_index(Query *root,
...
@@ -219,20 +213,21 @@ best_or_subclause_index(Query *root,
Cost
*
retCost
,
/* return value */
Cost
*
retCost
,
/* return value */
Cost
*
retSelec
)
/* return value */
Cost
*
retSelec
)
/* return value */
{
{
if
(
indices
!=
NIL
)
List
*
ilist
;
bool
first_run
=
true
;
foreach
(
ilist
,
indices
)
{
{
RelOptInfo
*
index
=
(
RelOptInfo
*
)
lfirst
(
ilist
);
Datum
value
;
Datum
value
;
int
flag
=
0
;
int
flag
=
0
;
Cost
subcost
;
Cost
subcost
;
RelOptInfo
*
index
=
(
RelOptInfo
*
)
lfirst
(
indices
);
AttrNumber
attno
=
(
get_leftop
(
subclause
))
->
varattno
;
AttrNumber
attno
=
(
get_leftop
(
subclause
))
->
varattno
;
Oid
opno
=
((
Oper
*
)
subclause
->
oper
)
->
opno
;
Oid
opno
=
((
Oper
*
)
subclause
->
oper
)
->
opno
;
bool
constant_on_right
=
non_null
((
Expr
*
)
get_rightop
(
subclause
));
bool
constant_on_right
=
non_null
((
Expr
*
)
get_rightop
(
subclause
));
float
npages
,
float
npages
,
selec
;
selec
;
int
subclause_indexid
;
Cost
subclause_cost
;
Cost
subclause_selec
;
if
(
constant_on_right
)
if
(
constant_on_right
)
value
=
((
Const
*
)
get_rightop
(
subclause
))
->
constvalue
;
value
=
((
Const
*
)
get_rightop
(
subclause
))
->
constvalue
;
...
@@ -242,6 +237,7 @@ best_or_subclause_index(Query *root,
...
@@ -242,6 +237,7 @@ best_or_subclause_index(Query *root,
flag
=
(
_SELEC_IS_CONSTANT_
||
_SELEC_CONSTANT_RIGHT_
);
flag
=
(
_SELEC_IS_CONSTANT_
||
_SELEC_CONSTANT_RIGHT_
);
else
else
flag
=
_SELEC_CONSTANT_RIGHT_
;
flag
=
_SELEC_CONSTANT_RIGHT_
;
index_selectivity
(
lfirsti
(
index
->
relids
),
index_selectivity
(
lfirsti
(
index
->
relids
),
index
->
classlist
,
index
->
classlist
,
lconsi
(
opno
,
NIL
),
lconsi
(
opno
,
NIL
),
...
@@ -262,26 +258,22 @@ best_or_subclause_index(Query *root,
...
@@ -262,26 +258,22 @@ best_or_subclause_index(Query *root,
index
->
pages
,
index
->
pages
,
index
->
tuples
,
index
->
tuples
,
false
);
false
);
best_or_subclause_index
(
root
,
rel
,
subclause
,
lnext
(
indices
),
&
subclause_indexid
,
&
subclause_cost
,
&
subclause_selec
);
if
(
subclause_indexid
==
0
||
subcost
<
subclause_c
ost
)
if
(
first_run
||
subcost
<
*
retC
ost
)
{
{
*
retIndexid
=
lfirsti
(
index
->
relids
);
*
retIndexid
=
lfirsti
(
index
->
relids
);
*
retCost
=
subcost
;
*
retCost
=
subcost
;
*
retSelec
=
selec
;
*
retSelec
=
selec
;
first_run
=
false
;
}
}
else
}
/* we didn't get any indexes, so zero return values */
if
(
first_run
)
{
{
*
retIndexid
=
0
;
*
retIndexid
=
0
;
*
retCost
=
0
.
0
;
*
retCost
=
0
.
0
;
*
retSelec
=
0
.
0
;
*
retSelec
=
0
.
0
;
}
}
}
return
;
return
;
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment