/* * BeginStreamScan */ void BeginStreamScan(ForeignScanState *node, int eflags) { ForeignScan *plan = (ForeignScan *) node->ss.ps.plan; StreamScanState *state; ListCell *lc; List *colnames = (List *) linitial(plan->fdw_private); List *physical_tlist = (List *) lsecond(plan->fdw_private); Value *sample_cutoff = (Value *) lthird(plan->fdw_private); int i = 0; state = palloc0(sizeof(StreamScanState)); state->pi = palloc(sizeof(StreamProjectionInfo)); state->pi->mcxt = AllocSetContextCreate(CurrentMemoryContext, "ExecProjectContext", ALLOCSET_DEFAULT_MINSIZE, ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE); state->pi->ecxt = CreateStandaloneExprContext(); state->pi->outdesc = ExecTypeFromTL(physical_tlist, false); state->pi->indesc = NULL; state->sample_cutoff = sample_cutoff ? intVal(sample_cutoff) : -1; Assert(state->pi->outdesc->natts == list_length(colnames)); foreach(lc, colnames) { Value *v = (Value *) lfirst(lc); namestrcpy(&(state->pi->outdesc->attrs[i++]->attname), strVal(v)); }
/* * makeRangeVarFromNameList * Utility routine to convert a qualified-name list into RangeVar form. * * Copied from backend/catalog/namespace.c */ RangeVar * makeRangeVarFromNameList(List *names) { RangeVar *rel = makeRangeVar(NULL, NULL, -1); switch (list_length(names)) { case 1: rel->relname = strVal(linitial(names)); break; case 2: rel->schemaname = strVal(linitial(names)); rel->relname = strVal(lsecond(names)); break; case 3: rel->catalogname = strVal(linitial(names)); rel->schemaname = strVal(lsecond(names)); rel->relname = strVal(lthird(names)); break; default: ereport(WARNING, (errmsg("invalid relation name, too many indirections, while converting from table name to RangeVar"))); break; } return rel; }
/* * makeRangeVarFromNameList * Utility routine to convert a qualified-name list into RangeVar form. * * Copied from backend/catalog/namespace.c */ RangeVar * makeRangeVarFromNameList(List *names) { RangeVar *rel = makeRangeVar(NULL, NULL, -1); switch (list_length(names)) { case 1: rel->relname = strVal(linitial(names)); break; case 2: rel->schemaname = strVal(linitial(names)); rel->relname = strVal(lsecond(names)); break; case 3: rel->catalogname = strVal(linitial(names)); rel->schemaname = strVal(lsecond(names)); rel->relname = strVal(lthird(names)); break; default: pool_error("improper relation name (too many dotted names)"); break; } return rel; }
/* * ExtractRangeTblExtraData extracts extra data stored for a range table entry * that previously has been stored with * Set/ModifyRangeTblExtraData. Parameters can be NULL if unintersting. It is * valid to use the function on a RTE without extra data. */ void ExtractRangeTblExtraData(RangeTblEntry *rte, CitusRTEKind *rteKind, char **fragmentSchemaName, char **fragmentTableName, List **tableIdList) { RangeTblFunction *fauxFunction = NULL; FuncExpr *fauxFuncExpr = NULL; Const *tmpConst = NULL; /* set base rte kind first, so this can be used for 'non-extended' RTEs as well */ if (rteKind != NULL) { *rteKind = (CitusRTEKind) rte->rtekind; } /* reset values of optionally-present fields, will later be overwritten, if present */ if (fragmentSchemaName != NULL) { *fragmentSchemaName = NULL; } if (fragmentTableName != NULL) { *fragmentTableName = NULL; } if (tableIdList != NULL) { *tableIdList = NIL; } /* only function RTEs have our special extra data */ if (rte->rtekind != RTE_FUNCTION) { return; } /* we only ever generate one argument */ if (list_length(rte->functions) != 1) { return; } /* should pretty much always be a FuncExpr, but be liberal in what we expect... */ fauxFunction = linitial(rte->functions); if (!IsA(fauxFunction->funcexpr, FuncExpr)) { return; } fauxFuncExpr = (FuncExpr *) fauxFunction->funcexpr; /* * There will never be a range table entry with this function id, but for * the purpose of this file. */ if (fauxFuncExpr->funcid != CitusExtraDataContainerFuncId()) { return; } /* * Extra data for rtes is stored in the function arguments. The first * argument stores the rtekind, second fragmentSchemaName, third * fragmentTableName, fourth tableIdList. */ if (list_length(fauxFuncExpr->args) != 4) { ereport(ERROR, (errmsg("unexpected number of function arguments to " "citus_extradata_container"))); return; } /* extract rteKind */ tmpConst = (Const *) linitial(fauxFuncExpr->args); Assert(IsA(tmpConst, Const)); Assert(tmpConst->consttype == INT4OID); if (rteKind != NULL) { *rteKind = DatumGetInt32(tmpConst->constvalue); } /* extract fragmentSchemaName */ tmpConst = (Const *) lsecond(fauxFuncExpr->args); Assert(IsA(tmpConst, Const)); Assert(tmpConst->consttype == CSTRINGOID); if (fragmentSchemaName != NULL && !tmpConst->constisnull) { *fragmentSchemaName = DatumGetCString(tmpConst->constvalue); } /* extract fragmentTableName */ tmpConst = (Const *) lthird(fauxFuncExpr->args); Assert(IsA(tmpConst, Const)); Assert(tmpConst->consttype == CSTRINGOID); if (fragmentTableName != NULL && !tmpConst->constisnull) { *fragmentTableName = DatumGetCString(tmpConst->constvalue); } /* extract tableIdList, stored as a serialized integer list */ tmpConst = (Const *) lfourth(fauxFuncExpr->args); Assert(IsA(tmpConst, Const)); Assert(tmpConst->consttype == CSTRINGOID); if (tableIdList != NULL && !tmpConst->constisnull) { Node *deserializedList = stringToNode(DatumGetCString(tmpConst->constvalue)); Assert(IsA(deserializedList, IntList)); *tableIdList = (List *) deserializedList; } }