Exporting Packages

You can directly export Oracle packages as Postgres Pro packages using ora2pgpro by setting the TYPE configuration option to PACKAGE. ora2pgpro finds the package, downloads and processes it, and reconstructs the abstract syntax tree (AST) representing the source code in the sources directory under the current output directory. Then it generates equivalent code in PL/pgSQL in the result directory under the current output directory. ora2pgpro aims to convert package code in such a way that the resulting package is as functional as possible and leaves WARNING messages in code places that require programmer's attention.

All the package functions and procedures are public if there is no #private modifier, and all the public package variables are listed under the #export modifier of the __init__ function. If there are no public package variables, then __init__ will contain #export off.

This is an example of the #export and #import modifiers:

CREATE OR REPLACE FUNCTION PKGB.__INIT__() RETURNS VOID AS $$
#package
#import pkga
#export x, y
DECLARE
  x integer;
  y integer;
  z integer;
BEGIN
  x = 1;
  y = 2;
  z = PKGA.z; --Here PKGA.z = 4
  PERFORM dbms_output.put_line(x::varchar || y::varchar || z::varchar);
END;
$$ LANGUAGE PLPGSQL;

This is an example of the #private modifier:

CREATE OR REPLACE FUNCTION PKGB.private_function(a integer) RETURNS integer AS $$
#package
#private
DECLARE
	b integer;
BEGIN
	b = a * 3;
	RETURN b;
END; $$ LANGUAGE PLPGSQL;

CREATE OR REPLACE FUNCTION PKGB.public_function(a integer) RETURNS integer AS $$
#package
BEGIN
	RETURN PKGB.private_function(a);
END; $$ LANGUAGE PLPGSQL;

This is how the function may be called:

test=# select pkgb.private_function(2);
ERROR:  private package function or procedure pkgb.private_function(integer) called out of its package
CONTEXT:  PL/pgSQL function pkgb.private_function(integer)
test=# select pkgb.public_function(2);
NOTICE:  124
 public_function
-----------------
               6
(1 row)

This is an example of an Oracle package.

package body pkgc is
TYPE r_customer_type IS RECORD(
    customer_name varchar2(50),
    credit_limit number(10,2)
);

TYPE t_customer_type IS VARRAY(2)
    OF r_customer_type;

PROCEDURE VARRAY_TEST AS
    t_customers t_customer_type := t_customer_type();
    rec r_customer_type;
    tmp_string varchar2(2000);
BEGIN
    t_customers.EXTEND;
    t_customers(t_customers.LAST).customer_name := 'ABC Corp';
    t_customers(t_customers.LAST).credit_limit  := 10000;
    t_customers.EXTEND;
    t_customers(t_customers.LAST).customer_name := 'XYZ Inc';
    t_customers(t_customers.LAST).credit_limit  := 20000;
    tmp_string := 'The number of customers is ' || t_customers.COUNT;
    insert into pkgc_log (id, line) values (1, tmp_string);
    FOR indx in 1 .. t_customers.COUNT LOOP
        rec := t_customers(indx);
        tmp_string := 'RECORD: ' || rec.customer_name || ', ' || rec.credit_limit;
        insert into pkgc_log (id, line) values (1+ indx, tmp_string);
    END LOOP;
END;

BEGIN
  DELETE FROM pkgc_log;
END pkgc;

The resulting Postgres Pro package looks as follows.

BEGIN;
DROP SCHEMA IF EXISTS PKGC CASCADE;
CREATE SCHEMA PKGC;

CREATE TYPE PKGC.r_customer_type AS (
    customer_name varchar(50),
    credit_limit numeric(10,2)
);

CREATE DOMAIN PKGC.t_customer_type /*VARRAY(2)
    OF*/ PKGC.r_customer_type[];

CREATE OR REPLACE FUNCTION PKGC.__INIT__() RETURNS VOID AS $$
#package
#export off

BEGIN
  DELETE FROM pkgc_log;
END;
$$ LANGUAGE plpgsql;

CREATE OR REPLACE PROCEDURE PKGC.VARRAY_TEST() AS $$
#package
DECLARE
    /*WARNING: collection constructors are not supported.*/
    t_customers PKGC.t_customer_type /*:=*/ /*t_customer_type() /*WARNING: varray constructors are not supported.*/*/;
    rec PKGC.r_customer_type;
    tmp_string varchar(2000);
BEGIN
    t_customers = array_cat(t_customers, array_fill(NULL::PKGC.R_CUSTOMER_TYPE, ARRAY[1]));
    t_customers[array_upper(T_CUSTOMERS, 1)].customer_name = 'ABC Corp';
    t_customers[array_upper(T_CUSTOMERS, 1)].credit_limit  = 10000;

    t_customers = array_cat(t_customers, array_fill(NULL::PKGC.R_CUSTOMER_TYPE, ARRAY[1]));
    t_customers[array_upper(T_CUSTOMERS, 1)].customer_name = 'XYZ Inc';
    t_customers[array_upper(T_CUSTOMERS, 1)].credit_limit  = 20000;

    tmp_string = 'The number of customers is ' || array_length(T_CUSTOMERS, 1);
    insert into pkgc_log (id, line) values (1, tmp_string);

    FOR indx in 1 .. array_length(T_CUSTOMERS, 1) LOOP
        rec = t_customers[indx];
        tmp_string = 'RECORD: ' || rec.customer_name || ', ' || rec.credit_limit;
        insert into pkgc_log (id, line) values (1+ indx, tmp_string);
    END LOOP;
END; $$ LANGUAGE PLPGSQL;
/*end pkgc;*/

COMMIT;
pdf