Thanks to visit codestin.com
Credit goes to github.com

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

Lines changed: 1 addition & 23 deletions
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

Lines changed: 114 additions & 95 deletions
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)