Использование ROLLBACK TO SAVEPOINT с условием

Возможно ли ROLLBACK TO SAVEPOINT с помощью CASE? Мой запрос

BEGIN;
SAVEPOINT my_savepoint;
INSERT INTO DPoint (uuid) VALUES ('5547f4b7-00b3-4aac-8ceb-c9ca163a0214')
ON CONFLICT (uuid) DO NOTHING;
WITH
 ins1 AS (INSERT INTO Point (latitude, longitude, srid)
VALUES (37.251667, 14.917222, 4326) RETURNING id),
 ins2 as (INSERT INTO SPoint (idPt, uuiddpt)
     VALUES ((SELECT id FROM ins1), '5547f4b7-00b3-4aac-8ceb-c9ca163a0214') RETURNING id),
 ins3 as (INSERT INTO Distance (idSpt, uuiddpt)
     VALUES ((SELECT id FROM ins2), '5547f4b7-00b3-4aac-8ceb-c9ca163a0214'))
INSERT INTO DPointTS (uuid, type, name, idPoint)
VALUES ('5547f4b7-00b3-4aac-8ceb-c9ca163a0214', NULL, NULL, (SELECT id FROM ins1));

SELECT CASE WHEN
(SELECT uuid FROM DPoint
WHERE uuid = '5547f4b7-00b3-4aac-8ceb-c9ca163a0214' )
is not NULL THEN ROLLBACK TO SAVEPOINT my_savepoint END;
COMMIT;

Моя идея такова:

При попытке вставить еще раз DPoint.uuid='5547f4b7-00b3-4aac-8ceb-c9ca163a0214' не нужно вставлять Point, SPoint, Distance, DPointTS. Поэтому я хотел бы ОТМЕНИТЬ эти вставки в my_savepoint в транзакции. Может быть, есть идеи, каким образом я должен переписать свой код?

ИЗМЕНИТЬ:

SELECT uuid IS NULL AS is_not_uuid FROM DPoint WHERE uuid = '5547f4b7-00b3-4aac-8ceb-c9ca163a0214';
\gset
\if :is_not_uuid
    \echo 'insert row to DPoint'
    INSERT INTO DPoint (uuid) VALUES ('5547f4b7-00b3-4aac-8ceb-c9ca163a0214');
    ... 
    my INSERT query

\endif

Я обновляю свою стратегию без точек сохранения - если запрос SELECT возвращает TRUE, я оцениваю все вставки. Каким образом я выполняю запрос, только в командной строке? При попытке в console.sql в DataGRIP выдает ошибку - честно выполняет все строки и терпит неудачу в INSERT INTO DPoint (uuid)... если точка уже существует. Я хотел бы выполнить операторы одним способом


person Jane    schedule 20.12.2019    source источник


Ответы (1)


Нет, так нельзя.

Вам придется написать клиентский код и использовать условную обработку.

Например, с psql:

-- set the variable "want_rollback" to TRUE or FALSE
SELECT uuid IS NOT NULL AS want_rollback
FROM dpoint
WHERE uuid = '5547f4b7-00b3-4aac-8ceb-c9ca163a0214' \gset
\if :want_rollback
ROLLBACK TO SAVEPOINT my_savepoint;
\endif

Подробнее о \if см. в документации:

\if expression
\elif expression
\else
\endif

Эта группа команд реализует вложенные условные блоки. Условный блок должен начинаться с \if и заканчиваться \endif. Между ними может быть любое количество предложений \elif, за которыми может дополнительно следовать одно предложение \else. Обычные запросы и другие типы команд обратной косой черты могут (и обычно появляются) появляться между командами, образующими условный блок.

Команды \if и \elif считывают свои аргументы и оценивают их как логические выражения. Если выражение дает true, то обработка продолжается в обычном режиме; в противном случае строки пропускаются до тех пор, пока не будет достигнуто соответствие \elif, \else или \endif. После успешного выполнения теста \if или \elif аргументы более поздних команд \elif в том же блоке не оцениваются, а рассматриваются как ложные. Строки, следующие за \else, обрабатываются только в том случае, если ни одно из предыдущих совпадений \if или \elif не было успешным.

Аргумент expression команды \if или \elif подлежит интерполяции переменных и расширению обратных кавычек, как и любой другой аргумент команды обратной косой черты. После этого он оценивается как значение переменной опции включения/выключения. Таким образом, допустимым значением является любое однозначное совпадение без учета регистра для одного из: true, false, 1, 0, on, off, yes, no. Например, t, T и tR будут считаться true.

Выражения, которые неправильно оцениваются как истинные или ложные, будут генерировать предупреждение и рассматриваться как ложные.

Пропущенные строки обычно анализируются для идентификации запросов и команд обратной косой черты, но запросы не отправляются на сервер, а команды обратной косой черты, кроме условных (\if, \elif, \else, \endif), игнорируются. Условные команды проверяются только на допустимую вложенность. Ссылки на переменные в пропущенных строках не раскрываются, и раскрытие обратных кавычек также не выполняется.

Все команды обратной косой черты данного условного блока должны появляться в одном и том же исходном файле. Если EOF будет достигнут в основном входном файле или файле с \include-ed до того, как все локальные блоки \if будут закрыты, psql выдаст ошибку.

На той же странице будет также объяснено \gset.

person Laurenz Albe    schedule 20.12.2019
comment
Спасибо за быстрый ответ! Не могли бы вы дать мне более подробную информацию об условной обработке? Я не понял про использование want_rollback, \gset... - person Jane; 20.12.2019
comment
Я добавил некоторую документацию. - person Laurenz Albe; 20.12.2019
comment
\if работает только в psql. Если вы работаете в другой среде, вы должны использовать язык программирования, доступный в этой среде. - person Laurenz Albe; 07.01.2020