php / php/php-src

unicode string corruption when using PDO_ODBC with FreeTDS 1.3.6 and MS SQL Server 2016

未关闭
#9,498 10 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看

还没有人认领这个 Issue。

Bug Extension: pdo_odbc Status: Needs Triage
主要语言
C
星标
40.4k
派生
8.1k
平均合并
2 天 13 小时
30 天内合并 PR
96

描述

Description

The following code:

<?php
// setup database connection
$u = getenv('DB_USERNAME');
$p = getenv('DB_PASSWORD');
$dsn = 'odbc:testUTF8';
$db = new \PDO($dsn, $u, $p);
$db->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);

$constant_tests = [
    "SELECT CAST(0x72006f017e016f007600fd00 AS nvarchar(10)) AS pink_in_czech_binary_encoded_utf16;",
    "SELECT CAST(0x6b26 AS nvarchar(3)) AS Beamed_Eighth_Notes_binary_encoded_utf16;",
    "SELECT NCHAR(0x266b) AS Beamed_Eighth_Notes_nchar;",
    "SELECT N'♫' AS Beamed_Eighth_Notes_unicode_string_constant;",
    "SELECT N'růžový' AS pink_in_czech_unicode_string_constant;",
];
foreach($constant_tests as $t) {
    fwrite(STDERR, "Running query '$t'...\n");
    var_dump($db->query($t, \PDO::FETCH_ASSOC)->fetchAll());
}

Resulted in this output:

Running query 'SELECT CAST(0x72006f017e016f007600fd00 AS nvarchar(10)) AS pink_in_czech_binary_encoded_utf16;'...
array(1) {
  [0]=>
  array(1) {
    ["pink_in_czech_binary_encoded_utf16"]=>
    string(9) "růžový"
  }
}
Running query 'SELECT CAST(0x6b26 AS nvarchar(3)) AS Beamed_Eighth_Notes_binary_encoded_utf16;'...
array(1) {
  [0]=>
  array(1) {
    ["Beamed_Eighth_Notes_binary_encoded_utf16"]=>
    string(3) "♫"
  }
}
Running query 'SELECT NCHAR(0x266b) AS Beamed_Eighth_Notes_nchar;'...
array(1) {
  [0]=>
  array(1) {
    ["Beamed_Eighth_Notes_nchar"]=>
    string(3) "▒▒"
  }
}
Running query 'SELECT N'♫' AS Beamed_Eighth_Notes_unicode_string_constant;'...
array(1) {
  [0]=>
  array(1) {
    ["Beamed_Eighth_Notes_unicode_string_constant"]=>
    string(3) "▒▒"
  }
}
Running query 'SELECT N'růžový' AS pink_in_czech_unicode_string_constant;'...
array(1) {
  [0]=>
  array(1) {
    ["pink_in_czech_unicode_string_constant"]=>
    string(9) "růžo"
  }
}

But I expected this output instead:

Running query 'SELECT CAST(0x72006f017e016f007600fd00 AS nvarchar(10)) AS pink_in_czech_binary_encoded_utf16;'...
array(1) {
  [0]=>
  array(1) {
    ["pink_in_czech_binary_encoded_utf16"]=>
    string(9) "růžový"
  }
}
Running query 'SELECT CAST(0x6b26 AS nvarchar(3)) AS Beamed_Eighth_Notes_binary_encoded_utf16;'...
array(1) {
  [0]=>
  array(1) {
    ["Beamed_Eighth_Notes_binary_encoded_utf16"]=>
    string(3) "♫"
  }
}
Running query 'SELECT NCHAR(0x266b) AS Beamed_Eighth_Notes_nchar;'...
array(1) {
  [0]=>
  array(1) {
    ["Beamed_Eighth_Notes_nchar"]=>
    string(3) "♫"
  }
}
Running query 'SELECT N'♫' AS Beamed_Eighth_Notes_unicode_string_constant;'...
array(1) {
  [0]=>
  array(1) {
    ["Beamed_Eighth_Notes_unicode_string_constant"]=>
    string(3) "♫"
  }
}
Running query 'SELECT N'růžový' AS pink_in_czech_unicode_string_constant;'...
array(1) {
  [0]=>
  array(1) {
    ["pink_in_czech_unicode_string_constant"]=>
    string(9) "růžový"
  }
}
PHP Version

PHP 8.1.7

Operating System

Debian GNU/Linux testing/bookworm/unstable

贡献指南

打开贡献指南

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

调研方向

首先,使用提供的 PHP 脚本、PDO::query() 和 fetchAll(),通过 PDO_ODBC、FreeTDS 1.3.6 和 SQL Server 2016 重现该问题。将 NCHAR 和带 N 前缀的字符串常量返回的值与预期的 Unicode 字符串进行比较;当列出的所有查询都返回未损坏的预期字符时,即表示完成。

由索引模型根据 Issue 内容生成。

评估

技术栈
php, sql
领域
databases
Issue 类型
缺陷
难度
4/5
预计耗时
3-5 天
活跃度
停滞
描述清晰度
基本清楚
新手友好度
35/100

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。