<?php
/**
* @category Horde
- * @package Horde_Rdo
+ * @package Horde_Rdo
*/
/**
* @TODO implement ArrayAccess as well?
*
* @category Horde
- * @package Horde_Rdo
+ * @package Horde_Rdo
*/
-class Horde_Rdo_List implements Iterator {
-
+class Horde_Rdo_List implements Iterator
+{
/**
* Rdo Mapper
* @var Horde_Rdo_Mapper
// Convert the query into a SQL statement and an array of
// bind parameters.
- list($this->_sql, $this->_bindParams) = $mapper->adapter->dml->getQuery($query);
+ list($this->_sql, $this->_bindParams) = $query->getQuery();
} elseif (is_string($query)) {
// Straight SQL query, empty bind parameters array.
$this->_sql = $query;
* Rdo Mapper base class.
*
* @category Horde
- * @package Horde_Rdo
+ * @package Horde_Rdo
*/
/**
* the main table of this entity.
*
* @category Horde
- * @package Horde_Rdo
+ * @package Horde_Rdo
*/
-abstract class Horde_Rdo_Mapper implements Countable {
-
+abstract class Horde_Rdo_Mapper implements Countable
+{
/**
* If this is true and fields named created and updated are
* present, Rdo will automatically set creation and last updated
return $this->table;
case 'tableDefinition':
+ $this->tableDefinition = $this->adapter->table($this->table);
+ return $this->tableDefinition;
case 'fields':
- $this->fields = array_diff($this->model->listFields(), $this->_lazyFields);
+ $this->fields = array_diff($this->tableDefinition->getColumnNames(), $this->_lazyFields);
return $this->fields;
case 'lazyFields':
}
}
- if (isset($relationships[$m->model->table])) {
- $o->$relationship = $m->map($relationships[$m->model->table]);
+ if (isset($relationships[$m->table])) {
+ $o->$relationship = $m->map($relationships[$m->table]);
}
}
}
$query = Horde_Rdo_Query::create($query, $this);
$query->setFields('COUNT(*)')
->clearSort();
- list($sql, $bindParams) = $this->adapter->dml->getCount($query);
- return $this->adapter->selectOne($sql, $bindParams);
+ list($sql, $bindParams) = $query->getQuery();
+ return $this->adapter->selectValue($sql, $bindParams);
}
/**
$query = Horde_Rdo_Query::create($query, $this);
$query->setFields(1)
->clearSort();
- list($sql, $bindParams) = $this->adapter->dml->getQuery($query);
- return (bool)$this->adapter->selectOne($sql, $bindParams);
+ list($sql, $bindParams) = $query->getQuery();
+ return (bool)$this->adapter->selectValue($sql, $bindParams);
}
/**
}
// Filter out any extra fields.
- $fields = array_intersect_key($fields, $this->model->getFields());
+ $fields = array_intersect_key($fields, $this->tableDefinition->getColumnNames());
if (!$fields) {
throw new Horde_Rdo_Exception('create() requires at least one field value.');
$id = $this->adapter->insert($sql, $bindParams);
- return $this->map(array_merge(array($this->model->key => $id),
+ return $this->map(array_merge(array($this->tableDefinition->getPrimaryKey() => $id),
$fields));
}
public function update($object, $fields = null)
{
if ($object instanceof Horde_Rdo_Base) {
- $key = $this->model->key;
+ $key = $this->tableDefinition->getPrimaryKey();
$id = $object->$key;
$fields = iterator_to_array($object);
}
// Filter out any extra fields.
- $fields = array_intersect_key($fields, $this->model->getFields());
+ $fields = array_intersect_key($fields, $this->tableDefinition->getColumnNames());
if (!$fields) {
// Nothing to change.
$sql .= ' ' . $this->adapter->quoteColumnName($field) . ' = ?,';
$bindParams[] = $value;
}
- $sql = substr($sql, 0, -1) . ' WHERE ' . $this->model->key . ' = ?';
+ $sql = substr($sql, 0, -1) . ' WHERE ' . $this->tableDefinition->getPrimaryKey() . ' = ?';
$bindParams[] = $id;
return $this->adapter->update($sql, $bindParams);
public function delete($object)
{
if ($object instanceof Horde_Rdo_Base) {
- $key = $this->model->key;
+ $key = $this->tableDefinition->getPrimaryKey();
$id = $object->$key;
$query = array($key => $id);
} elseif ($object instanceof Horde_Rdo_Query) {
$query = $object;
} else {
- $key = $this->model->key;
+ $key = $this->tableDefinition->getPrimaryKey();
$query = array($key => $object);
}
if (is_numeric(key($arg))) {
// Numerically indexed arrays are assumed to be an array of
// primary keys.
- $key = $this->model->key;
+ $key = $this->tableDefinition->getPrimaryKey();
$query = new Horde_Rdo_Query();
$query->combineWith('OR');
foreach ($argv[0] as $id) {
if (is_null($arg)) {
$query = null;
} elseif (is_scalar($arg)) {
- $query = array($this->model->key => $arg);
+ $query = array($this->tableDefinition->getPrimaryKey() => $arg);
} else {
$query = $arg;
}
* Represent a single query or a tree of many query elements uniformly to clients.
*
* @category Horde
- * @package Horde_Rdo
+ * @package Horde_Rdo
*/
/**
* @category Horde
- * @package Horde_Rdo
+ * @package Horde_Rdo
*/
-class Horde_Rdo_Query {
-
+class Horde_Rdo_Query
+{
/**
* @var Horde_Rdo_Mapper
*/
$q = new Horde_Rdo_Query($mapper);
if (is_scalar($query)) {
- $q->addTest($mapper->model->key, '=', $query);
+ $q->addTest($mapper->tableDefinition->getPrimaryKey(), '=', $query);
} elseif ($query) {
$q->combineWith('AND');
foreach ($query as $key => $value) {
$this->mapper = $mapper;
// Fetch all non-lazy-loaded fields for the mapper.
- $this->setFields($mapper->fields, $mapper->model->table . '.');
+ $this->setFields($mapper->fields, $mapper->table . '.');
if (!is_null($mapper)) {
// Add all non-lazy relationships.
}
// Add the fields for this relationship to the query.
- $this->addFields($m->fields, $m->model->table . '.@');
+ $this->addFields($m->fields, $m->table . '.@');
switch ($rel['type']) {
case Horde_Rdo::ONE_TO_ONE:
if (isset($rel['query'])) {
$query = $this->_fillJoinPlaceholders($m, $mapper, $rel['query']);
} else {
- $query = array($mapper->model->table . '.' . $rel['foreignKey'] => new Horde_Rdo_Query_Literal($m->model->table . '.' . $m->model->key));
+ $query = array($mapper->table . '.' . $rel['foreignKey'] => new Horde_Rdo_Query_Literal($m->table . '.' . $m->tableDefinition->getPrimaryKey()));
}
$this->addRelationship($relationship, array('mapper' => $m,
'type' => $rel['type'],
throw new InvalidArgumentException('Relationships must contain a Horde_Rdo_Mapper object.');
}
if (!isset($args['table'])) {
- $args['table'] = $args['mapper']->model->table;
+ $args['table'] = $args['mapper']->table;
}
if (!isset($args['type'])) {
$args['type'] = Horde_Rdo::MANY_TO_MANY;
}
/**
+ * Query generator.
+ *
+ * @return array A two-element array of the SQL query and an array
+ * of bind parameters.
+ */
+ public function getQuery()
+ {
+ $bindParams = array();
+ $sql = '';
+
+ $this->_select($sql, $bindParams);
+ $this->_from($sql, $bindParams);
+ $this->_join($sql, $bindParams);
+ $this->_where($sql, $bindParams);
+ $this->_orderBy($sql, $bindParams);
+ $this->_limit($sql, $bindParams);
+
+ return array($sql, $bindParams);
+ }
+
+ /**
+ */
+ protected function _select(&$sql, &$bindParams)
+ {
+ $fields = array();
+ foreach ($this->fields as $field) {
+ $parts = explode('.@', $field, 2);
+ if (count($parts) == 1) {
+ $fields[] = $field;
+ } else {
+ $fields[] = str_replace('.@', '.', $field) . ' AS ' . $this->mapper->adapter->quoteColumnName($parts[0] . '@' . $parts[1]);
+ }
+ }
+
+ $sql = 'SELECT ' . implode(', ', $fields);
+ }
+
+ /**
+ */
+ protected function _from(&$sql, &$bindParams)
+ {
+ $sql .= ' FROM ' . $this->mapper->table;
+ }
+
+ /**
+ */
+ protected function _join(&$sql, &$bindParams)
+ {
+ foreach ($this->relationships as $relationship) {
+ $relsql = array();
+ foreach ($relationship['query'] as $key => $value) {
+ if ($value instanceof Horde_Rdo_Query_Literal) {
+ $relsql[] = $key . ' = ' . (string)$value;
+ } else {
+ $relsql[] = $key . ' = ?';
+ $bindParams[] = $value;
+ }
+ }
+
+ $sql .= ' ' . $relationship['join_type'] . ' ' . $relationship['table'] . ' ON ' . implode(' AND ', $relsql);
+ }
+ }
+
+ /**
+ */
+ protected function _where(&$sql, &$bindParams)
+ {
+ $clauses = array();
+ foreach ($this->tests as $test) {
+ if (strpos($test['field'], '@') !== false) {
+ list($rel, $field) = explode('@', $test['field']);
+ if (!isset($this->relationships[$rel])) {
+ continue;
+ }
+ $clause = $this->relationships[$rel]['table'] . '.' . $field . ' ' . $test['test'];
+ } else {
+ $clause = $this->mapper->table . '.' . $this->mapper->adapter->quoteColumnName($test['field']) . ' ' . $test['test'];
+ }
+
+ if ($test['value'] instanceof Horde_Rdo_Query_Literal) {
+ $clauses[] = $clause . ' ' . (string)$test['value'];
+ } else {
+ if ($test['test'] == 'IN' && is_array($test['value'])) {
+ $clauses[] = $clause . '(?' . str_repeat(',?', count($test['value']) - 1) . ')';
+ $bindParams = array_merge($bindParams, array_values($test['value']));
+ } else {
+ $clauses[] = $clause . ' ?';
+ $bindParams[] = $test['value'];
+ }
+ }
+ }
+
+ if ($clauses) {
+ $sql .= ' WHERE ' . implode(' ' . $this->conjunction . ' ', $clauses);
+ }
+ }
+
+ /**
+ */
+ protected function _orderBy(&$sql, &$bindParams)
+ {
+ if ($this->sortby) {
+ $sql .= ' ORDER BY';
+ foreach ($this->sortby as $sort) {
+ if (strpos($sort, '@') !== false) {
+ /* @TODO parse these placeholders out, or drop them */
+ list($field, $direction) = $sort;
+ list($rel, $field) = explode('@', $field);
+ if (!isset($this->relationships[$rel])) {
+ continue;
+ }
+ $sql .= ' ' . $this->relationships[$rel]['table'] . '.' . $field . ' ' . $direction . ',';
+ } else {
+ $sql .= " $sort,";
+ }
+ }
+
+ $sql = substr($sql, 0, -1);
+ }
+ }
+
+ /**
+ */
+ protected function _limit(&$sql, &$bindParams)
+ {
+ if ($this->limit) {
+ $opts = array('limit' => $this->limit, 'offset' => $this->limitOffset);
+ $sql = $this->mapper->adapter->addLimitOffset($sql, $opts);
+ }
+ }
+
+ /**
* Callback for array_walk to prefix all elements of an array with
* a given prefix.
*/
foreach (array_keys($query) as $field) {
$value = $query[$field];
if (preg_match('/^@(.*)@$/', $value, $matches)) {
- $q[$m1->model->table . '.' . $field] = new Horde_Rdo_Query_Literal($m2->model->table . '.' . $matches[1]);
+ $q[$m1->table . '.' . $field] = new Horde_Rdo_Query_Literal($m2->table . '.' . $matches[1]);
} else {
- $q[$m1->model->table . '.' . $field] = $value;
+ $q[$m1->table . '.' . $field] = $value;
}
}
+++ /dev/null
-<?php
-/**
- * @category Horde
- * @package Horde_Rdo
- */
-
-/**
- * Horde_Rdo query building abstract base
- *
- * @category Horde
- * @package Horde_Rdo
- */
-abstract class Horde_Rdo_Query_Builder {
-
- /**
- */
- public function getCount($query)
- {
- return $this->getQuery($query);
- }
-
- /**
- * Query generator.
- *
- * @param Horde_Rdo_Query $query The query object to turn into SQL.
- *
- * @return array A two-element array of the SQL query and an array
- * of bind parameters.
- */
- public function getQuery($query)
- {
- if ($query instanceof Horde_Rdo_Query_Literal) {
- return array((string)$query, array());
- }
-
- $bindParams = array();
- $sql = '';
-
- $this->_select($query, $sql, $bindParams);
- $this->_from($query, $sql, $bindParams);
- $this->_join($query, $sql, $bindParams);
- $this->_where($query, $sql, $bindParams);
- $this->_orderBy($query, $sql, $bindParams);
- $this->_limit($query, $sql, $bindParams);
-
- return array($sql, $bindParams);
- }
-
- /**
- * Return the database-specific version of a test.
- *
- * @param string $test The test to "localize"
- */
- public function getTest($test)
- {
- return $test;
- }
-
- /**
- */
- protected function _select($query, &$sql, &$bindParams)
- {
- $fields = array();
- foreach ($query->fields as $field) {
- $parts = explode('.@', $field, 2);
- if (count($parts) == 1) {
- $fields[] = $field;
- } else {
- $fields[] = str_replace('.@', '.', $field) . ' AS ' . $query->mapper->adapter->quoteColumnName($parts[0] . '@' . $parts[1]);
- }
- }
-
- $sql = 'SELECT ' . implode(', ', $fields);
- }
-
- /**
- */
- protected function _from($query, &$sql, &$bindParams)
- {
- $sql .= ' FROM ' . $query->mapper->model->table;
- }
-
- /**
- */
- protected function _join($query, &$sql, &$bindParams)
- {
- foreach ($query->relationships as $relationship) {
- $relsql = array();
- foreach ($relationship['query'] as $key => $value) {
- if ($value instanceof Horde_Rdo_Query_Literal) {
- $relsql[] = $key . ' = ' . (string)$value;
- } else {
- $relsql[] = $key . ' = ?';
- $bindParams[] = $value;
- }
- }
-
- $sql .= ' ' . $relationship['join_type'] . ' ' . $relationship['table'] . ' ON ' . implode(' AND ', $relsql);
- }
- }
-
- /**
- */
- protected function _where($query, &$sql, &$bindParams)
- {
- $clauses = array();
- foreach ($query->tests as $test) {
- if (strpos($test['field'], '@') !== false) {
- list($rel, $field) = explode('@', $test['field']);
- if (!isset($query->relationships[$rel])) {
- continue;
- }
- $clause = $query->relationships[$rel]['table'] . '.' . $field . ' ' . $this->getTest($test['test']);
- } else {
- $clause = $query->mapper->model->table . '.' . $query->mapper->adapter->quoteColumnName($test['field']) . ' ' . $this->getTest($test['test']);
- }
-
- if ($test['value'] instanceof Horde_Rdo_Query_Literal) {
- $clauses[] = $clause . ' ' . (string)$test['value'];
- } else {
- if ($test['test'] == 'IN' && is_array($test['value'])) {
- $clauses[] = $clause . '(?' . str_repeat(',?', count($test['value']) - 1) . ')';
- $bindParams = array_merge($bindParams, array_values($test['value']));
- } else {
- $clauses[] = $clause . ' ?';
- $bindParams[] = $test['value'];
- }
- }
- }
-
- if ($clauses) {
- $sql .= ' WHERE ' . implode(' ' . $query->conjunction . ' ', $clauses);
- }
- }
-
- /**
- */
- protected function _orderBy($query, &$sql, &$bindParams)
- {
- if ($query->sortby) {
- $sql .= ' ORDER BY';
- foreach ($query->sortby as $sort) {
- if (strpos($sort, '@') !== false) {
- /*@TODO parse these placeholders out, or drop them*/
- list($field, $direction) = $sort;
- list($rel, $field) = explode('@', $field);
- if (!isset($query->relationships[$rel])) {
- continue;
- }
- $sql .= ' ' . $query->relationships[$rel]['table'] . '.' . $field . ' ' . $direction . ',';
- } else {
- $sql .= " $sort,";
- }
- }
-
- $sql = substr($sql, 0, -1);
- }
- }
-
- /**
- */
- protected function _limit($query, &$sql, &$bindParams)
- {
- if ($query->limit) {
- $sql .= ' LIMIT ' . $query->limit;
- if (!is_null($query->limitOffset)) {
- $sql .= ' OFFSET ' . $query->limitOffset;
- }
- }
- }
-
-}
<?php
/**
* @category Horde
- * @package Horde_Rdo
+ * @package Horde_Rdo
*/
/**
* $literal = new Horde_Rdo_Query_Literal('MAX(column_name)');
*
* @category Horde
- * @package Horde_Rdo
+ * @package Horde_Rdo
*/
-class Horde_Rdo_Query_Literal {
-
+class Horde_Rdo_Query_Literal
+{
/**
* SQL literal string.
*
/**
* @param Horde_Rdo_Mapper $mapper Rdo mapper base class
- *
- * @return Horde_Rdo_Query Return the query object for fluent chaining.
*/
public function setMapper($mapper)
{
- if ($mapper === $this->mapper) {
- return $this;
+ if ($mapper !== $this->mapper) {
+ $this->mapper = $mapper;
}
-
- $this->mapper = $mapper;
}
}
<dir name="Horde">
<dir name="Rdo">
<dir name="Query">
- <file name="Builder.php" role="php" />
<file name="Literal.php" role="php" />
</dir> <!-- /lib/Horde/Rdo/Query -->
<file name="Base.php" role="php" />
</dependencies>
<phprelease>
<filelist>
- <install name="lib/Horde/Rdo/Query/Builder.php" as="Horde/Rdo/Query/Builder.php" />
<install name="lib/Horde/Rdo/Query/Literal.php" as="Horde/Rdo/Query/Literal.php" />
<install name="lib/Horde/Rdo/Base.php" as="Horde/Rdo/Base.php" />
<install name="lib/Horde/Rdo/Iterator.php" as="Horde/Rdo/Iterator.php" />