/* ---------------------------------------------------------------- * ExecInitBitmapIndexScan * * Initializes the index scan's state information. * ---------------------------------------------------------------- */ BitmapIndexScanState * ExecInitBitmapIndexScan(BitmapIndexScan *node, EState *estate, int eflags) { BitmapIndexScanState *indexstate; ScanKey scanKeys; int numScanKeys; ExprState **runtimeKeyInfo; bool have_runtime_keys; /* check for unsupported flags */ Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK))); /* * create state structure */ indexstate = makeNode(BitmapIndexScanState); indexstate->ss.ps.plan = (Plan *) node; indexstate->ss.ps.state = estate; /* normally we don't make the result bitmap till runtime */ indexstate->biss_result = NULL; indexstate->odbiss_result = NULL; /* * Miscellaneous initialization * * We do not need a standard exprcontext for this node, though we may * decide below to create a runtime-key exprcontext */ /* * initialize child expressions * * We don't need to initialize targetlist or qual since neither are used. * * Note: we don't initialize all of the indexqual expression, only the * sub-parts corresponding to runtime keys (see below). */ #define BITMAPINDEXSCAN_NSLOTS 0 /* * Initialize index-specific scan state */ indexstate->biss_RuntimeKeysReady = false; CXT1_printf("ExecInitBitmapIndexScan: context is %d\n", CurrentMemoryContext); /* * build the index scan keys from the index qualification */ have_runtime_keys = ExecIndexBuildScanKeys((PlanState *) indexstate, node->indexqual, node->indexstrategy, node->indexsubtype, &runtimeKeyInfo, &scanKeys, &numScanKeys); indexstate->biss_RuntimeKeyInfo = runtimeKeyInfo; indexstate->biss_ScanKeys = scanKeys; indexstate->biss_NumScanKeys = numScanKeys; /* * If we have runtime keys, we need an ExprContext to evaluate them. We * could just create a "standard" plan node exprcontext, but to keep the * code looking similar to nodeIndexscan.c, it seems better to stick with * the approach of using a separate ExprContext. */ if (have_runtime_keys) { ExprContext *stdecontext = indexstate->ss.ps.ps_ExprContext; ExecAssignExprContext(estate, &indexstate->ss.ps); indexstate->biss_RuntimeContext = indexstate->ss.ps.ps_ExprContext; indexstate->ss.ps.ps_ExprContext = stdecontext; } else { indexstate->biss_RuntimeContext = NULL; } /* * We do not open or lock the base relation here. We assume that an * ancestor BitmapHeapScan node is holding AccessShareLock on the heap * relation throughout the execution of the plan tree. */ indexstate->ss.ss_currentRelation = NULL; indexstate->ss.ss_currentScanDesc = NULL; /* * open the index relation and initialize relation and scan descriptors. * Note we acquire no locks here; the index machinery does its own locks * and unlocks. */ indexstate->biss_RelationDesc = index_open(node->indexid); indexstate->biss_ScanDesc = index_beginscan_multi(indexstate->biss_RelationDesc, estate->es_snapshot, numScanKeys, scanKeys); if (node->indexam == BITMAP_AM_OID) { indexstate->odbiss_ScanDesc = index_beginscan_bitmapwords(indexstate->biss_RelationDesc, estate->es_snapshot, numScanKeys, scanKeys); node->inmem = false; } else { indexstate->odbiss_ScanDesc = NULL; node->inmem = true; } /* * all done. */ return indexstate; }
/* ---------------------------------------------------------------- * ExecInitAppend * * Begin all of the subscans of the append node. * * (This is potentially wasteful, since the entire result of the * append node may not be scanned, but this way all of the * structures get allocated in the executor's top level memory * block instead of that of the call to ExecProcAppend.) * * Special case: during an EvalPlanQual recheck query of an inherited * target relation, we only want to initialize and scan the single * subplan that corresponds to the target relation being checked. * ---------------------------------------------------------------- */ AppendState * ExecInitAppend(Append *node, EState *estate) { AppendState *appendstate = makeNode(AppendState); PlanState **appendplanstates; int nplans; int i; Plan *initNode; CXT1_printf("ExecInitAppend: context is %d\n", CurrentMemoryContext); /* * Set up empty vector of subplan states */ nplans = length(node->appendplans); appendplanstates = (PlanState **) palloc0(nplans * sizeof(PlanState *)); /* * create new AppendState for our append node */ appendstate->ps.plan = (Plan *) node; appendstate->ps.state = estate; appendstate->appendplans = appendplanstates; appendstate->as_nplans = nplans; /* * Do we want to scan just one subplan? (Special case for * EvalPlanQual) XXX pretty dirty way of determining that this case * applies ... */ if (node->isTarget && estate->es_evTuple != NULL) { int tplan; tplan = estate->es_result_relation_info - estate->es_result_relations; Assert(tplan >= 0 && tplan < nplans); appendstate->as_firstplan = tplan; appendstate->as_lastplan = tplan; } else { /* normal case, scan all subplans */ appendstate->as_firstplan = 0; appendstate->as_lastplan = nplans - 1; } /* * Miscellaneous initialization * * Append plans don't have expression contexts because they never call * ExecQual or ExecProject. */ #define APPEND_NSLOTS 1 /* * append nodes still have Result slots, which hold pointers to * tuples, so we have to initialize them. */ ExecInitResultTupleSlot(estate, &appendstate->ps); /* * call ExecInitNode on each of the plans to be executed and save the * results into the array "appendplans". Note we *must* set * estate->es_result_relation_info correctly while we initialize each * sub-plan; ExecContextForcesOids depends on that! */ for (i = appendstate->as_firstplan; i <= appendstate->as_lastplan; i++) { appendstate->as_whichplan = i; exec_append_initialize_next(appendstate); initNode = (Plan *) nth(i, node->appendplans); appendplanstates[i] = ExecInitNode(initNode, estate); } /* * initialize tuple type */ ExecAssignResultTypeFromTL(&appendstate->ps); appendstate->ps.ps_ProjInfo = NULL; /* * return the result from the first subplan's initialization */ appendstate->as_whichplan = appendstate->as_firstplan; exec_append_initialize_next(appendstate); return appendstate; }
/* ---------------------------------------------------------------- * ExecInitBitmapHeapScan * * Initializes the scan's state information. * ---------------------------------------------------------------- */ BitmapHeapScanState * ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags) { BitmapHeapScanState *scanstate; RangeTblEntry *rtentry; Index relid; Oid reloid; Relation currentRelation; /* check for unsupported flags */ Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK))); /* * create state structure */ scanstate = makeNode(BitmapHeapScanState); scanstate->ss.ps.plan = (Plan *) node; scanstate->ss.ps.state = estate; scanstate->tbm = NULL; scanstate->tbmres = NULL; /* * Miscellaneous initialization * * create expression context for node */ ExecAssignExprContext(estate, &scanstate->ss.ps); /* * initialize child expressions */ scanstate->ss.ps.targetlist = (List *) ExecInitExpr((Expr *) node->scan.plan.targetlist, (PlanState *) scanstate); scanstate->ss.ps.qual = (List *) ExecInitExpr((Expr *) node->scan.plan.qual, (PlanState *) scanstate); scanstate->bitmapqualorig = (List *) ExecInitExpr((Expr *) node->bitmapqualorig, (PlanState *) scanstate); #define BITMAPHEAPSCAN_NSLOTS 2 /* * tuple table initialization */ ExecInitResultTupleSlot(estate, &scanstate->ss.ps); ExecInitScanTupleSlot(estate, &scanstate->ss); CXT1_printf("ExecInitBitmapHeapScan: context is %d\n", CurrentMemoryContext); /* * open the base relation and acquire AccessShareLock on it. */ relid = node->scan.scanrelid; rtentry = rt_fetch(relid, estate->es_range_table); reloid = rtentry->relid; currentRelation = heap_open(reloid, AccessShareLock); scanstate->ss.ss_currentRelation = currentRelation; /* * Even though we aren't going to do a conventional seqscan, it is useful * to create a HeapScanDesc --- this checks the relation size and sets up * statistical infrastructure for us. */ scanstate->ss.ss_currentScanDesc = heap_beginscan(currentRelation, estate->es_snapshot, 0, NULL); /* * One problem is that heap_beginscan counts a "sequential scan" start, * when we actually aren't doing any such thing. Reverse out the added * scan count. (Eventually we may want to count bitmap scans separately.) */ pgstat_discount_heap_scan(&scanstate->ss.ss_currentScanDesc->rs_pgstat_info); /* * get the scan type from the relation descriptor. */ ExecAssignScanType(&scanstate->ss, RelationGetDescr(currentRelation), false); /* * Initialize result tuple type and projection info. */ ExecAssignResultTypeFromTL(&scanstate->ss.ps); ExecAssignScanProjectionInfo(&scanstate->ss); /* * initialize child nodes * * We do this last because the child nodes will open indexscans on our * relation's indexes, and we want to be sure we have acquired a lock * on the relation first. */ outerPlanState(scanstate) = ExecInitNode(outerPlan(node), estate, eflags); if (IsA(outerPlan(node), BitmapIndexScan)) node->inmem = (((BitmapIndexScan*)outerPlan(node))->indexam != BITMAP_AM_OID); else if (IsA(outerPlan(node), BitmapAnd)) node->inmem = ((BitmapAnd*)outerPlan(node))->inmem; else if (IsA(outerPlan(node), BitmapOr)) node->inmem = ((BitmapOr*)outerPlan(node))->inmem; else node->inmem = true; /* * all done. */ return scanstate; }