List:Commits« Previous MessageNext Message »
From:marko.makela Date:June 5 2012 2:33pm
Subject:bzr push into mysql-trunk-wl6255 branch (marko.makela:3940 to 3944) WL#6255
View as plain text  
 3944 Marko Mäkelä	2012-06-05
      WL#6255 ALTER_ADD_COLUMN (ALTER TABLE ... ADD COLUMN)
      
      innobase_build_col_map_add(): Convert a default value of an ADD COLUMN
      to the InnoDB format.
      
      ha_innobase_inplace_ctx(): Add add_cols.
      
      innobase_build_col_map(), row_merge_build_indexes(),
      row_log_table_apply(), row_build(), row_log_table_apply_convert_mrec(),
      row_log_table_apply_insert(), row_log_table_apply_update(),
      row_log_table_apply_op(), row_log_table_apply_ops(),
      row_merge_read_clustered_index(): Add the parameter add_cols.
      
      prepare_inplace_alter_table_dict(): When rebuilding a table, make it a
      *.ibd file if the original table was in an *.ibd file, or if
      innodb_file_per_table=1.

    modified:
      mysql-test/suite/innodb/r/innodb-create-options.result
      mysql-test/suite/innodb/r/innodb.result
      mysql-test/suite/innodb/t/innodb-create-options.test
      storage/innobase/handler/handler0alter.cc
      storage/innobase/include/row0log.h
      storage/innobase/include/row0merge.h
      storage/innobase/include/row0row.h
      storage/innobase/row/row0log.cc
      storage/innobase/row/row0merge.cc
      storage/innobase/row/row0row.cc
      storage/innobase/row/row0undo.cc
      storage/innobase/row/row0upd.cc
      storage/innobase/row/row0vers.cc
 3943 Marko Mäkelä	2012-06-05
      Add some const qualifiers to Field::is_null methods.

    modified:
      sql/field.h
 3942 Marko Mäkelä	2012-06-05
      Fix a typo in a test name.

    renamed:
      mysql-test/suite/innodb_fts/r/innodb_fts_mutiple_index.result => mysql-test/suite/innodb_fts/r/innodb_fts_multiple_index.result
      mysql-test/suite/innodb_fts/t/innodb_fts_mutiple_index.test => mysql-test/suite/innodb_fts/t/innodb_fts_multiple_index.test
 3941 Marko Mäkelä	2012-06-05
      mem_heap_free_heap_top(): Enable validation checks in UNIV_DEBUG.

    modified:
      storage/innobase/include/mem0mem.ic
 3940 Marko Mäkelä	2012-06-05
      WL#6255 DROP COLUMN: Test FOREIGN KEY checks.

    modified:
      mysql-test/suite/innodb/r/innodb-index.result
      mysql-test/suite/innodb/t/innodb-index.test
=== modified file 'mysql-test/suite/innodb/r/innodb-create-options.result'
--- a/mysql-test/suite/innodb/r/innodb-create-options.result	revid:marko.makela@stripped
+++ b/mysql-test/suite/innodb/r/innodb-create-options.result	revid:marko.makela@strippeds91t
@@ -320,12 +320,19 @@ DROP TABLE IF EXISTS t1;
 CREATE TABLE t1 ( i INT ) ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=4;
 SET GLOBAL innodb_file_format=Antelope;
 ALTER TABLE t1 ADD COLUMN f1 INT;
-ERROR HY000: Can't create table '#sql-temporary' (errno: 1478)
-SHOW WARNINGS;
-Level	Code	Message
+Warnings:
 Warning	1478	InnoDB: KEY_BLOCK_SIZE requires innodb_file_format > Antelope.
+Warning	1478	InnoDB: ignoring KEY_BLOCK_SIZE=4.
 Warning	1478	InnoDB: ROW_FORMAT=COMPRESSED requires innodb_file_format > Antelope.
-Error	1005	Can't create table '#sql-temporary' (errno: 1478)
+Warning	1478	InnoDB: assuming ROW_FORMAT=COMPACT.
+SHOW CREATE TABLE t1;
+Table	Create Table
+t1	CREATE TABLE `t1` (
+  `i` int(11) DEFAULT NULL,
+  `f1` int(11) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=4
+SHOW WARNINGS;
+Level	Code	Message
 ALTER TABLE t1 ROW_FORMAT=DEFAULT KEY_BLOCK_SIZE=0;
 SHOW WARNINGS;
 Level	Code	Message
@@ -415,12 +422,8 @@ DROP TABLE IF EXISTS t1;
 CREATE TABLE t1 ( i INT ) ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=4;
 SET GLOBAL innodb_file_per_table=OFF;
 ALTER TABLE t1 ADD COLUMN f1 INT;
-ERROR HY000: Can't create table '#sql-temporary' (errno: 1478)
 SHOW WARNINGS;
 Level	Code	Message
-Warning	1478	InnoDB: KEY_BLOCK_SIZE requires innodb_file_per_table.
-Warning	1478	InnoDB: ROW_FORMAT=COMPRESSED requires innodb_file_per_table.
-Error	1005	Can't create table '#sql-temporary' (errno: 1478)
 ALTER TABLE t1 ROW_FORMAT=DEFAULT KEY_BLOCK_SIZE=0;
 SHOW WARNINGS;
 Level	Code	Message
@@ -804,20 +807,11 @@ TABLE_NAME	ROW_FORMAT	CREATE_OPTIONS
 t1	Compressed	row_format=COMPRESSED KEY_BLOCK_SIZE=2
 SET GLOBAL innodb_file_per_table=OFF;
 ALTER TABLE t1 ADD COLUMN f1 INT;
-Warnings:
-Warning	1478	InnoDB: KEY_BLOCK_SIZE requires innodb_file_per_table.
-Warning	1478	InnoDB: ignoring KEY_BLOCK_SIZE=2.
-Warning	1478	InnoDB: ROW_FORMAT=COMPRESSED requires innodb_file_per_table.
-Warning	1478	InnoDB: assuming ROW_FORMAT=COMPACT.
 SHOW WARNINGS;
 Level	Code	Message
-Warning	1478	InnoDB: KEY_BLOCK_SIZE requires innodb_file_per_table.
-Warning	1478	InnoDB: ignoring KEY_BLOCK_SIZE=2.
-Warning	1478	InnoDB: ROW_FORMAT=COMPRESSED requires innodb_file_per_table.
-Warning	1478	InnoDB: assuming ROW_FORMAT=COMPACT.
 SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1';
 TABLE_NAME	ROW_FORMAT	CREATE_OPTIONS
-t1	Compact	row_format=COMPRESSED KEY_BLOCK_SIZE=2
+t1	Compressed	row_format=COMPRESSED KEY_BLOCK_SIZE=2
 SET GLOBAL innodb_file_per_table=ON;
 ALTER TABLE t1 ADD COLUMN f2 INT;
 SHOW WARNINGS;
@@ -834,16 +828,11 @@ TABLE_NAME	ROW_FORMAT	CREATE_OPTIONS
 t1	Dynamic	row_format=DYNAMIC
 SET GLOBAL innodb_file_per_table=OFF;
 ALTER TABLE t1 ADD COLUMN f1 INT;
-Warnings:
-Warning	1478	InnoDB: ROW_FORMAT=DYNAMIC requires innodb_file_per_table.
-Warning	1478	InnoDB: assuming ROW_FORMAT=COMPACT.
 SHOW WARNINGS;
 Level	Code	Message
-Warning	1478	InnoDB: ROW_FORMAT=DYNAMIC requires innodb_file_per_table.
-Warning	1478	InnoDB: assuming ROW_FORMAT=COMPACT.
 SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1';
 TABLE_NAME	ROW_FORMAT	CREATE_OPTIONS
-t1	Compact	row_format=DYNAMIC
+t1	Dynamic	row_format=DYNAMIC
 SET GLOBAL innodb_file_per_table=ON;
 ALTER TABLE t1 ADD COLUMN f2 INT;
 SHOW WARNINGS;

=== modified file 'mysql-test/suite/innodb/r/innodb.result'
--- a/mysql-test/suite/innodb/r/innodb.result	revid:marko.makela@oracle.com-20120605072828-xyp11q7yo2zm6xpy
+++ b/mysql-test/suite/innodb/r/innodb.result	revid:marko.makela@stripped-20120605143232-ned9z2rxx931s91t
@@ -1679,7 +1679,7 @@ variable_value - @innodb_rows_deleted_or
 71
 SELECT variable_value - @innodb_rows_inserted_orig FROM information_schema.global_status WHERE LOWER(variable_name) = 'innodb_rows_inserted';
 variable_value - @innodb_rows_inserted_orig
-1043
+1006
 SELECT variable_value - @innodb_rows_updated_orig FROM information_schema.global_status WHERE LOWER(variable_name) = 'innodb_rows_updated';
 variable_value - @innodb_rows_updated_orig
 866

=== modified file 'mysql-test/suite/innodb/t/innodb-create-options.test'
--- a/mysql-test/suite/innodb/t/innodb-create-options.test	revid:marko.makela@stripped
+++ b/mysql-test/suite/innodb/t/innodb-create-options.test	revid:marko.makela@stripped931s91t
@@ -97,10 +97,8 @@ SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTI
 ALTER TABLE t1 ROW_FORMAT=DEFAULT KEY_BLOCK_SIZE=0;
 SHOW WARNINGS;
 SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1';
---replace_regex /'[^']*test\.#sql-[0-9a-f_]*'/'#sql-temporary'/
 --error ER_ILLEGAL_HA_CREATE_OPTION
 ALTER TABLE t1 ROW_FORMAT=FIXED KEY_BLOCK_SIZE=0;
---replace_regex /'[^']*test\.#sql-[0-9a-f_]*'/'#sql-temporary'/
 SHOW WARNINGS;
 SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1';
 
@@ -136,25 +134,17 @@ SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTI
 --echo # Test 3) StrictMode=ON, ALTER with each ROW_FORMAT & a valid non-zero KEY_BLOCK_SIZE
 DROP TABLE IF EXISTS t1;
 CREATE TABLE t1 ( i INT );
---replace_regex /'[^']*test\.#sql-[0-9a-f_]*'/'#sql-temporary'/
 --error ER_ILLEGAL_HA_CREATE_OPTION
 ALTER TABLE t1 ROW_FORMAT=FIXED KEY_BLOCK_SIZE=1;
---replace_regex /'[^']*test\.#sql-[0-9a-f_]*'/'#sql-temporary'/
 SHOW WARNINGS;
---replace_regex /'[^']*test\.#sql-[0-9a-f_]*'/'#sql-temporary'/
 --error ER_ILLEGAL_HA_CREATE_OPTION
 ALTER TABLE t1 ROW_FORMAT=COMPACT KEY_BLOCK_SIZE=2;
---replace_regex /'[^']*test\.#sql-[0-9a-f_]*'/'#sql-temporary'/
 SHOW WARNINGS;
---replace_regex /'[^']*test\.#sql-[0-9a-f_]*'/'#sql-temporary'/
 --error ER_ILLEGAL_HA_CREATE_OPTION
 ALTER TABLE t1 ROW_FORMAT=DYNAMIC KEY_BLOCK_SIZE=4;
---replace_regex /'[^']*test\.#sql-[0-9a-f_]*'/'#sql-temporary'/
 SHOW WARNINGS;
---replace_regex /'[^']*test\.#sql-[0-9a-f_]*'/'#sql-temporary'/
 --error ER_ILLEGAL_HA_CREATE_OPTION
 ALTER TABLE t1 ROW_FORMAT=REDUNDANT KEY_BLOCK_SIZE=2;
---replace_regex /'[^']*test\.#sql-[0-9a-f_]*'/'#sql-temporary'/
 SHOW WARNINGS;
 ALTER TABLE t1 ROW_FORMAT=DEFAULT KEY_BLOCK_SIZE=1;
 SHOW WARNINGS;
@@ -168,26 +158,20 @@ SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTI
 DROP TABLE IF EXISTS t1;
 CREATE TABLE t1 ( i INT ) ROW_FORMAT=COMPACT;
 SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1';
---replace_regex /'[^']*test\.#sql-[0-9a-f_]*'/'#sql-temporary'/
 --error ER_ILLEGAL_HA_CREATE_OPTION
 ALTER TABLE t1 KEY_BLOCK_SIZE=2;
---replace_regex /'[^']*test\.#sql-[0-9a-f_]*'/'#sql-temporary'/
 SHOW WARNINGS;
 ALTER TABLE t1 ROW_FORMAT=REDUNDANT;
 SHOW WARNINGS;
 SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1';
---replace_regex /'[^']*test\.#sql-[0-9a-f_]*'/'#sql-temporary'/
 --error ER_ILLEGAL_HA_CREATE_OPTION
 ALTER TABLE t1 KEY_BLOCK_SIZE=4;
---replace_regex /'[^']*test\.#sql-[0-9a-f_]*'/'#sql-temporary'/
 SHOW WARNINGS;
 ALTER TABLE t1 ROW_FORMAT=DYNAMIC;
 SHOW WARNINGS;
 SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_NAME = 't1';
---replace_regex /'[^']*test\.#sql-[0-9a-f_]*'/'#sql-temporary'/
 --error ER_ILLEGAL_HA_CREATE_OPTION
 ALTER TABLE t1 KEY_BLOCK_SIZE=2;
---replace_regex /'[^']*test\.#sql-[0-9a-f_]*'/'#sql-temporary'/
 SHOW WARNINGS;
 ALTER TABLE t1 ROW_FORMAT=COMPRESSED;
 SHOW WARNINGS;
@@ -208,20 +192,14 @@ CREATE TABLE t1 ( i INT ) KEY_BLOCK_SIZE
 SHOW CREATE TABLE t1;
 ALTER TABLE t1 ADD COLUMN f1 INT;
 SHOW CREATE TABLE t1;
---replace_regex /'[^']*test\.#sql-[0-9a-f_]*'/'#sql-temporary'/
 --error ER_ILLEGAL_HA_CREATE_OPTION
 ALTER TABLE t1 ROW_FORMAT=COMPACT;
---replace_regex /'[^']*test\.#sql-[0-9a-f_]*'/'#sql-temporary'/
 SHOW WARNINGS;
---replace_regex /'[^']*test\.#sql-[0-9a-f_]*'/'#sql-temporary'/
 --error ER_ILLEGAL_HA_CREATE_OPTION
 ALTER TABLE t1 ROW_FORMAT=REDUNDANT;
---replace_regex /'[^']*test\.#sql-[0-9a-f_]*'/'#sql-temporary'/
 SHOW WARNINGS;
---replace_regex /'[^']*test\.#sql-[0-9a-f_]*'/'#sql-temporary'/
 --error ER_ILLEGAL_HA_CREATE_OPTION
 ALTER TABLE t1 ROW_FORMAT=DYNAMIC;
---replace_regex /'[^']*test\.#sql-[0-9a-f_]*'/'#sql-temporary'/
 SHOW WARNINGS;
 ALTER TABLE t1 ROW_FORMAT=COMPRESSED;
 SHOW WARNINGS;
@@ -263,29 +241,21 @@ SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTI
 DROP TABLE IF EXISTS t1;
 CREATE TABLE t1 ( i INT ) ROW_FORMAT=DEFAULT;
 SHOW WARNINGS;
---replace_regex /'[^']*test\.#sql-[0-9a-f_]*'/'#sql-temporary'/
 --error ER_ILLEGAL_HA_CREATE_OPTION
 ALTER TABLE t1 KEY_BLOCK_SIZE=2;
---replace_regex /'[^']*test\.#sql-[0-9a-f_]*'/'#sql-temporary'/
 SHOW WARNINGS;
---replace_regex /'[^']*test\.#sql-[0-9a-f_]*'/'#sql-temporary'/
 --error ER_ILLEGAL_HA_CREATE_OPTION
 ALTER TABLE t1 ROW_FORMAT=COMPRESSED;
---replace_regex /'[^']*test\.#sql-[0-9a-f_]*'/'#sql-temporary'/
 SHOW WARNINGS;
---replace_regex /'[^']*test\.#sql-[0-9a-f_]*'/'#sql-temporary'/
 --error ER_ILLEGAL_HA_CREATE_OPTION
 ALTER TABLE t1 ROW_FORMAT=DYNAMIC;
---replace_regex /'[^']*test\.#sql-[0-9a-f_]*'/'#sql-temporary'/
 SHOW WARNINGS;
 SET GLOBAL innodb_file_format=Barracuda;
 DROP TABLE IF EXISTS t1;
 CREATE TABLE t1 ( i INT ) ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=4;
 SET GLOBAL innodb_file_format=Antelope;
---replace_regex /'[^']*test\.#sql-[0-9a-f_]*'/'#sql-temporary'/
---error ER_CANT_CREATE_TABLE
 ALTER TABLE t1 ADD COLUMN f1 INT;
---replace_regex /'[^']*test\.#sql-[0-9a-f_]*'/'#sql-temporary'/
+SHOW CREATE TABLE t1;
 SHOW WARNINGS;
 ALTER TABLE t1 ROW_FORMAT=DEFAULT KEY_BLOCK_SIZE=0;
 SHOW WARNINGS;
@@ -318,20 +288,14 @@ SELECT TABLE_NAME,ROW_FORMAT,CREATE_OPTI
 DROP TABLE IF EXISTS t1;
 CREATE TABLE t1 ( i INT ) ROW_FORMAT=DEFAULT;
 SHOW WARNINGS;
---replace_regex /'[^']*test\.#sql-[0-9a-f_]*'/'#sql-temporary'/
 --error ER_ILLEGAL_HA_CREATE_OPTION
 ALTER TABLE t1 KEY_BLOCK_SIZE=1;
---replace_regex /'[^']*test\.#sql-[0-9a-f_]*'/'#sql-temporary'/
 SHOW WARNINGS;
---replace_regex /'[^']*test\.#sql-[0-9a-f_]*'/'#sql-temporary'/
 --error ER_ILLEGAL_HA_CREATE_OPTION
 ALTER TABLE t1 ROW_FORMAT=COMPRESSED;
---replace_regex /'[^']*test\.#sql-[0-9a-f_]*'/'#sql-temporary'/
 SHOW WARNINGS;
---replace_regex /'[^']*test\.#sql-[0-9a-f_]*'/'#sql-temporary'/
 --error ER_ILLEGAL_HA_CREATE_OPTION
 ALTER TABLE t1 ROW_FORMAT=DYNAMIC;
---replace_regex /'[^']*test\.#sql-[0-9a-f_]*'/'#sql-temporary'/
 SHOW WARNINGS;
 ALTER TABLE t1 ROW_FORMAT=COMPACT;
 SHOW WARNINGS;
@@ -346,10 +310,7 @@ SET GLOBAL innodb_file_per_table=ON;
 DROP TABLE IF EXISTS t1;
 CREATE TABLE t1 ( i INT ) ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=4;
 SET GLOBAL innodb_file_per_table=OFF;
---replace_regex /'[^']*test\.#sql-[0-9a-f_]*'/'#sql-temporary'/
---error ER_CANT_CREATE_TABLE
 ALTER TABLE t1 ADD COLUMN f1 INT;
---replace_regex /'[^']*test\.#sql-[0-9a-f_]*'/'#sql-temporary'/
 SHOW WARNINGS;
 ALTER TABLE t1 ROW_FORMAT=DEFAULT KEY_BLOCK_SIZE=0;
 SHOW WARNINGS;

=== renamed file 'mysql-test/suite/innodb_fts/r/innodb_fts_mutiple_index.result' => 'mysql-test/suite/innodb_fts/r/innodb_fts_multiple_index.result'
=== renamed file 'mysql-test/suite/innodb_fts/t/innodb_fts_mutiple_index.test' => 'mysql-test/suite/innodb_fts/t/innodb_fts_multiple_index.test'
=== modified file 'sql/field.h'
--- a/sql/field.h	revid:marko.makela@oracle.com-20120605072828-xyp11q7yo2zm6xpy
+++ b/sql/field.h	revid:marko.makela@strippeds91t
@@ -868,7 +868,7 @@ public:
   {
     return is_temporal_type_with_date_and_time(type());
   }
-  inline bool is_null(my_ptrdiff_t row_offset= 0)
+  inline bool is_null (my_ptrdiff_t row_offset= 0) const
   {
     /*
       The table may have been marked as containing only NULL values
@@ -890,16 +890,16 @@ public:
 
     return false;
   }
-  inline bool is_real_null(my_ptrdiff_t row_offset= 0)
-    { return null_ptr ? (null_ptr[row_offset] & null_bit ? 1 : 0) : 0; }
-  inline bool is_null_in_record(const uchar *record)
+  inline bool is_real_null (my_ptrdiff_t row_offset= 0) const
+    { return null_ptr && (null_ptr[row_offset] & null_bit); }
+  inline bool is_null_in_record (const uchar *record) const
   {
     if (!null_ptr)
       return 0;
     return test(record[(uint) (null_ptr -table->record[0])] &
 		null_bit);
   }
-  inline bool is_null_in_record_with_offset(my_ptrdiff_t offset)
+  inline bool is_null_in_record_with_offset (my_ptrdiff_t offset) const
   {
     if (!null_ptr)
       return 0;
@@ -909,7 +909,8 @@ public:
     { if (null_ptr) null_ptr[row_offset]|= null_bit; }
   inline void set_notnull(my_ptrdiff_t row_offset= 0)
     { if (null_ptr) null_ptr[row_offset]&= (uchar) ~null_bit; }
-  inline bool maybe_null(void) { return null_ptr != 0 || table->maybe_null; }
+  inline bool maybe_null(void) const
+    { return null_ptr != 0 || table->maybe_null; }
   /**
      Signals that this field is NULL-able.
   */

=== modified file 'storage/innobase/handler/handler0alter.cc'
--- a/storage/innobase/handler/handler0alter.cc	revid:marko.makela@stripped120605072828-xyp11q7yo2zm6xpy
+++ b/storage/innobase/handler/handler0alter.cc	revid:marko.makela@stripped05143232-ned9z2rxx931s91t
@@ -61,10 +61,10 @@ static const Alter_inplace_info::HA_ALTE
 	| Alter_inplace_info::ALTER_COLUMN_NOT_NULLABLE
 	| Alter_inplace_info::ALTER_COLUMN_ORDER
 	| Alter_inplace_info::DROP_COLUMN
+	| Alter_inplace_info::ADD_COLUMN
 	/*
 	| Alter_inplace_info::ALTER_COLUMN_TYPE
 	| Alter_inplace_info::ALTER_COLUMN_EQUAL_PACK_LENGTH
-	| Alter_inplace_info::ADD_COLUMN
 	*/
 	;
 
@@ -1761,6 +1761,8 @@ public:
 	dict_table_t*	indexed_table;
 	/** mapping of old column numbers to new ones, or NULL */
 	const ulint*	col_map;
+	/** default values of ADD COLUMN, or NULL */
+	const dtuple_t*	add_cols;
 	ha_innobase_inplace_ctx(trx_t* user_trx,
 				dict_index_t** add_arg,
 				const ulint* add_key_numbers_arg,
@@ -1775,7 +1777,8 @@ public:
 				mem_heap_t* heap_arg,
 				trx_t* trx_arg,
 				dict_table_t* indexed_table_arg,
-				const ulint* col_map_arg) :
+				const ulint* col_map_arg,
+				const dtuple_t*	add_cols_arg) :
 		inplace_alter_handler_ctx(),
 		add (add_arg), add_key_numbers (add_key_numbers_arg),
 		num_to_add (num_to_add_arg),
@@ -1784,7 +1787,7 @@ public:
 		add_fk (add_fk_arg), num_to_add_fk (num_to_add_fk_arg),
 		online (online_arg), heap (heap_arg), trx (trx_arg),
 		indexed_table (indexed_table_arg),
-		col_map (col_map_arg) {
+		col_map (col_map_arg), add_cols (add_cols_arg) {
 #ifdef UNIV_DEBUG
 		for (ulint i = 0; i < num_to_add; i++) {
 			ut_ad(!add[i]->to_be_dropped);
@@ -2045,6 +2048,35 @@ innobase_check_foreigns(
 	return(false);
 }
 
+/** Convert a default value for ADD COLUMN.
+
+@param heap	Memory heap where allocated
+@param dfield	InnoDB data field to copy to
+@param field	MySQL value for the column
+@param comp	nonzero if in compact format
+ */
+static __attribute__((nonnull))
+void
+innobase_build_col_map_add(
+/*=======================*/
+	mem_heap_t*	heap,
+	dfield_t*	dfield,
+	const Field*	field,
+	ulint		comp)
+{
+	if (field->is_real_null()) {
+		dfield_set_null(dfield);
+		return;
+	}
+
+	ulint	size	= field->pack_length();
+
+	byte*	buf	= static_cast<byte*>(mem_heap_alloc(heap, size));
+
+	row_mysql_store_col_in_innobase_format(
+		dfield, buf, TRUE, field->ptr, size, comp);
+}
+
 /** Construct the translation table for reordering, dropping or
 adding columns.
 
@@ -2053,10 +2085,11 @@ adding columns.
 @param table		MySQL table as it is before the ALTER operation
 @param new_table	InnoDB table corresponding to MySQL altered_table
 @param old_table	InnoDB table corresponding to MYSQL table
-@param heap	Memory heap where allocated
+@param add_cols		Default values for ADD COLUMN, or NULL if no ADD COLUMN
+@param heap		Memory heap where allocated
 @return	array of integers, mapping column numbers in the table
 to column numbers in altered_table */
-static __attribute__((nonnull, warn_unused_result))
+static __attribute__((nonnull(1,2,3,4,5,7), warn_unused_result))
 const ulint*
 innobase_build_col_map(
 /*===================*/
@@ -2065,6 +2098,7 @@ innobase_build_col_map(
 	const TABLE*		table,
 	const dict_table_t*	new_table,
 	const dict_table_t*	old_table,
+	dtuple_t*		add_cols,
 	mem_heap_t*		heap)
 {
 	DBUG_ENTER("innobase_build_col_map");
@@ -2074,6 +2108,10 @@ innobase_build_col_map(
 		    >= altered_table->s->fields + DATA_N_SYS_COLS);
 	DBUG_ASSERT(dict_table_get_n_cols(old_table)
 		    >= table->s->fields + DATA_N_SYS_COLS);
+	DBUG_ASSERT(!!add_cols == !!(ha_alter_info->handler_flags
+				     & Alter_inplace_info::ADD_COLUMN));
+	DBUG_ASSERT(!add_cols || dtuple_get_n_fields(add_cols)
+		    == dict_table_get_n_cols(new_table));
 
 	ulint*	col_map = static_cast<ulint*>(
 		mem_heap_alloc(heap, old_table->n_cols * sizeof *col_map));
@@ -2096,8 +2134,12 @@ innobase_build_col_map(
 				goto found_col;
 			}
 		}
+
 		/* ALTER_ADD_COLUMN */
-		ut_ad(0);//TODO
+		innobase_build_col_map_add(
+			heap, dtuple_get_nth_field(add_cols, i),
+			altered_table->s->field[i],
+			dict_table_is_comp(new_table));
 found_col:
 		i++;
 		continue;
@@ -2201,6 +2243,7 @@ prepare_inplace_alter_table_dict(
 	dberr_t			error;
 	THD*			user_thd	= user_trx->mysql_thd;
 	const ulint*		col_map;
+	dtuple_t*		add_cols;
 
 	const bool locked =
 		add_fts_doc_id
@@ -2324,7 +2367,8 @@ prepare_inplace_alter_table_dict(
 		if (!innobase_table_flags(table_name, altered_table,
 					  ha_alter_info->create_info,
 					  trx->mysql_thd,
-					  srv_file_per_table,
+					  srv_file_per_table
+					  || user_table->space != 0,
 					  &flags, &flags2)) {
 			goto new_clustered_failed;
 		}
@@ -2479,12 +2523,22 @@ col_fail:
 			goto err_exit;
 		}
 
+		if (ha_alter_info->handler_flags
+		    & Alter_inplace_info::ADD_COLUMN) {
+			add_cols = dtuple_create(
+				heap, dict_table_get_n_cols(indexed_table));
+			dict_table_copy_types(add_cols, indexed_table);
+		} else {
+			add_cols = NULL;
+		}
+
 		col_map = innobase_build_col_map(
 			ha_alter_info, altered_table, old_table,
-			indexed_table, user_table, heap);
+			indexed_table, user_table, add_cols, heap);
 	} else {
 		DBUG_ASSERT(!innobase_need_rebuild(ha_alter_info));
 		col_map = NULL;
+		add_cols = NULL;
 	}
 
 	/* Assign table_id, so that no table id of
@@ -2657,7 +2711,7 @@ error_handling:
 			drop_index, n_drop_index,
 			drop_foreign, n_drop_foreign,
 			add_foreign, n_add_foreign,
-			!locked, heap, trx, indexed_table, col_map);
+			!locked, heap, trx, indexed_table, col_map, add_cols);
 		DBUG_RETURN(false);
 	case DB_TABLESPACE_ALREADY_EXISTS:
 		my_error(ER_TABLE_EXISTS_ERROR, MYF(0), "(unknown)");
@@ -3188,7 +3242,7 @@ index_needed:
 					drop_index, n_drop_index,
 					drop_fk, n_drop_fk,
 					add_fk, n_add_fk, !locked,
-					heap, NULL, indexed_table, NULL);
+					heap, NULL, indexed_table, NULL, NULL);
 		}
 
 func_exit:
@@ -3352,7 +3406,7 @@ ok_exit:
 		prebuilt->table, ctx->indexed_table,
 		ctx->online,
 		ctx->add, ctx->add_key_numbers, ctx->num_to_add, table,
-		ctx->col_map);
+		ctx->add_cols, ctx->col_map);
 #ifndef DBUG_OFF
 oom:
 #endif /* !DBUG_OFF */
@@ -3360,7 +3414,8 @@ oom:
 	    && ctx->indexed_table != prebuilt->table) {
 		DEBUG_SYNC_C("row_log_table_apply1_before");
 		error = row_log_table_apply(
-			ctx->thr, prebuilt->table, table, ctx->col_map);
+			ctx->thr, prebuilt->table, table,
+			ctx->add_cols, ctx->col_map);
 	}
 
 	/* After an error, remove all those index definitions
@@ -3946,7 +4001,7 @@ ha_innobase::commit_inplace_alter_table(
 			DEBUG_SYNC_C("row_log_table_apply2_before");
 			error = row_log_table_apply(
 				ctx->thr, prebuilt->table, table,
-				ctx->col_map);
+				ctx->add_cols, ctx->col_map);
 
 			switch (error) {
 				KEY*	dup_key;

=== modified file 'storage/innobase/include/mem0mem.ic'
--- a/storage/innobase/include/mem0mem.ic	revid:marko.makela@stripped72828-xyp11q7yo2zm6xpy
+++ b/storage/innobase/include/mem0mem.ic	revid:marko.makela@strippedz2rxx931s91t
@@ -247,7 +247,7 @@ mem_heap_free_heap_top(
 {
 	mem_block_t*	block;
 	mem_block_t*	prev_block;
-#ifdef UNIV_MEM_DEBUG
+#if defined UNIV_MEM_DEBUG || defined UNIV_DEBUG
 	ibool		error;
 	ulint		total_size;
 	ulint		size;
@@ -255,7 +255,7 @@ mem_heap_free_heap_top(
 
 	ut_ad(mem_heap_check(heap));
 
-#ifdef UNIV_MEM_DEBUG
+#if defined UNIV_MEM_DEBUG || defined UNIV_DEBUG
 
 	/* Validate the heap and get its total allocated size */
 	mem_heap_validate_or_print(heap, NULL, FALSE, &error, &total_size,
@@ -294,9 +294,9 @@ mem_heap_free_heap_top(
 	/* Set the free field of block */
 	mem_block_set_free(block, old_top - (byte*) block);
 
-#ifdef UNIV_MEM_DEBUG
 	ut_ad(mem_block_get_start(block) <= mem_block_get_free(block));
-
+	UNIV_MEM_ASSERT_W(old_top, (byte*) block + block->len - old_top);
+#if defined UNIV_MEM_DEBUG
 	/* In the debug version erase block from top up */
 	mem_erase_buf(old_top, (byte*) block + block->len - old_top);
 
@@ -304,8 +304,6 @@ mem_heap_free_heap_top(
 	mutex_enter(&mem_hash_mutex);
 	mem_current_allocated_memory -= (total_size - size);
 	mutex_exit(&mem_hash_mutex);
-#else /* UNIV_MEM_DEBUG */
-	UNIV_MEM_ASSERT_W(old_top, (byte*) block + block->len - old_top);
 #endif /* UNIV_MEM_DEBUG */
 	UNIV_MEM_ALLOC(old_top, (byte*) block + block->len - old_top);
 

=== modified file 'storage/innobase/include/row0log.h'
--- a/storage/innobase/include/row0log.h	revid:marko.makela@stripped
+++ b/storage/innobase/include/row0log.h	revid:marko.makela@strippedom-20120605143232-ned9z2rxx931s91t
@@ -178,9 +178,12 @@ row_log_table_apply(
 				/*!< in: old table */
 	struct TABLE*	table,	/*!< in/out: MySQL table
 				(for reporting duplicates) */
+	const dtuple_t*	add_cols,
+				/*!< in: default values of
+				added columns, or NULL */
 	const ulint*	col_map)/*!< in: mapping of old column
 				numbers to new ones, or NULL */
-	__attribute__((nonnull, warn_unused_result));
+	__attribute__((nonnull(1,2,3,5), warn_unused_result));
 
 /******************************************************//**
 Get the latest transaction ID that has invoked row_log_online_op()

=== modified file 'storage/innobase/include/row0merge.h'
--- a/storage/innobase/include/row0merge.h	revid:marko.makela@stripped605072828-xyp11q7yo2zm6xpy
+++ b/storage/innobase/include/row0merge.h	revid:marko.makela@stripped-ned9z2rxx931s91t
@@ -293,6 +293,8 @@ row_merge_build_indexes(
 	struct TABLE*	table,		/*!< in/out: MySQL table, for
 					reporting erroneous key value
 					if applicable */
+	const dtuple_t*	add_cols,	/*!< in: default values of
+					added columns, or NULL */
 	const ulint*	col_map)	/*!< in: mapping of old column
 					numbers to new ones, or NULL
 					if old_table == new_table */

=== modified file 'storage/innobase/include/row0row.h'
--- a/storage/innobase/include/row0row.h	revid:marko.makela@strippedm-20120605072828-xyp11q7yo2zm6xpy
+++ b/storage/innobase/include/row0row.h	revid:marko.makela@stripped43232-ned9z2rxx931s91t
@@ -143,6 +143,9 @@ row_build(
 					consulted instead; the user
 					columns in this table should be
 					the same columns as in index->table */
+	const dtuple_t*		add_cols,
+					/*!< in: default values of
+					added columns, or NULL */
 	const ulint*		col_map,/*!< in: mapping of old column
 					numbers to new ones, or NULL */
 	row_ext_t**		ext,	/*!< out, own: cache of
@@ -150,7 +153,7 @@ row_build(
 					prefixes, or NULL */
 	mem_heap_t*		heap)	/*!< in: memory heap from which
 					the memory needed is allocated */
-	__attribute__((nonnull(2,3,8), warn_unused_result));
+	__attribute__((nonnull(2,3,9), warn_unused_result));
 /*******************************************************************//**
 Converts an index record to a typed data tuple.
 @return index entry built; does not set info_bits, and the data fields

=== modified file 'storage/innobase/row/row0log.cc'
--- a/storage/innobase/row/row0log.cc	revid:marko.makela@oracle.com-20120605072828-xyp11q7yo2zm6xpy
+++ b/storage/innobase/row/row0log.cc	revid:marko.makela@stripped0605143232-ned9z2rxx931s91t
@@ -1002,13 +1002,15 @@ row_log_table_is_rollback(
 /******************************************************//**
 Converts a log record to a table row.
 @return converted row, or NULL if the conversion fails */
-static __attribute__((nonnull, warn_unused_result))
+static __attribute__((nonnull(1,2,3,5,6,7,8), warn_unused_result))
 const dtuple_t*
 row_log_table_apply_convert_mrec(
 /*=============================*/
 	const mrec_t*		mrec,		/*!< in: merge record */
 	const dict_index_t*	index,		/*!< in: index of mrec */
 	const ulint*		offsets,	/*!< in: offsets of mrec */
+	const dtuple_t*		add_cols,	/*!< in: default values of
+						added columns, or NULL */
 	const ulint*		col_map,	/*!< in: mapping of old column
 						numbers to new ones, or NULL */
 	mem_heap_t*		heap,		/*!< in/out: memory heap */
@@ -1020,8 +1022,18 @@ row_log_table_apply_convert_mrec(
 	dtuple_t*	row;
 
 	/* This is based on row_build(). */
-	row = dtuple_create(heap, dict_table_get_n_cols(new_table));
-	dict_table_copy_types(row, new_table);
+	if (add_cols) {
+		row = dtuple_copy(add_cols, heap);
+		/* dict_table_copy_types() would set the fields to NULL */
+		for (ulint i = 0; i < dict_table_get_n_cols(new_table); i++) {
+			dict_col_copy_type(
+				dict_table_get_nth_col(new_table, i),
+				dfield_get_type(dtuple_get_nth_field(row, i)));
+		}
+	} else {
+		row = dtuple_create(heap, dict_table_get_n_cols(new_table));
+		dict_table_copy_types(row, new_table);
+	}
 
 	for (ulint i = 0; i < rec_offs_n_fields(offsets); i++) {
 		const dict_field_t*	ind_field
@@ -1166,7 +1178,7 @@ row_log_table_apply_insert_low(
 /******************************************************//**
 Replays an insert operation on a table that was rebuilt.
 @return DB_SUCCESS or error code */
-static __attribute__((nonnull, warn_unused_result))
+static __attribute__((nonnull(1,2,3,4,6,7,8,9), warn_unused_result))
 dberr_t
 row_log_table_apply_insert(
 /*=======================*/
@@ -1175,6 +1187,8 @@ row_log_table_apply_insert(
 	const ulint*		offsets,	/*!< in: offsets of mrec */
 	mem_heap_t*		offsets_heap,	/*!< in/out: memory heap
 						that can be emptied */
+	const dtuple_t*		add_cols,	/*!< in: default values of
+						added columns, or NULL */
 	const ulint*		col_map,	/*!< in: mapping of old column
 						numbers to new ones, or NULL */
 	mem_heap_t*		heap,		/*!< in/out: memory heap */
@@ -1185,7 +1199,7 @@ row_log_table_apply_insert(
 {
 	dberr_t		error;
 	const dtuple_t*	row	= row_log_table_apply_convert_mrec(
-		mrec, dup->index, offsets, col_map, heap, new_table,
+		mrec, dup->index, offsets, add_cols, col_map, heap, new_table,
 		&error);
 
 	ut_ad(!row == (error != DB_SUCCESS));
@@ -1228,7 +1242,7 @@ row_log_table_apply_delete_low(
 		/* Build a row template for purging secondary index entries. */
 		row = row_build(
 			ROW_COPY_DATA, index, btr_pcur_get_rec(pcur),
-			offsets, NULL, NULL, &ext, heap);
+			offsets, NULL, NULL, NULL, &ext, heap);
 	} else {
 		row = NULL;
 	}
@@ -1389,7 +1403,7 @@ all_done:
 /******************************************************//**
 Replays an update operation on a table that was rebuilt.
 @return DB_SUCCESS or error code */
-static __attribute__((nonnull, warn_unused_result))
+static __attribute__((nonnull(1,4,5,6,8,9,10,11,12), warn_unused_result))
 dberr_t
 row_log_table_apply_update(
 /*=======================*/
@@ -1404,6 +1418,8 @@ row_log_table_apply_update(
 	const ulint*		offsets,	/*!< in: offsets of mrec */
 	mem_heap_t*		offsets_heap,	/*!< in/out: memory heap
 						that can be emptied */
+	const dtuple_t*		add_cols,	/*!< in: default values of
+						added columns, or NULL */
 	const ulint*		col_map,	/*!< in: mapping of old column
 						numbers to new ones, or NULL */
 	mem_heap_t*		heap,		/*!< in/out: memory heap */
@@ -1429,7 +1445,8 @@ row_log_table_apply_update(
 	      + (dup->index->online_log->same_pk ? 0 : 2));
 
 	row = row_log_table_apply_convert_mrec(
-		mrec, dup->index, offsets, col_map, heap, new_table, &error);
+		mrec, dup->index, offsets, add_cols, col_map,
+		heap, new_table, &error);
 
 	ut_ad(!row == (error != DB_SUCCESS));
 
@@ -1560,7 +1577,7 @@ delete_insert:
 		old_row = row_build(ROW_COPY_DATA, index,
 				    btr_pcur_get_rec(&pcur),
 				    cur_offsets, new_table,
-				    col_map, &old_ext, heap);
+				    add_cols, col_map, &old_ext, heap);
 		ut_ad(old_row);
 	} else {
 		old_row = NULL;
@@ -1650,7 +1667,7 @@ func_exit:
 Applies an operation to a table that was rebuilt.
 @return NULL on failure (mrec corruption) or when out of data;
 pointer to next record on success */
-static __attribute__((nonnull, warn_unused_result))
+static __attribute__((nonnull(1,4,6,7,8,9,10,11,12,13), warn_unused_result))
 const mrec_t*
 row_log_table_apply_op(
 /*===================*/
@@ -1661,6 +1678,8 @@ row_log_table_apply_op(
 						DB_TRX_ID in new index */
 	dict_table_t*		new_table,	/*!< in/out: table
 						being rebuilt */
+	const dtuple_t*		add_cols,	/*!< in: default values of
+						added columns, or NULL */
 	const ulint*		col_map,	/*!< in: mapping of old column
 						numbers to new ones, or NULL */
 	row_merge_dup_t*	dup,		/*!< in/out: for reporting
@@ -1728,7 +1747,8 @@ row_log_table_apply_op(
 				    trx_read_trx_id(db_trx_id))) {
 				*error = row_log_table_apply_insert(
 					thr, mrec, offsets, offsets_heap,
-					col_map, heap, new_table, dup);
+					add_cols, col_map,
+					heap, new_table, dup);
 			}
 		}
 		break;
@@ -1898,7 +1918,7 @@ row_log_table_apply_op(
 				*error = row_log_table_apply_update(
 					thr, trx_id_col, new_trx_id_col,
 					mrec, offsets, offsets_heap,
-					col_map,
+					add_cols, col_map,
 					heap, new_table, dup, old_pk);
 			}
 		}
@@ -1914,11 +1934,14 @@ row_log_table_apply_op(
 /******************************************************//**
 Applies operations to a table was rebuilt.
 @return DB_SUCCESS, or error code on failure */
-static __attribute__((nonnull))
+static __attribute__((nonnull(1,3,4), warn_unused_result))
 dberr_t
 row_log_table_apply_ops(
 /*====================*/
 	que_thr_t*	thr,	/*!< in: query graph */
+	const dtuple_t*	add_cols,
+				/*!< in: default values of
+				added columns, or NULL */
 	const ulint*	col_map,/*!< in: mapping of old column
 				numbers to new ones, or NULL */
 	row_merge_dup_t*dup)	/*!< in/out: for reporting duplicate key
@@ -2095,7 +2118,7 @@ all_done:
 		       (&index->online_log->head.buf)[1] - mrec_end);
 		mrec = row_log_table_apply_op(
 			thr, trx_id_col, new_trx_id_col,
-			index->online_log->table, col_map,
+			index->online_log->table, add_cols, col_map,
 			dup, &error, offsets_heap, heap,
 			index->online_log->head.buf,
 			(&index->online_log->head.buf)[1], offsets);
@@ -2194,7 +2217,7 @@ all_done:
 
 		next_mrec = row_log_table_apply_op(
 			thr, trx_id_col, new_trx_id_col,
-			index->online_log->table, col_map,
+			index->online_log->table, add_cols, col_map,
 			dup, &error, offsets_heap, heap,
 			mrec, mrec_end, offsets);
 
@@ -2263,6 +2286,9 @@ row_log_table_apply(
 				/*!< in: old table */
 	struct TABLE*	table,	/*!< in/out: MySQL table
 				(for reporting duplicates) */
+	const dtuple_t*	add_cols,
+				/*!< in: default values of
+				added columns, or NULL */
 	const ulint*	col_map)/*!< in: mapping of old column
 				numbers to new ones, or NULL */
 {
@@ -2291,7 +2317,7 @@ row_log_table_apply(
 		ut_ad(0);
 		error = DB_ERROR;
 	} else {
-		error = row_log_table_apply_ops(thr, col_map, &dup);
+		error = row_log_table_apply_ops(thr, add_cols, col_map, &dup);
 	}
 
 	rw_lock_x_unlock(dict_index_get_lock(clust_index));

=== modified file 'storage/innobase/row/row0merge.cc'
--- a/storage/innobase/row/row0merge.cc	revid:marko.makela@strippedyp11q7yo2zm6xpy
+++ b/storage/innobase/row/row0merge.cc	revid:marko.makela@stripped91t
@@ -1213,7 +1213,7 @@ row_merge_skip_rec(
 Reads clustered index of the table and create temporary files
 containing the index entries for the indexes to be built.
 @return	DB_SUCCESS or error */
-static __attribute__((nonnull(1,2,3,4,6,9,10,13),warn_unused_result))
+static __attribute__((nonnull(1,2,3,4,6,9,10,14),warn_unused_result))
 dberr_t
 row_merge_read_clustered_index(
 /*===========================*/
@@ -1238,6 +1238,9 @@ row_merge_read_clustered_index(
 	const ulint*		key_numbers,
 					/*!< in: MySQL key numbers to create */
 	ulint			n_index,/*!< in: number of indexes to create */
+	const dtuple_t*		add_cols,
+					/*!< in: default values of
+					added columns, or NULL */
 	const ulint*		col_map,/*!< in: mapping of old column
 					numbers to new ones, or NULL
 					if old_table == new_table */
@@ -1262,7 +1265,8 @@ row_merge_read_clustered_index(
 	ibool			fts_pll_sort = FALSE;
 	ib_int64_t		sig_count = 0;
 
-	ut_ad(old_table == new_table || col_map);
+	ut_ad((old_table == new_table) == !col_map);
+	ut_ad(!add_cols || col_map);
 
 	trx->op_info = "reading clustered index";
 
@@ -1512,7 +1516,7 @@ row_merge_read_clustered_index(
 
 		row = row_build(ROW_COPY_POINTERS, clust_index,
 				rec, offsets, new_table,
-				col_map, &ext, row_heap);
+				add_cols, col_map, &ext, row_heap);
 		ut_ad(row);
 
 		for (ulint i = 0; i < n_nonnull; i++) {
@@ -3199,6 +3203,8 @@ row_merge_build_indexes(
 	struct TABLE*	table,		/*!< in/out: MySQL table, for
 					reporting erroneous key value
 					if applicable */
+	const dtuple_t*	add_cols,	/*!< in: default values of
+					added columns, or NULL */
 	const ulint*	col_map)	/*!< in: mapping of old column
 					numbers to new ones, or NULL
 					if old_table == new_table */
@@ -3215,7 +3221,8 @@ row_merge_build_indexes(
 	fts_psort_t*		merge_info = NULL;
 	ib_int64_t		sig_count = 0;
 
-	ut_ad(old_table == new_table || col_map);
+	ut_ad((old_table == new_table) == !col_map);
+	ut_ad(!add_cols || col_map);
 
 	/* Allocate memory for merge file data structure and initialize
 	fields */
@@ -3264,7 +3271,7 @@ row_merge_build_indexes(
 	error = row_merge_read_clustered_index(
 		trx, table, old_table, new_table, online, indexes,
 		fts_sort_idx, psort_info, merge_files, key_numbers,
-		n_indexes, col_map, block);
+		n_indexes, add_cols, col_map, block);
 
 	if (error != DB_SUCCESS) {
 

=== modified file 'storage/innobase/row/row0row.cc'
--- a/storage/innobase/row/row0row.cc	revid:marko.makela@stripped11q7yo2zm6xpy
+++ b/storage/innobase/row/row0row.cc	revid:marko.makela@stripped
@@ -217,6 +217,9 @@ row_build(
 					of an index, or NULL if
 					index->table should be
 					consulted instead */
+	const dtuple_t*		add_cols,
+					/*!< in: default values of
+					added columns, or NULL */
 	const ulint*		col_map,/*!< in: mapping of old column
 					numbers to new ones, or NULL */
 	row_ext_t**		ext,	/*!< out, own: cache of
@@ -282,13 +285,24 @@ row_build(
 
 	if (!col_table) {
 		ut_ad(!col_map);
+		ut_ad(!add_cols);
 		col_table = index->table;
 	}
 
-	//row = dtuple_copy(heap, default_row);// todo: ADD_COLUMN
-	row = dtuple_create(heap, dict_table_get_n_cols(col_table));
+	if (add_cols) {
+		ut_ad(col_map);
+		row = dtuple_copy(add_cols, heap);
+		/* dict_table_copy_types() would set the fields to NULL */
+		for (ulint i = 0; i < dict_table_get_n_cols(col_table); i++) {
+			dict_col_copy_type(
+				dict_table_get_nth_col(col_table, i),
+				dfield_get_type(dtuple_get_nth_field(row, i)));
+		}
+	} else {
+		row = dtuple_create(heap, dict_table_get_n_cols(col_table));
+		dict_table_copy_types(row, col_table);
+	}
 
-	dict_table_copy_types(row, col_table);
 	dtuple_set_info_bits(row, rec_get_info_bits(
 				     copy, rec_offs_comp(offsets)));
 

=== modified file 'storage/innobase/row/row0undo.cc'
--- a/storage/innobase/row/row0undo.cc	revid:marko.makela@stripped120605072828-xyp11q7yo2zm6xpy
+++ b/storage/innobase/row/row0undo.cc	revid:marko.makela@strippedned9z2rxx931s91t
@@ -217,7 +217,7 @@ row_undo_search_clust_to_pcur(
 
 		node->row = row_build(ROW_COPY_DATA, clust_index, rec,
 				      offsets, NULL,
-				      NULL, ext, node->heap);
+				      NULL, NULL, ext, node->heap);
 		if (node->update) {
 			node->undo_row = dtuple_copy(node->row, node->heap);
 			row_upd_replace(node->undo_row, &node->undo_ext,

=== modified file 'storage/innobase/row/row0upd.cc'
--- a/storage/innobase/row/row0upd.cc	revid:marko.makela@strippedpy
+++ b/storage/innobase/row/row0upd.cc	revid:marko.makela@stripped
@@ -1584,7 +1584,7 @@ row_upd_store_row(
 	}
 
 	node->row = row_build(ROW_COPY_DATA, clust_index, rec, offsets,
-			      NULL, NULL, ext, node->heap);
+			      NULL, NULL, NULL, ext, node->heap);
 	if (node->is_delete) {
 		node->upd_row = NULL;
 		node->upd_ext = NULL;

=== modified file 'storage/innobase/row/row0vers.cc'
--- a/storage/innobase/row/row0vers.cc	revid:marko.makela@stripped8-xyp11q7yo2zm6xpy
+++ b/storage/innobase/row/row0vers.cc	revid:marko.makela@stripped1s91t
@@ -164,7 +164,7 @@ row_vers_impl_x_locked_low(
 
 		row = row_build(ROW_COPY_POINTERS, clust_index, prev_version,
 				clust_offsets,
-				NULL, NULL, &ext, heap);
+				NULL, NULL, NULL, &ext, heap);
 
 		entry = row_build_index_entry(row, ext, index, heap);
 
@@ -385,7 +385,7 @@ row_vers_old_has_index_entry(
 		externally stored columns. */
 		row = row_build(ROW_COPY_POINTERS, clust_index,
 				rec, clust_offsets,
-				NULL, NULL, &ext, heap);
+				NULL, NULL, NULL, &ext, heap);
 		entry = row_build_index_entry(row, ext, index, heap);
 
 		/* If entry == NULL, the record contains unset BLOB
@@ -446,7 +446,7 @@ row_vers_old_has_index_entry(
 			externally stored columns. */
 			row = row_build(ROW_COPY_POINTERS, clust_index,
 					prev_version, clust_offsets,
-					NULL, NULL, &ext, heap);
+					NULL, NULL, NULL, &ext, heap);
 			entry = row_build_index_entry(row, ext, index, heap);
 
 			/* If entry == NULL, the record contains unset

No bundle (reason: useless for push emails).
Thread
bzr push into mysql-trunk-wl6255 branch (marko.makela:3940 to 3944) WL#6255marko.makela6 Jun