Компиляция PLSQL из командной строки (не внутри sqlplus) - PullRequest
1 голос
/ 10 августа 2010

есть ли способ скомпилировать plsql из командной строки, не открывая sqlplus и записывая команду или @filename?

Мы хотим импортировать вывод в файл и проанализировать его для инструмента обзора кода, с которым мы работаем

Спасибо ...

Ответы [ 3 ]

2 голосов
/ 10 августа 2010

Не уверен, что я полностью понимаю, что вы имеете в виду, похоже, вы просто хотите захватить результаты выполнения, но не можете сказать, действительно ли вы хотите сказать, что хотите полностью избежать SQL * Plus. С моего первого прочтения это так просто:

sqlplus -s user/password @filename > outputfile

... но это заставляет меня думать, что я пропустил что-то важное.

1 голос
/ 10 августа 2010

Не думайте, смотрите эту презентацию Пита Финнигана о некоторых внутренностях компилятора.В нем перечислены ANTLR грамматика файл , которые вы можете использовать.

Я также видел упоминания о Scala комбинаторах реализации парсера для PL / SQL.

0 голосов
/ 10 августа 2010

Если вам просто нужно вывести исходный код - USER_SOURCE.

Я много динамически генерирую пакеты, и я написал код, который извлекает, добавляет дополнительный код и перекомпилирует пакет.

В самом простом случае вам просто нужно заключить команду CREATE PACKAGE в динамический SQL.

EXECUTE IMMEDIATE 
    'CREATE OR REPLACE PACKAGE myPackageName AS '||pPackageSource;

Однако это означает, что ваш источник - это всего лишь одна строка.Я использую более старый метод DBMS_SQL.PARSE, который может принимать массив строк VARCHAR2 (dbms_sql.varchar2s).

Пример - код для извлечения источника из user_source в varchar 2s, а затем перекомпилировать тот же пакет через dbms_sql.

DECLARE
    lCid INTEGER;
    lError INTEGER;
    lSource dbms_sql.varchar2s;

    FUNCTION fSource(
        pName IN VARCHAR2,
        pType IN VARCHAR2)
    RETURN dbms_sql.varchar2s
    IS
        CURSOR cSource IS
        SELECT  RTRIM(text,CHR(10))
        FROM    user_source
        WHERE   name = pName
        AND     type = pType
        ORDER BY line;
        lSource pp_type.gtyp_ArrayOfSource;
    BEGIN
       OPEN cSource;
       FETCH cSourcee BULK COLLECT INTO lSource;
       CLOSE cSource;
       RETURN lSource;
     END fSource;
BEGIN
    lSource := fSource(pName => 'myPackageName',pType => 'PACKAGE');
    /* Add CREATE or REPLACE to the start of the source */
    lSource(1) := 'CREATE OR REPLACE '||lSource(1);
-- Cannot use EXECUTE IMMEDIATE as this is an ARRAY
    lCid := dbms_sql.OPEN_CURSOR;
    --
    dbms_sql.parse(
       c    => lCid ,
       statement => lSource,
       lb   => 1,
       ub   => p_source.count,
       lfflg    => true,
       language_flag => dbms_sql.v7
   );
   dbms_sql.close_cursor (lCid);
END;

Это можно легко изменить, чтобы извлечь источник из файла, службы HTTP и т. Д. - всего, чего может достичь код / ​​база данных pl / sql.

Фактический код включает проверкупроверяет, верен ли результат, отправляет по электронной почте любые ошибки (из user_errors), сопоставленные со строками в user_source и т. д.

Security

Код должен быть запущен с привилегиямиустановить пакет - это может означать установку пакета против пользователя с более высокими привилегиями, чем у исполняющего пользователя.

Если вы делаете это, вам нужно быть очень осторожным в отношении того, какие интерфейсы открыты для «нормальной» БДпользователи - то есть вы не хотите создавать что-либо, что позволяет обычному пользователю извлекать или изменять источник или привилегии пакета.

Мой подход заключался в создании низкоуровневого пакета (скрытого от обычных пользователей) для всех сервисных функций (получение исходного кода, установка, динамическое выполнение и т. Д.), А затем пакета более высокого уровня, который предоставлял ограниченный набор конкретныхдействия для обычных пользователей - в вашем случае это будет что-то вроде показа процедуры 'reviewCode'.

...