List:Commits« Previous MessageNext Message »
From:marko.makela Date:May 31 2012 7:23pm
Subject:bzr push into mysql-trunk-wl6255 branch (marko.makela:3920 to 3921) WL#6255
View as plain text  
 3921 Marko Mäkelä	2012-05-31
      WL#6255 On-line ALTER TABLE...MODIFY...NULL
      
      Support Alter_inplace_info::ALTER_COLUMN_NULLABLE.
      
      row_log_table_apply_convert_mrec(): Convert the DATA_NOT_NULL flag.
      Add a TODO comment for MODIFY...NOT NULL.
      
      row_merge_read_clustered_index(): Add an nullable[] array in addition
      to nonnull[]. Adjust the DATA_NOT_NULL flag as needed.

    modified:
      mysql-test/r/alter_table.result
      mysql-test/suite/innodb/r/innodb-table-online.result
      mysql-test/suite/innodb/t/innodb-table-online.test
      storage/innobase/handler/handler0alter.cc
      storage/innobase/row/row0log.cc
      storage/innobase/row/row0merge.cc
 3920 Marko Mäkelä	2012-05-31
      Fix race condition in InnoDB transaction commit flushing.
      
      trx_flush_log_if_needed_low(), trx_flush_log_if_needed():
      Refactored common code. Read srv_flush_log_at_trx_commit only once.
      Previously, a race condition could occur if srv_flush_log_at_trx_commit
      changed during the checks.
      
      trx_commit(), trx_prepare(), trx_commit_complete_for_mysql():
      Invoke trx_flush_log_if_needed() instead of duplicating the code.

    modified:
      storage/innobase/include/trx0trx.h
      storage/innobase/trx/trx0trx.cc
=== modified file 'mysql-test/r/alter_table.result'
--- a/mysql-test/r/alter_table.result	revid:marko.makela@strippedm-20120531182212-u1l372oy77ggvl6a
+++ b/mysql-test/r/alter_table.result	revid:marko.makela@stripped36-hjso1xpadewdu19a
@@ -1770,8 +1770,8 @@ ALTER TABLE tm1 MODIFY COLUMN c INT NOT
 affected rows: 2
 info: Records: 2  Duplicates: 0  Warnings: 0
 ALTER TABLE ti1 MODIFY COLUMN c INT NULL;
-affected rows: 2
-info: Records: 2  Duplicates: 0  Warnings: 0
+affected rows: 0
+info: Records: 0  Duplicates: 0  Warnings: 0
 ALTER TABLE tm1 MODIFY COLUMN c INT NULL;
 affected rows: 2
 info: Records: 2  Duplicates: 0  Warnings: 0

=== modified file 'mysql-test/suite/innodb/r/innodb-table-online.result'
--- a/mysql-test/suite/innodb/r/innodb-table-online.result	revid:marko.makela@stripped
+++ b/mysql-test/suite/innodb/r/innodb-table-online.result	revid:marko.makela@stripped
@@ -3,7 +3,7 @@ call mtr.add_suppression("InnoDB: Error:
 call mtr.add_suppression("MySQL is trying to open a table handle but the .ibd file for");
 SET @global_innodb_file_per_table_orig = @@global.innodb_file_per_table;
 SET GLOBAL innodb_file_per_table = on;
-CREATE TABLE t1 (c1 INT PRIMARY KEY, c2 INT NOT NULL, c3 TEXT)
+CREATE TABLE t1 (c1 INT PRIMARY KEY, c2 INT NOT NULL, c3 TEXT NOT NULL)
 ENGINE = InnoDB;
 INSERT INTO t1 VALUES (1,1,''), (2,2,''), (3,3,''), (4,4,''), (5,5,'');
 SET GLOBAL innodb_monitor_enable = module_ddl;
@@ -42,7 +42,7 @@ Table	Create Table
 t1	CREATE TABLE `t1` (
   `c1` int(11) NOT NULL,
   `c2` int(11) NOT NULL,
-  `c3` text,
+  `c3` text NOT NULL,
   PRIMARY KEY (`c1`)
 ) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=REDUNDANT
 BEGIN;
@@ -63,7 +63,7 @@ Table	Create Table
 t1	CREATE TABLE `t1` (
   `c1` int(11) NOT NULL,
   `c2` int(11) NOT NULL,
-  `c3` text,
+  `c3` text NOT NULL,
   UNIQUE KEY `c2` (`c2`),
   UNIQUE KEY `c2_2` (`c2`)
 ) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=COMPACT
@@ -74,7 +74,7 @@ Table	Create Table
 t1	CREATE TABLE `t1` (
   `c1` int(11) NOT NULL,
   `c2` int(11) NOT NULL,
-  `c3` text,
+  `c3` text NOT NULL,
   UNIQUE KEY `c2` (`c2`),
   UNIQUE KEY `c2_2` (`c2`)
 ) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=COMPACT
@@ -96,7 +96,7 @@ Table	Create Table
 t1	CREATE TABLE `t1` (
   `c1` int(11) NOT NULL,
   `c2` int(11) NOT NULL,
-  `c3` text,
+  `c3` text NOT NULL,
   UNIQUE KEY `c2` (`c2`),
   UNIQUE KEY `c2_2` (`c2`)
 ) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=COMPACT
@@ -155,7 +155,7 @@ Table	Create Table
 t1	CREATE TABLE `t1` (
   `c1` int(11) NOT NULL,
   `c2` int(11) NOT NULL,
-  `c3` text,
+  `c3` text NOT NULL,
   PRIMARY KEY (`c1`)
 ) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=COMPACT
 SET DEBUG_SYNC = 'row_log_table_apply1_before SIGNAL rebuilt2 WAIT_FOR dml2_done';
@@ -214,7 +214,8 @@ ALTER TABLE t1 ADD PRIMARY KEY(c22f), CH
 ERROR 42000: Multiple primary key defined
 ALTER TABLE t1 DROP PRIMARY KEY, ADD PRIMARY KEY(c22f), CHANGE c2 c22f INT;
 ERROR 23000: Duplicate entry '5' for key 'PRIMARY'
-ALTER TABLE t1 DROP PRIMARY KEY, ADD PRIMARY KEY(c1,c22f), CHANGE c2 c22f INT;
+ALTER TABLE t1 DROP PRIMARY KEY, ADD PRIMARY KEY(c1,c22f), CHANGE c2 c22f INT,
+CHANGE c3 c3 TEXT NULL;
 SET DEBUG_SYNC = 'now WAIT_FOR rebuilt3';
 SELECT name, count FROM INFORMATION_SCHEMA.INNODB_METRICS WHERE subsystem = 'ddl';
 name	count

=== modified file 'mysql-test/suite/innodb/t/innodb-table-online.test'
--- a/mysql-test/suite/innodb/t/innodb-table-online.test	revid:marko.makela@stripped72oy77ggvl6a
+++ b/mysql-test/suite/innodb/t/innodb-table-online.test	revid:marko.makela@stripped-hjso1xpadewdu19a
@@ -16,7 +16,7 @@ SET GLOBAL innodb_file_per_table = on;
 # Save the initial number of concurrent sessions.
 --source include/count_sessions.inc
 
-CREATE TABLE t1 (c1 INT PRIMARY KEY, c2 INT NOT NULL, c3 TEXT)
+CREATE TABLE t1 (c1 INT PRIMARY KEY, c2 INT NOT NULL, c3 TEXT NOT NULL)
 ENGINE = InnoDB;
 INSERT INTO t1 VALUES (1,1,''), (2,2,''), (3,3,''), (4,4,''), (5,5,'');
 
@@ -220,7 +220,8 @@ ALTER TABLE t1 ADD PRIMARY KEY(c22f), CH
 --error ER_DUP_ENTRY
 ALTER TABLE t1 DROP PRIMARY KEY, ADD PRIMARY KEY(c22f), CHANGE c2 c22f INT;
 --send
-ALTER TABLE t1 DROP PRIMARY KEY, ADD PRIMARY KEY(c1,c22f), CHANGE c2 c22f INT;
+ALTER TABLE t1 DROP PRIMARY KEY, ADD PRIMARY KEY(c1,c22f), CHANGE c2 c22f INT,
+CHANGE c3 c3 TEXT NULL;
 
 connection default;
 SET DEBUG_SYNC = 'now WAIT_FOR rebuilt3';

=== modified file 'storage/innobase/handler/handler0alter.cc'
--- a/storage/innobase/handler/handler0alter.cc	revid:marko.makela@stripped-u1l372oy77ggvl6a
+++ b/storage/innobase/handler/handler0alter.cc	revid:marko.makela@strippedo1xpadewdu19a
@@ -56,8 +56,8 @@ static const Alter_inplace_info::HA_ALTE
 	= Alter_inplace_info::ADD_PK_INDEX
 	| Alter_inplace_info::DROP_PK_INDEX
 	| Alter_inplace_info::CHANGE_CREATE_OPTION
-	/*
 	| Alter_inplace_info::ALTER_COLUMN_NULLABLE
+	/*
 	| Alter_inplace_info::ALTER_COLUMN_NOT_NULLABLE
 	| Alter_inplace_info::ALTER_COLUMN_TYPE
 	| Alter_inplace_info::ALTER_COLUMN_EQUAL_PACK_LENGTH,

=== modified file 'storage/innobase/row/row0log.cc'
--- a/storage/innobase/row/row0log.cc	revid:marko.makela@oracle.com-20120531182212-u1l372oy77ggvl6a
+++ b/storage/innobase/row/row0log.cc	revid:marko.makela@stripped92236-hjso1xpadewdu19a
@@ -1045,6 +1045,40 @@ row_log_table_apply_convert_mrec(
 			data = rec_get_nth_field(mrec, offsets, i, &len);
 			dfield_set_data(dfield, data, len);
 		}
+
+		ut_ad(dict_col_type_assert_equal(col,
+						 dfield_get_type(dfield)));
+
+		/* See if any columns were changed to NULL or NOT NULL. */
+		/* TODO: adjust for ADD COLUMN, DROP COLUMN */
+		if (col_no >= dict_table_get_n_cols(new_table)) {
+			continue;
+		}
+
+		const dict_col_t*	new_col
+			= dict_table_get_nth_col(new_table, col_no);
+		ut_ad(new_col->mtype == col->mtype);
+		/* Assert that prtype matches except for nullability. */
+		ut_ad(!((new_col->prtype ^ col->prtype) & ~DATA_NOT_NULL));
+		ut_ad(!((new_col->prtype ^ dfield_get_type(dfield)->prtype)
+			& ~DATA_NOT_NULL));
+
+		if (new_col->prtype == col->prtype) {
+			continue;
+		}
+
+		if ((new_col->prtype & DATA_NOT_NULL)
+		    && dfield_is_null(dfield)) {
+			/* We got a NULL value in a NOT NULL field. */
+			ut_ad(0);/* TODO: ALTER_COLUMN_NOT_NULLABLE */
+			return(NULL);
+		}
+
+		/* Adjust the DATA_NOT_NULL flag in the parsed row. */
+		dfield_get_type(dfield)->prtype = new_col->prtype;
+
+		ut_ad(dict_col_type_assert_equal(new_col,
+						 dfield_get_type(dfield)));
 	}
 
 	/* TODO: convert row to new_table->cols, in case columns are

=== modified file 'storage/innobase/row/row0merge.cc'
--- a/storage/innobase/row/row0merge.cc	revid:marko.makela@oracle.com-20120531182212-u1l372oy77ggvl6a
+++ b/storage/innobase/row/row0merge.cc	revid:marko.makela@stripped192236-hjso1xpadewdu19a
@@ -1270,6 +1270,9 @@ row_merge_read_clustered_index(
 	ulint			n_nonnull = 0;	/* number of columns
 						changed to NOT NULL */
 	ulint*			nonnull = NULL;	/* NOT NULL columns */
+	ulint			n_nullable = 0;	/* number of columns
+						changed to NULL */
+	ulint*			nullable = NULL;/* NULLable columns */
 	dict_index_t*		fts_index = NULL;/* FTS index */
 	doc_id_t		doc_id = 0;
 	doc_id_t		max_doc_id = 0;
@@ -1346,25 +1349,30 @@ row_merge_read_clustered_index(
 		}
 
 		nonnull = static_cast<ulint*>(
-			mem_alloc(n_cols * sizeof *nonnull));
+			mem_alloc(2 * n_cols * sizeof *nonnull));
+		nullable = nonnull + n_cols;
 
 		for (ulint i = 0; i < n_cols; i++) {
-			if (dict_table_get_nth_col(old_table, i)->prtype
-			    & DATA_NOT_NULL) {
+			/* TODO: adjust for ADD COLUMN, DROP COLUMN */
+			ulint	old_nonnull	= DATA_NOT_NULL
+				& dict_table_get_nth_col(old_table, i)->prtype;
+			ulint	new_nonnull	= DATA_NOT_NULL
+				& dict_table_get_nth_col(new_table, i)->prtype;
 
+			if (old_nonnull == new_nonnull) {
 				continue;
 			}
 
-			if (dict_table_get_nth_col(new_table, i)->prtype
-			    & DATA_NOT_NULL) {
-
+			if (old_nonnull) {
+				nullable[n_nullable++] = i;
+			} else {
 				nonnull[n_nonnull++] = i;
 			}
 		}
 
-		if (!n_nonnull) {
+		if (!n_nonnull && !n_nullable) {
 			mem_free(nonnull);
-			nonnull = NULL;
+			nonnull = nullable = NULL;
 		}
 	}
 
@@ -1439,7 +1447,7 @@ row_merge_read_clustered_index(
 				row = NULL;
 				mtr_commit(&mtr);
 				mem_heap_free(row_heap);
-				if (UNIV_LIKELY_NULL(nonnull)) {
+				if (nonnull) {
 					mem_free(nonnull);
 				}
 				goto write_buffers;
@@ -1536,7 +1544,7 @@ row_merge_read_clustered_index(
 			dtype_t*	field_type
 				= dfield_get_type(field);
 
-			ut_a(!(field_type->prtype & DATA_NOT_NULL));
+			ut_ad(!(field_type->prtype & DATA_NOT_NULL));
 
 			if (dfield_is_null(field)) {
 				err = DB_PRIMARY_KEY_IS_NULL;
@@ -1547,6 +1555,13 @@ row_merge_read_clustered_index(
 			field_type->prtype |= DATA_NOT_NULL;
 		}
 
+		for (ulint i = 0; i < n_nullable; i++) {
+			dtype_t*	field_type
+				= dfield_get_type(&row->fields[nullable[i]]);
+			ut_ad((field_type->prtype & DATA_NOT_NULL));
+			field_type->prtype &= ~DATA_NOT_NULL;
+		}
+
 		/* Get the next Doc ID */
 		if (add_doc_id) {
 			doc_id++;
@@ -1683,7 +1698,7 @@ func_exit:
 	mtr_commit(&mtr);
 	mem_heap_free(row_heap);
 
-	if (UNIV_LIKELY_NULL(nonnull)) {
+	if (nonnull) {
 		mem_free(nonnull);
 	}
 

No bundle (reason: useless for push emails).
Thread
bzr push into mysql-trunk-wl6255 branch (marko.makela:3920 to 3921) WL#6255marko.makela31 May