List:Commits« Previous MessageNext Message »
From:marko.makela Date:May 2 2012 11:04am
Subject:bzr push into mysql-trunk-wl5854 branch (marko.makela:3759 to 3761) WL#5854
View as plain text  
 3761 Marko Mäkelä	2012-05-02
      WL#5854 phase 1: MODIFY...NULL for ROW_FORMAT=REDUNDANT
      
      check_if_supported_inplace_alter(): Allow ALTER_COLUMN_NULLABLE for
      ROW_FORMAT=REDUNDANT tables.
      
      innobase_set_nullable(): Allow a column to be set NULL in
      a ROW_FORMAT=REDUNDANT table.
      
      commit_inplace_alter_table(): Invoke innobase_set_nullable() when needed.

    added:
      mysql-test/suite/innodb/r/innodb-alter-nullable.result
      mysql-test/suite/innodb/t/innodb-alter-nullable.test
    modified:
      storage/innobase/handler/handler0alter.cc
 3760 Marko Mäkelä	2012-05-02
      Branch mysql-trunk-wl5854 from mysql-trunk.

    modified:
      .bzr-mysql/default.conf
 3759 Andrei Elkin	2012-04-30
      Bug#14018843 - FAULTY LOGICS IN MTS_DEBUG_CONCURRENT_ACCESS HANDLING
      
      Introduced to verify MTS concurrent behavior `mts_debug_concurrent_access'
      debug flag was unnecessaliry checked by IO thread which leads to a hang like. 
      
         http://pb2.no.oracle.com/web.py?template=mysql_show_test_failure&search=yes&push_id=3396783&test_id=3400389&test_run=rpl_binlog-debug-big&test_suite=rpl&test_case=rpl_mts_debug
      
      Fixed with excluding other than MTS worker threads 
      from checking the debug flag.
      
      One-liner fixes suppressing a warning in rpl_filter_tables_not_exist is piggybacked.
     @ mysql-test/suite/rpl/r/rpl_filter_tables_not_exist.result
        results got updated.
     @ mysql-test/suite/rpl/t/rpl_filter_tables_not_exist.test
        a necessary unsafe suppression on the master side is added.

    modified:
      mysql-test/suite/rpl/r/rpl_filter_tables_not_exist.result
      mysql-test/suite/rpl/t/rpl_filter_tables_not_exist.test
      sql/rpl_info_table.cc
=== modified file '.bzr-mysql/default.conf'
--- a/.bzr-mysql/default.conf	revid:andrei.elkin@oracle.com-20120430161426-810vqz82xvp2c9dy
+++ b/.bzr-mysql/default.conf	revid:marko.makela@stripped5852-0rnowlt6pnlscfmp
@@ -1,4 +1,4 @@
 [MYSQL]
 post_commit_to = "commits@stripped"
 post_push_to = "commits@stripped"
-tree_name = "mysql-trunk"
+tree_name = "mysql-trunk-wl5854"

=== added file 'mysql-test/suite/innodb/r/innodb-alter-nullable.result'
--- a/mysql-test/suite/innodb/r/innodb-alter-nullable.result	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/innodb/r/innodb-alter-nullable.result	revid:marko.makela@stripped852-0rnowlt6pnlscfmp
@@ -0,0 +1,58 @@
+CREATE TABLE tr (c1 INT PRIMARY KEY, c2 INT NOT NULL, c3 INT)
+ENGINE=InnoDB ROW_FORMAT=REDUNDANT;
+CREATE TABLE tc (c1 INT PRIMARY KEY, c2 INT NOT NULL, c3 INT)
+ENGINE=InnoDB;
+ALTER TABLE tr CHANGE c1 c1 INT NULL FIRST, ALGORITHM=INPLACE;
+ALTER TABLE tc CHANGE c1 c1 INT NULL FIRST, ALGORITHM=INPLACE;
+ALTER TABLE tr MODIFY c3 INT NOT NULL, ALGORITHM=INPLACE;
+ERROR 42000: This version of MySQL doesn't yet support 'ALTER TABLE tr MODIFY c3 INT NOT NULL, ALGORITHM=INPLACE'
+ALTER TABLE tc MODIFY c3 INT NOT NULL, ALGORITHM=INPLACE;
+ERROR 42000: This version of MySQL doesn't yet support 'ALTER TABLE tc MODIFY c3 INT NOT NULL, ALGORITHM=INPLACE'
+ALTER TABLE tr CHANGE c2 c2 INT, CHANGE c2 c2 INT NOT NULL;
+ERROR 42S22: Unknown column 'c2' in 'tr'
+ALTER TABLE tr MODIFY c2 INT, MODIFY c2 INT NOT NULL;
+ERROR 42S22: Unknown column 'c2' in 'tr'
+ALTER TABLE tr MODIFY c2 INT UNSIGNED, MODIFY c2 INT;
+ERROR 42S22: Unknown column 'c2' in 'tr'
+ALTER TABLE tr MODIFY c2 CHAR(1) NOT NULL, MODIFY c2 INT NOT NULL;
+ERROR 42S22: Unknown column 'c2' in 'tr'
+ALTER TABLE tr CHANGE c2 c2 INT NOT NULL, ALGORITHM=INPLACE;
+ALTER TABLE tc CHANGE c2 c2 INT NOT NULL, ALGORITHM=INPLACE;
+ALTER TABLE tr MODIFY c2 INT NOT NULL, ALGORITHM=INPLACE;
+ALTER TABLE tc MODIFY c2 INT NOT NULL, ALGORITHM=INPLACE;
+ALTER TABLE tr MODIFY c2 INT, ALGORITHM=INPLACE;
+ALTER TABLE tc MODIFY c2 INT, ALGORITHM=INPLACE;
+ERROR 42000: This version of MySQL doesn't yet support 'ALTER TABLE tc MODIFY c2 INT, ALGORITHM=INPLACE'
+ALTER TABLE tr MODIFY c2 INT NULL, ALGORITHM=INPLACE;
+ALTER TABLE tc MODIFY c2 INT NULL, ALGORITHM=INPLACE;
+ERROR 42000: This version of MySQL doesn't yet support 'ALTER TABLE tc MODIFY c2 INT NULL, ALGORITHM=INPLACE'
+DROP TABLE tc, tr;
+CREATE TABLE tr (c1 INT PRIMARY KEY, c2 INT NOT NULL, c3 INT)
+ENGINE=InnoDB ROW_FORMAT=REDUNDANT;
+CREATE TABLE tc (c1 INT PRIMARY KEY, c2 INT NOT NULL, c3 INT)
+ENGINE=InnoDB;
+ALTER TABLE tr CHANGE c1 c1 INT NULL FIRST, ALGORITHM=INPLACE;
+ALTER TABLE tc CHANGE c1 c1 INT NULL FIRST, ALGORITHM=INPLACE;
+ALTER TABLE tr MODIFY c3 INT NOT NULL, ALGORITHM=INPLACE;
+ERROR 42000: This version of MySQL doesn't yet support 'ALTER TABLE tr MODIFY c3 INT NOT NULL, ALGORITHM=INPLACE'
+ALTER TABLE tc MODIFY c3 INT NOT NULL, ALGORITHM=INPLACE;
+ERROR 42000: This version of MySQL doesn't yet support 'ALTER TABLE tc MODIFY c3 INT NOT NULL, ALGORITHM=INPLACE'
+ALTER TABLE tr CHANGE c2 c2 INT, CHANGE c2 c2 INT NOT NULL;
+ERROR 42S22: Unknown column 'c2' in 'tr'
+ALTER TABLE tr MODIFY c2 INT, MODIFY c2 INT NOT NULL;
+ERROR 42S22: Unknown column 'c2' in 'tr'
+ALTER TABLE tr MODIFY c2 INT UNSIGNED, MODIFY c2 INT;
+ERROR 42S22: Unknown column 'c2' in 'tr'
+ALTER TABLE tr MODIFY c2 CHAR(1) NOT NULL, MODIFY c2 INT NOT NULL;
+ERROR 42S22: Unknown column 'c2' in 'tr'
+ALTER TABLE tr CHANGE c2 c2 INT NOT NULL, ALGORITHM=INPLACE;
+ALTER TABLE tc CHANGE c2 c2 INT NOT NULL, ALGORITHM=INPLACE;
+ALTER TABLE tr MODIFY c2 INT NOT NULL, ALGORITHM=INPLACE;
+ALTER TABLE tc MODIFY c2 INT NOT NULL, ALGORITHM=INPLACE;
+ALTER TABLE tr MODIFY c2 INT, ALGORITHM=INPLACE;
+ALTER TABLE tc MODIFY c2 INT, ALGORITHM=INPLACE;
+ERROR 42000: This version of MySQL doesn't yet support 'ALTER TABLE tc MODIFY c2 INT, ALGORITHM=INPLACE'
+ALTER TABLE tr MODIFY c2 INT NULL, ALGORITHM=INPLACE;
+ALTER TABLE tc MODIFY c2 INT NULL, ALGORITHM=INPLACE;
+ERROR 42000: This version of MySQL doesn't yet support 'ALTER TABLE tc MODIFY c2 INT NULL, ALGORITHM=INPLACE'
+DROP TABLE tc, tr;

=== added file 'mysql-test/suite/innodb/t/innodb-alter-nullable.test'
--- a/mysql-test/suite/innodb/t/innodb-alter-nullable.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/innodb/t/innodb-alter-nullable.test	revid:marko.makela@stripped
@@ -0,0 +1,104 @@
+--source include/have_innodb.inc
+
+# WL#5854 part 1: MODIFY...NULL
+# First, this is only implemented for ROW_FORMAT=REDUNDANT tables,
+# because that one does not change the storage format of B-tree records.
+#
+# Implementing the rest of WL#5854 will require a multi-versioned
+# data dictionary (multiple SYS_TABLES and clustered index for the table).
+
+CREATE TABLE tr (c1 INT PRIMARY KEY, c2 INT NOT NULL, c3 INT)
+ENGINE=InnoDB ROW_FORMAT=REDUNDANT;
+
+CREATE TABLE tc (c1 INT PRIMARY KEY, c2 INT NOT NULL, c3 INT)
+ENGINE=InnoDB;
+
+# This one will be a no-op.
+# MySQL should perhaps issue an error, because it refuses to modify
+# the PRIMARY KEY column c1 from NOT NULL to NULL.
+ALTER TABLE tr CHANGE c1 c1 INT NULL FIRST, ALGORITHM=INPLACE;
+ALTER TABLE tc CHANGE c1 c1 INT NULL FIRST, ALGORITHM=INPLACE;
+
+--error ER_NOT_SUPPORTED_YET
+ALTER TABLE tr MODIFY c3 INT NOT NULL, ALGORITHM=INPLACE;
+--error ER_NOT_SUPPORTED_YET
+ALTER TABLE tc MODIFY c3 INT NOT NULL, ALGORITHM=INPLACE;
+
+# Request some conflicting changes for a single column.
+--error ER_BAD_FIELD_ERROR
+ALTER TABLE tr CHANGE c2 c2 INT, CHANGE c2 c2 INT NOT NULL;
+--error ER_BAD_FIELD_ERROR
+ALTER TABLE tr MODIFY c2 INT, MODIFY c2 INT NOT NULL;
+--error ER_BAD_FIELD_ERROR
+ALTER TABLE tr MODIFY c2 INT UNSIGNED, MODIFY c2 INT;
+--error ER_BAD_FIELD_ERROR
+ALTER TABLE tr MODIFY c2 CHAR(1) NOT NULL, MODIFY c2 INT NOT NULL;
+
+# No-ops.
+ALTER TABLE tr CHANGE c2 c2 INT NOT NULL, ALGORITHM=INPLACE;
+ALTER TABLE tc CHANGE c2 c2 INT NOT NULL, ALGORITHM=INPLACE;
+ALTER TABLE tr MODIFY c2 INT NOT NULL, ALGORITHM=INPLACE;
+ALTER TABLE tc MODIFY c2 INT NOT NULL, ALGORITHM=INPLACE;
+
+ALTER TABLE tr MODIFY c2 INT, ALGORITHM=INPLACE;
+--error ER_NOT_SUPPORTED_YET
+ALTER TABLE tc MODIFY c2 INT, ALGORITHM=INPLACE;
+
+ALTER TABLE tr MODIFY c2 INT NULL, ALGORITHM=INPLACE;
+--error ER_NOT_SUPPORTED_YET
+ALTER TABLE tc MODIFY c2 INT NULL, ALGORITHM=INPLACE;
+
+DROP TABLE tc, tr;
+--source include/have_innodb.inc
+
+# WL#5854 part 1: MODIFY...NULL
+# This is only implemented for ROW_FORMAT=REDUNDANT tables,
+# because that one does not change the storage format of B-tree records.
+#
+# Implementing the change for later InnoDB formats would require a
+# multi-versioned data dictionary (and multi-versioned SYS_COLUMNS at that).
+# Implementing ADD COLUMN and DROP COLUMN only needs a multi-versioned
+# clustered index, and simple "append" versioning of SYS_COLUMNS.
+
+CREATE TABLE tr (c1 INT PRIMARY KEY, c2 INT NOT NULL, c3 INT)
+ENGINE=InnoDB ROW_FORMAT=REDUNDANT;
+
+CREATE TABLE tc (c1 INT PRIMARY KEY, c2 INT NOT NULL, c3 INT)
+ENGINE=InnoDB;
+
+# This one will be a no-op.
+# MySQL should perhaps issue an error, because it refuses to modify
+# the PRIMARY KEY column c1 from NOT NULL to NULL.
+ALTER TABLE tr CHANGE c1 c1 INT NULL FIRST, ALGORITHM=INPLACE;
+ALTER TABLE tc CHANGE c1 c1 INT NULL FIRST, ALGORITHM=INPLACE;
+
+--error ER_NOT_SUPPORTED_YET
+ALTER TABLE tr MODIFY c3 INT NOT NULL, ALGORITHM=INPLACE;
+--error ER_NOT_SUPPORTED_YET
+ALTER TABLE tc MODIFY c3 INT NOT NULL, ALGORITHM=INPLACE;
+
+# Request some conflicting changes for a single column.
+--error ER_BAD_FIELD_ERROR
+ALTER TABLE tr CHANGE c2 c2 INT, CHANGE c2 c2 INT NOT NULL;
+--error ER_BAD_FIELD_ERROR
+ALTER TABLE tr MODIFY c2 INT, MODIFY c2 INT NOT NULL;
+--error ER_BAD_FIELD_ERROR
+ALTER TABLE tr MODIFY c2 INT UNSIGNED, MODIFY c2 INT;
+--error ER_BAD_FIELD_ERROR
+ALTER TABLE tr MODIFY c2 CHAR(1) NOT NULL, MODIFY c2 INT NOT NULL;
+
+# No-ops.
+ALTER TABLE tr CHANGE c2 c2 INT NOT NULL, ALGORITHM=INPLACE;
+ALTER TABLE tc CHANGE c2 c2 INT NOT NULL, ALGORITHM=INPLACE;
+ALTER TABLE tr MODIFY c2 INT NOT NULL, ALGORITHM=INPLACE;
+ALTER TABLE tc MODIFY c2 INT NOT NULL, ALGORITHM=INPLACE;
+
+ALTER TABLE tr MODIFY c2 INT, ALGORITHM=INPLACE;
+--error ER_NOT_SUPPORTED_YET
+ALTER TABLE tc MODIFY c2 INT, ALGORITHM=INPLACE;
+
+ALTER TABLE tr MODIFY c2 INT NULL, ALGORITHM=INPLACE;
+--error ER_NOT_SUPPORTED_YET
+ALTER TABLE tc MODIFY c2 INT NULL, ALGORITHM=INPLACE;
+
+DROP TABLE tc, tr;

=== modified file 'storage/innobase/handler/handler0alter.cc'
--- a/storage/innobase/handler/handler0alter.cc	revid:andrei.elkin@stripped0430161426-810vqz82xvp2c9dy
+++ b/storage/innobase/handler/handler0alter.cc	revid:marko.makela@stripped105852-0rnowlt6pnlscfmp
@@ -55,9 +55,15 @@ static const Alter_inplace_info::HA_ALTE
 	| Alter_inplace_info::ALTER_RENAME
 	| Alter_inplace_info::CHANGE_CREATE_OPTION;
 
+/** Operations for altering the record format */
+static const Alter_inplace_info::HA_ALTER_FLAGS INNOBASE_INPLACE_REFORMAT
+	= 0;
+
 /** Operations that InnoDB can perform online */
 static const Alter_inplace_info::HA_ALTER_FLAGS INNOBASE_ONLINE_OPERATIONS
 	= INNOBASE_INPLACE_IGNORE
+	| INNOBASE_INPLACE_REFORMAT
+	| Alter_inplace_info::ALTER_COLUMN_NULLABLE
 	| Alter_inplace_info::ADD_INDEX
 	| Alter_inplace_info::DROP_INDEX
 	| Alter_inplace_info::ADD_UNIQUE_INDEX
@@ -199,6 +205,22 @@ ha_innobase::check_if_supported_inplace_
 		DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED);
 	}
 
+	if ((ha_alter_info->handler_flags
+	     & Alter_inplace_info::ALTER_COLUMN_NULLABLE)
+	    && dict_table_is_comp(prebuilt->table)) {
+		/* For now, we only support changing a column from
+		NOT NULL to NULL when ROW_FORMAT=REDUNDANT. */
+		DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED);
+	}
+
+	if (!(ha_alter_info->handler_flags &
+	      ~(INNOBASE_INPLACE_REFORMAT
+		| Alter_inplace_info::ALTER_COLUMN_NULLABLE))) {
+		/* These operations will actually be performed during
+		ha_innobase::commit_inplace_alter_table(). */
+		DBUG_RETURN(HA_ALTER_INPLACE_NO_LOCK);
+	}
+
 	update_thd();
 	trx_search_latch_release_if_reserved(prebuilt->trx);
 
@@ -254,11 +276,6 @@ ha_innobase::check_if_supported_inplace_
 
 	prebuilt->trx->will_lock++;
 
-	/* TODO: Reject if creating a fulltext index and there is an
-	incompatible FTS_DOC_ID or FTS_DOC_ID_INDEX, either in the table
-	or in the ha_alter_info. We can and should reject this before
-	locking the data dictionary. */
-
 	/* Creating the primary key requires an exclusive lock on the
 	table during the whole copying operation. */
 	if (ha_alter_info->handler_flags & Alter_inplace_info::ADD_PK_INDEX) {
@@ -2743,6 +2760,79 @@ err_exit:
 	DBUG_RETURN(false);
 }
 
+/** Allow a column to be set NULL in a ROW_FORMAT=REDUNDANT table.
+@param table_share	the TABLE_SHARE
+@param prebuilt		the prebuilt struct
+@param trx		data dictionary transaction
+@param nth_col		0-based index of the column
+@retval true		Failure
+@retval false		Success */
+static __attribute__((nonnull, warn_unused_result))
+bool
+innobase_set_nullable(
+/*==================*/
+	const TABLE_SHARE*	table_share,
+	row_prebuilt_t*		prebuilt,
+	trx_t*			trx,
+	ulint			nth_col)
+{
+	pars_info_t*	info;
+	dberr_t		error;
+	dict_col_t*	col;
+
+	DBUG_ENTER("innobase_set_nullable");
+	DBUG_ASSERT(trx_get_dict_operation(trx) == TRX_DICT_OP_INDEX);
+	ut_ad(trx->dict_operation_lock_mode == RW_X_LATCH);
+	ut_ad(mutex_own(&dict_sys->mutex));
+#ifdef UNIV_SYNC_DEBUG
+	ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_EX));
+#endif /* UNIV_SYNC_DEBUG */
+
+	/* The NULL flag is stored in SYS_COLUMNS, not in SYS_INDEXES
+	(or SYS_FIELDS). ADD COLUMN and DROP COLUMN will only
+	multi-version the clustered index, not the table columns.
+	Thus, we can only change the NULLable flag of a column in
+	tables where the change does not affect the B-tree record
+	format (ROW_FORMAT=REDUNDANT). */
+	ut_ad(!dict_table_is_comp(prebuilt->table));
+	col = dict_table_get_nth_col(prebuilt->table, nth_col);
+
+	ut_ad(col->prtype & DATA_NOT_NULL);
+
+	info = pars_info_create();
+
+	pars_info_add_ull_literal(info, "tableid", prebuilt->table->id);
+	pars_info_add_int4_literal(info, "nth", nth_col);
+	pars_info_add_int4_literal(info, "prtype",
+				   col->prtype & ~DATA_NOT_NULL);
+
+	trx->op_info = "setting column nullable in SYS_COLUMNS";
+
+	error = que_eval_sql(
+		info,
+		"PROCEDURE NULLABLE_SYS_COLUMNS_PROC () IS\n"
+		"BEGIN\n"
+		"UPDATE SYS_COLUMNS SET PRTYPE=:prtype\n"
+		"WHERE TABLE_ID=:tableid AND POS=:nth;\n"
+		"END;\n",
+		FALSE, trx);
+
+	DBUG_EXECUTE_IF("ib_set_nullable_error",
+			error = DB_OUT_OF_FILE_SPACE;);
+
+	trx->op_info = "";
+
+	if (error != DB_SUCCESS) {
+		my_error_innodb(error, table_share->table_name.str, 0);
+		trx->error_state = DB_SUCCESS;
+		DBUG_RETURN(true);
+	}
+
+	/* Set the column nullable in the data dictionary cache. */
+	col->prtype &= ~DATA_NOT_NULL;
+	DBUG_RETURN(false);
+}
+
 /** Commit or rollback the changes made during
 prepare_inplace_alter_table() and inplace_alter_table() inside
 the storage engine. Note that the allowed level of concurrency
@@ -2960,6 +3050,39 @@ processed_field:
 		}
 	}
 
+	if (err == 0 && !new_clustered
+	    && (ha_alter_info->handler_flags
+		& Alter_inplace_info::ALTER_COLUMN_NULLABLE)) {
+		DBUG_ASSERT(!dict_table_is_comp(prebuilt->table));
+
+		List_iterator_fast<Create_field> cf_it;
+		ulint				col = 0;
+
+		for (Field** fp = table->field;
+		     err == 0 && col < dict_table_get_n_cols(prebuilt->table);
+		     fp++, col++) {
+			cf_it.init(ha_alter_info->alter_info->create_list);
+			while (Create_field* cf = cf_it++) {
+				if (cf->field == *fp
+				    && ((cf->flags ^ (*fp)->flags)
+					& NOT_NULL_FLAG)) {
+					DBUG_ASSERT((*fp)->flags
+						    & NOT_NULL_FLAG);
+					if (innobase_set_nullable(
+						    table_share,
+						    prebuilt, trx, col)) {
+						err = -1;
+					}
+				}
+			}
+		}
+	}
+
+	if (err == 0 && !new_clustered
+	    && (ha_alter_info->handler_flags & INNOBASE_INPLACE_REFORMAT)) {
+		ut_error;
+	}
+
 	if (err == 0) {
 trx_commit:
 		trx_commit_for_mysql(trx);

No bundle (reason: useless for push emails).
Thread
bzr push into mysql-trunk-wl5854 branch (marko.makela:3759 to 3761) WL#5854marko.makela2 May