Edit report at https://bugs.php.net/bug.php?id=81084&edit=1
ID: 81084
Updated by: nikic@php.net
Reported by: corey dot taylor dot fl at gmail dot com
Summary: PDOStatement::queryString is uninitialized
Status: Open
Type: Bug
Package: PDO Core
PHP Version: master-Git-2021-05-26 (Git)
Block user comment: N
Private report: N
New Comment:
Would it be possible to share a snippet (not necessarily runnable on 3v4l) where this occurs when
going through the PDO::prepare() API?
Based on my reading of the code we will always initialize $queryString when PDO creates the
PDOStatement
(https://github.com/php/php-src/blob/ae6c1b0c4ff3468cbc14ffaaaee4e5dc6e480427/ext/pdo/pdo_dbh.c#L457-L460)
and I wasn't able to create an uninitialized $queryString via PDO::prepare() in some simple
experiments. I'm probably missing something really basic here.
Previous Comments:
------------------------------------------------------------------------
[2021-05-27 09:31:22] corey dot taylor dot fl at gmail dot com
We are not manually instantiating the PDOStatement. That was clearly just a simple snippet that
would run in that environment.
The statement is generated by a call to "PDO::prepare()".
The use of $queryString in this instance is determining if certain drivers need a post-execute query
such as SQLite for a row count.
Since we didn't know how to tell if the query string was available, we were using something
like "if ($statement->queryString)". However, that now throws an error since it's
uninitialized.
------------------------------------------------------------------------
[2021-05-27 08:09:43] nikic@php.net
I'm generally open to making this nullable, but would first like to understand how you ended up
in this situation.
The reason why we decided that it's okay to make it non-nullable, is that the only way to end
up with an uninitialized $queryString is if you don't create the PDOStatement through the PDO
API and instead do something like "new PDOStatement". This is an illegal operation and the
resulting object will throw "Error: PDO object is uninitialized" for all method calls. Now
it will also throw an Error when accessing its only property, so that seems sensible and consistent.
(Ideally we'd throw when you do "new PDOStatement" in the first place, but
unfortunately this interferes with the ability to extend PDOStatement, thus we get the current
situation where the object can be created but throws on all operations.)
Is my assumption about how you can end up with an uninitialized $queryString wrong? Is there some
other pathway besides "new PDOStatement()"? If no, why are you creating / interacting with
this kind of object?
------------------------------------------------------------------------
[2021-05-26 23:24:21] corey dot taylor dot fl at gmail dot com
Description:
------------
At some point in php 8.1 development, PDOStatement::queryString became a typed property which throws
an error when uninitialized.
https://www.php.net/manual/en/class.pdostatement.php
We were checking whether $queryString was truthy before using it, but now that access throws an
error.
https://3v4l.org/gHlc0/rfc#git.master
The property is documented as "readonly string" which implies that it is always non-null.
Can we make it nullable or initialize it when PDOStatement is created?
The work around is using "isset($statement->queryString)" directly, but doesn't
seem like it should be uninitialized.
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=81084&edit=1