diff --git a/src/common/pl/plpgsql/src/gram.y b/src/common/pl/plpgsql/src/gram.y index a0139ef3ca881d7c4dd1fa48e2143c09239a918d..fa7934a2d9441a795b2267b2b21349408b8ddffb 100755 --- a/src/common/pl/plpgsql/src/gram.y +++ b/src/common/pl/plpgsql/src/gram.y @@ -12430,11 +12430,7 @@ read_into_target(PLpgSQL_rec **rec, PLpgSQL_row **row, bool *strict, int firstto *rec = NULL; *row = NULL; if (strict) { - if (DB_IS_CMPT(PG_FORMAT | B_FORMAT) && firsttoken == K_SELECT && SELECT_INTO_RETURN_NULL) { - *strict = false; - } else { - *strict = true; - } + *strict = false; } #ifdef ENABLE_MULTIPLE_NODES if (strict) diff --git a/src/common/pl/plpgsql/src/pl_exec.cpp b/src/common/pl/plpgsql/src/pl_exec.cpp index 5c0696258215e696b4b206f4c7f984739d8228a0..7cdb5fb78cb6f7aa668b0fe0e62922625870aa96 100644 --- a/src/common/pl/plpgsql/src/pl_exec.cpp +++ b/src/common/pl/plpgsql/src/pl_exec.cpp @@ -7827,6 +7827,7 @@ static int exec_stmt_execsql(PLpgSQL_execstate* estate, PLpgSQL_stmt_execsql* st Cursor_Data* saved_cursor_data = NULL; bool has_alloc = false; bool multi_res_return = false; + bool isStrict = stmt->strict; NodeTag old_node_tag = t_thrd.postgres_cxt.cur_command_tag; TransactionId oldTransactionId = SPI_get_top_transaction_id(); @@ -7898,17 +7899,17 @@ static int exec_stmt_execsql(PLpgSQL_execstate* estate, PLpgSQL_stmt_execsql* st if (stmt->into) { if (!stmt->mod_stmt && !stmt->bulk_collect) { if (!DB_IS_CMPT(PG_FORMAT | B_FORMAT) || SELECT_INTO_RETURN_NULL == 0) { - stmt->strict = true; + isStrict = true; } } #ifdef ENABLE_MULTIPLE_NODES if (!stmt->mod_stmt && !stmt->bulk_collect) { - stmt->strict = true; + isStrict = true; } #endif if (stmt->bulk_collect) { tcount = 0; - } else if (stmt->strict || stmt->mod_stmt) { + } else if (isStrict || stmt->mod_stmt) { tcount = 2; } else { tcount = 1; @@ -8077,7 +8078,7 @@ static int exec_stmt_execsql(PLpgSQL_execstate* estate, PLpgSQL_stmt_execsql* st * allow the query to find any number of rows. */ if (n == 0) { - if (stmt->strict) { + if (isStrict) { ereport(ERROR, (errcode(ERRCODE_NO_DATA_FOUND), errmodule(MOD_PLSQL), @@ -8188,6 +8189,8 @@ static void exec_into_dynexecute(PLpgSQL_execstate* estate, PLpgSQL_stmt_dynexec uint32 n = SPI_processed; PLpgSQL_rec* rec = NULL; PLpgSQL_row* row = NULL; + bool isStrict = stmt->strict || !DB_IS_CMPT(PG_FORMAT | B_FORMAT) || + SELECT_INTO_RETURN_NULL == 0; if (!stmt->into) { return; @@ -8224,14 +8227,14 @@ static void exec_into_dynexecute(PLpgSQL_execstate* estate, PLpgSQL_stmt_dynexec * allow the query to find any number of rows. */ if (n == 0) { - if (stmt->strict) { + if (isStrict) { ereport( ERROR, (errcode(ERRCODE_NO_DATA_FOUND), errmodule(MOD_PLSQL), errmsg("query returned no rows"))); } /* set the target to NULL(s) */ exec_move_row(estate, rec, row, NULL, tuptab->tupdesc); } else { - if (n > 1 && stmt->strict) { + if (n > 1 && isStrict) { ereport(ERROR, (errcode(ERRCODE_TOO_MANY_ROWS), errmodule(MOD_PLSQL), errmsg("query returned more than one row"))); } @@ -8507,6 +8510,9 @@ static int exec_stmt_dynexecute(PLpgSQL_execstate* estate, PLpgSQL_stmt_dynexecu /* normal way: for only one statement in dynamic query */ if (stmt->into) { tcount = stmt->strict ? 2 : 1; + if (!DB_IS_CMPT(PG_FORMAT | B_FORMAT) || SELECT_INTO_RETURN_NULL == 0) { + tcount = 2; + } } else { tcount = 0; } diff --git a/src/test/regress/expected/function.out b/src/test/regress/expected/function.out index 496c352c8e094184a46a046642b6381db2379419..f9609f4cfb8c60a837564af064bff5926a1b35f2 100644 --- a/src/test/regress/expected/function.out +++ b/src/test/regress/expected/function.out @@ -1708,8 +1708,89 @@ select select_into_null_func('aaa') is null; t (1 row) +CREATE OR REPLACE FUNCTION execute_into_null_func(canshu varchar(16)) +returns int +as $$ +DECLARE test_table_030a int; +begin + EXECUTE 'SELECT ID FROM test_table_030 WHERE NAME = ' || quote_literal(canshu) into test_table_030a; + return test_table_030a; +end; $$ language plpgsql; +select execute_into_null_func('aaa'); + execute_into_null_func +------------------------ + +(1 row) + +select execute_into_null_func('aaa') is null; + ?column? +---------- + t +(1 row) + +CREATE OR REPLACE FUNCTION strict_select_into_null_func(canshu varchar(16)) +returns int +as $$ +DECLARE test_table_030a int; +begin + SELECT ID into STRICT test_table_030a FROM test_table_030 WHERE NAME = canshu; + return test_table_030a; +end; $$ language plpgsql; +select strict_select_into_null_func('aaa'); +ERROR: query returned no rows when process INTO +CONTEXT: PL/pgSQL function strict_select_into_null_func(character varying) line 4 at SQL statement +referenced column: strict_select_into_null_func +CREATE OR REPLACE FUNCTION strict_execute_into_null_func(canshu varchar(16)) +returns int +as $$ +DECLARE test_table_030a int; +begin + EXECUTE 'SELECT ID FROM test_table_030 WHERE NAME = ' || quote_literal(canshu) into STRICT test_table_030a; + return test_table_030a; +end; $$ language plpgsql; +select strict_execute_into_null_func('aaa'); +ERROR: query returned no rows +CONTEXT: PL/pgSQL function strict_execute_into_null_func(character varying) line 4 at EXECUTE statement +referenced column: strict_execute_into_null_func +reset behavior_compat_options; +select select_into_null_func('aaa'); +ERROR: query returned no rows when process INTO +CONTEXT: PL/pgSQL function select_into_null_func(character varying) line 4 at SQL statement +referenced column: select_into_null_func +select execute_into_null_func('aaa'); +ERROR: query returned no rows +CONTEXT: PL/pgSQL function execute_into_null_func(character varying) line 4 at EXECUTE statement +referenced column: execute_into_null_func +set behavior_compat_options='select_into_return_null'; +select select_into_null_func('aaa'); + select_into_null_func +----------------------- + +(1 row) + +select select_into_null_func('aaa') is null; + ?column? +---------- + t +(1 row) + +select execute_into_null_func('aaa'); + execute_into_null_func +------------------------ + +(1 row) + +select execute_into_null_func('aaa') is null; + ?column? +---------- + t +(1 row) + drop table test_table_030; drop function select_into_null_func; +drop function execute_into_null_func; +drop function strict_select_into_null_func; +drop function strict_execute_into_null_func; reset behavior_compat_options; \c regression; drop database IF EXISTS pl_test_funcion; diff --git a/src/test/regress/sql/function.sql b/src/test/regress/sql/function.sql index 49817673f88238688fbadf338782988cb11881bb..6042b97268d1d261545b0cb3c7641ee8f967234b 100644 --- a/src/test/regress/sql/function.sql +++ b/src/test/regress/sql/function.sql @@ -958,8 +958,53 @@ end; $$ language plpgsql; select select_into_null_func('aaa'); select select_into_null_func('aaa') is null; +CREATE OR REPLACE FUNCTION execute_into_null_func(canshu varchar(16)) +returns int +as $$ +DECLARE test_table_030a int; +begin + EXECUTE 'SELECT ID FROM test_table_030 WHERE NAME = ' || quote_literal(canshu) into test_table_030a; + return test_table_030a; +end; $$ language plpgsql; + +select execute_into_null_func('aaa'); +select execute_into_null_func('aaa') is null; + +CREATE OR REPLACE FUNCTION strict_select_into_null_func(canshu varchar(16)) +returns int +as $$ +DECLARE test_table_030a int; +begin + SELECT ID into STRICT test_table_030a FROM test_table_030 WHERE NAME = canshu; + return test_table_030a; +end; $$ language plpgsql; +select strict_select_into_null_func('aaa'); + +CREATE OR REPLACE FUNCTION strict_execute_into_null_func(canshu varchar(16)) +returns int +as $$ +DECLARE test_table_030a int; +begin + EXECUTE 'SELECT ID FROM test_table_030 WHERE NAME = ' || quote_literal(canshu) into STRICT test_table_030a; + return test_table_030a; +end; $$ language plpgsql; +select strict_execute_into_null_func('aaa'); + +reset behavior_compat_options; +select select_into_null_func('aaa'); +select execute_into_null_func('aaa'); + +set behavior_compat_options='select_into_return_null'; +select select_into_null_func('aaa'); +select select_into_null_func('aaa') is null; +select execute_into_null_func('aaa'); +select execute_into_null_func('aaa') is null; + drop table test_table_030; drop function select_into_null_func; +drop function execute_into_null_func; +drop function strict_select_into_null_func; +drop function strict_execute_into_null_func; reset behavior_compat_options; \c regression; drop database IF EXISTS pl_test_funcion;