Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
zachdaniel committed Jun 19, 2020
1 parent 26de27b commit 234e6bb
Show file tree
Hide file tree
Showing 18 changed files with 314 additions and 219 deletions.
2 changes: 1 addition & 1 deletion .credo.exs
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@
## Refactoring Opportunities
#
{Credo.Check.Refactor.CondStatements, []},
{Credo.Check.Refactor.CyclomaticComplexity, [max_complexity: 12]},
{Credo.Check.Refactor.CyclomaticComplexity, [max_complexity: 13]},
{Credo.Check.Refactor.FunctionArity, []},
{Credo.Check.Refactor.LongQuoteBlocks, []},
{Credo.Check.Refactor.MapInto, []},
Expand Down
19 changes: 19 additions & 0 deletions benchmarks/sat_solver.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
query =
AshExample.Api.query(AshExample.Representative)
|> Ash.Query.filter(
id: [in: ["35c73627-d24c-4d37-99c5-f6309202f514", "35c73627-d24c-4d37-99c5-f6309202f514"]]
)

candidate =
AshExample.Api.query(AshExample.Representative)
|> Ash.Query.filter(id: "35c73627-d24c-4d37-99c5-f6309202f514")

Benchee.run(
%{
"picosat" => fn ->
Ash.SatSolver.strict_filter_subset(query.filter, candidate.filter)
end
},
time: 10,
memory_time: 2
)
19 changes: 12 additions & 7 deletions lib/ash/actions/relationships.ex
Original file line number Diff line number Diff line change
Expand Up @@ -170,20 +170,20 @@ defmodule Ash.Actions.Relationships do
) do
relationship_name = relationship.name

filter =
{possible?, filter} =
case identifiers do
[single_identifier] ->
if Keyword.keyword?(single_identifier) do
single_identifier
{true, single_identifier}
else
[single_identifier]
{true, [single_identifier]}
end

[] ->
[__impossible__: true]
{false, []}

many ->
[or: many]
{true, [or: many]}
end

query =
Expand All @@ -198,10 +198,15 @@ defmodule Ash.Actions.Relationships do
action: Ash.primary_action!(relationship.destination, :read),
query: query,
path: [:relationships, relationship_name, type],
authorize?: possible?,
data:
Request.resolve(fn _data ->
query
|> api.read()
if possible? do
query
|> api.read()
else
[]
end
end),
name: "read prior to write related #{relationship.name}"
)
Expand Down
6 changes: 3 additions & 3 deletions lib/ash/actions/side_load.ex
Original file line number Diff line number Diff line change
Expand Up @@ -432,7 +432,7 @@ defmodule Ash.Actions.SideLoad do
root_filter =
case data do
[] ->
[__impossible__: true]
false

[%resource{} = item] ->
item
Expand Down Expand Up @@ -588,8 +588,8 @@ defmodule Ash.Actions.SideLoad do
end

defp put_nested_relationship(request_filter, path, value, records? \\ true)
defp put_nested_relationship(_, _, [], true), do: [__impossible__: true]
defp put_nested_relationship(_, _, nil, true), do: [__impossible__: true]
defp put_nested_relationship(_, _, [], true), do: false
defp put_nested_relationship(_, _, nil, true), do: false
defp put_nested_relationship(_, _, [], false), do: []
defp put_nested_relationship(_, _, nil, false), do: []

Expand Down
4 changes: 1 addition & 3 deletions lib/ash/data_layer/data_layer.ex
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,10 @@ defmodule Ash.DataLayer do
to ensure that the engine only ever tries to interact with the data layer in ways
that it supports.
"""
@type filter_type :: :eq | :in
@type feature() ::
:transact
| :async_engine
| {:filter, filter_type}
| {:filter_related, Ash.relationship_cardinality()}
| {:filter_predicate, struct}
| :upsert
| :composite_primary_key

Expand Down
14 changes: 3 additions & 11 deletions lib/ash/data_layer/ets/ets.ex
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ defmodule Ash.DataLayer.Ets do
This is used for testing. *Do not use this data layer in production*
"""

alias Ash.Filter.{Predicate, Expression, Not}
alias Ash.Filter.{Expression, Not, Predicate}
alias Ash.Filter.Predicate.{Eq, In}

@behaviour Ash.DataLayer
Expand Down Expand Up @@ -41,18 +41,10 @@ defmodule Ash.DataLayer.Ets do
not private?(resource)
end

def can?(_, :transact), do: false

def can?(_, :composite_primary_key), do: true
def can?(_, :upsert), do: true
def can?(_, {:filter, :in}), do: true
def can?(_, {:filter, :not_in}), do: true
def can?(_, {:filter, :not_eq}), do: true
def can?(_, {:filter, :eq}), do: true
def can?(_, {:filter, :and}), do: true
def can?(_, {:filter, :or}), do: true
def can?(_, {:filter, :not}), do: true
def can?(_, {:filter_related, _}), do: true
def can?(_, {:filter_predicate, %In{}}), do: true
def can?(_, {:filter_predicate, %Eq{}}), do: true
def can?(_, _), do: false

@impl true
Expand Down
57 changes: 17 additions & 40 deletions lib/ash/engine/request.ex
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ defmodule Ash.Engine.Request do
:data,
:name,
:api,
:authorization_filter,
:query,
:write_to_data?,
:strict_check_only?,
Expand Down Expand Up @@ -393,6 +392,8 @@ defmodule Ash.Engine.Request do
end

defp do_strict_check(authorizer, request, notifications \\ []) do
strict_check_only? = request.strict_check_only?

case missing_strict_check_dependencies?(authorizer, request) do
[] ->
case strict_check_authorizer(authorizer, request) do
Expand All @@ -402,41 +403,25 @@ defmodule Ash.Engine.Request do
{:filter, filter} ->
request
|> Map.update!(:query, &Ash.Query.filter(&1, filter))
|> Map.update(:authorization_filter, filter, fn authorization_filter ->
if authorization_filter do
Ash.Filter.add_to_filter(authorization_filter, filter)
else
filter
end
end)
|> set_authorizer_state(authorizer, :authorized)
|> try_resolve([request.path ++ [:query]], false, false)

{:filter_and_continue, _, _} when strict_check_only? ->
{:error, "Request must pass strict check"}

{:filter_and_continue, filter, new_authorizer_state} ->
if request.strict_check_only? do
{:error, "Request must pass strict check"}
else
new_request =
request
|> Map.update(:authorization_filter, filter, fn authorization_filter ->
if authorization_filter do
Ash.Filter.add_to_filter(authorization_filter, filter)
else
filter
end
end)
|> Map.update!(:query, &Ash.Query.filter(&1, filter))
|> set_authorizer_state(authorizer, new_authorizer_state)

{:ok, new_request}
end
new_request =
request
|> Map.update!(:query, &Ash.Query.filter(&1, filter))
|> set_authorizer_state(authorizer, new_authorizer_state)

{:ok, new_request}

{:continue, _} when strict_check_only? ->
{:error, "Request must pass strict check"}

{:continue, authorizer_state} ->
if request.strict_check_only? do
{:error, "Request must pass strict check"}
else
{:ok, set_authorizer_state(request, authorizer, authorizer_state)}
end
{:ok, set_authorizer_state(request, authorizer, authorizer_state)}

{:error, error} ->
{:error, error}
Expand Down Expand Up @@ -499,15 +484,7 @@ defmodule Ash.Engine.Request do
{:ok, set_authorizer_state(request, authorizer, :authorized)}

{:filter, filter} ->
request
|> Map.update(:authorization_filter, filter, fn authorization_filter ->
if authorization_filter do
Ash.Filter.add_to_filter(authorization_filter, filter)
else
filter
end
end)
|> runtime_filter(authorizer, filter)
runtime_filter(request, authorizer, filter)

{:error, error} ->
{:error, error}
Expand Down Expand Up @@ -624,7 +601,7 @@ defmodule Ash.Engine.Request do
authorized? = Enum.all?(Map.values(request.authorizer_state), &(&1 == :authorized))

# Don't fetch honor requests for dat until the request is authorized
if field in [:data, :query, :authorization_filter] and not authorized? and not internal? do
if field in [:data, :query] and not authorized? and not internal? do
try_resolve_dependencies_of(request, field, internal?, optional?)
else
case Map.get(request, field) do
Expand Down
Empty file removed lib/ash/filter/cosimplify.ex
Empty file.
2 changes: 2 additions & 0 deletions lib/ash/filter/expression.ex
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
defmodule Ash.Filter.Expression do
@moduledoc "Represents a boolean expression"

defstruct [:op, :left, :right]

def new(_, nil, nil), do: nil
Expand Down
Loading

0 comments on commit 234e6bb

Please sign in to comment.