powered by simpleCommunicator - 2.0.52     © 2025 Programmizd 02
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / Оператор WHEN
25 сообщений из 37, страница 1 из 2
Оператор WHEN
    #38801288
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Чтобы не замусоривать тему документации, начну новую.

Оператор WHEN … DO вызывается только в том случае, если произошло
одно из указанных в его условии событий. В случае выполнения оператора
(даже если в нем фактически не было выполнено никаких действий) ошибка или
пользовательское исключение не прерывает и не отменяет действий триггера
или хранимой процедуры, где был выдан этот оператор
, работа продолжается,
как если бы никаких исключительных ситуаций не было.
Да щаззз же. Весь блок BEGIN-END в котором стоит WHEN - откатывается. Что особенно
прикольно, после его выполнения откатывается и то, что им (блоком WHEN) сделано.

Дока молчит по поводу "в каком состоянии операторы блока WHEN должны видеть БД?" В
примерах в блоке исключительно один оператор, но что если их там несколько и исключение
возникло только в последнем? Должен блок WHEN видеть изменения, сделанные успешно
завершенными операторами до того как они будут отменены?.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Оператор WHEN
    #38801319
dimitr
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry SibiryakovДа щаззз же. Весь блок BEGIN-END в котором стоит WHEN - откатывается.
да щаззз. Весь откатывается только если ошибка была не в DML, иначе откатывается только сбойный стейтмент.
...
Рейтинг: 0 / 0
Оператор WHEN
    #38801322
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
dimitrВесь откатывается только если ошибка была не в DML, иначе откатывается только
сбойный стейтмент.
Ага, щаззз. Сбойный стейтмент откатывается до выполнения блоков WHEN. Остальное
откатывается сразу после них.

И таки да, любой из двух ныне имеющихся в тройке багов может откатить по сейфпоинту
сверху. А если объединятся и сильно постараются, то, возможно, смогут сожрать и
транзакционный.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Оператор WHEN
    #38801328
dimitr
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry SibiryakovАга, щаззз. Сбойный стейтмент откатывается до выполнения блоков WHEN. Остальное
откатывается сразу после них.
откатывается, если WHEN не выбрасывает исключения?

Dimitry SibiryakovИ таки да, любой из двух ныне имеющихся в тройке багов может откатить по сейфпоинту
сверху.
этому баяну лет 10 уже, наверное. И не в тройке, а во всех версиях ФБ.
...
Рейтинг: 0 / 0
Оператор WHEN
    #38801346
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
dimitrоткатывается, если WHEN не выбрасывает исключения?
Разумеется. Атомарность блока BEGIN-END нарушать нехорошо.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Оператор WHEN
    #38801592
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry Sibiryakov
Оператор WHEN … DO вызывается только в том случае, если произошло
одно из указанных в его условии событий. В случае выполнения оператора
(даже если в нем фактически не было выполнено никаких действий) ошибка или
пользовательское исключение не прерывает и не отменяет действий триггера
или хранимой процедуры, где был выдан этот оператор
, работа продолжается,
как если бы никаких исключительных ситуаций не было.
Да щаззз же. Весь блок BEGIN-END в котором стоит WHEN - откатывается. Что особенно
прикольно, после его выполнения откатывается и то, что им (блоком WHEN) сделано.


В целом предложение верное. Действие процедуры или триггера целиком действительно не отменяется. А вот про BEGIN...END и действия в WHEN действительно не описано.

Dimitry SibiryakovДока молчит по поводу "в каком состоянии операторы блока WHEN должны видеть БД?" В примерах в блоке исключительно один оператор, но что если их там несколько и исключение возникло только в последнем? Должен блок WHEN видеть изменения, сделанные успешно завершенными операторами до того как они будут отменены?.

Не знаю. По идее WHEN должен видеть всё что произошло до сбойного оператора.
Надо будет провести эксперимент. Если ты знаешь то скажи как обстоят дела.
...
Рейтинг: 0 / 0
Оператор WHEN
    #38801626
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Симонов Денис,

так оно и есть

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
create table T(
  id int not null primary key,
  a int
);

create sequence gen_t_log;

create table T_LOG(
  id int not null primary key,
  a int
);

set term ^;

execute block
as
declare variable m int;
begin
  insert into t(id, a) values(1, 1);
  begin
    insert into t(id, a) values(2, 2);
    -- дубликат первичного ключа
    insert into t(id, a) values(2, 3);
    when any do
    begin
      select max(a) from t into m;
      in autonomous transaction do
        insert into t_log(id, a)
        values (next value for gen_t_log, :m);
    end
  end
end^

set term ;^

commit;

select * from t;

ID	A
---------
1	1
2	2

select * from t_log;

ID	A
---------
1	2
...
Рейтинг: 0 / 0
Оператор WHEN
    #38801628
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry Sibiryakov,

и таки я не увидел что весь блок BEGIN...END откатывается. Откатилось только начиная со сбойного оператора.
...
Рейтинг: 0 / 0
Оператор WHEN
    #38801817
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Симонов Дениси таки я не увидел что весь блок BEGIN...END откатывается. Откатилось
только начиная со сбойного оператора.
Хммм... Ага, я понял что я делал неправильно. Я помещал WHEN после END. И кроме того,
использовал деление на ноль как генератор ошибки.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Оператор WHEN
    #38802081
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry Sibiryakovя понял что я делал неправильно.
И в том, что результат работы самого блока WHEN откатывается я тоже неправ. Где тут
смайлик, бьющийся об стену?..
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Оператор WHEN
    #38802098
Фотография wadman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry SibiryakovГде тут
смайлик, бьющийся об стену?..
Держи.
...
Рейтинг: 0 / 0
Оператор WHEN
    #38802101
Таблоид
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Симонов Денися не увидел что весь блок BEGIN...END откатывается. Откатилось только начиная со сбойного оператора .Это если сей "сбойный оператор" не является вызовом ХП.
Иначе всё наоборот.

DDL:
Код: plaintext
1.
2.
3.
4.
5.
6.
create or alter procedure p_ins(a_id int) as begin end;
recreate table t(id int not null primary key);
commit;
create or alter procedure p_ins(a_id int) as
begin
  insert into t values( :a_id );
end;

Test:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
commit;
set term ^;
execute block as
begin
  rdb$set_context('USER_SESSION', 'SEEN_FROM_WHEN_CASE_1', null );
  delete from t;
  begin
    insert into t(id) values(1);
    insert into t(id) values(2);
    insert into t(id) values(3);
    insert into t(id) values(3);
  when any do
    rdb$set_context('USER_SESSION', 'SEEN_FROM_WHEN_CASE _1 ', (select list(id) from t) );
  end
  
  rdb$set_context('USER_SESSION', 'SEEN_FROM_WHEN_CASE_2', null );
  delete from t;
  begin
    insert into t(id) values(1);
    insert into t(id) values(2);
    insert into t(id) values(3);
    execute procedure p_ins(3);
  when any do
    rdb$set_context('USER_SESSION', 'SEEN_FROM_WHEN_CASE _2 ', (select list(id) from t) );
  end

end
^ set term ;^
rollback;

set width seen_in_when_1 10;
set width seen_in_when_2 10;
set list on;
select 
   rdb$get_context('USER_SESSION', 'SEEN_FROM_WHEN_CASE_1' ) as seen_in_when_1
  ,rdb$get_context('USER_SESSION', 'SEEN_FROM_WHEN_CASE_2' ) as seen_in_when_2
from rdb$database;
set list off;
rollback;

Result:
Код: plaintext
1.
SEEN_IN_WHEN _1                   1,2,3
SEEN_IN_WHEN _2                   <null>

PS. CORE-4483 : "Changed data not visible in WHEN-section if exception occured inside SP that has been called from this code"

PPS. Денис, а я вроде бы тебе говорил про эту "мегафичу" в личке, когда .doc отсылал ?
...
Рейтинг: 0 / 0
Оператор WHEN
    #38802132
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Таблоид,

посмотрел. Там такой же эффект даёт 0/0. Пожалуй это стоит вписать как примечание.
...
Рейтинг: 0 / 0
Оператор WHEN
    #38802169
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Симонов ДенисПожалуй это стоит вписать как примечание.
Разве что как ссылку на бага. Но тогда туда же придётся запихать и
CORE-4424 .
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Оператор WHEN
    #38802691
Евгений Болтик
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Симонов Денис,

Умеете ж Вы радовать. Пошёл код перепроверять.
...
Рейтинг: 0 / 0
Оператор WHEN
    #38802727
Евгений Болтик
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Евгений БолтикСимонов Денис,

Умеете ж Вы радовать. Пошёл код перепроверять.

Мнда слов нет. Теперь понятно почему иногда были не понятки. Благо это место пока мало используется.

Уже не раз пытался через логи найти. Блин неужели никому из вас не надо было текст сообщения ошибки в блоке
WHEN ANY DO begin

в DELPHI уже давно с помощью try и лога сообщений ловлю самые замысловатые ошибки, но SQL кроме танца с бубном перед WHEN ANY DO begin и в блоке WHEN ANY DO begin ничего не сделаешь, если все запросы виртуальные.
...
Рейтинг: 0 / 0
Период между сообщениями больше года.
Оператор WHEN
    #39436787
sezavasasilov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Dimitry Sibiryakov, Симонов Денис,

Добрый день.

Только вчера столкнулся с этой багой (фитчей?):

Оставил вопрос на тостере , но там народ видимо немного другой тематики - просмотров много, а ответов нет.

Либо я криворукий, либо действительно
Код: plsql
1.
2.
3.
4.
5.
begin
  ...
  when any do
    ...
end

откатывает только ошибочную команду и последующие. Все что до ошибки - прекрасно комитится. Отката всего блока begin/end не происходит.
...
Рейтинг: 0 / 0
Оператор WHEN
    #39436795
Гаджимурадов Рустам
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
sezavasasilov> Все что до ошибки - прекрасно комитится.
sezavasasilov> Отката всего блока begin/end не происходит.

Так ты полный пример приведи.
Что там до ошибки, suspend-ы поди ?
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Оператор WHEN
    #39436807
hvlad
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
sezavasasilovОтката всего блока begin/end не происходит.Никто этого и не обещал.
RTFM: Scope of a WHEN ... DO Statement
...
Рейтинг: 0 / 0
Оператор WHEN
    #39436812
sezavasasilov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Гаджимурадов РустамЧто там до ошибки, suspend-ы поди ?

а вот и нет.

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
create or alter procedure EXECUTE_SCRIPT (
    I_SCRIPT blob sub_type 1 segment size 80 not null)
returns (
    ERR smallint)
as
declare variable V_COMMAND blob sub_type 1 segment size 80;
begin
  ERR = 0;
  begin
    for
      select COMMAND
      from SPLIT_SCRIPT(:I_SCRIPT)
      into :V_COMMAND
    do
      execute statement(V_COMMAND);

    when any do
      ERR = 1;
  end
end



for select в данном случае возвращает код DDL операторов:
Код: plsql
1.
2.
3.
4.
create table test_table1 (
    id integer,
    name varchar(30)
)


Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
create or alter procedure test_proc1 (
    I_ID integer,
    I_NAME varchar(30))
returns (
    O_MSG varchar(30))
as
begin
  insert into test1 (id, name)
  values(:i_id, :i_name);
  o_msg = 'Запись №' || i_id || ' с именем ' || i_name || ' вставлена!';
  suspend;
end



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

Из доки строки (стр. 495):
авторВнутренне автоматические точки сохранения используется для:
• отмены всех действий внутри блока BEGIN ... END, где происходит исключение;

авторСами по себе блок BEGIN..END не создаёт автоматическую точку сохранения. Она создаётся
только в блоках, которых присутствует блок WHEN для обработки исключений или ошибок.


Вот я и ожидал такого поведения, что если произойдет ошибка, то должен сработать откат всего блока, включая и команды, выполненных без ошибок. Однако после комита, таблица test_table1 все-таки создается.
...
Рейтинг: 0 / 0
Оператор WHEN
    #39436824
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
sezavasasilov,

там кучу примечаний написано, прочитай их
...
Рейтинг: 0 / 0
Оператор WHEN
    #39436827
Ivan_Pisarevsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Любители "стрелять себе в ногу" созданием на лету таблиц - должны страдать, что собственно мы и видим.

исполни скрипт в isql, закоммить изменение метаданных, потом следующим коннектом уже заливай данные.
...
Рейтинг: 0 / 0
Оператор WHEN
    #39436860
sezavasasilov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Ivan_Pisarevsky,

это слишком просто
А мы не ищем легких путей)

Задача стоит именно такая - накатить скрипт из процедуры
...
Рейтинг: 0 / 0
Оператор WHEN
    #39436917
Фотография kdv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
sezavasasilovоткатывает только ошибочную команду и последующие. Все что до ошибки - прекрасно комитится. Отката всего блока begin/end не происходит.
немедленно читать
http://www.ibase.ru/savepoints/
...
Рейтинг: 0 / 0
Оператор WHEN
    #39436918
Фотография kdv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
sezavasasilovЗадача стоит именно такая - накатить скрипт из процедуры
если скрипт содержит ddl, то задача вполне себе идиотская. Еще более идиотским является выполнение команд ddl из execute statement. Таким образом, уровень идиотизма постановщика задачи зашкалил.

p.s. я не шучу и никого не оскорбляю. Просто констатирую, как специалист по работе с ИБ-ФБ с 23-летним стажем.
...
Рейтинг: 0 / 0
25 сообщений из 37, страница 1 из 2
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / Оператор WHEN
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]