We cannot revert the ALTER, so anything happening after
the point of no return should not be treated as an error. A
very unfortunate condition that a user needs to be warned about - yes,
but we cannot say "ALTER TABLE has failed" if the table was successfully
altered.
In other ROW_FORMAT than REDUNDANT, the InnoDB record header
size calculation depends on dict_index_t::n_core_null_bytes.
In ROW_FORMAT=REDUNDANT, the record header always is 6 bytes
plus n_fields or 2*n_fields bytes, depending on the maximum
record size. But, during online ALTER TABLE, the log records
in the temporary file always use a format similar to
ROW_FORMAT=DYNAMIC, even omitting the 5-byte fixed-length part
of the header.
While creating a temporary file record for a ROW_FORMAT=REDUNDANT
table, InnoDB must refer to dict_index_t::n_nullable.
The field dict_index_t::n_core_null_bytes is only valid for
other than ROW_FORMAT=REDUNDANT tables.
The bug does not affect MariaDB 10.3, because only
commit 7a27db778e (MDEV-15563)
allowed an ALGORITHM=INSTANT change of a NOT NULL column to
NULL in a ROW_FORMAT=REDUNDANT table.
The fix was developed by Thirunarayanan Balathandayuthapani
and tested by Matthias Leich. The test case was simplified by me.
This is a backport of 161e4bfafd.
trans_rollback_to_savepoint(): Only release metadata locks (MDL)
if the storage engines agree, after the changes were already rolled back.
Ever since commit 3792693f31
and mysql/mysql-server@55ceedbc3f
we used to cheat here and always release MDL if the binlog is disabled.
MDL are supposed to prevent race conditions between DML and DDL also
when no replication is in use. MDL are supposed to be a superset of
InnoDB table locks: InnoDB table lock may only exist if the thread
also holds MDL on the table name.
In the included test case, ROLLBACK TO SAVEPOINT would wrongly release
the MDL on both tables and let ALTER TABLE proceed, even though the DML
transaction is actually holding locks on the table.
Until commit 1bd681c8b3 (MDEV-25506)
in MariaDB 10.6, InnoDB would often work around the locking violation
in a blatantly non-ACID way: If locks exist on a table that is being
dropped (in this case, actually a partition of a table that is being
rebuilt by ALTER TABLE), InnoDB could move the table (or partition)
into a queue, to be dropped after the locks and references had been
released. If the lock is not released and the original copy of the
table not dropped quickly enough, a name conflict could occur on
a subsequent ALTER TABLE.
The scenario of commit 3792693f31
is unaffected by this fix, because mysqldump
would use non-locking reads, and the transaction would not be holding
any InnoDB locks during the execution of ROLLBACK TO SAVEPOINT.
MVCC reads inside InnoDB are only covered by MDL and page latches,
not by any table or record locks.
FIXME: It would be nice if storage engines were specifically asked
which MDL can be released, instead of only offering a choice
between all or nothing. InnoDB should be able to release any
locks for tables that are no longer in trx_t::mod_tables, except
if another transaction had converted some implicit record locks
to explicit ones, before the ROLLBACK TO SAVEPOINT had been completed.
Reviewed by: Sergei Golubchik
A table rebuild that would truncate the default value of a
DATE column is expected to issue data truncation warnings.
But, these warnings are not being issued if the ADD COLUMN
is being executed with ALGORITHM=INSTANT. InnoDB sets the
warning of the field while assigning the default value
of the field during check_if_supported_inplace_alter().
C:\projects\server\sql\sql_show.cc(7913): error C2220: warning treated as error - no 'object' file generated [C:\projects\server\win_build\sql\sql.vcxproj]
C:\projects\server\sql\sql_show.cc(7913): warning C4267: 'initializing': conversion from 'size_t' to 'uint', possible loss of data [C:\projects\server\win_build\sql\sql.vcxproj]
caused by 768c51880a
ha_innobase::truncate(): If the operation fails, preserve
also dict_table_t::def_trx_id.
This fixes a regression that had been introduced in
commit 1bd681c8b3 (MDEV-25506).
With commit 1bd681c8b3 (MDEV-25506)
it no longer is necessary to run DDL and DML operations in
separate transactions. Let us remove the flag trx_t::internal.
Dictionary transactions will be distinguished by trx_t::dict_operation.
In commit e71e613353 we
accidentally made innodb_lock_wait_timeout=100000000
a "literal" value, not the smallest special value that
would mean "infinite" timeout.
trans_rollback_to_savepoint(): Only release metadata locks (MDL)
if the storage engines agree, after the changes were already rolled back.
Ever since commit 3792693f31
and mysql/mysql-server@55ceedbc3f
we used to cheat here and always release MDL if the binlog is disabled.
MDL are supposed to prevent race conditions between DML and DDL also
when no replication is in use. MDL are supposed to be a superset of
InnoDB table locks: InnoDB table lock may only exist if the thread
also holds MDL on the table name.
In the included test case, ROLLBACK TO SAVEPOINT would wrongly release
the MDL on both tables and let ALTER TABLE proceed, even though the DML
transaction is actually holding locks on the table.
Until commit 1bd681c8b3 (MDEV-25506)
InnoDB worked around the locking violation in a blatantly non-ACID way:
If locks exist on a table that is being dropped (in this case, actually
a partition of a table that is being rebuilt by ALTER TABLE), InnoDB
would move the table (or partition) into a queue, to be dropped after
the locks and references had been released.
The scenario of commit 3792693f31
is unaffected by this fix, because mariadb-dump (a.k.a. mysqldump)
would use non-locking reads, and the transaction would not be holding
any InnoDB locks during the execution of ROLLBACK TO SAVEPOINT.
MVCC reads inside InnoDB are only covered by MDL and page latches,
not by any table or record locks.
FIXME: It would be nice if storage engines were specifically asked
which MDL can be released, instead of only offering a choice
between all or nothing. InnoDB should be able to release any
locks for tables that are no longer in trx_t::mod_tables, except
if another transaction had converted some implicit record locks
to explicit ones, before the ROLLBACK TO SAVEPOINT had been completed.
Reviewed by: Sergei Golubchik
The practical maximum value of the parameter innodb_lock_wait_timeout
is 100,000,000. Any value larger than that specifies an infinite timeout.
Therefore, we should make 100,000,000 the maximum value of the parameter.
Let us use innodb_lock_wait_timeout=0 for an immediate timeout.
Also, do not override the timeout in the default connection,
so that further tests will use the default setting.
This replaces 8711adb786
if a temptable field is created for some json expression (is_json_type()
returns true), make this temptable field a proper json field.
A field is a json field (see Item_field::is_json_type()) if it
has a CHECK constraint of JSON_VALID(field).
Note that it will never be actually checked for temptable fields,
so it won't cause a run-time slowdown.
Revert "fix JSON_ARRAYAGG not to over-quote json in joins"
This removes 8711adb786 but keeps the test case.
A different fix is coming up.
Because args can be Item_field's that are later
replaced by Item_direct_view_ref to the actual field.
While Item_field preserved in orig_args will stay unfixed
with item->field==NULL and no metadata
Consider a query of the form:
select ... from (select item2 as COL1) as T where COL1=123
Condition pushdown into derived table will try to push "COL1=123" condition
down into table T.
The process of pushdown involves "substituting" the item, that is,
replacing Item_field("T.COL1") with its "producing item" item2.
In order to use item2, one needs to clone it (call Item::build_clone).
If the item is not cloneable (e.g. Item_func_sp is not), the pushdown
process will fail and nothing at all will be pushed.
Fixed by introducing transform_condition_or_part() which will try to apply
the transformation for as many parts of condition as possible. The parts of
condition that couldn't be transformed are dropped.
use metadata (in particular is_json() property) of the original
argument item, even if the actual argument was later replaced
with an Item_temptable_field
when checking whether thd wasn't killed before this
emb_advanced_command(), take into account that it
could've been killed before the *previous*
emb_advanced_command(). That is, the previous one has
already set thd to NULL and this one only wanted a COM_STMT_RESET
after a failure.
trx_t::drop_table(): Relax also another assertion that would fail
due to an AUTO_INCREMENT lock that is being held by the current
test case. This should have been part of
commit 63e9a05440.
Add KEYWORDS table and SQL_FUNCTIONS table to INFORMATION_SCHEMA.
This commits needs some minor changes when propagated upwards
(e.g. func_array in item_create.cc has a termination element that
doesn't exist in later versions of MariaDB)
my_init_atomic_write(): Detect all forms of SSD, in case multiple
types of devices are installed in the same machine.
This was broken in commit ed008a74cf
and further in commit 70684afef2.
SAME_DEV(): Match block devices, ignoring partition numbers.
Let us use stat() instead of lstat(), in case someone has a symbolic
link in /dev.
Instead of reporting errors with perror(), let us use fprintf(stderr)
with the file name, the impact of the error, and the strerror(errno).
Because this code is specific to Linux, we may depend on the
GNU libc/uClibc/musl extension %m for strerror(errno).
trx_t::drop_table(): Delete-mark the SYS_TABLES and SYS_INDEXES
record before delete-marking any SYS_COLUMNS or SYS_FIELDS records.
Otherwise, dict_load_indexes() could fail on recovery. This fixes up
commit 1bd681c8b3 (MDEV-25506).