1
0
mirror of https://github.com/MariaDB/server.git synced 2025-04-28 06:45:23 +03:00

194 Commits

Author SHA1 Message Date
Alexander Barkov
ae33ebe5b3 MDEV-23525 Wrong result of MIN(time_expr) and MAX(time_expr) with GROUP BY
Problem:

When calculatung MIN() and MAX() in a query with GROUP BY, like this:

  SELECT MIN(time_expr), MAX(time_expr) FROM t1 GROUP BY i;

the code in Item_sum_min_max::update_field() erroneosly used
string format comparison, therefore '100:20:30' was considered as
smaller than '10:20:30'.

Fix:

1. Implementing low level "native" related methods in class Time:
     Time::Time(const Native &native)           - convert native to Time
     Time::to_native(Native *to, uint decimals) - convert Time to native

   The "native" binary representation for TIME is equal to
   the binary data format of Field_timef, which is used to
   store TIME when mysql56_temporal_format is ON (default).

2. Implementing Type_handler_time_common "native" related methods:

  Type_handler_time_common::cmp_native()
  Type_handler_time_common::Item_val_native_with_conversion()
  Type_handler_time_common::Item_val_native_with_conversion_result()
  Type_handler_time_common::Item_param_val_native()

3. Implementing missing "native representation" related methods
   in Field_time and Field_timef:

  Field_time::store_native()
  Field_time::val_native()
  Field_timef::store_native()
  Field_timef::val_native()

4. Implementing missing "native" related methods in all Items
   that can have the TIME data type:

  Item_timefunc::val_native()
  Item_name_const::val_native()
  Item_time_literal::val_native()
  Item_cache_time::val_native()
  Item_handled_func::val_native()

5. Marking Type_handler_time_common as "native ready".
   So now Item_sum_min_max::update_field() calculates
   values using min_max_update_native_field(),
   which uses native binary representation rather than string representation.

   Before this change, only the TIMESTAMP data type used native
   representation to calculate MIN() and MAX().

Benchmarks (see more details in MDEV):

  This change not only fixes the wrong result, but also
  makes a "SELECT .. MAX.. GROUP BY .." query faster:

  # TIME(0)
  CREATE TABLE t1 (id INT, time_col TIME) ENGINE=HEAP;
  INSERT INTO t1 VALUES (1,'10:10:10'); -- repeat this 1m times
  SELECT id, MAX(time_col) FROM t1 GROUP BY id;

  MySQL80: 0.159 sec
  10.3:    0.108 sec
  10.4:    0.094 sec (fixed)

  # TIME(6):
  CREATE TABLE t1 (id INT, time_col TIME(6)) ENGINE=HEAP;
  INSERT INTO t1 VALUES (1,'10:10:10.999999'); -- repeat this 1m times
  SELECT id, MAX(time_col) FROM t1 GROUP BY id;

  My80: 0.154
  10.3: 0.135
  10.4: 0.093 (fixed)
2020-08-22 07:53:44 +04:00
Marko Mäkelä
101ddc5e27 Merge mariadb-10.4.14 2020-08-10 20:37:52 +03:00
Alexander Barkov
100f0c965c MDEV-23388 Assertion `args[0]->decimals == 0' failed in Item_func_round::fix_arg_int
Type_handler_temporal_result::Item_func_min_max_fix_attributes()
in an expression GREATEST(string,date), e.g:

  SELECT GREATEST('1', CAST('2020-12-12' AS DATE));

incorrectly evaluated decimals as 6 (like for DATETIME).

Adding a separate virtual implementation:
  Type_handler_date_common::Item_func_min_max_fix_attributes()
This makes the code simpler.
2020-08-04 08:38:32 +04:00
Oleksandr Byelkin
57325e4706 Merge branch '10.3' into 10.4 2020-08-03 14:44:06 +02:00
Alexander Barkov
9840bb21ef MDEV-23366 ROUND(18446744073709551615,rand()*0) returns a wrong result
Changing that in case of *INT and hex hybrid input:
- ROUND(x,NULL) creates a column with the same type as x.
  The old code created a DOUBLE column, which was not relevant at all.
  This change simplifies the code a lot.

- ROUND(x,non_constant) creates a column of the INT, BIGINT or DECIMAL
  data type (depending on the exact type of x).
  The old code created a column of the DOUBLE data type,
  which lead to precision loss. Hence MDEV-23366.

- ROUND(bigint_30,negative_constant) creates a column of the DECIMAL(30,0)
  data type. The old code created DECIMAL(29,0), which looked strange:
  the data type promoted to a higher one, but max length reduced.
  Now the length attribute is preserved.
2020-08-03 10:53:06 +04:00
Alexander Barkov
3b87a68169 MDEV-23368 ROUND(18446744073709551615,-11) returns a wrong result
Item_func_round::fix_arg_int() did not take into account cases
when the result of ROUND(bigint_subject,negative_precision)
could go outside of the BIGINT range. The old code only incremented
max_length, but did not extend change the data type.
Fixing to extend the data type (together with max_length increment).
2020-08-02 22:48:53 +04:00
Alexander Barkov
d63631c3fa MDEV-19632 Replication aborts with ER_SLAVE_CONVERSION_FAILED upon CREATE ... SELECT in ORACLE mode
- Adding optional qualifiers to data types:
    CREATE TABLE t1 (a schema.DATE);
  Qualifiers now work only for three pre-defined schemas:

    mariadb_schema
    oracle_schema
    maxdb_schema

  These schemas are virtual (hard-coded) for now, but may turn into real
  databases on disk in the future.

- mariadb_schema.TYPE now always resolves to a true MariaDB data
  type TYPE without sql_mode specific translations.

- oracle_schema.DATE translates to MariaDB DATETIME.

- maxdb_schema.TIMESTAMP translates to MariaDB DATETIME.

- Fixing SHOW CREATE TABLE to use a qualifier for a data type TYPE
  if the current sql_mode translates TYPE to something else.

The above changes fix the reported problem, so this script:

    SET sql_mode=ORACLE;
    CREATE TABLE t2 AS SELECT mariadb_date_column FROM t1;

is now replicated as:

    SET sql_mode=ORACLE;
    CREATE TABLE t2 (mariadb_date_column mariadb_schema.DATE);

and the slave can unambiguously treat DATE as the true MariaDB DATE
without ORACLE specific translation to DATETIME.

Similar,

    SET sql_mode=MAXDB;
    CREATE TABLE t2 AS SELECT mariadb_timestamp_column FROM t1;

is now replicated as:

    SET sql_mode=MAXDB;
    CREATE TABLE t2 (mariadb_timestamp_column mariadb_schema.TIMESTAMP);

so the slave treats TIMESTAMP as the true MariaDB TIMESTAMP
without MAXDB specific translation to DATETIME.
2020-08-01 07:43:50 +04:00
Marko Mäkelä
9216114ce7 Merge 10.3 into 10.4 2020-07-31 18:09:08 +03:00
Alexander Barkov
dc513dff91 MDEV-23351 Rounding functions return wrong data types for DATE input
Fixing ROUND(date,0), TRUNCATE(date,x), FLOOR(date), CEILING(date)
to return the `int(8) unsigned` data type.

Details:
1. Cleanup: moving virtual implementations
   - Type_handler_temporal_result::Item_func_int_val_fix_length_and_dec()
   - Type_handler_temporal_result::Item_func_round_fix_length_and_dec()
   to Type_handler_date_common. Other temporal data type handlers
   override these methods anyway. So they were only DATE specific.
   This change makes the code clearer.
2. Backporting DTCollation_numeric from 10.5, to reuse the code easier.
3. Adding the `preferred_attrs` argument to Item_func_round::fix_arg_int(). Now
   Type_handler_xxx::Item_func_round_val_fix_length_and_dec() work as follows:
   - The INT-alike and YEAR handlers copy preferred_attrs from args[0].
   - The DATE handler passes explicit attributes, to get `int(8) unsigned`.
   - The hex hybrid handler passes NULL, so fix_arg_int() calculates attributes.
4. Type_handler_date_common::Item_func_int_val_fix_length_and_dec()
   now sets the type handler and attributes to get `int(8) unsigned`.
2020-07-31 17:45:39 +04:00
Alexander Barkov
a874b6c445 MDEV-23337 Rounding functions create a wrong data type for integer input
1. Fixing ROUND(x) and TRUNCATE(x,0) with TINYINT, SMALLINT, MEDIUMINT, BIGINT
   input to preserve the exact data type of the argument when it's possible.

2. Fixing FLOOR(x) and CEILING(x) with TINYINT, SMALLINT, MEDIUMINT, BIGINT
  to preserve the exact data type of the argument.

3. Adding dedicated Type_handler_year::Item_func_round_fix_length_and_dec()
  to easier handle ROUND(x) and TRUNCATE(x,y) for the YEAR(2) and YEAR(4)
  input. They still return INT(2) UNSIGNED and INT(4) UNSIGNED correspondingly,
  as before.
2020-07-31 07:41:30 +04:00
Alexander Barkov
6d3186e326 MDEV-23323 Rounding functions return a wrong data type for a BIT, ENUM, SET argument
Implementing dedicated fixing methods:
- Type_handler_bit::Item_func_round_fix_length_and_dec()
- Type_handler_bit::Item_func_int_val_fix_length_and_dec()
- Type_handler_typelib::Item_func_round_fix_length_and_dec()

because the inherited methods did not work well.

Fixing:
- Type_handler_typelib::Item_func_int_val_fix_length_and_dec
  It did not work well, because it used args[0]->max_length to
  calculate the result data type. In case of ENUM and SET it was
  not correct, because in FLOOR() and CEILING() context
  ENUM and SET return not more than 5 digits (65535 is the biggest
  possible value).

Misc:
- Changing the API of
    Type_handler_bit::Bit_decimal_notation_int_digits(const Item *item)
  to a more generic form:
    Type_handler_bit::Bit_decimal_notation_int_digits_by_nbits(uint nbits)

- Fixing Type_handler_bit::Bit_decimal_notation_int_digits_by_nbits() to
  return the exact number of decimal digits for all nbits 1..64.
  The old implementation was approximate.
  This change gives better (more precise) data types.
2020-07-30 08:04:58 +04:00
Alexander Barkov
92499ae95c MDEV-23320 Hex hybrid constants 0xHHHH work badly in rounding functions
- Type_handler_hex_hybrid did not override
  Type_handler_string_result::Item_func_round_fix_length_and_dec(),
  so the result type of ROUND(0xFFFFFFFFFFFFFFFF) was erroneously
  calculated ad DOUBLE with a wrong length.
  Overriding Item_func_round_fix_length_and_dec(), to calculated
  the result type as INT/BIGINT.

  Also, fixing Item_func_round::fix_arg_int() to use
  args[0]->decimal_precision() instead of args[0]->max_length
  when calculating this->max_length, to get a correct result
  for hex hybrids.

- Type_handler_hex_hybrid::Item_func_int_val_fix_length_and_dec()
  called item->fix_length_and_dec_int_or_decimal(), which did not
  produce a correct result data type for hex hybrid.
  Implementing a dedicated code instead, to return INT UNSIGNED or
  BIGINT UNSIGNED depending in the number of digits in the arguments.
2020-07-29 21:45:41 +04:00
Alexander Barkov
5b3b53ce36 MDEV-23311 CEILING() and FLOOR() convert temporal input to numbers, unlike ROUND() and TRUNCATE()
Fixing functions CEILING and FLOOR to return
- TIME for TIME input
- DATETIME for DATETIME and TIMESTAMP input
2020-07-28 23:29:08 +04:00
Marko Mäkelä
805340936a Merge 10.3 into 10.4 2020-06-13 19:01:28 +03:00
Alexander Barkov
6c30bc2181 MDEV-22268 virtual longlong Item_func_div::int_op(): Assertion `0' failed in Item_func_div::int_op
Item_func_div::fix_length_and_dec_temporal() set the return data type to
integer in case of @div_precision_increment==0 for temporal input with FSP=0.
This caused Item_func_div to call int_op(), which is not implemented,
so a crash on DBUG_ASSERT(0) happened.

Fixing fix_length_and_dec_temporal() to set the result type to DECIMAL.
2020-06-13 09:30:04 +04:00
Gagan Goel
f0ca9bc669 MDEV-20732 Correctly set the length of the FORMAT() result for float data type as argument. 2020-01-16 09:46:58 +02:00
Roman Nozdrin
ad8266a5c2 MDEV-20732 MDB now correctly estimates a length of the FORMAT() result for
doubles in scientific notation with a big integer part.
2019-10-31 02:26:04 -05:00
Alexander Barkov
235cf969d2 MDEV-20397 Support TIMESTAMP, DATETIME, TIME in ROUND() and TRUNCATE() 2019-08-22 15:09:59 +04:00
Alexander Barkov
95cdc1ca5f Merge commit '43882e764d6867c6855b1ff057758a3f08b25c55' into 10.4 2019-08-13 11:42:31 +04:00
Alexander Barkov
2dac123515 A cleanup for MDEV-20273 Add class Item_sum_min_max - removing duplicate code
Reusing the MIN()/MAX() fix_length_and_dec() related code for window functions
- FIRST_VALUE()
- LAST_VALUE()
- NTH_VALUE()
- LEAD()
- LAG
2019-08-09 09:00:17 +04:00
Alexander Barkov
e978efd96b MDEV-20273 Add class Item_sum_min_max 2019-08-07 14:13:44 +04:00
Marko Mäkelä
9c16460e63 Merge 10.3 into 10.4 2019-07-01 18:37:15 +03:00
Monty
9053047f3d MDEV-17551 assert or crashed table when using blobs
The bug was that when long item-strings was converted to VARCHAR,
type_handler::string_type_handler() didn't take into account max
VARCHAR length.  The resulting Aria temporary table was created with
a VARCHAR field of length 1 when it should have been 65537. This caused
MariaDB to send impossible records to ma_write() and Aria reported
eventually the table as crashed.

Fixed by updating Type_handler::string_type_handler() to not create too long
VARCHAR fields. To make things extra safe, I also added checks in when
writing dynamic Aria records to ensure we find the wrong record during write
instead of during read.
2019-06-27 19:01:51 +03:00
Eugene Kosov
a82e42fd13 NFC: refactor Field::is_equal() and related stuff
Make Field::is_equal() const and return bool as it's a naturally fitting
type for it. Also it's agrument was narrowed to Column_definition.

InnoDB can change type of some columns by itself. InnoDB-specific code used to
reside in Field_xxx:is_equal() methods. Now engine-specific stuff was
moved to a virtual methods of handler::can_convert{string,varstring,blob,geom}.
These methods are called by Field::can_be_converted_by_engine() which is a
double dispatch pattern.

Some InnoDB-specific code still resides in compare_keys_but_name(). It should
be moved from here someday to handler::compare_key_parts(...) or similar.

IS_EQUAL_WITH_REINTERPRET_COMPATIBLE_CHARSET
IS_EQUAL_WITH_REINTERPRET_COMPATIBLE_CHARSET_BUT_COLLATE: both was removed

IS_EQUAL_NO, IS_EQUAL_YES are not needed now and should be removed
along with deprecated handler::check_if_incompatible_data().

HA_EXTENDED_TYPES_CONVERSION: was removed as such logic is not needed now by
server code.

ALTER_COLUMN_EQUAL_PACK_LENGTH: was renamed to a more generic
ALTER_COLUMN_TYPE_CHANGE_BY_ENGINE
2019-06-22 14:09:12 +03:00
Eugene Kosov
854c219a7f MDEV-17301 Change of COLLATE unnecessarily requires ALGORITHM=COPY
Patch is about two cases:
1) On some collate changes it's possible to rebuild only secondary indexes
2) For non-indexed columns collate can be changed INSTANTly

Implemented mostly in Field_{string,varstring,blob}::is_equal().
Make this method return how exactly collationa differs.
This information is later used by fill_alter_inplace_info() to pass
correct info to engine.
2019-06-22 14:09:12 +03:00
Oleksandr Byelkin
c07325f932 Merge branch '10.3' into 10.4 2019-05-19 20:55:37 +02:00
Alexander Barkov
d9f392848a A cleanup for MDEV-19284, MDEV-19285
Fixing a test failure tokudb.change_column_varbin_descriptor
2019-05-18 07:26:56 +04:00
Alexander Barkov
d682dc2e70 MDEV-8919 Wrong result for CAST(9999999999999999999.0) 2019-05-17 08:08:11 +04:00
Alexander Barkov
c59d6395a6 A joint patch for MDEV-19284 and MDEV-19285 (INSTANT ALTER)
This patch fixes:

- MDEV-19284 INSTANT ALTER with ucs2-to-utf16 conversion produces bad data
- MDEV-19285 INSTANT ALTER from ascii_general_ci to latin1_general_ci produces corrupt data

These regressions were introduced in 10.4.3 by:
- MDEV-15564 Avoid table rebuild in ALTER TABLE on collation or charset changes

Changes:

1. Cleanup: Adding a helper method
   Field_longstr::csinfo_change_allows_instant_alter(),
   to remove some duplicate code in field.cc.

2. Cleanup: removing Type_handler::Charsets_are_compatible() and static
   function charsets_are_compatible() and
   introducing new methods in the recently added class Charset instead:
   - encoding_allows_reinterpret_as()
   - encoding_and_order_allow_reinterpret_as()

3. Bug fix: Removing the code that allowed instant conversion for
   ascii-to->8bit and ucs2-to->utf16.
   This actually fixes MDEV-19284 and MDEV-19285.

4. Bug fix: Adding a helper method Charset::collation_specific_name().
   The old corresponding code in Type_handler::Charsets_are_compatible()
   was not safe against (badly named) user-defined collations whose
   character set name can be longer than collation name.
2019-05-16 16:20:25 +04:00
Alexander Barkov
b7d22a843e MDEV-16872 Add CAST(expr AS FLOAT) 2019-05-16 10:16:32 +04:00
Alexander Barkov
462d689397 MDEV-19468 Hybrid type expressions return wrong format for FLOAT 2019-05-15 07:21:00 +04:00
Marko Mäkelä
be85d3e61b Merge 10.2 into 10.3 2019-05-14 17:18:46 +03:00
Marko Mäkelä
26a14ee130 Merge 10.1 into 10.2 2019-05-13 17:54:04 +03:00
Vicențiu Ciorbaru
cb248f8806 Merge branch '5.5' into 10.1 2019-05-11 22:19:05 +03:00
Marko Mäkelä
d3dcec5d65 Merge 10.3 into 10.4 2019-05-05 15:06:44 +03:00
Alexander Barkov
8c8bee0a56 MDEV-10307 CAST(11068046444225730969 AS SIGNED) does not return a warning 2019-04-30 15:51:49 +04:00
Alexander Barkov
baadbe9601 MDEV-9234 Add Type_handler::union_element_finalize() 2019-04-23 13:45:28 +04:00
Alexander Barkov
f4019f5b35 Backporting from 10.4 to 10.3: MDEV-17325 NULL-ability problems with LEAST() in combination with NO_ZERO_DATE and NO_ZERO_IN_DATE
This also fixes:
MDEV-17299 Assertion `maybe_null' failed in make_sortkey

Note, during merge of the 10.1 version of MDEV-17299,
please use the 10.3 version of the code (i.e. null merge the 10.1 version).
2019-04-20 00:11:50 +04:00
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