From 49267095638a982b7d1fc0924dfb058cf9cc7bdc Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Fri, 25 Feb 2000 02:58:48 +0000 Subject: [PATCH] Fix longstanding bug that kept functional indexes from working when you defaulted the opclass. This addresses TODO item * Allow creation of functional indexes to use default types (Does that make it a feature? Oh dear...) --- src/backend/catalog/index.c | 24 +--- src/backend/commands/indexcmds.c | 209 +++++++++++++++++-------------- 2 files changed, 115 insertions(+), 118 deletions(-) diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index b7d49ed3bc..5bfc332f0d 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.105 2000/02/18 09:28:41 inoue Exp $ + * $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.106 2000/02/25 02:58:47 tgl Exp $ * * * INTERFACE ROUTINES @@ -1032,28 +1032,6 @@ index_create(char *heapRelationName, * We create the disk file for this relation here */ heap_storage_create(indexRelation); - /* ---------------- - * Now get the index procedure (only relevant for functional indices). - * ---------------- - */ - - if (PointerIsValid(funcInfo)) - { - HeapTuple proc_tup; - - proc_tup = SearchSysCacheTuple(PROCNAME, - PointerGetDatum(FIgetname(funcInfo)), - Int32GetDatum(FIgetnArgs(funcInfo)), - PointerGetDatum(FIgetArglist(funcInfo)), - 0); - - if (!HeapTupleIsValid(proc_tup)) - { - func_error("index_create", FIgetname(funcInfo), - FIgetnArgs(funcInfo), FIgetArglist(funcInfo), NULL); - } - FIgetProcOid(funcInfo) = proc_tup->t_data->t_oid; - } /* ---------------- * now update the object id's of all the attribute diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c index cbd7b26ae8..93ad0eb63b 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.21 2000/02/18 09:29:37 inoue Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.22 2000/02/25 02:58:48 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -31,24 +31,26 @@ #include "optimizer/planmain.h" #include "optimizer/prep.h" #include "parser/parsetree.h" +#include "parser/parse_func.h" #include "utils/builtins.h" #include "utils/syscache.h" #include "miscadmin.h" /* ReindexDatabase() */ #include "utils/portal.h" /* ReindexDatabase() */ #include "catalog/catalog.h" /* ReindexDatabase() */ -#define IsFuncIndex(ATTR_LIST) (((IndexElem*)lfirst(ATTR_LIST))->args!=NULL) +#define IsFuncIndex(ATTR_LIST) (((IndexElem*)lfirst(ATTR_LIST))->args != NIL) /* non-export function prototypes */ static void CheckPredicate(List *predList, List *rangeTable, Oid baseRelOid); -static void CheckPredExpr(Node *predicate, List *rangeTable, - Oid baseRelOid); -static void - CheckPredClause(Expr *predicate, List *rangeTable, Oid baseRelOid); -static void FuncIndexArgs(IndexElem *funcIndex, AttrNumber *attNumP, - Oid *argTypes, Oid *opOidP, Oid relId); +static void CheckPredExpr(Node *predicate, List *rangeTable, Oid baseRelOid); +static void CheckPredClause(Expr *predicate, List *rangeTable, Oid baseRelOid); +static void FuncIndexArgs(IndexElem *funcIndex, FuncIndexInfo *funcInfo, + AttrNumber *attNumP, Oid *opOidP, Oid relId); static void NormIndexAttrs(List *attList, AttrNumber *attNumP, - Oid *opOidP, Oid relId); + Oid *opOidP, Oid relId); +static void ProcessAttrTypename(IndexElem *attribute, + Oid defType, int32 defTypmod); +static Oid GetAttrOpClass(IndexElem *attribute, Oid attrType); static char *GetDefaultOpClass(Oid atttypid); /* @@ -169,30 +171,30 @@ DefineIndex(char *heapRelationName, FIsetnArgs(&fInfo, nargs); - strcpy(FIgetname(&fInfo), funcIndex->name); - - attributeNumberA = (AttrNumber *) palloc(nargs * sizeof attributeNumberA[0]); + namestrcpy(&fInfo.funcName, funcIndex->name); - classObjectId = (Oid *) palloc(sizeof classObjectId[0]); + attributeNumberA = (AttrNumber *) palloc(nargs * + sizeof attributeNumberA[0]); + classObjectId = (Oid *) palloc(sizeof(Oid)); - FuncIndexArgs(funcIndex, attributeNumberA, - &(FIgetArg(&fInfo, 0)), + FuncIndexArgs(funcIndex, &fInfo, attributeNumberA, classObjectId, relationId); index_create(heapRelationName, indexRelationName, &fInfo, NULL, accessMethodId, numberOfAttributes, attributeNumberA, - classObjectId, parameterCount, parameterA, (Node *) cnfPred, + classObjectId, parameterCount, parameterA, + (Node *) cnfPred, lossy, unique, primary); } else { attributeNumberA = (AttrNumber *) palloc(numberOfAttributes * - sizeof attributeNumberA[0]); + sizeof attributeNumberA[0]); - classObjectId = (Oid *) palloc(numberOfAttributes * sizeof classObjectId[0]); + classObjectId = (Oid *) palloc(numberOfAttributes * sizeof(Oid)); NormIndexAttrs(attributeList, attributeNumberA, classObjectId, relationId); @@ -200,9 +202,11 @@ DefineIndex(char *heapRelationName, index_create(heapRelationName, indexRelationName, NULL, attributeList, accessMethodId, numberOfAttributes, attributeNumberA, - classObjectId, parameterCount, parameterA, (Node *) cnfPred, + classObjectId, parameterCount, parameterA, + (Node *) cnfPred, lossy, unique, primary); } + setRelhasindexInplace(relationId, true, false); } @@ -320,7 +324,6 @@ ExtendIndex(char *indexRelationName, Expr *predicate, List *rangetable) if (indproc != InvalidOid) { funcInfo = &fInfo; -/* FIgetnArgs(funcInfo) = numberOfAttributes; */ FIsetnArgs(funcInfo, numberOfAttributes); tuple = SearchSysCacheTuple(PROCOID, @@ -407,51 +410,62 @@ CheckPredClause(Expr *predicate, List *rangeTable, Oid baseRelOid) static void FuncIndexArgs(IndexElem *funcIndex, + FuncIndexInfo *funcInfo, AttrNumber *attNumP, - Oid *argTypes, Oid *opOidP, Oid relId) { List *rest; HeapTuple tuple; - Form_pg_attribute att; - - tuple = SearchSysCacheTuple(CLANAME, - PointerGetDatum(funcIndex->class), - 0, 0, 0); - - if (!HeapTupleIsValid(tuple)) - { - elog(ERROR, "DefineIndex: %s class not found", - funcIndex->class); - } - *opOidP = tuple->t_data->t_oid; - - MemSet(argTypes, 0, FUNC_MAX_ARGS * sizeof(Oid)); + Oid retType; + int argn = 0; /* - * process the function arguments + * process the function arguments, which are a list of T_String + * (someday ought to allow more general expressions?) */ - for (rest = funcIndex->args; rest != NIL; rest = lnext(rest)) - { - char *arg; + MemSet(funcInfo->arglist, 0, FUNC_MAX_ARGS * sizeof(Oid)); - arg = strVal(lfirst(rest)); + foreach(rest, funcIndex->args) + { + char *arg = strVal(lfirst(rest)); + Form_pg_attribute att; tuple = SearchSysCacheTuple(ATTNAME, ObjectIdGetDatum(relId), PointerGetDatum(arg), 0, 0); if (!HeapTupleIsValid(tuple)) - { - elog(ERROR, - "DefineIndex: attribute \"%s\" not found", - arg); - } + elog(ERROR, "DefineIndex: attribute \"%s\" not found", arg); att = (Form_pg_attribute) GETSTRUCT(tuple); *attNumP++ = att->attnum; - *argTypes++ = att->atttypid; + funcInfo->arglist[argn++] = att->atttypid; + } + + /* ---------------- + * Lookup the function procedure to get its OID and result type. + * ---------------- + */ + tuple = SearchSysCacheTuple(PROCNAME, + PointerGetDatum(FIgetname(funcInfo)), + Int32GetDatum(FIgetnArgs(funcInfo)), + PointerGetDatum(FIgetArglist(funcInfo)), + 0); + + if (!HeapTupleIsValid(tuple)) + { + func_error("DefineIndex", FIgetname(funcInfo), + FIgetnArgs(funcInfo), FIgetArglist(funcInfo), NULL); } + + FIsetProcOid(funcInfo, tuple->t_data->t_oid); + retType = ((Form_pg_proc) GETSTRUCT(tuple))->prorettype; + + /* Process type and opclass, using func return type as default */ + + ProcessAttrTypename(funcIndex, retType, -1); + + *opOidP = GetAttrOpClass(funcIndex, retType); } static void @@ -461,80 +475,85 @@ NormIndexAttrs(List *attList, /* list of IndexElem's */ Oid relId) { List *rest; - HeapTuple atttuple, - tuple; /* * process attributeList */ - - for (rest = attList; rest != NIL; rest = lnext(rest)) + foreach(rest, attList) { - IndexElem *attribute; + IndexElem *attribute = lfirst(rest); + HeapTuple atttuple; Form_pg_attribute attform; - attribute = lfirst(rest); - if (attribute->name == NULL) elog(ERROR, "missing attribute for define index"); atttuple = SearchSysCacheTupleCopy(ATTNAME, ObjectIdGetDatum(relId), - PointerGetDatum(attribute->name), + PointerGetDatum(attribute->name), 0, 0); if (!HeapTupleIsValid(atttuple)) - { - elog(ERROR, - "DefineIndex: attribute \"%s\" not found", + elog(ERROR, "DefineIndex: attribute \"%s\" not found", attribute->name); - } - attform = (Form_pg_attribute) GETSTRUCT(atttuple); + *attNumP++ = attform->attnum; - /* we want the type so we can set the proper alignment, etc. */ - if (attribute->typename == NULL) - { - tuple = SearchSysCacheTuple(TYPEOID, - ObjectIdGetDatum(attform->atttypid), - 0, 0, 0); - if (!HeapTupleIsValid(tuple)) - elog(ERROR, "create index: type for attribute '%s' undefined", - attribute->name); - /* we just set the type name because that is all we need */ - attribute->typename = makeNode(TypeName); - attribute->typename->name = nameout(&((Form_pg_type) GETSTRUCT(tuple))->typname); - - /* we all need the typmod for the char and varchar types. */ - attribute->typename->typmod = attform->atttypmod; - } + ProcessAttrTypename(attribute, attform->atttypid, attform->atttypmod); - if (attribute->class == NULL) - { - /* no operator class specified, so find the default */ - attribute->class = GetDefaultOpClass(attform->atttypid); - if (attribute->class == NULL) - { - elog(ERROR, - "Can't find a default operator class for type %u.", - attform->atttypid); - } - } + *classOidP++ = GetAttrOpClass(attribute, attform->atttypid); - tuple = SearchSysCacheTuple(CLANAME, - PointerGetDatum(attribute->class), - 0, 0, 0); + heap_freetuple(atttuple); + } +} +static void +ProcessAttrTypename(IndexElem *attribute, + Oid defType, int32 defTypmod) +{ + HeapTuple tuple; + + /* build a type node so we can set the proper alignment, etc. */ + if (attribute->typename == NULL) + { + tuple = SearchSysCacheTuple(TYPEOID, + ObjectIdGetDatum(defType), + 0, 0, 0); if (!HeapTupleIsValid(tuple)) - { - elog(ERROR, "DefineIndex: %s class not found", - attribute->class); - } - *classOidP++ = tuple->t_data->t_oid; - heap_freetuple(atttuple); + elog(ERROR, "DefineIndex: type for attribute '%s' undefined", + attribute->name); + + attribute->typename = makeNode(TypeName); + attribute->typename->name = nameout(&((Form_pg_type) GETSTRUCT(tuple))->typname); + attribute->typename->typmod = defTypmod; } } +static Oid +GetAttrOpClass(IndexElem *attribute, Oid attrType) +{ + HeapTuple tuple; + + if (attribute->class == NULL) + { + /* no operator class specified, so find the default */ + attribute->class = GetDefaultOpClass(attrType); + if (attribute->class == NULL) + elog(ERROR, "Can't find a default operator class for type %u", + attrType); + } + + tuple = SearchSysCacheTuple(CLANAME, + PointerGetDatum(attribute->class), + 0, 0, 0); + + if (!HeapTupleIsValid(tuple)) + elog(ERROR, "DefineIndex: %s opclass not found", + attribute->class); + + return tuple->t_data->t_oid; +} + static char * GetDefaultOpClass(Oid atttypid) { -- 2.40.0