OLD VALUE OF INPUT PARAMETER.
The user-visible problem was that CASE-control-flow function
(not CASE-statement) misbehaved in stored routines under some
circumstances. The problem resulted in a crash or wrong data
returned. The error happened when expressions in CASE-function
were not of the same character set.
A CASE-function should return values of the same character set
for all branches. Internally, that means a new Item-instance
for the CONVERT(... USING <some charset>)-function is added
to the item tree when needed. The problem was that such changes
were not properly recorded using THD::change_item_tree(),
thus dangling pointers remain in the item tree after
THD::rollback_item_tree_changes(), which lead to undefined
behavior (i.e. crash / wrong data) for subsequent executions of
the stored routine.
This bug was introduced by a patch for Bug 11753363
(44793 - CHARACTER SETS: CASE CLAUSE, UCS2 OR UTF32, FAILURE).
The fixed function is Item_func_case::fix_length_and_dec().
New CONVERT-items are added in agg_item_set_converter(),
which calls THD::change_item_tree().
The problem was that an intermediate array was passed
to agg_item_set_converter(). Thus, THD::change_item_tree() there
was called on intermediate objects.
Note: those intermediate objects are allocated on THD's
memory root, so it's Ok to put them into "changed item lists".
The fix is to track changes on the correct objects.
- Added regression test with queries over the WORLD database.
- Discovered and fixed several bugs in the related cost calculation
functionality both in the semijoin and non-semijon subquery code.
- Added DBUG printing of the cost variables used to decide between
IN-EXISTS and MATERIALIZATION.
TO POSITION FIRST CAN CAUSE DATA TO BE CORRUPTED".
ALTER TABLE MODIFY/CHANGE ... FIRST did nothing except renaming
columns if new version of the table had exactly the same
structure as the old one (i.e. as result of such statement, names
of columns changed their order as specified but data in columns
didn't). The same thing happened for ALTER TABLE DROP COLUMN/ADD
COLUMN statements which were supposed to produce new version of
table with exactly the same structure as the old version of table.
I.e. in the latter case the result was the same as if old column
was renamed instead of being dropped and new column with default
as value being created.
Both these problems were caused by the fact that ALTER TABLE
implementation incorrectly interpreted both these situations as
simple renaming of columns and assumed that in-place ALTER TABLE
algorithm could have been used for them.
This patch fixes this problem by ensuring that in cases when some
column is moved to the first position or some column is dropped
the default ALTER TABLE algorithm involving table copying is
always used. This is achieved by detecting such situations in
mysql_prepare_alter_table() and setting Alter_info::change_level
to ALTER_TABLE_DATA_CHANGED for them.
mysql-test/r/alter_table.result:
Added test for bug #12652385 - "61493: REORDERING COLUMNS TO
POSITION FIRST CAN CAUSE DATA TO BE CORRUPTED".
mysql-test/t/alter_table.test:
Added test for bug #12652385 - "61493: REORDERING COLUMNS TO
POSITION FIRST CAN CAUSE DATA TO BE CORRUPTED".
sql/sql_table.cc:
Changed mysql_prepare_alter_table() to detect situations in
which we some column moved to the first position or some column
is dropped and ensure that such ALTER TABLE statements won't
be carried out using in-place algorithm. The latter could have
happened before this patch if new version of table had the same
structure as the old one (except the column names).
UPDATED TWICE
For multi update it is not allowed to update a column
of a table if that table is accessed through multiple aliases
and either
1) the updated column is used as partitioning key
2) the updated column is part of the primary key
and the primary key is clustered
This check is done in unsafe_key_update().
The bug was that for case 2), it was checked whether
updated_column_number == table_share->primary_key
However, the primary_key variable is the index number of the
primary key, not a column number.
Prior to this bugfix, the first column was wrongly believed to be
the primary key. The columns covered by an index is found in
table->key_info[idx_number]->key_part. The bugfix is to check if
any of the columns in the keyparts of the primary key are
updated.
The user-visible effect is that for storage engines with
clustered primary key (e.g. InnoDB but not MyISAM) queries
like
"UPDATE t1 AS A JOIN t2 AS B SET A.primkey=..."
will now error with
"ERROR HY000: Primary key/partition key update is not allowed
since the table is updated both as 'A' and 'B'."
instead of
"ERROR 1032 (HY000): Can't find record in 't1_tb'"
even if primkey is not the first column in the table. This
was the intended behavior of bugfix 11764529.
mysql-test/r/multi_update.result:
Add test for bug#11882110
mysql-test/r/multi_update_innodb.result:
Add test for bug#11882110
mysql-test/t/multi_update.test:
Add test for bug#11882110
mysql-test/t/multi_update_innodb.test:
Add test for bug#11882110
sql/sql_update.cc:
unsafe_key_update() wrongly checked if the primary key index
number was the same as updated column number. Now it is checked
whether any of the columns making up the primary key is updated.
sql/table.h:
Fix comment on TABLE_SHARE::primary_key. Incorrect comment
was introduced by an earlier merge conflict (as per dlenev)
Changed the code that processing of multi-updates and multi-deletes
with multitable views at the prepare stage.
A proper solution would be: never to perform any transformations of views
before and at the prepare stage. Yet it would require re-engineering
of the code that checks privileges and updatability of views.
Ultimately this re-engineering has to be done to provide a clean solution
for INSERT/UPDATE/DELETE statements that use views.
Fixed a valgrind problem in the function TABLE::use_index.
Issue:
When libmysqld/example/mysql_embedded is executed, it was getting abort. Its a
regression as it was working in 5.1 and failed in 5.5. Issue is there because
remaining_argc/remaining_argv were not getting assigned correctly in
init_embedded_server() which were being used later in init_common_variable().
Solution:
Rectified code to pass correct argc/argv to be used in init_common_variable().
libmysqld/lib_sql.cc:
Rectified remaining_argc/remaining_argv assignment.
mysql-test/r/mysql_embedded.result:
Result file for the test case added.
mysql-test/t/mysql_embedded.test:
Added test case to verify libmysqld/example/mysql_embedded works.
Added option to aria_read_log to crash recovery at certain points in the recovery process.
Fixed bug that caused future recovery attempts to fail if we got a crash/got killed during closing of tables at end of recovery process.
mysql-test/mysql-test-run.pl:
Don't abort if 'var' points to stale place; Just remove it.
mysql-test/suite/maria/r/maria.result:
Fixed wrong indentation
mysql-test/t/partition_error.test:
Fixed portability problem with partiton_error.test
storage/maria/ma_close.c:
More DBUG_PRINT info
storage/maria/ma_pagecache.c:
Copy flush_log_callback when writing to page cache. This fixes problem in recovery when switching from mode of file
storage/maria/ma_recovery.c:
Added option to aria_read_log to crash recovery at certain points in the recovery process.
storage/maria/ma_recovery.h:
Added option to aria_read_log to crash recovery at certain points in the recovery process.
storage/maria/maria_chk.c:
Align aria_chk -d output
Don't write warning Aria table '...' is usable but should be fixed if the table was before marked as crashed but now is ok
storage/maria/maria_read_log.c:
Added option to aria_read_log to crash recovery at certain points in the recovery process.
The previous patch partially fixed things by waiting for the old dump thread
on the master to exit before injecting the DBUG error. This prevents the error
injection going to the wrong thread.
However, there is still the problem that the old dump thread may never exit,
causing the wait to time out. This happens if the dump thread manages to write
all events down the socket before the socket is closed by the slave. The
master dump thread only checks for slave gone when writing a new event, so if
no new events are generated, old dump threads can hang around forever on the
master after the slave disconnects.
Fix by explicitly killing the old dump thread if it is still around.
Noted that there was no memory leak, just a lot of used partitioned tables.
Fixed old bug: 'show status' now shows memory usage when compiled with safemalloc.
Added option --flush to mysqlcheck.c to run a 'flush tables' between each check to keep down memory usage.
Changed '--safemalloc' options to mysqld so that one can use --safemalloc and --skip-safemalloc.
Now skip-safemalloc is default (ie, we only do checking of memory overrun during free()) to speed up tests.
client/client_priv.h:
Added OPT_FLUSH_TABLES
client/mysqlcheck.c:
Added option --flush to mysqlcheck.c to run a 'flush tables' between each check to keep down memory usage.
mysql-test/mysql-test-run.pl:
Always run tests with --loose-skip-safemysqld for higher speed
sql/mysqld.cc:
Changed '--safemalloc' options so that one can use --safemalloc and --skip-safemalloc.
Now skip-safemalloc is default (ie, we only do checking of memory overrun during free()) to speed up tests
sql/sql_parse.cc:
Fixed old bug: 'show status' now shows memory usage when compiled with safemalloc.
storage/archive/archive_reader.c:
Changed all malloc() calls to use my_malloc()/my_free()
Added checks of malloc() calls.
storage/archive/ha_archive.cc:
Detect failure if init_archive_reader() and return errno. This fixed assert crash in my_seek().
Changed all malloc() calls to use my_malloc()/my_free()
mysql-test/suite/maria/t/maria3.test:
Fix when compiling with safemalloc
storage/maria/ha_maria.cc:
Fix that MAX_FILE_SIZE is not limited on 32 bit machines.
This test case was failing on 5.5 and trunk for two reasons.
1) It waited for the "Waiting for table level lock" process
state while this state was renamed "Waiting for table
metadata lock" with the introduction of MDL in 5.5.
2) SET GLOBAL query_cache_size= 100000; gave a warning since
query_cache_size is supposed to be multiples of 1024.
This patch fixes these two issues and re-enables the test case.
RESULT CONSISTED OF MORE THAN ONE ROW
MySQL converts incorrect DATEs and DATETIMEs to '0000-00-00' on
insertion by default. This means that this sequence is possible:
CREATE TABLE t1(date_notnull DATE NOT NULL);
INSERT INTO t1 values (NULL);
SELECT * FROM t1;
0000-00-00
At the same time, ODBC drivers do not (or at least did not in the
90's) understand the DATE and DATETIME value '0000-00-00'. Thus,
to be able to query for the value 0000-00-00 it was decided in
MySQL 4.x (or maybe even before that) that for the special case
of DATE/DATETIME NOT NULL columns, the query "SELECT ... WHERE
date_notnull IS NULL" should return rows with date_notnull ==
'0000-00-00'. This is documented misbehavior that we do not want
to change.
The hack used to make MySQL return these rows is to convert
"date_notnull IS NULL" to "date_notnull = 0". This is, however,
only done if the table date_notnull belongs to is not an inner
table of an outer join. The rationale for this seems to be that
if there is no join match for the row in the outer table,
null-complemented rows would otherwise not be returned because
the null-complemented DATE value is actually NULL. On the other
hand, this means that the "return rows with 0000-00-00 when the
query asks for IS NULL"-hack is not in effect for outer joins.
In this bug, we have a LEFT JOIN that does not misbehave like
the documentation says it should. The fix is to rewrite
"date_notnull IS NULL" to "date_notnull IS NULL OR
date_notnull = 0"
if dealing with an OUTER JOIN, otherwise
"date_notnull IS NULL" to "date_notnull = 0"
as was done before.
Note:
The bug was originally reported as different result on first
and second execution of SP. The reason was that during first
execution the query was correctly rewritten to an inner join
due to a null-rejecting predicate. On second execution the
"IS NULL" -> "= 0" rewrite was done because there was no outer
join. The real problem, though, was incorrect date/datetime
IS NULL handling for OUTER JOINs.
mysql-test/r/type_datetime.result:
Add test for BUG#12561818
mysql-test/t/type_datetime.test:
Add test for BUG#12561818
sql/sql_select.cc:
Special handling of NULL for DATE/DATETIME NOT NULL columns:
In the case of outer join,
"date_notnull IS NULL"
is now rewritten to
"date_notnull IS NULL OR date_notnull = 0"
SYNTAX TRIGGERS IN ANY WAY
Table with triggers which were using deprecated (5.0-only) syntax became
unavailable for any DML and DDL after upgrade to 5.1 version of server.
Attempt to execute any statement on such a table resulted in parsing
error reported. Since this included DROP TRIGGER and DROP TABLE
statements (actually, the latter was allowed but was not functioning
properly for such tables) it was impossible to fix the problem without
manual operations on .TRG and .TRN files in data directory.
The problem was that failure to parse trigger body (due to 5.0-only
syntax) when opening trigger file for a table prevented the table
from being open. This made all operations on the table impossible
(except DROP TABLE which due to peculiarity in its implementation
dropped the table but left trigger files around).
This patch solves this problem by silencing error which occurs when
we parse trigger body during table open. Error message is preserved
for the future use and table is marked as having a broken trigger.
We also try to analyze parse tree to recover trigger name, which
will be needed in order to drop the broken trigger. DML statements
which invoke triggers on the table marked as having broken trigger
are prohibited and emit saved error message. The same happens for
DDL which change triggers except DROP TRIGGER and DROP TABLE which
try their best to do what was requested. Table becomes no longer
marked as having broken trigger when last such trigger is dropped.
mysql-test/r/trigger-compat.result:
Add results for test case for bug#45235
mysql-test/t/trigger-compat.test:
Add test case for bug#45235.
sql/sp_head.cc:
Added protection against MEM_ROOT double restoring to
sp_head::restore_thd_mem_root() method. Since this
method can be sometimes called twice during parsing
of stored routine (the first time during normal flow
of parsing, and the second time when a syntax error
is detected) we need to shortcut execution of the
method to avoid damaging MEM_ROOT by the second
consecutive call to this method.
sql/sql_trigger.cc:
Added error handler Deprecated_trigger_syntax_handler to
catch non-OOM errors during parsing of trigger body.
Added handling of parse errors into method
Table_triggers_list::check_n_load().
sql/sql_trigger.h:
Added new members to handle broken triggers and error messages.
The function generate_derived_keys did not take into account the fact
that the last element in the array of keyuses could be just a barrier
element. In some cases it could lead to a crash of the server.
Also fixed a couple of other bugs in generate_derived_keys: the inner
loop in the body of if this function did not change the cycle variables
properly.