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\Attributes
59 protected $attributes;
62 * @var \pq\Gateway\Table\Relations
67 * @var \pq\Gateway\Table\CacheInterface
69 protected $metadataCache;
72 * @var \pq\Gateway\Table\LockInterface
77 * @param string $table
78 * @return \pq\Gateway\Table
80 public static function resolve($table) {
81 if ($table instanceof Table
) {
84 if (is_callable(static::$defaultResolver)) {
85 if (($resolved = call_user_func(static::$defaultResolver, $table))) {
89 return new Table($table);
94 * @param \pq\Connection $conn
95 * @param array $dependents
97 function __construct($name = null, \pq\Connection
$conn = null) {
100 } elseif (!isset($this->name
)) {
101 throw new \
InvalidArgumentException("Table must have a name");
103 $this->conn
= $conn ?
: static::$defaultConnection ?
: new \pq\Connection
;
107 * Get the complete PostgreSQL connection string
110 function __toString() {
111 return sprintf("postgresql://%s:%s@%s:%d/%s?%s#%s",
117 $this->conn
->options
,
123 * Set the rowset prototype
124 * @param mixed $rowset
125 * @return \pq\Gateway\Table
127 function setRowsetPrototype($rowset) {
128 $this->rowset
= $rowset;
133 * Get the rowset prototype
136 function getRowsetPrototype() {
137 return $this->rowset
;
141 * Set the query writer
142 * @param \pq\Query\WriterInterface $query
143 * @return \pq\Gateway\Table
145 function setQueryWriter(\pq\Query\WriterInterface
$query) {
146 $this->query
= $query;
151 * Get the query writer
152 * @return \pq\Query\WriterInterface
154 function getQueryWriter() {
156 $this->query
= new QueryWriter
;
162 * Set the query executor
163 * @param \pq\Query\ExecutorInterface $exec
164 * @return \pq\Gateway\Table
166 function setQueryExecutor(\pq\Query\ExecutorInterface
$exec) {
172 * Get the query executor
173 * @return \pq\Query\ExecutorInterface
175 function getQueryExecutor() {
177 $this->exec
= new QueryExecutor($this->conn
);
183 * Get the metadata cache
184 * @return \pq\Gateway\Table\CacheInterface
186 function getMetadataCache() {
187 if (!isset($this->metadatCache
)) {
188 $this->metadataCache
= static::$defaultMetadataCache ?
: new Table\StaticCache
;
190 return $this->metadataCache
;
194 * Set the metadata cache
195 * @param \pq\Gateway\Table\CacheInterface $cache
197 function setMetadataCache(Table\CacheInterface
$cache) {
198 $this->metadataCache
= $cache;
203 * Get the primary key
204 * @return \pq\Gateway\Table\Identity
206 function getIdentity() {
207 if (!isset($this->identity
)) {
208 $this->identity
= new Table\
Identity($this);
210 return $this->identity
;
213 function getAttributes() {
214 if (!isset($this->attributes
)) {
215 $this->attributes
= new Table\
Attributes($this);
217 return $this->attributes
;
221 * Get foreign key relations
222 * @param string $to fkey
223 * @return \pq\Gateway\Table\Relations|stdClass
225 function getRelations($to = null) {
226 if (!isset($this->relations
)) {
227 $this->relations
= new Table\
Relations($this);
230 if (!isset($this->relations
->$to)) {
233 return $this->relations
->$to;
235 return $this->relations
;
239 * Check whether a certain relation exists
240 * @param string $name
241 * @param string $table
244 function hasRelation($name, $table = null) {
245 if (!($rel = $this->getRelations($name))) {
248 if (!isset($table)) {
251 return isset($rel->$table);
255 * @return \pq\Connection
257 function getConnection() {
269 * Set a lock provider
270 * @param \pq\Gateway\Table\LockInterface $lock
271 * @return \pq\Gateway\Table
273 function setLock(Table\LockInterface
$lock) {
279 * Get any set lock provider
280 * @return \pq\Gateway\Table\LockIntferace
288 * @param \pq\Query\WriterInterface $query
291 protected function execute(QueryWriter
$query) {
292 return $this->getQueryExecutor()->execute($query, array($this, "onResult"));
296 * Retreives the result of an executed query
297 * @param \pq\Result $result
300 public function onResult(\pq\Result
$result = null) {
301 if ($result && $result->status
!= \pq\Result
::TUPLES_OK
) {
305 $rowset = $this->getRowsetPrototype();
306 if (is_callable($rowset)) {
307 return $rowset($result);
309 return new $rowset($this, $result);
316 * Find rows in the table
317 * @param array $where
318 * @param array|string $order
321 * @param string $lock
324 function find(array $where = null, $order = null, $limit = 0, $offset = 0, $lock = null) {
325 $query = $this->getQueryWriter()->reset();
326 $query->write("SELECT * FROM", $this->conn
->quoteName($this->name
));
328 $query->write("WHERE")->criteria($where);
331 $query->write("ORDER BY", $order);
334 $query->write("LIMIT", $limit);
337 $query->write("OFFSET", $offset);
340 $query->write("FOR", $lock);
342 return $this->execute($query);
346 * Get the child rows of a row by foreign key
347 * @param \pq\Gateway\Row $foreign
348 * @param string $name optional fkey name
349 * @param string $order
354 function of(Row
$foreign, $name = null, $order = null, $limit = 0, $offset = 0) {
355 // select * from $this where $this->$foreignColumn = $foreign->$referencedColumn
358 $name = $foreign->getTable()->getName();
361 if (!$foreign->getTable()->hasRelation($name, $this->getName())) {
362 return $this->onResult(null);
364 $rel = $foreign->getTable()->getRelations($name)->{$this->getName()};
367 array($rel->foreignColumn
. "=" => $foreign->{$rel->referencedColumn
}),
368 $order, $limit, $offset
373 * Get the parent rows of a row by foreign key
374 * @param \pq\Gateway\Row $me
375 * @param string $foreign
376 * @param string $order
381 function by(Row
$me, $foreign, $order = null, $limit = 0, $offset = 0) {
382 // select * from $foreign where $foreign->$referencedColumn = $me->$foreignColumn
384 if (!$this->hasRelation($foreign, $this->getName())) {
385 return $this->onResult(null);
387 $rel = $this->getRelations($foreign)->{$this->getName()};
389 return static::resolve($rel->referencedTable
)->find(
390 array($rel->referencedColumn
. "=" => $me->{$rel->foreignColumn
}),
391 $order, $limit, $offset
396 * Get rows dependent on other rows by foreign keys
397 * @param array $relations
398 * @param array $where
399 * @param string $order
404 function with(array $relations, array $where = null, $order = null, $limit = 0, $offset = 0) {
405 $qthis = $this->conn
->quoteName($this->getName());
406 $query = $this->getQueryWriter()->reset();
407 $query->write("SELECT", "$qthis.*", "FROM", $qthis);
408 foreach ($relations as $relation) {
409 $query->write("JOIN", $relation->foreignTable
)->write("ON")->criteria(
411 "{$relation->referencedTable}.{$relation->referencedColumn}=" =>
412 new QueryExpr("{$relation->foreignTable}.{$relation->foreignColumn}")
417 $query->write("WHERE")->criteria($where);
420 $query->write("ORDER BY", $order);
423 $query->write("LIMIT", $limit);
426 $query->write("OFFSET", $offset);
428 return $this->execute($query);
432 * Insert a row into the table
434 * @param string $returning
437 function create(array $data = null, $returning = "*") {
438 $query = $this->getQueryWriter()->reset();
439 $query->write("INSERT INTO", $this->conn
->quoteName($this->name
));
443 foreach ($data as $key => $val) {
444 $query->write($first ?
"(" : ",", $key);
445 $params[] = $query->param($val, $this->getAttributes()->getColumn($key)->type
);
446 $first and $first = false;
448 $query->write(") VALUES (", $params, ")");
450 $query->write("DEFAULT VALUES");
453 if (strlen($returning)) {
454 $query->write("RETURNING", $returning);
456 return $this->execute($query);
460 * Update rows in the table
461 * @param array $where
463 * @param string $returning
466 function update(array $where, array $data, $returning = "*") {
467 $query = $this->getQueryWriter()->reset();
468 $query->write("UPDATE", $this->conn
->quoteName($this->name
));
470 foreach ($data as $key => $val) {
471 $query->write($first ?
"SET" : ",", $key, "=",
472 $query->param($val, $this->getAttributes()->getColumn($key)->type
));
473 $first and $first = false;
475 $query->write("WHERE")->criteria($where);
476 if (strlen($returning)) {
477 $query->write("RETURNING", $returning);
479 return $this->execute($query);
483 * Delete rows from the table
484 * @param array $where
485 * @param string $returning
488 function delete(array $where, $returning = null) {
489 $query = $this->getQueryWriter()->reset();
490 $query->write("DELETE FROM", $this->conn
->quoteName($this->name
));
491 $query->write("WHERE")->criteria($where);
492 if (strlen($returning)) {
493 $query->write("RETURNING", $returning);
495 return $this->execute($query);