Commit graph

54 commits

Author SHA1 Message Date
Alexander Barkov
607fc15393 MDEV-31302 Assertion `mon > 0 && mon < 13' failed in my_time_t sec_since_epoch(int, int, int, int, int, int)
The code erroneously called sec_since_epoch() for dates with zeros,
e.g. '2024-00-01'.
Fixi: adding a test that the date does not have zeros before
calling TIME_to_native().
2024-09-20 14:13:53 +04:00
Alexander Barkov
b697dce8ca MDEV-29149 Assertion `!is_valid_datetime() || fraction_remainder(((item->decimals) < (6) ? (item->decimals) : (6))) == 0' failed in Datetime_truncation_not_needed::Datetime_truncation_not_needed
TIME-alike string and numeric arguments to TIMEDIFF()
can get additional fractional seconds during the supported
TIME range adjustment in get_time().

For example, during TIMEDIFF('839:00:00','00:00:00') evaluation
in Item_func_timediff::get_date(), the call for args[0]->get_time()
returns MYSQL_TIME '838:59:59.999999'.

Item_func_timediff::get_date() did not handle these extra digits
and returned a MYSQL_TIME result with fractional digits outside
of Item_func_timediff::decimals. This mismatch could further be
caught by a DBUG_ASSERT() in various other pieces of the code,
leading to a crash.

Fix:

In case if get_time() returned MYSQL_TIMESTAMP_TIME,
let's truncate all extra digits using my_time_trunc(&l_time,decimals).
This guarantees that the rest of the code returns a MYSQL_TIME
with second_part not conflicting with Item_func_timediff::decimals.
2024-04-10 17:02:24 +04:00
Alexander Barkov
e63311c2cf MDEV-33496 Out of range error in AVG(YEAR(datetime)) due to a wrong data type
Functions extracting non-negative datetime components:

- YEAR(dt),        EXTRACT(YEAR FROM dt)
- QUARTER(td),     EXTRACT(QUARTER FROM dt)
- MONTH(dt),       EXTRACT(MONTH FROM dt)
- WEEK(dt),        EXTRACT(WEEK FROM dt)
- HOUR(dt),
- MINUTE(dt),
- SECOND(dt),
- MICROSECOND(dt),
- DAYOFYEAR(dt)
- EXTRACT(YEAR_MONTH FROM dt)

did not set their max_length properly, so in the DECIMAL
context they created a too small DECIMAL column, which
led to the 'Out of range value' error.

The problem is that most of these functions historically
returned the signed INT data type.

There were two simple ways to fix these functions:
1. Add +1 to max_length.
   But this would also change their size in the string context
   and create too long VARCHAR columns, with +1 excessive size.

2. Preserve max_length, but change the data type from INT to INT UNSIGNED.
   But this would break backward compatibility.
   Also, using UNSIGNED is generally not desirable,
   it's better to stay with signed when possible.

This fix implements another solution, which it makes all these functions
work well in all contexts: int, decimal, string.

Fix details:

- Adding a new special class Type_handler_long_ge0 - the data type
  handler for expressions which:
  * should look like normal signed INT
  * but which known not to return negative values
  Expressions handled by Type_handler_long_ge0 store in Item::max_length
  only the number of digits, without adding +1 for the sign.

- Fixing Item_extract to use Type_handler_long_ge0
  for non-negative datetime components:
   YEAR, YEAR_MONTH, QUARTER, MONTH, WEEK

- Adding a new abstract class Item_long_ge0_func, for functions
  returning non-negative datetime components.
  Item_long_ge0_func uses Type_handler_long_ge0 as the type handler.
  The class hierarchy now looks as follows:

Item_long_ge0_func
  Item_long_func_date_field
    Item_func_to_days
    Item_func_dayofmonth
    Item_func_dayofyear
    Item_func_quarter
    Item_func_year
  Item_long_func_time_field
    Item_func_hour
    Item_func_minute
    Item_func_second
    Item_func_microsecond

- Cleanup: EXTRACT(QUARTER FROM dt) created an excessive VARCHAR column
  in string context. Changing its length from 2 to 1.
2024-02-23 18:30:06 +04:00
Oleksandr Byelkin
6cfd2ba397 Merge branch '10.4' into 10.5 2023-11-08 12:59:00 +01:00
Oleksandr Byelkin
d594f1e531 Removing MDEV-27871 because it is not a bug
Part 1
2023-10-13 14:09:22 +02:00
Alexander Barkov
fe844c16b6 Merge remote-tracking branch 'origin/10.4' into 10.5 2022-09-14 16:24:51 +04:00
Marko Mäkelä
18795f5512 Merge 10.3 into 10.4 2022-09-13 16:36:38 +03:00
Alexander Barkov
f1544424de MDEV-29446 Change SHOW CREATE TABLE to display default collation 2022-09-12 22:10:39 +04:00
Alexander Barkov
57f5c319af MDEV-21445 Strange/inconsistent behavior of IN condition when mixing numbers and strings 2022-07-06 15:42:21 +04:00
Sergei Golubchik
ef781162ff Merge branch '10.4' into 10.5 2022-05-09 22:04:06 +02:00
Sergei Golubchik
a70a1cf3f4 Merge branch '10.3' into 10.4 2022-05-08 23:03:08 +02:00
Oleksandr Byelkin
9614fde1aa Merge branch '10.2' into 10.3 2022-05-03 10:59:54 +02:00
Alexander Barkov
79cdd7e76b MDEV-20305 Data loss on DOUBLE and DECIMAL conversion to INT
Bit operators (~ ^ | & << >>) and the function BIT_COUNT()
always called val_int() for their arguments.
It worked correctly only for INT type arguments.

In case of DECIMAL and DOUBLE arguments it did not work well:
the argument values were truncated to the maximum SIGNED BIGINT value
of 9223372036854775807.

Fixing the code as follows:

- If the argument if of an integer data type,
  it works using val_int() as before.

- If the argument if of some other data type, it gets the argument value
  using val_decimal(), to avoid truncation, and then converts the result
  to ulonglong.

Using Item_handled_func to switch between the two approaches easier.

As an additional advantage, with Item_handled_func it will be easier
to implement overloading in the future, so data type plugings will be able
to define their own behavioir of bit operators and BIT_COUNT().

Moving the code from the former val_int() implementations
as methods to Longlong_null, to avoid code duplication in the
INT and DECIMAL branches.
2020-06-06 11:33:11 +04:00
Vicențiu Ciorbaru
45bc7574fb MDEV-18650: Options deprecated in previous versions - storage_engine
Remove usage of deprecated variable storage_engine. It was deprecated in 5.5 but
it never issued a deprecation warning. Make it issue a warning in 10.5.1.

Replaced with default_storage_engine.
2020-02-13 13:42:01 +02:00
Marko Mäkelä
8cc15c036d Merge 10.4 into 10.5 2019-12-27 21:17:16 +02:00
Marko Mäkelä
4c25e75ce7 Merge 10.3 into 10.4 2019-12-27 18:20:28 +02:00
Marko Mäkelä
5ab70e7f68 Merge 10.2 into 10.3 2019-12-27 15:14:48 +02:00
Marko Mäkelä
fba9883bc4 Merge 10.4 into 10.5 2019-09-25 10:18:22 +03:00
Marko Mäkelä
d3350c160a Merge 10.3 into 10.4 2019-09-25 10:14:33 +03:00
Alexander Barkov
b6bb64e54a Merge remote-tracking branch 'origin/10.2' into 10.3 2019-09-24 23:05:09 +04:00
Marko Mäkelä
780d2bb8a7 Merge 10.4 into 10.5 2019-09-06 14:25:20 +03:00
Alexander Barkov
235cf969d2 MDEV-20397 Support TIMESTAMP, DATETIME, TIME in ROUND() and TRUNCATE() 2019-08-22 15:09:59 +04:00
Alexander Barkov
b511202335 MDEV-19923 Add type handlers for geometry sub-types 2019-07-03 14:51:00 +04:00
Alexander Barkov
cfbd714868 MDEV-19774 Assertion `sec.se c() <= 0x7FFFFFFFL' failed in Item_func_from_unixtime::get_date 2019-06-20 09:48:34 +04:00
Alexander Barkov
ea5cda5269 MDEV-18402 Assertion `sec.sec() <= 59' failed in Item_func_maketime::get_date 2019-04-02 11:40:22 +04:00
Marko Mäkelä
514b305dfb Merge 10.3 into 10.4
The MDEV-17262 commit 26432e49d3
was skipped. In Galera 4, the implementation would seem to require
changes to the streaming replication.

In the tests archive.rnd_pos main.profiling, disable_ps_protocol
for SHOW STATUS and SHOW PROFILE commands until MDEV-18974
has been fixed.
2019-03-20 10:41:32 +02:00
Sergei Golubchik
b64fde8f38 Merge branch '10.2' into 10.3 2019-03-17 13:06:41 +01:00
Alexander Barkov
218c75eb1d Making the test for MDEV-17854 independent from the host time zone 2018-11-28 10:46:19 +04:00
Alexander Barkov
d6bcf3a4c8 MDEV-17854 Assertion `decimals <= 6' failed in my_time_fraction_remainder on SELECT with NULLIF and FROM_UNIXTIME on incorrect time 2018-11-28 06:18:05 +04:00
Marko Mäkelä
dde2ca4aa1 Merge 10.3 into 10.4 2018-11-19 20:22:33 +02:00
Marko Mäkelä
fd58bb71e2 Merge 10.2 into 10.3 2018-11-19 18:45:53 +02:00
Alexander Barkov
d2ba9edd66 MDEV-17740 Extend EXTRACT(x AS DAY*) to understand long time intervals 2018-11-17 10:14:44 +04:00
Alexander Barkov
07e4853c23 MDEV-17563 Different results using table or view when comparing values of time type
MDEV-17625 Different warnings when comparing a garbage to DATETIME vs TIME

- Splitting processes of data type conversion (to TIME/DATE,DATETIME)
  and warning generation.
  Warning are now only get collected during conversion (in an "int" variable),
  and are pushed in the very end of conversion (not in parallel).
  Warnings generated by the low level routines str_to_xxx() and number_to_xxx()
  can now be changed at the end, when TIME_FUZZY_DATES is applied,
  from "Invalid value" to "Truncated invalid value".

  Now "Illegal value" is issued only when the low level routine returned
  an error and TIME_FUZZY_DATES was not set. Otherwise, if the low level
  routine returned "false" (success), or if NULL was converted to a zero
  datetime by TIME_FUZZY_DATES, then "Truncated illegal value"
  is issued. This gives better warnings.

- Methods Type_handler::Item_get_date() and
  Type_handler::Item_func_hybrid_field_type_get_date() now only
  convert and collect warning information, but do not push warnings.

- Changing the return data type for Type_handler::Item_get_date()
  and Type_handler::Item_func_hybrid_field_type_get_date() from
  "bool" to "void". The conversion result (success vs error) can be
  checked by testing ltime->time_type. MYSQL_TIME_{NONE|ERROR}
  mean mean error, other values mean success.

- Adding new wrapper methods Type_handler::Item_get_date_with_warn() and
  Type_handler::Item_func_hybrid_field_type_get_date_with_warn()
  to do conversion followed by raising warnings, and changing
  the code to call new Type_handler::***_with_warn() methods.

- Adding a helper class Temporal::Status, a wrapper
  for MYSQL_TIME_STATUS with automatic initialization.

- Adding a helper class Temporal::Warn, to collect warnings
  but without actually raising them. Moving a part of ErrConv
  into a separate class ErrBuff, and deriving both Temporal::Warn
  and ErrConv from ErrBuff. The ErrBuff part of Temporal::Warn
  is used to collect textual representation of the input data.

- Adding a helper class Temporal::Warn_push. It's used
  to collect warning information during conversion, and
  automatically pushes warnings to the diagnostics area
  on its destructor time (in case of non-zero warning).

- Moving more code from various functions inside class Temporal.

- Adding more Temporal_hybrid constructors and
  protected Temporal methods make_from_xxx(),
  which convert and only collect warning information, but do not
  actually raise warnings.

- Now the low level functions  str_to_datetime() and str_to_time()
  always set status->warning if the return value is "true" (error).

- Now the low level functions number_to_time() and number_to_datetime()
  set the "*was_cut" argument if the return value is "true" (error).

- Adding a few DBUG_ASSERTs to make sure that str_to_xxx() and
  number_to_xxx() always set warnings on error.

- Adding new warning flags MYSQL_TIME_WARN_EDOM and MYSQL_TIME_WARN_ZERO_DATE
  for the code symmetry. Before this change there was a special
  code path for (rc==true && was_cut==0) which was treated by
  Field_temporal::store_invalid_with_warning as "zero date violation".
  Now was_cut==0 always means that there are no any error/warnings/notes
  to be raised, not matter what rc is.

- Using new Temporal_hybrid constructors in combination with
  Temporal::Warn_push inside str_to_datetime_with_warn(),
  double_to_datetime_with_warn(), int_to_datetime_with_warn(),
  Field::get_date(), Item::get_date_from_string(), and a few other places.

- Removing methods Dec_ptr::to_datetime_with_warn(),
  Year::to_time_with_warn(), my_decimal::to_datetime_with_warn(),
  Dec_ptr::to_datetime_with_warn().
  Fixing Sec6::to_time() and Sec6::to_datetime() to
  convert and only collect warnings, without raising warnings.
  Now warning raising functionality resides in Temporal::Warn_push.

- Adding classes Longlong_hybrid_null and Double_null, to
  return both value and the "IS NULL" flag. Adding methods
  Item::to_double_null(), to_longlong_hybrid_null(),
  Item_func_hybrid_field_type::to_longlong_hybrid_null_op(),
  Item_func_hybrid_field_type::to_double_null_op().
  Removing separate classes VInt and VInt_op, as they
  have been replaced by a single class Longlong_hybrid_null.

- Adding a helper method Temporal::type_name_by_timestamp_type(),
  moving a part of make_truncated_value_warning() into it,
  and reusing in Temporal::Warn::push_conversion_warnings().

- Removing Item::make_zero_date() and
  Item_func_hybrid_field_type::make_zero_mysql_time().
  They provided duplicate functionality.
  Now this code resides in Temporal::make_fuzzy_date().
  The latter is now called for all Item types when data type
  conversion (to DATE/TIME/DATETIME) is involved, including
  Item_field and Item_direct_view_ref.
  This fixes MDEV-17563: Item_direct_view_ref now correctly converts
  NULL to a zero date when TIME_FUZZY_DATES says so.
2018-11-08 09:31:46 +04:00
Alexander Barkov
f6a2020514 MDEV-17477 Wrong result for TIME('-2001-01-01 10:20:30') and numerous other str-to-time conversion problems
MDEV-17478 Wrong result for TIME('+100:20:30')
2018-10-20 19:51:14 +04:00
Alexander Barkov
d3745c385e Fixing "mtr --ps func_time" failures in the tests added for MDEV-17351
It seems mysqltest does not print warnings raised at mysql_prepare() time.

Suppressing such --ps dependent warnings.
2018-10-18 10:17:34 +04:00
Alexander Barkov
22e75434e7 MDEV-17434 EXTRACT(DAY FROM negative_time) returns wrong result 2018-10-15 17:46:25 +04:00
Alexander Barkov
c57bbb2596 MDEV-17400 The result of TIME('42949672965959-01') depends on architecture
- Fixing portabibily problems in sql-common/my_time.c
  (and additionally in sql/sql_time.cc)

- Re-enabling func_time.test
  Now all new chunks added in MDEV-17351 work fine on all platforms.
2018-10-09 07:50:24 +04:00
Alexander Barkov
b639fe2be1 MDEV-17351 Wrong results for GREATEST,TIMESTAMP,ADDTIME with an out-of-range TIME-alike argument
Problems:

Functions LEAST() and GREATEST() in TIME context, as well as functions
TIMESTAMP(a,b) and ADDTIME(a,b), returned confusing results when the
input TIME-alike value in a number or in a string was out of the TIME
supported range.

In case of TIMESTAMP(a,b) and ADDTIME(a,b), the second argument
value could get extra unexpected digits. For example, in:
    ADDTIME('2001-01-01 00:00:00', 10000000)  or
    ADDTIME('2001-01-01 00:00:00', '1000:00:00')
the second argument was converted to '838:59:59.999999'
with six fractional digits, which contradicted "decimals"
previously set to 0 in fix_length_and_dec().
These unexpected fractional digits led to confusing function results.

Changes:
1. GREATEST(), LEAST()

   - fixing Item_func_min_max::get_time_native()
   to respect "decimals" set by fix_length_and_dec().
   If a value of some numeric or string time-alike argument
   goes outside of the TIME range and gets limited to '838:59:59.999999',
   it's now right-truncated to the correct fractional precision.

   - fixing, Type_handler_temporal_result::Item_func_min_max_fix_attributes()
   to take into account arguments' time_precision() or datetime_precision(),
   rather than rely on "decimals" calculated by the generic implementation
   in Type_handler::Item_func_min_max_fix_attributes(). This makes
   GREATEST() and LEAST() return better data types, with the same
   fractional precision with what TIMESTAMP(a,b) and ADDTIME(a,b) return
   for the same arguments, and with DATE(a) and TIMESTAMP(a).

2. Item_func_add_time and Item_func_timestamp

   It was semantically wrong to apply the limit of the TIME data type
   to the argument "b", which plays the role of "INTERVAL DAY TO SECOND" here.
   Changing the code to fetch the argument "b" as INTERVAL rather than as TIME.

   The low level routine calc_time_diff() now gets the interval
   value without limiting to '838:59:59.999999', so in these examples:
     ADDTIME('2001-01-01 00:00:00', 10000000)
     ADDTIME('2001-01-01 00:00:00', '1000:00:00')
   calc_time_diff() gets '1000:00:00' as is.  The SQL function result
   now gets limited to the supported result data type range
   (datetime or time) inside calc_time_diff(), which now calculates
   the return value using the real fractional digits that
   came directly from the arguments (without the effect of limiting
   to the TIME range), so the result does not have any unexpected
   fractional digits any more.

   Detailed changes in TIMESTAMP() and ADDTIME():

   - Adding a new class Interval_DDhhmmssff. It's similar to Time, but:
     * does not try to parse datetime format, as it's not needed for
       functions TIMESTAMP() and ADDTIME().
     * does not cut values to '838:59:59.999999'

     The maximum supported Interval_DDhhmmssff's hard limit is
     'UINT_MAX32:59:59.999999'. The maximum used soft limit is:
     - '87649415:59:59.999999'   (in 'hh:mm:ss.ff' format)
     - '3652058 23:59:59.999999' (in 'DD hh:mm:ss.ff' format)
     which is a difference between:
     - TIMESTAMP'0001-01-01 00:00:00' and
     - TIMESTAMP'9999-12-31 23:59:59.999999'
     (the minimum datetime that supports arithmetic, and the
     maximum possible datetime value).

   - Fixing get_date() methods in the classes related to functions
     ADDTIME(a,b) and TIMESTAMP(a,b) to use the new class Interval_DDhhmmssff
     for fetching data from the second argument, instead of get_date().

   - Fixing fix_length_and_dec() methods in the classes related
     to functions ADDTIME(a,b) and TIMESTAMP(a,b) to use
     Interval_DDhhmmssff::fsp(item) instead of item->time_precision()
     to get the fractional precision of the second argument correctly.

   - Splitting the low level function str_to_time() into smaller pieces
     to reuse the code. Adding a new function str_to_DDhhmmssff(), to
     parse "INTERVAL DAY TO SECOND" values.

   After these changes, functions TIMESTAMP() and ADDTIME()
   return much more predictable results, in terms of fractional
   digits, and in terms of the overall result.

   The full ranges of DATETIME and TIME values are now covered by TIMESTAMP()
   and ADDTIME(), so the following can now be calculated:

    SELECT ADDTIME(TIMESTAMP'0001-01-01 00:00:00', '87649415:59:59.999999');
    -> '9999-12-31 23:59:59.999999'

    SELECT TIMESTAMP(DATE'0001-01-01', '87649415:59:59.999999')
    -> '9999-12-31 23:59:59.999999'

    SELECT ADDTIME(TIME'-838:59:59.999999', '1677:59:59.999998');
    -> '838:59:59.999999'
2018-10-08 13:38:01 +04:00
Marko Mäkelä
444c380ceb Merge 10.3 into 10.4 2018-10-05 08:09:49 +03:00
Sergei Golubchik
57e0da50bb Merge branch '10.2' into 10.3 2018-09-28 16:37:06 +02:00
Alexander Barkov
492998c0d8 MDEV-15406 NO_ZERO_IN_DATE erroneously affects how CAST(AS DATE) warns about fractional digit truncation 2018-09-27 16:38:14 +04:00
Marko Mäkelä
1bf3e8ab43 Merge 10.3 into 10.4 2018-09-11 21:31:03 +03:00
Monty
39c6775a35 Fixed func_time.test that was depending on current time 2018-09-02 22:47:57 +03:00
Marko Mäkelä
7830fb7f45 Merge 10.2 into 10.3 2018-08-28 12:22:56 +03:00
Marko Mäkelä
734db318ac Merge 10.3 into 10.4 2018-08-16 10:08:30 +03:00
Alexander Barkov
8524bb6872 MDEV-14032 SEC_TO_TIME executes side effect two times
- Adding a helper class Sec6 to store (neg,seconds,microseconds)
- Adding a helper class VSec6 (Sec6  with a flag for "IS NULL")
- Wrapping related functions as methods of Sec6;
  * number_to_datetime()
  * number_to_time()
  * my_decimal2seconds()
  * Item::get_seconds()
  * A big piece of code in Item_func_sec_to_time::get_date()

- Using the new classes in places where second-to-temporal
  conversion takes place:
  * Field_timestamp::store(double)
  * Field_timestamp::store(longlong)
  * Field_timestamp_with_dec::store_decimal(my_decimal)
  * Field_temporal_with_date::store(double)
  * Field_temporal_with_date::store(longlong)
  * Field_time::store(double)
  * Field_time::store(longlong)
  * Field_time::store_decimal(my_decimal)
  * Field_temporal_with_date::store_decimal(my_decimal)
  * get_interval_value()
  * Item_func_sec_to_time::get_date()
  * Item_func_from_unixtime::get_date()
  * Item_func_maketime::get_date()
  This change simplifies these methods and functions a lot.

- Warnings are now sent at VSec6 initialization time, when the source
  data is available in its original data type representation.

  If Sec6::to_time() or Sec6::to_datetime() truncate data again during
  conversion to MYSQL_TIME, they send warnings, but only if no warnings
  were sent during VSec6 initialization. This helps prevents double warnings.

  The call for val_str() in Item_func_sec_to_time::get_date() is not
  needed any more, so it's removed. This change actually fixes the problem.

  As a good effect, FROM_UNIXTIME() and MAKETIME() now also send warnings
  in case if the seconds arguments is out of range. Previously these
  functions returned NULL silently.

- Splitting the code in the global function make_truncated_value_warning()
  into a number of methods THD::raise_warning_xxxx().
  This was needed to reuse the logic that chooses between:
  * ER_TRUNCATED_WRONG_VALUE
  * ER_WRONG_VALUE
  * ER_TRUNCATED_WRONG_VALUE_FOR_FIELD
  for non-temporal data types (Sec6).

- Removing:
  * Item::get_seconds()
  * number_to_time_with_warn()
  as this code now resides inside methods of Sec6.

- Cleanup (changes that are not directly related to the fix):
  * Removing calls for field_name_or_null() and passing NULL instead
    in Item_func_hybrid_field_type::get_date_from_{int|real}_op,
    because Item_func_hybrid_field_type::field_name_or_null()
    always returns NULL
  * Replacing a number of calls for make_truncated_value_warning()
    to calls for THD::raise_warning_xxx(). In these places
    we know that the execution went through a certain
    branch of make_truncated_value_warning(),
    (e.g. the exact error code is known, or field name is always NULL,
     or field name is always not-NULL). So calls for the entire
    make_truncated_value_warning() after splitting are not necessary.
2018-08-09 06:31:05 +04:00
Alexander Barkov
8ae2a2dbe6 MDEV-15363 Wrong result for CAST(LAST_DAY(TIME'00:00:00') AS TIME)
This problem was earlier fixed by the patch for MDEV-15340.
Adding tests only.
2018-08-03 09:03:11 +04:00
Alexander Barkov
1b87cd80a2 MDEV-16878 Functions ADDTIME and SUBTIME get wrongly removed from WHERE by the equal expression optimizer 2018-08-02 10:48:55 +04:00
Alexander Barkov
54fc47960d MDEV-16874 Implement class Item_handled_func 2018-08-01 16:15:16 +04:00
Alexander Barkov
28ff7e89c6 MDEV-16852 Get rid of Item_temporal_hybrid_func::fix_temporal_type()
- Implementing the task according to the MDEV description.
- Adding a helper class Sec6_add to share the code in type-specific
  branches in Item_func_add_time::get_date().
2018-07-30 20:40:48 +04:00