修复为嵌套数组的一维数组赋类型不匹配的值时挂库的问题

This commit is contained in:
yelingzhi
2024-08-02 03:22:34 +00:00
parent 4d46d4a0f7
commit bdd8e2ecda
3 changed files with 102 additions and 18 deletions

View File

@ -10018,30 +10018,58 @@ void exec_assign_value(PLpgSQL_execstate* estate, PLpgSQL_datum* target, Datum v
* Evaluate the subscripts, switch into left-to-right order.
* Like ExecEvalArrayRef(), complain if any subscript is null.
*/
for (i = 0; i < nsubscripts; i++) {
bool subisnull = false;
bool isNestedArray = ((PLpgSQL_var*)target)->nest_table != NULL;
subscriptvals[i] = exec_eval_integer(estate, subscripts[nsubscripts - 1 - i], &subisnull);
if (subisnull) {
if (isNestedArray) {
Oid subscriptType = ((PLpgSQL_var*)target)->datatype->tableOfIndexType;
HTAB* elemTableOfIndex = ((PLpgSQL_var*)target)->tableOfIndex;
PLpgSQL_var* innerVar = evalSubsciptsNested(estate, (PLpgSQL_var*)target, subscripts, nsubscripts,
0, subscriptvals, subscriptType, elemTableOfIndex);
target = (PLpgSQL_datum*)innerVar;
/* should assign inner var as an array, copy value's index */
if (innerVar->ispkg) {
MemoryContext temp = MemoryContextSwitchTo(innerVar->pkg->pkg_cxt);
innerVar->tableOfIndex = copyTableOfIndex(tableOfIndex);
MemoryContextSwitchTo(temp);
} else {
innerVar->tableOfIndex = copyTableOfIndex(tableOfIndex);
}
if (tableOfIndexInfo != NULL && innerVar->nest_layers != tableOfIndexInfo->tableOfLayers) {
ereport(ERROR,
(errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
(errcode(ERRCODE_DATATYPE_MISMATCH),
errmodule(MOD_PLSQL),
errmsg("array subscript in assignment must not be null")));
errmsg("Nest layer of assigned value is miss match to tableof var(%s)'s expection",
innerVar->refname)));
}
/*
* Clean up in case the subscript expression wasn't
* simple. We can't do exec_eval_cleanup, but we can do
* this much (which is safe because the integer subscript
* value is surely pass-by-value), and we must do it in
* case the next subscript expression isn't simple either.
*/
if (estate->eval_tuptable != NULL) {
SPI_freetuptable(estate->eval_tuptable);
exec_assign_value(estate, target, PointerGetDatum(value),
valtype, isNull, innerVar->tableOfIndex);
break;
} else {
for (i = 0; i < nsubscripts; i++) {
bool subisnull = false;
subscriptvals[i] = exec_eval_integer(estate, subscripts[nsubscripts - 1 - i], &subisnull);
if (subisnull) {
ereport(ERROR,
(errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
errmodule(MOD_PLSQL),
errmsg("array subscript in assignment must not be null")));
}
/*
* Clean up in case the subscript expression wasn't
* simple. We can't do exec_eval_cleanup, but we can do
* this much (which is safe because the integer subscript
* value is surely pass-by-value), and we must do it in
* case the next subscript expression isn't simple either.
*/
if (estate->eval_tuptable != NULL) {
SPI_freetuptable(estate->eval_tuptable);
}
estate->eval_tuptable = NULL;
}
estate->eval_tuptable = NULL;
}
/* Now we can restore caller's SPI_execute result if any. */
AssertEreport(estate->eval_tuptable == NULL, MOD_PLSQL, "eval tuptable should not be null");
estate->eval_tuptable = save_eval_tuptable;

View File

@ -26,6 +26,36 @@ NOTICE: RESULT: 2
NOTICE: RESULT: 3
NOTICE: RESULT: 4
NOTICE: RESULT: 5
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;
nstarr typ_PLArray_case0002;
BEGIN
nstarr(1):=1;
RAISE NOTICE '二维数组(1):%', nstarr(1);
END;
/
CALL test_nested_array();
ERROR: array value must start with "{" or dimension information
CONTEXT: PL/pgSQL function test_nested_array() line 5 at assignment
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;
nstarr typ_PLArray_case0002;
arr typ_PLArray_case0001;
BEGIN
arr(1):=1;
nstarr(1):=arr;
RAISE NOTICE '二维数组(1):%', nstarr(1);
END;
/
CALL test_nested_array();
NOTICE: 二维数组(1):{1}
test_nested_array
-------------------
(1 row)
-- record of arrays
DECLARE
TYPE arr1 IS VARRAY(5) OF INTEGER;
@ -149,4 +179,6 @@ NOTICE: drop cascades to 2 other objects
DETAIL: drop cascades to function plpgsql_nested_array_and_record.p_plarray_1()
drop cascades to function plpgsql_nested_array_and_record.p_plarray_2(undefined)
DROP SCHEMA plpgsql_nested_array_and_record CASCADE;
NOTICE: drop cascades to function test_nested()
NOTICE: drop cascades to 2 other objects
DETAIL: drop cascades to function test_nested_array()
drop cascades to function test_nested()

View File

@ -18,6 +18,30 @@ BEGIN
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;
nstarr typ_PLArray_case0002;
BEGIN
nstarr(1):=1;
RAISE NOTICE '二维数组(1):%', nstarr(1);
END;
/
CALL test_nested_array();
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;
nstarr typ_PLArray_case0002;
arr typ_PLArray_case0001;
BEGIN
arr(1):=1;
nstarr(1):=arr;
RAISE NOTICE '二维数组(1):%', nstarr(1);
END;
/
CALL test_nested_array();
-- record of arrays
DECLARE
TYPE arr1 IS VARRAY(5) OF INTEGER;