Skip to content

Commit 7971489

Browse files
committed
Skip the default cache_statement when :comments are given
1 parent 39ea348 commit 7971489

4 files changed

Lines changed: 62 additions & 23 deletions

File tree

integration_test/sql/logging.exs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -199,12 +199,18 @@ defmodule Ecto.Integration.LoggingTest do
199199
end) =~ ~r{/\* before_q \*/ SELECT.* /\* after_q \*/}
200200
end
201201

202-
test "renders with query_cache: false (the escape hatch for dynamic comments)" do
202+
test "dynamic comments render and skip the query cache by default" do
203203
assert capture_log(fn ->
204-
TestRepo.all(Post, comments: [pre: "dyn_#{System.unique_integer()}"], query_cache: false, log: :error)
204+
TestRepo.all(Post, comments: [pre: "dyn_#{System.unique_integer()}"], log: :error)
205205
end) =~ ~r{/\* dyn_-?\d+ \*/ SELECT}
206206
end
207207

208+
test "query_cache: true opts back into caching for static comments" do
209+
assert capture_log(fn ->
210+
TestRepo.all(Post, comments: [pre: "static_q"], query_cache: true, log: :error)
211+
end) =~ "/* static_q */ SELECT"
212+
end
213+
208214
test "comments insert/update/delete/insert_all" do
209215
assert capture_log(fn ->
210216
TestRepo.insert!(%Post{title: "1"}, comments: [pre: "insert_create_post_q"], log: :error)

lib/ecto/adapters/myxql.ex

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -373,15 +373,9 @@ defmodule Ecto.Adapters.MyXQL do
373373
insert_opts = if opts[:insert_mode], do: [insert_mode: opts[:insert_mode]], else: []
374374
sql = @conn.insert(prefix, source, fields, [fields], on_conflict, [], [], insert_opts)
375375

376-
opts =
377-
if is_nil(Keyword.get(opts, :cache_statement)) do
378-
[{:cache_statement, "ecto_insert_#{source}_#{length(fields)}"} | opts]
379-
else
380-
opts
381-
end
382-
383376
# This adapter overrides insert/6 instead of going through
384377
# Ecto.Adapters.SQL.struct/10, so wrap the `:comments` here too.
378+
opts = Ecto.Adapters.SQL.put_default_cache_statement(opts, "ecto_insert_#{source}_#{length(fields)}")
385379
sql = Ecto.Adapters.SQL.wrap_comments(sql, opts)
386380

387381
case Ecto.Adapters.SQL.query(adapter_meta, sql, values ++ query_params, opts) do

lib/ecto/adapters/sql.ex

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -985,13 +985,7 @@ defmodule Ecto.Adapters.SQL do
985985

986986
sql = conn.insert(prefix, source, header, rows, on_conflict, returning, placeholders, opts)
987987

988-
opts =
989-
if is_nil(Keyword.get(opts, :cache_statement)) do
990-
[{:cache_statement, "ecto_insert_all_#{source}"} | opts]
991-
else
992-
opts
993-
end
994-
988+
opts = put_default_cache_statement(opts, "ecto_insert_all_#{source}")
995989
sql = wrap_comments(sql, opts)
996990

997991
all_params = placeholders ++ Enum.reverse(params, conflict_params)
@@ -1179,6 +1173,20 @@ defmodule Ecto.Adapters.SQL do
11791173
[pre, sql | post]
11801174
end
11811175

1176+
# Comments become part of the statement text, so a varying comment under a
1177+
# fixed cache name would make the driver close and re-prepare the statement
1178+
# on every call (drivers compare the cached text). Skip the default statement
1179+
# cache whenever comments are given; an explicit :cache_statement still wins,
1180+
# which keeps caching available for callers with static comments.
1181+
@doc false
1182+
def put_default_cache_statement(opts, name) do
1183+
if is_nil(Keyword.get(opts, :cache_statement)) and Keyword.get(opts, :comments, []) == [] do
1184+
[{:cache_statement, name} | opts]
1185+
else
1186+
opts
1187+
end
1188+
end
1189+
11821190
@doc false
11831191
def comments(comments) when is_list(comments) do
11841192
{pre, post} =
@@ -1222,13 +1230,7 @@ defmodule Ecto.Adapters.SQL do
12221230
returning,
12231231
opts
12241232
) do
1225-
opts =
1226-
if is_nil(Keyword.get(opts, :cache_statement)) do
1227-
[{:cache_statement, "ecto_#{operation}_#{source}_#{length(params)}"} | opts]
1228-
else
1229-
opts
1230-
end
1231-
1233+
opts = put_default_cache_statement(opts, "ecto_#{operation}_#{source}_#{length(params)}")
12321234
sql = wrap_comments(sql, opts)
12331235

12341236
case query(adapter_meta, sql, values, [source: source] ++ opts) do

test/ecto/adapters/sql_test.exs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,4 +54,41 @@ defmodule Ecto.Adapters.SQLTest do
5454
assert wrap("INSERT INTO posts ...", timeout: 5000) == "INSERT INTO posts ..."
5555
end
5656
end
57+
58+
describe "put_default_cache_statement/2" do
59+
test "sets the default name" do
60+
opts = Ecto.Adapters.SQL.put_default_cache_statement([timeout: 5000], "ecto_insert_posts")
61+
assert Keyword.get(opts, :cache_statement) == "ecto_insert_posts"
62+
end
63+
64+
test "honors an explicit :cache_statement" do
65+
opts = Ecto.Adapters.SQL.put_default_cache_statement([cache_statement: "mine"], "default")
66+
assert Keyword.get(opts, :cache_statement) == "mine"
67+
end
68+
69+
test "skips the default when comments are given" do
70+
opts =
71+
Ecto.Adapters.SQL.put_default_cache_statement(
72+
[comments: [pre: "dyn_123"]],
73+
"ecto_insert_posts"
74+
)
75+
76+
assert Keyword.get(opts, :cache_statement) == nil
77+
end
78+
79+
test "an explicit :cache_statement wins even with comments" do
80+
opts =
81+
Ecto.Adapters.SQL.put_default_cache_statement(
82+
[comments: [pre: "static_tag"], cache_statement: "mine"],
83+
"default"
84+
)
85+
86+
assert Keyword.get(opts, :cache_statement) == "mine"
87+
end
88+
89+
test "an empty :comments list still gets the default" do
90+
opts = Ecto.Adapters.SQL.put_default_cache_statement([comments: []], "ecto_insert_posts")
91+
assert Keyword.get(opts, :cache_statement) == "ecto_insert_posts"
92+
end
93+
end
5794
end

0 commit comments

Comments
 (0)