From 88798a98c4099adca3e0a4394317e59ed6720cfd Mon Sep 17 00:00:00 2001 From: Dave MacFarlane Date: Wed, 4 Dec 2024 10:46:06 -0500 Subject: [PATCH] [Core] Fix loading of pselectRow queries 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. --- 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; } }