From d8d468a97fb4d2a6cdaee5c4e9fca5f0958da984 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Fri, 17 Apr 2020 19:32:30 +0200 Subject: [PATCH] Allow cache statement to be per operation instead Closes https://github.com/elixir-ecto/ecto/issues/3284. --- lib/ecto/adapters/myxql.ex | 4 ++++ lib/ecto/adapters/postgres.ex | 4 ++++ lib/ecto/adapters/sql.ex | 14 ++++++++++---- lib/ecto/adapters/tds.ex | 7 +++++++ 4 files changed, 25 insertions(+), 4 deletions(-) diff --git a/lib/ecto/adapters/myxql.ex b/lib/ecto/adapters/myxql.ex index 839633ff..b7bdb7d7 100644 --- a/lib/ecto/adapters/myxql.ex +++ b/lib/ecto/adapters/myxql.ex @@ -28,6 +28,10 @@ defmodule Ecto.Adapters.MyXQL do This option is only used for `mix ecto.load` and `mix ecto.dump`, via the `mysql` command. For more information, please check [MySQL docs](https://dev.mysql.com/doc/en/connecting.html) + * `:cache_statement` - how Ecto should cache INSERT/UPDATE/DELETE statements. + It can either be `:per_schema` (one cache key is used for each schema) or + `:per_operation` (one cache key is use for each operation). Note SELECTs + use a more complete cache mechanism that considers the query itself. * `:socket_options` - Specifies socket configuration * `:show_sensitive_data_on_connection_error` - show connection data and configuration whenever there is an error attempting to connect to the diff --git a/lib/ecto/adapters/postgres.ex b/lib/ecto/adapters/postgres.ex index 44ccf99f..5f56f2b2 100644 --- a/lib/ecto/adapters/postgres.ex +++ b/lib/ecto/adapters/postgres.ex @@ -40,6 +40,10 @@ defmodule Ecto.Adapters.Postgres do * `:ssl` - Set to true if ssl should be used (default: false) * `:ssl_opts` - A list of ssl options, see Erlang's `ssl` docs * `:parameters` - Keyword list of connection parameters + * `:cache_statement` - how Ecto should cache INSERT/UPDATE/DELETE statements. + It can either be `:per_schema` (one cache key is used for each schema) or + `:per_operation` (one cache key is use for each operation). Note SELECTs + use a more complete cache mechanism that considers the query itself. * `:connect_timeout` - The timeout for establishing new connections (default: 5000) * `:prepare` - How to prepare queries, either `:named` to use named queries or `:unnamed` to force unnamed queries (default: `:named`) diff --git a/lib/ecto/adapters/sql.ex b/lib/ecto/adapters/sql.ex index 4e42f8d3..ad1537eb 100644 --- a/lib/ecto/adapters/sql.ex +++ b/lib/ecto/adapters/sql.ex @@ -453,9 +453,10 @@ defmodule Ecto.Adapters.SQL do telemetry_prefix = Keyword.fetch!(config, :telemetry_prefix) telemetry = {config[:repo], log, telemetry_prefix ++ [:query]} + cache_statement = Keyword.get(config, :cache_statement, :per_schema) config = adapter_config(config) opts = Keyword.take(config, @pool_opts) - meta = %{telemetry: telemetry, sql: connection, opts: opts} + meta = %{telemetry: telemetry, sql: connection, opts: opts, cache_statement: cache_statement} {:ok, connection.child_spec(config), meta} end @@ -489,6 +490,12 @@ defmodule Ecto.Adapters.SQL do ## Query + defp cache_statement(%{cache_statement: :per_schema}, operation, source), + do: "ecto_#{operation}_#{source}" + + defp cache_statement(%{cache_statement: :per_operation}, operation, _source), + do: "ecto_#{operation}" + @doc false def insert_all(adapter_meta, schema_meta, conn, header, rows, on_conflict, returning, opts) do %{source: source, prefix: prefix} = schema_meta @@ -496,8 +503,7 @@ defmodule Ecto.Adapters.SQL do {rows, params} = unzip_inserts(header, rows) sql = conn.insert(prefix, source, header, rows, on_conflict, returning) - cache_statement = "ecto_insert_all_#{source}" - opts = [{:cache_statement, cache_statement} | opts] + opts = [{:cache_statement, cache_statement(adapter_meta, "insert_all", source)} | opts] %{num_rows: num, rows: rows} = query!(adapter_meta, sql, Enum.reverse(params) ++ conflict_params, opts) @@ -626,7 +632,7 @@ defmodule Ecto.Adapters.SQL do @doc false def struct(adapter_meta, conn, sql, operation, source, params, values, on_conflict, returning, opts) do - cache_statement = "ecto_#{operation}_#{source}" + cache_statement = cache_statement(adapter_meta, operation, source) case query(adapter_meta, sql, values, [cache_statement: cache_statement] ++ opts) do {:ok, %{rows: nil, num_rows: 1}} -> diff --git a/lib/ecto/adapters/tds.ex b/lib/ecto/adapters/tds.ex index 235d75e6..4e6d3110 100644 --- a/lib/ecto/adapters/tds.ex +++ b/lib/ecto/adapters/tds.ex @@ -18,6 +18,13 @@ defmodule Ecto.Adapters.Tds do * `:pool` - The connection pool module, defaults to `DBConnection.ConnectionPool` * `:ssl` - Set to true if ssl should be used (default: false) * `:ssl_opts` - A list of ssl options, see Erlang's `ssl` docs + * `:cache_statement` - how Ecto should cache INSERT/UPDATE/DELETE statements. + It can either be `:per_schema` (one cache key is used for each schema) or + `:per_operation` (one cache key is use for each operation). Note SELECTs + use a more complete cache mechanism that considers the query itself. + * `:show_sensitive_data_on_connection_error` - show connection data and + configuration whenever there is an error attempting to connect to the + database We also recommend developers to consult the `Tds.start_link/1` documentation for a complete list of all supported options for driver.