支持array和record嵌套

This commit is contained in:
yelingzhi
2024-04-29 05:44:51 +00:00
committed by yaoxin
parent 6bcb754afd
commit ccc71965e5
8 changed files with 187 additions and 26 deletions

View File

@ -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);

View File

@ -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];

View File

@ -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
---+---

View File

@ -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()

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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;