When having an empty text field in a database table, where the value is
NULL, I get
ERR: sql: Scan error on column index 2: unsupported driver -> Scan pair:
<nil> -> *string
I was hoping from the changelogs that this was fixed in this weekly
snapshot, but apparently still getting it. Does someone have a solution?
At the moment, I just would do "update table set textfield = ''" :)
Cheers,
C.
We quite frequently run into situations at work where we end up
needing to know the distinction between a NULL value and "" (or more
often, NULL and 0).
Sorry, been away for a few days. didnt get to file the bug. Anyway, I
agree with you, also because "" is the default "not set" value for a
string member in a struct. So everybody should know how to handle that.
And sql.NullString is a nice way out in situations, where the default is
not enough.
var test string = nil
gives you an error - you will set string to "", which is the default
value for an uninitialsed string. So there is no way to pick up a NULL
as nil when passing this var to the Scan func.
On the other hand, there is sql.NullString defined as
type NullString struct {
String string
Valid bool // Valid is true if String is not NULL
}
So if NULL matters to you, you will use this as the type to pass to
Scan. Mission accomplished :)
And for building queries from types in structs, that one will also make
the difference.
There may be a point for blobs, where it seems you could stuff text into
string and binary data into []byte. Perhaps there is a need for a
NullBlob type? Dunno, most if the time if its empty, its empty, right? :))
> - Anssi K��ri�inen
>
I agree that it is a very nice feature to set the values to their
defaults if a NULL is returned during the scan.
I also agree that sql.NullString (and related) help to fill the void
where it IS important to know the difference between a NULL value and
the default value for a type.
But wouldn't it also be nice to simply pass the address of a pointer
type (see example below) and have database/sql populate the pointer
with nil (if NULL) or the actual value if one was provided? As stated
before, there may be some underlying reason why this is a horrible
idea, but I cannot for the life of me think of what it might be?
--------
var id *int
rows.Scan(&id)
if id == nil {
// NULL value returned
} else {
// Actual value returned
}
--------
it's not the only one. encoding/xml, encoding/json and encoding/gob
(for structs only)
all support this style. if you want a nullable X, a pointer to X seems
like a good
way to represent it.
defining NullString seems unnecessary.
actually, i take that back - NullString is nice because it avoids an allocation.
but i can see a reasonable argument for allowing pointer values too.
actually i think it's the other way around. with the NullBool type,
it's very easy to do:
if !x.Bool {
}
which might be incorrect.
with the pointer version:
if !*x {
}
it'll panic when it's null, emphatically demonstrating your mistake.
i think there are cases for both uses.
if the sql package were to support named rows, it might do that
by allowing a pointer to a struct as the first argument to Scan.
in which case supporting pointers would make it much more easily
interchangeable with the other marshalling packages.
type Record struct {
Name string
Age *int `xml:"omit_empty"`
}
func convertToXML(r *sql.Rows, enc xml.Encoder) {
for rows.Next() {
var rec Record
rows.Scan(&rec)
enc.Encode(&rec)
}
}
I am very much a fan of the way Go returns errors, so I wasn't advocating the use of nil as sentinel.
Being that the Scan functions return any error that may have occurred, doesn't that mean that any nil value returned should simply be treated as a value rather than a sentinel (as long as the type being provided to the Scan function is a pointer to a pointer, e.g. **Type)?
----
Furthermore, while the use of the nullable types (e.g. NullString) promotes slightly more explicit NULL checking, doesn't this leave a gap in one of the original goals of the package: "Be flexible with type conversions, but be paranoid about silent truncation or other loss of precision."
Allow me to explain what I mean. If my understanding is correct, the sql package provides precision checking when casting to the types provided to the Scan function. Based on this assumption, wouldn't you need a NullInt8, NullInt16, and NullInt32 in addition to NullInt64 to aid in proper prevention of loss of precision? Because the NullInt64 isn't going to report a loss of precision, but would encourage an ill practice of casting the NullInt64's value directly to a uint8, for example.
I hope my I expressed my concern properly, if not, please let me know and I would be glad to try explaining it a different way!