Если вам просто нужно вывести исходный код - 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'.