improvement: support string_length and string_trim

This commit is contained in:
Zach Daniel 2023-12-21 19:52:29 -05:00
parent 9ca9272426
commit 9bc5b2af9f
4 changed files with 67 additions and 60 deletions

View file

@ -19,7 +19,9 @@ defmodule AshPostgres.Expr do
Length,
Now,
StringJoin,
StringLength,
StringSplit,
StringTrim,
Today,
Type
}
@ -564,6 +566,52 @@ defmodule AshPostgres.Expr do
)
end
defp do_dynamic_expr(
query,
%StringLength{arguments: [value], embedded?: pred_embedded?},
bindings,
embedded?,
acc,
type
) do
do_dynamic_expr(
query,
%Fragment{
embedded?: pred_embedded?,
arguments: [raw: "length(", expr: value, raw: ")"]
},
bindings,
embedded?,
acc,
type
)
end
defp do_dynamic_expr(
query,
%StringTrim{arguments: [value], embedded?: pred_embedded?},
bindings,
embedded?,
acc,
type
) do
do_dynamic_expr(
query,
%Fragment{
embedded?: pred_embedded?,
arguments: [
raw: "REGEXP_REPLACE(REGEXP_REPLACE(",
expr: value,
raw: ", '\s+$', ''), '^\s+', '')"
]
},
bindings,
embedded?,
acc,
type
)
end
# Sorry :(
# This is bad to do, but is the only reasonable way I could find.
defp do_dynamic_expr(

View file

@ -204,7 +204,7 @@ defmodule AshPostgres.MixProject do
{:ecto, "~> 3.9"},
{:jason, "~> 1.0"},
{:postgrex, ">= 0.0.0"},
{:ash, ash_version("~> 2.17 and >= 2.17.13")},
{:ash, ash_version("~> 2.17 and >= 2.17.14")},
{:benchee, "~> 1.1", only: [:dev, :test]},
{:git_ops, "~> 2.5", only: [:dev, :test]},
{:ex_doc, github: "elixir-lang/ex_doc", only: [:dev, :test], runtime: false},

View file

@ -1,5 +1,5 @@
%{
"ash": {:hex, :ash, "2.17.14", "ccb68a0eacd7d4f4652a01baa3ceda510d793ab769c82958d644638905f08f7d", [:mix], [{:comparable, "~> 1.0", [hex: :comparable, repo: "hexpm", optional: false]}, {:decimal, "~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:earmark, "~> 1.4", [hex: :earmark, repo: "hexpm", optional: false]}, {:ecto, "~> 3.7", [hex: :ecto, repo: "hexpm", optional: false]}, {:ets, "~> 0.8", [hex: :ets, repo: "hexpm", optional: false]}, {:jason, ">= 1.0.0", [hex: :jason, repo: "hexpm", optional: false]}, {:picosat_elixir, "~> 0.2", [hex: :picosat_elixir, repo: "hexpm", optional: false]}, {:plug, ">= 0.0.0", [hex: :plug, repo: "hexpm", optional: true]}, {:spark, ">= 1.1.50 and < 2.0.0-0", [hex: :spark, repo: "hexpm", optional: false]}, {:stream_data, "~> 0.6", [hex: :stream_data, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.1", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "b09a585924f222a1d353ebd13ec8691c4b9c5e37a8be271ee8960c34feb3fad0"},
"ash": {:hex, :ash, "2.17.15", "5a71025ad4878c0522408032e5f6253b43dee19de50d0ef23ff57555f05ea646", [:mix], [{:comparable, "~> 1.0", [hex: :comparable, repo: "hexpm", optional: false]}, {:decimal, "~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:earmark, "~> 1.4", [hex: :earmark, repo: "hexpm", optional: false]}, {:ecto, "~> 3.7", [hex: :ecto, repo: "hexpm", optional: false]}, {:ets, "~> 0.8", [hex: :ets, repo: "hexpm", optional: false]}, {:jason, ">= 1.0.0", [hex: :jason, repo: "hexpm", optional: false]}, {:picosat_elixir, "~> 0.2", [hex: :picosat_elixir, repo: "hexpm", optional: false]}, {:plug, ">= 0.0.0", [hex: :plug, repo: "hexpm", optional: true]}, {:spark, ">= 1.1.50 and < 2.0.0-0", [hex: :spark, repo: "hexpm", optional: false]}, {:stream_data, "~> 0.6", [hex: :stream_data, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.1", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "44082e414ee43dc2c15f31ec26121a626855587413eee2f5325e5e783a04f59b"},
"benchee": {:hex, :benchee, "1.1.0", "f3a43817209a92a1fade36ef36b86e1052627fd8934a8b937ac9ab3a76c43062", [:mix], [{:deep_merge, "~> 1.0", [hex: :deep_merge, repo: "hexpm", optional: false]}, {:statistex, "~> 1.0", [hex: :statistex, repo: "hexpm", optional: false]}], "hexpm", "7da57d545003165a012b587077f6ba90b89210fd88074ce3c60ce239eb5e6d93"},
"bunt": {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38", [:mix], [], "hexpm", "7af5c7e09fe1d40f76c8e4f9dd2be7cebd83909f31fee7cd0e9eadc567da8353"},
"certifi": {:hex, :certifi, "2.9.0", "6f2a475689dd47f19fb74334859d460a2dc4e3252a3324bd2111b8f0429e7e21", [:rebar3], [], "hexpm", "266da46bdb06d6c6d35fde799bcb28d36d985d424ad7c08b5bb48f5b5cdd4641"},

View file

@ -618,63 +618,22 @@ defmodule AshPostgres.CalculationTest do
|> Enum.map(&Map.get(&1, :calc_returning_json))
end
# test "calculation passes actor to aggregate from calculation on aggregate" do
# org =
# Organization
# |> Ash.Changeset.new(%{name: "The Org"})
# |> Api.create!()
test "string_length and string_trim work" do
Author
|> Ash.Changeset.for_create(:create, %{
first_name: "Bill",
last_name: "Jones",
bio: %{title: "Mr.", bio: "Bones"}
})
|> Api.create!()
# user =
# User
# |> Ash.Changeset.for_create(:create, %{is_active: true})
# |> Ash.Changeset.manage_relationship(:organization, org, type: :append_and_remove)
# |> Api.create!()
# profile =
# Profile
# |> Ash.Changeset.for_create(:create, %{description: "Prolific describer of worlds..."})
# |> Api.create!()
# author =
# Author
# |> Ash.Changeset.for_create(:create, %{
# first_name: "Foo",
# bio: %{title: "Mr.", bio: "Bones"}
# })
# |> Ash.Changeset.manage_relationship(:profile, profile, type: :append)
# |> Api.create!()
# created_post =
# Post
# |> Ash.Changeset.new(%{title: "match"})
# |> Ash.Changeset.manage_relationship(:organization, org, type: :append_and_remove)
# |> Ash.Changeset.manage_relationship(:author, author, type: :append_and_remove)
# |> Api.create!()
# can_get_author_description_post =
# Post
# |> Ash.Query.filter(id == ^created_post.id)
# |> Ash.Query.load(author: :description)
# |> Api.read_one!(actor: user)
# assert can_get_author_description_post.author.description == "Prolific describer of worlds..."
# can_get_author_description_from_aggregate_post =
# Post
# |> Ash.Query.filter(id == ^created_post.id)
# |> Ash.Query.load(:author_profile_description)
# |> Api.read_one!(actor: user)
# assert can_get_author_description_from_aggregate_post.author_profile_description ==
# "Prolific describer of worlds..."
# can_get_author_description_from_calculation_of_aggregate_post =
# Post
# |> Ash.Query.filter(id == ^created_post.id)
# |> Ash.Query.load(:author_profile_description_from_agg)
# |> Api.read_one!(actor: user)
# assert can_get_author_description_from_calculation_of_aggregate_post.author_profile_description_from_agg ==
# "Prolific describer of worlds..."
# end
assert %{calculations: %{length: 9}} =
Author
|> Ash.Query.calculate(
:length,
expr(string_length(string_trim(first_name <> last_name <> " "))),
:integer
)
|> Api.read_one!()
end
end