51 #define DEFAULT_FDW_STARTUP_COST 100.0 54 #define DEFAULT_FDW_TUPLE_COST 0.01 57 #define DEFAULT_FDW_SORT_MULTIPLIER 1.2 334 Index resultRelation,
362 Index resultRelation,
400 List *param_join_conds,
403 double *p_rows,
int *p_width,
404 Cost *p_startup_cost,
Cost *p_total_cost);
413 double retrieved_rows,
416 Cost *p_startup_cost,
446 List *returningList);
451 List *fdw_scan_tlist,
469 double *totaldeadrows);
758 List *useful_eclass_list =
NIL;
773 useful_eclass_list =
lappend(useful_eclass_list, cur_ec);
783 return useful_eclass_list;
839 return useful_eclass_list;
854 List *useful_pathkeys_list =
NIL;
855 List *useful_eclass_list;
867 bool query_pathkeys_ok =
true;
889 query_pathkeys_ok =
false;
894 if (query_pathkeys_ok)
911 return useful_pathkeys_list;
931 foreach(lc, useful_eclass_list)
938 if (cur_ec == query_ec)
951 useful_pathkeys_list =
lappend(useful_pathkeys_list,
955 return useful_pathkeys_list;
1049 Assert(param_info != NULL);
1088 if (arg.current == NULL)
1095 foreach(lc, clauses)
1119 Assert(param_info != NULL);
1126 arg.already_used =
lappend(arg.already_used, arg.current);
1133 foreach(lc, ppi_list)
1145 &startup_cost, &total_cost);
1187 List *fdw_recheck_quals =
NIL;
1190 bool has_final_sort =
false;
1191 bool has_limit =
false;
1210 scan_relid = foreignrel->
relid;
1231 foreach(lc, scan_clauses)
1253 fdw_recheck_quals = remote_exprs;
1313 foreach(lc, local_exprs)
1329 Join *join_plan = (
Join *) outer_plan;
1353 has_final_sort, has_limit,
false,
1367 fdw_private =
lappend(fdw_private,
1427 userid = rte->checkAsUser ? rte->checkAsUser :
GetUserId();
1441 fsstate->cursor_exists =
false;
1453 "postgres_fdw tuple data",
1456 "postgres_fdw temporary data",
1470 fsstate->rel = NULL;
1485 &fsstate->param_flinfo,
1486 &fsstate->param_exprs,
1487 &fsstate->param_values);
1555 snprintf(sql,
sizeof(sql),
"CLOSE c%u",
1560 snprintf(sql,
sizeof(sql),
"MOVE BACKWARD ALL IN c%u",
1597 if (fsstate == NULL)
1606 fsstate->
conn = NULL;
1621 const char *attrname;
1655 Index resultRelation,
1663 List *withCheckOptionList =
NIL;
1666 bool doNothing =
false;
1695 for (attnum = 1; attnum <= tupdesc->
natts; attnum++)
1699 if (!attr->attisdropped)
1715 elog(
ERROR,
"system-column update is not supported");
1742 elog(
ERROR,
"unexpected ON CONFLICT specification: %d",
1752 targetAttrs, doNothing,
1753 withCheckOptionList, returningList,
1759 withCheckOptionList, returningList,
1768 elog(
ERROR,
"unexpected operation: %d", (
int) operation);
1904 if (fmstate == NULL)
1930 bool doNothing =
false;
1944 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1945 errmsg(
"cannot route tuples into foreign table to be updated \"%s\"",
1951 for (attnum = 1; attnum <= tupdesc->
natts; attnum++)
1955 if (!attr->attisdropped)
1968 elog(
ERROR,
"unexpected ON CONFLICT specification: %d",
1969 (
int) onConflictAction);
1986 rte->
relkind = RELKIND_FOREIGN_TABLE;
2013 retrieved_attrs !=
NIL,
2081 if (strcmp(def->
defname,
"updatable") == 0)
2088 if (strcmp(def->
defname,
"updatable") == 0)
2114 Assert(outerPlan != NULL);
2137 Index resultRelation,
2212 elog(
ERROR,
"system-column update is not supported");
2217 elog(
ERROR,
"attribute number %d not found in subplan targetlist",
2274 ((
Plan *) fscan)->targetlist,
2276 remote_exprs, ¶ms_list,
2277 returningList, &retrieved_attrs);
2282 remote_exprs, ¶ms_list,
2283 returningList, &retrieved_attrs);
2286 elog(
ERROR,
"unexpected operation: %d", (
int) operation);
2359 rtindex = estate->es_result_relation_info->ri_RangeTableIndex;
2361 userid = rte->checkAsUser ? rte->checkAsUser :
GetUserId();
2381 dmstate->resultRel = dmstate->rel;
2389 dmstate->rel = NULL;
2393 dmstate->num_tuples = -1;
2407 "postgres_fdw temporary data",
2411 if (dmstate->has_returning)
2440 &dmstate->param_flinfo,
2441 &dmstate->param_exprs,
2442 &dmstate->param_values);
2454 ResultRelInfo *resultRelInfo = estate->es_result_relation_info;
2465 if (!resultRelInfo->ri_projectReturning)
2499 if (dmstate == NULL)
2508 dmstate->
conn = NULL;
2553 if (isdigit((
unsigned char) *ptr))
2555 int rti = strtol(ptr, &ptr, 10);
2570 if (isdigit((
unsigned char) *ptr))
2572 int rti = strtol(ptr, &ptr, 10);
2596 if (refname == NULL)
2598 if (strcmp(refname, relname) != 0)
2677 List *param_join_conds,
2680 double *p_rows,
int *p_width,
2681 Cost *p_startup_cost,
Cost *p_total_cost)
2685 double retrieved_rows;
2702 List *remote_param_join_conds;
2703 List *local_param_join_conds;
2719 &remote_param_join_conds, &local_param_join_conds);
2725 fdw_scan_tlist =
NIL;
2732 remote_conds =
list_concat(remote_param_join_conds,
2743 remote_conds, pathkeys,
2746 false, &retrieved_attrs, NULL);
2751 &startup_cost, &total_cost);
2754 retrieved_rows = rows;
2758 local_param_join_conds,
2770 startup_cost += local_cost.
startup;
2771 total_cost += local_cost.
per_tuple * retrieved_rows;
2786 startup_cost -= tlist_cost.
startup;
2787 total_cost -= tlist_cost.
startup;
2788 total_cost -= tlist_cost.
per_tuple * rows;
2812 rows = fpinfo->
rows;
2814 width = fpinfo->
width;
2845 rows = foreignrel->
rows;
2855 nrows = fpinfo_i->
rows * fpinfo_o->
rows;
2862 retrieved_rows =
Min(retrieved_rows, nrows);
2885 startup_cost += join_cost.
startup;
2886 startup_cost += remote_conds_cost.
startup;
2906 run_cost += nrows * join_cost.
per_tuple;
2908 run_cost += nrows * remote_conds_cost.
per_tuple;
2922 double numGroups = 1;
2940 input_rows = ofpinfo->
rows;
2984 rows = retrieved_rows = numGroups;
3023 startup_cost += remote_cost.
startup;
3024 run_cost += remote_cost.
per_tuple * numGroups;
3039 rows = foreignrel->
rows;
3047 retrieved_rows =
Min(retrieved_rows, foreignrel->
tuples);
3060 run_cost += cpu_per_tuple * foreignrel->
tuples;
3076 if (pathkeys !=
NIL)
3083 retrieved_rows, width,
3085 &startup_cost, &run_cost);
3094 total_cost = startup_cost + run_cost;
3101 retrieved_rows = rows;
3134 if (pathkeys ==
NIL && param_join_conds ==
NIL && fpextra == NULL)
3172 total_cost -= (total_cost - startup_cost) * 0.05 *
3179 *p_startup_cost = startup_cost;
3180 *p_total_cost = total_cost;
3189 double *rows,
int *width,
3190 Cost *startup_cost,
Cost *total_cost)
3214 p = strrchr(line,
'(');
3216 elog(
ERROR,
"could not interpret EXPLAIN output: \"%s\"", line);
3217 n = sscanf(p,
"(cost=%lf..%lf rows=%lf width=%d)",
3218 startup_cost, total_cost, rows, width);
3220 elog(
ERROR,
"could not interpret EXPLAIN output: \"%s\"", line);
3237 double retrieved_rows,
3239 double limit_tuples,
3240 Cost *p_startup_cost,
3259 *p_startup_cost + *p_run_cost,
3278 *p_startup_cost *= sort_multiplier;
3279 *p_run_cost *= sort_multiplier;
3360 NULL,
values, NULL, NULL, 0))
3412 snprintf(sql,
sizeof(sql),
"FETCH %d FROM c%u",
3426 for (i = 0; i < numrows; i++)
3515 snprintf(sql,
sizeof(sql),
"CLOSE c%u", cursor_number);
3580 "postgres_fdw temporary data",
3600 elog(
ERROR,
"could not find junk ctid column");
3616 Assert(!attr->attisdropped);
3647 const char **p_values;
3721 return (n_rows > 0) ? slot : NULL;
3736 snprintf(prep_name,
sizeof(prep_name),
"pgsql_fdw_prep_%u",
3766 fmstate->
p_name = p_name;
3778 static const char **
3783 const char **p_values;
3789 p_values = (
const char **)
palloc(
sizeof(
char *) * fmstate->
p_nums);
3792 if (tupleid != NULL)
3816 p_values[pindex] = NULL;
3900 fmstate->
conn = NULL;
3911 bool have_wholerow =
false;
3929 var->
varno == rtindex &&
3932 have_wholerow =
true;
3942 for (i = 1; i <= tupdesc->
natts; i++)
3948 if (attr->attisdropped)
3977 var->
varno == rtindex &&
4012 List *new_tlist = tlist;
4016 foreach(lc, old_tlist)
4023 new_tlist =
lappend(new_tlist,
4060 NULL,
values, NULL, NULL, 0))
4090 ResultRelInfo *resultRelInfo = estate->es_result_relation_info;
4094 Assert(resultRelInfo->ri_projectReturning);
4102 estate->es_processed += 1;
4150 resultRelInfo->ri_projectReturning->pi_exprContext->ecxt_scantuple =
4161 List *fdw_scan_tlist,
4187 foreach(lc, fdw_scan_tlist)
4198 if (var->
varno == rtindex &&
4268 for (i = 0; i < resultTupType->
natts; i++)
4279 values[
i] = old_values[j - 1];
4280 isnull[
i] = old_isnull[j - 1];
4304 resultTup->
t_self = *ctid;
4348 foreach(lc, fdw_exprs)
4355 fmgr_info(typefnoid, &(*param_flinfo)[i]);
4370 *param_values = (
const char **)
palloc0(numParams *
sizeof(
char *));
4389 foreach(lc, param_exprs)
4396 expr_value =
ExecEvalExpr(expr_state, econtext, &isNull);
4403 param_values[
i] = NULL;
4460 elog(
ERROR,
"unexpected result from deparseAnalyzeSizeSql query");
4461 *totalpages = strtoul(
PQgetvalue(res, 0, 0), NULL, 10);
4495 double *totaldeadrows)
4507 astate.
rel = relation;
4520 "postgres_fdw temporary data",
4562 if (strcmp(def->
defname,
"fetch_size") == 0)
4572 if (strcmp(def->
defname,
"fetch_size") == 0)
4580 snprintf(fetch_sql,
sizeof(fetch_sql),
"FETCH %d FROM c%u",
4581 fetch_size, cursor_number);
4606 for (i = 0; i < numrows; i++)
4613 if (numrows < fetch_size)
4631 *totaldeadrows = 0.0;
4640 (
errmsg(
"\"%s\": table contains %.0f rows, %d rows in sample",
4666 if (astate->
numrows < targrows)
4685 Assert(pos >= 0 && pos < targrows);
4723 bool import_collate =
true;
4724 bool import_default =
false;
4725 bool import_not_null =
true;
4740 if (strcmp(def->
defname,
"import_collate") == 0)
4742 else if (strcmp(def->
defname,
"import_default") == 0)
4744 else if (strcmp(def->
defname,
"import_not_null") == 0)
4748 (
errcode(ERRCODE_FDW_INVALID_OPTION_NAME),
4762 import_collate =
false;
4780 (
errcode(ERRCODE_FDW_SCHEMA_NOT_FOUND),
4781 errmsg(
"schema \"%s\" is not present on foreign server \"%s\"",
4809 " format_type(atttypid, atttypmod), " 4811 " pg_get_expr(adbin, adrelid), " 4815 " JOIN pg_namespace n ON " 4816 " relnamespace = n.oid " 4817 " LEFT JOIN pg_attribute a ON " 4818 " attrelid = c.oid AND attnum > 0 " 4819 " AND NOT attisdropped " 4820 " LEFT JOIN pg_attrdef ad ON " 4821 " adrelid = c.oid AND adnum = attnum " 4822 " LEFT JOIN pg_collation coll ON " 4823 " coll.oid = attcollation " 4824 " LEFT JOIN pg_namespace collnsp ON " 4825 " collnsp.oid = collnamespace ");
4830 " format_type(atttypid, atttypmod), " 4832 " pg_get_expr(adbin, adrelid), " 4835 " JOIN pg_namespace n ON " 4836 " relnamespace = n.oid " 4837 " LEFT JOIN pg_attribute a ON " 4838 " attrelid = c.oid AND attnum > 0 " 4839 " AND NOT attisdropped " 4840 " LEFT JOIN pg_attrdef ad ON " 4841 " adrelid = c.oid AND adnum = attnum ");
4844 "WHERE c.relkind IN (" 4850 " AND n.nspname = ");
4861 bool first_item =
true;
4893 for (i = 0; i < numrows;)
4896 bool first_item =
true;
4910 char *collnamespace;
4919 attdefault =
PQgetisnull(res, i, 4) ? (
char *) NULL :
4921 collname =
PQgetisnull(res, i, 5) ? (
char *) NULL :
4923 collnamespace =
PQgetisnull(res, i, 6) ? (
char *) NULL :
4946 if (import_collate && collname != NULL && collnamespace != NULL)
4952 if (import_default && attdefault != NULL)
4956 if (import_not_null && attnotnull[0] ==
't')
4959 while (++i < numrows &&
4960 strcmp(
PQgetvalue(res, i, 0), tablename) == 0);
5070 if (!is_remote_clause)
5072 joinclauses =
lappend(joinclauses, rinfo);
5076 if (is_remote_clause)
5197 elog(
ERROR,
"unsupported join type %d", jointype);
5224 fpinfo->
user = NULL;
5263 List *useful_pathkeys_list =
NIL;
5269 foreach(lc, useful_pathkeys_list)
5276 Path *sorted_epq_path;
5279 &rows, &width, &startup_cost, &total_cost);
5285 sorted_epq_path = epq_path;
5286 if (sorted_epq_path != NULL &&
5289 sorted_epq_path = (
Path *)
5335 if (strcmp(def->
defname,
"use_remote_estimate") == 0)
5337 else if (strcmp(def->
defname,
"fdw_startup_cost") == 0)
5339 else if (strcmp(def->
defname,
"fdw_tuple_cost") == 0)
5341 else if (strcmp(def->
defname,
"extensions") == 0)
5344 else if (strcmp(def->
defname,
"fetch_size") == 0)
5363 if (strcmp(def->
defname,
"use_remote_estimate") == 0)
5365 else if (strcmp(def->
defname,
"fetch_size") == 0)
5489 elog(
DEBUG3,
"could not push down foreign join because a local path suitable for EPQ checks was not found");
5496 if (!
foreign_join_ok(root, joinrel, jointype, outerrel, innerrel, extra))
5530 &rows, &width, &startup_cost, &total_cost);
5532 joinrel->
rows = rows;
5534 fpinfo->
rows = rows;
5535 fpinfo->
width = width;
5592 if (ofpinfo->local_conds)
5612 foreach(lc, grouping_target->exprs)