sql.exs (5295B)
1 defmodule Ecto.Integration.SQLTest do 2 use Ecto.Integration.Case, async: Application.compile_env(:ecto, :async_integration_tests, true) 3 4 alias Ecto.Integration.PoolRepo 5 alias Ecto.Integration.TestRepo 6 alias Ecto.Integration.Barebone 7 alias Ecto.Integration.Post 8 alias Ecto.Integration.CorruptedPk 9 import Ecto.Query, only: [from: 2] 10 11 test "fragmented types" do 12 datetime = ~N[2014-01-16 20:26:51] 13 TestRepo.insert!(%Post{inserted_at: datetime}) 14 query = from p in Post, where: fragment("? >= ?", p.inserted_at, ^datetime), select: p.inserted_at 15 assert [^datetime] = TestRepo.all(query) 16 end 17 18 test "fragmented schemaless types" do 19 TestRepo.insert!(%Post{visits: 123}) 20 assert [123] = TestRepo.all(from p in "posts", select: type(fragment("visits"), :integer)) 21 end 22 23 @tag :array_type 24 test "fragment array types" do 25 text1 = "foo" 26 text2 = "bar" 27 result = TestRepo.query!("SELECT $1::text[]", [[text1, text2]]) 28 assert result.rows == [[[text1, text2]]] 29 end 30 31 test "query!/4 with dynamic repo" do 32 TestRepo.put_dynamic_repo(:unknown) 33 assert_raise RuntimeError, ~r/:unknown/, fn -> TestRepo.query!("SELECT 1") end 34 end 35 36 test "query!/4" do 37 result = TestRepo.query!("SELECT 1") 38 assert result.rows == [[1]] 39 end 40 41 test "query!/4 with iodata" do 42 result = TestRepo.query!(["SELECT", ?\s, ?1]) 43 assert result.rows == [[1]] 44 end 45 46 test "disconnect_all/2" do 47 assert :ok = PoolRepo.disconnect_all(0) 48 end 49 50 test "to_sql/3" do 51 {sql, []} = TestRepo.to_sql(:all, Barebone) 52 assert sql =~ "SELECT" 53 assert sql =~ "barebones" 54 55 {sql, [0]} = TestRepo.to_sql(:update_all, from(b in Barebone, update: [set: [num: ^0]])) 56 assert sql =~ "UPDATE" 57 assert sql =~ "barebones" 58 assert sql =~ "SET" 59 60 {sql, []} = TestRepo.to_sql(:delete_all, Barebone) 61 assert sql =~ "DELETE" 62 assert sql =~ "barebones" 63 end 64 65 test "raises when primary key is not unique on struct operation" do 66 schema = %CorruptedPk{a: "abc"} 67 TestRepo.insert!(schema) 68 TestRepo.insert!(schema) 69 TestRepo.insert!(schema) 70 71 assert_raise Ecto.MultiplePrimaryKeyError, 72 ~r|expected delete on corrupted_pk to return at most one entry but got 3 entries|, 73 fn -> TestRepo.delete!(schema) end 74 end 75 76 test "Repo.insert! escape" do 77 TestRepo.insert!(%Post{title: "'"}) 78 79 query = from(p in Post, select: p.title) 80 assert ["'"] == TestRepo.all(query) 81 end 82 83 test "Repo.update! escape" do 84 p = TestRepo.insert!(%Post{title: "hello"}) 85 TestRepo.update!(Ecto.Changeset.change(p, title: "'")) 86 87 query = from(p in Post, select: p.title) 88 assert ["'"] == TestRepo.all(query) 89 end 90 91 @tag :insert_cell_wise_defaults 92 test "Repo.insert_all escape" do 93 TestRepo.insert_all(Post, [%{title: "'"}]) 94 95 query = from(p in Post, select: p.title) 96 assert ["'"] == TestRepo.all(query) 97 end 98 99 test "Repo.update_all escape" do 100 TestRepo.insert!(%Post{title: "hello"}) 101 102 TestRepo.update_all(Post, set: [title: "'"]) 103 reader = from(p in Post, select: p.title) 104 assert ["'"] == TestRepo.all(reader) 105 106 query = from(Post, where: "'" != "") 107 TestRepo.update_all(query, set: [title: "''"]) 108 assert ["''"] == TestRepo.all(reader) 109 end 110 111 test "Repo.delete_all escape" do 112 TestRepo.insert!(%Post{title: "hello"}) 113 assert [_] = TestRepo.all(Post) 114 115 TestRepo.delete_all(from(Post, where: "'" == "'")) 116 assert [] == TestRepo.all(Post) 117 end 118 119 test "load" do 120 inserted_at = ~N[2016-01-01 09:00:00] 121 TestRepo.insert!(%Post{title: "title1", inserted_at: inserted_at, public: false}) 122 123 result = Ecto.Adapters.SQL.query!(TestRepo, "SELECT * FROM posts", []) 124 posts = Enum.map(result.rows, &TestRepo.load(Post, {result.columns, &1})) 125 assert [%Post{title: "title1", inserted_at: ^inserted_at, public: false}] = posts 126 end 127 128 test "returns true when table exists" do 129 assert Ecto.Adapters.SQL.table_exists?(TestRepo, "posts") 130 end 131 132 test "returns false table doesn't exists" do 133 refute Ecto.Adapters.SQL.table_exists?(TestRepo, "unknown") 134 end 135 136 test "returns result as a formatted table" do 137 TestRepo.insert_all(Post, [%{title: "my post title", counter: 1, public: nil}]) 138 139 # resolve correct query for each adapter 140 query = from(p in Post, select: [p.title, p.counter, p.public]) 141 {query, _} = Ecto.Adapters.SQL.to_sql(:all, TestRepo, query) 142 143 table = 144 query 145 |> TestRepo.query!() 146 |> Ecto.Adapters.SQL.format_table() 147 148 assert table == "+---------------+---------+--------+\n| title | counter | public |\n+---------------+---------+--------+\n| my post title | 1 | NULL |\n+---------------+---------+--------+" 149 end 150 151 test "format_table edge cases" do 152 assert Ecto.Adapters.SQL.format_table(nil) == "" 153 assert Ecto.Adapters.SQL.format_table(%{columns: nil, rows: nil}) == "" 154 assert Ecto.Adapters.SQL.format_table(%{columns: [], rows: []}) == "" 155 assert Ecto.Adapters.SQL.format_table(%{columns: [], rows: [["test"]]}) == "" 156 assert Ecto.Adapters.SQL.format_table(%{columns: ["test"], rows: []}) == "+------+\n| test |\n+------+\n+------+" 157 assert Ecto.Adapters.SQL.format_table(%{columns: ["test"], rows: nil}) == "+------+\n| test |\n+------+\n+------+" 158 end 159 end