J.2. Package Export Using ora2pgpro

ora2pgpro is a utility based on the ora2pg application, which can be used for porting Oracle packages and autonomous transactions as Postgres Pro packages and autonomous transactions when migrating an Oracle database to a Postgres Pro-compatible schema. ora2pgpro properly extracts type and variable declarations from the package body and specification, including the initialization section. Moreover, ora2pgpro exports autonomous transactions directly as opposed to ora2pg's translation of autonomous transactions into wrapper functions using dblink or pg_background extensions. It's worth noting that autonomous transactions are syntactically very different in Oracle and Postgres Pro. Currently, circular dependencies of packages are not supported.

To export packages using ora2pgpro, first edit the ora2pgpro.conf file.

  • Configure settings to control the access to the Oracle database.

    ORACLE_HOME "my_oracle_home_dir"
    ORACLE_DSN dbi:Oracle:host=localhost;sid=MY_SID;port=1521
    ORACLE_USER USER
    ORACLE_PWD PASSWORD
    SCHEMA SCHEMA
    
  • Optionally, you can set the TYPE variable to PACKAGE. Note that you can also set the type of export when running ora2pgpro as shown in the example below.

  • If you want to export autonomous transactions directly as Postgres Pro Enterprise autonomous transactions, set POSTGRESPRO_ATX to 1. Note that this disables the AUTONOMOUS_TRANSACTION parameter responsible for translation of autonomous transactions into a wrapper function.

    POSTGRESPRO_ATX 1
    
  • If you want to export only some packages, list them separated by commas in the INCLUDE_PACKAGES parameter, or specify the unwanted packages names in the EXCLUDE_PACKAGES parameter.

    INCLUDE_PACKAGES 'PKG_A', 'PKG_B'
    

Now you can run ora2pgpro.

ora2pgpro -t PACKAGE -c ora2pgpro.conf -o packages.sql

A short example below shows how the CUSTOMER_PKG package can be ported using ora2pgpro. This is the Oracle version:

CREATE OR REPLACE PACKAGE customer_pkg IS

  gBatchSize constant integer := 100;

  type
    TCustomerInfo is record
    (
      Id          number(9,0),
      Name        varchar2(32 char),
      Description varchar2(512 char)
    );

  type
    TBuffer is table of TCustomerInfo index by pls_integer;
  v_gBuffer TBuffer;

  v_cMainCustomer constant number(9,0) := 1;

  v_gCurrentCustomerId number(9,0);

...

  PROCEDURE dump(v_pCustomer in out nocopy TCustomerInfo);

  PROCEDURE init_package;
END;

CREATE OR REPLACE PACKAGE BODY customer_pkg IS

...

  PROCEDURE dump(v_pCustomer in out nocopy TCustomerInfo) IS
  BEGIN
    console.log('------------------  Dump of customer_pkg.TCustomerInfo  ------------------------');
    console.log('Id          => ' || v_pCustomer.Id);
    console.log('Name        => ' || v_pCustomer.Name);
    console.log('Description => ' || v_pCustomer.Description);
    console.log('--------------------------------------------------------------------------------');
  END;

  PROCEDURE init_package IS
  BEGIN
    v_gCurrentCustomerId := 0;
  END;

BEGIN
  init_package();
END;

Here is how this package would end up in Postgres Pro:

-- Oracle package 'CUSTOMER_PKG' declaration, edit to match PostgreSQL syntax

DROP SCHEMA IF EXISTS customer_pkg CASCADE;
CREATE SCHEMA IF NOT EXISTS customer_pkg;
CREATE TYPE customer_pkg.tcustomerinfo AS (
Id          integer,
      Name        varchar(32),
      Description varchar(512)

);

CREATE TYPE customer_pkg.tbuffer AS (tbuffer CUSTOMER_PKG.TCustomerInfo[]);

CREATE OR REPLACE FUNCTION customer_pkg.__init__ () RETURNS VOID AS $body$
#import CONSOLE
DECLARE

	gBatchSize constant integer := 100;
	v_gBuffer CUSTOMER_PKG.TBuffer;
	v_cMainCustomer constant integer := 1;
	v_gCurrentCustomerId integer;

BEGIN
  CALL customer_pkg.init_package();
end;

$body$
LANGUAGE PLPGSQL
SECURITY DEFINER
;
-- REVOKE ALL ON FUNCTION customer_pkg.__init__ () FROM PUBLIC;

CREATE OR REPLACE PROCEDURE customer_pkg.init_package () AS $body$
#package
BEGIN
    v_gCurrentCustomerId := 0;
  end;
$body$
LANGUAGE PLPGSQL
SECURITY DEFINER
;
-- REVOKE ALL ON PROCEDURE customer_pkg.init_package () FROM PUBLIC;

CREATE OR REPLACE PROCEDURE customer_pkg.dump (v_pCustomer INOUT CUSTOMER_PKG.TCustomerInfo) AS $body$
#package
BEGIN
    CALL console.log('------------------  Dump of customer_pkg.TCustomerInfo  ------------------------');
    CALL console.log('Id          => ' || v_pCustomer.Id);
    CALL console.log('Name        => ' || v_pCustomer.Name);
    CALL console.log('Description => ' || v_pCustomer.Description);
    CALL console.log('--------------------------------------------------------------------------------');
  end;
$body$
LANGUAGE PLPGSQL
SECURITY DEFINER
;
-- REVOKE ALL ON PROCEDURE customer_pkg.dump (v_pCustomer INOUT CUSTOMER_PKG.TCustomerInfo) FROM PUBLIC;

Complete package examples are available at ora2pgpro.postgrespro.ru. The scripts are distributed under the PostgreSQL license.