Skip to content

Commit f3fb71b

Browse files
Refactor selected_as/2 implementation (#434)
1 parent 70e3b07 commit f3fb71b

8 files changed

Lines changed: 20 additions & 74 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
* [postgres] Support the use of advisory locks for migrations
99
* [sql] Add `dump_cmd` to `postgrex` and `myxql` adapters
1010
* [sql] Log human-readable UUIDs by using pre-dumped query parameters
11+
* [sql] Support select aliases from `selected_as/1` and `selected_as/2`
1112
* [telemetry] Emit `schema_migration: true` under `telemetry_options`
1213

1314
## v3.8.3 (2022-06-04)

lib/ecto/adapters/myxql/connection.ex

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -279,8 +279,6 @@ if Code.ensure_loaded?(MyXQL) do
279279
end
280280
{key, value} ->
281281
[expr(value, sources, query), " AS ", quote_name(key)]
282-
{:selected_as, _, [field_expr, name]} ->
283-
[expr(field_expr, sources, query), " AS ", Atom.to_string(name)]
284282
value ->
285283
expr(value, sources, query)
286284
end)
@@ -575,14 +573,7 @@ if Code.ensure_loaded?(MyXQL) do
575573
end
576574

577575
defp expr({:selected_as, _, [name]}, _sources, _query) do
578-
[Atom.to_string(name)]
579-
end
580-
581-
defp expr({:selected_as, _, [_field_expr, _name]}, _sources, _query) do
582-
raise ArgumentError,
583-
"`selected_as/2` can only be used in the outer most `select` expression. " <>
584-
"If you are attempting to alias a field from a subquery, it is not allowed " <>
585-
"because subquery fields are automatically aliased by the corresponding map/struct key."
576+
[quote_name(name)]
586577
end
587578

588579
defp expr({:datetime_add, _, [datetime, count, interval]}, sources, query) do

lib/ecto/adapters/postgres/connection.ex

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -374,8 +374,6 @@ if Code.ensure_loaded?(Postgrex) do
374374
end
375375
{key, value} ->
376376
[expr(value, sources, query), " AS " | quote_name(key)]
377-
{:selected_as, _, [field_expr, name]} ->
378-
[expr(field_expr, sources, query), " AS ", Atom.to_string(name)]
379377
value ->
380378
expr(value, sources, query)
381379
end)
@@ -679,14 +677,7 @@ if Code.ensure_loaded?(Postgrex) do
679677
end
680678

681679
defp expr({:selected_as, _, [name]}, _sources, _query) do
682-
[Atom.to_string(name)]
683-
end
684-
685-
defp expr({:selected_as, _, [_field_expr, _name]}, _sources, _query) do
686-
raise ArgumentError,
687-
"`selected_as/2` can only be used in the outer most `select` expression. " <>
688-
"If you are attempting to alias a field from a subquery, it is not allowed " <>
689-
"because subquery fields are automatically aliased by the corresponding map/struct key."
680+
[quote_name(name)]
690681
end
691682

692683
defp expr({:datetime_add, _, [datetime, count, interval]}, sources, query) do

lib/ecto/adapters/tds/connection.ex

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -409,9 +409,6 @@ if Code.ensure_loaded?(Tds) do
409409
{key, value} ->
410410
[select_expr(value, sources, query), " AS ", quote_name(key)]
411411

412-
{:selected_as, _, [field_expr, name]} ->
413-
[expr(field_expr, sources, query), " AS ", Atom.to_string(name)]
414-
415412
value ->
416413
select_expr(value, sources, query)
417414
end)
@@ -768,14 +765,7 @@ if Code.ensure_loaded?(Tds) do
768765
end
769766

770767
defp expr({:selected_as, _, [name]}, _sources, _query) do
771-
[Atom.to_string(name)]
772-
end
773-
774-
defp expr({:selected_as, _, [_field_expr, _name]}, _sources, _query) do
775-
raise ArgumentError,
776-
"`selected_as/2` can only be used in the outer most `select` expression. " <>
777-
"If you are attempting to alias a field from a subquery, it is not allowed " <>
778-
"because subquery fields are automatically aliased by the corresponding map/struct key."
768+
[quote_name(name)]
779769
end
780770

781771
defp expr({:datetime_add, _, [datetime, count, interval]}, sources, query) do

mix.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"decimal": {:hex, :decimal, "1.9.0", "83e8daf59631d632b171faabafb4a9f4242c514b0a06ba3df493951c08f64d07", [:mix], [], "hexpm", "b1f2343568eed6928f3e751cf2dffde95bfaa19dd95d09e8a9ea92ccfd6f7d85"},
77
"deep_merge": {:hex, :deep_merge, "0.2.0", "c1050fa2edf4848b9f556fba1b75afc66608a4219659e3311d9c9427b5b680b3", [:mix], [], "hexpm", "e3bf435a54ed27b0ba3a01eb117ae017988804e136edcbe8a6a14c310daa966e"},
88
"earmark_parser": {:hex, :earmark_parser, "1.4.25", "2024618731c55ebfcc5439d756852ec4e85978a39d0d58593763924d9a15916f", [:mix], [], "hexpm", "56749c5e1c59447f7b7a23ddb235e4b3defe276afc220a6227237f3efe83f51e"},
9-
"ecto": {:git, "https://github.com/elixir-ecto/ecto.git", "8d1fa601a91a77f5eeb502ad8787f82c80caab8c", []},
9+
"ecto": {:git, "https://github.com/elixir-ecto/ecto.git", "8831fe1fa8223c6db863559c41f68733eec301f6", []},
1010
"ex_doc": {:hex, :ex_doc, "0.28.4", "001a0ea6beac2f810f1abc3dbf4b123e9593eaa5f00dd13ded024eae7c523298", [:mix], [{:earmark_parser, "~> 1.4.19", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "bf85d003dd34911d89c8ddb8bda1a958af3471a274a4c2150a9c01c78ac3f8ed"},
1111
"jason": {:hex, :jason, "1.3.0", "fa6b82a934feb176263ad2df0dbd91bf633d4a46ebfdffea0c8ae82953714946", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "53fc1f51255390e0ec7e50f9cb41e751c260d065dcba2bf0d08dc51a4002c2ac"},
1212
"makeup": {:hex, :makeup, "1.1.0", "6b67c8bc2882a6b6a445859952a602afc1a41c2e08379ca057c0f525366fc3ca", [:mix], [{:nimble_parsec, "~> 1.2.2 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "0a45ed501f4a8897f580eabf99a2e5234ea3e75a4373c8a52824f6e873be57a6"},

test/ecto/adapters/myxql_test.exs

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -529,32 +529,23 @@ defmodule Ecto.Adapters.MyXQLTest do
529529

530530
test "aliasing a selected value with selected_as/2" do
531531
query = "schema" |> select([s], selected_as(s.x, :integer)) |> plan()
532-
assert all(query) == ~s{SELECT s0.`x` AS integer FROM `schema` AS s0}
532+
assert all(query) == ~s{SELECT s0.`x` AS `integer` FROM `schema` AS s0}
533533

534534
query = "schema" |> select([s], s.x |> coalesce(0) |> sum() |> selected_as(:integer)) |> plan()
535-
assert all(query) == ~s{SELECT sum(coalesce(s0.`x`, 0)) AS integer FROM `schema` AS s0}
536-
end
537-
538-
test "raises if selected_as/2 is used in a subquery" do
539-
message = ~r"`selected_as/2` can only be used in the outer most `select` expression."
540-
541-
assert_raise ArgumentError, message, fn ->
542-
subquery = "schema" |> select([s], %{x: selected_as(s.x, :integer)}) |> subquery() |> plan()
543-
all(subquery)
544-
end
535+
assert all(query) == ~s{SELECT sum(coalesce(s0.`x`, 0)) AS `integer` FROM `schema` AS s0}
545536
end
546537

547538
test "group_by can reference the alias of a selected value with selected_as/1" do
548539
query = "schema" |> select([s], selected_as(s.x, :integer)) |> group_by(selected_as(:integer)) |> plan()
549-
assert all(query) == ~s{SELECT s0.`x` AS integer FROM `schema` AS s0 GROUP BY integer}
540+
assert all(query) == ~s{SELECT s0.`x` AS `integer` FROM `schema` AS s0 GROUP BY `integer`}
550541
end
551542

552543
test "order_by can reference the alias of a selected value with selected_as/1" do
553544
query = "schema" |> select([s], selected_as(s.x, :integer)) |> order_by(selected_as(:integer)) |> plan()
554-
assert all(query) == ~s{SELECT s0.`x` AS integer FROM `schema` AS s0 ORDER BY integer}
545+
assert all(query) == ~s{SELECT s0.`x` AS `integer` FROM `schema` AS s0 ORDER BY `integer`}
555546

556547
query = "schema" |> select([s], selected_as(s.x, :integer)) |> order_by([desc: selected_as(:integer)]) |> plan()
557-
assert all(query) == ~s{SELECT s0.`x` AS integer FROM `schema` AS s0 ORDER BY integer DESC}
548+
assert all(query) == ~s{SELECT s0.`x` AS `integer` FROM `schema` AS s0 ORDER BY `integer` DESC}
558549
end
559550

560551
test "having can reference the alias of a selected value with selected_as/1" do
@@ -565,7 +556,7 @@ defmodule Ecto.Adapters.MyXQLTest do
565556
|> having(selected_as(:integer) > 0)
566557
|> plan()
567558

568-
assert all(query) == ~s{SELECT s0.`x` AS integer FROM `schema` AS s0 GROUP BY integer HAVING (integer > 0)}
559+
assert all(query) == ~s{SELECT s0.`x` AS `integer` FROM `schema` AS s0 GROUP BY `integer` HAVING (`integer` > 0)}
569560
end
570561

571562
test "tagged type" do

test/ecto/adapters/postgres_test.exs

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -577,32 +577,23 @@ defmodule Ecto.Adapters.PostgresTest do
577577

578578
test "aliasing a selected value with selected_as/2" do
579579
query = "schema" |> select([s], selected_as(s.x, :integer)) |> plan()
580-
assert all(query) == ~s{SELECT s0."x" AS integer FROM "schema" AS s0}
580+
assert all(query) == ~s{SELECT s0."x" AS "integer" FROM "schema" AS s0}
581581

582582
query = "schema" |> select([s], s.x |> coalesce(0) |> sum() |> selected_as(:integer)) |> plan()
583-
assert all(query) == ~s{SELECT sum(coalesce(s0."x", 0)) AS integer FROM "schema" AS s0}
584-
end
585-
586-
test "raises if selected_as/2 is used in a subquery" do
587-
message = ~r"`selected_as/2` can only be used in the outer most `select` expression."
588-
589-
assert_raise ArgumentError, message, fn ->
590-
subquery = "schema" |> select([s], %{x: selected_as(s.x, :integer)}) |> subquery() |> plan()
591-
all(subquery)
592-
end
583+
assert all(query) == ~s{SELECT sum(coalesce(s0."x", 0)) AS "integer" FROM "schema" AS s0}
593584
end
594585

595586
test "group_by can reference the alias of a selected value with selected_as/1" do
596587
query = "schema" |> select([s], selected_as(s.x, :integer)) |> group_by(selected_as(:integer)) |> plan()
597-
assert all(query) == ~s{SELECT s0."x" AS integer FROM "schema" AS s0 GROUP BY integer}
588+
assert all(query) == ~s{SELECT s0."x" AS "integer" FROM "schema" AS s0 GROUP BY "integer"}
598589
end
599590

600591
test "order_by can reference the alias of a selected value with selected_as/1" do
601592
query = "schema" |> select([s], selected_as(s.x, :integer)) |> order_by(selected_as(:integer)) |> plan()
602-
assert all(query) == ~s{SELECT s0."x" AS integer FROM "schema" AS s0 ORDER BY integer}
593+
assert all(query) == ~s{SELECT s0."x" AS "integer" FROM "schema" AS s0 ORDER BY "integer"}
603594

604595
query = "schema" |> select([s], selected_as(s.x, :integer)) |> order_by([desc: selected_as(:integer)]) |> plan()
605-
assert all(query) == ~s{SELECT s0."x" AS integer FROM "schema" AS s0 ORDER BY integer DESC}
596+
assert all(query) == ~s{SELECT s0."x" AS "integer" FROM "schema" AS s0 ORDER BY "integer" DESC}
606597
end
607598

608599
test "datetime_add" do

test/ecto/adapters/tds_test.exs

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -643,27 +643,18 @@ defmodule Ecto.Adapters.TdsTest do
643643

644644
test "aliasing a selected value with selected_as/2" do
645645
query = "schema" |> select([s], selected_as(s.x, :integer)) |> plan()
646-
assert all(query) == ~s{SELECT s0.[x] AS integer FROM [schema] AS s0}
646+
assert all(query) == ~s{SELECT s0.[x] AS [integer] FROM [schema] AS s0}
647647

648648
query = "schema" |> select([s], s.x |> coalesce(0) |> sum() |> selected_as(:integer)) |> plan()
649-
assert all(query) == ~s{SELECT sum(coalesce(s0.[x], 0)) AS integer FROM [schema] AS s0}
650-
end
651-
652-
test "raises if selected_as/2 is used in a subquery" do
653-
message = ~r"`selected_as/2` can only be used in the outer most `select` expression."
654-
655-
assert_raise ArgumentError, message, fn ->
656-
subquery = "schema" |> select([s], %{x: selected_as(s.x, :integer)}) |> subquery() |> plan()
657-
all(subquery)
658-
end
649+
assert all(query) == ~s{SELECT sum(coalesce(s0.[x], 0)) AS [integer] FROM [schema] AS s0}
659650
end
660651

661652
test "order_by can reference the alias of a selected value with selected_as/1s" do
662653
query = "schema" |> select([s], selected_as(s.x, :integer)) |> order_by(selected_as(:integer)) |> plan()
663-
assert all(query) == ~s{SELECT s0.[x] AS integer FROM [schema] AS s0 ORDER BY integer}
654+
assert all(query) == ~s{SELECT s0.[x] AS [integer] FROM [schema] AS s0 ORDER BY [integer]}
664655

665656
query = "schema" |> select([s], selected_as(s.x, :integer)) |> order_by([desc: selected_as(:integer)]) |> plan()
666-
assert all(query) == ~s{SELECT s0.[x] AS integer FROM [schema] AS s0 ORDER BY integer DESC}
657+
assert all(query) == ~s{SELECT s0.[x] AS [integer] FROM [schema] AS s0 ORDER BY [integer] DESC}
667658
end
668659

669660
test "tagged type" do

0 commit comments

Comments
 (0)