-
Notifications
You must be signed in to change notification settings - Fork 17.7k
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: database/sql: define a SQL driver unwrapper interface and helper function #42460
Comments
CC @kardianos |
I suspect this will be a "no". Have you explored a custom connector that then exposes this functionality? |
It sounds like this is errors.Unwrap for sql.Driver. But why are sql.Drivers being wrapped so much? |
A reason we use sql driver wrapping at ZipRecruiter is to extract tracing information from a context.Context and inject it into the actual query as a comment to achieve basic tracing. This way if a query is taking a long time to run you can see who initiated the query. https://github.com/ngrok/sqlmw is a package that assists with this and could trivially implement the proposal here. |
Related: #18080 |
OK, so I understand the point of having an "add tracing of SQL commands" wrapper driver. In general unwrapping is not a safe operation. Supposed you had, as a dumb example, a rot13-wrapping driver that stored all the data rot13'd (and did the reverse on the way back out). If you unwrapped to the raw driver underneath, any use of the calls would break the rot13 invariant. This comes up all the time for various things the wrappers are trying to ensure. We struggled a lot with errors here and for that specific case it was important to get at the underlying ones to test for specific errors and so on. But in general - for example in the FS API that we just adopted - unwrapping is not something that is safe and should be done. So why is unwrapping important for SQL drivers? When is it necessary, and why? |
A common pattern (across languages) is to use the driver to figure out what sql variant to use. For example pagination is different in almost all relational databases. I don't see a clear way (other than running queries against the database) to interrogate the DB object to figure out what kind of database you might be connected to. That's what's mentioned in the original post (dialect inference.) Frankly, I would suggest that sql generators (ORMs) not infer based on connection but instead outer layers, but I bet that's the main thought here. |
I wrote some MySQL wrappers at my last job and many ORMs allow to pass in a string or other identifier to tell it the "flavor" of the connection vs trying to type assert it. This is probably preferred since even a Unwrap method would still require modifications to the ORM/generator. |
This sounds like that it should be specified when creating ORM itself rather than derived from the driver or queries. e.g. For example, let's say there's a proxy driver, how would you query the instance to determine what dialect it's using? In principle the exact same driver/connector type could be used for different dialects. |
Well, in projects where I've come across this in the past, you start by discovering the driver, and if it's a multi-db driver (ODBC is an example of that) you then do queries against the DB to figure out what it is. Again: I'm not emphasizing that this should be done, but if you do it, this is how. |
How do you know it's a multi-db driver in the first place? |
Adding our application security agent use-case too: our sql-injection detection needs to know what is the SQL dialect being used. But when the driver is wrapped, we get the wrapper package path instead, and we can no longer infer the dialect. Note that our use-case would be definitely better solved by a specific way of getting the dialect being used at run time. |
How do you know it's a multi-db driver in the first place?
In the same way that you have code mapping drivers to dialects, you end up
with code that can do more and more accurate detection. The same thing
needs to be done even within a single driver if you care about different
support as a single engine evolves.
I'm not sure describing this in more depth is helpful for this discussion
any more. If someone is interested let me know and I can point at some
resources.
…On Wed, Dec 9, 2020, 11:41 PM Egon Elbre ***@***.***> wrote:
... discovering the driver, and if it's a multi-db driver ...
How do you know it's a multi-db driver in the first place?
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
<#42460 (comment)>, or
unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAAB7Y6RJQW5BTRSDR7WT3DSUB3RZANCNFSM4TPO5SIQ>
.
|
I'm not hearing a compelling use case for Unwrap. These seem like less-than-elegant uses that would not be 100% satisfied by Unwrap. Egon's comment above about orm.FromPostgres seems like a cleaner solution. (And if you want a 90% solution, instead of Unwrap you could use reflect to poke around.) |
Based on the discussion above, this proposal seems like a likely decline. |
No change in consensus, so declined. |
This proposal is motivated by the common need for a standard interface defining a standard way to unwrap SQL drivers that may have been wrapped by SQL instrumentation packages.
Problem
Such SQL driver wrapper types hide every other interface the wrapped type may implement. For example,
database/sql/driver
defines many optional interfaces that would be hidden by the following wrapper type definition:With this straightforward type definition,
myDriverWrapper
only implements interfacedriver.Driver
, no matter what the actual driver may implement besides thedriver.Driver
interface.SQL dialect detection functions based on the package path name gotten with
reflect
(withreflect.TypeOf(db.Driver()).PkgPath()
) will also break when using the wrapped driver.Proposed solution
Similarly to the
Unwrap
function of packageerrors
(https://golang.org/pkg/errors/#Unwrap), packagedatabase/sql/driver
could provide theUnwrapper
interface allowing a driver wrapper to return its underlying SQL driver, but also let third-party packages know about it:When a driver wrapper implements the
Unwrapper
interface, a third-party package is able to:And probably other use-cases I haven't considered :-)
The text was updated successfully, but these errors were encountered: