来自 PHP PDO FreeTDS ODBC 执行的分段错误
Segmentation Fault from PHP PDO FreeTDS ODBC execution
我目前正在将 PHP 项目从使用 PHP 的 mssql
库迁移到使用带有 FreeTDS 的 PDO
库。我已经修改了我所有的数据库调用,但是 运行 在 SQL 服务器数据库上执行准备好的语句时遇到了一个非常奇怪的问题。
下面是我遇到问题的代码片段。
public static function gift_cards_exist($start_number, $end_number = null) {
global $sol_donations;
$db = $sol_donations->get_db();
$store_id = get_option('pos-store-id', false);
//$store_id = '01'; // Won't work if value assigned this way
$payment_method = 'Gift';
if (empty($end_number)) {
$end_number = $start_number;
}
$query = '
SELECT * FROM dbo.tblPmtSerialHdr
WHERE SerialId BETWEEN ? AND ?
AND StoreId = ?';
//AND PmtMethodId = ?';
$stmt = $db->prepare($query);
$stmt->bindParam(1, $start_number, \PDO::PARAM_STR | \PDO::PARAM_INPUT_OUTPUT);
$stmt->bindParam(2, $end_number, \PDO::PARAM_STR | \PDO::PARAM_INPUT_OUTPUT);
$stmt->bindParam(3, $store_id, \PDO::PARAM_STR | \PDO::PARAM_INPUT_OUTPUT);
//$stmt->bindParam(4, $payment_method, \PDO::PARAM_STR | \PDO::PARAM_INPUT_OUTPUT);
$result = $stmt->execute();
$result = $stmt->fetchAll(\PDO::FETCH_ASSOC);
$stmt->closeCursor();
/* Nothing printed from this
echo $stmt->errorCode();
echo '<br />';
echo $stmt->errorInfo();
*/
var_dump($result);
exit();
if ($result) {
return true;
}
return false;
}
这里是问题所在。 运行 这种形式的代码(所有注释行都保留注释)导致正确执行查询,尽管对我的程序来说不正确,但结果是预期的。
但是,如果我修改查询以使用第二个 AND
语句并取消注释最后一个 bindParam
语句以与该语句一起使用,脚本将失败导致分段错误。我在 apache 错误日志中得到的实际错误消息是:
[Fri Feb 06 10:43:05.406772 2015] [core:notice] [pid 1415] AH00051: child pid 1541 exit signal Segmentation fault (11), possible coredump in /etc/apache2
我完全不知道为什么为准备好的语句添加这个额外的参数会导致问题。
有关情况的一些额外信息:
FreeTDS安装正确,可以用来连接数据库和查询数据。
我试过同时使用 bindParam
和 bindValue
,两者的结果相同。
我已经尝试 运行使用和不使用按位或 PDO::PARAM_INPUT_OUTPUT
的语句。
最后,我检查以确保记录集中没有 NULL
应该返回,以确保 NULL
值不是原因。
所以,事实证明这是 FreeTDS ODBC 驱动程序中的某种错误。我切换到使用 dblib
驱动程序,我的所有查询都正常工作,没有分段错误。
有一个类似的问题,我通过 PDO 和 DBLIB 进行的查询 运行 返回的是货币类型值。
我必须使用的 DBLIB 版本导致了 apache 中的分段错误,google 导致我遇到这个问题。
只需将货币类型值转换为十进制意味着我可以解决这个问题,同时仍然保持小数精度。
我目前正在将 PHP 项目从使用 PHP 的 mssql
库迁移到使用带有 FreeTDS 的 PDO
库。我已经修改了我所有的数据库调用,但是 运行 在 SQL 服务器数据库上执行准备好的语句时遇到了一个非常奇怪的问题。
下面是我遇到问题的代码片段。
public static function gift_cards_exist($start_number, $end_number = null) {
global $sol_donations;
$db = $sol_donations->get_db();
$store_id = get_option('pos-store-id', false);
//$store_id = '01'; // Won't work if value assigned this way
$payment_method = 'Gift';
if (empty($end_number)) {
$end_number = $start_number;
}
$query = '
SELECT * FROM dbo.tblPmtSerialHdr
WHERE SerialId BETWEEN ? AND ?
AND StoreId = ?';
//AND PmtMethodId = ?';
$stmt = $db->prepare($query);
$stmt->bindParam(1, $start_number, \PDO::PARAM_STR | \PDO::PARAM_INPUT_OUTPUT);
$stmt->bindParam(2, $end_number, \PDO::PARAM_STR | \PDO::PARAM_INPUT_OUTPUT);
$stmt->bindParam(3, $store_id, \PDO::PARAM_STR | \PDO::PARAM_INPUT_OUTPUT);
//$stmt->bindParam(4, $payment_method, \PDO::PARAM_STR | \PDO::PARAM_INPUT_OUTPUT);
$result = $stmt->execute();
$result = $stmt->fetchAll(\PDO::FETCH_ASSOC);
$stmt->closeCursor();
/* Nothing printed from this
echo $stmt->errorCode();
echo '<br />';
echo $stmt->errorInfo();
*/
var_dump($result);
exit();
if ($result) {
return true;
}
return false;
}
这里是问题所在。 运行 这种形式的代码(所有注释行都保留注释)导致正确执行查询,尽管对我的程序来说不正确,但结果是预期的。
但是,如果我修改查询以使用第二个 AND
语句并取消注释最后一个 bindParam
语句以与该语句一起使用,脚本将失败导致分段错误。我在 apache 错误日志中得到的实际错误消息是:
[Fri Feb 06 10:43:05.406772 2015] [core:notice] [pid 1415] AH00051: child pid 1541 exit signal Segmentation fault (11), possible coredump in /etc/apache2
我完全不知道为什么为准备好的语句添加这个额外的参数会导致问题。
有关情况的一些额外信息:
FreeTDS安装正确,可以用来连接数据库和查询数据。
我试过同时使用 bindParam
和 bindValue
,两者的结果相同。
我已经尝试 运行使用和不使用按位或 PDO::PARAM_INPUT_OUTPUT
的语句。
最后,我检查以确保记录集中没有 NULL
应该返回,以确保 NULL
值不是原因。
所以,事实证明这是 FreeTDS ODBC 驱动程序中的某种错误。我切换到使用 dblib
驱动程序,我的所有查询都正常工作,没有分段错误。
有一个类似的问题,我通过 PDO 和 DBLIB 进行的查询 运行 返回的是货币类型值。 我必须使用的 DBLIB 版本导致了 apache 中的分段错误,google 导致我遇到这个问题。
只需将货币类型值转换为十进制意味着我可以解决这个问题,同时仍然保持小数精度。