From: Marc Alff Date: April 13 2012 7:28am Subject: bzr push into mysql-trunk-pfs-tuning branch (marc.alff:3496 to 3497) List-Archive: http://lists.mysql.com/commits/143473 Message-Id: <201204130728.q3D7Sxkt005735@acsmt356.oracle.com> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit 3497 Marc Alff 2012-04-13 [merge] Merge mysql-trunk --> mysql-trunk-pfs-tuning modified: mysql-test/r/partition_exchange.result mysql-test/suite/parts/r/partition_exch_qa_12.result mysql-test/suite/parts/t/partition_exch_qa_12.test mysql-test/t/partition_exchange.test sql/item.cc sql/item.h sql/item_func.cc sql/item_func.h sql/item_timefunc.h sql/item_xmlfunc.cc sql/log_event.cc sql/sp_head.cc sql/sql_analyse.cc sql/sql_base.cc sql/sql_executor.cc sql/sql_partition_admin.cc sql/sql_show.h sql/sql_string.h sql/sql_view.cc sql/sql_yacc.yy 3496 Marc Alff 2012-04-12 [merge] merge added: mysql-test/suite/binlog/r/binlog_gtid_cache.result mysql-test/suite/binlog/t/binlog_gtid_cache-master.opt mysql-test/suite/binlog/t/binlog_gtid_cache.test modified: mysql-test/extra/rpl_tests/rpl_loaddata.test mysql-test/extra/rpl_tests/rpl_mts_crash_safe.inc mysql-test/extra/rpl_tests/rpl_row_basic.test mysql-test/extra/rpl_tests/rpl_stm_EE_err2.test mysql-test/r/alter_table.result mysql-test/r/explain.result mysql-test/r/get_diagnostics.result mysql-test/r/help.result mysql-test/r/innodb_explain_json_non_select_all.result mysql-test/r/innodb_explain_json_non_select_none.result mysql-test/r/innodb_explain_non_select_all.result mysql-test/r/innodb_explain_non_select_none.result mysql-test/r/myisam_explain_json_non_select_all.result mysql-test/r/myisam_explain_json_non_select_none.result mysql-test/r/myisam_explain_non_select_all.result mysql-test/r/myisam_explain_non_select_none.result mysql-test/r/partition_error.result mysql-test/r/partition_exchange.result mysql-test/r/read_only_innodb.result mysql-test/r/sp-destruct.result mysql-test/r/type_time.result mysql-test/r/variables.result mysql-test/suite/binlog/r/binlog_rewrite.result mysql-test/suite/innodb_fts/r/innodb_fts_misc.result mysql-test/suite/innodb_fts/t/innodb_fts_misc.test mysql-test/suite/perfschema/r/digest_table_full.result mysql-test/suite/perfschema/r/statement_digest.result mysql-test/suite/perfschema/r/statement_digest_consumers.result mysql-test/suite/perfschema/r/statement_digest_long_query.result mysql-test/suite/rpl/r/rpl_alter_repository.result mysql-test/suite/rpl/r/rpl_mixed_binlog_max_cache_size.result mysql-test/suite/rpl/r/rpl_mixed_mts_crash_safe.result mysql-test/suite/rpl/r/rpl_mixed_mts_rec_crash_safe.result mysql-test/suite/rpl/r/rpl_mixed_mts_rec_crash_safe_checksum.result mysql-test/suite/rpl/r/rpl_mts_debug.result mysql-test/suite/rpl/r/rpl_parallel_start_stop.result mysql-test/suite/rpl/r/rpl_row_basic_2myisam.result mysql-test/suite/rpl/r/rpl_row_basic_3innodb.result mysql-test/suite/rpl/r/rpl_row_basic_allow_batching.result mysql-test/suite/rpl/r/rpl_row_binlog_max_cache_size.result mysql-test/suite/rpl/r/rpl_row_mts_crash_safe.result mysql-test/suite/rpl/r/rpl_row_mts_rec_crash_safe.result mysql-test/suite/rpl/r/rpl_stm_binlog_max_cache_size.result mysql-test/suite/rpl/r/rpl_stm_mts_crash_safe.result mysql-test/suite/rpl/r/rpl_stm_mts_rec_crash_safe.result mysql-test/suite/rpl/t/rpl_alter_repository.test mysql-test/suite/rpl/t/rpl_mts_debug.test mysql-test/suite/rpl/t/rpl_parallel_start_stop.test mysql-test/suite/rpl/t/rpl_row_crash_safe.test mysql-test/suite/rpl/t/rpl_stm_mixed_crash_safe.test mysql-test/suite/rpl/t/rpl_stm_until.test mysql-test/suite/sys_vars/r/max_binlog_cache_size_basic.result mysql-test/suite/sys_vars/r/max_binlog_stmt_cache_size_basic.result mysql-test/t/alter_table.test mysql-test/t/help.test sql/binlog.cc sql/field.cc sql/field.h sql/field_conv.cc sql/handler.cc sql/handler.h sql/lex.h sql/log_event.cc sql/rpl_info_dummy.cc sql/rpl_info_dummy.h sql/rpl_info_factory.cc sql/rpl_info_factory.h sql/rpl_info_file.cc sql/rpl_info_file.h sql/rpl_info_handler.h sql/rpl_info_table.cc sql/rpl_info_table.h sql/rpl_mi.cc sql/rpl_rli.cc sql/rpl_rli.h sql/rpl_rli_pdb.cc sql/rpl_rli_pdb.h sql/rpl_slave.cc sql/rpl_slave.h sql/share/errmsg-utf8.txt sql/sql_class.h sql/sql_lex.h sql/sql_table.cc sql/sql_yacc.yy sql/sys_vars.cc storage/example/ha_example.cc storage/innobase/api/api0api.cc storage/innobase/api/api0misc.cc storage/innobase/btr/btr0btr.cc storage/innobase/btr/btr0cur.cc storage/innobase/buf/buf0buf.cc storage/innobase/buf/buf0dump.cc storage/innobase/buf/buf0rea.cc storage/innobase/dict/dict0boot.cc storage/innobase/dict/dict0crea.cc storage/innobase/dict/dict0dict.cc storage/innobase/dict/dict0load.cc storage/innobase/dict/dict0stats.cc storage/innobase/fil/fil0fil.cc storage/innobase/fts/fts0ast.cc storage/innobase/fts/fts0blex.cc storage/innobase/fts/fts0blex.l storage/innobase/fts/fts0config.cc storage/innobase/fts/fts0fts.cc storage/innobase/fts/fts0opt.cc storage/innobase/fts/fts0que.cc storage/innobase/fts/fts0sql.cc storage/innobase/fts/fts0tlex.cc storage/innobase/fts/fts0tlex.l storage/innobase/handler/ha_innodb.cc storage/innobase/handler/ha_innodb.h storage/innobase/handler/handler0alter.cc storage/innobase/ibuf/ibuf0ibuf.cc storage/innobase/include/api0api.h storage/innobase/include/api0misc.h storage/innobase/include/btr0cur.h storage/innobase/include/buf0buf.h storage/innobase/include/db0err.h storage/innobase/include/dict0crea.h storage/innobase/include/dict0dict.h storage/innobase/include/dict0load.h storage/innobase/include/dict0stats.h storage/innobase/include/fil0fil.h storage/innobase/include/fts0ast.h storage/innobase/include/fts0fts.h storage/innobase/include/fts0priv.h storage/innobase/include/ha_prototypes.h storage/innobase/include/lock0lock.h storage/innobase/include/log0recv.h storage/innobase/include/que0que.h storage/innobase/include/read0read.h storage/innobase/include/read0read.ic storage/innobase/include/row0ftsort.h storage/innobase/include/row0ins.h storage/innobase/include/row0log.h storage/innobase/include/row0merge.h storage/innobase/include/row0mysql.h storage/innobase/include/row0sel.h storage/innobase/include/row0uins.h storage/innobase/include/row0umod.h storage/innobase/include/row0upd.h storage/innobase/include/row0vers.h storage/innobase/include/srv0srv.h storage/innobase/include/srv0start.h storage/innobase/include/trx0rec.h storage/innobase/include/trx0roll.h storage/innobase/include/trx0sys.h storage/innobase/include/trx0trx.h storage/innobase/include/trx0undo.h storage/innobase/include/ut0ut.h storage/innobase/lock/lock0lock.cc storage/innobase/log/log0recv.cc storage/innobase/os/os0file.cc storage/innobase/que/que0que.cc storage/innobase/row/row0ftsort.cc storage/innobase/row/row0ins.cc storage/innobase/row/row0log.cc storage/innobase/row/row0merge.cc storage/innobase/row/row0mysql.cc storage/innobase/row/row0purge.cc storage/innobase/row/row0sel.cc storage/innobase/row/row0uins.cc storage/innobase/row/row0umod.cc storage/innobase/row/row0undo.cc storage/innobase/row/row0upd.cc storage/innobase/row/row0vers.cc storage/innobase/srv/srv0conc.cc storage/innobase/srv/srv0srv.cc storage/innobase/srv/srv0start.cc storage/innobase/trx/trx0i_s.cc storage/innobase/trx/trx0rec.cc storage/innobase/trx/trx0roll.cc storage/innobase/trx/trx0sys.cc storage/innobase/trx/trx0trx.cc storage/innobase/trx/trx0undo.cc storage/innobase/ut/ut0ut.cc storage/myisam/ha_myisam.cc unittest/gunit/alignment-t.cc unittest/gunit/fake_table.h unittest/gunit/field-t.cc unittest/gunit/field_timestamp-t.cc === modified file 'mysql-test/r/partition_exchange.result' --- a/mysql-test/r/partition_exchange.result 2012-04-11 13:50:46 +0000 +++ b/mysql-test/r/partition_exchange.result 2012-04-13 07:19:19 +0000 @@ -1,5 +1,366 @@ DROP TABLE IF EXISTS t1, t2, t3, t, tp, tsp, tmp; # +# Bug#11894100: EXCHANGE PARTITION CAN'T BE EXECUTED IF +# ROW_FORMAT WAS SET EXPLICITLY +# +# Same definition (both have ROW_FORMAT set) +CREATE TABLE t1 ( +id int(11) NOT NULL AUTO_INCREMENT, +year year(2) DEFAULT NULL, +modified timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', +PRIMARY KEY (id) +) ENGINE=InnoDB ROW_FORMAT=COMPACT +PARTITION BY HASH (id) +PARTITIONS 2; +CREATE TABLE t2 LIKE t1; +ALTER TABLE t2 REMOVE PARTITIONING; +SHOW CREATE TABLE t1; +Table t1 +Create Table CREATE TABLE `t1` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `year` year(2) DEFAULT NULL, + `modified` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=COMPACT +/*!50100 PARTITION BY HASH (id) +PARTITIONS 2 */ +SHOW CREATE TABLE t2; +Table t2 +Create Table CREATE TABLE `t2` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `year` year(2) DEFAULT NULL, + `modified` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=COMPACT +SELECT TABLE_NAME, TABLE_TYPE, ENGINE, ROW_FORMAT, CREATE_OPTIONS +FROM INFORMATION_SCHEMA.TABLES +WHERE TABLE_SCHEMA = 'test' AND TABLE_NAME IN ('t1', 't2'); +TABLE_NAME t1 +TABLE_TYPE BASE TABLE +ENGINE InnoDB +ROW_FORMAT Compact +CREATE_OPTIONS row_format=COMPACT partitioned +TABLE_NAME t2 +TABLE_TYPE BASE TABLE +ENGINE InnoDB +ROW_FORMAT Compact +CREATE_OPTIONS row_format=COMPACT +ALTER TABLE t1 EXCHANGE PARTITION p1 WITH TABLE t2; +SHOW CREATE TABLE t1; +Table t1 +Create Table CREATE TABLE `t1` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `year` year(2) DEFAULT NULL, + `modified` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=COMPACT +/*!50100 PARTITION BY HASH (id) +PARTITIONS 2 */ +SHOW CREATE TABLE t2; +Table t2 +Create Table CREATE TABLE `t2` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `year` year(2) DEFAULT NULL, + `modified` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=COMPACT +SELECT TABLE_NAME, TABLE_TYPE, ENGINE, ROW_FORMAT, CREATE_OPTIONS +FROM INFORMATION_SCHEMA.TABLES +WHERE TABLE_SCHEMA = 'test' AND TABLE_NAME IN ('t1', 't2'); +TABLE_NAME t1 +TABLE_TYPE BASE TABLE +ENGINE InnoDB +ROW_FORMAT Compact +CREATE_OPTIONS row_format=COMPACT partitioned +TABLE_NAME t2 +TABLE_TYPE BASE TABLE +ENGINE InnoDB +ROW_FORMAT Compact +CREATE_OPTIONS row_format=COMPACT +DROP TABLE t2; +# Only the partitioned table have ROW_FORMAT set. +CREATE TABLE t2 ( +id int(11) NOT NULL AUTO_INCREMENT, +year year(2) DEFAULT NULL, +modified timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', +PRIMARY KEY (id) +) ENGINE=InnoDB; +ALTER TABLE t1 EXCHANGE PARTITION p1 WITH TABLE t2; +SHOW CREATE TABLE t1; +Table t1 +Create Table CREATE TABLE `t1` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `year` year(2) DEFAULT NULL, + `modified` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=COMPACT +/*!50100 PARTITION BY HASH (id) +PARTITIONS 2 */ +SHOW CREATE TABLE t2; +Table t2 +Create Table CREATE TABLE `t2` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `year` year(2) DEFAULT NULL, + `modified` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +SELECT TABLE_NAME, TABLE_TYPE, ENGINE, ROW_FORMAT, CREATE_OPTIONS +FROM INFORMATION_SCHEMA.TABLES +WHERE TABLE_SCHEMA = 'test' AND TABLE_NAME IN ('t1', 't2'); +TABLE_NAME t1 +TABLE_TYPE BASE TABLE +ENGINE InnoDB +ROW_FORMAT Compact +CREATE_OPTIONS row_format=COMPACT partitioned +TABLE_NAME t2 +TABLE_TYPE BASE TABLE +ENGINE InnoDB +ROW_FORMAT Compact +CREATE_OPTIONS +# Only the non partitioned table have ROW_FORMAT set. +DROP TABLE t1, t2; +CREATE TABLE t1 ( +id int(11) NOT NULL AUTO_INCREMENT, +year year(2) DEFAULT NULL, +modified timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', +PRIMARY KEY (id) +) ENGINE=InnoDB +PARTITION BY HASH (id) +PARTITIONS 2; +CREATE TABLE t2 ( +id int(11) NOT NULL AUTO_INCREMENT, +year year(2) DEFAULT NULL, +modified timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', +PRIMARY KEY (id) +) ENGINE=InnoDB ROW_FORMAT = COMPACT; +ALTER TABLE t1 EXCHANGE PARTITION p1 WITH TABLE t2; +SHOW CREATE TABLE t1; +Table t1 +Create Table CREATE TABLE `t1` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `year` year(2) DEFAULT NULL, + `modified` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +/*!50100 PARTITION BY HASH (id) +PARTITIONS 2 */ +SHOW CREATE TABLE t2; +Table t2 +Create Table CREATE TABLE `t2` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `year` year(2) DEFAULT NULL, + `modified` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=COMPACT +SELECT TABLE_NAME, TABLE_TYPE, ENGINE, ROW_FORMAT, CREATE_OPTIONS +FROM INFORMATION_SCHEMA.TABLES +WHERE TABLE_SCHEMA = 'test' AND TABLE_NAME IN ('t1', 't2'); +TABLE_NAME t1 +TABLE_TYPE BASE TABLE +ENGINE InnoDB +ROW_FORMAT Compact +CREATE_OPTIONS partitioned +TABLE_NAME t2 +TABLE_TYPE BASE TABLE +ENGINE InnoDB +ROW_FORMAT Compact +CREATE_OPTIONS row_format=COMPACT +# No table have ROW_FORMAT set. +DROP TABLE t1, t2; +CREATE TABLE t1 ( +id int(11) NOT NULL AUTO_INCREMENT, +year year(2) DEFAULT NULL, +modified timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', +PRIMARY KEY (id) +) ENGINE=InnoDB +PARTITION BY HASH (id) +PARTITIONS 2; +CREATE TABLE t2 ( +id int(11) NOT NULL AUTO_INCREMENT, +year year(2) DEFAULT NULL, +modified timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', +PRIMARY KEY (id) +) ENGINE=InnoDB; +ALTER TABLE t1 EXCHANGE PARTITION p1 WITH TABLE t2; +SHOW CREATE TABLE t1; +Table t1 +Create Table CREATE TABLE `t1` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `year` year(2) DEFAULT NULL, + `modified` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +/*!50100 PARTITION BY HASH (id) +PARTITIONS 2 */ +SHOW CREATE TABLE t2; +Table t2 +Create Table CREATE TABLE `t2` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `year` year(2) DEFAULT NULL, + `modified` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +SELECT TABLE_NAME, TABLE_TYPE, ENGINE, ROW_FORMAT, CREATE_OPTIONS +FROM INFORMATION_SCHEMA.TABLES +WHERE TABLE_SCHEMA = 'test' AND TABLE_NAME IN ('t1', 't2'); +TABLE_NAME t1 +TABLE_TYPE BASE TABLE +ENGINE InnoDB +ROW_FORMAT Compact +CREATE_OPTIONS partitioned +TABLE_NAME t2 +TABLE_TYPE BASE TABLE +ENGINE InnoDB +ROW_FORMAT Compact +CREATE_OPTIONS +# Not same ROW_FORMAT as default (but same). +DROP TABLE t1, t2; +CREATE TABLE t1 ( +id int(11) NOT NULL AUTO_INCREMENT, +year year(2) DEFAULT NULL, +modified timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', +PRIMARY KEY (id) +) ENGINE=InnoDB ROW_FORMAT = REDUNDANT +PARTITION BY HASH (id) +PARTITIONS 2; +CREATE TABLE t2 ( +id int(11) NOT NULL AUTO_INCREMENT, +year year(2) DEFAULT NULL, +modified timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', +PRIMARY KEY (id) +) ENGINE=InnoDB ROW_FORMAT = REDUNDANT; +ALTER TABLE t1 EXCHANGE PARTITION p1 WITH TABLE t2; +SHOW CREATE TABLE t1; +Table t1 +Create Table CREATE TABLE `t1` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `year` year(2) DEFAULT NULL, + `modified` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=REDUNDANT +/*!50100 PARTITION BY HASH (id) +PARTITIONS 2 */ +SHOW CREATE TABLE t2; +Table t2 +Create Table CREATE TABLE `t2` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `year` year(2) DEFAULT NULL, + `modified` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=REDUNDANT +SELECT TABLE_NAME, TABLE_TYPE, ENGINE, ROW_FORMAT, CREATE_OPTIONS +FROM INFORMATION_SCHEMA.TABLES +WHERE TABLE_SCHEMA = 'test' AND TABLE_NAME IN ('t1', 't2'); +TABLE_NAME t1 +TABLE_TYPE BASE TABLE +ENGINE InnoDB +ROW_FORMAT Redundant +CREATE_OPTIONS row_format=REDUNDANT partitioned +TABLE_NAME t2 +TABLE_TYPE BASE TABLE +ENGINE InnoDB +ROW_FORMAT Redundant +CREATE_OPTIONS row_format=REDUNDANT +# Not same ROW_FORMAT as default (tables differs). +DROP TABLE t1, t2; +CREATE TABLE t1 ( +id int(11) NOT NULL AUTO_INCREMENT, +year year(2) DEFAULT NULL, +modified timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', +PRIMARY KEY (id) +) ENGINE=InnoDB +PARTITION BY HASH (id) +PARTITIONS 2; +CREATE TABLE t2 ( +id int(11) NOT NULL AUTO_INCREMENT, +year year(2) DEFAULT NULL, +modified timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', +PRIMARY KEY (id) +) ENGINE=InnoDB ROW_FORMAT = REDUNDANT; +ALTER TABLE t1 EXCHANGE PARTITION p1 WITH TABLE t2; +ERROR HY000: Non matching attribute 'ROW_FORMAT' between partition and table +SHOW CREATE TABLE t1; +Table t1 +Create Table CREATE TABLE `t1` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `year` year(2) DEFAULT NULL, + `modified` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +/*!50100 PARTITION BY HASH (id) +PARTITIONS 2 */ +SHOW CREATE TABLE t2; +Table t2 +Create Table CREATE TABLE `t2` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `year` year(2) DEFAULT NULL, + `modified` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=REDUNDANT +SELECT TABLE_NAME, TABLE_TYPE, ENGINE, ROW_FORMAT, CREATE_OPTIONS +FROM INFORMATION_SCHEMA.TABLES +WHERE TABLE_SCHEMA = 'test' AND TABLE_NAME IN ('t1', 't2'); +TABLE_NAME t1 +TABLE_TYPE BASE TABLE +ENGINE InnoDB +ROW_FORMAT Compact +CREATE_OPTIONS partitioned +TABLE_NAME t2 +TABLE_TYPE BASE TABLE +ENGINE InnoDB +ROW_FORMAT Redundant +CREATE_OPTIONS row_format=REDUNDANT +# Different than default (forced ROW_TYPE) +DROP TABLE t1, t2; +CREATE TABLE t1 ( +id int(11) NOT NULL AUTO_INCREMENT, +year year(2) DEFAULT NULL, +modified timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', +PRIMARY KEY (id) +) ENGINE=InnoDB ROW_FORMAT = COMPACT +PARTITION BY HASH (id) +PARTITIONS 2; +CREATE TABLE t2 ( +id int(11) NOT NULL AUTO_INCREMENT, +year year(2) DEFAULT NULL, +modified timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', +PRIMARY KEY (id) +) ENGINE=InnoDB ROW_FORMAT = REDUNDANT; +ALTER TABLE t1 EXCHANGE PARTITION p1 WITH TABLE t2; +ERROR HY000: Non matching attribute 'ROW_FORMAT' between partition and table +SHOW CREATE TABLE t1; +Table t1 +Create Table CREATE TABLE `t1` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `year` year(2) DEFAULT NULL, + `modified` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=COMPACT +/*!50100 PARTITION BY HASH (id) +PARTITIONS 2 */ +SHOW CREATE TABLE t2; +Table t2 +Create Table CREATE TABLE `t2` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `year` year(2) DEFAULT NULL, + `modified` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=REDUNDANT +SELECT TABLE_NAME, TABLE_TYPE, ENGINE, ROW_FORMAT, CREATE_OPTIONS +FROM INFORMATION_SCHEMA.TABLES +WHERE TABLE_SCHEMA = 'test' AND TABLE_NAME IN ('t1', 't2'); +TABLE_NAME t1 +TABLE_TYPE BASE TABLE +ENGINE InnoDB +ROW_FORMAT Compact +CREATE_OPTIONS row_format=COMPACT partitioned +TABLE_NAME t2 +TABLE_TYPE BASE TABLE +ENGINE InnoDB +ROW_FORMAT Redundant +CREATE_OPTIONS row_format=REDUNDANT +DROP TABLE t1, t2; +# # Bug#56484: !table || (!table->read_set || # bitmap_is_set(table->read_set, field_index)) # === modified file 'mysql-test/suite/parts/r/partition_exch_qa_12.result' --- a/mysql-test/suite/parts/r/partition_exch_qa_12.result 2010-11-16 13:48:04 +0000 +++ b/mysql-test/suite/parts/r/partition_exch_qa_12.result 2012-04-13 07:19:19 +0000 @@ -101,8 +101,12 @@ a b 9 Nine ALTER TABLE tp EXCHANGE PARTITION p0 WITH TABLE t_10; ERROR HY000: Tables have different definitions +SELECT TABLE_NAME, ROW_FORMAT FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'test' +AND TABLE_NAME IN ('tp', 't_100'); +TABLE_NAME ROW_FORMAT +t_100 Dynamic +tp Dynamic ALTER TABLE tp EXCHANGE PARTITION p1 WITH TABLE t_100; -ERROR HY000: Tables have different definitions ALTER TABLE tp EXCHANGE PARTITION p1 WITH TABLE t_1000; ERROR HY000: Non matching attribute 'MAX_ROWS' between partition and table DROP TABLE IF EXISTS t_10; === modified file 'mysql-test/suite/parts/t/partition_exch_qa_12.test' --- a/mysql-test/suite/parts/t/partition_exch_qa_12.test 2010-11-16 13:48:04 +0000 +++ b/mysql-test/suite/parts/t/partition_exch_qa_12.test 2012-04-13 07:19:19 +0000 @@ -164,7 +164,8 @@ SELECT * FROM tsp_04; ALTER TABLE tp EXCHANGE PARTITION p0 WITH TABLE t_10; #--error ER_TABLES_DIFFERENT_METADATA #ALTER TABLE tp EXCHANGE PARTITION p0 WITH TABLE t_10 IGNORE; ---error ER_TABLES_DIFFERENT_METADATA +SELECT TABLE_NAME, ROW_FORMAT FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'test' +AND TABLE_NAME IN ('tp', 't_100'); ALTER TABLE tp EXCHANGE PARTITION p1 WITH TABLE t_100; #--error ER_TABLES_DIFFERENT_METADATA #ALTER TABLE tp EXCHANGE PARTITION p1 WITH TABLE t_100 IGNORE; === modified file 'mysql-test/t/partition_exchange.test' --- a/mysql-test/t/partition_exchange.test 2010-11-16 00:55:42 +0000 +++ b/mysql-test/t/partition_exchange.test 2012-04-13 07:19:19 +0000 @@ -6,6 +6,180 @@ DROP TABLE IF EXISTS t1, t2, t3, t, tp, --enable_warnings --echo # +--echo # Bug#11894100: EXCHANGE PARTITION CAN'T BE EXECUTED IF +--echo # ROW_FORMAT WAS SET EXPLICITLY +--echo # + +--echo # Same definition (both have ROW_FORMAT set) +CREATE TABLE t1 ( + id int(11) NOT NULL AUTO_INCREMENT, + year year(2) DEFAULT NULL, + modified timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', + PRIMARY KEY (id) +) ENGINE=InnoDB ROW_FORMAT=COMPACT +PARTITION BY HASH (id) +PARTITIONS 2; + +CREATE TABLE t2 LIKE t1; +ALTER TABLE t2 REMOVE PARTITIONING; + +--vertical_results +SHOW CREATE TABLE t1; +SHOW CREATE TABLE t2; + +SELECT TABLE_NAME, TABLE_TYPE, ENGINE, ROW_FORMAT, CREATE_OPTIONS +FROM INFORMATION_SCHEMA.TABLES +WHERE TABLE_SCHEMA = 'test' AND TABLE_NAME IN ('t1', 't2'); + +ALTER TABLE t1 EXCHANGE PARTITION p1 WITH TABLE t2; +SHOW CREATE TABLE t1; +SHOW CREATE TABLE t2; +SELECT TABLE_NAME, TABLE_TYPE, ENGINE, ROW_FORMAT, CREATE_OPTIONS +FROM INFORMATION_SCHEMA.TABLES +WHERE TABLE_SCHEMA = 'test' AND TABLE_NAME IN ('t1', 't2'); + +DROP TABLE t2; + +--echo # Only the partitioned table have ROW_FORMAT set. +CREATE TABLE t2 ( + id int(11) NOT NULL AUTO_INCREMENT, + year year(2) DEFAULT NULL, + modified timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', + PRIMARY KEY (id) +) ENGINE=InnoDB; + +ALTER TABLE t1 EXCHANGE PARTITION p1 WITH TABLE t2; +SHOW CREATE TABLE t1; +SHOW CREATE TABLE t2; +SELECT TABLE_NAME, TABLE_TYPE, ENGINE, ROW_FORMAT, CREATE_OPTIONS +FROM INFORMATION_SCHEMA.TABLES +WHERE TABLE_SCHEMA = 'test' AND TABLE_NAME IN ('t1', 't2'); + +--echo # Only the non partitioned table have ROW_FORMAT set. +DROP TABLE t1, t2; +CREATE TABLE t1 ( + id int(11) NOT NULL AUTO_INCREMENT, + year year(2) DEFAULT NULL, + modified timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', + PRIMARY KEY (id) +) ENGINE=InnoDB +PARTITION BY HASH (id) +PARTITIONS 2; +CREATE TABLE t2 ( + id int(11) NOT NULL AUTO_INCREMENT, + year year(2) DEFAULT NULL, + modified timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', + PRIMARY KEY (id) +) ENGINE=InnoDB ROW_FORMAT = COMPACT; + +ALTER TABLE t1 EXCHANGE PARTITION p1 WITH TABLE t2; +SHOW CREATE TABLE t1; +SHOW CREATE TABLE t2; +SELECT TABLE_NAME, TABLE_TYPE, ENGINE, ROW_FORMAT, CREATE_OPTIONS +FROM INFORMATION_SCHEMA.TABLES +WHERE TABLE_SCHEMA = 'test' AND TABLE_NAME IN ('t1', 't2'); + +--echo # No table have ROW_FORMAT set. +DROP TABLE t1, t2; +CREATE TABLE t1 ( + id int(11) NOT NULL AUTO_INCREMENT, + year year(2) DEFAULT NULL, + modified timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', + PRIMARY KEY (id) +) ENGINE=InnoDB +PARTITION BY HASH (id) +PARTITIONS 2; +CREATE TABLE t2 ( + id int(11) NOT NULL AUTO_INCREMENT, + year year(2) DEFAULT NULL, + modified timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', + PRIMARY KEY (id) +) ENGINE=InnoDB; + +ALTER TABLE t1 EXCHANGE PARTITION p1 WITH TABLE t2; +SHOW CREATE TABLE t1; +SHOW CREATE TABLE t2; +SELECT TABLE_NAME, TABLE_TYPE, ENGINE, ROW_FORMAT, CREATE_OPTIONS +FROM INFORMATION_SCHEMA.TABLES +WHERE TABLE_SCHEMA = 'test' AND TABLE_NAME IN ('t1', 't2'); + +--echo # Not same ROW_FORMAT as default (but same). +DROP TABLE t1, t2; +CREATE TABLE t1 ( + id int(11) NOT NULL AUTO_INCREMENT, + year year(2) DEFAULT NULL, + modified timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', + PRIMARY KEY (id) +) ENGINE=InnoDB ROW_FORMAT = REDUNDANT +PARTITION BY HASH (id) +PARTITIONS 2; +CREATE TABLE t2 ( + id int(11) NOT NULL AUTO_INCREMENT, + year year(2) DEFAULT NULL, + modified timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', + PRIMARY KEY (id) +) ENGINE=InnoDB ROW_FORMAT = REDUNDANT; + +ALTER TABLE t1 EXCHANGE PARTITION p1 WITH TABLE t2; +SHOW CREATE TABLE t1; +SHOW CREATE TABLE t2; +SELECT TABLE_NAME, TABLE_TYPE, ENGINE, ROW_FORMAT, CREATE_OPTIONS +FROM INFORMATION_SCHEMA.TABLES +WHERE TABLE_SCHEMA = 'test' AND TABLE_NAME IN ('t1', 't2'); + +--echo # Not same ROW_FORMAT as default (tables differs). +DROP TABLE t1, t2; +CREATE TABLE t1 ( + id int(11) NOT NULL AUTO_INCREMENT, + year year(2) DEFAULT NULL, + modified timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', + PRIMARY KEY (id) +) ENGINE=InnoDB +PARTITION BY HASH (id) +PARTITIONS 2; +CREATE TABLE t2 ( + id int(11) NOT NULL AUTO_INCREMENT, + year year(2) DEFAULT NULL, + modified timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', + PRIMARY KEY (id) +) ENGINE=InnoDB ROW_FORMAT = REDUNDANT; + +--error ER_PARTITION_EXCHANGE_DIFFERENT_OPTION +ALTER TABLE t1 EXCHANGE PARTITION p1 WITH TABLE t2; +SHOW CREATE TABLE t1; +SHOW CREATE TABLE t2; +SELECT TABLE_NAME, TABLE_TYPE, ENGINE, ROW_FORMAT, CREATE_OPTIONS +FROM INFORMATION_SCHEMA.TABLES +WHERE TABLE_SCHEMA = 'test' AND TABLE_NAME IN ('t1', 't2'); + +--echo # Different than default (forced ROW_TYPE) +DROP TABLE t1, t2; +CREATE TABLE t1 ( + id int(11) NOT NULL AUTO_INCREMENT, + year year(2) DEFAULT NULL, + modified timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', + PRIMARY KEY (id) +) ENGINE=InnoDB ROW_FORMAT = COMPACT +PARTITION BY HASH (id) +PARTITIONS 2; +CREATE TABLE t2 ( + id int(11) NOT NULL AUTO_INCREMENT, + year year(2) DEFAULT NULL, + modified timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', + PRIMARY KEY (id) +) ENGINE=InnoDB ROW_FORMAT = REDUNDANT; + +--error ER_PARTITION_EXCHANGE_DIFFERENT_OPTION +ALTER TABLE t1 EXCHANGE PARTITION p1 WITH TABLE t2; +SHOW CREATE TABLE t1; +SHOW CREATE TABLE t2; +SELECT TABLE_NAME, TABLE_TYPE, ENGINE, ROW_FORMAT, CREATE_OPTIONS +FROM INFORMATION_SCHEMA.TABLES +WHERE TABLE_SCHEMA = 'test' AND TABLE_NAME IN ('t1', 't2'); +--horizontal_results +DROP TABLE t1, t2; + +--echo # --echo # Bug#56484: !table || (!table->read_set || --echo # bitmap_is_set(table->read_set, field_index)) --echo # === modified file 'sql/item.cc' --- a/sql/item.cc 2012-03-30 15:38:01 +0000 +++ b/sql/item.cc 2012-04-12 15:31:01 +0000 @@ -670,11 +670,11 @@ void Item::print_item_w_name(String *str { print(str, query_type); - if (item_name.ptr()) + if (item_name.is_set()) { THD *thd= current_thd; str->append(STRING_WITH_LEN(" AS ")); - append_identifier(thd, str, item_name.ptr(), item_name.length()); + append_identifier(thd, str, item_name); } } @@ -696,9 +696,9 @@ void Item::print_for_order(String *str, { if (used_alias) { - DBUG_ASSERT(item_name.ptr() != NULL); + DBUG_ASSERT(item_name.is_set()); // In the clause, user has referenced expression using an alias; we use it - append_identifier(current_thd, str, item_name.ptr(), item_name.length()); + append_identifier(current_thd, str, item_name); } else print(str,query_type); @@ -710,7 +710,7 @@ void Item::cleanup() DBUG_ENTER("Item::cleanup"); fixed=0; marker= 0; - if (orig_name.ptr()) + if (orig_name.is_set()) item_name= orig_name; DBUG_VOID_RETURN; } @@ -742,7 +742,7 @@ void Item::rename(char *new_name) we can compare pointers to names here, because if name was not changed, pointer will be same */ - if (!orig_name.ptr() && new_name != item_name.ptr()) + if (!orig_name.is_set() && new_name != item_name.ptr()) orig_name= item_name; item_name.set(new_name); } @@ -958,18 +958,19 @@ bool Item::check_cols(uint c) } +NameString null_name_string(NULL, 0); + + void NameString::copy(const char *str, uint length, const CHARSET_INFO *cs) { if (!length) { /* Empty string, used by AS or internal function like last_insert_id() */ - m_str= (char*) str; - m_length= 0; + set(str ? "" : NULL, 0); return; } if (cs->ctype) { - uint orig_len= length; /* This will probably need a better implementation in the future: a function in CHARSET_INFO structure. @@ -979,27 +980,41 @@ void NameString::copy(const char *str, u length--; str++; } - if (orig_len != length && !is_autogenerated()) - { - if (length == 0) - push_warning_printf(current_thd, Sql_condition::WARN_LEVEL_WARN, - ER_NAME_BECOMES_EMPTY, ER(ER_NAME_BECOMES_EMPTY), - str + length - orig_len); - else - push_warning_printf(current_thd, Sql_condition::WARN_LEVEL_WARN, - ER_REMOVED_SPACES, ER(ER_REMOVED_SPACES), - str + length - orig_len); - } } if (!my_charset_same(cs, system_charset_info)) { size_t res_length; - m_str= sql_strmake_with_convert(str, length, cs, MAX_ALIAS_NAME, - system_charset_info, &res_length); - m_length= res_length; + char *tmp= sql_strmake_with_convert(str, length, cs, MAX_ALIAS_NAME, + system_charset_info, &res_length); + set(tmp, tmp ? res_length : 0); } else - m_str= sql_strmake(str, (m_length= min(length, MAX_ALIAS_NAME))); + { + size_t len= min(length, MAX_ALIAS_NAME); + char *tmp= sql_strmake(str, len); + set(tmp, tmp ? len : 0); + } +} + + +void ItemNameString::copy(const char *str_arg, uint length_arg, + const CHARSET_INFO *cs_arg, + bool is_autogenerated_arg) +{ + m_is_autogenerated= is_autogenerated_arg; + copy(str_arg, length_arg, cs_arg); + if (length_arg > length() && !is_autogenerated()) + { + ErrConvString tmp(str_arg, length_arg, cs_arg); + if (length() == 0) + push_warning_printf(current_thd, Sql_condition::WARN_LEVEL_WARN, + ER_NAME_BECOMES_EMPTY, ER(ER_NAME_BECOMES_EMPTY), + tmp.ptr()); + else + push_warning_printf(current_thd, Sql_condition::WARN_LEVEL_WARN, + ER_REMOVED_SPACES, ER(ER_REMOVED_SPACES), + tmp.ptr()); + } } @@ -1017,7 +1032,7 @@ bool Item::eq(const Item *item, bool bin for all basic constants we have special checks, and Item_param's type() can be only among basic constant types. */ - return type() == item->type() && item_name.eq(&item->item_name); + return type() == item->type() && item_name.eq_safe(item->item_name); } @@ -1493,15 +1508,12 @@ bool Item::is_blob_field() const Item_sp_variable methods *****************************************************************************/ -Item_sp_variable::Item_sp_variable(char *sp_var_name_str, - uint sp_var_name_length) - :m_thd(0) +Item_sp_variable::Item_sp_variable(const NameString sp_var_name) + :m_thd(0), m_name(sp_var_name) #ifndef DBUG_OFF , m_sp(0) #endif { - m_name.str= sp_var_name_str; - m_name.length= sp_var_name_length; } @@ -1616,11 +1628,11 @@ bool Item_sp_variable::is_null() Item_splocal methods *****************************************************************************/ -Item_splocal::Item_splocal(const LEX_STRING &sp_var_name, +Item_splocal::Item_splocal(const NameString sp_var_name, uint sp_var_idx, enum_field_types sp_var_type, uint pos_in_q, uint len_in_q) - :Item_sp_variable(sp_var_name.str, sp_var_name.length), + :Item_sp_variable(sp_var_name), m_var_idx(sp_var_idx), limit_clause_param(FALSE), pos_in_query(pos_in_q), len_in_query(len_in_q) @@ -1662,8 +1674,8 @@ Item_splocal::this_item_addr(THD *thd, I void Item_splocal::print(String *str, enum_query_type) { - str->reserve(m_name.length+8); - str->append(m_name.str, m_name.length); + str->reserve(m_name.length() + 8); + str->append(m_name); str->append('@'); str->qs_append(m_var_idx); } @@ -1680,7 +1692,7 @@ bool Item_splocal::set_value(THD *thd, s *****************************************************************************/ Item_case_expr::Item_case_expr(uint case_expr_id) - :Item_sp_variable( C_STRING_WITH_LEN("case_expr")), + :Item_sp_variable(NameString(C_STRING_WITH_LEN("case_expr"))), m_case_expr_id(case_expr_id) { } @@ -2559,7 +2571,7 @@ const char *Item_ident::full_name() cons { char *tmp; if (!table_name || !field_name) - return field_name ? field_name : item_name.ptr() ? item_name.ptr() : "tmp_field"; + return field_name ? field_name : item_name.is_set() ? item_name.ptr() : "tmp_field"; if (db_name && db_name[0]) { tmp=(char*) sql_alloc((uint) strlen(db_name)+(uint) strlen(table_name)+ @@ -2605,7 +2617,7 @@ void Item_ident::print(String *str, enum if (!table_name || !field_name || !field_name[0]) { const char *nm= (field_name && field_name[0]) ? - field_name : item_name.ptr() ? item_name.ptr() : "tmp_field"; + field_name : item_name.is_set() ? item_name.ptr() : "tmp_field"; append_identifier(thd, str, nm, (uint) strlen(nm)); return; } @@ -2829,7 +2841,7 @@ bool Item_field::eq(const Item *item, bo (In cases where we would choose wrong we would have to generate a ER_NON_UNIQ_ERROR). */ - return (item_field->item_name.eq(field_name) && + return (item_field->item_name.eq_safe(field_name) && (!item_field->table_name || !table_name || (!my_strcasecmp(table_alias_charset, item_field->table_name, table_name) && @@ -3993,7 +4005,7 @@ Item_param::clone_item() return new Item_float(item_name.ptr(), value.real, decimals, max_length); case STRING_VALUE: case LONG_DATA_VALUE: - return new Item_string(item_name.ptr(), str_value.c_ptr_quick(), str_value.length(), + return new Item_string(item_name, str_value.c_ptr_quick(), str_value.length(), str_value.charset()); case TIME_VALUE: break; @@ -6007,7 +6019,7 @@ void Item_field::make_field(Send_field * { field->make_field(tmp_field); DBUG_ASSERT(tmp_field->table_name != 0); - if (item_name.ptr()) + if (item_name.is_set()) tmp_field->col_name= item_name.ptr(); // Use user supplied name if (table_name) tmp_field->table_name= table_name; @@ -7315,8 +7327,7 @@ void Item_ref::print(String *str, enum_q !table_name && item_name.ptr() && alias_name_used) { THD *thd= current_thd; - append_identifier(thd, str, (*ref)->real_item()->item_name.ptr(), - (*ref)->real_item()->item_name.length()); + append_identifier(thd, str, (*ref)->real_item()->item_name); } else (*ref)->print(str, query_type); @@ -7531,7 +7542,7 @@ void Item_ref::make_field(Send_field *fi { (*ref)->make_field(field); /* Non-zero in case of a view */ - if (item_name.ptr()) + if (item_name.is_set()) field->col_name= item_name.ptr(); if (table_name) field->table_name= table_name; @@ -8152,7 +8163,7 @@ void resolve_const_item(THD *thd, Item * return; // Can't be better Item_result res_type=item_cmp_type(comp_item->result_type(), item->result_type()); - char *name= item->item_name.ptr(); // Alloced by sql_alloc + const char *name= item->item_name.ptr(); // Alloced by sql_alloc switch (res_type) { case STRING_RESULT: @@ -8173,7 +8184,7 @@ void resolve_const_item(THD *thd, Item * { uint length= result->length(); char *tmp_str= sql_strmake(result->ptr(), length); - new_item= new Item_string(name, tmp_str, length, result->charset()); + new_item= new Item_string(item->item_name, tmp_str, length, result->charset()); } break; } @@ -9085,7 +9096,7 @@ bool Item_type_holder::join_types(THD *t DBUG_ENTER("Item_type_holder::join_types"); DBUG_PRINT("info:", ("was type %d len %d, dec %d name %s", fld_type, max_length, decimals, - (item_name.ptr() ? item_name.ptr() : ""))); + (item_name.is_set() ? item_name.ptr() : ""))); DBUG_PRINT("info:", ("in type %d len %d, dec %d", get_real_type(item), item->max_length, item->decimals)); === modified file 'sql/item.h' --- a/sql/item.h 2012-03-30 15:38:01 +0000 +++ b/sql/item.h 2012-04-12 15:31:01 +0000 @@ -143,6 +143,130 @@ public: }; /*************************************************************************/ + +/** + Storage for name strings. + Enpowers SimpleCString with allocation routines from the sql_strmake family. +*/ +class NameString: public SimpleCString +{ +private: + void set_or_copy(const char *str, uint length, bool is_null_terminated) + { + if (is_null_terminated) + set(str, length); + else + copy(str, length); + } +public: + NameString(): SimpleCString() {} + NameString(const char *str, uint length): + SimpleCString(str, length) {} + NameString(const LEX_STRING str): SimpleCString(str) {} + NameString(const char *str, uint length, bool is_null_terminated): + SimpleCString() + { + set_or_copy(str, length, is_null_terminated); + } + NameString(const LEX_STRING str, bool is_null_terminated): + SimpleCString() + { + set_or_copy(str.str, str.length, is_null_terminated); + } + /** + Allocate space using sql_strmake() or sql_strmake_with_convert(). + */ + void copy(const char *str, uint length, const CHARSET_INFO *cs); + /** + Variants for copy(), for various argument combinations. + */ + void copy(const char *str, uint length) + { + copy(str, length, system_charset_info); + } + void copy(const char *str) + { + copy(str, (uint) (str ? strlen(str) : 0), system_charset_info); + } + void copy(const LEX_STRING lex) + { + copy(lex.str, lex.length); + } + void copy(const LEX_STRING *lex) + { + copy(lex->str, lex->length); + } + void copy(const NameString str) + { + copy(str.ptr(), str.length()); + } + /** + Compare name to another name in C string, case insensitively. + */ + bool eq(const char *str) const + { + DBUG_ASSERT(str && ptr()); + return my_strcasecmp(system_charset_info, ptr(), str) == 0; + } + bool eq_safe(const char *str) const + { + return is_set() && str && eq(str); + } + /** + Compare name to another name in NameString, case insensitively. + */ + bool eq(const NameString name) const + { + return eq(name.ptr()); + } + bool eq_safe(const NameString name) const + { + return is_set() && name.is_set() && eq(name); + } +}; + + +extern NameString null_name_string; + + +/** + Storage for Item names. + Adds "autogenerated" flag and warning functionality to NameString. +*/ +class ItemNameString: public NameString +{ +private: + bool m_is_autogenerated; /* indicates if name of this Item + was autogenerated or set by user */ +public: + ItemNameString(): NameString(), m_is_autogenerated(true) + { } + ItemNameString(const NameString name) + :NameString(name), m_is_autogenerated(true) + { } + /** + Set m_is_autogenerated flag to the given value. + */ + void set_autogenerated(bool is_autogenerated) + { + m_is_autogenerated= is_autogenerated; + } + /** + Return the auto-generated flag. + */ + bool is_autogenerated() const { return m_is_autogenerated; } + using NameString::copy; + /** + Copy name together with autogenerated flag. + Produce a warning if name was cut. + */ + void copy(const char *str_arg, uint length_arg, const CHARSET_INFO *cs_arg, + bool is_autogenerated_arg); +}; + + + +/*************************************************************************/ /* A framework to easily handle different return types for hybrid items (hybrid item is an item whose operand can be of any type, e.g. integer, @@ -504,87 +628,6 @@ typedef Item* (Item::*Item_transformer) typedef void (*Cond_traverser) (const Item *item, void *arg); -class NameString -{ -private: - char *m_str; - uint m_length; - bool m_is_autogenerated; /* indicates if name of this Item - was autogenerated or set by user */ -public: - NameString() - { - m_str= 0; - m_length= 0; - m_is_autogenerated= true; - } - /** - Set m_is_autogenerated flag to the given value. - */ - void set_autogenerated(bool is_autogenerated) - { - m_is_autogenerated= is_autogenerated; - } - /** - Allocate space using sql_strmake() or sql_strmake_with_convert(). - */ - void copy(const char *str, uint length, const CHARSET_INFO *cs); - /** - Variants for copy(), for various argument combinations. - */ - void copy(const char *str, uint length, const CHARSET_INFO *cs, - bool is_autogenerated) - { - m_is_autogenerated= is_autogenerated; // Must be done before set/copy - copy(str, length, cs); - } - void copy(const char *str, uint length) - { - copy(str, length, system_charset_info); - } - void copy(const char *str) - { - copy(str, (uint) (str ? strlen(str) : 0), system_charset_info); - } - /** - Set name to the existing memory. No allocation happens. - */ - void set(const char *str) - { - m_str= (char *) str; - m_length= str ? strlen(str) : 0; - } - /** - Return name buffer. - */ - char *ptr() const { return m_str; } - /** - Return name length. - */ - uint length() const { return m_length; } - /** - Return if name was auto-generated. - */ - bool is_autogenerated() const { return m_is_autogenerated; } - /** - Compare name to another name in NameString. - */ - bool eq(const NameString *name) const - { - return ptr() && name->ptr() && - my_strcasecmp(system_charset_info, ptr(), name->ptr()) == 0; - } - /** - Compare name to another name in C string. - */ - bool eq(const char *str) const - { - return ptr() && str && - my_strcasecmp(system_charset_info, ptr(), str) == 0; - } -}; - - class Item { Item(const Item &); /* Prevent use of these */ @@ -624,8 +667,8 @@ public: */ String str_value; - NameString item_name; /* Name from select */ - NameString orig_name; /* Original item name (if it was renamed)*/ + ItemNameString item_name; /* Name from select */ + ItemNameString orig_name; /* Original item name (if it was renamed)*/ /** Intrusive list pointer for free list. If not null, points to the next @@ -1085,7 +1128,7 @@ public: virtual Field *tmp_table_field(TABLE *t_arg) { return 0; } virtual const char *full_name() const { - return item_name.ptr() ? item_name.ptr() : "???"; + return item_name.is_set() ? item_name.ptr() : "???"; } /* @@ -1610,7 +1653,7 @@ public: in the statement memory. If the name is auto generated, it must be done again between subsequent executions of a prepared statement. */ - if (orig_name.ptr()) + if (orig_name.is_set()) item_name= orig_name; } }; @@ -1633,7 +1676,7 @@ protected: THD *m_thd; public: - LEX_STRING m_name; + NameString m_name; public: #ifndef DBUG_OFF @@ -1645,7 +1688,7 @@ public: #endif public: - Item_sp_variable(char *sp_var_name_str, uint sp_var_name_length); + Item_sp_variable(const NameString sp_var_name); public: bool fix_fields(THD *thd, Item **); @@ -1671,11 +1714,7 @@ public: inline void Item_sp_variable::make_field(Send_field *field) { Item *it= this_item(); - - if (item_name.ptr()) - it->item_name.copy(item_name.ptr(), (uint) item_name.length()); - else - it->item_name.copy(m_name.str, (uint) m_name.length); + it->item_name.copy(item_name.is_set() ? item_name : m_name); it->make_field(field); } @@ -1731,7 +1770,7 @@ public: */ uint len_in_query; - Item_splocal(const LEX_STRING &sp_var_name, uint sp_var_idx, + Item_splocal(const NameString sp_var_name, uint sp_var_idx, enum_field_types sp_var_type, uint pos_in_q= 0, uint len_in_q= 0); @@ -1744,8 +1783,6 @@ public: virtual void print(String *str, enum_query_type query_type); public: - inline const LEX_STRING *my_name() const; - inline uint get_var_idx() const; inline enum Type type() const; @@ -1766,11 +1803,6 @@ public: Item_splocal inline implementation. *****************************************************************************/ -inline const LEX_STRING *Item_splocal::my_name() const -{ - return &m_name; -} - inline uint Item_splocal::get_var_idx() const { return m_var_idx; @@ -2180,7 +2212,7 @@ public: class Item_null :public Item_basic_constant { public: - Item_null(char *name_par=0) + Item_null(const char *name_par=0) { maybe_null= null_value= TRUE; max_length= 0; @@ -2646,6 +2678,7 @@ public: class Item_string :public Item_basic_constant { public: + /* Create from a string, set name from the string itself. */ Item_string(const char *str,uint length, const CHARSET_INFO *cs, Derivation dv= DERIVATION_COERCIBLE, uint repertoire= MY_REPERTOIRE_UNICODE30) @@ -2672,11 +2705,11 @@ public: { collation.set(cs, dv); max_length= 0; - item_name.copy(NULL, 0, cs); decimals= NOT_FIXED_DEC; fixed= 1; } - Item_string(const char *name_par, const char *str, uint length, + /* Create from the given name and string. */ + Item_string(const NameString name_par, const char *str, uint length, const CHARSET_INFO *cs, Derivation dv= DERIVATION_COERCIBLE, uint repertoire= MY_REPERTOIRE_UNICODE30) : m_cs_specified(FALSE) @@ -2684,7 +2717,7 @@ public: str_value.set_or_copy_aligned(str, length, cs); collation.set(cs, dv, repertoire); max_length= str_value.numchars()*cs->mbmaxlen; - item_name.copy(name_par, 0, cs); + item_name= name_par; decimals=NOT_FIXED_DEC; // it is constant => can be used without fix_fields (and frequently used) fixed= 1; @@ -2728,7 +2761,7 @@ public: bool eq(const Item *item, bool binary_cmp) const; Item *clone_item() { - return new Item_string(item_name.ptr(), str_value.ptr(), + return new Item_string((NameString) item_name, str_value.ptr(), str_value.length(), collation.collation); } Item *safe_charset_converter(const CHARSET_INFO *tocs); @@ -2799,7 +2832,7 @@ public: Item_static_string_func(const char *name_par, const char *str, uint length, const CHARSET_INFO *cs, Derivation dv= DERIVATION_COERCIBLE) - :Item_string(NullS, str, length, cs, dv), func_name(name_par) + :Item_string(null_name_string, str, length, cs, dv), func_name(name_par) {} Item *safe_charset_converter(const CHARSET_INFO *tocs); @@ -2816,10 +2849,12 @@ public: class Item_partition_func_safe_string: public Item_string { public: - Item_partition_func_safe_string(const char *name, uint length, + Item_partition_func_safe_string(const NameString name, uint length, const CHARSET_INFO *cs= NULL): - Item_string(name, length, cs) - {} + Item_string(name, NullS, 0, cs) + { + max_length= length; + } }; @@ -2828,7 +2863,8 @@ class Item_return_date_time :public Item enum_field_types date_time_field_type; public: Item_return_date_time(const char *name_arg, enum_field_types field_type_arg) - :Item_partition_func_safe_string(name_arg, 0, &my_charset_bin), + :Item_partition_func_safe_string(NameString((char *) name_arg, strlen(name_arg)), + 0, &my_charset_bin), date_time_field_type(field_type_arg) { decimals= 0; } enum_field_types field_type() const { return date_time_field_type; } @@ -2839,8 +2875,9 @@ class Item_blob :public Item_partition_f { public: Item_blob(const char *name, uint length) : - Item_partition_func_safe_string(name, length, &my_charset_bin) - { max_length= length; } + Item_partition_func_safe_string(NameString((char *) name, strlen(name)), + length, &my_charset_bin) + { } enum Type type() const { return TYPE_HOLDER; } enum_field_types field_type() const { return MYSQL_TYPE_BLOB; } }; @@ -2857,9 +2894,9 @@ class Item_empty_string :public Item_par public: Item_empty_string(const char *header, uint length, const CHARSET_INFO *cs= NULL) : - Item_partition_func_safe_string("",0, cs ? cs : &my_charset_utf8_general_ci) + Item_partition_func_safe_string(NameString((char *)header, strlen(header)), + 0, cs ? cs : &my_charset_utf8_general_ci) { - item_name.set(header); max_length= length * collation.collation->mbmaxlen; } void make_field(Send_field *field); === modified file 'sql/item_func.cc' --- a/sql/item_func.cc 2012-03-30 15:38:01 +0000 +++ b/sql/item_func.cc 2012-04-12 15:31:01 +0000 @@ -3584,7 +3584,7 @@ udf_handler::fix_fields(THD *thd, Item_r f_args.lengths[i]= arguments[i]->max_length; f_args.maybe_null[i]= (char) arguments[i]->maybe_null; - f_args.attributes[i]= arguments[i]->item_name.ptr(); + f_args.attributes[i]= (char*) arguments[i]->item_name.ptr(); f_args.attribute_lengths[i]= arguments[i]->item_name.length(); if (arguments[i]->const_item()) @@ -4546,23 +4546,23 @@ longlong Item_func_sleep::val_int() #define extra_size sizeof(double) -static user_var_entry *get_variable(HASH *hash, LEX_STRING &name, +static user_var_entry *get_variable(HASH *hash, NameString &name, bool create_if_not_exists) { user_var_entry *entry; - if (!(entry = (user_var_entry*) my_hash_search(hash, (uchar*) name.str, - name.length)) && + if (!(entry = (user_var_entry*) my_hash_search(hash, (uchar*) name.ptr(), + name.length())) && create_if_not_exists) { - uint size=ALIGN_SIZE(sizeof(user_var_entry))+name.length+1+extra_size; + uint size=ALIGN_SIZE(sizeof(user_var_entry))+name.length()+1+extra_size; if (!my_hash_inited(hash)) return 0; if (!(entry = (user_var_entry*) my_malloc(size,MYF(MY_WME | ME_FATALERROR)))) return 0; entry->name.str=(char*) entry+ ALIGN_SIZE(sizeof(user_var_entry))+ extra_size; - entry->name.length=name.length; + entry->name.length= name.length(); entry->value=0; entry->length=0; entry->update_query_id=0; @@ -4580,7 +4580,7 @@ static user_var_entry *get_variable(HASH */ entry->used_query_id=current_thd->query_id; entry->type=STRING_RESULT; - memcpy(entry->name.str, name.str, name.length+1); + name.strcpy(entry->name.str); if (my_hash_insert(hash,(uchar*) entry)) { my_free(entry); @@ -5162,7 +5162,7 @@ bool Item_func_set_user_var::is_null_res void Item_func_set_user_var::print(String *str, enum_query_type query_type) { str->append(STRING_WITH_LEN("(@")); - str->append(name.str, name.length); + str->append(name); str->append(STRING_WITH_LEN(":=")); args[0]->print(str, query_type); str->append(')'); @@ -5173,7 +5173,7 @@ void Item_func_set_user_var::print_as_st enum_query_type query_type) { str->append(STRING_WITH_LEN("set @")); - str->append(name.str, name.length); + str->append(name); str->append(STRING_WITH_LEN(":=")); args[0]->print(str, query_type); str->append(')'); @@ -5196,7 +5196,7 @@ void Item_func_set_user_var::make_field( { result_field->make_field(tmp_field); DBUG_ASSERT(tmp_field->table_name != 0); - if (Item::item_name.ptr()) + if (Item::item_name.is_set()) tmp_field->col_name=Item::item_name.ptr(); // Use user supplied name } else @@ -5365,7 +5365,7 @@ longlong Item_func_get_user_var::val_int static int get_var_with_binlog(THD *thd, enum_sql_command sql_command, - LEX_STRING &name, user_var_entry **out_entry) + NameString &name, user_var_entry **out_entry) { BINLOG_USER_VAR_EVENT *user_var_event; user_var_entry *var_entry; @@ -5548,7 +5548,7 @@ enum Item_result Item_func_get_user_var: void Item_func_get_user_var::print(String *str, enum_query_type query_type) { str->append(STRING_WITH_LEN("(@")); - str->append(name.str,name.length); + str->append(name); str->append(')'); } @@ -5563,15 +5563,14 @@ bool Item_func_get_user_var::eq(const It ((Item_func*) item)->functype() != functype()) return 0; Item_func_get_user_var *other=(Item_func_get_user_var*) item; - return (name.length == other->name.length && - !memcmp(name.str, other->name.str, name.length)); + return name.eq_bin(other->name); } bool Item_func_get_user_var::set_value(THD *thd, sp_rcontext * /*ctx*/, Item **it) { - Item_func_set_user_var *suv= new Item_func_set_user_var(get_name(), *it); + Item_func_set_user_var *suv= new Item_func_set_user_var(name, *it); /* Item_func_set_user_var is not fixed after construction, call fix_fields(). @@ -5647,7 +5646,7 @@ my_decimal* Item_user_var_as_out_param:: void Item_user_var_as_out_param::print(String *str, enum_query_type query_type) { str->append('@'); - str->append(name.str,name.length); + str->append(name); } @@ -6805,7 +6804,7 @@ Item_func_sp::make_field(Send_field *tmp DBUG_ENTER("Item_func_sp::make_field"); DBUG_ASSERT(sp_result_field); sp_result_field->make_field(tmp_field); - if (item_name.ptr()) + if (item_name.is_set()) tmp_field->col_name= item_name.ptr(); DBUG_VOID_RETURN; } === modified file 'sql/item_func.h' --- a/sql/item_func.h 2012-03-30 15:38:01 +0000 +++ b/sql/item_func.h 2012-04-12 15:31:01 +0000 @@ -1634,8 +1634,8 @@ class Item_func_set_user_var :public Ite } save_result; public: - LEX_STRING name; // keep it public - Item_func_set_user_var(LEX_STRING a,Item *b) + NameString name; // keep it public + Item_func_set_user_var(NameString a, Item *b) :Item_var_func(b), cached_result_type(INT_RESULT), entry(NULL), entry_thread_id(0), name(a) {} @@ -1689,11 +1689,10 @@ class Item_func_get_user_var :public Ite Item_result m_cached_result_type; public: - LEX_STRING name; // keep it public - Item_func_get_user_var(LEX_STRING a): + NameString name; // keep it public + Item_func_get_user_var(NameString a): Item_var_func(), m_cached_result_type(STRING_RESULT), name(a) {} enum Functype functype() const { return GUSERVAR_FUNC; } - LEX_STRING get_name() { return name; } double val_real(); longlong val_int(); my_decimal *val_decimal(my_decimal*); @@ -1732,11 +1731,11 @@ public: */ class Item_user_var_as_out_param :public Item { - LEX_STRING name; + NameString name; user_var_entry *entry; public: - Item_user_var_as_out_param(LEX_STRING a) : name(a) - { item_name.copy(a.str, 0); } + Item_user_var_as_out_param(NameString a) :name(a) + { item_name.copy(a); } /* We should return something different from FIELD_ITEM here */ enum Type type() const { return STRING_ITEM;} double val_real(); === modified file 'sql/item_timefunc.h' --- a/sql/item_timefunc.h 2012-03-30 15:38:01 +0000 +++ b/sql/item_timefunc.h 2012-04-12 15:31:01 +0000 @@ -899,7 +899,7 @@ public: void cleanup() { // See Item_basic_const::cleanup() - if (orig_name.ptr()) + if (orig_name.is_set()) item_name= orig_name; } bool eq(const Item *item, bool binary_cmp) const; @@ -956,7 +956,7 @@ public: void cleanup() { // See Item_basic_const::cleanup() - if (orig_name.ptr()) + if (orig_name.is_set()) item_name= orig_name; } bool eq(const Item *item, bool binary_cmp) const; @@ -1013,7 +1013,7 @@ public: void cleanup() { // See Item_basic_const::cleanup() - if (orig_name.ptr()) + if (orig_name.is_set()) item_name= orig_name; } bool eq(const Item *item, bool binary_cmp) const; === modified file 'sql/item_xmlfunc.cc' --- a/sql/item_xmlfunc.cc 2012-03-13 13:27:02 +0000 +++ b/sql/item_xmlfunc.cc 2012-04-12 15:31:01 +0000 @@ -2485,7 +2485,7 @@ my_xpath_parse_VariableReference(MY_XPAT name.str= (char*) xpath->prevtok.beg; if (user_var) - xpath->item= new Item_func_get_user_var(name); + xpath->item= new Item_func_get_user_var(NameString(name, false)); else { sp_variable *spv; @@ -2495,7 +2495,8 @@ my_xpath_parse_VariableReference(MY_XPAT (spc= lex->get_sp_current_parsing_ctx()) && (spv= spc->find_variable(name, false))) { - Item_splocal *splocal= new Item_splocal(name, spv->offset, spv->type, 0); + Item_splocal *splocal= new Item_splocal(NameString(name, false), + spv->offset, spv->type, 0); #ifndef DBUG_OFF if (splocal) splocal->m_sp= lex->sphead; === modified file 'sql/log_event.cc' --- a/sql/log_event.cc 2012-04-12 08:43:18 +0000 +++ b/sql/log_event.cc 2012-04-12 15:31:01 +0000 @@ -7388,9 +7388,6 @@ int User_var_log_event::do_apply_event(R CHARSET_INFO *charset; if (!(charset= get_charset(charset_number, MYF(MY_WME)))) return 1; - LEX_STRING user_var_name; - user_var_name.str= name; - user_var_name.length= name_len; double real_val; longlong int_val; @@ -7436,7 +7433,7 @@ int User_var_log_event::do_apply_event(R return 0; } } - Item_func_set_user_var e(user_var_name, it); + Item_func_set_user_var e(NameString(name, name_len, false), it); /* Item_func_set_user_var can't substitute something else on its place => 0 can be passed as last argument (reference on item) === modified file 'sql/sp_head.cc' --- a/sql/sp_head.cc 2012-03-31 18:30:05 +0000 +++ b/sql/sp_head.cc 2012-04-12 15:31:01 +0000 @@ -1010,7 +1010,7 @@ subst_spvars(THD *thd, sp_instr *instr, /* append the spvar substitute */ res|= qbuf.append(STRING_WITH_LEN(" NAME_CONST('")); - res|= qbuf.append((*splocal)->m_name.str, (*splocal)->m_name.length); + res|= qbuf.append((*splocal)->m_name); res|= qbuf.append(STRING_WITH_LEN("',")); if (res) @@ -2814,7 +2814,7 @@ sp_head::show_routine_code(THD *thd) if (check_show_routine_access(thd, this, &full_access) || !full_access) DBUG_RETURN(1); - field_list.push_back(new Item_uint("Pos", 9)); + field_list.push_back(new Item_uint("Pos", 0, 9)); // 1024 is for not to confuse old clients field_list.push_back(new Item_empty_string("Instruction", max(buffer.length(), 1024U))); === modified file 'sql/sql_analyse.cc' --- a/sql/sql_analyse.cc 2012-03-30 15:38:01 +0000 +++ b/sql/sql_analyse.cc 2012-04-12 15:31:01 +0000 @@ -70,7 +70,7 @@ Procedure * proc_analyse_init(THD *thd, ORDER *param, select_result *result, List &field_list) { - char *proc_name = (*param->item)->item_name.ptr(); + const char *proc_name = (*param->item)->item_name.ptr(); analyse *pc = new analyse(result); field_info **f_info; DBUG_ENTER("proc_analyse_init"); === modified file 'sql/sql_base.cc' --- a/sql/sql_base.cc 2012-04-05 07:59:23 +0000 +++ b/sql/sql_base.cc 2012-04-13 07:25:44 +0000 @@ -7259,7 +7259,7 @@ find_item_in_list(Item *find, List (if this field created from expression argument of group_concat()), => we have to check presence of name before compare */ - if (!item_field->item_name.ptr()) + if (!item_field->item_name.is_set()) continue; if (table_name) @@ -7314,7 +7314,7 @@ find_item_in_list(Item *find, List int fname_cmp= my_strcasecmp(system_charset_info, item_field->field_name, field_name); - if (item_field->item_name.eq(field_name)) + if (item_field->item_name.eq_safe(field_name)) { /* If table name was not given we should scan through aliases @@ -7358,7 +7358,7 @@ find_item_in_list(Item *find, List } else if (!table_name) { - if (is_ref_by_name && item->item_name.eq(&find->item_name)) + if (is_ref_by_name && item->item_name.eq_safe(find->item_name)) { found= li.ref(); *counter= i; @@ -7389,7 +7389,7 @@ find_item_in_list(Item *find, List Item_field for tables. */ Item_ident *item_ref= (Item_ident *) item; - if (item_ref->item_name.eq(field_name) && + if (item_ref->item_name.eq_safe(field_name) && item_ref->table_name && !my_strcasecmp(table_alias_charset, item_ref->table_name, table_name) && === modified file 'sql/sql_executor.cc' --- a/sql/sql_executor.cc 2012-03-30 15:38:01 +0000 +++ b/sql/sql_executor.cc 2012-04-12 15:31:01 +0000 @@ -4839,7 +4839,7 @@ change_to_use_tmp_fields(THD *thd, Ref_p ifield->db_name= iref->db_name; } #ifndef DBUG_OFF - if (!item_field->item_name.ptr()) + if (!item_field->item_name.is_set()) { char buff[256]; String str(buff,sizeof(buff),&my_charset_bin); === modified file 'sql/sql_partition_admin.cc' --- a/sql/sql_partition_admin.cc 2012-04-02 12:41:08 +0000 +++ b/sql/sql_partition_admin.cc 2012-04-13 07:19:19 +0000 @@ -203,6 +203,19 @@ static bool compare_table_with_partition part_create_info.auto_increment_value= table_create_info.auto_increment_value; + /* Check compatible row_types and set create_info accordingly. */ + { + enum row_type part_row_type= part_table->file->get_row_type(); + enum row_type table_row_type= table->file->get_row_type(); + if (part_row_type != table_row_type) + { + my_error(ER_PARTITION_EXCHANGE_DIFFERENT_OPTION, MYF(0), + "ROW_FORMAT"); + DBUG_RETURN(true); + } + part_create_info.row_type= table->s->row_type; + } + /* NOTE: ha_blackhole does not support check_if_compatible_data, so this always fail for blackhole tables. @@ -222,6 +235,10 @@ static bool compare_table_with_partition my_error(ER_TABLES_DIFFERENT_METADATA, MYF(0)); DBUG_RETURN(TRUE); } + DBUG_ASSERT(table->s->db_create_options == + part_table->s->db_create_options); + DBUG_ASSERT(table->s->db_options_in_use == + part_table->s->db_options_in_use); if (table_create_info.avg_row_length != part_create_info.avg_row_length) { === modified file 'sql/sql_show.h' --- a/sql/sql_show.h 2011-12-09 21:08:37 +0000 +++ b/sql/sql_show.h 2012-04-12 15:31:01 +0000 @@ -166,6 +166,10 @@ int copy_event_to_schema_table(THD *thd, void append_identifier(THD *thd, String *packet, const char *name, uint length); +inline void append_identifier(THD *thd, String *packet, SimpleCString str) +{ + append_identifier(thd, packet, str.ptr(), str.length()); +} void mysqld_list_fields(THD *thd,TABLE_LIST *table, const char *wild); bool mysqld_show_create(THD *thd, TABLE_LIST *table_list); bool mysqld_show_create_db(THD *thd, char *dbname, HA_CREATE_INFO *create); === modified file 'sql/sql_string.h' --- a/sql/sql_string.h 2012-03-06 14:29:42 +0000 +++ b/sql/sql_string.h 2012-04-12 15:31:01 +0000 @@ -22,6 +22,85 @@ #include "my_sys.h" /* alloc_root, my_free, my_realloc */ #include "m_string.h" /* TRASH */ + +/** + A wrapper class for null-terminated constant strings. + Constructors make sure that the position of the '\0' terminating byte + in m_str is always in sync with m_length. +*/ +class SimpleCString +{ +private: + const char *m_str; + uint m_length; +protected: + /** + Initialize from a C string whose length is already known. + */ + void set(const char *str_arg, uint length_arg) + { + // NULL is allowed only with length==0 + DBUG_ASSERT(str_arg || length_arg == 0); + // For non-NULL, make sure length_arg is in sync with '\0' terminator. + DBUG_ASSERT(!str_arg || str_arg[length_arg] == '\0'); + m_str= str_arg; + m_length= length_arg; + } +public: + SimpleCString() + { + set(NULL, 0); + } + SimpleCString(const char *str_arg, uint length_arg) + { + set(str_arg, length_arg); + } + SimpleCString(const LEX_STRING arg) + { + set(arg.str, arg.length); + } + void reset() + { + set(NULL, 0); + } + /** + Set to a null-terminated string. + */ + void set(const char *str) + { + set(str, str ? strlen(str) : 0); + } + /** + Return string buffer. + */ + const char *ptr() const { return m_str; } + /** + Check if m_ptr is set. + */ + bool is_set() const { return m_str != NULL; } + /** + Return name length. + */ + uint length() const { return m_length; } + /** + Compare to another SimpleCString. + */ + bool eq_bin(const SimpleCString other) const + { + return m_length == other.m_length && + memcmp(m_str, other.m_str, m_length) == 0; + } + /** + Copy to the given buffer + */ + void strcpy(char *buff) const + { + memcpy(buff, m_str, m_length); + buff[m_length]= '\0'; + } +}; + + class String; typedef struct charset_info_st CHARSET_INFO; typedef struct st_io_cache IO_CACHE; @@ -290,6 +369,10 @@ public: { return append(ls->str, ls->length); } + bool append(SimpleCString str) + { + return append(str.ptr(), str.length()); + } bool append(const char *s, uint32 arg_length); bool append(const char *s, uint32 arg_length, const CHARSET_INFO *cs); bool append_ulonglong(ulonglong val); === modified file 'sql/sql_view.cc' --- a/sql/sql_view.cc 2012-03-30 15:38:01 +0000 +++ b/sql/sql_view.cc 2012-04-12 15:31:01 +0000 @@ -61,9 +61,8 @@ static void make_unique_view_field_name( List &item_list, Item *last_element) { - char *name= (target->orig_name.ptr() ? - target->orig_name.ptr() : - target->item_name.ptr()); + const char *name= (target->orig_name.is_set() ? + target->orig_name.ptr() : target->item_name.ptr()); size_t name_len; uint attempt; char buff[NAME_LEN+1]; @@ -137,7 +136,7 @@ bool check_duplicate_names(List &i itc.rewind(); while ((check= itc++) && check != item) { - if (item->item_name.eq(&check->item_name)) + if (item->item_name.eq(check->item_name)) { if (!gen_unique_view_name) goto err; === modified file 'sql/sql_yacc.yy' --- a/sql/sql_yacc.yy 2012-04-12 08:24:17 +0000 +++ b/sql/sql_yacc.yy 2012-04-12 15:31:01 +0000 @@ -8275,7 +8275,7 @@ select_item: } $2->item_name.copy($4.str, $4.length, system_charset_info, false); } - else if (!$2->item_name.ptr()) + else if (!$2->item_name.is_set()) { $2->item_name.copy($1, (uint) ($3 - $1), thd->charset()); } @@ -8885,7 +8885,7 @@ simple_expr: { Item_splocal *il= static_cast($3); - my_error(ER_WRONG_COLUMN_NAME, MYF(0), il->my_name()->str); + my_error(ER_WRONG_COLUMN_NAME, MYF(0), il->m_name.ptr()); MYSQL_YYABORT; } $$= new (YYTHD->mem_root) Item_default_value(Lex->current_context(), @@ -10994,7 +10994,7 @@ procedure_item: if (add_proc_to_list(thd, $2)) MYSQL_YYABORT; - if (!$2->item_name.ptr()) + if (!$2->item_name.is_set()) $2->item_name.copy($1, (uint) ($3 - $1), thd->charset()); } ; @@ -12781,7 +12781,7 @@ literal: Item_string *item_str; item_str= new (YYTHD->mem_root) - Item_string(NULL, /* name will be set in select_item */ + Item_string(null_name_string, /* name will be set in select_item */ str ? str->ptr() : "", str ? str->length() : 0, $1); @@ -12810,7 +12810,7 @@ literal: Item_string *item_str; item_str= new (YYTHD->mem_root) - Item_string(NULL, /* name will be set in select_item */ + Item_string(null_name_string, /* name will be set in select_item */ str ? str->ptr() : "", str ? str->length() : 0, $1); No bundle (reason: useless for push emails).