Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Search path is already supported by parameters option #729

Merged
merged 2 commits into from
Feb 2, 2025
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
9 changes: 0 additions & 9 deletions lib/postgrex.ex
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@ defmodule Postgrex do
| {:prepare, :named | :unnamed}
| {:transactions, :strict | :naive}
| {:types, module}
| {:search_path, [String.t()]}
| {:disconnect_on_error_codes, [atom]}
| DBConnection.start_option()

Expand Down Expand Up @@ -161,14 +160,6 @@ defmodule Postgrex do
option is only required when using custom encoding or decoding (default:
`Postgrex.DefaultTypes`);

* `:search_path` - A list of strings used to set the search path for the connection.
This is useful when, for instance, an extension like `citext` is installed in a
separate schema. If that schema is not in the connection's search path, Postgrex
might not be able to recognize the extension's data type. When this option is `nil`,
the search path is not modified. (default: `nil`).
See the [PostgreSQL docs](https://www.postgresql.org/docs/current/ddl-schemas.html#DDL-SCHEMAS-PATH)
for more details.

* `:disable_composite_types` - Set to `true` to disable composite types support.
This is useful when using Postgrex against systems that do not support composite types
(default: `false`).
Expand Down
89 changes: 23 additions & 66 deletions lib/postgrex/protocol.ex
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ defmodule Postgrex.Protocol do
disconnect_on_error_codes = opts[:disconnect_on_error_codes] || []
target_server_type = opts[:target_server_type] || :any
disable_composite_types = opts[:disable_composite_types] || false
parameters = opts[:parameters] || []

{ssl_opts, opts} =
case Keyword.pop(opts, :ssl, false) do
Expand Down Expand Up @@ -116,6 +117,25 @@ defmodule Postgrex.Protocol do
:unnamed -> :unnamed
end

parameters =
case opts[:search_path] do
path when is_list(path) ->
Logger.warning(
"the `:search_path` option is deprecated. Please use the `:parameters` option by " <>
"passing `:search_path` as a key and a comma delimited string as the value."
)

path = Enum.intersperse(path, ", ")
Keyword.put(parameters, :search_path, path)

nil ->
parameters

other ->
raise ArgumentError,
"expected :search_path to be a list of strings, got: #{inspect(other)}"
end

s = %__MODULE__{
timeout: timeout,
ping_timeout: ping_timeout,
Expand All @@ -128,15 +148,14 @@ defmodule Postgrex.Protocol do
connect_timeout = Keyword.get(opts, :connect_timeout, timeout)

status = %{
opts: opts,
opts: Keyword.put(opts, :parameters, parameters),
types_mod: types_mod,
types_key: nil,
types_lock: nil,
prepare: prepare,
messages: [],
ssl: ssl_opts,
target_server_type: target_server_type,
search_path: opts[:search_path]
target_server_type: target_server_type
}

connect_endpoints(endpoints, sock_opts ++ @sock_opts, connect_timeout, s, status, [])
Expand Down Expand Up @@ -916,7 +935,7 @@ defmodule Postgrex.Protocol do
init_recv(%{s | connection_id: pid, connection_key: key}, status, buffer)

{:ok, msg_ready(), buffer} ->
set_search_path(s, status, buffer)
check_target_server_type(s, status, buffer)

{:ok, msg_error(fields: fields), buffer} ->
disconnect(s, Postgrex.Error.exception(postgres: fields), buffer)
Expand All @@ -930,68 +949,6 @@ defmodule Postgrex.Protocol do
end
end

## set search path on connection startup

defp set_search_path(s, %{search_path: nil} = status, buffer),
do: set_search_path_done(s, status, buffer)

defp set_search_path(s, %{search_path: search_path} = status, buffer)
when is_list(search_path),
do: set_search_path_send(s, status, buffer)

defp set_search_path(_, %{search_path: search_path}, _) do
raise ArgumentError,
"expected :search_path to be a list of strings, got: #{inspect(search_path)}"
end

defp set_search_path_send(s, status, buffer) do
search_path = Enum.intersperse(status.search_path, ",")
msg = msg_query(statement: ["set search_path to " | search_path])

case msg_send(s, msg, buffer) do
:ok ->
set_search_path_recv(s, status, buffer)

{:disconnect, _, _} = dis ->
dis
end
end

defp set_search_path_recv(s, status, buffer) do
case msg_recv(s, :infinity, buffer) do
{:ok, msg_row_desc(fields: fields), buffer} ->
{[@text_type_oid], ["search_path"], _} = columns(fields)
set_search_path_recv(s, status, buffer)

{:ok, msg_data_row(), buffer} ->
set_search_path_recv(s, status, buffer)

{:ok, msg_command_complete(), buffer} ->
set_search_path_recv(s, status, buffer)

{:ok, msg_ready(status: :idle), buffer} ->
set_search_path_done(s, status, buffer)

{:ok, msg_ready(status: postgres), _buffer} ->
err = %Postgrex.Error{message: "unexpected postgres status: #{postgres}"}
{:disconnect, err, s}

{:ok, msg_error(fields: fields), buffer} ->
err = Postgrex.Error.exception(postgres: fields)
{:disconnect, err, %{s | buffer: buffer}}

{:ok, msg, buffer} ->
s = handle_msg(s, status, msg)
set_search_path_recv(s, status, buffer)

{:disconnect, _, _} = dis ->
dis
end
end

defp set_search_path_done(s, status, buffer),
do: check_target_server_type(s, status, buffer)

## check_target_server_type

defp check_target_server_type(s, %{target_server_type: :any} = status, buffer),
Expand Down
Loading