You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
in MySQL, although now() is a datetime, now() + 0 is an integer formed from all of the decimal digits in the date. e.g. 2021-05-27 17:00:26 vs 20210527170026. (I'm not sure why one would ever want that.)
in Go's database/sql API for prepared statements, "?" applied to a duration value treats the duration (thanks to reflection on the underlying type) as an integer number of nanoseconds, not an interval. I don't know why one would ever want that either, since nanoseconds are not really useful in SQL.
The combination of these two facts means that the behavior of query("now() + ?", 1*time.Hour) isn't remotely close to what one might expect:
Perhaps go-sql-driver could support time.Duration by mapping it to interval 1 hour, thereby avoiding this pitfall.
Alternatively, simply rejecting it with a clear error ("you cannot possibly have wanted this behavior") would be an improvement.
(See also golang/go#46427: I reported this initially against database/sql, and it was closed as a driver-specific issue.)
in MySQL, although now() is a datetime, now() + 0 is an integer formed from all of the decimal digits in the date. e.g. 2021-05-27 17:00:26 vs 20210527170026. (I'm not sure why one would ever want that.)
I am also surprised by this fact, however it is a MySQL specification.
If the fsp argument is given to specify a fractional seconds precision from 0 to 6, the return value includes a fractional seconds part of that many digits.
Thanks for clarifying. If the driver can't support it, then please consider the alternative of specifically rejecting time.Duration from the generic conversion applied to other integer data types. The error message could suggest how to use either the INTERVAL syntax or an explicit integer number of nanoseconds (for the vanishing minority who might want the current behavior).
BTW, you can use d.Microseconds() in place of the int64 conversion.
time.Duration is not a valid driver.Value and doesn't implement the driver.Valuer interface. You should not expect it to work in a special way. database/sql just use the native representation (int64) as a fallback.
This kind of error in your code should be caught by a static analysis tool that would target database/sql usage and check types given to Query/QueryContext/Exec/Scan. Unfortunately I don't know a tool that does that kind of checks.
time.Duration is not a valid driver.Value and doesn't implement the driver.Valuer interface. You should not expect it to work in a special way. database/sql just use the native representation (int64) as a fallback.
This kind of error in your code should be caught by a static analysis tool [...]
I understand that Duration does not implement the SQL value interface, but that does not mean we cannot treat it specially, given how important it is (though I recognize there are pros and cons to doing so). A static analysis might have caught the problem, but that requires users to know that the analysis exists, to know how to run it, and to remember to run it---and if I knew that, I wouldn't have made the mistake. :)
If the library itself detects the mistake at little cost, so much the better.
If the library itself detects the mistake at little cost, so much the better.
I don't think that's a task for the MySQL driver. The same mistake could happen when using database/sql with any other SQL driver. So I don't think that's the right place for the improvement you dream of.
I don't think that's a task for the MySQL driver. The same mistake could happen when using database/sql with any other SQL driver. So I don't think that's the right place for the improvement you dream of.
As I pointed out in my first note, my original report against the standard database/sql package was closed on the basis that it was a driver-specific issue. :)
I don't see why the objection "the same mistake could happen when using database/sql with any other SQL driver" should present an obstacle to preventing the mistake in this MySQL driver. The worst case outcome is that both layers perform the check, making the driver's check redundant.
Activity
shogo82148 commentedon May 28, 2021
The driver can't support
time.Duration.I am also surprised by this fact, however it is a MySQL specification.
MySQL doesn't have time duration types. https://dev.mysql.com/doc/refman/8.0/en/data-types.html
interval 1 houris not a time duration value, but a temporal interval syntax.The driver doesn't know which unit you use, so you need to convert the unit yourself.
For example:
adonovan commentedon Jun 1, 2021
Thanks for clarifying. If the driver can't support it, then please consider the alternative of specifically rejecting time.Duration from the generic conversion applied to other integer data types. The error message could suggest how to use either the INTERVAL syntax or an explicit integer number of nanoseconds (for the vanishing minority who might want the current behavior).
BTW, you can use
d.Microseconds()in place of the int64 conversion.dolmen commentedon Jun 30, 2021
time.Durationis not a validdriver.Valueand doesn't implement thedriver.Valuerinterface. You should not expect it to work in a special way.database/sqljust use the native representation (int64) as a fallback.This kind of error in your code should be caught by a static analysis tool that would target
database/sqlusage and check types given to Query/QueryContext/Exec/Scan. Unfortunately I don't know a tool that does that kind of checks.adonovan commentedon Jun 30, 2021
I understand that Duration does not implement the SQL value interface, but that does not mean we cannot treat it specially, given how important it is (though I recognize there are pros and cons to doing so). A static analysis might have caught the problem, but that requires users to know that the analysis exists, to know how to run it, and to remember to run it---and if I knew that, I wouldn't have made the mistake. :)
If the library itself detects the mistake at little cost, so much the better.
dolmen commentedon Jul 1, 2021
I don't think that's a task for the MySQL driver. The same mistake could happen when using
database/sqlwith any other SQL driver. So I don't think that's the right place for the improvement you dream of.adonovan commentedon Jul 1, 2021
As I pointed out in my first note, my original report against the standard
database/sqlpackage was closed on the basis that it was a driver-specific issue. :)I don't see why the objection "the same mistake could happen when using database/sql with any other SQL driver" should present an obstacle to preventing the mistake in this MySQL driver. The worst case outcome is that both layers perform the check, making the driver's check redundant.
zihengCat commentedon Jul 10, 2021
Well,
time.Durationis treated asint64. When programmer typesdb.Query("SELECT now() + ?", 1*time.Hour), the converted SQL statement becomesSELECT now() + 3600000000000(int64 nanosecond count).It's programmer's responsibility to know something under the hood and make sure their codes act as what they want, not driver.
It's fun MySQL implements expression

datetime + integerlike this, a little counterintuitive. I tried in SQLite, the behavior is different. :)adonovan commentedon Jul 11, 2021
It's a car-driver's responsibility to drive safely, but cars still come with seatbelts to reduce the cost of mistakes.
zihengCat commentedon Jul 11, 2021
Well, SQL expression
datetime + integermaybe is a kind of undefined behavior in my thought. Different SQL engine implemented in different ways.I prefer static analysis solution, reported a warning alert like:
WARN: undefined addition operation, mismatched types datetime and integer.