blob: 2908672132a28bef1d6ceaff2a89399ae7f90ec4 [file] [log] [blame]
/*-------------------------------------------------------------------------
*
* nodeDynamicIndexOnlyscan.c
* Support routines for scanning one or more indexes that are
* determined at runtime.
*
* DynamicIndexOnlyScan node scans each index one after the other. For each
* index, it creates a regular IndexOnlyScan executor node, scans, and returns
* the relevant tuples.
*
* Copyright (C) 2023 VMware, Inc. or its affiliates. All Rights Reserved.
*
*
* IDENTIFICATION
* src/backend/executor/nodeDynamicIndexOnlyscan.c
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
#include "catalog/partition.h"
#include "executor/executor.h"
#include "executor/execDynamicIndexes.h"
#include "executor/instrument.h"
#include "nodes/execnodes.h"
#include "executor/execPartition.h"
#include "executor/nodeIndexonlyscan.h"
#include "executor/nodeDynamicIndexOnlyscan.h"
#include "access/table.h"
#include "access/tableam.h"
#include "utils/memutils.h"
#include "utils/rel.h"
/*
* Initialize ScanState in DynamicIndexOnlyScan.
*/
DynamicIndexScanState *
ExecInitDynamicIndexOnlyScan(DynamicIndexOnlyScan *node, EState *estate, int eflags)
{
DynamicIndexScanState *dynamicIndexOnlyScanState;
ListCell *lc;
int i;
/* check for unsupported flags */
Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
dynamicIndexOnlyScanState = makeNode(DynamicIndexScanState);
dynamicIndexOnlyScanState->ss.ps.plan = (Plan *) node;
dynamicIndexOnlyScanState->ss.ps.state = estate;
dynamicIndexOnlyScanState->ss.ps.ExecProcNode = ExecDynamicIndexOnlyScan;
dynamicIndexOnlyScanState->eflags = eflags;
dynamicIndexOnlyScanState->scan_state = SCAN_INIT;
dynamicIndexOnlyScanState->whichPart = -1;
dynamicIndexOnlyScanState->nOids = list_length(node->partOids);
dynamicIndexOnlyScanState->partOids = palloc(sizeof(Oid) * dynamicIndexOnlyScanState->nOids);
foreach_with_count(lc, node->partOids, i)
dynamicIndexOnlyScanState->partOids[i] = lfirst_oid(lc);
/*
* Initialize child expressions
*
* These are not used for anything, we rely on the child IndexOnlyScan
* node to do all evaluation for us. But I think this is still needed to
* find and process any SubPlans. See comment in ExecInitIndexOnlyScan.
*/
dynamicIndexOnlyScanState->ss.ps.qual = ExecInitQual(node->indexscan.scan.plan.qual,
(PlanState *) dynamicIndexOnlyScanState);
/*
* tuple table initialization
*/
Relation scanRel = ExecOpenScanRelation(estate, node->indexscan.scan.scanrelid, eflags);
ExecInitScanTupleSlot(estate, &dynamicIndexOnlyScanState->ss, RelationGetDescr(scanRel), table_slot_callbacks(scanRel));
/*
* Initialize result tuple type and projection info.
*/
ExecInitResultTypeTL(&dynamicIndexOnlyScanState->ss.ps);
/*
* This context will be reset per-partition to free up per-partition copy
* of LogicalIndexInfo
*/
dynamicIndexOnlyScanState->partitionMemoryContext = AllocSetContextCreate(CurrentMemoryContext,
"DynamicIndexOnlyScanPerPartition",
ALLOCSET_DEFAULT_MINSIZE,
ALLOCSET_DEFAULT_INITSIZE,
ALLOCSET_DEFAULT_MAXSIZE);
return dynamicIndexOnlyScanState;
}
/*
* Execution of DynamicIndexOnlyScan
*/
TupleTableSlot *
ExecDynamicIndexOnlyScan(PlanState *pstate)
{
DynamicIndexScanState *node = castNode(DynamicIndexScanState, pstate);
DynamicIndexOnlyScan *plan = (DynamicIndexOnlyScan *) node->ss.ps.plan;
node->as_valid_subplans = NULL;
if (NULL != plan->join_prune_paramids && !node->did_pruning)
{
node->did_pruning = true;
node->as_valid_subplans =
ExecFindMatchingSubPlans(node->as_prune_state,
node->ss.ps.state,
list_length(plan->partOids),
plan->join_prune_paramids);
int i;
int partOidIdx = -1;
List *newPartOids = NIL;
ListCell *lc;
for (i = 0; i < bms_num_members(node->as_valid_subplans); i++)
{
partOidIdx = bms_next_member(node->as_valid_subplans, partOidIdx);
newPartOids = lappend_oid(newPartOids, node->partOids[partOidIdx]);
}
node->partOids = palloc(sizeof(Oid) * list_length(newPartOids));
foreach_with_count(lc, newPartOids, i)
node->partOids[i] = lfirst_oid(lc);
node->nOids = list_length(newPartOids);
}
return ExecNextDynamicIndexScan(node);
}