static bool DynamicIndexScan_ReMapColumns(DynamicIndexScanState *scanState, Oid newOid) { Assert(OidIsValid(newOid)); IndexScan *indexScan = (IndexScan *) scanState->indexScanState.ss.ps.plan; if (!isDynamicScan(&indexScan->scan)) { return false; } Oid oldOid = scanState->columnLayoutOid; if (!OidIsValid(oldOid)) { /* Very first partition */ oldOid = rel_partition_get_root(newOid); } Assert(OidIsValid(oldOid)); if (oldOid == newOid) { /* * If we have only one partition and we are rescanning * then we can have this scenario. */ return false; } AttrNumber *attMap = IndexScan_GetColumnMapping(oldOid, newOid); scanState->columnLayoutOid = newOid; if (attMap) { IndexScan_MapLogicalIndexInfo(indexScan->logicalIndexInfo, attMap, indexScan->scan.scanrelid); change_varattnos_of_a_varno((Node*)indexScan->scan.plan.targetlist, attMap, indexScan->scan.scanrelid); change_varattnos_of_a_varno((Node*)indexScan->scan.plan.qual, attMap, indexScan->scan.scanrelid); change_varattnos_of_a_varno((Node*)indexScan->indexqual, attMap, indexScan->scan.scanrelid); pfree(attMap); return true; } else { return false; } }
/* * DynamicScan_RemapExpression * Re-maps the expression using the provided attMap. */ bool DynamicScan_RemapExpression(ScanState *scanState, AttrNumber *attMap, Node *expr) { if (!isDynamicScan((Scan *)scanState->ps.plan)) { return false; } if (NULL != attMap) { change_varattnos_of_a_varno((Node*)expr, attMap, ((Scan *)scanState->ps.plan)->scanrelid); return true; } return false; }
/* * initNextTableToScan * Find the next table to scan and initiate the scan if the previous table * is finished. * * If scanning on the current table is not finished, or a new table is found, * this function returns true. * If no more table is found, this function returns false. */ static bool initNextTableToScan(DynamicTableScanState *node) { ScanState *scanState = (ScanState *)node; if (scanState->scan_state == SCAN_INIT || scanState->scan_state == SCAN_DONE) { Oid *pid = hash_seq_search(&node->pidStatus); if (pid == NULL) { node->shouldCallHashSeqTerm = false; return false; } /* Collect number of partitions scanned in EXPLAIN ANALYZE */ if (NULL != scanState->ps.instrument) { Instrumentation *instr = scanState->ps.instrument; instr->numPartScanned ++; } /* * Inside ExecInitScanTupleSlot() we set the tuple table slot's oid * to range table entry's relid, which for partitioned table always set * to parent table's oid. In queries where we need to read table oids * (MPP-20736) we use the tuple table slot's saved oid (refer to slot_getsysattr()). * This wrongly returns parent oid, instead of partition oid. Therefore, * to return correct partition oid, we need to update * our tuple table slot's oid to reflect the partition oid. */ scanState->ss_ScanTupleSlot->tts_tableOid = *pid; scanState->ss_currentRelation = OpenScanRelationByOid(*pid); Relation lastScannedRel = OpenScanRelationByOid(node->lastRelOid); TupleDesc lastTupDesc = RelationGetDescr(lastScannedRel); CloseScanRelation(lastScannedRel); TupleDesc partTupDesc = RelationGetDescr(scanState->ss_currentRelation); ExecAssignScanType(scanState, partTupDesc); AttrNumber *attMap = NULL; attMap = varattnos_map(lastTupDesc, partTupDesc); /* If attribute remapping is not necessary, then do not change the varattno */ if (attMap) { change_varattnos_of_a_varno((Node*)scanState->ps.plan->qual, attMap, node->scanrelid); change_varattnos_of_a_varno((Node*)scanState->ps.plan->targetlist, attMap, node->scanrelid); /* * Now that the varattno mapping has been changed, change the relation that * the new varnos correspond to */ node->lastRelOid = *pid; } /* * For the very first partition, the targetlist of planstate is set to null. So, we must * initialize quals and targetlist, regardless of remapping requirements. For later * partitions, we only initialize quals and targetlist if a column re-mapping is necessary. */ if (attMap || node->firstPartition) { node->firstPartition = false; MemoryContextReset(node->partitionMemoryContext); MemoryContext oldCxt = MemoryContextSwitchTo(node->partitionMemoryContext); /* Initialize child expressions */ scanState->ps.qual = (List *)ExecInitExpr((Expr *)scanState->ps.plan->qual, (PlanState*)scanState); scanState->ps.targetlist = (List *)ExecInitExpr((Expr *)scanState->ps.plan->targetlist, (PlanState*)scanState); MemoryContextSwitchTo(oldCxt); } if (attMap) { pfree(attMap); } ExecAssignScanProjectionInfo(scanState); scanState->tableType = getTableType(scanState->ss_currentRelation); BeginTableScanRelation(scanState); } return true; }