diff --git a/CHANGELOG.md b/CHANGELOG.md index 842b80e..6b1297b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,15 @@ See [Conventional Commits](Https://conventionalcommits.org) for commit guideline +## [v0.2.17](https://github.com/ash-project/ash_sql/compare/v0.2.16...v0.2.17) (2024-07-14) + + + + +### Improvements: + +* use `determine_types/3` in callback + ## [v0.2.16](https://github.com/ash-project/ash_sql/compare/v0.2.15...v0.2.16) (2024-07-14) diff --git a/README.md b/README.md index 2a5abf8..6d8334f 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ Shared functionality for ecto-based sql data layers. ```elixir def deps do [ - {:ash_sql, "~> 0.2.16"} + {:ash_sql, "~> 0.2.17"} ] end ``` diff --git a/lib/expr.ex b/lib/expr.ex index 3672aed..20eb68e 100644 --- a/lib/expr.ex +++ b/lib/expr.ex @@ -466,33 +466,26 @@ defmodule AshSql.Expr do acc, type ) do - [condition_type, when_true_type, when_false_type] = - case bindings.sql_behaviour.determine_types(If, [condition, when_true, when_false]) do - [condition_type, when_true] -> - [condition_type, when_true, nil] + {[condition_type, when_true_type, when_false_type], type} = + case determine_types(bindings.sql_behaviour, If, [condition, when_true, when_false], type) do + {[condition_type, when_true], type} -> + {[condition_type, when_true, when_true], type} - [condition_type, when_true, when_false] -> - [condition_type, when_true, when_false] + {[condition_type, when_true, when_false], type} -> + {[condition_type, when_true, when_false], type} - {[condition_type, when_true], _} -> - [condition_type, when_true, nil] + {[condition_type, nil, nil], type} -> + {[condition_type, type, type], type} - {[condition_type, when_true, when_false], _} -> - [condition_type, when_true, when_false] - end - |> case do - [condition_type, nil, nil] -> - [condition_type, type, type] - - [condition_type, when_true, nil] -> - [condition_type, when_true, type] + {[condition_type, when_true, nil], type} -> + {[condition_type, when_true, type], type} - [condition_type, nil, when_false] -> - [condition_type, type, when_false] + {[condition_type, nil, when_false], type} -> + {[condition_type, type, when_false], type} - [condition_type, when_true, when_false] -> - [condition_type, when_true, when_false] - end + {[condition_type, when_true, when_false], type} -> + {[condition_type, when_true, when_false], type} + end when_true_type = when_true_type || when_false_type || type when_false_type = when_false_type || when_true_type || type @@ -865,11 +858,7 @@ defmodule AshSql.Expr do acc, type ) do - [determined_type] = - case bindings.sql_behaviour.determine_types(Ash.Query.Function.Minus, [arg]) do - {v, _} -> v - v -> v - end + {[determined_type], type} = determine_types(bindings.sql_behaviour, Ash.Query.Function.Minus, [arg], type) {expr, acc} = do_dynamic_expr( @@ -902,13 +891,7 @@ defmodule AshSql.Expr do acc, type ) do - [left_type, right_type] = - mod - |> bindings.sql_behaviour.determine_types([left, right]) - |> case do - {v, _} -> v - v -> v - end + {[left_type, right_type], type} = determine_types(bindings.sql_behaviour, mod, [left, right], type) {left_expr, acc} = if left_type && operator in @cast_operands_for do @@ -2082,34 +2065,28 @@ defmodule AshSql.Expr do type, list_acc ) do - [condition_type, when_true_type, when_false_type] = - case bindings.sql_behaviour.determine_types(If, [condition, when_true, when_false]) do - [condition_type, when_true] -> - [condition_type, when_true, nil] + {[condition_type, when_true_type, when_false_type], type} = + case determine_types(bindings.sql_behaviour, If, [condition, when_true, when_false], type) do + {[condition_type, when_true], type} -> + {[condition_type, when_true, when_true], type} - [condition_type, when_true, when_false] -> - [condition_type, when_true, when_false] + {[condition_type, when_true, when_false], type} -> + {[condition_type, when_true, when_false], type} - {[condition_type, when_true], _} -> - [condition_type, when_true, nil] - - {[condition_type, when_true, when_false], _} -> - [condition_type, when_true, when_false] - end - |> case do - [condition_type, nil, nil] -> - [condition_type, type, type] + {[condition_type, nil, nil], type} -> + {[condition_type, type, type], type} - [condition_type, when_true, nil] -> - [condition_type, when_true, type] + {[condition_type, when_true, nil], type} -> + {[condition_type, when_true, type], type} - [condition_type, nil, when_false] -> - [condition_type, type, when_false] + {[condition_type, nil, when_false], type} -> + {[condition_type, type, when_false], type} - [condition_type, when_true, when_false] -> - [condition_type, when_true, when_false] + {[condition_type, when_true, when_false], type} -> + {[condition_type, when_true, when_false], type} end + {condition, acc} = do_dynamic_expr( query, @@ -2413,6 +2390,12 @@ defmodule AshSql.Expr do {:parameterized, {AshSql.Type.CiString, _}} -> require_extension!(resource, extension, context, query) + {:parameterized, {AshPostgres.Type.CiStringWrapper.EctoType, _}} -> + require_extension!(resource, extension, context, query) + + {:parameterized, AshPostgres.Type.CiStringWrapper.EctoType, _} -> + require_extension!(resource, extension, context, query) + :ci_string -> require_extension!(resource, extension, context, query) @@ -2677,4 +2660,14 @@ defmodule AshSql.Expr do defp escape_contains(text) do "%" <> String.replace(text, ~r/([\%_])/u, "\\\\\\0") <> "%" end + + defp determine_types(sql_behaviour, mod, args, returns) do + {types, new_returns} = + if function_exported?(sql_behaviour, :determine_types, 3) do + sql_behaviour.determine_types(mod, args, returns) + else + sql_behaviour.determine_types(mod, args) + end + {types, new_returns || returns} + end end diff --git a/lib/implementation.ex b/lib/implementation.ex index ce41f07..7498bb6 100644 --- a/lib/implementation.ex +++ b/lib/implementation.ex @@ -25,6 +25,7 @@ defmodule AshSql.Implementation do @callback ilike?() :: boolean() @callback determine_types(module, list(term)) :: list(term) + @callback determine_types(module, list(term), returns :: term) :: list(term) @callback list_aggregate(Ash.Resource.t()) :: String.t() | nil @@ -38,6 +39,8 @@ defmodule AshSql.Implementation do @callback strpos_function() :: String.t() @callback type_expr(expr :: term, type :: term) :: term + @optional_callbacks determine_types: 3 + defmacro __using__(_) do quote do @behaviour AshSql.Implementation diff --git a/mix.exs b/mix.exs index 1f0bc14..9dff44b 100644 --- a/mix.exs +++ b/mix.exs @@ -6,7 +6,7 @@ defmodule AshSql.MixProject do Shared utilities for ecto-based sql data layers. """ - @version "0.2.16" + @version "0.2.17" def project do [ @@ -69,7 +69,7 @@ defmodule AshSql.MixProject do # Run "mix help deps" to learn about dependencies. defp deps do [ - {:ash, "~> 3.0 and >= 3.1.5"}, + {:ash, "~> 3.0 and >= 3.1.7"}, {:ecto_sql, "~> 3.9"}, {:ecto, "~> 3.9"}, # dev/test dependencies diff --git a/mix.lock b/mix.lock index 291f15b..82c9441 100644 --- a/mix.lock +++ b/mix.lock @@ -1,5 +1,5 @@ %{ - "ash": {:hex, :ash, "3.1.5", "2e9b3c54ce5d52661e51ae76cf1648aa47a41876749025760267ca57e153c6ef", [:mix], [{:comparable, "~> 1.0", [hex: :comparable, repo: "hexpm", optional: false]}, {:decimal, "~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:ecto, "~> 3.7", [hex: :ecto, repo: "hexpm", optional: false]}, {:ets, "~> 0.8", [hex: :ets, repo: "hexpm", optional: false]}, {:igniter, "~> 0.2.12", [hex: :igniter, repo: "hexpm", optional: false]}, {:jason, ">= 1.0.0", [hex: :jason, repo: "hexpm", optional: false]}, {:picosat_elixir, "~> 0.2", [hex: :picosat_elixir, repo: "hexpm", optional: true]}, {:plug, ">= 0.0.0", [hex: :plug, repo: "hexpm", optional: true]}, {:reactor, ">= 0.8.1 and < 1.0.0-0", [hex: :reactor, repo: "hexpm", optional: false]}, {:simple_sat, ">= 0.1.1 and < 1.0.0-0", [hex: :simple_sat, repo: "hexpm", optional: true]}, {:spark, ">= 2.2.7 and < 3.0.0-0", [hex: :spark, repo: "hexpm", optional: false]}, {:splode, "~> 0.2", [hex: :splode, repo: "hexpm", optional: false]}, {:stream_data, "~> 1.0", [hex: :stream_data, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.1", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "9f43e066e0b478343091242c133d7a32b22f9f9be111d1bc950f76f1609c83e3"}, + "ash": {:hex, :ash, "3.1.7", "99e50347e70dd6fa62c9afa5246ef83e363bb7c0236b2081d7b7f35b6095c099", [:mix], [{:comparable, "~> 1.0", [hex: :comparable, repo: "hexpm", optional: false]}, {:decimal, "~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:ecto, "~> 3.7", [hex: :ecto, repo: "hexpm", optional: false]}, {:ets, "~> 0.8", [hex: :ets, repo: "hexpm", optional: false]}, {:igniter, "~> 0.2.12", [hex: :igniter, repo: "hexpm", optional: false]}, {:jason, ">= 1.0.0", [hex: :jason, repo: "hexpm", optional: false]}, {:picosat_elixir, "~> 0.2", [hex: :picosat_elixir, repo: "hexpm", optional: true]}, {:plug, ">= 0.0.0", [hex: :plug, repo: "hexpm", optional: true]}, {:reactor, ">= 0.8.1 and < 1.0.0-0", [hex: :reactor, repo: "hexpm", optional: false]}, {:simple_sat, ">= 0.1.1 and < 1.0.0-0", [hex: :simple_sat, repo: "hexpm", optional: true]}, {:spark, ">= 2.2.7 and < 3.0.0-0", [hex: :spark, repo: "hexpm", optional: false]}, {:splode, "~> 0.2", [hex: :splode, repo: "hexpm", optional: false]}, {:stream_data, "~> 1.0", [hex: :stream_data, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.1", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "c16b5a8c9dc5bd081b61e76e97abff6f61fbf7f0f34955901755644dcd7519ce"}, "benchee": {:hex, :benchee, "1.3.1", "c786e6a76321121a44229dde3988fc772bca73ea75170a73fd5f4ddf1af95ccf", [:mix], [{:deep_merge, "~> 1.0", [hex: :deep_merge, repo: "hexpm", optional: false]}, {:statistex, "~> 1.0", [hex: :statistex, repo: "hexpm", optional: false]}, {:table, "~> 0.1.0", [hex: :table, repo: "hexpm", optional: true]}], "hexpm", "76224c58ea1d0391c8309a8ecbfe27d71062878f59bd41a390266bf4ac1cc56d"}, "bunt": {:hex, :bunt, "1.0.0", "081c2c665f086849e6d57900292b3a161727ab40431219529f13c4ddcf3e7a44", [:mix], [], "hexpm", "dc5f86aa08a5f6fa6b8096f0735c4e76d54ae5c9fa2c143e5a1fc7c1cd9bb6b5"}, "castore": {:hex, :castore, "1.0.8", "dedcf20ea746694647f883590b82d9e96014057aff1d44d03ec90f36a5c0dc6e", [:mix], [], "hexpm", "0b2b66d2ee742cb1d9cb8c8be3b43c3a70ee8651f37b75a8b982e036752983f1"},