diff options
Diffstat (limited to 'src/backend/access')
-rw-r--r-- | src/backend/access/common/indexvalid.c | 9 | ||||
-rw-r--r-- | src/backend/access/common/scankey.c | 77 | ||||
-rw-r--r-- | src/backend/access/gist/Makefile | 4 | ||||
-rw-r--r-- | src/backend/access/gist/gistget.c | 22 | ||||
-rw-r--r-- | src/backend/access/gist/gistscan.c | 14 | ||||
-rw-r--r-- | src/backend/access/gist/giststrat.c | 125 | ||||
-rw-r--r-- | src/backend/access/hash/Makefile | 4 | ||||
-rw-r--r-- | src/backend/access/hash/hashstrat.c | 84 | ||||
-rw-r--r-- | src/backend/access/heap/tuptoaster.c | 51 | ||||
-rw-r--r-- | src/backend/access/index/Makefile | 4 | ||||
-rw-r--r-- | src/backend/access/index/istrat.c | 479 | ||||
-rw-r--r-- | src/backend/access/nbtree/Makefile | 4 | ||||
-rw-r--r-- | src/backend/access/nbtree/nbtinsert.c | 4 | ||||
-rw-r--r-- | src/backend/access/nbtree/nbtsearch.c | 13 | ||||
-rw-r--r-- | src/backend/access/nbtree/nbtstrat.c | 138 | ||||
-rw-r--r-- | src/backend/access/nbtree/nbtutils.c | 148 | ||||
-rw-r--r-- | src/backend/access/rtree/rtscan.c | 26 | ||||
-rw-r--r-- | src/backend/access/rtree/rtstrat.c | 201 |
18 files changed, 173 insertions, 1234 deletions
diff --git a/src/backend/access/common/indexvalid.c b/src/backend/access/common/indexvalid.c index 6b31636275..e2ca5a7563 100644 --- a/src/backend/access/common/indexvalid.c +++ b/src/backend/access/common/indexvalid.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/common/Attic/indexvalid.c,v 1.29 2003/08/04 02:39:56 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/common/Attic/indexvalid.c,v 1.30 2003/11/09 21:30:35 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -57,12 +57,9 @@ index_keytest(IndexTuple tuple, if (key->sk_flags & SK_ISNULL) return false; - if (key->sk_flags & SK_COMMUTE) - test = FunctionCall2(&key->sk_func, key->sk_argument, datum); - else - test = FunctionCall2(&key->sk_func, datum, key->sk_argument); + test = FunctionCall2(&key->sk_func, datum, key->sk_argument); - if (DatumGetBool(test) == !!(key->sk_flags & SK_NEGATE)) + if (!DatumGetBool(test)) return false; key++; diff --git a/src/backend/access/common/scankey.c b/src/backend/access/common/scankey.c index f79b2c7143..93741cbb84 100644 --- a/src/backend/access/common/scankey.c +++ b/src/backend/access/common/scankey.c @@ -1,73 +1,46 @@ /*------------------------------------------------------------------------- * - * scan.c - * scan direction and key code + * scankey.c + * scan key support code * * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/common/scankey.c,v 1.22 2003/08/04 02:39:56 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/common/scankey.c,v 1.23 2003/11/09 21:30:35 tgl Exp $ * *------------------------------------------------------------------------- */ - #include "postgres.h" #include "access/skey.h" -/* - * ScanKeyEntryIsLegal - * True iff the scan key entry is legal. - */ -#define ScanKeyEntryIsLegal(entry) \ -( \ - AssertMacro(PointerIsValid(entry)), \ - AttributeNumberIsValid((entry)->sk_attno) \ -) - -/* - * ScanKeyEntrySetIllegal - * Marks a scan key entry as illegal. - */ -void -ScanKeyEntrySetIllegal(ScanKey entry) -{ - - Assert(PointerIsValid(entry)); - - entry->sk_flags = 0; /* just in case... */ - entry->sk_attno = InvalidAttrNumber; - entry->sk_procedure = 0; /* should be InvalidRegProcedure */ - entry->sk_func.fn_oid = InvalidOid; - entry->sk_argument = (Datum) 0; -} /* * ScanKeyEntryInitialize - * Initializes a scan key entry. + * Initializes a scan key entry given all the field values. + * The target procedure is specified by OID. * - * Note: - * Assumes the scan key entry is valid. - * Assumes the intialized scan key entry will be legal. + * Note: CurrentMemoryContext at call should be as long-lived as the ScanKey + * itself, because that's what will be used for any subsidiary info attached + * to the ScanKey's FmgrInfo record. */ void ScanKeyEntryInitialize(ScanKey entry, - bits16 flags, + int flags, AttrNumber attributeNumber, + StrategyNumber strategy, RegProcedure procedure, - Datum argument) + Datum argument, + Oid argtype) { - Assert(PointerIsValid(entry)); - entry->sk_flags = flags; entry->sk_attno = attributeNumber; - entry->sk_procedure = procedure; + entry->sk_strategy = strategy; entry->sk_argument = argument; + entry->sk_argtype = argtype; fmgr_info(procedure, &entry->sk_func); - - Assert(ScanKeyEntryIsLegal(entry)); } /* @@ -75,25 +48,23 @@ ScanKeyEntryInitialize(ScanKey entry, * Initializes a scan key entry using an already-completed FmgrInfo * function lookup record. * - * mcxt is the memory context holding the scan key; it'll be used for - * any subsidiary info attached to the scankey's FmgrInfo record. + * Note: CurrentMemoryContext at call should be as long-lived as the ScanKey + * itself, because that's what will be used for any subsidiary info attached + * to the ScanKey's FmgrInfo record. */ void ScanKeyEntryInitializeWithInfo(ScanKey entry, - bits16 flags, + int flags, AttrNumber attributeNumber, + StrategyNumber strategy, FmgrInfo *finfo, - MemoryContext mcxt, - Datum argument) + Datum argument, + Oid argtype) { - Assert(PointerIsValid(entry)); - Assert(RegProcedureIsValid(finfo->fn_oid)); - entry->sk_flags = flags; entry->sk_attno = attributeNumber; - entry->sk_procedure = finfo->fn_oid; + entry->sk_strategy = strategy; entry->sk_argument = argument; - fmgr_info_copy(&entry->sk_func, finfo, mcxt); - - Assert(ScanKeyEntryIsLegal(entry)); + entry->sk_argtype = argtype; + fmgr_info_copy(&entry->sk_func, finfo, CurrentMemoryContext); } diff --git a/src/backend/access/gist/Makefile b/src/backend/access/gist/Makefile index 7f982d0dfd..f2c7ddf3a7 100644 --- a/src/backend/access/gist/Makefile +++ b/src/backend/access/gist/Makefile @@ -4,7 +4,7 @@ # Makefile for access/gist # # IDENTIFICATION -# $Header: /cvsroot/pgsql/src/backend/access/gist/Makefile,v 1.10 2000/08/31 16:09:31 petere Exp $ +# $Header: /cvsroot/pgsql/src/backend/access/gist/Makefile,v 1.11 2003/11/09 21:30:35 tgl Exp $ # #------------------------------------------------------------------------- @@ -12,7 +12,7 @@ subdir = src/backend/access/gist top_builddir = ../../../.. include $(top_builddir)/src/Makefile.global -OBJS = gist.o gistget.o gistscan.o giststrat.o +OBJS = gist.o gistget.o gistscan.o all: SUBSYS.o diff --git a/src/backend/access/gist/gistget.c b/src/backend/access/gist/gistget.c index bfa557bb9c..24168c9926 100644 --- a/src/backend/access/gist/gistget.c +++ b/src/backend/access/gist/gistget.c @@ -8,7 +8,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/gist/gistget.c,v 1.36 2003/08/04 02:39:57 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/gist/gistget.c,v 1.37 2003/11/09 21:30:35 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -249,26 +249,16 @@ gistindex_keytest(IndexTuple tuple, IndexTupleSize(tuple) - sizeof(IndexTupleData), FALSE, isNull); - if (key[0].sk_flags & SK_COMMUTE) - { - test = FunctionCall3(&key[0].sk_func, - key[0].sk_argument, - PointerGetDatum(&de), - ObjectIdGetDatum(key[0].sk_procedure)); - } - else - { - test = FunctionCall3(&key[0].sk_func, - PointerGetDatum(&de), - key[0].sk_argument, - ObjectIdGetDatum(key[0].sk_procedure)); - } + test = FunctionCall3(&key[0].sk_func, + PointerGetDatum(&de), + key[0].sk_argument, + Int32GetDatum(key[0].sk_strategy)); if (de.key != datum && !isAttByVal(giststate, key[0].sk_attno - 1)) if (DatumGetPointer(de.key) != NULL) pfree(DatumGetPointer(de.key)); - if (DatumGetBool(test) == !!(key[0].sk_flags & SK_NEGATE)) + if (!DatumGetBool(test)) return false; scanKeySize--; diff --git a/src/backend/access/gist/gistscan.c b/src/backend/access/gist/gistscan.c index 790048aef3..960d1c2f25 100644 --- a/src/backend/access/gist/gistscan.c +++ b/src/backend/access/gist/gistscan.c @@ -8,7 +8,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/gist/gistscan.c,v 1.47 2003/08/04 02:39:57 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/gist/gistscan.c,v 1.48 2003/11/09 21:30:35 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -106,17 +106,13 @@ gistrescan(PG_FUNCTION_ARGS) s->numberOfKeys * sizeof(ScanKeyData)); /* - * Play games here with the scan key to use the Consistent - * function for all comparisons: 1) the sk_procedure field will - * now be used to hold the strategy number 2) the sk_func field - * will point to the Consistent function + * Modify the scan key so that the Consistent function is called + * for all comparisons. The original operator is passed to the + * Consistent function in the form of its strategy number, which + * is available from the sk_strategy field. */ for (i = 0; i < s->numberOfKeys; i++) { - s->keyData[i].sk_procedure = - RelationGetGISTStrategy(s->indexRelation, - s->keyData[i].sk_attno, - s->keyData[i].sk_procedure); s->keyData[i].sk_func = p->giststate->consistentFn[s->keyData[i].sk_attno - 1]; } } diff --git a/src/backend/access/gist/giststrat.c b/src/backend/access/gist/giststrat.c deleted file mode 100644 index fe83b5ac79..0000000000 --- a/src/backend/access/gist/giststrat.c +++ /dev/null @@ -1,125 +0,0 @@ -/*------------------------------------------------------------------------- - * - * giststrat.c - * strategy map data for GiSTs. - * - * - * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group - * Portions Copyright (c) 1994, Regents of the University of California - * - * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/gist/Attic/giststrat.c,v 1.21 2003/08/04 02:39:57 momjian Exp $ - * - *------------------------------------------------------------------------- - */ -#include "postgres.h" - -#include "access/gist.h" -#include "access/istrat.h" - - -/* - * Note: negate, commute, and negatecommute all assume that operators are - * ordered as follows in the strategy map: - * - * contains, contained-by - * - * The negate, commute, and negatecommute arrays are used by the planner - * to plan indexed scans over data that appears in the qualificiation in - * a boolean negation, or whose operands appear in the wrong order. For - * example, if the operator "<%" means "contains", and the user says - * - * where not rel.box <% "(10,10,20,20)"::box - * - * the planner can plan an index scan by noting that GiST indices have - * an operator in their operator class for negating <%. - * - * Similarly, if the user says something like - * - * where "(10,10,20,20)"::box <% rel.box - * - * the planner can see that the GiST index on rel.box has an operator in - * its opclass for commuting <%, and plan the scan using that operator. - * This added complexity in the access methods makes the planner a lot easier - * to write. - */ - -/* if a op b, what operator tells us if (not a op b)? */ -static StrategyNumber GISTNegate[GISTNStrategies] = { - InvalidStrategy, - InvalidStrategy, - InvalidStrategy -}; - -/* if a op_1 b, what is the operator op_2 such that b op_2 a? */ -static StrategyNumber GISTCommute[GISTNStrategies] = { - InvalidStrategy, - InvalidStrategy, - InvalidStrategy -}; - -/* if a op_1 b, what is the operator op_2 such that (b !op_2 a)? */ -static StrategyNumber GISTNegateCommute[GISTNStrategies] = { - InvalidStrategy, - InvalidStrategy, - InvalidStrategy -}; - -/* - * GiSTs do not currently support TermData (see rtree/rtstrat.c for - * discussion of - * TermData) -- such logic must be encoded in the user's Consistent function. - */ - -static StrategyExpression GISTEvaluationExpressions[GISTNStrategies] = { - NULL, - NULL, - NULL -}; - -/* - * If you were sufficiently attentive to detail, you would go through - * the ExpressionData pain above for every one of the strategies - * we defined. I am not. Now we declare the StrategyEvaluationData - * structure that gets shipped around to help the planner and the access - * method decide what sort of scan it should do, based on (a) what the - * user asked for, (b) what operators are defined for a particular opclass, - * and (c) the reams of information we supplied above. - * - * The idea of all of this initialized data is to make life easier on the - * user when he defines a new operator class to use this access method. - * By filling in all the data, we let him get away with leaving holes in his - * operator class, and still let him use the index. The added complexity - * in the access methods just isn't worth the trouble, though. - */ - -static StrategyEvaluationData GISTEvaluationData = { - GISTNStrategies, /* # of strategies */ - (StrategyTransformMap) GISTNegate, /* how to do (not qual) */ - (StrategyTransformMap) GISTCommute, /* how to swap operands */ - (StrategyTransformMap) GISTNegateCommute, /* how to do both */ - GISTEvaluationExpressions -}; - - -StrategyNumber -RelationGetGISTStrategy(Relation r, - AttrNumber attnum, - RegProcedure proc) -{ - return RelationGetStrategy(r, attnum, &GISTEvaluationData, proc); -} - -#ifdef NOT_USED -bool -RelationInvokeGISTStrategy(Relation r, - AttrNumber attnum, - StrategyNumber s, - Datum left, - Datum right) -{ - return (RelationInvokeStrategy(r, &GISTEvaluationData, attnum, s, - left, right)); -} - -#endif diff --git a/src/backend/access/hash/Makefile b/src/backend/access/hash/Makefile index 5e4f56a80c..5203db34b1 100644 --- a/src/backend/access/hash/Makefile +++ b/src/backend/access/hash/Makefile @@ -4,7 +4,7 @@ # Makefile for access/hash # # IDENTIFICATION -# $Header: /cvsroot/pgsql/src/backend/access/hash/Makefile,v 1.10 2000/08/31 16:09:33 petere Exp $ +# $Header: /cvsroot/pgsql/src/backend/access/hash/Makefile,v 1.11 2003/11/09 21:30:35 tgl Exp $ # #------------------------------------------------------------------------- @@ -13,7 +13,7 @@ top_builddir = ../../../.. include $(top_builddir)/src/Makefile.global OBJS = hash.o hashfunc.o hashinsert.o hashovfl.o hashpage.o hashscan.o \ - hashsearch.o hashstrat.o hashutil.o + hashsearch.o hashutil.o all: SUBSYS.o diff --git a/src/backend/access/hash/hashstrat.c b/src/backend/access/hash/hashstrat.c deleted file mode 100644 index d72ad08ee1..0000000000 --- a/src/backend/access/hash/hashstrat.c +++ /dev/null @@ -1,84 +0,0 @@ -/*------------------------------------------------------------------------- - * - * hashstrat.c - * Strategy map entries for the hash indexed access method - * - * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group - * Portions Copyright (c) 1994, Regents of the University of California - * - * - * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/hash/Attic/hashstrat.c,v 1.23 2003/08/04 02:39:57 momjian Exp $ - * - *------------------------------------------------------------------------- - */ -#include "postgres.h" - -#include "access/hash.h" - - -/* - * only one valid strategy for hash tables: equality. - */ - -#ifdef NOT_USED - -static StrategyNumber HTNegate[HTMaxStrategyNumber] = { - InvalidStrategy -}; - -static StrategyNumber HTCommute[HTMaxStrategyNumber] = { - HTEqualStrategyNumber -}; - -static StrategyNumber HTNegateCommute[HTMaxStrategyNumber] = { - InvalidStrategy -}; - -static StrategyExpression HTEvaluationExpressions[HTMaxStrategyNumber] = { - NULL -}; - -static StrategyEvaluationData HTEvaluationData = { - HTMaxStrategyNumber, - (StrategyTransformMap) HTNegate, - (StrategyTransformMap) HTCommute, - (StrategyTransformMap) HTNegateCommute, - HTEvaluationExpressions -}; -#endif - -/* ---------------------------------------------------------------- - * RelationGetHashStrategy - * ---------------------------------------------------------------- - */ - -#ifdef NOT_USED -static StrategyNumber -_hash_getstrat(Relation rel, - AttrNumber attno, - RegProcedure proc) -{ - StrategyNumber strat; - - strat = RelationGetStrategy(rel, attno, &HTEvaluationData, proc); - - Assert(StrategyNumberIsValid(strat)); - - return strat; -} -#endif - -#ifdef NOT_USED -static bool -_hash_invokestrat(Relation rel, - AttrNumber attno, - StrategyNumber strat, - Datum left, - Datum right) -{ - return (RelationInvokeStrategy(rel, &HTEvaluationData, attno, strat, - left, right)); -} - -#endif diff --git a/src/backend/access/heap/tuptoaster.c b/src/backend/access/heap/tuptoaster.c index 1840e0d1d7..0bfe3c01b8 100644 --- a/src/backend/access/heap/tuptoaster.c +++ b/src/backend/access/heap/tuptoaster.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/heap/tuptoaster.c,v 1.38 2003/08/04 23:59:37 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/heap/tuptoaster.c,v 1.39 2003/11/09 21:30:35 tgl Exp $ * * * INTERFACE ROUTINES @@ -31,6 +31,7 @@ #include "access/genam.h" #include "access/tuptoaster.h" #include "catalog/catalog.h" +#include "catalog/pg_type.h" #include "utils/rel.h" #include "utils/builtins.h" #include "utils/fmgroids.h" @@ -967,11 +968,11 @@ toast_delete_datum(Relation rel, Datum value) * Setup a scan key to fetch from the index by va_valueid (we don't * particularly care whether we see them in sequence or not) */ - ScanKeyEntryInitialize(&toastkey, - (bits16) 0, + ScanKeyEntryInitialize(&toastkey, 0, (AttrNumber) 1, - (RegProcedure) F_OIDEQ, - ObjectIdGetDatum(attr->va_content.va_external.va_valueid)); + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(attr->va_content.va_external.va_valueid), + OIDOID); /* * Find the chunks by index @@ -1039,11 +1040,11 @@ toast_fetch_datum(varattrib *attr) /* * Setup a scan key to fetch from the index by va_valueid */ - ScanKeyEntryInitialize(&toastkey, - (bits16) 0, + ScanKeyEntryInitialize(&toastkey, 0, (AttrNumber) 1, - (RegProcedure) F_OIDEQ, - ObjectIdGetDatum(attr->va_content.va_external.va_valueid)); + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(attr->va_content.va_external.va_valueid), + OIDOID); /* * Read the chunks by index @@ -1194,37 +1195,33 @@ toast_fetch_datum_slice(varattrib *attr, int32 sliceoffset, int32 length) * Setup a scan key to fetch from the index. This is either two keys * or three depending on the number of chunks. */ - ScanKeyEntryInitialize(&toastkey[0], - (bits16) 0, + ScanKeyEntryInitialize(&toastkey[0], 0, (AttrNumber) 1, - (RegProcedure) F_OIDEQ, - ObjectIdGetDatum(attr->va_content.va_external.va_valueid)); + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(attr->va_content.va_external.va_valueid), + OIDOID); /* - * Now dependent on number of chunks: + * Use equality condition for one chunk, a range condition otherwise: */ - if (numchunks == 1) { - ScanKeyEntryInitialize(&toastkey[1], - (bits16) 0, + ScanKeyEntryInitialize(&toastkey[1], 0, (AttrNumber) 2, - (RegProcedure) F_INT4EQ, - Int32GetDatum(startchunk)); + BTEqualStrategyNumber, F_INT4EQ, + Int32GetDatum(startchunk), INT4OID); nscankeys = 2; } else { - ScanKeyEntryInitialize(&toastkey[1], - (bits16) 0, + ScanKeyEntryInitialize(&toastkey[1], 0, (AttrNumber) 2, - (RegProcedure) F_INT4GE, - Int32GetDatum(startchunk)); - ScanKeyEntryInitialize(&toastkey[2], - (bits16) 0, + BTGreaterEqualStrategyNumber, F_INT4GE, + Int32GetDatum(startchunk), INT4OID); + ScanKeyEntryInitialize(&toastkey[2], 0, (AttrNumber) 2, - (RegProcedure) F_INT4LE, - Int32GetDatum(endchunk)); + BTLessEqualStrategyNumber, F_INT4LE, + Int32GetDatum(endchunk), INT4OID); nscankeys = 3; } diff --git a/src/backend/access/index/Makefile b/src/backend/access/index/Makefile index dcae193bff..cc3d2ee138 100644 --- a/src/backend/access/index/Makefile +++ b/src/backend/access/index/Makefile @@ -4,7 +4,7 @@ # Makefile for access/index # # IDENTIFICATION -# $Header: /cvsroot/pgsql/src/backend/access/index/Makefile,v 1.10 2000/08/31 16:09:36 petere Exp $ +# $Header: /cvsroot/pgsql/src/backend/access/index/Makefile,v 1.11 2003/11/09 21:30:35 tgl Exp $ # #------------------------------------------------------------------------- @@ -12,7 +12,7 @@ subdir = src/backend/access/index top_builddir = ../../../.. include $(top_builddir)/src/Makefile.global -OBJS = genam.o indexam.o istrat.o +OBJS = genam.o indexam.o all: SUBSYS.o diff --git a/src/backend/access/index/istrat.c b/src/backend/access/index/istrat.c deleted file mode 100644 index 1298420d4f..0000000000 --- a/src/backend/access/index/istrat.c +++ /dev/null @@ -1,479 +0,0 @@ -/*------------------------------------------------------------------------- - * - * istrat.c - * index scan strategy manipulation code and index strategy manipulation - * operator code. - * - * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group - * Portions Copyright (c) 1994, Regents of the University of California - * - * - * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/index/Attic/istrat.c,v 1.60 2003/08/04 02:39:57 momjian Exp $ - * - *------------------------------------------------------------------------- - */ -#include "postgres.h" - -#include "access/istrat.h" - - -#ifdef USE_ASSERT_CHECKING -static bool StrategyEvaluationIsValid(StrategyEvaluation evaluation); -static bool StrategyExpressionIsValid(StrategyExpression expression, - StrategyNumber maxStrategy); -static bool StrategyOperatorIsValid(StrategyOperator operator, - StrategyNumber maxStrategy); -static bool StrategyTermIsValid(StrategyTerm term, - StrategyNumber maxStrategy); -#endif - - -/* ---------------------------------------------------------------- - * misc strategy support routines - * ---------------------------------------------------------------- - */ - -/* - * StrategyNumberIsValid - * StrategyNumberIsInBounds - * StrategyMapIsValid - * StrategyTransformMapIsValid - * IndexStrategyIsValid - * - * ... are now macros in istrat.h -cim 4/27/91 - */ - -/* - * StrategyMapGetScanKeyEntry - * Returns a scan key entry of a index strategy mapping member. - * - * Note: - * Assumes that the index strategy mapping is valid. - * Assumes that the index strategy number is valid. - * Bounds checking should be done outside this routine. - */ -ScanKey -StrategyMapGetScanKeyEntry(StrategyMap map, - StrategyNumber strategyNumber) -{ - Assert(StrategyMapIsValid(map)); - Assert(StrategyNumberIsValid(strategyNumber)); - return &map->entry[strategyNumber - 1]; -} - -/* - * IndexStrategyGetStrategyMap - * Returns an index strategy mapping of an index strategy. - * - * Note: - * Assumes that the index strategy is valid. - * Assumes that the number of index strategies is valid. - * Bounds checking should be done outside this routine. - */ -StrategyMap -IndexStrategyGetStrategyMap(IndexStrategy indexStrategy, - StrategyNumber maxStrategyNum, - AttrNumber attrNum) -{ - Assert(IndexStrategyIsValid(indexStrategy)); - Assert(StrategyNumberIsValid(maxStrategyNum)); - Assert(AttributeNumberIsValid(attrNum)); - - maxStrategyNum = AMStrategies(maxStrategyNum); /* XXX */ - return &indexStrategy->strategyMapData[maxStrategyNum * (attrNum - 1)]; -} - -/* - * AttributeNumberGetIndexStrategySize - * Computes the size of an index strategy. - */ -Size -AttributeNumberGetIndexStrategySize(AttrNumber maxAttributeNumber, - StrategyNumber maxStrategyNumber) -{ - maxStrategyNumber = AMStrategies(maxStrategyNumber); /* XXX */ - return maxAttributeNumber * maxStrategyNumber * sizeof(ScanKeyData); -} - -#ifdef USE_ASSERT_CHECKING -/* - * StrategyTransformMapIsValid is now a macro in istrat.h -cim 4/27/91 - */ - -/* ---------------- - * StrategyOperatorIsValid - * ---------------- - */ -static bool -StrategyOperatorIsValid(StrategyOperator operator, - StrategyNumber maxStrategy) -{ - return (bool) - (PointerIsValid(operator) && - StrategyNumberIsInBounds(operator->strategy, maxStrategy) && - !(operator->flags & ~(SK_NEGATE | SK_COMMUTE))); -} - -/* ---------------- - * StrategyTermIsValid - * ---------------- - */ -static bool -StrategyTermIsValid(StrategyTerm term, - StrategyNumber maxStrategy) -{ - Index index; - - if (!PointerIsValid(term) || term->degree == 0) - return false; - - for (index = 0; index < term->degree; index += 1) - { - if (!StrategyOperatorIsValid(&term->operatorData[index], - maxStrategy)) - return false; - } - - return true; -} - -/* ---------------- - * StrategyExpressionIsValid - * ---------------- - */ -static bool -StrategyExpressionIsValid(StrategyExpression expression, - StrategyNumber maxStrategy) -{ - StrategyTerm *termP; - - if (!PointerIsValid(expression)) - return true; - - if (!StrategyTermIsValid(expression->term[0], maxStrategy)) - return false; - - termP = &expression->term[1]; - while (StrategyTermIsValid(*termP, maxStrategy)) - termP += 1; - - return (bool) - (!PointerIsValid(*termP)); -} - -/* ---------------- - * StrategyEvaluationIsValid - * ---------------- - */ -static bool -StrategyEvaluationIsValid(StrategyEvaluation evaluation) -{ - Index index; - - if (!PointerIsValid(evaluation) || - !StrategyNumberIsValid(evaluation->maxStrategy) || - !StrategyTransformMapIsValid(evaluation->negateTransform) || - !StrategyTransformMapIsValid(evaluation->commuteTransform) || - !StrategyTransformMapIsValid(evaluation->negateCommuteTransform)) - return false; - - for (index = 0; index < evaluation->maxStrategy; index += 1) - { - if (!StrategyExpressionIsValid(evaluation->expression[index], - evaluation->maxStrategy)) - return false; - } - return true; -} -#endif - -#ifdef NOT_USED -/* ---------------- - * StrategyTermEvaluate - * ---------------- - */ -static bool -StrategyTermEvaluate(StrategyTerm term, - StrategyMap map, - Datum left, - Datum right) -{ - bool result = false; - Index index; - StrategyOperator operator; - - for (index = 0, operator = &term->operatorData[0]; - index < term->degree; index += 1, operator += 1) - { - ScanKey entry; - - entry = &map->entry[operator->strategy - 1]; - - Assert(RegProcedureIsValid(entry->sk_procedure)); - - switch (operator->flags ^ entry->sk_flags) - { - case 0x0: - result = DatumGetBool(FunctionCall2(&entry->sk_func, - left, right)); - break; - - case SK_NEGATE: - result = !DatumGetBool(FunctionCall2(&entry->sk_func, - left, right)); - break; - - case SK_COMMUTE: - result = DatumGetBool(FunctionCall2(&entry->sk_func, - right, left)); - break; - - case SK_NEGATE | SK_COMMUTE: - result = !DatumGetBool(FunctionCall2(&entry->sk_func, - right, left)); - break; - - default: - elog(ERROR, "impossible strategy case: %d", - operator->flags ^ entry->sk_flags); - } - if (!result) - return result; - } - - return result; -} -#endif - -/* ---------------- - * RelationGetStrategy - * - * Identify strategy number that describes given procedure, if there is one. - * ---------------- - */ -StrategyNumber -RelationGetStrategy(Relation relation, - AttrNumber attributeNumber, - StrategyEvaluation evaluation, - RegProcedure procedure) -{ - StrategyNumber strategy; - StrategyMap strategyMap; - ScanKey entry; - Index index; - int numattrs; - - Assert(RelationIsValid(relation)); - numattrs = RelationGetNumberOfAttributes(relation); - - Assert(relation->rd_rel->relkind == RELKIND_INDEX); /* XXX use accessor */ - Assert((attributeNumber >= 1) && (attributeNumber <= numattrs)); - - Assert(StrategyEvaluationIsValid(evaluation)); - Assert(RegProcedureIsValid(procedure)); - - strategyMap = IndexStrategyGetStrategyMap(RelationGetIndexStrategy(relation), - evaluation->maxStrategy, - attributeNumber); - - /* get a strategy number for the procedure ignoring flags for now */ - for (index = 0; index < evaluation->maxStrategy; index += 1) - { - if (strategyMap->entry[index].sk_procedure == procedure) - break; - } - - if (index == evaluation->maxStrategy) - return InvalidStrategy; - - strategy = 1 + index; - entry = StrategyMapGetScanKeyEntry(strategyMap, strategy); - - Assert(!(entry->sk_flags & ~(SK_NEGATE | SK_COMMUTE))); - - switch (entry->sk_flags & (SK_NEGATE | SK_COMMUTE)) - { - case 0x0: - return strategy; - - case SK_NEGATE: - strategy = evaluation->negateTransform->strategy[strategy - 1]; - break; - - case SK_COMMUTE: - strategy = evaluation->commuteTransform->strategy[strategy - 1]; - break; - - case SK_NEGATE | SK_COMMUTE: - strategy = evaluation->negateCommuteTransform->strategy[strategy - 1]; - break; - - default: - elog(ERROR, "impossible strategy case: %d", - entry->sk_flags); - } - - if (!StrategyNumberIsInBounds(strategy, evaluation->maxStrategy)) - { - if (!StrategyNumberIsValid(strategy)) - elog(ERROR, "corrupted strategy evaluation"); - } - - return strategy; -} - -#ifdef NOT_USED -/* ---------------- - * RelationInvokeStrategy - * ---------------- - */ -bool /* XXX someday, this may return Datum */ -RelationInvokeStrategy(Relation relation, - StrategyEvaluation evaluation, - AttrNumber attributeNumber, - StrategyNumber strategy, - Datum left, - Datum right) -{ - StrategyNumber newStrategy; - StrategyMap strategyMap; - ScanKey entry; - StrategyTermData termData; - int numattrs; - - Assert(RelationIsValid(relation)); - Assert(relation->rd_rel->relkind == RELKIND_INDEX); /* XXX use accessor */ - numattrs = RelationGetNumberOfAttributes(relation); - - Assert(StrategyEvaluationIsValid(evaluation)); - Assert(AttributeNumberIsValid(attributeNumber)); - Assert((attributeNumber >= 1) && (attributeNumber < 1 + numattrs)); - - Assert(StrategyNumberIsInBounds(strategy, evaluation->maxStrategy)); - - termData.degree = 1; - - strategyMap = IndexStrategyGetStrategyMap(RelationGetIndexStrategy(relation), - evaluation->maxStrategy, - attributeNumber); - - entry = StrategyMapGetScanKeyEntry(strategyMap, strategy); - - if (RegProcedureIsValid(entry->sk_procedure)) - { - termData.operatorData[0].strategy = strategy; - termData.operatorData[0].flags = 0x0; - - return StrategyTermEvaluate(&termData, strategyMap, left, right); - } - - - newStrategy = evaluation->negateTransform->strategy[strategy - 1]; - if (newStrategy != strategy && StrategyNumberIsValid(newStrategy)) - { - entry = StrategyMapGetScanKeyEntry(strategyMap, newStrategy); - - if (RegProcedureIsValid(entry->sk_procedure)) - { - termData.operatorData[0].strategy = newStrategy; - termData.operatorData[0].flags = SK_NEGATE; - - return StrategyTermEvaluate(&termData, strategyMap, left, right); - } - } - - newStrategy = evaluation->commuteTransform->strategy[strategy - 1]; - if (newStrategy != strategy && StrategyNumberIsValid(newStrategy)) - { - entry = StrategyMapGetScanKeyEntry(strategyMap, newStrategy); - - if (RegProcedureIsValid(entry->sk_procedure)) - { - termData.operatorData[0].strategy = newStrategy; - termData.operatorData[0].flags = SK_COMMUTE; - - return StrategyTermEvaluate(&termData, strategyMap, left, right); - } - } - - newStrategy = evaluation->negateCommuteTransform->strategy[strategy - 1]; - if (newStrategy != strategy && StrategyNumberIsValid(newStrategy)) - { - entry = StrategyMapGetScanKeyEntry(strategyMap, newStrategy); - - if (RegProcedureIsValid(entry->sk_procedure)) - { - termData.operatorData[0].strategy = newStrategy; - termData.operatorData[0].flags = SK_NEGATE | SK_COMMUTE; - - return StrategyTermEvaluate(&termData, strategyMap, left, right); - } - } - - if (PointerIsValid(evaluation->expression[strategy - 1])) - { - StrategyTerm *termP; - - termP = &evaluation->expression[strategy - 1]->term[0]; - while (PointerIsValid(*termP)) - { - Index index; - - for (index = 0; index < (*termP)->degree; index += 1) - { - entry = StrategyMapGetScanKeyEntry(strategyMap, - (*termP)->operatorData[index].strategy); - - if (!RegProcedureIsValid(entry->sk_procedure)) - break; - } - - if (index == (*termP)->degree) - return StrategyTermEvaluate(*termP, strategyMap, left, right); - - termP += 1; - } - } - - elog(ERROR, "cannot evaluate strategy %d", strategy); - - /* not reached, just to make compiler happy */ - return FALSE; -} -#endif - -/* ---------------- - * IndexStrategyDisplay - * ---------------- - */ -#ifdef ISTRATDEBUG -int -IndexStrategyDisplay(IndexStrategy indexStrategy, - StrategyNumber numberOfStrategies, - int numberOfAttributes) -{ - StrategyMap strategyMap; - AttrNumber attributeNumber; - StrategyNumber strategyNumber; - - for (attributeNumber = 1; attributeNumber <= numberOfAttributes; - attributeNumber += 1) - { - strategyMap = IndexStrategyGetStrategyMap(indexStrategy, - numberOfStrategies, - attributeNumber); - - for (strategyNumber = 1; - strategyNumber <= AMStrategies(numberOfStrategies); - strategyNumber += 1) - { - printf(":att %d\t:str %d\t:opr 0x%x(%d)\n", - attributeNumber, strategyNumber, - strategyMap->entry[strategyNumber - 1].sk_procedure, - strategyMap->entry[strategyNumber - 1].sk_procedure); - } - } -} - -#endif /* defined(ISTRATDEBUG) */ diff --git a/src/backend/access/nbtree/Makefile b/src/backend/access/nbtree/Makefile index cf525f9f1f..487c0a9444 100644 --- a/src/backend/access/nbtree/Makefile +++ b/src/backend/access/nbtree/Makefile @@ -4,7 +4,7 @@ # Makefile for access/nbtree # # IDENTIFICATION -# $Header: /cvsroot/pgsql/src/backend/access/nbtree/Makefile,v 1.12 2003/02/21 00:06:21 tgl Exp $ +# $Header: /cvsroot/pgsql/src/backend/access/nbtree/Makefile,v 1.13 2003/11/09 21:30:35 tgl Exp $ # #------------------------------------------------------------------------- @@ -13,7 +13,7 @@ top_builddir = ../../../.. include $(top_builddir)/src/Makefile.global OBJS = nbtcompare.o nbtinsert.o nbtpage.o nbtree.o nbtsearch.o \ - nbtstrat.o nbtutils.o nbtsort.o nbtxlog.o + nbtutils.o nbtsort.o nbtxlog.o all: SUBSYS.o diff --git a/src/backend/access/nbtree/nbtinsert.c b/src/backend/access/nbtree/nbtinsert.c index 27c833408d..98f3abb511 100644 --- a/src/backend/access/nbtree/nbtinsert.c +++ b/src/backend/access/nbtree/nbtinsert.c @@ -1,6 +1,6 @@ /*------------------------------------------------------------------------- * - * btinsert.c + * nbtinsert.c * Item insertion in Lehman and Yao btrees for Postgres. * * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.106 2003/09/25 06:57:57 petere Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.107 2003/11/09 21:30:35 tgl Exp $ * *------------------------------------------------------------------------- */ diff --git a/src/backend/access/nbtree/nbtsearch.c b/src/backend/access/nbtree/nbtsearch.c index d27af61c5c..432a1ab0c2 100644 --- a/src/backend/access/nbtree/nbtsearch.c +++ b/src/backend/access/nbtree/nbtsearch.c @@ -8,7 +8,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtsearch.c,v 1.80 2003/08/08 21:41:27 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtsearch.c,v 1.81 2003/11/09 21:30:35 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -488,8 +488,6 @@ _bt_first(IndexScanDesc scan, ScanDirection dir) /* if we didn't find a boundary for the preceding attr, quit */ if (attno > keysCount + 1) break; - strat = _bt_getstrat(rel, attno, - so->keyData[i].sk_procedure); /* * Can we use this key as a starting boundary for this attr? @@ -497,6 +495,7 @@ _bt_first(IndexScanDesc scan, ScanDirection dir) * We can use multiple keys if they look like, say, = >= = but we * have to stop after accepting a > or < boundary. */ + strat = so->keyData[i].sk_strategy; if (strat == strat_total || strat == BTEqualStrategyNumber) nKeyIs[keysCount++] = i; @@ -555,13 +554,17 @@ _bt_first(IndexScanDesc scan, ScanDirection dir) elog(ERROR, "btree doesn't support is(not)null, yet"); return false; } + /* + * XXX what if sk_argtype is not same as index? + */ procinfo = index_getprocinfo(rel, i + 1, BTORDER_PROC); ScanKeyEntryInitializeWithInfo(scankeys + i, so->keyData[j].sk_flags, i + 1, + InvalidStrategy, procinfo, - CurrentMemoryContext, - so->keyData[j].sk_argument); + so->keyData[j].sk_argument, + so->keyData[j].sk_argtype); } if (nKeyIs) pfree(nKeyIs); diff --git a/src/backend/access/nbtree/nbtstrat.c b/src/backend/access/nbtree/nbtstrat.c deleted file mode 100644 index 15544d4757..0000000000 --- a/src/backend/access/nbtree/nbtstrat.c +++ /dev/null @@ -1,138 +0,0 @@ -/*------------------------------------------------------------------------- - * - * nbtstrat.c - * Strategy map entries for the btree indexed access method - * - * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group - * Portions Copyright (c) 1994, Regents of the University of California - * - * - * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/nbtree/Attic/nbtstrat.c,v 1.18 2003/08/04 02:39:57 momjian Exp $ - * - *------------------------------------------------------------------------- - */ - -#include "postgres.h" - -#include "access/istrat.h" -#include "access/nbtree.h" - -/* - * Note: - * StrategyNegate, StrategyCommute, and StrategyNegateCommute - * assume <, <=, ==, >=, > ordering. - */ -static StrategyNumber BTNegate[BTMaxStrategyNumber] = { - BTGreaterEqualStrategyNumber, - BTGreaterStrategyNumber, - InvalidStrategy, - BTLessStrategyNumber, - BTLessEqualStrategyNumber -}; - -static StrategyNumber BTCommute[BTMaxStrategyNumber] = { - BTGreaterStrategyNumber, - BTGreaterEqualStrategyNumber, - InvalidStrategy, - BTLessEqualStrategyNumber, - BTLessStrategyNumber -}; - -static StrategyNumber BTNegateCommute[BTMaxStrategyNumber] = { - BTLessEqualStrategyNumber, - BTLessStrategyNumber, - InvalidStrategy, - BTGreaterStrategyNumber, - BTGreaterEqualStrategyNumber -}; - -static uint16 BTLessTermData[] = { /* XXX type clash */ - 2, - BTLessStrategyNumber, - SK_NEGATE, - BTLessStrategyNumber, - SK_NEGATE | SK_COMMUTE -}; - -static uint16 BTLessEqualTermData[] = { /* XXX type clash */ - 2, - BTLessEqualStrategyNumber, - 0x0, - BTLessEqualStrategyNumber, - SK_COMMUTE -}; - -static uint16 BTGreaterEqualTermData[] = { /* XXX type clash */ - 2, - BTGreaterEqualStrategyNumber, - 0x0, - BTGreaterEqualStrategyNumber, - SK_COMMUTE -}; - -static uint16 BTGreaterTermData[] = { /* XXX type clash */ - 2, - BTGreaterStrategyNumber, - SK_NEGATE, - BTGreaterStrategyNumber, - SK_NEGATE | SK_COMMUTE -}; - -static StrategyTerm BTEqualExpressionData[] = { - (StrategyTerm) BTLessTermData, /* XXX */ - (StrategyTerm) BTLessEqualTermData, /* XXX */ - (StrategyTerm) BTGreaterEqualTermData, /* XXX */ - (StrategyTerm) BTGreaterTermData, /* XXX */ - NULL -}; - -static StrategyExpression BTEvaluationExpressions[BTMaxStrategyNumber] = { - NULL, - NULL, - (StrategyExpression) BTEqualExpressionData, - NULL, - NULL -}; - -static StrategyEvaluationData BTEvaluationData = { - BTMaxStrategyNumber, - (StrategyTransformMap) BTNegate, - (StrategyTransformMap) BTCommute, - (StrategyTransformMap) BTNegateCommute, - BTEvaluationExpressions -}; - -/* ---------------------------------------------------------------- - * RelationGetBTStrategy - * ---------------------------------------------------------------- - */ - -StrategyNumber -_bt_getstrat(Relation rel, - AttrNumber attno, - RegProcedure proc) -{ - StrategyNumber strat; - - strat = RelationGetStrategy(rel, attno, &BTEvaluationData, proc); - - Assert(StrategyNumberIsValid(strat)); - - return strat; -} - -#ifdef NOT_USED - -bool -_bt_invokestrat(Relation rel, - AttrNumber attno, - StrategyNumber strat, - Datum left, - Datum right) -{ - return (RelationInvokeStrategy(rel, &BTEvaluationData, attno, strat, - left, right)); -} - -#endif diff --git a/src/backend/access/nbtree/nbtutils.c b/src/backend/access/nbtree/nbtutils.c index 44980588a8..54cd7c8cd0 100644 --- a/src/backend/access/nbtree/nbtutils.c +++ b/src/backend/access/nbtree/nbtutils.c @@ -1,6 +1,6 @@ /*------------------------------------------------------------------------- * - * btutils.c + * nbtutils.c * Utility code for Postgres btree implementation. * * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtutils.c,v 1.54 2003/08/04 02:39:57 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtutils.c,v 1.55 2003/11/09 21:30:35 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -16,13 +16,10 @@ #include "postgres.h" #include "access/genam.h" -#include "access/istrat.h" #include "access/nbtree.h" #include "catalog/catalog.h" #include "executor/execdebug.h" - - -static int _bt_getstrategynumber(RegProcedure sk_procedure, StrategyMap map); +#include "utils/lsyscache.h" /* @@ -39,10 +36,6 @@ _bt_mkscankey(Relation rel, IndexTuple itup) TupleDesc itupdesc; int natts; int i; - FmgrInfo *procinfo; - Datum arg; - bool null; - bits16 flag; itupdesc = RelationGetDescr(rel); natts = RelationGetNumberOfAttributes(rel); @@ -51,15 +44,23 @@ _bt_mkscankey(Relation rel, IndexTuple itup) for (i = 0; i < natts; i++) { + FmgrInfo *procinfo; + Datum arg; + bool null; + + /* + * We can use the cached support procs since no cross-type comparison + * can be needed. + */ procinfo = index_getprocinfo(rel, i + 1, BTORDER_PROC); arg = index_getattr(itup, i + 1, itupdesc, &null); - flag = null ? SK_ISNULL : 0x0; ScanKeyEntryInitializeWithInfo(&skey[i], - flag, + null ? SK_ISNULL : 0, (AttrNumber) (i + 1), + InvalidStrategy, procinfo, - CurrentMemoryContext, - arg); + arg, + itupdesc->attrs[i]->atttypid); } return skey; @@ -68,33 +69,42 @@ _bt_mkscankey(Relation rel, IndexTuple itup) /* * _bt_mkscankey_nodata * Build a scan key that contains comparator routines appropriate to - * the key datatypes, but no comparison data. + * the key datatypes, but no comparison data. The comparison data + * ultimately used must match the key datatypes. * * The result cannot be used with _bt_compare(). Currently this - * routine is only called by utils/sort/tuplesort.c, which has its - * own comparison routine. + * routine is only called by nbtsort.c and tuplesort.c, which have + * their own comparison routines. */ ScanKey _bt_mkscankey_nodata(Relation rel) { ScanKey skey; + TupleDesc itupdesc; int natts; int i; - FmgrInfo *procinfo; + itupdesc = RelationGetDescr(rel); natts = RelationGetNumberOfAttributes(rel); skey = (ScanKey) palloc(natts * sizeof(ScanKeyData)); for (i = 0; i < natts; i++) { + FmgrInfo *procinfo; + + /* + * We can use the cached support procs since no cross-type comparison + * can be needed. + */ procinfo = index_getprocinfo(rel, i + 1, BTORDER_PROC); ScanKeyEntryInitializeWithInfo(&skey[i], SK_ISNULL, (AttrNumber) (i + 1), + InvalidStrategy, procinfo, - CurrentMemoryContext, - (Datum) 0); + (Datum) 0, + itupdesc->attrs[i]->atttypid); } return skey; @@ -185,17 +195,6 @@ _bt_formitem(IndexTuple itup) * The initial ordering of the keys is expected to be by attribute already * (see group_clauses_by_indexkey() in indxpath.c). The task here is to * standardize the appearance of multiple keys for the same attribute. - * - * XXX this routine is one of many places that fail to handle SK_COMMUTE - * scankeys properly. Currently, the planner is careful never to generate - * any indexquals that would require SK_COMMUTE to be set. Someday we ought - * to try to fix this, though it's not real critical as long as indexable - * operators all have commutators... - * - * Note: this routine invokes comparison operators via OidFunctionCallN, - * ie, without caching function lookups. No point in trying to be smarter, - * since these comparisons are executed only when the user expresses a - * hokey qualification, and happen only once per scan anyway. *---------- */ void @@ -208,7 +207,6 @@ _bt_orderkeys(IndexScanDesc scan) int numberOfKeys = so->numberOfKeys; ScanKey key; ScanKey cur; - StrategyMap map; Datum test; int i, j; @@ -229,6 +227,32 @@ _bt_orderkeys(IndexScanDesc scan) if (cur->sk_attno != 1) elog(ERROR, "key(s) for attribute 1 missed"); +#if 0 + /* XXX verify that operator strategy info is correct */ + /* XXX this is temporary for debugging; it's pretty expensive */ + /* XXX can't do it during bootstrap, else will recurse infinitely */ + { + extern bool criticalRelcachesBuilt; + static bool inRecursion = false; + + if (criticalRelcachesBuilt && !inRecursion) + { + inRecursion = true; + for (i = 0; i < numberOfKeys; i++) + { + AttrNumber attno = key[i].sk_attno; + Oid opclass; + Oid chk_oper; + + opclass = relation->rd_index->indclass[attno-1]; + chk_oper = get_opclass_member(opclass, key[i].sk_strategy); + Assert(key[i].sk_func.fn_oid == get_opcode(chk_oper)); + } + inRecursion = false; + } + } +#endif + /* We can short-circuit most of the work if there's just one key */ if (numberOfKeys == 1) { @@ -243,11 +267,7 @@ _bt_orderkeys(IndexScanDesc scan) relation->rd_rel->relnatts == 1) { /* it's a unique index, do we have an equality qual? */ - map = IndexStrategyGetStrategyMap(RelationGetIndexStrategy(relation), - BTMaxStrategyNumber, - 1); - j = _bt_getstrategynumber(cur->sk_procedure, map); - if (j == (BTEqualStrategyNumber - 1)) + if (cur->sk_strategy == BTEqualStrategyNumber) scan->keys_are_unique = true; } so->numberOfRequiredKeys = 1; @@ -267,9 +287,6 @@ _bt_orderkeys(IndexScanDesc scan) * any; init[i] is TRUE if we have found such a key for this attr. */ attno = 1; - map = IndexStrategyGetStrategyMap(RelationGetIndexStrategy(relation), - BTMaxStrategyNumber, - attno); MemSet(xform, 0, sizeof(xform)); /* not really necessary */ MemSet(init, 0, sizeof(init)); @@ -324,9 +341,9 @@ _bt_orderkeys(IndexScanDesc scan) j == (BTEqualStrategyNumber - 1)) continue; chk = &xform[j]; - test = OidFunctionCall2(chk->sk_procedure, - eq->sk_argument, - chk->sk_argument); + test = FunctionCall2(&chk->sk_func, + eq->sk_argument, + chk->sk_argument); if (!DatumGetBool(test)) so->qual_ok = false; } @@ -350,9 +367,9 @@ _bt_orderkeys(IndexScanDesc scan) ScanKeyData *lt = &xform[BTLessStrategyNumber - 1]; ScanKeyData *le = &xform[BTLessEqualStrategyNumber - 1]; - test = OidFunctionCall2(le->sk_procedure, - lt->sk_argument, - le->sk_argument); + test = FunctionCall2(&le->sk_func, + lt->sk_argument, + le->sk_argument); if (DatumGetBool(test)) init[BTLessEqualStrategyNumber - 1] = false; else @@ -366,9 +383,9 @@ _bt_orderkeys(IndexScanDesc scan) ScanKeyData *gt = &xform[BTGreaterStrategyNumber - 1]; ScanKeyData *ge = &xform[BTGreaterEqualStrategyNumber - 1]; - test = OidFunctionCall2(ge->sk_procedure, - gt->sk_argument, - ge->sk_argument); + test = FunctionCall2(&ge->sk_func, + gt->sk_argument, + ge->sk_argument); if (DatumGetBool(test)) init[BTGreaterEqualStrategyNumber - 1] = false; else @@ -404,15 +421,12 @@ _bt_orderkeys(IndexScanDesc scan) /* Re-initialize for new attno */ attno = cur->sk_attno; - map = IndexStrategyGetStrategyMap(RelationGetIndexStrategy(relation), - BTMaxStrategyNumber, - attno); MemSet(xform, 0, sizeof(xform)); /* not really necessary */ MemSet(init, 0, sizeof(init)); } /* figure out which strategy this key's operator corresponds to */ - j = _bt_getstrategynumber(cur->sk_procedure, map); + j = cur->sk_strategy - 1; /* have we seen one of these before? */ if (init[j]) @@ -447,25 +461,6 @@ _bt_orderkeys(IndexScanDesc scan) } /* - * Determine which btree strategy an operator procedure matches. - * - * Result is strategy number minus 1. - */ -static int -_bt_getstrategynumber(RegProcedure sk_procedure, StrategyMap map) -{ - int j; - - for (j = BTMaxStrategyNumber; --j >= 0;) - { - if (sk_procedure == map->entry[j].sk_procedure) - return j; - } - elog(ERROR, "could not identify operator %u", sk_procedure); - return -1; /* keep compiler quiet */ -} - -/* * Test whether an indextuple satisfies all the scankey conditions. * * If the tuple fails to pass the qual, we also determine whether there's @@ -533,14 +528,9 @@ _bt_checkkeys(IndexScanDesc scan, IndexTuple tuple, return false; } - if (key->sk_flags & SK_COMMUTE) - test = FunctionCall2(&key->sk_func, - key->sk_argument, datum); - else - test = FunctionCall2(&key->sk_func, - datum, key->sk_argument); + test = FunctionCall2(&key->sk_func, datum, key->sk_argument); - if (DatumGetBool(test) == !!(key->sk_flags & SK_NEGATE)) + if (!DatumGetBool(test)) { /* * Tuple fails this qual. If it's a required qual, then we diff --git a/src/backend/access/rtree/rtscan.c b/src/backend/access/rtree/rtscan.c index f3329448d9..263fff4bf2 100644 --- a/src/backend/access/rtree/rtscan.c +++ b/src/backend/access/rtree/rtscan.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/rtree/Attic/rtscan.c,v 1.47 2003/08/04 02:39:57 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/rtree/Attic/rtscan.c,v 1.48 2003/11/09 21:30:35 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -17,7 +17,7 @@ #include "access/genam.h" #include "access/rtree.h" - +#include "utils/lsyscache.h" /* routines defined and used here */ @@ -71,7 +71,6 @@ rtrescan(PG_FUNCTION_ARGS) IndexScanDesc s = (IndexScanDesc) PG_GETARG_POINTER(0); ScanKey key = (ScanKey) PG_GETARG_POINTER(1); RTreeScanOpaque p; - RegProcedure internal_proc; int i; /* @@ -116,14 +115,23 @@ rtrescan(PG_FUNCTION_ARGS) */ for (i = 0; i < s->numberOfKeys; i++) { - internal_proc = RTMapOperator(s->indexRelation, - s->keyData[i].sk_attno, - s->keyData[i].sk_procedure); + AttrNumber attno = s->keyData[i].sk_attno; + Oid opclass; + StrategyNumber int_strategy; + Oid int_oper; + RegProcedure int_proc; + + opclass = s->indexRelation->rd_index->indclass[attno-1]; + int_strategy = RTMapToInternalOperator(s->keyData[i].sk_strategy); + int_oper = get_opclass_member(opclass, int_strategy); + int_proc = get_opcode(int_oper); ScanKeyEntryInitialize(&(p->s_internalKey[i]), s->keyData[i].sk_flags, - s->keyData[i].sk_attno, - internal_proc, - s->keyData[i].sk_argument); + attno, + int_strategy, + int_proc, + s->keyData[i].sk_argument, + s->keyData[i].sk_argtype); } } diff --git a/src/backend/access/rtree/rtstrat.c b/src/backend/access/rtree/rtstrat.c index f7253a48e1..7d9097c8ea 100644 --- a/src/backend/access/rtree/rtstrat.c +++ b/src/backend/access/rtree/rtstrat.c @@ -8,176 +8,18 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/rtree/Attic/rtstrat.c,v 1.21 2003/08/04 02:39:57 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/rtree/Attic/rtstrat.c,v 1.22 2003/11/09 21:30:35 tgl Exp $ * *------------------------------------------------------------------------- */ #include "postgres.h" -#include "access/istrat.h" #include "access/rtree.h" -static StrategyNumber RelationGetRTStrategy(Relation r, - AttrNumber attnum, RegProcedure proc); /* - * Note: negate, commute, and negatecommute all assume that operators are - * ordered as follows in the strategy map: - * - * left, left-or-overlap, overlap, right-or-overlap, right, same, - * contains, contained-by - * - * The negate, commute, and negatecommute arrays are used by the planner - * to plan indexed scans over data that appears in the qualificiation in - * a boolean negation, or whose operands appear in the wrong order. For - * example, if the operator "<%" means "contains", and the user says - * - * where not rel.box <% "(10,10,20,20)"::box - * - * the planner can plan an index scan by noting that rtree indices have - * an operator in their operator class for negating <%. - * - * Similarly, if the user says something like - * - * where "(10,10,20,20)"::box <% rel.box - * - * the planner can see that the rtree index on rel.box has an operator in - * its opclass for commuting <%, and plan the scan using that operator. - * This added complexity in the access methods makes the planner a lot easier - * to write. - */ - -/* if a op b, what operator tells us if (not a op b)? */ -static StrategyNumber RTNegate[RTNStrategies] = { - InvalidStrategy, - InvalidStrategy, - InvalidStrategy, - InvalidStrategy, - InvalidStrategy, - InvalidStrategy, - InvalidStrategy, - InvalidStrategy -}; - -/* if a op_1 b, what is the operator op_2 such that b op_2 a? */ -static StrategyNumber RTCommute[RTNStrategies] = { - InvalidStrategy, - InvalidStrategy, - InvalidStrategy, - InvalidStrategy, - InvalidStrategy, - InvalidStrategy, - InvalidStrategy, - InvalidStrategy -}; - -/* if a op_1 b, what is the operator op_2 such that (b !op_2 a)? */ -static StrategyNumber RTNegateCommute[RTNStrategies] = { - InvalidStrategy, - InvalidStrategy, - InvalidStrategy, - InvalidStrategy, - InvalidStrategy, - InvalidStrategy, - InvalidStrategy, - InvalidStrategy -}; - -/* - * Now do the TermData arrays. These exist in case the user doesn't give - * us a full set of operators for a particular operator class. The idea - * is that by making multiple comparisons using any one of the supplied - * operators, we can decide whether two n-dimensional polygons are equal. - * For example, if a contains b and b contains a, we may conclude that - * a and b are equal. - * - * The presence of the TermData arrays in all this is a historical accident. - * Early in the development of the POSTGRES access methods, it was believed - * that writing functions was harder than writing arrays. This is wrong; - * TermData is hard to understand and hard to get right. In general, when - * someone populates a new operator class, they populate it completely. If - * Mike Hirohama had forced Cimarron Taylor to populate the strategy map - * for btree int2_ops completely in 1988, you wouldn't have to deal with - * all this now. Too bad for you. - * - * Since you can't necessarily do this in all cases (for example, you can't - * do it given only "intersects" or "disjoint"), TermData arrays for some - * operators don't appear below. - * - * Note that if you DO supply all the operators required in a given opclass - * by inserting them into the pg_opclass system catalog, you can get away - * without doing all this TermData stuff. Since the rtree code is intended - * to be a reference for access method implementors, I'm doing TermData - * correctly here. - * - * Note on style: these are all actually of type StrategyTermData, but - * since those have variable-length data at the end of the struct we can't - * properly initialize them if we declare them to be what they are. - */ - -/* if you only have "contained-by", how do you determine equality? */ -static uint16 RTContainedByTermData[] = { - 2, /* make two comparisons */ - RTContainedByStrategyNumber, /* use "a contained-by b" */ - 0x0, /* without any magic */ - RTContainedByStrategyNumber, /* then use contained-by, */ - SK_COMMUTE /* swapping a and b */ -}; - -/* if you only have "contains", how do you determine equality? */ -static uint16 RTContainsTermData[] = { - 2, /* make two comparisons */ - RTContainsStrategyNumber, /* use "a contains b" */ - 0x0, /* without any magic */ - RTContainsStrategyNumber, /* then use contains again, */ - SK_COMMUTE /* swapping a and b */ -}; - -/* now put all that together in one place for the planner */ -static StrategyTerm RTEqualExpressionData[] = { - (StrategyTerm) RTContainedByTermData, - (StrategyTerm) RTContainsTermData, - NULL -}; - -/* - * If you were sufficiently attentive to detail, you would go through - * the ExpressionData pain above for every one of the seven strategies - * we defined. I am not. Now we declare the StrategyEvaluationData - * structure that gets shipped around to help the planner and the access - * method decide what sort of scan it should do, based on (a) what the - * user asked for, (b) what operators are defined for a particular opclass, - * and (c) the reams of information we supplied above. - * - * The idea of all of this initialized data is to make life easier on the - * user when he defines a new operator class to use this access method. - * By filling in all the data, we let him get away with leaving holes in his - * operator class, and still let him use the index. The added complexity - * in the access methods just isn't worth the trouble, though. - */ - -static StrategyExpression RTEvaluationExpressions[RTNStrategies] = { - NULL, /* express left */ - NULL, /* express overleft */ - NULL, /* express overlap */ - NULL, /* express overright */ - NULL, /* express right */ - (StrategyExpression) RTEqualExpressionData, /* express same */ - NULL, /* express contains */ - NULL /* express contained-by */ -}; - -static StrategyEvaluationData RTEvaluationData = { - RTNStrategies, /* # of strategies */ - (StrategyTransformMap) RTNegate, /* how to do (not qual) */ - (StrategyTransformMap) RTCommute, /* how to swap operands */ - (StrategyTransformMap) RTNegateCommute, /* how to do both */ - RTEvaluationExpressions -}; - -/* - * Okay, now something peculiar to rtrees that doesn't apply to most other + * Here's something peculiar to rtrees that doesn't apply to most other * indexing structures: When we're searching a tree for a given value, we * can't do the same sorts of comparisons on internal node entries as we * do at leaves. The reason is that if we're looking for (say) all boxes @@ -191,7 +33,7 @@ static StrategyEvaluationData RTEvaluationData = { * left, left-or-overlap, overlap, right-or-overlap, right, same, * contains, contained-by */ -static StrategyNumber RTOperMap[RTNStrategies] = { +static const StrategyNumber RTOperMap[RTNStrategies] = { RTOverLeftStrategyNumber, RTOverLeftStrategyNumber, RTOverlapStrategyNumber, @@ -202,39 +44,10 @@ static StrategyNumber RTOperMap[RTNStrategies] = { RTOverlapStrategyNumber }; -static StrategyNumber -RelationGetRTStrategy(Relation r, - AttrNumber attnum, - RegProcedure proc) -{ - return RelationGetStrategy(r, attnum, &RTEvaluationData, proc); -} -#ifdef NOT_USED -bool -RelationInvokeRTStrategy(Relation r, - AttrNumber attnum, - StrategyNumber s, - Datum left, - Datum right) +StrategyNumber +RTMapToInternalOperator(StrategyNumber strat) { - return (RelationInvokeStrategy(r, &RTEvaluationData, attnum, s, - left, right)); -} -#endif - -RegProcedure -RTMapOperator(Relation r, - AttrNumber attnum, - RegProcedure proc) -{ - StrategyNumber procstrat; - StrategyMap strategyMap; - - procstrat = RelationGetRTStrategy(r, attnum, proc); - strategyMap = IndexStrategyGetStrategyMap(RelationGetIndexStrategy(r), - RTNStrategies, - attnum); - - return strategyMap->entry[RTOperMap[procstrat - 1] - 1].sk_procedure; + Assert(strat > 0 && strat <= RTNStrategies); + return RTOperMap[strat - 1]; } |