Add path query builder
This commit is contained in:
parent
b6aafccc7d
commit
8d68e925ad
2 changed files with 67 additions and 0 deletions
|
@ -144,4 +144,35 @@ defmodule RDF.Query.Builder do
|
|||
defp literal(%Literal{} = literal), do: literal
|
||||
defp literal(value), do: Literal.coerce(value)
|
||||
|
||||
|
||||
def path(query, opts \\ [])
|
||||
|
||||
def path(query, _) when is_list(query) and length(query) < 3 do
|
||||
{:error, %RDF.Query.InvalidError{
|
||||
message: "Invalid path expression: must have at least three elements"}
|
||||
}
|
||||
end
|
||||
|
||||
def path([subject | rest], opts) do
|
||||
path_pattern(subject, rest, [], 0, Keyword.get(opts, :with_elements, false))
|
||||
|> bgp()
|
||||
end
|
||||
|
||||
def path!(query, opts \\ []) do
|
||||
case path(query, opts) do
|
||||
{:ok, bgp} -> bgp
|
||||
{:error, error} -> raise error
|
||||
end
|
||||
end
|
||||
|
||||
defp path_pattern(subject, [predicate, object], triple_patterns, _, _) do
|
||||
[{subject, predicate, object} | triple_patterns]
|
||||
|> Enum.reverse()
|
||||
end
|
||||
|
||||
defp path_pattern(subject, [predicate | rest], triple_patterns, count, with_elements) do
|
||||
object = if with_elements, do: :"el#{count}?", else: RDF.bnode(count)
|
||||
|
||||
path_pattern(object, rest, [{subject, predicate, object} | triple_patterns], count + 1, with_elements)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -150,4 +150,40 @@ defmodule RDF.Query.BuilderTest do
|
|||
bgp [{EX.s, EX.p, EX.o}]
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
describe "path/2" do
|
||||
test "element count == 3" do
|
||||
assert Builder.path([EX.s, EX.p, EX.o]) == bgp [{EX.s, EX.p, EX.o}]
|
||||
assert Builder.path([:s?, :p?, :o?]) == bgp [{:s, :p, :o}]
|
||||
end
|
||||
|
||||
test "element count > 3" do
|
||||
assert Builder.path([EX.s, EX.p1, EX.p2, EX.o]) ==
|
||||
bgp [
|
||||
{EX.s, EX.p1, RDF.bnode("0")},
|
||||
{RDF.bnode("0"), EX.p2, EX.o},
|
||||
]
|
||||
|
||||
assert Builder.path([:s?, :p1?, :p2?, :o?]) ==
|
||||
bgp [
|
||||
{:s, :p1, RDF.bnode("0")},
|
||||
{RDF.bnode("0"), :p2, :o},
|
||||
]
|
||||
end
|
||||
|
||||
test "element count < 3" do
|
||||
assert {:error, %RDF.Query.InvalidError{}} = Builder.path([EX.s, EX.p])
|
||||
assert {:error, %RDF.Query.InvalidError{}} = Builder.path([EX.s])
|
||||
assert {:error, %RDF.Query.InvalidError{}} = Builder.path([])
|
||||
end
|
||||
|
||||
test "with_elements: true" do
|
||||
assert Builder.path([EX.s, EX.p1, EX.p2, :o?], with_elements: true) ==
|
||||
bgp [
|
||||
{EX.s, EX.p1, :el0},
|
||||
{:el0, EX.p2, :o},
|
||||
]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue