diff --git a/lib/ecto/adapters/sqlite3/connection.ex b/lib/ecto/adapters/sqlite3/connection.ex index 91d46bc..907f66d 100644 --- a/lib/ecto/adapters/sqlite3/connection.ex +++ b/lib/ecto/adapters/sqlite3/connection.ex @@ -1203,7 +1203,6 @@ defmodule Ecto.Adapters.SQLite3.Connection do quote_name(field) end - # def expr({{:., _, [{:parent_as, _, [{:&, _, [idx]}]}, field]}, _, []}, _sources, query) def expr({{:., _, [{:parent_as, _, [as]}, field]}, _, []}, _sources, query) when is_atom(field) do {ix, sources} = get_parent_sources_ix(query, as) @@ -1288,6 +1287,14 @@ defmodule Ecto.Adapters.SQLite3.Connection do |> parens_for_select end + def expr({:literal, _, [literal]}, _sources, _query) do + quote_name(literal) + end + + def expr({:selected_as, _, [name]}, _sources, _query) do + [quote_name(name)] + end + def expr({:datetime_add, _, [datetime, count, interval]}, sources, query) do [ "CAST (", @@ -1366,6 +1373,7 @@ defmodule Ecto.Adapters.SQLite3.Connection do end end + # TODO It technically is, its just a json array, so we *could* support it def expr(list, _sources, query) when is_list(list) do raise Ecto.QueryError, query: query, @@ -1404,8 +1412,7 @@ defmodule Ecto.Adapters.SQLite3.Connection do end def expr(literal, _sources, _query) when is_float(literal) do - # Unsure if SQLite3 supports float casting - ["(0 + ", Float.to_string(literal), ?)] + ["CAST(", Float.to_string(literal), " AS REAL)"] end def expr(expr, _sources, query) do diff --git a/test/ecto/adapters/sqlite3/connection_test.exs b/test/ecto/adapters/sqlite3/connection_test.exs index 82ffda0..1dc3c9f 100644 --- a/test/ecto/adapters/sqlite3/connection_test.exs +++ b/test/ecto/adapters/sqlite3/connection_test.exs @@ -946,7 +946,30 @@ defmodule Ecto.Adapters.SQLite3.ConnectionTest do |> select([], true) |> plan() - assert all(query) == ~s{SELECT 1 FROM "schema" AS s0 WHERE (s0."foo" = (0 + 123.0))} + assert all(query) == + ~s{SELECT 1 FROM "schema" AS s0 WHERE (s0."foo" = CAST(123.0 AS REAL))} + + name = "y" + + query = + "schema" + |> where(fragment("? = ?", literal(^name), "Main")) + |> select([], true) + |> plan() + + assert all(query) == ~s|SELECT 1 FROM "schema" AS s0 WHERE ("y" = 'Main')| + end + + test "selected_as" do + query = + from(s in "schema", + select: %{ + y: selected_as(s.y, :y2) + } + ) + |> plan() + + assert all(query) == ~s|SELECT s0."y" AS "y2" FROM "schema" AS s0| end test "tagged type" do diff --git a/test/ecto/integration/crud_test.exs b/test/ecto/integration/crud_test.exs index ef8d036..51267d9 100644 --- a/test/ecto/integration/crud_test.exs +++ b/test/ecto/integration/crud_test.exs @@ -244,5 +244,53 @@ defmodule Ecto.Integration.CrudTest do assert [_] = TestRepo.all(from(a in Account, as: :user, where: exists(subquery))) end + + test "can handle fragment literal" do + account1 = TestRepo.insert!(%Account{name: "Main"}) + + name = "name" + query = from(a in Account, where: fragment("? = ?", literal(^name), "Main")) + + assert [account] = TestRepo.all(query) + assert account.id == account1.id + end + + test "can handle selected_as" do + TestRepo.insert!(%Account{name: "Main"}) + TestRepo.insert!(%Account{name: "Main"}) + TestRepo.insert!(%Account{name: "Main2"}) + TestRepo.insert!(%Account{name: "Main3"}) + + query = + from(a in Account, + select: %{ + name: selected_as(a.name, :name2), + count: count() + }, + group_by: selected_as(:name2) + ) + + assert [ + %{name: "Main", count: 2}, + %{name: "Main2", count: 1}, + %{name: "Main3", count: 1} + ] = TestRepo.all(query) + end + + test "can handle floats" do + TestRepo.insert!(%Account{name: "Main"}) + + one = "1.0" + two = 2.0 + + query = + from(a in Account, + select: %{ + sum: ^one + ^two + } + ) + + assert [%{sum: 3.0}] = TestRepo.all(query) + end end end