SET sql_mode=ORACLE; # Testing routines with no parameters CREATE FUNCTION f1 RETURN INT AS BEGIN RETURN 10; END; / SHOW CREATE FUNCTION f1; Function f1 sql_mode PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ORACLE,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS,NO_AUTO_CREATE_USER,SIMULTANEOUS_ASSIGNMENT Create Function CREATE DEFINER="root"@"localhost" FUNCTION "f1"() RETURN int(11) AS BEGIN RETURN 10; END character_set_client latin1 collation_connection latin1_swedish_ci Database Collation latin1_swedish_ci SELECT f1(); f1() 10 DROP FUNCTION f1; CREATE PROCEDURE p1 AS BEGIN SET @a=10; END; / SHOW CREATE PROCEDURE p1; Procedure p1 sql_mode PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ORACLE,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS,NO_AUTO_CREATE_USER,SIMULTANEOUS_ASSIGNMENT Create Procedure CREATE DEFINER="root"@"localhost" PROCEDURE "p1"() AS BEGIN SET @a=10; END character_set_client latin1 collation_connection latin1_swedish_ci Database Collation latin1_swedish_ci SET @a=0; CALL p1(); SELECT @a; @a 10 DROP PROCEDURE p1; # Testing ":=" to set the default value of a variable CREATE FUNCTION f1 () RETURN NUMBER(10) AS a NUMBER(10) := 10; BEGIN DECLARE b NUMBER(10) DEFAULT 3; BEGIN RETURN a+b; END; END; / SELECT f1(); f1() 13 DROP FUNCTION f1; # Testing labels CREATE FUNCTION f1 (a INT) RETURN CLOB AS BEGIN <> BEGIN IF a = 1 THEN LEAVE label1; END IF; RETURN 'IS NOT 1'; END label1; RETURN 'IS 1'; END; / SELECT f1(1); f1(1) IS 1 SELECT f1(2); f1(2) IS NOT 1 DROP FUNCTION f1; CREATE FUNCTION f1 (a INT) RETURN INT IS BEGIN <> LOOP IF a = 2 THEN LEAVE label1; END IF; SET a= a-1; END LOOP; RETURN a; END; / SELECT f1(4); f1(4) 2 DROP FUNCTION f1; CREATE FUNCTION f1 (a INT) RETURN INT AS BEGIN <> WHILE a>0 LOOP IF a = 2 THEN LEAVE label1; END IF; SET a= a-1; END LOOP label1; RETURN a; END; / SELECT f1(4); f1(4) 2 DROP FUNCTION f1; CREATE FUNCTION f1 (a INT) RETURN INT AS BEGIN <> REPEAT IF a = 2 THEN LEAVE label1; END IF; SET a= a-1; UNTIL a=0 END REPEAT; RETURN a; END; / SELECT f1(4); f1(4) 2 DROP FUNCTION f1; # Testing IN/OUT/INOUT CREATE PROCEDURE p1 (p1 IN VARCHAR2(10), p2 OUT VARCHAR2(10)) AS BEGIN SET p1='p1new'; SET p2='p2new'; END; / SET @p1='p1', @p2='p2'; CALL p1(@p1, @p2); SELECT @p1, @p2; @p1 @p2 p1 p2new DROP PROCEDURE p1; # Testing Oracle-style assigment CREATE PROCEDURE p1 (p1 OUT VARCHAR2(10)) AS BEGIN p1:= 'p1new'; END; / SET @p1='p1'; CALL p1(@p1); SELECT @p1; @p1 p1new DROP PROCEDURE p1; # Testing that NULL is a valid statement CREATE PROCEDURE p1(a INT) AS BEGIN NULL; END; / DROP PROCEDURE p1; CREATE PROCEDURE p1(a INT) AS a INT:=10; BEGIN IF a=10 THEN NULL; ELSE NULL; END IF; END; / DROP PROCEDURE p1; # Keywords that are OK for table names, but not for SP variables CREATE TABLE function (function int); INSERT INTO function SET function=10; SELECT function.function FROM function; function 10 DROP TABLE function; # Testing that (some) keyword_sp are allowed in Oracle-style assignments CREATE PROCEDURE p1 (action OUT INT) AS BEGIN action:=10; END;/ DROP PROCEDURE p1/ CREATE PROCEDURE p1 (clob OUT INT) AS BEGIN clob:=10; END;/ DROP PROCEDURE p1/ CREATE PROCEDURE p1 (enum OUT INT) AS BEGIN enum:=10; END;/ DROP PROCEDURE p1/ CREATE PROCEDURE p1 (via OUT INT) AS BEGIN via:=10; END;/ DROP PROCEDURE p1/ # Testing keyword_directly_assignable CREATE PROCEDURE p1 (ascii OUT INT) AS BEGIN ascii:=10; END;/ DROP PROCEDURE p1/ CREATE PROCEDURE p1 (backup OUT INT) AS BEGIN backup:=10; END;/ DROP PROCEDURE p1/ CREATE PROCEDURE p1 (binlog OUT INT) AS BEGIN binlog:=10; END;/ DROP PROCEDURE p1/ CREATE PROCEDURE p1 (byte OUT INT) AS BEGIN byte:=10; END;/ DROP PROCEDURE p1/ CREATE PROCEDURE p1 (cache OUT INT) AS BEGIN cache:=10; END;/ DROP PROCEDURE p1/ CREATE PROCEDURE p1 (checksum OUT INT) AS BEGIN checksum:=10; END;/ DROP PROCEDURE p1/ CREATE PROCEDURE p1 (checkpoint OUT INT) AS BEGIN checkpoint:=10; END;/ DROP PROCEDURE p1/ CREATE PROCEDURE p1 (column_add OUT INT) AS BEGIN column_add:=10; END;/ DROP PROCEDURE p1/ CREATE PROCEDURE p1 (column_check OUT INT) AS BEGIN column_check:=10; END;/ DROP PROCEDURE p1/ CREATE PROCEDURE p1 (column_create OUT INT) AS BEGIN column_create:=10; END;/ DROP PROCEDURE p1/ CREATE PROCEDURE p1 (column_delete OUT INT) AS BEGIN column_delete:=10; END;/ DROP PROCEDURE p1/ CREATE PROCEDURE p1 (column_get OUT INT) AS BEGIN column_get:=10; END;/ DROP PROCEDURE p1/ CREATE PROCEDURE p1 (deallocate OUT INT) AS BEGIN deallocate:=10; END;/ DROP PROCEDURE p1/ CREATE PROCEDURE p1 (examined OUT INT) AS BEGIN examined:=10; END;/ DROP PROCEDURE p1/ CREATE PROCEDURE p1 (execute OUT INT) AS BEGIN execute:=10; END;/ DROP PROCEDURE p1/ CREATE PROCEDURE p1 (flush OUT INT) AS BEGIN flush:=10; END;/ DROP PROCEDURE p1/ CREATE PROCEDURE p1 (format OUT INT) AS BEGIN format:=10; END;/ DROP PROCEDURE p1/ CREATE PROCEDURE p1 (get OUT INT) AS BEGIN get:=10; END;/ DROP PROCEDURE p1/ CREATE PROCEDURE p1 (help OUT INT) AS BEGIN help:=10; END;/ DROP PROCEDURE p1/ CREATE PROCEDURE p1 (host OUT INT) AS BEGIN host:=10; END;/ DROP PROCEDURE p1/ CREATE PROCEDURE p1 (install OUT INT) AS BEGIN install:=10; END;/ DROP PROCEDURE p1/ CREATE PROCEDURE p1 (option OUT INT) AS BEGIN option:=10; END;/ DROP PROCEDURE p1/ CREATE PROCEDURE p1 (options OUT INT) AS BEGIN options:=10; END;/ DROP PROCEDURE p1/ CREATE PROCEDURE p1 (owner OUT INT) AS BEGIN owner:=10; END;/ DROP PROCEDURE p1/ CREATE PROCEDURE p1 (parser OUT INT) AS BEGIN parser:=10; END;/ DROP PROCEDURE p1/ CREATE PROCEDURE p1 (port OUT INT) AS BEGIN port:=10; END;/ DROP PROCEDURE p1/ CREATE PROCEDURE p1 (prepare OUT INT) AS BEGIN prepare:=10; END;/ DROP PROCEDURE p1/ CREATE PROCEDURE p1 (remove OUT INT) AS BEGIN remove:=10; END;/ DROP PROCEDURE p1/ CREATE PROCEDURE p1 (reset OUT INT) AS BEGIN reset:=10; END;/ DROP PROCEDURE p1/ CREATE PROCEDURE p1 (restore OUT INT) AS BEGIN restore:=10; END;/ DROP PROCEDURE p1/ CREATE PROCEDURE p1 (security OUT INT) AS BEGIN security:=10; END;/ DROP PROCEDURE p1/ CREATE PROCEDURE p1 (server OUT INT) AS BEGIN server:=10; END;/ DROP PROCEDURE p1/ CREATE PROCEDURE p1 (signed OUT INT) AS BEGIN signed:=10; END;/ DROP PROCEDURE p1/ CREATE PROCEDURE p1 (socket OUT INT) AS BEGIN socket:=10; END;/ DROP PROCEDURE p1/ CREATE PROCEDURE p1 (slave OUT INT) AS BEGIN slave:=10; END;/ DROP PROCEDURE p1/ CREATE PROCEDURE p1 (slaves OUT INT) AS BEGIN slaves:=10; END;/ DROP PROCEDURE p1/ CREATE PROCEDURE p1 (soname OUT INT) AS BEGIN soname:=10; END;/ DROP PROCEDURE p1/ CREATE PROCEDURE p1 (start OUT INT) AS BEGIN start:=10; END;/ DROP PROCEDURE p1/ CREATE PROCEDURE p1 (stop OUT INT) AS BEGIN stop:=10; END;/ DROP PROCEDURE p1/ CREATE PROCEDURE p1 (stored OUT INT) AS BEGIN stored:=10; END;/ DROP PROCEDURE p1/ CREATE PROCEDURE p1 (unicode OUT INT) AS BEGIN unicode:=10; END;/ DROP PROCEDURE p1/ CREATE PROCEDURE p1 (uninstall OUT INT) AS BEGIN uninstall:=10; END;/ DROP PROCEDURE p1/ CREATE PROCEDURE p1 (upgrade OUT INT) AS BEGIN upgrade:=10; END;/ DROP PROCEDURE p1/ CREATE PROCEDURE p1 (wrapper OUT INT) AS BEGIN wrapper:=10; END;/ DROP PROCEDURE p1/ CREATE PROCEDURE p1 (xa OUT INT) AS BEGIN xa:=10; END;/ DROP PROCEDURE p1/ # Testing that keyword_directly_not_assignable does not work in := CREATE PROCEDURE p1 (commit OUT INT) AS BEGIN commit:=10; END;/ ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ':=10; END' at line 1 CREATE PROCEDURE p1 (rollback OUT INT) AS BEGIN rollback:=10; END;/ ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ':=10; END' at line 1 CREATE PROCEDURE p1 (shutdown OUT INT) AS BEGIN shutdown:=10; END;/ ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ':=10; END' at line 1 CREATE PROCEDURE p1 (exception OUT INT) AS BEGIN exception:=10; END;/ ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ':=10; END' at line 1 # Testing that keyword_directly_not_assignable works in SET statements. CREATE PROCEDURE p1 (contains OUT INT) AS BEGIN SET contains=10; END;/ DROP PROCEDURE p1/ CREATE PROCEDURE p1 (language OUT INT) AS BEGIN SET language=10; END;/ DROP PROCEDURE p1/ CREATE PROCEDURE p1 (no OUT INT) AS BEGIN SET no=10; END;/ DROP PROCEDURE p1/ CREATE PROCEDURE p1 (charset OUT INT) AS BEGIN SET charset=10; END;/ DROP PROCEDURE p1/ CREATE PROCEDURE p1 (do OUT INT) AS BEGIN SET do=10; END;/ DROP PROCEDURE p1/ CREATE PROCEDURE p1 (repair OUT INT) AS BEGIN SET repair=10; END;/ DROP PROCEDURE p1/ CREATE PROCEDURE p1 (handler OUT INT) AS BEGIN SET handler=10; END;/ DROP PROCEDURE p1/ CREATE PROCEDURE p1 (open OUT INT) AS BEGIN SET open=10; END;/ DROP PROCEDURE p1/ CREATE PROCEDURE p1 (close OUT INT) AS BEGIN SET close=10; END;/ DROP PROCEDURE p1/ CREATE PROCEDURE p1 (savepoint OUT INT) AS BEGIN SET savepoint=10; END;/ DROP PROCEDURE p1/ CREATE PROCEDURE p1 (truncate OUT INT) AS BEGIN SET truncate=10; END;/ DROP PROCEDURE p1/ CREATE PROCEDURE p1 (begin OUT INT) AS BEGIN SET begin=10; END;/ DROP PROCEDURE p1/ CREATE PROCEDURE p1 (end OUT INT) AS BEGIN SET end=10; END;/ DROP PROCEDURE p1/ CREATE PROCEDURE p1 (exception OUT INT) AS BEGIN SET exception=10; END;/ DROP PROCEDURE p1/ # Testing that keyword_directly_not_assignable works in table/column names CREATE TABLE contains (contains INT); DROP TABLE contains; CREATE TABLE language (language INT); DROP TABLE language; CREATE TABLE no (no INT); DROP TABLE no; CREATE TABLE charset (charset INT); DROP TABLE charset; CREATE TABLE do (do INT); DROP TABLE do; CREATE TABLE repair (repair INT); DROP TABLE repair; CREATE TABLE handler (handler INT); DROP TABLE handler; CREATE TABLE open (open INT); DROP TABLE open; CREATE TABLE close (close INT); DROP TABLE close; CREATE TABLE savepoint (savepoint INT); DROP TABLE savepoint; CREATE TABLE truncate (truncate INT); DROP TABLE truncate; CREATE TABLE begin (begin INT); DROP TABLE begin; CREATE TABLE end (end INT); DROP TABLE end; CREATE TABLE exception (exception INT); DROP TABLE exception; # Testing ELSIF CREATE FUNCTION f1(a INT) RETURN CLOB AS BEGIN IF a=1 THEN RETURN 'a is 1'; ELSIF a=2 THEN RETURN 'a is 2'; ELSE RETURN 'a is unknown'; END IF; END; / SELECT f1(2) FROM DUAL; f1(2) a is 2 DROP FUNCTION f1; # Testing top-level declarations CREATE PROCEDURE p1 (p1 OUT VARCHAR2(10)) AS p2 VARCHAR(10); BEGIN p2:='p1new'; p1:=p2; END; / SET @p1='p1'; CALL p1(@p1); SELECT @p1; @p1 p1new DROP PROCEDURE p1; CREATE FUNCTION f1 (p1 VARCHAR2(10)) RETURN VARCHAR(20) AS p2 VARCHAR(10); BEGIN p2:='new'; RETURN CONCAT(p1, p2); END; / SET @p1='p1'; SELECT f1(@p1); f1(@p1) p1new DROP FUNCTION f1; # Testing non-top declarations CREATE PROCEDURE p1 (p1 OUT VARCHAR2(10)) AS BEGIN DECLARE p2 VARCHAR(10); BEGIN p2:='p1new'; p1:=p2; END; DECLARE t1 VARCHAR(10); t2 VARCHAR(10); BEGIN END; END; / SET @p1='p1'; CALL p1(@p1); SELECT @p1; @p1 p1new DROP PROCEDURE p1; CREATE FUNCTION f1 (p1 VARCHAR2(10)) RETURN VARCHAR(20) AS BEGIN DECLARE p2 VARCHAR(10); BEGIN p2:='new'; RETURN CONCAT(p1, p2); END; DECLARE t1 VARCHAR(10); t2 VARCHAR(10); BEGIN END; END; / SET @p1='p1'; SELECT f1(@p1); f1(@p1) p1new DROP FUNCTION f1; # Testing exceptions CREATE TABLE t1 (c1 INT); CREATE PROCEDURE sp1 (p1 IN VARCHAR2(20), p2 OUT VARCHAR2(30)) IS v1 INT; BEGIN SELECT c1 INTO v1 FROM t1; p2 := p1; EXCEPTION WHEN NOT FOUND THEN BEGIN p2 := 'def'; END; END; / CALL sp1('abc', @a); SELECT @a; @a def DROP PROCEDURE sp1; DROP TABLE t1; CREATE PROCEDURE sp1 (v IN OUT INT, error IN INT) IS BEGIN SIGNAL SQLSTATE '45000' SET MYSQL_ERRNO=error, MESSAGE_TEXT='User defined error!'; v:= 223; EXCEPTION WHEN 30001 THEN BEGIN v:= 113; END; END; / SET @v=10; CALL sp1(@v, 30001); CALL sp1(@v, 30002); ERROR 45000: User defined error! SELECT @v; @v 113 DROP PROCEDURE sp1; CREATE PROCEDURE sp1 (v IN OUT INT, error IN INT) IS BEGIN BEGIN BEGIN SIGNAL SQLSTATE '45000' SET MYSQL_ERRNO=error, MESSAGE_TEXT='User defined error!'; v:= 223; EXCEPTION WHEN 30001 THEN BEGIN v:= 113; END; END; END; END; / SET @v=10; CALL sp1(@v, 30001); SELECT @v; @v 113 SET @v=10; CALL sp1(@v, 30002); ERROR 45000: User defined error! SELECT @v; @v 10 DROP PROCEDURE sp1; # # Testing EXIT statement # CREATE FUNCTION f1 RETURN INT IS i INT := 0; BEGIN EXIT; END; / ERROR 42000: EXIT with no matching label: CREATE FUNCTION f1 RETURN INT IS i INT := 0; BEGIN <> BEGIN <> LOOP EXIT label1; END LOOP; END; END; / ERROR 42000: EXIT with no matching label: label1 CREATE FUNCTION f1 RETURN INT IS i INT := 0; BEGIN LOOP LOOP i:= i + 1; IF i >= 5 THEN EXIT; END IF; END LOOP; i:= i + 100; EXIT; END LOOP; RETURN i; END; / SELECT f1() FROM DUAL; f1() 105 DROP FUNCTION f1; CREATE FUNCTION f1 RETURN INT IS i INT := 0; BEGIN <> LOOP <> LOOP i:= i + 1; IF i >= 5 THEN EXIT label2; END IF; END LOOP; i:= i + 100; EXIT; END LOOP; RETURN i; END; / SELECT f1() FROM DUAL; f1() 105 DROP FUNCTION f1; CREATE FUNCTION f1 RETURN INT IS i INT := 0; BEGIN <> LOOP <> LOOP i:= i + 1; IF i >= 5 THEN EXIT label1; END IF; END LOOP; i:= i + 100; EXIT; END LOOP; RETURN i; END; / SELECT f1() FROM DUAL; f1() 5 DROP FUNCTION f1; CREATE FUNCTION f1 RETURN INT IS i INT := 0; BEGIN LOOP i:= i + 1; EXIT WHEN i >=5; END LOOP; RETURN i; END; / SELECT f1() FROM DUAL; f1() 5 DROP FUNCTION f1; CREATE FUNCTION f1 RETURN INT IS i INT := 0; BEGIN <> LOOP <> LOOP i:= i + 1; EXIT label2 WHEN i >= 5; END LOOP; i:= i + 100; EXIT; END LOOP; RETURN i; END; / SELECT f1() FROM DUAL; f1() 105 DROP FUNCTION f1; CREATE FUNCTION f1 RETURN INT IS i INT := 0; BEGIN <> LOOP <> LOOP i:= i + 1; EXIT label1 WHEN i >= 5; END LOOP; i:= i + 100; EXIT; END LOOP; RETURN i; END; / SELECT f1() FROM DUAL; f1() 5 DROP FUNCTION f1; # Testing CURSOR declaration CREATE TABLE t1 (a INT); INSERT INTO t1 VALUES (1); CREATE FUNCTION f1 RETURN INT AS v_a INT:=10; CURSOR c IS SELECT a FROM t1; BEGIN OPEN c; FETCH c INTO v_a; CLOSE c; RETURN v_a; EXCEPTION WHEN OTHERS THEN RETURN -1; END; / SELECT f1() FROM DUAL; f1() 1 DROP FUNCTION f1; DROP TABLE t1; # Testing RETURN in procedures CREATE PROCEDURE p1 (a IN OUT INT) AS BEGIN RETURN 10; END; / ERROR 42000: RETURN is only allowed in a FUNCTION CREATE FUNCTION f1 (a INT) RETURN INT AS BEGIN RETURN; END; / ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '; END' at line 4 CREATE PROCEDURE p1 (a IN OUT INT) AS BEGIN IF a < 10 THEN BEGIN a:= a - 1; RETURN; END; END IF; a:= a + 1; EXCEPTION WHEN OTHERS THEN RETURN; END; / SET @v=10; CALL p1(@v); SELECT @v; @v 11 SET @v=9; CALL p1(@v); SELECT @v; @v 8 DROP PROCEDURE p1; CREATE PROCEDURE p1 (a IN OUT INT) AS BEGIN DROP TABLE t1_non_existent; EXCEPTION WHEN OTHERS THEN BEGIN a:= 100; RETURN; END; END; / SET @v=10; CALL p1(@v); SELECT @v; @v 100 DROP PROCEDURE p1; # Testing WHILE loop CREATE PROCEDURE p1 (a IN OUT INT) AS i INT:= 1; j INT:= 3; BEGIN WHILE i<=j LOOP a:= a + i; i:= i + 1; END LOOP; END; / SET @v=0; CALL p1(@v); SELECT @v; @v 6 DROP PROCEDURE p1; CREATE PROCEDURE p1 (a IN OUT INT) AS i INT:= 1; j INT:= 3; BEGIN <