Firebird / IBPP插入失败

时间:2016-03-16 19:09:53

标签: c++ firebird firebird2.5 firebird-embedded

我有一个C ++应用程序,它通过IBPP库使用嵌入式Firebird数据库(例如,在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 ...在同一事务中获取ID,或者通过上面... returning ID变量末尾的SQL_STMT获取ID。但是一旦提交了事务并且代码的其他部分试图获取表中的值,它就不存在了。在任何时候我都不会收到错误/异常。

为什么我在这些情况下没有收到错误的任何想法?

1 个答案:

答案 0 :(得分:2)

So a few weeks later a coworker and I stumbled onto the cause of this issue while looking into a slightly different issue. We were doing our work/testing using the 64 bit Microsoft Visual Studio C++ toolchain. The Firebird libraries return status and error information through an array of type ISC_STATUS. The libraries define this as a typedef of intptr_t which is pointer sized and thus on a 64 bit system is 64 bits.

The IBPP library dynamically loads the Firebird client libraries. When it defines its version of ISC_STATUS, it defines it as a long. On Linux/GCC I think this works (e.g. will be 32 bits on a 32 bit architecture and 64 bits on a 64 bit architecture) but in Microsoft's Visual C++ long is always 32 bits. The result was that when we compiled and ran in a 64 bit configuration it was interpreting an array of 64 bit integers as an array of 32 bit integers. The result was that, as all the values that were put in the array were positive integers that fit in 32 bits, it appeared that every other value in the status array was 0. IBPP detects errors by checking for a non-zero value in the second spot in the array which in 64 bit processing would always be zero because of this.

The solution was to update IBPP's definition of ISC_STATUS to properly match what the Firebird client library was using (this is in the 'ibase.h' header file).