Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ADBDEV-6808: Fix initplan functions returning NULL. #1141

Merged
merged 8 commits into from
Dec 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 63 additions & 2 deletions src/backend/optimizer/plan/createplan.c
Original file line number Diff line number Diff line change
Expand Up @@ -1970,6 +1970,8 @@ pathtarget_contains_rowidexpr(PathTarget *pathtarget)
return false;
}

static bool is_function_scan_on_initplan(PlannerInfo *root, Path *best_path);

/*
* create_projection_plan
*
Expand Down Expand Up @@ -2026,8 +2028,8 @@ create_projection_plan(PlannerInfo *root, ProjectionPath *best_path, int flags)
* Tell create_plan_recurse that we're going to ignore the tlist it
* produces.
*/
subplan = create_plan_recurse(root, best_path->subpath,
CP_IGNORE_TLIST);
int subplan_flags = is_function_scan_on_initplan(root, best_path->subpath) ? 0 : CP_IGNORE_TLIST;
subplan = create_plan_recurse(root, best_path->subpath, subplan_flags);
Assert(is_projection_capable_plan(subplan));
tlist = build_path_tlist(root, &best_path->path);
bimboterminator1 marked this conversation as resolved.
Show resolved Hide resolved
}
Expand Down Expand Up @@ -8205,6 +8207,65 @@ cdbpathtoplan_create_motion_plan(PlannerInfo *root,
return motion;
} /* cdbpathtoplan_create_motion_plan */

/*
* is_function_scan_on_initplan
*
* CDB: gpdb specific function to check if a function scan should be executed on an initplan.
*/
static bool
is_function_scan_on_initplan(PlannerInfo *root, Path *best_path) {
Index scan_relid = best_path->parent->relid;
RangeTblEntry *rte;
RangeTblFunction *rtfunc;
FuncExpr *funcexpr;
char exec_location;

if (best_path->pathtype != T_FunctionScan)
return false;

/*
* In utility mode (or when planning a local query in QE), ignore EXECUTE
* ON markings and run the function the normal way.
*/
if (Gp_role != GP_ROLE_DISPATCH)
return false;

/* Current function scan is already in an initplan, do nothing. */
if (!get_allow_append_initplan_for_function_scan())
return false;

/*
* If INITPLAN function is executed on QD, there is no
* need to add additional initplan to run this function.
* Recall that the reason to introduce INITPLAN function
* is that function runing on QE can not do dispatch.
*/
if (root->curSlice->parentIndex == -1)
return false;

/* it should be a function base rel... */
Assert(scan_relid > 0);
rte = planner_rt_fetch(scan_relid, root);
Assert(rte->rtekind == RTE_FUNCTION);

/* Currently we limit function number to one */
if (list_length(rte->functions) != 1)
return false;

rtfunc = (RangeTblFunction *) linitial(rte->functions);

if (!IsA(rtfunc->funcexpr, FuncExpr))
return false;

/* function must be specified EXECUTE ON INITPLAN */
funcexpr = (FuncExpr *) rtfunc->funcexpr;
exec_location = func_exec_location(funcexpr->funcid);
if (exec_location != PROEXECLOCATION_INITPLAN)
return false;

return true;
}

/*
* append_initplan_for_function_scan
*
Expand Down
19 changes: 19 additions & 0 deletions src/test/regress/expected/function_extensions.out
Original file line number Diff line number Diff line change
Expand Up @@ -577,3 +577,22 @@ select array(select f from hello_initplan() as f);
{hello}
(1 row)

-- Test INITPLAN functions with projections
DROP TABLE IF EXISTS t8_function_scan;
-- should succeed and add 3 rows with IDs (112, 223, 334)
CREATE TABLE t8_function_scan AS SELECT country_id+1 AS a, country FROM get_country();
-- should succeed and add 3 rows with IDs (113, 224, 335)
INSERT INTO t8_function_scan SELECT country_id+2 AS a, country FROM get_country();
-- should have 6 rows without any NULL entries
SELECT * FROM t8_function_scan ORDER BY a;
a | country
-----+---------
112 | INDIA
113 | INDIA
223 | CANADA
224 | CANADA
334 | USA
335 | USA
(6 rows)

DROP TABLE t8_function_scan;
19 changes: 19 additions & 0 deletions src/test/regress/expected/function_extensions_optimizer.out
Original file line number Diff line number Diff line change
Expand Up @@ -578,3 +578,22 @@ select array(select f from hello_initplan() as f);
{hello}
(1 row)

-- Test INITPLAN functions with projections
DROP TABLE IF EXISTS t8_function_scan;
-- should succeed and add 3 rows with IDs (112, 223, 334)
CREATE TABLE t8_function_scan AS SELECT country_id+1 AS a, country FROM get_country();
-- should succeed and add 3 rows with IDs (113, 224, 335)
INSERT INTO t8_function_scan SELECT country_id+2 AS a, country FROM get_country();
-- should have 6 rows without any NULL entries
SELECT * FROM t8_function_scan ORDER BY a;
a | country
-----+---------
112 | INDIA
113 | INDIA
223 | CANADA
224 | CANADA
334 | USA
335 | USA
(6 rows)

DROP TABLE t8_function_scan;
10 changes: 9 additions & 1 deletion src/test/regress/sql/function_extensions.sql
Original file line number Diff line number Diff line change
Expand Up @@ -298,5 +298,13 @@ execute on initplan;
explain select array(select f from hello_initplan() as f);
select array(select f from hello_initplan() as f);


-- Test INITPLAN functions with projections
bimboterminator1 marked this conversation as resolved.
Show resolved Hide resolved
DROP TABLE IF EXISTS t8_function_scan;
-- should succeed and add 3 rows with IDs (112, 223, 334)
CREATE TABLE t8_function_scan AS SELECT country_id+1 AS a, country FROM get_country();
-- should succeed and add 3 rows with IDs (113, 224, 335)
INSERT INTO t8_function_scan SELECT country_id+2 AS a, country FROM get_country();
-- should have 6 rows without any NULL entries
SELECT * FROM t8_function_scan ORDER BY a;
RekGRpth marked this conversation as resolved.
Show resolved Hide resolved
DROP TABLE t8_function_scan;
hilltracer marked this conversation as resolved.
Show resolved Hide resolved

Loading