Эквивалент RaiseError (PERL, DBI) для unixODBC C API?

У меня проблема с выполнением некоторых хранимых процедур/функций в INFORMIX DB. Пробовал с разными клиентами и все одинаково - ни один не выявляет ошибок при выполнении, вместо этого - возвращают пустые ответы. И это не работает для меня.

Наконец, я обнаружил, что PERL DBI имеет возможность установить RaiseError, что-то вроде:

{  PrintError => 0, RaiseError => 1 }

И это работает идеально. А есть ли аналог (к сожалению, ничего не нашел) для библиотеки unixODBC C API?


Кроме того: я попробовал тот же запрос с isql, и это то же самое! Никаких ошибок, просто пустой результат :\ Может быть, это какая-то опция, которую нужно настроить (в odbc.ini, я думаю..)?


РЕДАКТИРОВАНИЕ: Хорошо, вот еще некоторые подробности:
Версия: unixODBC 2.3.0

CREATE FUNCTION "test".NOK_func_k() RETURNING LVARCHAR(1000);
set debug file to '/home/directory_does_not_exists/unknown.log';
trace off;
trace on;
trace off;
return 'result is set here';
END FUNCTION;

CREATE PROCEDURE "test".NOK_proc_k(pDummy SMALLINT)
set debug file to '/home/directory_does_not_exists/unknown.log';
trace off;
trace on;
LET pDummy = 2;
trace off;
END PROCEDURE;

И результаты от isql и ODBC C API одинаковы. Вот дополнительная информация о C API:

Executing: execute procedure NOK_proc_k(1)
retcode = SQL_ERROR     SQL_SUCCEEDED( retcode ) = 0
--------------------------------------------------
Executing: execute function NOK_func_k()
retcode = SQL_SUCCESS       SQL_SUCCEEDED( retcode ) = 1
--------------------------------------------------
--------------------------------------------------
Executing: execute function NOK_proc_k(1)
retcode = SQL_ERROR     SQL_SUCCEEDED( retcode ) = 0
--------------------------------------------------
Executing: execute procedure NOK_func_k()
retcode = SQL_SUCCESS       SQL_SUCCEEDED( retcode ) = 1
--------------------------------------------------
--------------------------------------------------
Executing: call NOK_proc_k(1)
retcode = SQL_ERROR     SQL_SUCCEEDED( retcode ) = 0
--------------------------------------------------
Executing: call NOK_func_k()
retcode = SQL_SUCCESS       SQL_SUCCEEDED( retcode ) = 1

Все вызовы SQLMoreResults возвращают SQL_NO_DATA, все SQLFetch возвращают SQL_ERROR.

Резюме - все вызовы неправильных процедур в порядке - возвращается ошибка. Но если эта ошибка находится в сохраненной функции - ошибка не обнаруживается; вместо этого - возвращается ПУСТАЯ строка. Уч!

SQL_SUCCESS_WITH_INFO нигде не возвращается. И так со многими другими ошибками (не со всеми, конечно, это просто пример)


И даже больше! Процедура или функция, например:

CREATE PROCEDURE "test".nok_proc_k_2() RETURNING LVARCHAR(1000);
DEFINE vNotDefined VARCHAR(10);
LET vNotDefined = current;
END PROCEDURE;

Не возвращает никакой ошибки, в то время как студия Aqua DB возвращает

Converted value does not fit into the allotted space

ОТВЕЧАТЬ:

Я приму ответ Бохики, так как он правильный и правильно отвечает на часть PERL DBI. Также он мне очень помог (попадание с strace).

В любом случае, настоящего решения здесь нет. Я разместил его в соответствующем вопросе, который является более конкретным и изолированным в конкретном случае: Та же ошибка обнаружена в сохраненной **процедуре**, но не в сохраненной **функции**


person Kiril Kirov    schedule 13.07.2011    source источник
comment
Я не могу сказать, что должно работать, а что нет. Все ваши процессы и функции называются nok_something. Вызов nok_func_k(), кажется, возвращает успех - хорошо, но выполнение процедуры nok_func_k() завершается успешно, а такой процедуры нет? Также, если эта ошибка в хранимой функции - возвращается ПУСТАЯ строка - где? если ошибка функции/процедуры, конечно, вы не ожидаете, что они вернут фактические значения. Я не могу больше помочь без конкретного примера того, какая у вас процедура/функция, как вы ее вызвали, что произошло и чего вы ожидали.   -  person bohica    schedule 27.07.2011
comment
@bohica - я разместил тела NOK_func_k и NOK_proc_k. Одно из них - процедура, другое - функция. Я написал, как они создаются. Кроме того, я разместил, как они выполняются: Executing: .... + результаты. Я не понимаю, какую еще информацию я должен опубликовать. NOK_proc_k - это процедура с ошибкой внутри. И ошибка обнаружена, поэтому я не ожидаю, что она что-то вернет. Как вы меня процитировали - если эта ошибка в сохраненной функции - возвращается ПУСТАЯ строка - видите, я говорю о ФУНКЦИИ, то есть я имею в виду nok_func_k.   -  person Kiril Kirov    schedule 27.07.2011
comment
@bohica - Все время удается nok_func_k, и это функция, а не процедура. Но у нее такое же тело, как и у процедуры (NOK_proc_k), просто она объявлена ​​как функция и возвращает строку. Обратите внимание, как NOK_func_k имеет возврат e в конце: return 'result is set here';. А так как ошибка не обнаружена, SQLExecute возвращает SQL_SUCCESS, а возвращаемая строка НЕ ​​"result is set here", а "". Какую часть я не объясню, хорошо..? :\   -  person Kiril Kirov    schedule 27.07.2011
comment
Также, выполняя call NOK_func_k() из Aqua Data Studio и то же самое из PERL DBI, выявляется ошибка: Cannot open DEBUG file for SPL routine trace...   -  person Kiril Kirov    schedule 27.07.2011
comment
@bohica - вы можете увидеть мой связанный вопрос - stackoverflow.com/questions/6843403/ Это более понятно (или, по крайней мере, я на это надеюсь), оно изолировано и без лишних Информация.   -  person Kiril Kirov    schedule 27.07.2011
comment
Спасибо за разъяснение. Итак, теперь мы знаем, что NOK_func_k должен дать сбой с сообщением «Невозможно открыть файл DEBUG», а я не мог знать этого раньше. Запустите свой Perl, вызвав NOK_func_k и показывая, что он не работает, но включите регистрацию в unixODBC. Вы делаете это, добавляя раздел [ODBC] в начало файла odbcinst.ini и добавляя под ним две строки Trace=yes и TraceFile=/tmp/unixodbc.log. Затем мы увидим, где обнаружена ошибка в трассировке ODBC.   -  person bohica    schedule 27.07.2011
comment
@bohica - интересно, что они у меня уже установлены, но файл трассировки не создается в /tmp/ :\   -  person Kiril Kirov    schedule 28.07.2011
comment
Вы должны убедиться, что он установлен в правильном файле. Запустите odbcinst -j, и он сообщит вам, какой файл/каталог unixODBC использует для системного ini-файла (odbcinst.ini). Вы должны иметь: [ODBC]\nTrace=yes\nTraceFile=/tmp/unixodbc.log вверху. Если вы не получаете трассировку, это могут быть разрешения или вы не используете unixODBC, как вы думаете.   -  person bohica    schedule 28.07.2011
comment
@bohica - это было в нужном файле, но не в том месте. Это было в моем разделе драйверов, а не в [ODBC]. Исправлено :). Теперь файл создается, но он все время пустой, что бы я ни выполнял.. :D   -  person Kiril Kirov    schedule 28.07.2011
comment
В случае, если я не знаю, если у вас есть место на диске. Вы можете найти его и посмотреть, где файл открыт, и посмотреть, что происходит с этим файловым дескриптором, но сейчас мы попадаем в темные воды.   -  person bohica    schedule 28.07.2011
comment
@bohica - если я установлю nTrace=yes или nTrace=on - ничего не произойдет. Когда ставлю 1 (nTrace=1) файл создается, но пустой :D Блин :\ А места хватает, дело в другом. Думаю попробовать strace, давно пора научиться им пользоваться :)   -  person Kiril Kirov    schedule 29.07.2011


Ответы (1)


Все, что делает RaiseError в Perl, это говорит, что когда DBD, такой как DBD::ODBC, видит ошибку, DBI вызывает любые зарегистрированные обработчики ошибок и вызывает die с этой ошибкой (в зависимости от того, что вернул обработчик ошибок). DBD по-прежнему должен сообщить об ошибке DBI с помощью метода set_err.

Я предполагаю, что ваш Perl использовал DBD::ODBC. DBD::ODBC просто проверит статус возврата каждого API ODBC, который он вызывает, и если это SQL_SUCCESS_WITH_INFO, он вызовет DBI set_err, говоря, что это предупреждение, а если это !SQL_SUCCEEDED, он вызовет set_err, говоря, что есть ошибка (есть некоторые исключения, такие как SQL_NO_DATA, что не всегда является ошибкой).

Если вы говорите, что ваш Perl умирает с ожидаемой ошибкой, а ваш код C - нет, то вы не должны проверять возврат ODBC API или, возможно (поскольку вы упоминаете процедуры), вы не гарантируете, что вызов SQLMoreResults в цикле после SQLExecute на SQL для вызова процедуры. Имейте в виду, что некоторые базы данных выполняют каждую вставку/выборку/обновление в процедуре по одному, и в ODBC вам нужно вызывать SQLMoreResults для перемещения по каждому из них. Если вы этого не сделаете, ваша процедура не будет завершена и, следовательно, вы, возможно, не столкнулись с ошибкой.

person bohica    schedule 13.07.2011
comment
Ну, я пробовал с SQLExecDirect и SQLExecute, и оба возвращают SQL_SUCCESS :( Соответственно, SQL_SUCCEEDED(SQLExecute( stmt )) возвращает true :\ Вот что меня беспокоит, но я еще не пробовал SQLMoreResults. - person Kiril Kirov; 13.07.2011
comment
Интересно, что выполнение того же с isql снова не дает мне никаких ошибок. Итак, я предполагаю, что это может быть какой-то настраиваемый параметр? - person Kiril Kirov; 13.07.2011
comment
isql не вызывает SQLMoreResults - person bohica; 13.07.2011
comment
Если хотите, я могу показать вам, что делает DBD::ODBC с точки зрения ODBC. Просто установите DBI_TRACE=15=x.log и экспортируйте его, а затем перезапустите Perl. Вы получите грузы, которые дадут вам подсказку. В качестве альтернативы, предполагая, что вы используете диспетчер драйверов unixODBC, вы можете включить в нем отслеживание всех вызовов ODBC. - person bohica; 13.07.2011
comment
isql не вызывает SQLMoreResults — Да, вызывает - person Nick Gorham; 13.07.2011
comment
ладно, это не использовалось, и в случае с Кириллом мы не знаем, какую версию unixODBC он использует, поэтому это все еще может объяснить, почему isql не показывает ошибку для его процедуры. - person bohica; 14.07.2011
comment
в bohica и @Nick Gorham - я просто добавил несколько тестов, чтобы проиллюстрировать, что я имею в виду. + добавлена ​​версия. Пожалуйста, просмотрите обновленный вопрос. Спасибо! - person Kiril Kirov; 26.07.2011
comment
Смотрите мое редактирование (часть ОТВЕТА, чтобы не повторять ее здесь :)). Спасибо, в любом случае! :) +1 и принято. - person Kiril Kirov; 01.08.2011