PDO SQlite扩展/ PDOStatement错误?

时间:2016-05-25 08:24:17

标签: php sqlite pdo

我们目前在内存数据库中遇到一个使用PDO和SQLite的奇怪错误。

这是重现问题的代码的和平。

执行以下PHP代码

<?php 

// Gets a PDO reference with in memory SQLite (i.e using the 'sqlite::memory:' dsn)
$pdo = new \PDO('sqlite::memory:', 'sa', '');

$pdo->exec(
    'CREATE TABLE IF NOT EXISTS scheduled_task' . 
    '(' .
        'id                                          INTEGER         NOT NULL,' .
        'date_and_time                               INTEGER         NOT NULL,' . 
        'task_class                                  VARCHAR(256)    NOT NULL,' .
        'task_parameters                             VARCHAR(1024)   NOT NULL' .
    ')'
);

// Just a statement to count rows in our table
$pdoStatementCount = $pdo->prepare('select count(*) from scheduled_task');

// At first ensure our table is empty
$pdoStatementCount->execute();
var_dump('At beginning table has size \'' . intval($pdoStatementCount->fetchColumn()) . '\'.');

// Insert 2 rows inside our table
$pdoStatementInsert = $pdo->prepare(
    'insert into scheduled_task(id, task_class, date_and_time, task_parameters) values(?,?,?,?)'
);
$pdoStatementInsert->execute([1, 'tk1', '2015-01-01', '{}']);
$pdoStatementInsert->execute([2, 'tk2', '2015-01-02', '{}']);

// Ensure the 2 rows were inserted
$pdoStatementCount->execute();
var_dump('Then table has size \'' . intval($pdoStatementCount->fetchColumn()) . '\'.');

// Now create a statement to select only the first row
$pdoStatementSelect1 = $pdo->query('select * from scheduled_task where date_and_time < \'2015-01-02\'');

// Here it seems their is a bug with the Iterator associated to the PDO Statement
foreach($pdoStatementSelect1 as $row) {
    var_dump($row['id']);

    // Inserts a new row inside our table
    $pdoStatementInsert = $pdo->prepare(
        'insert into scheduled_task(id, task_class, date_and_time, task_parameters) values(?,?,?,?)'
    );
    if($pdoStatementInsert->execute([3, 'tk3', '2015-01-01', '{}']) === false)  {
        var_dump('Fail inserting row in loop !');
        var_dump($pdoStatementInsert->errorCode());
        var_dump($pdoStatementInsert->errorInfo());
    }

    // Deletes the first row
    $pdo->query('delete from scheduled_task where id = ' . $row['id']);
}

// This fails with SQLite, we should have 2 rows inside our table here
$pdoStatementCount->execute();
var_dump('At the end table has size \'' . intval($pdoStatementCount->fetchColumn()) . '\'.');

此测试的输出如下:

string(32) "At beginning table has size '0'."
string(24) "Then table has size '2'."
string(1) "1"
string(1) "3"
string(30) "At the end table has size '1'."

结论,PDO SQLite中的错误?

请注意,我们的foreach循环执行2次而不是1次。因此我们循环中使用的PDOStatement对象似乎已更新(不知道如何),因为我们在循环中插入了一个新行。

如果我们将PDO实例更改为使用MySQL,那么它可以工作,所以我认为这个bug只与SQLite有关。

虽然如果我将循环内部的插入指令更改为此(即日期与我们的选择不匹配),那么它可以正常工作。

$pdoStatementInsert->execute([3, 'tk3', '2015-01-02', '{}'])

因此它与SQLite PDOStatement一样透明地执行新的选择查询......

你知道为什么我们会遇到这种行为吗?你认为这是正常的吗?如果不是,我们必须在https://bugs.php.ne报告?

最终答案 - 这不是一个错误https://bugs.php.net/bug.php?id=72267&edit=2 谢谢你的帮助!

感谢。

0 个答案:

没有答案