diff --git a/CHANGELOG.md b/CHANGELOG.md index dbdfa2f..b8b7d82 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ This is a breaking change in the sense that rebuilding the schema from scratch w We kept `TEXT_DATETIME` to satisfy the old Ecto2 implementation to keep backwards compatibility. +- **breaking**: raise when table prefixes are used. [#103](https://github.com/elixir-sqlite/ecto_sqlite3/pull/103) ## v0.9.1 - 2022-12-21 - changed: Use `Connection.connect` instead of `Sqlite3.open`. [#96](https://github.com/elixir-sqlite/ecto_sqlite3/pull/96) diff --git a/lib/ecto/adapters/sqlite3/connection.ex b/lib/ecto/adapters/sqlite3/connection.ex index 907f66d..f1f546e 100644 --- a/lib/ecto/adapters/sqlite3/connection.ex +++ b/lib/ecto/adapters/sqlite3/connection.ex @@ -54,7 +54,6 @@ defmodule Ecto.Adapters.SQLite3.Connection do DBConnection.execute(conn, cached, params, options) end - @impl true def execute( conn, %Exqlite.Query{statement: statement, ref: nil}, @@ -64,7 +63,6 @@ defmodule Ecto.Adapters.SQLite3.Connection do execute(conn, statement, params, options) end - @impl true def execute(conn, sql, params, options) when is_binary(sql) or is_list(sql) do query = Exqlite.Query.build(name: "", statement: IO.iodata_to_binary(sql)) @@ -75,7 +73,6 @@ defmodule Ecto.Adapters.SQLite3.Connection do end end - @impl true def execute(conn, query, params, options) do case DBConnection.execute(conn, query, params, options) do {:ok, _} = ok -> ok @@ -163,7 +160,6 @@ defmodule Ecto.Adapters.SQLite3.Connection do raise ArgumentError, "locks are not supported by SQLite3" end - @impl true def all(query, as_prefix \\ []) do sources = create_names(query, as_prefix) @@ -233,7 +229,6 @@ defmodule Ecto.Adapters.SQLite3.Connection do raise ArgumentError, "JOINS are not supported on DELETE statements by SQLite" end - @impl true def delete_all(query) do sources = create_names(query, []) cte = cte(query, sources) @@ -261,7 +256,6 @@ defmodule Ecto.Adapters.SQLite3.Connection do ] end - @impl true def insert(prefix, table, header, rows, on_conflict, returning, _placeholders) do fields = quote_names(header) @@ -375,7 +369,6 @@ defmodule Ecto.Adapters.SQLite3.Connection do raise ArgumentError, "SQLite3 adapter does not support keyword lists in :options" end - @impl true def execute_ddl({:create, %Table{} = table, columns}) do {table, composite_pk_def} = composite_pk_definition(table, columns) composite_fk_defs = composite_fk_definitions(table, columns) @@ -395,7 +388,6 @@ defmodule Ecto.Adapters.SQLite3.Connection do ] end - @impl true def execute_ddl({:create_if_not_exists, %Table{} = table, columns}) do {table, composite_pk_def} = composite_pk_definition(table, columns) composite_fk_defs = composite_fk_definitions(table, columns) @@ -415,7 +407,6 @@ defmodule Ecto.Adapters.SQLite3.Connection do ] end - @impl true def execute_ddl({:drop, %Table{} = table}) do [ [ @@ -425,12 +416,10 @@ defmodule Ecto.Adapters.SQLite3.Connection do ] end - @impl true def execute_ddl({:drop, %Table{} = table, _mode}) do execute_ddl({:drop, table}) end - @impl true def execute_ddl({:drop_if_exists, %Table{} = table}) do [ [ @@ -440,12 +429,10 @@ defmodule Ecto.Adapters.SQLite3.Connection do ] end - @impl true def execute_ddl({:drop_if_exists, %Table{} = table, _mode}) do execute_ddl({:drop_if_exists, table}) end - @impl true def execute_ddl({:alter, %Table{} = table, changes}) do Enum.map(changes, fn change -> [ @@ -457,111 +444,6 @@ defmodule Ecto.Adapters.SQLite3.Connection do end) end - @impl true - def execute_ddl({:create, %Index{} = index}) do - fields = intersperse_map(index.columns, ", ", &index_expr/1) - - [ - [ - "CREATE ", - if_do(index.unique, "UNIQUE "), - "INDEX ", - quote_name(index.name), - " ON ", - quote_table(index.prefix, index.table), - " (", - fields, - ?), - if_do(index.where, [" WHERE ", to_string(index.where)]) - ] - ] - end - - @impl true - def execute_ddl({:create_if_not_exists, %Index{} = index}) do - fields = intersperse_map(index.columns, ", ", &index_expr/1) - - [ - [ - "CREATE ", - if_do(index.unique, "UNIQUE "), - "INDEX IF NOT EXISTS ", - quote_name(index.name), - " ON ", - quote_table(index.prefix, index.table), - " (", - fields, - ?), - if_do(index.where, [" WHERE ", to_string(index.where)]) - ] - ] - end - - @impl true - def execute_ddl({:drop, %Index{} = index}) do - [ - [ - "DROP INDEX ", - quote_table(index.prefix, index.name) - ] - ] - end - - @impl true - def execute_ddl({:drop, %Index{} = index, _mode}) do - execute_ddl({:drop, index}) - end - - @impl true - def execute_ddl({:drop_if_exists, %Index{} = index}) do - [ - [ - "DROP INDEX IF EXISTS ", - quote_table(index.prefix, index.name) - ] - ] - end - - @impl true - def execute_ddl({:drop_if_exists, %Index{} = index, _mode}) do - execute_ddl({:drop_if_exists, index}) - end - - @impl true - def execute_ddl({:rename, %Table{} = current_table, %Table{} = new_table}) do - [ - [ - "ALTER TABLE ", - quote_table(current_table.prefix, current_table.name), - " RENAME TO ", - quote_table(nil, new_table.name) - ] - ] - end - - @impl true - def execute_ddl({:rename, %Table{} = current_table, old_col, new_col}) do - [ - [ - "ALTER TABLE ", - quote_table(current_table.prefix, current_table.name), - " RENAME COLUMN ", - quote_name(old_col), - " TO ", - quote_name(new_col) - ] - ] - end - - @impl true - def execute_ddl(string) when is_binary(string), do: [string] - - @impl true - def execute_ddl(keyword) when is_list(keyword) do - raise ArgumentError, "SQLite3 adapter does not support keyword lists in execute" - end - - @impl true def execute_ddl({:create, %Index{} = index}) do fields = intersperse_map(index.columns, ", ", &index_expr/1) @@ -574,8 +456,7 @@ defmodule Ecto.Adapters.SQLite3.Connection do quote_name(index.name), " ON ", quote_table(index.prefix, index.table), - ?\s, - ?(, + " (", fields, ?), if_do(index.where, [" WHERE ", to_string(index.where)]) @@ -583,7 +464,6 @@ defmodule Ecto.Adapters.SQLite3.Connection do ] end - @impl true def execute_ddl({:create_if_not_exists, %Index{} = index}) do fields = intersperse_map(index.columns, ", ", &index_expr/1) @@ -596,8 +476,7 @@ defmodule Ecto.Adapters.SQLite3.Connection do quote_name(index.name), " ON ", quote_table(index.prefix, index.table), - ?\s, - ?(, + " (", fields, ?), if_do(index.where, [" WHERE ", to_string(index.where)]) @@ -605,12 +484,10 @@ defmodule Ecto.Adapters.SQLite3.Connection do ] end - @impl true def execute_ddl({:create, %Constraint{}}) do raise ArgumentError, "SQLite3 does not support ALTER TABLE ADD CONSTRAINT." end - @impl true def execute_ddl({:drop, %Index{} = index}) do [ [ @@ -620,12 +497,10 @@ defmodule Ecto.Adapters.SQLite3.Connection do ] end - @impl true def execute_ddl({:drop, %Index{} = index, _mode}) do execute_ddl({:drop, index}) end - @impl true def execute_ddl({:drop_if_exists, %Index{} = index}) do [ [ @@ -635,22 +510,18 @@ defmodule Ecto.Adapters.SQLite3.Connection do ] end - @impl true def execute_ddl({:drop_if_exists, %Index{} = index, _mode}) do execute_ddl({:drop_if_exists, index}) end - @impl true def execute_ddl({:drop, %Constraint{}, _mode}) do raise ArgumentError, "SQLite3 does not support ALTER TABLE DROP CONSTRAINT." end - @impl true def execute_ddl({:drop_if_exists, %Constraint{}, _mode}) do raise ArgumentError, "SQLite3 does not support ALTER TABLE DROP CONSTRAINT." end - @impl true def execute_ddl({:rename, %Table{} = current_table, %Table{} = new_table}) do [ [ @@ -662,7 +533,6 @@ defmodule Ecto.Adapters.SQLite3.Connection do ] end - @impl true def execute_ddl({:rename, %Table{} = table, current_column, new_column}) do [ [ @@ -676,10 +546,8 @@ defmodule Ecto.Adapters.SQLite3.Connection do ] end - @impl true def execute_ddl(string) when is_binary(string), do: [string] - @impl true def execute_ddl(keyword) when is_list(keyword) do raise ArgumentError, "SQLite3 adapter does not support keyword lists in execute" end @@ -1799,7 +1667,10 @@ defmodule Ecto.Adapters.SQLite3.Connection do def quote_table(table), do: quote_entity(table) defp quote_table(nil, name), do: quote_entity(name) - defp quote_table(prefix, name), do: [quote_entity(prefix), ?., quote_entity(name)] + + defp quote_table(_prefix, _name) do + raise ArgumentError, "SQLite3 does not support table prefixes" + end defp quote_entity(val) when is_atom(val) do quote_entity(Atom.to_string(val)) diff --git a/test/ecto/adapters/sqlite3/connection_test.exs b/test/ecto/adapters/sqlite3/connection_test.exs index 1dc3c9f..a09942f 100644 --- a/test/ecto/adapters/sqlite3/connection_test.exs +++ b/test/ecto/adapters/sqlite3/connection_test.exs @@ -1365,7 +1365,9 @@ defmodule Ecto.Adapters.SQLite3.ConnectionTest do |> Map.put(:prefix, "prefix") |> plan(:update_all) - assert update_all(query) == ~s{UPDATE "prefix"."schema" AS s0 SET "x" = 0} + assert_raise ArgumentError, "SQLite3 does not support table prefixes", fn -> + update_all(query) + end query = (m in Schema) @@ -1373,7 +1375,9 @@ defmodule Ecto.Adapters.SQLite3.ConnectionTest do |> Map.put(:prefix, "prefix") |> plan(:update_all) - assert update_all(query) == ~s{UPDATE "first"."schema" AS s0 SET "x" = 0} + assert_raise ArgumentError, "SQLite3 does not support table prefixes", fn -> + update_all(query) + end end test "update all with returning" do @@ -1448,7 +1452,9 @@ defmodule Ecto.Adapters.SQLite3.ConnectionTest do |> Map.put(:prefix, "prefix") |> plan() - assert delete_all(query) == ~s{DELETE FROM "prefix"."schema" AS s0} + assert_raise ArgumentError, "SQLite3 does not support table prefixes", fn -> + delete_all(query) + end query = Schema @@ -1456,7 +1462,9 @@ defmodule Ecto.Adapters.SQLite3.ConnectionTest do |> Map.put(:prefix, "prefix") |> plan() - assert delete_all(query) == ~s{DELETE FROM "first"."schema" AS s0} + assert_raise ArgumentError, "SQLite3 does not support table prefixes", fn -> + delete_all(query) + end end ## @@ -1769,12 +1777,9 @@ defmodule Ecto.Adapters.SQLite3.ConnectionTest do |> Map.put(:prefix, "prefix") |> plan() - assert all(query) == - """ - SELECT 1 \ - FROM "prefix"."schema" AS s0 \ - INNER JOIN "prefix"."schema2" AS s1 ON s0."x" = s1."z"\ - """ + assert_raise ArgumentError, "SQLite3 does not support table prefixes", fn -> + all(query) + end query = Schema @@ -1784,12 +1789,9 @@ defmodule Ecto.Adapters.SQLite3.ConnectionTest do |> Map.put(:prefix, "prefix") |> plan() - assert all(query) == - """ - SELECT 1 \ - FROM "first"."schema" AS s0 \ - INNER JOIN "second"."schema2" AS s1 ON s0."x" = s1."z"\ - """ + assert_raise ArgumentError, "SQLite3 does not support table prefixes", fn -> + all(query) + end end test "join with fragment" do @@ -2015,8 +2017,9 @@ defmodule Ecto.Adapters.SQLite3.ConnectionTest do query = insert(nil, "schema", [], [[]], {:raise, [], []}, []) assert query == ~s{INSERT INTO "schema" DEFAULT VALUES} - query = insert("prefix", "schema", [], [[]], {:raise, [], []}, []) - assert query == ~s{INSERT INTO "prefix"."schema" DEFAULT VALUES} + assert_raise ArgumentError, "SQLite3 does not support table prefixes", fn -> + insert("prefix", "schema", [], [[]], {:raise, [], []}, []) + end query = insert(nil, "schema", [:x, :y], [[:x, :y]], {:raise, [], []}, [:id]) assert query == ~s{INSERT INTO "schema" ("x","y") VALUES (?,?) RETURNING "id"} @@ -2150,8 +2153,9 @@ defmodule Ecto.Adapters.SQLite3.ConnectionTest do query = delete(nil, "schema", [x: 1, y: 2], []) assert query == ~s{DELETE FROM "schema" WHERE "x" = ? AND "y" = ?} - query = delete("prefix", "schema", [x: 1, y: 2], []) - assert query == ~s{DELETE FROM "prefix"."schema" WHERE "x" = ? AND "y" = ?} + assert_raise ArgumentError, "SQLite3 does not support table prefixes", fn -> + delete("prefix", "schema", [x: 1, y: 2], []) + end query = delete(nil, "schema", [x: nil, y: 1], []) assert query == ~s{DELETE FROM "schema" WHERE "x" IS NULL AND "y" = ?} @@ -2209,13 +2213,9 @@ defmodule Ecto.Adapters.SQLite3.ConnectionTest do {:create, table(:posts, prefix: :foo), [{:add, :category_0, %Reference{table: :categories}, []}]} - assert execute_ddl(create) == [ - """ - CREATE TABLE "foo"."posts" (\ - "category_0" INTEGER CONSTRAINT "posts_category_0_fkey" REFERENCES "foo"."categories"("id")\ - )\ - """ - ] + assert_raise ArgumentError, "SQLite3 does not support table prefixes", fn -> + execute_ddl(create) + end end test "create table with references" do @@ -2230,8 +2230,9 @@ defmodule Ecto.Adapters.SQLite3.ConnectionTest do [null: false]}, {:add, :category_4, %Reference{table: :categories, on_delete: :nilify_all}, []}, - {:add, :category_5, - %Reference{table: :categories, prefix: :foo, on_delete: :nilify_all}, []}, + # SQLite3 does not support table prefixes + # {:add, :category_5, + # %Reference{table: :categories, prefix: :foo, on_delete: :nilify_all}, []}, {:add, :category_6, %Reference{table: :categories, with: [here: :there], on_delete: :nilify_all}, []}, @@ -2248,7 +2249,7 @@ defmodule Ecto.Adapters.SQLite3.ConnectionTest do "category_2" INTEGER CONSTRAINT "posts_category_2_fkey" REFERENCES "categories"("id"), \ "category_3" INTEGER NOT NULL CONSTRAINT "posts_category_3_fkey" REFERENCES "categories"("id") ON DELETE CASCADE, \ "category_4" INTEGER CONSTRAINT "posts_category_4_fkey" REFERENCES "categories"("id") ON DELETE SET NULL, \ - "category_5" INTEGER CONSTRAINT "posts_category_5_fkey" REFERENCES "foo"."categories"("id") ON DELETE SET NULL, \ + \ "category_6" INTEGER, \ "category_7" INTEGER, \ FOREIGN KEY ("category_6","here") REFERENCES "categories"("id","there") ON DELETE SET NULL, \ @@ -2402,7 +2403,9 @@ defmodule Ecto.Adapters.SQLite3.ConnectionTest do test "drop table with prefixes" do drop = {:drop, table(:posts, prefix: :foo), :restrict} - assert execute_ddl(drop) == [~s|DROP TABLE "foo"."posts"|] + assert_raise ArgumentError, "SQLite3 does not support table prefixes", fn -> + execute_ddl(drop) + end end test "drop constraint" do @@ -2479,17 +2482,9 @@ defmodule Ecto.Adapters.SQLite3.ConnectionTest do {:add, :author_id, %Reference{table: :author}, []} ]} - assert execute_ddl(alter) == [ - """ - ALTER TABLE "foo"."posts" \ - ADD COLUMN "title" TEXT DEFAULT 'Untitled' NOT NULL\ - """, - """ - ALTER TABLE "foo"."posts" \ - ADD COLUMN "author_id" INTEGER \ - CONSTRAINT "posts_author_id_fkey" REFERENCES "foo"."author"("id")\ - """ - ] + assert_raise ArgumentError, "SQLite3 does not support table prefixes", fn -> + execute_ddl(alter) + end end test "alter column errors for :modify column" do @@ -2567,32 +2562,25 @@ defmodule Ecto.Adapters.SQLite3.ConnectionTest do test "create index with prefix" do create = {:create, index(:posts, [:category_id, :permalink], prefix: :foo)} - assert execute_ddl(create) == [ - """ - CREATE INDEX "posts_category_id_permalink_index" \ - ON "foo"."posts" ("category_id", "permalink")\ - """ - ] + assert_raise ArgumentError, "SQLite3 does not support table prefixes", fn -> + execute_ddl(create) + end create = {:create, index(:posts, ["lower(permalink)"], name: "posts$main", prefix: :foo)} - assert execute_ddl(create) == [ - """ - CREATE INDEX "posts$main" ON "foo"."posts" (lower(permalink))\ - """ - ] + assert_raise ArgumentError, "SQLite3 does not support table prefixes", fn -> + execute_ddl(create) + end end test "create index with comment" do - create = - {:create, - index(:posts, [:category_id, :permalink], prefix: :foo, comment: "comment")} + create = {:create, index(:posts, [:category_id, :permalink], comment: "comment")} assert execute_ddl(create) == [ """ CREATE INDEX "posts_category_id_permalink_index" \ - ON "foo"."posts" ("category_id", "permalink")\ + ON "posts" ("category_id", "permalink")\ """ ] @@ -2676,7 +2664,10 @@ defmodule Ecto.Adapters.SQLite3.ConnectionTest do test "drop index with prefix" do drop = {:drop, index(:posts, [:id], name: "posts$main", prefix: :foo), :restrict} - assert execute_ddl(drop) == [~s|DROP INDEX "foo"."posts$main"|] + + assert_raise ArgumentError, "SQLite3 does not support table prefixes", fn -> + execute_ddl(drop) + end end test "drop index if exists" do @@ -2757,9 +2748,9 @@ defmodule Ecto.Adapters.SQLite3.ConnectionTest do test "rename table with prefix" do rename = {:rename, table(:posts, prefix: :foo), table(:new_posts, prefix: :foo)} - assert execute_ddl(rename) == [ - ~s|ALTER TABLE "foo"."posts" RENAME TO "new_posts"| - ] + assert_raise ArgumentError, "SQLite3 does not support table prefixes", fn -> + execute_ddl(rename) + end end test "rename column" do @@ -2773,9 +2764,9 @@ defmodule Ecto.Adapters.SQLite3.ConnectionTest do test "rename column in prefixed table" do rename = {:rename, table(:posts, prefix: :foo), :given_name, :first_name} - assert execute_ddl(rename) == [ - ~s|ALTER TABLE "foo"."posts" RENAME COLUMN "given_name" TO "first_name"| - ] + assert_raise ArgumentError, "SQLite3 does not support table prefixes", fn -> + execute_ddl(rename) + end end test "drop column" do