From dcbf2823c7d64380f06372d77d1522e97fb8f066 Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Fri, 10 Nov 2017 13:58:00 -0800 Subject: [PATCH 01/18] Fixed MDEV-13994 Bad join results with orderby_uses_equalities=on. This patch effectively blocks the optimization that uses multiple equalities for ORDER BY to remove tmp table in the case when the first table happens to be the result of materialization of a semi-join nest. Currently there is no code at the execution level that would support the optimization in this case. --- mysql-test/r/order_by.result | 48 +++++++++++++++++++ mysql-test/r/order_by_innodb.result | 73 +++++++++++++++++++++++++++++ mysql-test/t/order_by.test | 43 +++++++++++++++++ mysql-test/t/order_by_innodb.test | 47 +++++++++++++++++++ sql/sql_select.cc | 31 +++++++++++- 5 files changed, 241 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/order_by.result b/mysql-test/r/order_by.result index f43e6ce18af..5a9f2fae1e0 100644 --- a/mysql-test/r/order_by.result +++ b/mysql-test/r/order_by.result @@ -3159,3 +3159,51 @@ pk 2 3 DROP TABLE t1; +# +# MDEV-13994: Bad join results with orderby_uses_equalities=on +# +CREATE TABLE books ( +id int(16) NOT NULL AUTO_INCREMENT, +library_id int(16) NOT NULL DEFAULT 0, +wings_id int(12) NOT NULL DEFAULT 0, +scheduled_for_removal int(1) DEFAULT 0, +PRIMARY KEY (id), +KEY library_idx (library_id) +) ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; +INSERT INTO books VALUES (32625,8663,707,0),(32624,8663,505,1); +CREATE TABLE wings ( +id int(11) NOT NULL AUTO_INCREMENT, +department_id int(11) DEFAULT NULL, +PRIMARY KEY (id) +) ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; +INSERT INTO wings VALUES (505,11745),(707,11768); +SET @save_optimizer_switch=@@optimizer_switch; +SET optimizer_switch='orderby_uses_equalities=off'; +SELECT wings.id as wing_id, wings.department_id FROM wings +WHERE wings.id IN ( SELECT books.wings_id FROM books +WHERE books.library_id = 8663 AND +books.scheduled_for_removal=0 ) +ORDER BY wings.id; +wing_id department_id +707 11768 +SET optimizer_switch='orderby_uses_equalities=on'; +SELECT wings.id as wing_id, wings.department_id FROM wings +WHERE wings.id IN ( SELECT books.wings_id FROM books +WHERE books.library_id = 8663 AND +books.scheduled_for_removal=0 ) +ORDER BY wings.id; +wing_id department_id +707 11768 +explain extended SELECT wings.id as wing_id, wings.department_id FROM wings +WHERE wings.id IN ( SELECT books.wings_id FROM books +WHERE books.library_id = 8663 AND +books.scheduled_for_removal=0 ) +ORDER BY wings.id; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 PRIMARY ALL distinct_key NULL NULL NULL 1 100.00 Using temporary; Using filesort +1 PRIMARY wings eq_ref PRIMARY PRIMARY 4 test.books.wings_id 1 100.00 +2 MATERIALIZED books ref library_idx library_idx 4 const 1 100.00 Using where +Warnings: +Note 1003 select `test`.`wings`.`id` AS `wing_id`,`test`.`wings`.`department_id` AS `department_id` from `test`.`wings` semi join (`test`.`books`) where `test`.`books`.`library_id` = 8663 and `test`.`books`.`scheduled_for_removal` = 0 and `test`.`wings`.`id` = `test`.`books`.`wings_id` order by `test`.`wings`.`id` +set optimizer_switch= @save_optimizer_switch; +DROP TABLE books, wings; diff --git a/mysql-test/r/order_by_innodb.result b/mysql-test/r/order_by_innodb.result index 4f59a2f8c20..3ff1f92e94a 100644 --- a/mysql-test/r/order_by_innodb.result +++ b/mysql-test/r/order_by_innodb.result @@ -48,3 +48,76 @@ where key1<3 or key2<3; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 index_merge key1,key2 key1,key2 5,5 NULL # Using sort_union(key1,key2); Using where drop table t0, t1; +# +# MDEV-14071: wrong results with orderby_uses_equalities=on +# (duplicate of MDEV-13994) +# +CREATE TABLE t1 (i int, j int, z int,PRIMARY KEY (i,j), KEY (z)) ENGINE=InnoDB; +CREATE TABLE t2 (i int, j int, PRIMARY KEY (i,j)) ENGINE=InnoDB; +CREATE TABLE t3 (j int, n varchar(5), PRIMARY KEY (j)) ENGINE=InnoDB; +INSERT INTO t1 VALUES +(127,0,1),(188,0,1),(206,0,1),(218,0,1),(292,0,1),(338,0,1),(375,0,1), +(381,0,1),(409,0,1),(466,0,1),(469,0,1),(498,0,1),(656,0,1); +INSERT INTO t1 VALUES +(77,4,0),(86,7,0),(96,6,0),(96,7,0),(99,9,0),(99,10,0),(99,11,0),(104,4,0), +(106,5,0),(148,6,0),(177,6,0),(181,5,0),(188,8,0),(218,8,0),(253,7,0), +(268,4,0),(338,4,0),(409,7,0),(466,8,0),(469,8,0),(498,8,0),(656,8,0); +INSERT INTO t2 VALUES +(127,7),(188,8),(188,9),(206,6),(218,8),(218,9),(292,7),(338,4),(338,5), +(375,6),(381,5),(409,7),(409,8),(466,8),(466,9),(469,8),(469,9),(498,8), +(498,9),(656,8),(656,9); +INSERT INTO t3 VALUES +(4,'four'),(5,'five'),(6,'six'),(7,'seven'),(8,'eight'),(9,'nine'); +SET @save_optimizer_switch=@@optimizer_switch; +SET optimizer_switch='orderby_uses_equalities=off'; +SELECT i,n +FROM t1 INNER JOIN t2 USING (i,j) LEFT JOIN t3 USING (j) +WHERE i IN (SELECT i FROM t1 WHERE z=1) AND z=0 ORDER BY i; +i n +188 eight +218 eight +338 four +409 seven +466 eight +469 eight +498 eight +656 eight +SELECT i,n +FROM t1 x INNER JOIN t2 USING (i,j) LEFT JOIN t3 USING (j) +WHERE EXISTS (SELECT * FROM t1 WHERE i=x.i AND z=1) AND z=0 ORDER BY i; +i n +188 eight +218 eight +338 four +409 seven +466 eight +469 eight +498 eight +656 eight +SET optimizer_switch='orderby_uses_equalities=on'; +SELECT i,n +FROM t1 INNER JOIN t2 USING (i,j) LEFT JOIN t3 USING (j) +WHERE i IN (SELECT i FROM t1 WHERE z=1) AND z=0 ORDER BY i; +i n +188 eight +218 eight +338 four +409 seven +466 eight +469 eight +498 eight +656 eight +SELECT i,n +FROM t1 x INNER JOIN t2 USING (i,j) LEFT JOIN t3 USING (j) +WHERE EXISTS (SELECT * FROM t1 WHERE i=x.i AND z=1) AND z=0 ORDER BY i; +i n +188 eight +218 eight +338 four +409 seven +466 eight +469 eight +498 eight +656 eight +set optimizer_switch= @save_optimizer_switch; +DROP TABLE t1,t2,t3; diff --git a/mysql-test/t/order_by.test b/mysql-test/t/order_by.test index 8722401ccae..914911648b2 100644 --- a/mysql-test/t/order_by.test +++ b/mysql-test/t/order_by.test @@ -2106,3 +2106,46 @@ INSERT INTO t1 VALUES (1),(2),(3); SELECT DISTINCT pk FROM t1 GROUP BY 'foo'; SELECT DISTINCT pk FROM t1; DROP TABLE t1; + +--echo # +--echo # MDEV-13994: Bad join results with orderby_uses_equalities=on +--echo # + +CREATE TABLE books ( + id int(16) NOT NULL AUTO_INCREMENT, + library_id int(16) NOT NULL DEFAULT 0, + wings_id int(12) NOT NULL DEFAULT 0, + scheduled_for_removal int(1) DEFAULT 0, + PRIMARY KEY (id), + KEY library_idx (library_id) +) ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; + +INSERT INTO books VALUES (32625,8663,707,0),(32624,8663,505,1); + +CREATE TABLE wings ( + id int(11) NOT NULL AUTO_INCREMENT, + department_id int(11) DEFAULT NULL, + PRIMARY KEY (id) +) ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; + +INSERT INTO wings VALUES (505,11745),(707,11768); + +let $q= +SELECT wings.id as wing_id, wings.department_id FROM wings + WHERE wings.id IN ( SELECT books.wings_id FROM books + WHERE books.library_id = 8663 AND + books.scheduled_for_removal=0 ) +ORDER BY wings.id; + +SET @save_optimizer_switch=@@optimizer_switch; + +SET optimizer_switch='orderby_uses_equalities=off'; +eval $q; + +SET optimizer_switch='orderby_uses_equalities=on'; +eval $q; +eval explain extended $q; + +set optimizer_switch= @save_optimizer_switch; + +DROP TABLE books, wings; diff --git a/mysql-test/t/order_by_innodb.test b/mysql-test/t/order_by_innodb.test index 097eddd24f1..0debb777749 100644 --- a/mysql-test/t/order_by_innodb.test +++ b/mysql-test/t/order_by_innodb.test @@ -61,3 +61,50 @@ from t1 where key1<3 or key2<3; drop table t0, t1; + +--echo # +--echo # MDEV-14071: wrong results with orderby_uses_equalities=on +--echo # (duplicate of MDEV-13994) +--echo # + +CREATE TABLE t1 (i int, j int, z int,PRIMARY KEY (i,j), KEY (z)) ENGINE=InnoDB; +CREATE TABLE t2 (i int, j int, PRIMARY KEY (i,j)) ENGINE=InnoDB; +CREATE TABLE t3 (j int, n varchar(5), PRIMARY KEY (j)) ENGINE=InnoDB; + +INSERT INTO t1 VALUES + (127,0,1),(188,0,1),(206,0,1),(218,0,1),(292,0,1),(338,0,1),(375,0,1), + (381,0,1),(409,0,1),(466,0,1),(469,0,1),(498,0,1),(656,0,1); +INSERT INTO t1 VALUES + (77,4,0),(86,7,0),(96,6,0),(96,7,0),(99,9,0),(99,10,0),(99,11,0),(104,4,0), + (106,5,0),(148,6,0),(177,6,0),(181,5,0),(188,8,0),(218,8,0),(253,7,0), + (268,4,0),(338,4,0),(409,7,0),(466,8,0),(469,8,0),(498,8,0),(656,8,0); + +INSERT INTO t2 VALUES + (127,7),(188,8),(188,9),(206,6),(218,8),(218,9),(292,7),(338,4),(338,5), + (375,6),(381,5),(409,7),(409,8),(466,8),(466,9),(469,8),(469,9),(498,8), + (498,9),(656,8),(656,9); +INSERT INTO t3 VALUES + (4,'four'),(5,'five'),(6,'six'),(7,'seven'),(8,'eight'),(9,'nine'); + +let $q1= +SELECT i,n +FROM t1 INNER JOIN t2 USING (i,j) LEFT JOIN t3 USING (j) +WHERE i IN (SELECT i FROM t1 WHERE z=1) AND z=0 ORDER BY i; +let $q2= +SELECT i,n +FROM t1 x INNER JOIN t2 USING (i,j) LEFT JOIN t3 USING (j) +WHERE EXISTS (SELECT * FROM t1 WHERE i=x.i AND z=1) AND z=0 ORDER BY i; + +SET @save_optimizer_switch=@@optimizer_switch; + +SET optimizer_switch='orderby_uses_equalities=off'; +eval $q1; +eval $q2; + +SET optimizer_switch='orderby_uses_equalities=on'; +eval $q1; +eval $q2; + +set optimizer_switch= @save_optimizer_switch; + +DROP TABLE t1,t2,t3; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 21e48c1ade7..676b26e7db0 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -12519,8 +12519,37 @@ remove_const(JOIN *join,ORDER *first_order, COND *cond, can be used without tmp. table. */ bool can_subst_to_first_table= false; + bool first_is_in_sjm_nest= false; + if (first_is_base_table) + { + TABLE_LIST *tbl_for_first= + join->join_tab[join->const_tables].table->pos_in_table_list; + first_is_in_sjm_nest= tbl_for_first->sj_mat_info && + tbl_for_first->sj_mat_info->is_used; + } + /* + Currently we do not employ the optimization that uses multiple + equalities for ORDER BY to remove tmp table in the case when + the first table happens to be the result of materialization of + a semi-join nest ( <=> first_is_in_sjm_nest == true). + + When a semi-join nest is materialized and scanned to look for + possible matches in the remaining tables for every its row + the fields from the result of materialization are copied + into the record buffers of tables from the semi-join nest. + So these copies are used to access the remaining tables rather + than the fields from the result of materialization. + + Unfortunately now this so-called 'copy back' technique is + supported only if the rows are scanned with the rr_sequential + function, but not with other rr_* functions that are employed + when the result of materialization is required to be sorted. + + TODO: either to support 'copy back' technique for the above case, + or to get rid of this technique altogether. + */ if (optimizer_flag(join->thd, OPTIMIZER_SWITCH_ORDERBY_EQ_PROP) && - first_is_base_table && + first_is_base_table && !first_is_in_sjm_nest && order->item[0]->real_item()->type() == Item::FIELD_ITEM && join->cond_equal) { From 1e2d4f677e08294691a7d218acb3b9f78727ae18 Mon Sep 17 00:00:00 2001 From: Alexey Botchkov Date: Sat, 11 Nov 2017 13:54:56 +0400 Subject: [PATCH 02/18] MDEV-13971 crash in skip_num_constant. Character bigger than 0x60 wasn't handled properly inside a numeric constant. --- mysql-test/r/func_json.result | 3 +++ mysql-test/t/func_json.test | 4 ++++ strings/json_lib.c | 2 +- 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/func_json.result b/mysql-test/r/func_json.result index dc27062bc27..041030f4aab 100644 --- a/mysql-test/r/func_json.result +++ b/mysql-test/r/func_json.result @@ -725,3 +725,6 @@ json_contains_path('{"foo":"bar"}', 'one', '$[]') NULL Warnings: Warning 4042 Syntax error in JSON path in argument 3 to function 'json_contains_path' at position 3 +select JSON_VALID(0x36f0c8dccd83c5eac156da); +JSON_VALID(0x36f0c8dccd83c5eac156da) +0 diff --git a/mysql-test/t/func_json.test b/mysql-test/t/func_json.test index 2b865360b51..2052fad0c04 100644 --- a/mysql-test/t/func_json.test +++ b/mysql-test/t/func_json.test @@ -378,3 +378,7 @@ SELECT JSON_OBJECT("user","Jožko Mrkvičká") as json_data; select json_contains_path('{"foo":"bar"}', 'one', '$[]'); +# +# MDEV-13971 crash in skip_num_constant. +# +select JSON_VALID(0x36f0c8dccd83c5eac156da); diff --git a/strings/json_lib.c b/strings/json_lib.c index cf99afd6f7b..413ce128149 100644 --- a/strings/json_lib.c +++ b/strings/json_lib.c @@ -503,7 +503,7 @@ static int skip_num_constant(json_engine_t *j) for (;;) { j->num_flags|= json_num_state_flags[state]; - if ((c_len= json_next_char(&j->s)) > 0) + if ((c_len= json_next_char(&j->s)) > 0 && j->s.c_next < 128) { if ((state= json_num_states[state][json_num_chr_map[j->s.c_next]]) > 0) { From 17bd6ed29ad32c2c99d503db9a167aca16558c99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Sat, 11 Nov 2017 22:48:19 +0200 Subject: [PATCH 03/18] Remove STATUS_VERBOSE (there is no visible output) --- storage/innobase/buf/buf0dump.cc | 47 -------------------------------- 1 file changed, 47 deletions(-) diff --git a/storage/innobase/buf/buf0dump.cc b/storage/innobase/buf/buf0dump.cc index 945a1543b72..b1614e0a580 100644 --- a/storage/innobase/buf/buf0dump.cc +++ b/storage/innobase/buf/buf0dump.cc @@ -47,7 +47,6 @@ Created April 08, 2011 Vasil Dimov #include "mysql/service_wsrep.h" /* wsrep_recovery */ enum status_severity { - STATUS_VERBOSE, STATUS_INFO, STATUS_ERR }; @@ -133,9 +132,6 @@ buf_dump_status( case STATUS_ERR: ib::error() << export_vars.innodb_buffer_pool_dump_status; break; - - case STATUS_VERBOSE: - break; } va_end(ap); @@ -175,9 +171,6 @@ buf_load_status( case STATUS_ERR: ib::error() << export_vars.innodb_buffer_pool_load_status; break; - - case STATUS_VERBOSE: - break; } va_end(ap); @@ -298,8 +291,6 @@ buf_dump( buf_dump_t* dump; ulint n_pages; ulint j; - ulint limit; - ulint counter; buf_pool = buf_pool_from_array(i); @@ -368,9 +359,6 @@ buf_dump( buf_pool_mutex_exit(buf_pool); - limit = (ulint)((double)n_pages * ((double)srv_buf_dump_status_frequency / (double)100)); - counter = 0; - for (j = 0; j < n_pages && !SHOULD_QUIT(); j++) { ret = fprintf(f, ULINTPF "," ULINTPF "\n", BUF_DUMP_SPACE(dump[j]), @@ -384,23 +372,6 @@ buf_dump( /* leave tmp_filename to exist */ return; } - - counter++; - - /* Print buffer pool dump status only if - srv_buf_dump_status_frequency is > 0 and - we have processed that amount of pages. */ - if (srv_buf_dump_status_frequency && - counter == limit) { - counter = 0; - buf_dump_status( - STATUS_VERBOSE, - "Dumping buffer pool" - " " ULINTPF "/%lu," - " page " ULINTPF "/" ULINTPF, - i + 1, srv_buf_pool_instances, - j + 1, n_pages); - } } ut_free(dump); @@ -718,21 +689,6 @@ buf_load() os_aio_simulated_wake_handler_threads(); } - /* Update the progress every 32 MiB, which is every Nth page, - where N = 32*1024^2 / page_size. */ - static const ulint update_status_every_n_mb = 32; - static const ulint update_status_every_n_pages - = update_status_every_n_mb * 1024 * 1024 - / page_size.physical(); - - if (i % update_status_every_n_pages == 0) { - buf_load_status(STATUS_VERBOSE, - "Loaded " ULINTPF "/" ULINTPF " pages", - i + 1, dump_n); - /* mysql_stage_set_work_completed(pfs_stage_progress, - i); */ - } - if (buf_load_abort_flag) { if (space != NULL) { fil_space_release(space); @@ -805,9 +761,6 @@ DECLARE_THREAD(buf_dump_thread)(void*) pfs_register_thread(buf_dump_thread_key); #endif */ /* UNIV_PFS_THREAD */ - buf_dump_status(STATUS_VERBOSE, "Dumping of buffer pool not started"); - buf_load_status(STATUS_VERBOSE, "Loading of buffer pool not started"); - if (srv_buffer_pool_load_at_startup) { #ifdef WITH_WSREP From c19ef508b89b8abd2d320153a3d8960f60a0ad84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Sat, 11 Nov 2017 23:07:24 +0200 Subject: [PATCH 04/18] InnoDB: Remove ut_snprintf() and the use of my_snprintf(); use snprintf() --- extra/mariabackup/backup_copy.cc | 13 +- extra/mariabackup/backup_mysql.cc | 14 +- extra/mariabackup/changed_page_bitmap.cc | 2 +- extra/mariabackup/xtrabackup.cc | 8 +- storage/innobase/buf/buf0dump.cc | 22 ++-- storage/innobase/dict/dict0dict.cc | 32 ++--- storage/innobase/dict/dict0mem.cc | 2 +- storage/innobase/dict/dict0stats.cc | 149 +++++++++++----------- storage/innobase/fts/fts0config.cc | 4 +- storage/innobase/fts/fts0fts.cc | 2 +- storage/innobase/handler/ha_innodb.cc | 22 ++-- storage/innobase/handler/handler0alter.cc | 4 +- storage/innobase/handler/i_s.cc | 26 ++-- storage/innobase/include/data0type.ic | 38 +++--- storage/innobase/include/ut0ut.h | 17 --- storage/innobase/os/os0file.cc | 7 +- storage/innobase/page/page0zip.cc | 4 +- storage/innobase/row/row0import.cc | 18 +-- storage/innobase/row/row0quiesce.cc | 6 +- storage/innobase/row/row0row.cc | 4 +- storage/innobase/row/row0trunc.cc | 14 +- storage/innobase/srv/srv0start.cc | 20 +-- storage/innobase/trx/trx0i_s.cc | 18 +-- storage/innobase/trx/trx0purge.cc | 8 +- storage/innobase/ut/ut0ut.cc | 37 ------ 25 files changed, 215 insertions(+), 276 deletions(-) diff --git a/extra/mariabackup/backup_copy.cc b/extra/mariabackup/backup_copy.cc index 0b501970efa..5c18098355f 100644 --- a/extra/mariabackup/backup_copy.cc +++ b/extra/mariabackup/backup_copy.cc @@ -252,9 +252,8 @@ datadir_iter_next_database(datadir_iter_t *it) it->dbpath = static_cast( malloc(it->dbpath_len)); } - ut_snprintf(it->dbpath, it->dbpath_len, - "%s/%s", it->datadir_path, - it->dbinfo.name); + snprintf(it->dbpath, it->dbpath_len, "%s/%s", + it->datadir_path, it->dbinfo.name); os_normalize_path(it->dbpath); if (it->dbinfo.type == OS_FILE_TYPE_FILE) { @@ -1034,8 +1033,8 @@ move_file(ds_ctxt_t *datasink, char dst_dir_abs[FN_REFLEN]; size_t dirname_length; - ut_snprintf(dst_file_path_abs, sizeof(dst_file_path_abs), - "%s/%s", dst_dir, dst_file_path); + snprintf(dst_file_path_abs, sizeof(dst_file_path_abs), + "%s/%s", dst_dir, dst_file_path); dirname_part(dst_dir_abs, dst_file_path_abs, &dirname_length); @@ -1252,8 +1251,8 @@ backup_files(const char *from, bool prep_mode) } else if (!prep_mode) { /* backup fake file into empty directory */ char path[FN_REFLEN]; - ut_snprintf(path, sizeof(path), - "%s/db.opt", node.filepath); + snprintf(path, sizeof(path), + "%s/db.opt", node.filepath); if (!(ret = backup_file_printf( trim_dotslash(path), "%s", ""))) { msg("Failed to create file %s\n", path); diff --git a/extra/mariabackup/backup_mysql.cc b/extra/mariabackup/backup_mysql.cc index aa683e320fc..4a33f9ef4e5 100644 --- a/extra/mariabackup/backup_mysql.cc +++ b/extra/mariabackup/backup_mysql.cc @@ -589,7 +589,7 @@ select_incremental_lsn_from_history(lsn_t *incremental_lsn) mysql_real_escape_string(mysql_connection, buf, opt_incremental_history_name, (unsigned long)strlen(opt_incremental_history_name)); - ut_snprintf(query, sizeof(query), + snprintf(query, sizeof(query), "SELECT innodb_to_lsn " "FROM PERCONA_SCHEMA.xtrabackup_history " "WHERE name = '%s' " @@ -602,7 +602,7 @@ select_incremental_lsn_from_history(lsn_t *incremental_lsn) mysql_real_escape_string(mysql_connection, buf, opt_incremental_history_uuid, (unsigned long)strlen(opt_incremental_history_uuid)); - ut_snprintf(query, sizeof(query), + snprintf(query, sizeof(query), "SELECT innodb_to_lsn " "FROM PERCONA_SCHEMA.xtrabackup_history " "WHERE uuid = '%s' " @@ -766,7 +766,7 @@ kill_long_queries(MYSQL *connection, time_t timeout) is_select_query(info))) { msg_ts("Killing query %s (duration %d sec): %s\n", id, (int)duration, info); - ut_snprintf(kill_stmt, sizeof(kill_stmt), + snprintf(kill_stmt, sizeof(kill_stmt), "KILL %s", id); xb_mysql_query(connection, kill_stmt, false, false); } @@ -1288,8 +1288,8 @@ write_current_binlog_file(MYSQL *connection) goto cleanup; } - ut_snprintf(filepath, sizeof(filepath), "%s%c%s", - log_bin_dir, FN_LIBCHAR, log_bin_file); + snprintf(filepath, sizeof(filepath), "%s%c%s", + log_bin_dir, FN_LIBCHAR, log_bin_file); result = copy_file(ds_data, filepath, log_bin_file, 0); } @@ -1574,8 +1574,8 @@ char *make_argv(char *buf, size_t len, int argc, char **argv) if (strncmp(*argv, "--password", strlen("--password")) == 0) { arg = "--password=..."; } - left-= ut_snprintf(buf + len - left, left, - "%s%c", arg, argc > 1 ? ' ' : 0); + left-= snprintf(buf + len - left, left, + "%s%c", arg, argc > 1 ? ' ' : 0); ++argv; --argc; } diff --git a/extra/mariabackup/changed_page_bitmap.cc b/extra/mariabackup/changed_page_bitmap.cc index a430a6cb0af..46bb3a7bcb5 100644 --- a/extra/mariabackup/changed_page_bitmap.cc +++ b/extra/mariabackup/changed_page_bitmap.cc @@ -441,7 +441,7 @@ log_online_open_bitmap_file_read_only( xb_ad(name[0] != '\0'); - ut_snprintf(bitmap_file->name, FN_REFLEN, "%s%s", srv_data_home, name); + snprintf(bitmap_file->name, FN_REFLEN, "%s%s", srv_data_home, name); bitmap_file->file = os_file_create_simple_no_error_handling( 0, bitmap_file->name, OS_FILE_OPEN, OS_FILE_READ_ONLY, true, &success); diff --git a/extra/mariabackup/xtrabackup.cc b/extra/mariabackup/xtrabackup.cc index de32b5b864f..4c09bea28ba 100644 --- a/extra/mariabackup/xtrabackup.cc +++ b/extra/mariabackup/xtrabackup.cc @@ -2685,10 +2685,10 @@ xb_load_single_table_tablespace( name = static_cast(ut_malloc_nokey(pathlen)); if (dirname != NULL) { - ut_snprintf(name, pathlen, "%s/%s", dirname, filname); + snprintf(name, pathlen, "%s/%s", dirname, filname); name[pathlen - 5] = 0; } else { - ut_snprintf(name, pathlen, "%s", filname); + snprintf(name, pathlen, "%s", filname); name[pathlen - 5] = 0; } @@ -2806,8 +2806,8 @@ static dberr_t enumerate_ibd_files(process_single_tablespace_func_t callback) dbpath = static_cast(ut_malloc_nokey(dbpath_len)); } - ut_snprintf(dbpath, dbpath_len, - "%s/%s", fil_path_to_mysql_datadir, dbinfo.name); + snprintf(dbpath, dbpath_len, + "%s/%s", fil_path_to_mysql_datadir, dbinfo.name); os_normalize_path(dbpath); if (check_if_skip_database_by_path(dbpath)) { diff --git a/storage/innobase/buf/buf0dump.cc b/storage/innobase/buf/buf0dump.cc index b1614e0a580..56fb00f1e1d 100644 --- a/storage/innobase/buf/buf0dump.cc +++ b/storage/innobase/buf/buf0dump.cc @@ -206,8 +206,8 @@ buf_dump_generate_path( { char buf[FN_REFLEN]; - ut_snprintf(buf, sizeof(buf), "%s%c%s", get_buf_dump_dir(), - OS_PATH_SEPARATOR, srv_buf_dump_filename); + snprintf(buf, sizeof(buf), "%s%c%s", get_buf_dump_dir(), + OS_PATH_SEPARATOR, srv_buf_dump_filename); os_file_type_t type; bool exists = false; @@ -233,14 +233,14 @@ buf_dump_generate_path( if (srv_data_home_full[strlen(srv_data_home_full) - 1] == OS_PATH_SEPARATOR) { - ut_snprintf(path, path_size, "%s%s", - srv_data_home_full, - srv_buf_dump_filename); + snprintf(path, path_size, "%s%s", + srv_data_home_full, + srv_buf_dump_filename); } else { - ut_snprintf(path, path_size, "%s%c%s", - srv_data_home_full, - OS_PATH_SEPARATOR, - srv_buf_dump_filename); + snprintf(path, path_size, "%s%c%s", + srv_data_home_full, + OS_PATH_SEPARATOR, + srv_buf_dump_filename); } } } @@ -269,8 +269,8 @@ buf_dump( buf_dump_generate_path(full_filename, sizeof(full_filename)); - ut_snprintf(tmp_filename, sizeof(tmp_filename), - "%s.incomplete", full_filename); + snprintf(tmp_filename, sizeof(tmp_filename), + "%s.incomplete", full_filename); buf_dump_status(STATUS_INFO, "Dumping buffer pool(s) to %s", full_filename); diff --git a/storage/innobase/dict/dict0dict.cc b/storage/innobase/dict/dict0dict.cc index 137b88b15b3..e368fafad2a 100644 --- a/storage/innobase/dict/dict0dict.cc +++ b/storage/innobase/dict/dict0dict.cc @@ -6512,7 +6512,7 @@ dict_table_schema_check( } if (should_print) { - ut_snprintf(errstr, errstr_sz, + snprintf(errstr, errstr_sz, "Table %s not found.", ut_format_name(req_schema->table_name, buf, sizeof(buf))); @@ -6526,7 +6526,7 @@ dict_table_schema_check( fil_space_get(table->space) == NULL) { /* missing tablespace */ - ut_snprintf(errstr, errstr_sz, + snprintf(errstr, errstr_sz, "Tablespace for table %s is missing.", ut_format_name(req_schema->table_name, buf, sizeof(buf))); @@ -6537,13 +6537,13 @@ dict_table_schema_check( ulint n_sys_cols = dict_table_get_n_sys_cols(table); if ((ulint) table->n_def - n_sys_cols != req_schema->n_cols) { /* the table has a different number of columns than required */ - ut_snprintf(errstr, errstr_sz, - "%s has " ULINTPF " columns but should have " - ULINTPF ".", - ut_format_name(req_schema->table_name, - buf, sizeof(buf)), - table->n_def - n_sys_cols, - req_schema->n_cols); + snprintf(errstr, errstr_sz, + "%s has " ULINTPF " columns but should have " + ULINTPF ".", + ut_format_name(req_schema->table_name, buf, + sizeof buf), + table->n_def - n_sys_cols, + req_schema->n_cols); return(DB_ERROR); } @@ -6559,7 +6559,7 @@ dict_table_schema_check( if (j == table->n_def) { - ut_snprintf(errstr, errstr_sz, + snprintf(errstr, errstr_sz, "required column %s" " not found in table %s.", req_schema->columns[i].name, @@ -6578,7 +6578,7 @@ dict_table_schema_check( CREATE_TYPES_NAMES(); - ut_snprintf(errstr, errstr_sz, + snprintf(errstr, errstr_sz, "Column %s in table %s is %s" " but should be %s (length mismatch).", req_schema->columns[i].name, @@ -6602,7 +6602,7 @@ dict_table_schema_check( { CREATE_TYPES_NAMES(); - ut_snprintf(errstr, errstr_sz, + snprintf(errstr, errstr_sz, "Column %s in table %s is %s" " but should be %s (type mismatch).", req_schema->columns[i].name, @@ -6621,7 +6621,7 @@ dict_table_schema_check( CREATE_TYPES_NAMES(); - ut_snprintf(errstr, errstr_sz, + snprintf(errstr, errstr_sz, "Column %s in table %s is %s" " but should be %s (flags mismatch).", req_schema->columns[i].name, @@ -6634,7 +6634,7 @@ dict_table_schema_check( } if (req_schema->n_foreign != table->foreign_set.size()) { - ut_snprintf( + snprintf( errstr, errstr_sz, "Table %s has " ULINTPF " foreign key(s) pointing" " to other tables, but it must have " ULINTPF ".", @@ -6646,7 +6646,7 @@ dict_table_schema_check( } if (req_schema->n_referenced != table->referenced_set.size()) { - ut_snprintf( + snprintf( errstr, errstr_sz, "There are " ULINTPF " foreign key(s) pointing to %s, " "but there must be " ULINTPF ".", @@ -6720,7 +6720,7 @@ dict_fs2utf8( &errors); if (errors != 0) { - ut_snprintf(table_utf8, table_utf8_size, "%s%s", + snprintf(table_utf8, table_utf8_size, "%s%s", srv_mysql50_table_name_prefix, table); } } diff --git a/storage/innobase/dict/dict0mem.cc b/storage/innobase/dict/dict0mem.cc index bcaa5ae4a15..0808cc61f28 100644 --- a/storage/innobase/dict/dict0mem.cc +++ b/storage/innobase/dict/dict0mem.cc @@ -1067,7 +1067,7 @@ dict_mem_create_temporary_tablename( size = dblen + (sizeof(TEMP_FILE_PREFIX) + 3 + 20 + 1 + 10); name = static_cast(mem_heap_alloc(heap, size)); memcpy(name, dbtab, dblen); - ut_snprintf(name + dblen, size - dblen, + snprintf(name + dblen, size - dblen, TEMP_FILE_PREFIX_INNODB UINT64PF "-" UINT32PF, id, dict_temp_file_num); diff --git a/storage/innobase/dict/dict0stats.cc b/storage/innobase/dict/dict0stats.cc index 99fb115ea2c..2ea482095ce 100644 --- a/storage/innobase/dict/dict0stats.cc +++ b/storage/innobase/dict/dict0stats.cc @@ -2578,21 +2578,20 @@ dict_stats_save( char stat_name[16]; char stat_description[1024]; - ut_snprintf(stat_name, sizeof(stat_name), - "n_diff_pfx%02u", i + 1); + snprintf(stat_name, sizeof(stat_name), + "n_diff_pfx%02u", i + 1); /* craft a string that contains the column names */ - ut_snprintf(stat_description, - sizeof(stat_description), - "%s", index->fields[0].name()); + snprintf(stat_description, sizeof(stat_description), + "%s", index->fields[0].name()); for (unsigned j = 1; j <= i; j++) { size_t len; len = strlen(stat_description); - ut_snprintf(stat_description + len, - sizeof(stat_description) - len, - ",%s", index->fields[j].name()); + snprintf(stat_description + len, + sizeof(stat_description) - len, + ",%s", index->fields[j].name()); } ret = dict_stats_save_index_stat( @@ -3461,23 +3460,23 @@ dict_stats_drop_index( } if (ret != DB_SUCCESS) { - ut_snprintf(errstr, errstr_sz, - "Unable to delete statistics for index %s" - " from %s%s: %s. They can be deleted later using" - " DELETE FROM %s WHERE" - " database_name = '%s' AND" - " table_name = '%s' AND" - " index_name = '%s';", - iname, - INDEX_STATS_NAME_PRINT, - (ret == DB_LOCK_WAIT_TIMEOUT - ? " because the rows are locked" - : ""), - ut_strerr(ret), - INDEX_STATS_NAME_PRINT, - db_utf8, - table_utf8, - iname); + snprintf(errstr, errstr_sz, + "Unable to delete statistics for index %s" + " from %s%s: %s. They can be deleted later using" + " DELETE FROM %s WHERE" + " database_name = '%s' AND" + " table_name = '%s' AND" + " index_name = '%s';", + iname, + INDEX_STATS_NAME_PRINT, + (ret == DB_LOCK_WAIT_TIMEOUT + ? " because the rows are locked" + : ""), + ut_strerr(ret), + INDEX_STATS_NAME_PRINT, + db_utf8, + table_utf8, + iname); ut_print_timestamp(stderr); fprintf(stderr, " InnoDB: %s\n", errstr); @@ -3607,26 +3606,26 @@ dict_stats_drop_table( if (ret != DB_SUCCESS) { - ut_snprintf(errstr, errstr_sz, - "Unable to delete statistics for table %s.%s: %s." - " They can be deleted later using" + snprintf(errstr, errstr_sz, + "Unable to delete statistics for table %s.%s: %s." + " They can be deleted later using" - " DELETE FROM %s WHERE" - " database_name = '%s' AND" - " table_name = '%s';" + " DELETE FROM %s WHERE" + " database_name = '%s' AND" + " table_name = '%s';" - " DELETE FROM %s WHERE" - " database_name = '%s' AND" - " table_name = '%s';", + " DELETE FROM %s WHERE" + " database_name = '%s' AND" + " table_name = '%s';", - db_utf8, table_utf8, - ut_strerr(ret), + db_utf8, table_utf8, + ut_strerr(ret), - INDEX_STATS_NAME_PRINT, - db_utf8, table_utf8, + INDEX_STATS_NAME_PRINT, + db_utf8, table_utf8, - TABLE_STATS_NAME_PRINT, - db_utf8, table_utf8); + TABLE_STATS_NAME_PRINT, + db_utf8, table_utf8); } return(ret); @@ -3790,26 +3789,26 @@ dict_stats_rename_table( && n_attempts < 5); if (ret != DB_SUCCESS) { - ut_snprintf(errstr, errstr_sz, - "Unable to rename statistics from" - " %s.%s to %s.%s in %s: %s." - " They can be renamed later using" + snprintf(errstr, errstr_sz, + "Unable to rename statistics from" + " %s.%s to %s.%s in %s: %s." + " They can be renamed later using" - " UPDATE %s SET" - " database_name = '%s'," - " table_name = '%s'" - " WHERE" - " database_name = '%s' AND" - " table_name = '%s';", + " UPDATE %s SET" + " database_name = '%s'," + " table_name = '%s'" + " WHERE" + " database_name = '%s' AND" + " table_name = '%s';", - old_db_utf8, old_table_utf8, - new_db_utf8, new_table_utf8, - TABLE_STATS_NAME_PRINT, - ut_strerr(ret), + old_db_utf8, old_table_utf8, + new_db_utf8, new_table_utf8, + TABLE_STATS_NAME_PRINT, + ut_strerr(ret), - TABLE_STATS_NAME_PRINT, - new_db_utf8, new_table_utf8, - old_db_utf8, old_table_utf8); + TABLE_STATS_NAME_PRINT, + new_db_utf8, new_table_utf8, + old_db_utf8, old_table_utf8); mutex_exit(&dict_sys->mutex); rw_lock_x_unlock(dict_operation_lock); return(ret); @@ -3849,26 +3848,26 @@ dict_stats_rename_table( rw_lock_x_unlock(dict_operation_lock); if (ret != DB_SUCCESS) { - ut_snprintf(errstr, errstr_sz, - "Unable to rename statistics from" - " %s.%s to %s.%s in %s: %s." - " They can be renamed later using" + snprintf(errstr, errstr_sz, + "Unable to rename statistics from" + " %s.%s to %s.%s in %s: %s." + " They can be renamed later using" - " UPDATE %s SET" - " database_name = '%s'," - " table_name = '%s'" - " WHERE" - " database_name = '%s' AND" - " table_name = '%s';", + " UPDATE %s SET" + " database_name = '%s'," + " table_name = '%s'" + " WHERE" + " database_name = '%s' AND" + " table_name = '%s';", - old_db_utf8, old_table_utf8, - new_db_utf8, new_table_utf8, - INDEX_STATS_NAME_PRINT, - ut_strerr(ret), + old_db_utf8, old_table_utf8, + new_db_utf8, new_table_utf8, + INDEX_STATS_NAME_PRINT, + ut_strerr(ret), - INDEX_STATS_NAME_PRINT, - new_db_utf8, new_table_utf8, - old_db_utf8, old_table_utf8); + INDEX_STATS_NAME_PRINT, + new_db_utf8, new_table_utf8, + old_db_utf8, old_table_utf8); } return(ret); @@ -3971,7 +3970,7 @@ test_dict_table_schema_check() }; char errstr[512]; - ut_snprintf(errstr, sizeof(errstr), "Table not found"); + snprintf(errstr, sizeof(errstr), "Table not found"); /* prevent any data dictionary modifications while we are checking the tables' structure */ diff --git a/storage/innobase/fts/fts0config.cc b/storage/innobase/fts/fts0config.cc index 4d41df1abf9..7ad7459ea6a 100644 --- a/storage/innobase/fts/fts0config.cc +++ b/storage/innobase/fts/fts0config.cc @@ -349,7 +349,7 @@ fts_config_set_index_ulint( // FIXME: Get rid of snprintf ut_a(FTS_MAX_INT_LEN < FTS_MAX_CONFIG_VALUE_LEN); - value.f_len = ut_snprintf( + value.f_len = snprintf( (char*) value.f_str, FTS_MAX_INT_LEN, ULINTPF, int_value); error = fts_config_set_index_value(trx, index, name, &value); @@ -422,7 +422,7 @@ fts_config_set_ulint( ut_a(FTS_MAX_INT_LEN < FTS_MAX_CONFIG_VALUE_LEN); - value.f_len = my_snprintf( + value.f_len = snprintf( (char*) value.f_str, FTS_MAX_INT_LEN, ULINTPF, int_value); error = fts_config_set_value(trx, fts_table, name, &value); diff --git a/storage/innobase/fts/fts0fts.cc b/storage/innobase/fts/fts0fts.cc index 2372d9dbaf4..056eee5187a 100644 --- a/storage/innobase/fts/fts0fts.cc +++ b/storage/innobase/fts/fts0fts.cc @@ -2827,7 +2827,7 @@ fts_update_sync_doc_id( info = pars_info_create(); - id_len = ut_snprintf( + id_len = snprintf( (char*) id, sizeof(id), FTS_DOC_ID_FORMAT, doc_id + 1); pars_info_bind_varchar_literal(info, "doc_id", id, id_len); diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 0698bbc0576..8885fafb47b 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -14840,9 +14840,9 @@ ha_innobase::info_low( dict_table_stats_unlock(ib_table, RW_S_LATCH); } - my_snprintf(path, sizeof(path), "%s/%s%s", - mysql_data_home, table->s->normalized_path.str, - reg_ext); + snprintf(path, sizeof(path), "%s/%s%s", + mysql_data_home, table->s->normalized_path.str, + reg_ext); unpack_filename(path,path); @@ -16693,13 +16693,13 @@ ShowStatus::to_string( int name_len; char name_buf[IO_SIZE]; - name_len = ut_snprintf( + name_len = snprintf( name_buf, sizeof(name_buf), "%s", it->m_name.c_str()); int status_len; char status_buf[IO_SIZE]; - status_len = ut_snprintf( + status_len = snprintf( status_buf, sizeof(status_buf), "spins=%lu,waits=%lu,calls=%llu", static_cast(it->m_spins), @@ -16786,7 +16786,7 @@ innodb_show_rwlock_status( continue; } - buf1len = ut_snprintf( + buf1len = snprintf( buf1, sizeof buf1, "rwlock: %s:%u", innobase_basename(rw_lock->cfile_name), rw_lock->cline); @@ -16794,7 +16794,7 @@ innodb_show_rwlock_status( int buf2len; char buf2[IO_SIZE]; - buf2len = ut_snprintf( + buf2len = snprintf( buf2, sizeof buf2, "waits=%u", rw_lock->count_os_wait); @@ -16814,7 +16814,7 @@ innodb_show_rwlock_status( int buf1len; char buf1[IO_SIZE]; - buf1len = ut_snprintf( + buf1len = snprintf( buf1, sizeof buf1, "sum rwlock: %s:%u", innobase_basename(block_rwlock->cfile_name), block_rwlock->cline); @@ -16822,7 +16822,7 @@ innodb_show_rwlock_status( int buf2len; char buf2[IO_SIZE]; - buf2len = ut_snprintf( + buf2len = snprintf( buf2, sizeof buf2, "waits=" ULINTPF, block_rwlock_oswait_count); @@ -17570,7 +17570,7 @@ ha_innobase::get_foreign_dup_key( child_table_name[len] = '\0'; /* copy index name */ - ut_snprintf(child_key_name, child_key_name_len, "%s", + snprintf(child_key_name, child_key_name_len, "%s", err_index->name()); return(true); @@ -18474,7 +18474,7 @@ innodb_buffer_pool_size_update( { longlong in_val = *static_cast(save); - ut_snprintf(export_vars.innodb_buffer_pool_resize_status, + snprintf(export_vars.innodb_buffer_pool_resize_status, sizeof(export_vars.innodb_buffer_pool_resize_status), "Requested to resize buffer pool."); diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index f2ad11845d8..3e15c090b2f 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -8367,7 +8367,7 @@ alter_stats_rebuild( # define DBUG_INJECT_CRASH(prefix, count) \ do { \ char buf[32]; \ - ut_snprintf(buf, sizeof buf, prefix "_%u", count); \ + snprintf(buf, sizeof buf, prefix "_%u", count); \ DBUG_EXECUTE_IF(buf, DBUG_SUICIDE();); \ } while (0) #else @@ -8649,7 +8649,7 @@ ha_innobase::commit_inplace_alter_table( /* Generate a dynamic dbug text. */ char buf[32]; - ut_snprintf(buf, sizeof buf, + snprintf(buf, sizeof buf, "ib_commit_inplace_fail_%u", failure_inject_count++); diff --git a/storage/innobase/handler/i_s.cc b/storage/innobase/handler/i_s.cc index c9525f36c13..7615dba9a0e 100644 --- a/storage/innobase/handler/i_s.cc +++ b/storage/innobase/handler/i_s.cc @@ -597,7 +597,7 @@ fill_innodb_trx_from_cache( cache, I_S_INNODB_TRX, i); /* trx_id */ - ut_snprintf(trx_id, sizeof(trx_id), TRX_ID_FMT, row->trx_id); + snprintf(trx_id, sizeof(trx_id), TRX_ID_FMT, row->trx_id); OK(field_store_string(fields[IDX_TRX_ID], trx_id)); /* trx_state */ @@ -931,8 +931,8 @@ fill_innodb_locks_from_cache( lock_id)); /* lock_trx_id */ - ut_snprintf(lock_trx_id, sizeof(lock_trx_id), - TRX_ID_FMT, row->lock_trx_id); + snprintf(lock_trx_id, sizeof(lock_trx_id), + TRX_ID_FMT, row->lock_trx_id); OK(field_store_string(fields[IDX_LOCK_TRX_ID], lock_trx_id)); /* lock_mode */ @@ -1131,8 +1131,8 @@ fill_innodb_lock_waits_from_cache( cache, I_S_INNODB_LOCK_WAITS, i); /* requesting_trx_id */ - ut_snprintf(requesting_trx_id, sizeof(requesting_trx_id), - TRX_ID_FMT, row->requested_lock_row->lock_trx_id); + snprintf(requesting_trx_id, sizeof(requesting_trx_id), + TRX_ID_FMT, row->requested_lock_row->lock_trx_id); OK(field_store_string(fields[IDX_REQUESTING_TRX_ID], requesting_trx_id)); @@ -1145,8 +1145,8 @@ fill_innodb_lock_waits_from_cache( sizeof(requested_lock_id)))); /* blocking_trx_id */ - ut_snprintf(blocking_trx_id, sizeof(blocking_trx_id), - TRX_ID_FMT, row->blocking_lock_row->lock_trx_id); + snprintf(blocking_trx_id, sizeof(blocking_trx_id), + TRX_ID_FMT, row->blocking_lock_row->lock_trx_id); OK(field_store_string(fields[IDX_BLOCKING_TRX_ID], blocking_trx_id)); @@ -1748,8 +1748,8 @@ i_s_cmp_per_index_fill_low( index->name); } else { /* index not found */ - ut_snprintf(name, sizeof(name), - "index_id:" IB_ID_FMT, iter->first); + snprintf(name, sizeof(name), + "index_id:" IB_ID_FMT, iter->first); field_store_string(fields[IDX_DATABASE_NAME], "unknown"); field_store_string(fields[IDX_TABLE_NAME], @@ -9221,8 +9221,8 @@ i_s_innodb_mutexes_fill_table( if (block_mutex) { char buf1[IO_SIZE]; - my_snprintf(buf1, sizeof buf1, "combined %s", - innobase_basename(block_mutex->cfile_name)); + snprintf(buf1, sizeof buf1, "combined %s", + innobase_basename(block_mutex->cfile_name)); OK(field_store_string(fields[MUTEXES_NAME], block_mutex->cmutex_name)); OK(field_store_string(fields[MUTEXES_CREATE_FILE], buf1)); @@ -9260,8 +9260,8 @@ i_s_innodb_mutexes_fill_table( if (block_lock) { char buf1[IO_SIZE]; - my_snprintf(buf1, sizeof buf1, "combined %s", - innobase_basename(block_lock->cfile_name)); + snprintf(buf1, sizeof buf1, "combined %s", + innobase_basename(block_lock->cfile_name)); //OK(field_store_string(fields[MUTEXES_NAME], block_lock->lock_name)); OK(field_store_string(fields[MUTEXES_CREATE_FILE], buf1)); diff --git a/storage/innobase/include/data0type.ic b/storage/innobase/include/data0type.ic index a68f4829561..0af2dcf9fa1 100644 --- a/storage/innobase/include/data0type.ic +++ b/storage/innobase/include/data0type.ic @@ -387,79 +387,79 @@ dtype_sql_name( #define APPEND_UNSIGNED() \ do { \ if (prtype & DATA_UNSIGNED) { \ - ut_snprintf(name + strlen(name), \ + snprintf(name + strlen(name), \ name_sz - strlen(name), \ " UNSIGNED"); \ } \ } while (0) - ut_snprintf(name, name_sz, "UNKNOWN"); + snprintf(name, name_sz, "UNKNOWN"); switch (mtype) { case DATA_INT: switch (len) { case 1: - ut_snprintf(name, name_sz, "TINYINT"); + snprintf(name, name_sz, "TINYINT"); break; case 2: - ut_snprintf(name, name_sz, "SMALLINT"); + snprintf(name, name_sz, "SMALLINT"); break; case 3: - ut_snprintf(name, name_sz, "MEDIUMINT"); + snprintf(name, name_sz, "MEDIUMINT"); break; case 4: - ut_snprintf(name, name_sz, "INT"); + snprintf(name, name_sz, "INT"); break; case 8: - ut_snprintf(name, name_sz, "BIGINT"); + snprintf(name, name_sz, "BIGINT"); break; } APPEND_UNSIGNED(); break; case DATA_FLOAT: - ut_snprintf(name, name_sz, "FLOAT"); + snprintf(name, name_sz, "FLOAT"); APPEND_UNSIGNED(); break; case DATA_DOUBLE: - ut_snprintf(name, name_sz, "DOUBLE"); + snprintf(name, name_sz, "DOUBLE"); APPEND_UNSIGNED(); break; case DATA_FIXBINARY: - ut_snprintf(name, name_sz, "BINARY(%u)", len); + snprintf(name, name_sz, "BINARY(%u)", len); break; case DATA_CHAR: case DATA_MYSQL: - ut_snprintf(name, name_sz, "CHAR(%u)", len); + snprintf(name, name_sz, "CHAR(%u)", len); break; case DATA_VARCHAR: case DATA_VARMYSQL: - ut_snprintf(name, name_sz, "VARCHAR(%u)", len); + snprintf(name, name_sz, "VARCHAR(%u)", len); break; case DATA_BINARY: - ut_snprintf(name, name_sz, "VARBINARY(%u)", len); + snprintf(name, name_sz, "VARBINARY(%u)", len); break; case DATA_GEOMETRY: - ut_snprintf(name, name_sz, "GEOMETRY"); + snprintf(name, name_sz, "GEOMETRY"); break; case DATA_BLOB: switch (len) { case 9: - ut_snprintf(name, name_sz, "TINYBLOB"); + snprintf(name, name_sz, "TINYBLOB"); break; case 10: - ut_snprintf(name, name_sz, "BLOB"); + snprintf(name, name_sz, "BLOB"); break; case 11: - ut_snprintf(name, name_sz, "MEDIUMBLOB"); + snprintf(name, name_sz, "MEDIUMBLOB"); break; case 12: - ut_snprintf(name, name_sz, "LONGBLOB"); + snprintf(name, name_sz, "LONGBLOB"); break; } } if (prtype & DATA_NOT_NULL) { - ut_snprintf(name + strlen(name), + snprintf(name + strlen(name), name_sz - strlen(name), " NOT NULL"); } diff --git a/storage/innobase/include/ut0ut.h b/storage/innobase/include/ut0ut.h index b8282b7d0de..0e7f87d2ef0 100644 --- a/storage/innobase/include/ut0ut.h +++ b/storage/innobase/include/ut0ut.h @@ -410,19 +410,6 @@ ut_vsnprintf( size_t size, /*!< in: str size */ const char* fmt, /*!< in: format */ va_list ap); /*!< in: format values */ - -/**********************************************************************//** -A substitute for snprintf(3), formatted output conversion into -a limited buffer. -@return number of characters that would have been printed if the size -were unlimited, not including the terminating '\0'. */ -int -ut_snprintf( -/*========*/ - char* str, /*!< out: string */ - size_t size, /*!< in: str size */ - const char* fmt, /*!< in: format */ - ...); /*!< in: format values */ #else /**********************************************************************//** A wrapper for vsnprintf(3), formatted output conversion into @@ -433,10 +420,6 @@ _vscprintf() in addition to estimate that but we would need another copy of "ap" for that and VC does not provide va_copy(). */ # define ut_vsnprintf(buf, size, fmt, ap) \ ((void) vsnprintf(buf, size, fmt, ap)) -/**********************************************************************//** -A wrapper for snprintf(3), formatted output conversion into -a limited buffer. */ -# define ut_snprintf snprintf #endif /* _WIN32 */ /*************************************************************//** diff --git a/storage/innobase/os/os0file.cc b/storage/innobase/os/os0file.cc index 03793a1d064..51227696c1c 100644 --- a/storage/innobase/os/os0file.cc +++ b/storage/innobase/os/os0file.cc @@ -1305,11 +1305,8 @@ os_file_make_new_pathname( new_path = static_cast(ut_malloc_nokey(new_path_len)); memcpy(new_path, old_path, dir_len); - ut_snprintf(new_path + dir_len, - new_path_len - dir_len, - "%c%s.ibd", - OS_PATH_SEPARATOR, - base_name); + snprintf(new_path + dir_len, new_path_len - dir_len, + "%c%s.ibd", OS_PATH_SEPARATOR, base_name); return(new_path); } diff --git a/storage/innobase/page/page0zip.cc b/storage/innobase/page/page0zip.cc index f31ac653dc6..ea9926fe139 100644 --- a/storage/innobase/page/page0zip.cc +++ b/storage/innobase/page/page0zip.cc @@ -1340,8 +1340,8 @@ page_zip_compress( if (UNIV_UNLIKELY(page_zip_compress_log)) { /* Create a log file for every compression attempt. */ char logfilename[9]; - ut_snprintf(logfilename, sizeof logfilename, - "%08x", page_zip_compress_log++); + snprintf(logfilename, sizeof logfilename, + "%08x", page_zip_compress_log++); logfile = fopen(logfilename, "wb"); if (logfile) { diff --git a/storage/innobase/row/row0import.cc b/storage/innobase/row/row0import.cc index f06bc878c3b..44453599e68 100644 --- a/storage/innobase/row/row0import.cc +++ b/storage/innobase/row/row0import.cc @@ -725,7 +725,7 @@ FetchIndexRootPages::build_row_import(row_import* cfg) const UNIV_NOTHROW char name[BUFSIZ]; - ut_snprintf(name, sizeof(name), "index" IB_ID_FMT, it->m_id); + snprintf(name, sizeof(name), "index" IB_ID_FMT, it->m_id); ulint len = strlen(name) + 1; @@ -2561,11 +2561,11 @@ row_import_read_index_data( if (n_bytes != sizeof(row)) { char msg[BUFSIZ]; - ut_snprintf(msg, sizeof(msg), - "while reading index meta-data, expected " - "to read " ULINTPF - " bytes but read only " ULINTPF " bytes", - sizeof(row), n_bytes); + snprintf(msg, sizeof(msg), + "while reading index meta-data, expected " + "to read " ULINTPF + " bytes but read only " ULINTPF " bytes", + sizeof(row), n_bytes); ib_senderrf( thd, IB_LOG_LEVEL_ERROR, ER_IO_READ_ERROR, @@ -3084,9 +3084,9 @@ row_import_read_cfg( if (file == NULL) { char msg[BUFSIZ]; - ut_snprintf(msg, sizeof(msg), - "Error opening '%s', will attempt to import" - " without schema verification", name); + snprintf(msg, sizeof(msg), + "Error opening '%s', will attempt to import" + " without schema verification", name); ib_senderrf( thd, IB_LOG_LEVEL_WARN, ER_IO_READ_ERROR, diff --git a/storage/innobase/row/row0quiesce.cc b/storage/innobase/row/row0quiesce.cc index ccf58b9e73f..00897d747ff 100644 --- a/storage/innobase/row/row0quiesce.cc +++ b/storage/innobase/row/row0quiesce.cc @@ -454,8 +454,7 @@ row_quiesce_write_cfg( char msg[BUFSIZ]; - ut_snprintf(msg, sizeof(msg), "%s flush() failed", - name); + snprintf(msg, sizeof(msg), "%s flush() failed", name); ib_senderrf( thd, IB_LOG_LEVEL_WARN, ER_IO_WRITE_ERROR, @@ -465,8 +464,7 @@ row_quiesce_write_cfg( if (fclose(file) != 0) { char msg[BUFSIZ]; - ut_snprintf(msg, sizeof(msg), "%s flose() failed", - name); + snprintf(msg, sizeof(msg), "%s flose() failed", name); ib_senderrf( thd, IB_LOG_LEVEL_WARN, ER_IO_WRITE_ERROR, diff --git a/storage/innobase/row/row0row.cc b/storage/innobase/row/row0row.cc index 748ac194110..add12057910 100644 --- a/storage/innobase/row/row0row.cc +++ b/storage/innobase/row/row0row.cc @@ -1137,7 +1137,7 @@ row_raw_format_int( value = mach_read_int_type( (const byte*) data, data_len, unsigned_type); - ret = ut_snprintf( + ret = snprintf( buf, buf_size, unsigned_type ? "%llu" : "%lld", (longlong) value)+1; } else { @@ -1234,7 +1234,7 @@ row_raw_format( if (data_len == UNIV_SQL_NULL) { - ret = ut_snprintf((char*) buf, buf_size, "NULL") + 1; + ret = snprintf((char*) buf, buf_size, "NULL") + 1; return(ut_min(ret, buf_size)); } diff --git a/storage/innobase/row/row0trunc.cc b/storage/innobase/row/row0trunc.cc index afa49082136..068b4d96ed2 100644 --- a/storage/innobase/row/row0trunc.cc +++ b/storage/innobase/row/row0trunc.cc @@ -293,13 +293,13 @@ public: log_file_name_len = strlen(m_log_file_name); } - ut_snprintf(m_log_file_name + log_file_name_len, - log_file_name_buf_sz - log_file_name_len, - "%s%lu_%lu_%s", - TruncateLogger::s_log_prefix, - (ulong) m_table->space, - (ulong) m_table->id, - TruncateLogger::s_log_ext); + snprintf(m_log_file_name + log_file_name_len, + log_file_name_buf_sz - log_file_name_len, + "%s%lu_%lu_%s", + TruncateLogger::s_log_prefix, + (ulong) m_table->space, + (ulong) m_table->id, + TruncateLogger::s_log_ext); return(DB_SUCCESS); diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc index dc1b1eca0ef..85a6d2fa516 100644 --- a/storage/innobase/srv/srv0start.cc +++ b/storage/innobase/srv/srv0start.cc @@ -687,8 +687,8 @@ srv_undo_tablespace_open( dberr_t err = DB_ERROR; char undo_name[sizeof "innodb_undo000"]; - ut_snprintf(undo_name, sizeof(undo_name), - "innodb_undo%03u", static_cast(space_id)); + snprintf(undo_name, sizeof(undo_name), + "innodb_undo%03u", static_cast(space_id)); if (!srv_file_check_mode(name)) { ib::error() << "UNDO tablespaces must be " << @@ -766,7 +766,7 @@ srv_check_undo_redo_logs_exists() /* Check if any undo tablespaces exist */ for (ulint i = 1; i <= srv_undo_tablespaces; ++i) { - ut_snprintf( + snprintf( name, sizeof(name), "%s%cundo%03zu", srv_undo_dir, OS_PATH_SEPARATOR, @@ -863,7 +863,7 @@ srv_undo_tablespaces_init(bool create_new_db) DBUG_EXECUTE_IF("innodb_undo_upgrade", space_id = i + 3;); - ut_snprintf( + snprintf( name, sizeof(name), "%s%cundo%03zu", srv_undo_dir, OS_PATH_SEPARATOR, space_id); @@ -925,10 +925,10 @@ srv_undo_tablespaces_init(bool create_new_db) char name[OS_FILE_MAX_PATH]; - ut_snprintf(name, sizeof(name), - "%s%cundo%03zu", - srv_undo_dir, OS_PATH_SEPARATOR, - undo_tablespace_ids[i]); + snprintf(name, sizeof(name), + "%s%cundo%03zu", + srv_undo_dir, OS_PATH_SEPARATOR, + undo_tablespace_ids[i]); os_file_delete(innodb_data_file_key, name); @@ -958,7 +958,7 @@ srv_undo_tablespaces_init(bool create_new_db) for (i = 0; i < n_undo_tablespaces; ++i) { char name[OS_FILE_MAX_PATH]; - ut_snprintf( + snprintf( name, sizeof(name), "%s%cundo%03zu", srv_undo_dir, OS_PATH_SEPARATOR, @@ -996,7 +996,7 @@ srv_undo_tablespaces_init(bool create_new_db) for (i = prev_space_id + 1; i < TRX_SYS_N_RSEGS; ++i) { char name[OS_FILE_MAX_PATH]; - ut_snprintf( + snprintf( name, sizeof(name), "%s%cundo%03zu", srv_undo_dir, OS_PATH_SEPARATOR, i); diff --git a/storage/innobase/trx/trx0i_s.cc b/storage/innobase/trx/trx0i_s.cc index 327ebf79211..f0dc2fb78bd 100644 --- a/storage/innobase/trx/trx0i_s.cc +++ b/storage/innobase/trx/trx0i_s.cc @@ -1607,17 +1607,17 @@ trx_i_s_create_lock_id( if (row->lock_space != ULINT_UNDEFINED) { /* record lock */ - res_len = ut_snprintf(lock_id, lock_id_size, - TRX_ID_FMT - ":" ULINTPF ":" ULINTPF ":" ULINTPF, - row->lock_trx_id, row->lock_space, - row->lock_page, row->lock_rec); + res_len = snprintf(lock_id, lock_id_size, + TRX_ID_FMT + ":" ULINTPF ":" ULINTPF ":" ULINTPF, + row->lock_trx_id, row->lock_space, + row->lock_page, row->lock_rec); } else { /* table lock */ - res_len = ut_snprintf(lock_id, lock_id_size, - TRX_ID_FMT":" UINT64PF, - row->lock_trx_id, - row->lock_table_id); + res_len = snprintf(lock_id, lock_id_size, + TRX_ID_FMT":" UINT64PF, + row->lock_trx_id, + row->lock_table_id); } /* the typecast is safe because snprintf(3) never returns diff --git a/storage/innobase/trx/trx0purge.cc b/storage/innobase/trx/trx0purge.cc index 8d3c5b18cec..c04fd5353a3 100644 --- a/storage/innobase/trx/trx0purge.cc +++ b/storage/innobase/trx/trx0purge.cc @@ -567,10 +567,10 @@ namespace undo { log_file_name_len = strlen(log_file_name); } - ut_snprintf(log_file_name + log_file_name_len, - log_file_name_sz - log_file_name_len, - "%s%lu_%s", undo::s_log_prefix, - (ulong) space_id, s_log_ext); + snprintf(log_file_name + log_file_name_len, + log_file_name_sz - log_file_name_len, + "%s%lu_%s", undo::s_log_prefix, + (ulong) space_id, s_log_ext); return(DB_SUCCESS); } diff --git a/storage/innobase/ut/ut0ut.cc b/storage/innobase/ut/ut0ut.cc index 7ad80c3cd1f..877c4440f7a 100644 --- a/storage/innobase/ut/ut0ut.cc +++ b/storage/innobase/ut/ut0ut.cc @@ -542,43 +542,6 @@ ut_vsnprintf( _vsnprintf(str, size, fmt, ap); str[size - 1] = '\0'; } - -/**********************************************************************//** -A substitute for snprintf(3), formatted output conversion into -a limited buffer. -@return number of characters that would have been printed if the size -were unlimited, not including the terminating '\0'. */ -int -ut_snprintf( -/*========*/ - char* str, /*!< out: string */ - size_t size, /*!< in: str size */ - const char* fmt, /*!< in: format */ - ...) /*!< in: format values */ -{ - int res; - va_list ap1; - va_list ap2; - - va_start(ap1, fmt); - va_start(ap2, fmt); - - res = _vscprintf(fmt, ap1); - ut_a(res != -1); - - if (size > 0) { - _vsnprintf(str, size, fmt, ap2); - - if ((size_t) res >= size) { - str[size - 1] = '\0'; - } - } - - va_end(ap1); - va_end(ap2); - - return(res); -} #endif /* _WIN32 */ /** Convert an error number to a human readable text message. From b2dd5232d4872d6c9ee565f1a88e70514ceb1780 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 13 Nov 2017 04:32:56 +0200 Subject: [PATCH 05/18] InnoDB: Remove ut_vsnprintf() and the use of my_vsnprintf(); use vsnprintf() --- storage/innobase/buf/buf0buf.cc | 2 +- storage/innobase/buf/buf0dump.cc | 4 ++-- storage/innobase/handler/ha_innodb.cc | 4 ++-- storage/innobase/include/ut0ut.h | 27 --------------------------- storage/innobase/ut/ut0ut.cc | 22 ---------------------- 5 files changed, 5 insertions(+), 54 deletions(-) diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc index 3a201f5cef4..7382a40c781 100644 --- a/storage/innobase/buf/buf0buf.cc +++ b/storage/innobase/buf/buf0buf.cc @@ -2212,7 +2212,7 @@ buf_resize_status( va_start(ap, fmt); - ut_vsnprintf( + vsnprintf( export_vars.innodb_buffer_pool_resize_status, sizeof(export_vars.innodb_buffer_pool_resize_status), fmt, ap); diff --git a/storage/innobase/buf/buf0dump.cc b/storage/innobase/buf/buf0dump.cc index 56fb00f1e1d..6cd8111e902 100644 --- a/storage/innobase/buf/buf0dump.cc +++ b/storage/innobase/buf/buf0dump.cc @@ -119,7 +119,7 @@ buf_dump_status( va_start(ap, fmt); - ut_vsnprintf( + vsnprintf( export_vars.innodb_buffer_pool_dump_status, sizeof(export_vars.innodb_buffer_pool_dump_status), fmt, ap); @@ -158,7 +158,7 @@ buf_load_status( va_start(ap, fmt); - ut_vsnprintf( + vsnprintf( export_vars.innodb_buffer_pool_load_status, sizeof(export_vars.innodb_buffer_pool_load_status), fmt, ap); diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 8885fafb47b..aea7e67c9af 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -22494,7 +22494,7 @@ ib_errf( if (vasprintf(&str, format, args) == -1) { /* In case of failure use a fixed length string */ str = static_cast(malloc(BUFSIZ)); - my_vsnprintf(str, BUFSIZ, format, args); + vsnprintf(str, BUFSIZ, format, args); } #else /* Use a fixed length string. */ @@ -22503,7 +22503,7 @@ ib_errf( va_end(args); return; /* Watch for Out-Of-Memory */ } - my_vsnprintf(str, BUFSIZ, format, args); + vsnprintf(str, BUFSIZ, format, args); #endif /* _WIN32 */ ib_senderrf(thd, level, code, str); diff --git a/storage/innobase/include/ut0ut.h b/storage/innobase/include/ut0ut.h index 0e7f87d2ef0..4e9c2599933 100644 --- a/storage/innobase/include/ut0ut.h +++ b/storage/innobase/include/ut0ut.h @@ -395,33 +395,6 @@ ut_copy_file( FILE* dest, /*!< in: output file */ FILE* src); /*!< in: input file to be appended to output */ -#ifdef _WIN32 -/**********************************************************************//** -A substitute for vsnprintf(3), formatted output conversion into -a limited buffer. Note: this function DOES NOT return the number of -characters that would have been printed if the buffer was unlimited because -VC's _vsnprintf() returns -1 in this case and we would need to call -_vscprintf() in addition to estimate that but we would need another copy -of "ap" for that and VC does not provide va_copy(). */ -void -ut_vsnprintf( -/*=========*/ - char* str, /*!< out: string */ - size_t size, /*!< in: str size */ - const char* fmt, /*!< in: format */ - va_list ap); /*!< in: format values */ -#else -/**********************************************************************//** -A wrapper for vsnprintf(3), formatted output conversion into -a limited buffer. Note: this function DOES NOT return the number of -characters that would have been printed if the buffer was unlimited because -VC's _vsnprintf() returns -1 in this case and we would need to call -_vscprintf() in addition to estimate that but we would need another copy -of "ap" for that and VC does not provide va_copy(). */ -# define ut_vsnprintf(buf, size, fmt, ap) \ - ((void) vsnprintf(buf, size, fmt, ap)) -#endif /* _WIN32 */ - /*************************************************************//** Convert an error number to a human readable text message. The returned string is static and should not be freed or modified. diff --git a/storage/innobase/ut/ut0ut.cc b/storage/innobase/ut/ut0ut.cc index 877c4440f7a..28e327a2a77 100644 --- a/storage/innobase/ut/ut0ut.cc +++ b/storage/innobase/ut/ut0ut.cc @@ -522,28 +522,6 @@ ut_copy_file( } while (len > 0); } -#ifdef _WIN32 -# include -/**********************************************************************//** -A substitute for vsnprintf(3), formatted output conversion into -a limited buffer. Note: this function DOES NOT return the number of -characters that would have been printed if the buffer was unlimited because -VC's _vsnprintf() returns -1 in this case and we would need to call -_vscprintf() in addition to estimate that but we would need another copy -of "ap" for that and VC does not provide va_copy(). */ -void -ut_vsnprintf( -/*=========*/ - char* str, /*!< out: string */ - size_t size, /*!< in: str size */ - const char* fmt, /*!< in: format */ - va_list ap) /*!< in: format values */ -{ - _vsnprintf(str, size, fmt, ap); - str[size - 1] = '\0'; -} -#endif /* _WIN32 */ - /** Convert an error number to a human readable text message. The returned string is static and should not be freed or modified. @param[in] num InnoDB internal error number From f48d56c459aba62444f5b605bbf96dab0c96769a Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Thu, 9 Nov 2017 16:25:16 +0000 Subject: [PATCH 06/18] MDEV-14192 Apply marko's patch --- storage/innobase/log/log0recv.cc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc index 0a6679be721..2d707820f4a 100644 --- a/storage/innobase/log/log0recv.cc +++ b/storage/innobase/log/log0recv.cc @@ -622,6 +622,8 @@ log_group_read_log_seg( lsn_t source_offset; ut_ad(log_mutex_own()); + ut_ad(!(start_lsn % OS_FILE_LOG_BLOCK_SIZE)); + ut_ad(!(end_lsn % OS_FILE_LOG_BLOCK_SIZE)); loop: source_offset = log_group_calc_lsn_offset(start_lsn, group); @@ -2899,7 +2901,8 @@ recv_group_scan_log_recs( recv_apply_hashed_log_recs(false); } - start_lsn = end_lsn; + start_lsn = ut_uint64_align_down(end_lsn, + OS_FILE_LOG_BLOCK_SIZE); end_lsn = log_group_read_log_seg( log_sys->buf, group, start_lsn, start_lsn + RECV_SCAN_SIZE); From 56326528044a8b8c688f3223cf88634403d40da2 Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Mon, 13 Nov 2017 14:59:43 +0000 Subject: [PATCH 07/18] update C/C --- libmariadb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libmariadb b/libmariadb index 7e53ab36981..9b7b25993f0 160000 --- a/libmariadb +++ b/libmariadb @@ -1 +1 @@ -Subproject commit 7e53ab369815590ff92913b581d43eb7786f2fe2 +Subproject commit 9b7b25993f0f0c3e2c6502d94792f68fba2284b1 From 24184938ad9954f25c082a1afd74a053a8ab6d8c Mon Sep 17 00:00:00 2001 From: Alexey Botchkov Date: Tue, 14 Nov 2017 13:36:50 +0400 Subject: [PATCH 08/18] MDEV-11881 Empty coordinates must be rejected in GeoJSON objects. Check for the empty 'coordinates' array. --- mysql-test/r/gis-json.result | 15 +++++++++++++++ mysql-test/t/gis-json.test | 4 ++++ sql/item_geofunc.cc | 3 +++ sql/share/errmsg-utf8.txt | 3 +++ sql/spatial.cc | 35 ++++++++++++++++++++++++++++++++++- sql/spatial.h | 1 + 6 files changed, 60 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/gis-json.result b/mysql-test/r/gis-json.result index d888b08351d..1d6e2193fc9 100644 --- a/mysql-test/r/gis-json.result +++ b/mysql-test/r/gis-json.result @@ -89,6 +89,21 @@ ST_AsGeoJSON(ST_GeomFromText("POINT(10 11)"), 100, 1) SELECT ST_AsGeoJSON(ST_GeomFromText("POINT(10 11)"), 100, 5); ST_AsGeoJSON(ST_GeomFromText("POINT(10 11)"), 100, 5) {"bbox": [10, 11, 10, 11], "type": "Point", "coordinates": [10, 11]} +SELECT st_astext(st_geomfromgeojson('{"type": "MultiLineString","coordinates": []}')) as a; +a +NULL +Warnings: +Warning 4076 Incorrect GeoJSON format - empty 'coordinates' array. +SELECT st_astext(st_geomfromgeojson('{"type": "Polygon","coordinates": []}')) as a; +a +NULL +Warnings: +Warning 4076 Incorrect GeoJSON format - empty 'coordinates' array. +SELECT st_astext(st_geomfromgeojson('{"type": "MultiPolygon","coordinates": []}')) as a; +a +NULL +Warnings: +Warning 4076 Incorrect GeoJSON format - empty 'coordinates' array. # # End of 10.2 tests # diff --git a/mysql-test/t/gis-json.test b/mysql-test/t/gis-json.test index 5e695fbca9c..b91ef235fd0 100644 --- a/mysql-test/t/gis-json.test +++ b/mysql-test/t/gis-json.test @@ -40,6 +40,10 @@ SELECT ST_AsGeoJSON(ST_GeomFromText('POINT(5.363 7.266)'),10); SELECT ST_AsGeoJSON(ST_GeomFromText("POINT(10 11)"), 100, 1); SELECT ST_AsGeoJSON(ST_GeomFromText("POINT(10 11)"), 100, 5); +SELECT st_astext(st_geomfromgeojson('{"type": "MultiLineString","coordinates": []}')) as a; +SELECT st_astext(st_geomfromgeojson('{"type": "Polygon","coordinates": []}')) as a; +SELECT st_astext(st_geomfromgeojson('{"type": "MultiPolygon","coordinates": []}')) as a; + --echo # --echo # End of 10.2 tests --echo # diff --git a/sql/item_geofunc.cc b/sql/item_geofunc.cc index 6f79bd9a039..3119f5a577b 100644 --- a/sql/item_geofunc.cc +++ b/sql/item_geofunc.cc @@ -174,6 +174,9 @@ String *Item_func_geometry_from_json::val_str(String *str) case Geometry::GEOJ_TOO_FEW_POINTS: code= ER_GEOJSON_TOO_FEW_POINTS; break; + case Geometry::GEOJ_EMPTY_COORDINATES: + code= ER_GEOJSON_EMPTY_COORDINATES; + break; case Geometry::GEOJ_POLYGON_NOT_CLOSED: code= ER_GEOJSON_NOT_CLOSED; break; diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt index 554b6c7afec..0e93f0546c9 100644 --- a/sql/share/errmsg-utf8.txt +++ b/sql/share/errmsg-utf8.txt @@ -7746,3 +7746,6 @@ ER_SUM_FUNC_WITH_WINDOW_FUNC_AS_ARG ER_NET_OK_PACKET_TOO_LARGE eng "OK packet too large" + +ER_GEOJSON_EMPTY_COORDINATES + eng "Incorrect GeoJSON format - empty 'coordinates' array." diff --git a/sql/spatial.cc b/sql/spatial.cc index 357e311543f..2aca528dd15 100644 --- a/sql/spatial.cc +++ b/sql/spatial.cc @@ -1041,7 +1041,7 @@ bool Gis_line_string::init_from_json(json_engine_t *je, bool er_on_3D, } if (n_points < 1) { - je->s.error= GEOJ_TOO_FEW_POINTS; + je->s.error= Geometry::GEOJ_TOO_FEW_POINTS; return TRUE; } wkb->write_at_position(np_pos, n_points); @@ -1440,6 +1440,15 @@ bool Gis_polygon::init_from_json(json_engine_t *je, bool er_on_3D, String *wkb) } n_linear_rings++; } + + if (je->s.error) + return TRUE; + + if (n_linear_rings == 0) + { + je->s.error= Geometry::GEOJ_EMPTY_COORDINATES; + return TRUE; + } wkb->write_at_position(lr_pos, n_linear_rings); return FALSE; } @@ -1945,6 +1954,14 @@ bool Gis_multi_point::init_from_json(json_engine_t *je, bool er_on_3D, n_points++; } + if (je->s.error) + return TRUE; + if (n_points == 0) + { + je->s.error= Geometry::GEOJ_EMPTY_COORDINATES; + return TRUE; + } + wkb->write_at_position(np_pos, n_points); return FALSE; } @@ -2214,6 +2231,15 @@ bool Gis_multi_line_string::init_from_json(json_engine_t *je, bool er_on_3D, n_line_strings++; } + if (je->s.error) + return TRUE; + + if (n_line_strings == 0) + { + je->s.error= Geometry::GEOJ_EMPTY_COORDINATES; + return TRUE; + } + wkb->write_at_position(ls_pos, n_line_strings); return FALSE; } @@ -2603,6 +2629,13 @@ bool Gis_multi_polygon::init_from_json(json_engine_t *je, bool er_on_3D, n_polygons++; } + if (je->s.error) + return TRUE; + if (n_polygons == 0) + { + je->s.error= Geometry::GEOJ_EMPTY_COORDINATES; + return TRUE; + } wkb->write_at_position(np_pos, n_polygons); return FALSE; } diff --git a/sql/spatial.h b/sql/spatial.h index 78e850dc2d7..901544b6916 100644 --- a/sql/spatial.h +++ b/sql/spatial.h @@ -256,6 +256,7 @@ public: GEOJ_TOO_FEW_POINTS= 2, GEOJ_POLYGON_NOT_CLOSED= 3, GEOJ_DIMENSION_NOT_SUPPORTED= 4, + GEOJ_EMPTY_COORDINATES= 5, }; From 3afc9629fd84fbbc615f02aac0154e6b5ba92168 Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Tue, 14 Nov 2017 12:22:30 -0800 Subject: [PATCH 09/18] Fixed bug mdev-13453 Executing a query via CTE requires more permissions than the query itself ACL checks were not properly supported for tables used in CTE specifications. This patch fixes the problem. --- mysql-test/r/cte_nonrecursive.result | 58 ++++++++++++++++++++++++++++ mysql-test/t/cte_nonrecursive.test | 51 ++++++++++++++++++++++++ sql/sql_acl.cc | 4 ++ sql/sql_cte.cc | 3 +- sql/sql_parse.cc | 8 ++++ 5 files changed, 123 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/cte_nonrecursive.result b/mysql-test/r/cte_nonrecursive.result index ebe1aae1e8f..21a1fa3164f 100644 --- a/mysql-test/r/cte_nonrecursive.result +++ b/mysql-test/r/cte_nonrecursive.result @@ -1147,3 +1147,61 @@ SELECT * FROM cte_test; a 1 DROP VIEW cte_test; +# +# MDEV-13453: privileges checking for CTE +# +create database db; +use db; +create table t1 (i int); +insert into t1 +values (3), (7), (1), (4), (2), (3), (1); +create table t2 (a int, b int); +insert into t2 +values (3,10), (7,11), (1,17), (4,15), (2,11), (3,10), (1,15); +create user foo@localhost; +grant SELECT on db.t1 to foo@localhost; +grant SELECT(a) on db.t2 to foo@localhost; +connect con1,localhost,foo,,; +use db; +with cte as (select * from t1 where i < 4) +select * from cte; +i +3 +1 +2 +3 +1 +with cte as (select * from t1 where i < 4 group by i) +select * from cte; +i +1 +2 +3 +with cte as (select * from t1 where i < 4) +select * from cte cte1 where i < 2 union select * from cte cte2 where i > 2; +i +1 +3 +with cte as (select * from t1 where i < 4 group by i) +select * from cte cte1 where i < 2 union select * from cte cte2 where i > 2; +i +1 +3 +with cte as (select b from t2 where a < 4) +select * from cte cte1 where b < 15 union select * from cte cte2 where b > 15; +ERROR 42000: SELECT command denied to user 'foo'@'localhost' for column 'b' in table 't2' +with cte as (select a from t2 where a < 4) +select * from cte cte1 where a < 2 union select * from cte cte2 where a > 2; +a +1 +3 +connection default; +revoke SELECT on db.t1 from foo@localhost; +connection con1; +with cte as (select * from t1 where i < 4) +select * from cte; +ERROR 42000: SELECT command denied to user 'foo'@'localhost' for table 't1' +disconnect con1; +connection default; +drop database db; +drop user foo@localhost; diff --git a/mysql-test/t/cte_nonrecursive.test b/mysql-test/t/cte_nonrecursive.test index 742e8f6e4d7..03e6e298fa8 100644 --- a/mysql-test/t/cte_nonrecursive.test +++ b/mysql-test/t/cte_nonrecursive.test @@ -790,3 +790,54 @@ SHOW CREATE VIEW cte_test; SELECT * FROM cte_test; DROP VIEW cte_test; + +--echo # +--echo # MDEV-13453: privileges checking for CTE +--echo # + +create database db; +use db; +create table t1 (i int); +insert into t1 + values (3), (7), (1), (4), (2), (3), (1); + +create table t2 (a int, b int); +insert into t2 + values (3,10), (7,11), (1,17), (4,15), (2,11), (3,10), (1,15); + +create user foo@localhost; +grant SELECT on db.t1 to foo@localhost; +grant SELECT(a) on db.t2 to foo@localhost; + +--connect (con1,localhost,foo,,) +use db; +with cte as (select * from t1 where i < 4) + select * from cte; +with cte as (select * from t1 where i < 4 group by i) + select * from cte; +with cte as (select * from t1 where i < 4) + select * from cte cte1 where i < 2 union select * from cte cte2 where i > 2; +with cte as (select * from t1 where i < 4 group by i) + select * from cte cte1 where i < 2 union select * from cte cte2 where i > 2; + +--error ER_COLUMNACCESS_DENIED_ERROR +with cte as (select b from t2 where a < 4) + select * from cte cte1 where b < 15 union select * from cte cte2 where b > 15; +with cte as (select a from t2 where a < 4) + select * from cte cte1 where a < 2 union select * from cte cte2 where a > 2; + +--connection default +revoke SELECT on db.t1 from foo@localhost; + +--connection con1 + +--error ER_TABLEACCESS_DENIED_ERROR +with cte as (select * from t1 where i < 4) + select * from cte; + +# Cleanup +--disconnect con1 + +--connection default +drop database db; +drop user foo@localhost; diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 555865804f9..74f06e7654d 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -7557,6 +7557,10 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables, tl->correspondent_table ? tl->correspondent_table : tl; sctx= t_ref->security_ctx ? t_ref->security_ctx : thd->security_ctx; + if (tl->with || + (tl->with= tl->select_lex->find_table_def_in_with_clauses(tl))) + continue; + const ACL_internal_table_access *access= get_cached_table_access(&t_ref->grant.m_internal, t_ref->get_db_name(), diff --git a/sql/sql_cte.cc b/sql/sql_cte.cc index 6fe08e3c0ed..e1bd455830d 100644 --- a/sql/sql_cte.cc +++ b/sql/sql_cte.cc @@ -823,9 +823,10 @@ st_select_lex_unit *With_element::clone_parsed_spec(THD *thd, tbl; tbl= tbl->next_global) { - tbl->grant.privilege= with_table->grant.privilege; spec_tables_tail= tbl; } + if (check_table_access(thd, SELECT_ACL, spec_tables, FALSE, UINT_MAX, FALSE)) + goto err; if (spec_tables) { if (with_table->next_global) diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index bf5144bfda6..fff58427aff 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -3443,6 +3443,14 @@ mysql_execute_command(THD *thd) ulong privileges_requested= lex->exchange ? SELECT_ACL | FILE_ACL : SELECT_ACL; + /* + The same function must be called for DML commands + when CTEs are supported in DML statements + */ + res= check_dependencies_in_with_clauses(thd->lex->with_clauses_list); + if (res) + break; + if (all_tables) res= check_table_access(thd, privileges_requested, From 5e7435c4b01737e106c19e8417a374df313cc344 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 15 Nov 2017 08:53:02 +0200 Subject: [PATCH 10/18] Correct a merge error (remove a bogus #ifdef) --- storage/innobase/buf/buf0buf.cc | 2 -- 1 file changed, 2 deletions(-) diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc index 7382a40c781..90d5e12948f 100644 --- a/storage/innobase/buf/buf0buf.cc +++ b/storage/innobase/buf/buf0buf.cc @@ -4298,10 +4298,8 @@ loop: case BUF_GET_IF_IN_POOL_OR_WATCH: case BUF_PEEK_IF_IN_POOL: case BUF_EVICT_IF_IN_POOL: -#ifdef UNIV_SYNC_DEBUG ut_ad(!rw_lock_own(hash_lock, RW_LOCK_X)); ut_ad(!rw_lock_own(hash_lock, RW_LOCK_S)); -#endif /* UNIV_SYNC_DEBUG */ return(NULL); } From 88cc6db0a48eef6556743979935f2a3725205c57 Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Wed, 15 Nov 2017 13:25:55 +0100 Subject: [PATCH 11/18] MDEV-13453: Executing a query via CTE requires more permissions than the query itself Fix of nondebuging version issue --- sql/sql_acl.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 74f06e7654d..7f155ec7808 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -7558,7 +7558,8 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables, sctx= t_ref->security_ctx ? t_ref->security_ctx : thd->security_ctx; if (tl->with || - (tl->with= tl->select_lex->find_table_def_in_with_clauses(tl))) + (tl->select_lex && + (tl->with= tl->select_lex->find_table_def_in_with_clauses(tl)))) continue; const ACL_internal_table_access *access= From 2401d14e6b4449dd6181f728e160eb7c8f23bd40 Mon Sep 17 00:00:00 2001 From: Jun Su Date: Wed, 25 Oct 2017 17:41:23 +0800 Subject: [PATCH 12/18] Support CRC32 SSE2 implementation under Windows --- storage/innobase/ut/ut0crc32.cc | 45 ++++++++++++++++++++++++++++++--- 1 file changed, 41 insertions(+), 4 deletions(-) diff --git a/storage/innobase/ut/ut0crc32.cc b/storage/innobase/ut/ut0crc32.cc index 386d32f6a60..4e80ca67562 100644 --- a/storage/innobase/ut/ut0crc32.cc +++ b/storage/innobase/ut/ut0crc32.cc @@ -86,6 +86,10 @@ mysys/my_perf.c, contributed by Facebook under the following license. #include "univ.i" #include "ut0crc32.h" +#ifdef _MSC_VER +#include +#endif + /** Pointer to CRC32 calculation function. */ ut_crc32_func_t ut_crc32; @@ -135,7 +139,7 @@ ut_crc32_power8( } #endif -#if defined(__GNUC__) && defined(__x86_64__) +#if (defined(__GNUC__) && defined(__x86_64__)) || defined(_MSC_VER) /********************************************************************//** Fetches CPU info */ static @@ -150,10 +154,29 @@ ut_cpuid( uint32_t* features_edx) /*!< out: CPU features edx */ { uint32_t sig; +#ifdef _MSC_VER + int data[4]; + __cpuid(data, 0); + /* ebx */ + vend[0] = data[1]; + /* edx */ + vend[1] = data[3]; + /* ecx */ + vend[2] = data[2]; + + __cpuid(data, 1); + /* eax */ + sig = data[0]; + /* ecx */ + *features_ecx = data[2]; + /* edx */ + *features_edx = data[3]; +#else asm("cpuid" : "=b" (vend[0]), "=c" (vend[2]), "=d" (vend[1]) : "a" (0)); asm("cpuid" : "=a" (sig), "=c" (*features_ecx), "=d" (*features_edx) : "a" (1) : "ebx"); +#endif *model = ((sig >> 4) & 0xF); *family = ((sig >> 8) & 0xF); @@ -180,11 +203,15 @@ ut_crc32_8_hw( const byte** data, ulint* len) { +#ifdef _MSC_VER + *crc = _mm_crc32_u8(*crc, (*data)[0]); +#else asm("crc32b %1, %0" /* output operands */ : "+r" (*crc) /* input operands */ : "rm" ((*data)[0])); +#endif (*data)++; (*len)--; @@ -201,12 +228,22 @@ ut_crc32_64_low_hw( uint64_t data) { uint64_t crc_64bit = crc; - +#ifdef _MSC_VER +#ifdef _M_X64 + crc_64bit = _mm_crc32_u64(crc_64bit, data); +#elif defined(_M_IX86) + crc = _mm_crc32_u32(crc, static_cast(data)); + crc_64bit = _mm_crc32_u32(crc, static_cast(data >> 32)); +#else +#error Not Supported processors type. +#endif +#else asm("crc32q %1, %0" /* output operands */ : "+r" (crc_64bit) /* input operands */ : "rm" (data)); +#endif return(static_cast(crc_64bit)); } @@ -429,7 +466,7 @@ ut_crc32_byte_by_byte_hw( return(~crc); } -#endif /* defined(__GNUC__) && defined(__x86_64__) */ +#endif /* defined(__GNUC__) && defined(__x86_64__) || (_WIN64) */ /* CRC32 software implementation. */ @@ -704,7 +741,7 @@ ut_crc32_init() ut_crc32_byte_by_byte = ut_crc32_byte_by_byte_sw; ut_crc32_implementation = "Using generic crc32 instructions"; -#if defined(__GNUC__) && defined(__x86_64__) +#if (defined(__GNUC__) && defined(__x86_64__)) || defined(_MSC_VER) uint32_t vend[3]; uint32_t model; uint32_t family; From 0c4d11e8199f4c7a9e41fc3f86819219c21ddc4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Thu, 16 Nov 2017 11:05:24 +0200 Subject: [PATCH 13/18] MDEV-13206: INSERT ON DUPLICATE KEY UPDATE foreign key fail MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is caused by following change: commit 95d29c99f01882ffcc2259f62b3163f9b0e80c75 Author: Marko Mäkelä Date: Tue Nov 27 11:12:13 2012 +0200 Bug#15920445 INNODB REPORTS ER_DUP_KEY BEFORE CREATE UNIQUE INDEX COMPLETED There is a phase during online secondary index creation where the index has been internally completed inside InnoDB, but does not 'officially' exist yet. We used to report ER_DUP_KEY in these situations, like this: ERROR 23000: Can't write; duplicate key in table 't1' What we should do is to let the 'offending' operation complete, but report an error to the ALTER TABLE t1 ADD UNIQUE KEY (c2): ERROR HY000: Index c2 is corrupted (This misleading error message should be fixed separately: Bug#15920713 CREATE UNIQUE INDEX REPORTS ER_INDEX_CORRUPT INSTEAD OF DUPLICATE) row_ins_sec_index_entry_low(): flag the index corrupted instead of reporting a duplicate, in case the index has not been published yet. rb:1614 approved by Jimmy Yang Problem is that after we have found duplicate key on primary key we continue to get necessary gap locks in secondary indexes to block concurrent transactions from inserting the searched records. However, search from unique index used in foreign key constraint could return DB_NO_REFERENCED_ROW if INSERT .. ON DUPLICATE KEY UPDATE does not contain value for foreign key column. In this case we should return the original DB_DUPLICATE_KEY error instead of DB_NO_REFERENCED_ROW. Consider as a example following: create table child(a int not null primary key, b int not null, c int, unique key (b), foreign key (b) references parent (id)) engine=innodb; insert into child values (1,1,2); insert into child(a) values (1) on duplicate key update c = 3; Now primary key value 1 naturally causes duplicate key error that will be stored on node->duplicate. If there was no duplicate key error, we should return the actual no referenced row error. As value for column b used in both unique key and foreign key is not provided, server uses 0 as a search value. This is naturally, not found leading to DB_NO_REFERENCED_ROW. But, we should update the row with primay key value 1 anyway as requested by on duplicate key update clause. --- .../r/innodb-on-duplicate-update.result | 60 ++++++++++++++++++ .../innodb/t/innodb-on-duplicate-update.test | 63 +++++++++++++++++++ storage/innobase/row/row0ins.cc | 55 +++++++++++++++- 3 files changed, 177 insertions(+), 1 deletion(-) create mode 100644 mysql-test/suite/innodb/r/innodb-on-duplicate-update.result create mode 100644 mysql-test/suite/innodb/t/innodb-on-duplicate-update.test diff --git a/mysql-test/suite/innodb/r/innodb-on-duplicate-update.result b/mysql-test/suite/innodb/r/innodb-on-duplicate-update.result new file mode 100644 index 00000000000..474ebf33bbd --- /dev/null +++ b/mysql-test/suite/innodb/r/innodb-on-duplicate-update.result @@ -0,0 +1,60 @@ +set sql_mode=''; +set innodb_strict_mode=0; +CREATE TABLE `v` ( +`id` int(11) unsigned NOT NULL AUTO_INCREMENT, +PRIMARY KEY (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; +INSERT v values (1); +CREATE TABLE `vp` ( +`id` int(11) unsigned NOT NULL AUTO_INCREMENT, +`v_id` int(10) unsigned NOT NULL, +`p_id` int(10) unsigned NOT NULL, +`ppp` varchar(255) NOT NULL, +PRIMARY KEY (`id`), +UNIQUE KEY `IDX_vp_uniq` (`v_id`,`p_id`), +KEY `FK_vp_v` (`v_id`), +CONSTRAINT `FK_vp_v` FOREIGN KEY (`v_id`) REFERENCES `v` (`id`) ON DELETE CASCADE ON UPDATE CASCADE +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; +INSERT vp VALUES (12, 1, 100, 'text12'); +INSERT INTO `vp` (`id`,`ppp`) VALUES (12, 'test12-2') ON DUPLICATE KEY UPDATE `ppp` = VALUES(`ppp`); +Warnings: +Warning 1364 Field 'v_id' doesn't have a default value +Warning 1364 Field 'p_id' doesn't have a default value +SELECT * FROM vp; +id v_id p_id ppp +12 1 100 test12-2 +DROP TABLE vp, v; +CREATE TABLE t1 (i int PRIMARY KEY) ENGINE=InnoDB; +INSERT into t1 values (1); +CREATE TABLE t2 ( +i int not null primary key, +vi int not null, +m int, +UNIQUE KEY (vi), +CONSTRAINT `cc` FOREIGN KEY (vi) REFERENCES t1 (i) ON DELETE CASCADE ON UPDATE CASCADE +) ENGINE=InnoDB; +INSERT into t2 VALUES (1, 1, 100); +INSERT INTO t2 (i,m) VALUES (1, 2) ON DUPLICATE KEY UPDATE m=3; +Warnings: +Warning 1364 Field 'vi' doesn't have a default value +SELECT * FROM t2; +i vi m +1 1 3 +DROP TABLE t2,t1; +CREATE TABLE t1 (i int PRIMARY KEY) ENGINE=InnoDB; +INSERT into t1 values (1); +CREATE TABLE t2 ( +i int not null primary key, +vi int not null, +m int, +KEY (vi), +CONSTRAINT `cc` FOREIGN KEY (vi) REFERENCES t1 (i) ON DELETE CASCADE ON UPDATE CASCADE +) ENGINE=InnoDB; +INSERT into t2 VALUES (1, 1, 100); +INSERT INTO t2 (i,m) VALUES (1, 2) ON DUPLICATE KEY UPDATE m=3; +Warnings: +Warning 1364 Field 'vi' doesn't have a default value +SELECT * FROM t2; +i vi m +1 1 3 +DROP TABLE t2, t1; diff --git a/mysql-test/suite/innodb/t/innodb-on-duplicate-update.test b/mysql-test/suite/innodb/t/innodb-on-duplicate-update.test new file mode 100644 index 00000000000..cc80198d24a --- /dev/null +++ b/mysql-test/suite/innodb/t/innodb-on-duplicate-update.test @@ -0,0 +1,63 @@ +--source include/have_innodb.inc + +# +# MDEV-13206: INSERT ON DUPLICATE KEY UPDATE foreign key fail +# +set sql_mode=''; +set innodb_strict_mode=0; + +CREATE TABLE `v` ( + `id` int(11) unsigned NOT NULL AUTO_INCREMENT, + PRIMARY KEY (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; + +INSERT v values (1); + +CREATE TABLE `vp` ( + `id` int(11) unsigned NOT NULL AUTO_INCREMENT, + `v_id` int(10) unsigned NOT NULL, + `p_id` int(10) unsigned NOT NULL, + `ppp` varchar(255) NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `IDX_vp_uniq` (`v_id`,`p_id`), + KEY `FK_vp_v` (`v_id`), + CONSTRAINT `FK_vp_v` FOREIGN KEY (`v_id`) REFERENCES `v` (`id`) ON DELETE CASCADE ON UPDATE CASCADE +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; + +INSERT vp VALUES (12, 1, 100, 'text12'); +INSERT INTO `vp` (`id`,`ppp`) VALUES (12, 'test12-2') ON DUPLICATE KEY UPDATE `ppp` = VALUES(`ppp`); +SELECT * FROM vp; +DROP TABLE vp, v; + +CREATE TABLE t1 (i int PRIMARY KEY) ENGINE=InnoDB; +INSERT into t1 values (1); + +CREATE TABLE t2 ( + i int not null primary key, + vi int not null, + m int, + UNIQUE KEY (vi), + CONSTRAINT `cc` FOREIGN KEY (vi) REFERENCES t1 (i) ON DELETE CASCADE ON UPDATE CASCADE +) ENGINE=InnoDB; + +INSERT into t2 VALUES (1, 1, 100); +INSERT INTO t2 (i,m) VALUES (1, 2) ON DUPLICATE KEY UPDATE m=3; +SELECT * FROM t2; + +DROP TABLE t2,t1; + +CREATE TABLE t1 (i int PRIMARY KEY) ENGINE=InnoDB; +INSERT into t1 values (1); + +CREATE TABLE t2 ( + i int not null primary key, + vi int not null, + m int, + KEY (vi), + CONSTRAINT `cc` FOREIGN KEY (vi) REFERENCES t1 (i) ON DELETE CASCADE ON UPDATE CASCADE +) ENGINE=InnoDB; + +INSERT into t2 VALUES (1, 1, 100); +INSERT INTO t2 (i,m) VALUES (1, 2) ON DUPLICATE KEY UPDATE m=3; +SELECT * FROM t2; +DROP TABLE t2, t1; diff --git a/storage/innobase/row/row0ins.cc b/storage/innobase/row/row0ins.cc index a4c395610f5..301940bafa0 100644 --- a/storage/innobase/row/row0ins.cc +++ b/storage/innobase/row/row0ins.cc @@ -3608,6 +3608,11 @@ row_ins( switch (err) { case DB_SUCCESS: break; + case DB_NO_REFERENCED_ROW: + if (!dict_index_is_unique(node->index)) { + DBUG_RETURN(err); + } + /* fall through */ case DB_DUPLICATE_KEY: ut_ad(dict_index_is_unique(node->index)); @@ -3624,7 +3629,55 @@ row_ins( secondary indexes to block concurrent transactions from inserting the searched records. */ - if (!node->duplicate) { + if (err == DB_NO_REFERENCED_ROW + && node->duplicate) { + /* A foreign key check on a + unique index may fail to + find the record. + + Consider as a example + following: + create table child(a int not null + primary key, b int not null, + c int, + unique key (b), + foreign key (b) references + parent (id)) engine=innodb; + + insert into child values + (1,1,2); + + insert into child(a) values + (1) on duplicate key update + c = 3; + + Now primary key value 1 + naturally causes duplicate + key error that will be + stored on node->duplicate. + If there was no duplicate + key error, we should return + the actual no referenced + row error. + + As value for + column b used in both unique + key and foreign key is not + provided, server uses 0 as a + search value. This is + naturally, not found leading + to DB_NO_REFERENCED_ROW. + But, we should update the + row with primay key value 1 + anyway. + + Return the + original DB_DUPLICATE_KEY + error after + placing all gaplocks. */ + err = DB_DUPLICATE_KEY; + break; + } else if (!node->duplicate) { /* Save 1st dup error. Ignore subsequent dup errors. */ node->duplicate = node->index; From 842dce378aae168a339fc8d789e3e395903aeb26 Mon Sep 17 00:00:00 2001 From: Alexey Botchkov Date: Thu, 16 Nov 2017 19:59:27 +0400 Subject: [PATCH 14/18] MDEV-14402 JSON_VALUE doesn't escape quote. Result unescaping added. --- mysql-test/r/func_json.result | 3 +++ mysql-test/t/func_json.test | 1 + sql/item_jsonfunc.cc | 10 ++++++---- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/mysql-test/r/func_json.result b/mysql-test/r/func_json.result index 041030f4aab..55e64ea38e3 100644 --- a/mysql-test/r/func_json.result +++ b/mysql-test/r/func_json.result @@ -28,6 +28,9 @@ NULL select json_value('{"key1": [1,2,3], "key1":123}', '$.key1'); json_value('{"key1": [1,2,3], "key1":123}', '$.key1') 123 +select JSON_VALUE('{ "x": [0,1], "y": "[0,1]", "z": "Mon\\\"t\\\"y" }','$.z'); +JSON_VALUE('{ "x": [0,1], "y": "[0,1]", "z": "Mon\\\"t\\\"y" }','$.z') +Mon"t"y select json_query('{"key1":{"a":1, "b":[1,2]}}', '$.key2'); json_query('{"key1":{"a":1, "b":[1,2]}}', '$.key2') NULL diff --git a/mysql-test/t/func_json.test b/mysql-test/t/func_json.test index 2052fad0c04..c6c7c8d3976 100644 --- a/mysql-test/t/func_json.test +++ b/mysql-test/t/func_json.test @@ -9,6 +9,7 @@ select json_value('{"key1":123}', '$.key2'); select json_value('{"key1":123}', '$.key1'); select json_value('{"key1":[1,2,3]}', '$.key1'); select json_value('{"key1": [1,2,3], "key1":123}', '$.key1'); +select JSON_VALUE('{ "x": [0,1], "y": "[0,1]", "z": "Mon\\\"t\\\"y" }','$.z'); select json_query('{"key1":{"a":1, "b":[1,2]}}', '$.key2'); select json_query('{"key1":{"a":1, "b":[1,2]}}', '$.key1'); diff --git a/sql/item_jsonfunc.cc b/sql/item_jsonfunc.cc index 9493d75018d..ff062b81a2e 100644 --- a/sql/item_jsonfunc.cc +++ b/sql/item_jsonfunc.cc @@ -69,6 +69,7 @@ static inline bool append_simple(String *s, const uchar *a, size_t a_len) /* Appends JSON string to the String object taking charsets in consideration. +*/ static int st_append_json(String *s, CHARSET_INFO *json_cs, const uchar *js, uint js_len) { @@ -82,9 +83,8 @@ static int st_append_json(String *s, return 0; } - return js_len; + return str_len; } -*/ /* @@ -475,6 +475,9 @@ String *Item_func_json_value::val_str(String *str) json_scan_start(&je, js->charset(),(const uchar *) js->ptr(), (const uchar *) js->ptr() + js->length()); + str->length(0); + str->set_charset(&my_charset_utf8mb4_bin); + path.cur_step= path.p.steps; continue_search: if (json_find_path(&je, &path.p, &path.cur_step, array_counters)) @@ -515,8 +518,7 @@ bool Item_func_json_value::check_and_get_value(json_engine_t *je, String *res, return true; } - res->set((const char *) je->value, je->value_len, je->s.cs); - return false; + return st_append_json(res, je->s.cs, je->value, je->value_len); } From 689168be1240cf61d0ea17529e79660e98d15b46 Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Thu, 16 Nov 2017 18:57:18 +0000 Subject: [PATCH 15/18] MDEV-13852 - redefine WinWriteableFile such as IsSyncThreadSafe() is set to true, as it should. Copy and modify original io_win.h header file to a different location (as we cannot patch anything in submodule). Make sure modified header is used. --- storage/rocksdb/build_rocksdb.cmake | 5 + storage/rocksdb/mysql-test/rocksdb/suite.pm | 1 - storage/rocksdb/patch/port/win/io_win.h | 446 ++++++++++++++++++++ 3 files changed, 451 insertions(+), 1 deletion(-) create mode 100644 storage/rocksdb/patch/port/win/io_win.h diff --git a/storage/rocksdb/build_rocksdb.cmake b/storage/rocksdb/build_rocksdb.cmake index f7a2cdda46f..dd23304a223 100644 --- a/storage/rocksdb/build_rocksdb.cmake +++ b/storage/rocksdb/build_rocksdb.cmake @@ -11,6 +11,11 @@ INCLUDE_DIRECTORIES( ${ROCKSDB_SOURCE_DIR}/third-party/gtest-1.7.0/fused-src ) +IF(WIN32) + INCLUDE_DIRECTORIES(BEFORE + ${CMAKE_CURRENT_SOURCE_DIR}/patch) +ENDIF() + list(APPEND CMAKE_MODULE_PATH "${ROCKSDB_SOURCE_DIR}/cmake/modules/") if(WIN32) diff --git a/storage/rocksdb/mysql-test/rocksdb/suite.pm b/storage/rocksdb/mysql-test/rocksdb/suite.pm index 133d9344414..3423d34ded5 100644 --- a/storage/rocksdb/mysql-test/rocksdb/suite.pm +++ b/storage/rocksdb/mysql-test/rocksdb/suite.pm @@ -23,7 +23,6 @@ $ENV{MARIAROCKS_SST_DUMP}="$sst_dump"; # Temporarily disable testing under valgrind, due to MDEV-12439 return "RocksDB tests disabled under valgrind" if ($::opt_valgrind); -return "Temporarily disabled on Windows due to MDEV-13852" if (My::SysInfo::IS_WINDOWS); bless { }; diff --git a/storage/rocksdb/patch/port/win/io_win.h b/storage/rocksdb/patch/port/win/io_win.h new file mode 100644 index 00000000000..f5ff253bbaa --- /dev/null +++ b/storage/rocksdb/patch/port/win/io_win.h @@ -0,0 +1,446 @@ +// Copyright (c) 2011-present, Facebook, Inc. All rights reserved. +// This source code is licensed under both the GPLv2 (found in the +// COPYING file in the root directory) and Apache 2.0 License +// (found in the LICENSE.Apache file in the root directory). +// +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +#pragma once + +#include +#include +#include + +#include "rocksdb/status.h" +#include "rocksdb/env.h" +#include "util/aligned_buffer.h" + +#include + + +namespace rocksdb { +namespace port { + +std::string GetWindowsErrSz(DWORD err); + +inline Status IOErrorFromWindowsError(const std::string& context, DWORD err) { + return ((err == ERROR_HANDLE_DISK_FULL) || (err == ERROR_DISK_FULL)) + ? Status::NoSpace(context, GetWindowsErrSz(err)) + : Status::IOError(context, GetWindowsErrSz(err)); +} + +inline Status IOErrorFromLastWindowsError(const std::string& context) { + return IOErrorFromWindowsError(context, GetLastError()); +} + +inline Status IOError(const std::string& context, int err_number) { + return (err_number == ENOSPC) + ? Status::NoSpace(context, strerror(err_number)) + : Status::IOError(context, strerror(err_number)); +} + +// Note the below two do not set errno because they are used only here in this +// file +// on a Windows handle and, therefore, not necessary. Translating GetLastError() +// to errno +// is a sad business +inline int fsync(HANDLE hFile) { + if (!FlushFileBuffers(hFile)) { + return -1; + } + + return 0; +} + +SSIZE_T pwrite(HANDLE hFile, const char* src, size_t numBytes, uint64_t offset); + +SSIZE_T pread(HANDLE hFile, char* src, size_t numBytes, uint64_t offset); + +Status fallocate(const std::string& filename, HANDLE hFile, uint64_t to_size); + +Status ftruncate(const std::string& filename, HANDLE hFile, uint64_t toSize); + +size_t GetUniqueIdFromFile(HANDLE hFile, char* id, size_t max_size); + +class WinFileData { + protected: + const std::string filename_; + HANDLE hFile_; + // If ture, the I/O issued would be direct I/O which the buffer + // will need to be aligned (not sure there is a guarantee that the buffer + // passed in is aligned). + const bool use_direct_io_; + + public: + // We want this class be usable both for inheritance (prive + // or protected) and for containment so __ctor and __dtor public + WinFileData(const std::string& filename, HANDLE hFile, bool direct_io) + : filename_(filename), hFile_(hFile), use_direct_io_(direct_io) {} + + virtual ~WinFileData() { this->CloseFile(); } + + bool CloseFile() { + bool result = true; + + if (hFile_ != NULL && hFile_ != INVALID_HANDLE_VALUE) { + result = ::CloseHandle(hFile_); + assert(result); + hFile_ = NULL; + } + return result; + } + + const std::string& GetName() const { return filename_; } + + HANDLE GetFileHandle() const { return hFile_; } + + bool use_direct_io() const { return use_direct_io_; } + + WinFileData(const WinFileData&) = delete; + WinFileData& operator=(const WinFileData&) = delete; +}; + +class WinSequentialFile : protected WinFileData, public SequentialFile { + + // Override for behavior change when creating a custom env + virtual SSIZE_T PositionedReadInternal(char* src, size_t numBytes, + uint64_t offset) const; + +public: + WinSequentialFile(const std::string& fname, HANDLE f, + const EnvOptions& options); + + ~WinSequentialFile(); + + WinSequentialFile(const WinSequentialFile&) = delete; + WinSequentialFile& operator=(const WinSequentialFile&) = delete; + + virtual Status Read(size_t n, Slice* result, char* scratch) override; + virtual Status PositionedRead(uint64_t offset, size_t n, Slice* result, + char* scratch) override; + + virtual Status Skip(uint64_t n) override; + + virtual Status InvalidateCache(size_t offset, size_t length) override; + + virtual bool use_direct_io() const override { return WinFileData::use_direct_io(); } +}; + +// mmap() based random-access +class WinMmapReadableFile : private WinFileData, public RandomAccessFile { + HANDLE hMap_; + + const void* mapped_region_; + const size_t length_; + + public: + // mapped_region_[0,length-1] contains the mmapped contents of the file. + WinMmapReadableFile(const std::string& fileName, HANDLE hFile, HANDLE hMap, + const void* mapped_region, size_t length); + + ~WinMmapReadableFile(); + + WinMmapReadableFile(const WinMmapReadableFile&) = delete; + WinMmapReadableFile& operator=(const WinMmapReadableFile&) = delete; + + virtual Status Read(uint64_t offset, size_t n, Slice* result, + char* scratch) const override; + + virtual Status InvalidateCache(size_t offset, size_t length) override; + + virtual size_t GetUniqueId(char* id, size_t max_size) const override; +}; + +// We preallocate and use memcpy to append new +// data to the file. This is safe since we either properly close the +// file before reading from it, or for log files, the reading code +// knows enough to skip zero suffixes. +class WinMmapFile : private WinFileData, public WritableFile { + private: + HANDLE hMap_; + + const size_t page_size_; // We flush the mapping view in page_size + // increments. We may decide if this is a memory + // page size or SSD page size + const size_t + allocation_granularity_; // View must start at such a granularity + + size_t reserved_size_; // Preallocated size + + size_t mapping_size_; // The max size of the mapping object + // we want to guess the final file size to minimize the remapping + size_t view_size_; // How much memory to map into a view at a time + + char* mapped_begin_; // Must begin at the file offset that is aligned with + // allocation_granularity_ + char* mapped_end_; + char* dst_; // Where to write next (in range [mapped_begin_,mapped_end_]) + char* last_sync_; // Where have we synced up to + + uint64_t file_offset_; // Offset of mapped_begin_ in file + + // Do we have unsynced writes? + bool pending_sync_; + + // Can only truncate or reserve to a sector size aligned if + // used on files that are opened with Unbuffered I/O + Status TruncateFile(uint64_t toSize); + + Status UnmapCurrentRegion(); + + Status MapNewRegion(); + + virtual Status PreallocateInternal(uint64_t spaceToReserve); + + public: + WinMmapFile(const std::string& fname, HANDLE hFile, size_t page_size, + size_t allocation_granularity, const EnvOptions& options); + + ~WinMmapFile(); + + WinMmapFile(const WinMmapFile&) = delete; + WinMmapFile& operator=(const WinMmapFile&) = delete; + + virtual Status Append(const Slice& data) override; + + // Means Close() will properly take care of truncate + // and it does not need any additional information + virtual Status Truncate(uint64_t size) override; + + virtual Status Close() override; + + virtual Status Flush() override; + + // Flush only data + virtual Status Sync() override; + + /** + * Flush data as well as metadata to stable storage. + */ + virtual Status Fsync() override; + + /** + * Get the size of valid data in the file. This will not match the + * size that is returned from the filesystem because we use mmap + * to extend file by map_size every time. + */ + virtual uint64_t GetFileSize() override; + + virtual Status InvalidateCache(size_t offset, size_t length) override; + + virtual Status Allocate(uint64_t offset, uint64_t len) override; + + virtual size_t GetUniqueId(char* id, size_t max_size) const override; +}; + +class WinRandomAccessImpl { + protected: + WinFileData* file_base_; + size_t alignment_; + + // Override for behavior change when creating a custom env + virtual SSIZE_T PositionedReadInternal(char* src, size_t numBytes, + uint64_t offset) const; + + WinRandomAccessImpl(WinFileData* file_base, size_t alignment, + const EnvOptions& options); + + virtual ~WinRandomAccessImpl() {} + + Status ReadImpl(uint64_t offset, size_t n, Slice* result, + char* scratch) const; + + size_t GetAlignment() const { return alignment_; } + + public: + + WinRandomAccessImpl(const WinRandomAccessImpl&) = delete; + WinRandomAccessImpl& operator=(const WinRandomAccessImpl&) = delete; +}; + +// pread() based random-access +class WinRandomAccessFile + : private WinFileData, + protected WinRandomAccessImpl, // Want to be able to override + // PositionedReadInternal + public RandomAccessFile { + public: + WinRandomAccessFile(const std::string& fname, HANDLE hFile, size_t alignment, + const EnvOptions& options); + + ~WinRandomAccessFile(); + + virtual Status Read(uint64_t offset, size_t n, Slice* result, + char* scratch) const override; + + virtual size_t GetUniqueId(char* id, size_t max_size) const override; + + virtual bool use_direct_io() const override { return WinFileData::use_direct_io(); } + + virtual Status InvalidateCache(size_t offset, size_t length) override; + + virtual size_t GetRequiredBufferAlignment() const override; +}; + +// This is a sequential write class. It has been mimicked (as others) after +// the original Posix class. We add support for unbuffered I/O on windows as +// well +// we utilize the original buffer as an alignment buffer to write directly to +// file with no buffering. +// No buffering requires that the provided buffer is aligned to the physical +// sector size (SSD page size) and +// that all SetFilePointer() operations to occur with such an alignment. +// We thus always write in sector/page size increments to the drive and leave +// the tail for the next write OR for Close() at which point we pad with zeros. +// No padding is required for +// buffered access. +class WinWritableImpl { + protected: + WinFileData* file_data_; + const uint64_t alignment_; + uint64_t next_write_offset_; // Needed because Windows does not support O_APPEND + uint64_t reservedsize_; // how far we have reserved space + + virtual Status PreallocateInternal(uint64_t spaceToReserve); + + WinWritableImpl(WinFileData* file_data, size_t alignment); + + ~WinWritableImpl() {} + + + uint64_t GetAlignement() const { return alignment_; } + + Status AppendImpl(const Slice& data); + + // Requires that the data is aligned as specified by + // GetRequiredBufferAlignment() + Status PositionedAppendImpl(const Slice& data, uint64_t offset); + + Status TruncateImpl(uint64_t size); + + Status CloseImpl(); + + Status SyncImpl(); + + uint64_t GetFileNextWriteOffset() { + // Double accounting now here with WritableFileWriter + // and this size will be wrong when unbuffered access is used + // but tests implement their own writable files and do not use + // WritableFileWrapper + // so we need to squeeze a square peg through + // a round hole here. + return next_write_offset_; + } + + Status AllocateImpl(uint64_t offset, uint64_t len); + + public: + WinWritableImpl(const WinWritableImpl&) = delete; + WinWritableImpl& operator=(const WinWritableImpl&) = delete; +}; + +class WinWritableFile : private WinFileData, + protected WinWritableImpl, + public WritableFile { + public: + WinWritableFile(const std::string& fname, HANDLE hFile, size_t alignment, + size_t capacity, const EnvOptions& options); + + ~WinWritableFile(); + + bool IsSyncThreadSafe() const override { + return true; + } + + virtual Status Append(const Slice& data) override; + + // Requires that the data is aligned as specified by + // GetRequiredBufferAlignment() + virtual Status PositionedAppend(const Slice& data, uint64_t offset) override; + + // Need to implement this so the file is truncated correctly + // when buffered and unbuffered mode + virtual Status Truncate(uint64_t size) override; + + virtual Status Close() override; + + // write out the cached data to the OS cache + // This is now taken care of the WritableFileWriter + virtual Status Flush() override; + + virtual Status Sync() override; + + virtual Status Fsync() override; + + // Indicates if the class makes use of direct I/O + // Use PositionedAppend + virtual bool use_direct_io() const override; + + virtual size_t GetRequiredBufferAlignment() const override; + + virtual uint64_t GetFileSize() override; + + virtual Status Allocate(uint64_t offset, uint64_t len) override; + + virtual size_t GetUniqueId(char* id, size_t max_size) const override; +}; + +class WinRandomRWFile : private WinFileData, + protected WinRandomAccessImpl, + protected WinWritableImpl, + public RandomRWFile { + public: + WinRandomRWFile(const std::string& fname, HANDLE hFile, size_t alignment, + const EnvOptions& options); + + ~WinRandomRWFile() {} + + // Indicates if the class makes use of direct I/O + // If false you must pass aligned buffer to Write() + virtual bool use_direct_io() const override; + + // Use the returned alignment value to allocate aligned + // buffer for Write() when use_direct_io() returns true + virtual size_t GetRequiredBufferAlignment() const override; + + // Write bytes in `data` at offset `offset`, Returns Status::OK() on success. + // Pass aligned buffer when use_direct_io() returns true. + virtual Status Write(uint64_t offset, const Slice& data) override; + + // Read up to `n` bytes starting from offset `offset` and store them in + // result, provided `scratch` size should be at least `n`. + // Returns Status::OK() on success. + virtual Status Read(uint64_t offset, size_t n, Slice* result, + char* scratch) const override; + + virtual Status Flush() override; + + virtual Status Sync() override; + + virtual Status Fsync() { return Sync(); } + + virtual Status Close() override; +}; + +class WinDirectory : public Directory { + public: + WinDirectory() {} + + virtual Status Fsync() override; +}; + +class WinFileLock : public FileLock { + public: + explicit WinFileLock(HANDLE hFile) : hFile_(hFile) { + assert(hFile != NULL); + assert(hFile != INVALID_HANDLE_VALUE); + } + + ~WinFileLock(); + + private: + HANDLE hFile_; +}; +} +} From 0d1e805aeb47c2ff9398ca87589a9bd7687f8f97 Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Thu, 16 Nov 2017 22:11:08 +0000 Subject: [PATCH 16/18] Fix rocksdb tests on Windows --- storage/rocksdb/mysql-test/rocksdb/t/2pc_group_commit.test | 2 +- storage/rocksdb/mysql-test/rocksdb/t/bulk_load_unsorted.test | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/storage/rocksdb/mysql-test/rocksdb/t/2pc_group_commit.test b/storage/rocksdb/mysql-test/rocksdb/t/2pc_group_commit.test index 124d700d51d..1a77424de39 100644 --- a/storage/rocksdb/mysql-test/rocksdb/t/2pc_group_commit.test +++ b/storage/rocksdb/mysql-test/rocksdb/t/2pc_group_commit.test @@ -1,6 +1,6 @@ --source include/have_rocksdb.inc --source include/have_log_bin.inc - +--source include/not_windows.inc --echo # Disable for valgrind because this takes too long --source include/not_valgrind.inc diff --git a/storage/rocksdb/mysql-test/rocksdb/t/bulk_load_unsorted.test b/storage/rocksdb/mysql-test/rocksdb/t/bulk_load_unsorted.test index 9d9433eaafa..78bb9312ca5 100644 --- a/storage/rocksdb/mysql-test/rocksdb/t/bulk_load_unsorted.test +++ b/storage/rocksdb/mysql-test/rocksdb/t/bulk_load_unsorted.test @@ -82,6 +82,7 @@ eval CREATE TABLE t3(a INT, b INT, PRIMARY KEY(a) COMMENT "$pk_cf") perl; my $fn = $ENV{'ROCKSDB_INFILE'}; open(my $fh, '>', $fn) || die "perl open($fn): $!"; +binmode $fh; my $max = 5000000; my $sign = 1; for (my $ii = 0; $ii < $max; $ii++) From 4c2c5ec94e9b06a240629c43a9686b873bd7d3b3 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Sat, 18 Nov 2017 00:19:46 +0400 Subject: [PATCH 17/18] MDEV-14434 Wrong result for CHARSET(CONCAT(?,const)) --- mysql-test/r/ps.result | 37 +++++++++++++++++++++++++++++++++++++ mysql-test/t/ps.test | 19 +++++++++++++++++++ sql/item.cc | 5 +++++ 3 files changed, 61 insertions(+) diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result index fcd5a8aa7ee..6dfc7e80ba0 100644 --- a/mysql-test/r/ps.result +++ b/mysql-test/r/ps.result @@ -4992,3 +4992,40 @@ ERROR 42000: OUT or INOUT argument 1 for routine test.p1 is not a variable or NE EXECUTE IMMEDIATE 'CALL p1(?)' USING IGNORE; ERROR 42000: OUT or INOUT argument 1 for routine test.p1 is not a variable or NEW pseudo-variable in BEFORE trigger DROP PROCEDURE p1; +# +# MDEV-14434 Wrong result for CHARSET(CONCAT(?,const)) +# +SET NAMES utf8; +EXECUTE IMMEDIATE "SELECT CHARSET(CONCAT(5,_latin1'a'))"; +CHARSET(CONCAT(5,_latin1'a')) +latin1 +EXECUTE IMMEDIATE "SELECT CHARSET(CONCAT(?,_latin1'a'))" USING 5; +CHARSET(CONCAT(?,_latin1'a')) +latin1 +EXECUTE IMMEDIATE "SELECT CHARSET(CONCAT(?,_latin1'a'))" USING 5.5; +CHARSET(CONCAT(?,_latin1'a')) +latin1 +EXECUTE IMMEDIATE "SELECT CHARSET(CONCAT(?,_latin1'a'))" USING 5.5e0; +CHARSET(CONCAT(?,_latin1'a')) +latin1 +EXECUTE IMMEDIATE "SELECT CHARSET(CONCAT(?,_latin1'a'))" USING TIME'10:20:30'; +CHARSET(CONCAT(?,_latin1'a')) +latin1 +EXECUTE IMMEDIATE "SELECT CHARSET(CONCAT(?,_latin1'a'))" USING TIMESTAMP'2001-01-01 10:20:30'; +CHARSET(CONCAT(?,_latin1'a')) +latin1 +EXECUTE IMMEDIATE "SELECT COERCIBILITY(?)" USING 5; +COERCIBILITY(?) +5 +EXECUTE IMMEDIATE "SELECT COERCIBILITY(?)" USING 5.5; +COERCIBILITY(?) +5 +EXECUTE IMMEDIATE "SELECT COERCIBILITY(?)" USING 5.5e0; +COERCIBILITY(?) +5 +EXECUTE IMMEDIATE "SELECT COERCIBILITY(?)" USING TIME'10:20:30'; +COERCIBILITY(?) +5 +EXECUTE IMMEDIATE "SELECT COERCIBILITY(?)" USING TIMESTAMP'2001-01-01 10:20:30'; +COERCIBILITY(?) +5 diff --git a/mysql-test/t/ps.test b/mysql-test/t/ps.test index b61c4cf2568..90f2b7179f9 100644 --- a/mysql-test/t/ps.test +++ b/mysql-test/t/ps.test @@ -4476,3 +4476,22 @@ EXECUTE IMMEDIATE 'CALL p1(?)' USING DEFAULT; --error ER_SP_NOT_VAR_ARG EXECUTE IMMEDIATE 'CALL p1(?)' USING IGNORE; DROP PROCEDURE p1; + + +--echo # +--echo # MDEV-14434 Wrong result for CHARSET(CONCAT(?,const)) +--echo # + +SET NAMES utf8; +EXECUTE IMMEDIATE "SELECT CHARSET(CONCAT(5,_latin1'a'))"; +EXECUTE IMMEDIATE "SELECT CHARSET(CONCAT(?,_latin1'a'))" USING 5; +EXECUTE IMMEDIATE "SELECT CHARSET(CONCAT(?,_latin1'a'))" USING 5.5; +EXECUTE IMMEDIATE "SELECT CHARSET(CONCAT(?,_latin1'a'))" USING 5.5e0; +EXECUTE IMMEDIATE "SELECT CHARSET(CONCAT(?,_latin1'a'))" USING TIME'10:20:30'; +EXECUTE IMMEDIATE "SELECT CHARSET(CONCAT(?,_latin1'a'))" USING TIMESTAMP'2001-01-01 10:20:30'; + +EXECUTE IMMEDIATE "SELECT COERCIBILITY(?)" USING 5; +EXECUTE IMMEDIATE "SELECT COERCIBILITY(?)" USING 5.5; +EXECUTE IMMEDIATE "SELECT COERCIBILITY(?)" USING 5.5e0; +EXECUTE IMMEDIATE "SELECT COERCIBILITY(?)" USING TIME'10:20:30'; +EXECUTE IMMEDIATE "SELECT COERCIBILITY(?)" USING TIMESTAMP'2001-01-01 10:20:30'; diff --git a/sql/item.cc b/sql/item.cc index e7816b34b7e..63373fc1b0d 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -3409,6 +3409,7 @@ void Item_param::set_int(longlong i, uint32 max_length_arg) DBUG_ENTER("Item_param::set_int"); value.integer= (longlong) i; state= INT_VALUE; + collation.set_numeric(); max_length= max_length_arg; decimals= 0; maybe_null= 0; @@ -3421,6 +3422,7 @@ void Item_param::set_double(double d) DBUG_ENTER("Item_param::set_double"); value.real= d; state= REAL_VALUE; + collation.set_numeric(); max_length= DBL_DIG + 8; decimals= NOT_FIXED_DEC; maybe_null= 0; @@ -3450,6 +3452,7 @@ void Item_param::set_decimal(const char *str, ulong length) str2my_decimal(E_DEC_FATAL_ERROR, str, &decimal_value, &end); state= DECIMAL_VALUE; decimals= decimal_value.frac; + collation.set_numeric(); max_length= my_decimal_precision_to_length_no_truncation(decimal_value.precision(), decimals, unsigned_flag); @@ -3465,6 +3468,7 @@ void Item_param::set_decimal(const my_decimal *dv, bool unsigned_arg) my_decimal2decimal(dv, &decimal_value); decimals= (uint8) decimal_value.frac; + collation.set_numeric(); unsigned_flag= unsigned_arg; max_length= my_decimal_precision_to_length(decimal_value.intg + decimals, decimals, unsigned_flag); @@ -3475,6 +3479,7 @@ void Item_param::set_decimal(const my_decimal *dv, bool unsigned_arg) void Item_param::fix_temporal(uint32 max_length_arg, uint decimals_arg) { state= TIME_VALUE; + collation.set_numeric(); max_length= max_length_arg; decimals= decimals_arg; fix_type(Item::DATE_ITEM); From a20c1217a5ce4235f72c59935a03b56fead2f6c4 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Sat, 18 Nov 2017 18:29:50 +0400 Subject: [PATCH 18/18] MDEV-14435 Different UNSIGNED flag of out user variable for YEAR parameter for direct vs prepared CALL --- mysql-test/r/ps.result | 49 ++++++++++++++++++++++++++++++++++++++++-- mysql-test/t/ps.test | 34 +++++++++++++++++++++++++++++ sql/item.cc | 1 + 3 files changed, 82 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result index 6dfc7e80ba0..6857ebc68af 100644 --- a/mysql-test/r/ps.result +++ b/mysql-test/r/ps.result @@ -3388,7 +3388,7 @@ CREATE TEMPORARY TABLE tmp1 AS SELECT @a AS c1; SHOW CREATE TABLE tmp1; Table Create Table tmp1 CREATE TEMPORARY TABLE `tmp1` ( - `c1` bigint(20) DEFAULT NULL + `c1` bigint(20) unsigned DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 SELECT @a, @a = b'10100100101'; @a @a = b'10100100101' @@ -3478,7 +3478,7 @@ CREATE TEMPORARY TABLE tmp1 AS SELECT @a AS c1; SHOW CREATE TABLE tmp1; Table Create Table tmp1 CREATE TEMPORARY TABLE `tmp1` ( - `c1` bigint(20) DEFAULT NULL + `c1` bigint(20) unsigned DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 SELECT @a, @a = 2010; @a @a = 2010 @@ -5029,3 +5029,48 @@ COERCIBILITY(?) EXECUTE IMMEDIATE "SELECT COERCIBILITY(?)" USING TIMESTAMP'2001-01-01 10:20:30'; COERCIBILITY(?) 5 +# +# MDEV-14435 Different UNSIGNED flag of out user variable for YEAR parameter for direct vs prepared CALL +# +CREATE PROCEDURE p1(OUT v INT UNSIGNED) SET v = 2010; +CALL p1(@a); +PREPARE stmt FROM 'CALL p1(?)'; +EXECUTE stmt USING @b; +DEALLOCATE PREPARE stmt; +CREATE TABLE t1 AS SELECT @a AS a, @b AS b; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` bigint(20) unsigned DEFAULT NULL, + `b` bigint(20) unsigned DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE t1; +DROP PROCEDURE p1; +CREATE PROCEDURE p1(OUT v YEAR) SET v = 2010; +CALL p1(@a); +PREPARE stmt FROM 'CALL p1(?)'; +EXECUTE stmt USING @b; +DEALLOCATE PREPARE stmt; +CREATE TABLE t1 AS SELECT @a AS a, @b AS b; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` bigint(20) unsigned DEFAULT NULL, + `b` bigint(20) unsigned DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE t1; +DROP PROCEDURE p1; +CREATE PROCEDURE p1(OUT v BIT(16)) SET v = 2010; +CALL p1(@a); +PREPARE stmt FROM 'CALL p1(?)'; +EXECUTE stmt USING @b; +DEALLOCATE PREPARE stmt; +CREATE TABLE t1 AS SELECT @a AS a, @b AS b; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` bigint(20) unsigned DEFAULT NULL, + `b` bigint(20) unsigned DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +DROP TABLE t1; +DROP PROCEDURE p1; diff --git a/mysql-test/t/ps.test b/mysql-test/t/ps.test index 90f2b7179f9..a7683b5aae6 100644 --- a/mysql-test/t/ps.test +++ b/mysql-test/t/ps.test @@ -4495,3 +4495,37 @@ EXECUTE IMMEDIATE "SELECT COERCIBILITY(?)" USING 5.5; EXECUTE IMMEDIATE "SELECT COERCIBILITY(?)" USING 5.5e0; EXECUTE IMMEDIATE "SELECT COERCIBILITY(?)" USING TIME'10:20:30'; EXECUTE IMMEDIATE "SELECT COERCIBILITY(?)" USING TIMESTAMP'2001-01-01 10:20:30'; + +--echo # +--echo # MDEV-14435 Different UNSIGNED flag of out user variable for YEAR parameter for direct vs prepared CALL +--echo # + +CREATE PROCEDURE p1(OUT v INT UNSIGNED) SET v = 2010; +CALL p1(@a); +PREPARE stmt FROM 'CALL p1(?)'; +EXECUTE stmt USING @b; +DEALLOCATE PREPARE stmt; +CREATE TABLE t1 AS SELECT @a AS a, @b AS b; +SHOW CREATE TABLE t1; +DROP TABLE t1; +DROP PROCEDURE p1; + +CREATE PROCEDURE p1(OUT v YEAR) SET v = 2010; +CALL p1(@a); +PREPARE stmt FROM 'CALL p1(?)'; +EXECUTE stmt USING @b; +DEALLOCATE PREPARE stmt; +CREATE TABLE t1 AS SELECT @a AS a, @b AS b; +SHOW CREATE TABLE t1; +DROP TABLE t1; +DROP PROCEDURE p1; + +CREATE PROCEDURE p1(OUT v BIT(16)) SET v = 2010; +CALL p1(@a); +PREPARE stmt FROM 'CALL p1(?)'; +EXECUTE stmt USING @b; +DEALLOCATE PREPARE stmt; +CREATE TABLE t1 AS SELECT @a AS a, @b AS b; +SHOW CREATE TABLE t1; +DROP TABLE t1; +DROP PROCEDURE p1; diff --git a/sql/item.cc b/sql/item.cc index 63373fc1b0d..029f8216bf1 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -4247,6 +4247,7 @@ Item_param::set_value(THD *thd, sp_rcontext *ctx, Item **it) } null_value= FALSE; + unsigned_flag= arg->unsigned_flag; switch (arg->result_type()) { case STRING_RESULT: