X-Git-Url: https://git.m6w6.name/?p=m6w6%2Fpq-gateway;a=blobdiff_plain;f=lib%2Fpq%2FGateway%2FTable.php;h=2789963a35f2ee0ac38620820004a84d0979d35e;hp=fe5efbdd454309b2efa15fbdddb21d1f9a1a7a3e;hb=3aa333045c0bb93b83e87e190b4ed49333d106f0;hpb=580991717f5e8bb237403757e2111a8d04aca616 diff --git a/lib/pq/Gateway/Table.php b/lib/pq/Gateway/Table.php index fe5efbd..2789963 100644 --- a/lib/pq/Gateway/Table.php +++ b/lib/pq/Gateway/Table.php @@ -2,10 +2,11 @@ namespace pq\Gateway; +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 @@ -52,6 +53,11 @@ class Table */ protected $identity; + /** + * @var \pq\Gateway\Table\Attributes + */ + protected $attributes; + /** * @var \pq\Gateway\Table\Relations */ @@ -63,9 +69,9 @@ class Table protected $metadataCache; /** - * @var \pq\Gateway\Table\LockInterface + * @var \SplObjectStorage */ - protected $lock; + protected $observers; /** * @param string $table @@ -88,9 +94,14 @@ class Table * @param \pq\Connection $conn * @param array $dependents */ - function __construct($name, \pq\Connection $conn = null) { - $this->name = $name; + function __construct($name = null, \pq\Connection $conn = null) { + if (isset($name)) { + $this->name = $name; + } elseif (!isset($this->name)) { + throw new \InvalidArgumentException("Table must have a name"); + } $this->conn = $conn ?: static::$defaultConnection ?: new \pq\Connection; + $this->observers = new \SplObjectStorage; } /** @@ -98,13 +109,12 @@ class Table * @return string */ function __toString() { - return sprintf("postgresql://%s:%s@%s:%d/%s?%s#%s", + return (string) sprintf("postgresql://%s:%s@%s:%d/%s#%s", $this->conn->user, $this->conn->pass, $this->conn->host, $this->conn->port, $this->conn->db, - $this->conn->options, $this->getName() ); } @@ -200,38 +210,36 @@ class Table return $this->identity; } + /** + * Get the table attribute definition (column list) + * @return \pq\Table\Attributes + */ + function getAttributes() { + if (!isset($this->attributes)) { + $this->attributes = new Table\Attributes($this); + } + return $this->attributes; + } + /** * Get foreign key relations - * @param string $to fkey - * @return \pq\Gateway\Table\Relations|stdClass + * @return \pq\Gateway\Table\Relations */ - function getRelations($to = null) { + function getRelations() { if (!isset($this->relations)) { $this->relations = new Table\Relations($this); } - if (isset($to)) { - if (!isset($this->relations->$to)) { - return null; - } - return $this->relations->$to; - } return $this->relations; } /** - * Check whether a certain relation exists - * @param string $name + * Get a foreign key relation * @param string $table - * @return bool + * @param string $ref + * @return \pq\Gateway\Table\Reference */ - function hasRelation($name, $table = null) { - if (!($rel = $this->getRelations($name))) { - return false; - } - if (!isset($table)) { - return true; - } - return isset($rel->$table); + function getRelation($table, $ref = null) { + return $this->getRelations()->getReference($table, $ref); } /** @@ -249,21 +257,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); + } } /** @@ -328,51 +347,99 @@ class Table /** * Get the child rows of a row by foreign key * @param \pq\Gateway\Row $foreign - * @param string $name optional fkey name + * @param string $ref optional fkey name * @param string $order * @param int $limit * @param int $offset * @return mixed */ - function of(Row $foreign, $name = null, $order = null, $limit = 0, $offset = 0) { + function of(Row $foreign, $ref = null, $order = null, $limit = 0, $offset = 0) { // select * from $this where $this->$foreignColumn = $foreign->$referencedColumn - if (!isset($name)) { - $name = $foreign->getTable()->getName(); + if (!($rel = $this->getRelation($foreign->getTable()->getName(), $ref))) { + return $this->onResult(null); } - if (!$foreign->getTable()->hasRelation($name, $this->getName())) { - return $this->onResult(null); + $where = array(); + foreach ($rel as $key => $ref) { + $where["$key="] = $foreign->$ref; } - $rel = $foreign->getTable()->getRelations($name)->{$this->getName()}; - return $this->find( - array($rel->foreignColumn . "=" => $foreign->{$rel->referencedColumn}), - $order, $limit, $offset - ); + return $this->find($where, $order, $limit, $offset); } /** * Get the parent rows of a row by foreign key - * @param \pq\Gateway\Row $me - * @param string $foreign - * @param string $order - * @param int $limit - * @param int $offset + * @param \pq\Gateway\Row $foreign + * @param string $ref * @return mixed */ - function by(Row $me, $foreign, $order = null, $limit = 0, $offset = 0) { - // select * from $foreign where $foreign->$referencedColumn = $me->$foreignColumn + function by(Row $foreign, $ref = null) { + // select * from $this where $this->$referencedColumn = $me->$foreignColumn - if (!$this->hasRelation($foreign, $this->getName())) { + if (!($rel = $foreign->getTable()->getRelation($this->getName(), $ref))) { return $this->onResult(null); } - $rel = $this->getRelations($foreign)->{$this->getName()}; - return static::resolve($rel->referencedTable)->find( - array($rel->referencedColumn . "=" => $me->{$rel->foreignColumn}), - $order, $limit, $offset - ); + $where = array(); + foreach ($rel as $key => $ref) { + $where["$ref="] = $foreign->$key; + } + return $this->find($where); + } + + /** + * Get rows dependent on other rows by foreign keys + * @param array $relations + * @param array $where + * @param string $order + * @param int $limit + * @param int $offset + * @return mixed + */ + function with(array $relations, array $where = null, $order = null, $limit = 0, $offset = 0) { + $qthis = $this->conn->quoteName($this->getName()); + $query = $this->getQueryWriter()->reset(); + $query->write("SELECT", "$qthis.*", "FROM", $qthis); + foreach ($relations as $relation) { + if (!($relation instanceof Table\Reference)) { + $relation = static::resolve($relation)->getRelation($this->getName()); + } + if ($this->getName() === $relation->foreignTable) { + $query->write("JOIN", $relation->referencedTable)->write("ON"); + foreach ($relation as $key => $ref) { + $query->criteria( + array( + "{$relation->referencedTable}.{$ref}=" => + new QueryExpr("{$relation->foreignTable}.{$key}") + ) + ); + } + } else { + $query->write("JOIN", $relation->foreignTable)->write("ON"); + foreach ($relation as $key => $ref) { + $query->criteria( + array( + "{$relation->referencedTable}.{$ref}=" => + new QueryExpr("{$relation->foreignTable}.{$key}") + ) + ); + } + } + } + if ($where) { + $query->write("WHERE")->criteria($where); + } + if ($order) { + $query->write("ORDER BY", $order); + } + if ($limit) { + $query->write("LIMIT", $limit); + } + if ($offset) { + $query->write("OFFSET", $offset); + } + return $this->execute($query); } /** @@ -389,7 +456,7 @@ class Table $params = array(); foreach ($data as $key => $val) { $query->write($first ? "(" : ",", $key); - $params[] = $query->param($val); + $params[] = $query->param($val, $this->getAttributes()->getColumn($key)->type); $first and $first = false; } $query->write(") VALUES (", $params, ")"); @@ -415,7 +482,8 @@ class Table $query->write("UPDATE", $this->conn->quoteName($this->name)); $first = true; foreach ($data as $key => $val) { - $query->write($first ? "SET" : ",", $key, "=", $query->param($val)); + $query->write($first ? "SET" : ",", $key, "=", + $query->param($val, $this->getAttributes()->getColumn($key)->type)); $first and $first = false; } $query->write("WHERE")->criteria($where);