Packages
ash_sql
0.2.2
0.6.5
0.6.4
0.6.3
0.6.2
0.6.1
0.6.0
0.5.5
0.5.4
0.5.3
0.5.2
0.5.1
0.5.0
0.4.5
0.4.4
0.4.3
0.4.2
0.4.1
0.4.0
0.3.16
0.3.15
0.3.14
0.3.13
0.3.12
0.3.11
0.3.10
0.3.9
0.3.8
0.3.7
0.3.6
0.3.5
0.3.4
0.3.3
0.3.2
0.3.1
0.3.0
0.2.93
0.2.92
0.2.91
0.2.90
0.2.89
0.2.88
0.2.87
0.2.86
0.2.85
0.2.84
0.2.83
0.2.82
0.2.81
0.2.80
0.2.79
0.2.78
0.2.77
0.2.76
0.2.75
0.2.74
0.2.73
0.2.72
0.2.71
0.2.70
0.2.69
0.2.68
0.2.67
0.2.66
0.2.65
0.2.64
0.2.63
0.2.62
0.2.61
0.2.60
0.2.59
0.2.58
0.2.57
0.2.56
0.2.55
0.2.54
0.2.53
0.2.52
0.2.51
0.2.50
0.2.49
0.2.48
0.2.47
0.2.46
0.2.45
0.2.44
0.2.43
0.2.42
0.2.41
0.2.40
0.2.39
0.2.38
0.2.37
0.2.36
0.2.35
0.2.34
0.2.33
0.2.32
0.2.31
0.2.30
0.2.29
0.2.28
0.2.27
0.2.26
0.2.25
0.2.24
0.2.23
0.2.22
0.2.21
0.2.20
0.2.19
0.2.18
0.2.17
0.2.16
0.2.15
0.2.14
0.2.13
0.2.12
0.2.11
0.2.10
0.2.9
0.2.8
0.2.7
0.2.6
0.2.5
0.2.4
0.2.3
0.2.2
0.2.1
0.2.0
0.1.3
0.1.2
0.1.1-rc.20
0.1.1-rc.19
0.1.1-rc.18
0.1.1-rc.17
0.1.1-rc.16
0.1.1-rc.15
0.1.1-rc.14
0.1.1-rc.13
0.1.1-rc.12
0.1.1-rc.11
0.1.1-rc.10
0.1.1-rc.9
0.1.1-rc.8
0.1.1-rc.7
0.1.1-rc.6
0.1.1-rc.5
0.1.1-rc.4
0.1.1-rc.3
0.1.1-rc.2
0.1.1-rc.1
0.1.1-rc.0
Shared utilities for ecto-based sql data layers.
Current section
Files
Jump to
Current section
Files
lib/query.ex
defmodule AshSql.Query do
@moduledoc false
import Ecto.Query, only: [subquery: 1, from: 2]
def resource_to_query(resource, implementation) do
from(row in {implementation.table(resource) || "", resource}, [])
end
def set_context(resource, data_layer_query, sql_behaviour, context) do
start_bindings = context[:data_layer][:start_bindings_at] || 0
data_layer_query = from(row in data_layer_query, as: ^start_bindings)
data_layer_query =
if context[:data_layer][:table] do
%{
data_layer_query
| from: %{data_layer_query.from | source: {context[:data_layer][:table], resource}}
}
else
data_layer_query
end
data_layer_query =
if context[:data_layer][:schema] do
Ecto.Query.put_query_prefix(data_layer_query, to_string(context[:data_layer][:schema]))
else
data_layer_query
end
data_layer_query =
data_layer_query
|> AshSql.Bindings.default_bindings(resource, sql_behaviour, context)
|> AshSql.Bindings.add_parent_bindings(context)
case context[:data_layer][:lateral_join_source] do
{_, [{%{resource: resource}, _, _, _} | rest]} ->
parent =
resource
|> resource_to_query(data_layer_query.__ash_bindings__.sql_behaviour)
|> AshSql.Bindings.default_bindings(resource, sql_behaviour, context)
parent =
case rest do
[{resource, _, _, %{name: join_relationship_name}} | _] ->
binding_data = %{type: :inner, path: [join_relationship_name], source: resource}
AshSql.Bindings.add_binding(parent, binding_data)
_ ->
parent
end
query_with_ash_bindings =
data_layer_query
|> AshSql.Bindings.add_parent_bindings(%{
data_layer: %{parent_bindings: parent.__ash_bindings__}
})
|> Map.update!(:__ash_bindings__, &Map.put(&1, :lateral_join?, true))
{:ok, query_with_ash_bindings}
_ ->
ash_bindings =
data_layer_query.__ash_bindings__
|> Map.put(:lateral_join?, false)
{:ok, %{data_layer_query | __ash_bindings__: ash_bindings}}
end
end
def return_query(%{__ash_bindings__: %{lateral_join?: true}} = query, resource) do
query =
AshSql.Bindings.default_bindings(query, resource, query.__ash_bindings__.sql_behaviour)
if query.__ash_bindings__[:sort_applied?] do
{:ok, query}
else
AshSql.Sort.apply_sort(
query,
query.__ash_bindings__[:sort],
query.__ash_bindings__.resource
)
end
end
def return_query(query, resource) do
query =
AshSql.Bindings.default_bindings(query, resource, query.__ash_bindings__.sql_behaviour)
with_sort_applied =
if query.__ash_bindings__[:sort_applied?] do
{:ok, query}
else
AshSql.Sort.apply_sort(query, query.__ash_bindings__[:sort], resource)
end
case with_sort_applied do
{:error, error} ->
{:error, error}
{:ok, query} ->
if query.__ash_bindings__[:__order__?] && query.windows[:order] do
if query.distinct do
query_with_order =
from(row in query, select_merge: %{__order__: over(row_number(), :order)})
query_without_limit_and_offset =
query_with_order
|> Ecto.Query.exclude(:limit)
|> Ecto.Query.exclude(:offset)
{:ok,
from(row in subquery(query_without_limit_and_offset),
select: row,
order_by: row.__order__
)
|> Map.put(:limit, query.limit)
|> Map.put(:offset, query.offset)}
else
order_by = %{query.windows[:order] | expr: query.windows[:order].expr[:order_by]}
{:ok,
%{
query
| windows: Keyword.delete(query.windows, :order),
order_bys: [order_by]
}}
end
else
{:ok, %{query | windows: Keyword.delete(query.windows, :order)}}
end
end
end
end