J.2. Экспорт пакетов с использованием ora2pgpro

ora2pgpro — это утилита, основанная на приложении ora2pg, которая может использоваться для портирования пакетов и автономных транзакций Oracle в пакеты и автономные транзакции Postgres Pro при переносе базы данных из Oracle в схему, совместимую с Postgres Pro. Утилита ora2pgpro правильно извлекает объявления типов и переменных из тела пакета и спецификации, включая секцию инициализации. Кроме того, ora2pgpro экспортирует автономные транзакции напрямую, в отличие от приложения ora2pg, которое преобразовывает автономные транзакции в функции-обёртки, используя dblink или pg_background. Стоит отметить, что автономные транзакции в Oracle и Postgres Pro синтаксически сильно различаются. На данный момент циклические зависимости пакетов не поддерживаются.

Чтобы экспортировать пакеты, используя ora2pgpro, сначала отредактируйте файл ora2pgpro.conf.

  • Настройте параметры для управления доступом к базе данных Oracle.

    ORACLE_HOME "домашний_каталог_oracle"
    ORACLE_DSN dbi:Oracle:host=localhost;sid=SID;port=1521
    ORACLE_USER ПОЛЬЗОВАТЕЛЬ
    ORACLE_PWD ПАРОЛЬ
    SCHEMA СХЕМА
  • Вы можете установить для переменной TYPE значение PACKAGE. Обратите внимание, что вы также можете установить тип экспорта при запуске ora2pgpro, как показано в примере ниже.

  • Если вы хотите экспортировать автономные транзакции напрямую как автономные транзакции Postgres Pro Enterprise, установите для параметра POSTGRESPRO_ATX значение 1. Обратите внимание, что при этом отключается параметр AUTONOMOUS_TRANSACTION, отвечающий за преобразование автономных транзакций в функции-обёртки.

    POSTGRESPRO_ATX 1
  • Если вы хотите экспортировать только некоторые пакеты, перечислите их через запятую в параметре INCLUDE_PACKAGES или укажите имена ненужных пакетов в параметре EXCLUDE_PACKAGES.

    INCLUDE_PACKAGES 'PKG_A', 'PKG_B'

Теперь можно запустить ora2pgpro.

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

В приведённом ниже простом примере показано, как можно перенести пакет CUSTOMER_PKG, используя ora2pgpro. Так выглядит версия Oracle:

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;

А так будет выглядеть этот пакет в 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;

Полные примеры пакетов доступны на ora2pgpro.postgrespro.ru. Скрипты распространяются по лицензии PostgreSQL.