From 5de9c36e0fd29f8441b7e87a5ae7fbae68098d25 Mon Sep 17 00:00:00 2001 From: chenxiaobin19 <1025221611@qq.com> Date: Thu, 8 Aug 2024 10:46:19 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=B5=8C=E5=A5=97=E6=95=B0?= =?UTF-8?q?=E7=BB=84=E6=8F=92=E5=85=A5=E8=A1=A8=E6=97=B6=E6=8A=A5=E9=94=99?= =?UTF-8?q?=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/common/backend/parser/parse_target.cpp | 6 ++ src/common/pl/plpgsql/src/pl_comp.cpp | 28 +++++- .../expected/plpgsql_table_opengauss.out | 95 +++++++++++++++++++ .../regress/sql/plpgsql_table_opengauss.sql | 79 +++++++++++++++ 4 files changed, 207 insertions(+), 1 deletion(-) diff --git a/src/common/backend/parser/parse_target.cpp b/src/common/backend/parser/parse_target.cpp index ff960c57c..22991b0ac 100644 --- a/src/common/backend/parser/parse_target.cpp +++ b/src/common/backend/parser/parse_target.cpp @@ -54,6 +54,8 @@ static List* ExpandSingleTable(ParseState* pstate, RangeTblEntry* rte, int locat static List* ExpandRowReference(ParseState* pstate, Node* expr, bool targetlist); static int FigureColnameInternal(Node* node, char** name); +extern void checkArrayTypeInsert(ParseState* pstate, Expr* expr); + /* * @Description: return the last filed's name and ignore * or subscrpts * @in field: list of field to search @@ -443,6 +445,10 @@ Expr* transformAssignedExpr(ParseState* pstate, Expr* expr, ParseExprKind exprKi type_id = exprType((Node*)expr); type_mod = exprTypmod((Node*)expr); + if (IsA(expr, Param) || (IsA(expr, ArrayRef) && ((ArrayRef*)expr)->refexpr != NULL)) { + checkArrayTypeInsert(pstate, expr); + } + ELOG_FIELD_NAME_START(colname); /* diff --git a/src/common/pl/plpgsql/src/pl_comp.cpp b/src/common/pl/plpgsql/src/pl_comp.cpp index c853a087d..b6f2f8499 100644 --- a/src/common/pl/plpgsql/src/pl_comp.cpp +++ b/src/common/pl/plpgsql/src/pl_comp.cpp @@ -5685,4 +5685,30 @@ Oid searchsubtypebytypeId(Oid typeOid, int32 *typmod) errmsg("unsupported search subtype by type %u", typeOid))); } return type == TYPTYPE_TABLEOF ? searchsubtypebytypeId(resultType, typmod) : resultType; -} \ No newline at end of file +} + +void checkArrayTypeInsert(ParseState* pstate, Expr* expr) +{ + Param* param = NULL; + if (IsA(expr, Param)) { + param = (Param*)expr; + } else if (IsA(expr, ArrayRef) && IsA(((ArrayRef*)expr)->refexpr, Param)) { + param = (Param*)((ArrayRef*)expr)->refexpr; + } else { + return; + } + + if (pstate->p_pre_columnref_hook == plpgsql_pre_column_ref && pstate->p_ref_hook_state != NULL) { + PLpgSQL_expr* pl_expr = (PLpgSQL_expr*)pstate->p_ref_hook_state; + + if (pl_expr->func != NULL && param->paramid <= pl_expr->func->ndatums && + pl_expr->func->datums[param->paramid - 1]->dtype == PLPGSQL_DTYPE_VAR) { + PLpgSQL_var* var = (PLpgSQL_var*)pl_expr->func->datums[param->paramid - 1]; + + if (var->nest_table != NULL && (IsA(expr, Param) || + var->nest_layers != list_length(((ArrayRef*)expr)->refupperindexpr))) { + ereport(ERROR, (errmsg("The tableof type variable cannot be used as an insertion value. "))); + } + } + } +} diff --git a/src/test/regress/expected/plpgsql_table_opengauss.out b/src/test/regress/expected/plpgsql_table_opengauss.out index 2c207040f..f66bd458d 100644 --- a/src/test/regress/expected/plpgsql_table_opengauss.out +++ b/src/test/regress/expected/plpgsql_table_opengauss.out @@ -926,6 +926,101 @@ INFO: plpgsql_table_opengauss.pck1.v2(2) is 3 0 (1 row) +create table t_PLArray_ (id int ,col varchar(500)); +create or replace procedure p_PLArray_ +as +type typ_PLArray_1 is table of varchar(50); +type typ_PLArray_2 is table of typ_PLArray_1; +nstarr typ_PLArray_2; +begin +nstarr(1)(1):='第一行第一列'; +nstarr(1)(2):='第一行第二列'; + +insert into t_PLArray_(col) values (nstarr(1)); +end; +/ +call p_PLArray_(); +ERROR: The tableof type variable cannot be used as an insertion value. +CONTEXT: SQL statement "insert into t_PLArray_(col) values (nstarr[1])" +PL/pgSQL function p_plarray_() line 8 at SQL statement +create or replace procedure p_PLArray_ +as +type typ_PLArray_1 is table of varchar(50); +type typ_PLArray_2 is table of typ_PLArray_1; +nstarr typ_PLArray_2; +begin +nstarr(1)(1):='第一行第一列'; +nstarr(1)(2):='第一行第二列'; + +insert into t_PLArray_(col) values (nstarr); +end; +/ +call p_PLArray_(); +ERROR: The tableof type variable cannot be used as an insertion value. +CONTEXT: SQL statement "insert into t_PLArray_(col) values (nstarr)" +PL/pgSQL function p_plarray_() line 8 at SQL statement +create or replace procedure p_PLArray_ +as +type typ_PLArray_1 is table of varchar(50); +type typ_PLArray_2 is table of typ_PLArray_1; +nstarr typ_PLArray_2; +begin +nstarr(1)(1):='第一行第一列'; +nstarr(1)(2):='第一行第二列'; + +insert into t_PLArray_(col) values (nstarr(1)(1)); +insert into t_PLArray_(col) values (nstarr(1)(2)); +end; +/ +call p_PLArray_(); + p_plarray_ +------------ + +(1 row) + +declare +type typ_PLArray_1 is varray(3) of varchar(50); +type typ_PLArray_2 is varray(3) of typ_PLArray_1; +nstarr typ_PLArray_2; +begin +nstarr(1)(1):='第一行第一列'; +insert into t_PLArray_(col) values (nstarr(1)); +end; +/ +ERROR: The tableof type variable cannot be used as an insertion value. +CONTEXT: SQL statement "insert into t_PLArray_(col) values (nstarr[1])" +PL/pgSQL function inline_code_block line 6 at SQL statement +declare +type typ_PLArray_1 is varray(3) of varchar(50); +type typ_PLArray_2 is varray(3) of typ_PLArray_1; +nstarr typ_PLArray_2; +begin +nstarr(1)(1):='第一行第一列'; +insert into t_PLArray_(col) values (nstarr); +end; +/ +ERROR: The tableof type variable cannot be used as an insertion value. +CONTEXT: SQL statement "insert into t_PLArray_(col) values (nstarr)" +PL/pgSQL function inline_code_block line 6 at SQL statement +declare +type typ_PLArray_1 is varray(3) of varchar(50); +type typ_PLArray_2 is varray(3) of typ_PLArray_1; +nstarr typ_PLArray_2; +begin +nstarr(1)(1):='第一行第一列'; +insert into t_PLArray_(col) values (nstarr(1)(1)); +end; +/ +select * from t_PLArray_; + id | col +----+-------------- + | 第一行第一列 + | 第一行第二列 + | 第一行第一列 +(3 rows) + +drop table t_PLArray_; +drop procedure p_PLArray_; -- test pg_get_function_result and pg_get_function_arguments create type ty_test is(col1 int,col2 char(10),col3 varchar2(10)); create type tyt_test is table of ty_test; diff --git a/src/test/regress/sql/plpgsql_table_opengauss.sql b/src/test/regress/sql/plpgsql_table_opengauss.sql index 323898b37..ab586da3c 100644 --- a/src/test/regress/sql/plpgsql_table_opengauss.sql +++ b/src/test/regress/sql/plpgsql_table_opengauss.sql @@ -769,6 +769,85 @@ end; / call func2(); +create table t_PLArray_ (id int ,col varchar(500)); +create or replace procedure p_PLArray_ +as +type typ_PLArray_1 is table of varchar(50); +type typ_PLArray_2 is table of typ_PLArray_1; +nstarr typ_PLArray_2; +begin +nstarr(1)(1):='第一行第一列'; +nstarr(1)(2):='第一行第二列'; + +insert into t_PLArray_(col) values (nstarr(1)); +end; +/ +call p_PLArray_(); + +create or replace procedure p_PLArray_ +as +type typ_PLArray_1 is table of varchar(50); +type typ_PLArray_2 is table of typ_PLArray_1; +nstarr typ_PLArray_2; +begin +nstarr(1)(1):='第一行第一列'; +nstarr(1)(2):='第一行第二列'; + +insert into t_PLArray_(col) values (nstarr); +end; +/ +call p_PLArray_(); + +create or replace procedure p_PLArray_ +as +type typ_PLArray_1 is table of varchar(50); +type typ_PLArray_2 is table of typ_PLArray_1; +nstarr typ_PLArray_2; +begin +nstarr(1)(1):='第一行第一列'; +nstarr(1)(2):='第一行第二列'; + +insert into t_PLArray_(col) values (nstarr(1)(1)); +insert into t_PLArray_(col) values (nstarr(1)(2)); +end; +/ +call p_PLArray_(); + +declare +type typ_PLArray_1 is varray(3) of varchar(50); +type typ_PLArray_2 is varray(3) of typ_PLArray_1; +nstarr typ_PLArray_2; +begin +nstarr(1)(1):='第一行第一列'; +insert into t_PLArray_(col) values (nstarr(1)); +end; +/ + +declare +type typ_PLArray_1 is varray(3) of varchar(50); +type typ_PLArray_2 is varray(3) of typ_PLArray_1; +nstarr typ_PLArray_2; +begin +nstarr(1)(1):='第一行第一列'; +insert into t_PLArray_(col) values (nstarr); +end; +/ + +declare +type typ_PLArray_1 is varray(3) of varchar(50); +type typ_PLArray_2 is varray(3) of typ_PLArray_1; +nstarr typ_PLArray_2; +begin +nstarr(1)(1):='第一行第一列'; +insert into t_PLArray_(col) values (nstarr(1)(1)); +end; +/ + +select * from t_PLArray_; + +drop table t_PLArray_; +drop procedure p_PLArray_; + -- test pg_get_function_result and pg_get_function_arguments create type ty_test is(col1 int,col2 char(10),col3 varchar2(10)); create type tyt_test is table of ty_test;