-
Notifications
You must be signed in to change notification settings - Fork 313
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
Proposal: Add :prepare option for Postgres Adapter #372
Proposal: Add :prepare option for Postgres Adapter #372
Conversation
My only concern with this option is the |
I'll take a closer look at the cache handling and come back with a different proposal. Thanks! |
It looks like something like this can be done: In the ecto repository, specifically Ecto.Query.Planner.finalize_cache, can add
Then in ecto_sql can can have the name creation logic ( I think it's possible to ignore this option for everything that's not Postgres and default it to |
Oh, I think we may be fine with the current approach, as long as we store if the query was prepared or not in the cache? If the query was not prepared and then it is later requested to be prepared, then do so and we update the cache? We can use the callback functions listed here: https://github.com/elixir-ecto/ecto/blob/master/lib/ecto/query/planner.ex#L129-L135 |
That makes sense. I'm trying to see if it's necessary to use the It looks like if you use the I'm just not sure if somehow this code segment can get hit when we wouldn't want it to. If it hits this then potentially something that needs to be prepared wouldn't be defp handle_execute_result(%{ref: ref} = query, params, opts, %{postgres: {_, ref}} = s) do
# ref in lock so query is prepared
status = new_status(opts)
case query do
%{name: ""} -> bind_execute_close(s, status, query, params)
_ -> bind_execute(s, status, query, params)
end
end Do you think it's safer to always call |
Actually nevermind it seems like the query It seems like |
I will do the following changes, if you are alright with them. Submit a PR to Ecto with the following changes:
Then to this PR will add:
Or I can do the cache key change if it's preferable to avoid the re-preparing when flip flopping. |
Can’t we handle it in ecto_sql exclusively? |
Ah yes sorry I see what you mean now. I'll submit something soon. |
@josevalim Thanks for your guidance. Was curious what you think about this approach. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I love this direction! I am just not sure why we have the :use_cache
option. Couldn't we access the prepare option downstream instead? 🤔
Oh yeah if you prefer to leave it as |
I could also leave the option name as edit: Though I guess having prepare = false and then calling prepare_execute kind of looks weird. |
I didn't dive a lot into this issue, so I may be saying some non-sense here, but doesn't this do the same as passing |
I think using
|
@josevalim Sorry just to be clear, did you mean to use |
I think we can keep it as |
I think it's a good way to go. It works for everything existing now. Can change later if needed. |
@josevalim Think it's good to go. Did the following things:
|
I had one thought actually. I think it's possible custom adapters can specify their own Like if someone creates their own Teradata adapter then they might want to call It probably makes more sense to add a |
Beautiful! The solution you landed on is quite elegant! 💚 💙 💜 💛 ❤️ |
Because of the way Postgres generates plans for prepared statements, sometimes it is beneficial to disable them (i.e. use an unnamed prepared statement). See this Postgrex issue for more details.
You can currently use unnamed prepared statements, but they are set at the Repo config level and would apply to all queries. This means the user can't pick and choose which queries benefit from this feature.
This proposal is to allow the Postgres adapter to recognize a
:prepare
option and to overwrite the Ecto-generated name with empty string. This is similar to what happens in Postgrex whenprepare: :unnamed
is configured on the connection. See this excerpt from Postgrex.Protocol:This way you still get the benefits of the Ecto cache but without the potentially harmful effects of the Postgres cache. One potential pitfall is that once you issue the query you can't change the
:prepare
option because the prepare step will be skipped. I think that's ok but let me know what you guys think.The change is restricted to the Postgres adapter because I don't think the other adapters handle empty string names the same way. I could be mistaken though, since I'm not as familiar with them. Postgres will treat this as a "one shot" name and allow it to be re-defined without explicitly telling it that you're done with the old definition.
Note that this option is meant as a convenience. You can currently issue an unnamed query using
Ecto.Adapters.SQL.query
but then you don't get all the nice Ecto conveniences.If you guys like this proposal then I think the following things also need to be done:
Ecto.Adapters.Postgres.Connection.prepare_execute
then I could inspect the name of the query.