From 009297fb1a7dc495cb963bf42e5ee36a1b5263ac Mon Sep 17 00:00:00 2001 From: Dave MacFarlane Date: Thu, 5 Dec 2024 11:04:29 -0500 Subject: [PATCH] [Core] Fix loading of pselectRow queries (#9501) Queries which use pselectRow that return data can fail to load with an error about not being able to execute queries with pending results. pselectRow does a count on the database connection, which executes the query. When getFirstRow is called after, the query has already been executed but the results have not been fetched when getIterator() attempts to re-execute the query. This keeps track of the execution state so that it is only executed the first time. Fixes #9500 --- src/Database/Query.php | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/Database/Query.php b/src/Database/Query.php index 64c8baabe28..20a038e05f1 100644 --- a/src/Database/Query.php +++ b/src/Database/Query.php @@ -5,6 +5,7 @@ class Query implements \Countable, \IteratorAggregate { protected \PDOStatement $stmt; + private bool $executed; public function __construct( protected \PDO $DB, @@ -12,14 +13,18 @@ public function __construct( protected array $params = [], protected bool $buffered = true ) { - $this->stmt = $DB->prepare($query); + $this->stmt = $DB->prepare($query); + $this->executed = false; } public function count(): int { // PDOStatement->rowCount only works for buffered connections if ($this->buffered == true) { - $this->stmt->execute($this->params); + if ($this->executed === false) { + $this->stmt->execute($this->params); + $this->executed = true; + } return $this->stmt->rowCount(); } else { $stmt = $this->DB->prepare("SELECT COUNT('x') FROM ({$this->query})"); @@ -32,14 +37,15 @@ public function getFirstRow() : array { $rows = $this->getIterator(); assert($rows instanceof \PDOStatement); - $val = $rows->fetch(); - $rows->closeCursor(); - return $val; + return $rows->fetch(); } public function getIterator() : \Traversable { - $this->stmt->execute($this->params); + if ($this->executed === false) { + $this->stmt->execute($this->params); + $this->executed = true; + } return $this->stmt; } }