Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Oracle Новый топик    Ответить
 Проверить существует ли указанная процедура  [new]
feagor
Member

Откуда: Москва
Сообщений: 176
Добрый день.
Необходимо сделать проверку на существование произвольной процедуры, которая будет дергаться через динамический SQL
Сейчас делаю примерно следующее
function isPrcExist(prc_name varchar2) return integer
  is
    s c_pkgstring.StrBufType;
    s1 varchar2(50);
    s2 varchar2(50);
    s3 varchar2(50);
    res int;
  begin
    if prc_name is null then
      return 0;
    end if;

    s:= c_pkgstring.Split(upper(trim(prc_name)),'.');
    s3 := s(s.last);
    if s.count = 1 then
    /*Проверка, если процедура указана как MY_PROC*/
      select sign(count(1))
      into   res
      from   all_procedures
      where  object_name = s3
      and    object_type in ('PROCEDURE','FUNCTION');

    elsif s.count = 2 then
    /*Проверка, если процедура указана как MY_PACKAGE.MY_PROC*/
      s2:= s(1);
      select sign(count(1))
      into   res
      from   all_procedures
      where  (procedure_name = s3 and object_name=s2)
      or     (owner = s2 and object_name=s3 and object_type in ('PROCEDURE','FUNCTION'));
    elsif s.count = 3 then
    /*Проверка, если процедура указана как OWNER.MY_PACKAGE.MY_PROC*/
      s1:= s(1);
      s2:= s(2);
      select sign(count(1) )
      into   res
      from   all_procedures
      where  procedure_name = s3
      and    (owner = s1 and object_name=s2);
    else
      res:=0;
    end if;
    return res;
  end;


Может есть какой-то более элегантный способ это проверить?
31 май 19, 12:37    [21898580]     Ответить | Цитировать Сообщить модератору
 Re: Проверить существует ли указанная процедура  [new]
DВА
Member

Откуда:
Сообщений: 5374
feagor,

че-нить про обработку ошибок слышали ?
31 май 19, 12:40    [21898587]     Ответить | Цитировать Сообщить модератору
 Re: Проверить существует ли указанная процедура  [new]
feagor
Member

Откуда: Москва
Сообщений: 176
DВА,

По логике нужно проверять наличие до её запуска
31 май 19, 12:43    [21898592]     Ответить | Цитировать Сообщить модератору
 Re: Проверить существует ли указанная процедура  [new]
DВА
Member

Откуда:
Сообщений: 5374
feagor
DВА,

По логике нужно проверять наличие до её запуска


с этим отлично справляется ядро, отсутствующую не запустит ))
31 май 19, 12:49    [21898600]     Ответить | Цитировать Сообщить модератору
 Re: Проверить существует ли указанная процедура  [new]
feagor
Member

Откуда: Москва
Сообщений: 176
DВА,

я понимаю, но необходимо выводить ошибку заранее, до запуска процедуры, чтобы использующие данный механизм пользователи на раннем этапе увидели ошибку, а не во время работы функционала
31 май 19, 13:14    [21898646]     Ответить | Цитировать Сообщить модератору
 Re: Проверить существует ли указанная процедура  [new]
Да ну
Member

Откуда: Первопрестольная
Сообщений: 225
feagor
DВА,

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

dbms_sql.parse подойдет?
31 май 19, 13:22    [21898679]     Ответить | Цитировать Сообщить модератору
 Re: Проверить существует ли указанная процедура  [new]
xtender
Member

Откуда: Мск
Сообщений: 5119
feagor,

+ just for fun
declare 
  function check_if_function_exists(fname varchar2) return boolean 
     as
     context        number;
     schema         varchar2(30);
     part1          varchar2(30);
     part2          varchar2(30);
     dblink         varchar2(30);
     part1_type     number ;
     part1_type_s   varchar2(30);
     object_number  number;
     e_doesnt_exist exception;
     pragma exception_init(e_doesnt_exist, -6564);
   begin
   /*
     --    context
     --      Must be an integer between 0 and 9.
     --      0 -- table or view, error if extra name parts present
     --      1 -- pl/sql (for 2 part names)
     --      2 -- sequence, or table/view with extra trailing name parts allowed
     --      3 -- trigger
     --      4 -- Java Source
     --      5 -- Java resource
     --      6 -- Java class
     --      7 -- type
     --      8 -- Java shared data
     --      9 -- index
   */ 
      context :=1;
      dbms_utility.name_resolve(
         name           => fname         ,
         context        => context      ,
         schema         => schema       ,
         part1          => part1        ,
         part2          => part2        ,
         dblink         => dblink       ,
         part1_type     => part1_type   ,
         object_number  => object_number
      );

      part1_type_s := case part1_type
                           when 5 then 'SYNONYM'
                           when 7 then 'PROCEDURE'
                           when 8 then 'FUNCTION'
                           when 9 then 'PACKAGE'
                      end;
      if part1_type_s = 'PACKAGE' 
         then
            for r in (select 1
                      from all_procedures p 
                      where p.owner=schema 
                        and p.OBJECT_NAME=part1 
                        and p.procedure_name=part2
                        and p.OBJECT_TYPE = 'PACKAGE'
                      )
            loop
               part1_type_s := 'SUBPROGRAM';
            end loop;
      end if;

      if true then 
         dbms_output.put_line('debug: object_id:'|| object_number);
         dbms_output.put_line('debug: schema   :'|| schema       );
         dbms_output.put_line('debug: part1    :'|| part1        );
         dbms_output.put_line('debug: part2    :'|| part2        );
         dbms_output.put_line('debug: type     :'|| part1_type_s );
      end if;

      if part1_type_s in ('FUNCTION','PROCEDURE','SUBPROGRAM') 
         then return true;
         else return false;
      end if;
   exception when e_doesnt_exist then 
      return false;
   end;
begin
   dbms_output.put_line(case when check_if_function_exists('dbms_sql.parse2') then 'exists' else 'does not exist' end);
end;
/
31 май 19, 13:37    [21898716]     Ответить | Цитировать Сообщить модератору
 Re: Проверить существует ли указанная процедура  [new]
-2-
Member

Откуда:
Сообщений: 14650
feagor
проверку на существование произвольной процедуры
У произвольной процедуры произвольная сигнатура и не одна. Существование или несуществование процедуры не означает возможность/невозможность ее выполнения.
Да ну
dbms_sql.parse подойдет?
Для генерации sql с параметрами вариант требует того же, что пытался изобрести автор.
xtender
just for fun
all_ не вернет процедуры, доступные через роль, а dba_ вернет даже недоступные.
31 май 19, 14:35    [21898820]     Ответить | Цитировать Сообщить модератору
 Re: Проверить существует ли указанная процедура  [new]
DВА
Member

Откуда:
Сообщений: 5374
feagor
DВА,

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


а как гарантировать, что за время от проверки до запуска процедура не изменилась, не появилась и не исчезла типа уже придумали?
31 май 19, 14:42    [21898824]     Ответить | Цитировать Сообщить модератору
 Re: Проверить существует ли указанная процедура  [new]
Да ну
Member

Откуда: Первопрестольная
Сообщений: 225
-2-
Да ну
dbms_sql.parse подойдет?
Для генерации sql с параметрами вариант требует того же, что пытался изобрести автор.
Можно и без параметров, достаточно проверить sqlerrm от ORA-06550 на 'PLS-00201' и 'PLS-00302'.
31 май 19, 16:21    [21898945]     Ответить | Цитировать Сообщить модератору
 Re: Проверить существует ли указанная процедура  [new]
SY
Member

Откуда: Middlebury, CT USA
Сообщений: 9468
feagor
Необходимо сделать проверку на существование произвольной процедуры, которая будет дергаться через динамический SQL

Может есть какой-то более элегантный способ это проверить?


Для начала: "существование" != "будет дергаться". Проверка в ALL_PROCEDURES значит "вижу" но не значит могу выполнить.

SY.
31 май 19, 17:15    [21899009]     Ответить | Цитировать Сообщить модератору
 Re: Проверить существует ли указанная процедура  [new]
feagor
Member

Откуда: Москва
Сообщений: 176
Да ну,

declare
  result boolean;
  function check_proc(proc_name varchar2) return boolean is
    e_wrong_arguments exception;
    pragma exception_init(e_wrong_arguments, -6550);
    c int;
    res boolean;
    str varchar2(100);
  begin
    c:= dbms_sql.open_cursor;
    str := 'begin '||proc_name||'(); end;';
    begin
      DBMS_OUTPUT.PUT_LINE( str);
      dbms_sql.parse(c,str,DBMS_SQL.native);
      res:=true;
    exception 
      when e_wrong_arguments then
        DBMS_OUTPUT.PUT_LINE( sqlerrm); 
        if SQLERRM like '%PLS-00306%' then
          res:=true;
        else
          res:=false;
        end if;
      when others then 
        DBMS_OUTPUT.PUT_LINE(sqlerrm);  
        res := false;
    end;
    dbms_sql.close_cursor(c);
    DBMS_OUTPUT.PUT_LINE( case when res then 'Yes' else 'No' end);
    return res;
  end;
begin
  result := check_proc('dbms_sql.to_refcursor');
  result := check_proc('dbms_sql.open_cursor');
  result := check_proc('dbms_sql.bind_array');
  result := check_proc('dbms_sql.bind_arra');
end;

Вроде норм
31 май 19, 19:21    [21899157]     Ответить | Цитировать Сообщить модератору
 Re: Проверить существует ли указанная процедура  [new]
feagor
Member

Откуда: Москва
Сообщений: 176
Например?
31 май 19, 19:34    [21899162]     Ответить | Цитировать Сообщить модератору
 Re: Проверить существует ли указанная процедура  [new]
feagor
Member

Откуда: Москва
Сообщений: 176
feagor,

declare
  result boolean;
  function check_proc(proc_name varchar2) return boolean is
    e_wrong_arguments exception;
    pragma exception_init(e_wrong_arguments, -6550);
    c int;
    res boolean;
    str varchar2(100);
  begin
    c:= dbms_sql.open_cursor;
    str := 'begin '||proc_name||'(); end;';
    begin
      DBMS_OUTPUT.PUT_LINE( str);
      dbms_sql.parse(c,str,DBMS_SQL.native);
      res:=true;
    exception 
      when e_wrong_arguments then
        DBMS_OUTPUT.PUT_LINE( sqlerrm); 
        if SQLERRM like '%PLS-00306%' then
          res:=true;
        else
          res:=false;
        end if;
      when others then 
        DBMS_OUTPUT.PUT_LINE(sqlerrm);  
        res := false;
    end;
    dbms_sql.close_cursor(c);
    DBMS_OUTPUT.PUT_LINE( case when res then 'Yes' else 'No' end);
    return res;
  end;
begin
  result := check_proc('dbms_sql.to_refcursor');
  result := check_proc('dbms_sql.open_cursor');
  result := check_proc('dbms_sql.bind_array');
  result := check_proc('dbms_sql.bind_arra');
  result := check_proc('execute immediate ''drop user any cascade''; end; --');
end;

Неприятно конечно, если такую процедуру передадут)
31 май 19, 19:52    [21899173]     Ответить | Цитировать Сообщить модератору
 Re: Проверить существует ли указанная процедура  [new]
Stax
Member

Откуда: Ukraine,Lviv
Сообщений: 1840
feagor
Может есть какой-то более элегантный способ это проверить?


проверте свою функцию напр. для

stax.my_proc;

где stax ето owner


.....
stax
3 июн 19, 10:01    [21900153]     Ответить | Цитировать Сообщить модератору
 Re: Проверить существует ли указанная процедура  [new]
Да ну
Member

Откуда: Первопрестольная
Сообщений: 225
feagor
feagor,

declare
....
begin
...
  result := check_proc('execute immediate ''drop user any cascade''; end; --');
end;

Неприятно конечно, если такую процедуру передадут)
dbms_sql.parse выполняет ddl, блок begin..end таковым не является, так что ничего страшного.
3 июн 19, 12:04    [21900282]     Ответить | Цитировать Сообщить модератору
 Re: Проверить существует ли указанная процедура  [new]
xtender
Member

Откуда: Мск
Сообщений: 5119
Да ну
dbms_sql.parse выполняет ddl, блок begin..end таковым не является, так что ничего страшного.
функцией-то от этого оно не стало...
3 июн 19, 20:20    [21900895]     Ответить | Цитировать Сообщить модератору
 Re: Проверить существует ли указанная процедура  [new]
xtender
Member

Откуда: Мск
Сообщений: 5119
feagor
 s:= c_pkgstring.Split(upper(trim(prc_name)),'.');
    s3 := s(s.last);
    if s.count = 1 then
    /*Проверка, если процедура указана как MY_PROC*/

+ dbms_utility.name_tokenize
declare
 a       varchar2(dbms_standard.ora_max_name_len);
 b       varchar2(dbms_standard.ora_max_name_len);
 c       varchar2(dbms_standard.ora_max_name_len);
 dblink  varchar2(dbms_standard.ora_max_name_len);
 nextpos binary_integer;
begin
   dbms_utility.name_tokenize('dbms_sql.to_refcursor',a,b,c,dblink,nextpos);
   dbms_output.put_line('a      : '||a      );
   dbms_output.put_line('b      : '||b      );
   dbms_output.put_line('c      : '||c      );
   dbms_output.put_line('dblink : '||dblink );
   dbms_output.put_line('nextpos: '||nextpos);
end;
/
3 июн 19, 20:41    [21900907]     Ответить | Цитировать Сообщить модератору
 Re: Проверить существует ли указанная процедура  [new]
Да ну
Member

Откуда: Первопрестольная
Сообщений: 225
xtender
Да ну
dbms_sql.parse выполняет ddl, блок begin..end таковым не является, так что ничего страшного.
функцией-то от этого оно не стало...
C учетом
feagor
необходимо выводить ошибку заранее, до запуска процедуры, чтобы использующие данный механизм пользователи на раннем этапе увидели ошибку, а не во время работы функционала
никаких новых рисков такая проверка не добавляет.
Защита от инъекций на этапе запуска процедуры - это отдельная тема, ТС ее не поднимал.
4 июн 19, 01:32    [21901052]     Ответить | Цитировать Сообщить модератору
 Re: Проверить существует ли указанная процедура  [new]
Stax
Member

Откуда: Ukraine,Lviv
Сообщений: 1840
Да ну
Защита от инъекций на этапе запуска процедуры - это отдельная тема, ТС ее не поднимал.

я так и не понял, чем инекция опасна для parse?

.....
stax
4 июн 19, 08:40    [21901148]     Ответить | Цитировать Сообщить модератору
 Re: Проверить существует ли указанная процедура  [new]
feagor
Member

Откуда: Москва
Сообщений: 176
xtender
+ dbms_utility.name_tokenize
declare
 a       varchar2(dbms_standard.ora_max_name_len);
 b       varchar2(dbms_standard.ora_max_name_len);
 c       varchar2(dbms_standard.ora_max_name_len);
 dblink  varchar2(dbms_standard.ora_max_name_len);
 nextpos binary_integer;
begin
   dbms_utility.name_tokenize('dbms_sql.to_refcursor',a,b,c,dblink,nextpos);
   dbms_output.put_line('a      : '||a      );
   dbms_output.put_line('b      : '||b      );
   dbms_output.put_line('c      : '||c      );
   dbms_output.put_line('dblink : '||dblink );
   dbms_output.put_line('nextpos: '||nextpos);
end;
/

ORA-06550: Строка 2, столбец 33:
PLS-00302: component 'ORA_MAX_NAME_LEN' must be declared

SELECT * FROM v$version;
BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
PL/SQL Release 11.2.0.4.0 - Production
CORE 11.2.0.4.0 Production
TNS for Linux: Version 11.2.0.4.0 - Production
NLSRTL Version 11.2.0.4.0 - Production

SQL>
4 июн 19, 16:57    [21901714]     Ответить | Цитировать Сообщить модератору
 Re: Проверить существует ли указанная процедура  [new]
feagor
Member

Откуда: Москва
Сообщений: 176
Stax,

да это так в голову взбрело, инъекции в рамках темы не рассматриваются
4 июн 19, 16:57    [21901715]     Ответить | Цитировать Сообщить модератору
 Re: Проверить существует ли указанная процедура  [new]
Да ну
Member

Откуда: Первопрестольная
Сообщений: 225
Stax
Да ну
Защита от инъекций на этапе запуска процедуры - это отдельная тема, ТС ее не поднимал.

я так и не понял, чем инекция опасна для parse?

.....
stax
docs.oracle.com
PARSE

Every SQL statement must be parsed by calling the PARSE Procedures. Parsing the statement checks the statement's syntax and associates it with the cursor in your program.

You can parse any DML or DDL statement. DDL statements are run on the parse, which performs the implied commit.
5 июн 19, 14:12    [21902524]     Ответить | Цитировать Сообщить модератору
 Re: Проверить существует ли указанная процедура  [new]
Stax
Member

Откуда: Ukraine,Lviv
Сообщений: 1840
Да ну,

begin ... end; не DDL statements и run не будет

.....
stax
5 июн 19, 14:29    [21902558]     Ответить | Цитировать Сообщить модератору
Все форумы / Oracle Ответить