Skip to content

Commit 4926709

Browse files
committed
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...)
1 parent 7334831 commit 4926709

File tree

2 files changed

+115
-118
lines changed

2 files changed

+115
-118
lines changed

src/backend/catalog/index.c

+1-23
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.105 2000/02/18 09:28:41 inoue Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.106 2000/02/25 02:58:47 tgl Exp $
1212
*
1313
*
1414
* INTERFACE ROUTINES
@@ -1032,28 +1032,6 @@ index_create(char *heapRelationName,
10321032
* We create the disk file for this relation here
10331033
*/
10341034
heap_storage_create(indexRelation);
1035-
/* ----------------
1036-
* Now get the index procedure (only relevant for functional indices).
1037-
* ----------------
1038-
*/
1039-
1040-
if (PointerIsValid(funcInfo))
1041-
{
1042-
HeapTuple proc_tup;
1043-
1044-
proc_tup = SearchSysCacheTuple(PROCNAME,
1045-
PointerGetDatum(FIgetname(funcInfo)),
1046-
Int32GetDatum(FIgetnArgs(funcInfo)),
1047-
PointerGetDatum(FIgetArglist(funcInfo)),
1048-
0);
1049-
1050-
if (!HeapTupleIsValid(proc_tup))
1051-
{
1052-
func_error("index_create", FIgetname(funcInfo),
1053-
FIgetnArgs(funcInfo), FIgetArglist(funcInfo), NULL);
1054-
}
1055-
FIgetProcOid(funcInfo) = proc_tup->t_data->t_oid;
1056-
}
10571035

10581036
/* ----------------
10591037
* now update the object id's of all the attribute

src/backend/commands/indexcmds.c

+114-95
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.21 2000/02/18 09:29:37 inoue Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.22 2000/02/25 02:58:48 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -31,24 +31,26 @@
3131
#include "optimizer/planmain.h"
3232
#include "optimizer/prep.h"
3333
#include "parser/parsetree.h"
34+
#include "parser/parse_func.h"
3435
#include "utils/builtins.h"
3536
#include "utils/syscache.h"
3637
#include "miscadmin.h" /* ReindexDatabase() */
3738
#include "utils/portal.h" /* ReindexDatabase() */
3839
#include "catalog/catalog.h" /* ReindexDatabase() */
3940

40-
#define IsFuncIndex(ATTR_LIST) (((IndexElem*)lfirst(ATTR_LIST))->args!=NULL)
41+
#define IsFuncIndex(ATTR_LIST) (((IndexElem*)lfirst(ATTR_LIST))->args != NIL)
4142

4243
/* non-export function prototypes */
4344
static void CheckPredicate(List *predList, List *rangeTable, Oid baseRelOid);
44-
static void CheckPredExpr(Node *predicate, List *rangeTable,
45-
Oid baseRelOid);
46-
static void
47-
CheckPredClause(Expr *predicate, List *rangeTable, Oid baseRelOid);
48-
static void FuncIndexArgs(IndexElem *funcIndex, AttrNumber *attNumP,
49-
Oid *argTypes, Oid *opOidP, Oid relId);
45+
static void CheckPredExpr(Node *predicate, List *rangeTable, Oid baseRelOid);
46+
static void CheckPredClause(Expr *predicate, List *rangeTable, Oid baseRelOid);
47+
static void FuncIndexArgs(IndexElem *funcIndex, FuncIndexInfo *funcInfo,
48+
AttrNumber *attNumP, Oid *opOidP, Oid relId);
5049
static void NormIndexAttrs(List *attList, AttrNumber *attNumP,
51-
Oid *opOidP, Oid relId);
50+
Oid *opOidP, Oid relId);
51+
static void ProcessAttrTypename(IndexElem *attribute,
52+
Oid defType, int32 defTypmod);
53+
static Oid GetAttrOpClass(IndexElem *attribute, Oid attrType);
5254
static char *GetDefaultOpClass(Oid atttypid);
5355

5456
/*
@@ -169,40 +171,42 @@ DefineIndex(char *heapRelationName,
169171

170172
FIsetnArgs(&fInfo, nargs);
171173

172-
strcpy(FIgetname(&fInfo), funcIndex->name);
173-
174-
attributeNumberA = (AttrNumber *) palloc(nargs * sizeof attributeNumberA[0]);
174+
namestrcpy(&fInfo.funcName, funcIndex->name);
175175

176-
classObjectId = (Oid *) palloc(sizeof classObjectId[0]);
176+
attributeNumberA = (AttrNumber *) palloc(nargs *
177+
sizeof attributeNumberA[0]);
177178

179+
classObjectId = (Oid *) palloc(sizeof(Oid));
178180

179-
FuncIndexArgs(funcIndex, attributeNumberA,
180-
&(FIgetArg(&fInfo, 0)),
181+
FuncIndexArgs(funcIndex, &fInfo, attributeNumberA,
181182
classObjectId, relationId);
182183

183184
index_create(heapRelationName,
184185
indexRelationName,
185186
&fInfo, NULL, accessMethodId,
186187
numberOfAttributes, attributeNumberA,
187-
classObjectId, parameterCount, parameterA, (Node *) cnfPred,
188+
classObjectId, parameterCount, parameterA,
189+
(Node *) cnfPred,
188190
lossy, unique, primary);
189191
}
190192
else
191193
{
192194
attributeNumberA = (AttrNumber *) palloc(numberOfAttributes *
193-
sizeof attributeNumberA[0]);
195+
sizeof attributeNumberA[0]);
194196

195-
classObjectId = (Oid *) palloc(numberOfAttributes * sizeof classObjectId[0]);
197+
classObjectId = (Oid *) palloc(numberOfAttributes * sizeof(Oid));
196198

197199
NormIndexAttrs(attributeList, attributeNumberA,
198200
classObjectId, relationId);
199201

200202
index_create(heapRelationName, indexRelationName, NULL,
201203
attributeList,
202204
accessMethodId, numberOfAttributes, attributeNumberA,
203-
classObjectId, parameterCount, parameterA, (Node *) cnfPred,
205+
classObjectId, parameterCount, parameterA,
206+
(Node *) cnfPred,
204207
lossy, unique, primary);
205208
}
209+
206210
setRelhasindexInplace(relationId, true, false);
207211
}
208212

@@ -320,7 +324,6 @@ ExtendIndex(char *indexRelationName, Expr *predicate, List *rangetable)
320324
if (indproc != InvalidOid)
321325
{
322326
funcInfo = &fInfo;
323-
/* FIgetnArgs(funcInfo) = numberOfAttributes; */
324327
FIsetnArgs(funcInfo, numberOfAttributes);
325328

326329
tuple = SearchSysCacheTuple(PROCOID,
@@ -407,51 +410,62 @@ CheckPredClause(Expr *predicate, List *rangeTable, Oid baseRelOid)
407410

408411
static void
409412
FuncIndexArgs(IndexElem *funcIndex,
413+
FuncIndexInfo *funcInfo,
410414
AttrNumber *attNumP,
411-
Oid *argTypes,
412415
Oid *opOidP,
413416
Oid relId)
414417
{
415418
List *rest;
416419
HeapTuple tuple;
417-
Form_pg_attribute att;
418-
419-
tuple = SearchSysCacheTuple(CLANAME,
420-
PointerGetDatum(funcIndex->class),
421-
0, 0, 0);
422-
423-
if (!HeapTupleIsValid(tuple))
424-
{
425-
elog(ERROR, "DefineIndex: %s class not found",
426-
funcIndex->class);
427-
}
428-
*opOidP = tuple->t_data->t_oid;
429-
430-
MemSet(argTypes, 0, FUNC_MAX_ARGS * sizeof(Oid));
420+
Oid retType;
421+
int argn = 0;
431422

432423
/*
433-
* process the function arguments
424+
* process the function arguments, which are a list of T_String
425+
* (someday ought to allow more general expressions?)
434426
*/
435-
for (rest = funcIndex->args; rest != NIL; rest = lnext(rest))
436-
{
437-
char *arg;
427+
MemSet(funcInfo->arglist, 0, FUNC_MAX_ARGS * sizeof(Oid));
438428

439-
arg = strVal(lfirst(rest));
429+
foreach(rest, funcIndex->args)
430+
{
431+
char *arg = strVal(lfirst(rest));
432+
Form_pg_attribute att;
440433

441434
tuple = SearchSysCacheTuple(ATTNAME,
442435
ObjectIdGetDatum(relId),
443436
PointerGetDatum(arg), 0, 0);
444437

445438
if (!HeapTupleIsValid(tuple))
446-
{
447-
elog(ERROR,
448-
"DefineIndex: attribute \"%s\" not found",
449-
arg);
450-
}
439+
elog(ERROR, "DefineIndex: attribute \"%s\" not found", arg);
451440
att = (Form_pg_attribute) GETSTRUCT(tuple);
452441
*attNumP++ = att->attnum;
453-
*argTypes++ = att->atttypid;
442+
funcInfo->arglist[argn++] = att->atttypid;
443+
}
444+
445+
/* ----------------
446+
* Lookup the function procedure to get its OID and result type.
447+
* ----------------
448+
*/
449+
tuple = SearchSysCacheTuple(PROCNAME,
450+
PointerGetDatum(FIgetname(funcInfo)),
451+
Int32GetDatum(FIgetnArgs(funcInfo)),
452+
PointerGetDatum(FIgetArglist(funcInfo)),
453+
0);
454+
455+
if (!HeapTupleIsValid(tuple))
456+
{
457+
func_error("DefineIndex", FIgetname(funcInfo),
458+
FIgetnArgs(funcInfo), FIgetArglist(funcInfo), NULL);
454459
}
460+
461+
FIsetProcOid(funcInfo, tuple->t_data->t_oid);
462+
retType = ((Form_pg_proc) GETSTRUCT(tuple))->prorettype;
463+
464+
/* Process type and opclass, using func return type as default */
465+
466+
ProcessAttrTypename(funcIndex, retType, -1);
467+
468+
*opOidP = GetAttrOpClass(funcIndex, retType);
455469
}
456470

457471
static void
@@ -461,80 +475,85 @@ NormIndexAttrs(List *attList, /* list of IndexElem's */
461475
Oid relId)
462476
{
463477
List *rest;
464-
HeapTuple atttuple,
465-
tuple;
466478

467479
/*
468480
* process attributeList
469481
*/
470-
471-
for (rest = attList; rest != NIL; rest = lnext(rest))
482+
foreach(rest, attList)
472483
{
473-
IndexElem *attribute;
484+
IndexElem *attribute = lfirst(rest);
485+
HeapTuple atttuple;
474486
Form_pg_attribute attform;
475487

476-
attribute = lfirst(rest);
477-
478488
if (attribute->name == NULL)
479489
elog(ERROR, "missing attribute for define index");
480490

481491
atttuple = SearchSysCacheTupleCopy(ATTNAME,
482492
ObjectIdGetDatum(relId),
483-
PointerGetDatum(attribute->name),
493+
PointerGetDatum(attribute->name),
484494
0, 0);
485495
if (!HeapTupleIsValid(atttuple))
486-
{
487-
elog(ERROR,
488-
"DefineIndex: attribute \"%s\" not found",
496+
elog(ERROR, "DefineIndex: attribute \"%s\" not found",
489497
attribute->name);
490-
}
491-
492498
attform = (Form_pg_attribute) GETSTRUCT(atttuple);
499+
493500
*attNumP++ = attform->attnum;
494501

495-
/* we want the type so we can set the proper alignment, etc. */
496-
if (attribute->typename == NULL)
497-
{
498-
tuple = SearchSysCacheTuple(TYPEOID,
499-
ObjectIdGetDatum(attform->atttypid),
500-
0, 0, 0);
501-
if (!HeapTupleIsValid(tuple))
502-
elog(ERROR, "create index: type for attribute '%s' undefined",
503-
attribute->name);
504-
/* we just set the type name because that is all we need */
505-
attribute->typename = makeNode(TypeName);
506-
attribute->typename->name = nameout(&((Form_pg_type) GETSTRUCT(tuple))->typname);
507-
508-
/* we all need the typmod for the char and varchar types. */
509-
attribute->typename->typmod = attform->atttypmod;
510-
}
502+
ProcessAttrTypename(attribute, attform->atttypid, attform->atttypmod);
511503

512-
if (attribute->class == NULL)
513-
{
514-
/* no operator class specified, so find the default */
515-
attribute->class = GetDefaultOpClass(attform->atttypid);
516-
if (attribute->class == NULL)
517-
{
518-
elog(ERROR,
519-
"Can't find a default operator class for type %u.",
520-
attform->atttypid);
521-
}
522-
}
504+
*classOidP++ = GetAttrOpClass(attribute, attform->atttypid);
523505

524-
tuple = SearchSysCacheTuple(CLANAME,
525-
PointerGetDatum(attribute->class),
526-
0, 0, 0);
506+
heap_freetuple(atttuple);
507+
}
508+
}
527509

510+
static void
511+
ProcessAttrTypename(IndexElem *attribute,
512+
Oid defType, int32 defTypmod)
513+
{
514+
HeapTuple tuple;
515+
516+
/* build a type node so we can set the proper alignment, etc. */
517+
if (attribute->typename == NULL)
518+
{
519+
tuple = SearchSysCacheTuple(TYPEOID,
520+
ObjectIdGetDatum(defType),
521+
0, 0, 0);
528522
if (!HeapTupleIsValid(tuple))
529-
{
530-
elog(ERROR, "DefineIndex: %s class not found",
531-
attribute->class);
532-
}
533-
*classOidP++ = tuple->t_data->t_oid;
534-
heap_freetuple(atttuple);
523+
elog(ERROR, "DefineIndex: type for attribute '%s' undefined",
524+
attribute->name);
525+
526+
attribute->typename = makeNode(TypeName);
527+
attribute->typename->name = nameout(&((Form_pg_type) GETSTRUCT(tuple))->typname);
528+
attribute->typename->typmod = defTypmod;
535529
}
536530
}
537531

532+
static Oid
533+
GetAttrOpClass(IndexElem *attribute, Oid attrType)
534+
{
535+
HeapTuple tuple;
536+
537+
if (attribute->class == NULL)
538+
{
539+
/* no operator class specified, so find the default */
540+
attribute->class = GetDefaultOpClass(attrType);
541+
if (attribute->class == NULL)
542+
elog(ERROR, "Can't find a default operator class for type %u",
543+
attrType);
544+
}
545+
546+
tuple = SearchSysCacheTuple(CLANAME,
547+
PointerGetDatum(attribute->class),
548+
0, 0, 0);
549+
550+
if (!HeapTupleIsValid(tuple))
551+
elog(ERROR, "DefineIndex: %s opclass not found",
552+
attribute->class);
553+
554+
return tuple->t_data->t_oid;
555+
}
556+
538557
static char *
539558
GetDefaultOpClass(Oid atttypid)
540559
{

0 commit comments

Comments
 (0)