Browse Source

Merge pull request #6058 from cakephp/3.0-fix-statement

Fixed issue where query would be executed twice if used inside a collection
Mark Story 11 years ago
parent
commit
64792baa47

+ 11 - 2
src/Database/Statement/StatementDecorator.php

@@ -47,6 +47,13 @@ class StatementDecorator implements StatementInterface, \Countable, \IteratorAgg
     protected $_driver;
 
     /**
+     * Whether or not this statement has already been executed
+     *
+     * @var bool
+     */
+    protected $_hasExecuted = false;
+
+    /**
      * Constructor
      *
      * @param \Cake\Database\StatementInterface|null $statement Statement implementation such as PDOStatement
@@ -158,6 +165,7 @@ class StatementDecorator implements StatementInterface, \Countable, \IteratorAgg
      */
     public function execute($params = null)
     {
+        $this->_hasExecuted = true;
         return $this->_statement->execute($params);
     }
 
@@ -228,7 +236,6 @@ class StatementDecorator implements StatementInterface, \Countable, \IteratorAgg
      *
      * ```
      * $statement = $connection->prepare('SELECT id, title from articles');
-     * $statement->execute();
      * foreach ($statement as $row) {
      *   //do stuff
      * }
@@ -238,7 +245,9 @@ class StatementDecorator implements StatementInterface, \Countable, \IteratorAgg
      */
     public function getIterator()
     {
-        $this->execute();
+        if (!$this->_hasExecuted) {
+            $this->execute();
+        }
         return $this->_statement;
     }
 

+ 19 - 1
tests/TestCase/Database/Statement/StatementDecoratorTest.php

@@ -44,7 +44,8 @@ class StatemetDecoratorTest extends TestCase
     }
 
     /**
-     * Tests that calling lastInsertId will get the
+     * Tests that calling lastInsertId will get the last insert id by
+     * column name
      *
      * @return void
      */
@@ -62,4 +63,21 @@ class StatemetDecoratorTest extends TestCase
         $driver->expects($this->never())->method('lastInsertId');
         $this->assertEquals(2, $statement->lastInsertId('users', 'id'));
     }
+
+    /**
+     * Tests that the statement will not be executed twice if the iterator
+     * is requested more than once
+     *
+     * @return void
+     */
+    public function testNoDoubleExecution()
+    {
+        $inner = $this->getMock('\PDOStatement');
+        $driver = $this->getMock('\Cake\Database\Driver');
+        $statement = new StatementDecorator($inner, $driver);
+
+        $inner->expects($this->once())->method('execute');
+        $this->assertSame($inner, $statement->getIterator());
+        $this->assertSame($inner, $statement->getIterator());
+    }
 }