1

この質問は私の前の質問に関連しています:unixODBC C APIと同等のRaiseError(PERL、DBI)?

後で問題を切り分けたので、新しい質問を投稿します。それは、より具体的で、切り分けられ、不要な情報がないものです。


バージョン:unixODBC 2.3.0
lib:unixODBC-C API

ストアドファンクションがあるとします:

CREATE FUNCTION "test".func() 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".proc(pDummy SMALLINT)
set debug file to '/home/directory_does_not_exists/unknown.log';
trace off;
trace on;
LET pDummy = 2;
trace off;
END PROCEDURE;

ご覧のとおり、まったく同じです。デバッグファイルへのパスが間違っているため、エラーが発生する可能性があります。call func()エラーから実行するとAqua Data Studio、エラーが検出されます。

Cannot open DEBUG file for SPL routine trace

も同じですcall proc(1)

しかし、 unixODBCSQLExecuteを介して(を使用して)これらの2つの呼び出しを実行すると

execute procedure proc(1);

戻りますSQL_ERROR(これは期待されて問題ありません)が、

execute function func();

戻り値SQL_SUCCESS..しかし 'result is set here'、返されません。代わりに、空の文字列('')が返されます。

実行call func()すると、と同じ結果が得られます。execute function func();

を呼び出すと、がSQLMoreResults返されます。SQL_NO_DATASQLFetchSQL_ERROR

何か案は?

4

3 に答える 3

1

私はInformixを使用していませんが、Perl DBD :: ODBCとisql(Cで記述)で試した簡単な例はすべてエラーを返します。

use strict;
use warnings;
use DBI;

my $h = DBI->connect();
eval {
    $h->do(q/drop function fmje/);
};

$h->do(<<'EOS');
create function fmje (@p1 as int)
returns int
as
begin
    declare @a int;

    set @a = 'fred';
    return @p1;
end;
EOS

my $s = $h->prepare(q/{? = call fmje(?)/);
$s->bind_param_inout(1, \my $x, 10);
$s->bind_param(2, 1);
$s->execute;
print "return is ", ($x ? $x : "undef"), "\n";



isql -v baugi sa easysoft
+---------------------------------------+
| Connected!                            |
|                                       |
| sql-statement                         |
| help [tablename]                      |
| quit                                  |
|                                       |
+---------------------------------------+
SQL> {call fmje(1)}
[22005][unixODBC][Easysoft][SQL Server Driver 11.0][SQL Server]Conversion failed when converting the varchar value 'fred' to data type int.
[ISQL]ERROR: Could not SQLExecute
SQL>

Informixは関数に対して異なる動作をする必要があります。そうでない場合は、AquaDataStudioを介して汎用ODBCを使用していない可能性があります。

他の投稿で言うようにPerlからのエラーが表示された場合は、そこで推奨されているように実行し、次を追加します。

[ODBC]
Trace=yes
TraceFile=/tmp/unixodbc.log

odbcinst.iniファイルの先頭に移動し、Perlを実行します。次に、エラーのログの行を表示します。次に、isqlで繰り返して、ODBC呼び出しを比較できるようにします。

于 2011-07-27T16:21:57.493 に答える
1

これは、使用しているサーバーのバージョン(可能性は低いですが可能です)、または使用しているAPIに関係している可能性があります。ESQL / C(CSDK)3.70.FC2でビルドされた(my)sqlcmdプログラムを使用してMacOS X10.7でIDS11.70.FC2をテストすると、次のようになります。

$ sqlcmd -c -d stores -e begin -xf x1.sql -e 'execute procedure proc(2)' \
         -e 'execute function func()' 
+ CREATE FUNCTION "test".func() 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".proc(pDummy SMALLINT)
set debug file to '/home/directory_does_not_exists/unknown.log';
trace off;
trace on;
LET pDummy = 2;
trace off;
END PROCEDURE;
+ execute procedure proc(2)
SQL -648: Cannot open DEBUG file for SPL routine trace.
SQLSTATE: IX000 at /dev/stdin:0
+ execute function func()
SQL -648: Cannot open DEBUG file for SPL routine trace.
at /dev/stdin:0
$

ご覧のとおり、ESQL/Cのエラーfunc()を正しく報告します。proc()したがって、問題はほぼ確実にクライアント側のコードにあります。つまり、ODBCドライバーとエラーの処理方法、またはODBCドライバーを呼び出すコードにあります。

問題をさらに切り分ける方法は?

環境内でテストを実行SQLIDEBUG=2:xyzします。次に、名前が(たとえば、xyz_取得した)で始まるファイルを見つけて実行します。これにより、サーバーがエラーメッセージを2回生成しているかどうかがわかります。xyz_35424_0_819800sqliprint

1つのトレースでこれに似た2つのパケットを取得しました。

S->C (12)               Time: 2011-07-28 00:28:02.41736
    SQ_ERR
        SQL error..........: -648
        ISAM/RSAM error....: 0
        Offset in statement: 0
        Error message......: "" [0]
    SQ_EOT

-648エラーのある2つのパケットが表示された場合は、クライアントがエラーを処理している方法に問題があることがわかります。2つのエラーが表示されない場合は、何が起こっているのか非常に興味があります。

于 2011-07-28T07:31:33.950 に答える
0

まず第一に、@ Jonathan Leffler(+のヒントと彼のマシンでのテスト)と@bohica(のヒントのサポートに感謝します!それは私が本当の問題を見つけてそれを解決するのに本当に役立ちました!両方とも私から+1。 残念ながら、答えは彼らの投稿にはありませんでした。それが私が自分で答える理由です。SQLIDEBUG=2:xyzsqliprintstrace


概要:

SQLPrepare一部のエラーでSQLExecute失敗することもありますが、すべてではありません。ストアドプロシージャを使用すると、これらの関数はより多くのエラーをキャッチします。残念ながら、保存されている関数では状況が異なります。

エラーを今すぐキャッチするにはどうすればよいですか?成功した場合SQLExecute、私は電話しますSQLNumResultCols-それは正常です。その後、SQLFetchこれも期待通りに電話します。ただし、SQLFetch多くの理由で失敗する可能性があるため(たとえば、ストアドプロシージャでは常に失敗します)、エラーは無視されます。そして、のwhileようなものがあります

if ( SQLNumResultCols( stmt, &nAllCols ) != SQL_SUCCESS )
// ...

int nSucceededFetches = 0; // added now, see below why
while ( SQL_SUCCEEDED( SQLFetch( stmt ) ) )
{
    ++nSucceededFetches; // added now, see below why
    /* bla bla */ 
}

そしてここに鍵があります-追加のチェックを追加します:

if( 0 == nSucceededFetches && nColumns > 0 )

つまり、返された列あり、最初の呼び出しでフェッチが失敗した場合は、何かが間違っています。で、〜がある

while ( SQL_SUCCESS == SQLError( 0, 0, stmt, szSqlState, &nNativeError, szError, 500, &nErrorMsg ) )
{ /* bla bla */ }

そして、すべてが順調です。なぜSQLExecute戻るのかSQL_SUCCESSSQL_SUCCESS_WITH_INFO..でもない)はまだわかりませんが、それは問題ではありません。

于 2011-08-01T13:34:03.087 に答える