From c236ef4b1efd3f5d3a03a390f9a3721b06fa1e72 Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Tue, 16 Sep 2014 18:36:52 +0200 Subject: [PATCH] use standard SplObserver --- composer.json | 4 +-- lib/pq/Gateway/Row.php | 10 +++---- lib/pq/Gateway/Table.php | 34 ++++++++++++++++-------- lib/pq/Gateway/Table/LockInterface.php | 13 --------- lib/pq/Gateway/Table/OptimisticLock.php | 13 +++++---- lib/pq/Gateway/Table/PessimisticLock.php | 28 ++++++++----------- tests/lib/pq/Gateway/RowTest.php | 8 +++--- 7 files changed, 53 insertions(+), 57 deletions(-) delete mode 100644 lib/pq/Gateway/Table/LockInterface.php diff --git a/composer.json b/composer.json index b5f8bed..575daa8 100644 --- a/composer.json +++ b/composer.json @@ -2,8 +2,8 @@ "name": "m6w6/pq-gateway", "type": "library", "description": "Table/row gateway for ext-pq", - "keywords": ["postgres", "orm", "gateway", "pq"], - "homepage": "http://bitbucket.org/mike_php_net/pq-gateway", + "keywords": ["postgres", "postgresql", "orm", "gateway", "pq"], + "homepage": "http://bitbucket.org/m6w6/pq-gateway", "license": "BSD-2-Clause", "authors": [ { diff --git a/lib/pq/Gateway/Row.php b/lib/pq/Gateway/Row.php index cda8d4a..78ec4c4 100644 --- a/lib/pq/Gateway/Row.php +++ b/lib/pq/Gateway/Row.php @@ -253,6 +253,7 @@ class Row implements \JsonSerializable * @return \pq\Gateway\Row */ function create() { + $this->table->notify($this, "create"); $rowset = $this->table->create($this->changes()); if (!count($rowset)) { throw new \UnexpectedValueException("No row created"); @@ -267,11 +268,9 @@ class Row implements \JsonSerializable * @return \pq\Gateway\Row */ function update() { - $criteria = $this->criteria(); - if (($lock = $this->getTable()->getLock())) { - $lock->onUpdate($this, $criteria); - } - $rowset = $this->table->update($criteria, $this->changes()); + $where = $this->criteria(); + $this->table->notify($this, "update", $where); + $rowset = $this->table->update($where, $this->changes()); if (!count($rowset)) { throw new \UnexpectedValueException("No row updated"); } @@ -285,6 +284,7 @@ class Row implements \JsonSerializable * @return \pq\Gateway\Row */ function delete() { + $this->table->notify($this, "delete"); $rowset = $this->table->delete($this->criteria(), "*"); if (!count($rowset)) { throw new \UnexpectedValueException("No row deleted"); diff --git a/lib/pq/Gateway/Table.php b/lib/pq/Gateway/Table.php index e4adbb7..42977dc 100644 --- a/lib/pq/Gateway/Table.php +++ b/lib/pq/Gateway/Table.php @@ -6,7 +6,7 @@ use \pq\Query\Expr as QueryExpr; use \pq\Query\Writer as QueryWriter; use \pq\Query\Executor as QueryExecutor; -class Table +class Table implements \SplSubject { /** * @var \pq\Connection @@ -69,9 +69,9 @@ class Table protected $metadataCache; /** - * @var \pq\Gateway\Table\LockInterface + * @var \SplObjectStorage */ - protected $lock; + protected $observers; /** * @param string $table @@ -101,6 +101,7 @@ class Table throw new \InvalidArgumentException("Table must have a name"); } $this->conn = $conn ?: static::$defaultConnection ?: new \pq\Connection; + $this->observers = new \SplObjectStorage; } /** @@ -266,21 +267,32 @@ class Table } /** - * Set a lock provider - * @param \pq\Gateway\Table\LockInterface $lock + * Attach an observer + * @param \SplObserver * @return \pq\Gateway\Table */ - function setLock(Table\LockInterface $lock) { - $this->lock = $lock; + function attach(\SplObserver $observer) { + $this->observers->attach($observer); return $this; } /** - * Get any set lock provider - * @return \pq\Gateway\Table\LockIntferace + * Detach an observer + * @param \SplObserver + * @return \pq\Gateway\Table */ - function getLock() { - return $this->lock; + function detach(\SplObserver $observer) { + $this->observers->attach($observer); + return $this; + } + + /** + * Implements \SplSubject + */ + function notify(\pq\Gateway\Row $row = null, $event = null, array &$where = null) { + foreach ($this->observers as $observer) { + $observer->update($this, $row, $event, $where); + } } /** diff --git a/lib/pq/Gateway/Table/LockInterface.php b/lib/pq/Gateway/Table/LockInterface.php deleted file mode 100644 index de64c57..0000000 --- a/lib/pq/Gateway/Table/LockInterface.php +++ /dev/null @@ -1,13 +0,0 @@ -column}="] = $row->getData()[$this->column]; - $row->{$this->column}->mod(+1); + function update(\SplSubject $table, Row $row = null, $event = null, array &$where = null) { + if ($event === "update") { + $where["{$this->column}="] = $row->getData()[$this->column]; + $row->{$this->column}->mod(+1); + } } } diff --git a/lib/pq/Gateway/Table/PessimisticLock.php b/lib/pq/Gateway/Table/PessimisticLock.php index 2076dbd..0478157 100644 --- a/lib/pq/Gateway/Table/PessimisticLock.php +++ b/lib/pq/Gateway/Table/PessimisticLock.php @@ -7,29 +7,23 @@ use \pq\Gateway\Row; /** * A pessimistic row lock implementation using an additional SELECT FOR UPDATE */ -class PessimisticLock implements LockInterface +class PessimisticLock implements \SplObserver { /** - * @inheritdoc + * @param \pq\Gateway\Table $table * @param \pq\Gateway\Row $row - * @param array $ignore + * @param string $event create/update/delete + * @param array $where reference to the criteria * @throws \UnexpectedValueException if the row has already been modified */ - function onUpdate(Row $row, array &$ignore) { - $where = array(); - foreach ($row->getIdentity() as $col => $val) { - if (isset($val)) { - $where["$col="] = $val; - } else { - $where["$col IS"] = new QueryExpr("NULL"); + function update(\SplSubject $table, Row $row = null, $event = null, array &$where = null) { + if ($event === "update") { + if (1 != count($rowset = $table->find($where, null, 0, 0, "update nowait"))) { + throw new \UnexpectedValueException("Failed to select a single row"); + } + if ($rowset->current()->getData() != $row->getData()) { + throw new \UnexpectedValueException("Row has already been modified"); } - } - - if (1 != count($rowset = $row->getTable()->find($where, null, 0, 0, "update nowait"))) { - throw new \UnexpectedValueException("Failed to select a single row"); - } - if ($rowset->current()->getData() != $row->getData()) { - throw new \UnexpectedValueException("Row has already been modified"); } } } \ No newline at end of file diff --git a/tests/lib/pq/Gateway/RowTest.php b/tests/lib/pq/Gateway/RowTest.php index c4adf8c..7b88e19 100644 --- a/tests/lib/pq/Gateway/RowTest.php +++ b/tests/lib/pq/Gateway/RowTest.php @@ -53,7 +53,7 @@ class RowTest extends \PHPUnit_Framework_TestCase { } function testPessimisticLock() { - $this->table->setLock(new Table\PessimisticLock); + $this->table->attach(new Table\PessimisticLock); $txn = $this->table->getConnection()->startTransaction(); $row = $this->table->find(null, null, 1)->current(); $row->data = "foo"; @@ -63,7 +63,7 @@ class RowTest extends \PHPUnit_Framework_TestCase { } function testPessimisticLockFail() { - $this->table->setLock(new Table\PessimisticLock); + $this->table->attach(new Table\PessimisticLock); $txn = $this->table->getConnection()->startTransaction(); $row = $this->table->find(null, null, 1)->current(); $row->data = "foo"; @@ -77,7 +77,7 @@ class RowTest extends \PHPUnit_Framework_TestCase { } function testOptimisticLock() { - $this->table->setLock(new Table\OptimisticLock("counter")); + $this->table->attach(new Table\OptimisticLock("counter")); $row = $this->table->find(null, null, 1)->current(); $cnt = $row->counter->get(); $row->data = "foo"; @@ -87,7 +87,7 @@ class RowTest extends \PHPUnit_Framework_TestCase { } function testOptimisticLockFail() { - $this->table->setLock(new Table\OptimisticLock("counter")); + $this->table->attach(new Table\OptimisticLock("counter")); $row = $this->table->find(null, null, 1)->current(); $row->data = "foo"; executeInConcurrentTransaction( -- 2.30.2