摘要
我尝试通过ODBC连接使用PHP 7.0.9和PDO查询Vertica数据库,但在生成的HTML页面中无法正确显示重音字母和EURO符号等特殊字符。
根据Vertica docs:
数据库服务器接收的所有输入数据预计为UTF-8,Vertica输出的所有数据均为UTF-8
环境设置
操作系统是CentOS Linux版本7.2.1511,内核为3.10.0-327.28.3.el7.x86_64
安装了PHP 7.0.9软件包:
php70w-cli-7.0.9-1.w7.x86_64
php70w-7.0.9-1.w7.x86_64
php70w-pear-1.10.1-1.w7.noarch
php70w-odbc-7.0.9-1.w7.x86_64
php70w-mbstring-7.0.9-1.w7.x86_64
php70w-common-7.0.9-1.w7.x86_64
php70w-process-7.0.9-1.w7.x86_64
php70w-xml-7.0.9-1.w7.x86_64
php70w-pecl-xdebug-2.4.0-1.w7.x86_64
php70w-pdo-7.0.9-1.w7.x86_64
其他套餐:
unixODBC-2.3.1-11.el7.x86_64
vertica-client-7.2.3-0.x86_64
相关配置文件:
/etc/vertica.ini
[Driver]
DriverManagerEncoding=UTF-16
ODBCInstLib=/usr/lib64/libodbcinst.so
ErrorMessagesPath=/opt/vertica
LogLevel=4
LogPath=/tmp
/etc/odbcinst.ini
[HPVertica]
Description = Vertica ODBC Driver
Driver = /opt/vertica/lib64/libverticaodbc.so
[ODBC]
Threading = 1
/etc/odbc.ini
[ODBC Data Sources]
Test_Vertica = "Test Vertica"
[Test_Vertica]
Description = Test Vertica
Driver = HPVertica
Database = VMart
Servername = <redacted>
UID = <redacted>
PWD = <redacted>
Port = 5433
测试用例
如果我创建一个包含特殊字符的表并进行查询,结果会在终端中正确显示(环境变量$LANG
设置为en_US.UTF-8
):
# /opt/vertica/bin/vsql -h <redacted> -d VMart -U dbadmin
VMart=> create table stackoverflow(str varchar(100));
VMart=> insert into stackoverflow(str) values ('àèìòù €uro');
VMart=> commit;
# /opt/vertica/bin/vsql -h <redacted> -d VMart -U dbadmin -c 'select * from stackoverflow'
str
------------
àèìòù €uro
(1 row)
# echo 'select * from stackoverflow' | isql Test_Vertica
SQL> select * from stackoverflow
+-----------------------------------------------------------------------------------------------------+
| str |
+-----------------------------------------------------------------------------------------------------+
| àèìòù €uro |
+-----------------------------------------------------------------------------------------------------+
SQLRowCount returns 1
1 rows fetched
但是,这个简单的PHP脚本会向用户代理发送垃圾:
<?php
$dbconn = new PDO('odbc:Test_Vertica');
$sql = 'select * from stackoverflow';
$statement = $dbconn->prepare($sql);
$statement->execute();
$results = $statement->fetchAll(PDO::FETCH_ASSOC);
header('Content-Type: text/html; charset=utf-8');
var_dump($results);
终端输出:
# php /var/www/html/stackoverflow.php
/var/www/html/stackoverflow.php:8:
array(1) {
[0] =>
array(1) {
'str' =>
string(17) "àèìòù €uro"
}
}
浏览器中的输出(也在最新的Chrome和IE中尝试过):
# elinks -dump http://localhost/stackoverflow.php
/var/www/html/stackoverflow.php:10:
array (size=1)
0 =>
array (size=1)
'str' => string '..... .uro' (length=10)
似乎代替特殊字符,&#34; SUB&#34; ASCII代码(十六进制1A)发送给用户代理。有些浏览器将其显示为点,其他浏览器显示为空格。
有什么想法吗?感谢。