/* * Transform the subscript expressions. */ foreach(idx, indirection) { A_Indices *ai = (A_Indices *) lfirst(idx); Node *subexpr; Assert(IsA(ai, A_Indices)); if (isSlice) { if (ai->lidx) { subexpr = transformExpr(pstate, ai->lidx); /* If it's not int4 already, try to coerce */ subexpr = coerce_to_target_type(pstate, subexpr, exprType(subexpr), INT4OID, -1, COERCION_ASSIGNMENT, COERCE_IMPLICIT_CAST, -1); if (subexpr == NULL) ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), errmsg("array subscript must have type integer"), parser_errposition(pstate, exprLocation(ai->lidx)))); } else { /* Make a constant 1 */ subexpr = (Node *) makeConst(INT4OID, -1, InvalidOid, sizeof(int32), Int32GetDatum(1), false, true); /* pass by value */ } lowerIndexpr = lappend(lowerIndexpr, subexpr); } subexpr = transformExpr(pstate, ai->uidx); /* If it's not int4 already, try to coerce */ subexpr = coerce_to_target_type(pstate, subexpr, exprType(subexpr), INT4OID, -1, COERCION_ASSIGNMENT, COERCE_IMPLICIT_CAST, -1); if (subexpr == NULL) ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), errmsg("array subscript must have type integer"), parser_errposition(pstate, exprLocation(ai->uidx)))); upperIndexpr = lappend(upperIndexpr, subexpr); }
/* * transformTargetEntry() * Transform any ordinary "expression-type" node into a targetlist entry. * This is exported so that parse_clause.c can generate targetlist entries * for ORDER/GROUP BY items that are not already in the targetlist. * * node the (untransformed) parse tree for the value expression. * expr the transformed expression, or NULL if caller didn't do it yet. * colname the column name to be assigned, or NULL if none yet set. * resjunk true if the target should be marked resjunk, ie, it is not * wanted in the final projected tuple. */ TargetEntry * transformTargetEntry(ParseState *pstate, Node *node, Node *expr, char *colname, bool resjunk) { /* Transform the node if caller didn't do it already */ if (expr == NULL) expr = transformExpr(pstate, node); if (colname == NULL && !resjunk) { /* * Generate a suitable column name for a column without any explicit * 'AS ColumnName' clause. */ colname = FigureColname(node); } return makeTargetEntry((Expr *) expr, (AttrNumber) pstate->p_next_resno++, colname, resjunk); }
/* * Transform the subscript expressions. */ foreach(idx, indirection) { A_Indices *ai = castNode(A_Indices, lfirst(idx)); Node *subexpr; if (isSlice) { if (ai->lidx) { subexpr = transformExpr(pstate, ai->lidx, pstate->p_expr_kind); /* If it's not int4 already, try to coerce */ subexpr = coerce_to_target_type(pstate, subexpr, exprType(subexpr), INT4OID, -1, COERCION_ASSIGNMENT, COERCE_IMPLICIT_CAST, -1); if (subexpr == NULL) ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), errmsg("array subscript must have type integer"), parser_errposition(pstate, exprLocation(ai->lidx)))); } else if (!ai->is_slice) { /* Make a constant 1 */ subexpr = (Node *) makeConst(INT4OID, -1, InvalidOid, sizeof(int32), Int32GetDatum(1), false, true); /* pass by value */ } else { /* Slice with omitted lower bound, put NULL into the list */ subexpr = NULL; } lowerIndexpr = lappend(lowerIndexpr, subexpr); } else Assert(ai->lidx == NULL && !ai->is_slice); if (ai->uidx) { subexpr = transformExpr(pstate, ai->uidx, pstate->p_expr_kind); /* If it's not int4 already, try to coerce */ subexpr = coerce_to_target_type(pstate, subexpr, exprType(subexpr), INT4OID, -1, COERCION_ASSIGNMENT, COERCE_IMPLICIT_CAST, -1); if (subexpr == NULL) ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), errmsg("array subscript must have type integer"), parser_errposition(pstate, exprLocation(ai->uidx)))); } else { /* Slice with omitted upper bound, put NULL into the list */ Assert(isSlice && ai->is_slice); subexpr = NULL; } upperIndexpr = lappend(upperIndexpr, subexpr); }
/* * GetStreamScanPlan */ ForeignScan * GetStreamScanPlan(PlannerInfo *root, RelOptInfo *baserel, Oid relid, ForeignPath *best_path, List *tlist, List *scan_clauses, Plan *outer_plan) { StreamFdwInfo *sinfo = (StreamFdwInfo *) baserel->fdw_private; List *physical_tlist = build_physical_tlist(root, baserel); RangeTblEntry *rte = NULL; int i; TableSampleClause *sample; Value *sample_cutoff = NULL; /* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */ scan_clauses = extract_actual_clauses(scan_clauses, false); for (i = 1; i <= root->simple_rel_array_size; i++) { rte = root->simple_rte_array[i]; if (rte && rte->relid == relid) break; } if (!rte || rte->relid != relid) elog(ERROR, "stream RTE missing"); sample = rte->tablesample; if (sample) { double dcutoff; Datum d; ExprContext *econtext; bool isnull; Node *node; Expr *expr; ExprState *estate; ParseState *ps = make_parsestate(NULL); float4 percent; if (sample->tsmhandler != BERNOULLI_OID) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("tablesample method %s is not supported by streams", get_func_name(sample->tsmhandler)), errhint("Only bernoulli tablesample method can be used with streams."))); if (sample->repeatable) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("streams don't support the REPEATABLE clause for tablesample"))); econtext = CreateStandaloneExprContext(); ps = make_parsestate(NULL); node = (Node *) linitial(sample->args); node = transformExpr(ps, node, EXPR_KIND_OTHER); expr = expression_planner((Expr *) node); estate = ExecInitExpr(expr, NULL); d = ExecEvalExpr(estate, econtext, &isnull, NULL); free_parsestate(ps); FreeExprContext(econtext, false); percent = DatumGetFloat4(d); if (percent < 0 || percent > 100 || isnan(percent)) ereport(ERROR, (errcode(ERRCODE_INVALID_TABLESAMPLE_ARGUMENT), errmsg("sample percentage must be between 0 and 100"))); dcutoff = rint(((double) RAND_MAX + 1) * percent / 100); sample_cutoff = makeInteger((int) dcutoff); } return make_foreignscan(tlist, scan_clauses, baserel->relid, NIL, list_make3(sinfo->colnames, physical_tlist, sample_cutoff), NIL, NIL, outer_plan); }