diff --git a/src/common/pl/plpgsql/src/gram.y b/src/common/pl/plpgsql/src/gram.y index b67416ac8..1c68a20e0 100755 --- a/src/common/pl/plpgsql/src/gram.y +++ b/src/common/pl/plpgsql/src/gram.y @@ -1508,14 +1508,20 @@ decl_statement : decl_varname_list decl_const decl_datatype decl_collate decl_no | K_TYPE decl_varname as_is K_VARRAY '(' ICONST ')' K_OF varray_var ';' { - ereport(errstate, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmodule(MOD_PLSQL), - errmsg("array type nested by array is not supported yet."), - errdetail("Define array type \"%s\" of array is not supported yet.", $2->name), - errcause("feature not supported"), - erraction("check define of array type"))); - u_sess->plsql_cxt.have_error = true; + IsInPublicNamespace($2->name); + PLpgSQL_var *check_var = (PLpgSQL_var *)u_sess->plsql_cxt.curr_compile_context->plpgsql_Datums[$9]; + /* get and check nest tableof's depth */ + int depth = get_nest_tableof_layer(check_var, $2->name, errstate); + PLpgSQL_type *nest_type = plpgsql_build_nested_datatype(); + nest_type->tableOfIndexType = INT4OID; + nest_type->collectionType = PLPGSQL_COLLECTION_ARRAY; + PLpgSQL_var* var = (PLpgSQL_var*)plpgsql_build_varrayType($2->name, $2->lineno, nest_type, true); + /* nested table type */ + var->nest_table = (PLpgSQL_var *)u_sess->plsql_cxt.curr_compile_context->plpgsql_Datums[$9]; + var->nest_layers = depth; + var->isIndexByTblOf = false; + pfree_ext($2->name); + pfree($2); } | K_TYPE decl_varname as_is K_VARRAY '(' ICONST ')' K_OF table_var ';' @@ -1552,6 +1558,8 @@ decl_statement : decl_varname_list decl_const decl_datatype decl_collate decl_no IsInPublicNamespace(varname->name); PLpgSQL_type *var_type = ((PLpgSQL_var *)u_sess->plsql_cxt.curr_compile_context->plpgsql_Datums[$3])->datatype; + PLpgSQL_var *varray_type = (PLpgSQL_var *)u_sess->plsql_cxt.curr_compile_context->plpgsql_Datums[$3]; + PLpgSQL_var *newp; PLpgSQL_type *new_var_type; @@ -1571,6 +1579,10 @@ decl_statement : decl_varname_list decl_const decl_datatype decl_collate decl_no errmsg("build variable failed"))); u_sess->plsql_cxt.have_error = true; } + if (varray_type->nest_table != NULL) { + newp->nest_table = plpgsql_build_nested_variable(varray_type->nest_table, $2, varname->name, varname->lineno); + newp->nest_layers = varray_type->nest_layers; + } pfree_ext(varname->name); } list_free_deep($1); diff --git a/src/common/pl/plpgsql/src/pl_exec.cpp b/src/common/pl/plpgsql/src/pl_exec.cpp index 28f295b0e..d19feebb8 100644 --- a/src/common/pl/plpgsql/src/pl_exec.cpp +++ b/src/common/pl/plpgsql/src/pl_exec.cpp @@ -10506,7 +10506,8 @@ static void evalSubscriptList(PLpgSQL_execstate* estate, const List* subscripts, estate->eval_tuptable = NULL; if (*target != NULL && (*target)->dtype == PLPGSQL_DTYPE_VAR && - ((PLpgSQL_var*)(*target))->datatype->collectionType == PLPGSQL_COLLECTION_TABLE) { + (((PLpgSQL_var*)(*target))->datatype->collectionType == PLPGSQL_COLLECTION_TABLE || + ((PLpgSQL_var*)(*target))->datatype->collectionType == PLPGSQL_COLLECTION_ARRAY)) { int tableof_level = 0; char* valname = ((PLpgSQL_var*)(*target))->refname; PLpgSQL_expr* subexprs[nsubscripts]; diff --git a/src/test/regress/expected/plpgsql_array_opengauss.out b/src/test/regress/expected/plpgsql_array_opengauss.out index 9f0cc8ee3..f4e22ec76 100644 --- a/src/test/regress/expected/plpgsql_array_opengauss.out +++ b/src/test/regress/expected/plpgsql_array_opengauss.out @@ -124,7 +124,7 @@ end; ERROR: mismatched parentheses at or near ";" LINE 12: insert into tmp values (null, name_list(1]); ^ -QUERY: DECLARE cursor c_customers is (select c_name from customers order by id); +QUERY: DECLARE cursor c_customers is (select c_name from customers order by id); type c_list is varray(6) of customers.c_name%type; name_list c_list := c_list(); counter integer := 0; @@ -302,7 +302,7 @@ end; ERROR: mismatched parentheses at or near ";" LINE 6: insert into tmp values (null, names(i]); ^ -QUERY: DECLARE type students is varray(5) of varchar2(10); +QUERY: DECLARE type students is varray(5) of varchar2(10); names students; begin names := students(1, 'Zera ', 'Alice', 'Jim ', 'Kevin'); -- should be able read all values correctly -- @@ -498,9 +498,12 @@ begin insert into tmp values (null, mat(1)(2)); end; / -ERROR: array type nested by array is not supported yet. -DETAIL: Define array type "arraysecond" of array is not supported yet. -CONTEXT: compilation of PL/pgSQL function "inline_code_block" near line 3 +ERROR: cannot cast type integer[] to integer +LINE 1: SELECT ARRAY[(arr)::pg_catalog."int4", (arr)::pg_catalog."in... + ^ +QUERY: SELECT ARRAY[(arr)::pg_catalog."int4", (arr)::pg_catalog."int4"] +CONTEXT: referenced column: array +PL/pgSQL function inline_code_block line 5 during statement block local variable initialization select * from tmp order by 1, 2; a | b ---+--- diff --git a/src/test/regress/expected/plpgsql_nested_array_and_record.out b/src/test/regress/expected/plpgsql_nested_array_and_record.out new file mode 100644 index 000000000..421535daf --- /dev/null +++ b/src/test/regress/expected/plpgsql_nested_array_and_record.out @@ -0,0 +1,90 @@ +-- check compatibility -- +show sql_compatibility; -- expect A -- + sql_compatibility +------------------- + A +(1 row) + +DROP SCHEMA IF EXISTS plpgsql_nested_array_and_record CASCADE; +NOTICE: schema "plpgsql_nested_array_and_record" does not exist, skipping +CREATE SCHEMA plpgsql_nested_array_and_record; +SET current_schema = plpgsql_nested_array_and_record; +-- array of arrays +DECLARE + TYPE arr1 IS VARRAY(5) OF INTEGER; + TYPE arr2 IS VARRAY(5) OF arr1; + nst_arr arr2; +BEGIN + FOR I IN 1..5 LOOP + nst_arr(1)(I) := I; + RAISE NOTICE 'RESULT: %', nst_arr(1)(I); + END LOOP; +END; +/ +NOTICE: RESULT: 1 +NOTICE: RESULT: 2 +NOTICE: RESULT: 3 +NOTICE: RESULT: 4 +NOTICE: RESULT: 5 +-- record of arrays +DECLARE + TYPE arr1 IS VARRAY(5) OF INTEGER; + TYPE rec1 IS RECORD(id int, arrarg arr1); + arr_rec rec1; +BEGIN + FOR I IN 1..5 LOOP + arr_rec.arrarg(I):=I; + RAISE NOTICE 'RESULT: %', arr_rec.arrarg(I); + END LOOP; +END; +/ +NOTICE: RESULT: 1 +NOTICE: RESULT: 2 +NOTICE: RESULT: 3 +NOTICE: RESULT: 4 +NOTICE: RESULT: 5 +-- array of records +CREATE OR REPLACE PROCEDURE test_nested AS +DECLARE + TYPE rec1 IS RECORD(id int, name char(10)); + TYPE arr1 IS VARRAY(5) OF rec1; + rec_arr arr1; +BEGIN + FOR I IN 1..5 LOOP + rec_arr(I).id := I; + RAISE NOTICE 'RESULT: %', rec_arr(I).id; + END LOOP; +END; +/ +CALL test_nested(); +NOTICE: RESULT: 1 +NOTICE: RESULT: 2 +NOTICE: RESULT: 3 +NOTICE: RESULT: 4 +NOTICE: RESULT: 5 + test_nested +------------- + +(1 row) + +-- record of records +CREATE OR REPLACE PROCEDURE test_nested AS +DECLARE + TYPE rec1 IS RECORD(id int, name char(10)); + TYPE rec2 IS RECORD(id int, recarg rec1); + recrec rec2; +BEGIN + recrec.recarg.id := 1; + recrec.recarg.name := 'RECORD'; + RAISE NOTICE 'ID: %, NAME: %', recrec.recarg.id, recrec.recarg.name; +END; +/ +CALL test_nested(); +NOTICE: ID: 1, NAME: RECORD + test_nested +------------- + +(1 row) + +DROP SCHEMA plpgsql_nested_array_and_record CASCADE; +NOTICE: drop cascades to function test_nested() diff --git a/src/test/regress/expected/plpgsql_package_type.out b/src/test/regress/expected/plpgsql_package_type.out index ed631fcff..a49c27623 100644 --- a/src/test/regress/expected/plpgsql_package_type.out +++ b/src/test/regress/expected/plpgsql_package_type.out @@ -434,9 +434,6 @@ type t1 is varray(10) of int; type t2 is varray(10) of t1; end pck1; / -ERROR: array type nested by array is not supported yet. -DETAIL: Define array type "t2" of array is not supported yet. -CONTEXT: compilation of PL/pgSQL package near line 3 create or replace function func1() return int as type t1 is varray(10) of int; type t2 is varray(10) of t1; @@ -444,9 +441,6 @@ begin return 0; end; / -ERROR: array type nested by array is not supported yet. -DETAIL: Define array type "t2" of array is not supported yet. -CONTEXT: compilation of PL/pgSQL function "func1" near line 2 -- 2. table nest array create or replace package pck1 as type t1 is varray(10) of int; @@ -500,7 +494,6 @@ CONTEXT: compilation of PL/pgSQL function "func1" near line 2 -- / -- 5. record nest ref cursor drop package if exists pck1; -NOTICE: package pck1() does not exist, skipping create or replace package pck1 as type t1 is ref cursor; type t2 is record(c1 t1,c2 int); @@ -560,7 +553,6 @@ CONTEXT: compilation of PL/pgSQL function "func1" near line 2 DROP package pck1; ERROR: package pck1 does not exist DROP function func1(); -ERROR: function func1 does not exist -- 8.package nest create or replace package pck1 as type t1 is table of int; diff --git a/src/test/regress/parallel_schedule0 b/src/test/regress/parallel_schedule0 index ad1f3650a..990838a66 100644 --- a/src/test/regress/parallel_schedule0 +++ b/src/test/regress/parallel_schedule0 @@ -776,7 +776,7 @@ test: select_where_func test: arrayinterface_single test: plpgsql_table_opengauss test: plpgsql_assign_value_to_array_attribute -test: plpgsql_array_of_record +test: plpgsql_array_of_record #test: plpgsql_nest_compile test: arrayinterface_ted test: function_default_test plpgsql_inout_param record_slow_sql_in_proc @@ -787,7 +787,7 @@ test: plpgsql_record_attrname test: plpgsql_insert_record plpgsql_condition_name test: hw_package_variable package_typmod_test test: autonomous_cursor -test: plpgsql_reset_session +test: plpgsql_reset_session plpgsql_nested_array_and_record #test: plpgsql_depend test: plpgsql_depend/plpgsql_depend_type plpgsql_depend/plpgsql_pkg_dependency plpgsql_depend/plpgsql_recompile plpgsql_depend/plpgsql_pkg_variable_dependency plpgsql_depend/plpgsql_depend_reftype #test: plancache limit rangefuncs prepare diff --git a/src/test/regress/parallel_schedule0B b/src/test/regress/parallel_schedule0B index a0db5c345..fdbd2e30b 100644 --- a/src/test/regress/parallel_schedule0B +++ b/src/test/regress/parallel_schedule0B @@ -280,7 +280,7 @@ test: select_where_func test: arrayinterface_single test: plpgsql_table_opengauss test: plpgsql_assign_value_to_array_attribute -test: plpgsql_array_of_record +test: plpgsql_array_of_record #test: plpgsql_nest_compile test: arrayinterface_ted test: function_default_test plpgsql_inout_param @@ -291,7 +291,7 @@ test: plpgsql_record_attrname test: plpgsql_insert_record plpgsql_condition_name test: hw_package_variable package_typmod_test test: autonomous_cursor -test: plpgsql_reset_session +test: plpgsql_reset_session plpgsql_nested_array_and_record #test: plpgsql_depend test: plpgsql_depend/plpgsql_depend_type plpgsql_depend/plpgsql_pkg_dependency plpgsql_depend/plpgsql_recompile plpgsql_depend/plpgsql_pkg_variable_dependency plpgsql_depend/plpgsql_depend_reftype #test: plancache limit rangefuncs prepare diff --git a/src/test/regress/sql/plpgsql_nested_array_and_record.sql b/src/test/regress/sql/plpgsql_nested_array_and_record.sql new file mode 100644 index 000000000..da1bf741e --- /dev/null +++ b/src/test/regress/sql/plpgsql_nested_array_and_record.sql @@ -0,0 +1,63 @@ +-- check compatibility -- +show sql_compatibility; -- expect A -- + +DROP SCHEMA IF EXISTS plpgsql_nested_array_and_record CASCADE; +CREATE SCHEMA plpgsql_nested_array_and_record; +SET current_schema = plpgsql_nested_array_and_record; + +-- array of arrays +DECLARE + TYPE arr1 IS VARRAY(5) OF INTEGER; + TYPE arr2 IS VARRAY(5) OF arr1; + nst_arr arr2; +BEGIN + FOR I IN 1..5 LOOP + nst_arr(1)(I) := I; + RAISE NOTICE 'RESULT: %', nst_arr(1)(I); + END LOOP; +END; +/ + +-- record of arrays +DECLARE + TYPE arr1 IS VARRAY(5) OF INTEGER; + TYPE rec1 IS RECORD(id int, arrarg arr1); + arr_rec rec1; +BEGIN + FOR I IN 1..5 LOOP + arr_rec.arrarg(I):=I; + RAISE NOTICE 'RESULT: %', arr_rec.arrarg(I); + END LOOP; +END; +/ + +-- array of records +CREATE OR REPLACE PROCEDURE test_nested AS +DECLARE + TYPE rec1 IS RECORD(id int, name char(10)); + TYPE arr1 IS VARRAY(5) OF rec1; + rec_arr arr1; +BEGIN + FOR I IN 1..5 LOOP + rec_arr(I).id := I; + RAISE NOTICE 'RESULT: %', rec_arr(I).id; + END LOOP; +END; +/ +CALL test_nested(); + +-- record of records +CREATE OR REPLACE PROCEDURE test_nested AS +DECLARE + TYPE rec1 IS RECORD(id int, name char(10)); + TYPE rec2 IS RECORD(id int, recarg rec1); + recrec rec2; +BEGIN + recrec.recarg.id := 1; + recrec.recarg.name := 'RECORD'; + RAISE NOTICE 'ID: %, NAME: %', recrec.recarg.id, recrec.recarg.name; +END; +/ +CALL test_nested(); + +DROP SCHEMA plpgsql_nested_array_and_record CASCADE;