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

Откуда:
Сообщений: 9
Возможно ли добиться правильной обработки ошибки syntax_error, так, чтобы в контексте ошибки указывалась, непосредственно, ошибочная инструкция (в данном примере arr_test = (select id, val1 from aaa)).

Все попытки (в т.ч. явное указание when syntax_error then) не приводят к желаемому результату. Контекст, просто, не содержит инструкции-виновницы и начинается уровнем выше. В данном случае это блок do "PL/pgSQL function inline_code_block line 9 at assignment"

В документации указаны только две ошибки, при обработке которых есть тонкости (query_canceled и assert_failure). Про syntax_error ничего не нашёл.

Использую PostgresPRO: PostgreSQL 9.6.5, compiled by Visual C++ build 1800, 64-bit

create temp table aaa (id int, val1 text);

do language plpgsql $$
declare
	error_message			text;
    error_detailed_message	text;
    error_context			text;
    arr_test				aaa[];
begin
	--arr_test = (select row(id, val1) from aaa);		-- Правильный вариант
	arr_test = (select id, val1 from aaa);			-- Ошибка 42601 syntax_error 
exception
	when others then
		--get stacked diagnostics error_message = pg_context;
		get stacked diagnostics error_message = message_text;
        get stacked diagnostics error_detailed_message = pg_exception_detail;
        get stacked diagnostics error_context = pg_exception_context;
		raise notice 'message_text % message_text', error_message;
        raise notice 'pg_exception_detail % pg_exception_detail', error_detailed_message;
        raise notice 'pg_exception_context % pg_exception_context', error_context;
end
$$;

drop table if exists aaa;
4 окт 17, 18:07    [20843184]     Ответить | Цитировать Сообщить модератору
 Re: Обработка ошибки syntax_error  [new]
vyegorov
Member

Откуда: Рига
Сообщений: 970
ДонАтелло,

`GET STACKED DIAGNOSTICS` надо один раз вызывать, передавая набор переменных через запятую, как в доке:
https://www.postgresql.org/docs/current/static/plpgsql-control-structures.html#PLPGSQL-EXCEPTION-DIAGNOSTICS
GET STACKED DIAGNOSTICS text_var1 = MESSAGE_TEXT,
                        text_var2 = PG_EXCEPTION_DETAIL,
                        text_var3 = PG_EXCEPTION_HINT;
4 окт 17, 20:23    [20843481]     Ответить | Цитировать Сообщить модератору
 Re: Обработка ошибки syntax_error  [new]
ДонАтелло
Member

Откуда:
Сообщений: 9
vyegorov,
Да, спасибо, это в суматохе. Но сути проблемы это не меняет. С единственным вызовом то же самое.
4 окт 17, 20:27    [20843487]     Ответить | Цитировать Сообщить модератору
 Re: Обработка ошибки syntax_error  [new]
Павел Лузанов
Member

Откуда:
Сообщений: 401
ДонАтелло,

Ошибка возникает при синтаксическом анализе анонимного блока (DO) перед его выполнением.
Соответственно поймать эту ошибку в коде блока в принципе невозможно. Блок выполняться даже не начинает, какой exception.
4 окт 17, 21:27    [20843659]     Ответить | Цитировать Сообщить модератору
 Re: Обработка ошибки syntax_error  [new]
ДонАтелло
Member

Откуда:
Сообщений: 9
Павел Лузанов,
Ну ответ принимается. Разумно. Но есть одна нестыковка!
Если эта ошибка происходит на этапе парсинга, т.е. до выполнения, куда же она девается?
В блок выполнения явно входит. И даже в блок exception попадает (мы видим отработавшие notice).
Если закомментировать блок обработки ошибок, получаем законное:

ERROR: subquery must return only one column
LINE 1: SELECT (select id, val1 from aaa)

Т.е. видим проблемный запрос и знаем куда бежать исправлять.
А с обработчиком ошибок мы эту возможность теряем. Несправедливо же?
5 окт 17, 12:17    [20844940]     Ответить | Цитировать Сообщить модератору
 Re: Обработка ошибки syntax_error  [new]
Павел Лузанов
Member

Откуда:
Сообщений: 401
ДонАтелло,

Точно, именно эту ошибку синтаксиса, plpgsql парсер не понимает и она перехватывается только в момент выполнения.
Поэтому возвращаемся к исходному вопросу.

Текст текущего анонимного блока можно взять из pg_stat_activity.query.

Что-то типа:
do language plpgsql $$
declare
    arr_test                            aaa[];
    error_context                       text;
    current_query                       text;
begin
        --arr_test = (select row(id, val1) from aaa);           -- Правильный вариант
        arr_test = (select id, val1 from aaa);                  -- Ошибка 42601 syntax_error 
exception
        when syntax_error then
                get stacked diagnostics error_context = pg_exception_context;
                select query into current_query from pg_stat_activity where pid = pg_backend_pid();
                raise notice E'%\n\n%', error_context, current_query;
end;
$$;


Результат:
NOTICE:  PL/pgSQL function inline_code_block line 8 at assignment

do language plpgsql $$
declare
arr_test aaa[];
error_context text;
current_query text;
begin
--arr_test = (select row(id, val1) from aaa); -- Правильный вариант
arr_test = (select id, val1 from aaa); -- Ошибка 42601 syntax_error
exception
when syntax_error then
get stacked diagnostics error_context = pg_exception_context;
select query into current_query from pg_stat_activity where pid = pg_backend_pid();
raise notice E'%\n\n%', error_context, current_query;
end;
$$;
DO
Для красоты из get stacked diagnostics ... pg_exception_context можно вырезать номер строки где возникла ошибка.
Ну и вырезать нужную строку из запроса.
А можно и визуально посчитать.
5 окт 17, 13:01    [20845144]     Ответить | Цитировать Сообщить модератору
 Re: Обработка ошибки syntax_error  [new]
ДонАтелло
Member

Откуда:
Сообщений: 9
Павел Лузанов,
Ну не идеально, но с этим уже можно жить, спасибо.
А то я замучился каждый раз комментировать блок exception, чтобы понять в какой инструкции ошибка.
5 окт 17, 13:05    [20845157]     Ответить | Цитировать Сообщить модератору
Все форумы / PostgreSQL Ответить