Skip to content

Commit

Permalink
FIX Allow repeated iterations of predicated query result (#10857)
Browse files Browse the repository at this point in the history
  • Loading branch information
GuySartorelli authored Jul 5, 2023
1 parent bb5378e commit 612f7e7
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 0 deletions.
6 changes: 6 additions & 0 deletions src/ORM/Connect/MySQLStatement.php
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,12 @@ public function getIterator(): Traversable
}
yield $row;
}

// Check for the method first since $this->statement isn't strongly typed
if (method_exists($this->statement, 'data_seek')) {
// Reset so the query can be iterated over again
$this->statement->data_seek(0);
}
}

public function numRecords()
Expand Down
68 changes: 68 additions & 0 deletions tests/php/ORM/DatabaseTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,33 @@ public function testRepeatedIterationUsingAbstraction()
$this->assertEquals($inputData, $select->execute()->map());
}

/**
* Test that repeated abstracted iteration of a query result with predicates returns all records.
*/
public function testRepeatedIterationWithPredicates()
{
$inputData = ['one', 'two', 'three', 'four'];

foreach ($inputData as $i => $text) {
$x = new MyObject();
$x->MyField = $text;
$x->MyInt = $i;
$x->write();
}

// Note that by including a WHERE statement with predicates
// with MySQL the result is in a MySQLStatement object rather than a MySQLQuery object.
$select = SQLSelect::create(
['"MyInt"', '"MyField"'],
'"DatabaseTest_MyObject"',
['MyInt IN (?,?,?,?,?)' => [0,1,2,3,4]],
['"MyInt"']
)->execute();

$this->assertEquals($inputData, $select->map());
$this->assertEquals($inputData, $select->map());
}

/**
* Test that stopping iteration part-way through produces predictable results
* on a subsequent iteration.
Expand Down Expand Up @@ -345,4 +372,45 @@ public function testRepeatedPartialIteration()
$i++;
}
}

/**
* Test that stopping iteration part-way through produces predictable results even when we're using predicates
* on a subsequent iteration.
* This test is here to ensure consistency between implementations (e.g. mysql vs postgres, etc)
*/
public function testRepeatedPartialIterationWithPredicates()
{
$inputData = ['one', 'two', 'three', 'four'];

foreach ($inputData as $i => $text) {
$x = new MyObject();
$x->MyField = $text;
$x->MyInt = $i;
$x->write();
}

// Note that by including a WHERE statement with predicates
// with MySQL the result is in a MySQLStatement object rather than a MySQLQuery object.
$query = SQLSelect::create(
['"MyInt"', '"MyField"'],
'"DatabaseTest_MyObject"',
['MyInt IN (?,?,?,?,?)' => [0,1,2,3,4]],
['"MyInt"']
)->execute();

$i = 0;
foreach ($query as $record) {
$this->assertEquals($inputData[$i], $record['MyField']);
$i++;
if ($i > 1) {
break;
}
}

// Continue from where we left off, since we're using a Generator
foreach ($query as $record) {
$this->assertEquals($inputData[$i], $record['MyField']);
$i++;
}
}
}

0 comments on commit 612f7e7

Please sign in to comment.