Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / Оператор WHEN / 25 сообщений из 37, страница 1 из 2
10.11.2014, 19:57
    #38801288
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Оператор WHEN
Чтобы не замусоривать тему документации, начну новую.

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

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

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

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


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

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

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

так оно и есть

Код: 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
11.11.2014, 10:10
    #38801628
Симонов Денис
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Оператор WHEN
Dimitry Sibiryakov,

и таки я не увидел что весь блок BEGIN...END откатывается. Откатилось только начиная со сбойного оператора.
...
Рейтинг: 0 / 0
11.11.2014, 12:08
    #38801817
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Оператор WHEN
Симонов Дениси таки я не увидел что весь блок BEGIN...END откатывается. Откатилось
только начиная со сбойного оператора.
Хммм... Ага, я понял что я делал неправильно. Я помещал WHEN после END. И кроме того,
использовал деление на ноль как генератор ошибки.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
11.11.2014, 14:00
    #38802081
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Оператор WHEN
Dimitry Sibiryakovя понял что я делал неправильно.
И в том, что результат работы самого блока WHEN откатывается я тоже неправ. Где тут
смайлик, бьющийся об стену?..
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
11.11.2014, 14:08
    #38802098
wadman
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Оператор WHEN
Dimitry SibiryakovГде тут
смайлик, бьющийся об стену?..
Держи.
...
Рейтинг: 0 / 0
11.11.2014, 14:11
    #38802101
Таблоид
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Оператор WHEN
Симонов Денися не увидел что весь блок 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
11.11.2014, 14:28
    #38802132
Симонов Денис
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Оператор WHEN
Таблоид,

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

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

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

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

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

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

Добрый день.

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

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

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

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

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

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

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

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

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

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


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