57 #define DEFAULT_FDW_STARTUP_COST 100.0
60 #define DEFAULT_FDW_TUPLE_COST 0.01
63 #define DEFAULT_FDW_SORT_MULTIPLIER 1.2
350 Index resultRelation,
384 Index resultRelation,
429 List *param_join_conds,
432 double *p_rows,
int *p_width,
433 Cost *p_startup_cost,
Cost *p_total_cost);
442 double retrieved_rows,
445 Cost *p_startup_cost,
463 List *retrieved_attrs);
480 List *returningList);
485 List *fdw_scan_tlist,
496 const char ***param_values);
500 const char **param_values);
504 double *totaldeadrows);
514 List *retrieved_attrs,
527 Path *epq_path,
List *restrictlist);
634 baserel->fdw_private = (
void *) fpinfo;
809 List *useful_eclass_list =
NIL;
824 useful_eclass_list =
lappend(useful_eclass_list, cur_ec);
834 return useful_eclass_list;
851 if (restrictinfo->mergeopfamilies ==
NIL)
882 if (
bms_overlap(relids, restrictinfo->right_ec->ec_relids))
884 restrictinfo->right_ec);
885 else if (
bms_overlap(relids, restrictinfo->left_ec->ec_relids))
887 restrictinfo->left_ec);
890 return useful_eclass_list;
905 List *useful_pathkeys_list =
NIL;
906 List *useful_eclass_list;
918 bool query_pathkeys_ok =
true;
933 query_pathkeys_ok =
false;
938 if (query_pathkeys_ok)
955 return useful_pathkeys_list;
965 query_ec = query_pathkey->pk_eclass;
975 foreach(lc, useful_eclass_list)
981 if (cur_ec == query_ec)
986 OperatorFamilyRelationId, fpinfo))
998 useful_pathkeys_list =
lappend(useful_pathkeys_list,
1002 return useful_pathkeys_list;
1082 required_outer =
bms_union(rinfo->clause_relids,
1097 Assert(param_info != NULL);
1136 if (
arg.current == NULL)
1143 foreach(lc, clauses)
1158 required_outer =
bms_union(rinfo->clause_relids,
1167 Assert(param_info != NULL);
1181 foreach(lc, ppi_list)
1193 &startup_cost, &total_cost);
1236 List *fdw_recheck_quals =
NIL;
1237 List *retrieved_attrs;
1239 bool has_final_sort =
false;
1240 bool has_limit =
false;
1259 scan_relid = foreignrel->
relid;
1280 foreach(lc, scan_clauses)
1285 if (rinfo->pseudoconstant)
1302 fdw_recheck_quals = remote_exprs;
1360 foreach(lc, local_exprs)
1376 Join *join_plan = (
Join *) outer_plan;
1400 has_final_sort, has_limit,
false,
1401 &retrieved_attrs, ¶ms_list);
1414 fdw_private =
lappend(fdw_private,
1454 for (
int i = 0;
i < tupdesc->natts;
i++)
1462 if (att->atttypid != RECORDOID || att->atttypmod >= 0)
1479 att->atttypid = reltype;
1537 fsstate->cursor_exists =
false;
1549 "postgres_fdw tuple data",
1552 "postgres_fdw temporary data",
1566 fsstate->rel = NULL;
1576 fsstate->numParams = numParams;
1581 &fsstate->param_flinfo,
1582 &fsstate->param_exprs,
1583 &fsstate->param_values);
1671 snprintf(sql,
sizeof(sql),
"CLOSE c%u",
1676 snprintf(sql,
sizeof(sql),
"MOVE BACKWARD ALL IN c%u",
1713 if (fsstate == NULL)
1723 fsstate->
conn = NULL;
1763 Index resultRelation,
1771 List *withCheckOptionList =
NIL;
1774 bool doNothing =
false;
1775 int values_end_len = -1;
1808 if (!attr->attisdropped)
1825 elog(
ERROR,
"system-column update is not supported");
1833 if (
plan->withCheckOptionLists)
1840 if (
plan->returningLists)
1852 elog(
ERROR,
"unexpected ON CONFLICT specification: %d",
1853 (
int)
plan->onConflictAction);
1862 targetAttrs, doNothing,
1863 withCheckOptionList, returningList,
1864 &retrieved_attrs, &values_end_len);
1869 withCheckOptionList, returningList,
1878 elog(
ERROR,
"unexpected operation: %d", (
int) operation);
1911 List *retrieved_attrs;
1973 &slot, &planSlot, &numSlots);
1978 return rslot ? *rslot : NULL;
2002 slots, planSlots, numSlots);
2075 if (fmstate && fmstate->
p_nums > 0)
2095 &slot, &planSlot, &numSlots);
2097 return rslot ? rslot[0] : NULL;
2114 &slot, &planSlot, &numSlots);
2116 return rslot ? rslot[0] : NULL;
2130 if (fmstate == NULL)
2148 Index resultRelation;
2157 bool doNothing =
false;
2170 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2171 errmsg(
"cannot route tuples into foreign table to be updated \"%s\"",
2181 if (!attr->attisdropped)
2194 elog(
ERROR,
"unexpected ON CONFLICT specification: %d",
2195 (
int) onConflictAction);
2215 rte->
relkind = RELKIND_FOREIGN_TABLE;
2239 &retrieved_attrs, &values_end_len);
2250 retrieved_attrs !=
NIL,
2318 if (strcmp(def->
defname,
"updatable") == 0)
2325 if (strcmp(def->
defname,
"updatable") == 0)
2435 Index resultRelation,
2473 if (fscan->
scan.plan.qual !=
NIL)
2484 foreignrel = root->simple_rel_array[resultRelation];
2485 rte = root->simple_rte_array[resultRelation];
2502 &processed_tlist, &targetAttrs);
2503 forboth(lc, processed_tlist, lc2, targetAttrs)
2512 elog(
ERROR,
"system-column update is not supported");
2540 if (
plan->returningLists)
2568 remote_exprs, ¶ms_list,
2569 returningList, &retrieved_attrs);
2574 remote_exprs, ¶ms_list,
2575 returningList, &retrieved_attrs);
2578 elog(
ERROR,
"unexpected operation: %d", (
int) operation);
2608 fscan->
scan.plan.lefttree = NULL;
2619 if (fscan->
scan.plan.async_capable)
2620 fscan->
scan.plan.async_capable =
false;
2679 dmstate->resultRel = dmstate->rel;
2687 dmstate->rel = NULL;
2691 dmstate->num_tuples = -1;
2705 "postgres_fdw temporary data",
2709 if (dmstate->has_returning)
2733 dmstate->numParams = numParams;
2738 &dmstate->param_flinfo,
2739 &dmstate->param_exprs,
2740 &dmstate->param_values);
2763 if (!resultRelInfo->ri_projectReturning)
2797 if (dmstate == NULL)
2805 dmstate->
conn = NULL;
2818 List *fdw_private =
plan->fdw_private;
2850 if (isdigit((
unsigned char) *ptr))
2852 int rti = strtol(ptr, &ptr, 10);
2867 if (isdigit((
unsigned char) *ptr))
2869 int rti = strtol(ptr, &ptr, 10);
2893 if (refname == NULL)
2895 if (strcmp(refname,
relname) != 0)
2977 bool server_truncatable =
true;
3003 foreach(cell, server->
options)
3007 if (strcmp(defel->
defname,
"truncatable") == 0)
3022 truncatable = server_truncatable;
3027 if (strcmp(defel->
defname,
"truncatable") == 0)
3036 (
errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
3037 errmsg(
"foreign table \"%s\" does not allow truncates",
3076 List *param_join_conds,
3079 double *p_rows,
int *p_width,
3080 Cost *p_startup_cost,
Cost *p_total_cost)
3084 double retrieved_rows;
3101 List *remote_param_join_conds;
3102 List *local_param_join_conds;
3111 List *retrieved_attrs;
3118 &remote_param_join_conds, &local_param_join_conds);
3124 fdw_scan_tlist =
NIL;
3131 remote_conds =
list_concat(remote_param_join_conds,
3142 remote_conds, pathkeys,
3145 false, &retrieved_attrs, NULL);
3150 &startup_cost, &total_cost);
3153 retrieved_rows = rows;
3157 local_param_join_conds,
3169 startup_cost += local_cost.
startup;
3170 total_cost += local_cost.
per_tuple * retrieved_rows;
3185 startup_cost -= tlist_cost.
startup;
3186 total_cost -= tlist_cost.
startup;
3187 total_cost -= tlist_cost.
per_tuple * rows;
3211 rows = fpinfo->
rows;
3213 width = fpinfo->
width;
3244 rows = foreignrel->
rows;
3254 nrows = fpinfo_i->
rows * fpinfo_o->
rows;
3261 retrieved_rows =
Min(retrieved_rows, nrows);
3284 startup_cost += join_cost.
startup;
3285 startup_cost += remote_conds_cost.
startup;
3305 run_cost += nrows * join_cost.
per_tuple;
3307 run_cost += nrows * remote_conds_cost.
per_tuple;
3321 double numGroups = 1;
3339 input_rows = ofpinfo->
rows;
3343 if (root->
parse->hasAggs)
3353 input_rows, NULL, NULL);
3374 rows = retrieved_rows = numGroups;
3413 startup_cost += remote_cost.
startup;
3414 run_cost += remote_cost.
per_tuple * numGroups;
3429 rows = foreignrel->
rows;
3437 retrieved_rows =
Min(retrieved_rows, foreignrel->
tuples);
3450 run_cost += cpu_per_tuple * foreignrel->
tuples;
3466 if (pathkeys !=
NIL)
3473 retrieved_rows, width,
3475 &startup_cost, &run_cost);
3484 total_cost = startup_cost + run_cost;
3491 retrieved_rows = rows;
3524 if (pathkeys ==
NIL && param_join_conds ==
NIL && fpextra == NULL)
3562 total_cost -= (total_cost - startup_cost) * 0.05 *
3569 *p_startup_cost = startup_cost;
3570 *p_total_cost = total_cost;
3579 double *rows,
int *width,
3580 Cost *startup_cost,
Cost *total_cost)
3604 p = strrchr(line,
'(');
3606 elog(
ERROR,
"could not interpret EXPLAIN output: \"%s\"", line);
3607 n = sscanf(p,
"(cost=%lf..%lf rows=%lf width=%d)",
3608 startup_cost, total_cost, rows, width);
3610 elog(
ERROR,
"could not interpret EXPLAIN output: \"%s\"", line);
3626 double retrieved_rows,
3628 double limit_tuples,
3629 Cost *p_startup_cost,
3648 *p_startup_cost + *p_run_cost,
3667 *p_startup_cost *= sort_multiplier;
3668 *p_run_cost *= sort_multiplier;
3689 if (
state->current != NULL)
3699 state->current = expr;
3753 NULL,
values, NULL, NULL, 0))
3825 snprintf(sql,
sizeof(sql),
"FETCH %d FROM c%u",
3840 for (
i = 0;
i < numrows;
i++)
3964 List *retrieved_attrs)
3993 fmstate->
query = query;
4006 "postgres_fdw temporary data",
4026 elog(
ERROR,
"could not find junk ctid column");
4042 Assert(!attr->attisdropped);
4045 if (attr->attgenerated)
4084 const char **p_values;
4115 fmstate->
query = sql.data;
4148 fmstate->
p_nums * (*numSlots),
4187 return (n_rows > 0) ? slots : NULL;
4207 snprintf(prep_name,
sizeof(prep_name),
"pgsql_fdw_prep_%u",
4237 fmstate->
p_name = p_name;
4249 static const char **
4255 const char **p_values;
4263 p_values = (
const char **)
palloc(
sizeof(
char *) * fmstate->
p_nums * numSlots);
4266 Assert(!(tupleid != NULL && numSlots > 1));
4269 if (tupleid != NULL)
4287 for (
i = 0;
i < numSlots;
i++)
4289 j = (tupleid != NULL) ? 1 : 0;
4298 if (attr->attgenerated)
4302 p_values[pindex] = NULL;
4371 fmstate->
conn = NULL;
4411 bool have_wholerow =
false;
4429 var->
varno == rtindex &&
4432 have_wholerow =
true;
4442 for (
i = 1;
i <= tupdesc->
natts;
i++)
4448 if (attr->attisdropped)
4477 var->
varno == rtindex &&
4512 List *new_tlist = tlist;
4516 foreach(lc, old_tlist)
4523 new_tlist =
lappend(new_tlist,
4564 NULL,
values, NULL, NULL, 0))
4598 Assert(resultRelInfo->ri_projectReturning);
4606 estate->es_processed += 1;
4653 resultRelInfo->ri_projectReturning->pi_exprContext->ecxt_scantuple =
4664 List *fdw_scan_tlist,
4690 foreach(lc, fdw_scan_tlist)
4701 if (var->
varno == rtindex &&
4771 for (
i = 0;
i < resultTupType->
natts;
i++)
4783 isnull[
i] = old_isnull[
j - 1];
4807 resultTup->
t_self = *ctid;
4840 const char ***param_values)
4851 foreach(lc, fdw_exprs)
4873 *param_values = (
const char **)
palloc0(numParams *
sizeof(
char *));
4883 const char **param_values)
4892 foreach(lc, param_exprs)
4899 expr_value =
ExecEvalExpr(expr_state, econtext, &isNull);
4906 param_values[
i] = NULL;
4963 elog(
ERROR,
"unexpected result from deparseAnalyzeSizeSql query");
4992 volatile double reltuples = -1;
4993 volatile char relkind = 0;
4996 *can_tablesample =
false;
5020 elog(
ERROR,
"unexpected result from deparseAnalyzeInfoSql query");
5034 *can_tablesample = (relkind == RELKIND_RELATION ||
5035 relkind == RELKIND_MATVIEW ||
5036 relkind == RELKIND_PARTITIONED_TABLE);
5059 double *totaldeadrows)
5068 double sample_frac = -1.0;
5076 astate.
rel = relation;
5089 "postgres_fdw temporary data",
5111 if (strcmp(def->
defname,
"analyze_sampling") == 0)
5115 if (strcmp(
value,
"off") == 0)
5117 else if (strcmp(
value,
"auto") == 0)
5119 else if (strcmp(
value,
"random") == 0)
5121 else if (strcmp(
value,
"system") == 0)
5123 else if (strcmp(
value,
"bernoulli") == 0)
5134 if (strcmp(def->
defname,
"analyze_sampling") == 0)
5138 if (strcmp(
value,
"off") == 0)
5140 else if (strcmp(
value,
"auto") == 0)
5142 else if (strcmp(
value,
"random") == 0)
5144 else if (strcmp(
value,
"system") == 0)
5146 else if (strcmp(
value,
"bernoulli") == 0)
5161 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
5162 errmsg(
"remote server does not support TABLESAMPLE feature")));
5171 bool can_tablesample;
5188 if ((reltuples <= 0) || (targrows >= reltuples))
5216 sample_frac = targrows / reltuples;
5223 Assert(sample_frac >= 0.0 && sample_frac <= 1.0);
5270 if (strcmp(def->
defname,
"fetch_size") == 0)
5280 if (strcmp(def->
defname,
"fetch_size") == 0)
5288 snprintf(fetch_sql,
sizeof(fetch_sql),
"FETCH %d FROM c%u",
5314 for (
i = 0;
i < numrows;
i++)
5338 *totaldeadrows = 0.0;
5348 *totalrows = reltuples;
5354 (
errmsg(
"\"%s\": table contains %.0f rows, %d rows in sample",
5356 *totalrows, astate.
numrows)));
5380 if (astate->
numrows < targrows)
5399 Assert(pos >= 0 && pos < targrows);
5437 bool import_collate =
true;
5438 bool import_default =
false;
5439 bool import_generated =
true;
5440 bool import_not_null =
true;
5451 foreach(lc,
stmt->options)
5455 if (strcmp(def->
defname,
"import_collate") == 0)
5457 else if (strcmp(def->
defname,
"import_default") == 0)
5459 else if (strcmp(def->
defname,
"import_generated") == 0)
5461 else if (strcmp(def->
defname,
"import_not_null") == 0)
5465 (
errcode(ERRCODE_FDW_INVALID_OPTION_NAME),
5479 import_collate =
false;
5497 (
errcode(ERRCODE_FDW_SCHEMA_NOT_FOUND),
5498 errmsg(
"schema \"%s\" is not present on foreign server \"%s\"",
5527 " format_type(atttypid, atttypmod), "
5529 " pg_get_expr(adbin, adrelid), ");