PHPの提供するデータベースアクセスライブラリPDOの挙動について調べていて、動的プレースホルダ(Prepared Statementのエミュレーション)の場合については以下の記事にまとめました。
[PHP 7.2以降におけるPDO::PARAM_INTの仕様変更]
(https://blog.tokumaru.org/2020/03/php-72-pdo-param-int.html)
では静的プレースホルダ(Prepared Statement)の場合はどうかというと、中々にカオスな状況になっておりまして、まだまとめられていませんが、特徴的なトピックスについてこちらに書いてみます。
PoCを以下に示します。
<?php
$db = new PDO("mysql:host=HOST;dbname=DBNAME;charset=utf8", USER, PASSWORD);
$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); // 静的プレースホルダ
$ps = $db->prepare("SELECT :num");
$ps->bindValue(':num', 2147483648, PDO::PARAM_INT);
$ps->execute();
$row = $ps->fetch(PDO::FETCH_NUM);
echo "result = ${row[0]}\n";
単にプレースホルダに2147483648をバインドして、それをSELECTして表示しているだけです。
これをCentOS6, CentOS7, CentOS8のそれぞれ(32ビットが版が存在するCentOS6は、32ビットと64ビットの両方)で動かしてみた結果は以下のとおりです。なお、PHPはCentOSの標準パッケージのものです。
CentOS6 (32ビット)、CentOS8: 2147483648
CentOS6 (64ビット)、CentOS7: -2147483648
なぜそうなるかは調べてあるのですが、まずはクイズとして出題してみます。分かる人、いますか?