首页 > 解决方案 > 自动提交 ODBC api 无法通过 IBM iAccess 到 unixODBC 到 ruby​​-odbc

问题描述

我目前正在使用 ODBC 通过 Rails -> (small as400 odbc adapter) -> odbc_adapter (gem 4.2.4) -> ruby​​-odbc (gem 0.999991) -> unixODBC (2.3.4, ubuntu 18.04) 访问 IBM as400 机器-> IBMiAccess(最新)。出乎意料的是,这一切都运行良好,除了最近我们遇到了包含特定字符的字符串问题,导致 ruby​​-odbc 中出现错误。

检索带有特殊字符 '¬' 的记录失败:

ActiveRecord::StatementInvalid (ArgumentError: negative string size (or size too big): SELECT * from data WHERE id = 4220130.0)

似乎特殊字符最终占用了 2 个字节,并且发生的任何转换都无法正确处理。

使用编码 Encoding:ASCII-8BIT 返回没有特殊字符的字符串。

有一个 utf8 版本的 ruby​​-odbc,我可以通过在我们的 iSeries 适配器中需要它来加载它,然后需要 odbc_adapter:

require 'odbc_utf8'  # force odbc_adapter to use the utf8 version
require 'odbc_adapter'

这允许 odbc-ruby 的 utf8 版本占用 odbc_adapter 将使用的 ODBC 模块名称。虽然有问题:

odbc_adapter调用(odbc-ruby).get_info上的多个字段raw_connection,这些字符串返回错误,例如"DB2/400 SQL"来自 ODBC::SQL_DBMS_NAME 的字符串看起来像: "D\x00B\x002\x00/\x004\x000\x000\x00 \x00S\x00Q\x00L\x00",编码为Encoding:ASCII-8BIT. odbc_adapter使用正则表达式将 dbms 映射到我们的适配器,这不匹配: /DB2\/400 SQL/ =~ (this_string)=> null

我对字符串编码不是很熟悉,但是能够在.gsub("\0", "")这里破解来修复这个检测。之后,我可以返回字符串中包含特殊字符的记录。它们返回时没有错误,在 中带有可见的特殊字符Encoding:UTF-8

当然,现在查询特殊字符会失败:

ActiveRecord::StatementInvalid (ODBC::Error: HY001 (30027) [IBM][System i Access ODBC Driver]Memory allocation error.: SELECT * from data WHERE (mystring like '%¬%'))

但我不太在意。现在的问题是 ruby​​-odbc 的 UTF8 版本似乎将 ODBC 版本设置为 3,而在非 utf8 版本上它是 2:

Base.connection.raw_connection.odbc_version => 3

这似乎阻止了自动提交工作(适用于版本 2):

Base.connection.raw_connection.autocommit => true
Base.connection.raw_connection.autocommit = false 
ODBC::Error (IM001 (0) [unixODBC][Driver Manager]Driver does not support this function)

此函数用于在 odbc_adapter 中启动/结束事务,并且似乎是 odbc 的标准功能: https ://github.com/localytics/odbc_adapter/blob/master/lib/odbc_adapter/database_statements.rb#L51

我在 IBMiAccess 文档中四处寻找,发现了一些关于事务级别和新的“trueautocommit”选项的信息,但我似乎无法弄清楚这个 trueautocommit 是否取代了 autocommit,或者即使 autocommit 不再支持这种方式。 https://www.ibm.com/support/pages/ibm-i-access-odbc-commit-mode-data-source-setting-isolation-level-and-autocommit

当然,我不知道如何通过 ruby​​-odbc gem 设置这个新的“trueautocommit”连接设置。它确实支持.set_optionraw_connection,所以我可以调用类似的东西.set_option(ODBC::SQL_AUTOCOMMIT, false),它以完全相同的方式失败。ODBC::SQL_AUTOCOMMIT只是一个常量102,我发现在一些关于 ODBC 的地方引用了它,所以我想如果我能找出常量TRUEAUTOCOMMIT,我也许可以用这种方式设置它,但找不到任何文档这个。

.autocommit在这种配置下工作有什么建议吗?

编辑:显然你可以为 odbc 使用 DSN,所以我也尝试在 /etc/odbc.ini 中创建一个,以及“TrueAutoCommit = 1”的选项,但这并没有改变任何东西。去工作。

标签: rubyodbcibm-midrange

解决方案


推荐阅读