-
Notifications
You must be signed in to change notification settings - Fork 4
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
Implement driver.QueryerContext interface #4
Conversation
As per the [specifications](https://pkg.go.dev/database/sql/driver#QueryerContext), `QueryerContext` is an optional interface. When it's not implemented, the driver falls back to the `Queryer` interface that is also optional, and eventually defaults to: - preparing a query - executing the statement - closing the statement This means that the context passed to `QueryContext` gets completely ignored and therefore timeouts aren't honoured. This commit provides an implementation of the `QueryerContext` interface that honours the context. When the context expires or gets cancelled, the statement gets cancelled and closed, and upon completion, an error is returned.
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.
Looks great! We're definitely building this driver much better. This is not the first interface we've implemented, and it might not be the last.
A couple of comments:
- It seems like by implementing the interface, we need to copy-paste a lot of code from Somewhere ™️ . Where is this Somewhere? Is there any way we can use what already exists and add custom error handling just for when the context cancels?
- Did we consider adding any tests? I know its not the favourite chore but the feedback loop of pushing to master, building a new worker and testing that worker is really long. A testing framework could help. Also if we want this code merged upstream we are most likely going to need that. We want the code upstream so the open source community can maintain together with us.
What do y
} | ||
|
||
// namedValueToValue is a utility function that converts a driver.NamedValue into a driver.Value. | ||
func namedValueToValue(named []driver.NamedValue) ([]driver.Value, error) { |
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.
Should this be tested somehow?
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.
Whoops, I forgot to add code attribution for that part. This is coming from the Go codebase: https://github.com/golang/go/blob/03ac39ce5e6af4c4bca58b54d5b160a154b7aa0e/src/database/sql/ctxutil.go#L137-L146
A lot of the logic is coming from stmt.go, which we can't use directly unfortunately. We could potentially manually build a We would essentially replace Lines 107 to 120 in 86533c7
stmt := &Stmt{c: c, os: os, query: query}
rows, err := stmt.Query(dargs)
if err != nil {
errorChan <- err
} else {
rowsChan <- rows
} But then, there's also a chance the ODBC statement gets replaced by that function too. What do you think?
I have considered it, but I'm not so sure how to test it yet. In the repo, I can see tests mostly for MS SQL, which I don't have and therefore most likely can't test. I'm open to ideas if you have any suggestions though! |
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.
This LGTM, but it would be nice with comments indicating what's copied from where. The way I understand it is that this is roughly Query
, but with the call to Cancel
?
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.
Nice richard. I am not familiar with this code base but would it be easy to test this functionality?
I've been maintaining the My main concern regarding this change is that I am afraid that this driver, which is an utterly important piece, becomes a house of broken windows When our new functionality has no unit tests, and the feedback loop to test it end-to-end is really long, it is tempting to keep changes small and keep breaking windows. There are two ways we can solve for this:
I'm really bullish about 1 even though it is the hardest one. But I think we want to contribute to open source and make the world a better place one line of code at a time. I'm happy to merge this but we should keep this in mind when we keep patching this driver. |
I agree with what Håkon says, we should push for upstream changes. It might be possible to do some effort for 2), as well, to make the feeedback loop tighter. But I think it's sufficient to use a branch on core and update its reference to the module in this repository, since we have a good testing setup there, and we test queries against Spark. |
Btw I really appreciate the changes you made in c8a9911, I think that made things more clear! |
As per the [specifications](https://pkg.go.dev/database/sql/driver#QueryerContext), `QueryerContext` is an optional interface. When it's not implemented, the driver falls back to the `Queryer` interface that is also optional, and eventually defaults to: - preparing a query - executing the statement - closing the statement This means that the context passed to `QueryContext` gets completely ignored and therefore timeouts aren't honoured. This commit provides an implementation of the `QueryerContext` interface that honours the context. When the context expires or gets cancelled, the statement gets cancelled and closed, and upon completion, an error is returned.
As per the specifications,
QueryerContext
is an optional interface.When it's not implemented, the driver falls back to the
Queryer
interface that is also optional, and eventually defaults to:This means that the context passed to
QueryContext
gets completely ignored and therefore timeouts aren't honoured.This commit provides an implementation of the
QueryerContext
interface that honours the context. When the context expires or gets cancelled, the statement gets cancelled and closed, and upon completion, an error is returned.