Skip to content

Commit e9a535b

Browse files
committed
fix: various fixes around parameterized type data shape change
fixes #153
1 parent 918ce9b commit e9a535b

File tree

3 files changed

+29
-331
lines changed

3 files changed

+29
-331
lines changed

lib/sql_implementation.ex

Lines changed: 24 additions & 143 deletions
Original file line numberDiff line numberDiff line change
@@ -206,22 +206,20 @@ defmodule AshSqlite.SqlImplementation do
206206
def multicolumn_distinct?, do: false
207207

208208
@impl true
209-
def parameterized_type(type, constraints, no_maps? \\ false)
210-
211-
def parameterized_type({:parameterized, _, _} = type, _, _) do
209+
def parameterized_type({:parameterized, _} = type, _) do
212210
type
213211
end
214212

215-
def parameterized_type({:parameterized, _} = type, _, _) do
213+
def parameterized_type({:parameterized, _, _} = type, _) do
216214
type
217215
end
218216

219-
def parameterized_type({:in, type}, constraints, no_maps?) do
220-
parameterized_type({:array, type}, constraints, no_maps?)
217+
def parameterized_type({:in, type}, constraints) do
218+
parameterized_type({:array, type}, constraints)
221219
end
222220

223-
def parameterized_type({:array, type}, constraints, no_maps?) do
224-
case parameterized_type(type, constraints[:items] || [], no_maps?) do
221+
def parameterized_type({:array, type}, constraints) do
222+
case parameterized_type(type, constraints[:items] || []) do
225223
nil ->
226224
nil
227225

@@ -230,11 +228,15 @@ defmodule AshSqlite.SqlImplementation do
230228
end
231229
end
232230

233-
def parameterized_type(type, _constraints, _no_maps?)
231+
def parameterized_type({type, constraints}, []) do
232+
parameterized_type(type, constraints)
233+
end
234+
235+
def parameterized_type(type, _constraints)
234236
when type in [Ash.Type.Map, Ash.Type.Map.EctoType],
235237
do: nil
236238

237-
def parameterized_type(type, constraints, no_maps?) do
239+
def parameterized_type(type, constraints) do
238240
if Ash.Type.ash_type?(type) do
239241
cast_in_query? =
240242
if function_exported?(Ash.Type, :cast_in_query?, 2) do
@@ -244,7 +246,7 @@ defmodule AshSqlite.SqlImplementation do
244246
end
245247

246248
if cast_in_query? do
247-
parameterized_type(Ash.Type.ecto_type(type), constraints, no_maps?)
249+
parameterized_type(Ash.Type.ecto_type(type), constraints)
248250
else
249251
nil
250252
end
@@ -258,136 +260,22 @@ defmodule AshSqlite.SqlImplementation do
258260
end
259261

260262
@impl true
261-
def determine_types(mod, values) do
262-
Code.ensure_compiled(mod)
263-
264-
cond do
265-
:erlang.function_exported(mod, :types, 0) ->
266-
mod.types()
267-
268-
:erlang.function_exported(mod, :args, 0) ->
269-
mod.args()
270-
271-
true ->
272-
[:any]
273-
end
274-
|> Enum.map(fn types ->
275-
case types do
276-
:same ->
277-
types =
278-
for _ <- values do
279-
:same
280-
end
281-
282-
closest_fitting_type(types, values)
283-
284-
:any ->
285-
for _ <- values do
286-
:any
287-
end
288-
289-
types ->
290-
closest_fitting_type(types, values)
263+
def determine_types(mod, args, returns \\ nil) do
264+
returns =
265+
case returns do
266+
{:parameterized, _} -> nil
267+
{:array, {:parameterized, _}} -> nil
268+
{:array, {type, constraints}} when type != :array -> {type, [items: constraints]}
269+
{:array, _} -> nil
270+
{type, constraints} -> {type, constraints}
271+
other -> other
291272
end
292-
end)
293-
|> Enum.filter(fn types ->
294-
Enum.all?(types, &(vagueness(&1) == 0))
295-
end)
296-
|> case do
297-
[type] ->
298-
if type == :any || type == {:in, :any} do
299-
nil
300-
else
301-
type
302-
end
303-
304-
# There are things we could likely do here
305-
# We only say "we know what types these are" when we explicitly know
306-
_ ->
307-
Enum.map(values, fn _ -> nil end)
308-
end
309-
end
310-
311-
defp closest_fitting_type(types, values) do
312-
types_with_values = Enum.zip(types, values)
313-
314-
types_with_values
315-
|> fill_in_known_types()
316-
|> clarify_types()
317-
end
318-
319-
defp clarify_types(types) do
320-
basis =
321-
types
322-
|> Enum.map(&elem(&1, 0))
323-
|> Enum.min_by(&vagueness(&1))
324-
325-
Enum.map(types, fn {type, _value} ->
326-
replace_same(type, basis)
327-
end)
328-
end
329-
330-
defp replace_same({:in, type}, basis) do
331-
{:in, replace_same(type, basis)}
332-
end
333273

334-
defp replace_same(:same, :same) do
335-
:any
336-
end
337-
338-
defp replace_same(:same, {:in, :same}) do
339-
{:in, :any}
340-
end
341-
342-
defp replace_same(:same, basis) do
343-
basis
344-
end
345-
346-
defp replace_same(other, _basis) do
347-
other
348-
end
349-
350-
defp fill_in_known_types(types) do
351-
Enum.map(types, &fill_in_known_type/1)
352-
end
353-
354-
defp fill_in_known_type(
355-
{vague_type, %Ash.Query.Ref{attribute: %{type: type, constraints: constraints}}} = ref
356-
)
357-
when vague_type in [:any, :same] do
358-
if Ash.Type.ash_type?(type) do
359-
type = type |> parameterized_type(constraints, true) |> array_to_in()
360-
361-
{type || :any, ref}
362-
else
363-
type =
364-
if is_atom(type) && :erlang.function_exported(type, :type, 1) do
365-
parameterized_type(type, constraints, true) |> array_to_in()
366-
else
367-
type |> array_to_in()
368-
end
274+
{types, new_returns} = Ash.Expr.determine_types(mod, args, returns)
369275

370-
{type, ref}
371-
end
276+
{types, new_returns || returns}
372277
end
373278

374-
defp fill_in_known_type(
375-
{{:array, type}, %Ash.Query.Ref{attribute: %{type: {:array, type}} = attribute} = ref}
376-
) do
377-
{:in, fill_in_known_type({type, %{ref | attribute: %{attribute | type: type}}})}
378-
end
379-
380-
defp fill_in_known_type({type, value}), do: {array_to_in(type), value}
381-
382-
defp array_to_in({:array, v}), do: {:in, array_to_in(v)}
383-
384-
defp array_to_in(v), do: v
385-
386-
defp vagueness({:in, type}), do: vagueness(type)
387-
defp vagueness(:same), do: 2
388-
defp vagueness(:any), do: 1
389-
defp vagueness(_), do: 0
390-
391279
defp do_get_path(
392280
query,
393281
%Ash.Query.Function.GetPath{arguments: [left, right], embedded?: pred_embedded?},
@@ -438,13 +326,6 @@ defmodule AshSqlite.SqlImplementation do
438326
path
439327
|> Enum.reject(&is_integer/1)
440328
|> do_determine_type_at_path(type)
441-
|> case do
442-
nil ->
443-
nil
444-
445-
{type, constraints} ->
446-
AshSqlite.Types.parameterized_type(type, constraints)
447-
end
448329
end
449330

450331
defp do_determine_type_at_path([], _), do: nil

0 commit comments

Comments
 (0)