summaryrefslogtreecommitdiff
path: root/sql/sql_error.h
diff options
context:
space:
mode:
authorAlexander Barkov <bar@mariadb.com>2018-10-09 12:02:35 +0400
committerAlexander Barkov <bar@mariadb.com>2018-10-09 12:02:35 +0400
commit5646c4315918c1e4127bfb68b70d1c5333bfc2c7 (patch)
tree8b894deecb6371aa530ecebcd879dd5c2d52cf81 /sql/sql_error.h
parentf4cdf90d73aeffae37b400fa060bece5917cf4c2 (diff)
downloadmariadb-git-5646c4315918c1e4127bfb68b70d1c5333bfc2c7.tar.gz
MDEV-17216 Assertion `!dt->fraction_remainder(decimals())' failed in Field_temporal_with_date::store_TIME_with_warning
The problem happened because {{Field_xxx::store(longlong nr, bool unsigned_val)}} erroneously passed {{unsigned_flag}} to the {{usec}} parameter of this constructor: {code:cpp} Datetime(int *warn, longlong sec, ulong usec, date_conv_mode_t flags) {code} 1. Changing Time and Datetime constructors to accept data as Sec6 rather than as longlong/double/my_decimal, so it's not possible to do such mistakes in the future. Additional good effect of these changes: - This reduced some amount of similar code (minus ~35 lines). - The code now does not rely on the fact that "unsigned_flag" is not important inside Datetime(). The constructor always gets all three parts: sign, integer part, fractional part. The simple the better. 2. Fixing Field_xxx::store() to use the new Datetime constructor format. This change actually fixes the problem. 3. Adding "explicit" keyword to all Sec6 constructors, to avoid automatic hidden conversion from double/my_decimal to Sec6, as well as from longlong/ulonglong through double to Sec6. 4. Change#1 caused (as a dependency) changes in a few places with code like this: bool neg= nr < 0 && !unsigned_val; ulonglong value= m_neg ? (ulonglong) -nr : (ulonglong) nr; These fragments relied on a non-standard behavior with the operator "minus" applied to the lowest possible negative signed long long value. This can lead to different results depending on the platform and compilation flags. We have fixed such bugs a few times already. So instead of modifying the old wrong code to a new wrong code, replacing all such fragments to use Longlong_hybrid, which correctly handles this special case with -LONGLONG_MIN in its method abs(). This also reduced the amount of similar code (1 or 2 new lines instead 3 old lines in all 6 such fragments). 5. Removing ErrConvInteger(longlong nr, bool unsigned_flag= false) and adding ErrConvInteger(Longlong_hybrid) instead, to encourage use of safe Longlong_hybrid instead of unsafe pairs nr+neg. 6. Removing unused ErrConvInteger from Item_cache_temporal::get_date()
Diffstat (limited to 'sql/sql_error.h')
-rw-r--r--sql/sql_error.h4
1 files changed, 2 insertions, 2 deletions
diff --git a/sql/sql_error.h b/sql/sql_error.h
index 822503f89d3..b783d527cb3 100644
--- a/sql/sql_error.h
+++ b/sql/sql_error.h
@@ -846,8 +846,8 @@ public:
class ErrConvInteger : public ErrConv, public Longlong_hybrid
{
public:
- ErrConvInteger(longlong num_arg, bool unsigned_flag= false) :
- ErrConv(), Longlong_hybrid(num_arg, unsigned_flag) {}
+ ErrConvInteger(const Longlong_hybrid &nr)
+ : ErrConv(), Longlong_hybrid(nr) { }
const char *ptr() const
{
return m_unsigned ? ullstr(m_value, err_buffer) :