~vcs-imports/mammoth-replicator/trunk

« back to all changes in this revision

Viewing changes to src/backend/executor/execUtils.c

  • Committer: alvherre
  • Date: 2005-12-16 21:24:52 UTC
  • Revision ID: svn-v4:db760fc0-0f08-0410-9d63-cc6633f64896:trunk:1
Initial import of the REL8_0_3 sources from the Pgsql CVS repository.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*-------------------------------------------------------------------------
 
2
 *
 
3
 * execUtils.c
 
4
 *        miscellaneous executor utility routines
 
5
 *
 
6
 * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
 
7
 * Portions Copyright (c) 1994, Regents of the University of California
 
8
 *
 
9
 *
 
10
 * IDENTIFICATION
 
11
 *        $PostgreSQL: pgsql/src/backend/executor/execUtils.c,v 1.117 2004-12-31 21:59:45 pgsql Exp $
 
12
 *
 
13
 *-------------------------------------------------------------------------
 
14
 */
 
15
/*
 
16
 * INTERFACE ROUTINES
 
17
 *              CreateExecutorState             Create/delete executor working state
 
18
 *              FreeExecutorState
 
19
 *              CreateExprContext
 
20
 *              FreeExprContext
 
21
 *              ReScanExprContext
 
22
 *
 
23
 *              ExecAssignExprContext   Common code for plan node init routines.
 
24
 *              ExecAssignResultType
 
25
 *              etc
 
26
 *
 
27
 *              ExecOpenIndices                 \
 
28
 *              ExecCloseIndices                 | referenced by InitPlan, EndPlan,
 
29
 *              ExecInsertIndexTuples   /  ExecInsert, ExecUpdate
 
30
 *
 
31
 *              RegisterExprContextCallback    Register function shutdown callback
 
32
 *              UnregisterExprContextCallback  Deregister function shutdown callback
 
33
 *
 
34
 *       NOTES
 
35
 *              This file has traditionally been the place to stick misc.
 
36
 *              executor support stuff that doesn't really go anyplace else.
 
37
 */
 
38
 
 
39
#include "postgres.h"
 
40
 
 
41
#include "access/genam.h"
 
42
#include "access/heapam.h"
 
43
#include "catalog/catname.h"
 
44
#include "catalog/index.h"
 
45
#include "catalog/catalog.h"
 
46
#include "catalog/pg_index.h"
 
47
#include "executor/execdebug.h"
 
48
#include "miscadmin.h"
 
49
#include "utils/builtins.h"
 
50
#include "utils/fmgroids.h"
 
51
#include "utils/memutils.h"
 
52
#include "utils/relcache.h"
 
53
#include "utils/syscache.h"
 
54
 
 
55
 
 
56
/* ----------------------------------------------------------------
 
57
 *              global counters for number of tuples processed, retrieved,
 
58
 *              appended, replaced, deleted.
 
59
 * ----------------------------------------------------------------
 
60
 */
 
61
int                     NTupleProcessed;
 
62
int                     NTupleRetrieved;
 
63
int                     NTupleReplaced;
 
64
int                     NTupleAppended;
 
65
int                     NTupleDeleted;
 
66
int                     NIndexTupleInserted;
 
67
extern int      NIndexTupleProcessed;           /* have to be defined in the
 
68
                                                                                 * access method level so that the
 
69
                                                                                 * cinterface.a will link ok. */
 
70
 
 
71
 
 
72
static void ShutdownExprContext(ExprContext *econtext);
 
73
 
 
74
 
 
75
/* ----------------------------------------------------------------
 
76
 *                                              statistic functions
 
77
 * ----------------------------------------------------------------
 
78
 */
 
79
 
 
80
/* ----------------------------------------------------------------
 
81
 *              ResetTupleCount
 
82
 * ----------------------------------------------------------------
 
83
 */
 
84
#ifdef NOT_USED
 
85
void
 
86
ResetTupleCount(void)
 
87
{
 
88
        NTupleProcessed = 0;
 
89
        NTupleRetrieved = 0;
 
90
        NTupleAppended = 0;
 
91
        NTupleDeleted = 0;
 
92
        NTupleReplaced = 0;
 
93
        NIndexTupleProcessed = 0;
 
94
}
 
95
#endif
 
96
 
 
97
/* ----------------------------------------------------------------
 
98
 *              PrintTupleCount
 
99
 * ----------------------------------------------------------------
 
100
 */
 
101
#ifdef NOT_USED
 
102
void
 
103
DisplayTupleCount(FILE *statfp)
 
104
{
 
105
        if (NTupleProcessed > 0)
 
106
                fprintf(statfp, "!\t%d tuple%s processed, ", NTupleProcessed,
 
107
                                (NTupleProcessed == 1) ? "" : "s");
 
108
        else
 
109
        {
 
110
                fprintf(statfp, "!\tno tuples processed.\n");
 
111
                return;
 
112
        }
 
113
        if (NIndexTupleProcessed > 0)
 
114
                fprintf(statfp, "%d indextuple%s processed, ", NIndexTupleProcessed,
 
115
                                (NIndexTupleProcessed == 1) ? "" : "s");
 
116
        if (NIndexTupleInserted > 0)
 
117
                fprintf(statfp, "%d indextuple%s inserted, ", NIndexTupleInserted,
 
118
                                (NIndexTupleInserted == 1) ? "" : "s");
 
119
        if (NTupleRetrieved > 0)
 
120
                fprintf(statfp, "%d tuple%s retrieved. ", NTupleRetrieved,
 
121
                                (NTupleRetrieved == 1) ? "" : "s");
 
122
        if (NTupleAppended > 0)
 
123
                fprintf(statfp, "%d tuple%s appended. ", NTupleAppended,
 
124
                                (NTupleAppended == 1) ? "" : "s");
 
125
        if (NTupleDeleted > 0)
 
126
                fprintf(statfp, "%d tuple%s deleted. ", NTupleDeleted,
 
127
                                (NTupleDeleted == 1) ? "" : "s");
 
128
        if (NTupleReplaced > 0)
 
129
                fprintf(statfp, "%d tuple%s replaced. ", NTupleReplaced,
 
130
                                (NTupleReplaced == 1) ? "" : "s");
 
131
        fprintf(statfp, "\n");
 
132
}
 
133
#endif
 
134
 
 
135
 
 
136
/* ----------------------------------------------------------------
 
137
 *                               Executor state and memory management functions
 
138
 * ----------------------------------------------------------------
 
139
 */
 
140
 
 
141
/* ----------------
 
142
 *              CreateExecutorState
 
143
 *
 
144
 *              Create and initialize an EState node, which is the root of
 
145
 *              working storage for an entire Executor invocation.
 
146
 *
 
147
 * Principally, this creates the per-query memory context that will be
 
148
 * used to hold all working data that lives till the end of the query.
 
149
 * Note that the per-query context will become a child of the caller's
 
150
 * CurrentMemoryContext.
 
151
 * ----------------
 
152
 */
 
153
EState *
 
154
CreateExecutorState(void)
 
155
{
 
156
        EState     *estate;
 
157
        MemoryContext qcontext;
 
158
        MemoryContext oldcontext;
 
159
 
 
160
        /*
 
161
         * Create the per-query context for this Executor run.
 
162
         */
 
163
        qcontext = AllocSetContextCreate(CurrentMemoryContext,
 
164
                                                                         "ExecutorState",
 
165
                                                                         ALLOCSET_DEFAULT_MINSIZE,
 
166
                                                                         ALLOCSET_DEFAULT_INITSIZE,
 
167
                                                                         ALLOCSET_DEFAULT_MAXSIZE);
 
168
 
 
169
        /*
 
170
         * Make the EState node within the per-query context.  This way, we
 
171
         * don't need a separate pfree() operation for it at shutdown.
 
172
         */
 
173
        oldcontext = MemoryContextSwitchTo(qcontext);
 
174
 
 
175
        estate = makeNode(EState);
 
176
 
 
177
        /*
 
178
         * Initialize all fields of the Executor State structure
 
179
         */
 
180
        estate->es_direction = ForwardScanDirection;
 
181
        estate->es_snapshot = SnapshotNow;
 
182
        estate->es_crosscheck_snapshot = InvalidSnapshot;       /* no crosscheck */
 
183
        estate->es_range_table = NIL;
 
184
 
 
185
        estate->es_result_relations = NULL;
 
186
        estate->es_num_result_relations = 0;
 
187
        estate->es_result_relation_info = NULL;
 
188
 
 
189
        estate->es_junkFilter = NULL;
 
190
        estate->es_into_relation_descriptor = NULL;
 
191
 
 
192
        estate->es_param_list_info = NULL;
 
193
        estate->es_param_exec_vals = NULL;
 
194
 
 
195
        estate->es_query_cxt = qcontext;
 
196
 
 
197
        estate->es_tupleTable = NULL;
 
198
 
 
199
        estate->es_processed = 0;
 
200
        estate->es_lastoid = InvalidOid;
 
201
        estate->es_rowMark = NIL;
 
202
 
 
203
        estate->es_instrument = false;
 
204
        estate->es_select_into = false;
 
205
        estate->es_into_oids = false;
 
206
 
 
207
        estate->es_exprcontexts = NIL;
 
208
 
 
209
        estate->es_per_tuple_exprcontext = NULL;
 
210
 
 
211
        estate->es_topPlan = NULL;
 
212
        estate->es_evalPlanQual = NULL;
 
213
        estate->es_evTupleNull = NULL;
 
214
        estate->es_evTuple = NULL;
 
215
        estate->es_useEvalPlan = false;
 
216
 
 
217
        /*
 
218
         * Return the executor state structure
 
219
         */
 
220
        MemoryContextSwitchTo(oldcontext);
 
221
 
 
222
        return estate;
 
223
}
 
224
 
 
225
/* ----------------
 
226
 *              FreeExecutorState
 
227
 *
 
228
 *              Release an EState along with all remaining working storage.
 
229
 *
 
230
 * Note: this is not responsible for releasing non-memory resources,
 
231
 * such as open relations or buffer pins.  But it will shut down any
 
232
 * still-active ExprContexts within the EState.  That is sufficient
 
233
 * cleanup for situations where the EState has only been used for expression
 
234
 * evaluation, and not to run a complete Plan.
 
235
 *
 
236
 * This can be called in any memory context ... so long as it's not one
 
237
 * of the ones to be freed.
 
238
 * ----------------
 
239
 */
 
240
void
 
241
FreeExecutorState(EState *estate)
 
242
{
 
243
        /*
 
244
         * Shut down and free any remaining ExprContexts.  We do this
 
245
         * explicitly to ensure that any remaining shutdown callbacks get
 
246
         * called (since they might need to release resources that aren't
 
247
         * simply memory within the per-query memory context).
 
248
         */
 
249
        while (estate->es_exprcontexts)
 
250
        {
 
251
                /*
 
252
                 * XXX: seems there ought to be a faster way to implement this
 
253
                 * than repeated list_delete(), no?
 
254
                 */
 
255
                FreeExprContext((ExprContext *) linitial(estate->es_exprcontexts));
 
256
                /* FreeExprContext removed the list link for us */
 
257
        }
 
258
 
 
259
        /*
 
260
         * Free the per-query memory context, thereby releasing all working
 
261
         * memory, including the EState node itself.
 
262
         */
 
263
        MemoryContextDelete(estate->es_query_cxt);
 
264
}
 
265
 
 
266
/* ----------------
 
267
 *              CreateExprContext
 
268
 *
 
269
 *              Create a context for expression evaluation within an EState.
 
270
 *
 
271
 * An executor run may require multiple ExprContexts (we usually make one
 
272
 * for each Plan node, and a separate one for per-output-tuple processing
 
273
 * such as constraint checking).  Each ExprContext has its own "per-tuple"
 
274
 * memory context.
 
275
 *
 
276
 * Note we make no assumption about the caller's memory context.
 
277
 * ----------------
 
278
 */
 
279
ExprContext *
 
280
CreateExprContext(EState *estate)
 
281
{
 
282
        ExprContext *econtext;
 
283
        MemoryContext oldcontext;
 
284
 
 
285
        /* Create the ExprContext node within the per-query memory context */
 
286
        oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
 
287
 
 
288
        econtext = makeNode(ExprContext);
 
289
 
 
290
        /* Initialize fields of ExprContext */
 
291
        econtext->ecxt_scantuple = NULL;
 
292
        econtext->ecxt_innertuple = NULL;
 
293
        econtext->ecxt_outertuple = NULL;
 
294
 
 
295
        econtext->ecxt_per_query_memory = estate->es_query_cxt;
 
296
 
 
297
        /*
 
298
         * Create working memory for expression evaluation in this context.
 
299
         */
 
300
        econtext->ecxt_per_tuple_memory =
 
301
                AllocSetContextCreate(estate->es_query_cxt,
 
302
                                                          "ExprContext",
 
303
                                                          ALLOCSET_DEFAULT_MINSIZE,
 
304
                                                          ALLOCSET_DEFAULT_INITSIZE,
 
305
                                                          ALLOCSET_DEFAULT_MAXSIZE);
 
306
 
 
307
        econtext->ecxt_param_exec_vals = estate->es_param_exec_vals;
 
308
        econtext->ecxt_param_list_info = estate->es_param_list_info;
 
309
 
 
310
        econtext->ecxt_aggvalues = NULL;
 
311
        econtext->ecxt_aggnulls = NULL;
 
312
 
 
313
        econtext->caseValue_datum = (Datum) 0;
 
314
        econtext->caseValue_isNull = true;
 
315
 
 
316
        econtext->domainValue_datum = (Datum) 0;
 
317
        econtext->domainValue_isNull = true;
 
318
 
 
319
        econtext->ecxt_estate = estate;
 
320
 
 
321
        econtext->ecxt_callbacks = NULL;
 
322
 
 
323
        /*
 
324
         * Link the ExprContext into the EState to ensure it is shut down when
 
325
         * the EState is freed.  Because we use lcons(), shutdowns will occur
 
326
         * in reverse order of creation, which may not be essential but can't
 
327
         * hurt.
 
328
         */
 
329
        estate->es_exprcontexts = lcons(econtext, estate->es_exprcontexts);
 
330
 
 
331
        MemoryContextSwitchTo(oldcontext);
 
332
 
 
333
        return econtext;
 
334
}
 
335
 
 
336
/* ----------------
 
337
 *              FreeExprContext
 
338
 *
 
339
 *              Free an expression context, including calling any remaining
 
340
 *              shutdown callbacks.
 
341
 *
 
342
 * Since we free the temporary context used for expression evaluation,
 
343
 * any previously computed pass-by-reference expression result will go away!
 
344
 *
 
345
 * Note we make no assumption about the caller's memory context.
 
346
 * ----------------
 
347
 */
 
348
void
 
349
FreeExprContext(ExprContext *econtext)
 
350
{
 
351
        EState     *estate;
 
352
 
 
353
        /* Call any registered callbacks */
 
354
        ShutdownExprContext(econtext);
 
355
        /* And clean up the memory used */
 
356
        MemoryContextDelete(econtext->ecxt_per_tuple_memory);
 
357
        /* Unlink self from owning EState */
 
358
        estate = econtext->ecxt_estate;
 
359
        estate->es_exprcontexts = list_delete_ptr(estate->es_exprcontexts, econtext);
 
360
        /* And delete the ExprContext node */
 
361
        pfree(econtext);
 
362
}
 
363
 
 
364
/*
 
365
 * ReScanExprContext
 
366
 *
 
367
 *              Reset an expression context in preparation for a rescan of its
 
368
 *              plan node.      This requires calling any registered shutdown callbacks,
 
369
 *              since any partially complete set-returning-functions must be canceled.
 
370
 *
 
371
 * Note we make no assumption about the caller's memory context.
 
372
 */
 
373
void
 
374
ReScanExprContext(ExprContext *econtext)
 
375
{
 
376
        /* Call any registered callbacks */
 
377
        ShutdownExprContext(econtext);
 
378
        /* And clean up the memory used */
 
379
        MemoryContextReset(econtext->ecxt_per_tuple_memory);
 
380
}
 
381
 
 
382
/*
 
383
 * Build a per-output-tuple ExprContext for an EState.
 
384
 *
 
385
 * This is normally invoked via GetPerTupleExprContext() macro,
 
386
 * not directly.
 
387
 */
 
388
ExprContext *
 
389
MakePerTupleExprContext(EState *estate)
 
390
{
 
391
        if (estate->es_per_tuple_exprcontext == NULL)
 
392
                estate->es_per_tuple_exprcontext = CreateExprContext(estate);
 
393
 
 
394
        return estate->es_per_tuple_exprcontext;
 
395
}
 
396
 
 
397
 
 
398
/* ----------------------------------------------------------------
 
399
 *                               miscellaneous node-init support functions
 
400
 *
 
401
 * Note: all of these are expected to be called with CurrentMemoryContext
 
402
 * equal to the per-query memory context.
 
403
 * ----------------------------------------------------------------
 
404
 */
 
405
 
 
406
/* ----------------
 
407
 *              ExecAssignExprContext
 
408
 *
 
409
 *              This initializes the ps_ExprContext field.      It is only necessary
 
410
 *              to do this for nodes which use ExecQual or ExecProject
 
411
 *              because those routines require an econtext. Other nodes that
 
412
 *              don't have to evaluate expressions don't need to do this.
 
413
 * ----------------
 
414
 */
 
415
void
 
416
ExecAssignExprContext(EState *estate, PlanState *planstate)
 
417
{
 
418
        planstate->ps_ExprContext = CreateExprContext(estate);
 
419
}
 
420
 
 
421
/* ----------------
 
422
 *              ExecAssignResultType
 
423
 * ----------------
 
424
 */
 
425
void
 
426
ExecAssignResultType(PlanState *planstate,
 
427
                                         TupleDesc tupDesc, bool shouldFree)
 
428
{
 
429
        TupleTableSlot *slot = planstate->ps_ResultTupleSlot;
 
430
 
 
431
        ExecSetSlotDescriptor(slot, tupDesc, shouldFree);
 
432
}
 
433
 
 
434
/* ----------------
 
435
 *              ExecAssignResultTypeFromOuterPlan
 
436
 * ----------------
 
437
 */
 
438
void
 
439
ExecAssignResultTypeFromOuterPlan(PlanState *planstate)
 
440
{
 
441
        PlanState  *outerPlan;
 
442
        TupleDesc       tupDesc;
 
443
 
 
444
        outerPlan = outerPlanState(planstate);
 
445
        tupDesc = ExecGetResultType(outerPlan);
 
446
 
 
447
        ExecAssignResultType(planstate, tupDesc, false);
 
448
}
 
449
 
 
450
/* ----------------
 
451
 *              ExecAssignResultTypeFromTL
 
452
 * ----------------
 
453
 */
 
454
void
 
455
ExecAssignResultTypeFromTL(PlanState *planstate)
 
456
{
 
457
        bool            hasoid;
 
458
        TupleDesc       tupDesc;
 
459
 
 
460
        if (ExecContextForcesOids(planstate, &hasoid))
 
461
        {
 
462
                /* context forces OID choice; hasoid is now set correctly */
 
463
        }
 
464
        else
 
465
        {
 
466
                /* given free choice, don't leave space for OIDs in result tuples */
 
467
                hasoid = false;
 
468
        }
 
469
 
 
470
        /*
 
471
         * ExecTypeFromTL needs the parse-time representation of the tlist,
 
472
         * not a list of ExprStates.  This is good because some plan nodes
 
473
         * don't bother to set up planstate->targetlist ...
 
474
         */
 
475
        tupDesc = ExecTypeFromTL(planstate->plan->targetlist, hasoid);
 
476
        ExecAssignResultType(planstate, tupDesc, true);
 
477
}
 
478
 
 
479
/* ----------------
 
480
 *              ExecGetResultType
 
481
 * ----------------
 
482
 */
 
483
TupleDesc
 
484
ExecGetResultType(PlanState *planstate)
 
485
{
 
486
        TupleTableSlot *slot = planstate->ps_ResultTupleSlot;
 
487
 
 
488
        return slot->ttc_tupleDescriptor;
 
489
}
 
490
 
 
491
/* ----------------
 
492
 *              ExecBuildProjectionInfo
 
493
 *
 
494
 * Build a ProjectionInfo node for evaluating the given tlist in the given
 
495
 * econtext, and storing the result into the tuple slot.  (Caller must have
 
496
 * ensured that tuple slot has a descriptor matching the tlist!)  Note that
 
497
 * the given tlist should be a list of ExprState nodes, not Expr nodes.
 
498
 * ----------------
 
499
 */
 
500
ProjectionInfo *
 
501
ExecBuildProjectionInfo(List *targetList,
 
502
                                                ExprContext *econtext,
 
503
                                                TupleTableSlot *slot)
 
504
{
 
505
        ProjectionInfo *projInfo = makeNode(ProjectionInfo);
 
506
        int                     len;
 
507
 
 
508
        len = ExecTargetListLength(targetList);
 
509
 
 
510
        projInfo->pi_targetlist = targetList;
 
511
        projInfo->pi_exprContext = econtext;
 
512
        projInfo->pi_slot = slot;
 
513
        if (len > 0)
 
514
        {
 
515
                projInfo->pi_tupValues = (Datum *) palloc(len * sizeof(Datum));
 
516
                projInfo->pi_tupNulls = (char *) palloc(len * sizeof(char));
 
517
                projInfo->pi_itemIsDone = (ExprDoneCond *) palloc(len * sizeof(ExprDoneCond));
 
518
        }
 
519
 
 
520
        return projInfo;
 
521
}
 
522
 
 
523
/* ----------------
 
524
 *              ExecAssignProjectionInfo
 
525
 *
 
526
 * forms the projection information from the node's targetlist
 
527
 * ----------------
 
528
 */
 
529
void
 
530
ExecAssignProjectionInfo(PlanState *planstate)
 
531
{
 
532
        planstate->ps_ProjInfo =
 
533
                ExecBuildProjectionInfo(planstate->targetlist,
 
534
                                                                planstate->ps_ExprContext,
 
535
                                                                planstate->ps_ResultTupleSlot);
 
536
}
 
537
 
 
538
 
 
539
/* ----------------
 
540
 *              ExecFreeExprContext
 
541
 *
 
542
 * A plan node's ExprContext should be freed explicitly during ExecEndNode
 
543
 * because there may be shutdown callbacks to call.  (Other resources made
 
544
 * by the above routines, such as projection info, don't need to be freed
 
545
 * explicitly because they're just memory in the per-query memory context.)
 
546
 * ----------------
 
547
 */
 
548
void
 
549
ExecFreeExprContext(PlanState *planstate)
 
550
{
 
551
        ExprContext *econtext;
 
552
 
 
553
        /*
 
554
         * get expression context.      if NULL then this node has none so we just
 
555
         * return.
 
556
         */
 
557
        econtext = planstate->ps_ExprContext;
 
558
        if (econtext == NULL)
 
559
                return;
 
560
 
 
561
        FreeExprContext(econtext);
 
562
 
 
563
        planstate->ps_ExprContext = NULL;
 
564
}
 
565
 
 
566
/* ----------------------------------------------------------------
 
567
 *              the following scan type support functions are for
 
568
 *              those nodes which are stubborn and return tuples in
 
569
 *              their Scan tuple slot instead of their Result tuple
 
570
 *              slot..  luck fur us, these nodes do not do projections
 
571
 *              so we don't have to worry about getting the ProjectionInfo
 
572
 *              right for them...  -cim 6/3/91
 
573
 * ----------------------------------------------------------------
 
574
 */
 
575
 
 
576
/* ----------------
 
577
 *              ExecGetScanType
 
578
 * ----------------
 
579
 */
 
580
TupleDesc
 
581
ExecGetScanType(ScanState *scanstate)
 
582
{
 
583
        TupleTableSlot *slot = scanstate->ss_ScanTupleSlot;
 
584
 
 
585
        return slot->ttc_tupleDescriptor;
 
586
}
 
587
 
 
588
/* ----------------
 
589
 *              ExecAssignScanType
 
590
 * ----------------
 
591
 */
 
592
void
 
593
ExecAssignScanType(ScanState *scanstate,
 
594
                                   TupleDesc tupDesc, bool shouldFree)
 
595
{
 
596
        TupleTableSlot *slot = scanstate->ss_ScanTupleSlot;
 
597
 
 
598
        ExecSetSlotDescriptor(slot, tupDesc, shouldFree);
 
599
}
 
600
 
 
601
/* ----------------
 
602
 *              ExecAssignScanTypeFromOuterPlan
 
603
 * ----------------
 
604
 */
 
605
void
 
606
ExecAssignScanTypeFromOuterPlan(ScanState *scanstate)
 
607
{
 
608
        PlanState  *outerPlan;
 
609
        TupleDesc       tupDesc;
 
610
 
 
611
        outerPlan = outerPlanState(scanstate);
 
612
        tupDesc = ExecGetResultType(outerPlan);
 
613
 
 
614
        ExecAssignScanType(scanstate, tupDesc, false);
 
615
}
 
616
 
 
617
 
 
618
/* ----------------------------------------------------------------
 
619
 *                                ExecInsertIndexTuples support
 
620
 * ----------------------------------------------------------------
 
621
 */
 
622
 
 
623
/* ----------------------------------------------------------------
 
624
 *              ExecOpenIndices
 
625
 *
 
626
 *              Find the indices associated with a result relation, open them,
 
627
 *              and save information about them in the result ResultRelInfo.
 
628
 *
 
629
 *              At entry, caller has already opened and locked
 
630
 *              resultRelInfo->ri_RelationDesc.
 
631
 *
 
632
 *              This used to be horribly ugly code, and slow too because it
 
633
 *              did a sequential scan of pg_index.      Now we rely on the relcache
 
634
 *              to cache a list of the OIDs of the indices associated with any
 
635
 *              specific relation, and we use the pg_index syscache to get the
 
636
 *              entries we need from pg_index.
 
637
 * ----------------------------------------------------------------
 
638
 */
 
639
void
 
640
ExecOpenIndices(ResultRelInfo *resultRelInfo)
 
641
{
 
642
        Relation        resultRelation = resultRelInfo->ri_RelationDesc;
 
643
        List       *indexoidlist;
 
644
        ListCell   *l;
 
645
        int                     len,
 
646
                                i;
 
647
        RelationPtr relationDescs;
 
648
        IndexInfo **indexInfoArray;
 
649
 
 
650
        resultRelInfo->ri_NumIndices = 0;
 
651
 
 
652
        /* fast path if no indexes */
 
653
        if (!RelationGetForm(resultRelation)->relhasindex)
 
654
                return;
 
655
 
 
656
        /*
 
657
         * Get cached list of index OIDs
 
658
         */
 
659
        indexoidlist = RelationGetIndexList(resultRelation);
 
660
        len = list_length(indexoidlist);
 
661
        if (len == 0)
 
662
                return;
 
663
 
 
664
        /*
 
665
         * allocate space for result arrays
 
666
         */
 
667
        relationDescs = (RelationPtr) palloc(len * sizeof(Relation));
 
668
        indexInfoArray = (IndexInfo **) palloc(len * sizeof(IndexInfo *));
 
669
 
 
670
        resultRelInfo->ri_NumIndices = len;
 
671
        resultRelInfo->ri_IndexRelationDescs = relationDescs;
 
672
        resultRelInfo->ri_IndexRelationInfo = indexInfoArray;
 
673
 
 
674
        /*
 
675
         * For each index, open the index relation and save pg_index info.
 
676
         */
 
677
        i = 0;
 
678
        foreach(l, indexoidlist)
 
679
        {
 
680
                Oid                     indexOid = lfirst_oid(l);
 
681
                Relation        indexDesc;
 
682
                IndexInfo  *ii;
 
683
 
 
684
                /*
 
685
                 * Open and lock the index relation
 
686
                 *
 
687
                 * If the index AM supports concurrent updates, obtain RowExclusiveLock
 
688
                 * to signify that we are updating the index.  This locks out only
 
689
                 * operations that need exclusive access, such as relocating the index
 
690
                 * to a new tablespace.
 
691
                 *
 
692
                 * If the index AM is not safe for concurrent updates, obtain an
 
693
                 * exclusive lock on the index to lock out other updaters as well
 
694
                 * as readers (index_beginscan places AccessShareLock).
 
695
                 *
 
696
                 * If there are multiple not-concurrent-safe indexes, all backends
 
697
                 * must lock the indexes in the same order or we will get deadlocks
 
698
                 * here.  This is guaranteed by RelationGetIndexList(), which promises
 
699
                 * to return the index list in OID order.
 
700
                 *
 
701
                 * The locks will be released in ExecCloseIndices.
 
702
                 */
 
703
                indexDesc = index_open(indexOid);
 
704
 
 
705
                if (indexDesc->rd_am->amconcurrent)
 
706
                        LockRelation(indexDesc, RowExclusiveLock);
 
707
                else
 
708
                        LockRelation(indexDesc, AccessExclusiveLock);
 
709
 
 
710
                /* extract index key information from the index's pg_index info */
 
711
                ii = BuildIndexInfo(indexDesc);
 
712
 
 
713
                relationDescs[i] = indexDesc;
 
714
                indexInfoArray[i] = ii;
 
715
                i++;
 
716
        }
 
717
 
 
718
        list_free(indexoidlist);
 
719
}
 
720
 
 
721
/* ----------------------------------------------------------------
 
722
 *              ExecCloseIndices
 
723
 *
 
724
 *              Close the index relations stored in resultRelInfo
 
725
 * ----------------------------------------------------------------
 
726
 */
 
727
void
 
728
ExecCloseIndices(ResultRelInfo *resultRelInfo)
 
729
{
 
730
        int                     i;
 
731
        int                     numIndices;
 
732
        RelationPtr indexDescs;
 
733
 
 
734
        numIndices = resultRelInfo->ri_NumIndices;
 
735
        indexDescs = resultRelInfo->ri_IndexRelationDescs;
 
736
 
 
737
        for (i = 0; i < numIndices; i++)
 
738
        {
 
739
                if (indexDescs[i] == NULL)
 
740
                        continue;                       /* shouldn't happen? */
 
741
 
 
742
                /* Drop lock acquired by ExecOpenIndices */
 
743
                if (indexDescs[i]->rd_am->amconcurrent)
 
744
                        UnlockRelation(indexDescs[i], RowExclusiveLock);
 
745
                else
 
746
                        UnlockRelation(indexDescs[i], AccessExclusiveLock);
 
747
 
 
748
                index_close(indexDescs[i]);
 
749
        }
 
750
 
 
751
        /*
 
752
         * XXX should free indexInfo array here too?  Currently we assume that
 
753
         * such stuff will be cleaned up automatically in FreeExecutorState.
 
754
         */
 
755
}
 
756
 
 
757
/* ----------------------------------------------------------------
 
758
 *              ExecInsertIndexTuples
 
759
 *
 
760
 *              This routine takes care of inserting index tuples
 
761
 *              into all the relations indexing the result relation
 
762
 *              when a heap tuple is inserted into the result relation.
 
763
 *              Much of this code should be moved into the genam
 
764
 *              stuff as it only exists here because the genam stuff
 
765
 *              doesn't provide the functionality needed by the
 
766
 *              executor.. -cim 9/27/89
 
767
 * ----------------------------------------------------------------
 
768
 */
 
769
void
 
770
ExecInsertIndexTuples(TupleTableSlot *slot,
 
771
                                          ItemPointer tupleid,
 
772
                                          EState *estate,
 
773
                                          bool is_vacuum)
 
774
{
 
775
        HeapTuple       heapTuple;
 
776
        ResultRelInfo *resultRelInfo;
 
777
        int                     i;
 
778
        int                     numIndices;
 
779
        RelationPtr relationDescs;
 
780
        Relation        heapRelation;
 
781
        TupleDesc       heapDescriptor;
 
782
        IndexInfo **indexInfoArray;
 
783
        ExprContext *econtext;
 
784
        Datum           datum[INDEX_MAX_KEYS];
 
785
        char            nullv[INDEX_MAX_KEYS];
 
786
 
 
787
        heapTuple = slot->val;
 
788
 
 
789
        /*
 
790
         * Get information from the result relation info structure.
 
791
         */
 
792
        resultRelInfo = estate->es_result_relation_info;
 
793
        numIndices = resultRelInfo->ri_NumIndices;
 
794
        relationDescs = resultRelInfo->ri_IndexRelationDescs;
 
795
        indexInfoArray = resultRelInfo->ri_IndexRelationInfo;
 
796
        heapRelation = resultRelInfo->ri_RelationDesc;
 
797
        heapDescriptor = RelationGetDescr(heapRelation);
 
798
 
 
799
        /*
 
800
         * We will use the EState's per-tuple context for evaluating
 
801
         * predicates and index expressions (creating it if it's not already
 
802
         * there).
 
803
         */
 
804
        econtext = GetPerTupleExprContext(estate);
 
805
 
 
806
        /* Arrange for econtext's scan tuple to be the tuple under test */
 
807
        econtext->ecxt_scantuple = slot;
 
808
 
 
809
        /*
 
810
         * for each index, form and insert the index tuple
 
811
         */
 
812
        for (i = 0; i < numIndices; i++)
 
813
        {
 
814
                IndexInfo  *indexInfo;
 
815
                InsertIndexResult result;
 
816
 
 
817
                if (relationDescs[i] == NULL)
 
818
                        continue;
 
819
 
 
820
                indexInfo = indexInfoArray[i];
 
821
 
 
822
                /* Check for partial index */
 
823
                if (indexInfo->ii_Predicate != NIL)
 
824
                {
 
825
                        List       *predicate;
 
826
 
 
827
                        /*
 
828
                         * If predicate state not set up yet, create it (in the
 
829
                         * estate's per-query context)
 
830
                         */
 
831
                        predicate = indexInfo->ii_PredicateState;
 
832
                        if (predicate == NIL)
 
833
                        {
 
834
                                predicate = (List *)
 
835
                                        ExecPrepareExpr((Expr *) indexInfo->ii_Predicate,
 
836
                                                                        estate);
 
837
                                indexInfo->ii_PredicateState = predicate;
 
838
                        }
 
839
 
 
840
                        /* Skip this index-update if the predicate isn't satisfied */
 
841
                        if (!ExecQual(predicate, econtext, false))
 
842
                                continue;
 
843
                }
 
844
 
 
845
                /*
 
846
                 * FormIndexDatum fills in its datum and null parameters with
 
847
                 * attribute information taken from the given heap tuple. It also
 
848
                 * computes any expressions needed.
 
849
                 */
 
850
                FormIndexDatum(indexInfo,
 
851
                                           heapTuple,
 
852
                                           heapDescriptor,
 
853
                                           estate,
 
854
                                           datum,
 
855
                                           nullv);
 
856
 
 
857
                /*
 
858
                 * The index AM does the rest.  Note we suppress unique-index
 
859
                 * checks if we are being called from VACUUM, since VACUUM may
 
860
                 * need to move dead tuples that have the same keys as live ones.
 
861
                 */
 
862
                result = index_insert(relationDescs[i], /* index relation */
 
863
                                                          datum,        /* array of heaptuple Datums */
 
864
                                                          nullv,        /* info on nulls */
 
865
                                                          &(heapTuple->t_self),         /* tid of heap tuple */
 
866
                                                          heapRelation,
 
867
                                  relationDescs[i]->rd_index->indisunique && !is_vacuum);
 
868
 
 
869
                /*
 
870
                 * keep track of index inserts for debugging
 
871
                 */
 
872
                IncrIndexInserted();
 
873
 
 
874
                if (result)
 
875
                        pfree(result);
 
876
        }
 
877
}
 
878
 
 
879
/*
 
880
 * UpdateChangedParamSet
 
881
 *              Add changed parameters to a plan node's chgParam set
 
882
 */
 
883
void
 
884
UpdateChangedParamSet(PlanState *node, Bitmapset *newchg)
 
885
{
 
886
        Bitmapset  *parmset;
 
887
 
 
888
        /*
 
889
         * The plan node only depends on params listed in its allParam set.
 
890
         * Don't include anything else into its chgParam set.
 
891
         */
 
892
        parmset = bms_intersect(node->plan->allParam, newchg);
 
893
 
 
894
        /*
 
895
         * Keep node->chgParam == NULL if there's not actually any members;
 
896
         * this allows the simplest possible tests in executor node files.
 
897
         */
 
898
        if (!bms_is_empty(parmset))
 
899
                node->chgParam = bms_join(node->chgParam, parmset);
 
900
        else
 
901
                bms_free(parmset);
 
902
}
 
903
 
 
904
/*
 
905
 * Register a shutdown callback in an ExprContext.
 
906
 *
 
907
 * Shutdown callbacks will be called (in reverse order of registration)
 
908
 * when the ExprContext is deleted or rescanned.  This provides a hook
 
909
 * for functions called in the context to do any cleanup needed --- it's
 
910
 * particularly useful for functions returning sets.  Note that the
 
911
 * callback will *not* be called in the event that execution is aborted
 
912
 * by an error.
 
913
 */
 
914
void
 
915
RegisterExprContextCallback(ExprContext *econtext,
 
916
                                                        ExprContextCallbackFunction function,
 
917
                                                        Datum arg)
 
918
{
 
919
        ExprContext_CB *ecxt_callback;
 
920
 
 
921
        /* Save the info in appropriate memory context */
 
922
        ecxt_callback = (ExprContext_CB *)
 
923
                MemoryContextAlloc(econtext->ecxt_per_query_memory,
 
924
                                                   sizeof(ExprContext_CB));
 
925
 
 
926
        ecxt_callback->function = function;
 
927
        ecxt_callback->arg = arg;
 
928
 
 
929
        /* link to front of list for appropriate execution order */
 
930
        ecxt_callback->next = econtext->ecxt_callbacks;
 
931
        econtext->ecxt_callbacks = ecxt_callback;
 
932
}
 
933
 
 
934
/*
 
935
 * Deregister a shutdown callback in an ExprContext.
 
936
 *
 
937
 * Any list entries matching the function and arg will be removed.
 
938
 * This can be used if it's no longer necessary to call the callback.
 
939
 */
 
940
void
 
941
UnregisterExprContextCallback(ExprContext *econtext,
 
942
                                                          ExprContextCallbackFunction function,
 
943
                                                          Datum arg)
 
944
{
 
945
        ExprContext_CB **prev_callback;
 
946
        ExprContext_CB *ecxt_callback;
 
947
 
 
948
        prev_callback = &econtext->ecxt_callbacks;
 
949
 
 
950
        while ((ecxt_callback = *prev_callback) != NULL)
 
951
        {
 
952
                if (ecxt_callback->function == function && ecxt_callback->arg == arg)
 
953
                {
 
954
                        *prev_callback = ecxt_callback->next;
 
955
                        pfree(ecxt_callback);
 
956
                }
 
957
                else
 
958
                        prev_callback = &ecxt_callback->next;
 
959
        }
 
960
}
 
961
 
 
962
/*
 
963
 * Call all the shutdown callbacks registered in an ExprContext.
 
964
 *
 
965
 * The callback list is emptied (important in case this is only a rescan
 
966
 * reset, and not deletion of the ExprContext).
 
967
 */
 
968
static void
 
969
ShutdownExprContext(ExprContext *econtext)
 
970
{
 
971
        ExprContext_CB *ecxt_callback;
 
972
        MemoryContext oldcontext;
 
973
 
 
974
        /* Fast path in normal case where there's nothing to do. */
 
975
        if (econtext->ecxt_callbacks == NULL)
 
976
                return;
 
977
 
 
978
        /*
 
979
         * Call the callbacks in econtext's per-tuple context.  This ensures
 
980
         * that any memory they might leak will get cleaned up.
 
981
         */
 
982
        oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
 
983
 
 
984
        /*
 
985
         * Call each callback function in reverse registration order.
 
986
         */
 
987
        while ((ecxt_callback = econtext->ecxt_callbacks) != NULL)
 
988
        {
 
989
                econtext->ecxt_callbacks = ecxt_callback->next;
 
990
                (*ecxt_callback->function) (ecxt_callback->arg);
 
991
                pfree(ecxt_callback);
 
992
        }
 
993
 
 
994
        MemoryContextSwitchTo(oldcontext);
 
995
}