Skip to content

Commit 3ab8279

Browse files
Allow numbers in literal/1 (#4562)
1 parent 4990abd commit 3ab8279

File tree

3 files changed

+28
-15
lines changed

3 files changed

+28
-15
lines changed

lib/ecto/query/api.ex

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -480,17 +480,20 @@ defmodule Ecto.Query.API do
480480
def fragment(fragments), do: doc!([fragments])
481481

482482
@doc """
483-
Allows a literal identifier to be injected into a fragment:
483+
Allows a literal identifier or number to be injected into a fragment:
484484
485485
collation = "es_ES"
486486
fragment("? COLLATE ?", ^name, literal(^collation))
487487
488-
The example above will inject `collation` into the query as
489-
a literal identifier instead of a query parameter. Note that
490-
each different value of `collation` will emit a different query,
491-
which will be independently prepared and cached.
488+
limit = 10
489+
limit(query, fragment("?", literal(^limit)))
490+
491+
The example above will inject `collation` and `limit` into the queries as
492+
literals instead of query parameters. Note that each different value passed
493+
to `literal/1` will emit a different query, which will be independently prepared
494+
and cached.
492495
"""
493-
def literal(binary), do: doc!([binary])
496+
def literal(literal), do: doc!([literal])
494497

495498
@doc """
496499
Allows a list argument to be spliced into a fragment.

lib/ecto/query/builder.ex

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1256,13 +1256,12 @@ defmodule Ecto.Query.Builder do
12561256
@doc """
12571257
Called by escaper at runtime to verify literal in fragments.
12581258
"""
1259+
def literal!(literal) when is_binary(literal), do: literal
1260+
def literal!(literal) when is_number(literal), do: literal
1261+
12591262
def literal!(literal) do
1260-
if is_binary(literal) do
1261-
literal
1262-
else
1263-
raise ArgumentError,
1264-
"literal(^value) expects `value` to be a string, got `#{inspect(literal)}`"
1265-
end
1263+
raise ArgumentError,
1264+
"literal(^value) expects `value` to be a string or a number, got `#{inspect(literal)}`"
12661265
end
12671266

12681267
@doc """

test/ecto/query_test.exs

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -988,9 +988,20 @@ defmodule Ecto.QueryTest do
988988
raw: ""
989989
] = parts
990990

991-
assert_raise ArgumentError, "literal(^value) expects `value` to be a string, got `123`", fn ->
992-
from p in "posts", select: fragment("? COLLATE ?", p.name, literal(^123))
993-
end
991+
query = from p in "posts", limit: fragment("?", literal(^1))
992+
assert {:fragment, _, parts} = query.limit.expr
993+
994+
assert [
995+
raw: "",
996+
expr: {:literal, _, [1]},
997+
raw: ""
998+
] = parts
999+
1000+
assert_raise ArgumentError,
1001+
"literal(^value) expects `value` to be a string or a number, got `%{}`",
1002+
fn ->
1003+
from p in "posts", select: fragment("? COLLATE ?", p.name, literal(^%{}))
1004+
end
9941005
end
9951006

9961007
test "supports list splicing" do

0 commit comments

Comments
 (0)