Merge pull request #327 from philomena-dev/new-query-compile-api

New query compile internal API
This commit is contained in:
liamwhite 2024-07-13 16:06:27 -04:00 committed by GitHub
commit 3a8426e924
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
22 changed files with 52 additions and 38 deletions

View file

@ -92,8 +92,8 @@ defmodule Philomena.Comments.Query do
|> Parser.parse(query_string, context) |> Parser.parse(query_string, context)
end end
def compile(user, query_string) do def compile(query_string, opts \\ []) do
query_string = query_string || "" user = Keyword.get(opts, :user)
case user do case user do
nil -> nil ->

View file

@ -33,8 +33,8 @@ defmodule Philomena.Filters.Query do
|> Parser.parse(query_string, context) |> Parser.parse(query_string, context)
end end
def compile(user, query_string) do def compile(query_string, opts \\ []) do
query_string = query_string || "" user = Keyword.get(opts, :user)
case user do case user do
nil -> nil ->

View file

@ -15,8 +15,6 @@ defmodule Philomena.Galleries.Query do
end end
def compile(query_string) do def compile(query_string) do
query_string = query_string || ""
fields() fields()
|> Parser.new() |> Parser.new()
|> Parser.parse(query_string) |> Parser.parse(query_string)

View file

@ -144,8 +144,9 @@ defmodule Philomena.Images.Query do
|> Parser.parse(query_string, context) |> Parser.parse(query_string, context)
end end
def compile(user, query_string, watch \\ false) do def compile(query_string, opts \\ []) do
query_string = query_string || "" user = Keyword.get(opts, :user)
watch = Keyword.get(opts, :watch, false)
case user do case user do
nil -> nil ->

View file

@ -90,8 +90,8 @@ defmodule Philomena.Posts.Query do
|> Parser.parse(query_string, context) |> Parser.parse(query_string, context)
end end
def compile(user, query_string) do def compile(query_string, opts \\ []) do
query_string = query_string || "" user = Keyword.get(opts, :user)
case user do case user do
nil -> nil ->

View file

@ -17,6 +17,6 @@ defmodule Philomena.Reports.Query do
def compile(query_string) do def compile(query_string) do
fields() fields()
|> Parser.new() |> Parser.new()
|> Parser.parse(query_string || "", %{}) |> Parser.parse(query_string, %{})
end end
end end

View file

@ -5,7 +5,7 @@ defmodule Philomena.Schema.Search do
def validate_search(changeset, field, user, watched \\ false) do def validate_search(changeset, field, user, watched \\ false) do
query = changeset |> get_field(field) |> String.normalize() query = changeset |> get_field(field) |> String.normalize()
output = Query.compile(user, query, watched) output = Query.compile(query, user: user, watch: watched)
case output do case output do
{:ok, _} -> {:ok, _} ->

View file

@ -20,6 +20,6 @@ defmodule Philomena.Tags.Query do
def compile(query_string) do def compile(query_string) do
fields() fields()
|> Parser.new() |> Parser.new()
|> Parser.parse(query_string || "") |> Parser.parse(query_string)
end end
end end

View file

@ -184,18 +184,18 @@ defmodule PhilomenaQuery.Parse.Parser do
@spec parse(t(), String.t(), context()) :: {:ok, query()} | {:error, String.t()} @spec parse(t(), String.t(), context()) :: {:ok, query()} | {:error, String.t()}
def parse(parser, input, context \\ nil) def parse(parser, input, context \\ nil)
# Empty search should emit a match_none.
def parse(_parser, "", _context) do
{:ok, %{match_none: %{}}}
end
def parse(%Parser{} = parser, input, context) do def parse(%Parser{} = parser, input, context) do
parser = %{parser | __data__: context} parser = %{parser | __data__: context}
with {:ok, tokens, _1, _2, _3, _4} <- Lexer.lex(input), with {:ok, input} <- coerce_string(input),
{:ok, tokens, _1, _2, _3, _4} <- Lexer.lex(input),
{:ok, tokens} <- convert_empty_token_list(tokens),
{:ok, {tree, []}} <- search_top(parser, tokens) do {:ok, {tree, []}} <- search_top(parser, tokens) do
{:ok, tree} {:ok, tree}
else else
{:error, :empty_query} ->
{:ok, %{match_none: %{}}}
{:ok, {_tree, tokens}} -> {:ok, {_tree, tokens}} ->
{:error, "junk at end of expression: " <> debug_tokens(tokens)} {:error, "junk at end of expression: " <> debug_tokens(tokens)}
@ -211,6 +211,13 @@ defmodule PhilomenaQuery.Parse.Parser do
end end
end end
defp coerce_string(term) when is_binary(term), do: {:ok, term}
defp coerce_string(nil), do: {:ok, ""}
defp coerce_string(_), do: {:error, "search query is not a string"}
defp convert_empty_token_list([]), do: {:error, :empty_query}
defp convert_empty_token_list(tokens), do: {:ok, tokens}
defp debug_tokens(tokens) do defp debug_tokens(tokens) do
Enum.map_join(tokens, fn {_k, v} -> v end) Enum.map_join(tokens, fn {_k, v} -> v end)
end end

View file

@ -10,7 +10,7 @@ defmodule PhilomenaWeb.Api.Json.Search.CommentController do
user = conn.assigns.current_user user = conn.assigns.current_user
filter = conn.assigns.current_filter filter = conn.assigns.current_filter
case Query.compile(user, params["q"] || "") do case Query.compile(params["q"], user: user) do
{:ok, query} -> {:ok, query} ->
comments = comments =
Comment Comment

View file

@ -9,7 +9,7 @@ defmodule PhilomenaWeb.Api.Json.Search.FilterController do
def index(conn, params) do def index(conn, params) do
user = conn.assigns.current_user user = conn.assigns.current_user
case Query.compile(user, params["q"] || "") do case Query.compile(params["q"], user: user) do
{:ok, query} -> {:ok, query} ->
filters = filters =
Filter Filter

View file

@ -7,7 +7,7 @@ defmodule PhilomenaWeb.Api.Json.Search.GalleryController do
import Ecto.Query import Ecto.Query
def index(conn, params) do def index(conn, params) do
case Query.compile(params["q"] || "") do case Query.compile(params["q"]) do
{:ok, query} -> {:ok, query} ->
galleries = galleries =
Gallery Gallery

View file

@ -9,7 +9,7 @@ defmodule PhilomenaWeb.Api.Json.Search.PostController do
def index(conn, params) do def index(conn, params) do
user = conn.assigns.current_user user = conn.assigns.current_user
case Query.compile(user, params["q"] || "") do case Query.compile(params["q"], user: user) do
{:ok, query} -> {:ok, query} ->
posts = posts =
Post Post

View file

@ -7,7 +7,7 @@ defmodule PhilomenaWeb.Api.Json.Search.TagController do
import Ecto.Query import Ecto.Query
def index(conn, params) do def index(conn, params) do
case Query.compile(params["q"] || "") do case Query.compile(params["q"]) do
{:ok, query} -> {:ok, query} ->
tags = tags =
Tag Tag

View file

@ -13,8 +13,8 @@ defmodule PhilomenaWeb.CommentController do
conn = Map.put(conn, :params, params) conn = Map.put(conn, :params, params)
user = conn.assigns.current_user user = conn.assigns.current_user
user cq
|> Query.compile(cq) |> Query.compile(user: user)
|> render_index(conn, user) |> render_index(conn, user)
end end

View file

@ -13,8 +13,8 @@ defmodule PhilomenaWeb.FilterController do
def index(conn, %{"fq" => fq}) do def index(conn, %{"fq" => fq}) do
user = conn.assigns.current_user user = conn.assigns.current_user
user fq
|> Query.compile(fq) |> Query.compile(user: user)
|> render_index(conn, user) |> render_index(conn, user)
end end

View file

@ -54,7 +54,10 @@ defmodule PhilomenaWeb.Image.NavigateController do
defp compile_query(conn) do defp compile_query(conn) do
user = conn.assigns.current_user user = conn.assigns.current_user
{:ok, query} = Query.compile(user, match_all_if_blank(conn.params["q"])) {:ok, query} =
conn.params["q"]
|> match_all_if_blank()
|> Query.compile(user: user)
query query
end end

View file

@ -13,8 +13,8 @@ defmodule PhilomenaWeb.PostController do
conn = Map.put(conn, :params, params) conn = Map.put(conn, :params, params)
user = conn.assigns.current_user user = conn.assigns.current_user
user pq
|> Query.compile(pq) |> Query.compile(user: user)
|> render_index(conn, user) |> render_index(conn, user)
end end

View file

@ -121,7 +121,7 @@ defmodule PhilomenaWeb.TagController do
|> String.trim() |> String.trim()
|> String.downcase() |> String.downcase()
case Images.Query.compile(nil, name) do case Images.Query.compile(name) do
{:ok, %{term: %{"namespaced_tags.name" => ^name}}} -> {:ok, %{term: %{"namespaced_tags.name" => ^name}}} ->
name name

View file

@ -11,7 +11,7 @@ defmodule PhilomenaWeb.ImageLoader do
def search_string(conn, search_string, options \\ []) do def search_string(conn, search_string, options \\ []) do
user = conn.assigns.current_user user = conn.assigns.current_user
with {:ok, tree} <- Query.compile(user, search_string) do with {:ok, tree} <- Query.compile(search_string, user: user) do
{:ok, query(conn, tree, options)} {:ok, query(conn, tree, options)}
else else
error -> error ->

View file

@ -6,7 +6,7 @@ defmodule PhilomenaWeb.FilterForcedUsersPlug do
import Phoenix.Controller import Phoenix.Controller
import Plug.Conn import Plug.Conn
alias PhilomenaQuery.Parse.String, as: SearchString alias PhilomenaQuery.Parse.String
alias PhilomenaQuery.Parse.Evaluator alias PhilomenaQuery.Parse.Evaluator
alias Philomena.Images.Query alias Philomena.Images.Query
alias PhilomenaWeb.ImageView alias PhilomenaWeb.ImageView
@ -53,7 +53,10 @@ defmodule PhilomenaWeb.FilterForcedUsersPlug do
end end
defp compile_filter(user, search_string) do defp compile_filter(user, search_string) do
case Query.compile(user, SearchString.normalize(search_string)) do search_string
|> String.normalize()
|> Query.compile(user: user)
|> case do
{:ok, query} -> query {:ok, query} -> query
_error -> %{match_all: %{}} _error -> %{match_all: %{}}
end end

View file

@ -1,7 +1,6 @@
defmodule PhilomenaWeb.ImageFilterPlug do defmodule PhilomenaWeb.ImageFilterPlug do
import Plug.Conn import Plug.Conn
import PhilomenaQuery.Parse.String alias PhilomenaQuery.Parse.String
alias Philomena.Images.Query alias Philomena.Images.Query
# No options # No options
@ -50,7 +49,10 @@ defmodule PhilomenaWeb.ImageFilterPlug do
end end
defp invalid_filter_guard(user, search_string) do defp invalid_filter_guard(user, search_string) do
case Query.compile(user, normalize(search_string)) do search_string
|> String.normalize()
|> Query.compile(user: user)
|> case do
{:ok, query} -> query {:ok, query} -> query
_error -> %{match_all: %{}} _error -> %{match_all: %{}}
end end