From 10d97d8e51971322d59b590229b5f107b0b0b4d9 Mon Sep 17 00:00:00 2001 From: mark_story Date: Mon, 17 Jun 2013 23:24:17 -0400 Subject: [PATCH] Add basic table level updates. Add basic table level updates that can update multiple records. Don't implement _matchRecords or other join workarounds as they often lead to concurrency issues. We can revisit that functionality later on if necessary. --- lib/Cake/ORM/Query.php | 10 ++++--- lib/Cake/ORM/Table.php | 28 ++++++++++++++--- lib/Cake/Test/TestCase/ORM/TableTest.php | 38 ++++++++++++++++++++++++ 3 files changed, 68 insertions(+), 8 deletions(-) diff --git a/lib/Cake/ORM/Query.php b/lib/Cake/ORM/Query.php index a303295569a..2489b50d03e 100644 --- a/lib/Cake/ORM/Query.php +++ b/lib/Cake/ORM/Query.php @@ -412,11 +412,13 @@ protected function _transformQuery() { if (!$this->_dirty) { return parent::_transformQuery(); } - if (empty($this->_parts['from'])) { - $this->from([$this->_table->alias() => $this->_table->table()]); + if ($this->_type === 'select') { + if (empty($this->_parts['from'])) { + $this->from([$this->_table->alias() => $this->_table->table()]); + } + $this->_addDefaultFields(); + $this->_addContainments(); } - $this->_addDefaultFields(); - $this->_addContainments(); return parent::_transformQuery(); } diff --git a/lib/Cake/ORM/Table.php b/lib/Cake/ORM/Table.php index 2ed8026ebba..26cecbb8d1c 100644 --- a/lib/Cake/ORM/Table.php +++ b/lib/Cake/ORM/Table.php @@ -459,7 +459,9 @@ public function belongsToMany($associated, array $options = []) { * @return \Cake\ORM\Query */ public function find($type, $options = []) { - return $this->{'find' . ucfirst($type)}($this->_buildQuery(), $options); + $query = $this->_buildQuery(); + $query->select(); + return $this->{'find' . ucfirst($type)}($query, $options); } /** @@ -481,9 +483,27 @@ public function findAll(Query $query, array $options = []) { */ protected function _buildQuery() { $query = new Query($this->connection()); - return $query - ->repository($this) - ->select(); + return $query->repository($this); + } + +/** + * Update one or many rows. + * + * Sets the $fields to the provided values based on $conditions. + * This method will *not* trigger beforeSave/afterSave events. If you need those + * first load a collection of records and update them. + * + * @param array $fields A hash of field => new value. + * @param array $conditions An array of conditions, similar to those used with find() + * @return boolean Success + */ + public function update($fields, $conditions) { + $query = $this->_buildQuery(); + $query->update($this->table()) + ->set($fields) + ->where($conditions); + $query->execute(); + return true; } } diff --git a/lib/Cake/Test/TestCase/ORM/TableTest.php b/lib/Cake/Test/TestCase/ORM/TableTest.php index d84affbcb56..3f3b882e539 100644 --- a/lib/Cake/Test/TestCase/ORM/TableTest.php +++ b/lib/Cake/Test/TestCase/ORM/TableTest.php @@ -374,4 +374,42 @@ public function testBelongsToMany() { $this->assertSame('things_tags', $belongsToMany->pivot()->table()); } +/** + * Test basic multi row updates. + * + * @return void + */ + public function testUpdate() { + $table = new Table(['table' => 'users', 'connection' => $this->connection]); + $fields = ['user' => 'mark']; + $result = $table->update($fields, ['id <' => 4]); + $this->assertTrue($result); + + $result = $table->find('all')->select(['user'])->toArray(); + $expected = array_fill(0, 3, $fields); + $expected[] = ['user' => 'garrett']; + $this->assertEquals($expected, $result); + } + +/** + * Test that exceptions from the Query bubble up. + * + * @expectedException Cake\Database\Exception + */ + public function testUpdateFailure() { + $table = $this->getMock( + 'Cake\ORM\Table', + ['_buildQuery'], + ['table' => 'users', 'connection' => $this->connection] + ); + $query = $this->getMock('Cake\ORM\Query', ['execute'], [$this->connection]); + $table->expects($this->once()) + ->method('_buildQuery') + ->will($this->returnValue($query)); + $query->expects($this->once()) + ->method('execute') + ->will($this->throwException(new \Cake\Database\Exception('Not good'))); + $table->update(['user' => 'mark'], []); + } + }