2

我有一个 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 ...我可以(显然成功地)在执行插入后使用 a 或通过上述变量... returning ID末尾的a获取同一事务中的 ID 。SQL_STMT但是一旦事务提交并且代码的其他部分尝试获取表中的值,它就不存在了。我绝不会收到错误/异常。

有什么想法为什么我在这些情况下没有出错?

4

1 回答 1

2

所以几周后,我和一位同事在研究一个稍微不同的问题时偶然发现了这个问题的原因。我们正在使用 64 位 Microsoft Visual Studio C++ 工具链进行工作/测试。Firebird 库通过类型数组返回状态和错误信息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 位处理中总是为零。

解决方案是更新 IBPP 的定义ISC_STATUS以正确匹配 Firebird 客户端库正在使用的内容(位于“ibase.h”头文件中)。

于 2016-04-15T14:56:45.527 回答