-
Notifications
You must be signed in to change notification settings - Fork 18k
database/sql: convertAssign throws away type information stored at interface{} #23703
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
Even more disturbing example: var scan1 float64
var scan2 interface{} = float64(0)
err := db.QueryRow("SELECT 3.14, 3.14").Scan(&scan1, &scan2)
if err != nil {
t.Fatal(err)
}
t.Logf("%v (%T) %v (%T)", scan1, scan1, scan2, scan2)
|
Poke @kardianos |
@AlekSi Are you using sqlite? If not, what DB storage are you using. What you are noticing is the underlying type the database provides is coming though in scan2. You see, even when you assign a float64 or int8 to an interface{} type, the type is still an interface type. It just happens to have something stored in it already. We don't check for what is already stored in it, we just look at the type. The exact SQL used would depend on the system used, but for postgresql you could use You may already know all this. Then the question is, why would you like to do this? What is your goal? Do you want a generic or runtime configurable converter? If so, you could use something like this https://godoc.org/bitbucket.org/kardianos/table to pull data out, then have a custom routine that converts to your appropriate data type. What is the problem you want to solve? |
Sorry, I wasn't clear enough in my original message. I'm writing my own driver for MySQL X Protocol: https://github.com/AlekSi/mysqlx I noticed the behavior explained in the first message while writing tests. I think it is not very intuitive, although I also don't think my situation is very typical in real non-test non-driver code. |
Sorry for the delay @AlekSi Looking at the original example, scan1 has a Go type of int8, while scan2 has a Go type of interface{} (fmt.Spritf("%T") does a bit of reflection to look at the type stored in interface{}). I'm not convinced we want to look at what is currently stored in a type to determine how something should be scanned (which is what you are asking for I think). For your second example with float64 scanning, after looking through convertAssign, I can only assume that you are returning a Go string type from the driver and convertAssign is converting it to float64 in the scan1 case and directly assigning the string to the interface in the second case. Do you think convertAssign should do something different? |
It turned out that my driver code handles float numbers coming from database correctly, but in case of unqualified I don't think anything should be done for this issue. Thank you. |
What version of Go are you using (
go version
)?Both 1.9.3 and current master (e6756ec).
What did you do?
What did you expect to see?
42 (int8) 42 (int8)
What did you see instead?
42 (int8) 42 (int64)
https://golang.org/pkg/database/sql/#Rows.Scan says about it:
Is it possible to honor type information stored at
interface{}
in Go 1.x? If yes, I can work on it. If not, can we do that in Go 2, and expand documentation to mention current behavior?The text was updated successfully, but these errors were encountered: