diff --git a/mysql-test/r/show_check.result b/mysql-test/r/show_check.result index c8ea9d79a13..d707ebaeba5 100644 --- a/mysql-test/r/show_check.result +++ b/mysql-test/r/show_check.result @@ -1198,7 +1198,7 @@ CREATE DATABASE mysqltest1; use mysqltest1; CREATE TABLE t1(колонка1 INT); ----> Dumping mysqltest1 to show_check.mysqltest1.sql +---> Dumping mysqltest1 to outfile1 DROP DATABASE mysqltest1; diff --git a/mysql-test/t/mysql.test b/mysql-test/t/mysql.test index 40e87ee1cb0..7e970d5b104 100644 --- a/mysql-test/t/mysql.test +++ b/mysql-test/t/mysql.test @@ -98,35 +98,43 @@ drop table t1; # Bug #20432: mysql client interprets commands in comments # +--let $file = $MYSQLTEST_VARDIR/tmp/bug20432.sql + # if the client sees the 'use' within the comment, we haven't fixed ---exec echo "/*" > $MYSQLTEST_VARDIR/tmp/bug20432.sql ---exec echo "use" >> $MYSQLTEST_VARDIR/tmp/bug20432.sql ---exec echo "*/" >> $MYSQLTEST_VARDIR/tmp/bug20432.sql ---exec $MYSQL < $MYSQLTEST_VARDIR/tmp/bug20432.sql 2>&1 +--exec echo "/*" > $file +--exec echo "use" >> $file +--exec echo "*/" >> $file +--exec $MYSQL < $file 2>&1 # SQL can have embedded comments => workie ---exec echo "select /*" > $MYSQLTEST_VARDIR/tmp/bug20432.sql ---exec echo "use" >> $MYSQLTEST_VARDIR/tmp/bug20432.sql ---exec echo "*/ 1" >> $MYSQLTEST_VARDIR/tmp/bug20432.sql ---exec $MYSQL < $MYSQLTEST_VARDIR/tmp/bug20432.sql 2>&1 +--exec echo "select /*" > $file +--exec echo "use" >> $file +--exec echo "*/ 1" >> $file +--exec $MYSQL < $file 2>&1 # client commands on the other hand must be at BOL => error ---exec echo "/*" > $MYSQLTEST_VARDIR/tmp/bug20432.sql ---exec echo "xxx" >> $MYSQLTEST_VARDIR/tmp/bug20432.sql ---exec echo "*/ use" >> $MYSQLTEST_VARDIR/tmp/bug20432.sql +--exec echo "/*" > $file +--exec echo "xxx" >> $file +--exec echo "*/ use" >> $file --error 1 ---exec $MYSQL < $MYSQLTEST_VARDIR/tmp/bug20432.sql 2>&1 +--exec $MYSQL < $file 2>&1 # client comment recognized, but parameter missing => error ---exec echo "use" > $MYSQLTEST_VARDIR/tmp/bug20432.sql ---exec $MYSQL < $MYSQLTEST_VARDIR/tmp/bug20432.sql 2>&1 +--exec echo "use" > $file +--exec $MYSQL < $file 2>&1 + +--remove_file $file # # Bug #20328: mysql client interprets commands in comments # ---exec $MYSQL -e "help" > $MYSQLTEST_VARDIR/tmp/bug20328_1.result ---exec $MYSQL -e "help " > $MYSQLTEST_VARDIR/tmp/bug20328_2.result ---diff_files $MYSQLTEST_VARDIR/tmp/bug20328_1.result $MYSQLTEST_VARDIR/tmp/bug20328_2.result +--let $file1 = $MYSQLTEST_VARDIR/tmp/bug20328_1.result +--let $file2 = $MYSQLTEST_VARDIR/tmp/bug20328_2.result +--exec $MYSQL -e "help" > $file1 +--exec $MYSQL -e "help " > $file2 +--diff_files $file1 $file2 +--remove_file $file1 +--remove_file $file2 # # Bug #19216: Client crashes on long SELECT @@ -152,13 +160,15 @@ EOF # # Bug #20103: Escaping with backslash does not work # ---exec echo "SET SQL_MODE = 'NO_BACKSLASH_ESCAPES';" > $MYSQLTEST_VARDIR/tmp/bug20103.sql ---exec echo "SELECT '\';" >> $MYSQLTEST_VARDIR/tmp/bug20103.sql ---exec $MYSQL < $MYSQLTEST_VARDIR/tmp/bug20103.sql 2>&1 +--let $file = $MYSQLTEST_VARDIR/tmp/bug20103.sql +--exec echo "SET SQL_MODE = 'NO_BACKSLASH_ESCAPES';" > $file +--exec echo "SELECT '\';" >> $file +--exec $MYSQL < $file 2>&1 ---exec echo "SET SQL_MODE = '';" > $MYSQLTEST_VARDIR/tmp/bug20103.sql ---exec echo "SELECT '\';';" >> $MYSQLTEST_VARDIR/tmp/bug20103.sql ---exec $MYSQL < $MYSQLTEST_VARDIR/tmp/bug20103.sql 2>&1 +--exec echo "SET SQL_MODE = '';" > $file +--exec echo "SELECT '\';';" >> $file +--exec $MYSQL < $file 2>&1 +--remove_file $file # # Bug#17583: mysql drops connection when stdout is not writable diff --git a/mysql-test/t/mysqldump-compat.test b/mysql-test/t/mysqldump-compat.test index 848d66cc728..9a830b16f26 100644 --- a/mysql-test/t/mysqldump-compat.test +++ b/mysql-test/t/mysqldump-compat.test @@ -5,9 +5,13 @@ # Bug #30126: semicolon before closing */ in /*!... CREATE DATABASE ;*/ # +--let $file = $MYSQLTEST_VARDIR/tmp/bug30126.sql + CREATE DATABASE mysqldump_30126; USE mysqldump_30126; CREATE TABLE t1 (c1 int); ---exec $MYSQL_DUMP --add-drop-database mysqldump_30126 > $MYSQLTEST_VARDIR/tmp/bug30126.sql ---exec $MYSQL mysqldump_30126 < $MYSQLTEST_VARDIR/tmp/bug30126.sql +--exec $MYSQL_DUMP --add-drop-database mysqldump_30126 > $file +--exec $MYSQL mysqldump_30126 < $file DROP DATABASE mysqldump_30126; + +--remove_file $file diff --git a/mysql-test/t/mysqltest.test b/mysql-test/t/mysqltest.test index 142381e4c71..6689a805c5a 100644 --- a/mysql-test/t/mysqltest.test +++ b/mysql-test/t/mysqltest.test @@ -1463,7 +1463,7 @@ select "this will be executed"; remove_file $MYSQLTEST_VARDIR/tmp/zero_length_file.result; --error 0,1 -remove_file $MYSQLTEST_VARDIR/log/zero_length_file.reject; +remove_file $MYSQLTEST_VARDIR/tmp/zero_length_file.reject; --error 0,1 remove_file $MYSQL_TEST_DIR/r/zero_length_file.reject; diff --git a/mysql-test/t/show_check.test b/mysql-test/t/show_check.test index 116298a9c80..e960dbddf02 100644 --- a/mysql-test/t/show_check.test +++ b/mysql-test/t/show_check.test @@ -897,10 +897,12 @@ CREATE TABLE t1( # Check: # - Dump mysqltest1; ---echo ---echo ---> Dumping mysqltest1 to show_check.mysqltest1.sql +--let $outfile1=$MYSQLTEST_VARDIR/tmp/show_check.mysqltest1.sql ---exec $MYSQL_DUMP --default-character-set=latin1 --character-sets-dir=$CHARSETSDIR --databases mysqltest1 > $MYSQLTEST_VARDIR/tmp/show_check.mysqltest1.sql +--echo +--echo ---> Dumping mysqltest1 to outfile1 + +--exec $MYSQL_DUMP --default-character-set=latin1 --character-sets-dir=$CHARSETSDIR --databases mysqltest1 > $outfile1 # - Clean mysqltest1; @@ -915,7 +917,8 @@ DROP DATABASE mysqltest1; --echo --echo ---> Restoring mysqltest1... ---exec $MYSQL test < $MYSQLTEST_VARDIR/tmp/show_check.mysqltest1.sql +--exec $MYSQL test < $outfile1 +--remove_file $outfile1 # - Check definition of the table. diff --git a/storage/innobase/dict/dict0load.c b/storage/innobase/dict/dict0load.c index f594e64f517..65f1c9536bd 100644 --- a/storage/innobase/dict/dict0load.c +++ b/storage/innobase/dict/dict0load.c @@ -868,11 +868,11 @@ err_exit: of the error condition, since the user may want to dump data from the clustered index. However we load the foreign key information only if all indexes were loaded. */ - if (err != DB_SUCCESS && !srv_force_recovery) { - dict_mem_table_free(table); - table = NULL; - } else if (err == DB_SUCCESS) { + if (err == DB_SUCCESS) { err = dict_load_foreigns(table->name, TRUE); + } else if (!srv_force_recovery) { + dict_table_remove_from_cache(table); + table = NULL; } #if 0 if (err != DB_SUCCESS && table != NULL) { diff --git a/storage/innobase/include/rem0rec.h b/storage/innobase/include/rem0rec.h index 43ef6650e90..abc204bb583 100644 --- a/storage/innobase/include/rem0rec.h +++ b/storage/innobase/include/rem0rec.h @@ -365,8 +365,9 @@ rec_set_field_extern_bits( /*************************************************************** This is used to modify the value of an already existing field in a record. The previous value must have exactly the same size as the new value. If len -is UNIV_SQL_NULL then the field is treated as an SQL null for old-style -records. For new-style records, len must not be UNIV_SQL_NULL. */ +is UNIV_SQL_NULL then the field is treated as an SQL null. +For records in ROW_FORMAT=COMPACT (new-style records), len must not be +UNIV_SQL_NULL unless the field already is SQL null. */ UNIV_INLINE void rec_set_nth_field( @@ -375,11 +376,7 @@ rec_set_nth_field( const ulint* offsets,/* in: array returned by rec_get_offsets() */ ulint n, /* in: index number of the field */ const void* data, /* in: pointer to the data if not SQL null */ - ulint len); /* in: length of the data or UNIV_SQL_NULL. - If not SQL null, must have the same - length as the previous value. - If SQL null, previous value must be - SQL null. */ + ulint len); /* in: length of the data or UNIV_SQL_NULL */ /************************************************************** The following function returns the data size of an old-style physical record, that is the sum of field lengths. SQL null fields diff --git a/storage/innobase/include/rem0rec.ic b/storage/innobase/include/rem0rec.ic index 5a4a0a0b5df..d91fb4c4391 100644 --- a/storage/innobase/include/rem0rec.ic +++ b/storage/innobase/include/rem0rec.ic @@ -1219,8 +1219,9 @@ rec_get_nth_field_size( /*************************************************************** This is used to modify the value of an already existing field in a record. The previous value must have exactly the same size as the new value. If len -is UNIV_SQL_NULL then the field is treated as an SQL null for old-style -records. For new-style records, len must not be UNIV_SQL_NULL. */ +is UNIV_SQL_NULL then the field is treated as an SQL null. +For records in ROW_FORMAT=COMPACT (new-style records), len must not be +UNIV_SQL_NULL unless the field already is SQL null. */ UNIV_INLINE void rec_set_nth_field( @@ -1230,11 +1231,7 @@ rec_set_nth_field( ulint n, /* in: index number of the field */ const void* data, /* in: pointer to the data if not SQL null */ - ulint len) /* in: length of the data or UNIV_SQL_NULL. - If not SQL null, must have the same - length as the previous value. - If SQL null, previous value must be - SQL null. */ + ulint len) /* in: length of the data or UNIV_SQL_NULL */ { byte* data2; ulint len2; @@ -1242,9 +1239,11 @@ rec_set_nth_field( ut_ad(rec); ut_ad(rec_offs_validate(rec, NULL, offsets)); - if (len == UNIV_SQL_NULL) { - ut_ad(!rec_offs_comp(offsets)); - rec_set_nth_field_sql_null(rec, n); + if (UNIV_UNLIKELY(len == UNIV_SQL_NULL)) { + if (!rec_offs_nth_sql_null(offsets, n)) { + ut_a(!rec_offs_comp(offsets)); + rec_set_nth_field_sql_null(rec, n); + } return; } diff --git a/storage/innobase/include/trx0roll.h b/storage/innobase/include/trx0roll.h index 25546430ba0..c1eca3d5753 100644 --- a/storage/innobase/include/trx0roll.h +++ b/storage/innobase/include/trx0roll.h @@ -15,6 +15,8 @@ Created 3/26/1996 Heikki Tuuri #include "mtr0mtr.h" #include "trx0sys.h" +#define trx_roll_free_all_savepoints(s) trx_roll_savepoints_free((s), NULL) + /*********************************************************************** Returns a transaction savepoint taken at this point in time. */ @@ -237,7 +239,17 @@ trx_release_savepoint_for_mysql( const char* savepoint_name); /* in: savepoint name */ /*********************************************************************** -Frees savepoint structs. */ +Frees a single savepoint struct. */ + +void +trx_roll_savepoint_free( +/*=====================*/ + trx_t* trx, /* in: transaction handle */ + trx_named_savept_t* savep); /* in: savepoint to free */ + +/*********************************************************************** +Frees savepoint structs starting from savep, if savep == NULL then +free all savepoints. */ void trx_roll_savepoints_free( diff --git a/storage/innobase/lock/lock0lock.c b/storage/innobase/lock/lock0lock.c index 173d074cb82..d9bc8ba09e4 100644 --- a/storage/innobase/lock/lock0lock.c +++ b/storage/innobase/lock/lock0lock.c @@ -681,7 +681,10 @@ lock_is_table_exclusive( lock_t* lock; ibool ok = FALSE; - ut_ad(table && trx); + ut_ad(table); + ut_ad(trx); + + lock_mutex_enter_kernel(); for (lock = UT_LIST_GET_FIRST(table->locks); lock; @@ -689,7 +692,7 @@ lock_is_table_exclusive( if (lock->trx != trx) { /* A lock on the table is held by some other transaction. */ - return(FALSE); + goto not_ok; } if (!(lock_get_type(lock) & LOCK_TABLE)) { @@ -706,11 +709,16 @@ lock_is_table_exclusive( auto_increment lock. */ break; default: +not_ok: /* Other table locks than LOCK_IX are not allowed. */ - return(FALSE); + ok = FALSE; + goto func_exit; } } +func_exit: + lock_mutex_exit_kernel(); + return(ok); } @@ -3664,6 +3672,7 @@ lock_table_has_to_wait_in_queue( dict_table_t* table; lock_t* lock; + ut_ad(mutex_own(&kernel_mutex)); ut_ad(lock_get_wait(wait_lock)); table = wait_lock->un_member.tab_lock.table; diff --git a/storage/innobase/trx/trx0roll.c b/storage/innobase/trx/trx0roll.c index 91dcf035f96..8934fe87c7e 100644 --- a/storage/innobase/trx/trx0roll.c +++ b/storage/innobase/trx/trx0roll.c @@ -185,7 +185,25 @@ trx_rollback_last_sql_stat_for_mysql( } /*********************************************************************** -Frees savepoint structs. */ +Frees a single savepoint struct. */ + +void +trx_roll_savepoint_free( +/*=====================*/ + trx_t* trx, /* in: transaction handle */ + trx_named_savept_t* savep) /* in: savepoint to free */ +{ + ut_a(savep != NULL); + ut_a(UT_LIST_GET_LEN(trx->trx_savepoints) > 0); + + UT_LIST_REMOVE(trx_savepoints, trx->trx_savepoints, savep); + mem_free(savep->name); + mem_free(savep); +} + +/*********************************************************************** +Frees savepoint structs starting from savep, if savep == NULL then +free all savepoints. */ void trx_roll_savepoints_free( @@ -206,9 +224,7 @@ trx_roll_savepoints_free( while (savep != NULL) { next_savep = UT_LIST_GET_NEXT(trx_savepoints, savep); - UT_LIST_REMOVE(trx_savepoints, trx->trx_savepoints, savep); - mem_free(savep->name); - mem_free(savep); + trx_roll_savepoint_free(trx, savep); savep = next_savep; } @@ -343,8 +359,8 @@ trx_savepoint_for_mysql( } /*********************************************************************** -Releases a named savepoint. Savepoints which -were set after this savepoint are deleted. */ +Releases only the named savepoint. Savepoints which were set after this +savepoint are left as is. */ ulint trx_release_savepoint_for_mysql( @@ -360,31 +376,16 @@ trx_release_savepoint_for_mysql( savep = UT_LIST_GET_FIRST(trx->trx_savepoints); + /* Search for the savepoint by name and free if found. */ while (savep != NULL) { if (0 == ut_strcmp(savep->name, savepoint_name)) { - /* Found */ - break; + trx_roll_savepoint_free(trx, savep); + return(DB_SUCCESS); } savep = UT_LIST_GET_NEXT(trx_savepoints, savep); } - if (savep == NULL) { - - return(DB_NO_SAVEPOINT); - } - - /* We can now free all savepoints strictly later than this one */ - - trx_roll_savepoints_free(trx, savep); - - /* Now we can free this savepoint too */ - - UT_LIST_REMOVE(trx_savepoints, trx->trx_savepoints, savep); - - mem_free(savep->name); - mem_free(savep); - - return(DB_SUCCESS); + return(DB_NO_SAVEPOINT); } /*********************************************************************** diff --git a/storage/innobase/trx/trx0trx.c b/storage/innobase/trx/trx0trx.c index 1fceaa3562c..43456865903 100644 --- a/storage/innobase/trx/trx0trx.c +++ b/storage/innobase/trx/trx0trx.c @@ -930,8 +930,8 @@ trx_commit_off_kernel( mutex_enter(&kernel_mutex); } - /* Free savepoints */ - trx_roll_savepoints_free(trx, NULL); + /* Free all savepoints */ + trx_roll_free_all_savepoints(trx); trx->conc_state = TRX_NOT_STARTED; trx->rseg = NULL;