diff --git a/src/common/pl/plpgsql/src/gram.y b/src/common/pl/plpgsql/src/gram.y index 1ee23aff6..1b9dd59bc 100755 --- a/src/common/pl/plpgsql/src/gram.y +++ b/src/common/pl/plpgsql/src/gram.y @@ -2213,6 +2213,15 @@ record_attr : attr_name decl_datatype decl_notnull decl_rec_defval attr->attrname = $1; PLpgSQL_type *var_type = ((PLpgSQL_var *)u_sess->plsql_cxt.curr_compile_context->plpgsql_Datums[$2])->datatype; + PLpgSQL_var *varray_type = (PLpgSQL_var *)u_sess->plsql_cxt.curr_compile_context->plpgsql_Datums[$2]; + + if (varray_type->nest_table != NULL) { + ereport(errstate, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("nested table of type is not supported as record type attribute"), + parser_errposition(@3))); + u_sess->plsql_cxt.have_error = true; + } PLpgSQL_type *new_var_type = build_array_type_from_elemtype(var_type); new_var_type->collectionType = var_type->collectionType; new_var_type->tableOfIndexType = var_type->tableOfIndexType; @@ -2241,7 +2250,7 @@ record_attr : attr_name decl_datatype decl_notnull decl_rec_defval $$ = attr; } - | attr_name table_var decl_notnull decl_rec_defval + | attr_name table_var decl_notnull decl_rec_defval { PLpgSQL_rec_attr *attr = NULL; @@ -8674,6 +8683,11 @@ read_sql_construct6(int until, int loc = 0; int curloc = 0; int brack_cnt = 0; + int nest_layers = 0; + int left_brace_count = 0; + int right_brace_count = 0; + bool stop_count = false; + int stop_tok; /* mark if there are 2 table of index by var call functions in an expr */ int tableof_func_dno = -1; int tableof_var_dno = -1; @@ -8702,6 +8716,14 @@ read_sql_construct6(int until, { prev_tok = tok; tok = yylex(); + if (tok == '\"' || tok == '\'') { + if (stop_count && stop_tok == tok) { + stop_count = false; + } else { + stop_count = true; + stop_tok = tok; + } + } tokenstack = push_token_stack(tok, tokenstack); loc = yylloc; if (startlocation < 0) /* remember loc of first token */ @@ -8998,6 +9020,8 @@ read_sql_construct6(int until, brack_cnt--; /* fall through */ case ')': + if (!stop_count) + right_brace_count++; if (context.list_right_bracket && context.list_right_bracket->length && linitial_int(context.list_right_bracket) == parenlevel) { /* append bracket instead of parentheses */ @@ -9055,6 +9079,8 @@ read_sql_construct6(int until, brack_cnt++; /* fall through */ case '(': + if (!stop_count) + left_brace_count++; if (context.list_left_bracket && context.list_left_bracket->length && linitial_int(context.list_left_bracket) == parenlevel - 1) { appendStringInfoString(&ds, left_bracket); @@ -9266,6 +9292,10 @@ read_sql_construct6(int until, yylval = temptokendata->lval; u_sess->plsql_cxt.curr_compile_context->plpgsql_yyleng = temptokendata->leng; } + if (left_brace_count == 0) + { + nest_layers = var->nest_layers; + } ds_changed = construct_array_start(&ds, &context, var->datatype, &tok, parenlevel, loc); break; } @@ -9287,6 +9317,10 @@ read_sql_construct6(int until, } int dno = yylval.wdatum.datum->dno; PLpgSQL_var *var = (PLpgSQL_var *)u_sess->plsql_cxt.curr_compile_context->plpgsql_Datums[dno]; + if (left_brace_count == 0) + { + nest_layers = var->nest_layers; + } ds_changed = construct_array_start(&ds, &context, var->datatype, &tok, parenlevel, loc); break; } @@ -9364,7 +9398,9 @@ read_sql_construct6(int until, if (IS_ARRAY_STATE(context.list_array_state, ARRAY_COERCE)) { /* always append right parentheses at end of each element */ appendStringInfoString(&ds, right_parentheses); - plpgsql_append_object_typename(&ds, (PLpgSQL_type *)linitial(context.list_datatype)); + if ((left_brace_count - right_brace_count) > nest_layers) { + plpgsql_append_object_typename(&ds, (PLpgSQL_type *)linitial(context.list_datatype)); + } SET_ARRAY_STATE(context.list_array_state, ARRAY_SEPERATOR); } } diff --git a/src/gausskernel/runtime/executor/execQual.cpp b/src/gausskernel/runtime/executor/execQual.cpp index 3b3594d28..e0d0f3b86 100644 --- a/src/gausskernel/runtime/executor/execQual.cpp +++ b/src/gausskernel/runtime/executor/execQual.cpp @@ -1434,7 +1434,7 @@ static Datum ExecEvalParamExtern(ExprState* exprstate, ExprContext* econtext, bo *isNull = prm->isnull; if (prm->tabInfo && prm->tabInfo->isnestedtable && plpgsql_estate) { - plpgsql_estate->curr_nested_table_type = prm->ptype; + plpgsql_estate->curr_nested_table_type = prm->tabInfo->tableOfIndexType; plpgsql_estate->curr_nested_table_layers = prm->tabInfo->tableOfLayers; } /* copy cursor option from param to econtext */ diff --git a/src/test/regress/expected/plpgsql_nested_array_and_record.out b/src/test/regress/expected/plpgsql_nested_array_and_record.out index 36fe749ce..daef71c94 100644 --- a/src/test/regress/expected/plpgsql_nested_array_and_record.out +++ b/src/test/regress/expected/plpgsql_nested_array_and_record.out @@ -10,6 +10,52 @@ 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 +CREATE OR REPLACE PROCEDURE test_nested AS +DECLARE + TYPE arr2 IS VARRAY(5) OF INTEGER; + TYPE arr1 IS VARRAY(5) OF INTEGER; + TYPE nt1 IS VARRAY(10) OF arr1; + TYPE rec1 IS RECORD(id int, arrarg nt1); + arr_rec rec1:=rec1(7, nt1(arr1(1,2,4,5),arr1(1,3))); +BEGIN + RAISE NOTICE 'ID: %', arr_rec.id; +END; +/ +ERROR: nested table of type is not supported as record type attribute +LINE 5: TYPE rec1 IS RECORD(id int, arrarg nt1); + ^ +QUERY: DECLARE + TYPE arr2 IS VARRAY(5) OF INTEGER; + TYPE arr1 IS VARRAY(5) OF INTEGER; + TYPE nt1 IS VARRAY(10) OF arr1; + TYPE rec1 IS RECORD(id int, arrarg nt1); + arr_rec rec1:=rec1(7, nt1(arr1(1,2,4,5),arr1(1,3))); +BEGIN + RAISE NOTICE 'ID: %', arr_rec.id; +END +CREATE OR REPLACE PROCEDURE test_nested AS +DECLARE + TYPE arr2 IS TABLE OF INTEGER; + TYPE arr1 IS TABLE OF INTEGER; + TYPE nt1 IS TABLE OF arr1; + TYPE rec1 IS RECORD(id int, arrarg nt1); + arr_rec rec1:=rec1(7, nt1(arr1(1,2,4,5),arr1(1,3))); +BEGIN + RAISE NOTICE 'ID: %', arr_rec.id; +END; +/ +ERROR: nested table of type is not supported as record type attribute +LINE 5: TYPE rec1 IS RECORD(id int, arrarg nt1); + ^ +QUERY: DECLARE + TYPE arr2 IS TABLE OF INTEGER; + TYPE arr1 IS TABLE OF INTEGER; + TYPE nt1 IS TABLE OF arr1; + TYPE rec1 IS RECORD(id int, arrarg nt1); + arr_rec rec1:=rec1(7, nt1(arr1(1,2,4,5),arr1(1,3))); +BEGIN + RAISE NOTICE 'ID: %', arr_rec.id; +END DECLARE TYPE arr1 IS VARRAY(5) OF INTEGER; TYPE arr2 IS VARRAY(5) OF arr1; @@ -26,6 +72,84 @@ NOTICE: RESULT: 2 NOTICE: RESULT: 3 NOTICE: RESULT: 4 NOTICE: RESULT: 5 +DECLARE +TYPE t1 IS VARRAY(10) OF INTEGER; -- varray of integer +va t1 := t1(2,3); +TYPE nt1 IS VARRAY(10) OF t1; -- varray of varray of integer +nva nt1 := nt1(t1(2,3,5), t1(55,6), t1(2,3,8)); +i INTEGER; +va1 t1; +BEGIN + raise notice '%', nva(2)(3); +END; +/ +ERROR: multidimensional arrays must have array expressions with matching dimensions +CONTEXT: referenced column: array +SQL statement "SELECT ARRAY[(ARRAY[(2),(3),(5)]), (ARRAY[(55),(6)]), (ARRAY[(2),(3),(8)])]" +PL/pgSQL function inline_code_block line 7 during statement block local variable initialization +DECLARE +TYPE t1 IS VARRAY(10) OF INTEGER; -- varray of integer +va t1 := t1(2,3); +TYPE nt1 IS VARRAY(10) OF t1; -- varray of varray of integer +nva nt1 := nt1(t1(2,3,5), t1(55,8,6), t1(2,3,8)); +i INTEGER; +va1 t1; +BEGIN + raise notice '%', nva(2)(1); +END; +/ +NOTICE: 55 +DECLARE +TYPE t1 IS VARRAY(10) OF INTEGER; -- varray of integer +va t1 := t1(2,3,9); +TYPE nt1 IS VARRAY(10) OF t1; -- varray of varray of integer +nva nt1 := nt1(va, t1(55,8,6), t1(2,3,8)); +i INTEGER; +va1 t1; +BEGIN + raise notice '%', nva(1)(3); +END; +/ +NOTICE: 9 +DECLARE +TYPE t1 IS VARRAY(10) OF INTEGER; -- varray of integer +va t1 := t1(2,3,9); +TYPE nt1 IS VARRAY(10) OF t1; -- varray of varray of integer +TYPE nnt1 IS VARRAY(10) OF nt1; +nva nnt1 := nt1(nt1(t1(2,3,9), t1(55,8,6), t1(2,3,8)),nt1(t1(95,80,65), t1(2,3,9), t1(2,3,8))); +i INTEGER; +va1 t1; +BEGIN + raise notice '%', nva(2)(1)(3); +END; +/ +NOTICE: 65 +DECLARE +TYPE t1 IS VARRAY(10) OF INTEGER; -- varray of integer +va t1 := t1(2,3,9); +TYPE nt1 IS VARRAY(10) OF t1; -- varray of varray of integer +TYPE nnt1 IS VARRAY(10) OF nt1; +nva nnt1 := nt1(nt1(t1(2,3,9), va, t1(2,3,8)),nt1(t1(95,80,65), t1(2,3,9), t1(2,3,8))); +i INTEGER; +va1 t1; +BEGIN + raise notice '%', nva(1)(2)(2); +END; +/ +NOTICE: 3 +DECLARE +TYPE t1 IS VARRAY(10) OF INTEGER; -- varray of integer +va t1 := t1(2,3,9); +TYPE nt1 IS VARRAY(10) OF t1; -- varray of varray of integer +TYPE nnt1 IS VARRAY(10) OF nt1; +nva nnt1 := nt1(nt1(t1(2,3,9), va, t1(2,3,8)),nt1(va, t1(2,3,9), t1(2,3,8))); +i INTEGER; +va1 t1; +BEGIN + raise notice '%', nva(2)(1)(3); +END; +/ +NOTICE: 9 CREATE OR REPLACE PROCEDURE test_nested_array as TYPE typ_PLArray_case0001 IS varray(3) OF integer; TYPE typ_PLArray_case0002 IS varray(3) OF typ_PLArray_case0001; diff --git a/src/test/regress/sql/plpgsql_nested_array_and_record.sql b/src/test/regress/sql/plpgsql_nested_array_and_record.sql index aa2c7d2e4..6f96ab9f8 100644 --- a/src/test/regress/sql/plpgsql_nested_array_and_record.sql +++ b/src/test/regress/sql/plpgsql_nested_array_and_record.sql @@ -6,6 +6,30 @@ CREATE SCHEMA plpgsql_nested_array_and_record; SET current_schema = plpgsql_nested_array_and_record; -- array of arrays +CREATE OR REPLACE PROCEDURE test_nested AS +DECLARE + TYPE arr2 IS VARRAY(5) OF INTEGER; + TYPE arr1 IS VARRAY(5) OF INTEGER; + TYPE nt1 IS VARRAY(10) OF arr1; + TYPE rec1 IS RECORD(id int, arrarg nt1); + arr_rec rec1:=rec1(7, nt1(arr1(1,2,4,5),arr1(1,3))); +BEGIN + RAISE NOTICE 'ID: %', arr_rec.id; +END; +/ + +CREATE OR REPLACE PROCEDURE test_nested AS +DECLARE + TYPE arr2 IS TABLE OF INTEGER; + TYPE arr1 IS TABLE OF INTEGER; + TYPE nt1 IS TABLE OF arr1; + TYPE rec1 IS RECORD(id int, arrarg nt1); + arr_rec rec1:=rec1(7, nt1(arr1(1,2,4,5),arr1(1,3))); +BEGIN + RAISE NOTICE 'ID: %', arr_rec.id; +END; +/ + DECLARE TYPE arr1 IS VARRAY(5) OF INTEGER; TYPE arr2 IS VARRAY(5) OF arr1; @@ -18,6 +42,90 @@ BEGIN END; / +DECLARE +TYPE t1 IS VARRAY(10) OF INTEGER; -- varray of integer +va t1 := t1(2,3); + +TYPE nt1 IS VARRAY(10) OF t1; -- varray of varray of integer +nva nt1 := nt1(t1(2,3,5), t1(55,6), t1(2,3,8)); + +i INTEGER; +va1 t1; +BEGIN + raise notice '%', nva(2)(3); +END; +/ + +DECLARE +TYPE t1 IS VARRAY(10) OF INTEGER; -- varray of integer +va t1 := t1(2,3); + +TYPE nt1 IS VARRAY(10) OF t1; -- varray of varray of integer +nva nt1 := nt1(t1(2,3,5), t1(55,8,6), t1(2,3,8)); + +i INTEGER; +va1 t1; +BEGIN + raise notice '%', nva(2)(1); +END; +/ + +DECLARE +TYPE t1 IS VARRAY(10) OF INTEGER; -- varray of integer +va t1 := t1(2,3,9); + +TYPE nt1 IS VARRAY(10) OF t1; -- varray of varray of integer +nva nt1 := nt1(va, t1(55,8,6), t1(2,3,8)); + +i INTEGER; +va1 t1; +BEGIN + raise notice '%', nva(1)(3); +END; +/ + +DECLARE +TYPE t1 IS VARRAY(10) OF INTEGER; -- varray of integer +va t1 := t1(2,3,9); +TYPE nt1 IS VARRAY(10) OF t1; -- varray of varray of integer +TYPE nnt1 IS VARRAY(10) OF nt1; +nva nnt1 := nt1(nt1(t1(2,3,9), t1(55,8,6), t1(2,3,8)),nt1(t1(95,80,65), t1(2,3,9), t1(2,3,8))); + +i INTEGER; +va1 t1; +BEGIN + raise notice '%', nva(2)(1)(3); +END; +/ + +DECLARE +TYPE t1 IS VARRAY(10) OF INTEGER; -- varray of integer +va t1 := t1(2,3,9); +TYPE nt1 IS VARRAY(10) OF t1; -- varray of varray of integer +TYPE nnt1 IS VARRAY(10) OF nt1; +nva nnt1 := nt1(nt1(t1(2,3,9), va, t1(2,3,8)),nt1(t1(95,80,65), t1(2,3,9), t1(2,3,8))); + +i INTEGER; +va1 t1; +BEGIN + raise notice '%', nva(1)(2)(2); +END; +/ + +DECLARE +TYPE t1 IS VARRAY(10) OF INTEGER; -- varray of integer +va t1 := t1(2,3,9); +TYPE nt1 IS VARRAY(10) OF t1; -- varray of varray of integer +TYPE nnt1 IS VARRAY(10) OF nt1; +nva nnt1 := nt1(nt1(t1(2,3,9), va, t1(2,3,8)),nt1(va, t1(2,3,9), t1(2,3,8))); + +i INTEGER; +va1 t1; +BEGIN + raise notice '%', nva(2)(1)(3); +END; +/ + CREATE OR REPLACE PROCEDURE test_nested_array as TYPE typ_PLArray_case0001 IS varray(3) OF integer; TYPE typ_PLArray_case0002 IS varray(3) OF typ_PLArray_case0001;