ruby - 自动提交 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_option
raw_connection,所以我可以调用类似的东西.set_option(ODBC::SQL_AUTOCOMMIT, false)
,它以完全相同的方式失败。ODBC::SQL_AUTOCOMMIT
只是一个常量102
,我发现在一些关于 ODBC 的地方引用了它,所以我想如果我能找出常量TRUEAUTOCOMMIT
,我也许可以用这种方式设置它,但找不到任何文档这个。
.autocommit
在这种配置下工作有什么建议吗?
编辑:显然你可以为 odbc 使用 DSN,所以我也尝试在 /etc/odbc.ini 中创建一个,以及“TrueAutoCommit = 1”的选项,但这并没有改变任何东西。去工作。
解决方案
推荐阅读
- scala - Spark scala 在一个 jar 中具有依赖项
- javascript - 在angularjs中单击按钮时隐藏和显示
- android - React native App 在发布模式下崩溃,并出现以下错误 null is not an object (evalating 's.drawer._root')
- php - 当使用 BinaryFileResponse 文件校验和更改时
- .net-core - 尝试从 Web 安装 .net 核心托管捆绑包时,WiX 捆绑包获取“无法验证有效负载的哈希值”
- javascript - 有没有办法在反应一页应用程序中写入服务器上的文件?
- reactjs - 点击事件的反应路由不起作用
- mongodb - 如何知道集合何时更新?
- swift - “此版本的 Xcode 不支持”和更新后 Xcode 引发“不支持的 Swift 版本”
- python - 在已排序的python列表中,找到最接近目标值的值及其在列表中的索引