-
Notifications
You must be signed in to change notification settings - Fork 854
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
Simplify registration of custom types with pgxpool #2054
base: master
Are you sure you want to change the base?
Conversation
I'm not following all that's going on here, but I still wonder if we really want helper configuration like ... 🤔 ... 🤔 ... Hmm... I think you're half way to an enormous improvement in making it easy to support custom types. What if the There would be no new public function or methods, only a couple additions to |
The reason I see pgxpool as the right place for this is that if someone is directly using connections, they want more control over their operations, and can handle the sequencing of calling to autoload. The place where caching the calls comes in is when you are using connection pooling, and it doesn't make sense to have a mutex on each connection, as it's the pool which should coordinate the loading phase of things. I haven't fully reflected on this, so might follow up a little later in more detail. This PR is mostly meant to capture my idea, and it's better IMO to look at the other 2 PRs first, with this one just showing you what is going on in my head for subsequent enhancements. |
Okay, I'll comment on #2046. |
The problem of pushing this logic down the the connection (config) is that it gets harder to be smart about only doing this once for the connection pool. If every connection automatically makes up to 2 queries to the database when it's created (one if there are custom registrations, like If this logic is moved from pgxpool to the connection, either it would still need to be done here, causing code duplication, or we would need to provide a way for the pool to provide the I really think that if someone has elected to not use pgxpool, they want more fine-grained control of exactly how each connection is set up, including how types are registered. They are only creating a single connection, so whether they register a handler with ConnConfig or just call the function themself, it's all the same; there is no win for a single connection in registering a handler which is only called once. In general I'd say we want to promote the use of pgxpool over directly making connections, unless you know what you are doing. By keeping these optimisations on pgxpool, we aren't preventing people using |
0097c59
to
021bf72
Compare
Right. That's what I was thinking we would want to do. I'm not sure of the exact interface, but it just feels off to me to have a config option that really is for a connection to not be available on the connection and only be available on the pool. Perhaps the interface on the conn should be a callback function specifically for loading types. There could be a helper function to build this that would take the list of derived types and the map of custom types. The pool would replace this function on the config with a function that copied the the type map for each connection after the first. IDK... |
If someone is making a single connection, they need to:
We could have one ConnConfig field which can hold the sequence of functions, for the first step, and a second one holding a list of type names, for the second. But we would also need a third field which would hold a precalculated sequence of types. This last field would be populated by pgxpool with the types calculated by the first two steps (and one way or another, if the last field is populated, the first two fields would not be used). Is this what you mean? It can be done this way. If it was, I guess the process would be something like this, when pgxpool is used:
This can be done, and ultimately it's your call. If the majority of users did not want to reuse the type mapping, I would agree with you that it's better, as the same approach is used to define the type names and the registration functions regardless of whether the connection is going to be used with a pool or not. I really just want to repeat what I said earlier: that if someone is managing their connections manually (without using a pool), they are probably doing something exotic. If they have custom registrations, it doesn't help them to define them as functions. If they want to load types after (or before) doing their custom registrations, calling In a sense, From my perspective, my primary goal is to get these PRs merged. It's going to work either way. I would be wary of making |
44eb7b7
to
cc208ca
Compare
When loading even a single type into pgx's type map, multiple SQL queries are performed in series. Over a slow link, this is not ideal. Worse, if multiple types are being registered, this is repeated multiple times. This commit add LoadTypes, which can retrieve type mapping information for multiple types in a single SQL call, including recursive fetching of dependent types. RegisterTypes performs the second stage of this operation.
Provide a backwards-compatible configuration option for pgxpool which streamlines the use of the bulk loading and registration of types: - ReuseTypeMaps: if enabled, pgxpool will cache the typemap information, avoiding the need to perform any further queries as new connections are created. ReuseTypeMaps is disabled by default as in some situations, a connection string might resolve to a pool of servers which do not share the same type name -> OID mapping.
Provide a backwards-compatible configuration option for pgxpool which streamlines the use of the bulk loading and registration of types: - ReuseTypeMaps: if enabled, pgxpool will cache the typemap information, avoiding the need to perform any further queries as new connections are created. ReuseTypeMaps is disabled by default as in some situations, a connection string might resolve to a pool of servers which do not share the same type name -> OID mapping.
cc208ca
to
43edb0e
Compare
Sometimes pgx is not capable of inferring the correct codec by
inspecting the database, as is done with LoadType(s), and requires
a user-defined operation to be performed instead.
To allow these custom types to also benefit from connection
initialisation, it is possible to register these functions with pgxpool
using the new RegisterCustomType method.
When using the default configuration, this will still require each new
connection to perform one query to the backend to retrieve the OIDs for
these custom types. This is already a benefit, instead of requiring
a query for each custom type, with the associated latency.
Even better, when the reuseTypeMap pgxpool configuration is selected,
only the first connection requires this query; subsequent connections
will execute the custom registration code, using the cached OID mapping.