From 27fb7f29a849270b329533b8f7944beb163b1c06 Mon Sep 17 00:00:00 2001 From: Mitch Date: Thu, 29 May 2014 15:49:05 +1000 Subject: [PATCH 1/4] Restrict null primary keys on update/delete, resolves #203 --- idiorm.php | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/idiorm.php b/idiorm.php index 73072e6f..2794262c 100644 --- a/idiorm.php +++ b/idiorm.php @@ -1869,8 +1869,22 @@ protected function _get_id_column_name() { /** * Get the primary key ID of this object. */ - public function id() { - return $this->get($this->_get_id_column_name()); + public function id($disallow_null = false) { + $id = $this->get($this->_get_id_column_name()); + + if ($disallow_null) { + if (is_array($id)) { + foreach ($id as $id_part) { + if ($id_part === null) { + throw new Exception('Primary key ID contains null value(s)'); + } + } + } else if ($id === null) { + throw new Exception('Primary key ID missing from row or is null'); + } + } + + return $id; } /** @@ -1951,7 +1965,7 @@ public function save() { return true; } $query = $this->_build_update(); - $id = $this->id(); + $id = $this->id(true); if (is_array($id)) { $values = array_merge($values, array_values($id)); } else { @@ -2058,7 +2072,7 @@ public function delete() { $this->_quote_identifier($this->_table_name) ); $this->_add_id_column_conditions($query); - return self::_execute(join(" ", $query), is_array($this->id()) ? array_values($this->id()) : array($this->id()), $this->_connection_name); + return self::_execute(join(" ", $query), is_array($this->id(true)) ? array_values($this->id(true)) : array($this->id(true)), $this->_connection_name); } /** From a8c71384c2c767a4241f1ed3f14965218bb7bc2d Mon Sep 17 00:00:00 2001 From: Mitch Date: Sat, 7 Jun 2014 15:10:41 +1000 Subject: [PATCH 2/4] MockPDOStatement::execute() Strict Standards --- test/bootstrap.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/bootstrap.php b/test/bootstrap.php index 9a40762b..32f02881 100644 --- a/test/bootstrap.php +++ b/test/bootstrap.php @@ -21,7 +21,7 @@ public function __construct($statement) { /** * Check that the array */ - public function execute($params) { + public function execute($params = null) { $count = 0; $m = array(); if (preg_match_all('/"[^"\\\\]*(?:\\?)[^"\\\\]*"|\'[^\'\\\\]*(?:\\?)[^\'\\\\]*\'|(\\?)/', $this->statement, $m, PREG_SET_ORDER)) { From 2126f362562bb9e9a88dae27951d6da3dbc42103 Mon Sep 17 00:00:00 2001 From: Mitch Date: Sat, 7 Jun 2014 15:12:34 +1000 Subject: [PATCH 3/4] Tests for 27fb7f29a849270b329533b8f7944beb163b1c06 --- test/ORMTest.php | 68 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/test/ORMTest.php b/test/ORMTest.php index e0e4900d..3df3a738 100644 --- a/test/ORMTest.php +++ b/test/ORMTest.php @@ -99,4 +99,72 @@ public function testInvalidResultsSetFunctionCallShouldCreateException() { $resultSet = ORM::for_table('test')->find_result_set(); $resultSet->invalidFunctionCall(); } + + /** + * @expectedException Exception + * @expectedExceptionMessage Primary key ID missing from row or is null + * These next two tests are needed because if you have select()ed some fields, + * but not the primary key, then the primary key is not available for the + * update/delete query - see issue #203. + * We need to change the primary key here to something other than `id` + * becuase MockPDOStatement->fetch() always returns an id. + */ + public function testUpdateNullPrimaryKey() { + $widget = ORM::for_table('widget') + ->use_id_column('primary') + ->select('foo') + ->where('primary', 1) + ->find_one() + ; + + $widget->foo = 'bar'; + $widget->save(); + } + + /** + * @expectedException Exception + * @expectedExceptionMessage Primary key ID missing from row or is null + */ + public function testDeleteNullPrimaryKey() { + $widget = ORM::for_table('widget') + ->use_id_column('primary') + ->select('foo') + ->where('primary', 1) + ->find_one() + ; + + $widget->delete(); + } + + /** + * @expectedException Exception + * @expectedExceptionMessage Primary key ID missing from row or is null + */ + public function testNullPrimaryKey() { + $widget = ORM::for_table('widget') + ->use_id_column('primary') + ->select('foo') + ->where('primary', 1) + ->find_one() + ; + + $widget->id(true); + } + + /** + * @expectedException Exception + * @expectedExceptionMessage Primary key ID contains null value(s) + */ + public function testNullPrimaryKeyPart() { + $widget = ORM::for_table('widget') + ->use_id_column(array('id', 'primary')) + ->select('foo') + ->where('id', 1) + ->where('primary', 1) + ->find_one() + ; + + $widget->id(true); + + } } \ No newline at end of file From 90469df2980ff338e91fb23a514d24a135e3147b Mon Sep 17 00:00:00 2001 From: Mitch Date: Thu, 19 Jun 2014 22:25:08 +1000 Subject: [PATCH 4/4] Update tests to not expect generic exception, as PHPUnit < 3.7 (PHP 5.2) can't handle it --- test/ORMTest.php | 101 ++++++++++++++++++++++++++--------------------- 1 file changed, 55 insertions(+), 46 deletions(-) diff --git a/test/ORMTest.php b/test/ORMTest.php index 3df3a738..f244f120 100644 --- a/test/ORMTest.php +++ b/test/ORMTest.php @@ -101,8 +101,6 @@ public function testInvalidResultsSetFunctionCallShouldCreateException() { } /** - * @expectedException Exception - * @expectedExceptionMessage Primary key ID missing from row or is null * These next two tests are needed because if you have select()ed some fields, * but not the primary key, then the primary key is not available for the * update/delete query - see issue #203. @@ -110,61 +108,72 @@ public function testInvalidResultsSetFunctionCallShouldCreateException() { * becuase MockPDOStatement->fetch() always returns an id. */ public function testUpdateNullPrimaryKey() { - $widget = ORM::for_table('widget') - ->use_id_column('primary') - ->select('foo') - ->where('primary', 1) - ->find_one() - ; + try { + $widget = ORM::for_table('widget') + ->use_id_column('primary') + ->select('foo') + ->where('primary', 1) + ->find_one() + ; - $widget->foo = 'bar'; - $widget->save(); + $widget->foo = 'bar'; + $widget->save(); + + throw new Exception('Test did not throw expected exception'); + } catch (Exception $e) { + $this->assertEquals($e->getMessage(), 'Primary key ID missing from row or is null'); + } } - /** - * @expectedException Exception - * @expectedExceptionMessage Primary key ID missing from row or is null - */ public function testDeleteNullPrimaryKey() { - $widget = ORM::for_table('widget') - ->use_id_column('primary') - ->select('foo') - ->where('primary', 1) - ->find_one() - ; + try { + $widget = ORM::for_table('widget') + ->use_id_column('primary') + ->select('foo') + ->where('primary', 1) + ->find_one() + ; - $widget->delete(); + $widget->delete(); + + throw new Exception('Test did not throw expected exception'); + } catch (Exception $e) { + $this->assertEquals($e->getMessage(), 'Primary key ID missing from row or is null'); + } } - /** - * @expectedException Exception - * @expectedExceptionMessage Primary key ID missing from row or is null - */ public function testNullPrimaryKey() { - $widget = ORM::for_table('widget') - ->use_id_column('primary') - ->select('foo') - ->where('primary', 1) - ->find_one() - ; + try { + $widget = ORM::for_table('widget') + ->use_id_column('primary') + ->select('foo') + ->where('primary', 1) + ->find_one() + ; - $widget->id(true); + $widget->id(true); + + throw new Exception('Test did not throw expected exception'); + } catch (Exception $e) { + $this->assertEquals($e->getMessage(), 'Primary key ID missing from row or is null'); + } } - /** - * @expectedException Exception - * @expectedExceptionMessage Primary key ID contains null value(s) - */ public function testNullPrimaryKeyPart() { - $widget = ORM::for_table('widget') - ->use_id_column(array('id', 'primary')) - ->select('foo') - ->where('id', 1) - ->where('primary', 1) - ->find_one() - ; - - $widget->id(true); - + try { + $widget = ORM::for_table('widget') + ->use_id_column(array('id', 'primary')) + ->select('foo') + ->where('id', 1) + ->where('primary', 1) + ->find_one() + ; + + $widget->id(true); + + throw new Exception('Test did not throw expected exception'); + } catch (Exception $e) { + $this->assertEquals($e->getMessage(), 'Primary key ID contains null value(s)'); + } } } \ No newline at end of file