修复为嵌套数组的一维数组赋类型不匹配的值时挂库的问题
This commit is contained in:
@ -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;
|
||||
|
||||
@ -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()
|
||||
|
||||
@ -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;
|
||||
|
||||
Reference in New Issue
Block a user