Возможно ли проверить на наличие ошибок компиляции на этапе сборки CI?

Tолько что "убил" наш CI, потому что в Git commit был SQL файл с ошибкой. Проверил его в SQL Developer, но забыл скопипастить в файл. Ошибка была только в одном символе, вместо elsif осталось elsеif. Но сборка завершилась успешно, и проявилась только во время тестов.

Сборка проводится с SQL*Plus, упрощенно это выглядит так:

-- pack.sql
create or replace package pack as
    procedure proc;
end pack;
/
create or replace package body pack as
    procedure proc (par int) is 
    begin 
        if par = 1 then null;
        elseif par = 2 then null;
        end if;
    end proc;
end pack;
/

Если запустить этот файл в SQL*Plus, то возникнет ошибка компиляции, но процес в итоге, завершается нормально:

Package created.

Warning: Package Body created with compilation errors.

$ echo $?
0

Как можно в SQL*Plus, или возможно в другом инструменте, проверить на наличие ошибок компиляции во время сборки?


Свободный перевод вопроса Is it possible to validate sql and pl/sql syntax on compile time? от участника @Maxim Ostrovsky


Ответы (1 шт):

Автор решения: 0xdb

Возможно с SQL*Plus, или с его приемником - SQLcl. Надо сделать следующее:

  • Принудить командой WHENEVER к прекращению выполнения скрипта (exit) с кодом возврата сбой (failure) при первой встретившейся SQL ошибке (sqlerror).

  • Ошибка компиляции не вызывает SQL ошибку, это только предупереждение. В конце создания/обновления компилируемых объектов, надо проверить их статус и вызвать пользовательское исключение, если стаус не валиден.

Пример SQL файла из вопроса будет выглядеть так:

whenever sqlerror exit failure

set verify off
define objects="'PACK','PACK2'"

create or replace package pack as
    procedure proc;
end pack;
/
create or replace package body pack as
    procedure proc (par int) is 
    begin 
        if par = 1 then null;
        elseif par = 2 then null;
        end if;
    end proc;
end pack;
/
<<check_status>>
begin 
    for r in (
        select * from user_objects
        where object_name in (&objects) and status != 'VALID') loop
        raise_application_error (-20000, r.object_type||' '||r.object_name||' is '||r.status);
    end loop;
end;
/

Его выполнение завершится с кодом failure, если один из объектов, указанных в переменной objects, был скомпилирован с ошибкой:

Package created.

Warning: Package Body created with compilation errors.

<<check_status>>
*
ERROR at line 1:
ORA-20000: PACKAGE BODY PACK is INVALID
ORA-06512: at line 5
ORA-06512: at line 5

$ echo $?
1
→ Ссылка