54#define DEFAULT_FDW_STARTUP_COST 100.0
57#define DEFAULT_FDW_TUPLE_COST 0.2
60#define DEFAULT_FDW_SORT_MULTIPLIER 1.2
347 Index resultRelation,
381 Index resultRelation,
426 List *param_join_conds,
429 double *p_rows,
int *p_width,
430 int *p_disabled_nodes,
431 Cost *p_startup_cost,
Cost *p_total_cost);
440 double retrieved_rows,
444 Cost *p_startup_cost,
462 List *retrieved_attrs);
479 List *returningList);
484 List *fdw_scan_tlist,
495 const char ***param_values);
499 const char **param_values);
503 double *totaldeadrows);
513 List *retrieved_attrs,
526 Path *epq_path,
List *restrictlist);
633 baserel->fdw_private = fpinfo;
811 List *useful_eclass_list =
NIL;
821 foreach(lc,
root->eq_classes)
826 useful_eclass_list =
lappend(useful_eclass_list, cur_ec);
836 return useful_eclass_list;
853 if (restrictinfo->mergeopfamilies ==
NIL)
884 if (
bms_overlap(relids, restrictinfo->right_ec->ec_relids))
886 restrictinfo->right_ec);
887 else if (
bms_overlap(relids, restrictinfo->left_ec->ec_relids))
889 restrictinfo->left_ec);
892 return useful_eclass_list;
907 List *useful_pathkeys_list =
NIL;
908 List *useful_eclass_list;
920 bool query_pathkeys_ok =
true;
922 foreach(lc,
root->query_pathkeys)
935 query_pathkeys_ok =
false;
940 if (query_pathkeys_ok)
957 return useful_pathkeys_list;
967 query_ec = query_pathkey->pk_eclass;
977 foreach(lc, useful_eclass_list)
983 if (cur_ec == query_ec)
988 OperatorFamilyRelationId, fpinfo))
1000 useful_pathkeys_list =
lappend(useful_pathkeys_list,
1004 return useful_pathkeys_list;
1085 required_outer =
bms_union(rinfo->clause_relids,
1100 Assert(param_info != NULL);
1139 if (
arg.current == NULL)
1146 foreach(lc, clauses)
1161 required_outer =
bms_union(rinfo->clause_relids,
1170 Assert(param_info != NULL);
1184 foreach(lc, ppi_list)
1196 &rows, &width, &disabled_nodes,
1197 &startup_cost, &total_cost);
1241 List *fdw_recheck_quals =
NIL;
1242 List *retrieved_attrs;
1244 bool has_final_sort =
false;
1245 bool has_limit =
false;
1264 scan_relid = foreignrel->
relid;
1285 foreach(lc, scan_clauses)
1290 if (rinfo->pseudoconstant)
1307 fdw_recheck_quals = remote_exprs;
1365 foreach(lc, local_exprs)
1381 Join *join_plan = (
Join *) outer_plan;
1405 has_final_sort, has_limit,
false,
1406 &retrieved_attrs, ¶ms_list);
1419 fdw_private =
lappend(fdw_private,
1459 for (
int i = 0;
i < tupdesc->natts;
i++)
1467 if (att->atttypid != RECORDOID || att->atttypmod >= 0)
1484 att->atttypid = reltype;
1542 fsstate->cursor_exists =
false;
1554 "postgres_fdw tuple data",
1557 "postgres_fdw temporary data",
1571 fsstate->rel = NULL;
1581 fsstate->numParams = numParams;
1586 &fsstate->param_flinfo,
1587 &fsstate->param_exprs,
1588 &fsstate->param_values);
1679 snprintf(sql,
sizeof(sql),
"CLOSE c%u",
1685 snprintf(sql,
sizeof(sql),
"MOVE BACKWARD ALL IN c%u",
1690 snprintf(sql,
sizeof(sql),
"CLOSE c%u",
1728 if (fsstate == NULL)
1738 fsstate->
conn = NULL;
1778 Index resultRelation,
1786 List *withCheckOptionList =
NIL;
1789 bool doNothing =
false;
1790 int values_end_len = -1;
1840 elog(
ERROR,
"system-column update is not supported");
1848 if (
plan->withCheckOptionLists)
1855 if (
plan->returningLists)
1867 elog(
ERROR,
"unexpected ON CONFLICT specification: %d",
1868 (
int)
plan->onConflictAction);
1877 targetAttrs, doNothing,
1878 withCheckOptionList, returningList,
1879 &retrieved_attrs, &values_end_len);
1884 withCheckOptionList, returningList,
1893 elog(
ERROR,
"unexpected operation: %d", (
int) operation);
1926 List *retrieved_attrs;
1988 &slot, &planSlot, &numSlots);
1993 return rslot ? *rslot : NULL;
2017 slots, planSlots, numSlots);
2090 if (fmstate && fmstate->
p_nums > 0)
2110 &slot, &planSlot, &numSlots);
2112 return rslot ? rslot[0] : NULL;
2129 &slot, &planSlot, &numSlots);
2131 return rslot ? rslot[0] : NULL;
2145 if (fmstate == NULL)
2163 Index resultRelation;
2172 bool doNothing =
false;
2185 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2186 errmsg(
"cannot route tuples into foreign table to be updated \"%s\"",
2209 elog(
ERROR,
"unexpected ON CONFLICT specification: %d",
2210 (
int) onConflictAction);
2230 rte->relkind = RELKIND_FOREIGN_TABLE;
2254 &retrieved_attrs, &values_end_len);
2265 retrieved_attrs !=
NIL,
2333 if (strcmp(def->
defname,
"updatable") == 0)
2340 if (strcmp(def->
defname,
"updatable") == 0)
2450 Index resultRelation,
2488 if (fscan->
scan.plan.qual !=
NIL)
2499 foreignrel =
root->simple_rel_array[resultRelation];
2500 rte =
root->simple_rte_array[resultRelation];
2517 &processed_tlist, &targetAttrs);
2518 forboth(lc, processed_tlist, lc2, targetAttrs)
2527 elog(
ERROR,
"system-column update is not supported");
2555 if (
plan->returningLists)
2583 remote_exprs, ¶ms_list,
2584 returningList, &retrieved_attrs);
2589 remote_exprs, ¶ms_list,
2590 returningList, &retrieved_attrs);
2593 elog(
ERROR,
"unexpected operation: %d", (
int) operation);
2623 fscan->
scan.plan.lefttree = NULL;
2634 if (fscan->
scan.plan.async_capable)
2635 fscan->
scan.plan.async_capable =
false;
2694 dmstate->resultRel = dmstate->rel;
2702 dmstate->rel = NULL;
2706 dmstate->num_tuples = -1;
2720 "postgres_fdw temporary data",
2724 if (dmstate->has_returning)
2748 dmstate->numParams = numParams;
2753 &dmstate->param_flinfo,
2754 &dmstate->param_exprs,
2755 &dmstate->param_values);
2778 if (!resultRelInfo->ri_projectReturning)
2812 if (dmstate == NULL)
2820 dmstate->
conn = NULL;
2833 List *fdw_private =
plan->fdw_private;
2865 if (isdigit((
unsigned char) *ptr))
2867 int rti = strtol(ptr, &ptr, 10);
2882 if (isdigit((
unsigned char) *ptr))
2884 int rti = strtol(ptr, &ptr, 10);
2908 if (refname == NULL)
2909 refname = rte->eref->aliasname;
2910 if (strcmp(refname,
relname) != 0)
2992 bool server_truncatable =
true;
3018 foreach(cell, server->
options)
3022 if (strcmp(defel->
defname,
"truncatable") == 0)
3037 truncatable = server_truncatable;
3042 if (strcmp(defel->
defname,
"truncatable") == 0)
3051 (
errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
3052 errmsg(
"foreign table \"%s\" does not allow truncates",
3091 List *param_join_conds,
3094 double *p_rows,
int *p_width,
3095 int *p_disabled_nodes,
3096 Cost *p_startup_cost,
Cost *p_total_cost)
3100 double retrieved_rows;
3102 int disabled_nodes = 0;
3118 List *remote_param_join_conds;
3119 List *local_param_join_conds;
3128 List *retrieved_attrs;
3135 &remote_param_join_conds, &local_param_join_conds);
3141 fdw_scan_tlist =
NIL;
3148 remote_conds =
list_concat(remote_param_join_conds,
3159 remote_conds, pathkeys,
3162 false, &retrieved_attrs, NULL);
3167 &startup_cost, &total_cost);
3170 retrieved_rows = rows;
3174 local_param_join_conds,
3186 startup_cost += local_cost.
startup;
3187 total_cost += local_cost.
per_tuple * retrieved_rows;
3202 startup_cost -= tlist_cost.
startup;
3203 total_cost -= tlist_cost.
startup;
3204 total_cost -= tlist_cost.
per_tuple * rows;
3228 rows = fpinfo->
rows;
3230 width = fpinfo->
width;
3261 rows = foreignrel->
rows;
3271 nrows = fpinfo_i->
rows * fpinfo_o->
rows;
3278 retrieved_rows =
Min(retrieved_rows, nrows);
3301 startup_cost += join_cost.
startup;
3302 startup_cost += remote_conds_cost.
startup;
3322 run_cost += nrows * join_cost.
per_tuple;
3324 run_cost += nrows * remote_conds_cost.
per_tuple;
3338 double numGroups = 1;
3356 input_rows = ofpinfo->
rows;
3360 if (
root->parse->hasAggs)
3370 input_rows, NULL, NULL);
3376 if (
root->hasHavingQual)
3391 rows = retrieved_rows = numGroups;
3424 if (
root->hasHavingQual)
3430 startup_cost += remote_cost.
startup;
3431 run_cost += remote_cost.
per_tuple * numGroups;
3446 rows = foreignrel->
rows;
3454 retrieved_rows =
Min(retrieved_rows, foreignrel->
tuples);
3467 run_cost += cpu_per_tuple * foreignrel->
tuples;
3483 if (pathkeys !=
NIL)
3490 retrieved_rows, width,
3493 &startup_cost, &run_cost);
3502 total_cost = startup_cost + run_cost;
3509 retrieved_rows = rows;
3542 if (pathkeys ==
NIL && param_join_conds ==
NIL && fpextra == NULL)
3580 total_cost -= (total_cost - startup_cost) * 0.05 *
3587 *p_disabled_nodes = disabled_nodes;
3588 *p_startup_cost = startup_cost;
3589 *p_total_cost = total_cost;
3598 double *rows,
int *width,
3599 Cost *startup_cost,
Cost *total_cost)
3623 p = strrchr(line,
'(');
3625 elog(
ERROR,
"could not interpret EXPLAIN output: \"%s\"", line);
3626 n = sscanf(p,
"(cost=%lf..%lf rows=%lf width=%d)",
3627 startup_cost, total_cost, rows, width);
3629 elog(
ERROR,
"could not interpret EXPLAIN output: \"%s\"", line);
3645 double retrieved_rows,
3647 double limit_tuples,
3648 int *p_disabled_nodes,
3649 Cost *p_startup_cost,
3669 *p_startup_cost + *p_run_cost,
3688 *p_startup_cost *= sort_multiplier;
3689 *p_run_cost *= sort_multiplier;
3710 if (
state->current != NULL)
3720 state->current = expr;
3774 NULL,
values, NULL, NULL, 0))
3846 snprintf(sql,
sizeof(sql),
"FETCH %d FROM c%u",
3861 for (
i = 0;
i < numrows;
i++)
3985 List *retrieved_attrs)
4014 fmstate->
query = query;
4027 "postgres_fdw temporary data",
4047 elog(
ERROR,
"could not find junk ctid column");
4063 Assert(!attr->attisdropped);
4066 if (attr->attgenerated)
4105 const char **p_values;
4136 fmstate->
query = sql.data;
4169 fmstate->
p_nums * (*numSlots),
4208 return (n_rows > 0) ? slots : NULL;
4228 snprintf(prep_name,
sizeof(prep_name),
"pgsql_fdw_prep_%u",
4258 fmstate->
p_name = p_name;
4276 const char **p_values;
4284 p_values = (
const char **)
palloc(
sizeof(
char *) * fmstate->
p_nums * numSlots);
4287 Assert(!(tupleid != NULL && numSlots > 1));
4290 if (tupleid != NULL)
4308 for (
i = 0;
i < numSlots;
i++)
4310 j = (tupleid != NULL) ? 1 : 0;
4323 p_values[pindex] = NULL;
4392 fmstate->
conn = NULL;
4432 bool have_wholerow =
false;
4450 var->
varno == rtindex &&
4453 have_wholerow =
true;
4463 for (
i = 1;
i <= tupdesc->
natts;
i++)
4469 if (attr->attisdropped)
4498 var->
varno == rtindex &&
4533 List *new_tlist = tlist;
4537 foreach(lc, old_tlist)
4544 new_tlist =
lappend(new_tlist,
4585 NULL,
values, NULL, NULL, 0))
4619 Assert(resultRelInfo->ri_projectReturning);
4627 estate->es_processed += 1;
4674 resultRelInfo->ri_projectReturning->pi_exprContext->ecxt_scantuple =
4685 List *fdw_scan_tlist,
4711 foreach(lc, fdw_scan_tlist)
4722 if (var->
varno == rtindex &&
4792 for (
i = 0;
i < resultTupType->
natts;
i++)
4804 isnull[
i] = old_isnull[
j - 1];
4828 resultTup->
t_self = *ctid;
4861 const char ***param_values)
4872 foreach(lc, fdw_exprs)
4894 *param_values = (
const char **)
palloc0(numParams *
sizeof(
char *));
4904 const char **param_values)
4913 foreach(lc, param_exprs)
4920 expr_value =
ExecEvalExpr(expr_state, econtext, &isNull);
4927 param_values[
i] = NULL;
4984 elog(
ERROR,
"unexpected result from deparseAnalyzeSizeSql query");
5013 volatile double reltuples = -1;
5014 volatile char relkind = 0;
5017 *can_tablesample =
false;
5041 elog(
ERROR,
"unexpected result from deparseAnalyzeInfoSql query");
5055 *can_tablesample = (relkind == RELKIND_RELATION ||
5056 relkind == RELKIND_MATVIEW ||
5057 relkind == RELKIND_PARTITIONED_TABLE);
5080 double *totaldeadrows)
5089 double sample_frac = -1.0;
5097 astate.
rel = relation;
5110 "postgres_fdw temporary data",
5132 if (strcmp(def->
defname,
"analyze_sampling") == 0)
5136 if (strcmp(
value,
"off") == 0)
5138 else if (strcmp(
value,
"auto") == 0)
5140 else if (strcmp(
value,
"random") == 0)