From 9f44bc24e7501b3a13a7c6ea3aca9aac76f3a58b Mon Sep 17 00:00:00 2001 From: Gigitsu Date: Sat, 25 Nov 2023 18:05:39 +0100 Subject: [PATCH 01/38] Add basic bitwise operators support --- lib/ecto/adapters/postgres/connection.ex | 4 ++++ test/ecto/adapters/postgres_test.exs | 12 ++++++++++++ 2 files changed, 16 insertions(+) diff --git a/lib/ecto/adapters/postgres/connection.ex b/lib/ecto/adapters/postgres/connection.ex index 0b74241a..87a3ffe3 100644 --- a/lib/ecto/adapters/postgres/connection.ex +++ b/lib/ecto/adapters/postgres/connection.ex @@ -428,6 +428,10 @@ if Code.ensure_loaded?(Postgrex) do -: " - ", *: " * ", /: " / ", + &&&: " & ", + |||: " | ", + <<<: " << ", + >>>: " >> ", and: " AND ", or: " OR ", ilike: " ILIKE ", diff --git a/test/ecto/adapters/postgres_test.exs b/test/ecto/adapters/postgres_test.exs index eb1dcaaa..f6b857e0 100644 --- a/test/ecto/adapters/postgres_test.exs +++ b/test/ecto/adapters/postgres_test.exs @@ -774,6 +774,18 @@ defmodule Ecto.Adapters.PostgresTest do query = Schema |> select([r], r.x + 2) |> plan() assert all(query) == ~s{SELECT s0."x" + 2 FROM "schema" AS s0} + + query = Schema |> select([r], r.x &&& 2) |> plan() + assert all(query) == ~s{SELECT s0."x" & 2 FROM "schema" AS s0} + + query = Schema |> select([r], r.x ||| 2) |> plan() + assert all(query) == ~s{SELECT s0."x" | 2 FROM "schema" AS s0} + + query = Schema |> select([r], r.x <<< 2) |> plan() + assert all(query) == ~s{SELECT s0."x" << 2 FROM "schema" AS s0} + + query = Schema |> select([r], r.x >>> 2) |> plan() + assert all(query) == ~s{SELECT s0."x" >> 2 FROM "schema" AS s0} end test "is_nil" do From 015674655eff819c0e6c42abce552839617bd9ef Mon Sep 17 00:00:00 2001 From: Gigitsu Date: Sat, 25 Nov 2023 18:53:57 +0100 Subject: [PATCH 02/38] Add unary operator --- lib/ecto/adapters/postgres/connection.ex | 4 ++++ test/ecto/adapters/postgres_test.exs | 5 +++++ 2 files changed, 9 insertions(+) diff --git a/lib/ecto/adapters/postgres/connection.ex b/lib/ecto/adapters/postgres/connection.ex index 87a3ffe3..20116b6f 100644 --- a/lib/ecto/adapters/postgres/connection.ex +++ b/lib/ecto/adapters/postgres/connection.ex @@ -880,6 +880,10 @@ if Code.ensure_loaded?(Postgrex) do ["NOT (", expr(expr, sources, query), ?)] end + defp expr({:~~~, _, [expr]}, sources, query) do + ["~(", expr(expr, sources, query), ?)] + end + defp expr(%Ecto.SubQuery{query: query}, sources, parent_query) do combinations = Enum.map(query.combinations, fn {type, combination_query} -> diff --git a/test/ecto/adapters/postgres_test.exs b/test/ecto/adapters/postgres_test.exs index f6b857e0..713ba5fe 100644 --- a/test/ecto/adapters/postgres_test.exs +++ b/test/ecto/adapters/postgres_test.exs @@ -777,7 +777,9 @@ defmodule Ecto.Adapters.PostgresTest do query = Schema |> select([r], r.x &&& 2) |> plan() assert all(query) == ~s{SELECT s0."x" & 2 FROM "schema" AS s0} + end + test "bitwise ops" do query = Schema |> select([r], r.x ||| 2) |> plan() assert all(query) == ~s{SELECT s0."x" | 2 FROM "schema" AS s0} @@ -786,6 +788,9 @@ defmodule Ecto.Adapters.PostgresTest do query = Schema |> select([r], r.x >>> 2) |> plan() assert all(query) == ~s{SELECT s0."x" >> 2 FROM "schema" AS s0} + + query = Schema |> select([r], ~~~r.x) |> plan() + assert all(query) == ~s{SELECT ~(s0."x") FROM "schema" AS s0} end test "is_nil" do From a0a46a7a0f7d918e89130a0676e32695357f3177 Mon Sep 17 00:00:00 2001 From: Gigitsu Date: Sat, 25 Nov 2023 19:46:53 +0100 Subject: [PATCH 03/38] Add bitwise function and better handling parenthesis --- lib/ecto/adapters/postgres/connection.ex | 11 +++++--- test/ecto/adapters/postgres_test.exs | 34 +++++++++++++++++++++--- 2 files changed, 39 insertions(+), 6 deletions(-) diff --git a/lib/ecto/adapters/postgres/connection.ex b/lib/ecto/adapters/postgres/connection.ex index 20116b6f..323ecf8f 100644 --- a/lib/ecto/adapters/postgres/connection.ex +++ b/lib/ecto/adapters/postgres/connection.ex @@ -435,7 +435,12 @@ if Code.ensure_loaded?(Postgrex) do and: " AND ", or: " OR ", ilike: " ILIKE ", - like: " LIKE " + like: " LIKE ", + band: " & ", + bor: " | ", + bxor: " # ", + bsl: " << ", + bsr: " >> " ] @binary_ops Keyword.keys(binary_ops) @@ -880,8 +885,8 @@ if Code.ensure_loaded?(Postgrex) do ["NOT (", expr(expr, sources, query), ?)] end - defp expr({:~~~, _, [expr]}, sources, query) do - ["~(", expr(expr, sources, query), ?)] + defp expr({bnot, _, [expr]}, sources, query) when bnot in ~w(~~~ bnot)a do + ["~" | maybe_paren(expr, sources, query)] end defp expr(%Ecto.SubQuery{query: query}, sources, parent_query) do diff --git a/test/ecto/adapters/postgres_test.exs b/test/ecto/adapters/postgres_test.exs index 713ba5fe..21600670 100644 --- a/test/ecto/adapters/postgres_test.exs +++ b/test/ecto/adapters/postgres_test.exs @@ -777,9 +777,7 @@ defmodule Ecto.Adapters.PostgresTest do query = Schema |> select([r], r.x &&& 2) |> plan() assert all(query) == ~s{SELECT s0."x" & 2 FROM "schema" AS s0} - end - test "bitwise ops" do query = Schema |> select([r], r.x ||| 2) |> plan() assert all(query) == ~s{SELECT s0."x" | 2 FROM "schema" AS s0} @@ -789,8 +787,38 @@ defmodule Ecto.Adapters.PostgresTest do query = Schema |> select([r], r.x >>> 2) |> plan() assert all(query) == ~s{SELECT s0."x" >> 2 FROM "schema" AS s0} + end + + test "unary ops" do query = Schema |> select([r], ~~~r.x) |> plan() - assert all(query) == ~s{SELECT ~(s0."x") FROM "schema" AS s0} + assert all(query) == ~s{SELECT ~s0."x" FROM "schema" AS s0} + end + + test "bitwise functions" do + query = Schema |> select([r], band(r.x, 2)) |> plan() + assert all(query) == ~s{SELECT s0."x" & 2 FROM "schema" AS s0} + + query = Schema |> select([r], bor(r.x, 2)) |> plan() + assert all(query) == ~s{SELECT s0."x" | 2 FROM "schema" AS s0} + + query = Schema |> select([r], bxor(r.x, 2)) |> plan() + assert all(query) == ~s{SELECT s0."x" # 2 FROM "schema" AS s0} + + query = Schema |> select([r], bsl(r.x, 2)) |> plan() + assert all(query) == ~s{SELECT s0."x" << 2 FROM "schema" AS s0} + + query = Schema |> select([r], bsr(r.x, 2)) |> plan() + assert all(query) == ~s{SELECT s0."x" >> 2 FROM "schema" AS s0} + + query = Schema |> select([r], bnot(r.x)) |> plan() + assert all(query) == ~s{SELECT ~s0."x" FROM "schema" AS s0} + + # test parenthesis + query = Schema |> select([r], band(r.x ||| 1, 2)) |> plan() + assert all(query) == ~s{SELECT (s0."x" | 1) & 2 FROM "schema" AS s0} + + query = Schema |> select([r], bnot(r.x &&& 1)) |> plan() + assert all(query) == ~s{SELECT ~(s0."x" & 1) FROM "schema" AS s0} end test "is_nil" do From 5ecfbf24c6238acd573adcfe21a5f8c156b56ad3 Mon Sep 17 00:00:00 2001 From: Gigitsu Date: Sat, 25 Nov 2023 20:05:59 +0100 Subject: [PATCH 04/38] Add bitwise support to myxql --- lib/ecto/adapters/myxql/connection.ex | 15 ++++++++- test/ecto/adapters/myxql_test.exs | 45 +++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 1 deletion(-) diff --git a/lib/ecto/adapters/myxql/connection.ex b/lib/ecto/adapters/myxql/connection.ex index 39f31964..455be3e3 100644 --- a/lib/ecto/adapters/myxql/connection.ex +++ b/lib/ecto/adapters/myxql/connection.ex @@ -301,9 +301,18 @@ if Code.ensure_loaded?(MyXQL) do -: " - ", *: " * ", /: " / ", + &&&: " & ", + |||: " | ", + <<<: " << ", + >>>: " >> ", and: " AND ", or: " OR ", - like: " LIKE " + like: " LIKE ", + band: " & ", + bor: " | ", + bxor: " ^ ", + bsl: " << ", + bsr: " >> " ] @binary_ops Keyword.keys(binary_ops) @@ -683,6 +692,10 @@ if Code.ensure_loaded?(MyXQL) do ["NOT (", expr(expr, sources, query), ?)] end + defp expr({bnot, _, [expr]}, sources, query) when bnot in ~w(~~~ bnot)a do + ["~" | op_to_binary(expr, sources, query)] + end + defp expr({:filter, _, _}, _sources, query) do error!(query, "MySQL adapter does not support aggregate filters") end diff --git a/test/ecto/adapters/myxql_test.exs b/test/ecto/adapters/myxql_test.exs index 8cc5dd48..f21d78a7 100644 --- a/test/ecto/adapters/myxql_test.exs +++ b/test/ecto/adapters/myxql_test.exs @@ -578,6 +578,51 @@ defmodule Ecto.Adapters.MyXQLTest do query = Schema |> select([r], r.x + 2) |> plan() assert all(query) == ~s{SELECT s0.`x` + 2 FROM `schema` AS s0} + + query = Schema |> select([r], r.x &&& 2) |> plan() + assert all(query) == ~s{SELECT s0.`x` & 2 FROM `schema` AS s0} + + query = Schema |> select([r], r.x ||| 2) |> plan() + assert all(query) == ~s{SELECT s0.`x` | 2 FROM `schema` AS s0} + + query = Schema |> select([r], r.x <<< 2) |> plan() + assert all(query) == ~s{SELECT s0.`x` << 2 FROM `schema` AS s0} + + query = Schema |> select([r], r.x >>> 2) |> plan() + assert all(query) == ~s{SELECT s0.`x` >> 2 FROM `schema` AS s0} + + end + + test "unary ops" do + query = Schema |> select([r], ~~~r.x) |> plan() + assert all(query) == ~s{SELECT ~s0.`x` FROM `schema` AS s0} + end + + test "bitwise functions" do + query = Schema |> select([r], band(r.x, 2)) |> plan() + assert all(query) == ~s{SELECT s0.`x` & 2 FROM `schema` AS s0} + + query = Schema |> select([r], bor(r.x, 2)) |> plan() + assert all(query) == ~s{SELECT s0.`x` | 2 FROM `schema` AS s0} + + query = Schema |> select([r], bxor(r.x, 2)) |> plan() + assert all(query) == ~s{SELECT s0.`x` ^ 2 FROM `schema` AS s0} + + query = Schema |> select([r], bsl(r.x, 2)) |> plan() + assert all(query) == ~s{SELECT s0.`x` << 2 FROM `schema` AS s0} + + query = Schema |> select([r], bsr(r.x, 2)) |> plan() + assert all(query) == ~s{SELECT s0.`x` >> 2 FROM `schema` AS s0} + + query = Schema |> select([r], bnot(r.x)) |> plan() + assert all(query) == ~s{SELECT ~s0.`x` FROM `schema` AS s0} + + # test parenthesis + query = Schema |> select([r], band(r.x ||| 1, 2)) |> plan() + assert all(query) == ~s{SELECT (s0.`x` | 1) & 2 FROM `schema` AS s0} + + query = Schema |> select([r], bnot(r.x &&& 1)) |> plan() + assert all(query) == ~s{SELECT ~(s0.`x` & 1) FROM `schema` AS s0} end test "is_nil" do From 6ffd8d1be9a3dd713b674597586ce82a9c31cf58 Mon Sep 17 00:00:00 2001 From: Gigitsu Date: Sat, 25 Nov 2023 20:12:56 +0100 Subject: [PATCH 05/38] Format --- test/ecto/adapters/myxql_test.exs | 1 - test/ecto/adapters/postgres_test.exs | 1 - 2 files changed, 2 deletions(-) diff --git a/test/ecto/adapters/myxql_test.exs b/test/ecto/adapters/myxql_test.exs index f21d78a7..2493c9e3 100644 --- a/test/ecto/adapters/myxql_test.exs +++ b/test/ecto/adapters/myxql_test.exs @@ -590,7 +590,6 @@ defmodule Ecto.Adapters.MyXQLTest do query = Schema |> select([r], r.x >>> 2) |> plan() assert all(query) == ~s{SELECT s0.`x` >> 2 FROM `schema` AS s0} - end test "unary ops" do diff --git a/test/ecto/adapters/postgres_test.exs b/test/ecto/adapters/postgres_test.exs index 21600670..f802547f 100644 --- a/test/ecto/adapters/postgres_test.exs +++ b/test/ecto/adapters/postgres_test.exs @@ -786,7 +786,6 @@ defmodule Ecto.Adapters.PostgresTest do query = Schema |> select([r], r.x >>> 2) |> plan() assert all(query) == ~s{SELECT s0."x" >> 2 FROM "schema" AS s0} - end test "unary ops" do From b8693454f3e6b82f9cf2989831b84c221b452f39 Mon Sep 17 00:00:00 2001 From: Gigitsu Date: Sat, 25 Nov 2023 20:38:16 +0100 Subject: [PATCH 06/38] Add migration support to binary types --- lib/ecto/adapters/myxql/connection.ex | 1 + lib/ecto/adapters/postgres/connection.ex | 1 + test/ecto/adapters/myxql_test.exs | 6 ++++-- test/ecto/adapters/postgres_test.exs | 2 ++ 4 files changed, 8 insertions(+), 2 deletions(-) diff --git a/lib/ecto/adapters/myxql/connection.ex b/lib/ecto/adapters/myxql/connection.ex index 455be3e3..105a8b17 100644 --- a/lib/ecto/adapters/myxql/connection.ex +++ b/lib/ecto/adapters/myxql/connection.ex @@ -1474,6 +1474,7 @@ if Code.ensure_loaded?(MyXQL) do defp ecto_to_db(:bigserial, _query), do: "bigint unsigned not null auto_increment" defp ecto_to_db(:binary_id, _query), do: "binary(16)" defp ecto_to_db(:string, _query), do: "varchar" + defp ecto_to_db(:bitstring, _query), do: "varbinary" defp ecto_to_db(:float, _query), do: "double" defp ecto_to_db(:binary, _query), do: "blob" # MySQL does not support uuid diff --git a/lib/ecto/adapters/postgres/connection.ex b/lib/ecto/adapters/postgres/connection.ex index 323ecf8f..839a7a39 100644 --- a/lib/ecto/adapters/postgres/connection.ex +++ b/lib/ecto/adapters/postgres/connection.ex @@ -1883,6 +1883,7 @@ if Code.ensure_loaded?(Postgrex) do defp ecto_to_db(:bigserial), do: "bigserial" defp ecto_to_db(:binary_id), do: "uuid" defp ecto_to_db(:string), do: "varchar" + defp ecto_to_db(:bitstring), do: "bit varying" defp ecto_to_db(:binary), do: "bytea" defp ecto_to_db(:map), do: Application.fetch_env!(:ecto_sql, :postgres_map_type) defp ecto_to_db({:map, _}), do: Application.fetch_env!(:ecto_sql, :postgres_map_type) diff --git a/test/ecto/adapters/myxql_test.exs b/test/ecto/adapters/myxql_test.exs index 2493c9e3..807c1ae4 100644 --- a/test/ecto/adapters/myxql_test.exs +++ b/test/ecto/adapters/myxql_test.exs @@ -1623,7 +1623,8 @@ defmodule Ecto.Adapters.MyXQLTest do {:add, :on_hand, :integer, [default: 0, null: true]}, {:add, :likes, :"smallint unsigned", [default: 0, null: false]}, {:add, :published_at, :"datetime(6)", [null: true]}, - {:add, :is_active, :boolean, [default: true]} + {:add, :is_active, :boolean, [default: true]}, + {:add, :token, :bitstring, [size: 23]} ]} assert execute_ddl(create) == [ @@ -1634,7 +1635,8 @@ defmodule Ecto.Adapters.MyXQLTest do `on_hand` integer DEFAULT 0 NULL, `likes` smallint unsigned DEFAULT 0 NOT NULL, `published_at` datetime(6) NULL, - `is_active` boolean DEFAULT true) ENGINE = INNODB + `is_active` boolean DEFAULT true, + `token` varbinary(23)) ENGINE = INNODB """ |> remove_newlines ] diff --git a/test/ecto/adapters/postgres_test.exs b/test/ecto/adapters/postgres_test.exs index f802547f..e11c8843 100644 --- a/test/ecto/adapters/postgres_test.exs +++ b/test/ecto/adapters/postgres_test.exs @@ -2034,6 +2034,7 @@ defmodule Ecto.Adapters.PostgresTest do {:add, :on_hand, :integer, [default: 0, null: true]}, {:add, :published_at, :"time without time zone", [null: true]}, {:add, :is_active, :boolean, [default: true]}, + {:add, :token, :bitstring, [size: 23]}, {:add, :tags, {:array, :string}, [default: []]}, {:add, :languages, {:array, :string}, [default: ["pt", "es"]]}, {:add, :limits, {:array, :integer}, [default: [100, 30_000]]} @@ -2046,6 +2047,7 @@ defmodule Ecto.Adapters.PostgresTest do "on_hand" integer DEFAULT 0 NULL, "published_at" time without time zone NULL, "is_active" boolean DEFAULT true, + "token" bit varying(23), "tags" varchar(255)[] DEFAULT ARRAY[]::varchar[], "languages" varchar(255)[] DEFAULT ARRAY['pt','es']::varchar[], "limits" integer[] DEFAULT ARRAY[100,30000]::integer[]) From 253837d987796de9b82a79e7069dd96c061d6e99 Mon Sep 17 00:00:00 2001 From: Gigitsu Date: Sun, 26 Nov 2023 09:44:07 +0100 Subject: [PATCH 07/38] Change ecto main repo and branch --- mix.exs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mix.exs b/mix.exs index b5d9f2d7..c335912b 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.11.0"} + {:ecto, git: "https://github.com/Gigitsu/ecto.git", branch: "feature/bitstring-support"} end end From f59bc9d9f71e6ac33c97200e48e7d6ab21afe761 Mon Sep 17 00:00:00 2001 From: Gigitsu Date: Sun, 26 Nov 2023 13:18:16 +0100 Subject: [PATCH 08/38] Handle typecast parenthesis for bnot --- lib/ecto/adapters/myxql/connection.ex | 2 +- lib/ecto/adapters/postgres/connection.ex | 5 ++++- test/ecto/adapters/myxql_test.exs | 7 +++++-- test/ecto/adapters/postgres_test.exs | 7 +++++-- 4 files changed, 15 insertions(+), 6 deletions(-) diff --git a/lib/ecto/adapters/myxql/connection.ex b/lib/ecto/adapters/myxql/connection.ex index 105a8b17..af80ef67 100644 --- a/lib/ecto/adapters/myxql/connection.ex +++ b/lib/ecto/adapters/myxql/connection.ex @@ -693,7 +693,7 @@ if Code.ensure_loaded?(MyXQL) do end defp expr({bnot, _, [expr]}, sources, query) when bnot in ~w(~~~ bnot)a do - ["~" | op_to_binary(expr, sources, query)] + ["~(", expr(expr, sources, query), ?)] end defp expr({:filter, _, _}, _sources, query) do diff --git a/lib/ecto/adapters/postgres/connection.ex b/lib/ecto/adapters/postgres/connection.ex index 839a7a39..09a5e334 100644 --- a/lib/ecto/adapters/postgres/connection.ex +++ b/lib/ecto/adapters/postgres/connection.ex @@ -886,7 +886,7 @@ if Code.ensure_loaded?(Postgrex) do end defp expr({bnot, _, [expr]}, sources, query) when bnot in ~w(~~~ bnot)a do - ["~" | maybe_paren(expr, sources, query)] + ["~(", expr(expr, sources, query), ?)] end defp expr(%Ecto.SubQuery{query: query}, sources, parent_query) do @@ -1108,6 +1108,9 @@ if Code.ensure_loaded?(Postgrex) do defp maybe_paren({:is_nil, _, [_]} = expr, sources, query), do: paren_expr(expr, sources, query) + defp maybe_paren({bnot, _, [_]} = expr, sources, query) when bnot in ~w(~~~ bnot)a, + do: paren_expr(expr, sources, query) + defp maybe_paren(expr, sources, query), do: expr(expr, sources, query) diff --git a/test/ecto/adapters/myxql_test.exs b/test/ecto/adapters/myxql_test.exs index 807c1ae4..123c5345 100644 --- a/test/ecto/adapters/myxql_test.exs +++ b/test/ecto/adapters/myxql_test.exs @@ -594,7 +594,7 @@ defmodule Ecto.Adapters.MyXQLTest do test "unary ops" do query = Schema |> select([r], ~~~r.x) |> plan() - assert all(query) == ~s{SELECT ~s0.`x` FROM `schema` AS s0} + assert all(query) == ~s{SELECT ~(s0.`x`) FROM `schema` AS s0} end test "bitwise functions" do @@ -614,7 +614,7 @@ defmodule Ecto.Adapters.MyXQLTest do assert all(query) == ~s{SELECT s0.`x` >> 2 FROM `schema` AS s0} query = Schema |> select([r], bnot(r.x)) |> plan() - assert all(query) == ~s{SELECT ~s0.`x` FROM `schema` AS s0} + assert all(query) == ~s{SELECT ~(s0.`x`) FROM `schema` AS s0} # test parenthesis query = Schema |> select([r], band(r.x ||| 1, 2)) |> plan() @@ -749,6 +749,9 @@ defmodule Ecto.Adapters.MyXQLTest do end test "tagged type" do + query = Schema |> select([t], type(~~~t.x, :integer)) |> plan() + assert all(query) == ~s{SELECT CAST(~(s0.`x`) AS unsigned) FROM `schema` AS s0} + query = Schema |> select([], type(^"601d74e4-a8d3-4b6e-8365-eddb4c893327", Ecto.UUID)) |> plan() diff --git a/test/ecto/adapters/postgres_test.exs b/test/ecto/adapters/postgres_test.exs index e11c8843..06d1fbf8 100644 --- a/test/ecto/adapters/postgres_test.exs +++ b/test/ecto/adapters/postgres_test.exs @@ -790,7 +790,7 @@ defmodule Ecto.Adapters.PostgresTest do test "unary ops" do query = Schema |> select([r], ~~~r.x) |> plan() - assert all(query) == ~s{SELECT ~s0."x" FROM "schema" AS s0} + assert all(query) == ~s{SELECT ~(s0."x") FROM "schema" AS s0} end test "bitwise functions" do @@ -810,7 +810,7 @@ defmodule Ecto.Adapters.PostgresTest do assert all(query) == ~s{SELECT s0."x" >> 2 FROM "schema" AS s0} query = Schema |> select([r], bnot(r.x)) |> plan() - assert all(query) == ~s{SELECT ~s0."x" FROM "schema" AS s0} + assert all(query) == ~s{SELECT ~(s0."x") FROM "schema" AS s0} # test parenthesis query = Schema |> select([r], band(r.x ||| 1, 2)) |> plan() @@ -948,6 +948,9 @@ defmodule Ecto.Adapters.PostgresTest do query = Schema |> select([t], type(t.x + t.y, :integer)) |> plan() assert all(query) == ~s{SELECT (s0."x" + s0."y")::bigint FROM "schema" AS s0} + query = Schema |> select([t], type(~~~t.x, :integer)) |> plan() + assert all(query) == ~s{SELECT (~(s0."x"))::bigint FROM "schema" AS s0} + query = Schema |> select([], type(^"601d74e4-a8d3-4b6e-8365-eddb4c893327", Ecto.UUID)) |> plan() From c80c2a6a5a9e98f49d42de18e0d5c583d2047f79 Mon Sep 17 00:00:00 2001 From: Gigitsu Date: Sun, 26 Nov 2023 13:22:56 +0100 Subject: [PATCH 09/38] Add bnot op_to_binary case --- lib/ecto/adapters/myxql/connection.ex | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/ecto/adapters/myxql/connection.ex b/lib/ecto/adapters/myxql/connection.ex index af80ef67..a034b6b1 100644 --- a/lib/ecto/adapters/myxql/connection.ex +++ b/lib/ecto/adapters/myxql/connection.ex @@ -886,6 +886,9 @@ if Code.ensure_loaded?(MyXQL) do defp op_to_binary({:is_nil, _, [_]} = expr, sources, query), do: paren_expr(expr, sources, query) + defp op_to_binary({bnot, _, [_]} = expr, sources, query) when bnot in ~w(~~~ bnot)a, + do: paren_expr(expr, sources, query) + defp op_to_binary(expr, sources, query), do: expr(expr, sources, query) From 1ca7cb6857f0140afd1c3dc64267a2cf8ab0c3d8 Mon Sep 17 00:00:00 2001 From: Gigitsu Date: Sun, 26 Nov 2023 15:41:39 +0100 Subject: [PATCH 10/38] Reorder functions --- lib/ecto/adapters/myxql/connection.ex | 4 ++-- lib/ecto/adapters/postgres/connection.ex | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/ecto/adapters/myxql/connection.ex b/lib/ecto/adapters/myxql/connection.ex index a034b6b1..3e105ce3 100644 --- a/lib/ecto/adapters/myxql/connection.ex +++ b/lib/ecto/adapters/myxql/connection.ex @@ -883,10 +883,10 @@ if Code.ensure_loaded?(MyXQL) do defp op_to_binary({op, _, [_, _]} = expr, sources, query) when op in @binary_ops, do: paren_expr(expr, sources, query) - defp op_to_binary({:is_nil, _, [_]} = expr, sources, query), + defp op_to_binary({bnot, _, [_]} = expr, sources, query) when bnot in ~w(~~~ bnot)a, do: paren_expr(expr, sources, query) - defp op_to_binary({bnot, _, [_]} = expr, sources, query) when bnot in ~w(~~~ bnot)a, + defp op_to_binary({:is_nil, _, [_]} = expr, sources, query), do: paren_expr(expr, sources, query) defp op_to_binary(expr, sources, query), diff --git a/lib/ecto/adapters/postgres/connection.ex b/lib/ecto/adapters/postgres/connection.ex index 09a5e334..a1fc20eb 100644 --- a/lib/ecto/adapters/postgres/connection.ex +++ b/lib/ecto/adapters/postgres/connection.ex @@ -1105,10 +1105,10 @@ if Code.ensure_loaded?(Postgrex) do defp maybe_paren({op, _, [_, _]} = expr, sources, query) when op in @binary_ops, do: paren_expr(expr, sources, query) - defp maybe_paren({:is_nil, _, [_]} = expr, sources, query), + defp maybe_paren({bnot, _, [_]} = expr, sources, query) when bnot in ~w(~~~ bnot)a, do: paren_expr(expr, sources, query) - defp maybe_paren({bnot, _, [_]} = expr, sources, query) when bnot in ~w(~~~ bnot)a, + defp maybe_paren({:is_nil, _, [_]} = expr, sources, query), do: paren_expr(expr, sources, query) defp maybe_paren(expr, sources, query), From 894082d295bb1e85b7cbe724ac0d063acdc82e28 Mon Sep 17 00:00:00 2001 From: Gigitsu Date: Sun, 26 Nov 2023 17:38:04 +0100 Subject: [PATCH 11/38] Use bit as type for bitstring --- lib/ecto/adapters/myxql/connection.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ecto/adapters/myxql/connection.ex b/lib/ecto/adapters/myxql/connection.ex index 3e105ce3..27d7d6ec 100644 --- a/lib/ecto/adapters/myxql/connection.ex +++ b/lib/ecto/adapters/myxql/connection.ex @@ -1477,7 +1477,7 @@ if Code.ensure_loaded?(MyXQL) do defp ecto_to_db(:bigserial, _query), do: "bigint unsigned not null auto_increment" defp ecto_to_db(:binary_id, _query), do: "binary(16)" defp ecto_to_db(:string, _query), do: "varchar" - defp ecto_to_db(:bitstring, _query), do: "varbinary" + defp ecto_to_db(:bitstring, _query), do: "bit" defp ecto_to_db(:float, _query), do: "double" defp ecto_to_db(:binary, _query), do: "blob" # MySQL does not support uuid From ae107b8371f38a2409efa844428af3b55b49317c Mon Sep 17 00:00:00 2001 From: Gigitsu Date: Sun, 26 Nov 2023 17:38:22 +0100 Subject: [PATCH 12/38] Implement type casting with size --- lib/ecto/adapters/myxql/connection.ex | 4 ++++ lib/ecto/adapters/postgres/connection.ex | 4 ++++ test/ecto/adapters/myxql_test.exs | 6 +++--- test/ecto/adapters/postgres_test.exs | 4 ++-- 4 files changed, 13 insertions(+), 5 deletions(-) diff --git a/lib/ecto/adapters/myxql/connection.ex b/lib/ecto/adapters/myxql/connection.ex index 27d7d6ec..4db7be81 100644 --- a/lib/ecto/adapters/myxql/connection.ex +++ b/lib/ecto/adapters/myxql/connection.ex @@ -1465,6 +1465,10 @@ if Code.ensure_loaded?(MyXQL) do defp ecto_cast_to_db(:string, _query), do: "char" defp ecto_cast_to_db(:utc_datetime_usec, _query), do: "datetime(6)" defp ecto_cast_to_db(:naive_datetime_usec, _query), do: "datetime(6)" + + defp ecto_cast_to_db({type, size}, query) when is_number(size), + do: [ecto_to_db(type, query), ?(, to_string(size), ?)] + defp ecto_cast_to_db(type, query), do: ecto_to_db(type, query) defp ecto_size_to_db(:binary), do: "varbinary" diff --git a/lib/ecto/adapters/postgres/connection.ex b/lib/ecto/adapters/postgres/connection.ex index a1fc20eb..81a0a00d 100644 --- a/lib/ecto/adapters/postgres/connection.ex +++ b/lib/ecto/adapters/postgres/connection.ex @@ -1087,6 +1087,10 @@ if Code.ensure_loaded?(Postgrex) do defp tagged_to_db(:id), do: "bigint" defp tagged_to_db(:integer), do: "bigint" defp tagged_to_db({:array, type}), do: [tagged_to_db(type), ?[, ?]] + + defp tagged_to_db({type, size}) when is_number(size), + do: [ecto_to_db(type), ?(, to_string(size), ?)] + defp tagged_to_db(type), do: ecto_to_db(type) defp interval(count, interval, _sources, _query) when is_integer(count) do diff --git a/test/ecto/adapters/myxql_test.exs b/test/ecto/adapters/myxql_test.exs index 123c5345..9d6a05e4 100644 --- a/test/ecto/adapters/myxql_test.exs +++ b/test/ecto/adapters/myxql_test.exs @@ -749,8 +749,8 @@ defmodule Ecto.Adapters.MyXQLTest do end test "tagged type" do - query = Schema |> select([t], type(~~~t.x, :integer)) |> plan() - assert all(query) == ~s{SELECT CAST(~(s0.`x`) AS unsigned) FROM `schema` AS s0} + query = Schema |> select([t], type(~~~t.x, bitstring: 5)) |> plan() + assert all(query) == ~s{SELECT CAST(~(s0.`x`) AS bit(5)) FROM `schema` AS s0} query = Schema |> select([], type(^"601d74e4-a8d3-4b6e-8365-eddb4c893327", Ecto.UUID)) |> plan() @@ -1639,7 +1639,7 @@ defmodule Ecto.Adapters.MyXQLTest do `likes` smallint unsigned DEFAULT 0 NOT NULL, `published_at` datetime(6) NULL, `is_active` boolean DEFAULT true, - `token` varbinary(23)) ENGINE = INNODB + `token` bit(23)) ENGINE = INNODB """ |> remove_newlines ] diff --git a/test/ecto/adapters/postgres_test.exs b/test/ecto/adapters/postgres_test.exs index 06d1fbf8..188cd982 100644 --- a/test/ecto/adapters/postgres_test.exs +++ b/test/ecto/adapters/postgres_test.exs @@ -948,8 +948,8 @@ defmodule Ecto.Adapters.PostgresTest do query = Schema |> select([t], type(t.x + t.y, :integer)) |> plan() assert all(query) == ~s{SELECT (s0."x" + s0."y")::bigint FROM "schema" AS s0} - query = Schema |> select([t], type(~~~t.x, :integer)) |> plan() - assert all(query) == ~s{SELECT (~(s0."x"))::bigint FROM "schema" AS s0} + query = Schema |> select([t], type(~~~t.x, bitstring: 5)) |> plan() + assert all(query) == ~s{SELECT (~(s0."x"))::bit varying(5) FROM "schema" AS s0} query = Schema |> select([], type(^"601d74e4-a8d3-4b6e-8365-eddb4c893327", Ecto.UUID)) |> plan() From ce31aefda19a08840b719cf340ad3d3ca396e816 Mon Sep 17 00:00:00 2001 From: Gigitsu Date: Sun, 26 Nov 2023 18:56:06 +0100 Subject: [PATCH 13/38] Revert "Implement type casting with size" This reverts commit c36f274df4804e13a73f95e8cad3057ba99fc526. --- lib/ecto/adapters/myxql/connection.ex | 4 ---- lib/ecto/adapters/postgres/connection.ex | 4 ---- test/ecto/adapters/myxql_test.exs | 6 +++--- test/ecto/adapters/postgres_test.exs | 4 ++-- 4 files changed, 5 insertions(+), 13 deletions(-) diff --git a/lib/ecto/adapters/myxql/connection.ex b/lib/ecto/adapters/myxql/connection.ex index 4db7be81..27d7d6ec 100644 --- a/lib/ecto/adapters/myxql/connection.ex +++ b/lib/ecto/adapters/myxql/connection.ex @@ -1465,10 +1465,6 @@ if Code.ensure_loaded?(MyXQL) do defp ecto_cast_to_db(:string, _query), do: "char" defp ecto_cast_to_db(:utc_datetime_usec, _query), do: "datetime(6)" defp ecto_cast_to_db(:naive_datetime_usec, _query), do: "datetime(6)" - - defp ecto_cast_to_db({type, size}, query) when is_number(size), - do: [ecto_to_db(type, query), ?(, to_string(size), ?)] - defp ecto_cast_to_db(type, query), do: ecto_to_db(type, query) defp ecto_size_to_db(:binary), do: "varbinary" diff --git a/lib/ecto/adapters/postgres/connection.ex b/lib/ecto/adapters/postgres/connection.ex index 81a0a00d..a1fc20eb 100644 --- a/lib/ecto/adapters/postgres/connection.ex +++ b/lib/ecto/adapters/postgres/connection.ex @@ -1087,10 +1087,6 @@ if Code.ensure_loaded?(Postgrex) do defp tagged_to_db(:id), do: "bigint" defp tagged_to_db(:integer), do: "bigint" defp tagged_to_db({:array, type}), do: [tagged_to_db(type), ?[, ?]] - - defp tagged_to_db({type, size}) when is_number(size), - do: [ecto_to_db(type), ?(, to_string(size), ?)] - defp tagged_to_db(type), do: ecto_to_db(type) defp interval(count, interval, _sources, _query) when is_integer(count) do diff --git a/test/ecto/adapters/myxql_test.exs b/test/ecto/adapters/myxql_test.exs index 9d6a05e4..123c5345 100644 --- a/test/ecto/adapters/myxql_test.exs +++ b/test/ecto/adapters/myxql_test.exs @@ -749,8 +749,8 @@ defmodule Ecto.Adapters.MyXQLTest do end test "tagged type" do - query = Schema |> select([t], type(~~~t.x, bitstring: 5)) |> plan() - assert all(query) == ~s{SELECT CAST(~(s0.`x`) AS bit(5)) FROM `schema` AS s0} + query = Schema |> select([t], type(~~~t.x, :integer)) |> plan() + assert all(query) == ~s{SELECT CAST(~(s0.`x`) AS unsigned) FROM `schema` AS s0} query = Schema |> select([], type(^"601d74e4-a8d3-4b6e-8365-eddb4c893327", Ecto.UUID)) |> plan() @@ -1639,7 +1639,7 @@ defmodule Ecto.Adapters.MyXQLTest do `likes` smallint unsigned DEFAULT 0 NOT NULL, `published_at` datetime(6) NULL, `is_active` boolean DEFAULT true, - `token` bit(23)) ENGINE = INNODB + `token` varbinary(23)) ENGINE = INNODB """ |> remove_newlines ] diff --git a/test/ecto/adapters/postgres_test.exs b/test/ecto/adapters/postgres_test.exs index 188cd982..06d1fbf8 100644 --- a/test/ecto/adapters/postgres_test.exs +++ b/test/ecto/adapters/postgres_test.exs @@ -948,8 +948,8 @@ defmodule Ecto.Adapters.PostgresTest do query = Schema |> select([t], type(t.x + t.y, :integer)) |> plan() assert all(query) == ~s{SELECT (s0."x" + s0."y")::bigint FROM "schema" AS s0} - query = Schema |> select([t], type(~~~t.x, bitstring: 5)) |> plan() - assert all(query) == ~s{SELECT (~(s0."x"))::bit varying(5) FROM "schema" AS s0} + query = Schema |> select([t], type(~~~t.x, :integer)) |> plan() + assert all(query) == ~s{SELECT (~(s0."x"))::bigint FROM "schema" AS s0} query = Schema |> select([], type(^"601d74e4-a8d3-4b6e-8365-eddb4c893327", Ecto.UUID)) |> plan() From 676a6626d42254c7761b0a7272cc03c001c76882 Mon Sep 17 00:00:00 2001 From: Gigitsu Date: Sun, 26 Nov 2023 18:57:10 +0100 Subject: [PATCH 14/38] Fix test --- test/ecto/adapters/myxql_test.exs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/ecto/adapters/myxql_test.exs b/test/ecto/adapters/myxql_test.exs index 123c5345..c5cfef99 100644 --- a/test/ecto/adapters/myxql_test.exs +++ b/test/ecto/adapters/myxql_test.exs @@ -1639,7 +1639,7 @@ defmodule Ecto.Adapters.MyXQLTest do `likes` smallint unsigned DEFAULT 0 NOT NULL, `published_at` datetime(6) NULL, `is_active` boolean DEFAULT true, - `token` varbinary(23)) ENGINE = INNODB + `token` bit(23)) ENGINE = INNODB """ |> remove_newlines ] From 1f1627ee5dac49a2c21e69d73fb82fce0ff591e3 Mon Sep 17 00:00:00 2001 From: Luigi Clemente Date: Tue, 28 Nov 2023 22:12:11 +0100 Subject: [PATCH 15/38] Change Postgres type for bitstring Co-authored-by: Greg Rychlewski --- lib/ecto/adapters/postgres/connection.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ecto/adapters/postgres/connection.ex b/lib/ecto/adapters/postgres/connection.ex index a1fc20eb..c6151318 100644 --- a/lib/ecto/adapters/postgres/connection.ex +++ b/lib/ecto/adapters/postgres/connection.ex @@ -1886,7 +1886,7 @@ if Code.ensure_loaded?(Postgrex) do defp ecto_to_db(:bigserial), do: "bigserial" defp ecto_to_db(:binary_id), do: "uuid" defp ecto_to_db(:string), do: "varchar" - defp ecto_to_db(:bitstring), do: "bit varying" + defp ecto_to_db(:bitstring), do: "varbit" defp ecto_to_db(:binary), do: "bytea" defp ecto_to_db(:map), do: Application.fetch_env!(:ecto_sql, :postgres_map_type) defp ecto_to_db({:map, _}), do: Application.fetch_env!(:ecto_sql, :postgres_map_type) From 8772573cc32e43bd6a06b37f0c1f4241644686f9 Mon Sep 17 00:00:00 2001 From: Gigitsu Date: Tue, 28 Nov 2023 22:25:46 +0100 Subject: [PATCH 16/38] Fix tests --- test/ecto/adapters/postgres_test.exs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/ecto/adapters/postgres_test.exs b/test/ecto/adapters/postgres_test.exs index 06d1fbf8..d40d3501 100644 --- a/test/ecto/adapters/postgres_test.exs +++ b/test/ecto/adapters/postgres_test.exs @@ -2037,7 +2037,7 @@ defmodule Ecto.Adapters.PostgresTest do {:add, :on_hand, :integer, [default: 0, null: true]}, {:add, :published_at, :"time without time zone", [null: true]}, {:add, :is_active, :boolean, [default: true]}, - {:add, :token, :bitstring, [size: 23]}, + {:add, :token, :bitstring, []}, {:add, :tags, {:array, :string}, [default: []]}, {:add, :languages, {:array, :string}, [default: ["pt", "es"]]}, {:add, :limits, {:array, :integer}, [default: [100, 30_000]]} @@ -2050,7 +2050,7 @@ defmodule Ecto.Adapters.PostgresTest do "on_hand" integer DEFAULT 0 NULL, "published_at" time without time zone NULL, "is_active" boolean DEFAULT true, - "token" bit varying(23), + "token" varbit, "tags" varchar(255)[] DEFAULT ARRAY[]::varchar[], "languages" varchar(255)[] DEFAULT ARRAY['pt','es']::varchar[], "limits" integer[] DEFAULT ARRAY[100,30000]::integer[]) From 54ace51de49fec944b0eb5db0c9b2bafef3be93b Mon Sep 17 00:00:00 2001 From: Gigitsu Date: Mon, 4 Dec 2023 11:29:17 +0100 Subject: [PATCH 17/38] Fix integration test for arm powered host --- Earthfile | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/Earthfile b/Earthfile index 480ce47f..faf2b788 100644 --- a/Earthfile +++ b/Earthfile @@ -1,7 +1,7 @@ VERSION 0.6 all: - ARG ELIXIR_BASE=1.15.6-erlang-25.3.2.6-alpine-3.17.4 + ARG ELIXIR_BASE=1.15.6-erlang-25.3.2.6-alpine-3.18.4 BUILD \ --build-arg POSTGRES=15.0 \ --build-arg POSTGRES=11.11 \ @@ -20,7 +20,7 @@ all: +integration-test-mssql setup-base: - ARG ELIXIR_BASE=1.15.6-erlang-25.3.2.6-alpine-3.17.4 + ARG ELIXIR_BASE=1.15.6-erlang-25.3.2.6-alpine-3.18.4 FROM hexpm/elixir:$ELIXIR_BASE RUN apk add --no-progress --update git build-base ENV ELIXIR_ASSERT_TIMEOUT=10000 @@ -62,7 +62,7 @@ integration-test-postgres: # then run the tests WITH DOCKER \ - --pull "postgres:$POSTGRES" + --pull "postgres:$POSTGRES" --platform linux/amd64 RUN set -e; \ timeout=$(expr $(date +%s) + 30); \ docker run --name pg --network=host -d -e POSTGRES_USER=postgres -e POSTGRES_PASSWORD=postgres -e POSTGRES_DB=postgres "postgres:$POSTGRES"; \ @@ -84,7 +84,7 @@ integration-test-mysql: ARG MYSQL="5.7" WITH DOCKER \ - --pull "mysql:$MYSQL" + --pull "mysql:$MYSQL" --platform linux/amd64 RUN set -e; \ timeout=$(expr $(date +%s) + 30); \ docker run --name mysql --network=host -d -e MYSQL_ROOT_PASSWORD=root "mysql:$MYSQL" \ @@ -103,25 +103,26 @@ integration-test-mysql: integration-test-mssql: + ARG TARGETARCH FROM +setup-base RUN apk add --no-cache curl gnupg --virtual .build-dependencies -- && \ - curl -O https://download.microsoft.com/download/e/4/e/e4e67866-dffd-428c-aac7-8d28ddafb39b/msodbcsql17_17.5.2.1-1_amd64.apk && \ - curl -O https://download.microsoft.com/download/e/4/e/e4e67866-dffd-428c-aac7-8d28ddafb39b/mssql-tools_17.5.2.1-1_amd64.apk && \ - echo y | apk add --allow-untrusted msodbcsql17_17.5.2.1-1_amd64.apk mssql-tools_17.5.2.1-1_amd64.apk && \ + curl -O https://download.microsoft.com/download/3/5/5/355d7943-a338-41a7-858d-53b259ea33f5/msodbcsql18_18.3.2.1-1_${TARGETARCH}.apk && \ + curl -O https://download.microsoft.com/download/3/5/5/355d7943-a338-41a7-858d-53b259ea33f5/mssql-tools18_18.3.1.1-1_${TARGETARCH}.apk && \ + echo y | apk add --allow-untrusted msodbcsql18_18.3.2.1-1_${TARGETARCH}.apk mssql-tools18_18.3.1.1-1_${TARGETARCH}.apk && \ apk del .build-dependencies && rm -f msodbcsql*.sig mssql-tools*.apk - ENV PATH="/opt/mssql-tools/bin:${PATH}" + ENV PATH="/opt/mssql-tools18/bin:${PATH}" DO +COMMON_SETUP_AND_MIX ARG MSSQL="2017" WITH DOCKER \ - --pull "mcr.microsoft.com/mssql/server:$MSSQL-latest" + --pull "mcr.microsoft.com/mssql/server:$MSSQL-latest" --platform linux/amd64 RUN set -e; \ timeout=$(expr $(date +%s) + 30); \ docker run -d -p 1433:1433 --name mssql -e 'ACCEPT_EULA=Y' -e 'MSSQL_SA_PASSWORD=some!Password' "mcr.microsoft.com/mssql/server:$MSSQL-latest"; \ # wait for mssql to start - while ! sqlcmd -S tcp:127.0.0.1,1433 -U sa -P 'some!Password' -Q "SELECT 1" >/dev/null 2>&1; do \ + while ! sqlcmd -C -S tcp:127.0.0.1,1433 -U sa -P 'some!Password' -Q "SELECT 1" >/dev/null 2>&1; do \ test "$(date +%s)" -le "$timeout" || (echo "timed out waiting for mssql"; exit 1); \ echo "waiting for mssql"; \ sleep 1; \ From 42ba521f89f652ab5d425fed48724f602e9c6519 Mon Sep 17 00:00:00 2001 From: Gigitsu Date: Sat, 17 Feb 2024 17:29:25 +0100 Subject: [PATCH 18/38] Remove bitwise operators support --- lib/ecto/adapters/myxql/connection.ex | 18 +--------- lib/ecto/adapters/postgres/connection.ex | 18 +--------- test/ecto/adapters/myxql_test.exs | 44 ------------------------ test/ecto/adapters/postgres_test.exs | 44 ------------------------ 4 files changed, 2 insertions(+), 122 deletions(-) diff --git a/lib/ecto/adapters/myxql/connection.ex b/lib/ecto/adapters/myxql/connection.ex index 27d7d6ec..5a8a8d5f 100644 --- a/lib/ecto/adapters/myxql/connection.ex +++ b/lib/ecto/adapters/myxql/connection.ex @@ -301,18 +301,9 @@ if Code.ensure_loaded?(MyXQL) do -: " - ", *: " * ", /: " / ", - &&&: " & ", - |||: " | ", - <<<: " << ", - >>>: " >> ", and: " AND ", or: " OR ", - like: " LIKE ", - band: " & ", - bor: " | ", - bxor: " ^ ", - bsl: " << ", - bsr: " >> " + like: " LIKE " ] @binary_ops Keyword.keys(binary_ops) @@ -692,10 +683,6 @@ if Code.ensure_loaded?(MyXQL) do ["NOT (", expr(expr, sources, query), ?)] end - defp expr({bnot, _, [expr]}, sources, query) when bnot in ~w(~~~ bnot)a do - ["~(", expr(expr, sources, query), ?)] - end - defp expr({:filter, _, _}, _sources, query) do error!(query, "MySQL adapter does not support aggregate filters") end @@ -883,9 +870,6 @@ if Code.ensure_loaded?(MyXQL) do defp op_to_binary({op, _, [_, _]} = expr, sources, query) when op in @binary_ops, do: paren_expr(expr, sources, query) - defp op_to_binary({bnot, _, [_]} = expr, sources, query) when bnot in ~w(~~~ bnot)a, - do: paren_expr(expr, sources, query) - defp op_to_binary({:is_nil, _, [_]} = expr, sources, query), do: paren_expr(expr, sources, query) diff --git a/lib/ecto/adapters/postgres/connection.ex b/lib/ecto/adapters/postgres/connection.ex index c6151318..7de51319 100644 --- a/lib/ecto/adapters/postgres/connection.ex +++ b/lib/ecto/adapters/postgres/connection.ex @@ -428,19 +428,10 @@ if Code.ensure_loaded?(Postgrex) do -: " - ", *: " * ", /: " / ", - &&&: " & ", - |||: " | ", - <<<: " << ", - >>>: " >> ", and: " AND ", or: " OR ", ilike: " ILIKE ", - like: " LIKE ", - band: " & ", - bor: " | ", - bxor: " # ", - bsl: " << ", - bsr: " >> " + like: " LIKE " ] @binary_ops Keyword.keys(binary_ops) @@ -885,10 +876,6 @@ if Code.ensure_loaded?(Postgrex) do ["NOT (", expr(expr, sources, query), ?)] end - defp expr({bnot, _, [expr]}, sources, query) when bnot in ~w(~~~ bnot)a do - ["~(", expr(expr, sources, query), ?)] - end - defp expr(%Ecto.SubQuery{query: query}, sources, parent_query) do combinations = Enum.map(query.combinations, fn {type, combination_query} -> @@ -1105,9 +1092,6 @@ if Code.ensure_loaded?(Postgrex) do defp maybe_paren({op, _, [_, _]} = expr, sources, query) when op in @binary_ops, do: paren_expr(expr, sources, query) - defp maybe_paren({bnot, _, [_]} = expr, sources, query) when bnot in ~w(~~~ bnot)a, - do: paren_expr(expr, sources, query) - defp maybe_paren({:is_nil, _, [_]} = expr, sources, query), do: paren_expr(expr, sources, query) diff --git a/test/ecto/adapters/myxql_test.exs b/test/ecto/adapters/myxql_test.exs index c5cfef99..29d155d9 100644 --- a/test/ecto/adapters/myxql_test.exs +++ b/test/ecto/adapters/myxql_test.exs @@ -578,50 +578,6 @@ defmodule Ecto.Adapters.MyXQLTest do query = Schema |> select([r], r.x + 2) |> plan() assert all(query) == ~s{SELECT s0.`x` + 2 FROM `schema` AS s0} - - query = Schema |> select([r], r.x &&& 2) |> plan() - assert all(query) == ~s{SELECT s0.`x` & 2 FROM `schema` AS s0} - - query = Schema |> select([r], r.x ||| 2) |> plan() - assert all(query) == ~s{SELECT s0.`x` | 2 FROM `schema` AS s0} - - query = Schema |> select([r], r.x <<< 2) |> plan() - assert all(query) == ~s{SELECT s0.`x` << 2 FROM `schema` AS s0} - - query = Schema |> select([r], r.x >>> 2) |> plan() - assert all(query) == ~s{SELECT s0.`x` >> 2 FROM `schema` AS s0} - end - - test "unary ops" do - query = Schema |> select([r], ~~~r.x) |> plan() - assert all(query) == ~s{SELECT ~(s0.`x`) FROM `schema` AS s0} - end - - test "bitwise functions" do - query = Schema |> select([r], band(r.x, 2)) |> plan() - assert all(query) == ~s{SELECT s0.`x` & 2 FROM `schema` AS s0} - - query = Schema |> select([r], bor(r.x, 2)) |> plan() - assert all(query) == ~s{SELECT s0.`x` | 2 FROM `schema` AS s0} - - query = Schema |> select([r], bxor(r.x, 2)) |> plan() - assert all(query) == ~s{SELECT s0.`x` ^ 2 FROM `schema` AS s0} - - query = Schema |> select([r], bsl(r.x, 2)) |> plan() - assert all(query) == ~s{SELECT s0.`x` << 2 FROM `schema` AS s0} - - query = Schema |> select([r], bsr(r.x, 2)) |> plan() - assert all(query) == ~s{SELECT s0.`x` >> 2 FROM `schema` AS s0} - - query = Schema |> select([r], bnot(r.x)) |> plan() - assert all(query) == ~s{SELECT ~(s0.`x`) FROM `schema` AS s0} - - # test parenthesis - query = Schema |> select([r], band(r.x ||| 1, 2)) |> plan() - assert all(query) == ~s{SELECT (s0.`x` | 1) & 2 FROM `schema` AS s0} - - query = Schema |> select([r], bnot(r.x &&& 1)) |> plan() - assert all(query) == ~s{SELECT ~(s0.`x` & 1) FROM `schema` AS s0} end test "is_nil" do diff --git a/test/ecto/adapters/postgres_test.exs b/test/ecto/adapters/postgres_test.exs index d40d3501..2a93dfa1 100644 --- a/test/ecto/adapters/postgres_test.exs +++ b/test/ecto/adapters/postgres_test.exs @@ -774,50 +774,6 @@ defmodule Ecto.Adapters.PostgresTest do query = Schema |> select([r], r.x + 2) |> plan() assert all(query) == ~s{SELECT s0."x" + 2 FROM "schema" AS s0} - - query = Schema |> select([r], r.x &&& 2) |> plan() - assert all(query) == ~s{SELECT s0."x" & 2 FROM "schema" AS s0} - - query = Schema |> select([r], r.x ||| 2) |> plan() - assert all(query) == ~s{SELECT s0."x" | 2 FROM "schema" AS s0} - - query = Schema |> select([r], r.x <<< 2) |> plan() - assert all(query) == ~s{SELECT s0."x" << 2 FROM "schema" AS s0} - - query = Schema |> select([r], r.x >>> 2) |> plan() - assert all(query) == ~s{SELECT s0."x" >> 2 FROM "schema" AS s0} - end - - test "unary ops" do - query = Schema |> select([r], ~~~r.x) |> plan() - assert all(query) == ~s{SELECT ~(s0."x") FROM "schema" AS s0} - end - - test "bitwise functions" do - query = Schema |> select([r], band(r.x, 2)) |> plan() - assert all(query) == ~s{SELECT s0."x" & 2 FROM "schema" AS s0} - - query = Schema |> select([r], bor(r.x, 2)) |> plan() - assert all(query) == ~s{SELECT s0."x" | 2 FROM "schema" AS s0} - - query = Schema |> select([r], bxor(r.x, 2)) |> plan() - assert all(query) == ~s{SELECT s0."x" # 2 FROM "schema" AS s0} - - query = Schema |> select([r], bsl(r.x, 2)) |> plan() - assert all(query) == ~s{SELECT s0."x" << 2 FROM "schema" AS s0} - - query = Schema |> select([r], bsr(r.x, 2)) |> plan() - assert all(query) == ~s{SELECT s0."x" >> 2 FROM "schema" AS s0} - - query = Schema |> select([r], bnot(r.x)) |> plan() - assert all(query) == ~s{SELECT ~(s0."x") FROM "schema" AS s0} - - # test parenthesis - query = Schema |> select([r], band(r.x ||| 1, 2)) |> plan() - assert all(query) == ~s{SELECT (s0."x" | 1) & 2 FROM "schema" AS s0} - - query = Schema |> select([r], bnot(r.x &&& 1)) |> plan() - assert all(query) == ~s{SELECT ~(s0."x" & 1) FROM "schema" AS s0} end test "is_nil" do From 8a6da1d1b8925c3a93532301691154162a4b8519 Mon Sep 17 00:00:00 2001 From: Gigitsu Date: Sat, 17 Feb 2024 17:38:04 +0100 Subject: [PATCH 19/38] Remove remaining bitwise operator tests --- test/ecto/adapters/myxql_test.exs | 3 --- test/ecto/adapters/postgres_test.exs | 3 --- 2 files changed, 6 deletions(-) diff --git a/test/ecto/adapters/myxql_test.exs b/test/ecto/adapters/myxql_test.exs index 29d155d9..e0f3f253 100644 --- a/test/ecto/adapters/myxql_test.exs +++ b/test/ecto/adapters/myxql_test.exs @@ -705,9 +705,6 @@ defmodule Ecto.Adapters.MyXQLTest do end test "tagged type" do - query = Schema |> select([t], type(~~~t.x, :integer)) |> plan() - assert all(query) == ~s{SELECT CAST(~(s0.`x`) AS unsigned) FROM `schema` AS s0} - query = Schema |> select([], type(^"601d74e4-a8d3-4b6e-8365-eddb4c893327", Ecto.UUID)) |> plan() diff --git a/test/ecto/adapters/postgres_test.exs b/test/ecto/adapters/postgres_test.exs index 2a93dfa1..2959e22c 100644 --- a/test/ecto/adapters/postgres_test.exs +++ b/test/ecto/adapters/postgres_test.exs @@ -904,9 +904,6 @@ defmodule Ecto.Adapters.PostgresTest do query = Schema |> select([t], type(t.x + t.y, :integer)) |> plan() assert all(query) == ~s{SELECT (s0."x" + s0."y")::bigint FROM "schema" AS s0} - query = Schema |> select([t], type(~~~t.x, :integer)) |> plan() - assert all(query) == ~s{SELECT (~(s0."x"))::bigint FROM "schema" AS s0} - query = Schema |> select([], type(^"601d74e4-a8d3-4b6e-8365-eddb4c893327", Ecto.UUID)) |> plan() From 61fb5a8ae8c5f014b4cad1966c465eea6bf49dde Mon Sep 17 00:00:00 2001 From: Gigitsu Date: Sat, 17 Feb 2024 18:43:07 +0100 Subject: [PATCH 20/38] Add defaults --- lib/ecto/adapters/myxql/connection.ex | 10 ++++++++++ lib/ecto/adapters/postgres/connection.ex | 7 +++++++ 2 files changed, 17 insertions(+) diff --git a/lib/ecto/adapters/myxql/connection.ex b/lib/ecto/adapters/myxql/connection.ex index 5a8a8d5f..11dd14a7 100644 --- a/lib/ecto/adapters/myxql/connection.ex +++ b/lib/ecto/adapters/myxql/connection.ex @@ -1224,6 +1224,9 @@ if Code.ensure_loaded?(MyXQL) do defp default_expr({:ok, literal}) when is_binary(literal), do: [" DEFAULT '", escape_string(literal), ?'] + defp default_expr({:ok, literal}) when is_bitstring(literal), + do: [" DEFAULT b'", to_bit_literal(literal), ?'] + defp default_expr({:ok, literal}) when is_number(literal) or is_boolean(literal), do: [" DEFAULT ", to_string(literal)] @@ -1444,6 +1447,13 @@ if Code.ensure_loaded?(MyXQL) do |> :binary.replace("\"", "\\\\\"", [:global]) end + defp to_bit_literal(value) when is_bitstring(value) do + size = bit_size(value) + <> = value + + val |> Integer.to_string(2) |> String.pad_leading(size, ["0"]) + end + defp ecto_cast_to_db(:id, _query), do: "unsigned" defp ecto_cast_to_db(:integer, _query), do: "unsigned" defp ecto_cast_to_db(:string, _query), do: "char" diff --git a/lib/ecto/adapters/postgres/connection.ex b/lib/ecto/adapters/postgres/connection.ex index 7de51319..5a9eb95f 100644 --- a/lib/ecto/adapters/postgres/connection.ex +++ b/lib/ecto/adapters/postgres/connection.ex @@ -1580,6 +1580,13 @@ if Code.ensure_loaded?(Postgrex) do end end + defp default_type(literal, _type) when is_bitstring(literal) do + size = bit_size(literal) + <> = literal + + "#{val}::BIT(#{size})" + end + defp default_type(literal, _type) when is_number(literal), do: to_string(literal) defp default_type(literal, _type) when is_boolean(literal), do: to_string(literal) From 6fe3c05fd42e3e462987300282424a73fcf6764e Mon Sep 17 00:00:00 2001 From: Gigitsu Date: Sat, 17 Feb 2024 18:47:14 +0100 Subject: [PATCH 21/38] Update ecto dep --- mix.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mix.lock b/mix.lock index 22b215b7..8da8fd49 100644 --- a/mix.lock +++ b/mix.lock @@ -4,7 +4,7 @@ "decimal": {:hex, :decimal, "2.1.1", "5611dca5d4b2c3dd497dec8f68751f1f1a54755e8ed2a966c2633cf885973ad6", [:mix], [], "hexpm", "53cfe5f497ed0e7771ae1a475575603d77425099ba5faef9394932b35020ffcc"}, "deep_merge": {:hex, :deep_merge, "1.0.0", "b4aa1a0d1acac393bdf38b2291af38cb1d4a52806cf7a4906f718e1feb5ee961", [:mix], [], "hexpm", "ce708e5f094b9cd4e8f2be4f00d2f4250c4095be93f8cd6d018c753894885430"}, "earmark_parser": {:hex, :earmark_parser, "1.4.39", "424642f8335b05bb9eb611aa1564c148a8ee35c9c8a8bba6e129d51a3e3c6769", [:mix], [], "hexpm", "06553a88d1f1846da9ef066b87b57c6f605552cfbe40d20bd8d59cc6bde41944"}, - "ecto": {:hex, :ecto, "3.11.0", "ff8614b4e70a774f9d39af809c426def80852048440e8785d93a6e91f48fec00", [: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", "7769dad267ef967310d6e988e92d772659b11b09a0c015f101ce0fff81ce1f81"}, + "ecto": {:git, "https://github.com/Gigitsu/ecto.git", "528d9f25543737b37679278c8734d3eb7dfe61eb", [branch: "feature/bitstring-support"]}, "ex_doc": {:hex, :ex_doc, "0.30.9", "d691453495c47434c0f2052b08dd91cc32bc4e1a218f86884563448ee2502dd2", [:mix], [{:earmark_parser, "~> 1.4.31", [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", "d7aaaf21e95dc5cddabf89063327e96867d00013963eadf2c6ad135506a8bc10"}, "jason": {:hex, :jason, "1.4.1", "af1504e35f629ddcdd6addb3513c3853991f694921b1b9368b0bd32beb9f1b63", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "fbb01ecdfd565b56261302f7e1fcc27c4fb8f32d56eab74db621fc154604a7a1"}, "makeup": {:hex, :makeup, "1.1.1", "fa0bc768698053b2b3869fa8a62616501ff9d11a562f3ce39580d60860c3a55e", [:mix], [{:nimble_parsec, "~> 1.2.2 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "5dc62fbdd0de44de194898b6710692490be74baa02d9d108bc29f007783b0b48"}, From d979882d1fb17fcf85503ed7b9da2cde3f0163a4 Mon Sep 17 00:00:00 2001 From: Gigitsu Date: Sun, 18 Feb 2024 19:33:15 +0100 Subject: [PATCH 22/38] Add migration bitstring support --- integration_test/support/migration.exs | 1 + lib/ecto/adapters/tds/connection.ex | 2 ++ 2 files changed, 3 insertions(+) diff --git a/integration_test/support/migration.exs b/integration_test/support/migration.exs index 971c68e4..0b71b9ef 100644 --- a/integration_test/support/migration.exs +++ b/integration_test/support/migration.exs @@ -21,6 +21,7 @@ defmodule Ecto.Integration.Migration do add :links, {:map, :string} add :intensities, {:map, :float} add :public, :boolean + add :token, :bitstring, size: 3 add :cost, :decimal, precision: 2, scale: 1 add :visits, :integer add :wrapped_visits, :integer diff --git a/lib/ecto/adapters/tds/connection.ex b/lib/ecto/adapters/tds/connection.ex index 4c2ca9c1..0b9a53ef 100644 --- a/lib/ecto/adapters/tds/connection.ex +++ b/lib/ecto/adapters/tds/connection.ex @@ -1737,6 +1737,8 @@ if Code.ensure_loaded?(Tds) do defp ecto_to_db(:float, s, _, _, _) when s in 1..53, do: "float(#{s})" defp ecto_to_db(:binary, nil, _, _, _), do: "varbinary(max)" defp ecto_to_db(:binary, s, _, _, _) when s in 1..8_000, do: "varbinary(#{s})" + defp ecto_to_db(:bitstring, nil, _, _, _), do: "varbinary(max)" + defp ecto_to_db(:bitstring, s, _, _, _) when s in 1..8_000, do: "varbinary(#{s})" defp ecto_to_db(:uuid, _, _, _, _), do: "uniqueidentifier" defp ecto_to_db(:map, nil, _, _, _), do: "nvarchar(max)" defp ecto_to_db(:map, s, _, _, _) when s in 0..4_000, do: "nvarchar(#{s})" From 2578a126c5b63aa0952702d39ed84a4ae7a89d9c Mon Sep 17 00:00:00 2001 From: Gigitsu Date: Mon, 19 Feb 2024 09:35:07 +0100 Subject: [PATCH 23/38] Raise when defining a bitstring field without a size with mysql --- lib/ecto/adapters/myxql/connection.ex | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/ecto/adapters/myxql/connection.ex b/lib/ecto/adapters/myxql/connection.ex index 11dd14a7..3fd6c6c7 100644 --- a/lib/ecto/adapters/myxql/connection.ex +++ b/lib/ecto/adapters/myxql/connection.ex @@ -1462,6 +1462,7 @@ if Code.ensure_loaded?(MyXQL) do defp ecto_cast_to_db(type, query), do: ecto_to_db(type, query) defp ecto_size_to_db(:binary), do: "varbinary" + defp ecto_size_to_db(:bitstring), do: "bit" defp ecto_size_to_db(type), do: ecto_to_db(type) defp ecto_to_db(type, query \\ nil) @@ -1471,7 +1472,6 @@ if Code.ensure_loaded?(MyXQL) do defp ecto_to_db(:bigserial, _query), do: "bigint unsigned not null auto_increment" defp ecto_to_db(:binary_id, _query), do: "binary(16)" defp ecto_to_db(:string, _query), do: "varchar" - defp ecto_to_db(:bitstring, _query), do: "bit" defp ecto_to_db(:float, _query), do: "double" defp ecto_to_db(:binary, _query), do: "blob" # MySQL does not support uuid @@ -1485,6 +1485,12 @@ if Code.ensure_loaded?(MyXQL) do defp ecto_to_db(:naive_datetime_usec, _query), do: "datetime" defp ecto_to_db(atom, _query) when is_atom(atom), do: Atom.to_string(atom) + defp ecto_to_db(:bitstring, _query) do + raise ArgumentError, + "type `bitstring` without the `:size` option is unsupported." <> + "The type can be used with an explicit size attribute (eg. `add my_field, :bitstring, size: 42`)" + end + defp ecto_to_db(type, _query) do raise ArgumentError, "unsupported type `#{inspect(type)}`. The type can either be an atom, a string " <> From d2961b04145b7730023dd8eefed365a32a7d8707 Mon Sep 17 00:00:00 2001 From: Greg Rychlewski Date: Mon, 19 Feb 2024 07:28:13 -0500 Subject: [PATCH 24/38] Update mix.lock --- mix.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mix.lock b/mix.lock index 8da8fd49..893984d6 100644 --- a/mix.lock +++ b/mix.lock @@ -4,7 +4,7 @@ "decimal": {:hex, :decimal, "2.1.1", "5611dca5d4b2c3dd497dec8f68751f1f1a54755e8ed2a966c2633cf885973ad6", [:mix], [], "hexpm", "53cfe5f497ed0e7771ae1a475575603d77425099ba5faef9394932b35020ffcc"}, "deep_merge": {:hex, :deep_merge, "1.0.0", "b4aa1a0d1acac393bdf38b2291af38cb1d4a52806cf7a4906f718e1feb5ee961", [:mix], [], "hexpm", "ce708e5f094b9cd4e8f2be4f00d2f4250c4095be93f8cd6d018c753894885430"}, "earmark_parser": {:hex, :earmark_parser, "1.4.39", "424642f8335b05bb9eb611aa1564c148a8ee35c9c8a8bba6e129d51a3e3c6769", [:mix], [], "hexpm", "06553a88d1f1846da9ef066b87b57c6f605552cfbe40d20bd8d59cc6bde41944"}, - "ecto": {:git, "https://github.com/Gigitsu/ecto.git", "528d9f25543737b37679278c8734d3eb7dfe61eb", [branch: "feature/bitstring-support"]}, + "ecto": {:git, "https://github.com/Gigitsu/ecto.git", "1bf288b25f783634a57d13ca3b78ed0232b3d9d6", [branch: "feature/bitstring-support"]}, "ex_doc": {:hex, :ex_doc, "0.30.9", "d691453495c47434c0f2052b08dd91cc32bc4e1a218f86884563448ee2502dd2", [:mix], [{:earmark_parser, "~> 1.4.31", [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", "d7aaaf21e95dc5cddabf89063327e96867d00013963eadf2c6ad135506a8bc10"}, "jason": {:hex, :jason, "1.4.1", "af1504e35f629ddcdd6addb3513c3853991f694921b1b9368b0bd32beb9f1b63", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "fbb01ecdfd565b56261302f7e1fcc27c4fb8f32d56eab74db621fc154604a7a1"}, "makeup": {:hex, :makeup, "1.1.1", "fa0bc768698053b2b3869fa8a62616501ff9d11a562f3ce39580d60860c3a55e", [:mix], [{:nimble_parsec, "~> 1.2.2 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "5dc62fbdd0de44de194898b6710692490be74baa02d9d108bc29f007783b0b48"}, From d5938eac40f5866b888c1e78c78b0861d0082601 Mon Sep 17 00:00:00 2001 From: Gigitsu Date: Sun, 25 Feb 2024 13:06:17 +0100 Subject: [PATCH 25/38] Remove mysql bitstring support --- lib/ecto/adapters/myxql/connection.ex | 17 ----------------- test/ecto/adapters/myxql_test.exs | 6 ++---- 2 files changed, 2 insertions(+), 21 deletions(-) diff --git a/lib/ecto/adapters/myxql/connection.ex b/lib/ecto/adapters/myxql/connection.ex index 3fd6c6c7..39f31964 100644 --- a/lib/ecto/adapters/myxql/connection.ex +++ b/lib/ecto/adapters/myxql/connection.ex @@ -1224,9 +1224,6 @@ if Code.ensure_loaded?(MyXQL) do defp default_expr({:ok, literal}) when is_binary(literal), do: [" DEFAULT '", escape_string(literal), ?'] - defp default_expr({:ok, literal}) when is_bitstring(literal), - do: [" DEFAULT b'", to_bit_literal(literal), ?'] - defp default_expr({:ok, literal}) when is_number(literal) or is_boolean(literal), do: [" DEFAULT ", to_string(literal)] @@ -1447,13 +1444,6 @@ if Code.ensure_loaded?(MyXQL) do |> :binary.replace("\"", "\\\\\"", [:global]) end - defp to_bit_literal(value) when is_bitstring(value) do - size = bit_size(value) - <> = value - - val |> Integer.to_string(2) |> String.pad_leading(size, ["0"]) - end - defp ecto_cast_to_db(:id, _query), do: "unsigned" defp ecto_cast_to_db(:integer, _query), do: "unsigned" defp ecto_cast_to_db(:string, _query), do: "char" @@ -1462,7 +1452,6 @@ if Code.ensure_loaded?(MyXQL) do defp ecto_cast_to_db(type, query), do: ecto_to_db(type, query) defp ecto_size_to_db(:binary), do: "varbinary" - defp ecto_size_to_db(:bitstring), do: "bit" defp ecto_size_to_db(type), do: ecto_to_db(type) defp ecto_to_db(type, query \\ nil) @@ -1485,12 +1474,6 @@ if Code.ensure_loaded?(MyXQL) do defp ecto_to_db(:naive_datetime_usec, _query), do: "datetime" defp ecto_to_db(atom, _query) when is_atom(atom), do: Atom.to_string(atom) - defp ecto_to_db(:bitstring, _query) do - raise ArgumentError, - "type `bitstring` without the `:size` option is unsupported." <> - "The type can be used with an explicit size attribute (eg. `add my_field, :bitstring, size: 42`)" - end - defp ecto_to_db(type, _query) do raise ArgumentError, "unsupported type `#{inspect(type)}`. The type can either be an atom, a string " <> diff --git a/test/ecto/adapters/myxql_test.exs b/test/ecto/adapters/myxql_test.exs index e0f3f253..8cc5dd48 100644 --- a/test/ecto/adapters/myxql_test.exs +++ b/test/ecto/adapters/myxql_test.exs @@ -1579,8 +1579,7 @@ defmodule Ecto.Adapters.MyXQLTest do {:add, :on_hand, :integer, [default: 0, null: true]}, {:add, :likes, :"smallint unsigned", [default: 0, null: false]}, {:add, :published_at, :"datetime(6)", [null: true]}, - {:add, :is_active, :boolean, [default: true]}, - {:add, :token, :bitstring, [size: 23]} + {:add, :is_active, :boolean, [default: true]} ]} assert execute_ddl(create) == [ @@ -1591,8 +1590,7 @@ defmodule Ecto.Adapters.MyXQLTest do `on_hand` integer DEFAULT 0 NULL, `likes` smallint unsigned DEFAULT 0 NOT NULL, `published_at` datetime(6) NULL, - `is_active` boolean DEFAULT true, - `token` bit(23)) ENGINE = INNODB + `is_active` boolean DEFAULT true) ENGINE = INNODB """ |> remove_newlines ] From 6b1cbbe1ff041540ebf7c8363917e095160b6adc Mon Sep 17 00:00:00 2001 From: Gigitsu Date: Sun, 25 Feb 2024 13:26:50 +0100 Subject: [PATCH 26/38] Remove TDS bitstring support --- lib/ecto/adapters/tds/connection.ex | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/ecto/adapters/tds/connection.ex b/lib/ecto/adapters/tds/connection.ex index 0b9a53ef..4c2ca9c1 100644 --- a/lib/ecto/adapters/tds/connection.ex +++ b/lib/ecto/adapters/tds/connection.ex @@ -1737,8 +1737,6 @@ if Code.ensure_loaded?(Tds) do defp ecto_to_db(:float, s, _, _, _) when s in 1..53, do: "float(#{s})" defp ecto_to_db(:binary, nil, _, _, _), do: "varbinary(max)" defp ecto_to_db(:binary, s, _, _, _) when s in 1..8_000, do: "varbinary(#{s})" - defp ecto_to_db(:bitstring, nil, _, _, _), do: "varbinary(max)" - defp ecto_to_db(:bitstring, s, _, _, _) when s in 1..8_000, do: "varbinary(#{s})" defp ecto_to_db(:uuid, _, _, _, _), do: "uniqueidentifier" defp ecto_to_db(:map, nil, _, _, _), do: "nvarchar(max)" defp ecto_to_db(:map, s, _, _, _) when s in 0..4_000, do: "nvarchar(#{s})" From 24d6719e2c0875a10b5235bb322296f416f14056 Mon Sep 17 00:00:00 2001 From: Gigitsu Date: Sun, 25 Feb 2024 13:27:27 +0100 Subject: [PATCH 27/38] Add bitstring table with mysql exclusion --- integration_test/myxql/test_helper.exs | 3 ++- integration_test/support/migration.exs | 8 ++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/integration_test/myxql/test_helper.exs b/integration_test/myxql/test_helper.exs index 84402f8a..6b9bef8e 100644 --- a/integration_test/myxql/test_helper.exs +++ b/integration_test/myxql/test_helper.exs @@ -93,8 +93,9 @@ version = end excludes = [ - # MySQL does not have an array type + # MySQL does not have an array and bitstring type :array_type, + :bitstring_type, # The next two features rely on RETURNING, which MySQL does not support :read_after_writes, :returning, diff --git a/integration_test/support/migration.exs b/integration_test/support/migration.exs index 0b71b9ef..cdb92cb4 100644 --- a/integration_test/support/migration.exs +++ b/integration_test/support/migration.exs @@ -109,6 +109,14 @@ defmodule Ecto.Integration.Migration do end end + unless :bitstring_type in ExUnit.configuration()[:exclude] do + create table(:bitstrings) do + add :bs, :bitstring + add :bs_with_default, :bitstring, default: <<42::6>> + add :bs_with_size, :bitstring, size: 10 + end + end + create table(:composite_pk, primary_key: false) do add :a, :integer, primary_key: true add :b, :integer, primary_key: true From 7a552fadb36a13676a12aaf766461f224b25daff Mon Sep 17 00:00:00 2001 From: Gigitsu Date: Sun, 25 Feb 2024 13:29:45 +0100 Subject: [PATCH 28/38] Remove bitstring type from `posts` table --- integration_test/support/migration.exs | 1 - 1 file changed, 1 deletion(-) diff --git a/integration_test/support/migration.exs b/integration_test/support/migration.exs index cdb92cb4..c2a3e417 100644 --- a/integration_test/support/migration.exs +++ b/integration_test/support/migration.exs @@ -21,7 +21,6 @@ defmodule Ecto.Integration.Migration do add :links, {:map, :string} add :intensities, {:map, :float} add :public, :boolean - add :token, :bitstring, size: 3 add :cost, :decimal, precision: 2, scale: 1 add :visits, :integer add :wrapped_visits, :integer From 0cf502376efb21697b55ce7a2b8868a183ecd746 Mon Sep 17 00:00:00 2001 From: Gigitsu Date: Sun, 25 Feb 2024 13:40:50 +0100 Subject: [PATCH 29/38] Improve bitstring tests --- test/ecto/adapters/postgres_test.exs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test/ecto/adapters/postgres_test.exs b/test/ecto/adapters/postgres_test.exs index 2959e22c..33273a89 100644 --- a/test/ecto/adapters/postgres_test.exs +++ b/test/ecto/adapters/postgres_test.exs @@ -1990,7 +1990,8 @@ defmodule Ecto.Adapters.PostgresTest do {:add, :on_hand, :integer, [default: 0, null: true]}, {:add, :published_at, :"time without time zone", [null: true]}, {:add, :is_active, :boolean, [default: true]}, - {:add, :token, :bitstring, []}, + {:add, :flags, :bitstring, [null: false]}, + {:add, :flags_with_default, :bitstring, [default: <<42::6>>]}, {:add, :tags, {:array, :string}, [default: []]}, {:add, :languages, {:array, :string}, [default: ["pt", "es"]]}, {:add, :limits, {:array, :integer}, [default: [100, 30_000]]} @@ -2003,7 +2004,8 @@ defmodule Ecto.Adapters.PostgresTest do "on_hand" integer DEFAULT 0 NULL, "published_at" time without time zone NULL, "is_active" boolean DEFAULT true, - "token" varbit, + "flags" varbit NOT NULL, + "flags_with_default" varbit DEFAULT 42::BIT(6), "tags" varchar(255)[] DEFAULT ARRAY[]::varchar[], "languages" varchar(255)[] DEFAULT ARRAY['pt','es']::varchar[], "limits" integer[] DEFAULT ARRAY[100,30000]::integer[]) From a9d6d46dedbbf1b85cb243f5218a4a49d004f8f7 Mon Sep 17 00:00:00 2001 From: Gigitsu Date: Sun, 25 Feb 2024 13:56:26 +0100 Subject: [PATCH 30/38] Update ecto dep --- mix.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mix.lock b/mix.lock index 893984d6..eaf19455 100644 --- a/mix.lock +++ b/mix.lock @@ -4,7 +4,7 @@ "decimal": {:hex, :decimal, "2.1.1", "5611dca5d4b2c3dd497dec8f68751f1f1a54755e8ed2a966c2633cf885973ad6", [:mix], [], "hexpm", "53cfe5f497ed0e7771ae1a475575603d77425099ba5faef9394932b35020ffcc"}, "deep_merge": {:hex, :deep_merge, "1.0.0", "b4aa1a0d1acac393bdf38b2291af38cb1d4a52806cf7a4906f718e1feb5ee961", [:mix], [], "hexpm", "ce708e5f094b9cd4e8f2be4f00d2f4250c4095be93f8cd6d018c753894885430"}, "earmark_parser": {:hex, :earmark_parser, "1.4.39", "424642f8335b05bb9eb611aa1564c148a8ee35c9c8a8bba6e129d51a3e3c6769", [:mix], [], "hexpm", "06553a88d1f1846da9ef066b87b57c6f605552cfbe40d20bd8d59cc6bde41944"}, - "ecto": {:git, "https://github.com/Gigitsu/ecto.git", "1bf288b25f783634a57d13ca3b78ed0232b3d9d6", [branch: "feature/bitstring-support"]}, + "ecto": {:git, "https://github.com/Gigitsu/ecto.git", "9dce7d87b41c286b16091be53389de3a67fe2805", [branch: "feature/bitstring-support"]}, "ex_doc": {:hex, :ex_doc, "0.30.9", "d691453495c47434c0f2052b08dd91cc32bc4e1a218f86884563448ee2502dd2", [:mix], [{:earmark_parser, "~> 1.4.31", [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", "d7aaaf21e95dc5cddabf89063327e96867d00013963eadf2c6ad135506a8bc10"}, "jason": {:hex, :jason, "1.4.1", "af1504e35f629ddcdd6addb3513c3853991f694921b1b9368b0bd32beb9f1b63", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "fbb01ecdfd565b56261302f7e1fcc27c4fb8f32d56eab74db621fc154604a7a1"}, "makeup": {:hex, :makeup, "1.1.1", "fa0bc768698053b2b3869fa8a62616501ff9d11a562f3ce39580d60860c3a55e", [:mix], [{:nimble_parsec, "~> 1.2.2 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "5dc62fbdd0de44de194898b6710692490be74baa02d9d108bc29f007783b0b48"}, From 44d466d41fe3c5970817159d40b1cc693f243980 Mon Sep 17 00:00:00 2001 From: Gigitsu Date: Sun, 25 Feb 2024 14:15:39 +0100 Subject: [PATCH 31/38] Update ecto --- mix.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mix.lock b/mix.lock index eaf19455..7f1508e9 100644 --- a/mix.lock +++ b/mix.lock @@ -4,7 +4,7 @@ "decimal": {:hex, :decimal, "2.1.1", "5611dca5d4b2c3dd497dec8f68751f1f1a54755e8ed2a966c2633cf885973ad6", [:mix], [], "hexpm", "53cfe5f497ed0e7771ae1a475575603d77425099ba5faef9394932b35020ffcc"}, "deep_merge": {:hex, :deep_merge, "1.0.0", "b4aa1a0d1acac393bdf38b2291af38cb1d4a52806cf7a4906f718e1feb5ee961", [:mix], [], "hexpm", "ce708e5f094b9cd4e8f2be4f00d2f4250c4095be93f8cd6d018c753894885430"}, "earmark_parser": {:hex, :earmark_parser, "1.4.39", "424642f8335b05bb9eb611aa1564c148a8ee35c9c8a8bba6e129d51a3e3c6769", [:mix], [], "hexpm", "06553a88d1f1846da9ef066b87b57c6f605552cfbe40d20bd8d59cc6bde41944"}, - "ecto": {:git, "https://github.com/Gigitsu/ecto.git", "9dce7d87b41c286b16091be53389de3a67fe2805", [branch: "feature/bitstring-support"]}, + "ecto": {:git, "https://github.com/Gigitsu/ecto.git", "09c804b8905b4bc192dfffcdb222399dd41f5535", [branch: "feature/bitstring-support"]}, "ex_doc": {:hex, :ex_doc, "0.30.9", "d691453495c47434c0f2052b08dd91cc32bc4e1a218f86884563448ee2502dd2", [:mix], [{:earmark_parser, "~> 1.4.31", [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", "d7aaaf21e95dc5cddabf89063327e96867d00013963eadf2c6ad135506a8bc10"}, "jason": {:hex, :jason, "1.4.1", "af1504e35f629ddcdd6addb3513c3853991f694921b1b9368b0bd32beb9f1b63", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "fbb01ecdfd565b56261302f7e1fcc27c4fb8f32d56eab74db621fc154604a7a1"}, "makeup": {:hex, :makeup, "1.1.1", "fa0bc768698053b2b3869fa8a62616501ff9d11a562f3ce39580d60860c3a55e", [:mix], [{:nimble_parsec, "~> 1.2.2 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "5dc62fbdd0de44de194898b6710692490be74baa02d9d108bc29f007783b0b48"}, From cf89b25077d87c74eb365acaf22a1f6c0b2984f2 Mon Sep 17 00:00:00 2001 From: Gigitsu Date: Sun, 25 Feb 2024 14:22:04 +0100 Subject: [PATCH 32/38] Exclude bitstring for tds too --- integration_test/myxql/test_helper.exs | 5 +++-- integration_test/tds/test_helper.exs | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/integration_test/myxql/test_helper.exs b/integration_test/myxql/test_helper.exs index 6b9bef8e..e9b6a29e 100644 --- a/integration_test/myxql/test_helper.exs +++ b/integration_test/myxql/test_helper.exs @@ -93,9 +93,10 @@ version = end excludes = [ - # MySQL does not have an array and bitstring type - :array_type, + # not sure how to support this yet :bitstring_type, + # MySQL does not have an array type + :array_type, # The next two features rely on RETURNING, which MySQL does not support :read_after_writes, :returning, diff --git a/integration_test/tds/test_helper.exs b/integration_test/tds/test_helper.exs index dfc8b10f..89e2d13d 100644 --- a/integration_test/tds/test_helper.exs +++ b/integration_test/tds/test_helper.exs @@ -4,6 +4,7 @@ ExUnit.start( exclude: [ # not sure how to support this yet :aggregate_filters, + :bitstring_type, # subquery contains ORDER BY and that is not supported :subquery_aggregates, # sql don't have array type From 1a6df91d2cea1560bd004656ea2f85635d3fddd1 Mon Sep 17 00:00:00 2001 From: Gigitsu Date: Sun, 25 Feb 2024 17:05:06 +0100 Subject: [PATCH 33/38] Add bitstring literal support --- lib/ecto/adapters/postgres/connection.ex | 17 +++++++++++++---- mix.lock | 2 +- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/lib/ecto/adapters/postgres/connection.ex b/lib/ecto/adapters/postgres/connection.ex index 5a9eb95f..13365bef 100644 --- a/lib/ecto/adapters/postgres/connection.ex +++ b/lib/ecto/adapters/postgres/connection.ex @@ -1015,6 +1015,11 @@ if Code.ensure_loaded?(Postgrex) do ["'\\x", Base.encode16(binary, case: :lower) | "'::bytea"] end + defp expr(%Ecto.Query.Tagged{value: bitstring, type: :binary}, _sources, _query) + when is_bitstring(bitstring) do + bitstring_literal(bitstring) + end + defp expr(%Ecto.Query.Tagged{value: other, type: type}, sources, query) do [maybe_paren(other, sources, query), ?:, ?: | tagged_to_db(type)] end @@ -1581,10 +1586,7 @@ if Code.ensure_loaded?(Postgrex) do end defp default_type(literal, _type) when is_bitstring(literal) do - size = bit_size(literal) - <> = literal - - "#{val}::BIT(#{size})" + bitstring_literal(literal) end defp default_type(literal, _type) when is_number(literal), do: to_string(literal) @@ -1831,6 +1833,13 @@ if Code.ensure_loaded?(Postgrex) do defp single_quote(value), do: [?', escape_string(value), ?'] + defp bitstring_literal(value) do + size = bit_size(value) + <> = value + + [Integer.to_string(val) | "::BIT(#{size})"] + end + defp intersperse_reduce(list, separator, user_acc, reducer, acc \\ []) defp intersperse_reduce([], _separator, user_acc, _reducer, acc), diff --git a/mix.lock b/mix.lock index 7f1508e9..fc895cbb 100644 --- a/mix.lock +++ b/mix.lock @@ -4,7 +4,7 @@ "decimal": {:hex, :decimal, "2.1.1", "5611dca5d4b2c3dd497dec8f68751f1f1a54755e8ed2a966c2633cf885973ad6", [:mix], [], "hexpm", "53cfe5f497ed0e7771ae1a475575603d77425099ba5faef9394932b35020ffcc"}, "deep_merge": {:hex, :deep_merge, "1.0.0", "b4aa1a0d1acac393bdf38b2291af38cb1d4a52806cf7a4906f718e1feb5ee961", [:mix], [], "hexpm", "ce708e5f094b9cd4e8f2be4f00d2f4250c4095be93f8cd6d018c753894885430"}, "earmark_parser": {:hex, :earmark_parser, "1.4.39", "424642f8335b05bb9eb611aa1564c148a8ee35c9c8a8bba6e129d51a3e3c6769", [:mix], [], "hexpm", "06553a88d1f1846da9ef066b87b57c6f605552cfbe40d20bd8d59cc6bde41944"}, - "ecto": {:git, "https://github.com/Gigitsu/ecto.git", "09c804b8905b4bc192dfffcdb222399dd41f5535", [branch: "feature/bitstring-support"]}, + "ecto": {:git, "https://github.com/Gigitsu/ecto.git", "d83ee76a355e572d9a4ee9013ae816c57b1d0af0", [branch: "feature/bitstring-support"]}, "ex_doc": {:hex, :ex_doc, "0.30.9", "d691453495c47434c0f2052b08dd91cc32bc4e1a218f86884563448ee2502dd2", [:mix], [{:earmark_parser, "~> 1.4.31", [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", "d7aaaf21e95dc5cddabf89063327e96867d00013963eadf2c6ad135506a8bc10"}, "jason": {:hex, :jason, "1.4.1", "af1504e35f629ddcdd6addb3513c3853991f694921b1b9368b0bd32beb9f1b63", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "fbb01ecdfd565b56261302f7e1fcc27c4fb8f32d56eab74db621fc154604a7a1"}, "makeup": {:hex, :makeup, "1.1.1", "fa0bc768698053b2b3869fa8a62616501ff9d11a562f3ce39580d60860c3a55e", [:mix], [{:nimble_parsec, "~> 1.2.2 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "5dc62fbdd0de44de194898b6710692490be74baa02d9d108bc29f007783b0b48"}, From 661830ffba58af7a289fd48c3cb9a475b0633ca7 Mon Sep 17 00:00:00 2001 From: Gigitsu Date: Mon, 26 Feb 2024 18:28:55 +0100 Subject: [PATCH 34/38] Improve bitstring literal support --- lib/ecto/adapters/postgres/connection.ex | 6 +++--- test/ecto/adapters/postgres_test.exs | 6 ++++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/lib/ecto/adapters/postgres/connection.ex b/lib/ecto/adapters/postgres/connection.ex index 13365bef..77a868b5 100644 --- a/lib/ecto/adapters/postgres/connection.ex +++ b/lib/ecto/adapters/postgres/connection.ex @@ -1015,8 +1015,8 @@ if Code.ensure_loaded?(Postgrex) do ["'\\x", Base.encode16(binary, case: :lower) | "'::bytea"] end - defp expr(%Ecto.Query.Tagged{value: bitstring, type: :binary}, _sources, _query) - when is_bitstring(bitstring) do + defp expr(%Ecto.Query.Tagged{value: bitstring, type: type}, _sources, _query) + when type in ~w(bitstring binary)a and is_bitstring(bitstring) do bitstring_literal(bitstring) end @@ -1837,7 +1837,7 @@ if Code.ensure_loaded?(Postgrex) do size = bit_size(value) <> = value - [Integer.to_string(val) | "::BIT(#{size})"] + [?b, ?', val |> Integer.to_string(2) |> String.pad_leading(size, ["0"]), ?'] end defp intersperse_reduce(list, separator, user_acc, reducer, acc \\ []) diff --git a/test/ecto/adapters/postgres_test.exs b/test/ecto/adapters/postgres_test.exs index 33273a89..4ad150f1 100644 --- a/test/ecto/adapters/postgres_test.exs +++ b/test/ecto/adapters/postgres_test.exs @@ -1991,7 +1991,8 @@ defmodule Ecto.Adapters.PostgresTest do {:add, :published_at, :"time without time zone", [null: true]}, {:add, :is_active, :boolean, [default: true]}, {:add, :flags, :bitstring, [null: false]}, - {:add, :flags_with_default, :bitstring, [default: <<42::6>>]}, + {:add, :flags_with_default, :bitstring, [default: <<42::10>>]}, + {:add, :flags_with_size, :bitstring, [size: 10]}, {:add, :tags, {:array, :string}, [default: []]}, {:add, :languages, {:array, :string}, [default: ["pt", "es"]]}, {:add, :limits, {:array, :integer}, [default: [100, 30_000]]} @@ -2005,7 +2006,8 @@ defmodule Ecto.Adapters.PostgresTest do "published_at" time without time zone NULL, "is_active" boolean DEFAULT true, "flags" varbit NOT NULL, - "flags_with_default" varbit DEFAULT 42::BIT(6), + "flags_with_default" varbit DEFAULT b'0000101010', + "flags_with_size" varbit(10), "tags" varchar(255)[] DEFAULT ARRAY[]::varchar[], "languages" varchar(255)[] DEFAULT ARRAY['pt','es']::varchar[], "limits" integer[] DEFAULT ARRAY[100,30000]::integer[]) From a0c3a9e943ff7d9af9a480bd711f60c1256c41e9 Mon Sep 17 00:00:00 2001 From: Gigitsu Date: Tue, 27 Feb 2024 10:08:32 +0100 Subject: [PATCH 35/38] Update bitstring support --- lib/ecto/adapters/postgres/connection.ex | 4 ++-- mix.lock | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/ecto/adapters/postgres/connection.ex b/lib/ecto/adapters/postgres/connection.ex index 77a868b5..3aa8c34f 100644 --- a/lib/ecto/adapters/postgres/connection.ex +++ b/lib/ecto/adapters/postgres/connection.ex @@ -1015,8 +1015,8 @@ if Code.ensure_loaded?(Postgrex) do ["'\\x", Base.encode16(binary, case: :lower) | "'::bytea"] end - defp expr(%Ecto.Query.Tagged{value: bitstring, type: type}, _sources, _query) - when type in ~w(bitstring binary)a and is_bitstring(bitstring) do + defp expr(%Ecto.Query.Tagged{value: bitstring, type: :bitstring}, _sources, _query) + when is_bitstring(bitstring) do bitstring_literal(bitstring) end diff --git a/mix.lock b/mix.lock index fc895cbb..6b56ce5e 100644 --- a/mix.lock +++ b/mix.lock @@ -4,7 +4,7 @@ "decimal": {:hex, :decimal, "2.1.1", "5611dca5d4b2c3dd497dec8f68751f1f1a54755e8ed2a966c2633cf885973ad6", [:mix], [], "hexpm", "53cfe5f497ed0e7771ae1a475575603d77425099ba5faef9394932b35020ffcc"}, "deep_merge": {:hex, :deep_merge, "1.0.0", "b4aa1a0d1acac393bdf38b2291af38cb1d4a52806cf7a4906f718e1feb5ee961", [:mix], [], "hexpm", "ce708e5f094b9cd4e8f2be4f00d2f4250c4095be93f8cd6d018c753894885430"}, "earmark_parser": {:hex, :earmark_parser, "1.4.39", "424642f8335b05bb9eb611aa1564c148a8ee35c9c8a8bba6e129d51a3e3c6769", [:mix], [], "hexpm", "06553a88d1f1846da9ef066b87b57c6f605552cfbe40d20bd8d59cc6bde41944"}, - "ecto": {:git, "https://github.com/Gigitsu/ecto.git", "d83ee76a355e572d9a4ee9013ae816c57b1d0af0", [branch: "feature/bitstring-support"]}, + "ecto": {:git, "https://github.com/Gigitsu/ecto.git", "968bc59b463be3a7377c04fc7bece8ec7f4b51ef", [branch: "feature/bitstring-support"]}, "ex_doc": {:hex, :ex_doc, "0.30.9", "d691453495c47434c0f2052b08dd91cc32bc4e1a218f86884563448ee2502dd2", [:mix], [{:earmark_parser, "~> 1.4.31", [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", "d7aaaf21e95dc5cddabf89063327e96867d00013963eadf2c6ad135506a8bc10"}, "jason": {:hex, :jason, "1.4.1", "af1504e35f629ddcdd6addb3513c3853991f694921b1b9368b0bd32beb9f1b63", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "fbb01ecdfd565b56261302f7e1fcc27c4fb8f32d56eab74db621fc154604a7a1"}, "makeup": {:hex, :makeup, "1.1.1", "fa0bc768698053b2b3869fa8a62616501ff9d11a562f3ce39580d60860c3a55e", [:mix], [{:nimble_parsec, "~> 1.2.2 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "5dc62fbdd0de44de194898b6710692490be74baa02d9d108bc29f007783b0b48"}, From e9396a487a7b8e4943fc992c380ec3e790c73de8 Mon Sep 17 00:00:00 2001 From: Gigitsu Date: Tue, 27 Feb 2024 14:03:48 +0100 Subject: [PATCH 36/38] Update ecto dependency --- mix.exs | 2 +- mix.lock | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mix.exs b/mix.exs index c335912b..b5d9f2d7 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, git: "https://github.com/Gigitsu/ecto.git", branch: "feature/bitstring-support"} + {:ecto, "~> 3.11.0"} end end diff --git a/mix.lock b/mix.lock index 6b56ce5e..ac252cb2 100644 --- a/mix.lock +++ b/mix.lock @@ -4,7 +4,7 @@ "decimal": {:hex, :decimal, "2.1.1", "5611dca5d4b2c3dd497dec8f68751f1f1a54755e8ed2a966c2633cf885973ad6", [:mix], [], "hexpm", "53cfe5f497ed0e7771ae1a475575603d77425099ba5faef9394932b35020ffcc"}, "deep_merge": {:hex, :deep_merge, "1.0.0", "b4aa1a0d1acac393bdf38b2291af38cb1d4a52806cf7a4906f718e1feb5ee961", [:mix], [], "hexpm", "ce708e5f094b9cd4e8f2be4f00d2f4250c4095be93f8cd6d018c753894885430"}, "earmark_parser": {:hex, :earmark_parser, "1.4.39", "424642f8335b05bb9eb611aa1564c148a8ee35c9c8a8bba6e129d51a3e3c6769", [:mix], [], "hexpm", "06553a88d1f1846da9ef066b87b57c6f605552cfbe40d20bd8d59cc6bde41944"}, - "ecto": {:git, "https://github.com/Gigitsu/ecto.git", "968bc59b463be3a7377c04fc7bece8ec7f4b51ef", [branch: "feature/bitstring-support"]}, + "ecto": {:hex, :ecto, "3.11.1", "4b4972b717e7ca83d30121b12998f5fcdc62ba0ed4f20fd390f16f3270d85c3e", [: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", "ebd3d3772cd0dfcd8d772659e41ed527c28b2a8bde4b00fe03e0463da0f1983b"}, "ex_doc": {:hex, :ex_doc, "0.30.9", "d691453495c47434c0f2052b08dd91cc32bc4e1a218f86884563448ee2502dd2", [:mix], [{:earmark_parser, "~> 1.4.31", [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", "d7aaaf21e95dc5cddabf89063327e96867d00013963eadf2c6ad135506a8bc10"}, "jason": {:hex, :jason, "1.4.1", "af1504e35f629ddcdd6addb3513c3853991f694921b1b9368b0bd32beb9f1b63", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "fbb01ecdfd565b56261302f7e1fcc27c4fb8f32d56eab74db621fc154604a7a1"}, "makeup": {:hex, :makeup, "1.1.1", "fa0bc768698053b2b3869fa8a62616501ff9d11a562f3ce39580d60860c3a55e", [:mix], [{:nimble_parsec, "~> 1.2.2 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "5dc62fbdd0de44de194898b6710692490be74baa02d9d108bc29f007783b0b48"}, From 055880309770f82524288d568ff80b3fbb502e10 Mon Sep 17 00:00:00 2001 From: Greg Rychlewski Date: Tue, 27 Feb 2024 08:08:17 -0500 Subject: [PATCH 37/38] Update mix.exs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: José Valim --- mix.exs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mix.exs b/mix.exs index b5d9f2d7..9c07939b 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.11.0"} + {:ecto, github: "elixir-ecto/ecto"} end end From fe85b6f3c1b8d8fb40f3b55e5085843822587b96 Mon Sep 17 00:00:00 2001 From: Gigitsu Date: Tue, 27 Feb 2024 14:18:30 +0100 Subject: [PATCH 38/38] Update mix.lock --- mix.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mix.lock b/mix.lock index ac252cb2..68a05692 100644 --- a/mix.lock +++ b/mix.lock @@ -4,7 +4,7 @@ "decimal": {:hex, :decimal, "2.1.1", "5611dca5d4b2c3dd497dec8f68751f1f1a54755e8ed2a966c2633cf885973ad6", [:mix], [], "hexpm", "53cfe5f497ed0e7771ae1a475575603d77425099ba5faef9394932b35020ffcc"}, "deep_merge": {:hex, :deep_merge, "1.0.0", "b4aa1a0d1acac393bdf38b2291af38cb1d4a52806cf7a4906f718e1feb5ee961", [:mix], [], "hexpm", "ce708e5f094b9cd4e8f2be4f00d2f4250c4095be93f8cd6d018c753894885430"}, "earmark_parser": {:hex, :earmark_parser, "1.4.39", "424642f8335b05bb9eb611aa1564c148a8ee35c9c8a8bba6e129d51a3e3c6769", [:mix], [], "hexpm", "06553a88d1f1846da9ef066b87b57c6f605552cfbe40d20bd8d59cc6bde41944"}, - "ecto": {:hex, :ecto, "3.11.1", "4b4972b717e7ca83d30121b12998f5fcdc62ba0ed4f20fd390f16f3270d85c3e", [: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", "ebd3d3772cd0dfcd8d772659e41ed527c28b2a8bde4b00fe03e0463da0f1983b"}, + "ecto": {:git, "https://github.com/elixir-ecto/ecto.git", "bed81b9a69f3425147fb57df1b3dd5fb4c95792c", []}, "ex_doc": {:hex, :ex_doc, "0.30.9", "d691453495c47434c0f2052b08dd91cc32bc4e1a218f86884563448ee2502dd2", [:mix], [{:earmark_parser, "~> 1.4.31", [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", "d7aaaf21e95dc5cddabf89063327e96867d00013963eadf2c6ad135506a8bc10"}, "jason": {:hex, :jason, "1.4.1", "af1504e35f629ddcdd6addb3513c3853991f694921b1b9368b0bd32beb9f1b63", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "fbb01ecdfd565b56261302f7e1fcc27c4fb8f32d56eab74db621fc154604a7a1"}, "makeup": {:hex, :makeup, "1.1.1", "fa0bc768698053b2b3869fa8a62616501ff9d11a562f3ce39580d60860c3a55e", [:mix], [{:nimble_parsec, "~> 1.2.2 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "5dc62fbdd0de44de194898b6710692490be74baa02d9d108bc29f007783b0b48"},