Skip to content

Commit

Permalink
New "starts with" & "contains" query operators (#3803)
Browse files Browse the repository at this point in the history
  • Loading branch information
dafeder authored Jul 11, 2022
1 parent 2588d7e commit 69090f0
Show file tree
Hide file tree
Showing 4 changed files with 161 additions and 6 deletions.
24 changes: 21 additions & 3 deletions modules/common/src/Storage/SelectFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -253,15 +253,33 @@ private function setQueryConditions(Query $query) {
* A condition from the DKAN query object.
*/
private function addCondition($statementObj, $condition) {
if (!isset($condition->operator)) {
$condition->operator = '=';
}
$this->normalizeOperator($condition);
$field = (isset($condition->collection) ? $condition->collection : $this->alias)
. '.'
. $condition->property;
$statementObj->condition($field, $condition->value, strtoupper($condition->operator));
}

/**
* Fix any quirks in DKAN query object that won't translate well to SQL.
*
* @param object $condition
* A condition from the DKAN query object.
*/
private function normalizeOperator($condition) {
if (!isset($condition->operator)) {
$condition->operator = '=';
}
elseif ($condition->operator == 'contains') {
$condition->operator = 'like';
$condition->value = "%{$condition->value}%";
}
elseif ($condition->operator == 'starts with') {
$condition->operator = 'like';
$condition->value = "{$condition->value}%";
}
}

/**
* Add a condition group to the database query.
*
Expand Down
120 changes: 120 additions & 0 deletions modules/common/tests/src/Unit/Storage/QueryDataProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ class QueryDataProvider {
const QUERY_OBJECT = 1;
const SQL = 2;
const EXCEPTION = 3;
const VALUES = 4;

/**
*
Expand All @@ -34,6 +35,8 @@ public function getAllData($return): array {
'badExpressionOperandQuery',
'conditionQuery',
'likeConditionQuery',
'containsConditionQuery',
'startsWithConditionQuery',
'arrayConditionQuery',
'nestedConditionGroupQuery',
'sortQuery',
Expand All @@ -51,6 +54,7 @@ public function getAllData($return): array {
self::$test(self::QUERY_OBJECT),
self::$test(self::SQL),
self::$test(self::EXCEPTION),
self::$test(self::VALUES),
];
}
return $data;
Expand All @@ -70,6 +74,9 @@ public static function noPropertiesQuery($return) {

case self::EXCEPTION:
return '';

case self::VALUES:
return [];
}
}

Expand All @@ -88,6 +95,10 @@ public static function propertiesQuery($return) {

case self::EXCEPTION:
return '';

case self::VALUES:
return [];

}
}

Expand All @@ -106,6 +117,9 @@ public static function badPropertyQuery($return) {

case self::EXCEPTION:
return "Bad query property";

case self::VALUES:
return [];
}
}

Expand All @@ -124,6 +138,9 @@ public static function unsafePropertyQuery($return) {

case self::EXCEPTION:
return "Unsafe property name: l.field3";

case self::VALUES:
return [];
}
}

Expand Down Expand Up @@ -175,6 +192,9 @@ public static function expressionQuery($return) {

case self::EXCEPTION:
return '';

case self::VALUES:
return [];
}
}

Expand Down Expand Up @@ -214,6 +234,9 @@ public static function nestedExpressionQuery($return) {

case self::EXCEPTION:
return '';

case self::VALUES:
return [];
}
}

Expand All @@ -240,6 +263,9 @@ public static function badExpressionOperandQuery($return) {

case self::EXCEPTION:
return "Only basic arithmetic expressions and basic SQL functions currently supported.";

case self::VALUES:
return [];
}
}

Expand All @@ -264,6 +290,9 @@ public static function conditionQuery($return) {

case self::EXCEPTION:
return '';

case self::VALUES:
return ['value'];
}
}

Expand All @@ -289,9 +318,68 @@ public static function likeConditionQuery($return) {

case self::EXCEPTION:
return '';

case self::VALUES:
return ['%value%'];
}

}


/**
*
*/
public static function containsConditionQuery($return) {
switch ($return) {
case self::QUERY_OBJECT:
$query = new Query();
$query->conditions = [
(object) [
"collection" => "t",
"property" => "field1",
"value" => "value",
"operator" => "contains",
],
];
return $query;

case self::SQL:
return "WHERE t.field1 LIKE :db_condition_placeholder_0";

case self::EXCEPTION:
return '';

case self::VALUES:
return ['%value%'];
}
}

public static function startsWithConditionQuery($return) {
switch ($return) {
case self::QUERY_OBJECT:
$query = new Query();
$query->conditions = [
(object) [
"collection" => "t",
"property" => "field1",
"value" => "value",
"operator" => "starts with",
],
];
return $query;

case self::SQL:
return "WHERE t.field1 LIKE :db_condition_placeholder_0";

case self::EXCEPTION:
return '';

case self::VALUES:
return ['value%'];
}
}


/**
*
*/
Expand All @@ -314,7 +402,11 @@ public static function arrayConditionQuery($return) {

case self::EXCEPTION:
return '';

case self::VALUES:
return [1, 5];
}

}

/**
Expand Down Expand Up @@ -359,7 +451,11 @@ public static function nestedConditionGroupQuery($return) {

case self::EXCEPTION:
return '';

case self::VALUES:
return ['value1', 'value2', 'value3'];
}

}

/**
Expand Down Expand Up @@ -393,6 +489,9 @@ public static function sortQuery($return) {

case self::EXCEPTION:
return '';

case self::VALUES:
return [];
}
}

Expand All @@ -411,6 +510,9 @@ public static function badSortQuery($return) {

case self::EXCEPTION:
return "Invalid sort.";

case self::VALUES:
return [];
}
}

Expand All @@ -429,6 +531,9 @@ public static function offsetQuery($return) {

case self::EXCEPTION:
return '';

case self::VALUES:
return [];
}
}

Expand All @@ -448,6 +553,9 @@ public static function limitOffsetQuery($return) {

case self::EXCEPTION:
return '';

case self::VALUES:
return [];
}
}

Expand Down Expand Up @@ -479,6 +587,9 @@ public static function joinsQuery($return) {

case self::EXCEPTION:
return '';

case self::VALUES:
return [];
}
}

Expand Down Expand Up @@ -517,6 +628,9 @@ public static function joinWithPropertiesFromBothQuery($return) {

case self::EXCEPTION:
return '';

case self::VALUES:
return [];
}
}

Expand All @@ -535,6 +649,9 @@ public static function countQuery($return) {

case self::EXCEPTION:
return '';

case self::VALUES:
return [];
}
}

Expand Down Expand Up @@ -584,6 +701,9 @@ public static function groupByQuery(int $returnType) {

case self::EXCEPTION:
return '';

case self::VALUES:
return ['value'];
}

throw new \UnexpectedValueException('Unknown return type provided.');
Expand Down
6 changes: 5 additions & 1 deletion modules/common/tests/src/Unit/Storage/SelectFactoryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,18 @@ class SelectFactoryTest extends TestCase {
*
* @dataProvider \Drupal\Tests\common\Unit\Storage\QueryDataProvider::getAllData()
*/
public function testQuery(Query $query, string $sql, string $message) {
public function testQuery(Query $query, string $sql, string $message, array $values = []) {
if ($message) {
$this->expectExceptionMessage($message);
$this->selectFactory->create($query);
}
else {
$db_query = $this->selectFactory->create($query);
$this->assertStringContainsString($sql, $this->selectToString($db_query));

if (!empty($values)) {
$this->assertEquals($values, array_values($db_query->arguments()));
}
}
}

Expand Down
17 changes: 15 additions & 2 deletions modules/datastore/docs/query.json
Original file line number Diff line number Diff line change
Expand Up @@ -194,8 +194,21 @@
"operator": {
"type": "string",
"description": "Condition operator",
"enum": [ "=", "<>", "<", "<=", ">", ">=", "like", "between", "in", "not in" ],
"default": "="
"enum": [
"=",
"<>",
"<",
"<=",
">",
">=",
"like",
"between",
"in",
"not in",
"contains",
"starts with"
],
"default": "="
}
},
"required": [ "property", "value" ]
Expand Down

0 comments on commit 69090f0

Please sign in to comment.