1
0
mirror of https://github.com/MariaDB/server.git synced 2025-06-06 05:21:19 +03:00

156 Commits

Author SHA1 Message Date
Alexander Barkov
62c0ac2da6 A cleanup for MDEV-13916 Enforce check constraint on JSON type
1. Renaming Type_handler_json to Type_handler_json_longtext
   There will be other JSON handlers soon, e.g. Type_handler_json_varchar.

2. Making the code more symmetric for data types:

- Adding a new virtual method
  Type_handler::Column_definition_validate_check_constraint()
- Moving JSON-specific code from sql_yacc.yy to
  Type_handler_json_longtext::Column_definition_validate_check_constraint()

3. Adding new files sql_type_json.cc and sql_type_json.h
   and moving Type_handler+JSON related code into these files.
2019-02-15 19:46:58 +04:00
Marko Mäkelä
ea0be9e2d6 MDEV-15564 Avoid table rebuild in ALTER TABLE on collation or charset changes
Allow ALGORITHM=INSTANT (or avoid touching any data)
when changing the collation, or in some cases, the character set,
of a non-indexed CHAR or VARCHAR column. There is no penalty
for subsequent DDL or DML operations, and compatibility with
older MariaDB versions will be unaffected.

Character sets may be changed when the old encoding is compatible
with the new one. For example, changing from ASCII to anything
ASCII-based, or from 3-byte to 4-byte UTF-8 can sometimes be
performed instantly.

This is joint work with Eugene Kosov.
The test cases as well as ALTER_CONVERT_TO, charsets_are_compatible(),
Type_handler::Charsets_are_compatible() are his work.
The Field_str::is_equal(), Field_varstring::is_equal() and
the InnoDB changes were mostly rewritten by me due to conflicts
with MDEV-15563.

Limitations:

Changes of indexed columns will still require
ALGORITHM=COPY. We should allow ALGORITHM=NOCOPY and allow
the indexes to be rebuilt inside the storage engine,
without copying the entire table.

Instant column size changes (in bytes) are not supported by
all storage engines.

Instant CHAR column changes are only allowed for InnoDB
ROW_FORMAT=REDUNDANT. We could allow this for InnoDB
when the CHAR internally uses a variable-length encoding,
say, when converting from 3-byte UTF-8 to 4-byte UTF-8.

Instant VARCHAR column changes are allowed for InnoDB
ROW_FORMAT=REDUNDANT, and for others only if the size
in bytes does not change from 128..255 bytes to more
than 256 bytes.

Inside InnoDB, this slightly changes the way how MDEV-15563
works and fixes the result of the innodb.instant_alter_extend test.
We change the way how ALTER_COLUMN_EQUAL_PACK_LENGTH_EXT
is handled. All column extension, type changes and renaming
now go through a common route, except when ctx->is_instant()
is in effect, for example, instant ADD or DROP COLUMN has
been initiated. Only in that case we will go through
innobase_instant_try() and rewrite all column metadata.

get_type(field, prtype, mtype, len): Convert a SQL data type into
InnoDB column metadata.

innobase_rename_column_try(): Remove the update of SYS_COLUMNS.

innobase_rename_or_enlarge_column_try(): New function,
replacing part of innobase_rename_column_try() and all of
innobase_enlarge_column_try(). Also changes column types.

innobase_rename_or_enlarge_columns_cache(): Also change
the column type.
2019-02-14 20:17:14 +02:00
Monty
0f48949439 MDEV-13916 Enforce check constraint on JSON type
When creating a field of type JSON, it will be automatically
converted to TEXT with CHECK (json_valid(`a`)), if there wasn't any
previous check for the column.

Additional things:
- Added two bug fixes that was found while testing JSON. These bug
  fixes has also been pushed to 10.3 (with a test case), but as they
  where minimal and needed to get this task done and tested, the fixes
  are repeated here.
  - CREATE TABLE ... SELECT drops constraints for columns that
    are both in the create and select part.
  - If one has both a default expression and check constraint for a
    column, one can get the error "Expression for field `a` is refering
    to uninitialized field `a`.
- Removed some duplicate MYSQL_PLUGIN_IMPORT symbols
2019-02-13 19:40:26 +02:00
Alexander Barkov
b316989223 MDEV-18072 Assertion `is_null() == item->null_value || conv' failed in Timestamp_or_zero_datetime_native_null::Timestamp_or_zero_datetime_native_null upon query with GROUP BY 2018-12-25 08:27:07 +04:00
Marko Mäkelä
b5763ecd01 Merge 10.3 into 10.4 2018-12-18 11:33:53 +02:00
Alexander Barkov
4752a039b5 MDEV-17995 INET6_NTOA(ucs2_input) erroneously returns NULL 2018-12-13 15:09:03 +04:00
Alexander Barkov
c353b2a8fc --echo #
--echo # MDEV-17979 Assertion `0' failed in Item::val_native upon SELECT with timestamp, NULLIF, GROUP BY
--echo #
2018-12-12 10:39:06 +04:00
Alexander Barkov
34eb98387f MDEV-13995 MAX(timestamp) returns a wrong result near DST change 2018-12-10 19:25:12 +04:00
Alexander Barkov
f89a27b4e5 MDEV-17319 Assertion `ts_type != MYSQL_TIMESTAMP_TIME' failed upon inserting into TIME field 2018-12-02 18:59:04 +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
Alexander Barkov
4447a02cf1 MDEV-16991 Rounding vs truncation for TIME, DATETIME, TIMESTAMP 2018-11-26 08:10:47 +04:00
Alexander Barkov
740ce108a5 MDEV-17792 New class Timestamp and cleanups in Date, Datetime, Field for rounding 2018-11-22 14:53:25 +04:00
Alexander Barkov
ce32cae207 Fixing compilation failure on Windows introduced by MDEV-17776
commit 21a58840819530ed6a257550529e50e333237479
2018-11-21 11:29:41 +04:00
Alexander Barkov
21a5884081 MDEV-17776 CAST(x AS INTERVAL DAY_SECOND(N)) 2018-11-20 13:47:52 +04: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
b9a9055793 MDEV-17712 Remove C_TIME_FUZZY_DATES, C_TIME_DATETIME_ONLY, C_TIME_TIME_ONLY 2018-11-14 16:00:38 +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
563efeceec MDEV-17607 DATE(COALESCE(year_column)) returns a wrong result
C++ does not guarantee the order of parameter evaluation.
It was wrong to pass item->val_int() and item->null_value
at the same time to any function or constructor.
Adding a new helper class Longlong_null, and new methods
Item::to_longlong_null() and Item_func_hybrid_field_type::to_longlong_null_op(),
which make sure to properly call val_int()/int_op() and test null_value.
Reorganizing the rest of the code accordingly.
2018-11-04 07:13:07 +04:00
Alexander Barkov
5646c43159 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()
2018-10-09 12:02:35 +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
Alexander Barkov
e5aebc1408 A cleanup for MDEV-17317 Add THD* parameter into Item::get_date() and stricter data type control to "fuzzydate"
Fixing C++ function check_date() to get the "fuzzydate" as
date_mode_t rather than ulonglong, so conversion from
date_time_t to ulonglong is now done inside C++ check_date(),
and no conversion is needed in the callers' code.

As an additional safety, modified the code not to pass
TIME_FUZZY_DATE to the low level C functions:
- check_date()
- str_to_datetime()
- str_to_time()
- number_to_datetime()
because TIME_FUZZY_DATE is known only on the C++ level,
C functions do not know it.

Soon we'll be adding more flags into the C++ level (i.e. to date_time_t),
e.g. for rounding. It's a good idea to prevent passing C++ specific
flags into pure C routines before this change.

Asserts were added into the affected C functions to verify
that the caller passed only known C level flags.
2018-10-01 12:34:03 +04:00
Alexander Barkov
f79bab3ae6 MDEV-17318 CAST(LEAST(zero_date,non_zero_date) AS numeric_data_type) returns a wrong result
Also fixes:
MDEV-17330 Wrong result for 0 + LEAST(TIME'-10:00:00',TIME'10:00:00')

Problems:

1. These methods did not take into account the current session date flags
and passed date_mode_t(0) to func->get_date():

Type_handler_temporal_result::Item_func_min_max_val_real
Type_handler_temporal_result::Item_func_min_max_val_int
Type_handler_temporal_result::Item_func_min_max_val_decimal

Fixing to pass sql_mode_for_dates(thd) instead of date_mode_t(0).
Note, sql_mode_for_dates(thd) is only needed for DATE/DATETIME
data types. It is not needed for TIME.
So splitting value methods Type_handler_temporal_result::Item_func_min_max_xxx
into individual implementations for
Type_handler_{time|date|datetime|timestamp}_common
and, instead of calling get_date(), reusing inside classes
Time(), Date(), Datetime() and their methods to_longlong().
sql_mode_for_dates(thd) is automatically passed to get_date()
inside Date() and Datetime() constructors.

The switch to classes also fixed the problem reported in MDEV-17330.
Type_handler_temporal_result::Item_func_min_max_val_int() used to
call TIME_to_ulonglong(), which was not correct for TIME.
Changing the code to use Time().to_longlong() solved this.

2. Type_handler_temporal_result::Item_func_min_max_get_date
also did not take into account the current session
date flags in case of conversion from DATE/DATETIME to time
and passed date_mode_t(0) to get_date_native().
Fixing to pass sql_mode_for_dates(thd) in case of conversion
from DATE/DATETIME to TIME.
2018-09-30 17:24:19 +04:00
Alexander Barkov
23740441d8 MDEV-17325 NULL-ability problems with LEAST() in combination with NO_ZERO_DATE and NO_ZERO_IN_DATE 2018-09-29 21:20:24 +04:00
Alexander Barkov
ad8e02ac45 MDEV-17317 Add THD* parameter into Item::get_date() and stricter data type control to "fuzzydate" 2018-09-28 14:01:17 +04: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
Alexander Barkov
2fe51a6fdd MDEV-17175 Change Time/Datetime constructors to return warnings in MYSQL_TIME_STATUS 2018-09-12 09:06:27 +04:00
Alexander Barkov
4299b82ad8 MDEV-17015 Assertion `m_year <= 9999' failed in Year::Year upon bad argument to MAKEDATE 2018-08-18 23:22:22 +04:00
Alexander Barkov
2ef3d37a59 MDEV-16971 Assertion `is_valid_value_slow()' failed in Time::adjust_time_range_or_invalidate
The patch for MDEV-16928 added a few new asserts to check that
time, date, datetime values are valid and consistent after initialization.
One of the new asserts caught an improper initialization in
Time::make_from_datetime_with_days_diff()
(the former function calc_datetime_days_diff()).
If the YYYYMM part is not zero after unpack time
we have an out-of-range TIME value.
2018-08-15 19:14:20 +04:00
Alexander Barkov
c45050d253 MDEV-16935 Change the parameter of Field_xxx::store_TIME_with_dec() to const Datetime* and const Time* 2018-08-10 14:25:58 +04:00
Alexander Barkov
d2bba4ce25 MDEV-16928 Move MYSQL_TIME initialization from Field_xxx::store_time_dec() to new constructors Time() and Datetime() 2018-08-09 18:50:33 +04:00
Alexander Barkov
ffdae1a960 MDEV-16926 CAST(COALESCE(year_field)) returns wrong value 2018-08-09 11:08:11 +04: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
cb7b5fbf1c MDEV-16910 Add class VDec
Adding classes VDec and VDec2_lazy, according to the task description.
This patch removes around 250 duplicate code lines.
2018-08-07 10:48:42 +04:00
Alexander Barkov
c7115428ed MDEV-16881 Remove Item::get_temporal_with_sql_mode() and val_xxx_from_date() 2018-08-02 15:36:13 +04:00
Alexander Barkov
2bbee0e1ec MDEV-16861 Split Item::update_null_value() into a new virtual method in Type_handler 2018-07-31 10:09:53 +04:00
Alexander Barkov
998c97e865 MDEV-16823 Add Type_handler::Column_definition_reuse_fix_attributes()
Adding new methods:

- virtual void Type_handler::Column_definition_reuse_fix_attributes()
  according to the MDEV description

- virtual uint32 Field::character_octet_length()
  To simplify handling of Column_definition::length for
  TEXT and VARCHAR columns (with and without compression).
2018-07-25 13:08:01 +04:00
Alexander Barkov
a78d1aaaa3 MDEV-16806 Add Type_handler::create_literal_item() 2018-07-24 12:00:17 +04:00
Alexander Barkov
fee4632387 MDEV-15758 Split Item_bool_func::get_mm_leaf() into virtual methods in Field and Type_handler 2018-07-20 11:07:19 +04:00
Alexander Barkov
29da7a1a9a MDEV-16542 Fix ALTER TABLE FORCE to upgrade temporal types 2018-07-09 18:50:06 +04:00
Alexander Barkov
d60fdb5814 MDEV-16451 Split Item_equal::add_const() into a virtual method in type_handler()
MDEV-16452 Split TIME and DATETIME handling in Item_func_between, in_temporal, cmp_item_internal
2018-06-09 13:38:22 +04:00
Alexander Barkov
9043dd7a2d MDEV-11361 Equal condition propagation does not work for DECIMAL and temporal dynamic SQL parameters
MDEV-16426 Optimizer erroneously treats equal constants of different formats as same
A cleanup for MDEV-14630: fixing a crash in Item_decimal::eq().

Problems:
- old implementations of Item_decimal::eq() and
  Item_temporal_literal::eq() were not symmetric
  with Item_param::eq(), this caused MDEV-11361.

- old implementations for DECIMAL and temporal data types
  did not take into account that in case when eq() is called
  with binary_cmp==true, {{eq()}} should check not only equality
  of the two values, but also equality if their decimal precision.
  This cuases MDEV-16426.

- Item_decimal::eq() crashes with "item" pointing
  to a non-DECIMAL value. Before MDEV-14630
  non-DECIMAL values were filtered out by the test:
    type() == item->type()
  as literals of different types had different type().
  After MDEV-14630 type() for literals of all data types return CONST_ITEM.
  This caused failures in tests:
    ./mtr engines/iuds.insert_number
    ./mtr --ps --embedded main.explain_slowquerylog
  (revealed by buildbot)

The essence of the fix:
Making literals and Item_param reuse the same code to avoid
asymmetries between Item_param::eq(Item_literal) and
Item_literal::eq(Item_param), now and in the future, and to
avoid code duplication between Item_literal and Item_param.
Adding tests for "decimals" for DECIMAL and temporal data types,
to treat constants of different scale as not equal when "binary_cmp"
is "true".

Details:
1. Adding a helper class Item_const to extract constant values from Items easier
2. Deriving Item_basic_value from Item_const
3. Joining Type_handler::Item_basic_value_eq() and Item_basic_value_bin_eq()
   into a single method with an extra "binary_cmp" argument
   (it looks simple this way) and renaming the new method to Item_const_eq().
   Modifying its implementations to operate with
   Item_const instead of Item_basic_value.
4. Adding a new class Type_handler_hex_hybrid,
   to handle hex constants like 0x616263.
5. Removing Item::VARBIN_ITEM and fixing Item_hex_constant to
   use type_handler_hex_hybrid instead of type_handler_varchar.
   Item_hex_hybrid::type() now returns CONST_ITEM, like all
   other literals do.
6. Move virtual methods Item::type_handler_for_system_time() and
   Item::cast_to_int_type_handler() from Item to Type_handler.
7. Removing Item_decimal::eq() and Item_temporal_literal::eq().
   These classes are now handled by the generic Item_basic_value::eq().
8. Implementing Type_handler_temporal_result::Item_const_eq()
   and Type_handler_decimal_result::Item_const_eq(),
   this fixes MDEV-11361.
9. Adding tests for "decimals" into
   Type_handler_decimal_result::Item_const_eq() and
   Type_handler_temporal_result::Item_const_eq()
   in case if "binary_cmp" is true.
   This fixes MDEV-16426.
10. Moving Item_cache out of Item_basic_value.
   They share nothing. It simplifies implementation
   of Item_basic_value::eq(). Deriving Item_cache
   directly from Item.

11. Adding class DbugStringItemTypeValue, which
    used Item::print() internally, and using
    in instead of the old debug printing code.
    This gives nicer output in func_debug.result.

Changes N5 and N6 do not directly relate to the bugs fixed,
but make the code fully symmetric across all literal types.
Without a new handler Type_handler_hex_hybrid we'd have
to keep two code branches (for regular literals and for
hex hybrid literals).
2018-06-08 12:36:42 +04:00
Alexander Barkov
395212446a MDEV-16408 Remove tests for Item::type() in Item_basic_value::eq() 2018-06-05 22:26:24 +04:00
Alexander Barkov
f4dfc609cf MDEV-16388 Replace member Item::fixed to virtual method is_fixed() 2018-06-05 11:56:19 +04:00
Sergei Golubchik
c3a4dcd0f0 after merge fixes 2018-06-03 21:28:50 +02:00
Igor Babaev
cab1d63826 Merge branch '10.3' into 10.4 2018-06-03 10:34:41 -07:00
Alexander Barkov
ffe83e8e7b MDEV-16351 JSON_OBJECT() treats hybrid functions with boolean arguments as numbers
Now the boolean data type is preserved in hybrid functions and MIN/MAX,
so COALESCE(bool_expr,bool_expr) and MAX(bool_expr) are correctly
detected by JSON_OBJECT() as being boolean rather than numeric expressions.
2018-05-31 18:52:32 +04:00
Alexander Barkov
f584557406 MDEV-9216 Split field.cc:make_field() into virtual methods in Type_handler 2018-05-24 14:47:04 +04:00
Alexander Barkov
dc5802255d MDEV-16280 Add class Bit_addr 2018-05-24 09:31:36 +04:00
Alexander Barkov
46be31982a MDEV-16094 Crash when using AS OF with a stored function
MDEV-16100 FOR SYSTEM_TIME erroneously resolves string user variables as transaction IDs

Problem:

Vers_history_point::resolve_unit() tested item->result_type() before
item->fix_fields() was called.

- Item_func_get_user_var::result_type() returned REAL_RESULT by default.
  This caused MDEV-16100.
- Item_func_sp::result_type() crashed on assert.
  This caused MDEV-16094

Changes:
1. Adding item->fix_fields() into Vers_history_point::resolve_unit()
   before using data type specific properties of the history point
   expression.

2. Adding a new virtual method Type_handler::Vers_history_point_resolve_unit()

3. Implementing type-specific
   Type_handler_xxx::Type_handler::Vers_history_point_resolve_unit()
    in the way to:
    a. resolve temporal and general purpose string types to TIMESTAMP
    b. resolve BIT and general purpose INT types to TRANSACTION
    c. disallow use of non-relevant data type expressions in FOR SYSTEM_TIME

    Note, DOUBLE and DECIMAL data types are disallowed intentionally.
    - DOUBLE does not have enough precision to hold huge BIGINT UNSIGNED values
    - DECIMAL rounds on conversion to INT
    Both lack of precision and rounding might potentionally lead to
    very unpredictable results when a wrong transaction ID would be chosen.
    If one really wants dangerous use of DOUBLE and DECIMAL, explicit CAST
    can be used:

      FOR SYSTEM_TIME AS OF CAST(double_or_decimal AS UNSIGNED)

    QQ: perhaps DECIMAL(N,0) could still be allowed.

4. Adding a new virtual method Item::type_handler_for_system_time(),
   to make HEX hybrids and bit literals work as TRANSACTION rather
   than TIMESTAMP.

5. sql_yacc.yy: replacing the rule temporal_literal to "TIMESTAMP TEXT_STRING".
   Other temporal literals now resolve to TIMESTAMP through the new
   Type_handler methods. No special grammar needed. This removed
   a few shift/resolve conflicts.
   (TIMESTAMP related conflicts in "history_point:" will be removed separately)

6. Removing the "timestamp_only" parameter from
   vers_select_conds_t::resolve_units() and Vers_history_point::resolve_unit().
   It was a hint telling that a table did not have any TRANSACTION-aware
   system time columns, so it's OK to resolve to TIMESTAMP in case of uncertainty.
   In the new reduction it works as follows:
   - the decision between TIMESTAMP and TRANSACTION is first made
     based only on the expression data type only
   - then, in case if the expression resolved to TRANSACTION, the table
     is checked if TRANSACTION-aware columns really exist.
   This way is safer against possible ALTER TABLE statements changing
   ROW START and ROW END columns from "BIGINT UNSIGNED" to "TIMESTAMP(x)"
   or the other way around.
2018-05-15 09:33:29 +04:00
Alexander Barkov
461de7edea MDEV-15946 MEDIUMINT(N<8) creates a wrong data type on conversion to string 2018-04-23 18:34:06 +04:00