-
Notifications
You must be signed in to change notification settings - Fork 18k
database/sql: sql.Result has problems that should be fixed / replaced #19055
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
Comments
@mjibson You mentioned you were modifying lib/pq to support getting each result. Did you do this and if so could you point me to the code? I'd like to see the details. Supporting this seems really close to also supporting NOTICE messages too. @mattn It seems like the best solution might be to have a result that returned an interface{} value, then you could call x.Result().(int64) or x.Result().(GUID) or x.Result().(string). Might be useful for DBs like CRDB where keys may more often by strings of bytes. Can the Last Insert ID also be returned from non-exec queries? Is that also desirable? |
No, I haven't done this yet, although I would still like to. The current plan is to add an internal method with a flag to return these intermediate messages or not during calls to NextResultSet. |
Throwing out ideas here. What if there was a new method attached to sql.Rows that could be called after sql.Next but before sql.NextResultSet that would return an array of interfaces where you can do a type switch to return various items, such as informational NOTICE messages, last inserted ID, rows affected.
Buffered messages would be discarded after the next call to rows.NextResultSet or rows.Close. |
Calling .Message like this presents some ordering problems. Say I have the multi-statement query:
The above API would, as I read it, return a message only about the |
Point taken. I'll think on it. |
@mjibson An alternative is that messages are cached until they are dequeued or rows.Close is called.
Perhaps the rows.Message() could be valid anytime before close and it would dequeue any pending messages received up till then. It would be a bit awkward to call manually per query, but super easy in any type of framework / generic table buffer situation. |
Another choice is to have .Message be able to also indicate a rows result:
Something like this would preserve full statement ordering, which is a requirement for my use case. |
I like where this is going. We are only adding a single method, but allow a new way of consuming in sequence order all messages from the database, not just data results. It is also by nature is opt in. Furthermore the message buffer should be able to be reused easily. I think if the If you're happy with that, I'll see if I can work up a CL. |
I think rows.Message() is good for us to extend next feature. |
Please review https://go-review.googlesource.com/c/39355/ for API suitability and correctness. |
CL https://golang.org/cl/39355 mentions this issue. |
This would work for my use case as well. One thing I would proceed cautiously on is buffering of messages that aren't read. Some database procedures can produce a large number of messages. Right now I believe these are discarded by drivers. Existing clients may rely on the fact that these messages are discarded, but if this behavior changes underneath them I'm worried that this could lead to unbounded memory consumption in the driver waiting for the user to read such messages. My point is we might want to consider making the usage of this feature more opt-in, specifically for memory consumption. Perhaps: stop buffering if a call to rows.Next() is made before any call to rows.Message. |
In go1.9, drivers will be able to accept non-query parameters as arguments to a query. I think this can be solved with https://github.com/golang-sql/sqlexp/blob/master/messages.go if a driver supports it. I'm removing the milestone because I think this can be accomplished for now out of the std lib for now. If the approach works, we might want to bless this method in some way. |
Currently as of Go1.10, results from an Exec are wrapped in the
We should fix these issues in Go2 #22697 . |
Something like this has my vote. I'm struggling with this right now. I do want to make sure we think about something like BACKUP that doesn't return result sets but returns lots of messages while it's running. It seems like that would be handled. I'd even be happy if I could just pass in a logger of some type. The two options I'm thinking about now are to hack "sql" to print these out in a format I like or wrap sqlcmd.exe and just print all the results. I don't really like either :-) I also thought about sending in a channel to "sql" that I could consume. I'm afraid that has problems I haven't discovered though. |
I'm not proposing anything at this point. I'm just documenting various things I've come things I've come across that relate to sql.Result.
@mjibson has said:
The other @mattn has said:
@tgulacsi do you have anything to add?
The text was updated successfully, but these errors were encountered: