Извлечение имени пакета и комментариев из файлов пакета

#sql #oracle #plsql

#sql #Oracle #plsql

Вопрос:

Мне нужно получить имя пакета и первые строки комментариев из файла пакета PL / SQL (спецификация и / или тело) или из пакета, скомпилированного в BD.

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

Например, если мне нужно получить имена пакетов, я могу выполнить этот select:

 select * from all_objects where object_name like 'pack%';
  

Но если мне нужно получить в результате запроса плюс имя пакета, первые строки из package. Если пакет начинается с:

 CREATE OR REPLACE PACKAGE BODY pack_test AS
/* **************************************************** */
*  Description: maintenance package from suppliers table *
*  Author:  reymagnus                                    *
*  Creation date: 09/04/2019                             *
*  (another comments)                                    *
*  **************************************************** */
  

Я ожидаю получить это:

 Object_Type   Object_Name  Description
===========   ===========  ===========   
PACKAGE       pack_test    maintenance package from suppliers table
  

Или

 Object_Type   Object_Name  Description_line
===========   ===========  ================ 
PACKAGE       pack_test    CREATE OR REPLACE PACKAGE BODY pack_test AS
PACKAGE       pack_test    /* **************************************************** */
PACKAGE       pack_test    *  Description: maintenance package from suppliers table *
  

Возможно, мне нужно объединить таблицы all_objects и all_source и получить только <= 3 строки.

Комментарии:

1. Может быть, вы делаете (выглядит как хорошая идея). Вы пробовали это?

2. Что касается автора и даты, я думаю, что подобные вещи не должны быть в заголовке пакета. В конце концов, через некоторое время будут внесены изменения, и у вас будет несколько авторов и несколько дат. Вместо этого сохраните ваши изменения в системе управления версиями, чтобы у вас был автор дата сообщение о фиксации / описание изменения для каждого изменения, которое вы вносите в исходный код.

Ответ №1:

Я бы получил имя пакета из all_objects , потому что оно там в любом случае.

Синтаксический анализ комментария должен быть выполнимым. Просто найдите строку, начинающуюся с * Description: , и возьмите остальную часть этой строки.

REGEXP_SUBSTR может быть хорошей функцией для анализа этого или некоторых базовых строковых функций, таких как:

 select
  o.OWNER,
  o.OBJECT_NAME,
  ( select
      MIN(TRIM(SUBSTR(s.TEXT, INSTR(s.TEXT, 'Description:')   12)))
    from 
      ALL_SOURCE s 
    where
      s.NAME = o.OBJECT_NAME
      and s.OWNER = o.OWNER
      and s.LINE <= 5
      and s.TEXT like '% Description:%') as DESCRIPTION
from
  ALL_OBJECTS o
where
  o.OBJECT_TYPE = 'PACKAGE';
  

Следует отметить, что эта проверка немного грубовата. Теоретически текст Description: также может быть частью некоторого кода или запроса, поэтому теоретически вы можете получить ложноположительный результат и получить странное описание.

Кроме того, эта проверка довольно строгая. Если вы ввели description (нижний регистр), или description : (пробел перед двоеточием) или *Description: (между звездочкой и словом нет пробела), совпадения не будет.

Кроме того, я использовал MIN для получения любого описания на случай, если их несколько. Лично я думаю, что это нормально для обнаружения подобных крайних случаев. Вы также могли бы использовать LIST_AGG для возврата их всех, что имеет приятное преимущество, заключающееся в разрешении многострочных описаний … 🙂

Ответ №2:

В качестве альтернативы вы можете создать таблицу ведения журнала

 create table t_log( obj_name varchar2(35), obj_type varchar2(35), obj_rows varchar2(4000) );
  

и заполнить с помощью user_source словарного представления и ограничить тремя строками

 declare
  v_plsql_unit varchar2(35):= 'my_package';
begin
  for c in ( select * from user_source s where s.name = upper(v_plsql_unit) order by s.line )
  loop
   begin 
      insert into t_log values( c.name, c.type, c.text );
    exit when c.line = 3;
   end;  
    commit;
  end loop;
end; 
  

Ответ №3:

описания спецификации пакета и тела пакета в основном следуют за символами ‘/ *’ или ‘—‘, и не существует критериев, по которым ключевое слово description должно присутствовать там, если только это не бизнес-критерии. если это критерий, то можно использовать ключевое слово, иначе можно сослаться на приведенный ниже запрос и изменить его в соответствии с потребностями.

 -- package to query: sample_pkg
select o.owner, 
       o.object_name,
      (select listagg(a.text ) WITHIN GROUP (ORDER BY a.line asc)  
       from all_source a 
       where a.name =o.object_name
         and a.line between (select b.line from all_source b where b.name=a.name and b.text like '%'||chr(47)||'*%')
                        and (select c.line from all_source c where c.name =a.name and c.text like '%*'||chr(47)||'%')
            ) description
from all_objects o 
where o.object_type like 'PACK%' 
and o.object_name like 'SAMP%';

-- output
OWNER       OBJECT_NAME DESCRIPTION
SQL_user    SAMPLE_PKG  /* 
                        sample spec description 
                        */