1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-28 23:42:10 +03:00

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.
This commit is contained in:
Tom Lane
2003-11-12 21:15:59 +00:00
parent 49f98fa833
commit fa5c8a055a
76 changed files with 2237 additions and 1492 deletions

View File

@ -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,

View File

@ -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);

View File

@ -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);
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(pg_amop_scan)))
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);
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(pg_amproc_scan)))
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)))
{

View File

@ -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 */

View File

@ -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);