Skip to content

Search path is already supported by parameters option #729

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

Merged
merged 2 commits into from
Feb 2, 2025
Merged
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
@@ -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()

@@ -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`).
89 changes: 23 additions & 66 deletions lib/postgrex/protocol.ex
Original file line number Diff line number Diff line change
@@ -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
@@ -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,
@@ -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, [])
@@ -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)
@@ -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),