1
0
mirror of https://github.com/MariaDB/server.git synced 2026-10-23 18:49:29 +03:00

MDEV-41344 Timestamp conversion does not work for TRADITIONAL mode

Field_temporal::get_copy_func() returns do_field_datetime whenever the
session's sql_mode has NO_ZERO_DATE or NO_ZERO_IN_DATE (e.g. under
sql_mode=TRADITIONAL), or when the two fields are not eq_def(),
regardless of whether the field is a system-versioned
row_end.

get_copy_func() checked for that value and returned early, before ever
reaching the VERS_ROW_END check that installs
do_field_versioned_timestamp. So an ALTER TABLE .. FORCE meant to
convert an old-format row_end silently copied the value unchanged
instead: the conversion check correctly demanded a copy, but the copy
step never applied it, with no error or warning.

The fix checks the row_end conversion need first, independently of
what Field_temporal::get_copy_func() picked. row_end is
server-maintained and never zero, so NO_ZERO_DATE does not apply to
it.

Tested by "traditional" combination in old_timestamp.test, the test
restores real pre-11.5 row_end fixtures and runs mariadb-upgrade
--force.
This commit is contained in:
Aleksey Midenkov
2026-09-29 12:23:56 +03:00
parent 365d2d1f3e
commit dddbd5ff42
2 changed files with 10 additions and 4 deletions

View File

@@ -0,0 +1,4 @@
[normal]
[traditional]
sql-mode=TRADITIONAL

View File

@@ -782,12 +782,14 @@ Field::Copy_func *Field_timestamp::get_copy_func(const Field *from) const
Field::Copy_func *copy= Field_temporal::get_copy_func(from);
if (from->type() == MYSQL_TYPE_TIMESTAMP)
{
if ((flags & VERS_ROW_END) && (from->flags & VERS_ROW_END) &&
from->table->file->check_versioned_compatibility())
{
DBUG_ASSERT(eq_def(from));
return do_field_versioned_timestamp;
}
if (copy == do_field_datetime)
return do_field_timestamp;
if (copy == do_field_eq &&
from->table->file->check_versioned_compatibility() &&
(flags & VERS_ROW_END) && (from->flags & VERS_ROW_END))
return do_field_versioned_timestamp;
}
return copy;
}