Skip to content
Snippets Groups Projects
Commit 22a241ca authored by Alex Pott's avatar Alex Pott
Browse files

Issue #1267508 by fietserwin, lisa.ugray, daffie, chx, Crell: Subselects don't...

Issue #1267508 by fietserwin, lisa.ugray, daffie, chx, Crell: Subselects don't work in DBTNG conditions, except when used as value for IN
parent 3de79990
No related branches found
No related tags found
No related merge requests found
......@@ -39,6 +39,11 @@ class Condition implements ConditionInterface, \Countable {
*/
protected $queryPlaceholderIdentifier;
/**
* @var string Contains the string version of the Condition.
*/
protected $stringVersion;
/**
* Constructs a Condition object.
*
......@@ -158,86 +163,127 @@ public function compile(Connection $connection, PlaceholderInterface $queryPlace
$conjunction = $conditions['#conjunction'];
unset($conditions['#conjunction']);
foreach ($conditions as $condition) {
if (empty($condition['operator'])) {
// This condition is a literal string, so let it through as is.
$condition_fragments[] = ' (' . $condition['field'] . ') ';
// Process field.
if ($condition['field'] instanceof ConditionInterface) {
// Left hand part is a structured condition or a subquery. Compile,
// put brackets around it (if it is a query), and collect any
// arguments.
$condition['field']->compile($connection, $queryPlaceholder);
$field_fragment = (string) $condition['field'];
if ($condition['field'] instanceof SelectInterface) {
$field_fragment = '(' . $field_fragment . ')';
}
$arguments += $condition['field']->arguments();
// If the operator and value were not passed in to the
// @see ConditionInterface::condition() method (and thus have the
// default value as defined over there) it is assumed to be a valid
// condition on its own: ignore the operator and value parts.
$ignore_operator = $condition['operator'] === '=' && $condition['value'] === NULL;
}
elseif (!isset($condition['operator'])) {
// Left hand part is a literal string added with the
// @see ConditionInterface::where() method. Put brackets around
// the snippet and collect the arguments from the value part.
// Also ignore the operator and value parts.
$field_fragment = '(' . $condition['field'] . ')';
$arguments += $condition['value'];
$ignore_operator = TRUE;
}
else {
// Left hand part is a normal field. Add it as is.
$field_fragment = $condition['field'];
$ignore_operator = FALSE;
}
// Process operator.
if ($ignore_operator) {
$operator = array('operator' => '', 'use_value' => FALSE);
}
else {
// It's a structured condition, so parse it out accordingly.
// Note that $condition['field'] will only be an object for a dependent
// DatabaseCondition object, not for a dependent subquery.
if ($condition['field'] instanceof ConditionInterface) {
// Compile the sub-condition recursively and add it to the list.
$condition['field']->compile($connection, $queryPlaceholder);
$condition_fragments[] = '(' . (string) $condition['field'] . ')';
$arguments += $condition['field']->arguments();
// Remove potentially dangerous characters.
// If something passed in an invalid character stop early, so we
// don't rely on a broken SQL statement when we would just replace
// those characters.
if (stripos($condition['operator'], 'UNION') !== FALSE || strpbrk($condition['operator'], '[-\'"();') !== FALSE) {
$this->changed = TRUE;
$this->arguments = [];
// Provide a string which will result into an empty query result.
$this->stringVersion = '( AND 1 = 0 )';
// Conceptually throwing an exception caused by user input is bad
// as you result into a WSOD, which depending on your webserver
// configuration can result into the assumption that your site is
// broken.
// On top of that the database API relies on __toString() which
// does not allow to throw exceptions.
trigger_error('Invalid characters in query operator: ' . $condition['operator'], E_USER_ERROR);
return;
}
else {
// For simplicity, we treat all operators as the same data structure.
// In the typical degenerate case, this won't get changed.
$operator_defaults = array(
'prefix' => '',
'postfix' => '',
'delimiter' => '',
'operator' => $condition['operator'],
'use_value' => TRUE,
);
// Remove potentially dangerous characters.
// If something passed in an invalid character stop early, so we
// don't rely on a broken SQL statement when we would just replace
// those characters.
if (stripos($condition['operator'], 'UNION') !== FALSE || strpbrk($condition['operator'], '[-\'"();') !== FALSE) {
$this->changed = TRUE;
$this->arguments = [];
// Provide a string which will result into an empty query result.
$this->stringVersion = '( AND 1 = 0 )';
// Conceptually throwing an exception caused by user input is bad
// as you result into a WSOD, which depending on your webserver
// configuration can result into the assumption that your site is
// broken.
// On top of that the database API relies on __toString() which
// does not allow to throw exceptions.
trigger_error('Invalid characters in query operator: ' . $condition['operator'], E_USER_ERROR);
return;
}
$operator = $connection->mapConditionOperator($condition['operator']);
if (!isset($operator)) {
$operator = $this->mapConditionOperator($condition['operator']);
}
$operator += $operator_defaults;
$placeholders = array();
if ($condition['value'] instanceof SelectInterface) {
$condition['value']->compile($connection, $queryPlaceholder);
$placeholders[] = (string) $condition['value'];
$arguments += $condition['value']->arguments();
// Subqueries are the actual value of the operator, we don't
// need to add another below.
$operator['use_value'] = FALSE;
// For simplicity, we convert all operators to a data structure to
// allow to specify a prefix, a delimiter and such. Find the
// associated data structure by first doing a database specific
// lookup, followed by a specification according to the SQL standard.
$operator = $connection->mapConditionOperator($condition['operator']);
if (!isset($operator)) {
$operator = $this->mapConditionOperator($condition['operator']);
}
$operator += array('operator' => $condition['operator']);
}
// Add defaults.
$operator += array(
'prefix' => '',
'postfix' => '',
'delimiter' => '',
'use_value' => TRUE,
);
$operator_fragment = $operator['operator'];
// Process value.
$value_fragment = '';
if ($operator['use_value']) {
// For simplicity, we first convert to an array, so that we can handle
// the single and multi value cases the same.
if (!is_array($condition['value'])) {
if ($condition['value'] instanceof SelectInterface && ($operator['operator'] === 'IN' || $operator['operator'] === 'NOT IN')) {
// Special case: IN is followed by a single select query instead
// of a set of values: unset prefix and postfix to prevent double
// brackets.
$operator['prefix'] = '';
$operator['postfix'] = '';
}
// We assume that if there is a delimiter, then the value is an
// array. If not, it is a scalar. For simplicity, we first convert
// up to an array so that we can build the placeholders in the same way.
elseif (!$operator['delimiter'] && !is_array($condition['value'])) {
$condition['value'] = array($condition['value']);
$condition['value'] = array($condition['value']);
}
// Process all individual values.
$value_fragment = [];
foreach ($condition['value'] as $value) {
if ($value instanceof SelectInterface) {
// Right hand part is a subquery. Compile, put brackets around it
// and collect any arguments.
$value->compile($connection, $queryPlaceholder);
$value_fragment[] = '(' . (string) $value . ')';
$arguments += $value->arguments();
}
if ($operator['use_value']) {
foreach ($condition['value'] as $value) {
$placeholder = ':db_condition_placeholder_' . $queryPlaceholder->nextPlaceholder();
$arguments[$placeholder] = $value;
$placeholders[] = $placeholder;
}
else {
// Right hand part is a normal value. Replace the value with a
// placeholder and add the value as an argument.
$placeholder = ':db_condition_placeholder_' . $queryPlaceholder->nextPlaceholder();
$value_fragment[] = $placeholder;
$arguments[$placeholder] = $value;
}
$condition_fragments[] = ' (' . $connection->escapeField($condition['field']) . ' ' . $operator['operator'] . ' ' . $operator['prefix'] . implode($operator['delimiter'], $placeholders) . $operator['postfix'] . ') ';
}
$value_fragment = $operator['prefix'] . implode($operator['delimiter'], $value_fragment) . $operator['postfix'];
}
// Concatenate the left hand part, operator and right hand part.
$condition_fragments[] = trim(implode(' ', array($field_fragment, $operator_fragment, $value_fragment)));
}
$this->changed = FALSE;
$this->stringVersion = implode($conjunction, $condition_fragments);
// Concatenate all conditions using the conjunction and brackets around
// the individual conditions to assure the proper evaluation order.
$this->stringVersion = count($condition_fragments) > 1 ? '(' . implode(") $conjunction (", $condition_fragments) . ')' : implode($condition_fragments);
$this->arguments = $arguments;
$this->changed = FALSE;
}
}
......@@ -289,7 +335,7 @@ function __clone() {
* the value data they pass in is not a simple value. This is a simple
* overridable lookup function.
*
* @param $operator
* @param string $operator
* The condition operator, such as "IN", "BETWEEN", etc. Case-sensitive.
*
* @return array
......@@ -301,15 +347,17 @@ protected function mapConditionOperator($operator) {
static $specials = array(
'BETWEEN' => array('delimiter' => ' AND '),
'NOT BETWEEN' => array('delimiter' => ' AND '),
'IN' => array('delimiter' => ', ', 'prefix' => ' (', 'postfix' => ')'),
'NOT IN' => array('delimiter' => ', ', 'prefix' => ' (', 'postfix' => ')'),
'EXISTS' => array('prefix' => ' (', 'postfix' => ')'),
'NOT EXISTS' => array('prefix' => ' (', 'postfix' => ')'),
'IN' => array('delimiter' => ', ', 'prefix' => '(', 'postfix' => ')'),
'NOT IN' => array('delimiter' => ', ', 'prefix' => '(', 'postfix' => ')'),
'IS NULL' => array('use_value' => FALSE),
'IS NOT NULL' => array('use_value' => FALSE),
// Use backslash for escaping wildcard characters.
'LIKE' => array('postfix' => " ESCAPE '\\\\'"),
'NOT LIKE' => array('postfix' => " ESCAPE '\\\\'"),
// Exists expects an already bracketed subquery as right hand part. Do
// not define additional brackets.
'EXISTS' => array(),
'NOT EXISTS' => array(),
// These ones are here for performance reasons.
'=' => array(),
'<' => array(),
......
......@@ -12,13 +12,21 @@ interface ConditionInterface {
/**
* Helper function: builds the most common conditional clauses.
*
* This method can take a variable number of parameters. If called with two
* parameters, they are taken as $field and $value with $operator having a
* value of =.
* This method takes 1 to 3 parameters.
*
* If called with 1 parameter, it should be a ConditionInterface that in
* itself forms a valid where clause. Use e.g. to build clauses with nested
* AND's and OR's.
*
* If called with 2 parameters, they are taken as $field and $value with
* $operator having a value of =.
*
* Do not use this method to test for NULL values. Instead, use
* QueryConditionInterface::isNull() or QueryConditionInterface::isNotNull().
*
* To improve readability, the operators EXISTS and NOT EXISTS have their own
* utility method defined.
*
* Drupal considers LIKE case insensitive and the following is often used
* to tell the database that case insensitive equivalence is desired:
* @code
......@@ -32,33 +40,43 @@ interface ConditionInterface {
* be case sensitive and when a case insensitive collation is used, the =
* operator will also be case insensitive.
*
* @param $field
* The name of the field to check. If you would like to add a more complex
* condition involving operators or functions, use where().
* @param $value
* The value to test the field against. In most cases, this is a scalar.
* For more complex options, it is an array. The meaning of each element in
* the array is dependent on the $operator.
* @param $operator
* The comparison operator, such as =, <, or >=. It also accepts more
* complex options such as IN, LIKE, LIKE BINARY, or BETWEEN. Defaults to =.
* @param string|\Drupal\Core\Database\Query\ConditionInterface $field
* The name of the field to check. This can also be QueryConditionInterface
* in itself. Use where() if you would like to add a more complex condition
* involving operators or functions, or an already compiled condition.
* @param string|array|\Drupal\Core\Database\Query\SelectInterface|null $value
* The value to test the field against. In most cases, and depending on the
* operator, this will be a scalar or an array. As SQL accepts select
* queries on any place where a scalar value or set is expected, $value may
* also be a(n array of) SelectInterface(s). If $operator is a unary
* operator, e.g. EXISTS, $value will be ignored and should be null.
* @param string|null $operator
* The operator to use. Supported for all supported databases are at least:
* - The comparison operators =, <>, <, <=, >, >=.
* - The operators (NOT) BETWEEN, (NOT) IN, (NOT) EXISTS, (NOT) LIKE.
* Other operators (e.g. LIke BINARY) may or may not work. Defaults to =.
*
* @return \Drupal\Core\Database\Query\ConditionInterface
* The called object.
*
* @see \Drupal\Core\Database\Query\ConditionInterface::isNull()
* @see \Drupal\Core\Database\Query\ConditionInterface::isNotNull()
* @see \Drupal\Core\Database\Query\ConditionInterface::exists()
* @see \Drupal\Core\Database\Query\ConditionInterface::notExist()
* @see \Drupal\Core\Database\Query\ConditionInterface::where()
*/
public function condition($field, $value = NULL, $operator = '=');
/**
* Adds an arbitrary WHERE clause to the query.
*
* @param $snippet
* @param string $snippet
* A portion of a WHERE clause as a prepared statement. It must use named
* placeholders, not ? placeholders.
* @param $args
* An associative array of arguments.
* placeholders, not ? placeholders. The caller is responsible for providing
* unique placeholders that do not interfere with the placeholders generated
* by this QueryConditionInterface object.
* @param array $args
* An associative array of arguments keyed by the named placeholders.
*
* @return \Drupal\Core\Database\Query\ConditionInterface
* The called object.
......@@ -68,8 +86,8 @@ public function where($snippet, $args = array());
/**
* Sets a condition that the specified field be NULL.
*
* @param $field
* The name of the field to check.
* @param string|\Drupal\Core\Database\Query\SelectInterface $field
* The name of the field or a subquery to check.
*
* @return \Drupal\Core\Database\Query\ConditionInterface
* The called object.
......@@ -79,8 +97,8 @@ public function isNull($field);
/**
* Sets a condition that the specified field be NOT NULL.
*
* @param $field
* The name of the field to check.
* @param string|\Drupal\Core\Database\Query\SelectInterface $field
* The name of the field or a subquery to check.
*
* @return \Drupal\Core\Database\Query\ConditionInterface
* The called object.
......@@ -110,7 +128,7 @@ public function exists(SelectInterface $select);
public function notExists(SelectInterface $select);
/**
* Gets a complete list of all conditions in this conditional clause.
* Gets the, possibly nested, list of conditions in this conditional clause.
*
* This method returns by reference. That allows alter hooks to access the
* data structure directly and manipulate it before it gets compiled.
......@@ -131,6 +149,9 @@ public function notExists(SelectInterface $select);
*
* There will also be a single array entry of #conjunction, which is the
* conjunction that will be applied to the array, such as AND.
*
* @return array
* The, possibly nested, list of all conditions (by reference).
*/
public function &conditions();
......
......@@ -105,7 +105,7 @@ function testPreviewUI() {
$this->assertText(t('Query execute time'));
$this->assertText(t('View render time'));
$this->assertRaw('<strong>Query</strong>');
$this->assertText("SELECT views_test_data.name AS views_test_data_name\nFROM \n{views_test_data} views_test_data\nWHERE (( (views_test_data.id = &#039;100&#039; ) ))");
$this->assertText("SELECT views_test_data.name AS views_test_data_name\nFROM \n{views_test_data} views_test_data\nWHERE (views_test_data.id = &#039;100&#039; )");
// Test that the statistics and query are rendered above the preview.
$this->assertTrue(strpos($this->getRawContent(), 'views-query-info') < strpos($this->getRawContent(), 'view-test-preview'), 'Statistics shown above the preview.');
......
......@@ -39,7 +39,7 @@ function testFromSubquerySelect() {
// WHERE tt.task = 'code'
$people = $select->execute()->fetchCol();
$this->assertEqual(count($people), 1, 'Returned the correct number of rows.');
$this->assertCount(1, $people, 'Returned the correct number of rows.');
}
}
......@@ -66,11 +66,11 @@ function testFromSubquerySelectWithLimit() {
// INNER JOIN test t ON t.id=tt.pid
$people = $select->execute()->fetchCol();
$this->assertEqual(count($people), 1, 'Returned the correct number of rows.');
$this->assertCount(1, $people, 'Returned the correct number of rows.');
}
/**
* Tests that we can use a subquery in a WHERE clause.
* Tests that we can use a subquery with an IN operator in a WHERE clause.
*/
function testConditionSubquerySelect() {
// Create a subquery, which is just a normal query object.
......@@ -89,7 +89,92 @@ function testConditionSubquerySelect() {
// FROM test tt2
// WHERE tt2.pid IN (SELECT tt.pid AS pid FROM test_task tt WHERE tt.priority=1)
$people = $select->execute()->fetchCol();
$this->assertEqual(count($people), 5, 'Returned the correct number of rows.');
$this->assertCount(5, $people, 'Returned the correct number of rows.');
}
/**
* Test that we can use a subquery with a relational operator in a WHERE clause.
*/
function testConditionSubquerySelect2() {
// Create a subquery, which is just a normal query object.
$subquery = db_select('test', 't2');
$subquery->addExpression('AVG(t2.age)');
// Create another query that adds a clause using the subquery.
$select = db_select('test', 't');
$select->addField('t', 'name');
$select->condition('t.age', $subquery, '<');
// The resulting query should be equivalent to:
// SELECT t.name
// FROM test t
// WHERE t.age < (SELECT AVG(t2.age) FROM test t2)
$people = $select->execute()->fetchCol();
$this->assertEquals(['John', 'Paul'], $people, 'Returned Paul and John.', 0.0, 10, TRUE);
}
/**
* Test that we can use 2 subqueries with a relational operator in a WHERE clause.
*/
function testConditionSubquerySelect3() {
// Create subquery 1, which is just a normal query object.
$subquery1 = db_select('test_task', 'tt');
$subquery1->addExpression('AVG(tt.priority)');
$subquery1->where('tt.pid = t.id');
// Create subquery 2, which is just a normal query object.
$subquery2 = db_select('test_task', 'tt2');
$subquery2->addExpression('AVG(tt2.priority)');
// Create another query that adds a clause using the subqueries.
$select = db_select('test', 't');
$select->addField('t', 'name');
$select->condition($subquery1, $subquery2, '>');
// The resulting query should be equivalent to:
// SELECT t.name
// FROM test t
// WHERE (SELECT AVG(tt.priority) FROM test_task tt WHERE tt.pid = t.id) > (SELECT AVG(tt2.priority) FROM test_task tt2)
$people = $select->execute()->fetchCol();
$this->assertEquals(['John'], $people, 'Returned John.', 0.0, 10, TRUE);
}
/**
* Test that we can use multiple subqueries.
*
* This test uses a subquery at the left hand side and multiple subqueries at
* the right hand side. The test query may not be that logical but that's due
* to the limited amount of data and tables. 'Valid' use cases do exist :)
*/
function testConditionSubquerySelect4() {
// Create subquery 1, which is just a normal query object.
$subquery1 = db_select('test_task', 'tt');
$subquery1->addExpression('AVG(tt.priority)');
$subquery1->where('tt.pid = t.id');
// Create subquery 2, which is just a normal query object.
$subquery2 = db_select('test_task', 'tt2');
$subquery2->addExpression('MIN(tt2.priority)');
$subquery2->where('tt2.pid <> t.id');
// Create subquery 3, which is just a normal query object.
$subquery3 = db_select('test_task', 'tt3');
$subquery3->addExpression('AVG(tt3.priority)');
$subquery3->where('tt3.pid <> t.id');
// Create another query that adds a clause using the subqueries.
$select = db_select('test', 't');
$select->addField('t', 'name');
$select->condition($subquery1, [$subquery2, $subquery3], 'BETWEEN');
// The resulting query should be equivalent to:
// SELECT t.name AS name
// FROM {test} t
// WHERE (SELECT AVG(tt.priority) AS expression FROM {test_task} tt WHERE (tt.pid = t.id))
// BETWEEN (SELECT MIN(tt2.priority) AS expression FROM {test_task} tt2 WHERE (tt2.pid <> t.id))
// AND (SELECT AVG(tt3.priority) AS expression FROM {test_task} tt3 WHERE (tt3.pid <> t.id));
$people = $select->execute()->fetchCol();
$this->assertEquals(['George', 'Paul'], $people, 'Returned George and Paul.', 0.0, 10, TRUE);
}
/**
......@@ -113,7 +198,7 @@ function testJoinSubquerySelect() {
// INNER JOIN (SELECT tt.pid AS pid FROM test_task tt WHERE priority=1) tt ON t.id=tt.pid
$people = $select->execute()->fetchCol();
$this->assertEqual(count($people), 2, 'Returned the correct number of rows.');
$this->assertCount(2, $people, 'Returned the correct number of rows.');
}
/**
......@@ -143,7 +228,7 @@ function testExistsSubquerySelect() {
// Ensure that we got the right record.
$record = $result->fetch();
$this->assertEqual($record->name, 'George', 'Fetched name is correct using EXISTS query.');
$this->assertEquals('George', $record->name, 'Fetched name is correct using EXISTS query.');
}
/**
......@@ -173,7 +258,7 @@ function testNotExistsSubquerySelect() {
// Ensure that we got the right number of records.
$people = $query->execute()->fetchCol();
$this->assertEqual(count($people), 3, 'NOT EXISTS query returned the correct results.');
$this->assertCount(3, $people, 'NOT EXISTS query returned the correct results.');
}
}
......@@ -39,7 +39,7 @@ public function testSimpleCondition() {
$condition->condition('name', ['value']);
$condition->compile($connection, $query_placeholder);
$this->assertEquals(' (name = :db_condition_placeholder_0) ', $condition->__toString());
$this->assertEquals('name = :db_condition_placeholder_0', $condition->__toString());
$this->assertEquals([':db_condition_placeholder_0' => 'value'], $condition->arguments());
}
......@@ -96,28 +96,28 @@ public function dataProviderTestCompileWithKnownOperators() {
// aren't directly supported by core, but instead need manual handling with
// prefix/suffix at the moment.
$data = [];
$data[] = [' (name = :db_condition_placeholder_0) ', 'name', 'value', '='];
$data[] = [' (name != :db_condition_placeholder_0) ', 'name', 'value', '!='];
$data[] = [' (name <> :db_condition_placeholder_0) ', 'name', 'value', '<>'];
$data[] = [' (name >= :db_condition_placeholder_0) ', 'name', 'value', '>='];
$data[] = [' (name > :db_condition_placeholder_0) ', 'name', 'value', '>'];
$data[] = [' (name <= :db_condition_placeholder_0) ', 'name', 'value', '<='];
$data[] = [' (name < :db_condition_placeholder_0) ', 'name', 'value', '<'];
// $data[] = [' ( GREATEST (1, 2, 3) ) ', '', [1, 2, 3], 'GREATEST'];
$data[] = [' (name IN (:db_condition_placeholder_0, :db_condition_placeholder_1, :db_condition_placeholder_2)) ', 'name', ['1', '2', '3'], 'IN'];
$data[] = [' (name NOT IN (:db_condition_placeholder_0, :db_condition_placeholder_1, :db_condition_placeholder_2)) ', 'name', ['1', '2', '3'], 'NOT IN'];
// $data[] = [' ( INTERVAL (1, 2, 3) ) ', '', [1, 2, 3], 'INTERVAL'];
$data[] = [' (name IS NULL ) ', 'name', NULL, 'IS NULL'];
$data[] = [' (name IS NOT NULL ) ', 'name', NULL, 'IS NOT NULL'];
$data[] = [' (name IS :db_condition_placeholder_0) ', 'name', 'TRUE', 'IS'];
// $data[] = [' ( LEAST (1, 2, 3) ) ', '', [1, 2, 3], 'LEAST'];
$data[] = [" (name LIKE :db_condition_placeholder_0 ESCAPE '\\\\') ", 'name', '%muh%', 'LIKE', [':db_condition_placeholder_0' => '%muh%']];
$data[] = [" (name NOT LIKE :db_condition_placeholder_0 ESCAPE '\\\\') ", 'name', '%muh%', 'NOT LIKE', [':db_condition_placeholder_0' => '%muh%']];
$data[] = [" (name BETWEEN :db_condition_placeholder_0 AND :db_condition_placeholder_1) ", 'name', [1, 2], 'BETWEEN', [':db_condition_placeholder_0' => 1, ':db_condition_placeholder_1' => 2]];
$data[] = [" (name NOT BETWEEN :db_condition_placeholder_0 AND :db_condition_placeholder_1) ", 'name', [1, 2], 'NOT BETWEEN', [':db_condition_placeholder_0' => 1, ':db_condition_placeholder_1' => 2]];
// $data[] = [' ( STRCMP (name, :db_condition_placeholder_0) ) ', '', ['test-string'], 'STRCMP', [':db_condition_placeholder_0' => 'test-string']];
// $data[] = [' (EXISTS ) ', '', NULL, 'EXISTS'];
// $data[] = [' (name NOT EXISTS ) ', 'name', NULL, 'NOT EXISTS'];
$data[] = ['name = :db_condition_placeholder_0', 'name', 'value', '='];
$data[] = ['name != :db_condition_placeholder_0', 'name', 'value', '!='];
$data[] = ['name <> :db_condition_placeholder_0', 'name', 'value', '<>'];
$data[] = ['name >= :db_condition_placeholder_0', 'name', 'value', '>='];
$data[] = ['name > :db_condition_placeholder_0', 'name', 'value', '>'];
$data[] = ['name <= :db_condition_placeholder_0', 'name', 'value', '<='];
$data[] = ['name < :db_condition_placeholder_0', 'name', 'value', '<'];
// $data[] = ['GREATEST (1, 2, 3)', '', [1, 2, 3], 'GREATEST'];
$data[] = ['name IN (:db_condition_placeholder_0, :db_condition_placeholder_1, :db_condition_placeholder_2)', 'name', ['1', '2', '3'], 'IN'];
$data[] = ['name NOT IN (:db_condition_placeholder_0, :db_condition_placeholder_1, :db_condition_placeholder_2)', 'name', ['1', '2', '3'], 'NOT IN'];
// $data[] = ['INTERVAL (1, 2, 3)', '', [1, 2, 3], 'INTERVAL'];
$data[] = ['name IS NULL', 'name', NULL, 'IS NULL'];
$data[] = ['name IS NOT NULL', 'name', NULL, 'IS NOT NULL'];
$data[] = ['name IS :db_condition_placeholder_0', 'name', 'TRUE', 'IS'];
// $data[] = ['LEAST (1, 2, 3)', '', [1, 2, 3], 'LEAST'];
$data[] = ["name LIKE :db_condition_placeholder_0 ESCAPE '\\\\'", 'name', '%muh%', 'LIKE', [':db_condition_placeholder_0' => '%muh%']];
$data[] = ["name NOT LIKE :db_condition_placeholder_0 ESCAPE '\\\\'", 'name', '%muh%', 'NOT LIKE', [':db_condition_placeholder_0' => '%muh%']];
$data[] = ["name BETWEEN :db_condition_placeholder_0 AND :db_condition_placeholder_1", 'name', [1, 2], 'BETWEEN', [':db_condition_placeholder_0' => 1, ':db_condition_placeholder_1' => 2]];
$data[] = ["name NOT BETWEEN :db_condition_placeholder_0 AND :db_condition_placeholder_1", 'name', [1, 2], 'NOT BETWEEN', [':db_condition_placeholder_0' => 1, ':db_condition_placeholder_1' => 2]];
// $data[] = ['STRCMP (name, :db_condition_placeholder_0)', '', ['test-string'], 'STRCMP', [':db_condition_placeholder_0' => 'test-string']];
// $data[] = ['EXISTS', '', NULL, 'EXISTS'];
// $data[] = ['name NOT EXISTS', 'name', NULL, 'NOT EXISTS'];
return $data;
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment