Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Add 'having' to database adapter #485

Merged
merged 1 commit into from

2 participants

@jails
Collaborator

Close #262

@nateabele nateabele merged commit de87d62 into UnionOfRAD:data
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on May 24, 2012
  1. @jails

    Add 'having' to database adapter

    jails authored
This page is out of date. Refresh to see the latest.
View
17 data/model/Query.php
@@ -101,6 +101,7 @@ public function __construct(array $config = array()) {
'calculate' => null,
'schema' => null,
'conditions' => array(),
+ 'having' => array(),
'fields' => array(),
'data' => array(),
'model' => null,
@@ -225,6 +226,22 @@ public function conditions($conditions = null) {
}
/**
+ * Set and get method for havings.
+ *
+ * @param mixed $having String or array to append to existing having.
+ * @return array Returns an array of all having applied to this query.
+ */
+ public function having($having = null) {
+ if (!$having) {
+ return $this->_config['having'];
+ }
+ $having = (array) $having;
+ $this->_config['having'] = (array) $this->_config['having'];
+ $this->_config['having'] = array_merge($this->_config['having'], $having);
+ return $this;
+ }
+
+ /**
* Set, get or reset fields option for query.
*
* Usage:
View
51 data/source/Database.php
@@ -152,7 +152,7 @@ public function __construct(array $config = array()) {
);
$this->_strings += array(
'read' => 'SELECT {:fields} FROM {:source} {:alias} {:joins} {:conditions} {:group} ' .
- '{:order} {:limit};{:comment}'
+ '{:having} {:order} {:limit};{:comment}'
);
parent::__construct($config + $defaults);
}
@@ -572,7 +572,50 @@ public function schema($query, $resource = null, $context = null) {
* @return string Returns the `WHERE` clause of an SQL query.
*/
public function conditions($conditions, $context, array $options = array()) {
- $defaults = array('prepend' => true);
+ $defaults = array('prepend' => 'WHERE');
+ $options += $defaults;
+ return $this->_conditions($conditions, $context, $options);
+ }
+
+ /**
+ * Returns a string of formatted havings to be inserted into the query statement. If the
+ * query havings are defined as an array, key pairs are converted to SQL strings.
+ *
+ * Conversion rules are as follows:
+ *
+ * - If `$key` is numeric and `$value` is a string, `$value` is treated as a literal SQL
+ * fragment and returned.
+ *
+ * @param string|array $having The havings for this query.
+ * @param object $context The current `lithium\data\model\Query` instance.
+ * @param array $options
+ * - `prepend` _boolean_: Whether the return string should be prepended with the
+ * `HAVING` keyword.
+ * @return string Returns the `HAVING` clause of an SQL query.
+ */
+ public function having($conditions, $context, array $options = array()) {
+ $defaults = array('prepend' => 'HAVING');
+ $options += $defaults;
+ return $this->_conditions($conditions, $context, $options);
+ }
+
+ /**
+ * Returns a string of formatted conditions to be inserted into the query statement. If the
+ * query conditions are defined as an array, key pairs are converted to SQL strings.
+ *
+ * Conversion rules are as follows:
+ *
+ * - If `$key` is numeric and `$value` is a string, `$value` is treated as a literal SQL
+ * fragment and returned.
+ *
+ * @param string|array $conditions The conditions for this query.
+ * @param object $context The current `lithium\data\model\Query` instance.
+ * @param array $options
+ * - `prepend` mixed: The string to prepend or false for no prepending
+ * @return string Returns an SQL conditions clause.
+ */
+ protected function _conditions($conditions, $context, array $options = array()) {
+ $defaults = array('prepend' => false);
$ops = $this->_operators;
$options += $defaults;
$model = $context->model();
@@ -582,7 +625,7 @@ public function conditions($conditions, $context, array $options = array()) {
case empty($conditions):
return '';
case is_string($conditions):
- return ($options['prepend']) ? "WHERE {$conditions}" : $conditions;
+ return $options['prepend'] ? $options['prepend'] . " {$conditions}" : $conditions;
case !is_array($conditions):
return '';
}
@@ -596,7 +639,7 @@ public function conditions($conditions, $context, array $options = array()) {
}
}
$result = join(" AND ", $result);
- return ($options['prepend'] && $result) ? "WHERE {$result}" : $result;
+ return ($options['prepend'] && $result) ? $options['prepend'] . " {$result}" : $result;
}
public function _processConditions($key, $value, $context, $schema, $glue = 'AND') {
View
15 tests/cases/data/model/QueryTest.php
@@ -213,6 +213,20 @@ public function testConditions() {
$this->assertEqual($expected, $result);
}
+ public function testHaving() {
+ $query = new Query($this->_queryArr);
+
+ $expected = array();
+ $result = $query->having();
+ $this->assertEqual($expected, $result);
+
+ $query->having(array('count' => 5));
+
+ $expected = array('count' => 5);
+ $result = $query->having();
+ $this->assertEqual($expected, $result);
+ }
+
public function testConditionFromRecord() {
$entity = new Record();
$entity->id = 12;
@@ -248,6 +262,7 @@ public function testExport() {
'calculate',
'comment',
'conditions',
+ 'having',
'data',
'fields',
'group',
View
39 tests/cases/data/source/DatabaseTest.php
@@ -596,6 +596,38 @@ public function testConditions() {
$this->assertEqual($sql, $this->db->renderCommand($query));
}
+ public function testHaving() {
+ $query = new Query(array(
+ 'type' => 'read', 'model' => $this->_model,
+ 'having' => array(
+ 'or' => array(
+ 'id' => 'value1',
+ 'title' => 'value2',
+ 'and' => array('author_id' => '1', 'created' => '2'),
+ array('title' => 'value2'),
+ array('title' => null)
+ ),
+ 'id' => '3',
+ 'author_id' => false
+ )
+ ));
+ $sql = "SELECT * FROM {mock_database_posts} AS {MockDatabasePost} HAVING ";
+ $sql .= "({MockDatabasePost}.{id} = 0 OR {MockDatabasePost}.{title} = 'value2' OR ";
+ $sql .= "({MockDatabasePost}.{author_id} = 1 AND {MockDatabasePost}.{created} = '2') OR ";
+ $sql .= "({MockDatabasePost}.{title} = 'value2') OR ({MockDatabasePost}.{title} IS NULL)) AND ";
+ $sql .= "{MockDatabasePost}.{id} = 3 AND {MockDatabasePost}.{author_id} = 0;";
+ $this->assertEqual($sql, $this->db->renderCommand($query));
+
+ $query = new Query(array(
+ 'type' => 'read', 'model' => $this->_model,
+ 'having' => array('title' => array('0900'))
+ ));
+
+ $sql = 'SELECT * FROM {mock_database_posts} AS {MockDatabasePost}' .
+ ' HAVING {title} IN (\'0900\');';
+ $this->assertEqual($sql, $this->db->renderCommand($query));
+ }
+
public function testReadConditionsWithModel() {
$model = $this->_model;
$options = array(
@@ -660,6 +692,13 @@ public function testRawConditions() {
$this->assertEqual("WHERE CUSTOM", $this->db->conditions("CUSTOM", $query));
}
+ public function testRawHaving() {
+ $query = new Query(array('type' => 'read', 'model' => $this->_model, 'having' => null));
+ $this->assertFalse($this->db->having(5, $query));
+ $this->assertFalse($this->db->having(null, $query));
+ $this->assertEqual("HAVING CUSTOM", $this->db->having("CUSTOM", $query));
+ }
+
public function testRelationshipGeneration() {
$comment = 'lithium\tests\mocks\data\model\MockDatabaseComment';
Something went wrong with that request. Please try again.