]> granicus.if.org Git - postgresql/blob - src/backend/executor/execUtils.c
Goodbye register keyword. Compiler knows better.
[postgresql] / src / backend / executor / execUtils.c
1 /*-------------------------------------------------------------------------
2  *
3  * execUtils.c--
4  *        miscellanious executor utility routines
5  *
6  * Copyright (c) 1994, Regents of the University of California
7  *
8  *
9  * IDENTIFICATION
10  *        $Header: /cvsroot/pgsql/src/backend/executor/execUtils.c,v 1.28 1998/02/10 04:00:52 momjian Exp $
11  *
12  *-------------------------------------------------------------------------
13  */
14 /*
15  * INTERFACE ROUTINES
16  *              ExecAssignNodeBaseInfo  \
17  *              ExecAssignDebugHooks     >      preforms misc work done in all the
18  *              ExecAssignExprContext   /       init node routines.
19  *
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             /
26  *
27
28  *              QueryDescGetTypeInfo - moved here from main.c
29  *                                                              am not sure what uses it -cim 10/12/89
30  *
31  *              ExecGetIndexKeyInfo             \
32  *              ExecOpenIndices                  | referenced by InitPlan, EndPlan,
33  *              ExecCloseIndices                 | ExecAppend, ExecReplace
34  *              ExecFormIndexTuple               |
35  *              ExecInsertIndexTuple    /
36  *
37  *       NOTES
38  *              This file has traditionally been the place to stick misc.
39  *              executor support stuff that doesn't really go anyplace else.
40  *
41  */
42
43 #include "postgres.h"
44 #include "fmgr.h"
45
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"
61
62 static void
63 ExecGetIndexKeyInfo(IndexTupleForm indexTuple, int *numAttsOutP,
64                                         AttrNumber **attsOutP, FuncIndexInfoPtr fInfoP);
65
66 /* ----------------------------------------------------------------
67  *              global counters for number of tuples processed, retrieved,
68  *              appended, replaced, deleted.
69  * ----------------------------------------------------------------
70  */
71 int                     NTupleProcessed;
72 int                     NTupleRetrieved;
73 int                     NTupleReplaced;
74 int                     NTupleAppended;
75 int                     NTupleDeleted;
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. */
80
81 /* ----------------------------------------------------------------
82  *                                              statistic functions
83  * ----------------------------------------------------------------
84  */
85
86 /* ----------------------------------------------------------------
87  *              ResetTupleCount
88  * ----------------------------------------------------------------
89  */
90 #ifdef NOT_USED
91 void
92 ResetTupleCount(void)
93 {
94         NTupleProcessed = 0;
95         NTupleRetrieved = 0;
96         NTupleAppended = 0;
97         NTupleDeleted = 0;
98         NTupleReplaced = 0;
99         NIndexTupleProcessed = 0;
100 }
101
102 #endif
103
104 /* ----------------------------------------------------------------
105  *              PrintTupleCount
106  * ----------------------------------------------------------------
107  */
108 #ifdef NOT_USED
109 void
110 DisplayTupleCount(FILE *statfp)
111 {
112         if (NTupleProcessed > 0)
113                 fprintf(statfp, "!\t%d tuple%s processed, ", NTupleProcessed,
114                                 (NTupleProcessed == 1) ? "" : "s");
115         else
116         {
117                 fprintf(statfp, "!\tno tuples processed.\n");
118                 return;
119         }
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");
139 }
140
141 #endif
142
143 /* ----------------------------------------------------------------
144  *                               miscellanious init node support functions
145  *
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  * ----------------------------------------------------------------
150  */
151
152 /* ----------------
153  *              ExecAssignNodeBaseInfo
154  *
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.
158  * ----------------
159  */
160 void
161 ExecAssignNodeBaseInfo(EState *estate, CommonState *cstate, Plan *parent)
162 {
163         int                     baseId;
164
165         baseId = estate->es_BaseId;
166         cstate->cs_base_id = baseId;
167         estate->es_BaseId = baseId + 1;
168 }
169
170 /* ----------------
171  *              ExecAssignExprContext
172  *
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.
177  * ----------------
178  */
179 void
180 ExecAssignExprContext(EState *estate, CommonState *commonstate)
181 {
182         ExprContext *econtext;
183         ParamListInfo paraminfo;
184         List       *rangeTable;
185
186         paraminfo = estate->es_param_list_info;
187         rangeTable = estate->es_range_table;
188
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 */
197
198         commonstate->cs_ExprContext = econtext;
199 }
200
201 /* ----------------------------------------------------------------
202  *              Result slot tuple type and ProjectionInfo support
203  * ----------------------------------------------------------------
204  */
205
206 /* ----------------
207  *              ExecAssignResultType
208  * ----------------
209  */
210 void
211 ExecAssignResultType(CommonState *commonstate,
212                                          TupleDesc tupDesc)
213 {
214         TupleTableSlot *slot;
215
216         slot = commonstate->cs_ResultTupleSlot;
217         slot->ttc_tupleDescriptor = tupDesc;
218 }
219
220 /* ----------------
221  *              ExecAssignResultTypeFromOuterPlan
222  * ----------------
223  */
224 void
225 ExecAssignResultTypeFromOuterPlan(Plan *node, CommonState *commonstate)
226 {
227         Plan       *outerPlan;
228         TupleDesc       tupDesc;
229
230         outerPlan = outerPlan(node);
231         tupDesc = ExecGetTupType(outerPlan);
232
233         ExecAssignResultType(commonstate, tupDesc);
234 }
235
236 /* ----------------
237  *              ExecAssignResultTypeFromTL
238  * ----------------
239  */
240 void
241 ExecAssignResultTypeFromTL(Plan *node, CommonState *commonstate)
242 {
243         List       *targetList;
244         int                     i;
245         int                     len;
246         List       *tl;
247         TargetEntry *tle;
248         List       *fjtl;
249         TupleDesc       origTupDesc;
250
251         targetList = node->targetlist;
252         origTupDesc = ExecTypeFromTL(targetList);
253         len = ExecTargetListLength(targetList);
254
255         fjtl = NIL;
256         tl = targetList;
257         i = 0;
258         while (tl != NIL || fjtl != NIL)
259         {
260                 if (fjtl != NIL)
261                 {
262                         tle = lfirst(fjtl);
263                         fjtl = lnext(fjtl);
264                 }
265                 else
266                 {
267                         tle = lfirst(tl);
268                         tl = lnext(tl);
269                 }
270 #ifdef SETS_FIXED
271                 if (!tl_is_resdom(tle))
272                 {
273                         Fjoin      *fj = (Fjoin *) lfirst(tle);
274
275                         /* it is a FJoin */
276                         fjtl = lnext(tle);
277                         tle = fj->fj_innerNode;
278                 }
279 #endif
280                 i++;
281         }
282         if (len > 0)
283         {
284                 ExecAssignResultType(commonstate,
285                                                          origTupDesc);
286         }
287         else
288                 ExecAssignResultType(commonstate,
289                                                          (TupleDesc) NULL);
290 }
291
292 /* ----------------
293  *              ExecGetResultType
294  * ----------------
295  */
296 TupleDesc
297 ExecGetResultType(CommonState *commonstate)
298 {
299         TupleTableSlot *slot = commonstate->cs_ResultTupleSlot;
300
301         return slot->ttc_tupleDescriptor;
302 }
303
304 /* ----------------
305  *              ExecFreeResultType
306  * ----------------
307  */
308 #ifdef NOT_USED
309 void
310 ExecFreeResultType(CommonState *commonstate)
311 {
312         TupleTableSlot *slot;
313         TupleDesc       tupType;
314
315         slot = commonstate->cs_ResultTupleSlot;
316         tupType = slot->ttc_tupleDescriptor;
317
318 /*        ExecFreeTypeInfo(tupType); */
319         pfree(tupType);
320 }
321
322 #endif
323
324 /* ----------------
325  *              ExecAssignProjectionInfo
326                   forms the projection information from the node's targetlist
327  * ----------------
328  */
329 void
330 ExecAssignProjectionInfo(Plan *node, CommonState *commonstate)
331 {
332         ProjectionInfo *projInfo;
333         List       *targetList;
334         int                     len;
335
336         targetList = node->targetlist;
337         len = ExecTargetListLength(targetList);
338
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;
346
347         commonstate->cs_ProjInfo = projInfo;
348 }
349
350
351 /* ----------------
352  *              ExecFreeProjectionInfo
353  * ----------------
354  */
355 void
356 ExecFreeProjectionInfo(CommonState *commonstate)
357 {
358         ProjectionInfo *projInfo;
359
360         /* ----------------
361          *      get projection info.  if NULL then this node has
362          *      none so we just return.
363          * ----------------
364          */
365         projInfo = commonstate->cs_ProjInfo;
366         if (projInfo == NULL)
367                 return;
368
369         /* ----------------
370          *      clean up memory used.
371          * ----------------
372          */
373         if (projInfo->pi_tupValue != NULL)
374                 pfree(projInfo->pi_tupValue);
375
376         pfree(projInfo);
377         commonstate->cs_ProjInfo = NULL;
378 }
379
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  * ----------------------------------------------------------------
388  */
389
390 /* ----------------
391  *              ExecGetScanType
392  * ----------------
393  */
394 TupleDesc
395 ExecGetScanType(CommonScanState *csstate)
396 {
397         TupleTableSlot *slot = csstate->css_ScanTupleSlot;
398
399         return slot->ttc_tupleDescriptor;
400 }
401
402 /* ----------------
403  *              ExecFreeScanType
404  * ----------------
405  */
406 #ifdef NOT_USED
407 void
408 ExecFreeScanType(CommonScanState *csstate)
409 {
410         TupleTableSlot *slot;
411         TupleDesc       tupType;
412
413         slot = csstate->css_ScanTupleSlot;
414         tupType = slot->ttc_tupleDescriptor;
415
416 /*        ExecFreeTypeInfo(tupType); */
417         pfree(tupType);
418 }
419
420 #endif
421
422 /* ----------------
423  *              ExecAssignScanType
424  * ----------------
425  */
426 void
427 ExecAssignScanType(CommonScanState *csstate,
428                                    TupleDesc tupDesc)
429 {
430         TupleTableSlot *slot;
431
432         slot = (TupleTableSlot *) csstate->css_ScanTupleSlot;
433         slot->ttc_tupleDescriptor = tupDesc;
434 }
435
436 /* ----------------
437  *              ExecAssignScanTypeFromOuterPlan
438  * ----------------
439  */
440 void
441 ExecAssignScanTypeFromOuterPlan(Plan *node, CommonScanState *csstate)
442 {
443         Plan       *outerPlan;
444         TupleDesc       tupDesc;
445
446         outerPlan = outerPlan(node);
447         tupDesc = ExecGetTupType(outerPlan);
448
449         ExecAssignScanType(csstate, tupDesc);
450 }
451
452
453 /* ----------------------------------------------------------------
454  *              ExecTypeFromTL support routines.
455  *
456  *              these routines are used mainly from ExecTypeFromTL.
457  *              -cim 6/12/90
458  *
459  * old comments
460  *              Routines dealing with the structure 'attribute' which conatains
461  *              the type information about attributes in a tuple:
462  *
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  * ----------------------------------------------------------------
471  */
472
473 /* ----------------
474  *              ExecSetTypeInfo
475  *
476  *              This initializes fields of a single attribute in a
477  *              tuple descriptor from the specified parameters.
478  *
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.
482  * ----------------
483  */
484 #ifdef NOT_USED
485 void
486 ExecSetTypeInfo(int index,
487                                 TupleDesc typeInfo,
488                                 Oid typeID,
489                                 int attNum,
490                                 int attLen,
491                                 char *attName,
492                                 bool attbyVal,
493                                 char attalign)
494 {
495         AttributeTupleForm att;
496
497         /* ----------------
498          *      get attribute pointer and preform a sanity check..
499          * ----------------
500          */
501         att = typeInfo[index];
502         if (att == NULL)
503                 elog(ERROR, "ExecSetTypeInfo: trying to assign through NULL");
504
505         /* ----------------
506          *      assign values to the tuple descriptor, being careful not
507          *      to copy a null attName..
508          *
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
513          * ----------------
514          */
515         att->attrelid = 0;                      /* dummy value */
516
517         if (attName != (char *) NULL)
518                 StrNCpy(att->attname.data, attName, NAMEDATALEN);
519         else
520                 MemSet(att->attname.data, 0, NAMEDATALEN);
521
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;
534         att->atttypmod = -1;
535         att->attisset = false;
536         att->attalign = attalign;
537 }
538
539 /* ----------------
540  *              ExecFreeTypeInfo frees the array of attrbutes
541  *              created by ExecMakeTypeInfo and returned by ExecTypeFromTL...
542  * ----------------
543  */
544 void
545 ExecFreeTypeInfo(TupleDesc typeInfo)
546 {
547         /* ----------------
548          *      do nothing if asked to free a null pointer
549          * ----------------
550          */
551         if (typeInfo == NULL)
552                 return;
553
554         /* ----------------
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)
559          *      -cim 6/12/90
560          * ----------------
561          */
562         pfree(typeInfo);
563 }
564
565
566 /* ----------------------------------------------------------------
567  *              QueryDescGetTypeInfo
568  *
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  * ----------------------------------------------------------------
572  */
573 TupleDesc
574 QueryDescGetTypeInfo(QueryDesc *queryDesc)
575 {
576         Plan       *plan;
577         TupleDesc       tupleType;
578         List       *targetList;
579         AttrInfo   *attinfo = (AttrInfo *) palloc(sizeof(AttrInfo));
580
581         plan = queryDesc->plantree;
582         tupleType = (TupleDesc) ExecGetTupType(plan);
583 /*
584         targetList =  plan->targetlist;
585
586         attinfo->numAttr = ExecTargetListLength(targetList);
587         attinfo->attrs = tupleType;
588 */
589         attinfo->numAttr = tupleType->natts;
590         attinfo->attrs = tupleType->attrs;
591         return attinfo;
592 }
593
594 #endif
595
596 /* ----------------------------------------------------------------
597  *                                ExecInsertIndexTuples support
598  * ----------------------------------------------------------------
599  */
600 /* ----------------------------------------------------------------
601  *              ExecGetIndexKeyInfo
602  *
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
607  *              parameters.
608  * ----------------------------------------------------------------
609  */
610 static void
611 ExecGetIndexKeyInfo(IndexTupleForm indexTuple,
612                                         int *numAttsOutP,
613                                         AttrNumber **attsOutP,
614                                         FuncIndexInfoPtr fInfoP)
615 {
616         int                     i;
617         int                     numKeys;
618         AttrNumber *attKeys;
619
620         /* ----------------
621          *      check parameters
622          * ----------------
623          */
624         if (numAttsOutP == NULL && attsOutP == NULL)
625         {
626                 elog(DEBUG, "ExecGetIndexKeyInfo: %s",
627                 "invalid parameters: numAttsOutP and attsOutP must be non-NULL");
628         }
629
630         /* ----------------
631          * set the procid for a possible functional index.
632          * ----------------
633          */
634         FIsetProcOid(fInfoP, indexTuple->indproc);
635
636         /* ----------------
637          *      count the number of keys..
638          * ----------------
639          */
640         numKeys = 0;
641         for (i = 0; i < 8 && indexTuple->indkey[i] != 0; i++)
642                 numKeys++;
643
644         /* ----------------
645          *      place number keys in callers return area
646          *      or the number of arguments for a functional index.
647          *
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).
651          * ----------------
652          */
653         if (FIgetProcOid(fInfoP) != InvalidOid)
654         {
655                 FIsetnArgs(fInfoP, numKeys);
656                 (*numAttsOutP) = 1;
657         }
658         else
659                 (*numAttsOutP) = numKeys;
660
661         if (numKeys < 1)
662         {
663                 elog(DEBUG, "ExecGetIndexKeyInfo: %s",
664                          "all index key attribute numbers are zero!");
665                 (*attsOutP) = NULL;
666                 return;
667         }
668
669         /* ----------------
670          *      allocate and fill in array of key attribute numbers
671          * ----------------
672          */
673         CXT1_printf("ExecGetIndexKeyInfo: context is %d\n", CurrentMemoryContext);
674
675         attKeys = (AttrNumber *)
676                 palloc(numKeys * sizeof(AttrNumber));
677
678         for (i = 0; i < numKeys; i++)
679                 attKeys[i] = indexTuple->indkey[i];
680
681         /* ----------------
682          *      return array to caller.
683          * ----------------
684          */
685         (*attsOutP) = attKeys;
686 }
687
688 /* ----------------------------------------------------------------
689  *              ExecOpenIndices
690  *
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.
696  *
697  *              Note: much of this code duplicates effort done by
698  *              the IndexCatalogInformation function in plancat.c
699  *              because IndexCatalogInformation is poorly written.
700  *
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  * ----------------------------------------------------------------
708  */
709 void
710 ExecOpenIndices(Oid resultRelationOid,
711                                 RelationInfo *resultRelationInfo)
712 {
713         Relation        indexRd;
714         HeapScanDesc indexSd;
715         ScanKeyData key;
716         HeapTuple       tuple;
717         IndexTupleForm indexStruct;
718         Oid                     indexOid;
719         List       *oidList;
720         List       *nkeyList;
721         List       *keyList;
722         List       *fiList;
723         char       *predString;
724         List       *predList;
725         List       *indexoid;
726         List       *numkeys;
727         List       *indexkeys;
728         List       *indexfuncs;
729         List       *indexpreds;
730         int                     len;
731
732         RelationPtr relationDescs;
733         IndexInfo **indexInfoArray;
734         FuncIndexInfoPtr fInfoP;
735         int                     numKeyAtts;
736         AttrNumber *indexKeyAtts;
737         PredInfo   *predicate;
738         int                     i;
739
740         /* ----------------
741          *      open pg_index
742          * ----------------
743          */
744         indexRd = heap_openr(IndexRelationName);
745
746         /* ----------------
747          *      form a scan key
748          * ----------------
749          */
750         ScanKeyEntryInitialize(&key, 0, Anum_pg_index_indrelid,
751                                                    ObjectIdEqualRegProcedure,
752                                                    ObjectIdGetDatum(resultRelationOid));
753
754         /* ----------------
755          *      scan the index relation, looking for indices for our
756          *      result relation..
757          * ----------------
758          */
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 */
764
765         oidList = NIL;
766         nkeyList = NIL;
767         keyList = NIL;
768         fiList = NIL;
769         predList = NIL;
770
771         while (tuple = heap_getnext(indexSd,            /* scan desc */
772                                                                 false,  /* scan backward flag */
773                                                                 NULL),  /* return: buffer */
774                    HeapTupleIsValid(tuple))
775         {
776
777                 /* ----------------
778                  *      For each index relation we find, extract the information
779                  *      we need and store it in a list..
780                  *
781                  *      first get the oid of the index relation from the tuple
782                  * ----------------
783                  */
784                 indexStruct = (IndexTupleForm) GETSTRUCT(tuple);
785                 indexOid = indexStruct->indexrelid;
786
787                 /* ----------------
788                  * allocate space for functional index information.
789                  * ----------------
790                  */
791                 fInfoP = (FuncIndexInfoPtr) palloc(sizeof(*fInfoP));
792
793                 /* ----------------
794                  *      next get the index key information from the tuple
795                  * ----------------
796                  */
797                 ExecGetIndexKeyInfo(indexStruct,
798                                                         &numKeyAtts,
799                                                         &indexKeyAtts,
800                                                         fInfoP);
801
802                 /* ----------------
803                  *      next get the index predicate from the tuple
804                  * ----------------
805                  */
806                 if (VARSIZE(&indexStruct->indpred) != 0)
807                 {
808                         predString = fmgr(F_TEXTOUT, &indexStruct->indpred);
809                         predicate = (PredInfo *) stringToNode(predString);
810                         pfree(predString);
811                 }
812                 else
813                 {
814                         predicate = NULL;
815                 }
816
817                 /* ----------------
818                  *      save the index information into lists
819                  * ----------------
820                  */
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);
826         }
827
828         /* ----------------
829          *      we have the info we need so close the pg_index relation..
830          * ----------------
831          */
832         heap_endscan(indexSd);
833         heap_close(indexRd);
834
835         /* ----------------
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.
839          * ----------------
840          */
841         len = length(oidList);
842         if (len > 0)
843         {
844                 /* ----------------
845                  *       allocate space for relation descs
846                  * ----------------
847                  */
848                 CXT1_printf("ExecOpenIndices: context is %d\n", CurrentMemoryContext);
849                 relationDescs = (RelationPtr)
850                         palloc(len * sizeof(Relation));
851
852                 /* ----------------
853                  *       initialize index info array
854                  * ----------------
855                  */
856                 CXT1_printf("ExecOpenIndices: context is %d\n", CurrentMemoryContext);
857                 indexInfoArray = (IndexInfo **)
858                         palloc(len * sizeof(IndexInfo *));
859
860                 for (i = 0; i < len; i++)
861                 {
862                         IndexInfo  *ii = makeNode(IndexInfo);
863
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;
869                 }
870
871                 /* ----------------
872                  *       attempt to open each of the indices.  If we succeed,
873                  *       then store the index relation descriptor into the
874                  *       relation descriptor array.
875                  * ----------------
876                  */
877                 i = 0;
878                 foreach(indexoid, oidList)
879                 {
880                         Relation        indexDesc;
881
882                         indexOid = lfirsti(indexoid);
883                         indexDesc = index_open(indexOid);
884                         if (indexDesc != NULL)
885                                 relationDescs[i++] = indexDesc;
886                 }
887
888                 /* ----------------
889                  *       store the relation descriptor array and number of
890                  *       descs into the result relation info.
891                  * ----------------
892                  */
893                 resultRelationInfo->ri_NumIndices = i;
894                 resultRelationInfo->ri_IndexRelationDescs = relationDescs;
895
896                 /* ----------------
897                  *       store the index key information collected in our
898                  *       lists into the index info array
899                  * ----------------
900                  */
901                 i = 0;
902                 foreach(numkeys, nkeyList)
903                 {
904                         numKeyAtts = lfirsti(numkeys);
905                         indexInfoArray[i++]->ii_NumKeyAttributes = numKeyAtts;
906                 }
907
908                 i = 0;
909                 foreach(indexkeys, keyList)
910                 {
911                         indexKeyAtts = (AttrNumber *) lfirst(indexkeys);
912                         indexInfoArray[i++]->ii_KeyAttributeNumbers = indexKeyAtts;
913                 }
914
915                 i = 0;
916                 foreach(indexfuncs, fiList)
917                 {
918                         FuncIndexInfoPtr fiP = (FuncIndexInfoPtr) lfirst(indexfuncs);
919
920                         indexInfoArray[i++]->ii_FuncIndexInfo = fiP;
921                 }
922
923                 i = 0;
924                 foreach(indexpreds, predList)
925                 {
926                         indexInfoArray[i++]->ii_Predicate = lfirst(indexpreds);
927                 }
928                 /* ----------------
929                  *       store the index info array into relation info
930                  * ----------------
931                  */
932                 resultRelationInfo->ri_IndexRelationInfo = indexInfoArray;
933         }
934
935         /* ----------------
936          *      All done,  resultRelationInfo now contains complete information
937          *      on the indices associated with the result relation.
938          * ----------------
939          */
940
941         /* should free oidList, nkeyList and keyList here */
942         /* OK - let's do it   -jolly */
943         freeList(oidList);
944         freeList(nkeyList);
945         freeList(keyList);
946         freeList(fiList);
947         freeList(predList);
948 }
949
950 /* ----------------------------------------------------------------
951  *              ExecCloseIndices
952  *
953  *              Close the index relations stored in resultRelationInfo
954  * ----------------------------------------------------------------
955  */
956 void
957 ExecCloseIndices(RelationInfo *resultRelationInfo)
958 {
959         int                     i;
960         int                     numIndices;
961         RelationPtr relationDescs;
962
963         numIndices = resultRelationInfo->ri_NumIndices;
964         relationDescs = resultRelationInfo->ri_IndexRelationDescs;
965
966         for (i = 0; i < numIndices; i++)
967                 if (relationDescs[i] != NULL)
968                         index_close(relationDescs[i]);
969
970         /*
971          * XXX should free indexInfo array here too.
972          */
973 }
974
975 /* ----------------------------------------------------------------
976  *              ExecFormIndexTuple
977  *
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
981  *              set of routines..
982  * ----------------------------------------------------------------
983  */
984 #ifdef NOT_USED
985 IndexTuple
986 ExecFormIndexTuple(HeapTuple heapTuple,
987                                    Relation heapRelation,
988                                    Relation indexRelation,
989                                    IndexInfo *indexInfo)
990 {
991         IndexTuple      indexTuple;
992         TupleDesc       heapDescriptor;
993         TupleDesc       indexDescriptor;
994         Datum      *datum;
995         char       *nulls;
996
997         int                     numberOfAttributes;
998         AttrNumber *keyAttributeNumbers;
999         FuncIndexInfoPtr fInfoP;
1000
1001         /* ----------------
1002          *      get information from index info structure
1003          * ----------------
1004          */
1005         numberOfAttributes = indexInfo->ii_NumKeyAttributes;
1006         keyAttributeNumbers = indexInfo->ii_KeyAttributeNumbers;
1007         fInfoP = indexInfo->ii_FuncIndexInfo;
1008
1009         /* ----------------
1010          *      datum and null are arrays in which we collect the index attributes
1011          *      when forming a new index tuple.
1012          * ----------------
1013          */
1014         CXT1_printf("ExecFormIndexTuple: context is %d\n", CurrentMemoryContext);
1015         datum = (Datum *) palloc(numberOfAttributes * sizeof *datum);
1016         nulls = (char *) palloc(numberOfAttributes * sizeof *nulls);
1017
1018         /* ----------------
1019          *      get the tuple descriptors from the relations so we know
1020          *      how to form the index tuples..
1021          * ----------------
1022          */
1023         heapDescriptor = RelationGetTupleDescriptor(heapRelation);
1024         indexDescriptor = RelationGetTupleDescriptor(indexRelation);
1025
1026         /* ----------------
1027          *      FormIndexDatum fills in its datum and null parameters
1028          *      with attribute information taken from the given heap tuple.
1029          * ----------------
1030          */
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
1036                                                                                  * tuple */
1037                                    datum,               /* return: array of attributes */
1038                                    nulls,               /* return: array of char's */
1039                                    fInfoP);             /* functional index information */
1040
1041         indexTuple = index_formtuple(indexDescriptor,
1042                                                                  datum,
1043                                                                  nulls);
1044
1045         /* ----------------
1046          *      free temporary arrays
1047          *
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..
1051          *         -cim 9/27/89
1052          * ----------------
1053          */
1054         pfree(nulls);
1055         pfree(datum);
1056
1057         return indexTuple;
1058 }
1059
1060 #endif
1061
1062 /* ----------------------------------------------------------------
1063  *              ExecInsertIndexTuples
1064  *
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  * ----------------------------------------------------------------
1073  */
1074 void
1075 ExecInsertIndexTuples(TupleTableSlot *slot,
1076                                           ItemPointer tupleid,
1077                                           EState *estate,
1078                                           bool is_update)
1079 {
1080         HeapTuple       heapTuple;
1081         RelationInfo *resultRelationInfo;
1082         int                     i;
1083         int                     numIndices;
1084         RelationPtr relationDescs;
1085         Relation        heapRelation;
1086         IndexInfo **indexInfoArray;
1087         IndexInfo  *indexInfo;
1088         Node       *predicate;
1089         bool            satisfied;
1090         ExprContext *econtext;
1091         InsertIndexResult result;
1092         int                     numberOfAttributes;
1093         AttrNumber *keyAttributeNumbers;
1094         FuncIndexInfoPtr fInfoP;
1095         TupleDesc       heapDescriptor;
1096         Datum      *datum;
1097         char       *nulls;
1098
1099         heapTuple = slot->val;
1100
1101         /* ----------------
1102          *      get information from the result relation info structure.
1103          * ----------------
1104          */
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;
1110
1111         /* ----------------
1112          *      for each index, form and insert the index tuple
1113          * ----------------
1114          */
1115         econtext = NULL;
1116         for (i = 0; i < numIndices; i++)
1117         {
1118                 if (relationDescs[i] == NULL)
1119                         continue;
1120
1121                 indexInfo = indexInfoArray[i];
1122                 predicate = indexInfo->ii_Predicate;
1123                 if (predicate != NULL)
1124                 {
1125                         if (econtext == NULL)
1126                         {
1127                                 econtext = makeNode(ExprContext);
1128                         }
1129                         econtext->ecxt_scantuple = slot;
1130
1131                         /* Skip this index-update if the predicate isn't satisfied */
1132                         satisfied = ExecQual((List *) predicate, econtext);
1133                         if (satisfied == false)
1134                                 continue;
1135                 }
1136
1137                 /* ----------------
1138                  *              get information from index info structure
1139                  * ----------------
1140                  */
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);
1147
1148                 FormIndexDatum(numberOfAttributes,              /* num attributes */
1149                                            keyAttributeNumbers,         /* array of att nums to
1150                                                                                                  * extract */
1151                                            heapTuple,           /* tuple from base relation */
1152                                            heapDescriptor,      /* heap tuple's descriptor */
1153                                            InvalidBuffer,       /* buffer associated with heap
1154                                                                                  * tuple */
1155                                            datum,       /* return: array of attributes */
1156                                            nulls,       /* return: array of char's */
1157                                            fInfoP); /* functional index information */
1158
1159
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 */
1164                                                           heapRelation);
1165
1166                 /* ----------------
1167                  *              keep track of index inserts for debugging
1168                  * ----------------
1169                  */
1170                 IncrIndexInserted();
1171
1172                 /* ----------------
1173                  *              free index tuple after insertion
1174                  * ----------------
1175                  */
1176                 if (result)
1177                         pfree(result);
1178         }
1179         if (econtext != NULL)
1180                 pfree(econtext);
1181 }