在 Ubuntu 上将 Python ODBC 与 Cloudera Impala ODBC driver 一起使用时出现 ParseException 语法错误

ParseException Syntax error when using Python ODBC with Cloudera Impala ODBC driver on Ubuntu

我们在 AWS EC2 实例 (Amazon Linux) 上有一个 Python 3.7 应用程序 运行,它针对 Cloudera Impala 服务执行 SQL 查询使用 pyodbc (4.0.27) 和 Cloudera Impala ODBC driver(使用 ClouderaImpalaODBC-2.6.5.rpm 安装)。此应用程序已 运行 成功多年。

我目前正在尝试在 Docker 容器 运行 Ubuntu 18.04.4 LTS 中获取应用程序 运行,但遇到以下错误时遇到问题运行 即使是最基本的查询(例如 SELECT 'HELLO'):

Error: ('HY000', '[HY000] [Cloudera][ImpalaODBC] (110) Error while executing a query in Impala: [HY000] : ParseException: Syntax error in line 1:\n\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\n^\nEncountered: Unexpected character\nExpected: ALTER, COMMENT, COMPUTE, COPY, CREATE, DELETE, DESCRIBE, DROP, EXPLAIN, GRANT, INSERT, INVALIDATE, LOAD, REFRESH, REVOKE, SELECT, SET, SHOW, TRUNCATE, UPDATE, UPSERT, USE, VALUES, WITH\n\nCAUSED BY: Exception: Syntax error\n\x00\u6572\u3a64\u5520\u656e\u7078\u6365\u6574\u2064\u6863\u7261\u6361\u6574\u0a72 (110) (SQLExecDirectW)')"}

不用说这看起来像是字符串编码问题。

一些上下文管理:

我尝试为 Impala ODBC driver 参数“DriverManagerEncoding”设置不同的值,例如“UTF-16”、“UTF-32”完全有它(亚马逊 Linux 设置就是这种情况)但总是得到同样的错误。

我还尝试在两个系统上使用 odbclinux 工具 isql 尝试以这种方式进行故障排除;能够从 Amazon Linux 系统成功连接,但无法在 Ubuntu 上连接 - 始终得到以下信息(不确定这是否相关或其他问题):

iusql -v [DSN]
[unixODBC][
[ISQL]ERROR: Could not SQLDriverConnect

找到了罪魁祸首 - /opt/cloudera/impalaodbc/lib/64/cloudera.impalaodbc.ini 中的设置 DriverManagerEncoding:

[Driver]

## - Note that this default DriverManagerEncoding of UTF-32 is for iODBC.
## - unixODBC uses UTF-16 by default.
## - If unixODBC was compiled with -DSQL_WCHART_CONVERT, then UTF-32 is the correct value.
##   Execute 'odbc_config --cflags' to determine if you need UTF-32 or UTF-16 on unixODBC
## - SimbaDM can be used with UTF-8 or UTF-16.
##   The DriverUnicodeEncoding setting will cause SimbaDM to run in UTF-8 when set to 2 or UTF-16 when set to 1.

DriverManagerEncoding=UTF-32
ErrorMessagesPath=/opt/cloudera/impalaodbc/ErrorMessages/
LogLevel=0
LogPath=
SwapFilePath=/tmp


## - Uncomment the ODBCInstLib corresponding to the Driver Manager being used.
## - Note that the path to your ODBC Driver Manager must be specified in LD_LIBRARY_PATH (LIBPATH for AIX).
## - Note that AIX has a different format for specifying its shared libraries.

# Generic ODBCInstLib
#   iODBC
# ODBCInstLib=libiodbcinst.so

#   SimbaDM / unixODBC
#ODBCInstLib=libodbcinst.so

# AIX specific ODBCInstLib
#   iODBC
#ODBCInstLib=libiodbcinst.a(libiodbcinst.so.2)

#   SimbaDM
#ODBCInstLib=libodbcinst.a(odbcinst.so)

#   unixODBC
ODBCInstLib=libodbcinst.a(libodbcinst.so.1)

此文件是作为驱动程序安装的一部分自动生成的。请注意关于 iODBC 与 unixODBC 的评论——我们只安装了后者。

一旦我注释掉该配置,我们的 python 应用程序就可以运行了。它还修复了 iusql(这是 unixODBC 安装的一部分)的问题。

奖金内容:

我也遇到了 iqsl(不是 iusql)的问题 - 正在为命令 isql -v [DSN]:

获取此 error/output
[S1000][unixODBC][Cloudera][ODBC] (11560) Unable to locate SQLGetPrivateProfileString function.
[ISQL]ERROR: Could not SQLConnect

该错误与同一 ini 文件中的配置参数 ODBCInstLib 有关。一旦我将它从默认 libodbcinst.a(libodbcinst.so.1) 更改为 /usr/lib/x86_64-linux-gnu/libodbcinst.so 它就起作用了。找到答案就在这个post里面,居然帮我解决了原来的问题:

Can't connect to snowflake via unixODBC. Error: [S1000][unixODBC][Snowflake][ODBC] (11560) Unable to locate SQLGetPrivateProfileString function