5 use \pq\Query\Expr
as QueryExpr
;
6 use \pq\Query\Writer
as QueryWriter
;
7 use \pq\Query\Executor
as QueryExecutor
;
14 public static $defaultConnection;
19 public static $defaultResolver;
22 * @var \pq\Gateway\Table\CacheInterface
24 public static $defaultMetadataCache;
39 protected $rowset = "\\pq\\Gateway\\Rowset";
42 * @var \pq\Query\WriterIterface
47 * @var \pq\Query\ExecutorInterface
52 * @var \pq\Gateway\Table\Identity
57 * @var \pq\Gateway\Table\Relations
62 * @var \pq\Gateway\Table\CacheInterface
64 protected $metadataCache;
67 * @var \pq\Gateway\Table\LockInterface
72 * @param string $table
73 * @return \pq\Gateway\Table
75 public static function resolve($table) {
76 if ($table instanceof Table
) {
79 if (is_callable(static::$defaultResolver)) {
80 if (($resolved = call_user_func(static::$defaultResolver, $table))) {
84 return new Table($table);
89 * @param \pq\Connection $conn
90 * @param array $dependents
92 function __construct($name = null, \pq\Connection
$conn = null) {
95 } elseif (!isset($this->name
)) {
96 throw new \
InvalidArgumentException("Table must have a name");
98 $this->conn
= $conn ?
: static::$defaultConnection ?
: new \pq\Connection
;
102 * Get the complete PostgreSQL connection string
105 function __toString() {
106 return sprintf("postgresql://%s:%s@%s:%d/%s?%s#%s",
112 $this->conn
->options
,
118 * Set the rowset prototype
119 * @param mixed $rowset
120 * @return \pq\Gateway\Table
122 function setRowsetPrototype($rowset) {
123 $this->rowset
= $rowset;
128 * Get the rowset prototype
131 function getRowsetPrototype() {
132 return $this->rowset
;
136 * Set the query writer
137 * @param \pq\Query\WriterInterface $query
138 * @return \pq\Gateway\Table
140 function setQueryWriter(\pq\Query\WriterInterface
$query) {
141 $this->query
= $query;
146 * Get the query writer
147 * @return \pq\Query\WriterInterface
149 function getQueryWriter() {
151 $this->query
= new QueryWriter
;
157 * Set the query executor
158 * @param \pq\Query\ExecutorInterface $exec
159 * @return \pq\Gateway\Table
161 function setQueryExecutor(\pq\Query\ExecutorInterface
$exec) {
167 * Get the query executor
168 * @return \pq\Query\ExecutorInterface
170 function getQueryExecutor() {
172 $this->exec
= new QueryExecutor($this->conn
);
178 * Get the metadata cache
179 * @return \pq\Gateway\Table\CacheInterface
181 function getMetadataCache() {
182 if (!isset($this->metadatCache
)) {
183 $this->metadataCache
= static::$defaultMetadataCache ?
: new Table\StaticCache
;
185 return $this->metadataCache
;
189 * Set the metadata cache
190 * @param \pq\Gateway\Table\CacheInterface $cache
192 function setMetadataCache(Table\CacheInterface
$cache) {
193 $this->metadataCache
= $cache;
198 * Get the primary key
199 * @return \pq\Gateway\Table\Identity
201 function getIdentity() {
202 if (!isset($this->identity
)) {
203 $this->identity
= new Table\
Identity($this);
205 return $this->identity
;
209 * Get foreign key relations
210 * @param string $to fkey
211 * @return \pq\Gateway\Table\Relations|stdClass
213 function getRelations($to = null) {
214 if (!isset($this->relations
)) {
215 $this->relations
= new Table\
Relations($this);
218 if (!isset($this->relations
->$to)) {
221 return $this->relations
->$to;
223 return $this->relations
;
227 * Check whether a certain relation exists
228 * @param string $name
229 * @param string $table
232 function hasRelation($name, $table = null) {
233 if (!($rel = $this->getRelations($name))) {
236 if (!isset($table)) {
239 return isset($rel->$table);
243 * @return \pq\Connection
245 function getConnection() {
257 * Set a lock provider
258 * @param \pq\Gateway\Table\LockInterface $lock
259 * @return \pq\Gateway\Table
261 function setLock(Table\LockInterface
$lock) {
267 * Get any set lock provider
268 * @return \pq\Gateway\Table\LockIntferace
276 * @param \pq\Query\WriterInterface $query
279 protected function execute(QueryWriter
$query) {
280 return $this->getQueryExecutor()->execute($query, array($this, "onResult"));
284 * Retreives the result of an executed query
285 * @param \pq\Result $result
288 public function onResult(\pq\Result
$result = null) {
289 if ($result && $result->status
!= \pq\Result
::TUPLES_OK
) {
293 $rowset = $this->getRowsetPrototype();
294 if (is_callable($rowset)) {
295 return $rowset($result);
297 return new $rowset($this, $result);
304 * Find rows in the table
305 * @param array $where
306 * @param array|string $order
309 * @param string $lock
312 function find(array $where = null, $order = null, $limit = 0, $offset = 0, $lock = null) {
313 $query = $this->getQueryWriter()->reset();
314 $query->write("SELECT * FROM", $this->conn
->quoteName($this->name
));
316 $query->write("WHERE")->criteria($where);
319 $query->write("ORDER BY", $order);
322 $query->write("LIMIT", $limit);
325 $query->write("OFFSET", $offset);
328 $query->write("FOR", $lock);
330 return $this->execute($query);
334 * Get the child rows of a row by foreign key
335 * @param \pq\Gateway\Row $foreign
336 * @param string $name optional fkey name
337 * @param string $order
342 function of(Row
$foreign, $name = null, $order = null, $limit = 0, $offset = 0) {
343 // select * from $this where $this->$foreignColumn = $foreign->$referencedColumn
346 $name = $foreign->getTable()->getName();
349 if (!$foreign->getTable()->hasRelation($name, $this->getName())) {
350 return $this->onResult(null);
352 $rel = $foreign->getTable()->getRelations($name)->{$this->getName()};
355 array($rel->foreignColumn
. "=" => $foreign->{$rel->referencedColumn
}),
356 $order, $limit, $offset
361 * Get the parent rows of a row by foreign key
362 * @param \pq\Gateway\Row $me
363 * @param string $foreign
364 * @param string $order
369 function by(Row
$me, $foreign, $order = null, $limit = 0, $offset = 0) {
370 // select * from $foreign where $foreign->$referencedColumn = $me->$foreignColumn
372 if (!$this->hasRelation($foreign, $this->getName())) {
373 return $this->onResult(null);
375 $rel = $this->getRelations($foreign)->{$this->getName()};
377 return static::resolve($rel->referencedTable
)->find(
378 array($rel->referencedColumn
. "=" => $me->{$rel->foreignColumn
}),
379 $order, $limit, $offset
384 * Get rows dependent on other rows by foreign keys
385 * @param array $relations
386 * @param array $where
387 * @param string $order
392 function with(array $relations, array $where = null, $order = null, $limit = 0, $offset = 0) {
393 $qthis = $this->conn
->quoteName($this->getName());
394 $query = $this->getQueryWriter()->reset();
395 $query->write("SELECT", "$qthis.*", "FROM", $qthis);
396 foreach ($relations as $relation) {
397 $query->write("JOIN", $relation->foreignTable
)->write("ON")->criteria(
399 "{$relation->referencedTable}.{$relation->referencedColumn}=" =>
400 new QueryExpr("{$relation->foreignTable}.{$relation->foreignColumn}")
405 $query->write("WHERE")->criteria($where);
408 $query->write("ORDER BY", $order);
411 $query->write("LIMIT", $limit);
414 $query->write("OFFSET", $offset);
416 return $this->execute($query);
420 * Insert a row into the table
422 * @param string $returning
425 function create(array $data = null, $returning = "*") {
426 $query = $this->getQueryWriter()->reset();
427 $query->write("INSERT INTO", $this->conn
->quoteName($this->name
));
431 foreach ($data as $key => $val) {
432 $query->write($first ?
"(" : ",", $key);
433 $params[] = $query->param($val);
434 $first and $first = false;
436 $query->write(") VALUES (", $params, ")");
438 $query->write("DEFAULT VALUES");
441 if (strlen($returning)) {
442 $query->write("RETURNING", $returning);
444 return $this->execute($query);
448 * Update rows in the table
449 * @param array $where
451 * @param string $returning
454 function update(array $where, array $data, $returning = "*") {
455 $query = $this->getQueryWriter()->reset();
456 $query->write("UPDATE", $this->conn
->quoteName($this->name
));
458 foreach ($data as $key => $val) {
459 $query->write($first ?
"SET" : ",", $key, "=", $query->param($val));
460 $first and $first = false;
462 $query->write("WHERE")->criteria($where);
463 if (strlen($returning)) {
464 $query->write("RETURNING", $returning);
466 return $this->execute($query);
470 * Delete rows from the table
471 * @param array $where
472 * @param string $returning
475 function delete(array $where, $returning = null) {
476 $query = $this->getQueryWriter()->reset();
477 $query->write("DELETE FROM", $this->conn
->quoteName($this->name
));
478 $query->write("WHERE")->criteria($where);
479 if (strlen($returning)) {
480 $query->write("RETURNING", $returning);
482 return $this->execute($query);