mirror of
https://github.com/postgres/postgres.git
synced 2025-11-16 15:02:33 +03:00
Opclasses live in namespaces. I also took the opportunity to create
an 'opclass owner' column in pg_opclass. Nothing is done with it at present, but since there are plans to invent a CREATE OPERATOR CLASS command soon, we'll probably want DROP OPERATOR CLASS too, which suggests that a notion of ownership would be a good idea.
This commit is contained in:
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/access/index/indexam.c,v 1.56 2002/03/26 19:15:14 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/access/index/indexam.c,v 1.57 2002/04/17 20:57:56 tgl Exp $
|
||||
*
|
||||
* INTERFACE ROUTINES
|
||||
* index_open - open an index relation by relation OID
|
||||
@@ -498,10 +498,23 @@ index_getprocinfo(Relation irel,
|
||||
if (locinfo->fn_oid == InvalidOid)
|
||||
{
|
||||
RegProcedure *loc = irel->rd_support;
|
||||
RegProcedure procId;
|
||||
|
||||
Assert(loc != NULL);
|
||||
|
||||
fmgr_info_cxt(loc[procindex], locinfo, irel->rd_indexcxt);
|
||||
procId = loc[procindex];
|
||||
|
||||
/*
|
||||
* Complain if function was not found during IndexSupportInitialize.
|
||||
* This should not happen unless the system tables contain bogus
|
||||
* entries for the index opclass. (If an AM wants to allow a
|
||||
* support function to be optional, it can use index_getprocid.)
|
||||
*/
|
||||
if (!RegProcedureIsValid(procId))
|
||||
elog(ERROR, "Missing support function %d for attribute %d of index %s",
|
||||
procnum, attnum, RelationGetRelationName(irel));
|
||||
|
||||
fmgr_info_cxt(procId, locinfo, irel->rd_indexcxt);
|
||||
}
|
||||
|
||||
return locinfo;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/bootstrap/bootparse.y,v 1.44 2002/04/09 20:35:46 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/bootstrap/bootparse.y,v 1.45 2002/04/17 20:57:56 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -273,7 +273,7 @@ boot_index_param:
|
||||
IndexElem *n = makeNode(IndexElem);
|
||||
n->name = LexIDStr($1);
|
||||
n->funcname = n->args = NIL; /* no func indexes */
|
||||
n->class = LexIDStr($2);
|
||||
n->opclass = makeList1(makeString(LexIDStr($2)));
|
||||
$$ = n;
|
||||
}
|
||||
;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/catalog/indexing.c,v 1.89 2002/04/16 23:08:10 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/catalog/indexing.c,v 1.90 2002/04/17 20:57:56 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -60,7 +60,7 @@ char *Name_pg_largeobject_indices[Num_pg_largeobject_indices] =
|
||||
char *Name_pg_namespace_indices[Num_pg_namespace_indices] =
|
||||
{NamespaceNameIndex, NamespaceOidIndex};
|
||||
char *Name_pg_opclass_indices[Num_pg_opclass_indices] =
|
||||
{OpclassAmNameIndex, OpclassOidIndex};
|
||||
{OpclassAmNameNspIndex, OpclassOidIndex};
|
||||
char *Name_pg_operator_indices[Num_pg_operator_indices] =
|
||||
{OperatorOidIndex, OperatorNameNspIndex};
|
||||
char *Name_pg_proc_indices[Num_pg_proc_indices] =
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/catalog/namespace.c,v 1.10 2002/04/16 23:08:10 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/catalog/namespace.c,v 1.11 2002/04/17 20:57:56 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "catalog/namespace.h"
|
||||
#include "catalog/pg_inherits.h"
|
||||
#include "catalog/pg_namespace.h"
|
||||
#include "catalog/pg_opclass.h"
|
||||
#include "catalog/pg_operator.h"
|
||||
#include "catalog/pg_proc.h"
|
||||
#include "catalog/pg_shadow.h"
|
||||
@@ -311,6 +312,54 @@ TypenameGetTypid(const char *typname)
|
||||
return InvalidOid;
|
||||
}
|
||||
|
||||
/*
|
||||
* OpclassnameGetOpcid
|
||||
* Try to resolve an unqualified index opclass name.
|
||||
* Returns OID if opclass found in search path, else InvalidOid.
|
||||
*
|
||||
* This is essentially the same as TypenameGetTypid, but we have to have
|
||||
* an extra argument for the index AM OID.
|
||||
*/
|
||||
Oid
|
||||
OpclassnameGetOpcid(Oid amid, const char *opcname)
|
||||
{
|
||||
Oid opcid;
|
||||
List *lptr;
|
||||
|
||||
/*
|
||||
* If system namespace is not in path, implicitly search it before path
|
||||
*/
|
||||
if (!pathContainsSystemNamespace)
|
||||
{
|
||||
opcid = GetSysCacheOid(CLAAMNAMENSP,
|
||||
ObjectIdGetDatum(amid),
|
||||
PointerGetDatum(opcname),
|
||||
ObjectIdGetDatum(PG_CATALOG_NAMESPACE),
|
||||
0);
|
||||
if (OidIsValid(opcid))
|
||||
return opcid;
|
||||
}
|
||||
|
||||
/*
|
||||
* Else search the path
|
||||
*/
|
||||
foreach(lptr, namespaceSearchPath)
|
||||
{
|
||||
Oid namespaceId = (Oid) lfirsti(lptr);
|
||||
|
||||
opcid = GetSysCacheOid(CLAAMNAMENSP,
|
||||
ObjectIdGetDatum(amid),
|
||||
PointerGetDatum(opcname),
|
||||
ObjectIdGetDatum(namespaceId),
|
||||
0);
|
||||
if (OidIsValid(opcid))
|
||||
return opcid;
|
||||
}
|
||||
|
||||
/* Not found in path */
|
||||
return InvalidOid;
|
||||
}
|
||||
|
||||
/*
|
||||
* FuncnameGetCandidates
|
||||
* Given a possibly-qualified function name and argument count,
|
||||
@@ -652,6 +701,123 @@ OpernameGetCandidates(List *names, char oprkind)
|
||||
return resultList;
|
||||
}
|
||||
|
||||
/*
|
||||
* OpclassGetCandidates
|
||||
* Given an index access method OID, retrieve a list of all the
|
||||
* opclasses for that AM that are visible in the search path.
|
||||
*
|
||||
* NOTE: the opcname_tmp field in the returned structs should not be used
|
||||
* by callers, because it points at syscache entries that we release at
|
||||
* the end of this routine. If any callers needed the name information,
|
||||
* we could pstrdup() the names ... but at present it'd be wasteful.
|
||||
*/
|
||||
OpclassCandidateList
|
||||
OpclassGetCandidates(Oid amid)
|
||||
{
|
||||
OpclassCandidateList resultList = NULL;
|
||||
CatCList *catlist;
|
||||
int i;
|
||||
|
||||
/* Search syscache by AM OID only */
|
||||
catlist = SearchSysCacheList(CLAAMNAMENSP, 1,
|
||||
ObjectIdGetDatum(amid),
|
||||
0, 0, 0);
|
||||
|
||||
for (i = 0; i < catlist->n_members; i++)
|
||||
{
|
||||
HeapTuple opctup = &catlist->members[i]->tuple;
|
||||
Form_pg_opclass opcform = (Form_pg_opclass) GETSTRUCT(opctup);
|
||||
int pathpos = 0;
|
||||
OpclassCandidateList newResult;
|
||||
|
||||
/* Consider only opclasses that are in the search path */
|
||||
if (pathContainsSystemNamespace ||
|
||||
!IsSystemNamespace(opcform->opcnamespace))
|
||||
{
|
||||
List *nsp;
|
||||
|
||||
foreach(nsp, namespaceSearchPath)
|
||||
{
|
||||
pathpos++;
|
||||
if (opcform->opcnamespace == (Oid) lfirsti(nsp))
|
||||
break;
|
||||
}
|
||||
if (nsp == NIL)
|
||||
continue; /* opclass is not in search path */
|
||||
}
|
||||
|
||||
/*
|
||||
* Okay, it's in the search path, but does it have the same name
|
||||
* as something we already accepted? If so, keep
|
||||
* only the one that appears earlier in the search path.
|
||||
*
|
||||
* If we have an ordered list from SearchSysCacheList (the
|
||||
* normal case), then any conflicting opclass must immediately
|
||||
* adjoin this one in the list, so we only need to look at
|
||||
* the newest result item. If we have an unordered list,
|
||||
* we have to scan the whole result list.
|
||||
*/
|
||||
if (resultList)
|
||||
{
|
||||
OpclassCandidateList prevResult;
|
||||
|
||||
if (catlist->ordered)
|
||||
{
|
||||
if (strcmp(NameStr(opcform->opcname),
|
||||
resultList->opcname_tmp) == 0)
|
||||
prevResult = resultList;
|
||||
else
|
||||
prevResult = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (prevResult = resultList;
|
||||
prevResult;
|
||||
prevResult = prevResult->next)
|
||||
{
|
||||
if (strcmp(NameStr(opcform->opcname),
|
||||
prevResult->opcname_tmp) == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (prevResult)
|
||||
{
|
||||
/* We have a match with a previous result */
|
||||
Assert(pathpos != prevResult->pathpos);
|
||||
if (pathpos > prevResult->pathpos)
|
||||
continue; /* keep previous result */
|
||||
/* replace previous result */
|
||||
prevResult->opcname_tmp = NameStr(opcform->opcname);
|
||||
prevResult->pathpos = pathpos;
|
||||
prevResult->oid = opctup->t_data->t_oid;
|
||||
prevResult->opcintype = opcform->opcintype;
|
||||
prevResult->opcdefault = opcform->opcdefault;
|
||||
prevResult->opckeytype = opcform->opckeytype;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Okay to add it to result list
|
||||
*/
|
||||
newResult = (OpclassCandidateList)
|
||||
palloc(sizeof(struct _OpclassCandidateList));
|
||||
newResult->opcname_tmp = NameStr(opcform->opcname);
|
||||
newResult->pathpos = pathpos;
|
||||
newResult->oid = opctup->t_data->t_oid;
|
||||
newResult->opcintype = opcform->opcintype;
|
||||
newResult->opcdefault = opcform->opcdefault;
|
||||
newResult->opckeytype = opcform->opckeytype;
|
||||
newResult->next = resultList;
|
||||
resultList = newResult;
|
||||
}
|
||||
|
||||
ReleaseSysCacheList(catlist);
|
||||
|
||||
return resultList;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* QualifiedNameGetCreationNamespace
|
||||
* Given a possibly-qualified name for an object (in List-of-Values
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.70 2002/04/12 20:38:22 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.71 2002/04/17 20:57:56 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -31,7 +31,6 @@
|
||||
#include "parser/parse_coerce.h"
|
||||
#include "parser/parse_func.h"
|
||||
#include "utils/builtins.h"
|
||||
#include "utils/fmgroids.h"
|
||||
#include "utils/lsyscache.h"
|
||||
#include "utils/syscache.h"
|
||||
|
||||
@@ -390,11 +389,14 @@ static Oid
|
||||
GetAttrOpClass(IndexElem *attribute, Oid attrType,
|
||||
char *accessMethodName, Oid accessMethodId)
|
||||
{
|
||||
char *catalogname;
|
||||
char *schemaname = NULL;
|
||||
char *opcname = NULL;
|
||||
HeapTuple tuple;
|
||||
Oid opClassId,
|
||||
opInputType;
|
||||
|
||||
if (attribute->class == NULL)
|
||||
if (attribute->opclass == NIL)
|
||||
{
|
||||
/* no operator class specified, so find the default */
|
||||
opClassId = GetDefaultOpClass(attrType, accessMethodId);
|
||||
@@ -407,23 +409,79 @@ GetAttrOpClass(IndexElem *attribute, Oid attrType,
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the index operator class and verify that it accepts this
|
||||
* datatype. Note we will accept binary compatibility.
|
||||
* Specific opclass name given, so look up the opclass.
|
||||
*/
|
||||
tuple = SearchSysCache(CLAAMNAME,
|
||||
ObjectIdGetDatum(accessMethodId),
|
||||
PointerGetDatum(attribute->class),
|
||||
0, 0);
|
||||
|
||||
/* deconstruct the name list */
|
||||
switch (length(attribute->opclass))
|
||||
{
|
||||
case 1:
|
||||
opcname = strVal(lfirst(attribute->opclass));
|
||||
break;
|
||||
case 2:
|
||||
schemaname = strVal(lfirst(attribute->opclass));
|
||||
opcname = strVal(lsecond(attribute->opclass));
|
||||
break;
|
||||
case 3:
|
||||
catalogname = strVal(lfirst(attribute->opclass));
|
||||
schemaname = strVal(lsecond(attribute->opclass));
|
||||
opcname = strVal(lfirst(lnext(lnext(attribute->opclass))));
|
||||
/*
|
||||
* We check the catalog name and then ignore it.
|
||||
*/
|
||||
if (strcmp(catalogname, DatabaseName) != 0)
|
||||
elog(ERROR, "Cross-database references are not implemented");
|
||||
break;
|
||||
default:
|
||||
elog(ERROR, "Improper opclass name (too many dotted names)");
|
||||
break;
|
||||
}
|
||||
|
||||
if (schemaname)
|
||||
{
|
||||
/* Look in specific schema only */
|
||||
Oid namespaceId;
|
||||
|
||||
namespaceId = GetSysCacheOid(NAMESPACENAME,
|
||||
CStringGetDatum(schemaname),
|
||||
0, 0, 0);
|
||||
if (!OidIsValid(namespaceId))
|
||||
elog(ERROR, "Namespace \"%s\" does not exist",
|
||||
schemaname);
|
||||
tuple = SearchSysCache(CLAAMNAMENSP,
|
||||
ObjectIdGetDatum(accessMethodId),
|
||||
PointerGetDatum(opcname),
|
||||
ObjectIdGetDatum(namespaceId),
|
||||
0);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Unqualified opclass name, so search the search path */
|
||||
opClassId = OpclassnameGetOpcid(accessMethodId, opcname);
|
||||
if (!OidIsValid(opClassId))
|
||||
elog(ERROR, "DefineIndex: operator class \"%s\" not supported by access method \"%s\"",
|
||||
opcname, accessMethodName);
|
||||
tuple = SearchSysCache(CLAOID,
|
||||
ObjectIdGetDatum(opClassId),
|
||||
0, 0, 0);
|
||||
}
|
||||
|
||||
if (!HeapTupleIsValid(tuple))
|
||||
elog(ERROR, "DefineIndex: operator class \"%s\" not supported by access method \"%s\"",
|
||||
attribute->class, accessMethodName);
|
||||
NameListToString(attribute->opclass), accessMethodName);
|
||||
|
||||
/*
|
||||
* Verify that the index operator class accepts this
|
||||
* datatype. Note we will accept binary compatibility.
|
||||
*/
|
||||
opClassId = tuple->t_data->t_oid;
|
||||
opInputType = ((Form_pg_opclass) GETSTRUCT(tuple))->opcintype;
|
||||
ReleaseSysCache(tuple);
|
||||
|
||||
if (!IsBinaryCompatible(attrType, opInputType))
|
||||
elog(ERROR, "operator class \"%s\" does not accept data type %s",
|
||||
attribute->class, format_type_be(attrType));
|
||||
NameListToString(attribute->opclass), format_type_be(attrType));
|
||||
|
||||
ReleaseSysCache(tuple);
|
||||
|
||||
return opClassId;
|
||||
}
|
||||
@@ -431,10 +489,7 @@ GetAttrOpClass(IndexElem *attribute, Oid attrType,
|
||||
static Oid
|
||||
GetDefaultOpClass(Oid attrType, Oid accessMethodId)
|
||||
{
|
||||
Relation relation;
|
||||
ScanKeyData entry[1];
|
||||
HeapScanDesc scan;
|
||||
HeapTuple tuple;
|
||||
OpclassCandidateList opclass;
|
||||
int nexact = 0;
|
||||
int ncompatible = 0;
|
||||
Oid exactOid = InvalidOid;
|
||||
@@ -449,44 +504,32 @@ GetDefaultOpClass(Oid attrType, Oid accessMethodId)
|
||||
* require the user to specify which one he wants. If we find more
|
||||
* than one exact match, then someone put bogus entries in pg_opclass.
|
||||
*
|
||||
* We could use an indexscan here, but since pg_opclass is small and a
|
||||
* scan on opcamid won't be very selective, the indexscan would
|
||||
* probably actually be slower than heapscan.
|
||||
* The initial search is done by namespace.c so that we only consider
|
||||
* opclasses visible in the current namespace search path.
|
||||
*/
|
||||
ScanKeyEntryInitialize(&entry[0], 0x0,
|
||||
Anum_pg_opclass_opcamid,
|
||||
F_OIDEQ,
|
||||
ObjectIdGetDatum(accessMethodId));
|
||||
|
||||
relation = heap_openr(OperatorClassRelationName, AccessShareLock);
|
||||
scan = heap_beginscan(relation, false, SnapshotNow, 1, entry);
|
||||
|
||||
while (HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
|
||||
for (opclass = OpclassGetCandidates(accessMethodId);
|
||||
opclass != NULL;
|
||||
opclass = opclass->next)
|
||||
{
|
||||
Form_pg_opclass opclass = (Form_pg_opclass) GETSTRUCT(tuple);
|
||||
|
||||
if (opclass->opcdefault)
|
||||
{
|
||||
if (opclass->opcintype == attrType)
|
||||
{
|
||||
nexact++;
|
||||
exactOid = tuple->t_data->t_oid;
|
||||
exactOid = opclass->oid;
|
||||
}
|
||||
else if (IsBinaryCompatible(opclass->opcintype, attrType))
|
||||
{
|
||||
ncompatible++;
|
||||
compatibleOid = tuple->t_data->t_oid;
|
||||
compatibleOid = opclass->oid;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
heap_endscan(scan);
|
||||
heap_close(relation, AccessShareLock);
|
||||
|
||||
if (nexact == 1)
|
||||
return exactOid;
|
||||
if (nexact != 0)
|
||||
elog(ERROR, "pg_opclass contains multiple default opclasses for data tyype %s",
|
||||
elog(ERROR, "pg_opclass contains multiple default opclasses for data type %s",
|
||||
format_type_be(attrType));
|
||||
if (ncompatible == 1)
|
||||
return compatibleOid;
|
||||
|
||||
@@ -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.178 2002/04/16 23:08:10 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.179 2002/04/17 20:57:56 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -1714,8 +1714,7 @@ _copyIndexElem(IndexElem *from)
|
||||
newnode->name = pstrdup(from->name);
|
||||
Node_Copy(from, newnode, funcname);
|
||||
Node_Copy(from, newnode, args);
|
||||
if (from->class)
|
||||
newnode->class = pstrdup(from->class);
|
||||
Node_Copy(from, newnode, opclass);
|
||||
|
||||
return newnode;
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.126 2002/04/16 23:08:10 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.127 2002/04/17 20:57:56 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -1599,7 +1599,7 @@ _equalIndexElem(IndexElem *a, IndexElem *b)
|
||||
return false;
|
||||
if (!equal(a->args, b->args))
|
||||
return false;
|
||||
if (!equalstr(a->class, b->class))
|
||||
if (!equal(a->opclass, b->opclass))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.155 2002/04/16 23:08:10 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.156 2002/04/17 20:57:56 tgl Exp $
|
||||
*
|
||||
* NOTES
|
||||
* Every (plan) node in POSTGRES has an associated "out" routine which
|
||||
@@ -217,8 +217,8 @@ _outIndexElem(StringInfo str, IndexElem *node)
|
||||
_outNode(str, node->funcname);
|
||||
appendStringInfo(str, " :args ");
|
||||
_outNode(str, node->args);
|
||||
appendStringInfo(str, " :class ");
|
||||
_outToken(str, node->class);
|
||||
appendStringInfo(str, " :opclass ");
|
||||
_outNode(str, node->opclass);
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.230 2002/04/16 23:08:11 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.231 2002/04/17 20:57:56 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -1209,7 +1209,7 @@ transformIndexConstraints(ParseState *pstate, CreateStmtContext *cxt)
|
||||
iparam->name = pstrdup(key->name);
|
||||
iparam->funcname = NIL;
|
||||
iparam->args = NIL;
|
||||
iparam->class = NULL;
|
||||
iparam->opclass = NIL;
|
||||
index->indexParams = lappend(index->indexParams, iparam);
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.302 2002/04/16 23:08:11 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.303 2002/04/17 20:57:56 tgl Exp $
|
||||
*
|
||||
* HISTORY
|
||||
* AUTHOR DATE MAJOR EVENT
|
||||
@@ -174,15 +174,15 @@ static bool set_name_needs_quotes(const char *name);
|
||||
|
||||
%type <str> relation_name, copy_file_name, copy_delimiter, copy_null,
|
||||
database_name, access_method_clause, access_method, attr_name,
|
||||
class, index_name, name, function_name, file_name
|
||||
index_name, name, function_name, file_name
|
||||
|
||||
%type <list> func_name, handler_name, qual_Op, qual_all_Op, OptUseOp
|
||||
%type <list> func_name, handler_name, qual_Op, qual_all_Op, OptUseOp,
|
||||
opt_class
|
||||
|
||||
%type <range> qualified_name, OptConstrFromTable
|
||||
|
||||
%type <str> opt_id,
|
||||
all_Op, MathOp, opt_name,
|
||||
opt_class, SpecialRuleRelation
|
||||
all_Op, MathOp, opt_name, SpecialRuleRelation
|
||||
|
||||
%type <str> opt_level, opt_encoding
|
||||
%type <node> grantee
|
||||
@@ -2614,7 +2614,7 @@ func_index: func_name '(' name_list ')' opt_class
|
||||
$$->name = NULL;
|
||||
$$->funcname = $1;
|
||||
$$->args = $3;
|
||||
$$->class = $5;
|
||||
$$->opclass = $5;
|
||||
}
|
||||
;
|
||||
|
||||
@@ -2624,11 +2624,11 @@ index_elem: attr_name opt_class
|
||||
$$->name = $1;
|
||||
$$->funcname = NIL;
|
||||
$$->args = NIL;
|
||||
$$->class = $2;
|
||||
$$->opclass = $2;
|
||||
}
|
||||
;
|
||||
|
||||
opt_class: class
|
||||
opt_class: any_name
|
||||
{
|
||||
/*
|
||||
* Release 7.0 removed network_ops, timespan_ops, and
|
||||
@@ -2643,17 +2643,24 @@ opt_class: class
|
||||
* so suppress that too for awhile. I'm starting to
|
||||
* think we need a better approach. tgl 2000/10/01
|
||||
*/
|
||||
if (strcmp($1, "network_ops") != 0 &&
|
||||
strcmp($1, "timespan_ops") != 0 &&
|
||||
strcmp($1, "datetime_ops") != 0 &&
|
||||
strcmp($1, "lztext_ops") != 0 &&
|
||||
strcmp($1, "timestamp_ops") != 0)
|
||||
$$ = $1;
|
||||
if (length($1) == 1)
|
||||
{
|
||||
char *claname = strVal(lfirst($1));
|
||||
|
||||
if (strcmp(claname, "network_ops") != 0 &&
|
||||
strcmp(claname, "timespan_ops") != 0 &&
|
||||
strcmp(claname, "datetime_ops") != 0 &&
|
||||
strcmp(claname, "lztext_ops") != 0 &&
|
||||
strcmp(claname, "timestamp_ops") != 0)
|
||||
$$ = $1;
|
||||
else
|
||||
$$ = NIL;
|
||||
}
|
||||
else
|
||||
$$ = NULL;
|
||||
$$ = $1;
|
||||
}
|
||||
| USING class { $$ = $2; }
|
||||
| /*EMPTY*/ { $$ = NULL; }
|
||||
| USING any_name { $$ = $2; }
|
||||
| /*EMPTY*/ { $$ = NIL; }
|
||||
;
|
||||
|
||||
/*****************************************************************************
|
||||
@@ -5782,7 +5789,6 @@ name: ColId { $$ = $1; };
|
||||
database_name: ColId { $$ = $1; };
|
||||
access_method: ColId { $$ = $1; };
|
||||
attr_name: ColId { $$ = $1; };
|
||||
class: ColId { $$ = $1; };
|
||||
index_name: ColId { $$ = $1; };
|
||||
file_name: Sconst { $$ = $1; };
|
||||
|
||||
|
||||
10
src/backend/utils/cache/syscache.c
vendored
10
src/backend/utils/cache/syscache.c
vendored
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/cache/syscache.c,v 1.77 2002/04/16 23:08:11 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/cache/syscache.c,v 1.78 2002/04/17 20:57:56 tgl Exp $
|
||||
*
|
||||
* NOTES
|
||||
* These routines allow the parser/planner/executor to perform
|
||||
@@ -173,14 +173,14 @@ static const struct cachedesc cacheinfo[] = {
|
||||
0,
|
||||
0
|
||||
}},
|
||||
{OperatorClassRelationName, /* CLAAMNAME */
|
||||
OpclassAmNameIndex,
|
||||
{OperatorClassRelationName, /* CLAAMNAMENSP */
|
||||
OpclassAmNameNspIndex,
|
||||
0,
|
||||
2,
|
||||
3,
|
||||
{
|
||||
Anum_pg_opclass_opcamid,
|
||||
Anum_pg_opclass_opcname,
|
||||
0,
|
||||
Anum_pg_opclass_opcnamespace,
|
||||
0
|
||||
}},
|
||||
{OperatorClassRelationName, /* CLAOID */
|
||||
|
||||
Reference in New Issue
Block a user