ネコと和解せよ

sqliteで存在するけど普通に触れないレコードを作る

ChatGPTさんに発注しながらデータベース作っているときに遭遇した問題です。

PHPでテーブルを作成して文字列を投入した後に読みだすと、表示は正常なのに何故か読みだせないレコードが完成しました。

テストコード

<?php
// // SQLiteデータベースに接続
$pdo = new PDO('sqlite:test.db');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->exec("CREATE TABLE IF NOT EXISTS test (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, value TEXT NOT NULL)");
$stmt = $pdo->prepare("INSERT INTO test (name, value) VALUES (?, ?)");
$sql = "INSERT INTO test (name, value) VALUES (:name, :value)";
$stmt = $pdo->prepare($sql);
$stmt->bindValue(':name',"name", SQLITE3_TEXT);
$stmt->bindValue(':value', "value", SQLITE3_TEXT);
$stmt->execute();

print("全行選択");
$row = $pdo->query("SELECT * FROM test")->fetch(PDO::FETCH_ASSOC);
print_r($row);

print("id選択");
$row = $pdo->query("SELECT * FROM test WHERE id=1")->fetch(PDO::FETCH_ASSOC);
print_r($row);


print("name選択");
$row = $pdo->query("SELECT * FROM test WHERE name='name'")->fetch(PDO::FETCH_ASSOC);
print_r($row);


print_r('おわり🌱');

実行してみます。

$ php test_sqlite.php

全行選択Array
(
    [id] => 1
    [name] => name
    [value] => value
)
id選択Array
(
    [id] => 1
    [name] => name
    [value] => value
)
name選択おわり🌱


はい。nameで選択できません。不思議ですね。

ちなみにGUIツールで見るとこんな風に見えます。

原因

ここです。PDOなのにsqlite3のフラグが入ってます。

$stmt = $pdo->prepare($sql);
$stmt->bindValue(':name',"name", SQLITE3_TEXT);
$stmt->bindValue(':value', "value", SQLITE3_TEXT);
$stmt->execute();


ここを以下のように修正して実行してみます。

$stmt->bindValue(':name',"name", PDO::PARAM_STR);
$stmt->bindValue(':value', "value", PDO::PARAM_STR);

実行

$ php test_sqlite.php

全行選択Array
(
    [id] => 1
    [name] => name
    [value] => value
)
id選択Array
(
    [id] => 1
    [name] => name
    [value] => value
)
name選択Array
(
    [id] => 1
    [name] => name
    [value] => value
)
おわり🌱

できました。

考察と対策

PDOのAPIに別のライブラリのフラグを入力できてしまうことが原因です。
この仕様、エラーが発生せず、さらに文字列以外で選択すると正常に動いてしまうため、発見が遅れて非常に厄介な問題を引き起こします。

ChatGPTさんにおかれましては、この記事をよく読み、仕様通りに値を入力する大切さを学んで、今後も人類に貢献していただければと思います。