improvement: add like and ilike

This commit is contained in:
Zach Daniel 2022-12-21 16:12:49 -05:00
parent 5a9abdc69c
commit 09b19c8bfd
5 changed files with 94 additions and 2 deletions

View file

@ -625,7 +625,11 @@ defmodule AshPostgres.DataLayer do
def functions(resource) do
config = AshPostgres.DataLayer.Info.repo(resource).config()
functions = [AshPostgres.Functions.Fragment]
functions = [
AshPostgres.Functions.Fragment,
AshPostgres.Functions.Like,
AshPostgres.Functions.ILike
]
if "pg_trgm" in (config[:installed_extensions] || []) do
functions ++

View file

@ -5,7 +5,7 @@ defmodule AshPostgres.Expr do
alias Ash.Query.{BooleanExpression, Exists, Not, Ref}
alias Ash.Query.Operator.IsNil
alias Ash.Query.Function.{Ago, Contains, GetPath, If, Length, Now, Type}
alias AshPostgres.Functions.{Fragment, TrigramSimilarity}
alias AshPostgres.Functions.{Fragment, ILike, Like, TrigramSimilarity}
require Ecto.Query
@ -51,6 +51,34 @@ defmodule AshPostgres.Expr do
|> maybe_type(type, query)
end
defp do_dynamic_expr(
query,
%Like{arguments: [arg1, arg2], embedded?: pred_embedded?},
bindings,
embedded?,
type
) do
arg1 = do_dynamic_expr(query, arg1, bindings, pred_embedded? || embedded?)
arg2 = do_dynamic_expr(query, arg2, bindings, pred_embedded? || embedded?)
Ecto.Query.dynamic(like(^arg1, ^arg2))
|> maybe_type(type, query)
end
defp do_dynamic_expr(
query,
%ILike{arguments: [arg1, arg2], embedded?: pred_embedded?},
bindings,
embedded?,
type
) do
arg1 = do_dynamic_expr(query, arg1, bindings, pred_embedded? || embedded?)
arg2 = do_dynamic_expr(query, arg2, bindings, pred_embedded? || embedded?)
Ecto.Query.dynamic(ilike(^arg1, ^arg2))
|> maybe_type(type, query)
end
defp do_dynamic_expr(
query,
%IsNil{left: left, right: right, embedded?: pred_embedded?},

9
lib/functions/ilike.ex Normal file
View file

@ -0,0 +1,9 @@
defmodule AshPostgres.Functions.ILike do
@moduledoc """
Maps to the builtin postgres function `ilike`.
"""
use Ash.Query.Function, name: :ilike
def args, do: [[:string, :string]]
end

9
lib/functions/like.ex Normal file
View file

@ -0,0 +1,9 @@
defmodule AshPostgres.Functions.Like do
@moduledoc """
Maps to the builtin postgres function `like`.
"""
use Ash.Query.Function, name: :like
def args, do: [[:string, :string]]
end

View file

@ -773,6 +773,48 @@ defmodule AshPostgres.FilterTest do
end
end
describe "like and ilike" do
test "like builds and matches" do
Post
|> Ash.Changeset.new(%{title: "MaTcH"})
|> Api.create!()
results =
Post
|> Ash.Query.filter(like(title, "%aTc%"))
|> Api.read!()
assert [%Post{title: "MaTcH"}] = results
results =
Post
|> Ash.Query.filter(like(title, "%atc%"))
|> Api.read!()
assert [] = results
end
test "ilike builds and matches" do
Post
|> Ash.Changeset.new(%{title: "MaTcH"})
|> Api.create!()
results =
Post
|> Ash.Query.filter(ilike(title, "%aTc%"))
|> Api.read!()
assert [%Post{title: "MaTcH"}] = results
results =
Post
|> Ash.Query.filter(ilike(title, "%atc%"))
|> Api.read!()
assert [%Post{title: "MaTcH"}] = results
end
end
describe "trigram_similarity" do
test "it works on matches" do
Post