Skip to main content
Version: Devel

PL/iSQL

PL/iSQL is IvorySQL’s procedural language for writing custom Functions, Procedures, and Packages for IvorySQL. PL/iSQL is derived from PostgreSQL’s PL/pgsql with additional functionality while in the syntaxial terms PL/iSQL is more close to Oracle’s PL/SQL. This document describes the basic structure and constructs of PL/iSQL programs.

Structure of PL/iSQL Programs

iSQL is a procedural, block-structured language that supports four different types of programs, i.e. PACKAGES, PROCEDURES, FUNCTIONS, and TRIGGERS. iSQL uses the same block structure for each type of supported program. A block consists of up to three sections. Declaration section, executable, and exception sections. While declaration and exception sections are optional.

[DECLARE
declarations]
BEGIN
statements
[ EXCEPTION
WHEN <exception_condition> THEN
statements]
END;

At very minimal, a block can consist of just an executable section that contains one or more iSQL statements within the BEGIN and END keywords.

CREATE OR REPLACE FUNCTION null_func() RETURN VOID AS
BEGIN
NULL;
END;
/

All keywords are case-insensitive. Identifiers are implicitly converted to lower case unless double-quoted, just as they are in ordinary SQL commands. The declaration section can be used to declare variables and cursors and depending upon the context of where the block is used, the declaration section may begin with the keyword DECLARE.

CREATE OR REPLACE FUNCTION null_func() RETURN VOID AS
DECLARE
quantity integer := 30;
c_row pg_class%ROWTYPE;
r_cursor refcursor;
CURSOR c1 RETURN pg_proc%ROWTYPE;
BEGIN
NULL;
end;
/

The optional exception section can also be included within the BEGIN - END block. The exception section begins with the keyword, EXCEPTION, and continues until the end of the block in which it appears. If an exception is thrown by a statement within the block, program control goes to the exception section where the thrown exception may or may not be handled depending upon the exception and the contents of the exception section.

CREATE OR REPLACE FUNCTION reraise_test() RETURN void AS
BEGIN

BEGIN
RAISE syntax_error;
EXCEPTION
WHEN syntax_error THEN

BEGIN
raise notice 'exception % thrown in inner block, reraising', sqlerrm;
RAISE;
EXCEPTION
WHEN OTHERS THEN
raise notice 'RIGHT - exception % caught in inner block', sqlerrm;
END;
END;
EXCEPTION
WHEN OTHERS THEN
raise notice 'WRONG - exception % caught in outer block', sqlerrm;
END;
/
NOTE

Similar to PL/pgSQL, PL/iSQL uses BEGIN/END for grouping statements, and they are not to be confused with the similarly-named SQL commands for transaction control. PL/iSQL's BEGIN/END are only for grouping; they do not start or end a transaction

psql support for PL/iSQL programs

For creating the PL/iSQL programs from psql client you can either use the dollar quote syntax similar to PL/pgSQL

CREATE FUNCTION func() RETURNS void as
$$
..
end$$ language plisql;

Alternatively, you can use Oracle compatible syntax without $$ quote and language specification and end the program definition using / (forward slash). The / (forward slash) has to be on newline

CREATE FUNCTION func() RETURN void AS

END;
/

PL/iSQL programs syntax

PROCEDURES

CREATE [OR REPLACE] PROCEDURE procedure_name [(parameter_list)]
is
[DECLARE]
-- variable declaration
BEGIN
-- stored procedure body
END;
/

FUNCTIONS

CREATE [OR REPLACE] FUNCTION function_name ([parameter_list])
RETURN return_type AS
[DECLARE]
-- variable declaration
BEGIN
-- function body
return statement
END;
/

PACKAGES

PACKAGE HEADER

CREATE [ OR REPLACE ] PACKAGE [schema.] *package_name* [invoker_rights_clause] [IS | AS] 
item_list[, item_list ...]
END [*package_name*];


invoker_rights_clause:
AUTHID [CURRENT_USER | DEFINER]

item_list:
[
function_declaration |
procedure_declaration |
type_definition |
cursor_declaration |
item_declaration
]


function_declaration:
FUNCTION function_name [(parameter_declaration[, ...])] RETURN datatype;

procedure_declaration:
PROCEDURE procedure_name [(parameter_declaration[, ...])]

type_definition:
record_type_definition |
ref_cursor_type_definition

cursor_declaration:
CURSOR name [(cur_param_decl[, ...])] RETURN rowtype;

item_declaration:
cursor_declaration |
cursor_variable_declaration |
record_variable_declaration |
variable_declaration |

record_type_definition:
TYPE record_type IS RECORD ( variable_declaration [, variable_declaration]... ) ;

ref_cursor_type_definition:
TYPE type IS REF CURSOR [ RETURN type%ROWTYPE ];

cursor_variable_declaration:
curvar curtype;

record_variable_declaration:
recvar { record_type | rowtype_attribute | record_type%TYPE };

variable_declaration:
varname datatype [ [ NOT NULL ] := expr ]

parameter_declaration:
parameter_name [IN] datatype [[:= | DEFAULT] expr]

PACKAGE BODY

CREATE [ OR REPLACE ] PACKAGE BODY [schema.] package_name [IS | AS]
[item_list[, item_list ...]] |
item_list_2 [, item_list_2 ...]
[initialize_section]
END [package_name];


initialize_section:
BEGIN statement[, ...]

item_list:
[
function_declaration |
procedure_declaration |
type_definition |
cursor_declaration |
item_declaration
]

item_list_2:
[
function_declaration
function_definition
procedure_declaration
procedure_definition
cursor_definition
]

function_definition:
FUNCTION function_name [(parameter_declaration[, ...])] RETURN datatype [IS | AS]
[declare_section] body;

procedure_definition:
PROCEDURE procedure_name [(parameter_declaration[, ...])] [IS | AS]
[declare_section] body;

cursor_definition:
CURSOR name [(cur_param_decl[, ...])] RETURN rowtype IS select_statement;

body:
BEGIN statement[, ...] END [name];

statement:
[<<LABEL>>] pl_statments[, ...];

Refer to IvorySQL packages documentation for more details.