diff --git a/integration_test/pg/storage_test.exs b/integration_test/pg/storage_test.exs index 50e27154..e030655a 100644 --- a/integration_test/pg/storage_test.exs +++ b/integration_test/pg/storage_test.exs @@ -130,7 +130,7 @@ defmodule Ecto.Integration.StorageTest do {:ok, _} = Postgres.structure_load(tmp_path(), params()) {:ok, _} = Postgres.structure_dump(tmp_path(), [dump_path: dump_path] ++ params()) - assert dump == File.read!(dump_path) + assert redact_hashes(dump) == redact_hashes(File.read!(dump_path)) after drop_database() end @@ -248,11 +248,18 @@ defmodule Ecto.Integration.StorageTest do num = @base_migration + System.unique_integer([:positive]) :ok = Ecto.Migrator.up(PoolRepo, num, Migration, log: false) - assert {"--\n-- PostgreSQL database dump\n--\n\n--" <> _rest, 0} = + assert {"--\n-- PostgreSQL database dump\n--\n\n" <> _rest, 0} = Postgres.dump_cmd( ["--data-only", "--table", "schema_migrations"], [], PoolRepo.config() ) end + + defp redact_hashes(dump_output) do + dump_output + |> String.replace(~r/\\restrict\s+\S+/, "\\restrict ") + |> String.replace(~r/\\unrestrict\s+\S+/, "\\unrestrict ") + |> String.trim() + end end diff --git a/integration_test/sql/sql.exs b/integration_test/sql/sql.exs index 46d1eb8a..a07eab25 100644 --- a/integration_test/sql/sql.exs +++ b/integration_test/sql/sql.exs @@ -7,7 +7,12 @@ defmodule Ecto.Integration.SQLTest do alias Ecto.Integration.Post alias Ecto.Integration.CorruptedPk alias Ecto.Integration.Tag - import Ecto.Query, only: [from: 2] + import Ecto.Query, only: [from: 2, from: 1] + + test "fragment tuple sources" do + query = from f in {fragment("select 1 as num"), Barebone} + assert %Barebone{num: 1} = TestRepo.one(query) + end test "fragmented types" do datetime = ~N[2014-01-16 20:26:51] diff --git a/lib/ecto/adapters/myxql/connection.ex b/lib/ecto/adapters/myxql/connection.ex index 63d35520..f5a36695 100644 --- a/lib/ecto/adapters/myxql/connection.ex +++ b/lib/ecto/adapters/myxql/connection.ex @@ -735,11 +735,11 @@ if Code.ensure_loaded?(MyXQL) do end defp expr({:fragment, _, parts}, sources, query) do - Enum.map(parts, fn - {:raw, part} -> part - {:expr, expr} -> expr(expr, sources, query) - end) - |> parens_for_select + fragment_expr(parts, sources, query) + end + + defp expr({{:fragment, _, parts}, schema}, sources, query) when is_atom(schema) do + fragment_expr(parts, sources, query) end defp expr({:values, _, [types, _idx, num_rows]}, _, query) do @@ -911,6 +911,14 @@ if Code.ensure_loaded?(MyXQL) do end) end + defp fragment_expr(parts, sources, query) do + Enum.map(parts, fn + {:raw, part} -> part + {:expr, expr} -> expr(expr, sources, query) + end) + |> parens_for_select() + end + defp interval(count, "millisecond", sources, query) do ["INTERVAL (", expr(count, sources, query) | " * 1000) microsecond"] end @@ -949,6 +957,9 @@ if Code.ensure_loaded?(MyXQL) do {:fragment, _, _} -> {nil, as_prefix ++ [?f | Integer.to_string(pos)], nil} + {{:fragment, _, _}, schema, _} -> + {nil, as_prefix ++ [?f | Integer.to_string(pos)], schema} + {:values, _, _} -> {nil, as_prefix ++ [?v | Integer.to_string(pos)], nil} diff --git a/lib/ecto/adapters/postgres/connection.ex b/lib/ecto/adapters/postgres/connection.ex index 9ad05155..deae2379 100644 --- a/lib/ecto/adapters/postgres/connection.ex +++ b/lib/ecto/adapters/postgres/connection.ex @@ -974,11 +974,11 @@ if Code.ensure_loaded?(Postgrex) do end defp expr({:fragment, _, parts}, sources, query) do - Enum.map(parts, fn - {:raw, part} -> part - {:expr, expr} -> expr(expr, sources, query) - end) - |> parens_for_select + fragment_expr(parts, sources, query) + end + + defp expr({{:fragment, _, parts}, schema}, sources, query) when is_atom(schema) do + fragment_expr(parts, sources, query) end defp expr({:values, _, [types, idx, num_rows]}, _, _query) do @@ -1162,6 +1162,14 @@ if Code.ensure_loaded?(Postgrex) do end) end + defp fragment_expr(parts, sources, query) do + Enum.map(parts, fn + {:raw, part} -> part + {:expr, expr} -> expr(expr, sources, query) + end) + |> parens_for_select() + end + defp type_unless_typed(%Ecto.Query.Tagged{}, _type), do: [] defp type_unless_typed(_, type), do: [?:, ?: | type] @@ -1226,6 +1234,9 @@ if Code.ensure_loaded?(Postgrex) do {:fragment, _, _} -> {nil, as_prefix ++ [?f | Integer.to_string(pos)], nil} + {{:fragment, _, _}, schema, _} -> + {nil, as_prefix ++ [?f | Integer.to_string(pos)], schema} + {:values, _, _} -> {nil, as_prefix ++ [?v | Integer.to_string(pos)], nil} diff --git a/lib/ecto/adapters/tds/connection.ex b/lib/ecto/adapters/tds/connection.ex index 206d2f4f..dc295f46 100644 --- a/lib/ecto/adapters/tds/connection.ex +++ b/lib/ecto/adapters/tds/connection.ex @@ -815,11 +815,11 @@ if Code.ensure_loaded?(Tds) do end defp expr({:fragment, _, parts}, sources, query) do - Enum.map(parts, fn - {:raw, part} -> part - {:expr, expr} -> expr(expr, sources, query) - end) - |> parens_for_select + fragment_expr(parts, sources, query) + end + + defp expr({{:fragment, _, parts}, schema}, sources, query) when is_atom(schema) do + fragment_expr(parts, sources, query) end defp expr({:values, _, [types, idx, num_rows]}, _, _query) do @@ -1007,6 +1007,14 @@ if Code.ensure_loaded?(Tds) do end) end + defp fragment_expr(parts, sources, query) do + Enum.map(parts, fn + {:raw, part} -> part + {:expr, expr} -> expr(expr, sources, query) + end) + |> parens_for_select() + end + defp op_to_binary({op, _, [_, _]} = expr, sources, query) when op in @binary_ops do paren_expr(expr, sources, query) end @@ -1070,6 +1078,9 @@ if Code.ensure_loaded?(Tds) do {:fragment, _, _} -> {nil, as_prefix ++ [?f | Integer.to_string(pos)], nil} + {{:fragment, _, _}, schema, _} -> + {nil, as_prefix ++ [?f | Integer.to_string(pos)], schema} + {:values, _, _} -> {nil, as_prefix ++ [?v | Integer.to_string(pos)], nil} diff --git a/mix.exs b/mix.exs index bb51ca9d..96e57a8e 100644 --- a/mix.exs +++ b/mix.exs @@ -76,7 +76,7 @@ defmodule EctoSQL.MixProject do if path = System.get_env("ECTO_PATH") do {:ecto, path: path} else - {:ecto, "~> 3.13.0"} + {:ecto, git: "https://github.com/elixir-ecto/ecto.git", branch: "master"} end end diff --git a/mix.lock b/mix.lock index bbcb999f..4eed272a 100644 --- a/mix.lock +++ b/mix.lock @@ -4,7 +4,7 @@ "decimal": {:hex, :decimal, "2.3.0", "3ad6255aa77b4a3c4f818171b12d237500e63525c2fd056699967a3e7ea20f62", [:mix], [], "hexpm", "a4d66355cb29cb47c3cf30e71329e58361cfcb37c34235ef3bf1d7bf3773aeac"}, "deep_merge": {:hex, :deep_merge, "1.0.0", "b4aa1a0d1acac393bdf38b2291af38cb1d4a52806cf7a4906f718e1feb5ee961", [:mix], [], "hexpm", "ce708e5f094b9cd4e8f2be4f00d2f4250c4095be93f8cd6d018c753894885430"}, "earmark_parser": {:hex, :earmark_parser, "1.4.44", "f20830dd6b5c77afe2b063777ddbbff09f9759396500cdbe7523efd58d7a339c", [:mix], [], "hexpm", "4778ac752b4701a5599215f7030989c989ffdc4f6df457c5f36938cc2d2a2750"}, - "ecto": {:hex, :ecto, "3.13.0", "7528ef4f3a4cdcfebeb7eb6545806c8109529b385a69f701fc3d77b5b8bde6e7", [:mix], [{:decimal, "~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "061f095f1cc097f71f743b500affc792d6869df22b1946a73ab5495eb9b4a280"}, + "ecto": {:git, "https://github.com/elixir-ecto/ecto.git", "3ab6a20b255fe2cee1fd9f6ae160c6fde772dce7", [branch: "master"]}, "ex_doc": {:hex, :ex_doc, "0.38.2", "504d25eef296b4dec3b8e33e810bc8b5344d565998cd83914ffe1b8503737c02", [:mix], [{:earmark_parser, "~> 1.4.44", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_c, ">= 0.1.0", [hex: :makeup_c, repo: "hexpm", optional: true]}, {:makeup_elixir, "~> 0.14 or ~> 1.0", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1 or ~> 1.0", [hex: :makeup_erlang, repo: "hexpm", optional: false]}, {:makeup_html, ">= 0.1.0", [hex: :makeup_html, repo: "hexpm", optional: true]}], "hexpm", "732f2d972e42c116a70802f9898c51b54916e542cc50968ac6980512ec90f42b"}, "jason": {:hex, :jason, "1.4.4", "b9226785a9aa77b6857ca22832cffa5d5011a667207eb2a0ad56adb5db443b8a", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "c5eb0cab91f094599f94d55bc63409236a8ec69a21a67814529e8d5f6cc90b3b"}, "makeup": {:hex, :makeup, "1.2.1", "e90ac1c65589ef354378def3ba19d401e739ee7ee06fb47f94c687016e3713d1", [:mix], [{:nimble_parsec, "~> 1.4", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "d36484867b0bae0fea568d10131197a4c2e47056a6fbe84922bf6ba71c8d17ce"},