Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .formatter.exs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# Used by "mix format"
[
inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"],
inputs: [
"{mix,.formatter}.exs",
"{lib,test}/**/*.{ex,exs}"
],
line_length: 88
]
58 changes: 42 additions & 16 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,24 +1,50 @@
name: CI
on: [push, pull_request]
jobs:
test-elixir:
runs-on: ubuntu-latest
container: elixir:${{ matrix.elixir_version }}-slim

on:
pull_request:
push:
branches:
- main

jobs:
test:
runs-on: ubuntu-20.04
env:
MIX_ENV: test
strategy:
fail-fast: false
matrix:
elixir_version: ["1.8", "1.9", "1.10", "1.11"]

include:
- pair:
elixir: 1.8.2
otp: 20.3.8.26
- pair:
elixir: 1.11.4
otp: 23.2.7
lint: lint
steps:
- uses: actions/checkout@v2

- name: Install system dependencies
run: |
apt-get update
apt-get install --no-install-recommends -y git build-essential
mix local.rebar --force
mix local.hex --force
mix deps.get
- uses: erlef/setup-elixir@v1
with:
otp-version: ${{matrix.pair.otp}}
elixir-version: ${{matrix.pair.elixir}}

- name: Install Dependencies
run: mix deps.get --only test

- run: mix format --check-formatted
if: ${{ matrix.lint }}

- run: mix deps.get && mix deps.unlock --check-unused
if: ${{ matrix.lint }}

- run: mix deps.compile

# test/support throwing compile errors, but will soon be refactored
# - run: mix compile --warnings-as-errors
# if: ${{ matrix.lint }}

- run: mix test

- run: mix test --trace
- run: EXQLITE_INTEGRATION=true mix test --trace
- run: EXQLITE_INTEGRATION=true mix test
1 change: 1 addition & 0 deletions lib/ecto/adapters/sqlite3/codec.ex
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ defmodule Ecto.Adapters.SQLite3.Codec do
def decimal_encode(%Decimal{} = x) do
{:ok, Decimal.to_string(x, :normal)}
end

# def decimal_encode(x), do: {:ok, x}

def time_encode(value) do
Expand Down
41 changes: 30 additions & 11 deletions lib/ecto/adapters/sqlite3/connection.ex
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,10 @@ defmodule Ecto.Adapters.SQLite3.Connection do
end

@impl true
def to_constraints(%Exqlite.Error{message: "UNIQUE constraint failed: " <> constraint}, _opts) do
def to_constraints(
%Exqlite.Error{message: "UNIQUE constraint failed: " <> constraint},
_opts
) do
[unique: constraint_name_hack(constraint)]
end

Expand Down Expand Up @@ -267,6 +270,7 @@ defmodule Ecto.Adapters.SQLite3.Connection do
returning(returning)
]
end

def insert(prefix, table, header, rows, on_conflict, returning, _placeholders) do
fields = quote_names(header)

Expand Down Expand Up @@ -680,7 +684,11 @@ defmodule Ecto.Adapters.SQLite3.Connection do
end

defp on_conflict({query, _, targets}, _header) do
[" ON CONFLICT ", conflict_target(targets), "DO " | update_all(query, "UPDATE SET ")]
[
" ON CONFLICT ",
conflict_target(targets),
"DO " | update_all(query, "UPDATE SET ")
]
end

defp conflict_target([]), do: ""
Expand All @@ -691,11 +699,11 @@ defmodule Ecto.Adapters.SQLite3.Connection do

defp replace(fields) do
[
"UPDATE SET " |
intersperse_map(fields, ?,, fn field ->
quoted = quote_name(field)
[quoted, " = ", "EXCLUDED." | quoted]
end)
"UPDATE SET "
| intersperse_map(fields, ?,, fn field ->
quoted = quote_name(field)
[quoted, " = ", "EXCLUDED." | quoted]
end)
]
end

Expand Down Expand Up @@ -739,6 +747,7 @@ defmodule Ecto.Adapters.SQLite3.Connection do
{_expr, name, _schema} = create_name(sources, 0, [])
[" AS " | name]
end

defp insert_as({_, _, _}) do
[]
end
Expand Down Expand Up @@ -779,7 +788,10 @@ defmodule Ecto.Adapters.SQLite3.Connection do
end

def select(%{select: %{fields: fields}, distinct: distinct} = query, sources) do
["SELECT ", distinct(distinct, sources, query) | select_fields(fields, sources, query)]
[
"SELECT ",
distinct(distinct, sources, query) | select_fields(fields, sources, query)
]
end

defp select_fields([], _sources, _query), do: "1"
Expand Down Expand Up @@ -1157,7 +1169,13 @@ defmodule Ecto.Adapters.SQLite3.Connection do
end

def expr({:in, _, [left, right]}, sources, query) do
[expr(left, sources, query), " IN (SELECT value FROM JSON_EACH(", expr(right, sources, query), ?), ?)]
[
expr(left, sources, query),
" IN (SELECT value FROM JSON_EACH(",
expr(right, sources, query),
?),
?)
]
end

def expr({:is_nil, _, [arg]}, sources, query) do
Expand Down Expand Up @@ -1585,6 +1603,7 @@ defmodule Ecto.Adapters.SQLite3.Connection do
defp reference_on_update(_), do: []

defp returning(%{select: nil}, _sources), do: []

defp returning(%{select: %{fields: fields}} = query, sources) do
[
" RETURNING " | select_fields(fields, sources, query)
Expand Down Expand Up @@ -1625,7 +1644,8 @@ defmodule Ecto.Adapters.SQLite3.Connection do
end

defp composite_fk_definitions(%Table{} = table, columns) do
composite_fk_cols = columns
composite_fk_cols =
columns
|> Enum.filter(fn c ->
case c do
{_op, _name, %Reference{with: [_]}, _opts} -> true
Expand All @@ -1650,7 +1670,6 @@ defmodule Ecto.Adapters.SQLite3.Connection do
reference_on_delete(ref.on_delete),
reference_on_update(ref.on_update)
]

end

defp get_source(query, sources, ix, source) do
Expand Down
2 changes: 1 addition & 1 deletion mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ defmodule EctoSQLite3.MixProject do

defp docs do
[
main: "Ecto.Adapters.SQLite3",
main: "Ecto.Adapters.SQLite3"
]
end

Expand Down
5 changes: 2 additions & 3 deletions mix.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,14 @@
"benchee_json": {:hex, :benchee_json, "0.4.0", "59d3277829bd1dca8373cdb20b916cb435c2647be235d09963fc0959db908c36", [:mix], [{:benchee, "~> 0.10", [hex: :benchee, repo: "hexpm", optional: false]}, {:poison, ">= 1.4.0", [hex: :poison, repo: "hexpm", optional: false]}], "hexpm", "71a3edb6a30708de2a01368aa8f288e1c0ed7897b125adc396ce7c2c7245b1e7"},
"connection": {:hex, :connection, "1.1.0", "ff2a49c4b75b6fb3e674bfc5536451607270aac754ffd1bdfe175abe4a6d7a68", [:mix], [], "hexpm", "722c1eb0a418fbe91ba7bd59a47e28008a189d47e37e0e7bb85585a016b2869c"},
"db_connection": {:hex, :db_connection, "2.3.1", "4c9f3ed1ef37471cbdd2762d6655be11e38193904d9c5c1c9389f1b891a3088e", [:mix], [{:connection, "~> 1.0", [hex: :connection, repo: "hexpm", optional: false]}], "hexpm", "abaab61780dde30301d840417890bd9f74131041afd02174cf4e10635b3a63f5"},
"decimal": {:hex, :decimal, "1.9.0", "83e8daf59631d632b171faabafb4a9f4242c514b0a06ba3df493951c08f64d07", [:mix], [], "hexpm", "b1f2343568eed6928f3e751cf2dffde95bfaa19dd95d09e8a9ea92ccfd6f7d85"},
"decimal": {:hex, :decimal, "2.0.0", "a78296e617b0f5dd4c6caf57c714431347912ffb1d0842e998e9792b5642d697", [:mix], [], "hexpm", "34666e9c55dea81013e77d9d87370fe6cb6291d1ef32f46a1600230b1d44f577"},
"deep_merge": {:hex, :deep_merge, "0.2.0", "c1050fa2edf4848b9f556fba1b75afc66608a4219659e3311d9c9427b5b680b3", [:mix], [], "hexpm", "e3bf435a54ed27b0ba3a01eb117ae017988804e136edcbe8a6a14c310daa966e"},
"earmark_parser": {:hex, :earmark_parser, "1.4.12", "b245e875ec0a311a342320da0551da407d9d2b65d98f7a9597ae078615af3449", [:mix], [], "hexpm", "711e2cc4d64abb7d566d43f54b78f7dc129308a63bc103fbd88550d2174b3160"},
"ecto": {:hex, :ecto, "3.5.8", "8ebf12be6016cb99313348ba7bb4612f4114b9a506d6da79a2adc7ef449340bc", [:mix], [{:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "ea0be182ea8922eb7742e3ae8e71b67ee00ae177de1bf76210299a5f16ba4c77"},
"ecto_sql": {:hex, :ecto_sql, "3.5.4", "a9e292c40bd79fff88885f95f1ecd7b2516e09aa99c7dd0201aa84c54d2358e4", [:mix], [{:db_connection, "~> 2.2", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.5.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.3.0 or ~> 0.4.0", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.15.0 or ~> 1.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:tds, "~> 2.1.1", [hex: :tds, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "1fff1a28a898d7bbef263f1f3ea425b04ba9f33816d843238c84eff883347343"},
"elixir_make": {:hex, :elixir_make, "0.6.2", "7dffacd77dec4c37b39af867cedaabb0b59f6a871f89722c25b28fcd4bd70530", [:mix], [], "hexpm", "03e49eadda22526a7e5279d53321d1cced6552f344ba4e03e619063de75348d9"},
"esqlite": {:hex, :esqlite, "0.4.1", "ba5d0bab6b9c8432ffe1bf12fee8e154a50f1c3c40eadc3a9c870c23ca94d961", [:rebar3], [], "hexpm", "3584ca33172f4815ce56e96eed9835f5d8c987a9000fbc8c376c86acef8bf965"},
"ex_doc": {:hex, :ex_doc, "0.23.0", "a069bc9b0bf8efe323ecde8c0d62afc13d308b1fa3d228b65bca5cf8703a529d", [:mix], [{:earmark_parser, "~> 1.4.0", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}], "hexpm", "f5e2c4702468b2fd11b10d39416ddadd2fcdd173ba2a0285ebd92c39827a5a16"},
"exqlite": {:hex, :exqlite, "0.5.0", "1c48c817ef4ea802c45b069e139a34cf2d85d9188ab3a99c6d6eea3d4903dfa3", [:make, :mix], [{:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "fab56c6bdebcfb1a238c5b501df86d74083d75af70ae0fde595a535f0ab45811"},
"exqlite": {:hex, :exqlite, "0.5.1", "fae7e66718fd33318904e826a42769e0ddbe7afc41dfcbff3332cbf3e728daa4", [:make, :mix], [{:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "e04a66c3a51e3e9d1f00189c90591c4902ae32de557b98089d1846e69e44df67"},
"jason": {:hex, :jason, "1.2.2", "ba43e3f2709fd1aa1dce90aaabfd039d000469c05c56f0b8e31978e03fa39052", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "18a228f5f0058ee183f29f9eae0805c6e59d61c3b006760668d8d18ff0d12179"},
"makeup": {:hex, :makeup, "1.0.5", "d5a830bc42c9800ce07dd97fa94669dfb93d3bf5fcf6ea7a0c67b2e0e4a7f26c", [:mix], [{:nimble_parsec, "~> 0.5 or ~> 1.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "cfa158c02d3f5c0c665d0af11512fed3fba0144cf1aadee0f2ce17747fba2ca9"},
"makeup_elixir": {:hex, :makeup_elixir, "0.15.1", "b5888c880d17d1cc3e598f05cdb5b5a91b7b17ac4eaf5f297cb697663a1094dd", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.1", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "db68c173234b07ab2a07f645a5acdc117b9f99d69ebf521821d89690ae6c6ec8"},
Expand Down
80 changes: 47 additions & 33 deletions test/ecto/adapters/sqlite3/connection_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -386,10 +386,14 @@ defmodule Ecto.Adapters.SQLite3.ConnectionTest do

test "aggregate filters" do
query = Schema |> select([r], count(r.x) |> filter(r.x > 10)) |> plan()
assert all(query) == ~s{SELECT count(s0.x) FILTER (WHERE s0.x > 10) FROM schema AS s0}

assert all(query) ==
~s{SELECT count(s0.x) FILTER (WHERE s0.x > 10) FROM schema AS s0}

query = Schema |> select([r], count(r.x) |> filter(r.x > 10 and r.x < 50)) |> plan()
assert all(query) == ~s{SELECT count(s0.x) FILTER (WHERE (s0.x > 10) AND (s0.x < 50)) FROM schema AS s0}

assert all(query) ==
~s{SELECT count(s0.x) FILTER (WHERE (s0.x > 10) AND (s0.x < 50)) FROM schema AS s0}

query = Schema |> select([r], count() |> filter(r.x > 10)) |> plan()
assert all(query) == ~s{SELECT count(*) FILTER (WHERE s0.x > 10) FROM schema AS s0}
Expand Down Expand Up @@ -969,7 +973,9 @@ defmodule Ecto.Adapters.SQLite3.ConnectionTest do
assert all(query) == ~s{SELECT json_extract(s0.meta, '$.\\"a') FROM schema AS s0}

query = Schema |> select([s], s.meta["author"]["name"]) |> plan()
assert all(query) == ~s{SELECT json_extract(s0.meta, '$.author.name') FROM schema AS s0}

assert all(query) ==
~s{SELECT json_extract(s0.meta, '$.author.name') FROM schema AS s0}
end

test "nested expressions" do
Expand Down Expand Up @@ -1026,7 +1032,8 @@ defmodule Ecto.Adapters.SQLite3.ConnectionTest do
|> select([e], e in [1, 2, 3])
|> plan()

assert all(query) == "SELECT s0 IN (SELECT value FROM JSON_EACH('[1,2,3]')) FROM schema AS s0"
assert all(query) ==
"SELECT s0 IN (SELECT value FROM JSON_EACH('[1,2,3]')) FROM schema AS s0"
end

test "in subquery" do
Expand Down Expand Up @@ -1297,12 +1304,15 @@ defmodule Ecto.Adapters.SQLite3.ConnectionTest do
AND (s0.x = 123)\
"""

query = from(
p in Post,
where: p.title == ^"foo",
select: p.content,
update: [set: [title: "bar"]]
) |> plan(:update_all)
query =
from(
p in Post,
where: p.title == ^"foo",
select: p.content,
update: [set: [title: "bar"]]
)
|> plan(:update_all)

assert update_all(query) ==
"""
UPDATE posts AS p0 \
Expand Down Expand Up @@ -1335,6 +1345,7 @@ defmodule Ecto.Adapters.SQLite3.ConnectionTest do
from(p in Post, update: [set: [title: "foo"]])
|> select([p], p)
|> plan(:update_all)

assert update_all(query) ==
"""
UPDATE posts AS p0 \
Expand All @@ -1347,6 +1358,7 @@ defmodule Ecto.Adapters.SQLite3.ConnectionTest do
|> where([m], m.x == ^2)
|> select([m], m.x == ^3)
|> plan(:update_all)

assert update_all(query) ==
"""
UPDATE schema AS s0 \
Expand Down Expand Up @@ -1375,20 +1387,22 @@ defmodule Ecto.Adapters.SQLite3.ConnectionTest do
(e in Schema)
|> from(where: e.x == 123, select: e.x)
|> plan()

assert delete_all(query) ==
"""
DELETE FROM schema AS s0 \
WHERE (s0.x = 123) RETURNING s0.x\
"""
"""
DELETE FROM schema AS s0 \
WHERE (s0.x = 123) RETURNING s0.x\
"""
end

test "delete all with returning" do
query = Post |> Ecto.Queryable.to_query |> select([m], m) |> plan()
query = Post |> Ecto.Queryable.to_query() |> select([m], m) |> plan()

assert delete_all(query) ==
"""
DELETE FROM posts AS p0 \
RETURNING p0.id, p0.title, p0.content\
"""
"""
DELETE FROM posts AS p0 \
RETURNING p0.id, p0.title, p0.content\
"""
end

test "delete all with prefix" do
Expand Down Expand Up @@ -2095,10 +2109,11 @@ defmodule Ecto.Adapters.SQLite3.ConnectionTest do
end

test "insert with query as rows" do
query = from(s in "schema", select: %{ foo: fragment("3"), bar: s.bar }) |> plan(:all)
query = from(s in "schema", select: %{foo: fragment("3"), bar: s.bar}) |> plan(:all)
query = insert(nil, "schema", [:foo, :bar], query, {:raise, [], []}, [])

assert query == ~s{INSERT INTO schema (foo,bar) (SELECT 3, s0.bar FROM schema AS s0)}
assert query ==
~s{INSERT INTO schema (foo,bar) (SELECT 3, s0.bar FROM schema AS s0)}
end

# test "update" do
Expand Down Expand Up @@ -2198,8 +2213,7 @@ defmodule Ecto.Adapters.SQLite3.ConnectionTest do
%Reference{table: :categories, with: [here: :there], on_delete: :nilify_all},
[]},
{:add, :category_7,
%Reference{table: :tags, with: [that: :this], on_delete: :nilify_all},
[]},
%Reference{table: :tags, with: [that: :this], on_delete: :nilify_all}, []}
]}

assert execute_ddl(create) == [
Expand Down Expand Up @@ -2448,11 +2462,11 @@ defmodule Ecto.Adapters.SQLite3.ConnectionTest do
}

assert execute_ddl(alteration) == [
"""
ALTER TABLE posts \
DROP COLUMN price\
"""
]
"""
ALTER TABLE posts \
DROP COLUMN price\
"""
]
end

test "alter table with primary key" do
Expand Down Expand Up @@ -2714,11 +2728,11 @@ defmodule Ecto.Adapters.SQLite3.ConnectionTest do
drop_column = {:alter, table(:posts), [{:remove, :summary}]}

assert execute_ddl(drop_column) == [
"""
ALTER TABLE posts \
DROP COLUMN summary\
"""
]
"""
ALTER TABLE posts \
DROP COLUMN summary\
"""
]
end

test "arrays" do
Expand Down
Loading