From 3bdceb6f403aa0d61a890f2a489ab974c5b3e4d2 Mon Sep 17 00:00:00 2001 From: wangfeihuo Date: Tue, 2 Jul 2024 19:36:36 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E4=B8=80=E4=B8=AAcursor=20ex?= =?UTF-8?q?pression=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/common/backend/parser/parse_expr.cpp | 5 +- src/gausskernel/runtime/executor/execQual.cpp | 9 ++ .../regress/expected/cursor_expression.out | 100 ++++++++++++++++++ src/test/regress/sql/cursor_expression.sql | 44 ++++++++ 4 files changed, 155 insertions(+), 3 deletions(-) diff --git a/src/common/backend/parser/parse_expr.cpp b/src/common/backend/parser/parse_expr.cpp index 681cf44c5..7a55479be 100644 --- a/src/common/backend/parser/parse_expr.cpp +++ b/src/common/backend/parser/parse_expr.cpp @@ -3831,9 +3831,8 @@ static Node* transformCursorExpression(ParseState* pstate, CursorExpression* cur int nParamExec = 0; parse_state_temp = parse_state_parent; - while (parse_state_temp != NULL) { - nParamExec += list_length(parse_state_temp->cursor_expression_para_var); - parse_state_temp = parse_state_temp->parentParseState; + if (parse_state_temp != NULL) { + nParamExec = list_length(parse_state_temp->cursor_expression_para_var); } plan_tree->nParamExec = nParamExec; diff --git a/src/gausskernel/runtime/executor/execQual.cpp b/src/gausskernel/runtime/executor/execQual.cpp index 69e631247..ba8a50db3 100644 --- a/src/gausskernel/runtime/executor/execQual.cpp +++ b/src/gausskernel/runtime/executor/execQual.cpp @@ -5705,6 +5705,15 @@ static Datum ExecEvalCursorExpression(CursorExpressionState* state, ExprContext* PortalStart(portal, econtext->ecxt_param_list_info, 0, GetActiveSnapshot()); int plan_param_number = ((PlannedStmt*)(cursor_expression->plan))->nParamExec; + int state_param_number = list_length(state->param); + + if (unlikely(plan_param_number > state_param_number)) { + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmodule(MOD_EXECUTOR), + errmsg("The expected number of parameters is %d, but actual is %d.", plan_param_number, state_param_number))); + } + for (int i = 0; i < plan_param_number; i++) { bool expr_is_null = false; ParamExecData* prm = &(portal->queryDesc->estate->es_param_exec_vals[i]); diff --git a/src/test/regress/expected/cursor_expression.out b/src/test/regress/expected/cursor_expression.out index 6b3a59b67..576fa2789 100644 --- a/src/test/regress/expected/cursor_expression.out +++ b/src/test/regress/expected/cursor_expression.out @@ -804,7 +804,107 @@ NOTICE: last_name : heliu (1 row) drop procedure test_cursor_2; +-- +create table t_cursor_0011_01(department_id int, department_name varchar(50)); +create table t_cursor_0011_02(employees_id int, department_id int, first_name varchar(50), last_name varchar(50), email varchar(50), phone_number int); +insert into t_cursor_0011_01 values (1, 'sale'),(2, 'rd'),(3, 'pro'); +insert into t_cursor_0011_01 values (1, 'sale'),(2, 'rd'),(3, 'pro');; +insert into t_cursor_0011_02 values (1, 1, 'zhang', 'san', '1@abc.com', 123),(2, 1, 'li', 'si', '2@abc.com', 124); +insert into t_cursor_0011_02 values (1, 2, 'wang', 'wu', '3@abc.com', 321),(2, 2, 'he', 'liu', '4@abc.com', 421); +create or replace procedure pro_cursor_0011_02 +as + company_name varchar(100); + department_name varchar(100); + employees_id_var int; + name_var varchar(100); + type ref_cur_type is ref cursor; + my_cur ref_cur_type; + my_cur2 ref_cur_type; + cursor c1 is select department_id, cursor(select department_name, cursor(select department_id ) from t_cursor_0011_02) from t_cursor_0011_01 d order by department_name; +begin + open c1; + loop + fetch c1 into department_name, my_cur; + exit when c1%notfound; + raise notice 'department_name : % %',department_name, my_cur; + loop + fetch my_cur into name_var, my_cur2; + exit when my_cur%notfound; + raise notice ' department employees info : % %',name_var, my_cur2; + loop + fetch my_cur2 into employees_id_var; + exit when my_cur2%notfound; + raise notice ' employees_id_var : %',employees_id_var; + end loop; + end loop; + close my_cur; + end loop; +end; +/ +call pro_cursor_0011_02(); +NOTICE: department_name : 3 +NOTICE: department employees info : pro +NOTICE: employees_id_var : 1 +NOTICE: department employees info : pro +NOTICE: employees_id_var : 1 +NOTICE: department employees info : pro +NOTICE: employees_id_var : 2 +NOTICE: department employees info : pro +NOTICE: employees_id_var : 2 +NOTICE: department_name : 3 +NOTICE: department employees info : pro +NOTICE: employees_id_var : 1 +NOTICE: department employees info : pro +NOTICE: employees_id_var : 1 +NOTICE: department employees info : pro +NOTICE: employees_id_var : 2 +NOTICE: department employees info : pro +NOTICE: employees_id_var : 2 +NOTICE: department_name : 2 +NOTICE: department employees info : rd +NOTICE: employees_id_var : 1 +NOTICE: department employees info : rd +NOTICE: employees_id_var : 1 +NOTICE: department employees info : rd +NOTICE: employees_id_var : 2 +NOTICE: department employees info : rd +NOTICE: employees_id_var : 2 +NOTICE: department_name : 2 +NOTICE: department employees info : rd +NOTICE: employees_id_var : 1 +NOTICE: department employees info : rd +NOTICE: employees_id_var : 1 +NOTICE: department employees info : rd +NOTICE: employees_id_var : 2 +NOTICE: department employees info : rd +NOTICE: employees_id_var : 2 +NOTICE: department_name : 1 +NOTICE: department employees info : sale +NOTICE: employees_id_var : 1 +NOTICE: department employees info : sale +NOTICE: employees_id_var : 1 +NOTICE: department employees info : sale +NOTICE: employees_id_var : 2 +NOTICE: department employees info : sale +NOTICE: employees_id_var : 2 +NOTICE: department_name : 1 +NOTICE: department employees info : sale +NOTICE: employees_id_var : 1 +NOTICE: department employees info : sale +NOTICE: employees_id_var : 1 +NOTICE: department employees info : sale +NOTICE: employees_id_var : 2 +NOTICE: department employees info : sale +NOTICE: employees_id_var : 2 + pro_cursor_0011_02 +-------------------- + +(1 row) + -- clean +drop procedure pro_cursor_0011_02; +drop table t_cursor_0011_01; +drop table t_cursor_0011_02; drop table res_count1; drop table employees; drop table departments; diff --git a/src/test/regress/sql/cursor_expression.sql b/src/test/regress/sql/cursor_expression.sql index 6e5b1447a..6412a9e29 100644 --- a/src/test/regress/sql/cursor_expression.sql +++ b/src/test/regress/sql/cursor_expression.sql @@ -481,7 +481,51 @@ call test_cursor_2(); drop procedure test_cursor_2; +-- +create table t_cursor_0011_01(department_id int, department_name varchar(50)); +create table t_cursor_0011_02(employees_id int, department_id int, first_name varchar(50), last_name varchar(50), email varchar(50), phone_number int); + +insert into t_cursor_0011_01 values (1, 'sale'),(2, 'rd'),(3, 'pro'); +insert into t_cursor_0011_01 values (1, 'sale'),(2, 'rd'),(3, 'pro');; +insert into t_cursor_0011_02 values (1, 1, 'zhang', 'san', '1@abc.com', 123),(2, 1, 'li', 'si', '2@abc.com', 124); +insert into t_cursor_0011_02 values (1, 2, 'wang', 'wu', '3@abc.com', 321),(2, 2, 'he', 'liu', '4@abc.com', 421); + +create or replace procedure pro_cursor_0011_02 +as + company_name varchar(100); + department_name varchar(100); + employees_id_var int; + name_var varchar(100); + type ref_cur_type is ref cursor; + my_cur ref_cur_type; + my_cur2 ref_cur_type; + cursor c1 is select department_id, cursor(select department_name, cursor(select department_id ) from t_cursor_0011_02) from t_cursor_0011_01 d order by department_name; +begin + open c1; + loop + fetch c1 into department_name, my_cur; + exit when c1%notfound; + raise notice 'department_name : % %',department_name, my_cur; + loop + fetch my_cur into name_var, my_cur2; + exit when my_cur%notfound; + raise notice ' department employees info : % %',name_var, my_cur2; + loop + fetch my_cur2 into employees_id_var; + exit when my_cur2%notfound; + raise notice ' employees_id_var : %',employees_id_var; + end loop; + end loop; + close my_cur; + end loop; +end; +/ +call pro_cursor_0011_02(); + -- clean +drop procedure pro_cursor_0011_02; +drop table t_cursor_0011_01; +drop table t_cursor_0011_02; drop table res_count1; drop table employees; drop table departments;