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
d1463050
Commit
d1463050
authored
Mar 18, 1997
by
Marc G. Fournier
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Patches for Vadim's multikey indexing...
parent
c3d637ac
Changes
9
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
414 additions
and
248 deletions
+414
-248
src/backend/access/common/indexvalid.c
src/backend/access/common/indexvalid.c
+2
-2
src/backend/access/nbtree/nbtree.c
src/backend/access/nbtree/nbtree.c
+5
-2
src/backend/access/nbtree/nbtsearch.c
src/backend/access/nbtree/nbtsearch.c
+43
-32
src/backend/access/nbtree/nbtutils.c
src/backend/access/nbtree/nbtutils.c
+142
-110
src/backend/optimizer/path/indxpath.c
src/backend/optimizer/path/indxpath.c
+190
-86
src/backend/optimizer/plan/createplan.c
src/backend/optimizer/plan/createplan.c
+22
-9
src/backend/optimizer/util/pathnode.c
src/backend/optimizer/util/pathnode.c
+4
-3
src/include/access/nbtree.h
src/include/access/nbtree.h
+4
-3
src/include/nodes/relation.h
src/include/nodes/relation.h
+2
-1
No files found.
src/backend/access/common/indexvalid.c
View file @
d1463050
...
@@ -7,7 +7,7 @@
...
@@ -7,7 +7,7 @@
*
*
*
*
* IDENTIFICATION
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/common/Attic/indexvalid.c,v 1.1
3 1997/03/12 20:56:32
scrappy Exp $
* $Header: /cvsroot/pgsql/src/backend/access/common/Attic/indexvalid.c,v 1.1
4 1997/03/18 18:38:19
scrappy Exp $
*
*
*-------------------------------------------------------------------------
*-------------------------------------------------------------------------
*/
*/
...
@@ -48,7 +48,7 @@ index_keytest(IndexTuple tuple,
...
@@ -48,7 +48,7 @@ index_keytest(IndexTuple tuple,
while
(
scanKeySize
>
0
)
{
while
(
scanKeySize
>
0
)
{
datum
=
index_getattr
(
tuple
,
datum
=
index_getattr
(
tuple
,
1
,
key
[
0
].
sk_attno
,
tupdesc
,
tupdesc
,
&
isNull
);
&
isNull
);
...
...
src/backend/access/nbtree/nbtree.c
View file @
d1463050
...
@@ -8,7 +8,7 @@
...
@@ -8,7 +8,7 @@
*
*
*
*
* IDENTIFICATION
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtree.c,v 1.1
5 1997/02/22 10:04:14 vadim
Exp $
* $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtree.c,v 1.1
6 1997/03/18 18:38:35 scrappy
Exp $
*
*
* NOTES
* NOTES
* This file contains only the public interface routines.
* This file contains only the public interface routines.
...
@@ -423,6 +423,7 @@ btrescan(IndexScanDesc scan, bool fromEnd, ScanKey scankey)
...
@@ -423,6 +423,7 @@ btrescan(IndexScanDesc scan, bool fromEnd, ScanKey scankey)
/* reset the scan key */
/* reset the scan key */
so
->
numberOfKeys
=
scan
->
numberOfKeys
;
so
->
numberOfKeys
=
scan
->
numberOfKeys
;
so
->
numberOfFirstKeys
=
0
;
so
->
qual_ok
=
1
;
/* may be changed by _bt_orderkeys */
so
->
qual_ok
=
1
;
/* may be changed by _bt_orderkeys */
if
(
scan
->
numberOfKeys
>
0
)
{
if
(
scan
->
numberOfKeys
>
0
)
{
memmove
(
scan
->
keyData
,
memmove
(
scan
->
keyData
,
...
@@ -433,7 +434,9 @@ btrescan(IndexScanDesc scan, bool fromEnd, ScanKey scankey)
...
@@ -433,7 +434,9 @@ btrescan(IndexScanDesc scan, bool fromEnd, ScanKey scankey)
so
->
numberOfKeys
*
sizeof
(
ScanKeyData
));
so
->
numberOfKeys
*
sizeof
(
ScanKeyData
));
/* order the keys in the qualification */
/* order the keys in the qualification */
if
(
so
->
numberOfKeys
>
1
)
if
(
so
->
numberOfKeys
>
1
)
_bt_orderkeys
(
scan
->
relation
,
&
so
->
numberOfKeys
,
so
->
keyData
,
&
so
->
qual_ok
);
_bt_orderkeys
(
scan
->
relation
,
so
);
else
so
->
numberOfFirstKeys
=
1
;
}
}
/* finally, be sure that the scan exploits the tree order */
/* finally, be sure that the scan exploits the tree order */
...
...
src/backend/access/nbtree/nbtsearch.c
View file @
d1463050
...
@@ -7,7 +7,7 @@
...
@@ -7,7 +7,7 @@
*
*
*
*
* IDENTIFICATION
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtsearch.c,v 1.1
4 1997/02/18 17:13:48 momjian
Exp $
* $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtsearch.c,v 1.1
5 1997/03/18 18:38:41 scrappy
Exp $
*
*
*-------------------------------------------------------------------------
*-------------------------------------------------------------------------
*/
*/
...
@@ -562,7 +562,6 @@ _bt_next(IndexScanDesc scan, ScanDirection dir)
...
@@ -562,7 +562,6 @@ _bt_next(IndexScanDesc scan, ScanDirection dir)
Page
page
;
Page
page
;
OffsetNumber
offnum
;
OffsetNumber
offnum
;
RetrieveIndexResult
res
;
RetrieveIndexResult
res
;
BlockNumber
blkno
;
ItemPointer
current
;
ItemPointer
current
;
BTItem
btitem
;
BTItem
btitem
;
IndexTuple
itup
;
IndexTuple
itup
;
...
@@ -584,31 +583,35 @@ _bt_next(IndexScanDesc scan, ScanDirection dir)
...
@@ -584,31 +583,35 @@ _bt_next(IndexScanDesc scan, ScanDirection dir)
/* we still have the buffer pinned and locked */
/* we still have the buffer pinned and locked */
buf
=
so
->
btso_curbuf
;
buf
=
so
->
btso_curbuf
;
blkno
=
BufferGetBlockNumber
(
buf
);
/* step one tuple in the appropriate direction */
do
if
(
!
_bt_step
(
scan
,
&
buf
,
dir
))
{
return
((
RetrieveIndexResult
)
NULL
);
/* step one tuple in the appropriate direction */
if
(
!
_bt_step
(
scan
,
&
buf
,
dir
))
return
((
RetrieveIndexResult
)
NULL
);
/* by here, current is the tuple we want to return */
/* by here, current is the tuple we want to return */
offnum
=
ItemPointerGetOffsetNumber
(
current
);
offnum
=
ItemPointerGetOffsetNumber
(
current
);
page
=
BufferGetPage
(
buf
);
page
=
BufferGetPage
(
buf
);
btitem
=
(
BTItem
)
PageGetItem
(
page
,
PageGetItemId
(
page
,
offnum
));
btitem
=
(
BTItem
)
PageGetItem
(
page
,
PageGetItemId
(
page
,
offnum
));
itup
=
&
btitem
->
bti_itup
;
itup
=
&
btitem
->
bti_itup
;
if
(
_bt_checkqual
(
scan
,
itup
))
{
if
(
_bt_checkqual
(
scan
,
itup
))
res
=
FormRetrieveIndexResult
(
current
,
&
(
itup
->
t_tid
));
{
res
=
FormRetrieveIndexResult
(
current
,
&
(
itup
->
t_tid
));
/* remember which buffer we have pinned and locked */
/* remember which buffer we have pinned and locked */
so
->
btso_curbuf
=
buf
;
so
->
btso_curbuf
=
buf
;
}
else
{
return
(
res
);
ItemPointerSetInvalid
(
current
);
}
so
->
btso_curbuf
=
InvalidBuffer
;
_bt_relbuf
(
rel
,
buf
,
BT_READ
);
}
while
(
_bt_checkforkeys
(
scan
,
itup
,
so
->
numberOfFirstKeys
)
);
res
=
(
RetrieveIndexResult
)
NULL
;
}
ItemPointerSetInvalid
(
current
);
so
->
btso_curbuf
=
InvalidBuffer
;
_bt_relbuf
(
rel
,
buf
,
BT_READ
);
return
(
res
);
return
(
(
RetrieveIndexResult
)
NULL
);
}
}
/*
/*
...
@@ -660,13 +663,6 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
...
@@ -660,13 +663,6 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
* ordered to take advantage of index ordering) to position ourselves
* ordered to take advantage of index ordering) to position ourselves
* at the right place in the scan.
* at the right place in the scan.
*/
*/
/*
* XXX -- The attribute number stored in the scan key is the attno
* in the heap relation. We need to transmogrify this into
* the index relation attno here. For the moment, we have
* hardwired attno == 1.
*/
proc
=
index_getprocid
(
rel
,
1
,
BTORDER_PROC
);
proc
=
index_getprocid
(
rel
,
1
,
BTORDER_PROC
);
ScanKeyEntryInitialize
(
&
skdata
,
so
->
keyData
[
0
].
sk_flags
,
1
,
proc
,
ScanKeyEntryInitialize
(
&
skdata
,
so
->
keyData
[
0
].
sk_flags
,
1
,
proc
,
so
->
keyData
[
0
].
sk_argument
);
so
->
keyData
[
0
].
sk_argument
);
...
@@ -802,12 +798,20 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
...
@@ -802,12 +798,20 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
btitem
=
(
BTItem
)
PageGetItem
(
page
,
PageGetItemId
(
page
,
offnum
));
btitem
=
(
BTItem
)
PageGetItem
(
page
,
PageGetItemId
(
page
,
offnum
));
itup
=
&
btitem
->
bti_itup
;
itup
=
&
btitem
->
bti_itup
;
if
(
_bt_checkqual
(
scan
,
itup
))
{
if
(
_bt_checkqual
(
scan
,
itup
)
)
{
res
=
FormRetrieveIndexResult
(
current
,
&
(
itup
->
t_tid
));
res
=
FormRetrieveIndexResult
(
current
,
&
(
itup
->
t_tid
));
/* remember which buffer we have pinned */
/* remember which buffer we have pinned */
so
->
btso_curbuf
=
buf
;
so
->
btso_curbuf
=
buf
;
}
else
{
}
else
if
(
_bt_checkforkeys
(
scan
,
itup
,
so
->
numberOfFirstKeys
)
)
{
so
->
btso_curbuf
=
buf
;
return
(
_bt_next
(
scan
,
dir
));
}
else
{
ItemPointerSetInvalid
(
current
);
ItemPointerSetInvalid
(
current
);
so
->
btso_curbuf
=
InvalidBuffer
;
so
->
btso_curbuf
=
InvalidBuffer
;
_bt_relbuf
(
rel
,
buf
,
BT_READ
);
_bt_relbuf
(
rel
,
buf
,
BT_READ
);
...
@@ -1224,7 +1228,14 @@ _bt_endpoint(IndexScanDesc scan, ScanDirection dir)
...
@@ -1224,7 +1228,14 @@ _bt_endpoint(IndexScanDesc scan, ScanDirection dir)
/* remember which buffer we have pinned */
/* remember which buffer we have pinned */
so
->
btso_curbuf
=
buf
;
so
->
btso_curbuf
=
buf
;
}
else
{
}
else
if
(
_bt_checkforkeys
(
scan
,
itup
,
so
->
numberOfFirstKeys
)
)
{
so
->
btso_curbuf
=
buf
;
return
(
_bt_next
(
scan
,
dir
));
}
else
{
_bt_relbuf
(
rel
,
buf
,
BT_READ
);
_bt_relbuf
(
rel
,
buf
,
BT_READ
);
res
=
(
RetrieveIndexResult
)
NULL
;
res
=
(
RetrieveIndexResult
)
NULL
;
}
}
...
...
src/backend/access/nbtree/nbtutils.c
View file @
d1463050
...
@@ -7,7 +7,7 @@
...
@@ -7,7 +7,7 @@
*
*
*
*
* IDENTIFICATION
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtutils.c,v 1.
7 1996/11/05 10:35:38
scrappy Exp $
* $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtutils.c,v 1.
8 1997/03/18 18:38:46
scrappy Exp $
*
*
*-------------------------------------------------------------------------
*-------------------------------------------------------------------------
*/
*/
...
@@ -80,7 +80,7 @@ _bt_freestack(BTStack stack)
...
@@ -80,7 +80,7 @@ _bt_freestack(BTStack stack)
* more than one qual clauses using this index.
* more than one qual clauses using this index.
*/
*/
void
void
_bt_orderkeys
(
Relation
relation
,
uint16
*
numberOfKeys
,
ScanKey
key
,
uint16
*
qual_ok
)
_bt_orderkeys
(
Relation
relation
,
BTScanOpaque
so
)
{
{
ScanKey
xform
;
ScanKey
xform
;
ScanKeyData
*
cur
;
ScanKeyData
*
cur
;
...
@@ -89,42 +89,137 @@ _bt_orderkeys(Relation relation, uint16 *numberOfKeys, ScanKey key, uint16 *qual
...
@@ -89,42 +89,137 @@ _bt_orderkeys(Relation relation, uint16 *numberOfKeys, ScanKey key, uint16 *qual
long
test
;
long
test
;
int
i
,
j
;
int
i
,
j
;
int
init
[
BTMaxStrategyNumber
+
1
];
int
init
[
BTMaxStrategyNumber
+
1
];
ScanKey
key
;
uint16
numberOfKeys
,
new_numberOfKeys
=
0
;
AttrNumber
attno
=
1
;
/* haven't looked at any strategies yet */
numberOfKeys
=
so
->
numberOfKeys
;
for
(
i
=
0
;
i
<=
BTMaxStrategyNumber
;
i
++
)
key
=
so
->
keyData
;
init
[
i
]
=
0
;
if
(
numberOfKeys
<=
1
)
return
;
/* get space for the modified array of keys */
/* get space for the modified array of keys */
nbytes
=
BTMaxStrategyNumber
*
sizeof
(
ScanKeyData
);
nbytes
=
BTMaxStrategyNumber
*
sizeof
(
ScanKeyData
);
xform
=
(
ScanKey
)
palloc
(
nbytes
);
xform
=
(
ScanKey
)
palloc
(
nbytes
);
memset
(
xform
,
0
,
nbytes
);
cur
=
&
key
[
0
];
/* get the strategy map for this index/attribute pair */
if
(
cur
->
sk_attno
!=
1
)
/*
elog
(
WARN
,
"_bt_orderkeys: key(s) for attribute 1 missed"
);
* XXX
* When we support multiple keys in a single index, this is what
memset
(
xform
,
0
,
nbytes
);
* we'll want to do. At present, the planner is hosed, so we
* hard-wire the attribute number below. Postgres only does single-
* key indices...
* map = IndexStrategyGetStrategyMap(RelationGetIndexStrategy(relation),
* BTMaxStrategyNumber,
* key->data[0].attributeNumber);
*/
map
=
IndexStrategyGetStrategyMap
(
RelationGetIndexStrategy
(
relation
),
map
=
IndexStrategyGetStrategyMap
(
RelationGetIndexStrategy
(
relation
),
BTMaxStrategyNumber
,
BTMaxStrategyNumber
,
1
/* XXX */
);
attno
);
for
(
j
=
0
;
j
<=
BTMaxStrategyNumber
;
j
++
)
init
[
j
]
=
0
;
/* check each key passed in */
/* check each key passed in */
for
(
i
=
*
numberOfKeys
;
--
i
>=
0
;
)
{
for
(
i
=
0
;
;
)
cur
=
&
key
[
i
];
{
for
(
j
=
BTMaxStrategyNumber
;
--
j
>=
0
;
)
{
if
(
i
<
numberOfKeys
)
cur
=
&
key
[
i
];
if
(
i
==
numberOfKeys
||
cur
->
sk_attno
!=
attno
)
{
if
(
cur
->
sk_attno
!=
attno
+
1
&&
i
<
numberOfKeys
)
{
elog
(
WARN
,
"_bt_orderkeys: key(s) for attribute %d missed"
,
attno
+
1
);
}
/*
* If = has been specified, no other key will be used.
* In case of key < 2 && key == 1 and so on
* we have to set qual_ok to 0
*/
if
(
init
[
BTEqualStrategyNumber
-
1
])
{
ScanKeyData
*
eq
,
*
chk
;
eq
=
&
xform
[
BTEqualStrategyNumber
-
1
];
for
(
j
=
BTMaxStrategyNumber
;
--
j
>=
0
;
)
{
if
(
j
==
(
BTEqualStrategyNumber
-
1
)
||
init
[
j
]
==
0
)
continue
;
chk
=
&
xform
[
j
];
test
=
(
long
)
fmgr
(
chk
->
sk_procedure
,
eq
->
sk_argument
,
chk
->
sk_argument
);
if
(
!
test
)
so
->
qual_ok
=
0
;
}
init
[
BTLessStrategyNumber
-
1
]
=
0
;
init
[
BTLessEqualStrategyNumber
-
1
]
=
0
;
init
[
BTGreaterEqualStrategyNumber
-
1
]
=
0
;
init
[
BTGreaterStrategyNumber
-
1
]
=
0
;
}
/* only one of <, <= */
if
(
init
[
BTLessStrategyNumber
-
1
]
&&
init
[
BTLessEqualStrategyNumber
-
1
])
{
ScanKeyData
*
lt
,
*
le
;
lt
=
&
xform
[
BTLessStrategyNumber
-
1
];
le
=
&
xform
[
BTLessEqualStrategyNumber
-
1
];
/*
* DO NOT use the cached function stuff here -- this is key
* ordering, happens only when the user expresses a hokey
* qualification, and gets executed only once, anyway. The
* transform maps are hard-coded, and can't be initialized
* in the correct way.
*/
test
=
(
long
)
fmgr
(
le
->
sk_procedure
,
lt
->
sk_argument
,
le
->
sk_argument
);
if
(
test
)
init
[
BTLessEqualStrategyNumber
-
1
]
=
0
;
else
init
[
BTLessStrategyNumber
-
1
]
=
0
;
}
/* only one of >, >= */
if
(
init
[
BTGreaterStrategyNumber
-
1
]
&&
init
[
BTGreaterEqualStrategyNumber
-
1
])
{
ScanKeyData
*
gt
,
*
ge
;
gt
=
&
xform
[
BTGreaterStrategyNumber
-
1
];
ge
=
&
xform
[
BTGreaterEqualStrategyNumber
-
1
];
/* see note above on function cache */
test
=
(
long
)
fmgr
(
ge
->
sk_procedure
,
gt
->
sk_argument
,
ge
->
sk_argument
);
if
(
test
)
init
[
BTGreaterEqualStrategyNumber
-
1
]
=
0
;
else
init
[
BTGreaterStrategyNumber
-
1
]
=
0
;
}
/* okay, reorder and count */
for
(
j
=
BTMaxStrategyNumber
;
--
j
>=
0
;
)
if
(
init
[
j
])
key
[
new_numberOfKeys
++
]
=
xform
[
j
];
if
(
attno
==
1
)
so
->
numberOfFirstKeys
=
new_numberOfKeys
;
if
(
i
==
numberOfKeys
)
break
;
/* initialization for new attno */
attno
=
cur
->
sk_attno
;
memset
(
xform
,
0
,
nbytes
);
map
=
IndexStrategyGetStrategyMap
(
RelationGetIndexStrategy
(
relation
),
BTMaxStrategyNumber
,
attno
);
/* haven't looked at any strategies yet */
for
(
j
=
0
;
j
<=
BTMaxStrategyNumber
;
j
++
)
init
[
j
]
=
0
;
}
for
(
j
=
BTMaxStrategyNumber
;
--
j
>=
0
;
)
{
if
(
cur
->
sk_procedure
==
map
->
entry
[
j
].
sk_procedure
)
if
(
cur
->
sk_procedure
==
map
->
entry
[
j
].
sk_procedure
)
break
;
break
;
}
}
/* have we seen one of these before? */
/* have we seen one of these before? */
if
(
init
[
j
])
{
if
(
init
[
j
])
{
/* yup, use the appropriate value */
/* yup, use the appropriate value */
test
=
test
=
(
long
)
FMGR_PTR2
(
cur
->
sk_func
,
cur
->
sk_procedure
,
(
long
)
FMGR_PTR2
(
cur
->
sk_func
,
cur
->
sk_procedure
,
...
@@ -132,97 +227,18 @@ _bt_orderkeys(Relation relation, uint16 *numberOfKeys, ScanKey key, uint16 *qual
...
@@ -132,97 +227,18 @@ _bt_orderkeys(Relation relation, uint16 *numberOfKeys, ScanKey key, uint16 *qual
if
(
test
)
if
(
test
)
xform
[
j
].
sk_argument
=
cur
->
sk_argument
;
xform
[
j
].
sk_argument
=
cur
->
sk_argument
;
else
if
(
j
==
(
BTEqualStrategyNumber
-
1
)
)
else
if
(
j
==
(
BTEqualStrategyNumber
-
1
)
)
*
qual_ok
=
0
;
/* key == a && key == b, but a != b */
so
->
qual_ok
=
0
;
/* key == a && key == b, but a != b */
}
else
{
}
else
{
/* nope, use this value */
/* nope, use this value */
memmove
(
&
xform
[
j
],
cur
,
sizeof
(
*
cur
));
memmove
(
&
xform
[
j
],
cur
,
sizeof
(
*
cur
));
init
[
j
]
=
1
;
init
[
j
]
=
1
;
}
}
}
/* if = has been specified, no other key will be used */
/*
* XXX
* But in case of key < 2 && key == 1 and so on
* we have to set qual_ok to 0
*/
if
(
init
[
BTEqualStrategyNumber
-
1
])
{
ScanKeyData
*
eq
,
*
chk
;
eq
=
&
xform
[
BTEqualStrategyNumber
-
1
];
for
(
j
=
BTMaxStrategyNumber
;
--
j
>=
0
;
)
{
if
(
j
==
(
BTEqualStrategyNumber
-
1
)
||
init
[
j
]
==
0
)
continue
;
chk
=
&
xform
[
j
];
test
=
(
long
)
fmgr
(
chk
->
sk_procedure
,
eq
->
sk_argument
,
chk
->
sk_argument
);
if
(
!
test
)
i
++
;
*
qual_ok
=
0
;
}
init
[
BTLessStrategyNumber
-
1
]
=
0
;
init
[
BTLessEqualStrategyNumber
-
1
]
=
0
;
init
[
BTGreaterEqualStrategyNumber
-
1
]
=
0
;
init
[
BTGreaterStrategyNumber
-
1
]
=
0
;
}
}
/* only one of <, <= */
so
->
numberOfKeys
=
new_numberOfKeys
;
if
(
init
[
BTLessStrategyNumber
-
1
]
&&
init
[
BTLessEqualStrategyNumber
-
1
])
{
ScanKeyData
*
lt
,
*
le
;
lt
=
&
xform
[
BTLessStrategyNumber
-
1
];
le
=
&
xform
[
BTLessEqualStrategyNumber
-
1
];
/*
* DO NOT use the cached function stuff here -- this is key
* ordering, happens only when the user expresses a hokey
* qualification, and gets executed only once, anyway. The
* transform maps are hard-coded, and can't be initialized
* in the correct way.
*/
test
=
(
long
)
fmgr
(
le
->
sk_procedure
,
lt
->
sk_argument
,
le
->
sk_argument
);
if
(
test
)
init
[
BTLessEqualStrategyNumber
-
1
]
=
0
;
else
init
[
BTLessStrategyNumber
-
1
]
=
0
;
}
/* only one of >, >= */
if
(
init
[
BTGreaterStrategyNumber
-
1
]
&&
init
[
BTGreaterEqualStrategyNumber
-
1
])
{
ScanKeyData
*
gt
,
*
ge
;
gt
=
&
xform
[
BTGreaterStrategyNumber
-
1
];
ge
=
&
xform
[
BTGreaterEqualStrategyNumber
-
1
];
/* see note above on function cache */
test
=
(
long
)
fmgr
(
ge
->
sk_procedure
,
gt
->
sk_argument
,
ge
->
sk_argument
);
if
(
test
)
init
[
BTGreaterEqualStrategyNumber
-
1
]
=
0
;
else
init
[
BTGreaterStrategyNumber
-
1
]
=
0
;
}
/* okay, reorder and count */
j
=
0
;
for
(
i
=
BTMaxStrategyNumber
;
--
i
>=
0
;
)
if
(
init
[
i
])
key
[
j
++
]
=
xform
[
i
];
*
numberOfKeys
=
j
;
pfree
(
xform
);
pfree
(
xform
);
}
}
...
@@ -230,9 +246,25 @@ _bt_orderkeys(Relation relation, uint16 *numberOfKeys, ScanKey key, uint16 *qual
...
@@ -230,9 +246,25 @@ _bt_orderkeys(Relation relation, uint16 *numberOfKeys, ScanKey key, uint16 *qual
bool
bool
_bt_checkqual
(
IndexScanDesc
scan
,
IndexTuple
itup
)
_bt_checkqual
(
IndexScanDesc
scan
,
IndexTuple
itup
)
{
{
if
(
scan
->
numberOfKeys
>
0
)
BTScanOpaque
so
;
so
=
(
BTScanOpaque
)
scan
->
opaque
;
if
(
so
->
numberOfKeys
>
0
)
return
(
index_keytest
(
itup
,
RelationGetTupleDescriptor
(
scan
->
relation
),
so
->
numberOfKeys
,
so
->
keyData
));
else
return
(
true
);
}
bool
_bt_checkforkeys
(
IndexScanDesc
scan
,
IndexTuple
itup
,
Size
keysz
)
{
BTScanOpaque
so
;
so
=
(
BTScanOpaque
)
scan
->
opaque
;
if
(
keysz
>
0
&&
so
->
numberOfKeys
>=
keysz
)
return
(
index_keytest
(
itup
,
RelationGetTupleDescriptor
(
scan
->
relation
),
return
(
index_keytest
(
itup
,
RelationGetTupleDescriptor
(
scan
->
relation
),
scan
->
numberOfKeys
,
scan
->
keyData
));
keysz
,
so
->
keyData
));
else
else
return
(
true
);
return
(
true
);
}
}
...
...
src/backend/optimizer/path/indxpath.c
View file @
d1463050
...
@@ -8,7 +8,7 @@
...
@@ -8,7 +8,7 @@
*
*
*
*
* IDENTIFICATION
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.
6 1997/03/12 21:00:17
scrappy Exp $
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.
7 1997/03/18 18:39:40
scrappy Exp $
*
*
*-------------------------------------------------------------------------
*-------------------------------------------------------------------------
*/
*/
...
@@ -53,8 +53,9 @@ static bool match_index_to_operand(int indexkey, Expr *operand,
...
@@ -53,8 +53,9 @@ static bool match_index_to_operand(int indexkey, Expr *operand,
static
List
*
match_index_orclause
(
Rel
*
rel
,
Rel
*
index
,
int
indexkey
,
static
List
*
match_index_orclause
(
Rel
*
rel
,
Rel
*
index
,
int
indexkey
,
int
xclass
,
List
*
or_clauses
,
List
*
other_matching_indices
);
int
xclass
,
List
*
or_clauses
,
List
*
other_matching_indices
);
static
List
*
group_clauses_by_indexkey
(
Rel
*
rel
,
Rel
*
index
,
static
List
*
group_clauses_by_indexkey
(
Rel
*
rel
,
Rel
*
index
,
int
*
indexkeys
,
Oid
*
classes
,
List
*
clauseinfo_list
,
int
*
indexkeys
,
Oid
*
classes
,
List
*
clauseinfo_list
);
bool
join
);
static
List
*
group_clauses_by_ikey_for_joins
(
Rel
*
rel
,
Rel
*
index
,
int
*
indexkeys
,
Oid
*
classes
,
List
*
join_cinfo_list
,
List
*
restr_cinfo_list
);
static
CInfo
*
match_clause_to_indexkey
(
Rel
*
rel
,
Rel
*
index
,
int
indexkey
,
static
CInfo
*
match_clause_to_indexkey
(
Rel
*
rel
,
Rel
*
index
,
int
indexkey
,
int
xclass
,
CInfo
*
clauseInfo
,
bool
join
);
int
xclass
,
CInfo
*
clauseInfo
,
bool
join
);
static
bool
pred_test
(
List
*
predicate_list
,
List
*
clauseinfo_list
,
static
bool
pred_test
(
List
*
predicate_list
,
List
*
clauseinfo_list
,
...
@@ -63,7 +64,8 @@ static bool one_pred_test(Expr *predicate, List *clauseinfo_list);
...
@@ -63,7 +64,8 @@ static bool one_pred_test(Expr *predicate, List *clauseinfo_list);
static
bool
one_pred_clause_expr_test
(
Expr
*
predicate
,
Node
*
clause
);
static
bool
one_pred_clause_expr_test
(
Expr
*
predicate
,
Node
*
clause
);
static
bool
one_pred_clause_test
(
Expr
*
predicate
,
Node
*
clause
);
static
bool
one_pred_clause_test
(
Expr
*
predicate
,
Node
*
clause
);
static
bool
clause_pred_clause_test
(
Expr
*
predicate
,
Node
*
clause
);
static
bool
clause_pred_clause_test
(
Expr
*
predicate
,
Node
*
clause
);
static
List
*
indexable_joinclauses
(
Rel
*
rel
,
Rel
*
index
,
List
*
joininfo_list
);
static
List
*
indexable_joinclauses
(
Rel
*
rel
,
Rel
*
index
,
List
*
joininfo_list
,
List
*
clauseinfo_list
);
static
List
*
index_innerjoin
(
Query
*
root
,
Rel
*
rel
,
static
List
*
index_innerjoin
(
Query
*
root
,
Rel
*
rel
,
List
*
clausegroup_list
,
Rel
*
index
);
List
*
clausegroup_list
,
Rel
*
index
);
static
List
*
create_index_paths
(
Query
*
root
,
Rel
*
rel
,
Rel
*
index
,
static
List
*
create_index_paths
(
Query
*
root
,
Rel
*
rel
,
Rel
*
index
,
...
@@ -114,7 +116,6 @@ find_index_paths (Query *root,
...
@@ -114,7 +116,6 @@ find_index_paths (Query *root,
List
*
joinclausegroups
=
NIL
;
List
*
joinclausegroups
=
NIL
;
List
*
joinpaths
=
NIL
;
List
*
joinpaths
=
NIL
;
List
*
retval
=
NIL
;
List
*
retval
=
NIL
;
extern
List
*
add_index_paths
();
if
(
indices
==
NIL
)
if
(
indices
==
NIL
)
return
(
NULL
);
return
(
NULL
);
...
@@ -160,8 +161,7 @@ find_index_paths (Query *root,
...
@@ -160,8 +161,7 @@ find_index_paths (Query *root,
index
,
index
,
index
->
indexkeys
,
index
->
indexkeys
,
index
->
classlist
,
index
->
classlist
,
clauseinfo_list
,
clauseinfo_list
);
false
);
scanpaths
=
NIL
;
scanpaths
=
NIL
;
if
(
scanclausegroups
!=
NIL
)
if
(
scanclausegroups
!=
NIL
)
...
@@ -178,7 +178,7 @@ find_index_paths (Query *root,
...
@@ -178,7 +178,7 @@ find_index_paths (Query *root,
* useful for a mergejoin, or if the index can possibly be
* useful for a mergejoin, or if the index can possibly be
* used for scanning the inner relation of a nestloop join.
* used for scanning the inner relation of a nestloop join.
*/
*/
joinclausegroups
=
indexable_joinclauses
(
rel
,
index
,
joininfo_list
);
joinclausegroups
=
indexable_joinclauses
(
rel
,
index
,
joininfo_list
,
clauseinfo_list
);
joinpaths
=
NIL
;
joinpaths
=
NIL
;
if
(
joinclausegroups
!=
NIL
)
if
(
joinclausegroups
!=
NIL
)
...
@@ -375,10 +375,8 @@ match_index_orclause(Rel *rel,
...
@@ -375,10 +375,8 @@ match_index_orclause(Rel *rel,
* (2) a list of join clauses between 'rel' and a fixed set of
* (2) a list of join clauses between 'rel' and a fixed set of
* relations,
* relations,
* depending on the value of 'join'.
* depending on the value of 'join'.
* 'startlist' is a list of those clause nodes that have matched the keys
*
* that have already been checked.
* NOTE: it works now for restriction clauses only. - vadim 03/18/97
* 'join' is a flag indicating that the clauses being checked are join
* clauses.
*
*
* Returns all possible groups of clauses that will match (given that
* Returns all possible groups of clauses that will match (given that
* one or more clauses can match any of the remaining keys).
* one or more clauses can match any of the remaining keys).
...
@@ -391,45 +389,144 @@ group_clauses_by_indexkey(Rel *rel,
...
@@ -391,45 +389,144 @@ group_clauses_by_indexkey(Rel *rel,
Rel
*
index
,
Rel
*
index
,
int
*
indexkeys
,
int
*
indexkeys
,
Oid
*
classes
,
Oid
*
classes
,
List
*
clauseinfo_list
,
List
*
clauseinfo_list
)
bool
join
)
{
{
List
*
curCinfo
=
NIL
;
List
*
curCinfo
=
NIL
;
CInfo
*
matched_clause
=
(
CInfo
*
)
NULL
;
CInfo
*
matched_clause
=
(
CInfo
*
)
NULL
;
List
*
clausegroup
=
NIL
;
List
*
clausegroup
=
NIL
;
int
curIndxKey
;
Oid
curClass
;
if
(
clauseinfo_list
==
NIL
)
if
(
clauseinfo_list
==
NIL
)
return
NIL
;
return
NIL
;
foreach
(
curCinfo
,
clauseinfo_list
)
{
while
(
!
DoneMatchingIndexKeys
(
indexkeys
,
index
)
)
CInfo
*
temp
=
(
CInfo
*
)
lfirst
(
curCinfo
);
{
int
*
curIndxKey
=
indexkeys
;
List
*
tempgroup
=
NIL
;
Oid
*
curClass
=
classes
;
curIndxKey
=
indexkeys
[
0
];
curClass
=
classes
[
0
];
foreach
(
curCinfo
,
clauseinfo_list
)
{
CInfo
*
temp
=
(
CInfo
*
)
lfirst
(
curCinfo
);
matched_clause
=
match_clause_to_indexkey
(
rel
,
index
,
curIndxKey
,
curClass
,
temp
,
false
);
if
(
!
matched_clause
)
continue
;
tempgroup
=
lappend
(
tempgroup
,
matched_clause
);
}
if
(
tempgroup
==
NIL
)
break
;
clausegroup
=
nconc
(
clausegroup
,
tempgroup
);
indexkeys
++
;
classes
++
;
}
/* clausegroup holds all matched clauses ordered by indexkeys */
if
(
clausegroup
!=
NIL
)
return
(
lcons
(
clausegroup
,
NIL
));
return
NIL
;
}
/*
* group-clauses-by-ikey-for-joins--
* special edition of group-clauses-by-indexkey - will
* match join & restriction clauses. See comment in indexable_joinclauses.
* - vadim 03/18/97
*
*/
static
List
*
group_clauses_by_ikey_for_joins
(
Rel
*
rel
,
Rel
*
index
,
int
*
indexkeys
,
Oid
*
classes
,
List
*
join_cinfo_list
,
List
*
restr_cinfo_list
)
{
List
*
curCinfo
=
NIL
;
CInfo
*
matched_clause
=
(
CInfo
*
)
NULL
;
List
*
clausegroup
=
NIL
;
int
curIndxKey
;
Oid
curClass
;
bool
jfound
=
false
;
if
(
join_cinfo_list
==
NIL
)
return
NIL
;
while
(
!
DoneMatchingIndexKeys
(
indexkeys
,
index
)
)
{
List
*
tempgroup
=
NIL
;
curIndxKey
=
indexkeys
[
0
];
curClass
=
classes
[
0
];
foreach
(
curCinfo
,
join_cinfo_list
)
{
CInfo
*
temp
=
(
CInfo
*
)
lfirst
(
curCinfo
);
matched_clause
=
match_clause_to_indexkey
(
rel
,
index
,
curIndxKey
,
curClass
,
temp
,
true
);
if
(
!
matched_clause
)
continue
;
tempgroup
=
lappend
(
tempgroup
,
matched_clause
);
jfound
=
true
;
}
foreach
(
curCinfo
,
restr_cinfo_list
)
{
CInfo
*
temp
=
(
CInfo
*
)
lfirst
(
curCinfo
);
do
{
/*
* If we can't find any matching clauses for the first of
* the remaining keys, give up.
*/
matched_clause
=
match_clause_to_indexkey
(
rel
,
matched_clause
=
match_clause_to_indexkey
(
rel
,
index
,
index
,
curIndxKey
[
0
]
,
curIndxKey
,
curClass
[
0
]
,
curClass
,
temp
,
temp
,
join
);
false
);
if
(
!
matched_clause
)
if
(
!
matched_clause
)
break
;
continue
;
clausegroup
=
lcons
(
matched_clause
,
clausegroup
);
tempgroup
=
lappend
(
tempgroup
,
matched_clause
);
curIndxKey
++
;
}
curClass
++
;
if
(
tempgroup
==
NIL
)
break
;
}
while
(
!
DoneMatchingIndexKeys
(
curIndxKey
,
index
)
);
clausegroup
=
nconc
(
clausegroup
,
tempgroup
);
indexkeys
++
;
classes
++
;
}
}
/* clausegroup holds all matched clauses ordered by indexkeys */
if
(
clausegroup
!=
NIL
)
if
(
clausegroup
!=
NIL
)
{
/*
* if no one join clause was matched then there ain't clauses
* for joins at all.
*/
if
(
!
jfound
)
{
freeList
(
clausegroup
);
return
NIL
;
}
return
(
lcons
(
clausegroup
,
NIL
));
return
(
lcons
(
clausegroup
,
NIL
));
}
return
NIL
;
return
NIL
;
}
}
...
@@ -482,6 +579,7 @@ match_clause_to_indexkey(Rel *rel,
...
@@ -482,6 +579,7 @@ match_clause_to_indexkey(Rel *rel,
Expr
*
clause
=
clauseInfo
->
clause
;
Expr
*
clause
=
clauseInfo
->
clause
;
Var
*
leftop
,
*
rightop
;
Var
*
leftop
,
*
rightop
;
Oid
join_op
=
InvalidOid
;
Oid
join_op
=
InvalidOid
;
Oid
restrict_op
=
InvalidOid
;
bool
isIndexable
=
false
;
bool
isIndexable
=
false
;
if
(
or_clause
((
Node
*
)
clause
)
||
if
(
or_clause
((
Node
*
)
clause
)
||
...
@@ -495,90 +593,87 @@ match_clause_to_indexkey(Rel *rel,
...
@@ -495,90 +593,87 @@ match_clause_to_indexkey(Rel *rel,
* (operator var/func constant) and (operator constant var/func)
* (operator var/func constant) and (operator constant var/func)
*/
*/
if
(
!
join
)
if
(
!
join
)
{
{
Oid
restrict_op
=
InvalidOid
;
/*
* Check for standard s-argable clause
/*
*/
* Check for standard s-argable clause
*/
#ifdef INDEXSCAN_PATCH
#ifdef INDEXSCAN_PATCH
/* Handle also function parameters. DZ - 27-8-1996 */
/* Handle also function parameters. DZ - 27-8-1996 */
if
((
rightop
&&
IsA
(
rightop
,
Const
))
||
if
((
rightop
&&
IsA
(
rightop
,
Const
))
||
(
rightop
&&
IsA
(
rightop
,
Param
)))
(
rightop
&&
IsA
(
rightop
,
Param
)))
#else
#else
if
(
rightop
&&
IsA
(
rightop
,
Const
))
if
(
rightop
&&
IsA
(
rightop
,
Const
))
#endif
#endif
{
{
restrict_op
=
((
Oper
*
)((
Expr
*
)
clause
)
->
oper
)
->
opno
;
restrict_op
=
((
Oper
*
)((
Expr
*
)
clause
)
->
oper
)
->
opno
;
isIndexable
=
isIndexable
=
(
op_class
(
restrict_op
,
xclass
,
index
->
relam
)
&&
(
op_class
(
restrict_op
,
xclass
,
index
->
relam
)
&&
IndexScanableOperand
(
leftop
,
IndexScanableOperand
(
leftop
,
indexkey
,
indexkey
,
rel
,
rel
,
index
)
);
index
)
);
}
}
/*
/*
* Must try to commute the clause to standard s-arg format.
* Must try to commute the clause to standard s-arg format.
*/
*/
#ifdef INDEXSCAN_PATCH
#ifdef INDEXSCAN_PATCH
/* ...And here... - vadim 01/22/97 */
/* ...And here... - vadim 01/22/97 */
else
if
((
leftop
&&
IsA
(
leftop
,
Const
))
||
else
if
((
leftop
&&
IsA
(
leftop
,
Const
))
||
(
leftop
&&
IsA
(
leftop
,
Param
)))
(
leftop
&&
IsA
(
leftop
,
Param
)))
#else
#else
else
if
(
leftop
&&
IsA
(
leftop
,
Const
))
else
if
(
leftop
&&
IsA
(
leftop
,
Const
))
#endif
#endif
{
{
restrict_op
=
restrict_op
=
get_commutator
(((
Oper
*
)((
Expr
*
)
clause
)
->
oper
)
->
opno
);
get_commutator
(((
Oper
*
)((
Expr
*
)
clause
)
->
oper
)
->
opno
);
if
(
(
restrict_op
!=
InvalidOid
)
&&
if
(
(
restrict_op
!=
InvalidOid
)
&&
op_class
(
restrict_op
,
xclass
,
index
->
relam
)
&&
op_class
(
restrict_op
,
xclass
,
index
->
relam
)
&&
IndexScanableOperand
(
rightop
,
IndexScanableOperand
(
rightop
,
indexkey
,
rel
,
index
)
)
indexkey
,
rel
,
index
)
)
{
{
isIndexable
=
true
;
isIndexable
=
true
;
/*
/*
* In place list modification.
* In place list modification.
* (op const var/func) -> (op var/func const)
* (op const var/func) -> (op var/func const)
*/
*/
/* BUG! Old version:
CommuteClause
((
Node
*
)
clause
);
CommuteClause(clause, restrict_op);
}
*/
}
CommuteClause
((
Node
*
)
clause
);
}
}
}
}
/*
/*
* Check for an indexable scan on one of the join relations.
* Check for an indexable scan on one of the join relations.
* clause is of the form (operator var/func var/func)
* clause is of the form (operator var/func var/func)
*/
*/
else
else
{
if
(
rightop
&&
match_index_to_operand
(
indexkey
,(
Expr
*
)
rightop
,
rel
,
index
))
{
{
if
(
rightop
&&
match_index_to_operand
(
indexkey
,(
Expr
*
)
rightop
,
rel
,
index
))
{
join_op
=
get_commutator
(((
Oper
*
)((
Expr
*
)
clause
)
->
oper
)
->
opno
);
join_op
=
get_commutator
(((
Oper
*
)((
Expr
*
)
clause
)
->
oper
)
->
opno
);
}
else
if
(
leftop
}
else
if
(
leftop
&&
match_index_to_operand
(
indexkey
,
&&
match_index_to_operand
(
indexkey
,
(
Expr
*
)
leftop
,
rel
,
index
))
{
(
Expr
*
)
leftop
,
rel
,
index
))
{
join_op
=
((
Oper
*
)((
Expr
*
)
clause
)
->
oper
)
->
opno
;
join_op
=
((
Oper
*
)((
Expr
*
)
clause
)
->
oper
)
->
opno
;
}
}
if
(
join_op
&&
op_class
(
join_op
,
xclass
,
index
->
relam
)
&&
if
(
join_op
&&
op_class
(
join_op
,
xclass
,
index
->
relam
)
&&
join_clause_p
((
Node
*
)
clause
))
join_clause_p
((
Node
*
)
clause
))
{
{
isIndexable
=
true
;
isIndexable
=
true
;
/*
/*
* If we're using the operand's commutator we must
* If we're using the operand's commutator we must
* commute the clause.
* commute the clause.
*/
*/
if
(
join_op
!=
((
Oper
*
)((
Expr
*
)
clause
)
->
oper
)
->
opno
)
if
(
join_op
!=
((
Oper
*
)((
Expr
*
)
clause
)
->
oper
)
->
opno
)
CommuteClause
((
Node
*
)
clause
);
CommuteClause
((
Node
*
)
clause
);
}
}
}
}
if
(
isIndexable
)
if
(
isIndexable
)
return
(
clauseInfo
);
return
(
clauseInfo
);
...
@@ -955,10 +1050,15 @@ clause_pred_clause_test(Expr *predicate, Node *clause)
...
@@ -955,10 +1050,15 @@ clause_pred_clause_test(Expr *predicate, Node *clause)
* in the join clause as its outer join relation.
* in the join clause as its outer join relation.
*
*
* Returns a list of these clause groups.
* Returns a list of these clause groups.
*
* Added: clauseinfo_list - list of restriction CInfos. It's to
* support multi-column indices in joins and for cases
* when a key is in both join & restriction clauses. - vadim 03/18/97
*
*
*/
*/
static
List
*
static
List
*
indexable_joinclauses
(
Rel
*
rel
,
Rel
*
index
,
List
*
joininfo_list
)
indexable_joinclauses
(
Rel
*
rel
,
Rel
*
index
,
List
*
joininfo_list
,
List
*
clauseinfo_list
)
{
{
JInfo
*
joininfo
=
(
JInfo
*
)
NULL
;
JInfo
*
joininfo
=
(
JInfo
*
)
NULL
;
List
*
cg_list
=
NIL
;
List
*
cg_list
=
NIL
;
...
@@ -967,13 +1067,16 @@ indexable_joinclauses(Rel *rel, Rel *index, List *joininfo_list)
...
@@ -967,13 +1067,16 @@ indexable_joinclauses(Rel *rel, Rel *index, List *joininfo_list)
foreach
(
i
,
joininfo_list
)
{
foreach
(
i
,
joininfo_list
)
{
joininfo
=
(
JInfo
*
)
lfirst
(
i
);
joininfo
=
(
JInfo
*
)
lfirst
(
i
);
if
(
joininfo
->
jinfoclauseinfo
==
NIL
)
continue
;
clausegroups
=
clausegroups
=
group_clauses_by_i
ndexkey
(
rel
,
group_clauses_by_i
key_for_joins
(
rel
,
index
,
index
,
index
->
indexkeys
,
index
->
indexkeys
,
index
->
classlist
,
index
->
classlist
,
joininfo
->
jinfoclauseinfo
,
joininfo
->
jinfoclauseinfo
,
true
);
clauseinfo_list
);
if
(
clausegroups
!=
NIL
)
{
if
(
clausegroups
!=
NIL
)
{
List
*
clauses
=
lfirst
(
clausegroups
);
List
*
clauses
=
lfirst
(
clausegroups
);
...
@@ -1056,6 +1159,7 @@ index_innerjoin(Query *root, Rel *rel, List *clausegroup_list, Rel *index)
...
@@ -1056,6 +1159,7 @@ index_innerjoin(Query *root, Rel *rel, List *clausegroup_list, Rel *index)
pathnode
->
path
.
pathtype
=
T_IndexScan
;
pathnode
->
path
.
pathtype
=
T_IndexScan
;
pathnode
->
path
.
parent
=
rel
;
pathnode
->
path
.
parent
=
rel
;
pathnode
->
indexid
=
index
->
relids
;
pathnode
->
indexid
=
index
->
relids
;
pathnode
->
indexkeys
=
index
->
indexkeys
;
pathnode
->
indexqual
=
clausegroup
;
pathnode
->
indexqual
=
clausegroup
;
pathnode
->
path
.
joinid
=
((
CInfo
*
)
lfirst
(
clausegroup
))
->
cinfojoinid
;
pathnode
->
path
.
joinid
=
((
CInfo
*
)
lfirst
(
clausegroup
))
->
cinfojoinid
;
...
@@ -1130,7 +1234,7 @@ create_index_paths(Query *root,
...
@@ -1130,7 +1234,7 @@ create_index_paths(Query *root,
temp
=
false
;
temp
=
false
;
}
}
}
}
if
(
!
join
||
temp
)
{
/* restriction, ordering scan */
if
(
!
join
||
temp
)
{
/* restriction, ordering scan */
temp_path
=
create_index_path
(
root
,
rel
,
index
,
clausegroup
,
join
);
temp_path
=
create_index_path
(
root
,
rel
,
index
,
clausegroup
,
join
);
temp_node
=
temp_node
=
...
...
src/backend/optimizer/plan/createplan.c
View file @
d1463050
...
@@ -7,7 +7,7 @@
...
@@ -7,7 +7,7 @@
*
*
*
*
* IDENTIFICATION
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.
8 1997/03/12 21:05:56
scrappy Exp $
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.
9 1997/03/18 18:40:05
scrappy Exp $
*
*
*-------------------------------------------------------------------------
*-------------------------------------------------------------------------
*/
*/
...
@@ -417,22 +417,35 @@ create_nestloop_node(JoinPath *best_path,
...
@@ -417,22 +417,35 @@ create_nestloop_node(JoinPath *best_path,
NestLoop
*
join_node
=
(
NestLoop
*
)
NULL
;
NestLoop
*
join_node
=
(
NestLoop
*
)
NULL
;
if
(
IsA
(
inner_node
,
IndexScan
))
{
if
(
IsA
(
inner_node
,
IndexScan
))
{
/* An index is being used to reduce the number of tuples scanned in
/* An index is being used to reduce the number of tuples scanned in
* the inner relation.
* the inner relation. There will never be more than one index used
* There will never be more than one index used in the inner
* in the inner scan path, so we need only consider the first set of
* scan path, so we need only consider the first set of
* qualifications in indxqual.
* qualifications in indxqual.
*
* But there may be more than one clauses in this "first set"
* in the case of multi-column indices. - vadim 03/18/97
*/
*/
List
*
inner_indxqual
=
lfirst
(((
IndexScan
*
)
inner_node
)
->
indxqual
);
List
*
inner_indxqual
=
lfirst
(((
IndexScan
*
)
inner_node
)
->
indxqual
);
List
*
inner_qual
=
(
inner_indxqual
==
NULL
)
?
NULL
:
lfirst
(
inner_indxqual
);
List
*
inner_qual
;
bool
found
=
false
;
foreach
(
inner_qual
,
inner_indxqual
)
{
if
(
!
(
qual_clause_p
((
Node
*
)
inner_qual
))
)
{
found
=
true
;
break
;
}
}
/* If we have in fact found a join index qualification, remove these
/* If we have in fact found a join index qualification, remove these
* index clauses from the nestloop's join clauses and reset the
* index clauses from the nestloop's join clauses and reset the
* inner(index) scan's qualification so that the var nodes refer to
* inner(index) scan's qualification so that the var nodes refer to
* the proper outer join relation attributes.
* the proper outer join relation attributes.
*/
*/
if
(
!
(
qual_clause_p
((
Node
*
)
inner_qual
)))
{
if
(
found
)
{
List
*
new_inner_qual
=
NIL
;
List
*
new_inner_qual
=
NIL
;
clauses
=
set_difference
(
clauses
,
inner_indxqual
);
clauses
=
set_difference
(
clauses
,
inner_indxqual
);
...
@@ -613,7 +626,7 @@ fix_indxqual_references(Node *clause, Path *index_path)
...
@@ -613,7 +626,7 @@ fix_indxqual_references(Node *clause, Path *index_path)
if
(
lfirsti
(
index_path
->
parent
->
relids
)
==
((
Var
*
)
clause
)
->
varno
)
{
if
(
lfirsti
(
index_path
->
parent
->
relids
)
==
((
Var
*
)
clause
)
->
varno
)
{
int
pos
=
0
;
int
pos
=
0
;
int
varatt
=
((
Var
*
)
clause
)
->
varattno
;
int
varatt
=
((
Var
*
)
clause
)
->
varattno
;
int
*
indexkeys
=
index_path
->
parent
->
indexkeys
;
int
*
indexkeys
=
((
IndexPath
*
)
index_path
)
->
indexkeys
;
if
(
indexkeys
)
{
if
(
indexkeys
)
{
while
(
indexkeys
[
pos
]
!=
0
)
{
while
(
indexkeys
[
pos
]
!=
0
)
{
...
...
src/backend/optimizer/util/pathnode.c
View file @
d1463050
...
@@ -7,7 +7,7 @@
...
@@ -7,7 +7,7 @@
*
*
*
*
* IDENTIFICATION
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/pathnode.c,v 1.
1.1.1 1996/07/09 06:21:38
scrappy Exp $
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/pathnode.c,v 1.
2 1997/03/18 18:40:40
scrappy Exp $
*
*
*-------------------------------------------------------------------------
*-------------------------------------------------------------------------
*/
*/
...
@@ -248,10 +248,11 @@ create_index_path(Query *root,
...
@@ -248,10 +248,11 @@ create_index_path(Query *root,
pathnode
->
path
.
pathtype
=
T_IndexScan
;
pathnode
->
path
.
pathtype
=
T_IndexScan
;
pathnode
->
path
.
parent
=
rel
;
pathnode
->
path
.
parent
=
rel
;
pathnode
->
indexid
=
index
->
relids
;
pathnode
->
path
.
p_ordering
.
ordtype
=
SORTOP_ORDER
;
pathnode
->
path
.
p_ordering
.
ordtype
=
SORTOP_ORDER
;
pathnode
->
path
.
p_ordering
.
ord
.
sortop
=
index
->
ordering
;
pathnode
->
path
.
p_ordering
.
ord
.
sortop
=
index
->
ordering
;
pathnode
->
indexid
=
index
->
relids
;
pathnode
->
indexkeys
=
index
->
indexkeys
;
pathnode
->
indexqual
=
NIL
;
pathnode
->
indexqual
=
NIL
;
/* copy clauseinfo list into path for expensive function processing
/* copy clauseinfo list into path for expensive function processing
...
...
src/include/access/nbtree.h
View file @
d1463050
...
@@ -6,7 +6,7 @@
...
@@ -6,7 +6,7 @@
*
*
* Copyright (c) 1994, Regents of the University of California
* Copyright (c) 1994, Regents of the University of California
*
*
* $Id: nbtree.h,v 1.
9 1997/02/22 10:08:27 vadim
Exp $
* $Id: nbtree.h,v 1.
10 1997/03/18 18:41:16 scrappy
Exp $
*
*
*-------------------------------------------------------------------------
*-------------------------------------------------------------------------
*/
*/
...
@@ -68,6 +68,7 @@ typedef struct BTScanOpaqueData {
...
@@ -68,6 +68,7 @@ typedef struct BTScanOpaqueData {
Buffer
btso_mrkbuf
;
Buffer
btso_mrkbuf
;
uint16
qual_ok
;
/* 0 for quals like key == 1 && key > 2 */
uint16
qual_ok
;
/* 0 for quals like key == 1 && key > 2 */
uint16
numberOfKeys
;
/* number of key attributes */
uint16
numberOfKeys
;
/* number of key attributes */
uint16
numberOfFirstKeys
;
/* number of first key attributes */
ScanKey
keyData
;
/* key descriptor */
ScanKey
keyData
;
/* key descriptor */
}
BTScanOpaqueData
;
}
BTScanOpaqueData
;
...
@@ -270,9 +271,9 @@ extern bool _bt_invokestrat(Relation rel, AttrNumber attno,
...
@@ -270,9 +271,9 @@ extern bool _bt_invokestrat(Relation rel, AttrNumber attno,
extern
ScanKey
_bt_mkscankey
(
Relation
rel
,
IndexTuple
itup
);
extern
ScanKey
_bt_mkscankey
(
Relation
rel
,
IndexTuple
itup
);
extern
void
_bt_freeskey
(
ScanKey
skey
);
extern
void
_bt_freeskey
(
ScanKey
skey
);
extern
void
_bt_freestack
(
BTStack
stack
);
extern
void
_bt_freestack
(
BTStack
stack
);
extern
void
_bt_orderkeys
(
Relation
relation
,
uint16
*
numberOfKeys
,
extern
void
_bt_orderkeys
(
Relation
relation
,
BTScanOpaque
so
);
ScanKey
key
,
uint16
*
qual_ok
);
extern
bool
_bt_checkqual
(
IndexScanDesc
scan
,
IndexTuple
itup
);
extern
bool
_bt_checkqual
(
IndexScanDesc
scan
,
IndexTuple
itup
);
extern
bool
_bt_checkforkeys
(
IndexScanDesc
scan
,
IndexTuple
itup
,
Size
keysz
);
extern
BTItem
_bt_formitem
(
IndexTuple
itup
);
extern
BTItem
_bt_formitem
(
IndexTuple
itup
);
/*
/*
...
...
src/include/nodes/relation.h
View file @
d1463050
...
@@ -6,7 +6,7 @@
...
@@ -6,7 +6,7 @@
*
*
* Copyright (c) 1994, Regents of the University of California
* Copyright (c) 1994, Regents of the University of California
*
*
* $Id: relation.h,v 1.
3 1996/11/06 07:44:18
scrappy Exp $
* $Id: relation.h,v 1.
4 1997/03/18 18:41:37
scrappy Exp $
*
*
*-------------------------------------------------------------------------
*-------------------------------------------------------------------------
*/
*/
...
@@ -150,6 +150,7 @@ typedef struct IndexPath {
...
@@ -150,6 +150,7 @@ typedef struct IndexPath {
Path
path
;
Path
path
;
List
*
indexid
;
List
*
indexid
;
List
*
indexqual
;
List
*
indexqual
;
int
*
indexkeys
;
/* to transform heap attnos into index ones */
}
IndexPath
;
}
IndexPath
;
typedef
struct
JoinPath
{
typedef
struct
JoinPath
{
...
...
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