mirror of
https://github.com/postgres/postgres.git
synced 2025-11-12 05:01:15 +03:00
Restructure pg_opclass, pg_amop, and pg_amproc per previous discussions in
pgsql-hackers. pg_opclass now has a row for each opclass supported by each index AM, not a row for each opclass name. This allows pg_opclass to show directly whether an AM supports an opclass, and furthermore makes it possible to store additional information about an opclass that might be AM-dependent. pg_opclass and pg_amop now store "lossy" and "haskeytype" information that we previously expected the user to remember to provide in CREATE INDEX commands. Lossiness is no longer an index-level property, but is associated with the use of a particular operator in a particular index opclass. Along the way, IndexSupportInitialize now uses the syscaches to retrieve pg_amop and pg_amproc entries. I find this reduces backend launch time by about ten percent, at the cost of a couple more special cases in catcache.c's IndexScanOK. Initial work by Oleg Bartunov and Teodor Sigaev, further hacking by Tom Lane. initdb forced.
This commit is contained in:
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/adt/regproc.c,v 1.62 2001/06/22 19:16:23 wieck Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/adt/regproc.c,v 1.63 2001/08/21 16:36:04 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -19,12 +19,12 @@
|
||||
#include "catalog/catname.h"
|
||||
#include "catalog/indexing.h"
|
||||
#include "catalog/pg_proc.h"
|
||||
#include "catalog/pg_type.h"
|
||||
#include "miscadmin.h"
|
||||
#include "utils/builtins.h"
|
||||
#include "utils/fmgroids.h"
|
||||
#include "utils/syscache.h"
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* USER I/O ROUTINES *
|
||||
*****************************************************************************/
|
||||
@@ -32,126 +32,103 @@
|
||||
/*
|
||||
* regprocin - converts "proname" or "proid" to proid
|
||||
*
|
||||
* We need to accept an OID for cases where the name is ambiguous.
|
||||
*
|
||||
* proid of '-' signifies unknown, for consistency with regprocout
|
||||
*/
|
||||
Datum
|
||||
regprocin(PG_FUNCTION_ARGS)
|
||||
{
|
||||
char *pro_name_or_oid = PG_GETARG_CSTRING(0);
|
||||
HeapTuple proctup;
|
||||
HeapTupleData tuple;
|
||||
RegProcedure result = InvalidOid;
|
||||
int matches = 0;
|
||||
ScanKeyData skey[1];
|
||||
|
||||
if (pro_name_or_oid[0] == '-' && pro_name_or_oid[1] == '\0')
|
||||
PG_RETURN_OID(InvalidOid);
|
||||
|
||||
if (!IsIgnoringSystemIndexes())
|
||||
if (pro_name_or_oid[0] >= '0' &&
|
||||
pro_name_or_oid[0] <= '9')
|
||||
{
|
||||
Oid searchOid;
|
||||
|
||||
/*
|
||||
* we need to use the oid because there can be multiple entries
|
||||
* with the same name. We accept int4eq_1323 and 1323.
|
||||
*/
|
||||
if (pro_name_or_oid[0] >= '0' &&
|
||||
pro_name_or_oid[0] <= '9')
|
||||
searchOid = DatumGetObjectId(DirectFunctionCall1(oidin,
|
||||
CStringGetDatum(pro_name_or_oid)));
|
||||
result = (RegProcedure) GetSysCacheOid(PROCOID,
|
||||
ObjectIdGetDatum(searchOid),
|
||||
0, 0, 0);
|
||||
if (!RegProcedureIsValid(result))
|
||||
elog(ERROR, "No procedure with oid %s", pro_name_or_oid);
|
||||
matches = 1;
|
||||
}
|
||||
else if (!IsIgnoringSystemIndexes())
|
||||
{
|
||||
Relation hdesc;
|
||||
Relation idesc;
|
||||
IndexScanDesc sd;
|
||||
RetrieveIndexResult indexRes;
|
||||
HeapTupleData tuple;
|
||||
Buffer buffer;
|
||||
|
||||
ScanKeyEntryInitialize(&skey[0], 0x0,
|
||||
(AttrNumber) 1,
|
||||
(RegProcedure) F_NAMEEQ,
|
||||
CStringGetDatum(pro_name_or_oid));
|
||||
|
||||
hdesc = heap_openr(ProcedureRelationName, AccessShareLock);
|
||||
idesc = index_openr(ProcedureNameIndex);
|
||||
sd = index_beginscan(idesc, false, 1, skey);
|
||||
|
||||
while ((indexRes = index_getnext(sd, ForwardScanDirection)))
|
||||
{
|
||||
result = (RegProcedure)
|
||||
GetSysCacheOid(PROCOID,
|
||||
DirectFunctionCall1(oidin,
|
||||
CStringGetDatum(pro_name_or_oid)),
|
||||
0, 0, 0);
|
||||
if (!RegProcedureIsValid(result))
|
||||
elog(ERROR, "No procedure with oid %s", pro_name_or_oid);
|
||||
}
|
||||
else
|
||||
{
|
||||
Relation hdesc;
|
||||
Relation idesc;
|
||||
IndexScanDesc sd;
|
||||
ScanKeyData skey[1];
|
||||
RetrieveIndexResult indexRes;
|
||||
Buffer buffer;
|
||||
int matches = 0;
|
||||
|
||||
ScanKeyEntryInitialize(&skey[0],
|
||||
(bits16) 0x0,
|
||||
(AttrNumber) 1,
|
||||
(RegProcedure) F_NAMEEQ,
|
||||
CStringGetDatum(pro_name_or_oid));
|
||||
|
||||
hdesc = heap_openr(ProcedureRelationName, AccessShareLock);
|
||||
idesc = index_openr(ProcedureNameIndex);
|
||||
|
||||
sd = index_beginscan(idesc, false, 1, skey);
|
||||
while ((indexRes = index_getnext(sd, ForwardScanDirection)))
|
||||
tuple.t_datamcxt = NULL;
|
||||
tuple.t_data = NULL;
|
||||
tuple.t_self = indexRes->heap_iptr;
|
||||
heap_fetch(hdesc, SnapshotNow, &tuple, &buffer, sd);
|
||||
pfree(indexRes);
|
||||
if (tuple.t_data != NULL)
|
||||
{
|
||||
tuple.t_datamcxt = NULL;
|
||||
tuple.t_data = NULL;
|
||||
tuple.t_self = indexRes->heap_iptr;
|
||||
heap_fetch(hdesc, SnapshotNow,
|
||||
&tuple,
|
||||
&buffer,
|
||||
sd);
|
||||
pfree(indexRes);
|
||||
if (tuple.t_data != NULL)
|
||||
{
|
||||
result = (RegProcedure) tuple.t_data->t_oid;
|
||||
ReleaseBuffer(buffer);
|
||||
|
||||
if (++matches > 1)
|
||||
break;
|
||||
}
|
||||
result = (RegProcedure) tuple.t_data->t_oid;
|
||||
ReleaseBuffer(buffer);
|
||||
if (++matches > 1)
|
||||
break;
|
||||
}
|
||||
|
||||
index_endscan(sd);
|
||||
index_close(idesc);
|
||||
heap_close(hdesc, AccessShareLock);
|
||||
|
||||
if (matches > 1)
|
||||
elog(ERROR, "There is more than one procedure named %s.\n\tSupply the pg_proc oid inside single quotes.", pro_name_or_oid);
|
||||
else if (matches == 0)
|
||||
elog(ERROR, "No procedure with name %s", pro_name_or_oid);
|
||||
}
|
||||
|
||||
index_endscan(sd);
|
||||
index_close(idesc);
|
||||
heap_close(hdesc, AccessShareLock);
|
||||
}
|
||||
else
|
||||
{
|
||||
Relation proc;
|
||||
HeapScanDesc procscan;
|
||||
ScanKeyData key;
|
||||
bool isnull;
|
||||
HeapTuple proctup;
|
||||
|
||||
proc = heap_openr(ProcedureRelationName, AccessShareLock);
|
||||
ScanKeyEntryInitialize(&key,
|
||||
(bits16) 0,
|
||||
(AttrNumber) 1,
|
||||
ScanKeyEntryInitialize(&skey[0], 0x0,
|
||||
(AttrNumber) Anum_pg_proc_proname,
|
||||
(RegProcedure) F_NAMEEQ,
|
||||
CStringGetDatum(pro_name_or_oid));
|
||||
|
||||
procscan = heap_beginscan(proc, 0, SnapshotNow, 1, &key);
|
||||
if (!HeapScanIsValid(procscan))
|
||||
proc = heap_openr(ProcedureRelationName, AccessShareLock);
|
||||
procscan = heap_beginscan(proc, 0, SnapshotNow, 1, skey);
|
||||
|
||||
while (HeapTupleIsValid(proctup = heap_getnext(procscan, 0)))
|
||||
{
|
||||
heap_close(proc, AccessShareLock);
|
||||
elog(ERROR, "regprocin: could not begin scan of %s",
|
||||
ProcedureRelationName);
|
||||
PG_RETURN_OID(InvalidOid);
|
||||
result = proctup->t_data->t_oid;
|
||||
if (++matches > 1)
|
||||
break;
|
||||
}
|
||||
proctup = heap_getnext(procscan, 0);
|
||||
if (HeapTupleIsValid(proctup))
|
||||
{
|
||||
result = (RegProcedure) heap_getattr(proctup,
|
||||
ObjectIdAttributeNumber,
|
||||
RelationGetDescr(proc),
|
||||
&isnull);
|
||||
if (isnull)
|
||||
elog(ERROR, "regprocin: null procedure %s", pro_name_or_oid);
|
||||
}
|
||||
else
|
||||
elog(ERROR, "No procedure with name %s", pro_name_or_oid);
|
||||
|
||||
heap_endscan(procscan);
|
||||
heap_close(proc, AccessShareLock);
|
||||
}
|
||||
|
||||
if (matches > 1)
|
||||
elog(ERROR, "There is more than one procedure named %s.\n\tSupply the pg_proc oid inside single quotes.", pro_name_or_oid);
|
||||
else if (matches == 0)
|
||||
elog(ERROR, "No procedure with name %s", pro_name_or_oid);
|
||||
|
||||
PG_RETURN_OID(result);
|
||||
}
|
||||
|
||||
@@ -174,66 +151,22 @@ regprocout(PG_FUNCTION_ARGS)
|
||||
PG_RETURN_CSTRING(result);
|
||||
}
|
||||
|
||||
if (!IsBootstrapProcessingMode())
|
||||
proctup = SearchSysCache(PROCOID,
|
||||
ObjectIdGetDatum(proid),
|
||||
0, 0, 0);
|
||||
|
||||
if (HeapTupleIsValid(proctup))
|
||||
{
|
||||
proctup = SearchSysCache(PROCOID,
|
||||
ObjectIdGetDatum(proid),
|
||||
0, 0, 0);
|
||||
char *s;
|
||||
|
||||
if (HeapTupleIsValid(proctup))
|
||||
{
|
||||
char *s;
|
||||
|
||||
s = NameStr(((Form_pg_proc) GETSTRUCT(proctup))->proname);
|
||||
StrNCpy(result, s, NAMEDATALEN);
|
||||
ReleaseSysCache(proctup);
|
||||
}
|
||||
else
|
||||
{
|
||||
result[0] = '-';
|
||||
result[1] = '\0';
|
||||
}
|
||||
s = NameStr(((Form_pg_proc) GETSTRUCT(proctup))->proname);
|
||||
StrNCpy(result, s, NAMEDATALEN);
|
||||
ReleaseSysCache(proctup);
|
||||
}
|
||||
else
|
||||
{
|
||||
Relation proc;
|
||||
HeapScanDesc procscan;
|
||||
ScanKeyData key;
|
||||
|
||||
proc = heap_openr(ProcedureRelationName, AccessShareLock);
|
||||
ScanKeyEntryInitialize(&key,
|
||||
(bits16) 0,
|
||||
(AttrNumber) ObjectIdAttributeNumber,
|
||||
(RegProcedure) F_INT4EQ,
|
||||
ObjectIdGetDatum(proid));
|
||||
|
||||
procscan = heap_beginscan(proc, 0, SnapshotNow, 1, &key);
|
||||
if (!HeapScanIsValid(procscan))
|
||||
{
|
||||
heap_close(proc, AccessShareLock);
|
||||
elog(ERROR, "regprocout: could not begin scan of %s",
|
||||
ProcedureRelationName);
|
||||
}
|
||||
proctup = heap_getnext(procscan, 0);
|
||||
if (HeapTupleIsValid(proctup))
|
||||
{
|
||||
char *s;
|
||||
bool isnull;
|
||||
|
||||
s = (char *) heap_getattr(proctup, 1,
|
||||
RelationGetDescr(proc), &isnull);
|
||||
if (!isnull)
|
||||
StrNCpy(result, s, NAMEDATALEN);
|
||||
else
|
||||
elog(ERROR, "regprocout: null procedure %u", proid);
|
||||
}
|
||||
else
|
||||
{
|
||||
result[0] = '-';
|
||||
result[1] = '\0';
|
||||
}
|
||||
heap_endscan(procscan);
|
||||
heap_close(proc, AccessShareLock);
|
||||
result[0] = '-';
|
||||
result[1] = '\0';
|
||||
}
|
||||
|
||||
PG_RETURN_CSTRING(result);
|
||||
|
||||
17
src/backend/utils/cache/catcache.c
vendored
17
src/backend/utils/cache/catcache.c
vendored
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/cache/catcache.c,v 1.81 2001/06/22 19:16:23 wieck Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/cache/catcache.c,v 1.82 2001/08/21 16:36:04 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "access/hash.h"
|
||||
#include "access/heapam.h"
|
||||
#include "access/valid.h"
|
||||
#include "catalog/pg_opclass.h"
|
||||
#include "catalog/pg_operator.h"
|
||||
#include "catalog/pg_type.h"
|
||||
#include "catalog/catname.h"
|
||||
@@ -812,7 +813,7 @@ IndexScanOK(CatCache *cache, ScanKey cur_skey)
|
||||
sd = heap_beginscan(rel, false, SnapshotNow, 1, &key);
|
||||
ntp = heap_getnext(sd, 0);
|
||||
if (!HeapTupleIsValid(ntp))
|
||||
elog(ERROR, "SearchSelfReferences: %s not found in %s",
|
||||
elog(ERROR, "IndexScanOK: %s not found in %s",
|
||||
IndexRelidIndex, RelationRelationName);
|
||||
indexSelfOid = ntp->t_data->t_oid;
|
||||
heap_endscan(sd);
|
||||
@@ -823,6 +824,16 @@ IndexScanOK(CatCache *cache, ScanKey cur_skey)
|
||||
if (DatumGetObjectId(cur_skey[0].sk_argument) == indexSelfOid)
|
||||
return false;
|
||||
}
|
||||
else if (cache->id == AMOPSTRATEGY ||
|
||||
cache->id == AMPROCNUM)
|
||||
{
|
||||
/* Looking for an OID or INT2 btree operator or function? */
|
||||
Oid lookup_oid = DatumGetObjectId(cur_skey[0].sk_argument);
|
||||
|
||||
if (lookup_oid == OID_BTREE_OPS_OID ||
|
||||
lookup_oid == INT2_BTREE_OPS_OID)
|
||||
return false;
|
||||
}
|
||||
else if (cache->id == OPEROID)
|
||||
{
|
||||
/* Looking for an OID comparison function? */
|
||||
@@ -858,7 +869,7 @@ SearchCatCache(CatCache *cache,
|
||||
MemoryContext oldcxt;
|
||||
|
||||
/*
|
||||
* one-time startup overhead
|
||||
* one-time startup overhead for each cache
|
||||
*/
|
||||
if (cache->cc_tupdesc == NULL)
|
||||
CatalogCacheInitializeCache(cache);
|
||||
|
||||
72
src/backend/utils/cache/lsyscache.c
vendored
72
src/backend/utils/cache/lsyscache.c
vendored
@@ -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.56 2001/06/14 01:09:22 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.57 2001/08/21 16:36:05 tgl Exp $
|
||||
*
|
||||
* NOTES
|
||||
* Eventually, the index information should go through here, too.
|
||||
@@ -16,6 +16,8 @@
|
||||
#include "postgres.h"
|
||||
|
||||
#include "access/tupmacs.h"
|
||||
#include "catalog/pg_amop.h"
|
||||
#include "catalog/pg_opclass.h"
|
||||
#include "catalog/pg_operator.h"
|
||||
#include "catalog/pg_proc.h"
|
||||
#include "catalog/pg_shadow.h"
|
||||
@@ -30,19 +32,48 @@
|
||||
/* ---------- AMOP CACHES ---------- */
|
||||
|
||||
/*
|
||||
* op_class
|
||||
* op_in_opclass
|
||||
*
|
||||
* Return t iff operator 'opno' is in operator class 'opclass' for
|
||||
* access method 'amopid'.
|
||||
* Return t iff operator 'opno' is in operator class 'opclass'.
|
||||
*/
|
||||
bool
|
||||
op_class(Oid opno, Oid opclass, Oid amopid)
|
||||
op_in_opclass(Oid opno, Oid opclass)
|
||||
{
|
||||
return SearchSysCacheExists(AMOPOPID,
|
||||
ObjectIdGetDatum(opclass),
|
||||
ObjectIdGetDatum(opno),
|
||||
ObjectIdGetDatum(amopid),
|
||||
0);
|
||||
0, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* op_requires_recheck
|
||||
*
|
||||
* Return t if operator 'opno' requires a recheck when used as a
|
||||
* member of opclass 'opclass' (ie, this opclass is lossy for this
|
||||
* operator).
|
||||
*
|
||||
* Caller should already have verified that opno is a member of opclass,
|
||||
* therefore we raise an error if the tuple is not found.
|
||||
*/
|
||||
bool
|
||||
op_requires_recheck(Oid opno, Oid opclass)
|
||||
{
|
||||
HeapTuple tp;
|
||||
Form_pg_amop amop_tup;
|
||||
bool result;
|
||||
|
||||
tp = SearchSysCache(AMOPOPID,
|
||||
ObjectIdGetDatum(opclass),
|
||||
ObjectIdGetDatum(opno),
|
||||
0, 0);
|
||||
if (!HeapTupleIsValid(tp))
|
||||
elog(ERROR, "op_requires_recheck: op %u is not a member of opclass %u",
|
||||
opno, opclass);
|
||||
amop_tup = (Form_pg_amop) GETSTRUCT(tp);
|
||||
|
||||
result = amop_tup->amopreqcheck;
|
||||
ReleaseSysCache(tp);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* ---------- ATTRIBUTE CACHES ---------- */
|
||||
@@ -222,6 +253,33 @@ get_atttypetypmod(Oid relid, AttrNumber attnum,
|
||||
/* watch this space...
|
||||
*/
|
||||
|
||||
/* ---------- OPCLASS CACHE ---------- */
|
||||
|
||||
/*
|
||||
* opclass_is_btree
|
||||
*
|
||||
* Returns TRUE iff the specified opclass is associated with the
|
||||
* btree index access method.
|
||||
*/
|
||||
bool
|
||||
opclass_is_btree(Oid opclass)
|
||||
{
|
||||
HeapTuple tp;
|
||||
Form_pg_opclass cla_tup;
|
||||
bool result;
|
||||
|
||||
tp = SearchSysCache(CLAOID,
|
||||
ObjectIdGetDatum(opclass),
|
||||
0, 0, 0);
|
||||
if (!HeapTupleIsValid(tp))
|
||||
elog(ERROR, "cache lookup failed for opclass %u", opclass);
|
||||
cla_tup = (Form_pg_opclass) GETSTRUCT(tp);
|
||||
|
||||
result = (cla_tup->opcamid == BTREE_AM_OID);
|
||||
ReleaseSysCache(tp);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* ---------- OPERATOR CACHE ---------- */
|
||||
|
||||
/*
|
||||
|
||||
39
src/backend/utils/cache/syscache.c
vendored
39
src/backend/utils/cache/syscache.c
vendored
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/cache/syscache.c,v 1.64 2001/08/10 18:57:37 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/cache/syscache.c,v 1.65 2001/08/21 16:36:05 tgl Exp $
|
||||
*
|
||||
* NOTES
|
||||
* These routines allow the parser/planner/executor to perform
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "catalog/indexing.h"
|
||||
#include "catalog/pg_aggregate.h"
|
||||
#include "catalog/pg_amop.h"
|
||||
#include "catalog/pg_amproc.h"
|
||||
#include "catalog/pg_group.h"
|
||||
#include "catalog/pg_index.h"
|
||||
#include "catalog/pg_inherits.h"
|
||||
@@ -113,23 +114,33 @@ static struct cachedesc cacheinfo[] = {
|
||||
0
|
||||
}},
|
||||
{AccessMethodOperatorRelationName, /* AMOPOPID */
|
||||
AccessMethodOpidIndex,
|
||||
AccessMethodOperatorIndex,
|
||||
0,
|
||||
3,
|
||||
2,
|
||||
{
|
||||
Anum_pg_amop_amopclaid,
|
||||
Anum_pg_amop_amopopr,
|
||||
Anum_pg_amop_amopid,
|
||||
0,
|
||||
0
|
||||
}},
|
||||
{AccessMethodOperatorRelationName, /* AMOPSTRATEGY */
|
||||
AccessMethodStrategyIndex,
|
||||
0,
|
||||
3,
|
||||
2,
|
||||
{
|
||||
Anum_pg_amop_amopid,
|
||||
Anum_pg_amop_amopclaid,
|
||||
Anum_pg_amop_amopstrategy,
|
||||
0,
|
||||
0
|
||||
}},
|
||||
{AccessMethodProcedureRelationName, /* AMPROCNUM */
|
||||
AccessMethodProcedureIndex,
|
||||
0,
|
||||
2,
|
||||
{
|
||||
Anum_pg_amproc_amopclaid,
|
||||
Anum_pg_amproc_amprocnum,
|
||||
0,
|
||||
0
|
||||
}},
|
||||
{AttributeRelationName, /* ATTNAME */
|
||||
@@ -152,22 +163,22 @@ static struct cachedesc cacheinfo[] = {
|
||||
0,
|
||||
0
|
||||
}},
|
||||
{OperatorClassRelationName, /* CLADEFTYPE */
|
||||
OpclassDeftypeIndex,
|
||||
{OperatorClassRelationName, /* CLAAMNAME */
|
||||
OpclassAmNameIndex,
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
{
|
||||
Anum_pg_opclass_opcdeftype,
|
||||
0,
|
||||
Anum_pg_opclass_opcamid,
|
||||
Anum_pg_opclass_opcname,
|
||||
0,
|
||||
0
|
||||
}},
|
||||
{OperatorClassRelationName, /* CLANAME */
|
||||
OpclassNameIndex,
|
||||
{OperatorClassRelationName, /* CLAOID */
|
||||
OpclassOidIndex,
|
||||
0,
|
||||
1,
|
||||
{
|
||||
Anum_pg_opclass_opcname,
|
||||
ObjectIdAttributeNumber,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
|
||||
@@ -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.17 2001/06/02 19:01:52 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/sort/tuplesort.c,v 1.18 2001/08/21 16:36:05 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -2055,7 +2055,7 @@ SelectSortFunction(Oid sortOperator,
|
||||
{
|
||||
Relation relation;
|
||||
HeapScanDesc scan;
|
||||
ScanKeyData skey[3];
|
||||
ScanKeyData skey[1];
|
||||
HeapTuple tuple;
|
||||
Form_pg_operator optup;
|
||||
Oid opclass = InvalidOid;
|
||||
@@ -2068,25 +2068,20 @@ SelectSortFunction(Oid sortOperator,
|
||||
* If the operator is registered the same way in multiple opclasses,
|
||||
* assume we can use the associated comparator function from any one.
|
||||
*/
|
||||
relation = heap_openr(AccessMethodOperatorRelationName,
|
||||
AccessShareLock);
|
||||
|
||||
ScanKeyEntryInitialize(&skey[0], 0,
|
||||
Anum_pg_amop_amopid,
|
||||
F_OIDEQ,
|
||||
ObjectIdGetDatum(BTREE_AM_OID));
|
||||
|
||||
ScanKeyEntryInitialize(&skey[1], 0,
|
||||
ScanKeyEntryInitialize(&skey[0], 0x0,
|
||||
Anum_pg_amop_amopopr,
|
||||
F_OIDEQ,
|
||||
ObjectIdGetDatum(sortOperator));
|
||||
|
||||
scan = heap_beginscan(relation, false, SnapshotNow, 2, skey);
|
||||
relation = heap_openr(AccessMethodOperatorRelationName, AccessShareLock);
|
||||
scan = heap_beginscan(relation, false, SnapshotNow, 1, skey);
|
||||
|
||||
while (HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
|
||||
{
|
||||
Form_pg_amop aform = (Form_pg_amop) GETSTRUCT(tuple);
|
||||
|
||||
if (!opclass_is_btree(aform->amopclaid))
|
||||
continue;
|
||||
if (aform->amopstrategy == BTLessStrategyNumber)
|
||||
{
|
||||
opclass = aform->amopclaid;
|
||||
@@ -2107,39 +2102,18 @@ SelectSortFunction(Oid sortOperator,
|
||||
if (OidIsValid(opclass))
|
||||
{
|
||||
/* Found a suitable opclass, get its comparator support function */
|
||||
relation = heap_openr(AccessMethodProcedureRelationName,
|
||||
AccessShareLock);
|
||||
|
||||
ScanKeyEntryInitialize(&skey[0], 0,
|
||||
Anum_pg_amproc_amid,
|
||||
F_OIDEQ,
|
||||
ObjectIdGetDatum(BTREE_AM_OID));
|
||||
|
||||
ScanKeyEntryInitialize(&skey[1], 0,
|
||||
Anum_pg_amproc_amopclaid,
|
||||
F_OIDEQ,
|
||||
ObjectIdGetDatum(opclass));
|
||||
|
||||
ScanKeyEntryInitialize(&skey[2], 0,
|
||||
Anum_pg_amproc_amprocnum,
|
||||
F_INT2EQ,
|
||||
Int16GetDatum(BTORDER_PROC));
|
||||
|
||||
scan = heap_beginscan(relation, false, SnapshotNow, 3, skey);
|
||||
|
||||
*sortFunction = InvalidOid;
|
||||
|
||||
if (HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
|
||||
tuple = SearchSysCache(AMPROCNUM,
|
||||
ObjectIdGetDatum(opclass),
|
||||
Int16GetDatum(BTORDER_PROC),
|
||||
0, 0);
|
||||
if (HeapTupleIsValid(tuple))
|
||||
{
|
||||
Form_pg_amproc aform = (Form_pg_amproc) GETSTRUCT(tuple);
|
||||
*sortFunction = aform->amproc;
|
||||
}
|
||||
|
||||
heap_endscan(scan);
|
||||
heap_close(relation, AccessShareLock);
|
||||
|
||||
if (RegProcedureIsValid(*sortFunction))
|
||||
ReleaseSysCache(tuple);
|
||||
Assert(RegProcedureIsValid(*sortFunction));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2158,7 +2132,7 @@ SelectSortFunction(Oid sortOperator,
|
||||
*kind = SORTFUNC_REVLT;
|
||||
else
|
||||
*kind = SORTFUNC_LT;
|
||||
*sortFunction = optup->oprcode;
|
||||
*sortFunction = optup->oprcode;
|
||||
ReleaseSysCache(tuple);
|
||||
|
||||
Assert(RegProcedureIsValid(*sortFunction));
|
||||
|
||||
Reference in New Issue
Block a user