namespace pq\Gateway;
-use \pq\Query\Expr;
+use \pq\Query\Expressible;
-class Cell
+class Cell extends Expressible
{
/**
* @var \pq\Gateway\Row
*/
protected $name;
- /**
- * @var mixed
- */
- protected $data;
-
/**
* @var bool
*/
* @param bool $dirty
*/
function __construct(Row $row, $name, $data, $dirty = false) {
+ parent::__construct($data);
$this->row = $row;
$this->name = $name;
- $this->data = $data;
$this->dirty = $dirty;
}
- /**
- * Get value as string
- * @return string
- */
- function __toString() {
- return (string) $this->data;
- }
-
- /**
- * Test whether the value is an unevaluated expression
- * @return bool
- */
- function isExpr() {
- return $this->data instanceof Expr;
- }
-
/**
* Check whether the cell has been modified
* @return bool
}
/**
- * Get value
- * @return mixed
- */
- function get() {
- return $this->data;
- }
-
- /**
- * Modify the value in this cell
+ * Set the value
* @param mixed $data
- * @param string $op a specific operator
* @return \pq\Gateway\Cell
*/
- function mod($data, $op = null) {
- if (!($this->data instanceof Expr)) {
- $this->data = new Expr($this->name);
- }
-
- if ($data instanceof Expr) {
- $this->data->add($data);
- } elseif (!isset($op) && is_numeric($data)) {
- $this->data->add(new Expr("+ $data"));
- } else {
- $data = $this->row->getTable()->getConnection()->quote($data);
- $this->data->add(new Expr("%s %s", isset($op) ? $op : "||", $data));
- }
-
+ function set($data) {
+ parent::set($data);
$this->dirty = true;
-
return $this;
}
/**
- * Set the value in this cell
+ * Modify the value in this cell
* @param mixed $data
+ * @param string $op a specific operator
* @return \pq\Gateway\Cell
*/
- function set($data) {
- $this->data = $data;
+ function mod($data, $op = null) {
+ parent::mod($data, $op);
$this->dirty = true;
return $this;
}
+
}
namespace pq\Gateway;
use \pq\Query\Writer as QueryWriter;
+use \pq\Query\Executor as QueryExecutor;
class Table
{
protected $rowset = "\\pq\\Gateway\\Rowset";
/**
- * @var \pq\Query\Writer
+ * @var \pq\Query\WriterIterface
*/
protected $query;
+
+ /**
+ * @var \pq\Query\ExecutorInterface
+ */
+ protected $exec;
/**
* @param string $name
* @return \pq\Query\WriterInterface
*/
function getQueryWriter() {
- return $this->query ?: new QueryWriter;
+ if (!$this->query) {
+ $this->query = new QueryWriter;
+ }
+ return $this->query;
+ }
+
+ /**
+ * Set the query executor
+ * @param \pq\Query\ExecutorInterface $exec
+ * @return \pq\Gateway\Table
+ */
+ function setQueryExecutor(\pq\Query\ExecutorInterface $exec) {
+ $this->exec = $exec;
+ return $this;
+ }
+
+ /**
+ * Get the query executor
+ * @return \pq\Query\ExecutorInterface
+ */
+ function getQueryExecutor() {
+ if (!$this->exec) {
+ $this->exec = new QueryExecutor($this->conn);
+ }
+ return $this->exec;
}
/**
/**
* Execute the query
- * @param \pq\Query\Writer $query
+ * @param \pq\Query\WriterInterface $query
* @return mixed
*/
protected function execute(QueryWriter $query) {
- $result = $query->exec($this->conn);
-
+ return $this->getQueryExecutor()->execute($query, array($this, "onResult"));
+ }
+
+ /**
+ * Retreives the result of an executed query
+ * @param \pq\Result $result
+ * @return mixed
+ */
+ public function onResult(\pq\Result $result) {
if ($result->status != \pq\Result::TUPLES_OK) {
return $result;
}
return $result;
}
-
+
/**
* Find rows in the table
* @param array $where
* @param array|string $order
* @param int $limit
* @param int $offset
- * @return \pq\Result
+ * @return mixed
*/
function find(array $where = null, $order = null, $limit = 0, $offset = 0) {
$query = $this->getQueryWriter()->reset();
* Insert a row into the table
* @param array $data
* @param string $returning
- * @return \pq\Result
+ * @return mixed
*/
function create(array $data = null, $returning = "*") {
$query = $this->getQueryWriter()->reset();
* @param array $where
* @param array $data
* @param string $returning
- * @retunr \pq\Result
+ * @retunr mixed
*/
function update(array $where, array $data, $returning = "*") {
$query = $this->getQueryWriter()->reset();
* Delete rows from the table
* @param array $where
* @param string $returning
- * @return pq\Result
+ * @return mixed
*/
function delete(array $where, $returning = null) {
$query = $this->getQueryWriter()->reset();
--- /dev/null
+<?php
+
+namespace pq\Query;
+
+/**
+ * A synchronous query executor
+ */
+class Executor implements ExecutorInterface
+{
+ /**
+ * @var \pq\Connection
+ */
+ protected $conn;
+
+ /**
+ * Create a synchronous query executor
+ * @param \pq\Connection $conn
+ */
+ function __construct(\pq\Connection $conn) {
+ $this->conn = $conn;
+ }
+
+ /**
+ * @inheritdoc
+ * @return \pq\Connection
+ */
+ function getConnection() {
+ return $this->conn;
+ }
+
+ /**
+ * @inheritdoc
+ * @param \pq\Connection $conn
+ * @return \pq\Query\Executor
+ */
+ function setConnection(\pq\Connection $conn) {
+ $this->conn = $conn;
+ return $this;
+ }
+
+ /**
+ * Execute the query synchronously through \pq\Connection::execParams()
+ * @param \pq\Query\WriterInterface $query
+ * @param callable $callback
+ * @return mixed
+ */
+ function execute(WriterInterface $query, callable $callback) {
+ return $callback($this->getConnection()->execParams($query, $query->getParams(), $query->getTypes()));
+ }
+}
--- /dev/null
+<?php
+
+namespace pq\Query\Executor;
+
+use \pq\Query\ExecutorInterface;
+use \pq\Query\WriterInterface;
+
+use \React\Promise\Deferred;
+
+/**
+ * An asynchronous query executor
+ */
+class Async implements ExecutorInterface
+{
+ protected $conn;
+
+ /**
+ * Create a asynchronous query exectuor
+ * @param \pq\Connection $conn
+ */
+ function __construct(\pq\Connection $conn) {
+ $this->conn = $conn;
+ }
+
+ /**
+ * Get the connection
+ * @return \pq\Connection
+ */
+ function getConnection() {
+ return $this->conn;
+ }
+
+ /**
+ * Set the connection
+ * @param \pq\Connection $conn
+ * @return \pq\Query\Executor\Async
+ */
+ function setConnection(\pq\Connection $conn) {
+ $this->conn = $conn;
+ return $this;
+ }
+
+ /**
+ * Execute the query asynchronously through \pq\Connection::execParamsAsync()
+ * @param \pq\Query\WriterInterface $query
+ * @param callable $callback
+ * @return \React\Promise\DeferredPromise
+ */
+ function execute(WriterInterface $query, callable $callback) {
+ $deferred = new Deferred; // FIXME
+ $this->getConnection()->execParamsAsync($query, $query->getParams(), $query->getTypes(),
+ array($deferred->resolver(), "resolve"));
+ return $deferred->then($callback);
+ }
+}
--- /dev/null
+<?php
+
+namespace pq\Query;
+
+/**
+ * An executor of \pq\Query\Writer queries
+ */
+interface ExecutorInterface
+{
+ /**
+ * Get the connection
+ * @return \pq\Connection
+ */
+ function getConnection();
+
+ /**
+ * Set the connection
+ * @param \pq\Connection $conn
+ * @return \pq\Query\ExecutorInterface
+ */
+ function setConnection(\pq\Connection $conn);
+
+ /**
+ * Execute the query and return the \pq\Result through $callback
+ * @param \pq\Query\WriterInterface $query
+ * @param callable $callback
+ * @return mixed the result of the callback
+ */
+ function execute(WriterInterface $query, callable $callback);
+}
--- /dev/null
+<?php
+
+namespace pq\Query;
+
+class Expressible implements ExpressibleInterface
+{
+ /**
+ * @var mixed
+ */
+ protected $data;
+
+ function __construct($data) {
+ $this->data = $data;
+ }
+
+ /**
+ * Get value as string
+ * @return string
+ */
+ function __toString() {
+ return (string) $this->data;
+ }
+
+ /**
+ * Test whether the value is an unevaluated expression
+ * @return bool
+ */
+ function isExpr() {
+ return $this->data instanceof Expr;
+ }
+
+ /**
+ * Get value
+ * @return mixed
+ */
+ function get() {
+ return $this->data;
+ }
+
+ /**
+ * Set the value
+ * @param mixed $data
+ * @return \pq\Query\Expressible
+ */
+ function set($data) {
+ $this->data = $data;
+ return $this;
+ }
+
+ /**
+ * Modify the data
+ * @param mixed $data
+ * @param string $op a specific operator
+ * @return \pq\Query\Expressible
+ */
+ function mod($data, $op = null) {
+ if (!($this->data instanceof Expr)) {
+ $this->data = new Expr($this->name);
+ }
+
+ if ($data instanceof Expr) {
+ $this->data->add($data);
+ } elseif (!isset($op) && is_numeric($data)) {
+ $this->data->add(new Expr("+ $data"));
+ } else {
+ $data = $this->row->getTable()->getConnection()->quote($data);
+ $this->data->add(new Expr("%s %s", isset($op) ? $op : "||", $data));
+ }
+
+ return $this;
+ }
+}
\ No newline at end of file
--- /dev/null
+<?php
+
+namespace pq\Query;
+
+interface ExpressibleInterface
+{
+ /**
+ * Get the contained value as string
+ * @return string
+ */
+ function __toString();
+
+ /**
+ * Test whether we are an expression
+ * @return bool
+ */
+ function isExpr();
+
+ /**
+ * Get the literal value or the expression
+ * @return mixed
+ */
+ function get();
+
+ /**
+ * Set the contained value
+ * @param mixed $data
+ * @return \pq\Query\ExpressibleInterface
+ */
+ function set($data);
+
+ /**
+ * Modify the data
+ * @param mixed $data
+ * @param string $op a specific operator
+ * @return \pq\Query\ExpressibleInterface
+ */
+ function mod($data, $op = null);
+
+}
* @return string
*/
function param($param, $type = null) {
- if ($param instanceof \pq\Gateway\Cell) {
+ if ($param instanceof ExpressibleInterface) {
$param = $param->get();
}
if ($param instanceof Expr) {
}
return $this;
}
-
- /**
- * Execute the query through \pq\Connection::execParams($this, $this->params, $this->types)
- * @param \pq\Connection $c
- * @return \pq\Result
- */
- function exec(\pq\Connection $c) {
- return $c->execParams($this, $this->getParams(), $this->getTypes());
- }
}
namespace pq\Query;
+/**
+ * A query writer which supports easily constructing queries for \pq\Connection::execParams()
+ */
interface WriterInterface
{
+ /**
+ * Returns the plain constructed query as string
+ * @return string
+ */
function __toString();
+
+ /**
+ * Returns a list of parameters as array
+ * @return array
+ */
function getParams();
+
+ /**
+ * Returns a list any types associated with the params
+ */
function getTypes();
+
+ /**
+ * Reset the state of the query writer
+ */
+ function reset();
+
+ /**
+ * Write plain SQL to the query
+ * @param mixed $arg variable list of arguments, arrays will be imploded to a comm separated list
+ */
function write(/*...*/);
+
+ /**
+ * Remember the parameter with any associated type and return $N to be written to the query string
+ * @param mixed $param a literal parameter, a \pq\Gateway\Table\Cell or a \pq\Query\Expr
+ * @param int $type the oid of the type of the param
+ */
function param($param, $type = null);
+
+ /**
+ * An array of AND/OR criteria
+ * @param array $criteria
+ */
function criteria(array $criteria);
- function reset();
- function exec(\pq\Connection $c);
}