Skip to content

Commit 021f549

Browse files
committed
feat: implement PRAGMA AUTONOMOUS_TRANSACTION for PL/iSQL
Add Oracle-compatible autonomous transactions using dblink to execute functions/procedures in separate database sessions with independent transaction control.
1 parent 7261f1c commit 021f549

File tree

10 files changed

+1386
-23
lines changed

10 files changed

+1386
-23
lines changed

src/pl/plisql/src/Makefile

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ rpath =
3939

4040
OBJS = \
4141
$(WIN32RES) \
42+
pl_autonomous.o \
4243
pl_comp.o \
4344
pl_exec.o \
4445
pl_funcs.o \
@@ -52,13 +53,17 @@ OBJS = \
5253

5354
DATA = plisql.control plisql--1.0.sql
5455

56+
# dblink extension is required for autonomous transactions
57+
# Install dblink into the test instance
58+
EXTRA_INSTALL = contrib/dblink
59+
5560
ORACLE_REGRESS_OPTS = --dbname=$(PL_TESTDB)
5661

5762
REGRESS = plisql_array plisql_call plisql_control plisql_copy plisql_domain \
5863
plisql_record plisql_cache plisql_simple plisql_transaction \
5964
plisql_trap plisql_trigger plisql_varprops plisql_nested_subproc \
6065
plisql_nested_subproc2 plisql_out_parameter plisql_type_rowtype \
61-
plisql_exception
66+
plisql_exception plisql_autonomous
6267

6368
# where to find ora_gen_keywordlist.pl and subsidiary files
6469
TOOLSDIR = $(top_srcdir)/src/tools
@@ -87,6 +92,7 @@ install-headers: installdirs
8792
$(INSTALL_DATA) '$(srcdir)/plisql.h' '$(DESTDIR)$(includedir_server)'
8893
$(INSTALL_DATA) '$(srcdir)/pl_subproc_function.h' '$(DESTDIR)$(includedir_server)'
8994
$(INSTALL_DATA) '$(srcdir)/pl_package.h' '$(DESTDIR)$(includedir_server)'
95+
$(INSTALL_DATA) '$(srcdir)/pl_autonomous.h' '$(DESTDIR)$(includedir_server)'
9096

9197
uninstall-data:
9298
rm -f $(addprefix '$(DESTDIR)$(datadir)/extension'/, $(notdir $(DATA)))
@@ -95,12 +101,13 @@ uninstall-headers:
95101
rm -f '$(DESTDIR)$(includedir_server)/plisql.h'
96102
rm -f '$(DESTDIR)$(includedir_server)/pl_subproc_function.h'
97103
rm -f '$(DESTDIR)$(includedir_server)/pl_package.h'
104+
rm -f '$(DESTDIR)$(includedir_server)/pl_autonomous.h'
98105

99106
.PHONY: install-data install-headers uninstall-data uninstall-headers
100107

101108

102109
# Force these dependencies to be known even without dependency info built:
103-
pl_gram.o pl_handler.o pl_comp.o pl_exec.o pl_funcs.o pl_scanner.o: plisql.h pl_gram.h plerrcodes.h pl_subproc_function.h pl_package.h
110+
pl_gram.o pl_handler.o pl_comp.o pl_exec.o pl_funcs.o pl_scanner.o pl_autonomous.o: plisql.h pl_gram.h plerrcodes.h pl_subproc_function.h pl_package.h pl_autonomous.h
104111
pl_scanner.o: pl_reserved_kwlist_d.h pl_unreserved_kwlist_d.h
105112

106113
# See notes in src/backend/parser/Makefile about the following two rules
Lines changed: 227 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,227 @@
1+
NOTICE: extension "dblink" already exists, skipping
2+
CREATE EXTENSION
3+
CREATE TABLE
4+
CREATE PROCEDURE
5+
WARNING: there is no transaction in progress
6+
COMMIT
7+
CALL
8+
id | msg | tx_state
9+
----+------------+-----------
10+
1 | basic test | committed
11+
(1 row)
12+
13+
CREATE PROCEDURE
14+
WARNING: there is no transaction in progress
15+
COMMIT
16+
CALL
17+
id | msg | tx_state
18+
----+-------------+-----------
19+
2 | with params | committed
20+
(1 row)
21+
22+
CREATE PROCEDURE
23+
WARNING: there is no transaction in progress
24+
COMMIT
25+
BEGIN
26+
INSERT 0 1
27+
CALL
28+
INSERT 0 1
29+
ROLLBACK
30+
id | msg | tx_state
31+
-----+------------+-----------
32+
200 | autonomous | committed
33+
(1 row)
34+
35+
CREATE PROCEDURE
36+
WARNING: there is no transaction in progress
37+
COMMIT
38+
CALL
39+
id | msg
40+
----+------------------------
41+
4 | multi-type (bool=true)
42+
(1 row)
43+
44+
CREATE PROCEDURE
45+
WARNING: there is no transaction in progress
46+
COMMIT
47+
CALL
48+
id | msg
49+
----+----------
50+
5 | NULL msg
51+
(1 row)
52+
53+
CREATE PROCEDURE
54+
WARNING: there is no transaction in progress
55+
COMMIT
56+
CALL
57+
CALL
58+
CALL
59+
id | msg
60+
----+------------
61+
6 | sequential
62+
7 | sequential
63+
8 | sequential
64+
(3 rows)
65+
66+
TRUNCATE TABLE
67+
CREATE PROCEDURE
68+
WARNING: there is no transaction in progress
69+
COMMIT
70+
BEGIN
71+
INSERT 0 1
72+
CALL
73+
INSERT 0 1
74+
count_in_tx
75+
-------------
76+
3
77+
(1 row)
78+
79+
ROLLBACK
80+
id | msg | tx_state
81+
------+----------------+-----------
82+
2000 | should persist | committed
83+
(1 row)
84+
85+
CREATE PROCEDURE
86+
WARNING: there is no transaction in progress
87+
COMMIT
88+
CALL
89+
DROP EXTENSION
90+
CREATE EXTENSION
91+
CALL
92+
id | msg
93+
----+----------
94+
9 | oid test
95+
10 | oid test
96+
(2 rows)
97+
98+
CREATE FUNCTION
99+
WARNING: there is no transaction in progress
100+
COMMIT
101+
doubled_value
102+
---------------
103+
100
104+
(1 row)
105+
106+
id | msg
107+
----+---------------
108+
50 | function test
109+
(1 row)
110+
111+
CREATE FUNCTION
112+
WARNING: there is no transaction in progress
113+
COMMIT
114+
null_result
115+
-------------
116+
117+
(1 row)
118+
119+
id | msg
120+
----+------------------
121+
51 | null return test
122+
(1 row)
123+
124+
CREATE FUNCTION
125+
WARNING: there is no transaction in progress
126+
COMMIT
127+
ERROR: relation "nonexistent_table" does not exist
128+
CONTEXT: PL/iSQL function test_function_error() line 6 at SQL statement
129+
while executing query on unnamed dblink connection
130+
SQL statement "SELECT * FROM dblink('dbname=''testdb'' host=localhost port=5432', 'SET ivorysql.compatible_mode = oracle; SET plisql.inside_autonomous_transaction = true; SELECT public.test_function_error();') AS t(result pg_catalog.int4)"
131+
PL/iSQL function test_function_error() during function entry
132+
CREATE FUNCTION
133+
WARNING: there is no transaction in progress
134+
COMMIT
135+
text_result
136+
-----------------------
137+
test data - processed
138+
(1 row)
139+
140+
id | msg
141+
----+-----------------------
142+
52 | test data - processed
143+
(1 row)
144+
145+
CREATE FUNCTION
146+
CREATE FUNCTION
147+
WARNING: there is no transaction in progress
148+
COMMIT
149+
nested_result
150+
---------------
151+
175
152+
(1 row)
153+
154+
id | msg
155+
-----+----------------
156+
60 | outer function
157+
160 | inner function
158+
(2 rows)
159+
160+
CREATE FUNCTION
161+
WARNING: there is no transaction in progress
162+
COMMIT
163+
numeric_result
164+
----------------
165+
115.5750
166+
(1 row)
167+
168+
id | msg
169+
----+-------------------
170+
53 | numeric: 115.5750
171+
(1 row)
172+
173+
CREATE FUNCTION
174+
WARNING: there is no transaction in progress
175+
COMMIT
176+
date_result
177+
-------------
178+
2025-12-05
179+
(1 row)
180+
181+
id | msg
182+
----+------------------
183+
54 | date: 2025-12-05
184+
(1 row)
185+
186+
CREATE FUNCTION
187+
WARNING: there is no transaction in progress
188+
COMMIT
189+
bool_true_result
190+
------------------
191+
t
192+
(1 row)
193+
194+
bool_false_result
195+
-------------------
196+
f
197+
(1 row)
198+
199+
id | msg
200+
----+----------------
201+
55 | boolean: true
202+
55 | boolean: false
203+
(2 rows)
204+
205+
status
206+
--------------------------------------------
207+
All autonomous transaction tests completed
208+
(1 row)
209+
210+
DROP PROCEDURE
211+
DROP PROCEDURE
212+
DROP PROCEDURE
213+
DROP PROCEDURE
214+
DROP PROCEDURE
215+
DROP PROCEDURE
216+
DROP PROCEDURE
217+
DROP PROCEDURE
218+
DROP FUNCTION
219+
DROP FUNCTION
220+
DROP FUNCTION
221+
DROP FUNCTION
222+
DROP FUNCTION
223+
DROP FUNCTION
224+
DROP FUNCTION
225+
DROP FUNCTION
226+
DROP FUNCTION
227+
DROP TABLE

0 commit comments

Comments
 (0)