bug-18656-draft-fix.patch
text/x-diff
Filename: bug-18656-draft-fix.patch
Type: text/x-diff
Part: 0
Patch
Format: unified
| File | + | − |
|---|---|---|
| src/backend/executor/spi.c | 7 | 2 |
| src/pl/plpgsql/src/expected/plpgsql_call.out | 20 | 0 |
| src/pl/plpgsql/src/sql/plpgsql_call.sql | 17 | 0 |
diff --git a/src/backend/executor/spi.c b/src/backend/executor/spi.c index 90d9834576..a268c04097 100644 --- a/src/backend/executor/spi.c +++ b/src/backend/executor/spi.c @@ -584,6 +584,8 @@ SPI_inside_nonatomic_context(void) return false; /* not in any SPI context at all */ if (_SPI_current->atomic) return false; /* it's atomic (ie function not procedure) */ + if (IsSubTransaction()) + return false; /* if within subtransaction, it's atomic */ return true; } @@ -2411,9 +2413,12 @@ _SPI_execute_plan(SPIPlanPtr plan, const SPIExecuteOptions *options, /* * We allow nonatomic behavior only if options->allow_nonatomic is set - * *and* the SPI_OPT_NONATOMIC flag was given when connecting. + * *and* the SPI_OPT_NONATOMIC flag was given when connecting and we are + * not inside a subtransaction. The latter two tests match whether + * _SPI_commit() would allow a commit. */ - allow_nonatomic = options->allow_nonatomic && !_SPI_current->atomic; + allow_nonatomic = options->allow_nonatomic && + !_SPI_current->atomic && !IsSubTransaction(); /* * Setup error traceback support for ereport() diff --git a/src/pl/plpgsql/src/expected/plpgsql_call.out b/src/pl/plpgsql/src/expected/plpgsql_call.out index 0a63b1d44e..ea7107dca0 100644 --- a/src/pl/plpgsql/src/expected/plpgsql_call.out +++ b/src/pl/plpgsql/src/expected/plpgsql_call.out @@ -597,6 +597,26 @@ NOTICE: f_get_x(1) NOTICE: f_print_x(1) NOTICE: f_get_x(2) NOTICE: f_print_x(2) +-- test in non-atomic context, except exception block is locally atomic +DO $$ +BEGIN + BEGIN + UPDATE t_test SET x = x + 1; + RAISE NOTICE 'f_get_x(%)', f_get_x(); + CALL f_print_x(f_get_x()); + UPDATE t_test SET x = x + 1; + RAISE NOTICE 'f_get_x(%)', f_get_x(); + CALL f_print_x(f_get_x()); + EXCEPTION WHEN division_by_zero THEN + RAISE NOTICE '%', SQLERRM; + END; + ROLLBACK; +END +$$; +NOTICE: f_get_x(1) +NOTICE: f_print_x(1) +NOTICE: f_get_x(2) +NOTICE: f_print_x(2) -- test in atomic context BEGIN; DO $$ diff --git a/src/pl/plpgsql/src/sql/plpgsql_call.sql b/src/pl/plpgsql/src/sql/plpgsql_call.sql index 4cbda0382e..08c1659ef1 100644 --- a/src/pl/plpgsql/src/sql/plpgsql_call.sql +++ b/src/pl/plpgsql/src/sql/plpgsql_call.sql @@ -557,6 +557,23 @@ BEGIN END $$; +-- test in non-atomic context, except exception block is locally atomic +DO $$ +BEGIN + BEGIN + UPDATE t_test SET x = x + 1; + RAISE NOTICE 'f_get_x(%)', f_get_x(); + CALL f_print_x(f_get_x()); + UPDATE t_test SET x = x + 1; + RAISE NOTICE 'f_get_x(%)', f_get_x(); + CALL f_print_x(f_get_x()); + EXCEPTION WHEN division_by_zero THEN + RAISE NOTICE '%', SQLERRM; + END; + ROLLBACK; +END +$$; + -- test in atomic context BEGIN;