1 /*-------------------------------------------------------------------------
4 * miscellanious executor utility routines
6 * Copyright (c) 1994, Regents of the University of California
10 * $Header: /cvsroot/pgsql/src/backend/executor/execUtils.c,v 1.28 1998/02/10 04:00:52 momjian Exp $
12 *-------------------------------------------------------------------------
16 * ExecAssignNodeBaseInfo \
17 * ExecAssignDebugHooks > preforms misc work done in all the
18 * ExecAssignExprContext / init node routines.
20 * ExecGetTypeInfo | old execCStructs interface
21 * ExecMakeTypeInfo | code from the version 1
22 * ExecOrderTypeInfo | lisp system. These should
23 * ExecSetTypeInfo | go away or be updated soon.
24 * ExecFreeTypeInfo | -cim 11/1/89
25 * ExecTupleAttributes /
28 * QueryDescGetTypeInfo - moved here from main.c
29 * am not sure what uses it -cim 10/12/89
31 * ExecGetIndexKeyInfo \
32 * ExecOpenIndices | referenced by InitPlan, EndPlan,
33 * ExecCloseIndices | ExecAppend, ExecReplace
34 * ExecFormIndexTuple |
35 * ExecInsertIndexTuple /
38 * This file has traditionally been the place to stick misc.
39 * executor support stuff that doesn't really go anyplace else.
46 #include "executor/executor.h"
47 #include "executor/execdebug.h"
48 #include "access/itup.h"
49 #include "access/heapam.h"
50 #include "access/genam.h"
51 #include "optimizer/clauses.h"
52 #include "utils/palloc.h"
53 #include "utils/mcxt.h"
54 #include "utils/lsyscache.h"
55 #include "commands/command.h"
56 #include "catalog/index.h"
57 #include "catalog/catname.h"
58 #include "catalog/pg_proc.h"
59 #include "catalog/pg_type.h"
60 #include "parser/parsetree.h"
63 ExecGetIndexKeyInfo(IndexTupleForm indexTuple, int *numAttsOutP,
64 AttrNumber **attsOutP, FuncIndexInfoPtr fInfoP);
66 /* ----------------------------------------------------------------
67 * global counters for number of tuples processed, retrieved,
68 * appended, replaced, deleted.
69 * ----------------------------------------------------------------
76 int NIndexTupleInserted;
77 extern int NIndexTupleProcessed; /* have to be defined in the
78 * access method level so that the
79 * cinterface.a will link ok. */
81 /* ----------------------------------------------------------------
83 * ----------------------------------------------------------------
86 /* ----------------------------------------------------------------
88 * ----------------------------------------------------------------
99 NIndexTupleProcessed = 0;
104 /* ----------------------------------------------------------------
106 * ----------------------------------------------------------------
110 DisplayTupleCount(FILE *statfp)
112 if (NTupleProcessed > 0)
113 fprintf(statfp, "!\t%d tuple%s processed, ", NTupleProcessed,
114 (NTupleProcessed == 1) ? "" : "s");
117 fprintf(statfp, "!\tno tuples processed.\n");
120 if (NIndexTupleProcessed > 0)
121 fprintf(statfp, "%d indextuple%s processed, ", NIndexTupleProcessed,
122 (NIndexTupleProcessed == 1) ? "" : "s");
123 if (NIndexTupleInserted > 0)
124 fprintf(statfp, "%d indextuple%s inserted, ", NIndexTupleInserted,
125 (NIndexTupleInserted == 1) ? "" : "s");
126 if (NTupleRetrieved > 0)
127 fprintf(statfp, "%d tuple%s retrieved. ", NTupleRetrieved,
128 (NTupleRetrieved == 1) ? "" : "s");
129 if (NTupleAppended > 0)
130 fprintf(statfp, "%d tuple%s appended. ", NTupleAppended,
131 (NTupleAppended == 1) ? "" : "s");
132 if (NTupleDeleted > 0)
133 fprintf(statfp, "%d tuple%s deleted. ", NTupleDeleted,
134 (NTupleDeleted == 1) ? "" : "s");
135 if (NTupleReplaced > 0)
136 fprintf(statfp, "%d tuple%s replaced. ", NTupleReplaced,
137 (NTupleReplaced == 1) ? "" : "s");
138 fprintf(statfp, "\n");
143 /* ----------------------------------------------------------------
144 * miscellanious init node support functions
146 * ExecAssignNodeBaseInfo - assigns the baseid field of the node
147 * ExecAssignDebugHooks - assigns the node's debugging hooks
148 * ExecAssignExprContext - assigns the node's expression context
149 * ----------------------------------------------------------------
153 * ExecAssignNodeBaseInfo
155 * as it says, this assigns the baseid field of the node and
156 * increments the counter in the estate. In addition, it initializes
157 * the base_parent field of the basenode.
161 ExecAssignNodeBaseInfo(EState *estate, CommonState *cstate, Plan *parent)
165 baseId = estate->es_BaseId;
166 cstate->cs_base_id = baseId;
167 estate->es_BaseId = baseId + 1;
171 * ExecAssignExprContext
173 * This initializes the ExprContext field. It is only necessary
174 * to do this for nodes which use ExecQual or ExecTargetList
175 * because those routines depend on econtext. Other nodes which
176 * dont have to evaluate expressions don't need to do this.
180 ExecAssignExprContext(EState *estate, CommonState *commonstate)
182 ExprContext *econtext;
183 ParamListInfo paraminfo;
186 paraminfo = estate->es_param_list_info;
187 rangeTable = estate->es_range_table;
189 econtext = makeNode(ExprContext);
190 econtext->ecxt_scantuple = NULL; /* scan tuple slot */
191 econtext->ecxt_innertuple = NULL; /* inner tuple slot */
192 econtext->ecxt_outertuple = NULL; /* outer tuple slot */
193 econtext->ecxt_relation = NULL; /* relation */
194 econtext->ecxt_relid = 0; /* relid */
195 econtext->ecxt_param_list_info = paraminfo; /* param list info */
196 econtext->ecxt_range_table = rangeTable; /* range table */
198 commonstate->cs_ExprContext = econtext;
201 /* ----------------------------------------------------------------
202 * Result slot tuple type and ProjectionInfo support
203 * ----------------------------------------------------------------
207 * ExecAssignResultType
211 ExecAssignResultType(CommonState *commonstate,
214 TupleTableSlot *slot;
216 slot = commonstate->cs_ResultTupleSlot;
217 slot->ttc_tupleDescriptor = tupDesc;
221 * ExecAssignResultTypeFromOuterPlan
225 ExecAssignResultTypeFromOuterPlan(Plan *node, CommonState *commonstate)
230 outerPlan = outerPlan(node);
231 tupDesc = ExecGetTupType(outerPlan);
233 ExecAssignResultType(commonstate, tupDesc);
237 * ExecAssignResultTypeFromTL
241 ExecAssignResultTypeFromTL(Plan *node, CommonState *commonstate)
249 TupleDesc origTupDesc;
251 targetList = node->targetlist;
252 origTupDesc = ExecTypeFromTL(targetList);
253 len = ExecTargetListLength(targetList);
258 while (tl != NIL || fjtl != NIL)
271 if (!tl_is_resdom(tle))
273 Fjoin *fj = (Fjoin *) lfirst(tle);
277 tle = fj->fj_innerNode;
284 ExecAssignResultType(commonstate,
288 ExecAssignResultType(commonstate,
297 ExecGetResultType(CommonState *commonstate)
299 TupleTableSlot *slot = commonstate->cs_ResultTupleSlot;
301 return slot->ttc_tupleDescriptor;
310 ExecFreeResultType(CommonState *commonstate)
312 TupleTableSlot *slot;
315 slot = commonstate->cs_ResultTupleSlot;
316 tupType = slot->ttc_tupleDescriptor;
318 /* ExecFreeTypeInfo(tupType); */
325 * ExecAssignProjectionInfo
326 forms the projection information from the node's targetlist
330 ExecAssignProjectionInfo(Plan *node, CommonState *commonstate)
332 ProjectionInfo *projInfo;
336 targetList = node->targetlist;
337 len = ExecTargetListLength(targetList);
339 projInfo = makeNode(ProjectionInfo);
340 projInfo->pi_targetlist = targetList;
341 projInfo->pi_len = len;
342 projInfo->pi_tupValue =
343 (len <= 0) ? NULL : (Datum *) palloc(sizeof(Datum) * len);
344 projInfo->pi_exprContext = commonstate->cs_ExprContext;
345 projInfo->pi_slot = commonstate->cs_ResultTupleSlot;
347 commonstate->cs_ProjInfo = projInfo;
352 * ExecFreeProjectionInfo
356 ExecFreeProjectionInfo(CommonState *commonstate)
358 ProjectionInfo *projInfo;
361 * get projection info. if NULL then this node has
362 * none so we just return.
365 projInfo = commonstate->cs_ProjInfo;
366 if (projInfo == NULL)
370 * clean up memory used.
373 if (projInfo->pi_tupValue != NULL)
374 pfree(projInfo->pi_tupValue);
377 commonstate->cs_ProjInfo = NULL;
380 /* ----------------------------------------------------------------
381 * the following scan type support functions are for
382 * those nodes which are stubborn and return tuples in
383 * their Scan tuple slot instead of their Result tuple
384 * slot.. luck fur us, these nodes do not do projections
385 * so we don't have to worry about getting the ProjectionInfo
386 * right for them... -cim 6/3/91
387 * ----------------------------------------------------------------
395 ExecGetScanType(CommonScanState *csstate)
397 TupleTableSlot *slot = csstate->css_ScanTupleSlot;
399 return slot->ttc_tupleDescriptor;
408 ExecFreeScanType(CommonScanState *csstate)
410 TupleTableSlot *slot;
413 slot = csstate->css_ScanTupleSlot;
414 tupType = slot->ttc_tupleDescriptor;
416 /* ExecFreeTypeInfo(tupType); */
427 ExecAssignScanType(CommonScanState *csstate,
430 TupleTableSlot *slot;
432 slot = (TupleTableSlot *) csstate->css_ScanTupleSlot;
433 slot->ttc_tupleDescriptor = tupDesc;
437 * ExecAssignScanTypeFromOuterPlan
441 ExecAssignScanTypeFromOuterPlan(Plan *node, CommonScanState *csstate)
446 outerPlan = outerPlan(node);
447 tupDesc = ExecGetTupType(outerPlan);
449 ExecAssignScanType(csstate, tupDesc);
453 /* ----------------------------------------------------------------
454 * ExecTypeFromTL support routines.
456 * these routines are used mainly from ExecTypeFromTL.
460 * Routines dealing with the structure 'attribute' which conatains
461 * the type information about attributes in a tuple:
463 * ExecMakeTypeInfo(noType) --
464 * returns pointer to array of 'noType' structure 'attribute'.
465 * ExecSetTypeInfo(index, typeInfo, attNum, attLen) --
466 * sets the element indexed by 'index' in typeInfo with
467 * the values: attNum, attLen.
468 * ExecFreeTypeInfo(typeInfo) --
469 * frees the structure 'typeInfo'.
470 * ----------------------------------------------------------------
476 * This initializes fields of a single attribute in a
477 * tuple descriptor from the specified parameters.
479 * XXX this duplicates much of the functionality of TupleDescInitEntry.
480 * the routines should be moved to the same place and be rewritten
481 * to share common code.
486 ExecSetTypeInfo(int index,
495 AttributeTupleForm att;
498 * get attribute pointer and preform a sanity check..
501 att = typeInfo[index];
503 elog(ERROR, "ExecSetTypeInfo: trying to assign through NULL");
506 * assign values to the tuple descriptor, being careful not
507 * to copy a null attName..
509 * XXX it is unknown exactly what information is needed to
510 * initialize the attribute struct correctly so for now
511 * we use 0. this should be fixed -- otherwise we run the
512 * risk of using garbage data. -cim 5/5/91
515 att->attrelid = 0; /* dummy value */
517 if (attName != (char *) NULL)
518 StrNCpy(att->attname.data, attName, NAMEDATALEN);
520 MemSet(att->attname.data, 0, NAMEDATALEN);
522 att->atttypid = typeID;
523 att->attdefrel = 0; /* dummy value */
524 att->attdisbursion = 0; /* dummy value */
525 att->atttyparg = 0; /* dummy value */
526 att->attlen = attLen;
527 att->attnum = attNum;
528 att->attbound = 0; /* dummy value */
529 att->attbyval = attbyVal;
530 att->attcanindex = 0; /* dummy value */
531 att->attproc = 0; /* dummy value */
532 att->attnelems = 0; /* dummy value */
533 att->attcacheoff = -1;
535 att->attisset = false;
536 att->attalign = attalign;
540 * ExecFreeTypeInfo frees the array of attrbutes
541 * created by ExecMakeTypeInfo and returned by ExecTypeFromTL...
545 ExecFreeTypeInfo(TupleDesc typeInfo)
548 * do nothing if asked to free a null pointer
551 if (typeInfo == NULL)
555 * the entire array of typeinfo pointers created by
556 * ExecMakeTypeInfo was allocated with a single palloc()
557 * so we can deallocate the whole array with a single pfree().
558 * (we should not try and free all the elements in the array)
566 /* ----------------------------------------------------------------
567 * QueryDescGetTypeInfo
569 *| I don't know how this is used, all I know is that it
570 *| appeared one day in main.c so I moved it here. -cim 11/1/89
571 * ----------------------------------------------------------------
574 QueryDescGetTypeInfo(QueryDesc *queryDesc)
579 AttrInfo *attinfo = (AttrInfo *) palloc(sizeof(AttrInfo));
581 plan = queryDesc->plantree;
582 tupleType = (TupleDesc) ExecGetTupType(plan);
584 targetList = plan->targetlist;
586 attinfo->numAttr = ExecTargetListLength(targetList);
587 attinfo->attrs = tupleType;
589 attinfo->numAttr = tupleType->natts;
590 attinfo->attrs = tupleType->attrs;
596 /* ----------------------------------------------------------------
597 * ExecInsertIndexTuples support
598 * ----------------------------------------------------------------
600 /* ----------------------------------------------------------------
601 * ExecGetIndexKeyInfo
603 * Extracts the index key attribute numbers from
604 * an index tuple form (i.e. a tuple from the pg_index relation)
605 * into an array of attribute numbers. The array and the
606 * size of the array are returned to the caller via return
608 * ----------------------------------------------------------------
611 ExecGetIndexKeyInfo(IndexTupleForm indexTuple,
613 AttrNumber **attsOutP,
614 FuncIndexInfoPtr fInfoP)
624 if (numAttsOutP == NULL && attsOutP == NULL)
626 elog(DEBUG, "ExecGetIndexKeyInfo: %s",
627 "invalid parameters: numAttsOutP and attsOutP must be non-NULL");
631 * set the procid for a possible functional index.
634 FIsetProcOid(fInfoP, indexTuple->indproc);
637 * count the number of keys..
641 for (i = 0; i < 8 && indexTuple->indkey[i] != 0; i++)
645 * place number keys in callers return area
646 * or the number of arguments for a functional index.
648 * If we have a functional index then the number of
649 * attributes defined in the index must 1 (the function's
650 * single return value).
653 if (FIgetProcOid(fInfoP) != InvalidOid)
655 FIsetnArgs(fInfoP, numKeys);
659 (*numAttsOutP) = numKeys;
663 elog(DEBUG, "ExecGetIndexKeyInfo: %s",
664 "all index key attribute numbers are zero!");
670 * allocate and fill in array of key attribute numbers
673 CXT1_printf("ExecGetIndexKeyInfo: context is %d\n", CurrentMemoryContext);
675 attKeys = (AttrNumber *)
676 palloc(numKeys * sizeof(AttrNumber));
678 for (i = 0; i < numKeys; i++)
679 attKeys[i] = indexTuple->indkey[i];
682 * return array to caller.
685 (*attsOutP) = attKeys;
688 /* ----------------------------------------------------------------
691 * Here we scan the pg_index relation to find indices
692 * associated with a given heap relation oid. Since we
693 * don't know in advance how many indices we have, we
694 * form lists containing the information we need from
695 * pg_index and then process these lists.
697 * Note: much of this code duplicates effort done by
698 * the IndexCatalogInformation function in plancat.c
699 * because IndexCatalogInformation is poorly written.
701 * It would be much better the functionality provided
702 * by this function and IndexCatalogInformation was
703 * in the form of a small set of orthogonal routines..
704 * If you are trying to understand this, I suggest you
705 * look at the code to IndexCatalogInformation and
706 * FormIndexTuple.. -cim 9/27/89
707 * ----------------------------------------------------------------
710 ExecOpenIndices(Oid resultRelationOid,
711 RelationInfo *resultRelationInfo)
714 HeapScanDesc indexSd;
717 IndexTupleForm indexStruct;
732 RelationPtr relationDescs;
733 IndexInfo **indexInfoArray;
734 FuncIndexInfoPtr fInfoP;
736 AttrNumber *indexKeyAtts;
744 indexRd = heap_openr(IndexRelationName);
750 ScanKeyEntryInitialize(&key, 0, Anum_pg_index_indrelid,
751 ObjectIdEqualRegProcedure,
752 ObjectIdGetDatum(resultRelationOid));
755 * scan the index relation, looking for indices for our
759 indexSd = heap_beginscan(indexRd, /* scan desc */
760 false, /* scan backward flag */
761 false, /* see self */
762 1, /* number scan keys */
763 &key); /* scan keys */
771 while (tuple = heap_getnext(indexSd, /* scan desc */
772 false, /* scan backward flag */
773 NULL), /* return: buffer */
774 HeapTupleIsValid(tuple))
778 * For each index relation we find, extract the information
779 * we need and store it in a list..
781 * first get the oid of the index relation from the tuple
784 indexStruct = (IndexTupleForm) GETSTRUCT(tuple);
785 indexOid = indexStruct->indexrelid;
788 * allocate space for functional index information.
791 fInfoP = (FuncIndexInfoPtr) palloc(sizeof(*fInfoP));
794 * next get the index key information from the tuple
797 ExecGetIndexKeyInfo(indexStruct,
803 * next get the index predicate from the tuple
806 if (VARSIZE(&indexStruct->indpred) != 0)
808 predString = fmgr(F_TEXTOUT, &indexStruct->indpred);
809 predicate = (PredInfo *) stringToNode(predString);
818 * save the index information into lists
821 oidList = lconsi(indexOid, oidList);
822 nkeyList = lconsi(numKeyAtts, nkeyList);
823 keyList = lcons(indexKeyAtts, keyList);
824 fiList = lcons(fInfoP, fiList);
825 predList = lcons(predicate, predList);
829 * we have the info we need so close the pg_index relation..
832 heap_endscan(indexSd);
836 * Now that we've collected the index information into three
837 * lists, we open the index relations and store the descriptors
838 * and the key information into arrays.
841 len = length(oidList);
845 * allocate space for relation descs
848 CXT1_printf("ExecOpenIndices: context is %d\n", CurrentMemoryContext);
849 relationDescs = (RelationPtr)
850 palloc(len * sizeof(Relation));
853 * initialize index info array
856 CXT1_printf("ExecOpenIndices: context is %d\n", CurrentMemoryContext);
857 indexInfoArray = (IndexInfo **)
858 palloc(len * sizeof(IndexInfo *));
860 for (i = 0; i < len; i++)
862 IndexInfo *ii = makeNode(IndexInfo);
864 ii->ii_NumKeyAttributes = 0;
865 ii->ii_KeyAttributeNumbers = (AttrNumber *) NULL;
866 ii->ii_FuncIndexInfo = (FuncIndexInfoPtr) NULL;
867 ii->ii_Predicate = NULL;
868 indexInfoArray[i] = ii;
872 * attempt to open each of the indices. If we succeed,
873 * then store the index relation descriptor into the
874 * relation descriptor array.
878 foreach(indexoid, oidList)
882 indexOid = lfirsti(indexoid);
883 indexDesc = index_open(indexOid);
884 if (indexDesc != NULL)
885 relationDescs[i++] = indexDesc;
889 * store the relation descriptor array and number of
890 * descs into the result relation info.
893 resultRelationInfo->ri_NumIndices = i;
894 resultRelationInfo->ri_IndexRelationDescs = relationDescs;
897 * store the index key information collected in our
898 * lists into the index info array
902 foreach(numkeys, nkeyList)
904 numKeyAtts = lfirsti(numkeys);
905 indexInfoArray[i++]->ii_NumKeyAttributes = numKeyAtts;
909 foreach(indexkeys, keyList)
911 indexKeyAtts = (AttrNumber *) lfirst(indexkeys);
912 indexInfoArray[i++]->ii_KeyAttributeNumbers = indexKeyAtts;
916 foreach(indexfuncs, fiList)
918 FuncIndexInfoPtr fiP = (FuncIndexInfoPtr) lfirst(indexfuncs);
920 indexInfoArray[i++]->ii_FuncIndexInfo = fiP;
924 foreach(indexpreds, predList)
926 indexInfoArray[i++]->ii_Predicate = lfirst(indexpreds);
929 * store the index info array into relation info
932 resultRelationInfo->ri_IndexRelationInfo = indexInfoArray;
936 * All done, resultRelationInfo now contains complete information
937 * on the indices associated with the result relation.
941 /* should free oidList, nkeyList and keyList here */
942 /* OK - let's do it -jolly */
950 /* ----------------------------------------------------------------
953 * Close the index relations stored in resultRelationInfo
954 * ----------------------------------------------------------------
957 ExecCloseIndices(RelationInfo *resultRelationInfo)
961 RelationPtr relationDescs;
963 numIndices = resultRelationInfo->ri_NumIndices;
964 relationDescs = resultRelationInfo->ri_IndexRelationDescs;
966 for (i = 0; i < numIndices; i++)
967 if (relationDescs[i] != NULL)
968 index_close(relationDescs[i]);
971 * XXX should free indexInfo array here too.
975 /* ----------------------------------------------------------------
978 * Most of this code is cannabilized from DefaultBuild().
979 * As said in the comments for ExecOpenIndices, most of
980 * this functionality should be rearranged into a proper
982 * ----------------------------------------------------------------
986 ExecFormIndexTuple(HeapTuple heapTuple,
987 Relation heapRelation,
988 Relation indexRelation,
989 IndexInfo *indexInfo)
991 IndexTuple indexTuple;
992 TupleDesc heapDescriptor;
993 TupleDesc indexDescriptor;
997 int numberOfAttributes;
998 AttrNumber *keyAttributeNumbers;
999 FuncIndexInfoPtr fInfoP;
1002 * get information from index info structure
1005 numberOfAttributes = indexInfo->ii_NumKeyAttributes;
1006 keyAttributeNumbers = indexInfo->ii_KeyAttributeNumbers;
1007 fInfoP = indexInfo->ii_FuncIndexInfo;
1010 * datum and null are arrays in which we collect the index attributes
1011 * when forming a new index tuple.
1014 CXT1_printf("ExecFormIndexTuple: context is %d\n", CurrentMemoryContext);
1015 datum = (Datum *) palloc(numberOfAttributes * sizeof *datum);
1016 nulls = (char *) palloc(numberOfAttributes * sizeof *nulls);
1019 * get the tuple descriptors from the relations so we know
1020 * how to form the index tuples..
1023 heapDescriptor = RelationGetTupleDescriptor(heapRelation);
1024 indexDescriptor = RelationGetTupleDescriptor(indexRelation);
1027 * FormIndexDatum fills in its datum and null parameters
1028 * with attribute information taken from the given heap tuple.
1031 FormIndexDatum(numberOfAttributes, /* num attributes */
1032 keyAttributeNumbers, /* array of att nums to extract */
1033 heapTuple, /* tuple from base relation */
1034 heapDescriptor, /* heap tuple's descriptor */
1035 InvalidBuffer, /* buffer associated with heap
1037 datum, /* return: array of attributes */
1038 nulls, /* return: array of char's */
1039 fInfoP); /* functional index information */
1041 indexTuple = index_formtuple(indexDescriptor,
1046 * free temporary arrays
1048 * XXX should store these in the IndexInfo instead of allocating
1049 * and freeing on every insertion, but efficency here is not
1050 * that important and FormIndexTuple is wasteful anyways..
1062 /* ----------------------------------------------------------------
1063 * ExecInsertIndexTuples
1065 * This routine takes care of inserting index tuples
1066 * into all the relations indexing the result relation
1067 * when a heap tuple is inserted into the result relation.
1068 * Much of this code should be moved into the genam
1069 * stuff as it only exists here because the genam stuff
1070 * doesn't provide the functionality needed by the
1071 * executor.. -cim 9/27/89
1072 * ----------------------------------------------------------------
1075 ExecInsertIndexTuples(TupleTableSlot *slot,
1076 ItemPointer tupleid,
1080 HeapTuple heapTuple;
1081 RelationInfo *resultRelationInfo;
1084 RelationPtr relationDescs;
1085 Relation heapRelation;
1086 IndexInfo **indexInfoArray;
1087 IndexInfo *indexInfo;
1090 ExprContext *econtext;
1091 InsertIndexResult result;
1092 int numberOfAttributes;
1093 AttrNumber *keyAttributeNumbers;
1094 FuncIndexInfoPtr fInfoP;
1095 TupleDesc heapDescriptor;
1099 heapTuple = slot->val;
1102 * get information from the result relation info structure.
1105 resultRelationInfo = estate->es_result_relation_info;
1106 numIndices = resultRelationInfo->ri_NumIndices;
1107 relationDescs = resultRelationInfo->ri_IndexRelationDescs;
1108 indexInfoArray = resultRelationInfo->ri_IndexRelationInfo;
1109 heapRelation = resultRelationInfo->ri_RelationDesc;
1112 * for each index, form and insert the index tuple
1116 for (i = 0; i < numIndices; i++)
1118 if (relationDescs[i] == NULL)
1121 indexInfo = indexInfoArray[i];
1122 predicate = indexInfo->ii_Predicate;
1123 if (predicate != NULL)
1125 if (econtext == NULL)
1127 econtext = makeNode(ExprContext);
1129 econtext->ecxt_scantuple = slot;
1131 /* Skip this index-update if the predicate isn't satisfied */
1132 satisfied = ExecQual((List *) predicate, econtext);
1133 if (satisfied == false)
1138 * get information from index info structure
1141 numberOfAttributes = indexInfo->ii_NumKeyAttributes;
1142 keyAttributeNumbers = indexInfo->ii_KeyAttributeNumbers;
1143 fInfoP = indexInfo->ii_FuncIndexInfo;
1144 datum = (Datum *) palloc(numberOfAttributes * sizeof *datum);
1145 nulls = (char *) palloc(numberOfAttributes * sizeof *nulls);
1146 heapDescriptor = (TupleDesc) RelationGetTupleDescriptor(heapRelation);
1148 FormIndexDatum(numberOfAttributes, /* num attributes */
1149 keyAttributeNumbers, /* array of att nums to
1151 heapTuple, /* tuple from base relation */
1152 heapDescriptor, /* heap tuple's descriptor */
1153 InvalidBuffer, /* buffer associated with heap
1155 datum, /* return: array of attributes */
1156 nulls, /* return: array of char's */
1157 fInfoP); /* functional index information */
1160 result = index_insert(relationDescs[i], /* index relation */
1161 datum, /* array of heaptuple Datums */
1162 nulls, /* info on nulls */
1163 &(heapTuple->t_ctid), /* oid of heap tuple */
1167 * keep track of index inserts for debugging
1170 IncrIndexInserted();
1173 * free index tuple after insertion
1179 if (econtext != NULL)