Skip to content

Commit b1caefd

Browse files
authored
Merge pull request IvorySQL#972 from rophy/feat/user-exception
feat: add user-defined EXCEPTION support for PL/iSQL
2 parents 8002be5 + e020f53 commit b1caefd

File tree

12 files changed

+1158
-6
lines changed

12 files changed

+1158
-6
lines changed

src/pl/plisql/src/Makefile

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ OBJS = \
4747
pl_scanner.o \
4848
pl_subproc_function.o \
4949
pl_package.o \
50+
pl_exception_type.o \
5051
$(top_builddir)/src/backend/oracle_parser/ora_scan.o
5152

5253
DATA = plisql.control plisql--1.0.sql
@@ -56,7 +57,8 @@ ORACLE_REGRESS_OPTS = --dbname=$(PL_TESTDB)
5657
REGRESS = plisql_array plisql_call plisql_control plisql_copy plisql_domain \
5758
plisql_record plisql_cache plisql_simple plisql_transaction \
5859
plisql_trap plisql_trigger plisql_varprops plisql_nested_subproc \
59-
plisql_nested_subproc2 plisql_out_parameter plisql_type_rowtype
60+
plisql_nested_subproc2 plisql_out_parameter plisql_type_rowtype \
61+
plisql_exception
6062

6163
# where to find ora_gen_keywordlist.pl and subsidiary files
6264
TOOLSDIR = $(top_srcdir)/src/tools
Lines changed: 351 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,351 @@
1+
--
2+
-- Test user-defined EXCEPTION type declarations
3+
--
4+
-- Note: This test verifies EXCEPTION type declarations compile correctly.
5+
-- RAISE and WHEN handler support for user-defined exceptions is not yet
6+
-- implemented and is commented out below.
7+
--
8+
-- Test 1: Basic EXCEPTION declaration in package body
9+
CREATE OR REPLACE PACKAGE test_exc_pkg1 IS
10+
PROCEDURE test_proc;
11+
END test_exc_pkg1;
12+
/
13+
CREATE OR REPLACE PACKAGE BODY test_exc_pkg1 IS
14+
bad_interval EXCEPTION; -- User-defined exception
15+
PROCEDURE test_proc IS
16+
BEGIN
17+
RAISE INFO 'Package with EXCEPTION compiled successfully';
18+
END test_proc;
19+
END test_exc_pkg1;
20+
/
21+
-- Verify the package body was created
22+
SELECT 'Package test_exc_pkg1 created' AS result;
23+
result
24+
-------------------------------
25+
Package test_exc_pkg1 created
26+
(1 row)
27+
28+
-- Test 2: Multiple EXCEPTION declarations
29+
CREATE OR REPLACE PACKAGE test_exc_pkg2 IS
30+
PROCEDURE multi_exc_test;
31+
END test_exc_pkg2;
32+
/
33+
CREATE OR REPLACE PACKAGE BODY test_exc_pkg2 IS
34+
exc_invalid_data EXCEPTION;
35+
exc_timeout EXCEPTION;
36+
exc_not_found EXCEPTION;
37+
PROCEDURE multi_exc_test IS
38+
BEGIN
39+
RAISE INFO 'Multiple exceptions declared successfully';
40+
END multi_exc_test;
41+
END test_exc_pkg2;
42+
/
43+
SELECT 'Package test_exc_pkg2 with multiple exceptions created' AS result;
44+
result
45+
--------------------------------------------------------
46+
Package test_exc_pkg2 with multiple exceptions created
47+
(1 row)
48+
49+
-- Test 3: EXCEPTION in standalone procedure (should work in declaration block)
50+
CREATE OR REPLACE PROCEDURE test_standalone_exc IS
51+
my_exception EXCEPTION;
52+
BEGIN
53+
RAISE INFO 'Standalone procedure with EXCEPTION compiled';
54+
END;
55+
/
56+
SELECT 'Standalone procedure with EXCEPTION created' AS result;
57+
result
58+
---------------------------------------------
59+
Standalone procedure with EXCEPTION created
60+
(1 row)
61+
62+
-- Test 4: EXCEPTION mixed with other variable types
63+
CREATE OR REPLACE PACKAGE test_exc_pkg3 IS
64+
PROCEDURE mixed_decl_test;
65+
END test_exc_pkg3;
66+
/
67+
CREATE OR REPLACE PACKAGE BODY test_exc_pkg3 IS
68+
v_counter NUMBER := 0;
69+
exc_custom EXCEPTION;
70+
v_name VARCHAR2(100) := 'Test';
71+
exc_another EXCEPTION;
72+
v_date DATE;
73+
PROCEDURE mixed_decl_test IS
74+
BEGIN
75+
RAISE INFO 'Mixed declarations compiled successfully';
76+
END mixed_decl_test;
77+
END test_exc_pkg3;
78+
/
79+
SELECT 'Package test_exc_pkg3 with mixed declarations created' AS result;
80+
result
81+
-------------------------------------------------------
82+
Package test_exc_pkg3 with mixed declarations created
83+
(1 row)
84+
85+
--
86+
-- Test 5: RAISE and exception handling
87+
--
88+
CREATE OR REPLACE PACKAGE test_exc_raise IS
89+
PROCEDURE test_raise_catch;
90+
END test_exc_raise;
91+
/
92+
CREATE OR REPLACE PACKAGE BODY test_exc_raise IS
93+
custom_error EXCEPTION;
94+
PROCEDURE test_raise_catch IS
95+
BEGIN
96+
RAISE custom_error; -- Raise user-defined exception
97+
EXCEPTION
98+
WHEN custom_error THEN -- Catch user-defined exception
99+
RAISE INFO 'Successfully caught custom_error';
100+
END test_raise_catch;
101+
END test_exc_raise;
102+
/
103+
-- Test execution
104+
BEGIN
105+
test_exc_raise.test_raise_catch();
106+
END;
107+
/
108+
INFO: Successfully caught custom_error
109+
DROP PACKAGE test_exc_raise;
110+
--
111+
-- Test 6: PRAGMA EXCEPTION_INIT basic usage
112+
--
113+
CREATE OR REPLACE PACKAGE test_pragma_init IS
114+
PROCEDURE test_basic_pragma;
115+
END test_pragma_init;
116+
/
117+
CREATE OR REPLACE PACKAGE BODY test_pragma_init IS
118+
my_exception EXCEPTION;
119+
PRAGMA EXCEPTION_INIT(my_exception, -20001);
120+
PROCEDURE test_basic_pragma IS
121+
BEGIN
122+
RAISE INFO 'PRAGMA EXCEPTION_INIT compiled successfully';
123+
END test_basic_pragma;
124+
END test_pragma_init;
125+
/
126+
-- Test execution
127+
BEGIN
128+
test_pragma_init.test_basic_pragma();
129+
END;
130+
/
131+
INFO: PRAGMA EXCEPTION_INIT compiled successfully
132+
SELECT 'PRAGMA EXCEPTION_INIT basic test passed' AS result;
133+
result
134+
-----------------------------------------
135+
PRAGMA EXCEPTION_INIT basic test passed
136+
(1 row)
137+
138+
--
139+
-- Test 7: PRAGMA EXCEPTION_INIT with RAISE and WHEN
140+
--
141+
CREATE OR REPLACE PACKAGE test_pragma_raise IS
142+
PROCEDURE test_pragma_exception;
143+
END test_pragma_raise;
144+
/
145+
CREATE OR REPLACE PACKAGE BODY test_pragma_raise IS
146+
custom_exc EXCEPTION;
147+
PRAGMA EXCEPTION_INIT(custom_exc, -20002);
148+
PROCEDURE test_pragma_exception IS
149+
BEGIN
150+
RAISE custom_exc;
151+
EXCEPTION
152+
WHEN custom_exc THEN
153+
RAISE INFO 'Caught exception with PRAGMA EXCEPTION_INIT';
154+
END test_pragma_exception;
155+
END test_pragma_raise;
156+
/
157+
-- Test execution
158+
BEGIN
159+
test_pragma_raise.test_pragma_exception();
160+
END;
161+
/
162+
INFO: Caught exception with PRAGMA EXCEPTION_INIT
163+
--
164+
-- Test 8: PRAGMA EXCEPTION_INIT in procedure
165+
--
166+
CREATE OR REPLACE PROCEDURE test_pragma_proc IS
167+
my_exc EXCEPTION;
168+
PRAGMA EXCEPTION_INIT(my_exc, -20003);
169+
BEGIN
170+
RAISE INFO 'PRAGMA EXCEPTION_INIT in procedure works';
171+
RAISE my_exc;
172+
EXCEPTION
173+
WHEN my_exc THEN
174+
RAISE INFO 'Exception caught in procedure';
175+
END;
176+
/
177+
-- Test execution
178+
BEGIN
179+
test_pragma_proc();
180+
END;
181+
/
182+
INFO: PRAGMA EXCEPTION_INIT in procedure works
183+
INFO: Exception caught in procedure
184+
SELECT 'PRAGMA EXCEPTION_INIT in procedure test passed' AS result;
185+
result
186+
------------------------------------------------
187+
PRAGMA EXCEPTION_INIT in procedure test passed
188+
(1 row)
189+
190+
--
191+
-- Test 9: Multiple PRAGMA EXCEPTION_INIT declarations
192+
--
193+
CREATE OR REPLACE PACKAGE test_multi_pragma IS
194+
PROCEDURE test_multiple;
195+
END test_multi_pragma;
196+
/
197+
CREATE OR REPLACE PACKAGE BODY test_multi_pragma IS
198+
exc1 EXCEPTION;
199+
PRAGMA EXCEPTION_INIT(exc1, -20011);
200+
exc2 EXCEPTION;
201+
PRAGMA EXCEPTION_INIT(exc2, -20012);
202+
exc3 EXCEPTION;
203+
PRAGMA EXCEPTION_INIT(exc3, -20013);
204+
PROCEDURE test_multiple IS
205+
BEGIN
206+
RAISE INFO 'Multiple PRAGMA EXCEPTION_INIT declarations work';
207+
END test_multiple;
208+
END test_multi_pragma;
209+
/
210+
BEGIN
211+
test_multi_pragma.test_multiple();
212+
END;
213+
/
214+
INFO: Multiple PRAGMA EXCEPTION_INIT declarations work
215+
SELECT 'Multiple PRAGMA EXCEPTION_INIT test passed' AS result;
216+
result
217+
--------------------------------------------
218+
Multiple PRAGMA EXCEPTION_INIT test passed
219+
(1 row)
220+
221+
--
222+
-- Test 10: PRAGMA EXCEPTION_INIT with positive error codes
223+
-- Oracle documentation: Valid codes are 100 or any negative integer >= -1000000 (except -1403)
224+
-- This test verifies positive error codes: only 100 is accepted, all others are rejected.
225+
--
226+
-- Test 10a: Valid positive error code 100 (should succeed)
227+
CREATE OR REPLACE PACKAGE test_pragma_positive_100 IS
228+
PROCEDURE test_positive;
229+
END test_pragma_positive_100;
230+
/
231+
CREATE OR REPLACE PACKAGE BODY test_pragma_positive_100 IS
232+
exc_100 EXCEPTION;
233+
PRAGMA EXCEPTION_INIT(exc_100, 100); -- Oracle accepts: ANSI NO_DATA_FOUND
234+
PROCEDURE test_positive IS
235+
BEGIN
236+
RAISE INFO 'Error code 100 accepted (ANSI NO_DATA_FOUND)';
237+
END test_positive;
238+
END test_pragma_positive_100;
239+
/
240+
BEGIN
241+
test_pragma_positive_100.test_positive();
242+
END;
243+
/
244+
INFO: Error code 100 accepted (ANSI NO_DATA_FOUND)
245+
DROP PACKAGE test_pragma_positive_100;
246+
-- Test 10b: Invalid positive error code 1 (should fail with PLS-00701)
247+
CREATE OR REPLACE PACKAGE test_pragma_positive_1 IS
248+
exc_1 EXCEPTION;
249+
PRAGMA EXCEPTION_INIT(exc_1, 1); -- Oracle rejects: positive except 100
250+
END test_pragma_positive_1;
251+
/
252+
ERROR: illegal ORACLE error number 1 for PRAGMA EXCEPTION_INIT
253+
LINE 2: PRAGMA EXCEPTION_INIT(exc_1, 1); -- Oracle rejects: posit...
254+
^
255+
QUERY: exc_1 EXCEPTION;
256+
PRAGMA EXCEPTION_INIT(exc_1, 1); -- Oracle rejects: positive except 100
257+
END test_pragma_positive_1
258+
-- Test 10c: Invalid positive error code 1000000 (should fail with PLS-00701)
259+
CREATE OR REPLACE PACKAGE test_pragma_positive_1000000 IS
260+
exc_1000000 EXCEPTION;
261+
PRAGMA EXCEPTION_INIT(exc_1000000, 1000000); -- Oracle rejects: positive except 100
262+
END test_pragma_positive_1000000;
263+
/
264+
ERROR: illegal ORACLE error number 1000000 for PRAGMA EXCEPTION_INIT
265+
LINE 2: PRAGMA EXCEPTION_INIT(exc_1000000, 1000000); -- Oracle re...
266+
^
267+
QUERY: exc_1000000 EXCEPTION;
268+
PRAGMA EXCEPTION_INIT(exc_1000000, 1000000); -- Oracle rejects: positive except 100
269+
END test_pragma_positive_1000000
270+
SELECT 'PRAGMA EXCEPTION_INIT positive error code tests completed' AS result;
271+
result
272+
-----------------------------------------------------------
273+
PRAGMA EXCEPTION_INIT positive error code tests completed
274+
(1 row)
275+
276+
--
277+
-- Test 11: PRAGMA EXCEPTION_INIT with negative error codes and boundary
278+
-- Oracle documentation: Valid codes are 100 or any negative integer >= -1000000 (except -1403)
279+
-- This test verifies the -1000000 boundary and specifically rejected negative codes.
280+
--
281+
-- Test 11a: Valid error code -1000000 (should succeed - at boundary)
282+
CREATE OR REPLACE PACKAGE test_pragma_minus_1000000 IS
283+
PROCEDURE test_boundary;
284+
END test_pragma_minus_1000000;
285+
/
286+
CREATE OR REPLACE PACKAGE BODY test_pragma_minus_1000000 IS
287+
exc_boundary EXCEPTION;
288+
PRAGMA EXCEPTION_INIT(exc_boundary, -1000000); -- At the boundary
289+
PROCEDURE test_boundary IS
290+
BEGIN
291+
RAISE INFO 'Error code -1000000 accepted (at boundary)';
292+
END test_boundary;
293+
END test_pragma_minus_1000000;
294+
/
295+
BEGIN
296+
test_pragma_minus_1000000.test_boundary();
297+
END;
298+
/
299+
INFO: Error code -1000000 accepted (at boundary)
300+
DROP PACKAGE test_pragma_minus_1000000;
301+
-- Test 11b: Invalid error code -1000001 (should fail with PLS-00701 - beyond boundary)
302+
CREATE OR REPLACE PACKAGE test_pragma_minus_1000001 IS
303+
exc_beyond EXCEPTION;
304+
PRAGMA EXCEPTION_INIT(exc_beyond, -1000001); -- Beyond boundary
305+
END test_pragma_minus_1000001;
306+
/
307+
ERROR: illegal ORACLE error number -1000001 for PRAGMA EXCEPTION_INIT
308+
LINE 2: PRAGMA EXCEPTION_INIT(exc_beyond, -1000001); -- Beyond bo...
309+
^
310+
QUERY: exc_beyond EXCEPTION;
311+
PRAGMA EXCEPTION_INIT(exc_beyond, -1000001); -- Beyond boundary
312+
END test_pragma_minus_1000001
313+
-- Test 11c: Invalid error code -1403 (should fail with PLS-00701)
314+
CREATE OR REPLACE PACKAGE test_pragma_minus_1403 IS
315+
exc_1403 EXCEPTION;
316+
PRAGMA EXCEPTION_INIT(exc_1403, -1403); -- Oracle-specific NO_DATA_FOUND, must use 100
317+
END test_pragma_minus_1403;
318+
/
319+
ERROR: illegal ORACLE error number -1403 for PRAGMA EXCEPTION_INIT
320+
LINE 2: PRAGMA EXCEPTION_INIT(exc_1403, -1403); -- Oracle-specifi...
321+
^
322+
QUERY: exc_1403 EXCEPTION;
323+
PRAGMA EXCEPTION_INIT(exc_1403, -1403); -- Oracle-specific NO_DATA_FOUND, must use 100
324+
END test_pragma_minus_1403
325+
-- Test 11d: Invalid error code 0 (should fail with PLS-00701)
326+
CREATE OR REPLACE PACKAGE test_pragma_zero IS
327+
exc_zero EXCEPTION;
328+
PRAGMA EXCEPTION_INIT(exc_zero, 0); -- Zero is rejected by Oracle
329+
END test_pragma_zero;
330+
/
331+
ERROR: illegal ORACLE error number 0 for PRAGMA EXCEPTION_INIT
332+
LINE 2: PRAGMA EXCEPTION_INIT(exc_zero, 0); -- Zero is rejected b...
333+
^
334+
QUERY: exc_zero EXCEPTION;
335+
PRAGMA EXCEPTION_INIT(exc_zero, 0); -- Zero is rejected by Oracle
336+
END test_pragma_zero
337+
SELECT 'PRAGMA EXCEPTION_INIT negative error code tests completed' AS result;
338+
result
339+
-----------------------------------------------------------
340+
PRAGMA EXCEPTION_INIT negative error code tests completed
341+
(1 row)
342+
343+
-- Cleanup
344+
DROP PACKAGE test_pragma_init;
345+
DROP PACKAGE test_pragma_raise;
346+
DROP PROCEDURE test_pragma_proc;
347+
DROP PACKAGE test_multi_pragma;
348+
DROP PACKAGE test_exc_pkg1;
349+
DROP PACKAGE test_exc_pkg2;
350+
DROP PACKAGE test_exc_pkg3;
351+
DROP PROCEDURE test_standalone_exc;

0 commit comments

Comments
 (0)