From: Tom Lane Date: Wed, 12 Nov 2003 21:15:59 +0000 (+0000) Subject: Cross-data-type comparisons are now indexable by btrees, pursuant to my X-Git-Tag: REL8_0_0BETA1~1710 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=fa5c8a055a02e44f446e4593e397c33a572c4d67;p=postgresql Cross-data-type comparisons are now indexable by btrees, pursuant to my pghackers proposal of 8-Nov. All the existing cross-type comparison operators (int2/int4/int8 and float4/float8) have appropriate support. The original proposal of storing the right-hand-side datatype as part of the primary key for pg_amop and pg_amproc got modified a bit in the event; it is easier to store zero as the 'default' case and only store a nonzero when the operator is actually cross-type. Along the way, remove the long-since-defunct bigbox_ops operator class. --- diff --git a/contrib/dblink/dblink.c b/contrib/dblink/dblink.c index 5728682ccc..bb601c5436 100644 --- a/contrib/dblink/dblink.c +++ b/contrib/dblink/dblink.c @@ -1357,10 +1357,10 @@ get_pkey_attnames(Oid relid, int16 *numatts) /* use relid to get all related indexes */ indexRelation = heap_openr(IndexRelationName, AccessShareLock); - ScanKeyEntryInitialize(&entry, 0, - Anum_pg_index_indrelid, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(relid), OIDOID); + ScanKeyInit(&entry, + Anum_pg_index_indrelid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(relid)); scan = heap_beginscan(indexRelation, SnapshotNow, 1, &entry); while ((indexTuple = heap_getnext(scan, ForwardScanDirection)) != NULL) diff --git a/contrib/miscutil/misc_utils.c b/contrib/miscutil/misc_utils.c index bf84f3b3c2..fb121e8380 100644 --- a/contrib/miscutil/misc_utils.c +++ b/contrib/miscutil/misc_utils.c @@ -21,7 +21,6 @@ #include "access/tupdesc.h" #include "catalog/catname.h" #include "catalog/pg_listener.h" -#include "catalog/pg_type.h" #include "commands/async.h" #include "fmgr.h" #include "storage/lmgr.h" @@ -87,10 +86,10 @@ active_listeners(text *relname) MemSet(listen_name, 0, NAMEDATALEN); len = MIN(VARSIZE(relname) - VARHDRSZ, NAMEDATALEN - 1); memcpy(listen_name, VARDATA(relname), len); - ScanKeyEntryInitialize(&key, 0, - Anum_pg_listener_relname, - BTEqualStrategyNumber, F_NAMEEQ, - PointerGetDatum(listen_name), NAMEOID); + ScanKeyInit(&key, + Anum_pg_listener_relname, + BTEqualStrategyNumber, F_NAMEEQ, + PointerGetDatum(listen_name)); sRel = heap_beginscan(lRel, SnapshotNow, 1, &key); } else diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml index bd208906df..37f8b9cd65 100644 --- a/doc/src/sgml/catalogs.sgml +++ b/doc/src/sgml/catalogs.sgml @@ -1,6 +1,6 @@ @@ -499,6 +499,14 @@ The index operator class this entry is for + + amopsubtype + oid + pg_type.oid + Subtype to distinguish multiple entries for one strategy; + zero for default + + amopstrategy int2 @@ -562,6 +570,13 @@ The index operator class this entry is for + + amprocsubtype + oid + pg_type.oid + Subtype, if cross-type routine, else zero + + amprocnum int2 @@ -2435,7 +2450,7 @@ opcintype oid pg_type.oid - Input data type of the operator class + Data type that the operator class indexes @@ -2449,7 +2464,7 @@ opckeytype oid pg_type.oid - Type of index data, or zero if same as opcintype + Type of data stored in index, or zero if same as opcintype diff --git a/doc/src/sgml/xindex.sgml b/doc/src/sgml/xindex.sgml index 85aba8abe7..877709cee6 100644 --- a/doc/src/sgml/xindex.sgml +++ b/doc/src/sgml/xindex.sgml @@ -1,5 +1,5 @@ @@ -80,7 +80,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/xindex.sgml,v 1.34 2003/11/01 01:56:29 pete The same operator class name can be used for several different index methods (for example, both B-tree and hash index methods have operator classes named - oid_ops), but each such class is an independent + int4_ops), but each such class is an independent entity and must be defined separately. @@ -589,6 +589,71 @@ CREATE OPERATOR CLASS complex_abs_ops + + Cross-Data-Type Operator Classes + + + So far we have implicitly assumed that an operator class deals with + only one data type. While there certainly can be only one data type in + a particular index column, it is often useful to index operations that + compare an indexed column to a value of a different data type. This is + presently supported by the B-tree and GiST index methods. + + + + B-trees require the left-hand operand of each operator to be the indexed + data type, but the right-hand operand can be of a different type. There + must be a support function having a matching signature. For example, + the built-in operator class for type bigint (int8) + allows cross-type comparisons to int4 and int2. It + could be duplicated by this definition: + + +CREATE OPERATOR CLASS int8_ops +DEFAULT FOR TYPE int8 USING btree AS + -- standard int8 comparisons + OPERATOR 1 < , + OPERATOR 2 <= , + OPERATOR 3 = , + OPERATOR 4 >= , + OPERATOR 5 > , + FUNCTION 1 btint8cmp(int8, int8) , + + -- cross-type comparisons to int2 (smallint) + OPERATOR 1 < (int8, int2) , + OPERATOR 2 <= (int8, int2) , + OPERATOR 3 = (int8, int2) , + OPERATOR 4 >= (int8, int2) , + OPERATOR 5 > (int8, int2) , + FUNCTION 1 btint82cmp(int8, int2) , + + -- cross-type comparisons to int4 (integer) + OPERATOR 1 < (int8, int4) , + OPERATOR 2 <= (int8, int4) , + OPERATOR 3 = (int8, int4) , + OPERATOR 4 >= (int8, int4) , + OPERATOR 5 > (int8, int4) , + FUNCTION 1 btint84cmp(int8, int4) ; + + + Notice that this definition overloads the operator strategy and + support function numbers. This is allowed (for B-tree operator classes + only) so long as each instance of a particular number has a different + right-hand data type. The instances that are not cross-type are the + default or primary operators of the operator class. + + + + GiST indexes do not allow overloading of strategy or support function + numbers, but it is still possible to get the effect of supporting + multiple right-hand data types, by assigning a distinct strategy number + to each operator that needs to be supported. The consistent + support function must determine what it needs to do based on the strategy + number, and must be prepared to accept comparison values of the appropriate + data types. + + + System Dependencies on Operator Classes diff --git a/src/backend/access/common/scankey.c b/src/backend/access/common/scankey.c index 93741cbb84..2fa02b7d91 100644 --- a/src/backend/access/common/scankey.c +++ b/src/backend/access/common/scankey.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/common/scankey.c,v 1.23 2003/11/09 21:30:35 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/common/scankey.c,v 1.24 2003/11/12 21:15:46 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -31,15 +31,43 @@ ScanKeyEntryInitialize(ScanKey entry, int flags, AttrNumber attributeNumber, StrategyNumber strategy, + Oid subtype, RegProcedure procedure, - Datum argument, - Oid argtype) + Datum argument) { entry->sk_flags = flags; entry->sk_attno = attributeNumber; entry->sk_strategy = strategy; + entry->sk_subtype = subtype; + entry->sk_argument = argument; + fmgr_info(procedure, &entry->sk_func); +} + +/* + * ScanKeyInit + * Shorthand version of ScanKeyEntryInitialize: flags and subtype + * are assumed to be zero (the usual value). + * + * This is the recommended version for hardwired lookups in system catalogs. + * It cannot handle NULL arguments, unary operators, or nondefault operators, + * but we need none of those features for most hardwired lookups. + * + * 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 +ScanKeyInit(ScanKey entry, + AttrNumber attributeNumber, + StrategyNumber strategy, + RegProcedure procedure, + Datum argument) +{ + entry->sk_flags = 0; + entry->sk_attno = attributeNumber; + entry->sk_strategy = strategy; + entry->sk_subtype = InvalidOid; entry->sk_argument = argument; - entry->sk_argtype = argtype; fmgr_info(procedure, &entry->sk_func); } @@ -57,14 +85,14 @@ ScanKeyEntryInitializeWithInfo(ScanKey entry, int flags, AttrNumber attributeNumber, StrategyNumber strategy, + Oid subtype, FmgrInfo *finfo, - Datum argument, - Oid argtype) + Datum argument) { entry->sk_flags = flags; entry->sk_attno = attributeNumber; entry->sk_strategy = strategy; + entry->sk_subtype = subtype; entry->sk_argument = argument; - entry->sk_argtype = argtype; fmgr_info_copy(&entry->sk_func, finfo, CurrentMemoryContext); } diff --git a/src/backend/access/gist/gistget.c b/src/backend/access/gist/gistget.c index 24168c9926..5db69a6b40 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.37 2003/11/09 21:30:35 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/gist/gistget.c,v 1.38 2003/11/12 21:15:46 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -221,40 +221,50 @@ gistindex_keytest(IndexTuple tuple, Page p, OffsetNumber offset) { - bool isNull; - Datum datum; - Datum test; - GISTENTRY de; - IncrIndexProcessed(); while (scanKeySize > 0) { + Datum datum; + bool isNull; + Datum test; + GISTENTRY de; + datum = index_getattr(tuple, - key[0].sk_attno, + key->sk_attno, giststate->tupdesc, &isNull); + /* is the index entry NULL? */ if (isNull) { /* XXX eventually should check if SK_ISNULL */ return false; } - -/* this code from backend/access/common/indexvalid.c. But why and what??? - if (key[0].sk_flags & SK_ISNULL) + /* is the compared-to datum NULL? */ + if (key->sk_flags & SK_ISNULL) return false; -*/ - gistdentryinit(giststate, key[0].sk_attno - 1, &de, + + gistdentryinit(giststate, key->sk_attno - 1, &de, datum, r, p, offset, IndexTupleSize(tuple) - sizeof(IndexTupleData), FALSE, isNull); - test = FunctionCall3(&key[0].sk_func, + /* + * Call the Consistent function to evaluate the test. The arguments + * are the index datum (as a GISTENTRY*), the comparison datum, and + * the comparison operator's strategy number and subtype from pg_amop. + * + * (Presently there's no need to pass the subtype since it'll always + * be zero, but might as well pass it for possible future use.) + */ + test = FunctionCall4(&key->sk_func, PointerGetDatum(&de), - key[0].sk_argument, - Int32GetDatum(key[0].sk_strategy)); + key->sk_argument, + Int32GetDatum(key->sk_strategy), + ObjectIdGetDatum(key->sk_subtype)); - if (de.key != datum && !isAttByVal(giststate, key[0].sk_attno - 1)) + /* if index datum had to be decompressed, free it */ + if (de.key != datum && !isAttByVal(giststate, key->sk_attno - 1)) if (DatumGetPointer(de.key) != NULL) pfree(DatumGetPointer(de.key)); @@ -264,6 +274,7 @@ gistindex_keytest(IndexTuple tuple, scanKeySize--; key++; } + return true; } diff --git a/src/backend/access/gist/gistscan.c b/src/backend/access/gist/gistscan.c index 960d1c2f25..9b9d1f6034 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.48 2003/11/09 21:30:35 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/gist/gistscan.c,v 1.49 2003/11/12 21:15:46 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -109,7 +109,8 @@ gistrescan(PG_FUNCTION_ARGS) * 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. + * is available from the sk_strategy field, and its subtype from + * the sk_subtype field. */ for (i = 0; i < s->numberOfKeys; i++) { diff --git a/src/backend/access/heap/tuptoaster.c b/src/backend/access/heap/tuptoaster.c index 0bfe3c01b8..f643906da1 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.39 2003/11/09 21:30:35 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/heap/tuptoaster.c,v 1.40 2003/11/12 21:15:46 tgl Exp $ * * * INTERFACE ROUTINES @@ -31,7 +31,6 @@ #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" @@ -968,11 +967,10 @@ 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, 0, - (AttrNumber) 1, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(attr->va_content.va_external.va_valueid), - OIDOID); + ScanKeyInit(&toastkey, + (AttrNumber) 1, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(attr->va_content.va_external.va_valueid)); /* * Find the chunks by index @@ -1040,11 +1038,10 @@ toast_fetch_datum(varattrib *attr) /* * Setup a scan key to fetch from the index by va_valueid */ - ScanKeyEntryInitialize(&toastkey, 0, - (AttrNumber) 1, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(attr->va_content.va_external.va_valueid), - OIDOID); + ScanKeyInit(&toastkey, + (AttrNumber) 1, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(attr->va_content.va_external.va_valueid)); /* * Read the chunks by index @@ -1195,33 +1192,32 @@ 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], 0, - (AttrNumber) 1, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(attr->va_content.va_external.va_valueid), - OIDOID); + ScanKeyInit(&toastkey[0], + (AttrNumber) 1, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(attr->va_content.va_external.va_valueid)); /* * Use equality condition for one chunk, a range condition otherwise: */ if (numchunks == 1) { - ScanKeyEntryInitialize(&toastkey[1], 0, - (AttrNumber) 2, - BTEqualStrategyNumber, F_INT4EQ, - Int32GetDatum(startchunk), INT4OID); + ScanKeyInit(&toastkey[1], + (AttrNumber) 2, + BTEqualStrategyNumber, F_INT4EQ, + Int32GetDatum(startchunk)); nscankeys = 2; } else { - ScanKeyEntryInitialize(&toastkey[1], 0, - (AttrNumber) 2, - BTGreaterEqualStrategyNumber, F_INT4GE, - Int32GetDatum(startchunk), INT4OID); - ScanKeyEntryInitialize(&toastkey[2], 0, - (AttrNumber) 2, - BTLessEqualStrategyNumber, F_INT4LE, - Int32GetDatum(endchunk), INT4OID); + ScanKeyInit(&toastkey[1], + (AttrNumber) 2, + BTGreaterEqualStrategyNumber, F_INT4GE, + Int32GetDatum(startchunk)); + ScanKeyInit(&toastkey[2], + (AttrNumber) 2, + BTLessEqualStrategyNumber, F_INT4LE, + Int32GetDatum(endchunk)); nscankeys = 3; } diff --git a/src/backend/access/nbtree/nbtcompare.c b/src/backend/access/nbtree/nbtcompare.c index 79756513ab..bd69885830 100644 --- a/src/backend/access/nbtree/nbtcompare.c +++ b/src/backend/access/nbtree/nbtcompare.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtcompare.c,v 1.46 2003/08/04 02:39:57 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtcompare.c,v 1.47 2003/11/12 21:15:46 tgl Exp $ * * NOTES * @@ -97,6 +97,90 @@ btint8cmp(PG_FUNCTION_ARGS) PG_RETURN_INT32(-1); } +Datum +btint48cmp(PG_FUNCTION_ARGS) +{ + int32 a = PG_GETARG_INT32(0); + int64 b = PG_GETARG_INT64(1); + + if (a > b) + PG_RETURN_INT32(1); + else if (a == b) + PG_RETURN_INT32(0); + else + PG_RETURN_INT32(-1); +} + +Datum +btint84cmp(PG_FUNCTION_ARGS) +{ + int64 a = PG_GETARG_INT64(0); + int32 b = PG_GETARG_INT32(1); + + if (a > b) + PG_RETURN_INT32(1); + else if (a == b) + PG_RETURN_INT32(0); + else + PG_RETURN_INT32(-1); +} + +Datum +btint24cmp(PG_FUNCTION_ARGS) +{ + int16 a = PG_GETARG_INT16(0); + int32 b = PG_GETARG_INT32(1); + + if (a > b) + PG_RETURN_INT32(1); + else if (a == b) + PG_RETURN_INT32(0); + else + PG_RETURN_INT32(-1); +} + +Datum +btint42cmp(PG_FUNCTION_ARGS) +{ + int32 a = PG_GETARG_INT32(0); + int16 b = PG_GETARG_INT16(1); + + if (a > b) + PG_RETURN_INT32(1); + else if (a == b) + PG_RETURN_INT32(0); + else + PG_RETURN_INT32(-1); +} + +Datum +btint28cmp(PG_FUNCTION_ARGS) +{ + int16 a = PG_GETARG_INT16(0); + int64 b = PG_GETARG_INT64(1); + + if (a > b) + PG_RETURN_INT32(1); + else if (a == b) + PG_RETURN_INT32(0); + else + PG_RETURN_INT32(-1); +} + +Datum +btint82cmp(PG_FUNCTION_ARGS) +{ + int64 a = PG_GETARG_INT64(0); + int16 b = PG_GETARG_INT16(1); + + if (a > b) + PG_RETURN_INT32(1); + else if (a == b) + PG_RETURN_INT32(0); + else + PG_RETURN_INT32(-1); +} + Datum btoidcmp(PG_FUNCTION_ARGS) { diff --git a/src/backend/access/nbtree/nbtinsert.c b/src/backend/access/nbtree/nbtinsert.c index 98f3abb511..719b1e1f0e 100644 --- a/src/backend/access/nbtree/nbtinsert.c +++ b/src/backend/access/nbtree/nbtinsert.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.107 2003/11/09 21:30:35 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.108 2003/11/12 21:15:46 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1577,26 +1577,27 @@ _bt_isequal(TupleDesc itupdesc, Page page, OffsetNumber offnum, for (i = 1; i <= keysz; i++) { - ScanKey entry = &scankey[i - 1]; AttrNumber attno; Datum datum; bool isNull; int32 result; - attno = entry->sk_attno; + attno = scankey->sk_attno; Assert(attno == i); datum = index_getattr(itup, attno, itupdesc, &isNull); /* NULLs are never equal to anything */ - if ((entry->sk_flags & SK_ISNULL) || isNull) + if (isNull || (scankey->sk_flags & SK_ISNULL)) return false; - result = DatumGetInt32(FunctionCall2(&entry->sk_func, - entry->sk_argument, - datum)); + result = DatumGetInt32(FunctionCall2(&scankey->sk_func, + datum, + scankey->sk_argument)); if (result != 0) return false; + + scankey++; } /* if we get here, the keys are equal */ diff --git a/src/backend/access/nbtree/nbtree.c b/src/backend/access/nbtree/nbtree.c index 3979f79c35..f920d2497e 100644 --- a/src/backend/access/nbtree/nbtree.c +++ b/src/backend/access/nbtree/nbtree.c @@ -12,7 +12,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtree.c,v 1.106 2003/09/29 23:40:26 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtree.c,v 1.107 2003/11/12 21:15:46 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -397,7 +397,6 @@ btrescan(PG_FUNCTION_ARGS) so->keyData = (ScanKey) palloc(scan->numberOfKeys * sizeof(ScanKeyData)); else so->keyData = (ScanKey) NULL; - so->numberOfKeys = scan->numberOfKeys; scan->opaque = so; } @@ -423,38 +422,14 @@ btrescan(PG_FUNCTION_ARGS) * _bt_first. - vadim 05/05/97 */ if (scankey && scan->numberOfKeys > 0) - { memmove(scan->keyData, scankey, scan->numberOfKeys * sizeof(ScanKeyData)); - so->numberOfKeys = scan->numberOfKeys; - memmove(so->keyData, - scankey, - so->numberOfKeys * sizeof(ScanKeyData)); - } + so->numberOfKeys = 0; /* until _bt_preprocess_keys sets it */ PG_RETURN_VOID(); } -void -btmovescan(IndexScanDesc scan, Datum v) -{ - ItemPointer iptr; - BTScanOpaque so; - - so = (BTScanOpaque) scan->opaque; - - /* we aren't holding any read locks, but gotta drop the pin */ - if (ItemPointerIsValid(iptr = &(scan->currentItemData))) - { - ReleaseBuffer(so->btso_curbuf); - so->btso_curbuf = InvalidBuffer; - ItemPointerSetInvalid(iptr); - } - - so->keyData[0].sk_argument = v; -} - /* * btendscan() -- close down a scan */ diff --git a/src/backend/access/nbtree/nbtsearch.c b/src/backend/access/nbtree/nbtsearch.c index 432a1ab0c2..87178d1242 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.81 2003/11/09 21:30:35 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtsearch.c,v 1.82 2003/11/12 21:15:47 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -17,6 +17,7 @@ #include "access/genam.h" #include "access/nbtree.h" +#include "utils/lsyscache.h" static Buffer _bt_walk_left(Relation rel, Buffer buf); @@ -325,17 +326,16 @@ _bt_compare(Relation rel, * (see _bt_first). */ - for (i = 0; i < keysz; i++) + for (i = 1; i <= keysz; i++) { - ScanKey entry = &scankey[i]; Datum datum; bool isNull; int32 result; - datum = index_getattr(itup, entry->sk_attno, itupdesc, &isNull); + datum = index_getattr(itup, scankey->sk_attno, itupdesc, &isNull); /* see comments about NULLs handling in btbuild */ - if (entry->sk_flags & SK_ISNULL) /* key is NULL */ + if (scankey->sk_flags & SK_ISNULL) /* key is NULL */ { if (isNull) result = 0; /* NULL "=" NULL */ @@ -348,14 +348,28 @@ _bt_compare(Relation rel, } else { - result = DatumGetInt32(FunctionCall2(&entry->sk_func, - entry->sk_argument, - datum)); + /* + * The sk_func needs to be passed the index value as left arg + * and the sk_argument as right arg (they might be of different + * types). Since it is convenient for callers to think of + * _bt_compare as comparing the scankey to the index item, + * we have to flip the sign of the comparison result. + * + * Note: curious-looking coding is to avoid overflow if + * comparison function returns INT_MIN. There is no risk of + * overflow for positive results. + */ + result = DatumGetInt32(FunctionCall2(&scankey->sk_func, + datum, + scankey->sk_argument)); + result = (result < 0) ? 1 : -result; } /* if the keys are unequal, return the difference */ if (result != 0) return result; + + scankey++; } /* if we get here, the keys are equal */ @@ -448,126 +462,203 @@ _bt_first(IndexScanDesc scan, ScanDirection dir) StrategyNumber strat; bool res; int32 result; - bool scanFromEnd; bool continuescan; ScanKey scankeys = NULL; + ScanKey *startKeys = NULL; int keysCount = 0; - int *nKeyIs = NULL; - int i, - j; + int i; StrategyNumber strat_total; /* - * Order the scan keys in our canonical fashion and eliminate any - * redundant keys. + * Examine the scan keys and eliminate any redundant keys; also + * discover how many keys must be matched to continue the scan. */ - _bt_orderkeys(scan); + _bt_preprocess_keys(scan); /* - * Quit now if _bt_orderkeys() discovered that the scan keys can never - * be satisfied (eg, x == 1 AND x > 2). + * Quit now if _bt_preprocess_keys() discovered that the scan keys can + * never be satisfied (eg, x == 1 AND x > 2). */ if (!so->qual_ok) return false; - /* + /*---------- * Examine the scan keys to discover where we need to start the scan. + * + * We want to identify the keys that can be used as starting boundaries; + * these are =, >, or >= keys for a forward scan or =, <, <= keys for + * a backwards scan. We can use keys for multiple attributes so long as + * the prior attributes had only =, >= (resp. =, <=) keys. Once we accept + * a > or < boundary or find an attribute with no boundary (which can be + * thought of as the same as "> -infinity"), we can't use keys for any + * attributes to its right, because it would break our simplistic notion + * of what initial positioning strategy to use. + * + * When the scan keys include non-default operators, _bt_preprocess_keys + * may not be able to eliminate redundant keys; in such cases we will + * arbitrarily pick a usable one for each attribute. This is correct + * but possibly not optimal behavior. (For example, with keys like + * "x >= 4 AND x >= 5" we would elect to scan starting at x=4 when + * x=5 would be more efficient.) Since the situation only arises in + * hokily-worded queries, live with it. + * + * When both equality and inequality keys appear for a single attribute + * (again, only possible when non-default operators appear), we *must* + * select one of the equality keys for the starting point, because + * _bt_checkkeys() will stop the scan as soon as an equality qual fails. + * For example, if we have keys like "x >= 4 AND x = 10" and we elect to + * start at x=4, we will fail and stop before reaching x=10. If multiple + * equality quals survive preprocessing, however, it doesn't matter which + * one we use --- by definition, they are either redundant or + * contradictory. + *---------- */ - scanFromEnd = false; strat_total = BTEqualStrategyNumber; if (so->numberOfKeys > 0) { - nKeyIs = (int *) palloc(so->numberOfKeys * sizeof(int)); - for (i = 0; i < so->numberOfKeys; i++) - { - AttrNumber attno = so->keyData[i].sk_attno; - - /* ignore keys for already-determined attrs */ - if (attno <= keysCount) - continue; - /* if we didn't find a boundary for the preceding attr, quit */ - if (attno > keysCount + 1) - break; + AttrNumber curattr; + ScanKey chosen; + ScanKey cur; - /* - * Can we use this key as a starting boundary for this attr? - * - * 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; - else if (ScanDirectionIsBackward(dir) && - (strat == BTLessStrategyNumber || - strat == BTLessEqualStrategyNumber)) + startKeys = (ScanKey *) palloc(so->numberOfKeys * sizeof(ScanKey)); + /* + * chosen is the so-far-chosen key for the current attribute, if any. + * We don't cast the decision in stone until we reach keys for the + * next attribute. + */ + curattr = 1; + chosen = NULL; + /* + * Loop iterates from 0 to numberOfKeys inclusive; we use the last + * pass to handle after-last-key processing. Actual exit from the + * loop is at one of the "break" statements below. + */ + for (cur = so->keyData, i = 0;; cur++, i++) + { + if (i >= so->numberOfKeys || cur->sk_attno != curattr) { - nKeyIs[keysCount++] = i; - strat_total = strat; - if (strat == BTLessStrategyNumber) + /* + * Done looking at keys for curattr. If we didn't find a + * usable boundary key, quit; else save the boundary key + * pointer in startKeys. + */ + if (chosen == NULL) + break; + startKeys[keysCount++] = chosen; + /* + * Adjust strat_total, and quit if we have stored a > or < key. + */ + strat = chosen->sk_strategy; + if (strat != BTEqualStrategyNumber) + { + strat_total = strat; + if (strat == BTGreaterStrategyNumber || + strat == BTLessStrategyNumber) + break; + } + /* + * Done if that was the last attribute. + */ + if (i >= so->numberOfKeys) break; + /* + * Reset for next attr, which should be in sequence. + */ + Assert(cur->sk_attno == curattr + 1); + curattr = cur->sk_attno; + chosen = NULL; } - else if (ScanDirectionIsForward(dir) && - (strat == BTGreaterStrategyNumber || - strat == BTGreaterEqualStrategyNumber)) + + /* Can we use this key as a starting boundary for this attr? */ + switch (cur->sk_strategy) { - nKeyIs[keysCount++] = i; - strat_total = strat; - if (strat == BTGreaterStrategyNumber) + case BTLessStrategyNumber: + case BTLessEqualStrategyNumber: + if (chosen == NULL && ScanDirectionIsBackward(dir)) + chosen = cur; + break; + case BTEqualStrategyNumber: + /* override any non-equality choice */ + chosen = cur; + break; + case BTGreaterEqualStrategyNumber: + case BTGreaterStrategyNumber: + if (chosen == NULL && ScanDirectionIsForward(dir)) + chosen = cur; break; } } - if (keysCount == 0) - scanFromEnd = true; } - else - scanFromEnd = true; - /* if we just need to walk down one edge of the tree, do that */ - if (scanFromEnd) + /* + * If we found no usable boundary keys, we have to start from one end + * of the tree. Walk down that edge to the first or last key, and + * scan from there. + */ + if (keysCount == 0) { - if (nKeyIs) - pfree(nKeyIs); + if (startKeys) + pfree(startKeys); return _bt_endpoint(scan, dir); } /* * We want to start the scan somewhere within the index. Set up a - * scankey we can use to search for the correct starting point. + * 3-way-comparison scankey we can use to search for the boundary + * point we identified above. */ scankeys = (ScanKey) palloc(keysCount * sizeof(ScanKeyData)); for (i = 0; i < keysCount; i++) { - FmgrInfo *procinfo; - - j = nKeyIs[i]; + ScanKey cur = startKeys[i]; /* - * _bt_orderkeys disallows it, but it's place to add some code + * _bt_preprocess_keys disallows it, but it's place to add some code * later */ - if (so->keyData[j].sk_flags & SK_ISNULL) + if (cur->sk_flags & SK_ISNULL) { - pfree(nKeyIs); + pfree(startKeys); pfree(scankeys); elog(ERROR, "btree doesn't support is(not)null, yet"); return false; } /* - * XXX what if sk_argtype is not same as index? + * If scankey operator is of default subtype, we can use the + * cached comparison procedure; otherwise gotta look it up in + * the catalogs. */ - procinfo = index_getprocinfo(rel, i + 1, BTORDER_PROC); - ScanKeyEntryInitializeWithInfo(scankeys + i, - so->keyData[j].sk_flags, - i + 1, - InvalidStrategy, - procinfo, - so->keyData[j].sk_argument, - so->keyData[j].sk_argtype); + if (cur->sk_subtype == InvalidOid) + { + FmgrInfo *procinfo; + + procinfo = index_getprocinfo(rel, i + 1, BTORDER_PROC); + ScanKeyEntryInitializeWithInfo(scankeys + i, + cur->sk_flags, + i + 1, + InvalidStrategy, + InvalidOid, + procinfo, + cur->sk_argument); + } + else + { + RegProcedure cmp_proc; + + cmp_proc = get_opclass_proc(rel->rd_index->indclass[i], + cur->sk_subtype, + BTORDER_PROC); + ScanKeyEntryInitialize(scankeys + i, + cur->sk_flags, + i + 1, + InvalidStrategy, + cur->sk_subtype, + cmp_proc, + cur->sk_argument); + } } - if (nKeyIs) - pfree(nKeyIs); + + pfree(startKeys); current = &(scan->currentItemData); @@ -607,7 +698,8 @@ _bt_first(IndexScanDesc scan, ScanDirection dir) * * We could step forward in the latter case, but that'd be a waste of * time if we want to scan backwards. So, it's now time to examine - * the scan strategy to find the exact place to start the scan. + * the initial-positioning strategy to find the exact place to start + * the scan. * * Note: if _bt_step fails (meaning we fell off the end of the index in * one direction or the other), we either return false (no matches) or @@ -855,8 +947,8 @@ _bt_step(IndexScanDesc scan, Buffer *bufP, ScanDirection dir) } } else -/* backwards scan */ { + /* backwards scan */ if (offnum > P_FIRSTDATAKEY(opaque)) offnum = OffsetNumberPrev(offnum); else @@ -1115,7 +1207,8 @@ _bt_get_endpoint(Relation rel, uint32 level, bool rightmost) } /* - * _bt_endpoint() -- Find the first or last key in the index. + * _bt_endpoint() -- Find the first or last key in the index, and scan + * from there to the first key satisfying all the quals. * * This is used by _bt_first() to set up a scan when we've determined * that the scan must start at the beginning or end of the index (for @@ -1205,7 +1298,9 @@ _bt_endpoint(IndexScanDesc scan, ScanDirection dir) btitem = (BTItem) PageGetItem(page, PageGetItemId(page, start)); itup = &(btitem->bti_itup); - /* see if we picked a winner */ + /* + * Okay, we are on the first or last tuple. Does it pass all the quals? + */ if (_bt_checkkeys(scan, itup, dir, &continuescan)) { /* yes, return it */ @@ -1214,7 +1309,7 @@ _bt_endpoint(IndexScanDesc scan, ScanDirection dir) } else if (continuescan) { - /* no, but there might be another one that is */ + /* no, but there might be another one that does */ res = _bt_next(scan, dir); } else diff --git a/src/backend/access/nbtree/nbtsort.c b/src/backend/access/nbtree/nbtsort.c index a56665be5c..ed920eafd3 100644 --- a/src/backend/access/nbtree/nbtsort.c +++ b/src/backend/access/nbtree/nbtsort.c @@ -36,7 +36,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtsort.c,v 1.77 2003/09/29 23:40:26 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtsort.c,v 1.78 2003/11/12 21:15:47 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -594,33 +594,37 @@ _bt_load(Relation index, BTSpool *btspool, BTSpool *btspool2) * Another BTSpool for dead tuples exists. Now we have to merge * btspool and btspool2. */ - ScanKey entry; - Datum attrDatum1, - attrDatum2; - bool isFirstNull, - isSecondNull; - int32 compare; /* the preparation of merge */ - bti = (BTItem) tuplesort_getindextuple(btspool->sortstate, true, &should_free); - bti2 = (BTItem) tuplesort_getindextuple(btspool2->sortstate, true, &should_free2); + bti = (BTItem) tuplesort_getindextuple(btspool->sortstate, + true, &should_free); + bti2 = (BTItem) tuplesort_getindextuple(btspool2->sortstate, + true, &should_free2); indexScanKey = _bt_mkscankey_nodata(index); + for (;;) { load1 = true; /* load BTSpool next ? */ - if (NULL == bti2) + if (bti2 == NULL) { - if (NULL == bti) + if (bti == NULL) break; } - else if (NULL != bti) + else if (bti != NULL) { - for (i = 1; i <= keysz; i++) { + ScanKey entry; + Datum attrDatum1, + attrDatum2; + bool isFirstNull, + isSecondNull; + entry = indexScanKey + i - 1; - attrDatum1 = index_getattr((IndexTuple) bti, i, tupdes, &isFirstNull); - attrDatum2 = index_getattr((IndexTuple) bti2, i, tupdes, &isSecondNull); + attrDatum1 = index_getattr((IndexTuple) bti, i, tupdes, + &isFirstNull); + attrDatum2 = index_getattr((IndexTuple) bti2, i, tupdes, + &isSecondNull); if (isFirstNull) { if (!isSecondNull) @@ -633,7 +637,11 @@ _bt_load(Relation index, BTSpool *btspool, BTSpool *btspool2) break; else { - compare = DatumGetInt32(FunctionCall2(&entry->sk_func, attrDatum1, attrDatum2)); + int32 compare; + + compare = DatumGetInt32(FunctionCall2(&entry->sk_func, + attrDatum1, + attrDatum2)); if (compare > 0) { load1 = false; @@ -656,14 +664,16 @@ _bt_load(Relation index, BTSpool *btspool, BTSpool *btspool2) _bt_buildadd(index, state, bti); if (should_free) pfree((void *) bti); - bti = (BTItem) tuplesort_getindextuple(btspool->sortstate, true, &should_free); + bti = (BTItem) tuplesort_getindextuple(btspool->sortstate, + true, &should_free); } else { _bt_buildadd(index, state, bti2); if (should_free2) pfree((void *) bti2); - bti2 = (BTItem) tuplesort_getindextuple(btspool2->sortstate, true, &should_free2); + bti2 = (BTItem) tuplesort_getindextuple(btspool2->sortstate, + true, &should_free2); } } _bt_freeskey(indexScanKey); @@ -671,7 +681,8 @@ _bt_load(Relation index, BTSpool *btspool, BTSpool *btspool2) else { /* merge is unnecessary */ - while (bti = (BTItem) tuplesort_getindextuple(btspool->sortstate, true, &should_free), bti != (BTItem) NULL) + while ((bti = (BTItem) tuplesort_getindextuple(btspool->sortstate, + true, &should_free)) != NULL) { /* When we see first tuple, create first index page */ if (state == NULL) diff --git a/src/backend/access/nbtree/nbtutils.c b/src/backend/access/nbtree/nbtutils.c index 54cd7c8cd0..2c9fd741ff 100644 --- a/src/backend/access/nbtree/nbtutils.c +++ b/src/backend/access/nbtree/nbtutils.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtutils.c,v 1.55 2003/11/09 21:30:35 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtutils.c,v 1.56 2003/11/12 21:15:47 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -19,7 +19,6 @@ #include "access/nbtree.h" #include "catalog/catalog.h" #include "executor/execdebug.h" -#include "utils/lsyscache.h" /* @@ -49,8 +48,8 @@ _bt_mkscankey(Relation rel, IndexTuple itup) bool null; /* - * We can use the cached support procs since no cross-type comparison - * can be needed. + * We can use the cached (default) 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); @@ -58,9 +57,9 @@ _bt_mkscankey(Relation rel, IndexTuple itup) null ? SK_ISNULL : 0, (AttrNumber) (i + 1), InvalidStrategy, + InvalidOid, procinfo, - arg, - itupdesc->attrs[i]->atttypid); + arg); } return skey; @@ -94,17 +93,17 @@ _bt_mkscankey_nodata(Relation rel) FmgrInfo *procinfo; /* - * We can use the cached support procs since no cross-type comparison - * can be needed. + * We can use the cached (default) 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, + InvalidOid, procinfo, - (Datum) 0, - itupdesc->attrs[i]->atttypid); + (Datum) 0); } return skey; @@ -161,105 +160,104 @@ _bt_formitem(IndexTuple itup) } /*---------- - * _bt_orderkeys() -- Put keys in a sensible order for conjunctive quals. + * _bt_preprocess_keys() -- Preprocess scan keys * - * After this routine runs, the scan keys are ordered by index attribute - * (all quals for attr 1, then all for attr 2, etc) and within each attr - * the keys are ordered by constraint type: ">", ">=", "=", "<=", "<". - * Furthermore, redundant keys are eliminated: we keep only the tightest - * >/>= bound and the tightest keyData[]) are copied to + * so->keyData[] with possible transformation. scan->numberOfKeys is + * the number of input keys, so->numberOfKeys gets the number of output + * keys (possibly less, never greater). * - * As a byproduct of this work, we can detect contradictory quals such - * as "x = 1 AND x > 2". If we see that, we return so->quals_ok = FALSE, - * indicating the scan need not be run at all since no tuples can match. + * The primary purpose of this routine is to discover how many scan keys + * must be satisfied to continue the scan. It also attempts to eliminate + * redundant keys and detect contradictory keys. At present, redundant and + * contradictory keys can only be detected for same-data-type comparisons, + * but that's the usual case so it seems worth doing. + * + * The output keys must be sorted by index attribute. Presently we expect + * (but verify) that the input keys are already so sorted --- this is done + * by group_clauses_by_indexkey() in indxpath.c. Some reordering of the keys + * within each attribute may be done as a byproduct of the processing here, + * but no other code depends on that. * - * Another byproduct is to determine how many quals must be satisfied to + * Aside from preparing so->keyData[], this routine sets + * so->numberOfRequiredKeys to the number of quals that must be satisfied to * continue the scan. _bt_checkkeys uses this. For example, if the quals * are "x = 1 AND y < 4 AND z < 5", then _bt_checkkeys will reject a tuple * (1,2,7), but we must continue the scan in case there are tuples (1,3,z). * But once we reach tuples like (1,4,z) we can stop scanning because no * later tuples could match. This is reflected by setting - * so->numberOfRequiredKeys to the number of leading keys that must be - * matched to continue the scan. numberOfRequiredKeys is equal to the - * number of leading "=" keys plus the key(s) for the first non "=" - * attribute, which can be seen to be correct by considering the above - * example. + * so->numberOfRequiredKeys to 2, the number of leading keys that must be + * matched to continue the scan. In general, numberOfRequiredKeys is equal + * to the number of keys for leading attributes with "=" keys, plus the + * key(s) for the first non "=" attribute, which can be seen to be correct + * by considering the above example. + * + * If possible, redundant keys are eliminated: we keep only the tightest + * >/>= bound and the tightest 2". If we see that, we return so->quals_ok = FALSE, + * indicating the scan need not be run at all since no tuples can match. + * Again though, only keys with RHS datatype equal to the index datatype + * can be checked for contradictions. * * Furthermore, we detect the case where the index is unique and we have * equality quals for all columns. In this case there can be at most one * (visible) matching tuple. index_getnext uses this to avoid uselessly * continuing the scan after finding one match. - * - * 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. *---------- */ void -_bt_orderkeys(IndexScanDesc scan) +_bt_preprocess_keys(IndexScanDesc scan) { Relation relation = scan->indexRelation; BTScanOpaque so = (BTScanOpaque) scan->opaque; - ScanKeyData xform[BTMaxStrategyNumber]; - bool init[BTMaxStrategyNumber]; - int numberOfKeys = so->numberOfKeys; - ScanKey key; + int numberOfKeys = scan->numberOfKeys; + int new_numberOfKeys; + ScanKey inkeys; + ScanKey outkeys; ScanKey cur; + ScanKey xform[BTMaxStrategyNumber]; + bool allEqualSoFar; + bool hasOtherTypeEqual; Datum test; int i, j; AttrNumber attno; - int new_numberOfKeys; - bool allEqualSoFar; + /* initialize result variables */ so->qual_ok = true; + so->numberOfKeys = 0; so->numberOfRequiredKeys = 0; scan->keys_are_unique = false; if (numberOfKeys < 1) return; /* done if qual-less scan */ - key = so->keyData; - cur = &key[0]; - /* check input keys are correctly ordered */ + inkeys = scan->keyData; + outkeys = so->keyData; + cur = &inkeys[0]; + /* we check that input keys are correctly ordered */ 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) { /* * We don't use indices for 'A is null' and 'A is not null' * currently and 'A < = > <> NULL' will always fail - so qual is - * not Ok if comparison value is NULL. - vadim 03/21/97 + * not OK if comparison value is NULL. - vadim 03/21/97 */ if (cur->sk_flags & SK_ISNULL) so->qual_ok = false; @@ -270,6 +268,8 @@ _bt_orderkeys(IndexScanDesc scan) if (cur->sk_strategy == BTEqualStrategyNumber) scan->keys_are_unique = true; } + memcpy(outkeys, inkeys, sizeof(ScanKeyData)); + so->numberOfKeys = 1; so->numberOfRequiredKeys = 1; return; } @@ -283,12 +283,15 @@ _bt_orderkeys(IndexScanDesc scan) /* * Initialize for processing of keys for attr 1. * - * xform[i] holds a copy of the current scan key of strategy type i+1, if - * any; init[i] is TRUE if we have found such a key for this attr. + * xform[i] points to the currently best scan key of strategy type i+1, + * if any is found with a default operator subtype; it is NULL if we + * haven't yet found such a key for this attr. Scan keys of nondefault + * subtypes are transferred to the output with no processing except for + * noting if they are of "=" type. */ attno = 1; - MemSet(xform, 0, sizeof(xform)); /* not really necessary */ - MemSet(init, 0, sizeof(init)); + memset(xform, 0, sizeof(xform)); + hasOtherTypeEqual = false; /* * Loop iterates from 0 to numberOfKeys inclusive; we use the last @@ -329,80 +332,78 @@ _bt_orderkeys(IndexScanDesc scan) * of key > 2 && key == 1 and so on we have to set qual_ok to * false before discarding the other keys. */ - if (init[BTEqualStrategyNumber - 1]) + if (xform[BTEqualStrategyNumber - 1]) { - ScanKeyData *eq, - *chk; + ScanKey eq = xform[BTEqualStrategyNumber - 1]; - eq = &xform[BTEqualStrategyNumber - 1]; for (j = BTMaxStrategyNumber; --j >= 0;) { - if (!init[j] || - j == (BTEqualStrategyNumber - 1)) + ScanKey chk = xform[j]; + + if (!chk || j == (BTEqualStrategyNumber - 1)) continue; - chk = &xform[j]; test = FunctionCall2(&chk->sk_func, eq->sk_argument, chk->sk_argument); if (!DatumGetBool(test)) + { so->qual_ok = false; + break; + } } - init[BTLessStrategyNumber - 1] = false; - init[BTLessEqualStrategyNumber - 1] = false; - init[BTGreaterEqualStrategyNumber - 1] = false; - init[BTGreaterStrategyNumber - 1] = false; + xform[BTLessStrategyNumber - 1] = NULL; + xform[BTLessEqualStrategyNumber - 1] = NULL; + xform[BTGreaterEqualStrategyNumber - 1] = NULL; + xform[BTGreaterStrategyNumber - 1] = NULL; } else { /* - * No "=" for this key, so we're done with required keys + * If no "=" for this key, we're done with required keys */ - allEqualSoFar = false; + if (! hasOtherTypeEqual) + allEqualSoFar = false; } /* keep only one of <, <= */ - if (init[BTLessStrategyNumber - 1] - && init[BTLessEqualStrategyNumber - 1]) + if (xform[BTLessStrategyNumber - 1] + && xform[BTLessEqualStrategyNumber - 1]) { - ScanKeyData *lt = &xform[BTLessStrategyNumber - 1]; - ScanKeyData *le = &xform[BTLessEqualStrategyNumber - 1]; + ScanKey lt = xform[BTLessStrategyNumber - 1]; + ScanKey le = xform[BTLessEqualStrategyNumber - 1]; test = FunctionCall2(&le->sk_func, lt->sk_argument, le->sk_argument); if (DatumGetBool(test)) - init[BTLessEqualStrategyNumber - 1] = false; + xform[BTLessEqualStrategyNumber - 1] = NULL; else - init[BTLessStrategyNumber - 1] = false; + xform[BTLessStrategyNumber - 1] = NULL; } /* keep only one of >, >= */ - if (init[BTGreaterStrategyNumber - 1] - && init[BTGreaterEqualStrategyNumber - 1]) + if (xform[BTGreaterStrategyNumber - 1] + && xform[BTGreaterEqualStrategyNumber - 1]) { - ScanKeyData *gt = &xform[BTGreaterStrategyNumber - 1]; - ScanKeyData *ge = &xform[BTGreaterEqualStrategyNumber - 1]; + ScanKey gt = xform[BTGreaterStrategyNumber - 1]; + ScanKey ge = xform[BTGreaterEqualStrategyNumber - 1]; test = FunctionCall2(&ge->sk_func, gt->sk_argument, ge->sk_argument); if (DatumGetBool(test)) - init[BTGreaterEqualStrategyNumber - 1] = false; + xform[BTGreaterEqualStrategyNumber - 1] = NULL; else - init[BTGreaterStrategyNumber - 1] = false; + xform[BTGreaterStrategyNumber - 1] = NULL; } /* - * Emit the cleaned-up keys back into the key[] array in the - * correct order. Note we are overwriting our input here! - * It's OK because (a) xform[] is a physical copy of the keys - * we want, (b) we cannot emit more keys than we input, so we - * won't overwrite as-yet-unprocessed keys. + * Emit the cleaned-up keys into the outkeys[] array. */ for (j = BTMaxStrategyNumber; --j >= 0;) { - if (init[j]) - memcpy(&key[new_numberOfKeys++], &xform[j], + if (xform[j]) + memcpy(&outkeys[new_numberOfKeys++], xform[j], sizeof(ScanKeyData)); } @@ -421,31 +422,43 @@ _bt_orderkeys(IndexScanDesc scan) /* Re-initialize for new attno */ attno = cur->sk_attno; - MemSet(xform, 0, sizeof(xform)); /* not really necessary */ - MemSet(init, 0, sizeof(init)); + memset(xform, 0, sizeof(xform)); + hasOtherTypeEqual = false; } - /* figure out which strategy this key's operator corresponds to */ + /* check strategy this key's operator corresponds to */ j = cur->sk_strategy - 1; + /* if wrong RHS data type, punt */ + if (cur->sk_subtype != InvalidOid) + { + memcpy(&outkeys[new_numberOfKeys++], cur, + sizeof(ScanKeyData)); + if (j == (BTEqualStrategyNumber - 1)) + hasOtherTypeEqual = true; + continue; + } + /* have we seen one of these before? */ - if (init[j]) + if (xform[j]) { - /* yup, keep the more restrictive value */ + /* yup, keep the more restrictive key */ test = FunctionCall2(&cur->sk_func, cur->sk_argument, - xform[j].sk_argument); + xform[j]->sk_argument); if (DatumGetBool(test)) - xform[j].sk_argument = cur->sk_argument; + xform[j] = cur; else if (j == (BTEqualStrategyNumber - 1)) + { + /* key == a && key == b, but a != b */ so->qual_ok = false; - /* key == a && key == b, but a != b */ + return; + } } else { /* nope, so remember this scankey */ - memcpy(&xform[j], cur, sizeof(ScanKeyData)); - init[j] = true; + xform[j] = cur; } } @@ -465,8 +478,8 @@ _bt_orderkeys(IndexScanDesc scan) * * If the tuple fails to pass the qual, we also determine whether there's * any need to continue the scan beyond this tuple, and set *continuescan - * accordingly. See comments for _bt_orderkeys(), above, about how this is - * done. + * accordingly. See comments for _bt_preprocess_keys(), above, about how + * this is done. */ bool _bt_checkkeys(IndexScanDesc scan, IndexTuple tuple, @@ -474,7 +487,7 @@ _bt_checkkeys(IndexScanDesc scan, IndexTuple tuple, { BTScanOpaque so = (BTScanOpaque) scan->opaque; int keysz = so->numberOfKeys; - int keysok; + int ikey; TupleDesc tupdesc; ScanKey key; @@ -484,13 +497,11 @@ _bt_checkkeys(IndexScanDesc scan, IndexTuple tuple, if (keysz == 0) return true; - tupdesc = RelationGetDescr(scan->indexRelation); - key = so->keyData; - keysok = 0; - IncrIndexProcessed(); - while (keysz > 0) + tupdesc = RelationGetDescr(scan->indexRelation); + + for (key = so->keyData, ikey = 0; ikey < keysz; key++, ikey++) { Datum datum; bool isNull; @@ -504,7 +515,7 @@ _bt_checkkeys(IndexScanDesc scan, IndexTuple tuple, /* btree doesn't support 'A is null' clauses, yet */ if (key->sk_flags & SK_ISNULL) { - /* we shouldn't get here, really; see _bt_orderkeys() */ + /* we shouldn't get here, really; see _bt_preprocess_keys() */ *continuescan = false; return false; } @@ -518,7 +529,7 @@ _bt_checkkeys(IndexScanDesc scan, IndexTuple tuple, * one of the "must match" subset. On a backward scan, * however, we should keep going. */ - if (keysok < so->numberOfRequiredKeys && + if (ikey < so->numberOfRequiredKeys && ScanDirectionIsForward(dir)) *continuescan = false; @@ -534,16 +545,50 @@ _bt_checkkeys(IndexScanDesc scan, IndexTuple tuple, { /* * Tuple fails this qual. If it's a required qual, then we - * can conclude no further tuples will pass, either. + * may be able to conclude no further tuples will pass, either. + * We have to look at the scan direction and the qual type. + * + * Note: the only case in which we would keep going after failing + * a required qual is if there are partially-redundant quals that + * _bt_preprocess_keys() was unable to eliminate. For example, + * given "x > 4 AND x > 10" where both are cross-type comparisons + * and so not removable, we might start the scan at the x = 4 + * boundary point. The "x > 10" condition will fail until we + * pass x = 10, but we must not stop the scan on its account. + * + * Note: because we stop the scan as soon as any required equality + * qual fails, it is critical that equality quals be used for the + * initial positioning in _bt_first() when they are available. + * See comments in _bt_first(). + */ + if (ikey < so->numberOfRequiredKeys) + { + switch (key->sk_strategy) + { + case BTLessStrategyNumber: + case BTLessEqualStrategyNumber: + if (ScanDirectionIsForward(dir)) + *continuescan = false; + break; + case BTEqualStrategyNumber: + *continuescan = false; + break; + case BTGreaterEqualStrategyNumber: + case BTGreaterStrategyNumber: + if (ScanDirectionIsBackward(dir)) + *continuescan = false; + break; + default: + elog(ERROR, "unrecognized StrategyNumber: %d", + key->sk_strategy); + } + } + + /* + * In any case, this indextuple doesn't match the qual. */ - if (keysok < so->numberOfRequiredKeys) - *continuescan = false; return false; } - - keysok++; - key++; - keysz--; } /* If we get here, the tuple passes all quals. */ diff --git a/src/backend/access/rtree/rtproc.c b/src/backend/access/rtree/rtproc.c index 790f6bc7b6..985993fb68 100644 --- a/src/backend/access/rtree/rtproc.c +++ b/src/backend/access/rtree/rtproc.c @@ -15,7 +15,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/rtree/Attic/rtproc.c,v 1.37 2003/08/04 02:39:57 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/rtree/Attic/rtproc.c,v 1.38 2003/11/12 21:15:48 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -82,20 +82,6 @@ rt_box_size(PG_FUNCTION_ARGS) PG_RETURN_VOID(); } -/* - * rt_bigbox_size() -- Compute a size for big boxes. - * - * In an earlier release of the system, this routine did something - * different from rt_box_size. We now use floats, rather than ints, - * as the return type for the size routine, so we no longer need to - * have a special return type for big boxes. - */ -Datum -rt_bigbox_size(PG_FUNCTION_ARGS) -{ - return rt_box_size(fcinfo); -} - Datum rt_poly_union(PG_FUNCTION_ARGS) { diff --git a/src/backend/access/rtree/rtscan.c b/src/backend/access/rtree/rtscan.c index 263fff4bf2..5026bd78a7 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.48 2003/11/09 21:30:35 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/rtree/Attic/rtscan.c,v 1.49 2003/11/12 21:15:48 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -123,15 +123,17 @@ rtrescan(PG_FUNCTION_ARGS) 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_oper = get_opclass_member(opclass, + s->keyData[i].sk_subtype, + int_strategy); int_proc = get_opcode(int_oper); ScanKeyEntryInitialize(&(p->s_internalKey[i]), s->keyData[i].sk_flags, attno, int_strategy, + s->keyData[i].sk_subtype, int_proc, - s->keyData[i].sk_argument, - s->keyData[i].sk_argtype); + s->keyData[i].sk_argument); } } diff --git a/src/backend/catalog/aclchk.c b/src/backend/catalog/aclchk.c index a1b697bee8..7534750c99 100644 --- a/src/backend/catalog/aclchk.c +++ b/src/backend/catalog/aclchk.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/catalog/aclchk.c,v 1.92 2003/11/09 21:30:35 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/catalog/aclchk.c,v 1.93 2003/11/12 21:15:48 tgl Exp $ * * NOTES * See acl.h. @@ -366,10 +366,10 @@ ExecuteGrantStmt_Database(GrantStmt *stmt) char replaces[Natts_pg_database]; relation = heap_openr(DatabaseRelationName, RowExclusiveLock); - ScanKeyEntryInitialize(&entry[0], 0, - Anum_pg_database_datname, - BTEqualStrategyNumber, F_NAMEEQ, - CStringGetDatum(dbname), NAMEOID); + ScanKeyInit(&entry[0], + Anum_pg_database_datname, + BTEqualStrategyNumber, F_NAMEEQ, + CStringGetDatum(dbname)); scan = heap_beginscan(relation, SnapshotNow, 1, entry); tuple = heap_getnext(scan, ForwardScanDirection); if (!HeapTupleIsValid(tuple)) @@ -1131,10 +1131,10 @@ pg_database_aclcheck(Oid db_oid, AclId userid, AclMode mode) * There's no syscache for pg_database, so must look the hard way */ pg_database = heap_openr(DatabaseRelationName, AccessShareLock); - ScanKeyEntryInitialize(&entry[0], 0, - ObjectIdAttributeNumber, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(db_oid), OIDOID); + ScanKeyInit(&entry[0], + ObjectIdAttributeNumber, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(db_oid)); scan = heap_beginscan(pg_database, SnapshotNow, 1, entry); tuple = heap_getnext(scan, ForwardScanDirection); if (!HeapTupleIsValid(tuple)) @@ -1531,10 +1531,10 @@ pg_database_ownercheck(Oid db_oid, AclId userid) /* There's no syscache for pg_database, so must look the hard way */ pg_database = heap_openr(DatabaseRelationName, AccessShareLock); - ScanKeyEntryInitialize(&entry[0], 0, - ObjectIdAttributeNumber, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(db_oid), OIDOID); + ScanKeyInit(&entry[0], + ObjectIdAttributeNumber, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(db_oid)); scan = heap_beginscan(pg_database, SnapshotNow, 1, entry); dbtuple = heap_getnext(scan, ForwardScanDirection); diff --git a/src/backend/catalog/dependency.c b/src/backend/catalog/dependency.c index b0e17652c7..d64f027ef6 100644 --- a/src/backend/catalog/dependency.c +++ b/src/backend/catalog/dependency.c @@ -8,7 +8,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/catalog/dependency.c,v 1.32 2003/11/09 21:30:35 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/catalog/dependency.c,v 1.33 2003/11/12 21:15:48 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -31,7 +31,6 @@ #include "catalog/pg_opclass.h" #include "catalog/pg_rewrite.h" #include "catalog/pg_trigger.h" -#include "catalog/pg_type.h" #include "commands/comment.h" #include "commands/defrem.h" #include "commands/proclang.h" @@ -283,20 +282,20 @@ findAutoDeletableObjects(const ObjectAddress *object, * When dropping a whole object (subId = 0), find pg_depend records for * its sub-objects too. */ - ScanKeyEntryInitialize(&key[0], 0, - Anum_pg_depend_refclassid, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(object->classId), OIDOID); - ScanKeyEntryInitialize(&key[1], 0, - Anum_pg_depend_refobjid, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(object->objectId), OIDOID); + ScanKeyInit(&key[0], + Anum_pg_depend_refclassid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(object->classId)); + ScanKeyInit(&key[1], + Anum_pg_depend_refobjid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(object->objectId)); if (object->objectSubId != 0) { - ScanKeyEntryInitialize(&key[2], 0, - Anum_pg_depend_refobjsubid, - BTEqualStrategyNumber, F_INT4EQ, - Int32GetDatum(object->objectSubId), INT4OID); + ScanKeyInit(&key[2], + Anum_pg_depend_refobjsubid, + BTEqualStrategyNumber, F_INT4EQ, + Int32GetDatum(object->objectSubId)); nkeys = 3; } else @@ -418,20 +417,20 @@ recursiveDeletion(const ObjectAddress *object, * When dropping a whole object (subId = 0), remove all pg_depend records * for its sub-objects too. */ - ScanKeyEntryInitialize(&key[0], 0, - Anum_pg_depend_classid, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(object->classId), OIDOID); - ScanKeyEntryInitialize(&key[1], 0, - Anum_pg_depend_objid, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(object->objectId), OIDOID); + ScanKeyInit(&key[0], + Anum_pg_depend_classid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(object->classId)); + ScanKeyInit(&key[1], + Anum_pg_depend_objid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(object->objectId)); if (object->objectSubId != 0) { - ScanKeyEntryInitialize(&key[2], 0, - Anum_pg_depend_objsubid, - BTEqualStrategyNumber, F_INT4EQ, - Int32GetDatum(object->objectSubId), INT4OID); + ScanKeyInit(&key[2], + Anum_pg_depend_objsubid, + BTEqualStrategyNumber, F_INT4EQ, + Int32GetDatum(object->objectSubId)); nkeys = 3; } else @@ -651,20 +650,20 @@ deleteDependentObjects(const ObjectAddress *object, HeapTuple tup; ObjectAddress otherObject; - ScanKeyEntryInitialize(&key[0], 0, - Anum_pg_depend_refclassid, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(object->classId), OIDOID); - ScanKeyEntryInitialize(&key[1], 0, - Anum_pg_depend_refobjid, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(object->objectId), OIDOID); + ScanKeyInit(&key[0], + Anum_pg_depend_refclassid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(object->classId)); + ScanKeyInit(&key[1], + Anum_pg_depend_refobjid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(object->objectId)); if (object->objectSubId != 0) { - ScanKeyEntryInitialize(&key[2], 0, - Anum_pg_depend_refobjsubid, - BTEqualStrategyNumber, F_INT4EQ, - Int32GetDatum(object->objectSubId), INT4OID); + ScanKeyInit(&key[2], + Anum_pg_depend_refobjsubid, + BTEqualStrategyNumber, F_INT4EQ, + Int32GetDatum(object->objectSubId)); nkeys = 3; } else @@ -1473,11 +1472,10 @@ getObjectDescription(const ObjectAddress *object) castDesc = heap_openr(CastRelationName, AccessShareLock); - ScanKeyEntryInitialize(&skey[0], 0, - ObjectIdAttributeNumber, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(object->objectId), - OIDOID); + ScanKeyInit(&skey[0], + ObjectIdAttributeNumber, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(object->objectId)); rcscan = systable_beginscan(castDesc, CastOidIndex, true, SnapshotNow, 1, skey); @@ -1509,11 +1507,10 @@ getObjectDescription(const ObjectAddress *object) conDesc = heap_openr(ConstraintRelationName, AccessShareLock); - ScanKeyEntryInitialize(&skey[0], 0, - ObjectIdAttributeNumber, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(object->objectId), - OIDOID); + ScanKeyInit(&skey[0], + ObjectIdAttributeNumber, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(object->objectId)); rcscan = systable_beginscan(conDesc, ConstraintOidIndex, true, SnapshotNow, 1, skey); @@ -1570,11 +1567,10 @@ getObjectDescription(const ObjectAddress *object) attrdefDesc = heap_openr(AttrDefaultRelationName, AccessShareLock); - ScanKeyEntryInitialize(&skey[0], 0, - ObjectIdAttributeNumber, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(object->objectId), - OIDOID); + ScanKeyInit(&skey[0], + ObjectIdAttributeNumber, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(object->objectId)); adscan = systable_beginscan(attrdefDesc, AttrDefaultOidIndex, true, SnapshotNow, 1, skey); @@ -1672,11 +1668,10 @@ getObjectDescription(const ObjectAddress *object) ruleDesc = heap_openr(RewriteRelationName, AccessShareLock); - ScanKeyEntryInitialize(&skey[0], 0, - ObjectIdAttributeNumber, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(object->objectId), - OIDOID); + ScanKeyInit(&skey[0], + ObjectIdAttributeNumber, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(object->objectId)); rcscan = systable_beginscan(ruleDesc, RewriteOidIndex, true, SnapshotNow, 1, skey); @@ -1708,11 +1703,10 @@ getObjectDescription(const ObjectAddress *object) trigDesc = heap_openr(TriggerRelationName, AccessShareLock); - ScanKeyEntryInitialize(&skey[0], 0, - ObjectIdAttributeNumber, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(object->objectId), - OIDOID); + ScanKeyInit(&skey[0], + ObjectIdAttributeNumber, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(object->objectId)); tgscan = systable_beginscan(trigDesc, TriggerOidIndex, true, SnapshotNow, 1, skey); diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c index 75445334ec..a0962f487d 100644 --- a/src/backend/catalog/heap.c +++ b/src/backend/catalog/heap.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.254 2003/11/09 21:30:36 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.255 2003/11/12 21:15:48 tgl Exp $ * * * INTERFACE ROUTINES @@ -853,11 +853,10 @@ RelationRemoveInheritance(Relation relation) catalogRelation = heap_openr(InheritsRelationName, RowExclusiveLock); - ScanKeyEntryInitialize(&key, 0, - Anum_pg_inherits_inhrelid, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(RelationGetRelid(relation)), - OIDOID); + ScanKeyInit(&key, + Anum_pg_inherits_inhrelid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(RelationGetRelid(relation))); scan = systable_beginscan(catalogRelation, InheritsRelidSeqnoIndex, true, SnapshotNow, 1, &key); @@ -920,10 +919,10 @@ DeleteAttributeTuples(Oid relid) attrel = heap_openr(AttributeRelationName, RowExclusiveLock); /* Use the index to scan only attributes of the target relation */ - ScanKeyEntryInitialize(&key[0], 0, - Anum_pg_attribute_attrelid, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(relid), OIDOID); + ScanKeyInit(&key[0], + Anum_pg_attribute_attrelid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(relid)); scan = systable_beginscan(attrel, AttributeRelidNumIndex, true, SnapshotNow, 1, key); @@ -1035,14 +1034,14 @@ RemoveAttrDefault(Oid relid, AttrNumber attnum, attrdef_rel = heap_openr(AttrDefaultRelationName, RowExclusiveLock); - ScanKeyEntryInitialize(&scankeys[0], 0, - Anum_pg_attrdef_adrelid, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(relid), OIDOID); - ScanKeyEntryInitialize(&scankeys[1], 0, - Anum_pg_attrdef_adnum, - BTEqualStrategyNumber, F_INT2EQ, - Int16GetDatum(attnum), INT2OID); + ScanKeyInit(&scankeys[0], + Anum_pg_attrdef_adrelid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(relid)); + ScanKeyInit(&scankeys[1], + Anum_pg_attrdef_adnum, + BTEqualStrategyNumber, F_INT2EQ, + Int16GetDatum(attnum)); scan = systable_beginscan(attrdef_rel, AttrDefaultIndex, true, SnapshotNow, 2, scankeys); @@ -1092,10 +1091,10 @@ RemoveAttrDefaultById(Oid attrdefId) attrdef_rel = heap_openr(AttrDefaultRelationName, RowExclusiveLock); /* Find the pg_attrdef tuple */ - ScanKeyEntryInitialize(&scankeys[0], 0, - ObjectIdAttributeNumber, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(attrdefId), OIDOID); + ScanKeyInit(&scankeys[0], + ObjectIdAttributeNumber, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(attrdefId)); scan = systable_beginscan(attrdef_rel, AttrDefaultOidIndex, true, SnapshotNow, 1, scankeys); @@ -1829,10 +1828,10 @@ RemoveRelConstraints(Relation rel, const char *constrName, conrel = heap_openr(ConstraintRelationName, RowExclusiveLock); /* Use the index to scan only constraints of the target relation */ - ScanKeyEntryInitialize(&key[0], 0, - Anum_pg_constraint_conrelid, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(RelationGetRelid(rel)), OIDOID); + ScanKeyInit(&key[0], + Anum_pg_constraint_conrelid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(RelationGetRelid(rel))); conscan = systable_beginscan(conrel, ConstraintRelidIndex, true, SnapshotNow, 1, key); @@ -1883,19 +1882,19 @@ RemoveStatistics(Relation rel, AttrNumber attnum) pgstatistic = heap_openr(StatisticRelationName, RowExclusiveLock); - ScanKeyEntryInitialize(&key[0], 0, - Anum_pg_statistic_starelid, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(RelationGetRelid(rel)), OIDOID); + ScanKeyInit(&key[0], + Anum_pg_statistic_starelid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(RelationGetRelid(rel))); if (attnum == 0) nkeys = 1; else { - ScanKeyEntryInitialize(&key[1], 0, - Anum_pg_statistic_staattnum, - BTEqualStrategyNumber, F_INT2EQ, - Int16GetDatum(attnum), INT2OID); + ScanKeyInit(&key[1], + Anum_pg_statistic_staattnum, + BTEqualStrategyNumber, F_INT2EQ, + Int16GetDatum(attnum)); nkeys = 2; } @@ -2050,10 +2049,10 @@ heap_truncate_check_FKs(Relation rel) */ fkeyRel = heap_openr(ConstraintRelationName, AccessShareLock); - ScanKeyEntryInitialize(&key, 0, - Anum_pg_constraint_confrelid, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(relid), OIDOID); + ScanKeyInit(&key, + Anum_pg_constraint_confrelid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(relid)); fkeyScan = systable_beginscan(fkeyRel, NULL, false, SnapshotNow, 1, &key); diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 67f970c55d..72f76b01b0 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.220 2003/11/09 21:30:36 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.221 2003/11/12 21:15:48 tgl Exp $ * * * INTERFACE ROUTINES @@ -992,10 +992,10 @@ setRelhasindex(Oid relid, bool hasindex, bool isprimary, Oid reltoastidxid) { ScanKeyData key[1]; - ScanKeyEntryInitialize(&key[0], 0, - ObjectIdAttributeNumber, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(relid), OIDOID); + ScanKeyInit(&key[0], + ObjectIdAttributeNumber, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(relid)); pg_class_scan = heap_beginscan(pg_class, SnapshotNow, 1, key); tuple = heap_getnext(pg_class_scan, ForwardScanDirection); @@ -1195,10 +1195,10 @@ UpdateStats(Oid relid, double reltuples) { ScanKeyData key[1]; - ScanKeyEntryInitialize(&key[0], 0, - ObjectIdAttributeNumber, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(relid), OIDOID); + ScanKeyInit(&key[0], + ObjectIdAttributeNumber, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(relid)); pg_class_scan = heap_beginscan(pg_class, SnapshotNow, 1, key); tuple = heap_getnext(pg_class_scan, ForwardScanDirection); diff --git a/src/backend/catalog/pg_constraint.c b/src/backend/catalog/pg_constraint.c index 0fa665a568..2cb71f6bfc 100644 --- a/src/backend/catalog/pg_constraint.c +++ b/src/backend/catalog/pg_constraint.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/catalog/pg_constraint.c,v 1.17 2003/11/09 21:30:36 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/catalog/pg_constraint.c,v 1.18 2003/11/12 21:15:48 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -281,15 +281,15 @@ ConstraintNameIsUsed(CONSTRAINTCATEGORY conCat, Oid objId, Oid objNamespace, con found = false; - ScanKeyEntryInitialize(&skey[0], 0, - Anum_pg_constraint_conname, - BTEqualStrategyNumber, F_NAMEEQ, - CStringGetDatum(cname), NAMEOID); + ScanKeyInit(&skey[0], + Anum_pg_constraint_conname, + BTEqualStrategyNumber, F_NAMEEQ, + CStringGetDatum(cname)); - ScanKeyEntryInitialize(&skey[1], 0, - Anum_pg_constraint_connamespace, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(objNamespace), OIDOID); + ScanKeyInit(&skey[1], + Anum_pg_constraint_connamespace, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(objNamespace)); conscan = systable_beginscan(conDesc, ConstraintNameNspIndex, true, SnapshotNow, 2, skey); @@ -355,15 +355,15 @@ GenerateConstraintName(CONSTRAINTCATEGORY conCat, Oid objId, Oid objNamespace, i */ found = false; - ScanKeyEntryInitialize(&skey[0], 0, - Anum_pg_constraint_conname, - BTEqualStrategyNumber, F_NAMEEQ, - CStringGetDatum(cname), NAMEOID); + ScanKeyInit(&skey[0], + Anum_pg_constraint_conname, + BTEqualStrategyNumber, F_NAMEEQ, + CStringGetDatum(cname)); - ScanKeyEntryInitialize(&skey[1], 0, - Anum_pg_constraint_connamespace, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(objNamespace), OIDOID); + ScanKeyInit(&skey[1], + Anum_pg_constraint_connamespace, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(objNamespace)); conscan = systable_beginscan(conDesc, ConstraintNameNspIndex, true, SnapshotNow, 2, skey); @@ -422,10 +422,10 @@ RemoveConstraintById(Oid conId) conDesc = heap_openr(ConstraintRelationName, RowExclusiveLock); - ScanKeyEntryInitialize(&skey[0], 0, - ObjectIdAttributeNumber, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(conId), OIDOID); + ScanKeyInit(&skey[0], + ObjectIdAttributeNumber, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(conId)); conscan = systable_beginscan(conDesc, ConstraintOidIndex, true, SnapshotNow, 1, skey); diff --git a/src/backend/catalog/pg_conversion.c b/src/backend/catalog/pg_conversion.c index 709f50f2a5..7f7811c88d 100644 --- a/src/backend/catalog/pg_conversion.c +++ b/src/backend/catalog/pg_conversion.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/catalog/pg_conversion.c,v 1.16 2003/11/09 21:30:36 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/catalog/pg_conversion.c,v 1.17 2003/11/12 21:15:48 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -21,7 +21,6 @@ #include "catalog/pg_class.h" #include "catalog/pg_conversion.h" #include "catalog/namespace.h" -#include "catalog/pg_type.h" #include "utils/builtins.h" #include "utils/lsyscache.h" #include "utils/syscache.h" @@ -177,10 +176,10 @@ RemoveConversionById(Oid conversionOid) HeapScanDesc scan; ScanKeyData scanKeyData; - ScanKeyEntryInitialize(&scanKeyData, 0, - ObjectIdAttributeNumber, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(conversionOid), OIDOID); + ScanKeyInit(&scanKeyData, + ObjectIdAttributeNumber, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(conversionOid)); /* open pg_conversion */ rel = heap_openr(ConversionRelationName, RowExclusiveLock); diff --git a/src/backend/catalog/pg_depend.c b/src/backend/catalog/pg_depend.c index 21eeb3e654..2bdb5b12d8 100644 --- a/src/backend/catalog/pg_depend.c +++ b/src/backend/catalog/pg_depend.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/catalog/pg_depend.c,v 1.8 2003/11/09 21:30:36 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/catalog/pg_depend.c,v 1.9 2003/11/12 21:15:48 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -20,7 +20,6 @@ #include "catalog/indexing.h" #include "catalog/dependency.h" #include "catalog/pg_depend.h" -#include "catalog/pg_type.h" #include "miscadmin.h" #include "utils/fmgroids.h" @@ -139,14 +138,14 @@ deleteDependencyRecordsFor(Oid classId, Oid objectId) depRel = heap_openr(DependRelationName, RowExclusiveLock); - ScanKeyEntryInitialize(&key[0], 0, - Anum_pg_depend_classid, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(classId), OIDOID); - ScanKeyEntryInitialize(&key[1], 0, - Anum_pg_depend_objid, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(objectId), OIDOID); + ScanKeyInit(&key[0], + Anum_pg_depend_classid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(classId)); + ScanKeyInit(&key[1], + Anum_pg_depend_objid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(objectId)); scan = systable_beginscan(depRel, DependDependerIndex, true, SnapshotNow, 2, key); @@ -181,15 +180,15 @@ isObjectPinned(const ObjectAddress *object, Relation rel) HeapTuple tup; ScanKeyData key[2]; - ScanKeyEntryInitialize(&key[0], 0, - Anum_pg_depend_refclassid, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(object->classId), OIDOID); + ScanKeyInit(&key[0], + Anum_pg_depend_refclassid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(object->classId)); - ScanKeyEntryInitialize(&key[1], 0, - Anum_pg_depend_refobjid, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(object->objectId), OIDOID); + ScanKeyInit(&key[1], + Anum_pg_depend_refobjid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(object->objectId)); scan = systable_beginscan(rel, DependReferenceIndex, true, SnapshotNow, 2, key); diff --git a/src/backend/catalog/pg_largeobject.c b/src/backend/catalog/pg_largeobject.c index 96f73056cf..022ca67d10 100644 --- a/src/backend/catalog/pg_largeobject.c +++ b/src/backend/catalog/pg_largeobject.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/catalog/pg_largeobject.c,v 1.18 2003/11/09 21:30:36 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/catalog/pg_largeobject.c,v 1.19 2003/11/12 21:15:48 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -19,7 +19,6 @@ #include "catalog/catname.h" #include "catalog/indexing.h" #include "catalog/pg_largeobject.h" -#include "catalog/pg_type.h" #include "miscadmin.h" #include "utils/builtins.h" #include "utils/fmgroids.h" @@ -82,10 +81,10 @@ LargeObjectDrop(Oid loid) SysScanDesc sd; HeapTuple tuple; - ScanKeyEntryInitialize(&skey[0], 0, - Anum_pg_largeobject_loid, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(loid), OIDOID); + ScanKeyInit(&skey[0], + Anum_pg_largeobject_loid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(loid)); pg_largeobject = heap_openr(LargeObjectRelationName, RowExclusiveLock); @@ -120,10 +119,10 @@ LargeObjectExists(Oid loid) /* * See if we can find any tuples belonging to the specified LO */ - ScanKeyEntryInitialize(&skey[0], 0, - Anum_pg_largeobject_loid, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(loid), OIDOID); + ScanKeyInit(&skey[0], + Anum_pg_largeobject_loid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(loid)); pg_largeobject = heap_openr(LargeObjectRelationName, AccessShareLock); diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c index 2cda1f94a9..560a134aa8 100644 --- a/src/backend/commands/async.c +++ b/src/backend/commands/async.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/async.c,v 1.103 2003/11/09 21:30:36 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/async.c,v 1.104 2003/11/12 21:15:49 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -80,7 +80,6 @@ #include "access/heapam.h" #include "catalog/catname.h" #include "catalog/pg_listener.h" -#include "catalog/pg_type.h" #include "commands/async.h" #include "libpq/libpq.h" #include "libpq/pqformat.h" @@ -353,10 +352,10 @@ Async_UnlistenAll(void) tdesc = RelationGetDescr(lRel); /* Find and delete all entries with my listenerPID */ - ScanKeyEntryInitialize(&key[0], 0, - Anum_pg_listener_pid, - BTEqualStrategyNumber, F_INT4EQ, - Int32GetDatum(MyProcPid), INT4OID); + ScanKeyInit(&key[0], + Anum_pg_listener_pid, + BTEqualStrategyNumber, F_INT4EQ, + Int32GetDatum(MyProcPid)); scan = heap_beginscan(lRel, SnapshotNow, 1, key); while ((lTuple = heap_getnext(scan, ForwardScanDirection)) != NULL) @@ -817,10 +816,10 @@ ProcessIncomingNotify(void) tdesc = RelationGetDescr(lRel); /* Scan only entries with my listenerPID */ - ScanKeyEntryInitialize(&key[0], 0, - Anum_pg_listener_pid, - BTEqualStrategyNumber, F_INT4EQ, - Int32GetDatum(MyProcPid), INT4OID); + ScanKeyInit(&key[0], + Anum_pg_listener_pid, + BTEqualStrategyNumber, F_INT4EQ, + Int32GetDatum(MyProcPid)); scan = heap_beginscan(lRel, SnapshotNow, 1, key); /* Prepare data for rewriting 0 into notification field */ diff --git a/src/backend/commands/cluster.c b/src/backend/commands/cluster.c index 780a60f796..4d5bc491c7 100644 --- a/src/backend/commands/cluster.c +++ b/src/backend/commands/cluster.c @@ -11,7 +11,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/cluster.c,v 1.117 2003/11/09 21:30:36 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/cluster.c,v 1.118 2003/11/12 21:15:49 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -26,7 +26,6 @@ #include "catalog/index.h" #include "catalog/indexing.h" #include "catalog/namespace.h" -#include "catalog/pg_type.h" #include "commands/cluster.h" #include "commands/tablecmds.h" #include "miscadmin.h" @@ -879,10 +878,10 @@ get_tables_to_cluster(MemoryContext cluster_context) * when called with one of them as argument. */ indRelation = relation_openr(IndexRelationName, AccessShareLock); - ScanKeyEntryInitialize(&entry, 0, - Anum_pg_index_indisclustered, - BTEqualStrategyNumber, F_BOOLEQ, - BoolGetDatum(true), BOOLOID); + ScanKeyInit(&entry, + Anum_pg_index_indisclustered, + BTEqualStrategyNumber, F_BOOLEQ, + BoolGetDatum(true)); scan = heap_beginscan(indRelation, SnapshotNow, 1, &entry); while ((indexTuple = heap_getnext(scan, ForwardScanDirection)) != NULL) { diff --git a/src/backend/commands/comment.c b/src/backend/commands/comment.c index fbce38ca57..62765a96e0 100644 --- a/src/backend/commands/comment.c +++ b/src/backend/commands/comment.c @@ -7,7 +7,7 @@ * Copyright (c) 1996-2003, PostgreSQL Global Development Group * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/comment.c,v 1.72 2003/11/09 21:30:36 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/comment.c,v 1.73 2003/11/12 21:15:49 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -156,18 +156,18 @@ CreateComments(Oid oid, Oid classoid, int32 subid, char *comment) /* Use the index to search for a matching old tuple */ - ScanKeyEntryInitialize(&skey[0], 0, - Anum_pg_description_objoid, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(oid), OIDOID); - ScanKeyEntryInitialize(&skey[1], 0, - Anum_pg_description_classoid, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(classoid), OIDOID); - ScanKeyEntryInitialize(&skey[2], 0, - Anum_pg_description_objsubid, - BTEqualStrategyNumber, F_INT4EQ, - Int32GetDatum(subid), INT4OID); + ScanKeyInit(&skey[0], + Anum_pg_description_objoid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(oid)); + ScanKeyInit(&skey[1], + Anum_pg_description_classoid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(classoid)); + ScanKeyInit(&skey[2], + Anum_pg_description_objsubid, + BTEqualStrategyNumber, F_INT4EQ, + Int32GetDatum(subid)); description = heap_openr(DescriptionRelationName, RowExclusiveLock); @@ -231,21 +231,21 @@ DeleteComments(Oid oid, Oid classoid, int32 subid) /* Use the index to search for all matching old tuples */ - ScanKeyEntryInitialize(&skey[0], 0, - Anum_pg_description_objoid, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(oid), OIDOID); - ScanKeyEntryInitialize(&skey[1], 0, - Anum_pg_description_classoid, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(classoid), OIDOID); + ScanKeyInit(&skey[0], + Anum_pg_description_objoid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(oid)); + ScanKeyInit(&skey[1], + Anum_pg_description_classoid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(classoid)); if (subid != 0) { - ScanKeyEntryInitialize(&skey[2], 0, - Anum_pg_description_objsubid, - BTEqualStrategyNumber, F_INT4EQ, - Int32GetDatum(subid), INT4OID); + ScanKeyInit(&skey[2], + Anum_pg_description_objsubid, + BTEqualStrategyNumber, F_INT4EQ, + Int32GetDatum(subid)); nkeys = 3; } else @@ -538,10 +538,10 @@ CommentRule(List *qualname, char *comment) rulename = strVal(lfirst(qualname)); /* Search pg_rewrite for such a rule */ - ScanKeyEntryInitialize(&scanKeyData, 0, - Anum_pg_rewrite_rulename, - BTEqualStrategyNumber, F_NAMEEQ, - PointerGetDatum(rulename), NAMEOID); + ScanKeyInit(&scanKeyData, + Anum_pg_rewrite_rulename, + BTEqualStrategyNumber, F_NAMEEQ, + PointerGetDatum(rulename)); RewriteRelation = heap_openr(RewriteRelationName, AccessShareLock); scanDesc = heap_beginscan(RewriteRelation, SnapshotNow, @@ -791,15 +791,14 @@ CommentTrigger(List *qualname, char *comment) * because of the unique index. */ pg_trigger = heap_openr(TriggerRelationName, AccessShareLock); - ScanKeyEntryInitialize(&entry[0], 0, - Anum_pg_trigger_tgrelid, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(RelationGetRelid(relation)), - OIDOID); - ScanKeyEntryInitialize(&entry[1], 0, - Anum_pg_trigger_tgname, - BTEqualStrategyNumber, F_NAMEEQ, - CStringGetDatum(trigname), NAMEOID); + ScanKeyInit(&entry[0], + Anum_pg_trigger_tgrelid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(RelationGetRelid(relation))); + ScanKeyInit(&entry[1], + Anum_pg_trigger_tgname, + BTEqualStrategyNumber, F_NAMEEQ, + CStringGetDatum(trigname)); scan = systable_beginscan(pg_trigger, TriggerRelidNameIndex, true, SnapshotNow, 2, entry); triggertuple = systable_getnext(scan); @@ -872,11 +871,10 @@ CommentConstraint(List *qualname, char *comment) */ pg_constraint = heap_openr(ConstraintRelationName, AccessShareLock); - ScanKeyEntryInitialize(&skey[0], 0, - Anum_pg_constraint_conrelid, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(RelationGetRelid(relation)), - OIDOID); + ScanKeyInit(&skey[0], + Anum_pg_constraint_conrelid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(RelationGetRelid(relation))); scan = systable_beginscan(pg_constraint, ConstraintRelidIndex, true, SnapshotNow, 1, skey); diff --git a/src/backend/commands/dbcommands.c b/src/backend/commands/dbcommands.c index 5ac51bc84d..320f1fc0de 100644 --- a/src/backend/commands/dbcommands.c +++ b/src/backend/commands/dbcommands.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/dbcommands.c,v 1.125 2003/11/09 21:30:36 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/dbcommands.c,v 1.126 2003/11/12 21:15:50 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -27,7 +27,6 @@ #include "catalog/pg_database.h" #include "catalog/pg_shadow.h" #include "catalog/indexing.h" -#include "catalog/pg_type.h" #include "commands/comment.h" #include "commands/dbcommands.h" #include "miscadmin.h" @@ -531,10 +530,10 @@ dropdb(const char *dbname) /* * Find the database's tuple by OID (should be unique). */ - ScanKeyEntryInitialize(&key, 0, - ObjectIdAttributeNumber, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(db_id), OIDOID); + ScanKeyInit(&key, + ObjectIdAttributeNumber, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(db_id)); pgdbscan = systable_beginscan(pgdbrel, DatabaseOidIndex, true, SnapshotNow, 1, &key); @@ -616,10 +615,10 @@ RenameDatabase(const char *oldname, const char *newname) */ rel = heap_openr(DatabaseRelationName, AccessExclusiveLock); - ScanKeyEntryInitialize(&key, 0, - Anum_pg_database_datname, - BTEqualStrategyNumber, F_NAMEEQ, - NameGetDatum(oldname), NAMEOID); + ScanKeyInit(&key, + Anum_pg_database_datname, + BTEqualStrategyNumber, F_NAMEEQ, + NameGetDatum(oldname)); scan = systable_beginscan(rel, DatabaseNameIndex, true, SnapshotNow, 1, &key); @@ -651,10 +650,10 @@ RenameDatabase(const char *oldname, const char *newname) oldname))); /* make sure the new name doesn't exist */ - ScanKeyEntryInitialize(&key2, 0, - Anum_pg_database_datname, - BTEqualStrategyNumber, F_NAMEEQ, - NameGetDatum(newname), NAMEOID); + ScanKeyInit(&key2, + Anum_pg_database_datname, + BTEqualStrategyNumber, F_NAMEEQ, + NameGetDatum(newname)); scan2 = systable_beginscan(rel, DatabaseNameIndex, true, SnapshotNow, 1, &key2); if (HeapTupleIsValid(systable_getnext(scan2))) @@ -712,10 +711,10 @@ AlterDatabaseSet(AlterDatabaseSetStmt *stmt) valuestr = flatten_set_variable_args(stmt->variable, stmt->value); rel = heap_openr(DatabaseRelationName, RowExclusiveLock); - ScanKeyEntryInitialize(&scankey, 0, - Anum_pg_database_datname, - BTEqualStrategyNumber, F_NAMEEQ, - NameGetDatum(stmt->dbname), NAMEOID); + ScanKeyInit(&scankey, + Anum_pg_database_datname, + BTEqualStrategyNumber, F_NAMEEQ, + NameGetDatum(stmt->dbname)); scan = systable_beginscan(rel, DatabaseNameIndex, true, SnapshotNow, 1, &scankey); tuple = systable_getnext(scan); @@ -795,10 +794,10 @@ get_db_info(const char *name, Oid *dbIdP, int4 *ownerIdP, /* Caller may wish to grab a better lock on pg_database beforehand... */ relation = heap_openr(DatabaseRelationName, AccessShareLock); - ScanKeyEntryInitialize(&scanKey, 0, - Anum_pg_database_datname, - BTEqualStrategyNumber, F_NAMEEQ, - NameGetDatum(name), NAMEOID); + ScanKeyInit(&scanKey, + Anum_pg_database_datname, + BTEqualStrategyNumber, F_NAMEEQ, + NameGetDatum(name)); scan = systable_beginscan(relation, DatabaseNameIndex, true, SnapshotNow, 1, &scanKey); @@ -1001,10 +1000,10 @@ get_database_oid(const char *dbname) /* There's no syscache for pg_database, so must look the hard way */ pg_database = heap_openr(DatabaseRelationName, AccessShareLock); - ScanKeyEntryInitialize(&entry[0], 0, - Anum_pg_database_datname, - BTEqualStrategyNumber, F_NAMEEQ, - CStringGetDatum(dbname), NAMEOID); + ScanKeyInit(&entry[0], + Anum_pg_database_datname, + BTEqualStrategyNumber, F_NAMEEQ, + CStringGetDatum(dbname)); scan = systable_beginscan(pg_database, DatabaseNameIndex, true, SnapshotNow, 1, entry); @@ -1041,10 +1040,10 @@ get_database_name(Oid dbid) /* There's no syscache for pg_database, so must look the hard way */ pg_database = heap_openr(DatabaseRelationName, AccessShareLock); - ScanKeyEntryInitialize(&entry[0], 0, - ObjectIdAttributeNumber, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(dbid), OIDOID); + ScanKeyInit(&entry[0], + ObjectIdAttributeNumber, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(dbid)); scan = systable_beginscan(pg_database, DatabaseOidIndex, true, SnapshotNow, 1, entry); diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c index 9e1e0746f5..7e3c7410a1 100644 --- a/src/backend/commands/functioncmds.c +++ b/src/backend/commands/functioncmds.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/functioncmds.c,v 1.39 2003/11/09 21:30:36 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/functioncmds.c,v 1.40 2003/11/12 21:15:50 tgl Exp $ * * DESCRIPTION * These routines take the parse tree and pick out the @@ -1097,10 +1097,10 @@ DropCastById(Oid castOid) relation = heap_openr(CastRelationName, RowExclusiveLock); - ScanKeyEntryInitialize(&scankey, 0, - ObjectIdAttributeNumber, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(castOid), OIDOID); + ScanKeyInit(&scankey, + ObjectIdAttributeNumber, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(castOid)); scan = systable_beginscan(relation, CastOidIndex, true, SnapshotNow, 1, &scankey); diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c index dbbbc376e0..2f83e22a27 100644 --- a/src/backend/commands/indexcmds.c +++ b/src/backend/commands/indexcmds.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.114 2003/10/02 06:34:03 petere Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.115 2003/11/12 21:15:50 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -416,6 +416,9 @@ GetIndexOpClass(List *opclass, Oid attrType, * Release 7.2 renames timestamp_ops to timestamptz_ops, so suppress that * too for awhile. I'm starting to think we need a better approach. * tgl 2000/10/01 + * + * Release 7.5 removes bigbox_ops (which was dead code for a long while + * anyway). tgl 2003/11/11 */ if (length(opclass) == 1) { @@ -425,7 +428,8 @@ GetIndexOpClass(List *opclass, Oid attrType, strcmp(claname, "timespan_ops") == 0 || strcmp(claname, "datetime_ops") == 0 || strcmp(claname, "lztext_ops") == 0 || - strcmp(claname, "timestamp_ops") == 0) + strcmp(claname, "timestamp_ops") == 0 || + strcmp(claname, "bigbox_ops") == 0) opclass = NIL; } diff --git a/src/backend/commands/opclasscmds.c b/src/backend/commands/opclasscmds.c index 599d2eb825..e251f8577d 100644 --- a/src/backend/commands/opclasscmds.c +++ b/src/backend/commands/opclasscmds.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/opclasscmds.c,v 1.22 2003/11/09 21:30:36 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/opclasscmds.c,v 1.23 2003/11/12 21:15:50 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -25,6 +25,8 @@ #include "catalog/pg_amop.h" #include "catalog/pg_amproc.h" #include "catalog/pg_opclass.h" +#include "catalog/pg_operator.h" +#include "catalog/pg_proc.h" #include "catalog/pg_type.h" #include "commands/defrem.h" #include "miscadmin.h" @@ -38,9 +40,24 @@ #include "utils/syscache.h" -static void storeOperators(Oid opclassoid, int numOperators, - Oid *operators, bool *recheck); -static void storeProcedures(Oid opclassoid, int numProcs, Oid *procedures); +/* + * We use lists of this struct type to keep track of both operators and + * procedures during DefineOpClass. + */ +typedef struct +{ + Oid object; /* operator or support proc's OID */ + int number; /* strategy or support proc number */ + Oid subtype; /* subtype */ + bool recheck; /* oper recheck flag (unused for proc) */ +} OpClassMember; + + +static Oid assignOperSubtype(Oid amoid, Oid typeoid, Oid operOid); +static Oid assignProcSubtype(Oid amoid, Oid typeoid, Oid procOid); +static void addClassMember(List **list, OpClassMember *member, bool isProc); +static void storeOperators(Oid opclassoid, List *operators); +static void storeProcedures(Oid opclassoid, List *procedures); /* @@ -58,10 +75,9 @@ DefineOpClass(CreateOpClassStmt *stmt) opclassoid; /* oid of opclass we create */ int numOperators, /* amstrategies value */ numProcs; /* amsupport value */ - Oid *operators, /* oids of operators, by strategy num */ - *procedures; /* oids of support procs */ - bool *recheck; /* do operators need recheck */ - List *iteml; + List *operators; /* OpClassMember list for operators */ + List *procedures; /* OpClassMember list for support procs */ + List *l; Relation rel; HeapTuple tup; Datum values[Natts_pg_opclass]; @@ -123,26 +139,21 @@ DefineOpClass(CreateOpClassStmt *stmt) format_type_be(typeoid)); #endif + operators = NIL; + procedures = NIL; + /* Storage datatype is optional */ storageoid = InvalidOid; - /* - * Create work arrays to hold info about operators and procedures. We - * do this mainly so that we can detect duplicate strategy numbers and - * support-proc numbers. - */ - operators = (Oid *) palloc0(sizeof(Oid) * numOperators); - procedures = (Oid *) palloc0(sizeof(Oid) * numProcs); - recheck = (bool *) palloc0(sizeof(bool) * numOperators); - /* * Scan the "items" list to obtain additional info. */ - foreach(iteml, stmt->items) + foreach(l, stmt->items) { - CreateOpClassItem *item = lfirst(iteml); + CreateOpClassItem *item = lfirst(l); Oid operOid; Oid funcOid; + OpClassMember *member; AclResult aclresult; Assert(IsA(item, CreateOpClassItem)); @@ -155,11 +166,6 @@ DefineOpClass(CreateOpClassStmt *stmt) errmsg("invalid operator number %d," " must be between 1 and %d", item->number, numOperators))); - if (operators[item->number - 1] != InvalidOid) - ereport(ERROR, - (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), - errmsg("operator number %d appears more than once", - item->number))); if (item->args != NIL) { TypeName *typeName1 = (TypeName *) lfirst(item->args); @@ -183,8 +189,13 @@ DefineOpClass(CreateOpClassStmt *stmt) if (aclresult != ACLCHECK_OK) aclcheck_error(aclresult, ACL_KIND_PROC, get_func_name(funcOid)); - operators[item->number - 1] = operOid; - recheck[item->number - 1] = item->recheck; + /* Save the info */ + member = (OpClassMember *) palloc0(sizeof(OpClassMember)); + member->object = operOid; + member->number = item->number; + member->subtype = assignOperSubtype(amoid, typeoid, operOid); + member->recheck = item->recheck; + addClassMember(&operators, member, false); break; case OPCLASS_ITEM_FUNCTION: if (item->number <= 0 || item->number > numProcs) @@ -193,11 +204,6 @@ DefineOpClass(CreateOpClassStmt *stmt) errmsg("invalid procedure number %d," " must be between 1 and %d", item->number, numProcs))); - if (procedures[item->number - 1] != InvalidOid) - ereport(ERROR, - (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), - errmsg("procedure number %d appears more than once", - item->number))); funcOid = LookupFuncNameTypeNames(item->name, item->args, false); /* Caller must have execute permission on functions */ @@ -206,7 +212,12 @@ DefineOpClass(CreateOpClassStmt *stmt) if (aclresult != ACLCHECK_OK) aclcheck_error(aclresult, ACL_KIND_PROC, get_func_name(funcOid)); - procedures[item->number - 1] = funcOid; + /* Save the info */ + member = (OpClassMember *) palloc0(sizeof(OpClassMember)); + member->object = funcOid; + member->number = item->number; + member->subtype = assignProcSubtype(amoid, typeoid, funcOid); + addClassMember(&procedures, member, true); break; case OPCLASS_ITEM_STORAGETYPE: if (OidIsValid(storageoid)) @@ -271,10 +282,10 @@ DefineOpClass(CreateOpClassStmt *stmt) ScanKeyData skey[1]; SysScanDesc scan; - ScanKeyEntryInitialize(&skey[0], 0, - Anum_pg_opclass_opcamid, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(amoid), OIDOID); + ScanKeyInit(&skey[0], + Anum_pg_opclass_opcamid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(amoid)); scan = systable_beginscan(rel, OpclassAmNameNspIndex, true, SnapshotNow, 1, skey); @@ -327,8 +338,8 @@ DefineOpClass(CreateOpClassStmt *stmt) * Now add tuples to pg_amop and pg_amproc tying in the operators and * functions. */ - storeOperators(opclassoid, numOperators, operators, recheck); - storeProcedures(opclassoid, numProcs, procedures); + storeOperators(opclassoid, operators); + storeProcedures(opclassoid, procedures); /* * Create dependencies. Note: we do not create a dependency link to @@ -361,22 +372,22 @@ DefineOpClass(CreateOpClassStmt *stmt) /* dependencies on operators */ referenced.classId = get_system_catalog_relid(OperatorRelationName); - for (i = 0; i < numOperators; i++) + foreach(l, operators) { - if (operators[i] == InvalidOid) - continue; - referenced.objectId = operators[i]; + OpClassMember *op = (OpClassMember *) lfirst(l); + + referenced.objectId = op->object; referenced.objectSubId = 0; recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); } /* dependencies on procedures */ - for (i = 0; i < numProcs; i++) + foreach(l, procedures) { - if (procedures[i] == InvalidOid) - continue; + OpClassMember *proc = (OpClassMember *) lfirst(l); + referenced.classId = RelOid_pg_proc; - referenced.objectId = procedures[i]; + referenced.objectId = proc->object; referenced.objectSubId = 0; recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); } @@ -384,26 +395,159 @@ DefineOpClass(CreateOpClassStmt *stmt) heap_close(rel, RowExclusiveLock); } +/* + * Determine the subtype to assign to an operator, and do any validity + * checking we can manage + * + * Currently this is done using hardwired rules; we don't let the user + * specify it directly. + */ +static Oid +assignOperSubtype(Oid amoid, Oid typeoid, Oid operOid) +{ + Oid subtype; + Operator optup; + Form_pg_operator opform; + + /* Subtypes are currently only supported by btree, others use 0 */ + if (amoid != BTREE_AM_OID) + return InvalidOid; + + optup = SearchSysCache(OPEROID, + ObjectIdGetDatum(operOid), + 0, 0, 0); + if (optup == NULL) + elog(ERROR, "cache lookup failed for operator %u", operOid); + opform = (Form_pg_operator) GETSTRUCT(optup); + /* + * btree operators must be binary ops returning boolean, and the + * left-side input type must match the operator class' input type. + */ + if (opform->oprkind != 'b') + ereport(ERROR, + (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), + errmsg("btree operators must be binary"))); + if (opform->oprresult != BOOLOID) + ereport(ERROR, + (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), + errmsg("btree operators must return boolean"))); + if (opform->oprleft != typeoid) + ereport(ERROR, + (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), + errmsg("btree operators must have index type as left input"))); + /* + * The subtype is "default" (0) if oprright matches the operator class, + * otherwise it is oprright. + */ + if (opform->oprright == typeoid) + subtype = InvalidOid; + else + subtype = opform->oprright; + ReleaseSysCache(optup); + return subtype; +} + +/* + * Determine the subtype to assign to a support procedure, and do any validity + * checking we can manage + * + * Currently this is done using hardwired rules; we don't let the user + * specify it directly. + */ +static Oid +assignProcSubtype(Oid amoid, Oid typeoid, Oid procOid) +{ + Oid subtype; + HeapTuple proctup; + Form_pg_proc procform; + + /* Subtypes are currently only supported by btree, others use 0 */ + if (amoid != BTREE_AM_OID) + return InvalidOid; + + proctup = SearchSysCache(PROCOID, + ObjectIdGetDatum(procOid), + 0, 0, 0); + if (proctup == NULL) + elog(ERROR, "cache lookup failed for function %u", procOid); + procform = (Form_pg_proc) GETSTRUCT(proctup); + /* + * btree support procs must be 2-arg procs returning int4, and the + * first input type must match the operator class' input type. + */ + if (procform->pronargs != 2) + ereport(ERROR, + (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), + errmsg("btree procedures must have two arguments"))); + if (procform->prorettype != INT4OID) + ereport(ERROR, + (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), + errmsg("btree procedures must return integer"))); + if (procform->proargtypes[0] != typeoid) + ereport(ERROR, + (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), + errmsg("btree procedures must have index type as first input"))); + /* + * The subtype is "default" (0) if second input type matches the operator + * class, otherwise it is the second input type. + */ + if (procform->proargtypes[1] == typeoid) + subtype = InvalidOid; + else + subtype = procform->proargtypes[1]; + ReleaseSysCache(proctup); + return subtype; +} + +/* + * Add a new class member to the appropriate list, after checking for + * duplicated strategy or proc number. + */ +static void +addClassMember(List **list, OpClassMember *member, bool isProc) +{ + List *l; + + foreach(l, *list) + { + OpClassMember *old = (OpClassMember *) lfirst(l); + + if (old->number == member->number && + old->subtype == member->subtype) + { + if (isProc) + ereport(ERROR, + (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), + errmsg("procedure number %d appears more than once", + member->number))); + else + ereport(ERROR, + (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), + errmsg("operator number %d appears more than once", + member->number))); + } + } + *list = lappend(*list, member); +} + /* * Dump the operators to pg_amop */ static void -storeOperators(Oid opclassoid, int numOperators, - Oid *operators, bool *recheck) +storeOperators(Oid opclassoid, List *operators) { Relation rel; Datum values[Natts_pg_amop]; char nulls[Natts_pg_amop]; HeapTuple tup; - int i, - j; + List *l; + int i; rel = heap_openr(AccessMethodOperatorRelationName, RowExclusiveLock); - for (j = 0; j < numOperators; j++) + foreach(l, operators) { - if (operators[j] == InvalidOid) - continue; + OpClassMember *op = (OpClassMember *) lfirst(l); for (i = 0; i < Natts_pg_amop; ++i) { @@ -413,9 +557,10 @@ storeOperators(Oid opclassoid, int numOperators, i = 0; values[i++] = ObjectIdGetDatum(opclassoid); /* amopclaid */ - values[i++] = Int16GetDatum(j + 1); /* amopstrategy */ - values[i++] = BoolGetDatum(recheck[j]); /* amopreqcheck */ - values[i++] = ObjectIdGetDatum(operators[j]); /* amopopr */ + values[i++] = ObjectIdGetDatum(op->subtype); /* amopsubtype */ + values[i++] = Int16GetDatum(op->number); /* amopstrategy */ + values[i++] = BoolGetDatum(op->recheck); /* amopreqcheck */ + values[i++] = ObjectIdGetDatum(op->object); /* amopopr */ tup = heap_formtuple(rel->rd_att, values, nulls); @@ -433,21 +578,20 @@ storeOperators(Oid opclassoid, int numOperators, * Dump the procedures (support routines) to pg_amproc */ static void -storeProcedures(Oid opclassoid, int numProcs, Oid *procedures) +storeProcedures(Oid opclassoid, List *procedures) { Relation rel; Datum values[Natts_pg_amproc]; char nulls[Natts_pg_amproc]; HeapTuple tup; - int i, - j; + List *l; + int i; rel = heap_openr(AccessMethodProcedureRelationName, RowExclusiveLock); - for (j = 0; j < numProcs; j++) + foreach(l, procedures) { - if (procedures[j] == InvalidOid) - continue; + OpClassMember *proc = (OpClassMember *) lfirst(l); for (i = 0; i < Natts_pg_amproc; ++i) { @@ -457,8 +601,9 @@ storeProcedures(Oid opclassoid, int numProcs, Oid *procedures) i = 0; values[i++] = ObjectIdGetDatum(opclassoid); /* amopclaid */ - values[i++] = Int16GetDatum(j + 1); /* amprocnum */ - values[i++] = ObjectIdGetDatum(procedures[j]); /* amproc */ + values[i++] = ObjectIdGetDatum(proc->subtype); /* amprocsubtype */ + values[i++] = Int16GetDatum(proc->number); /* amprocnum */ + values[i++] = ObjectIdGetDatum(proc->object); /* amproc */ tup = heap_formtuple(rel->rd_att, values, nulls); @@ -590,10 +735,10 @@ RemoveOpClassById(Oid opclassOid) /* * Remove associated entries in pg_amop. */ - ScanKeyEntryInitialize(&skey[0], 0, - Anum_pg_amop_amopclaid, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(opclassOid), OIDOID); + ScanKeyInit(&skey[0], + Anum_pg_amop_amopclaid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(opclassOid)); rel = heap_openr(AccessMethodOperatorRelationName, RowExclusiveLock); @@ -609,10 +754,10 @@ RemoveOpClassById(Oid opclassOid) /* * Remove associated entries in pg_amproc. */ - ScanKeyEntryInitialize(&skey[0], 0, - Anum_pg_amproc_amopclaid, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(opclassOid), OIDOID); + ScanKeyInit(&skey[0], + Anum_pg_amproc_amopclaid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(opclassOid)); rel = heap_openr(AccessMethodProcedureRelationName, RowExclusiveLock); diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index df441ca476..feb9720a84 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.92 2003/11/09 21:30:36 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.93 2003/11/12 21:15:51 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1393,20 +1393,20 @@ update_ri_trigger_args(Oid relid, tgrel = heap_openr(TriggerRelationName, RowExclusiveLock); if (fk_scan) { - ScanKeyEntryInitialize(&skey[0], 0, - Anum_pg_trigger_tgconstrrelid, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(relid), OIDOID); + ScanKeyInit(&skey[0], + Anum_pg_trigger_tgconstrrelid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(relid)); trigscan = systable_beginscan(tgrel, TriggerConstrRelidIndex, true, SnapshotNow, 1, skey); } else { - ScanKeyEntryInitialize(&skey[0], 0, - Anum_pg_trigger_tgrelid, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(relid), OIDOID); + ScanKeyInit(&skey[0], + Anum_pg_trigger_tgrelid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(relid)); trigscan = systable_beginscan(tgrel, TriggerRelidNameIndex, true, SnapshotNow, 1, skey); diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c index 80225f8f25..4788d90e58 100644 --- a/src/backend/commands/trigger.c +++ b/src/backend/commands/trigger.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.161 2003/11/09 21:30:36 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.162 2003/11/12 21:15:51 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -253,10 +253,10 @@ CreateTrigger(CreateTrigStmt *stmt, bool forConstraint) * relation, so the trigger set won't be changing underneath us. */ tgrel = heap_openr(TriggerRelationName, RowExclusiveLock); - ScanKeyEntryInitialize(&key, 0, - Anum_pg_trigger_tgrelid, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(RelationGetRelid(rel)), OIDOID); + ScanKeyInit(&key, + Anum_pg_trigger_tgrelid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(RelationGetRelid(rel))); tgscan = systable_beginscan(tgrel, TriggerRelidNameIndex, true, SnapshotNow, 1, &key); while (HeapTupleIsValid(tuple = systable_getnext(tgscan))) @@ -465,15 +465,15 @@ DropTrigger(Oid relid, const char *trigname, DropBehavior behavior) */ tgrel = heap_openr(TriggerRelationName, AccessShareLock); - ScanKeyEntryInitialize(&skey[0], 0, - Anum_pg_trigger_tgrelid, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(relid), OIDOID); + ScanKeyInit(&skey[0], + Anum_pg_trigger_tgrelid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(relid)); - ScanKeyEntryInitialize(&skey[1], 0, - Anum_pg_trigger_tgname, - BTEqualStrategyNumber, F_NAMEEQ, - CStringGetDatum(trigname), NAMEOID); + ScanKeyInit(&skey[1], + Anum_pg_trigger_tgname, + BTEqualStrategyNumber, F_NAMEEQ, + CStringGetDatum(trigname)); tgscan = systable_beginscan(tgrel, TriggerRelidNameIndex, true, SnapshotNow, 2, skey); @@ -524,10 +524,10 @@ RemoveTriggerById(Oid trigOid) /* * Find the trigger to delete. */ - ScanKeyEntryInitialize(&skey[0], 0, - ObjectIdAttributeNumber, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(trigOid), OIDOID); + ScanKeyInit(&skey[0], + ObjectIdAttributeNumber, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(trigOid)); tgscan = systable_beginscan(tgrel, TriggerOidIndex, true, SnapshotNow, 1, skey); @@ -641,14 +641,14 @@ renametrig(Oid relid, /* * First pass -- look for name conflict */ - ScanKeyEntryInitialize(&key[0], 0, - Anum_pg_trigger_tgrelid, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(relid), OIDOID); - ScanKeyEntryInitialize(&key[1], 0, - Anum_pg_trigger_tgname, - BTEqualStrategyNumber, F_NAMEEQ, - PointerGetDatum(newname), NAMEOID); + ScanKeyInit(&key[0], + Anum_pg_trigger_tgrelid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(relid)); + ScanKeyInit(&key[1], + Anum_pg_trigger_tgname, + BTEqualStrategyNumber, F_NAMEEQ, + PointerGetDatum(newname)); tgscan = systable_beginscan(tgrel, TriggerRelidNameIndex, true, SnapshotNow, 2, key); if (HeapTupleIsValid(tuple = systable_getnext(tgscan))) @@ -661,14 +661,14 @@ renametrig(Oid relid, /* * Second pass -- look for trigger existing with oldname and update */ - ScanKeyEntryInitialize(&key[0], 0, - Anum_pg_trigger_tgrelid, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(relid), OIDOID); - ScanKeyEntryInitialize(&key[1], 0, - Anum_pg_trigger_tgname, - BTEqualStrategyNumber, F_NAMEEQ, - PointerGetDatum(oldname), NAMEOID); + ScanKeyInit(&key[0], + Anum_pg_trigger_tgrelid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(relid)); + ScanKeyInit(&key[1], + Anum_pg_trigger_tgname, + BTEqualStrategyNumber, F_NAMEEQ, + PointerGetDatum(oldname)); tgscan = systable_beginscan(tgrel, TriggerRelidNameIndex, true, SnapshotNow, 2, key); if (HeapTupleIsValid(tuple = systable_getnext(tgscan))) @@ -744,11 +744,10 @@ RelationBuildTriggers(Relation relation) * emergency-recovery operations (ie, IsIgnoringSystemIndexes). This * in turn ensures that triggers will be fired in name order. */ - ScanKeyEntryInitialize(&skey, 0, - Anum_pg_trigger_tgrelid, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(RelationGetRelid(relation)), - OIDOID); + ScanKeyInit(&skey, + Anum_pg_trigger_tgrelid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(RelationGetRelid(relation))); tgrel = heap_openr(TriggerRelationName, AccessShareLock); tgscan = systable_beginscan(tgrel, TriggerRelidNameIndex, true, @@ -2262,10 +2261,10 @@ DeferredTriggerSetState(ConstraintsSetStmt *stmt) /* * Setup to scan pg_trigger by tgconstrname ... */ - ScanKeyEntryInitialize(&skey, 0, - Anum_pg_trigger_tgconstrname, - BTEqualStrategyNumber, F_NAMEEQ, - PointerGetDatum(cname), NAMEOID); + ScanKeyInit(&skey, + Anum_pg_trigger_tgconstrname, + BTEqualStrategyNumber, F_NAMEEQ, + PointerGetDatum(cname)); tgscan = systable_beginscan(tgrel, TriggerConstrNameIndex, true, SnapshotNow, 1, &skey); diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c index 17b4df9217..896f104707 100644 --- a/src/backend/commands/typecmds.c +++ b/src/backend/commands/typecmds.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/typecmds.c,v 1.49 2003/11/09 21:30:36 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/typecmds.c,v 1.50 2003/11/12 21:15:51 tgl Exp $ * * DESCRIPTION * The "DefineFoo" routines take the parse tree and pick out the @@ -1362,10 +1362,10 @@ AlterDomainDropConstraint(List *names, const char *constrName, DropBehavior beha conrel = heap_openr(ConstraintRelationName, RowExclusiveLock); /* Use the index to scan only constraints of the target relation */ - ScanKeyEntryInitialize(&key[0], 0, - Anum_pg_constraint_contypid, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(HeapTupleGetOid(tup)), OIDOID); + ScanKeyInit(&key[0], + Anum_pg_constraint_contypid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(HeapTupleGetOid(tup))); conscan = systable_beginscan(conrel, ConstraintTypidIndex, true, SnapshotNow, 1, key); @@ -1615,14 +1615,14 @@ get_rels_with_domain(Oid domainOid, LOCKMODE lockmode) */ depRel = relation_openr(DependRelationName, AccessShareLock); - ScanKeyEntryInitialize(&key[0], 0, - Anum_pg_depend_refclassid, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(RelOid_pg_type), OIDOID); - ScanKeyEntryInitialize(&key[1], 0, - Anum_pg_depend_refobjid, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(domainOid), OIDOID); + ScanKeyInit(&key[0], + Anum_pg_depend_refclassid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(RelOid_pg_type)); + ScanKeyInit(&key[1], + Anum_pg_depend_refobjid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(domainOid)); depScan = systable_beginscan(depRel, DependReferenceIndex, true, SnapshotNow, 2, key); @@ -1901,10 +1901,10 @@ GetDomainConstraints(Oid typeOid) notNull = true; /* Look for CHECK Constraints on this domain */ - ScanKeyEntryInitialize(&key[0], 0, - Anum_pg_constraint_contypid, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(typeOid), OIDOID); + ScanKeyInit(&key[0], + Anum_pg_constraint_contypid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(typeOid)); scan = systable_beginscan(conRel, ConstraintTypidIndex, true, SnapshotNow, 1, key); diff --git a/src/backend/commands/user.c b/src/backend/commands/user.c index 4fad67f43a..869cd84792 100644 --- a/src/backend/commands/user.c +++ b/src/backend/commands/user.c @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Header: /cvsroot/pgsql/src/backend/commands/user.c,v 1.129 2003/11/09 21:30:36 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/user.c,v 1.130 2003/11/12 21:15:51 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1074,10 +1074,10 @@ DropUser(DropUserStmt *stmt) pg_rel = heap_openr(DatabaseRelationName, AccessShareLock); pg_dsc = RelationGetDescr(pg_rel); - ScanKeyEntryInitialize(&scankey, 0, - Anum_pg_database_datdba, - BTEqualStrategyNumber, F_INT4EQ, - Int32GetDatum(usesysid), INT4OID); + ScanKeyInit(&scankey, + Anum_pg_database_datdba, + BTEqualStrategyNumber, F_INT4EQ, + Int32GetDatum(usesysid)); scan = heap_beginscan(pg_rel, SnapshotNow, 1, &scankey); diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c index a4d6de2282..c1c5d64ea2 100644 --- a/src/backend/commands/vacuum.c +++ b/src/backend/commands/vacuum.c @@ -13,7 +13,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.264 2003/11/09 21:30:36 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.265 2003/11/12 21:15:51 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -30,7 +30,6 @@ #include "catalog/namespace.h" #include "catalog/pg_database.h" #include "catalog/pg_index.h" -#include "catalog/pg_type.h" #include "commands/vacuum.h" #include "executor/executor.h" #include "miscadmin.h" @@ -400,10 +399,10 @@ getrels(const RangeVar *vacrel, const char *stmttype) HeapTuple tuple; ScanKeyData key; - ScanKeyEntryInitialize(&key, 0, - Anum_pg_class_relkind, - BTEqualStrategyNumber, F_CHAREQ, - CharGetDatum(RELKIND_RELATION), CHAROID); + ScanKeyInit(&key, + Anum_pg_class_relkind, + BTEqualStrategyNumber, F_CHAREQ, + CharGetDatum(RELKIND_RELATION)); pgclass = heap_openr(RelationRelationName, AccessShareLock); @@ -583,10 +582,10 @@ vac_update_dbstats(Oid dbid, relation = heap_openr(DatabaseRelationName, RowExclusiveLock); /* Must use a heap scan, since there's no syscache for pg_database */ - ScanKeyEntryInitialize(&entry[0], 0, - ObjectIdAttributeNumber, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(dbid), OIDOID); + ScanKeyInit(&entry[0], + ObjectIdAttributeNumber, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(dbid)); scan = heap_beginscan(relation, SnapshotNow, 1, entry); diff --git a/src/backend/executor/nodeIndexscan.c b/src/backend/executor/nodeIndexscan.c index 54114ad924..98158a00c9 100644 --- a/src/backend/executor/nodeIndexscan.c +++ b/src/backend/executor/nodeIndexscan.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/nodeIndexscan.c,v 1.85 2003/11/09 21:30:36 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/nodeIndexscan.c,v 1.86 2003/11/12 21:15:52 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -31,7 +31,6 @@ #include "miscadmin.h" #include "nodes/nodeFuncs.h" #include "optimizer/clauses.h" -#include "parser/parse_expr.h" #include "parser/parsetree.h" @@ -615,6 +614,7 @@ ExecInitIndexScan(IndexScan *node, EState *estate) IndexScanState *indexstate; List *indxqual; List *indxstrategy; + List *indxsubtype; List *indxid; int i; int numIndices; @@ -711,10 +711,12 @@ ExecInitIndexScan(IndexScan *node, EState *estate) */ indxqual = node->indxqual; indxstrategy = node->indxstrategy; + indxsubtype = node->indxsubtype; for (i = 0; i < numIndices; i++) { List *quals; List *strategies; + List *subtypes; int n_keys; ScanKey scan_keys; ExprState **run_keys; @@ -724,6 +726,8 @@ ExecInitIndexScan(IndexScan *node, EState *estate) indxqual = lnext(indxqual); strategies = lfirst(indxstrategy); indxstrategy = lnext(indxstrategy); + subtypes = lfirst(indxsubtype); + indxsubtype = lnext(indxsubtype); n_keys = length(quals); scan_keys = (n_keys <= 0) ? (ScanKey) NULL : (ScanKey) palloc(n_keys * sizeof(ScanKeyData)); @@ -742,9 +746,9 @@ ExecInitIndexScan(IndexScan *node, EState *estate) int flags = 0; AttrNumber varattno; /* att number used in scan */ StrategyNumber strategy; /* op's strategy number */ + Oid subtype; /* op's strategy subtype */ RegProcedure opfuncid; /* operator proc id used in scan */ Datum scanvalue; /* value used in scan (if const) */ - Oid rhstype; /* datatype of comparison value */ /* * extract clause information from the qualification @@ -753,6 +757,8 @@ ExecInitIndexScan(IndexScan *node, EState *estate) quals = lnext(quals); strategy = lfirsti(strategies); strategies = lnext(strategies); + subtype = lfirsto(subtypes); + subtypes = lnext(subtypes); if (!IsA(clause, OpExpr)) elog(ERROR, "indxqual is not an OpExpr"); @@ -795,8 +801,6 @@ ExecInitIndexScan(IndexScan *node, EState *estate) */ rightop = (Expr *) get_rightop((Expr *) clause); - rhstype = exprType((Node *) rightop); - if (rightop && IsA(rightop, RelabelType)) rightop = ((RelabelType *) rightop)->arg; @@ -832,9 +836,9 @@ ExecInitIndexScan(IndexScan *node, EState *estate) varattno, /* attribute number to * scan */ strategy, /* op's strategy */ + subtype, /* strategy subtype */ opfuncid, /* reg proc to use */ - scanvalue, /* constant */ - rhstype); /* constant's type */ + scanvalue); /* constant */ } /* diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c index c02270fa2e..6cf8450567 100644 --- a/src/backend/nodes/copyfuncs.c +++ b/src/backend/nodes/copyfuncs.c @@ -15,7 +15,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.266 2003/11/09 21:30:36 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.267 2003/11/12 21:15:52 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -273,6 +273,17 @@ _copyIndexScan(IndexScan *from) } newnode->indxstrategy = newstrat; } + /* this can become COPY_NODE_FIELD when OID lists are normal objects: */ + { + List *newsubtype = NIL; + List *tmp; + + foreach(tmp, from->indxsubtype) + { + newsubtype = lappend(newsubtype, listCopy(lfirst(tmp))); + } + newnode->indxsubtype = newsubtype; + } COPY_SCALAR_FIELD(indxorderdir); return newnode; diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c index b2fa96bd5d..cb875bd676 100644 --- a/src/backend/nodes/outfuncs.c +++ b/src/backend/nodes/outfuncs.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.219 2003/11/09 21:30:36 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.220 2003/11/12 21:15:52 tgl Exp $ * * NOTES * Every node type that can appear in stored rules' parsetrees *must* @@ -346,6 +346,16 @@ _outIndexScan(StringInfo str, IndexScan *node) _outIntList(str, lfirst(tmp)); } } + /* this can become WRITE_NODE_FIELD when OID lists are normal objects: */ + { + List *tmp; + + appendStringInfo(str, " :indxsubtype "); + foreach(tmp, node->indxsubtype) + { + _outOidList(str, lfirst(tmp)); + } + } WRITE_ENUM_FIELD(indxorderdir, ScanDirection); } diff --git a/src/backend/optimizer/path/indxpath.c b/src/backend/optimizer/path/indxpath.c index 563bd17f41..9c57f12ca6 100644 --- a/src/backend/optimizer/path/indxpath.c +++ b/src/backend/optimizer/path/indxpath.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.147 2003/08/04 02:40:00 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.148 2003/11/12 21:15:52 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1072,7 +1072,7 @@ pred_test_recurse_pred(Expr *predicate, Node *clause) * * If you know, for some ATTR, that "ATTR given_op CONST1" is true, and you * want to determine whether "ATTR target_op CONST2" must also be true, then - * you can use "CONST1 test_op CONST2" as a test. If this test returns true, + * you can use "CONST2 test_op CONST1" as a test. If this test returns true, * then the target expression must be true; if the test returns false, then * the target expression may be false. * @@ -1082,11 +1082,11 @@ pred_test_recurse_pred(Expr *predicate, Node *clause) static const StrategyNumber BT_implic_table[BTMaxStrategyNumber][BTMaxStrategyNumber] = { - {2, 2, 0, 0, 0}, - {1, 2, 0, 0, 0}, - {1, 2, 3, 4, 5}, - {0, 0, 0, 4, 5}, - {0, 0, 0, 4, 4} + {4, 4, 0, 0, 0}, + {5, 4, 0, 0, 0}, + {5, 4, 3, 2, 1}, + {0, 0, 0, 2, 1}, + {0, 0, 0, 2, 2} }; @@ -1118,12 +1118,13 @@ pred_test_simple_clause(Expr *predicate, Node *clause) *clause_const; Oid pred_op, clause_op, - test_op; - Oid opclass_id = InvalidOid; + test_op = InvalidOid; + Oid opclass_id; bool found = false; - StrategyNumber pred_strategy = 0, - clause_strategy = 0, + StrategyNumber pred_strategy, + clause_strategy, test_strategy; + Oid clause_subtype; Expr *test_expr; ExprState *test_exprstate; Datum test_result; @@ -1140,7 +1141,9 @@ pred_test_simple_clause(Expr *predicate, Node *clause) /* * Can't do anything more unless they are both binary opclauses with a * Var on the left and a Const on the right. (XXX someday try to - * commute Const/Var cases?) + * commute Const/Var cases?) Note we don't have to think about binary + * relabeling of the Const node, since that would have been folded right + * into the Const. */ if (!is_opclause(predicate)) return false; @@ -1173,14 +1176,20 @@ pred_test_simple_clause(Expr *predicate, Node *clause) clause_op = ((OpExpr *) clause)->opno; /* - * 1. Find "btree" strategy numbers for the pred_op and clause_op. + * Try to find a btree opclass containing the needed operators. * * We must find a btree opclass that contains both operators, else the - * implication can't be determined. If there are multiple such - * opclasses, assume we can use any one to determine the logical - * relationship of the two operators and the correct corresponding - * test operator. This should work for any logically consistent - * opclasses. + * implication can't be determined. Also, the pred_op has to be of + * default subtype (implying left and right input datatypes are the same); + * otherwise it's unsafe to put the pred_const on the left side of the + * test. Also, the opclass must contain a suitable test operator + * matching the clause_const's type (which we take to mean that it has + * the same subtype as the original clause_operator). + * + * If there are multiple matching opclasses, assume we can use any one to + * determine the logical relationship of the two operators and the correct + * corresponding test operator. This should work for any logically + * consistent opclasses. */ catlist = SearchSysCacheList(AMOPOPID, 1, ObjectIdGetDatum(pred_op), @@ -1192,7 +1201,13 @@ pred_test_simple_clause(Expr *predicate, Node *clause) Form_pg_amop pred_form = (Form_pg_amop) GETSTRUCT(pred_tuple); HeapTuple clause_tuple; - if (!opclass_is_btree(pred_form->amopclaid)) + opclass_id = pred_form->amopclaid; + + /* must be btree */ + if (!opclass_is_btree(opclass_id)) + continue; + /* predicate operator must be default within this opclass */ + if (pred_form->amopsubtype != InvalidOid) continue; /* Get the predicate operator's btree strategy number */ @@ -1200,12 +1215,7 @@ pred_test_simple_clause(Expr *predicate, Node *clause) Assert(pred_strategy >= 1 && pred_strategy <= 5); /* - * Remember which operator class this strategy number came from - */ - opclass_id = pred_form->amopclaid; - - /* - * From the same opclass, find a strategy num for the clause_op, + * From the same opclass, find a strategy number for the clause_op, * if possible */ clause_tuple = SearchSysCache(AMOPOPID, @@ -1216,13 +1226,35 @@ pred_test_simple_clause(Expr *predicate, Node *clause) { Form_pg_amop clause_form = (Form_pg_amop) GETSTRUCT(clause_tuple); - /* Get the restriction clause operator's strategy number */ + /* Get the restriction clause operator's strategy/subtype */ clause_strategy = (StrategyNumber) clause_form->amopstrategy; Assert(clause_strategy >= 1 && clause_strategy <= 5); + clause_subtype = clause_form->amopsubtype; + /* done with clause_tuple */ ReleaseSysCache(clause_tuple); - found = true; - break; + + /* + * Look up the "test" strategy number in the implication table + */ + test_strategy = BT_implic_table[clause_strategy - 1][pred_strategy - 1]; + if (test_strategy == 0) + { + /* Can't determine implication using this interpretation */ + continue; + } + + /* + * See if opclass has an operator for the test strategy and the + * clause datatype. + */ + test_op = get_opclass_member(opclass_id, clause_subtype, + test_strategy); + if (OidIsValid(test_op)) + { + found = true; + break; + } } } @@ -1235,25 +1267,7 @@ pred_test_simple_clause(Expr *predicate, Node *clause) } /* - * 2. Look up the "test" strategy number in the implication table - */ - test_strategy = BT_implic_table[clause_strategy - 1][pred_strategy - 1]; - if (test_strategy == 0) - return false; /* the implication cannot be determined */ - - /* - * 3. From the same opclass, find the operator for the test strategy - */ - test_op = get_opclass_member(opclass_id, test_strategy); - if (!OidIsValid(test_op)) - { - /* This should not fail, else pg_amop entry is missing */ - elog(ERROR, "missing pg_amop entry for opclass %u strategy %d", - opclass_id, test_strategy); - } - - /* - * 4. Evaluate the test. For this we need an EState. + * Evaluate the test. For this we need an EState. */ estate = CreateExecutorState(); @@ -1264,8 +1278,8 @@ pred_test_simple_clause(Expr *predicate, Node *clause) test_expr = make_opclause(test_op, BOOLOID, false, - (Expr *) clause_const, - (Expr *) pred_const); + (Expr *) pred_const, + (Expr *) clause_const); /* Prepare it for execution */ test_exprstate = ExecPrepareExpr(test_expr, estate); @@ -1907,7 +1921,7 @@ match_special_index_operator(Expr *clause, Oid opclass, * (The latter is not depended on by any part of the planner, so far as I can * tell; but some parts of the executor do assume that the indxqual list * ultimately delivered to the executor is so ordered. One such place is - * _bt_orderkeys() in the btree support. Perhaps that ought to be fixed + * _bt_preprocess_keys() in the btree support. Perhaps that ought to be fixed * someday --- tgl 7/00) */ List * @@ -2103,7 +2117,8 @@ prefix_quals(Node *leftop, Oid opclass, */ if (pstatus == Pattern_Prefix_Exact) { - oproid = get_opclass_member(opclass, BTEqualStrategyNumber); + oproid = get_opclass_member(opclass, InvalidOid, + BTEqualStrategyNumber); if (oproid == InvalidOid) elog(ERROR, "no = operator for opclass %u", opclass); expr = make_opclause(oproid, BOOLOID, false, @@ -2117,7 +2132,8 @@ prefix_quals(Node *leftop, Oid opclass, * * We can always say "x >= prefix". */ - oproid = get_opclass_member(opclass, BTGreaterEqualStrategyNumber); + oproid = get_opclass_member(opclass, InvalidOid, + BTGreaterEqualStrategyNumber); if (oproid == InvalidOid) elog(ERROR, "no >= operator for opclass %u", opclass); expr = make_opclause(oproid, BOOLOID, false, @@ -2132,7 +2148,8 @@ prefix_quals(Node *leftop, Oid opclass, greaterstr = make_greater_string(prefix_const); if (greaterstr) { - oproid = get_opclass_member(opclass, BTLessStrategyNumber); + oproid = get_opclass_member(opclass, InvalidOid, + BTLessStrategyNumber); if (oproid == InvalidOid) elog(ERROR, "no < operator for opclass %u", opclass); expr = make_opclause(oproid, BOOLOID, false, @@ -2189,13 +2206,15 @@ network_prefix_quals(Node *leftop, Oid expr_op, Oid opclass, Datum rightop) */ if (is_eq) { - opr1oid = get_opclass_member(opclass, BTGreaterEqualStrategyNumber); + opr1oid = get_opclass_member(opclass, InvalidOid, + BTGreaterEqualStrategyNumber); if (opr1oid == InvalidOid) elog(ERROR, "no >= operator for opclass %u", opclass); } else { - opr1oid = get_opclass_member(opclass, BTGreaterStrategyNumber); + opr1oid = get_opclass_member(opclass, InvalidOid, + BTGreaterStrategyNumber); if (opr1oid == InvalidOid) elog(ERROR, "no > operator for opclass %u", opclass); } @@ -2210,7 +2229,8 @@ network_prefix_quals(Node *leftop, Oid expr_op, Oid opclass, Datum rightop) /* create clause "key <= network_scan_last( rightop )" */ - opr2oid = get_opclass_member(opclass, BTLessEqualStrategyNumber); + opr2oid = get_opclass_member(opclass, InvalidOid, + BTLessEqualStrategyNumber); if (opr2oid == InvalidOid) elog(ERROR, "no <= operator for opclass %u", opclass); diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c index 37478d7de0..a5efcb339e 100644 --- a/src/backend/optimizer/plan/createplan.c +++ b/src/backend/optimizer/plan/createplan.c @@ -10,7 +10,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.158 2003/11/09 21:30:36 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.159 2003/11/12 21:15:53 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -63,13 +63,15 @@ static HashJoin *create_hashjoin_plan(Query *root, HashPath *best_path, static void fix_indxqual_references(List *indexquals, IndexPath *index_path, List **fixed_indexquals, List **recheck_indexquals, - List **indxstrategy); + List **indxstrategy, + List **indxsubtype); static void fix_indxqual_sublist(List *indexqual, Relids baserelids, int baserelid, IndexOptInfo *index, List **fixed_quals, List **recheck_quals, - List **strategy); + List **strategy, + List **subtype); static Node *fix_indxqual_operand(Node *node, int baserelid, IndexOptInfo *index, Oid *opclass); @@ -79,8 +81,8 @@ static void copy_path_costsize(Plan *dest, Path *src); static void copy_plan_costsize(Plan *dest, Plan *src); static SeqScan *make_seqscan(List *qptlist, List *qpqual, Index scanrelid); static IndexScan *make_indexscan(List *qptlist, List *qpqual, Index scanrelid, - List *indxid, List *indxqual, - List *indxqualorig, List *indxstrategy, + List *indxid, List *indxqual, List *indxqualorig, + List *indxstrategy, List *indxsubtype, ScanDirection indexscandir); static TidScan *make_tidscan(List *qptlist, List *qpqual, Index scanrelid, List *tideval); @@ -704,6 +706,7 @@ create_indexscan_plan(Query *root, List *fixed_indxqual; List *recheck_indxqual; List *indxstrategy; + List *indxsubtype; FastList indexids; List *ixinfo; IndexScan *scan_plan; @@ -771,7 +774,7 @@ create_indexscan_plan(Query *root, */ fix_indxqual_references(indxqual, best_path, &fixed_indxqual, &recheck_indxqual, - &indxstrategy); + &indxstrategy, &indxsubtype); /* * If there were any "lossy" operators, need to add back the @@ -804,6 +807,7 @@ create_indexscan_plan(Query *root, fixed_indxqual, indxqual, indxstrategy, + indxsubtype, best_path->indexscandir); copy_path_costsize(&scan_plan->scan.plan, &best_path->path); @@ -1151,8 +1155,8 @@ create_hashjoin_plan(Query *root, * must add (the original form of) the indexqual clause to the "qpquals" * of the indexscan node, where the operator will be re-evaluated to * ensure it passes. - * * We must construct a list of operator strategy numbers corresponding - * to the top-level operators of each index clause. + * * We must construct lists of operator strategy numbers and subtypes for + * the top-level operators of each index clause. * * Both the input list and the output lists have the form of lists of sublists * of qual clauses --- the top-level list has one entry for each indexscan @@ -1167,11 +1171,12 @@ create_hashjoin_plan(Query *root, * need rechecking. * * indxstrategy receives a list of integer sublists of strategy numbers. + * indxsubtype receives a list of OID sublists of strategy subtypes. */ static void fix_indxqual_references(List *indexquals, IndexPath *index_path, List **fixed_indexquals, List **recheck_indexquals, - List **indxstrategy) + List **indxstrategy, List **indxsubtype) { FastList fixed_quals; FastList recheck_quals; @@ -1183,6 +1188,7 @@ fix_indxqual_references(List *indexquals, IndexPath *index_path, FastListInit(&fixed_quals); FastListInit(&recheck_quals); *indxstrategy = NIL; + *indxsubtype = NIL; foreach(i, indexquals) { List *indexqual = lfirst(i); @@ -1190,13 +1196,16 @@ fix_indxqual_references(List *indexquals, IndexPath *index_path, List *fixed_qual; List *recheck_qual; List *strategy; + List *subtype; fix_indxqual_sublist(indexqual, baserelids, baserelid, index, - &fixed_qual, &recheck_qual, &strategy); + &fixed_qual, &recheck_qual, + &strategy, &subtype); FastAppend(&fixed_quals, fixed_qual); if (recheck_qual != NIL) FastAppend(&recheck_quals, recheck_qual); *indxstrategy = lappend(*indxstrategy, strategy); + *indxsubtype = lappend(*indxsubtype, subtype); ixinfo = lnext(ixinfo); } @@ -1211,12 +1220,15 @@ fix_indxqual_references(List *indexquals, IndexPath *index_path, * For each qual clause, commute if needed to put the indexkey operand on the * left, and then fix its varattno. (We do not need to change the other side * of the clause.) Also change the operator if necessary, check for - * lossy index behavior, and determine the operator's strategy number. + * lossy index behavior, and determine the operator's strategy number and + * subtype number. * - * Returns three lists: the list of fixed indexquals, the list (usually - * empty) of original clauses that must be rechecked as qpquals because - * the index is lossy for this operator type, and the integer list of - * strategy numbers. + * Returns four lists: + * the list of fixed indexquals + * the list (usually empty) of original clauses that must be rechecked + * as qpquals because the index is lossy for this operator type + * the integer list of strategy numbers + * the OID list of strategy subtypes */ static void fix_indxqual_sublist(List *indexqual, @@ -1224,7 +1236,8 @@ fix_indxqual_sublist(List *indexqual, IndexOptInfo *index, List **fixed_quals, List **recheck_quals, - List **strategy) + List **strategy, + List **subtype) { FastList fixed_qual; FastList recheck_qual; @@ -1233,6 +1246,7 @@ fix_indxqual_sublist(List *indexqual, FastListInit(&fixed_qual); FastListInit(&recheck_qual); *strategy = NIL; + *subtype = NIL; foreach(i, indexqual) { OpExpr *clause = (OpExpr *) lfirst(i); @@ -1240,6 +1254,7 @@ fix_indxqual_sublist(List *indexqual, Relids leftvarnos; Oid opclass; int stratno; + Oid stratsubtype; bool recheck; if (!IsA(clause, OpExpr) || @@ -1278,13 +1293,14 @@ fix_indxqual_sublist(List *indexqual, /* * Look up the operator in the operator class to get its strategy - * number and the recheck indicator. This also double-checks that + * numbers and the recheck indicator. This also double-checks that * we found an operator matching the index. */ get_op_opclass_properties(newclause->opno, opclass, - &stratno, &recheck); + &stratno, &stratsubtype, &recheck); *strategy = lappendi(*strategy, stratno); + *subtype = lappendo(*subtype, stratsubtype); /* * If index is lossy for this operator, add (a copy of) original form @@ -1540,6 +1556,7 @@ make_indexscan(List *qptlist, List *indxqual, List *indxqualorig, List *indxstrategy, + List *indxsubtype, ScanDirection indexscandir) { IndexScan *node = makeNode(IndexScan); @@ -1555,6 +1572,7 @@ make_indexscan(List *qptlist, node->indxqual = indxqual; node->indxqualorig = indxqualorig; node->indxstrategy = indxstrategy; + node->indxsubtype = indxsubtype; node->indxorderdir = indexscandir; return node; diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index 8e621dd063..8c42b431aa 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/util/plancat.c,v 1.88 2003/11/09 21:30:37 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/util/plancat.c,v 1.89 2003/11/12 21:15:54 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -23,7 +23,6 @@ #include "catalog/pg_amop.h" #include "catalog/pg_inherits.h" #include "catalog/pg_index.h" -#include "catalog/pg_type.h" #include "nodes/makefuncs.h" #include "optimizer/clauses.h" #include "optimizer/plancat.h" @@ -329,10 +328,10 @@ find_inheritance_children(Oid inhparent) if (!has_subclass(inhparent)) return NIL; - ScanKeyEntryInitialize(&key[0], 0, - Anum_pg_inherits_inhparent, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(inhparent), OIDOID); + ScanKeyInit(&key[0], + Anum_pg_inherits_inhparent, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(inhparent)); relation = heap_openr(InheritsRelationName, AccessShareLock); scan = heap_beginscan(relation, SnapshotNow, 1, key); while ((inheritsTuple = heap_getnext(scan, ForwardScanDirection)) != NULL) diff --git a/src/backend/parser/parse_func.c b/src/backend/parser/parse_func.c index 95b5dc37cc..1068f036d1 100644 --- a/src/backend/parser/parse_func.c +++ b/src/backend/parser/parse_func.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.162 2003/11/09 21:30:37 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.163 2003/11/12 21:15:54 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1039,10 +1039,10 @@ find_inheritors(Oid relid, Oid **supervec) { /* find all types this relid inherits from, and add them to queue */ - ScanKeyEntryInitialize(&skey, 0, - Anum_pg_inherits_inhrelid, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(relid), OIDOID); + ScanKeyInit(&skey, + Anum_pg_inherits_inhrelid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(relid)); inhscan = heap_beginscan(inhrel, SnapshotNow, 1, &skey); diff --git a/src/backend/rewrite/rewriteRemove.c b/src/backend/rewrite/rewriteRemove.c index 53f94137e1..0c36b127a1 100644 --- a/src/backend/rewrite/rewriteRemove.c +++ b/src/backend/rewrite/rewriteRemove.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteRemove.c,v 1.57 2003/11/09 21:30:37 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteRemove.c,v 1.58 2003/11/12 21:15:54 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -20,7 +20,6 @@ #include "catalog/dependency.h" #include "catalog/indexing.h" #include "catalog/pg_rewrite.h" -#include "catalog/pg_type.h" #include "miscadmin.h" #include "rewrite/rewriteRemove.h" #include "rewrite/rewriteSupport.h" @@ -105,10 +104,10 @@ RemoveRewriteRuleById(Oid ruleOid) /* * Find the tuple for the target rule. */ - ScanKeyEntryInitialize(&skey[0], 0, - ObjectIdAttributeNumber, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(ruleOid), OIDOID); + ScanKeyInit(&skey[0], + ObjectIdAttributeNumber, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(ruleOid)); rcscan = systable_beginscan(RewriteRelation, RewriteOidIndex, true, SnapshotNow, 1, skey); diff --git a/src/backend/storage/large_object/inv_api.c b/src/backend/storage/large_object/inv_api.c index 33e40109d3..f777fb33b9 100644 --- a/src/backend/storage/large_object/inv_api.c +++ b/src/backend/storage/large_object/inv_api.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/storage/large_object/inv_api.c,v 1.99 2003/11/09 21:30:37 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/storage/large_object/inv_api.c,v 1.100 2003/11/12 21:15:54 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -202,10 +202,10 @@ inv_getsize(LargeObjectDesc *obj_desc) Assert(PointerIsValid(obj_desc)); - ScanKeyEntryInitialize(&skey[0], 0, - Anum_pg_largeobject_loid, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(obj_desc->id), OIDOID); + ScanKeyInit(&skey[0], + Anum_pg_largeobject_loid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(obj_desc->id)); sd = index_beginscan(obj_desc->heap_r, obj_desc->index_r, SnapshotNow, 1, skey); @@ -306,15 +306,15 @@ inv_read(LargeObjectDesc *obj_desc, char *buf, int nbytes) if (nbytes <= 0) return 0; - ScanKeyEntryInitialize(&skey[0], 0, - Anum_pg_largeobject_loid, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(obj_desc->id), OIDOID); + ScanKeyInit(&skey[0], + Anum_pg_largeobject_loid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(obj_desc->id)); - ScanKeyEntryInitialize(&skey[1], 0, - Anum_pg_largeobject_pageno, - BTGreaterEqualStrategyNumber, F_INT4GE, - Int32GetDatum(pageno), INT4OID); + ScanKeyInit(&skey[1], + Anum_pg_largeobject_pageno, + BTGreaterEqualStrategyNumber, F_INT4GE, + Int32GetDatum(pageno)); sd = index_beginscan(obj_desc->heap_r, obj_desc->index_r, SnapshotNow, 2, skey); @@ -413,15 +413,15 @@ inv_write(LargeObjectDesc *obj_desc, char *buf, int nbytes) indstate = CatalogOpenIndexes(obj_desc->heap_r); - ScanKeyEntryInitialize(&skey[0], 0, - Anum_pg_largeobject_loid, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(obj_desc->id), OIDOID); + ScanKeyInit(&skey[0], + Anum_pg_largeobject_loid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(obj_desc->id)); - ScanKeyEntryInitialize(&skey[1], 0, - Anum_pg_largeobject_pageno, - BTGreaterEqualStrategyNumber, F_INT4GE, - Int32GetDatum(pageno), INT4OID); + ScanKeyInit(&skey[1], + Anum_pg_largeobject_pageno, + BTGreaterEqualStrategyNumber, F_INT4GE, + Int32GetDatum(pageno)); sd = index_beginscan(obj_desc->heap_r, obj_desc->index_r, SnapshotNow, 2, skey); diff --git a/src/backend/utils/adt/float.c b/src/backend/utils/adt/float.c index 9f0fa0de32..1493a58de7 100644 --- a/src/backend/utils/adt/float.c +++ b/src/backend/utils/adt/float.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/float.c,v 1.94 2003/09/25 06:58:03 petere Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/float.c,v 1.95 2003/11/12 21:15:54 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -839,6 +839,26 @@ btfloat8cmp(PG_FUNCTION_ARGS) PG_RETURN_INT32(float8_cmp_internal(arg1, arg2)); } +Datum +btfloat48cmp(PG_FUNCTION_ARGS) +{ + float4 arg1 = PG_GETARG_FLOAT4(0); + float8 arg2 = PG_GETARG_FLOAT8(1); + + /* widen float4 to float8 and then compare */ + PG_RETURN_INT32(float8_cmp_internal(arg1, arg2)); +} + +Datum +btfloat84cmp(PG_FUNCTION_ARGS) +{ + float8 arg1 = PG_GETARG_FLOAT8(0); + float4 arg2 = PG_GETARG_FLOAT4(1); + + /* widen float4 to float8 and then compare */ + PG_RETURN_INT32(float8_cmp_internal(arg1, arg2)); +} + /* * =================== diff --git a/src/backend/utils/adt/regproc.c b/src/backend/utils/adt/regproc.c index 211549afea..ee8a00912a 100644 --- a/src/backend/utils/adt/regproc.c +++ b/src/backend/utils/adt/regproc.c @@ -13,7 +13,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/regproc.c,v 1.83 2003/11/09 21:30:37 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/regproc.c,v 1.84 2003/11/12 21:15:54 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -92,10 +92,10 @@ regprocin(PG_FUNCTION_ARGS) SysScanDesc sysscan; HeapTuple tuple; - ScanKeyEntryInitialize(&skey[0], 0, - Anum_pg_proc_proname, - BTEqualStrategyNumber, F_NAMEEQ, - CStringGetDatum(pro_name_or_oid), NAMEOID); + ScanKeyInit(&skey[0], + Anum_pg_proc_proname, + BTEqualStrategyNumber, F_NAMEEQ, + CStringGetDatum(pro_name_or_oid)); hdesc = heap_openr(ProcedureRelationName, AccessShareLock); sysscan = systable_beginscan(hdesc, ProcedureNameNspIndex, true, @@ -442,10 +442,10 @@ regoperin(PG_FUNCTION_ARGS) SysScanDesc sysscan; HeapTuple tuple; - ScanKeyEntryInitialize(&skey[0], 0, - Anum_pg_operator_oprname, - BTEqualStrategyNumber, F_NAMEEQ, - CStringGetDatum(opr_name_or_oid), NAMEOID); + ScanKeyInit(&skey[0], + Anum_pg_operator_oprname, + BTEqualStrategyNumber, F_NAMEEQ, + CStringGetDatum(opr_name_or_oid)); hdesc = heap_openr(OperatorRelationName, AccessShareLock); sysscan = systable_beginscan(hdesc, OperatorNameNspIndex, true, @@ -820,10 +820,10 @@ regclassin(PG_FUNCTION_ARGS) SysScanDesc sysscan; HeapTuple tuple; - ScanKeyEntryInitialize(&skey[0], 0, - Anum_pg_class_relname, - BTEqualStrategyNumber, F_NAMEEQ, - CStringGetDatum(class_name_or_oid), NAMEOID); + ScanKeyInit(&skey[0], + Anum_pg_class_relname, + BTEqualStrategyNumber, F_NAMEEQ, + CStringGetDatum(class_name_or_oid)); hdesc = heap_openr(RelationRelationName, AccessShareLock); sysscan = systable_beginscan(hdesc, ClassNameNspIndex, true, @@ -986,10 +986,10 @@ regtypein(PG_FUNCTION_ARGS) SysScanDesc sysscan; HeapTuple tuple; - ScanKeyEntryInitialize(&skey[0], 0, - Anum_pg_type_typname, - BTEqualStrategyNumber, F_NAMEEQ, - CStringGetDatum(typ_name_or_oid), NAMEOID); + ScanKeyInit(&skey[0], + Anum_pg_type_typname, + BTEqualStrategyNumber, F_NAMEEQ, + CStringGetDatum(typ_name_or_oid)); hdesc = heap_openr(TypeRelationName, AccessShareLock); sysscan = systable_beginscan(hdesc, TypeNameNspIndex, true, diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c index fe749cc9b1..70d5626948 100644 --- a/src/backend/utils/adt/ruleutils.c +++ b/src/backend/utils/adt/ruleutils.c @@ -3,7 +3,7 @@ * back to source text * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.158 2003/11/09 21:30:37 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.159 2003/11/12 21:15:55 tgl Exp $ * * This software is copyrighted by Jan Wieck - Hamburg. * @@ -488,10 +488,10 @@ pg_get_triggerdef(PG_FUNCTION_ARGS) */ tgrel = heap_openr(TriggerRelationName, AccessShareLock); - ScanKeyEntryInitialize(&skey[0], 0, - ObjectIdAttributeNumber, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(trigid), OIDOID); + ScanKeyInit(&skey[0], + ObjectIdAttributeNumber, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(trigid)); tgscan = systable_beginscan(tgrel, TriggerOidIndex, true, SnapshotNow, 1, skey); @@ -886,10 +886,10 @@ pg_get_constraintdef_worker(Oid constraintId, int prettyFlags) */ conDesc = heap_openr(ConstraintRelationName, AccessShareLock); - ScanKeyEntryInitialize(&skey[0], 0, - ObjectIdAttributeNumber, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(constraintId), OIDOID); + ScanKeyInit(&skey[0], + ObjectIdAttributeNumber, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(constraintId)); conscan = systable_beginscan(conDesc, ConstraintOidIndex, true, SnapshotNow, 1, skey); diff --git a/src/backend/utils/adt/selfuncs.c b/src/backend/utils/adt/selfuncs.c index 978c020146..3c4b780c56 100644 --- a/src/backend/utils/adt/selfuncs.c +++ b/src/backend/utils/adt/selfuncs.c @@ -15,7 +15,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/selfuncs.c,v 1.147 2003/10/16 21:37:54 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/selfuncs.c,v 1.148 2003/11/12 21:15:55 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -952,7 +952,8 @@ patternsel(PG_FUNCTION_ARGS, Pattern_Type ptype) /* * Pattern specifies an exact match, so pretend operator is '=' */ - Oid eqopr = get_opclass_member(opclass, BTEqualStrategyNumber); + Oid eqopr = get_opclass_member(opclass, InvalidOid, + BTEqualStrategyNumber); List *eqargs; if (eqopr == InvalidOid) @@ -3382,7 +3383,8 @@ prefix_selectivity(Query *root, Var *var, Oid opclass, Const *prefixcon) List *cmpargs; Const *greaterstrcon; - cmpopr = get_opclass_member(opclass, BTGreaterEqualStrategyNumber); + cmpopr = get_opclass_member(opclass, InvalidOid, + BTGreaterEqualStrategyNumber); if (cmpopr == InvalidOid) elog(ERROR, "no >= operator for opclass %u", opclass); cmpargs = makeList2(var, prefixcon); @@ -3403,7 +3405,8 @@ prefix_selectivity(Query *root, Var *var, Oid opclass, Const *prefixcon) { Selectivity topsel; - cmpopr = get_opclass_member(opclass, BTLessStrategyNumber); + cmpopr = get_opclass_member(opclass, InvalidOid, + BTLessStrategyNumber); if (cmpopr == InvalidOid) elog(ERROR, "no < operator for opclass %u", opclass); cmpargs = makeList2(var, greaterstrcon); diff --git a/src/backend/utils/cache/catcache.c b/src/backend/utils/cache/catcache.c index 640629c3a0..36125c2374 100644 --- a/src/backend/utils/cache/catcache.c +++ b/src/backend/utils/cache/catcache.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/cache/catcache.c,v 1.109 2003/11/09 21:30:37 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/cache/catcache.c,v 1.110 2003/11/12 21:15:55 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -967,9 +967,9 @@ CatalogCacheInitializeCache(CatCache *cache) /* Initialize sk_attno suitably for HeapKeyTest() and heap scans */ cache->cc_skey[i].sk_attno = cache->cc_key[i]; - /* Fill in sk_strategy and sk_argtype correctly as well */ + /* Fill in sk_strategy as well --- always standard equality */ cache->cc_skey[i].sk_strategy = BTEqualStrategyNumber; - cache->cc_skey[i].sk_argtype = keytype; + cache->cc_skey[i].sk_subtype = InvalidOid; CACHE4_elog(DEBUG2, "CatalogCacheInit %s %d %p", cache->cc_relname, diff --git a/src/backend/utils/cache/lsyscache.c b/src/backend/utils/cache/lsyscache.c index bed4fcdbce..20c10802bc 100644 --- a/src/backend/utils/cache/lsyscache.c +++ b/src/backend/utils/cache/lsyscache.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.109 2003/11/09 21:30:37 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.110 2003/11/12 21:15:55 tgl Exp $ * * NOTES * Eventually, the index information should go through here, too. @@ -55,7 +55,7 @@ op_in_opclass(Oid opno, Oid opclass) /* * get_op_opclass_properties * - * Get the operator's strategy number and recheck (lossy) flag + * Get the operator's strategy number, subtype, and recheck (lossy) flag * within the specified opclass. * * Caller should already have verified that opno is a member of opclass, @@ -63,7 +63,7 @@ op_in_opclass(Oid opno, Oid opclass) */ void get_op_opclass_properties(Oid opno, Oid opclass, - int *strategy, bool *recheck) + int *strategy, Oid *subtype, bool *recheck) { HeapTuple tp; Form_pg_amop amop_tup; @@ -77,6 +77,7 @@ get_op_opclass_properties(Oid opno, Oid opclass, opno, opclass); amop_tup = (Form_pg_amop) GETSTRUCT(tp); *strategy = amop_tup->amopstrategy; + *subtype = amop_tup->amopsubtype; *recheck = amop_tup->amopreqcheck; ReleaseSysCache(tp); } @@ -84,12 +85,12 @@ get_op_opclass_properties(Oid opno, Oid opclass, /* * get_opclass_member * Get the OID of the operator that implements the specified strategy - * for the specified opclass. + * with the specified subtype for the specified opclass. * * Returns InvalidOid if there is no pg_amop entry for the given keys. */ Oid -get_opclass_member(Oid opclass, int16 strategy) +get_opclass_member(Oid opclass, Oid subtype, int16 strategy) { HeapTuple tp; Form_pg_amop amop_tup; @@ -97,8 +98,9 @@ get_opclass_member(Oid opclass, int16 strategy) tp = SearchSysCache(AMOPSTRATEGY, ObjectIdGetDatum(opclass), + ObjectIdGetDatum(subtype), Int16GetDatum(strategy), - 0, 0); + 0); if (!HeapTupleIsValid(tp)) return InvalidOid; amop_tup = (Form_pg_amop) GETSTRUCT(tp); @@ -149,8 +151,8 @@ get_op_hash_function(Oid opno) if (OidIsValid(opclass)) { - /* Found a suitable opclass, get its hash support function */ - return get_opclass_proc(opclass, HASHPROC); + /* Found a suitable opclass, get its default hash support function */ + return get_opclass_proc(opclass, InvalidOid, HASHPROC); } /* Didn't find a match... */ @@ -163,12 +165,12 @@ get_op_hash_function(Oid opno) /* * get_opclass_proc * Get the OID of the specified support function - * for the specified opclass. + * for the specified opclass and subtype. * * Returns InvalidOid if there is no pg_amproc entry for the given keys. */ Oid -get_opclass_proc(Oid opclass, int16 procnum) +get_opclass_proc(Oid opclass, Oid subtype, int16 procnum) { HeapTuple tp; Form_pg_amproc amproc_tup; @@ -176,8 +178,9 @@ get_opclass_proc(Oid opclass, int16 procnum) tp = SearchSysCache(AMPROCNUM, ObjectIdGetDatum(opclass), + ObjectIdGetDatum(subtype), Int16GetDatum(procnum), - 0, 0); + 0); if (!HeapTupleIsValid(tp)) return InvalidOid; amproc_tup = (Form_pg_amproc) GETSTRUCT(tp); diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index 88c8cbb141..ac5e53a91a 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.191 2003/11/09 21:30:37 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.192 2003/11/12 21:15:56 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -262,7 +262,7 @@ do { \ /* * Special cache for opclass-related information * - * Note: only non-cross-type operators and support procs get cached + * Note: only default-subtype operators and support procs get cached */ typedef struct opclasscacheent { @@ -336,26 +336,23 @@ ScanPgRelation(RelationBuildDescInfo buildinfo, bool indexOK) switch (buildinfo.infotype) { case INFO_RELID: - ScanKeyEntryInitialize(&key[0], 0, - ObjectIdAttributeNumber, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(buildinfo.i.info_id), - OIDOID); + ScanKeyInit(&key[0], + ObjectIdAttributeNumber, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(buildinfo.i.info_id)); nkeys = 1; indexRelname = ClassOidIndex; break; case INFO_RELNAME: - ScanKeyEntryInitialize(&key[0], 0, - Anum_pg_class_relname, - BTEqualStrategyNumber, F_NAMEEQ, - NameGetDatum(buildinfo.i.info_name), - NAMEOID); - ScanKeyEntryInitialize(&key[1], 0, - Anum_pg_class_relnamespace, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(PG_CATALOG_NAMESPACE), - OIDOID); + ScanKeyInit(&key[0], + Anum_pg_class_relname, + BTEqualStrategyNumber, F_NAMEEQ, + NameGetDatum(buildinfo.i.info_name)); + ScanKeyInit(&key[1], + Anum_pg_class_relnamespace, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(PG_CATALOG_NAMESPACE)); nkeys = 2; indexRelname = ClassNameNspIndex; break; @@ -483,15 +480,14 @@ RelationBuildTupleDesc(RelationBuildDescInfo buildinfo, * (Eliminating system attribute rows at the index level is lots * faster than fetching them.) */ - ScanKeyEntryInitialize(&skey[0], 0, - Anum_pg_attribute_attrelid, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(RelationGetRelid(relation)), - OIDOID); - ScanKeyEntryInitialize(&skey[1], 0, - Anum_pg_attribute_attnum, - BTGreaterStrategyNumber, F_INT2GT, - Int16GetDatum(0), INT2OID); + ScanKeyInit(&skey[0], + Anum_pg_attribute_attrelid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(RelationGetRelid(relation))); + ScanKeyInit(&skey[1], + Anum_pg_attribute_attnum, + BTGreaterStrategyNumber, F_INT2GT, + Int16GetDatum(0)); /* * Open pg_attribute and begin a scan. Force heap scan if we haven't @@ -673,11 +669,10 @@ RelationBuildRuleLock(Relation relation) /* * form a scan key */ - ScanKeyEntryInitialize(&key, 0, - Anum_pg_rewrite_ev_class, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(RelationGetRelid(relation)), - OIDOID); + ScanKeyInit(&key, + Anum_pg_rewrite_ev_class, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(RelationGetRelid(relation))); /* * open pg_rewrite and begin a scan @@ -1058,7 +1053,7 @@ RelationInitIndexAccessInfo(Relation relation) /* * IndexSupportInitialize - * Initializes an index's cached lists of operators and support procs, + * Initializes an index's cached opclass information, * given the index's pg_index tuple. * * Data is returned into *indexOperator and *indexSupport, which are arrays @@ -1131,11 +1126,9 @@ LookupOpclassInfo(Oid operatorClassOid, { OpClassCacheEnt *opcentry; bool found; - Relation pg_amop_desc; - Relation pg_amproc_desc; - SysScanDesc pg_amop_scan; - SysScanDesc pg_amproc_scan; - ScanKeyData key; + Relation rel; + SysScanDesc scan; + ScanKeyData skey[2]; HeapTuple htup; bool indexOK; @@ -1191,7 +1184,7 @@ LookupOpclassInfo(Oid operatorClassOid, opcentry->supportProcs = NULL; /* - * To avoid infinite recursion during startup, force a heap scan if + * To avoid infinite recursion during startup, force heap scans if * we're looking up info for the opclasses used by the indexes we * would like to reference here. */ @@ -1200,24 +1193,25 @@ LookupOpclassInfo(Oid operatorClassOid, operatorClassOid != INT2_BTREE_OPS_OID); /* - * Scan pg_amop to obtain operators for the opclass + * Scan pg_amop to obtain operators for the opclass. We only fetch + * the default ones (those with subtype zero). */ if (numStrats > 0) { - ScanKeyEntryInitialize(&key, 0, - Anum_pg_amop_amopclaid, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(operatorClassOid), - OIDOID); - pg_amop_desc = heap_openr(AccessMethodOperatorRelationName, - AccessShareLock); - pg_amop_scan = systable_beginscan(pg_amop_desc, - AccessMethodStrategyIndex, - indexOK, - SnapshotNow, - 1, &key); - - while (HeapTupleIsValid(htup = systable_getnext(pg_amop_scan))) + ScanKeyInit(&skey[0], + Anum_pg_amop_amopclaid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(operatorClassOid)); + ScanKeyInit(&skey[1], + Anum_pg_amop_amopsubtype, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(InvalidOid)); + rel = heap_openr(AccessMethodOperatorRelationName, + AccessShareLock); + scan = systable_beginscan(rel, AccessMethodStrategyIndex, indexOK, + SnapshotNow, 2, skey); + + while (HeapTupleIsValid(htup = systable_getnext(scan))) { Form_pg_amop amopform = (Form_pg_amop) GETSTRUCT(htup); @@ -1229,29 +1223,30 @@ LookupOpclassInfo(Oid operatorClassOid, amopform->amopopr; } - systable_endscan(pg_amop_scan); - heap_close(pg_amop_desc, AccessShareLock); + systable_endscan(scan); + heap_close(rel, AccessShareLock); } /* - * Scan pg_amproc to obtain support procs for the opclass + * Scan pg_amproc to obtain support procs for the opclass. We only fetch + * the default ones (those with subtype zero). */ if (numSupport > 0) { - ScanKeyEntryInitialize(&key, 0, - Anum_pg_amproc_amopclaid, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(operatorClassOid), - OIDOID); - pg_amproc_desc = heap_openr(AccessMethodProcedureRelationName, - AccessShareLock); - pg_amproc_scan = systable_beginscan(pg_amproc_desc, - AccessMethodProcedureIndex, - indexOK, - SnapshotNow, - 1, &key); - - while (HeapTupleIsValid(htup = systable_getnext(pg_amproc_scan))) + ScanKeyInit(&skey[0], + Anum_pg_amproc_amopclaid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(operatorClassOid)); + ScanKeyInit(&skey[1], + Anum_pg_amproc_amprocsubtype, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(InvalidOid)); + rel = heap_openr(AccessMethodProcedureRelationName, + AccessShareLock); + scan = systable_beginscan(rel, AccessMethodProcedureIndex, indexOK, + SnapshotNow, 2, skey); + + while (HeapTupleIsValid(htup = systable_getnext(scan))) { Form_pg_amproc amprocform = (Form_pg_amproc) GETSTRUCT(htup); @@ -1264,8 +1259,8 @@ LookupOpclassInfo(Oid operatorClassOid, amprocform->amproc; } - systable_endscan(pg_amproc_scan); - heap_close(pg_amproc_desc, AccessShareLock); + systable_endscan(scan); + heap_close(rel, AccessShareLock); } opcentry->valid = true; @@ -2483,16 +2478,14 @@ AttrDefaultFetch(Relation relation) int found; int i; - ScanKeyEntryInitialize(&skey, 0, - Anum_pg_attrdef_adrelid, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(RelationGetRelid(relation)), - OIDOID); + ScanKeyInit(&skey, + Anum_pg_attrdef_adrelid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(RelationGetRelid(relation))); adrel = heap_openr(AttrDefaultRelationName, AccessShareLock); adscan = systable_beginscan(adrel, AttrDefaultIndex, true, - SnapshotNow, - 1, &skey); + SnapshotNow, 1, &skey); found = 0; while (HeapTupleIsValid(htup = systable_getnext(adscan))) @@ -2550,11 +2543,10 @@ CheckConstraintFetch(Relation relation) bool isnull; int found = 0; - ScanKeyEntryInitialize(&skey[0], 0, - Anum_pg_constraint_conrelid, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(RelationGetRelid(relation)), - OIDOID); + ScanKeyInit(&skey[0], + Anum_pg_constraint_conrelid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(RelationGetRelid(relation))); conrel = heap_openr(ConstraintRelationName, AccessShareLock); conscan = systable_beginscan(conrel, ConstraintRelidIndex, true, @@ -2642,16 +2634,14 @@ RelationGetIndexList(Relation relation) result = NIL; /* Prepare to scan pg_index for entries having indrelid = this rel. */ - ScanKeyEntryInitialize(&skey, 0, - Anum_pg_index_indrelid, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(RelationGetRelid(relation)), - OIDOID); + ScanKeyInit(&skey, + Anum_pg_index_indrelid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(RelationGetRelid(relation))); indrel = heap_openr(IndexRelationName, AccessShareLock); indscan = systable_beginscan(indrel, IndexIndrelidIndex, true, - SnapshotNow, - 1, &skey); + SnapshotNow, 1, &skey); while (HeapTupleIsValid(htup = systable_getnext(indscan))) { diff --git a/src/backend/utils/cache/syscache.c b/src/backend/utils/cache/syscache.c index 9b250eef62..eb2f6eb1af 100644 --- a/src/backend/utils/cache/syscache.c +++ b/src/backend/utils/cache/syscache.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/cache/syscache.c,v 1.91 2003/09/24 18:54:01 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/cache/syscache.c,v 1.92 2003/11/12 21:15:56 tgl Exp $ * * NOTES * These routines allow the parser/planner/executor to perform @@ -136,21 +136,21 @@ static const struct cachedesc cacheinfo[] = { {AccessMethodOperatorRelationName, /* AMOPSTRATEGY */ AccessMethodStrategyIndex, 0, - 2, + 3, { Anum_pg_amop_amopclaid, + Anum_pg_amop_amopsubtype, Anum_pg_amop_amopstrategy, - 0, 0 }}, {AccessMethodProcedureRelationName, /* AMPROCNUM */ AccessMethodProcedureIndex, 0, - 2, + 3, { Anum_pg_amproc_amopclaid, + Anum_pg_amproc_amprocsubtype, Anum_pg_amproc_amprocnum, - 0, 0 }}, {AttributeRelationName, /* ATTNAME */ diff --git a/src/backend/utils/cache/typcache.c b/src/backend/utils/cache/typcache.c index 9b7620b0f0..12d295c5a5 100644 --- a/src/backend/utils/cache/typcache.c +++ b/src/backend/utils/cache/typcache.c @@ -33,7 +33,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/cache/typcache.c,v 1.2 2003/11/09 21:30:37 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/cache/typcache.c,v 1.3 2003/11/12 21:15:56 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -158,22 +158,26 @@ lookup_type_cache(Oid type_id, int flags) { if (typentry->btree_opc != InvalidOid) typentry->eq_opr = get_opclass_member(typentry->btree_opc, + InvalidOid, BTEqualStrategyNumber); if (typentry->eq_opr == InvalidOid && typentry->hash_opc != InvalidOid) typentry->eq_opr = get_opclass_member(typentry->hash_opc, + InvalidOid, HTEqualStrategyNumber); } if ((flags & TYPECACHE_LT_OPR) && typentry->lt_opr == InvalidOid) { if (typentry->btree_opc != InvalidOid) typentry->lt_opr = get_opclass_member(typentry->btree_opc, + InvalidOid, BTLessStrategyNumber); } if ((flags & TYPECACHE_GT_OPR) && typentry->gt_opr == InvalidOid) { if (typentry->btree_opc != InvalidOid) typentry->gt_opr = get_opclass_member(typentry->btree_opc, + InvalidOid, BTGreaterStrategyNumber); } if ((flags & (TYPECACHE_CMP_PROC | TYPECACHE_CMP_PROC_FINFO)) && @@ -181,6 +185,7 @@ lookup_type_cache(Oid type_id, int flags) { if (typentry->btree_opc != InvalidOid) typentry->cmp_proc = get_opclass_proc(typentry->btree_opc, + InvalidOid, BTORDER_PROC); } @@ -248,10 +253,10 @@ lookup_default_opclass(Oid type_id, Oid am_id) */ rel = heap_openr(OperatorClassRelationName, AccessShareLock); - ScanKeyEntryInitialize(&skey[0], 0, - Anum_pg_opclass_opcamid, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(am_id), OIDOID); + ScanKeyInit(&skey[0], + Anum_pg_opclass_opcamid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(am_id)); scan = systable_beginscan(rel, OpclassAmNameNspIndex, true, SnapshotNow, 1, skey); diff --git a/src/backend/utils/init/postinit.c b/src/backend/utils/init/postinit.c index 21e2efdda7..54175189df 100644 --- a/src/backend/utils/init/postinit.c +++ b/src/backend/utils/init/postinit.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/init/postinit.c,v 1.128 2003/11/09 21:30:37 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/init/postinit.c,v 1.129 2003/11/12 21:15:56 tgl Exp $ * * *------------------------------------------------------------------------- @@ -26,7 +26,6 @@ #include "catalog/namespace.h" #include "catalog/pg_database.h" #include "catalog/pg_shadow.h" -#include "catalog/pg_type.h" #include "commands/trigger.h" #include "mb/pg_wchar.h" #include "miscadmin.h" @@ -92,10 +91,10 @@ ReverifyMyDatabase(const char *name) */ pgdbrel = heap_openr(DatabaseRelationName, AccessShareLock); - ScanKeyEntryInitialize(&key, 0, - Anum_pg_database_datname, - BTEqualStrategyNumber, F_NAMEEQ, - NameGetDatum(name), NAMEOID); + ScanKeyInit(&key, + Anum_pg_database_datname, + BTEqualStrategyNumber, F_NAMEEQ, + NameGetDatum(name)); pgdbscan = heap_beginscan(pgdbrel, SnapshotNow, 1, &key); diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c index 9b3c0bb407..a6accb5db4 100644 --- a/src/backend/utils/sort/tuplesort.c +++ b/src/backend/utils/sort/tuplesort.c @@ -78,7 +78,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/sort/tuplesort.c,v 1.38 2003/11/09 21:30:37 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/sort/tuplesort.c,v 1.39 2003/11/12 21:15:56 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -472,15 +472,14 @@ tuplesort_begin_heap(TupleDesc tupDesc, &state->sortFnKinds[i]); /* - * We needn't fill in sk_strategy or sk_argtype since these scankeys + * We needn't fill in sk_strategy or sk_subtype since these scankeys * will never be passed to an index. */ - ScanKeyEntryInitialize(&state->scanKeys[i], 0, - attNums[i], - InvalidStrategy, - sortFunction, - (Datum) 0, - InvalidOid); + ScanKeyInit(&state->scanKeys[i], + attNums[i], + InvalidStrategy, + sortFunction, + (Datum) 0); } return state; @@ -1739,6 +1738,10 @@ SelectSortFunction(Oid sortOperator, if (!opclass_is_btree(aform->amopclaid)) continue; + /* must be of default subtype, too */ + if (aform->amopsubtype != InvalidOid) + continue; + if (aform->amopstrategy == BTLessStrategyNumber) { opclass = aform->amopclaid; @@ -1757,8 +1760,8 @@ SelectSortFunction(Oid sortOperator, if (OidIsValid(opclass)) { - /* Found a suitable opclass, get its comparator support function */ - *sortFunction = get_opclass_proc(opclass, BTORDER_PROC); + /* Found a suitable opclass, get its default comparator function */ + *sortFunction = get_opclass_proc(opclass, InvalidOid, BTORDER_PROC); Assert(RegProcedureIsValid(*sortFunction)); return; } diff --git a/src/include/access/nbtree.h b/src/include/access/nbtree.h index 80d412a52e..2d75fa5b23 100644 --- a/src/include/access/nbtree.h +++ b/src/include/access/nbtree.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: nbtree.h,v 1.72 2003/11/09 21:30:37 tgl Exp $ + * $Id: nbtree.h,v 1.73 2003/11/12 21:15:57 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -341,7 +341,7 @@ typedef struct xl_btree_newpage /* * Operator strategy numbers for B-tree have been moved to access/skey.h, - * because many places need to use them in ScanKeyEntryInitialize() calls. + * because many places need to use them in ScanKeyInit() calls. */ /* @@ -404,12 +404,12 @@ typedef struct BTScanOpaqueData Buffer btso_mrkbuf; ItemPointerData curHeapIptr; ItemPointerData mrkHeapIptr; - /* these fields are set by _bt_orderkeys(), which see for more info: */ + /* these fields are set by _bt_preprocess_keys(): */ bool qual_ok; /* false if qual can never be satisfied */ - int numberOfKeys; /* number of scan keys */ + int numberOfKeys; /* number of preprocessed scan keys */ int numberOfRequiredKeys; /* number of keys that must be * matched to continue the scan */ - ScanKey keyData; /* array of scan keys */ + ScanKey keyData; /* array of preprocessed scan keys */ } BTScanOpaqueData; typedef BTScanOpaqueData *BTScanOpaque; @@ -424,7 +424,6 @@ extern Datum btinsert(PG_FUNCTION_ARGS); extern Datum btgettuple(PG_FUNCTION_ARGS); extern Datum btbeginscan(PG_FUNCTION_ARGS); extern Datum btrescan(PG_FUNCTION_ARGS); -extern void btmovescan(IndexScanDesc scan, Datum v); extern Datum btendscan(PG_FUNCTION_ARGS); extern Datum btmarkpos(PG_FUNCTION_ARGS); extern Datum btrestrpos(PG_FUNCTION_ARGS); @@ -480,7 +479,7 @@ extern ScanKey _bt_mkscankey(Relation rel, IndexTuple itup); extern ScanKey _bt_mkscankey_nodata(Relation rel); extern void _bt_freeskey(ScanKey skey); extern void _bt_freestack(BTStack stack); -extern void _bt_orderkeys(IndexScanDesc scan); +extern void _bt_preprocess_keys(IndexScanDesc scan); extern bool _bt_checkkeys(IndexScanDesc scan, IndexTuple tuple, ScanDirection dir, bool *continuescan); extern BTItem _bt_formitem(IndexTuple itup); diff --git a/src/include/access/skey.h b/src/include/access/skey.h index b7373dd641..5cce3249fb 100644 --- a/src/include/access/skey.h +++ b/src/include/access/skey.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: skey.h,v 1.23 2003/11/09 21:30:37 tgl Exp $ + * $Id: skey.h,v 1.24 2003/11/12 21:15:57 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -20,7 +20,8 @@ /* * Strategy numbers identify the semantics that particular operators have - * with respect to particular operator classes. + * with respect to particular operator classes. In some cases a strategy + * subtype (an OID) is used as further information. */ typedef uint16 StrategyNumber; @@ -47,23 +48,23 @@ typedef uint16 StrategyNumber; * (The data structure can support unary indexable operators too; in that * case sk_argument would go unused. This is not currently implemented.) * - * For an index scan, sk_strategy must be set correctly for the operator. - * When using a ScanKey in a heap scan, sk_strategy is not used and may be - * set to InvalidStrategy. + * For an index scan, sk_strategy and sk_subtype must be set correctly for + * the operator. When using a ScanKey in a heap scan, these fields are not + * used and may be set to InvalidStrategy/InvalidOid. * * Note: in some places, ScanKeys are used as a convenient representation * for the invocation of an access method support procedure. In this case - * sk_strategy is not meaningful, and sk_func may refer to a function that - * returns something other than boolean. + * sk_strategy/sk_subtype are not meaningful, and sk_func may refer to a + * function that returns something other than boolean. */ typedef struct ScanKeyData { int sk_flags; /* flags, see below */ AttrNumber sk_attno; /* table or index column number */ StrategyNumber sk_strategy; /* operator strategy number */ + Oid sk_subtype; /* strategy subtype */ FmgrInfo sk_func; /* lookup info for function to call */ Datum sk_argument; /* data to compare */ - Oid sk_argtype; /* datatype of sk_argument */ } ScanKeyData; typedef ScanKeyData *ScanKey; @@ -76,19 +77,24 @@ typedef ScanKeyData *ScanKey; /* * prototypes for functions in access/common/scankey.c */ +extern void ScanKeyInit(ScanKey entry, + AttrNumber attributeNumber, + StrategyNumber strategy, + RegProcedure procedure, + Datum argument); extern void ScanKeyEntryInitialize(ScanKey entry, int flags, AttrNumber attributeNumber, StrategyNumber strategy, + Oid subtype, RegProcedure procedure, - Datum argument, - Oid argtype); + Datum argument); extern void ScanKeyEntryInitializeWithInfo(ScanKey entry, int flags, AttrNumber attributeNumber, StrategyNumber strategy, + Oid subtype, FmgrInfo *finfo, - Datum argument, - Oid argtype); + Datum argument); #endif /* SKEY_H */ diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h index 9efcfe447d..8209b34880 100644 --- a/src/include/catalog/catversion.h +++ b/src/include/catalog/catversion.h @@ -37,7 +37,7 @@ * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: catversion.h,v 1.210 2003/10/21 16:23:16 tgl Exp $ + * $Id: catversion.h,v 1.211 2003/11/12 21:15:57 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -53,6 +53,6 @@ */ /* yyyymmddN */ -#define CATALOG_VERSION_NO 200310211 +#define CATALOG_VERSION_NO 200311101 #endif diff --git a/src/include/catalog/indexing.h b/src/include/catalog/indexing.h index 1150f1e47c..720c8eec0a 100644 --- a/src/include/catalog/indexing.h +++ b/src/include/catalog/indexing.h @@ -8,7 +8,7 @@ * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: indexing.h,v 1.79 2003/08/04 02:40:10 momjian Exp $ + * $Id: indexing.h,v 1.80 2003/11/12 21:15:57 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -24,8 +24,8 @@ * macros rather than hardwiring the actual index name. */ #define AccessMethodOperatorIndex "pg_amop_opr_opc_index" -#define AccessMethodStrategyIndex "pg_amop_opc_strategy_index" -#define AccessMethodProcedureIndex "pg_amproc_opc_procnum_index" +#define AccessMethodStrategyIndex "pg_amop_opc_strat_index" +#define AccessMethodProcedureIndex "pg_amproc_opc_proc_index" #define AggregateFnoidIndex "pg_aggregate_fnoid_index" #define AmNameIndex "pg_am_name_index" #define AmOidIndex "pg_am_oid_index" @@ -115,9 +115,9 @@ extern void CatalogUpdateIndexes(Relation heapRel, HeapTuple heapTuple); DECLARE_UNIQUE_INDEX(pg_aggregate_fnoid_index on pg_aggregate using btree(aggfnoid oid_ops)); DECLARE_UNIQUE_INDEX(pg_am_name_index on pg_am using btree(amname name_ops)); DECLARE_UNIQUE_INDEX(pg_am_oid_index on pg_am using btree(oid oid_ops)); +DECLARE_UNIQUE_INDEX(pg_amop_opc_strat_index on pg_amop using btree(amopclaid oid_ops, amopsubtype oid_ops, amopstrategy int2_ops)); DECLARE_UNIQUE_INDEX(pg_amop_opr_opc_index on pg_amop using btree(amopopr oid_ops, amopclaid oid_ops)); -DECLARE_UNIQUE_INDEX(pg_amop_opc_strategy_index on pg_amop using btree(amopclaid oid_ops, amopstrategy int2_ops)); -DECLARE_UNIQUE_INDEX(pg_amproc_opc_procnum_index on pg_amproc using btree(amopclaid oid_ops, amprocnum int2_ops)); +DECLARE_UNIQUE_INDEX(pg_amproc_opc_proc_index on pg_amproc using btree(amopclaid oid_ops, amprocsubtype oid_ops, amprocnum int2_ops)); DECLARE_UNIQUE_INDEX(pg_attrdef_adrelid_adnum_index on pg_attrdef using btree(adrelid oid_ops, adnum int2_ops)); DECLARE_UNIQUE_INDEX(pg_attrdef_oid_index on pg_attrdef using btree(oid oid_ops)); DECLARE_UNIQUE_INDEX(pg_attribute_relid_attnam_index on pg_attribute using btree(attrelid oid_ops, attname name_ops)); diff --git a/src/include/catalog/namespace.h b/src/include/catalog/namespace.h index 7e70d726d1..746b9bfb6d 100644 --- a/src/include/catalog/namespace.h +++ b/src/include/catalog/namespace.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: namespace.h,v 1.27 2003/08/04 02:40:10 momjian Exp $ + * $Id: namespace.h,v 1.28 2003/11/12 21:15:57 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -42,9 +42,9 @@ typedef struct _OpclassCandidateList char *opcname_tmp; /* for internal use of namespace lookup */ int pathpos; /* for internal use of namespace lookup */ Oid oid; /* the opclass's OID */ - Oid opcintype; /* type of input data for opclass */ + Oid opcintype; /* type of data indexed by opclass */ bool opcdefault; /* T if opclass is default for opcintype */ - Oid opckeytype; /* type of index data, or InvalidOid */ + Oid opckeytype; /* type of data in index, or InvalidOid */ } *OpclassCandidateList; diff --git a/src/include/catalog/pg_amop.h b/src/include/catalog/pg_amop.h index bff4b21700..1bab599fdb 100644 --- a/src/include/catalog/pg_amop.h +++ b/src/include/catalog/pg_amop.h @@ -6,17 +6,24 @@ * * The amop table identifies the operators associated with each index opclass. * - * Note: the primary key for this table is . + * The primary key for this table is . + * amopsubtype is equal to zero for an opclass's "default" operators + * (which normally are those that accept the opclass's opcintype on both + * left and right sides). Some index AMs allow nondefault operators to + * exist for a single strategy --- for example, in the btree AM nondefault + * operators can have right-hand input data types different from opcintype, + * and their amopsubtype is equal to the right-hand input data type. + * * We also keep a unique index on , so that we can * use a syscache to quickly answer questions of the form "is this operator * in this opclass?". This implies that the same operator cannot be listed - * for multiple strategy numbers of a single opclass. + * for multiple subtypes or strategy numbers of a single opclass. * * * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: pg_amop.h,v 1.55 2003/08/17 19:58:06 tgl Exp $ + * $Id: pg_amop.h,v 1.56 2003/11/12 21:15:57 tgl Exp $ * * NOTES * the genbki.sh script reads this file and generates .bki @@ -42,6 +49,7 @@ CATALOG(pg_amop) BKI_WITHOUT_OIDS { Oid amopclaid; /* the index opclass this entry is for */ + Oid amopsubtype; /* operator subtype, or zero if default */ int2 amopstrategy; /* operator strategy number */ bool amopreqcheck; /* index hit must be rechecked */ Oid amopopr; /* the operator's pg_operator OID */ @@ -58,11 +66,12 @@ typedef FormData_pg_amop *Form_pg_amop; * compiler constants for pg_amop * ---------------- */ -#define Natts_pg_amop 4 +#define Natts_pg_amop 5 #define Anum_pg_amop_amopclaid 1 -#define Anum_pg_amop_amopstrategy 2 -#define Anum_pg_amop_amopreqcheck 3 -#define Anum_pg_amop_amopopr 4 +#define Anum_pg_amop_amopsubtype 2 +#define Anum_pg_amop_amopstrategy 3 +#define Anum_pg_amop_amopreqcheck 4 +#define Anum_pg_amop_amopopr 5 /* ---------------- * initial contents of pg_amop @@ -73,460 +82,495 @@ typedef FormData_pg_amop *Form_pg_amop; * rtree box_ops */ -DATA(insert ( 425 1 f 493 )); -DATA(insert ( 425 2 f 494 )); -DATA(insert ( 425 3 f 500 )); -DATA(insert ( 425 4 f 495 )); -DATA(insert ( 425 5 f 496 )); -DATA(insert ( 425 6 f 499 )); -DATA(insert ( 425 7 f 498 )); -DATA(insert ( 425 8 f 497 )); - -/* - * rtree bigbox_ops - */ - -DATA(insert ( 422 1 f 493 )); -DATA(insert ( 422 2 f 494 )); -DATA(insert ( 422 3 f 500 )); -DATA(insert ( 422 4 f 495 )); -DATA(insert ( 422 5 f 496 )); -DATA(insert ( 422 6 f 499 )); -DATA(insert ( 422 7 f 498 )); -DATA(insert ( 422 8 f 497 )); +DATA(insert ( 425 0 1 f 493 )); +DATA(insert ( 425 0 2 f 494 )); +DATA(insert ( 425 0 3 f 500 )); +DATA(insert ( 425 0 4 f 495 )); +DATA(insert ( 425 0 5 f 496 )); +DATA(insert ( 425 0 6 f 499 )); +DATA(insert ( 425 0 7 f 498 )); +DATA(insert ( 425 0 8 f 497 )); /* * rtree poly_ops (supports polygons) */ -DATA(insert ( 1993 1 f 485 )); -DATA(insert ( 1993 2 f 486 )); -DATA(insert ( 1993 3 f 492 )); -DATA(insert ( 1993 4 f 487 )); -DATA(insert ( 1993 5 f 488 )); -DATA(insert ( 1993 6 f 491 )); -DATA(insert ( 1993 7 f 490 )); -DATA(insert ( 1993 8 f 489 )); +DATA(insert ( 1993 0 1 f 485 )); +DATA(insert ( 1993 0 2 f 486 )); +DATA(insert ( 1993 0 3 f 492 )); +DATA(insert ( 1993 0 4 f 487 )); +DATA(insert ( 1993 0 5 f 488 )); +DATA(insert ( 1993 0 6 f 491 )); +DATA(insert ( 1993 0 7 f 490 )); +DATA(insert ( 1993 0 8 f 489 )); /* * btree int2_ops */ -DATA(insert ( 1976 1 f 95 )); -DATA(insert ( 1976 2 f 522 )); -DATA(insert ( 1976 3 f 94 )); -DATA(insert ( 1976 4 f 524 )); -DATA(insert ( 1976 5 f 520 )); +DATA(insert ( 1976 0 1 f 95 )); +DATA(insert ( 1976 0 2 f 522 )); +DATA(insert ( 1976 0 3 f 94 )); +DATA(insert ( 1976 0 4 f 524 )); +DATA(insert ( 1976 0 5 f 520 )); +/* crosstype operators int24 */ +DATA(insert ( 1976 23 1 f 534 )); +DATA(insert ( 1976 23 2 f 540 )); +DATA(insert ( 1976 23 3 f 532 )); +DATA(insert ( 1976 23 4 f 542 )); +DATA(insert ( 1976 23 5 f 536 )); +/* crosstype operators int28 */ +DATA(insert ( 1976 20 1 f 1864 )); +DATA(insert ( 1976 20 2 f 1866 )); +DATA(insert ( 1976 20 3 f 1862 )); +DATA(insert ( 1976 20 4 f 1867 )); +DATA(insert ( 1976 20 5 f 1865 )); /* * btree int4_ops */ -DATA(insert ( 1978 1 f 97 )); -DATA(insert ( 1978 2 f 523 )); -DATA(insert ( 1978 3 f 96 )); -DATA(insert ( 1978 4 f 525 )); -DATA(insert ( 1978 5 f 521 )); +DATA(insert ( 1978 0 1 f 97 )); +DATA(insert ( 1978 0 2 f 523 )); +DATA(insert ( 1978 0 3 f 96 )); +DATA(insert ( 1978 0 4 f 525 )); +DATA(insert ( 1978 0 5 f 521 )); +/* crosstype operators int42 */ +DATA(insert ( 1978 21 1 f 535 )); +DATA(insert ( 1978 21 2 f 541 )); +DATA(insert ( 1978 21 3 f 533 )); +DATA(insert ( 1978 21 4 f 543 )); +DATA(insert ( 1978 21 5 f 537 )); +/* crosstype operators int48 */ +DATA(insert ( 1978 20 1 f 37 )); +DATA(insert ( 1978 20 2 f 80 )); +DATA(insert ( 1978 20 3 f 15 )); +DATA(insert ( 1978 20 4 f 82 )); +DATA(insert ( 1978 20 5 f 76 )); /* * btree int8_ops */ -DATA(insert ( 1980 1 f 412 )); -DATA(insert ( 1980 2 f 414 )); -DATA(insert ( 1980 3 f 410 )); -DATA(insert ( 1980 4 f 415 )); -DATA(insert ( 1980 5 f 413 )); +DATA(insert ( 1980 0 1 f 412 )); +DATA(insert ( 1980 0 2 f 414 )); +DATA(insert ( 1980 0 3 f 410 )); +DATA(insert ( 1980 0 4 f 415 )); +DATA(insert ( 1980 0 5 f 413 )); +/* crosstype operators int82 */ +DATA(insert ( 1980 21 1 f 1870 )); +DATA(insert ( 1980 21 2 f 1872 )); +DATA(insert ( 1980 21 3 f 1868 )); +DATA(insert ( 1980 21 4 f 1873 )); +DATA(insert ( 1980 21 5 f 1871 )); +/* crosstype operators int84 */ +DATA(insert ( 1980 23 1 f 418 )); +DATA(insert ( 1980 23 2 f 420 )); +DATA(insert ( 1980 23 3 f 416 )); +DATA(insert ( 1980 23 4 f 430 )); +DATA(insert ( 1980 23 5 f 419 )); /* * btree oid_ops */ -DATA(insert ( 1989 1 f 609 )); -DATA(insert ( 1989 2 f 611 )); -DATA(insert ( 1989 3 f 607 )); -DATA(insert ( 1989 4 f 612 )); -DATA(insert ( 1989 5 f 610 )); +DATA(insert ( 1989 0 1 f 609 )); +DATA(insert ( 1989 0 2 f 611 )); +DATA(insert ( 1989 0 3 f 607 )); +DATA(insert ( 1989 0 4 f 612 )); +DATA(insert ( 1989 0 5 f 610 )); /* * btree oidvector_ops */ -DATA(insert ( 1991 1 f 645 )); -DATA(insert ( 1991 2 f 647 )); -DATA(insert ( 1991 3 f 649 )); -DATA(insert ( 1991 4 f 648 )); -DATA(insert ( 1991 5 f 646 )); +DATA(insert ( 1991 0 1 f 645 )); +DATA(insert ( 1991 0 2 f 647 )); +DATA(insert ( 1991 0 3 f 649 )); +DATA(insert ( 1991 0 4 f 648 )); +DATA(insert ( 1991 0 5 f 646 )); /* * btree float4_ops */ -DATA(insert ( 1970 1 f 622 )); -DATA(insert ( 1970 2 f 624 )); -DATA(insert ( 1970 3 f 620 )); -DATA(insert ( 1970 4 f 625 )); -DATA(insert ( 1970 5 f 623 )); +DATA(insert ( 1970 0 1 f 622 )); +DATA(insert ( 1970 0 2 f 624 )); +DATA(insert ( 1970 0 3 f 620 )); +DATA(insert ( 1970 0 4 f 625 )); +DATA(insert ( 1970 0 5 f 623 )); +/* crosstype operators float48 */ +DATA(insert ( 1970 701 1 f 1122 )); +DATA(insert ( 1970 701 2 f 1124 )); +DATA(insert ( 1970 701 3 f 1120 )); +DATA(insert ( 1970 701 4 f 1125 )); +DATA(insert ( 1970 701 5 f 1123 )); /* * btree float8_ops */ -DATA(insert ( 1972 1 f 672 )); -DATA(insert ( 1972 2 f 673 )); -DATA(insert ( 1972 3 f 670 )); -DATA(insert ( 1972 4 f 675 )); -DATA(insert ( 1972 5 f 674 )); +DATA(insert ( 1972 0 1 f 672 )); +DATA(insert ( 1972 0 2 f 673 )); +DATA(insert ( 1972 0 3 f 670 )); +DATA(insert ( 1972 0 4 f 675 )); +DATA(insert ( 1972 0 5 f 674 )); +/* crosstype operators float84 */ +DATA(insert ( 1972 700 1 f 1132 )); +DATA(insert ( 1972 700 2 f 1134 )); +DATA(insert ( 1972 700 3 f 1130 )); +DATA(insert ( 1972 700 4 f 1135 )); +DATA(insert ( 1972 700 5 f 1133 )); /* * btree char_ops */ -DATA(insert ( 429 1 f 631 )); -DATA(insert ( 429 2 f 632 )); -DATA(insert ( 429 3 f 92 )); -DATA(insert ( 429 4 f 634 )); -DATA(insert ( 429 5 f 633 )); +DATA(insert ( 429 0 1 f 631 )); +DATA(insert ( 429 0 2 f 632 )); +DATA(insert ( 429 0 3 f 92 )); +DATA(insert ( 429 0 4 f 634 )); +DATA(insert ( 429 0 5 f 633 )); /* * btree name_ops */ -DATA(insert ( 1986 1 f 660 )); -DATA(insert ( 1986 2 f 661 )); -DATA(insert ( 1986 3 f 93 )); -DATA(insert ( 1986 4 f 663 )); -DATA(insert ( 1986 5 f 662 )); +DATA(insert ( 1986 0 1 f 660 )); +DATA(insert ( 1986 0 2 f 661 )); +DATA(insert ( 1986 0 3 f 93 )); +DATA(insert ( 1986 0 4 f 663 )); +DATA(insert ( 1986 0 5 f 662 )); /* * btree text_ops */ -DATA(insert ( 1994 1 f 664 )); -DATA(insert ( 1994 2 f 665 )); -DATA(insert ( 1994 3 f 98 )); -DATA(insert ( 1994 4 f 667 )); -DATA(insert ( 1994 5 f 666 )); +DATA(insert ( 1994 0 1 f 664 )); +DATA(insert ( 1994 0 2 f 665 )); +DATA(insert ( 1994 0 3 f 98 )); +DATA(insert ( 1994 0 4 f 667 )); +DATA(insert ( 1994 0 5 f 666 )); /* * btree bpchar_ops */ -DATA(insert ( 426 1 f 1058 )); -DATA(insert ( 426 2 f 1059 )); -DATA(insert ( 426 3 f 1054 )); -DATA(insert ( 426 4 f 1061 )); -DATA(insert ( 426 5 f 1060 )); +DATA(insert ( 426 0 1 f 1058 )); +DATA(insert ( 426 0 2 f 1059 )); +DATA(insert ( 426 0 3 f 1054 )); +DATA(insert ( 426 0 4 f 1061 )); +DATA(insert ( 426 0 5 f 1060 )); /* * btree varchar_ops (same operators as text_ops) */ -DATA(insert ( 2003 1 f 664 )); -DATA(insert ( 2003 2 f 665 )); -DATA(insert ( 2003 3 f 98 )); -DATA(insert ( 2003 4 f 667 )); -DATA(insert ( 2003 5 f 666 )); +DATA(insert ( 2003 0 1 f 664 )); +DATA(insert ( 2003 0 2 f 665 )); +DATA(insert ( 2003 0 3 f 98 )); +DATA(insert ( 2003 0 4 f 667 )); +DATA(insert ( 2003 0 5 f 666 )); /* * btree bytea_ops */ -DATA(insert ( 428 1 f 1957 )); -DATA(insert ( 428 2 f 1958 )); -DATA(insert ( 428 3 f 1955 )); -DATA(insert ( 428 4 f 1960 )); -DATA(insert ( 428 5 f 1959 )); +DATA(insert ( 428 0 1 f 1957 )); +DATA(insert ( 428 0 2 f 1958 )); +DATA(insert ( 428 0 3 f 1955 )); +DATA(insert ( 428 0 4 f 1960 )); +DATA(insert ( 428 0 5 f 1959 )); /* * btree abstime_ops */ -DATA(insert ( 421 1 f 562 )); -DATA(insert ( 421 2 f 564 )); -DATA(insert ( 421 3 f 560 )); -DATA(insert ( 421 4 f 565 )); -DATA(insert ( 421 5 f 563 )); +DATA(insert ( 421 0 1 f 562 )); +DATA(insert ( 421 0 2 f 564 )); +DATA(insert ( 421 0 3 f 560 )); +DATA(insert ( 421 0 4 f 565 )); +DATA(insert ( 421 0 5 f 563 )); /* * btree date_ops */ -DATA(insert ( 434 1 f 1095 )); -DATA(insert ( 434 2 f 1096 )); -DATA(insert ( 434 3 f 1093 )); -DATA(insert ( 434 4 f 1098 )); -DATA(insert ( 434 5 f 1097 )); +DATA(insert ( 434 0 1 f 1095 )); +DATA(insert ( 434 0 2 f 1096 )); +DATA(insert ( 434 0 3 f 1093 )); +DATA(insert ( 434 0 4 f 1098 )); +DATA(insert ( 434 0 5 f 1097 )); /* * btree time_ops */ -DATA(insert ( 1996 1 f 1110 )); -DATA(insert ( 1996 2 f 1111 )); -DATA(insert ( 1996 3 f 1108 )); -DATA(insert ( 1996 4 f 1113 )); -DATA(insert ( 1996 5 f 1112 )); +DATA(insert ( 1996 0 1 f 1110 )); +DATA(insert ( 1996 0 2 f 1111 )); +DATA(insert ( 1996 0 3 f 1108 )); +DATA(insert ( 1996 0 4 f 1113 )); +DATA(insert ( 1996 0 5 f 1112 )); /* * btree timetz_ops */ -DATA(insert ( 2000 1 f 1552 )); -DATA(insert ( 2000 2 f 1553 )); -DATA(insert ( 2000 3 f 1550 )); -DATA(insert ( 2000 4 f 1555 )); -DATA(insert ( 2000 5 f 1554 )); +DATA(insert ( 2000 0 1 f 1552 )); +DATA(insert ( 2000 0 2 f 1553 )); +DATA(insert ( 2000 0 3 f 1550 )); +DATA(insert ( 2000 0 4 f 1555 )); +DATA(insert ( 2000 0 5 f 1554 )); /* * btree timestamp_ops */ -DATA(insert ( 2039 1 f 2062 )); -DATA(insert ( 2039 2 f 2063 )); -DATA(insert ( 2039 3 f 2060 )); -DATA(insert ( 2039 4 f 2065 )); -DATA(insert ( 2039 5 f 2064 )); +DATA(insert ( 2039 0 1 f 2062 )); +DATA(insert ( 2039 0 2 f 2063 )); +DATA(insert ( 2039 0 3 f 2060 )); +DATA(insert ( 2039 0 4 f 2065 )); +DATA(insert ( 2039 0 5 f 2064 )); /* * btree timestamptz_ops */ -DATA(insert ( 1998 1 f 1322 )); -DATA(insert ( 1998 2 f 1323 )); -DATA(insert ( 1998 3 f 1320 )); -DATA(insert ( 1998 4 f 1325 )); -DATA(insert ( 1998 5 f 1324 )); +DATA(insert ( 1998 0 1 f 1322 )); +DATA(insert ( 1998 0 2 f 1323 )); +DATA(insert ( 1998 0 3 f 1320 )); +DATA(insert ( 1998 0 4 f 1325 )); +DATA(insert ( 1998 0 5 f 1324 )); /* * btree interval_ops */ -DATA(insert ( 1982 1 f 1332 )); -DATA(insert ( 1982 2 f 1333 )); -DATA(insert ( 1982 3 f 1330 )); -DATA(insert ( 1982 4 f 1335 )); -DATA(insert ( 1982 5 f 1334 )); +DATA(insert ( 1982 0 1 f 1332 )); +DATA(insert ( 1982 0 2 f 1333 )); +DATA(insert ( 1982 0 3 f 1330 )); +DATA(insert ( 1982 0 4 f 1335 )); +DATA(insert ( 1982 0 5 f 1334 )); /* * btree macaddr */ -DATA(insert ( 1984 1 f 1222 )); -DATA(insert ( 1984 2 f 1223 )); -DATA(insert ( 1984 3 f 1220 )); -DATA(insert ( 1984 4 f 1225 )); -DATA(insert ( 1984 5 f 1224 )); +DATA(insert ( 1984 0 1 f 1222 )); +DATA(insert ( 1984 0 2 f 1223 )); +DATA(insert ( 1984 0 3 f 1220 )); +DATA(insert ( 1984 0 4 f 1225 )); +DATA(insert ( 1984 0 5 f 1224 )); /* * btree inet */ -DATA(insert ( 1974 1 f 1203 )); -DATA(insert ( 1974 2 f 1204 )); -DATA(insert ( 1974 3 f 1201 )); -DATA(insert ( 1974 4 f 1206 )); -DATA(insert ( 1974 5 f 1205 )); +DATA(insert ( 1974 0 1 f 1203 )); +DATA(insert ( 1974 0 2 f 1204 )); +DATA(insert ( 1974 0 3 f 1201 )); +DATA(insert ( 1974 0 4 f 1206 )); +DATA(insert ( 1974 0 5 f 1205 )); /* * btree cidr */ -DATA(insert ( 432 1 f 822 )); -DATA(insert ( 432 2 f 823 )); -DATA(insert ( 432 3 f 820 )); -DATA(insert ( 432 4 f 825 )); -DATA(insert ( 432 5 f 824 )); +DATA(insert ( 432 0 1 f 822 )); +DATA(insert ( 432 0 2 f 823 )); +DATA(insert ( 432 0 3 f 820 )); +DATA(insert ( 432 0 4 f 825 )); +DATA(insert ( 432 0 5 f 824 )); /* * btree numeric */ -DATA(insert ( 1988 1 f 1754 )); -DATA(insert ( 1988 2 f 1755 )); -DATA(insert ( 1988 3 f 1752 )); -DATA(insert ( 1988 4 f 1757 )); -DATA(insert ( 1988 5 f 1756 )); +DATA(insert ( 1988 0 1 f 1754 )); +DATA(insert ( 1988 0 2 f 1755 )); +DATA(insert ( 1988 0 3 f 1752 )); +DATA(insert ( 1988 0 4 f 1757 )); +DATA(insert ( 1988 0 5 f 1756 )); /* * btree bool */ -DATA(insert ( 424 1 f 58 )); -DATA(insert ( 424 2 f 1694 )); -DATA(insert ( 424 3 f 91 )); -DATA(insert ( 424 4 f 1695 )); -DATA(insert ( 424 5 f 59 )); +DATA(insert ( 424 0 1 f 58 )); +DATA(insert ( 424 0 2 f 1694 )); +DATA(insert ( 424 0 3 f 91 )); +DATA(insert ( 424 0 4 f 1695 )); +DATA(insert ( 424 0 5 f 59 )); /* * btree bit */ -DATA(insert ( 423 1 f 1786 )); -DATA(insert ( 423 2 f 1788 )); -DATA(insert ( 423 3 f 1784 )); -DATA(insert ( 423 4 f 1789 )); -DATA(insert ( 423 5 f 1787 )); +DATA(insert ( 423 0 1 f 1786 )); +DATA(insert ( 423 0 2 f 1788 )); +DATA(insert ( 423 0 3 f 1784 )); +DATA(insert ( 423 0 4 f 1789 )); +DATA(insert ( 423 0 5 f 1787 )); /* * btree varbit */ -DATA(insert ( 2002 1 f 1806 )); -DATA(insert ( 2002 2 f 1808 )); -DATA(insert ( 2002 3 f 1804 )); -DATA(insert ( 2002 4 f 1809 )); -DATA(insert ( 2002 5 f 1807 )); +DATA(insert ( 2002 0 1 f 1806 )); +DATA(insert ( 2002 0 2 f 1808 )); +DATA(insert ( 2002 0 3 f 1804 )); +DATA(insert ( 2002 0 4 f 1809 )); +DATA(insert ( 2002 0 5 f 1807 )); /* * btree text pattern */ -DATA(insert ( 2095 1 f 2314 )); -DATA(insert ( 2095 2 f 2315 )); -DATA(insert ( 2095 3 f 2316 )); -DATA(insert ( 2095 4 f 2317 )); -DATA(insert ( 2095 5 f 2318 )); +DATA(insert ( 2095 0 1 f 2314 )); +DATA(insert ( 2095 0 2 f 2315 )); +DATA(insert ( 2095 0 3 f 2316 )); +DATA(insert ( 2095 0 4 f 2317 )); +DATA(insert ( 2095 0 5 f 2318 )); /* * btree varchar pattern (same operators as text) */ -DATA(insert ( 2096 1 f 2314 )); -DATA(insert ( 2096 2 f 2315 )); -DATA(insert ( 2096 3 f 2316 )); -DATA(insert ( 2096 4 f 2317 )); -DATA(insert ( 2096 5 f 2318 )); +DATA(insert ( 2096 0 1 f 2314 )); +DATA(insert ( 2096 0 2 f 2315 )); +DATA(insert ( 2096 0 3 f 2316 )); +DATA(insert ( 2096 0 4 f 2317 )); +DATA(insert ( 2096 0 5 f 2318 )); /* * btree bpchar pattern */ -DATA(insert ( 2097 1 f 2326 )); -DATA(insert ( 2097 2 f 2327 )); -DATA(insert ( 2097 3 f 2328 )); -DATA(insert ( 2097 4 f 2329 )); -DATA(insert ( 2097 5 f 2330 )); +DATA(insert ( 2097 0 1 f 2326 )); +DATA(insert ( 2097 0 2 f 2327 )); +DATA(insert ( 2097 0 3 f 2328 )); +DATA(insert ( 2097 0 4 f 2329 )); +DATA(insert ( 2097 0 5 f 2330 )); /* * btree name pattern */ -DATA(insert ( 2098 1 f 2332 )); -DATA(insert ( 2098 2 f 2333 )); -DATA(insert ( 2098 3 f 2334 )); -DATA(insert ( 2098 4 f 2335 )); -DATA(insert ( 2098 5 f 2336 )); +DATA(insert ( 2098 0 1 f 2332 )); +DATA(insert ( 2098 0 2 f 2333 )); +DATA(insert ( 2098 0 3 f 2334 )); +DATA(insert ( 2098 0 4 f 2335 )); +DATA(insert ( 2098 0 5 f 2336 )); /* * btree money_ops */ -DATA(insert ( 2099 1 f 902 )); -DATA(insert ( 2099 2 f 904 )); -DATA(insert ( 2099 3 f 900 )); -DATA(insert ( 2099 4 f 905 )); -DATA(insert ( 2099 5 f 903 )); +DATA(insert ( 2099 0 1 f 902 )); +DATA(insert ( 2099 0 2 f 904 )); +DATA(insert ( 2099 0 3 f 900 )); +DATA(insert ( 2099 0 4 f 905 )); +DATA(insert ( 2099 0 5 f 903 )); /* * btree reltime_ops */ -DATA(insert ( 2233 1 f 568 )); -DATA(insert ( 2233 2 f 570 )); -DATA(insert ( 2233 3 f 566 )); -DATA(insert ( 2233 4 f 569 )); -DATA(insert ( 2233 5 f 571 )); +DATA(insert ( 2233 0 1 f 568 )); +DATA(insert ( 2233 0 2 f 570 )); +DATA(insert ( 2233 0 3 f 566 )); +DATA(insert ( 2233 0 4 f 571 )); +DATA(insert ( 2233 0 5 f 569 )); /* * btree tinterval_ops */ -DATA(insert ( 2234 1 f 813 )); -DATA(insert ( 2234 2 f 815 )); -DATA(insert ( 2234 3 f 811 )); -DATA(insert ( 2234 4 f 814 )); -DATA(insert ( 2234 5 f 816 )); +DATA(insert ( 2234 0 1 f 813 )); +DATA(insert ( 2234 0 2 f 815 )); +DATA(insert ( 2234 0 3 f 811 )); +DATA(insert ( 2234 0 4 f 816 )); +DATA(insert ( 2234 0 5 f 814 )); /* * btree array_ops */ -DATA(insert ( 397 1 f 1072 )); -DATA(insert ( 397 2 f 1074 )); -DATA(insert ( 397 3 f 1070 )); -DATA(insert ( 397 4 f 1075 )); -DATA(insert ( 397 5 f 1073 )); +DATA(insert ( 397 0 1 f 1072 )); +DATA(insert ( 397 0 2 f 1074 )); +DATA(insert ( 397 0 3 f 1070 )); +DATA(insert ( 397 0 4 f 1075 )); +DATA(insert ( 397 0 5 f 1073 )); /* * hash index _ops */ /* bpchar_ops */ -DATA(insert ( 427 1 f 1054 )); +DATA(insert ( 427 0 1 f 1054 )); /* char_ops */ -DATA(insert ( 431 1 f 92 )); +DATA(insert ( 431 0 1 f 92 )); /* cidr_ops */ -DATA(insert ( 433 1 f 820 )); +DATA(insert ( 433 0 1 f 820 )); /* date_ops */ -DATA(insert ( 435 1 f 1093 )); +DATA(insert ( 435 0 1 f 1093 )); /* float4_ops */ -DATA(insert ( 1971 1 f 620 )); +DATA(insert ( 1971 0 1 f 620 )); /* float8_ops */ -DATA(insert ( 1973 1 f 670 )); +DATA(insert ( 1973 0 1 f 670 )); /* inet_ops */ -DATA(insert ( 1975 1 f 1201 )); +DATA(insert ( 1975 0 1 f 1201 )); /* int2_ops */ -DATA(insert ( 1977 1 f 94 )); +DATA(insert ( 1977 0 1 f 94 )); /* int4_ops */ -DATA(insert ( 1979 1 f 96 )); +DATA(insert ( 1979 0 1 f 96 )); /* int8_ops */ -DATA(insert ( 1981 1 f 410 )); +DATA(insert ( 1981 0 1 f 410 )); /* interval_ops */ -DATA(insert ( 1983 1 f 1330 )); +DATA(insert ( 1983 0 1 f 1330 )); /* macaddr_ops */ -DATA(insert ( 1985 1 f 1220 )); +DATA(insert ( 1985 0 1 f 1220 )); /* name_ops */ -DATA(insert ( 1987 1 f 93 )); +DATA(insert ( 1987 0 1 f 93 )); /* oid_ops */ -DATA(insert ( 1990 1 f 607 )); +DATA(insert ( 1990 0 1 f 607 )); /* oidvector_ops */ -DATA(insert ( 1992 1 f 649 )); +DATA(insert ( 1992 0 1 f 649 )); /* text_ops */ -DATA(insert ( 1995 1 f 98 )); +DATA(insert ( 1995 0 1 f 98 )); /* time_ops */ -DATA(insert ( 1997 1 f 1108 )); +DATA(insert ( 1997 0 1 f 1108 )); /* timestamptz_ops */ -DATA(insert ( 1999 1 f 1320 )); +DATA(insert ( 1999 0 1 f 1320 )); /* timetz_ops */ -DATA(insert ( 2001 1 f 1550 )); +DATA(insert ( 2001 0 1 f 1550 )); /* varchar_ops */ -DATA(insert ( 2004 1 f 98 )); +DATA(insert ( 2004 0 1 f 98 )); /* timestamp_ops */ -DATA(insert ( 2040 1 f 2060 )); +DATA(insert ( 2040 0 1 f 2060 )); /* bool_ops */ -DATA(insert ( 2222 1 f 91 )); +DATA(insert ( 2222 0 1 f 91 )); /* bytea_ops */ -DATA(insert ( 2223 1 f 1955 )); +DATA(insert ( 2223 0 1 f 1955 )); /* int2vector_ops */ -DATA(insert ( 2224 1 f 386 )); +DATA(insert ( 2224 0 1 f 386 )); /* xid_ops */ -DATA(insert ( 2225 1 f 352 )); +DATA(insert ( 2225 0 1 f 352 )); /* cid_ops */ -DATA(insert ( 2226 1 f 385 )); +DATA(insert ( 2226 0 1 f 385 )); /* abstime_ops */ -DATA(insert ( 2227 1 f 560 )); +DATA(insert ( 2227 0 1 f 560 )); /* reltime_ops */ -DATA(insert ( 2228 1 f 566 )); +DATA(insert ( 2228 0 1 f 566 )); /* text_pattern_ops */ -DATA(insert ( 2229 1 f 2316 )); +DATA(insert ( 2229 0 1 f 2316 )); /* varchar_pattern_ops */ -DATA(insert ( 2230 1 f 2316 )); +DATA(insert ( 2230 0 1 f 2316 )); /* bpchar_pattern_ops */ -DATA(insert ( 2231 1 f 2328 )); +DATA(insert ( 2231 0 1 f 2328 )); /* name_pattern_ops */ -DATA(insert ( 2232 1 f 2334 )); +DATA(insert ( 2232 0 1 f 2334 )); /* aclitem_ops */ -DATA(insert ( 2235 1 f 974 )); +DATA(insert ( 2235 0 1 f 974 )); #endif /* PG_AMOP_H */ diff --git a/src/include/catalog/pg_amproc.h b/src/include/catalog/pg_amproc.h index a2607db5eb..e284dedbf0 100644 --- a/src/include/catalog/pg_amproc.h +++ b/src/include/catalog/pg_amproc.h @@ -6,15 +6,20 @@ * * The amproc table identifies support procedures associated with index * opclasses. These procedures can't be listed in pg_amop since they are - * not associated with indexable operators for the opclass. + * not the implementation of any indexable operator for the opclass. * - * Note: the primary key for this table is . + * The primary key for this table is . + * amprocsubtype is equal to zero for an opclass's "default" procedures. + * Usually a nondefault amprocsubtype indicates a support procedure to be + * used with operators having the same nondefault amopsubtype. The exact + * behavior depends on the index AM, however, and some don't pay attention + * to subtype at all. * * * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: pg_amproc.h,v 1.44 2003/08/17 19:58:06 tgl Exp $ + * $Id: pg_amproc.h,v 1.45 2003/11/12 21:15:57 tgl Exp $ * * NOTES * the genbki.sh script reads this file and generates .bki @@ -40,6 +45,7 @@ CATALOG(pg_amproc) BKI_WITHOUT_OIDS { Oid amopclaid; /* the index opclass this entry is for */ + Oid amprocsubtype; /* procedure subtype, or zero if default */ int2 amprocnum; /* support procedure index */ regproc amproc; /* OID of the proc */ } FormData_pg_amproc; @@ -55,10 +61,11 @@ typedef FormData_pg_amproc *Form_pg_amproc; * compiler constants for pg_amproc * ---------------- */ -#define Natts_pg_amproc 3 +#define Natts_pg_amproc 4 #define Anum_pg_amproc_amopclaid 1 -#define Anum_pg_amproc_amprocnum 2 -#define Anum_pg_amproc_amproc 3 +#define Anum_pg_amproc_amprocsubtype 2 +#define Anum_pg_amproc_amprocnum 3 +#define Anum_pg_amproc_amproc 4 /* ---------------- * initial contents of pg_amproc @@ -66,88 +73,93 @@ typedef FormData_pg_amproc *Form_pg_amproc; */ /* rtree */ -DATA(insert ( 422 1 193 )); -DATA(insert ( 422 2 194 )); -DATA(insert ( 422 3 196 )); -DATA(insert ( 425 1 193 )); -DATA(insert ( 425 2 194 )); -DATA(insert ( 425 3 195 )); -DATA(insert ( 1993 1 197 )); -DATA(insert ( 1993 2 198 )); -DATA(insert ( 1993 3 199 )); +DATA(insert ( 425 0 1 193 )); +DATA(insert ( 425 0 2 194 )); +DATA(insert ( 425 0 3 195 )); +DATA(insert ( 1993 0 1 197 )); +DATA(insert ( 1993 0 2 198 )); +DATA(insert ( 1993 0 3 199 )); /* btree */ -DATA(insert ( 397 1 382 )); -DATA(insert ( 421 1 357 )); -DATA(insert ( 423 1 1596 )); -DATA(insert ( 424 1 1693 )); -DATA(insert ( 426 1 1078 )); -DATA(insert ( 428 1 1954 )); -DATA(insert ( 429 1 358 )); -DATA(insert ( 432 1 926 )); -DATA(insert ( 434 1 1092 )); -DATA(insert ( 1970 1 354 )); -DATA(insert ( 1972 1 355 )); -DATA(insert ( 1974 1 926 )); -DATA(insert ( 1976 1 350 )); -DATA(insert ( 1978 1 351 )); -DATA(insert ( 1980 1 842 )); -DATA(insert ( 1982 1 1315 )); -DATA(insert ( 1984 1 836 )); -DATA(insert ( 1986 1 359 )); -DATA(insert ( 1988 1 1769 )); -DATA(insert ( 1989 1 356 )); -DATA(insert ( 1991 1 404 )); -DATA(insert ( 1994 1 360 )); -DATA(insert ( 1996 1 1107 )); -DATA(insert ( 1998 1 1314 )); -DATA(insert ( 2000 1 1358 )); -DATA(insert ( 2002 1 1672 )); -DATA(insert ( 2003 1 360 )); -DATA(insert ( 2039 1 2045 )); -DATA(insert ( 2095 1 2166 )); -DATA(insert ( 2096 1 2166 )); -DATA(insert ( 2097 1 2180 )); -DATA(insert ( 2098 1 2187 )); -DATA(insert ( 2099 1 377 )); -DATA(insert ( 2233 1 380 )); -DATA(insert ( 2234 1 381 )); +DATA(insert ( 397 0 1 382 )); +DATA(insert ( 421 0 1 357 )); +DATA(insert ( 423 0 1 1596 )); +DATA(insert ( 424 0 1 1693 )); +DATA(insert ( 426 0 1 1078 )); +DATA(insert ( 428 0 1 1954 )); +DATA(insert ( 429 0 1 358 )); +DATA(insert ( 432 0 1 926 )); +DATA(insert ( 434 0 1 1092 )); +DATA(insert ( 1970 0 1 354 )); +DATA(insert ( 1970 701 1 2194 )); +DATA(insert ( 1972 0 1 355 )); +DATA(insert ( 1972 700 1 2195 )); +DATA(insert ( 1974 0 1 926 )); +DATA(insert ( 1976 0 1 350 )); +DATA(insert ( 1976 23 1 2190 )); +DATA(insert ( 1976 20 1 2192 )); +DATA(insert ( 1978 0 1 351 )); +DATA(insert ( 1978 20 1 2188 )); +DATA(insert ( 1978 21 1 2191 )); +DATA(insert ( 1980 0 1 842 )); +DATA(insert ( 1980 23 1 2189 )); +DATA(insert ( 1980 21 1 2193 )); +DATA(insert ( 1982 0 1 1315 )); +DATA(insert ( 1984 0 1 836 )); +DATA(insert ( 1986 0 1 359 )); +DATA(insert ( 1988 0 1 1769 )); +DATA(insert ( 1989 0 1 356 )); +DATA(insert ( 1991 0 1 404 )); +DATA(insert ( 1994 0 1 360 )); +DATA(insert ( 1996 0 1 1107 )); +DATA(insert ( 1998 0 1 1314 )); +DATA(insert ( 2000 0 1 1358 )); +DATA(insert ( 2002 0 1 1672 )); +DATA(insert ( 2003 0 1 360 )); +DATA(insert ( 2039 0 1 2045 )); +DATA(insert ( 2095 0 1 2166 )); +DATA(insert ( 2096 0 1 2166 )); +DATA(insert ( 2097 0 1 2180 )); +DATA(insert ( 2098 0 1 2187 )); +DATA(insert ( 2099 0 1 377 )); +DATA(insert ( 2233 0 1 380 )); +DATA(insert ( 2234 0 1 381 )); /* hash */ -DATA(insert ( 427 1 1080 )); -DATA(insert ( 431 1 454 )); -DATA(insert ( 433 1 456 )); -DATA(insert ( 435 1 450 )); -DATA(insert ( 1971 1 451 )); -DATA(insert ( 1973 1 452 )); -DATA(insert ( 1975 1 456 )); -DATA(insert ( 1977 1 449 )); -DATA(insert ( 1979 1 450 )); -DATA(insert ( 1981 1 949 )); -DATA(insert ( 1983 1 1697 )); -DATA(insert ( 1985 1 399 )); -DATA(insert ( 1987 1 455 )); -DATA(insert ( 1990 1 453 )); -DATA(insert ( 1992 1 457 )); -DATA(insert ( 1995 1 400 )); -DATA(insert ( 1997 1 452 )); -DATA(insert ( 1999 1 452 )); -DATA(insert ( 2001 1 1696 )); -DATA(insert ( 2004 1 400 )); -DATA(insert ( 2040 1 452 )); -DATA(insert ( 2222 1 454 )); -DATA(insert ( 2223 1 456 )); -DATA(insert ( 2224 1 398 )); -DATA(insert ( 2225 1 450 )); -DATA(insert ( 2226 1 450 )); -DATA(insert ( 2227 1 450 )); -DATA(insert ( 2228 1 450 )); -DATA(insert ( 2229 1 456 )); -DATA(insert ( 2230 1 456 )); -DATA(insert ( 2231 1 456 )); -DATA(insert ( 2232 1 455 )); -DATA(insert ( 2235 1 329 )); +DATA(insert ( 427 0 1 1080 )); +DATA(insert ( 431 0 1 454 )); +DATA(insert ( 433 0 1 456 )); +DATA(insert ( 435 0 1 450 )); +DATA(insert ( 1971 0 1 451 )); +DATA(insert ( 1973 0 1 452 )); +DATA(insert ( 1975 0 1 456 )); +DATA(insert ( 1977 0 1 449 )); +DATA(insert ( 1979 0 1 450 )); +DATA(insert ( 1981 0 1 949 )); +DATA(insert ( 1983 0 1 1697 )); +DATA(insert ( 1985 0 1 399 )); +DATA(insert ( 1987 0 1 455 )); +DATA(insert ( 1990 0 1 453 )); +DATA(insert ( 1992 0 1 457 )); +DATA(insert ( 1995 0 1 400 )); +DATA(insert ( 1997 0 1 452 )); +DATA(insert ( 1999 0 1 452 )); +DATA(insert ( 2001 0 1 1696 )); +DATA(insert ( 2004 0 1 400 )); +DATA(insert ( 2040 0 1 452 )); +DATA(insert ( 2222 0 1 454 )); +DATA(insert ( 2223 0 1 456 )); +DATA(insert ( 2224 0 1 398 )); +DATA(insert ( 2225 0 1 450 )); +DATA(insert ( 2226 0 1 450 )); +DATA(insert ( 2227 0 1 450 )); +DATA(insert ( 2228 0 1 450 )); +DATA(insert ( 2229 0 1 456 )); +DATA(insert ( 2230 0 1 456 )); +DATA(insert ( 2231 0 1 456 )); +DATA(insert ( 2232 0 1 455 )); +DATA(insert ( 2235 0 1 329 )); #endif /* PG_AMPROC_H */ diff --git a/src/include/catalog/pg_opclass.h b/src/include/catalog/pg_opclass.h index af277ad687..0f196de19f 100644 --- a/src/include/catalog/pg_opclass.h +++ b/src/include/catalog/pg_opclass.h @@ -16,17 +16,18 @@ * such an index. * * Normally opckeytype = InvalidOid (zero), indicating that the data stored - * in the index is the same as the input data. If opckeytype is nonzero - * then it indicates that a conversion step is needed to produce the stored - * index data, which will be of type opckeytype (which might be the same or - * different from the input data). Performing such a conversion is the - * responsibility of the index access method --- not all AMs support this. + * in the index is the same as the data in the indexed column. If opckeytype + * is nonzero then it indicates that a conversion step is needed to produce + * the stored index data, which will be of type opckeytype (which might be + * the same or different from the input datatype). Performing such a + * conversion is the responsibility of the index access method --- not all + * AMs support this. * * * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: pg_opclass.h,v 1.57 2003/08/17 19:58:06 tgl Exp $ + * $Id: pg_opclass.h,v 1.58 2003/11/12 21:15:57 tgl Exp $ * * NOTES * the genbki.sh script reads this file and generates .bki @@ -56,9 +57,9 @@ CATALOG(pg_opclass) NameData opcname; /* name of this opclass */ Oid opcnamespace; /* namespace of this opclass */ int4 opcowner; /* opclass owner */ - Oid opcintype; /* type of input data for opclass */ + Oid opcintype; /* type of data indexed by opclass */ bool opcdefault; /* T if opclass is default for opcintype */ - Oid opckeytype; /* type of index data, or InvalidOid */ + Oid opckeytype; /* type of data in index, or InvalidOid */ } FormData_pg_opclass; /* ---------------- @@ -89,7 +90,6 @@ typedef FormData_pg_opclass *Form_pg_opclass; DATA(insert OID = 421 ( 403 abstime_ops PGNSP PGUID 702 t 0 )); DATA(insert OID = 397 ( 403 array_ops PGNSP PGUID 2277 t 0 )); #define ARRAY_BTREE_OPS_OID 397 -DATA(insert OID = 422 ( 402 bigbox_ops PGNSP PGUID 603 f 0 )); DATA(insert OID = 423 ( 403 bit_ops PGNSP PGUID 1560 t 0 )); DATA(insert OID = 424 ( 403 bool_ops PGNSP PGUID 16 t 0 )); DATA(insert OID = 425 ( 402 box_ops PGNSP PGUID 603 t 0 )); diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h index 4128d5f164..50b363eda3 100644 --- a/src/include/catalog/pg_proc.h +++ b/src/include/catalog/pg_proc.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: pg_proc.h,v 1.314 2003/10/21 16:23:16 tgl Exp $ + * $Id: pg_proc.h,v 1.315 2003/11/12 21:15:57 tgl Exp $ * * NOTES * The script catalog/genbki.sh reads this file and generates .bki @@ -400,8 +400,6 @@ DATA(insert OID = 194 ( rt_box_inter PGNSP PGUID 12 f f t f i 2 2278 "603 60 DESCR("r-tree"); DATA(insert OID = 195 ( rt_box_size PGNSP PGUID 12 f f t f i 2 2278 "603 2281" rt_box_size - _null_ )); DESCR("r-tree"); -DATA(insert OID = 196 ( rt_bigbox_size PGNSP PGUID 12 f f t f i 2 2278 "603 2281" rt_bigbox_size - _null_ )); -DESCR("r-tree"); DATA(insert OID = 197 ( rt_poly_union PGNSP PGUID 12 f f t f i 2 604 "604 604" rt_poly_union - _null_ )); DESCR("r-tree"); DATA(insert OID = 198 ( rt_poly_inter PGNSP PGUID 12 f f t f i 2 2278 "604 604" rt_poly_inter - _null_ )); @@ -3075,6 +3073,15 @@ DATA(insert OID = 2185 ( name_pattern_gt PGNSP PGUID 12 f f t f i 2 16 "19 19" n DATA(insert OID = 2186 ( name_pattern_ne PGNSP PGUID 12 f f t f i 2 16 "19 19" name_pattern_ne - _null_ )); DATA(insert OID = 2187 ( btname_pattern_cmp PGNSP PGUID 12 f f t f i 2 23 "19 19" btname_pattern_cmp - _null_ )); +DATA(insert OID = 2188 ( btint48cmp PGNSP PGUID 12 f f t f i 2 23 "23 20" btint48cmp - _null_ )); +DATA(insert OID = 2189 ( btint84cmp PGNSP PGUID 12 f f t f i 2 23 "20 23" btint84cmp - _null_ )); +DATA(insert OID = 2190 ( btint24cmp PGNSP PGUID 12 f f t f i 2 23 "21 23" btint24cmp - _null_ )); +DATA(insert OID = 2191 ( btint42cmp PGNSP PGUID 12 f f t f i 2 23 "23 21" btint42cmp - _null_ )); +DATA(insert OID = 2192 ( btint28cmp PGNSP PGUID 12 f f t f i 2 23 "21 20" btint28cmp - _null_ )); +DATA(insert OID = 2193 ( btint82cmp PGNSP PGUID 12 f f t f i 2 23 "20 21" btint82cmp - _null_ )); +DATA(insert OID = 2194 ( btfloat48cmp PGNSP PGUID 12 f f t f i 2 23 "700 701" btfloat48cmp - _null_ )); +DATA(insert OID = 2195 ( btfloat84cmp PGNSP PGUID 12 f f t f i 2 23 "701 700" btfloat84cmp - _null_ )); + DATA(insert OID = 2212 ( regprocedurein PGNSP PGUID 12 f f t f s 1 2202 "2275" regprocedurein - _null_ )); DESCR("I/O"); @@ -3157,7 +3164,6 @@ DATA(insert OID = 2273 ( has_schema_privilege PGNSP PGUID 12 f f t f s 2 16 DESCR("current user privilege on schema by schema oid"); - DATA(insert OID = 2290 ( record_in PGNSP PGUID 12 f f t f i 1 2249 "2275" record_in - _null_ )); DESCR("I/O"); DATA(insert OID = 2291 ( record_out PGNSP PGUID 12 f f t f i 1 2275 "2249" record_out - _null_ )); diff --git a/src/include/nodes/plannodes.h b/src/include/nodes/plannodes.h index 2312c0562e..669ce93e70 100644 --- a/src/include/nodes/plannodes.h +++ b/src/include/nodes/plannodes.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: plannodes.h,v 1.69 2003/11/09 21:30:37 tgl Exp $ + * $Id: plannodes.h,v 1.70 2003/11/12 21:15:59 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -165,6 +165,7 @@ typedef struct IndexScan List *indxqual; /* list of sublists of index quals */ List *indxqualorig; /* the same in original form */ List *indxstrategy; /* list of sublists of strategy numbers */ + List *indxsubtype; /* list of sublists of strategy subtypes */ ScanDirection indxorderdir; /* forward or backward or don't care */ } IndexScan; diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h index 71615b6610..6025531147 100644 --- a/src/include/utils/builtins.h +++ b/src/include/utils/builtins.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: builtins.h,v 1.228 2003/08/17 19:58:06 tgl Exp $ + * $Id: builtins.h,v 1.229 2003/11/12 21:15:59 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -219,6 +219,14 @@ extern Datum btint4cmp(PG_FUNCTION_ARGS); extern Datum btint8cmp(PG_FUNCTION_ARGS); extern Datum btfloat4cmp(PG_FUNCTION_ARGS); extern Datum btfloat8cmp(PG_FUNCTION_ARGS); +extern Datum btint48cmp(PG_FUNCTION_ARGS); +extern Datum btint84cmp(PG_FUNCTION_ARGS); +extern Datum btint24cmp(PG_FUNCTION_ARGS); +extern Datum btint42cmp(PG_FUNCTION_ARGS); +extern Datum btint28cmp(PG_FUNCTION_ARGS); +extern Datum btint82cmp(PG_FUNCTION_ARGS); +extern Datum btfloat48cmp(PG_FUNCTION_ARGS); +extern Datum btfloat84cmp(PG_FUNCTION_ARGS); extern Datum btoidcmp(PG_FUNCTION_ARGS); extern Datum btoidvectorcmp(PG_FUNCTION_ARGS); extern Datum btabstimecmp(PG_FUNCTION_ARGS); diff --git a/src/include/utils/geo_decls.h b/src/include/utils/geo_decls.h index e029c136b8..8b94588509 100644 --- a/src/include/utils/geo_decls.h +++ b/src/include/utils/geo_decls.h @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: geo_decls.h,v 1.41 2003/08/04 02:40:15 momjian Exp $ + * $Id: geo_decls.h,v 1.42 2003/11/12 21:15:59 tgl Exp $ * * NOTE * These routines do *not* use the float types from adt/. @@ -399,7 +399,6 @@ extern Datum circle_area(PG_FUNCTION_ARGS); extern Datum rt_box_union(PG_FUNCTION_ARGS); extern Datum rt_box_inter(PG_FUNCTION_ARGS); extern Datum rt_box_size(PG_FUNCTION_ARGS); -extern Datum rt_bigbox_size(PG_FUNCTION_ARGS); extern Datum rt_poly_size(PG_FUNCTION_ARGS); extern Datum rt_poly_union(PG_FUNCTION_ARGS); extern Datum rt_poly_inter(PG_FUNCTION_ARGS); diff --git a/src/include/utils/lsyscache.h b/src/include/utils/lsyscache.h index 36146f23d1..2f017db844 100644 --- a/src/include/utils/lsyscache.h +++ b/src/include/utils/lsyscache.h @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: lsyscache.h,v 1.83 2003/11/09 21:30:38 tgl Exp $ + * $Id: lsyscache.h,v 1.84 2003/11/12 21:15:59 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -26,10 +26,11 @@ typedef enum IOFuncSelector extern bool op_in_opclass(Oid opno, Oid opclass); extern void get_op_opclass_properties(Oid opno, Oid opclass, - int *strategy, bool *recheck); -extern Oid get_opclass_member(Oid opclass, int16 strategy); + int *strategy, Oid *subtype, + bool *recheck); +extern Oid get_opclass_member(Oid opclass, Oid subtype, int16 strategy); extern Oid get_op_hash_function(Oid opno); -extern Oid get_opclass_proc(Oid opclass, int16 procnum); +extern Oid get_opclass_proc(Oid opclass, Oid subtype, int16 procnum); extern char *get_attname(Oid relid, AttrNumber attnum); extern char *get_relid_attribute_name(Oid relid, AttrNumber attnum); extern AttrNumber get_attnum(Oid relid, const char *attname); diff --git a/src/include/utils/rel.h b/src/include/utils/rel.h index f08d6c0f1f..eb24cf839f 100644 --- a/src/include/utils/rel.h +++ b/src/include/utils/rel.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: rel.h,v 1.69 2003/11/09 21:30:38 tgl Exp $ + * $Id: rel.h,v 1.70 2003/11/12 21:15:59 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -139,8 +139,8 @@ typedef struct RelationData /* * index access support info (used only for an index relation) * - * Note: only operators and support procs for the index's own datatype - * are cached, not any cross-type operators. The arrays are indexed by + * Note: only default operators and support procs for each opclass are + * cached, namely those with subtype zero. The arrays are indexed by * strategy or support number, which is a sufficient identifier given * that restriction. */ diff --git a/src/test/regress/expected/create_index.out b/src/test/regress/expected/create_index.out index 464ab8d7e8..46d2657d01 100644 --- a/src/test/regress/expected/create_index.out +++ b/src/test/regress/expected/create_index.out @@ -47,7 +47,7 @@ CREATE INDEX onek2_stu1_prtl ON onek2 USING btree(stringu1 name_ops) -- in the regression test (we check them using the sequoia 2000 -- benchmark). -- -CREATE INDEX rect2ind ON fast_emp4000 USING rtree (home_base bigbox_ops); +CREATE INDEX rect2ind ON fast_emp4000 USING rtree (home_base); -- there's no easy way to check that this command actually is using -- the index, unfortunately. (EXPLAIN would work, but its output -- changes too often for me to want to put an EXPLAIN in the test...) diff --git a/src/test/regress/expected/oidjoins.out b/src/test/regress/expected/oidjoins.out index 0bdecf5ed1..21628b6e69 100644 --- a/src/test/regress/expected/oidjoins.out +++ b/src/test/regress/expected/oidjoins.out @@ -129,6 +129,14 @@ WHERE amopclaid != 0 AND ------+----------- (0 rows) +SELECT ctid, amopsubtype +FROM pg_catalog.pg_amop fk +WHERE amopsubtype != 0 AND + NOT EXISTS(SELECT 1 FROM pg_catalog.pg_type pk WHERE pk.oid = fk.amopsubtype); + ctid | amopsubtype +------+------------- +(0 rows) + SELECT ctid, amopopr FROM pg_catalog.pg_amop fk WHERE amopopr != 0 AND @@ -145,6 +153,14 @@ WHERE amopclaid != 0 AND ------+----------- (0 rows) +SELECT ctid, amprocsubtype +FROM pg_catalog.pg_amproc fk +WHERE amprocsubtype != 0 AND + NOT EXISTS(SELECT 1 FROM pg_catalog.pg_type pk WHERE pk.oid = fk.amprocsubtype); + ctid | amprocsubtype +------+--------------- +(0 rows) + SELECT ctid, amproc FROM pg_catalog.pg_amproc fk WHERE amproc != 0 AND diff --git a/src/test/regress/expected/opr_sanity.out b/src/test/regress/expected/opr_sanity.out index 985e06595e..4e2c76de5c 100644 --- a/src/test/regress/expected/opr_sanity.out +++ b/src/test/regress/expected/opr_sanity.out @@ -685,30 +685,61 @@ WHERE p1.amopclaid = p3.oid AND p3.opcamid = p2.oid AND -----------+---------+-----+-------- (0 rows) --- Detect missing pg_amop entries: should have as many strategy functions --- as AM expects for each opclass for the AM -SELECT p1.oid, p1.amname, p2.oid, p2.opcname -FROM pg_am AS p1, pg_opclass AS p2 -WHERE p2.opcamid = p1.oid AND - p1.amstrategies != (SELECT count(*) FROM pg_amop AS p3 - WHERE p3.amopclaid = p2.oid); - oid | amname | oid | opcname ------+--------+-----+--------- +-- Detect missing pg_amop entries: should have as many strategy operators +-- as AM expects for each opclass for the AM. When nondefault subtypes are +-- present, enforce condition separately for each subtype. +SELECT p1.oid, p1.amname, p2.oid, p2.opcname, p3.amopsubtype +FROM pg_am AS p1, pg_opclass AS p2, pg_amop AS p3 +WHERE p2.opcamid = p1.oid AND p3.amopclaid = p2.oid AND + p1.amstrategies != (SELECT count(*) FROM pg_amop AS p4 + WHERE p4.amopclaid = p2.oid AND + p4.amopsubtype = p3.amopsubtype); + oid | amname | oid | opcname | amopsubtype +-----+--------+-----+---------+------------- (0 rows) -- Check that amopopr points at a reasonable-looking operator, ie a binary -- operator yielding boolean. --- NOTE: for 7.1, add restriction that operator inputs are of same type. --- We used to have opclasses like "int24_ops" but these were broken. SELECT p1.amopclaid, p1.amopopr, p2.oid, p2.oprname FROM pg_amop AS p1, pg_operator AS p2 WHERE p1.amopopr = p2.oid AND - (p2.oprkind != 'b' OR p2.oprresult != 'bool'::regtype OR - p2.oprleft != p2.oprright); + (p2.oprkind != 'b' OR p2.oprresult != 'bool'::regtype); amopclaid | amopopr | oid | oprname -----------+---------+-----+--------- (0 rows) +-- Make a list of all the distinct operator names being used in particular +-- strategy slots. This is a bit hokey, since the list might need to change +-- in future releases, but it's an effective way of spotting mistakes such as +-- swapping two operators within a class. +SELECT DISTINCT opcamid, amopstrategy, oprname +FROM pg_amop p1 LEFT JOIN pg_opclass p2 ON amopclaid = p2.oid + LEFT JOIN pg_operator p3 ON amopopr = p3.oid +ORDER BY 1, 2, 3; + opcamid | amopstrategy | oprname +---------+--------------+--------- + 402 | 1 | << + 402 | 2 | &< + 402 | 3 | && + 402 | 4 | &> + 402 | 5 | >> + 402 | 6 | ~= + 402 | 7 | ~ + 402 | 8 | @ + 403 | 1 | < + 403 | 1 | ~<~ + 403 | 2 | <= + 403 | 2 | ~<=~ + 403 | 3 | = + 403 | 3 | ~=~ + 403 | 4 | >= + 403 | 4 | ~>=~ + 403 | 5 | > + 403 | 5 | ~>~ + 405 | 1 | = + 405 | 1 | ~=~ +(20 rows) + -- Check that all operators linked to by opclass entries have selectivity -- estimators. This is not absolutely required, but it seems a reasonable -- thing to insist on for all standard datatypes. @@ -721,11 +752,31 @@ WHERE p1.amopopr = p2.oid AND (0 rows) -- Check that operator input types match the opclass +-- For 7.5, we require that oprleft match opcintype (possibly by coercion). +-- When amopsubtype is zero (default), oprright must equal oprleft; +-- when amopsubtype is not zero, oprright must equal amopsubtype. +SELECT p1.amopclaid, p1.amopopr, p2.oid, p2.oprname, p3.opcname +FROM pg_amop AS p1, pg_operator AS p2, pg_opclass AS p3 +WHERE p1.amopopr = p2.oid AND p1.amopclaid = p3.oid AND + NOT binary_coercible(p3.opcintype, p2.oprleft); + amopclaid | amopopr | oid | oprname | opcname +-----------+---------+-----+---------+--------- +(0 rows) + SELECT p1.amopclaid, p1.amopopr, p2.oid, p2.oprname, p3.opcname FROM pg_amop AS p1, pg_operator AS p2, pg_opclass AS p3 WHERE p1.amopopr = p2.oid AND p1.amopclaid = p3.oid AND - (NOT binary_coercible(p3.opcintype, p2.oprleft) OR - p2.oprleft != p2.oprright); + p1.amopsubtype = 0 AND + p2.oprleft != p2.oprright; + amopclaid | amopopr | oid | oprname | opcname +-----------+---------+-----+---------+--------- +(0 rows) + +SELECT p1.amopclaid, p1.amopopr, p2.oid, p2.oprname, p3.opcname +FROM pg_amop AS p1, pg_operator AS p2, pg_opclass AS p3 +WHERE p1.amopopr = p2.oid AND p1.amopclaid = p3.oid AND + p1.amopsubtype != 0 AND + p1.amopsubtype != p2.oprright; amopclaid | amopopr | oid | oprname | opcname -----------+---------+-----+---------+--------- (0 rows) @@ -749,14 +800,16 @@ WHERE p1.amopclaid = p3.oid AND p3.opcamid = p2.oid AND (0 rows) -- Detect missing pg_amproc entries: should have as many support functions --- as AM expects for each opclass for the AM -SELECT p1.oid, p1.amname, p2.oid, p2.opcname -FROM pg_am AS p1, pg_opclass AS p2 -WHERE p2.opcamid = p1.oid AND - p1.amsupport != (SELECT count(*) FROM pg_amproc AS p3 - WHERE p3.amopclaid = p2.oid); - oid | amname | oid | opcname ------+--------+-----+--------- +-- as AM expects for each opclass for the AM. When nondefault subtypes are +-- present, enforce condition separately for each subtype. +SELECT p1.oid, p1.amname, p2.oid, p2.opcname, p3.amprocsubtype +FROM pg_am AS p1, pg_opclass AS p2, pg_amproc AS p3 +WHERE p2.opcamid = p1.oid AND p3.amopclaid = p2.oid AND + p1.amsupport != (SELECT count(*) FROM pg_amproc AS p4 + WHERE p4.amopclaid = p2.oid AND + p4.amprocsubtype = p3.amprocsubtype); + oid | amname | oid | opcname | amprocsubtype +-----+--------+-----+---------+--------------- (0 rows) -- Unfortunately, we can't check the amproc link very well because the @@ -782,13 +835,15 @@ WHERE p1.amopclaid = p3.oid AND p4.amopclaid = p6.oid AND (0 rows) -- For btree, though, we can do better since we know the support routines --- must be of the form cmp(input, input) returns int4. +-- must be of the form cmp(input, input) returns int4 in the default case +-- (subtype = 0), and cmp(input, subtype) returns int4 when subtype != 0. SELECT p1.amopclaid, p1.amprocnum, p2.oid, p2.proname, p3.opcname FROM pg_amproc AS p1, pg_proc AS p2, pg_opclass AS p3 WHERE p3.opcamid = (SELECT oid FROM pg_am WHERE amname = 'btree') AND p1.amopclaid = p3.oid AND p1.amproc = p2.oid AND + amprocsubtype = 0 AND (opckeytype != 0 OR amprocnum != 1 OR proretset @@ -800,6 +855,24 @@ WHERE p3.opcamid = (SELECT oid FROM pg_am WHERE amname = 'btree') -----------+-----------+-----+---------+--------- (0 rows) +SELECT p1.amopclaid, p1.amprocnum, + p2.oid, p2.proname, + p3.opcname +FROM pg_amproc AS p1, pg_proc AS p2, pg_opclass AS p3 +WHERE p3.opcamid = (SELECT oid FROM pg_am WHERE amname = 'btree') + AND p1.amopclaid = p3.oid AND p1.amproc = p2.oid AND + amprocsubtype != 0 AND + (opckeytype != 0 + OR amprocnum != 1 + OR proretset + OR prorettype != 23 + OR pronargs != 2 + OR NOT binary_coercible(opcintype, proargtypes[0]) + OR proargtypes[1] != amprocsubtype); + amopclaid | amprocnum | oid | proname | opcname +-----------+-----------+-----+---------+--------- +(0 rows) + -- For hash we can also do a little better: the support routines must be -- of the form hash(something) returns int4. Ideally we'd check that the -- opcintype is binary-coercible to the function's input, but there are diff --git a/src/test/regress/sql/create_index.sql b/src/test/regress/sql/create_index.sql index 8400a3bb33..d904bacd66 100644 --- a/src/test/regress/sql/create_index.sql +++ b/src/test/regress/sql/create_index.sql @@ -68,7 +68,7 @@ CREATE INDEX onek2_stu1_prtl ON onek2 USING btree(stringu1 name_ops) -- in the regression test (we check them using the sequoia 2000 -- benchmark). -- -CREATE INDEX rect2ind ON fast_emp4000 USING rtree (home_base bigbox_ops); +CREATE INDEX rect2ind ON fast_emp4000 USING rtree (home_base); -- there's no easy way to check that this command actually is using -- the index, unfortunately. (EXPLAIN would work, but its output diff --git a/src/test/regress/sql/oidjoins.sql b/src/test/regress/sql/oidjoins.sql index 5e8323bc11..d822aaf4e5 100644 --- a/src/test/regress/sql/oidjoins.sql +++ b/src/test/regress/sql/oidjoins.sql @@ -65,6 +65,10 @@ SELECT ctid, amopclaid FROM pg_catalog.pg_amop fk WHERE amopclaid != 0 AND NOT EXISTS(SELECT 1 FROM pg_catalog.pg_opclass pk WHERE pk.oid = fk.amopclaid); +SELECT ctid, amopsubtype +FROM pg_catalog.pg_amop fk +WHERE amopsubtype != 0 AND + NOT EXISTS(SELECT 1 FROM pg_catalog.pg_type pk WHERE pk.oid = fk.amopsubtype); SELECT ctid, amopopr FROM pg_catalog.pg_amop fk WHERE amopopr != 0 AND @@ -73,6 +77,10 @@ SELECT ctid, amopclaid FROM pg_catalog.pg_amproc fk WHERE amopclaid != 0 AND NOT EXISTS(SELECT 1 FROM pg_catalog.pg_opclass pk WHERE pk.oid = fk.amopclaid); +SELECT ctid, amprocsubtype +FROM pg_catalog.pg_amproc fk +WHERE amprocsubtype != 0 AND + NOT EXISTS(SELECT 1 FROM pg_catalog.pg_type pk WHERE pk.oid = fk.amprocsubtype); SELECT ctid, amproc FROM pg_catalog.pg_amproc fk WHERE amproc != 0 AND diff --git a/src/test/regress/sql/opr_sanity.sql b/src/test/regress/sql/opr_sanity.sql index 9cba48b429..448f3ff0c5 100644 --- a/src/test/regress/sql/opr_sanity.sql +++ b/src/test/regress/sql/opr_sanity.sql @@ -574,25 +574,34 @@ FROM pg_amop AS p1, pg_am AS p2, pg_opclass AS p3 WHERE p1.amopclaid = p3.oid AND p3.opcamid = p2.oid AND p1.amopstrategy > p2.amstrategies; --- Detect missing pg_amop entries: should have as many strategy functions --- as AM expects for each opclass for the AM +-- Detect missing pg_amop entries: should have as many strategy operators +-- as AM expects for each opclass for the AM. When nondefault subtypes are +-- present, enforce condition separately for each subtype. -SELECT p1.oid, p1.amname, p2.oid, p2.opcname -FROM pg_am AS p1, pg_opclass AS p2 -WHERE p2.opcamid = p1.oid AND - p1.amstrategies != (SELECT count(*) FROM pg_amop AS p3 - WHERE p3.amopclaid = p2.oid); +SELECT p1.oid, p1.amname, p2.oid, p2.opcname, p3.amopsubtype +FROM pg_am AS p1, pg_opclass AS p2, pg_amop AS p3 +WHERE p2.opcamid = p1.oid AND p3.amopclaid = p2.oid AND + p1.amstrategies != (SELECT count(*) FROM pg_amop AS p4 + WHERE p4.amopclaid = p2.oid AND + p4.amopsubtype = p3.amopsubtype); -- Check that amopopr points at a reasonable-looking operator, ie a binary -- operator yielding boolean. --- NOTE: for 7.1, add restriction that operator inputs are of same type. --- We used to have opclasses like "int24_ops" but these were broken. SELECT p1.amopclaid, p1.amopopr, p2.oid, p2.oprname FROM pg_amop AS p1, pg_operator AS p2 WHERE p1.amopopr = p2.oid AND - (p2.oprkind != 'b' OR p2.oprresult != 'bool'::regtype OR - p2.oprleft != p2.oprright); + (p2.oprkind != 'b' OR p2.oprresult != 'bool'::regtype); + +-- Make a list of all the distinct operator names being used in particular +-- strategy slots. This is a bit hokey, since the list might need to change +-- in future releases, but it's an effective way of spotting mistakes such as +-- swapping two operators within a class. + +SELECT DISTINCT opcamid, amopstrategy, oprname +FROM pg_amop p1 LEFT JOIN pg_opclass p2 ON amopclaid = p2.oid + LEFT JOIN pg_operator p3 ON amopopr = p3.oid +ORDER BY 1, 2, 3; -- Check that all operators linked to by opclass entries have selectivity -- estimators. This is not absolutely required, but it seems a reasonable @@ -604,12 +613,26 @@ WHERE p1.amopopr = p2.oid AND (p2.oprrest = 0 OR p2.oprjoin = 0); -- Check that operator input types match the opclass +-- For 7.5, we require that oprleft match opcintype (possibly by coercion). +-- When amopsubtype is zero (default), oprright must equal oprleft; +-- when amopsubtype is not zero, oprright must equal amopsubtype. + +SELECT p1.amopclaid, p1.amopopr, p2.oid, p2.oprname, p3.opcname +FROM pg_amop AS p1, pg_operator AS p2, pg_opclass AS p3 +WHERE p1.amopopr = p2.oid AND p1.amopclaid = p3.oid AND + NOT binary_coercible(p3.opcintype, p2.oprleft); SELECT p1.amopclaid, p1.amopopr, p2.oid, p2.oprname, p3.opcname FROM pg_amop AS p1, pg_operator AS p2, pg_opclass AS p3 WHERE p1.amopopr = p2.oid AND p1.amopclaid = p3.oid AND - (NOT binary_coercible(p3.opcintype, p2.oprleft) OR - p2.oprleft != p2.oprright); + p1.amopsubtype = 0 AND + p2.oprleft != p2.oprright; + +SELECT p1.amopclaid, p1.amopopr, p2.oid, p2.oprname, p3.opcname +FROM pg_amop AS p1, pg_operator AS p2, pg_opclass AS p3 +WHERE p1.amopopr = p2.oid AND p1.amopclaid = p3.oid AND + p1.amopsubtype != 0 AND + p1.amopsubtype != p2.oprright; -- **************** pg_amproc **************** @@ -627,13 +650,15 @@ WHERE p1.amopclaid = p3.oid AND p3.opcamid = p2.oid AND p1.amprocnum > p2.amsupport; -- Detect missing pg_amproc entries: should have as many support functions --- as AM expects for each opclass for the AM +-- as AM expects for each opclass for the AM. When nondefault subtypes are +-- present, enforce condition separately for each subtype. -SELECT p1.oid, p1.amname, p2.oid, p2.opcname -FROM pg_am AS p1, pg_opclass AS p2 -WHERE p2.opcamid = p1.oid AND - p1.amsupport != (SELECT count(*) FROM pg_amproc AS p3 - WHERE p3.amopclaid = p2.oid); +SELECT p1.oid, p1.amname, p2.oid, p2.opcname, p3.amprocsubtype +FROM pg_am AS p1, pg_opclass AS p2, pg_amproc AS p3 +WHERE p2.opcamid = p1.oid AND p3.amopclaid = p2.oid AND + p1.amsupport != (SELECT count(*) FROM pg_amproc AS p4 + WHERE p4.amopclaid = p2.oid AND + p4.amprocsubtype = p3.amprocsubtype); -- Unfortunately, we can't check the amproc link very well because the -- signature of the function may be different for different support routines @@ -656,7 +681,8 @@ WHERE p1.amopclaid = p3.oid AND p4.amopclaid = p6.oid AND (p2.proretset OR p5.proretset OR p2.pronargs != p5.pronargs); -- For btree, though, we can do better since we know the support routines --- must be of the form cmp(input, input) returns int4. +-- must be of the form cmp(input, input) returns int4 in the default case +-- (subtype = 0), and cmp(input, subtype) returns int4 when subtype != 0. SELECT p1.amopclaid, p1.amprocnum, p2.oid, p2.proname, @@ -664,6 +690,7 @@ SELECT p1.amopclaid, p1.amprocnum, FROM pg_amproc AS p1, pg_proc AS p2, pg_opclass AS p3 WHERE p3.opcamid = (SELECT oid FROM pg_am WHERE amname = 'btree') AND p1.amopclaid = p3.oid AND p1.amproc = p2.oid AND + amprocsubtype = 0 AND (opckeytype != 0 OR amprocnum != 1 OR proretset @@ -672,6 +699,21 @@ WHERE p3.opcamid = (SELECT oid FROM pg_am WHERE amname = 'btree') OR NOT binary_coercible(opcintype, proargtypes[0]) OR proargtypes[0] != proargtypes[1]); +SELECT p1.amopclaid, p1.amprocnum, + p2.oid, p2.proname, + p3.opcname +FROM pg_amproc AS p1, pg_proc AS p2, pg_opclass AS p3 +WHERE p3.opcamid = (SELECT oid FROM pg_am WHERE amname = 'btree') + AND p1.amopclaid = p3.oid AND p1.amproc = p2.oid AND + amprocsubtype != 0 AND + (opckeytype != 0 + OR amprocnum != 1 + OR proretset + OR prorettype != 23 + OR pronargs != 2 + OR NOT binary_coercible(opcintype, proargtypes[0]) + OR proargtypes[1] != amprocsubtype); + -- For hash we can also do a little better: the support routines must be -- of the form hash(something) returns int4. Ideally we'd check that the -- opcintype is binary-coercible to the function's input, but there are