Commit 49267095 authored by Tom Lane's avatar Tom Lane

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...)
parent 73348316
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 * INTERFACE ROUTINES
...@@ -1032,28 +1032,6 @@ index_create(char *heapRelationName, ...@@ -1032,28 +1032,6 @@ index_create(char *heapRelationName,
* We create the disk file for this relation here * We create the disk file for this relation here
*/ */
heap_storage_create(indexRelation); 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 * now update the object id's of all the attribute
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 @@ ...@@ -31,24 +31,26 @@
#include "optimizer/planmain.h" #include "optimizer/planmain.h"
#include "optimizer/prep.h" #include "optimizer/prep.h"
#include "parser/parsetree.h" #include "parser/parsetree.h"
#include "parser/parse_func.h"
#include "utils/builtins.h" #include "utils/builtins.h"
#include "utils/syscache.h" #include "utils/syscache.h"
#include "miscadmin.h" /* ReindexDatabase() */ #include "miscadmin.h" /* ReindexDatabase() */
#include "utils/portal.h" /* ReindexDatabase() */ #include "utils/portal.h" /* ReindexDatabase() */
#include "catalog/catalog.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 */ /* non-export function prototypes */
static void CheckPredicate(List *predList, List *rangeTable, Oid baseRelOid); static void CheckPredicate(List *predList, List *rangeTable, Oid baseRelOid);
static void CheckPredExpr(Node *predicate, List *rangeTable, static void CheckPredExpr(Node *predicate, List *rangeTable, Oid baseRelOid);
Oid baseRelOid); static void CheckPredClause(Expr *predicate, List *rangeTable, Oid baseRelOid);
static void static void FuncIndexArgs(IndexElem *funcIndex, FuncIndexInfo *funcInfo,
CheckPredClause(Expr *predicate, List *rangeTable, Oid baseRelOid); AttrNumber *attNumP, Oid *opOidP, Oid relId);
static void FuncIndexArgs(IndexElem *funcIndex, AttrNumber *attNumP,
Oid *argTypes, Oid *opOidP, Oid relId);
static void NormIndexAttrs(List *attList, AttrNumber *attNumP, 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); static char *GetDefaultOpClass(Oid atttypid);
/* /*
...@@ -169,30 +171,30 @@ DefineIndex(char *heapRelationName, ...@@ -169,30 +171,30 @@ DefineIndex(char *heapRelationName,
FIsetnArgs(&fInfo, nargs); FIsetnArgs(&fInfo, nargs);
strcpy(FIgetname(&fInfo), funcIndex->name); namestrcpy(&fInfo.funcName, funcIndex->name);
attributeNumberA = (AttrNumber *) palloc(nargs * sizeof attributeNumberA[0]);
classObjectId = (Oid *) palloc(sizeof classObjectId[0]); attributeNumberA = (AttrNumber *) palloc(nargs *
sizeof attributeNumberA[0]);
classObjectId = (Oid *) palloc(sizeof(Oid));
FuncIndexArgs(funcIndex, attributeNumberA, FuncIndexArgs(funcIndex, &fInfo, attributeNumberA,
&(FIgetArg(&fInfo, 0)),
classObjectId, relationId); classObjectId, relationId);
index_create(heapRelationName, index_create(heapRelationName,
indexRelationName, indexRelationName,
&fInfo, NULL, accessMethodId, &fInfo, NULL, accessMethodId,
numberOfAttributes, attributeNumberA, numberOfAttributes, attributeNumberA,
classObjectId, parameterCount, parameterA, (Node *) cnfPred, classObjectId, parameterCount, parameterA,
(Node *) cnfPred,
lossy, unique, primary); lossy, unique, primary);
} }
else else
{ {
attributeNumberA = (AttrNumber *) palloc(numberOfAttributes * 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, NormIndexAttrs(attributeList, attributeNumberA,
classObjectId, relationId); classObjectId, relationId);
...@@ -200,9 +202,11 @@ DefineIndex(char *heapRelationName, ...@@ -200,9 +202,11 @@ DefineIndex(char *heapRelationName,
index_create(heapRelationName, indexRelationName, NULL, index_create(heapRelationName, indexRelationName, NULL,
attributeList, attributeList,
accessMethodId, numberOfAttributes, attributeNumberA, accessMethodId, numberOfAttributes, attributeNumberA,
classObjectId, parameterCount, parameterA, (Node *) cnfPred, classObjectId, parameterCount, parameterA,
(Node *) cnfPred,
lossy, unique, primary); lossy, unique, primary);
} }
setRelhasindexInplace(relationId, true, false); setRelhasindexInplace(relationId, true, false);
} }
...@@ -320,7 +324,6 @@ ExtendIndex(char *indexRelationName, Expr *predicate, List *rangetable) ...@@ -320,7 +324,6 @@ ExtendIndex(char *indexRelationName, Expr *predicate, List *rangetable)
if (indproc != InvalidOid) if (indproc != InvalidOid)
{ {
funcInfo = &fInfo; funcInfo = &fInfo;
/* FIgetnArgs(funcInfo) = numberOfAttributes; */
FIsetnArgs(funcInfo, numberOfAttributes); FIsetnArgs(funcInfo, numberOfAttributes);
tuple = SearchSysCacheTuple(PROCOID, tuple = SearchSysCacheTuple(PROCOID,
...@@ -407,51 +410,62 @@ CheckPredClause(Expr *predicate, List *rangeTable, Oid baseRelOid) ...@@ -407,51 +410,62 @@ CheckPredClause(Expr *predicate, List *rangeTable, Oid baseRelOid)
static void static void
FuncIndexArgs(IndexElem *funcIndex, FuncIndexArgs(IndexElem *funcIndex,
FuncIndexInfo *funcInfo,
AttrNumber *attNumP, AttrNumber *attNumP,
Oid *argTypes,
Oid *opOidP, Oid *opOidP,
Oid relId) Oid relId)
{ {
List *rest; List *rest;
HeapTuple tuple; HeapTuple tuple;
Form_pg_attribute att; Oid retType;
int argn = 0;
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));
/* /*
* 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)) MemSet(funcInfo->arglist, 0, FUNC_MAX_ARGS * sizeof(Oid));
{
char *arg;
arg = strVal(lfirst(rest)); foreach(rest, funcIndex->args)
{
char *arg = strVal(lfirst(rest));
Form_pg_attribute att;
tuple = SearchSysCacheTuple(ATTNAME, tuple = SearchSysCacheTuple(ATTNAME,
ObjectIdGetDatum(relId), ObjectIdGetDatum(relId),
PointerGetDatum(arg), 0, 0); PointerGetDatum(arg), 0, 0);
if (!HeapTupleIsValid(tuple)) 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); att = (Form_pg_attribute) GETSTRUCT(tuple);
*attNumP++ = att->attnum; *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 static void
...@@ -461,80 +475,85 @@ NormIndexAttrs(List *attList, /* list of IndexElem's */ ...@@ -461,80 +475,85 @@ NormIndexAttrs(List *attList, /* list of IndexElem's */
Oid relId) Oid relId)
{ {
List *rest; List *rest;
HeapTuple atttuple,
tuple;
/* /*
* process attributeList * process attributeList
*/ */
foreach(rest, attList)
for (rest = attList; rest != NIL; rest = lnext(rest))
{ {
IndexElem *attribute; IndexElem *attribute = lfirst(rest);
HeapTuple atttuple;
Form_pg_attribute attform; Form_pg_attribute attform;
attribute = lfirst(rest);
if (attribute->name == NULL) if (attribute->name == NULL)
elog(ERROR, "missing attribute for define index"); elog(ERROR, "missing attribute for define index");
atttuple = SearchSysCacheTupleCopy(ATTNAME, atttuple = SearchSysCacheTupleCopy(ATTNAME,
ObjectIdGetDatum(relId), ObjectIdGetDatum(relId),
PointerGetDatum(attribute->name), PointerGetDatum(attribute->name),
0, 0); 0, 0);
if (!HeapTupleIsValid(atttuple)) if (!HeapTupleIsValid(atttuple))
{ elog(ERROR, "DefineIndex: attribute \"%s\" not found",
elog(ERROR,
"DefineIndex: attribute \"%s\" not found",
attribute->name); attribute->name);
}
attform = (Form_pg_attribute) GETSTRUCT(atttuple); attform = (Form_pg_attribute) GETSTRUCT(atttuple);
*attNumP++ = attform->attnum; *attNumP++ = attform->attnum;
/* we want the type so we can set the proper alignment, etc. */ ProcessAttrTypename(attribute, attform->atttypid, attform->atttypmod);
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;
}
if (attribute->class == NULL) *classOidP++ = GetAttrOpClass(attribute, attform->atttypid);
{
/* 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);
}
}
tuple = SearchSysCacheTuple(CLANAME, heap_freetuple(atttuple);
PointerGetDatum(attribute->class), }
0, 0, 0); }
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)) if (!HeapTupleIsValid(tuple))
{ elog(ERROR, "DefineIndex: type for attribute '%s' undefined",
elog(ERROR, "DefineIndex: %s class not found", attribute->name);
attribute->class);
} attribute->typename = makeNode(TypeName);
*classOidP++ = tuple->t_data->t_oid; attribute->typename->name = nameout(&((Form_pg_type) GETSTRUCT(tuple))->typname);
heap_freetuple(atttuple); 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 * static char *
GetDefaultOpClass(Oid atttypid) GetDefaultOpClass(Oid atttypid)
{ {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment