Skip to content

Commit

Permalink
Postgres ILIKE (#44)
Browse files Browse the repository at this point in the history
* Added support for using ILIKE instead of LIKE on Postgres, parsing logic so that LIKE is used instead of in for single value

* Apply fixes from StyleCI

* Minor

* Minor fix

* Readme update

Co-authored-by: Josip Milotić <josip.milotic@asseco-see.hr>
Co-authored-by: StyleCI Bot <bot@styleci.io>
  • Loading branch information
3 people authored Dec 9, 2022
1 parent f329faa commit 1e5c0b3
Show file tree
Hide file tree
Showing 6 changed files with 45 additions and 10 deletions.
24 changes: 20 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,22 @@ can have micro-operators on them as well (i.e. `"column": "=value;!value2;%value

Example:

```
{
"search": {
"first_name": "=foo1;foo2",
"last_name": "!=bar1;bar2"
}
}
```

Will perform a ``SELECT * FROM some_table WHERE first_name IN
('foo1', 'foo2') AND last_name NOT IN ('bar1', 'bar2')``.

In case you pass a single value for a column on string type, LIKE operator will be used
instead of IN. For Postgres databases, ILIKE is used instead of LIKE to support
case-insensitive search.

```
{
"search": {
Expand All @@ -97,8 +113,8 @@ Example:
}
```

Will perform a ``SELECT * FROM some_table WHERE first_name IN
('foo') AND last_name NOT IN ('bar')``.
Will perform a ``SELECT * FROM some_table WHERE first_name LIKE 'foo' AND
last_name NOT LIKE 'bar'``.

#### Micro operators

Expand All @@ -120,8 +136,8 @@ single column (order matters!):
}
```

Will perform a ``SELECT * FROM some_table WHERE first_name NOT IN
('foo') AND last_name LIKE 'bar%'``.
Will perform a ``SELECT * FROM some_table WHERE first_name NOT LIKE
'foo' AND last_name LIKE 'bar%'``.

Notice that here ``!value`` behaved the same as ``!=`` main operator. The difference
is that ``!=`` main operator negates the complete list of values, whereas the
Expand Down
11 changes: 9 additions & 2 deletions src/CategorizedValues.php
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ public function categorize()
if ($this->isNegated($value)) {
$value = $this->replaceNegation($value);

if ($this->hasWildCard($value)) {
if ($this->hasWildCard($value) || $this->isSingleStringValue()) {
$value = $this->replaceWildCard($value);
$this->notLike[] = $value;
continue;
Expand All @@ -71,7 +71,7 @@ public function categorize()
continue;
}

if ($this->hasWildCard($value)) {
if ($this->hasWildCard($value) || $this->isSingleStringValue()) {
$value = $this->replaceWildCard($value);
$this->andLike[] = $value;
continue;
Expand Down Expand Up @@ -116,4 +116,11 @@ protected function replaceNegation($value)
{
return preg_replace('~' . self::NOT . '~', '', $value, 1);
}

// Hack so that LIKE operator is used when a single value of string type is passed.
// Not happy with this solution, might need to refactor this later
protected function isSingleStringValue(): bool
{
return count($this->searchParser->values) == 1 && $this->searchParser->type == 'string';
}
}
12 changes: 12 additions & 0 deletions src/SearchCallbacks/AbstractCallback.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@
use Asseco\JsonQueryBuilder\Exceptions\JsonQueryBuilderException;
use Asseco\JsonQueryBuilder\SearchParser;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
use PDO;

abstract class AbstractCallback
{
Expand Down Expand Up @@ -153,4 +155,14 @@ protected function isDate(string $type): bool
{
return in_array($type, self::DATE_FIELDS);
}

//Hack to enable case-insensitive search when using PostgreSQL database
protected function getLikeOperator(): string
{
if (DB::connection()->getPDO()->getAttribute(PDO::ATTR_DRIVER_NAME) == 'pgsql') {
return 'ILIKE';
}

return 'LIKE';
}
}
4 changes: 2 additions & 2 deletions src/SearchCallbacks/Equals.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,11 @@ public static function operator(): string
public function execute(Builder $builder, string $column, CategorizedValues $values): void
{
foreach ($values->andLike as $andLike) {
$builder->where($column, 'LIKE', $andLike);
$builder->where($column, $this->getLikeOperator(), $andLike);
}

foreach ($values->notLike as $notLike) {
$builder->where($column, 'NOT LIKE', $notLike);
$builder->where($column, 'NOT ' . $this->getLikeOperator(), $notLike);
}

if ($values->null) {
Expand Down
2 changes: 1 addition & 1 deletion src/SearchCallbacks/NotEquals.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public function execute(Builder $builder, string $column, CategorizedValues $val
throw new Exception('Not operator is not supported for date(time) fields');
}

$builder->where($column, 'NOT LIKE', $like);
$builder->where($column, 'NOT ' . $this->getLikeOperator(), $like);
}

if ($values->null || $values->notNull) {
Expand Down
2 changes: 1 addition & 1 deletion src/SearchParser.php
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ protected function parseOperator($operators, string $argument): string
* Output: val1
* val2
*
* @param $values
* @param string $values
* @return array
*
* @throws JsonQueryBuilderException
Expand Down

0 comments on commit 1e5c0b3

Please sign in to comment.