2

IBPP ライブラリ経由で組み込みの Firebird データベースを使用する C++ アプリケーションがあります (たとえば、Windows で組み込み用に fbembed.dll を使用する)。現在、Firebird のバージョン 2.5.3 と IBPP の 2.5.3.1 を使用しています。私が抱えている問題は、列サイズの問題または制約違反 (たとえば、挿入が失敗する必要がある) のために挿入できないデータを挿入しようとすると、エラーや挿入失敗の兆候が表示されないことです。

(単純化された代表的な)例として、次のような表があります。

create table USER_TABLE (
    ID BIGINT not null,
    USER_ID VARCHAR(10) not null,
    DISPLAY_NAME VARCHAR(50) not null,
-- etc...
    primary key (ID),
    unique (USER_ID)
);

ID 列には、挿入前トリガーのジェネレーターが取り込まれます。ここで、次のコードを使用してアプリケーションから挿入しようとします。

const string SQL_STMT = "insert into USER_TABLE "
        "(USER_ID, DISPLAY_NAME, etc) "
        "values (?, ?, ?);";
IBPP::Statement stmt = IBPP::StatementFactory(m_db, m_tr, SQL_STMT);
stmt->Set(1, userDataObject.getUserId());//returns const string&,
stmt->Set(2, userDataObject.getDisplayName());//returns const string&
//etc, etc...
stmt->Execute();

私のuserDataObject.getUserId()値が列に対して長すぎる文字列である場合、1234567890xxx期待するような例外は発生しません。select ID from user_table where ...挿入を行った後、または上記の変数... returning IDの末尾にあるa を使用して、同じトランザクション内で ID を取得できます (明らかに成功したようです) 。SQL_STMTしかし、トランザクションがコミットされ、コードの他の部分がテーブル内の値を取得しようとすると、そこにはありません。エラー/例外が発生することはありません。

これらの状況でエラーが発生しない理由はありますか?

4

1 に答える 1

2

そのため、数週間後、同僚と私は、わずかに異なる問題を調べているときに、この問題の原因に遭遇しました。私たちは、64 ビットの Microsoft Visual Studio C++ ツールチェーンを使用して作業/テストを行っていました。Firebird ライブラリは、 type の配列を介してステータスとエラー情報を返しますISC_STATUS。ライブラリはこれをポインタサイズの typedef として定義しているintptr_tため、64 ビットシステムでは 64 ビットです。

IBPP ライブラリは、Firebird クライアント ライブラリを動的にロードします。のバージョンを定義するときISC_STATUS、それを として定義しますlong。Linux/GCC ではこれが機能すると思います (たとえば、32 ビット アーキテクチャでは 32 ビット、64 ビット アーキテクチャでは 64 ビットになります) が、Microsoft の Visual C++ ではlong常に 32 ビットです。その結果、64 ビット構成でコンパイルして実行すると、64 ビット整数の配列が 32 ビット整数の配列として解釈されました。その結果、配列に入れられたすべての値は 32 ビットに収まる正の整数であったため、ステータス配列の他のすべての値は 0 のように見えました。IBPP は、このため、64ビット処理では常にゼロになる配列の2番目のスポット。

解決策は、IBPP の の定義をISC_STATUS、Firebird クライアント ライブラリが使用しているものに適切に一致するように更新することでした (これは 'ibase.h' ヘッダー ファイルにあります)。

于 2016-04-15T14:56:45.527 に答える