summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergei Golubchik <serg@mariadb.org>2016-05-05 08:47:17 +0200
committerSergei Golubchik <serg@mariadb.org>2016-05-05 08:47:17 +0200
commit46973bb3ad57281ae02f6d61bd7e47b6d26b8acd (patch)
tree8735789fc6a7ef9eed83088943858a03d2f76747
parentfba385e3b19149a4ec521d85b9db7717d22e3952 (diff)
parent153259874bfb32c9d1f89a682b96897e32a61986 (diff)
downloadmariadb-git-46973bb3ad57281ae02f6d61bd7e47b6d26b8acd.tar.gz
Merge branch 'bb-10.1-merge' into 10.1
-rw-r--r--VERSION2
-rw-r--r--client/client_priv.h1
-rw-r--r--client/mysql.cc35
-rw-r--r--client/mysql_upgrade.c2
-rw-r--r--client/mysqladmin.cc2
-rw-r--r--client/mysqlbinlog.cc15
-rw-r--r--client/mysqlcheck.c2
-rw-r--r--client/mysqldump.c2
-rw-r--r--client/mysqlimport.c2
-rw-r--r--client/mysqlshow.c2
-rw-r--r--client/mysqlslap.c2
-rw-r--r--client/mysqltest.cc2
-rw-r--r--cmake/plugin.cmake8
-rw-r--r--debian/mariadb-test-10.1.dirs2
-rw-r--r--extra/yassl/README6
-rw-r--r--extra/yassl/include/openssl/ssl.h2
-rw-r--r--extra/yassl/include/yassl_int.hpp8
-rw-r--r--extra/yassl/src/cert_wrapper.cpp13
-rw-r--r--extra/yassl/src/ssl.cpp14
-rw-r--r--extra/yassl/src/yassl_int.cpp33
-rw-r--r--extra/yassl/taocrypt/include/asn.hpp8
-rw-r--r--extra/yassl/taocrypt/src/asn.cpp12
-rw-r--r--extra/yassl/testsuite/test.hpp22
-rw-r--r--include/CMakeLists.txt6
-rw-r--r--libmysql/CMakeLists.txt46
-rw-r--r--libmysql/libmysql_versions.ld.in16
-rw-r--r--mysql-test/include/ctype_numconv.inc6
-rw-r--r--mysql-test/include/have_crypt.inc9
-rw-r--r--mysql-test/include/have_des.inc6
-rwxr-xr-xmysql-test/mysql-test-run.pl2
-rw-r--r--mysql-test/r/alter_table_online.result13
-rw-r--r--mysql-test/r/bigint.result6
-rw-r--r--mysql-test/r/cache_temporal_4265.result13
-rw-r--r--mysql-test/r/case.result13
-rw-r--r--mysql-test/r/ctype_binary.result9
-rw-r--r--mysql-test/r/ctype_cp1251.result9
-rw-r--r--mysql-test/r/ctype_cp850.result14
-rw-r--r--mysql-test/r/ctype_latin1.result9
-rw-r--r--mysql-test/r/ctype_ucs.result9
-rw-r--r--mysql-test/r/ctype_utf8.result9
-rw-r--r--mysql-test/r/fulltext3.result12
-rw-r--r--mysql-test/r/func_math.result9
-rw-r--r--mysql-test/r/grant5.result16
-rw-r--r--mysql-test/r/have_crypt.require2
-rw-r--r--mysql-test/r/insert_innodb.result30
-rw-r--r--mysql-test/r/locale.result11
-rw-r--r--mysql-test/r/mdev6830.result3
-rw-r--r--mysql-test/r/mysqld--help,win.rdiff2
-rw-r--r--mysql-test/r/mysqld--help.result6
-rw-r--r--mysql-test/r/null.result2
-rw-r--r--mysql-test/r/openssl_1.result9
-rw-r--r--mysql-test/r/select_debug.result2
-rw-r--r--mysql-test/r/set_password_plugin-9835.result160
-rw-r--r--mysql-test/r/sp-threads.result9
-rw-r--r--mysql-test/r/ssl_timeout-9836.result7
-rw-r--r--mysql-test/r/type_date.result35
-rw-r--r--mysql-test/r/type_timestamp.result9
-rw-r--r--mysql-test/r/wait_timeout_not_windows.result4
-rw-r--r--mysql-test/suite/binlog/r/binlog_row_binlog.result2
-rw-r--r--mysql-test/suite/handler/innodb.result1
-rw-r--r--mysql-test/suite/innodb/r/defrag_mdl-9155.result15
-rw-r--r--mysql-test/suite/innodb/r/innodb-corrupted-table.result49
-rw-r--r--mysql-test/suite/innodb/r/innodb-fk.result44
-rw-r--r--mysql-test/suite/innodb/t/defrag_mdl-9155.test22
-rw-r--r--mysql-test/suite/innodb/t/innodb-corrupted-table.test46
-rw-r--r--mysql-test/suite/innodb/t/innodb-fk.test41
-rw-r--r--mysql-test/suite/plugins/r/simple_password_check.result2
-rw-r--r--mysql-test/suite/plugins/t/simple_password_check.test6
-rw-r--r--mysql-test/suite/rpl/r/create_or_replace_mix.result2
-rw-r--r--mysql-test/suite/rpl/r/create_or_replace_row.result6
-rw-r--r--mysql-test/suite/rpl/r/create_or_replace_statement.result2
-rw-r--r--mysql-test/suite/rpl/r/rpl_killed_ddl.result10
-rw-r--r--mysql-test/suite/rpl/r/rpl_row_create_table.result4
-rw-r--r--mysql-test/suite/rpl/r/rpl_row_merge_engine.result5
-rw-r--r--mysql-test/suite/rpl/r/rpl_tmp_table_and_DDL_innodb.result13
-rw-r--r--mysql-test/suite/rpl/t/rpl_killed_ddl.test40
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_merge_engine.test6
-rw-r--r--mysql-test/suite/rpl/t/rpl_tmp_table_and_DDL_innodb.test55
-rw-r--r--mysql-test/suite/sys_vars/r/sysvars_innodb,xtradb.rdiff39
-rw-r--r--mysql-test/suite/sys_vars/r/sysvars_innodb.result2
-rw-r--r--mysql-test/suite/sys_vars/t/innodb_buffer_pool_load_now_basic.test18
-rw-r--r--mysql-test/suite/sys_vars/t/innodb_empty_free_list_algorithm_basic.opt1
-rw-r--r--mysql-test/t/alter_table_online.test26
-rw-r--r--mysql-test/t/bigint.test5
-rw-r--r--mysql-test/t/bootstrap.test2
-rw-r--r--mysql-test/t/cache_temporal_4265.test11
-rw-r--r--mysql-test/t/case.test10
-rw-r--r--mysql-test/t/ctype_cp850.test16
-rw-r--r--mysql-test/t/events_2.test4
-rw-r--r--mysql-test/t/fulltext3.test15
-rw-r--r--mysql-test/t/func_des_encrypt.test2
-rw-r--r--mysql-test/t/func_encrypt.test2
-rw-r--r--mysql-test/t/func_encrypt_ucs2.test2
-rw-r--r--mysql-test/t/func_math.test8
-rw-r--r--mysql-test/t/grant5.test18
-rw-r--r--mysql-test/t/insert_innodb.test43
-rw-r--r--mysql-test/t/kill_processlist-6619.test7
-rw-r--r--mysql-test/t/locale.test8
-rw-r--r--mysql-test/t/mdev6830-master.opt1
-rw-r--r--mysql-test/t/mdev6830.test10
-rw-r--r--mysql-test/t/mysqld--help.test2
-rw-r--r--mysql-test/t/openssl_1.test11
-rw-r--r--mysql-test/t/openssl_6975.test1
-rw-r--r--mysql-test/t/partition_innodb_plugin.test6
-rw-r--r--mysql-test/t/select_debug.test2
-rw-r--r--mysql-test/t/set_password_plugin-9835.test131
-rw-r--r--mysql-test/t/sp-threads.test9
-rw-r--r--mysql-test/t/ssl.test4
-rw-r--r--mysql-test/t/ssl_compress.test4
-rw-r--r--mysql-test/t/ssl_timeout-9836.opt1
-rw-r--r--mysql-test/t/ssl_timeout-9836.test11
-rw-r--r--mysql-test/t/ssl_timeout.test2
-rw-r--r--mysql-test/t/type_date.test30
-rw-r--r--mysql-test/t/type_timestamp.test8
-rw-r--r--mysql-test/t/wait_timeout_not_windows.test16
-rw-r--r--mysql-test/valgrind.supp7
-rw-r--r--mysys/my_copy.c1
-rw-r--r--plugin/handler_socket/client/hslongrun.cpp6
-rw-r--r--plugin/handler_socket/libhsclient/fatal.cpp8
-rw-r--r--plugin/handler_socket/libhsclient/fatal.hpp1
-rw-r--r--plugin/handler_socket/libhsclient/socket.cpp2
-rw-r--r--plugin/server_audit/server_audit.c10
-rw-r--r--scripts/mysql_system_tables.sql2
-rw-r--r--sql/create_options.cc15
-rw-r--r--sql/create_options.h6
-rw-r--r--sql/debug_sync.h1
-rw-r--r--sql/gen_lex_hash.cc2
-rw-r--r--sql/handler.cc5
-rw-r--r--sql/handler.h31
-rw-r--r--sql/item.cc11
-rw-r--r--sql/item.h2
-rw-r--r--sql/item_cmpfunc.cc26
-rw-r--r--sql/item_func.cc2
-rw-r--r--sql/item_func.h7
-rw-r--r--sql/item_geofunc.h6
-rw-r--r--sql/item_strfunc.cc10
-rw-r--r--sql/mysqld.cc5
-rw-r--r--sql/mysqld.h11
-rw-r--r--sql/opt_subselect.cc9
-rw-r--r--sql/share/errmsg-utf8.txt6
-rw-r--r--sql/sql_acl.cc78
-rw-r--r--sql/sql_admin.cc37
-rw-r--r--sql/sql_class.cc61
-rw-r--r--sql/sql_class.h14
-rw-r--r--sql/sql_connect.cc3
-rw-r--r--sql/sql_insert.cc48
-rw-r--r--sql/sql_load.cc5
-rw-r--r--sql/sql_locale.cc2
-rw-r--r--sql/sql_parse.cc43
-rw-r--r--sql/sql_parse.h3
-rw-r--r--sql/sql_select.cc71
-rw-r--r--sql/sql_table.cc22
-rw-r--r--sql/sql_update.cc14
-rw-r--r--sql/sql_yacc.yy1068
-rw-r--r--sql/sys_vars.ic2
-rw-r--r--storage/connect/CMakeLists.txt60
-rw-r--r--storage/connect/connect.cc2
-rw-r--r--storage/connect/ha_connect.cc285
-rw-r--r--storage/connect/ha_connect.h4
-rw-r--r--storage/connect/jdbccat.h29
-rw-r--r--storage/connect/jdbconn.cpp2076
-rw-r--r--storage/connect/jdbconn.h172
-rw-r--r--storage/connect/jsonudf.cpp11
-rw-r--r--storage/connect/maputil.cpp4
-rw-r--r--storage/connect/mycat.cc16
-rw-r--r--storage/connect/myconn.cpp11
-rw-r--r--storage/connect/myconn.h2
-rw-r--r--storage/connect/mysql-test/connect/r/drop-open-error.result13
-rw-r--r--storage/connect/mysql-test/connect/r/grant3.result5
-rw-r--r--storage/connect/mysql-test/connect/r/mysql_index.result321
-rw-r--r--storage/connect/mysql-test/connect/r/odbc_firebird.result93
-rw-r--r--storage/connect/mysql-test/connect/r/part_table.result25
-rw-r--r--storage/connect/mysql-test/connect/std_data/mdev9949.frmbin0 -> 35031 bytes
-rw-r--r--storage/connect/mysql-test/connect/t/drop-open-error.opt1
-rw-r--r--storage/connect/mysql-test/connect/t/drop-open-error.test29
-rw-r--r--storage/connect/mysql-test/connect/t/grant3.test11
-rw-r--r--storage/connect/mysql-test/connect/t/mysql_index.test67
-rw-r--r--storage/connect/mysql-test/connect/t/odbc_firebird.test4
-rw-r--r--storage/connect/mysql-test/connect/t/part_table.test15
-rw-r--r--storage/connect/odbconn.cpp2
-rw-r--r--storage/connect/plgdbsem.h12
-rw-r--r--storage/connect/plgdbutl.cpp3
-rw-r--r--storage/connect/reldef.cpp2
-rw-r--r--storage/connect/tabjdbc.cpp1704
-rw-r--r--storage/connect/tabjdbc.h348
-rw-r--r--storage/connect/tabmysql.cpp6
-rw-r--r--storage/connect/tabodbc.cpp8
-rwxr-xr-xstorage/connect/xindex.cpp26
-rw-r--r--storage/connect/xindex.h4
-rw-r--r--storage/federatedx/ha_federatedx.cc2
-rw-r--r--storage/innobase/dict/dict0boot.cc2
-rw-r--r--storage/innobase/dict/dict0crea.cc4
-rw-r--r--storage/innobase/fil/fil0fil.cc68
-rw-r--r--storage/innobase/fts/fts0fts.cc266
-rw-r--r--storage/innobase/fts/fts0opt.cc81
-rw-r--r--storage/innobase/handler/ha_innodb.cc157
-rw-r--r--storage/innobase/handler/ha_innodb.h15
-rw-r--r--storage/innobase/handler/handler0alter.cc14
-rw-r--r--storage/innobase/include/dict0mem.h18
-rw-r--r--storage/innobase/include/fts0fts.h24
-rw-r--r--storage/innobase/include/fts0types.h10
-rw-r--r--storage/innobase/include/os0file.h5
-rw-r--r--storage/innobase/include/os0sync.h46
-rw-r--r--storage/innobase/include/univ.i2
-rw-r--r--storage/innobase/os/os0file.cc57
-rw-r--r--storage/innobase/row/row0merge.cc5
-rw-r--r--storage/myisam/ft_boolean_search.c5
-rw-r--r--storage/myisammrg/ha_myisammrg.cc1
-rw-r--r--storage/oqgraph/ha_oqgraph.cc4
-rw-r--r--storage/oqgraph/oqgraph_judy.cc22
-rw-r--r--storage/sequence/mysql-test/sequence/group_by.result5
-rw-r--r--storage/sequence/mysql-test/sequence/group_by.test4
-rw-r--r--storage/spider/hs_client/fatal.cpp20
-rw-r--r--storage/spider/hs_client/fatal.hpp2
-rw-r--r--storage/spider/hs_client/socket.cpp2
-rw-r--r--storage/spider/spd_conn.cc34
-rw-r--r--storage/spider/spd_db_conn.cc4
-rw-r--r--storage/spider/spd_ping_table.cc4
-rw-r--r--storage/spider/spd_table.cc16
-rw-r--r--storage/spider/spd_trx.cc12
-rw-r--r--storage/tokudb/PerconaFT/cmake_modules/TokuSetupCompiler.cmake4
-rw-r--r--storage/tokudb/mysql-test/tokudb/r/cluster_filter_unpack_varchar.result4
-rw-r--r--storage/tokudb/mysql-test/tokudb/t/cluster_filter_unpack_varchar.test4
-rw-r--r--storage/xtradb/buf/buf0dump.cc25
-rw-r--r--storage/xtradb/buf/buf0flu.cc6
-rw-r--r--storage/xtradb/dict/dict0boot.cc2
-rw-r--r--storage/xtradb/dict/dict0dict.cc2
-rw-r--r--storage/xtradb/dict/dict0stats.cc19
-rw-r--r--storage/xtradb/fil/fil0fil.cc29
-rw-r--r--storage/xtradb/fts/fts0opt.cc11
-rw-r--r--storage/xtradb/handler/ha_innodb.cc484
-rw-r--r--storage/xtradb/handler/ha_innodb.h38
-rw-r--r--storage/xtradb/handler/handler0alter.cc40
-rw-r--r--storage/xtradb/include/buf0flu.h6
-rw-r--r--storage/xtradb/include/dict0mem.h18
-rw-r--r--storage/xtradb/include/ha_prototypes.h11
-rw-r--r--storage/xtradb/include/os0file.h29
-rw-r--r--storage/xtradb/include/row0log.h5
-rw-r--r--storage/xtradb/include/row0merge.h26
-rw-r--r--storage/xtradb/include/univ.i4
-rw-r--r--storage/xtradb/lock/lock0lock.cc2
-rw-r--r--storage/xtradb/os/os0file.cc22
-rw-r--r--storage/xtradb/row/row0ftsort.cc18
-rw-r--r--storage/xtradb/row/row0log.cc46
-rw-r--r--storage/xtradb/row/row0merge.cc183
-rw-r--r--storage/xtradb/srv/srv0srv.cc32
-rw-r--r--storage/xtradb/srv/srv0start.cc6
-rw-r--r--support-files/compiler_warnings.supp6
-rw-r--r--tests/mysql_client_test.c16
249 files changed, 8705 insertions, 1917 deletions
diff --git a/VERSION b/VERSION
index ea72c43ee64..6c14242d889 100644
--- a/VERSION
+++ b/VERSION
@@ -1,3 +1,3 @@
MYSQL_VERSION_MAJOR=10
MYSQL_VERSION_MINOR=1
-MYSQL_VERSION_PATCH=13
+MYSQL_VERSION_PATCH=14
diff --git a/client/client_priv.h b/client/client_priv.h
index 656c8fcf32a..c0c4954cdf0 100644
--- a/client/client_priv.h
+++ b/client/client_priv.h
@@ -1,5 +1,6 @@
/*
Copyright (c) 2001, 2012, Oracle and/or its affiliates.
+ Copyright (c) 2009, 2016, MariaDB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/client/mysql.cc b/client/mysql.cc
index e1f7ba0e5c6..be103224f87 100644
--- a/client/mysql.cc
+++ b/client/mysql.cc
@@ -1,7 +1,6 @@
/*
Copyright (c) 2000, 2014, Oracle and/or its affiliates.
- Copyright (c) 2009, 2013, Monty Program Ab.
- Copyright (c) 2013, 2014, SkySQL Ab
+ Copyright (c) 2009, 2016, MariaDB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -96,9 +95,16 @@ extern "C" {
#endif
}
-#if !defined(HAVE_VIDATTR)
-#undef vidattr
-#define vidattr(A) {} // Can't get this to work
+#ifdef HAVE_VIDATTR
+static int have_curses= 0;
+static void my_vidattr(chtype attrs)
+{
+ if (have_curses)
+ vidattr(attrs);
+}
+#else
+#undef HAVE_SETUPTERM
+#define my_vidattr(A) {} // Can't get this to work
#endif
#ifdef FN_NO_CASE_SENSE
@@ -4735,9 +4741,9 @@ com_status(String *buffer __attribute__((unused)),
if (skip_updates)
{
- vidattr(A_BOLD);
+ my_vidattr(A_BOLD);
tee_fprintf(stdout, "\nAll updates ignored to this database\n");
- vidattr(A_NORMAL);
+ my_vidattr(A_NORMAL);
}
#ifdef USE_POPEN
tee_fprintf(stdout, "Current pager:\t\t%s\n", pager);
@@ -4805,9 +4811,9 @@ com_status(String *buffer __attribute__((unused)),
}
if (safe_updates)
{
- vidattr(A_BOLD);
+ my_vidattr(A_BOLD);
tee_fprintf(stdout, "\nNote that you are running in safe_update_mode:\n");
- vidattr(A_NORMAL);
+ my_vidattr(A_NORMAL);
tee_fprintf(stdout, "\
UPDATEs and DELETEs that don't use a key in the WHERE clause are not allowed.\n\
(One can force an UPDATE/DELETE by adding LIMIT # at the end of the command.)\n\
@@ -4900,10 +4906,11 @@ put_info(const char *str,INFO_TYPE info_type, uint error, const char *sqlstate)
{
if (!inited)
{
- inited=1;
#ifdef HAVE_SETUPTERM
- (void) setupterm((char *)0, 1, (int *) 0);
+ int errret;
+ have_curses= setupterm((char *)0, 1, &errret) != ERR;
#endif
+ inited=1;
}
if (info_type == INFO_ERROR)
{
@@ -4915,7 +4922,7 @@ put_info(const char *str,INFO_TYPE info_type, uint error, const char *sqlstate)
putchar('\a'); /* This should make a bell */
#endif
}
- vidattr(A_STANDOUT);
+ my_vidattr(A_STANDOUT);
if (error)
{
if (sqlstate)
@@ -4934,9 +4941,9 @@ put_info(const char *str,INFO_TYPE info_type, uint error, const char *sqlstate)
tee_fputs(": ", file);
}
else
- vidattr(A_BOLD);
+ my_vidattr(A_BOLD);
(void) tee_puts(str, file);
- vidattr(A_NORMAL);
+ my_vidattr(A_NORMAL);
}
if (unbuffered)
fflush(file);
diff --git a/client/mysql_upgrade.c b/client/mysql_upgrade.c
index cdeaebf478f..e400087a2e8 100644
--- a/client/mysql_upgrade.c
+++ b/client/mysql_upgrade.c
@@ -1,6 +1,6 @@
/*
Copyright (c) 2006, 2013, Oracle and/or its affiliates.
- Copyright (c) 2010, 2015, MariaDB
+ Copyright (c) 2010, 2016, MariaDB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/client/mysqladmin.cc b/client/mysqladmin.cc
index 0089e03ac93..91e0b9fb405 100644
--- a/client/mysqladmin.cc
+++ b/client/mysqladmin.cc
@@ -1,6 +1,6 @@
/*
Copyright (c) 2000, 2014, Oracle and/or its affiliates.
- Copyright (c) 2010, 2015, MariaDB
+ Copyright (c) 2010, 2016, MariaDB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/client/mysqlbinlog.cc b/client/mysqlbinlog.cc
index c6a7c622ecd..da41268ee19 100644
--- a/client/mysqlbinlog.cc
+++ b/client/mysqlbinlog.cc
@@ -34,6 +34,7 @@
#define TABLE TABLE_CLIENT
#include "client_priv.h"
#include <my_time.h>
+#include <sslopt-vars.h>
/* That one is necessary for defines of OPTION_NO_FOREIGN_KEY_CHECKS etc */
#include "sql_priv.h"
#include "log_event.h"
@@ -1403,6 +1404,7 @@ static struct my_option my_options[] =
{"socket", 'S', "The socket file to use for connection.",
&sock, &sock, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0,
0, 0},
+#include <sslopt-longopts.h>
{"start-datetime", OPT_START_DATETIME,
"Start reading the binlog at first event having a datetime equal or "
"posterior to the argument; the argument must be a date and time "
@@ -1621,6 +1623,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
DBUG_PUSH(argument ? argument : default_dbug_option);
break;
#endif
+#include <sslopt-case.h>
case 'd':
one_database = 1;
break;
@@ -1773,6 +1776,18 @@ static Exit_status safe_connect()
return ERROR_STOP;
}
+#ifdef HAVE_OPENSSL
+ if (opt_use_ssl)
+ {
+ mysql_ssl_set(mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca,
+ opt_ssl_capath, opt_ssl_cipher);
+ mysql_options(mysql, MYSQL_OPT_SSL_CRL, opt_ssl_crl);
+ mysql_options(mysql, MYSQL_OPT_SSL_CRLPATH, opt_ssl_crlpath);
+ }
+ mysql_options(mysql,MYSQL_OPT_SSL_VERIFY_SERVER_CERT,
+ (char*)&opt_ssl_verify_server_cert);
+#endif /*HAVE_OPENSSL*/
+
if (opt_plugindir && *opt_plugindir)
mysql_options(mysql, MYSQL_PLUGIN_DIR, opt_plugindir);
diff --git a/client/mysqlcheck.c b/client/mysqlcheck.c
index 627fbcb1873..df5801ecbf6 100644
--- a/client/mysqlcheck.c
+++ b/client/mysqlcheck.c
@@ -1,6 +1,6 @@
/*
Copyright (c) 2001, 2013, Oracle and/or its affiliates.
- Copyright (c) 2010, 2015, MariaDB
+ Copyright (c) 2010, 2016, MariaDB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/client/mysqldump.c b/client/mysqldump.c
index 1c939b87c65..ae59380544a 100644
--- a/client/mysqldump.c
+++ b/client/mysqldump.c
@@ -1,6 +1,6 @@
/*
Copyright (c) 2000, 2013, Oracle and/or its affiliates.
- Copyright (c) 2010, 2015, Monty Program Ab.
+ Copyright (c) 2010, 2016, MariaDB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/client/mysqlimport.c b/client/mysqlimport.c
index 2363f1b69df..5b15155e039 100644
--- a/client/mysqlimport.c
+++ b/client/mysqlimport.c
@@ -1,6 +1,6 @@
/*
Copyright (c) 2000, 2015, Oracle and/or its affiliates.
- Copyright (c) 2011, 2015, MariaDB
+ Copyright (c) 2011, 2016, MariaDB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/client/mysqlshow.c b/client/mysqlshow.c
index fd81f18790a..444278d40f1 100644
--- a/client/mysqlshow.c
+++ b/client/mysqlshow.c
@@ -1,6 +1,6 @@
/*
Copyright (c) 2000, 2015, Oracle and/or its affiliates.
- Copyright (c) 2010, 2015, MariaDB
+ Copyright (c) 2010, 2016, MariaDB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/client/mysqlslap.c b/client/mysqlslap.c
index 29919f3028d..b3229980e77 100644
--- a/client/mysqlslap.c
+++ b/client/mysqlslap.c
@@ -1,6 +1,6 @@
/*
Copyright (c) 2005, 2015, Oracle and/or its affiliates.
- Copyright (c) 2010, 2015, MariaDB
+ Copyright (c) 2010, 2016, MariaDB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/client/mysqltest.cc b/client/mysqltest.cc
index 8fc8f30a9e4..bdd240e57e9 100644
--- a/client/mysqltest.cc
+++ b/client/mysqltest.cc
@@ -1,5 +1,5 @@
/* Copyright (c) 2000, 2013, Oracle and/or its affiliates.
- Copyright (c) 2009, 2013, Monty Program Ab.
+ Copyright (c) 2009, 2016, Monty Program Ab.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/cmake/plugin.cmake b/cmake/plugin.cmake
index 361cb597cac..329b60fc9f2 100644
--- a/cmake/plugin.cmake
+++ b/cmake/plugin.cmake
@@ -209,11 +209,13 @@ MACRO(MYSQL_ADD_PLUGIN)
IF(ARG_COMPONENT)
IF(CPACK_COMPONENTS_ALL AND
NOT CPACK_COMPONENTS_ALL MATCHES ${ARG_COMPONENT})
+ IF (ARG_STORAGE_ENGINE)
+ SET(ver " = %{version}-%{release}")
+ ENDIF()
+ SET(CPACK_COMPONENTS_ALL ${CPACK_COMPONENTS_ALL} ${ARG_COMPONENT} PARENT_SCOPE)
- SET(CPACK_COMPONENTS_ALL ${CPACK_COMPONENTS_ALL} ${ARG_COMPONENT})
- SET(CPACK_COMPONENTS_ALL ${CPACK_COMPONENTS_ALL} PARENT_SCOPE)
IF (NOT ARG_CLIENT)
- SET(CPACK_RPM_${ARG_COMPONENT}_PACKAGE_REQUIRES "MariaDB" PARENT_SCOPE)
+ SET(CPACK_RPM_${ARG_COMPONENT}_PACKAGE_REQUIRES "MariaDB${ver}" PARENT_SCOPE)
ENDIF()
# workarounds for cmake issues #13248 and #12864:
SET(CPACK_RPM_${ARG_COMPONENT}_PACKAGE_PROVIDES "cmake_bug_13248" PARENT_SCOPE)
diff --git a/debian/mariadb-test-10.1.dirs b/debian/mariadb-test-10.1.dirs
index 1a488d98195..b21c5b780f7 100644
--- a/debian/mariadb-test-10.1.dirs
+++ b/debian/mariadb-test-10.1.dirs
@@ -44,8 +44,6 @@ usr/share/mysql/mysql-test/suite/jp/r
usr/share/mysql/mysql-test/suite/jp/include
usr/share/mysql/mysql-test/suite/jp/std_data
usr/share/mysql/mysql-test/suite/maria
-usr/share/mysql/mysql-test/suite/maria/t
-usr/share/mysql/mysql-test/suite/maria/r
usr/share/mysql/mysql-test/suite/funcs_2
usr/share/mysql/mysql-test/suite/funcs_2/lib
usr/share/mysql/mysql-test/suite/funcs_2/t
diff --git a/extra/yassl/README b/extra/yassl/README
index 81d573d0b20..b5eb88824fb 100644
--- a/extra/yassl/README
+++ b/extra/yassl/README
@@ -12,6 +12,12 @@ before calling SSL_new();
*** end Note ***
+yaSSL Release notes, version 2.3.9b (2/03/2016)
+ This release of yaSSL fixes the OpenSSL compatibility function
+ X509_NAME_get_index_by_NID() to use the actual index of the common name
+ instead of searching on the format prefix. Thanks for the report from
+ yashwant.sahu@oracle.com . Anyone using this function should update.
+
yaSSL Release notes, version 2.3.9 (12/01/2015)
This release of yaSSL fixes two client side Diffie-Hellman problems.
yaSSL was only handling the cases of zero or one leading zeros for the key
diff --git a/extra/yassl/include/openssl/ssl.h b/extra/yassl/include/openssl/ssl.h
index 84ce40b8415..c95eb1ed887 100644
--- a/extra/yassl/include/openssl/ssl.h
+++ b/extra/yassl/include/openssl/ssl.h
@@ -34,7 +34,7 @@
#include "rsa.h"
-#define YASSL_VERSION "2.3.9"
+#define YASSL_VERSION "2.3.9b"
#if defined(__cplusplus)
diff --git a/extra/yassl/include/yassl_int.hpp b/extra/yassl/include/yassl_int.hpp
index 269976a6eaa..781eaa38dda 100644
--- a/extra/yassl/include/yassl_int.hpp
+++ b/extra/yassl/include/yassl_int.hpp
@@ -191,14 +191,18 @@ private:
class X509_NAME {
char* name_;
size_t sz_;
+ int cnPosition_; // start of common name, -1 is none
+ int cnLen_; // length of above
ASN1_STRING entry_;
public:
- X509_NAME(const char*, size_t sz);
+ X509_NAME(const char*, size_t sz, int pos, int len);
~X509_NAME();
const char* GetName() const;
ASN1_STRING* GetEntry(int i);
size_t GetLength() const;
+ int GetCnPosition() const { return cnPosition_; }
+ int GetCnLength() const { return cnLen_; }
private:
X509_NAME(const X509_NAME&); // hide copy
X509_NAME& operator=(const X509_NAME&); // and assign
@@ -226,7 +230,7 @@ class X509 {
StringHolder afterDate_; // not valid after
public:
X509(const char* i, size_t, const char* s, size_t,
- ASN1_STRING *b, ASN1_STRING *a);
+ ASN1_STRING *b, ASN1_STRING *a, int, int, int, int);
~X509() {}
X509_NAME* GetIssuer();
diff --git a/extra/yassl/src/cert_wrapper.cpp b/extra/yassl/src/cert_wrapper.cpp
index af94f5bc24f..1092e428351 100644
--- a/extra/yassl/src/cert_wrapper.cpp
+++ b/extra/yassl/src/cert_wrapper.cpp
@@ -304,7 +304,10 @@ int CertManager::Validate()
afterDate.type= cert.GetAfterDateType();
afterDate.length= strlen((char *) afterDate.data) + 1;
peerX509_ = NEW_YS X509(cert.GetIssuer(), iSz, cert.GetCommonName(),
- sSz, &beforeDate, &afterDate);
+ sSz, &beforeDate, &afterDate,
+ cert.GetIssuerCnStart(), cert.GetIssuerCnLength(),
+ cert.GetSubjectCnStart(), cert.GetSubjectCnLength()
+ );
if (err == TaoCrypt::SIG_OTHER_E && verifyCallback_) {
X509_STORE_CTX store;
@@ -350,7 +353,9 @@ int CertManager::SetPrivateKey(const x509& key)
afterDate.type= cd.GetAfterDateType();
afterDate.length= strlen((char *) afterDate.data) + 1;
selfX509_ = NEW_YS X509(cd.GetIssuer(), iSz, cd.GetCommonName(),
- sSz, &beforeDate, &afterDate);
+ sSz, &beforeDate, &afterDate,
+ cd.GetIssuerCnStart(), cd.GetIssuerCnLength(),
+ cd.GetSubjectCnStart(), cd.GetSubjectCnLength());
}
return 0;
}
@@ -367,7 +372,9 @@ void CertManager::setPeerX509(X509* x)
ASN1_STRING* after = x->GetAfter();
peerX509_ = NEW_YS X509(issuer->GetName(), issuer->GetLength(),
- subject->GetName(), subject->GetLength(), before, after);
+ subject->GetName(), subject->GetLength(), before, after,
+ issuer->GetCnPosition(), issuer->GetCnLength(),
+ subject->GetCnPosition(), subject->GetCnLength());
}
diff --git a/extra/yassl/src/ssl.cpp b/extra/yassl/src/ssl.cpp
index ccc1ad24b39..1972b29c92d 100644
--- a/extra/yassl/src/ssl.cpp
+++ b/extra/yassl/src/ssl.cpp
@@ -1351,15 +1351,13 @@ int ASN1_STRING_type(ASN1_STRING *x)
int X509_NAME_get_index_by_NID(X509_NAME* name,int nid, int lastpos)
{
int idx = -1; // not found
- const char* start = &name->GetName()[lastpos + 1];
+ int cnPos = -1;
switch (nid) {
case NID_commonName:
- const char* found = strstr(start, "/CN=");
- if (found) {
- found += 4; // advance to str
- idx = found - start + lastpos + 1;
- }
+ cnPos = name->GetCnPosition();
+ if (lastpos < cnPos)
+ idx = cnPos;
break;
}
@@ -1471,10 +1469,6 @@ int SSL_peek(SSL* ssl, void* buffer, int sz)
int SSL_pending(SSL* ssl)
{
- // Just in case there's pending data that hasn't been processed yet...
- char c;
- SSL_peek(ssl, &c, 1);
-
return ssl->bufferedData();
}
diff --git a/extra/yassl/src/yassl_int.cpp b/extra/yassl/src/yassl_int.cpp
index a38b7a5c81f..ff9c8155d0c 100644
--- a/extra/yassl/src/yassl_int.cpp
+++ b/extra/yassl/src/yassl_int.cpp
@@ -1554,8 +1554,9 @@ void SSL_SESSION::CopyX509(X509* x)
ASN1_TIME* after = x->GetAfter();
peerX509_ = NEW_YS X509(issuer->GetName(), issuer->GetLength(),
- subject->GetName(), subject->GetLength(),
- before, after);
+ subject->GetName(), subject->GetLength(), before, after,
+ issuer->GetCnPosition(), issuer->GetCnLength(),
+ subject->GetCnPosition(), subject->GetCnLength());
}
@@ -2472,8 +2473,8 @@ void Security::set_resuming(bool b)
}
-X509_NAME::X509_NAME(const char* n, size_t sz)
- : name_(0), sz_(sz)
+X509_NAME::X509_NAME(const char* n, size_t sz, int pos, int len)
+ : name_(0), sz_(sz), cnPosition_(pos), cnLen_(len)
{
if (sz) {
name_ = NEW_YS char[sz];
@@ -2503,8 +2504,10 @@ size_t X509_NAME::GetLength() const
X509::X509(const char* i, size_t iSz, const char* s, size_t sSz,
- ASN1_STRING *b, ASN1_STRING *a)
- : issuer_(i, iSz), subject_(s, sSz),
+ ASN1_STRING *b, ASN1_STRING *a,
+ int issPos, int issLen,
+ int subPos, int subLen)
+ : issuer_(i, iSz, issPos, issLen), subject_(s, sSz, subPos, subLen),
beforeDate_((char *) b->data, b->length, b->type),
afterDate_((char *) a->data, a->length, a->type)
{}
@@ -2539,17 +2542,19 @@ ASN1_STRING* X509_NAME::GetEntry(int i)
if (i < 0 || i >= int(sz_))
return 0;
+ if (i != cnPosition_ || cnLen_ <= 0) // only entry currently supported
+ return 0;
+
+ if (cnLen_ > int(sz_-i)) // make sure there's room in read buffer
+ return 0;
+
if (entry_.data)
ysArrayDelete(entry_.data);
- entry_.data = NEW_YS byte[sz_]; // max size;
+ entry_.data = NEW_YS byte[cnLen_+1]; // max size;
- memcpy(entry_.data, &name_[i], sz_ - i);
- if (entry_.data[sz_ -i - 1]) {
- entry_.data[sz_ - i] = 0;
- entry_.length = int(sz_) - i;
- }
- else
- entry_.length = int(sz_) - i - 1;
+ memcpy(entry_.data, &name_[i], cnLen_);
+ entry_.data[cnLen_] = 0;
+ entry_.length = cnLen_;
entry_.type = 0;
return &entry_;
diff --git a/extra/yassl/taocrypt/include/asn.hpp b/extra/yassl/taocrypt/include/asn.hpp
index 2854b8fe06d..999e853b941 100644
--- a/extra/yassl/taocrypt/include/asn.hpp
+++ b/extra/yassl/taocrypt/include/asn.hpp
@@ -285,6 +285,10 @@ public:
byte GetBeforeDateType() const { return beforeDateType_; }
const char* GetAfterDate() const { return afterDate_; }
byte GetAfterDateType() const { return afterDateType_; }
+ int GetSubjectCnStart() const { return subCnPos_; }
+ int GetIssuerCnStart() const { return issCnPos_; }
+ int GetSubjectCnLength() const { return subCnLen_; }
+ int GetIssuerCnLength() const { return issCnLen_; }
void DecodeToKey();
private:
@@ -294,6 +298,10 @@ private:
word32 sigLength_; // length of signature
word32 signatureOID_; // sum of algorithm object id
word32 keyOID_; // sum of key algo object id
+ int subCnPos_; // subject common name start, -1 is none
+ int subCnLen_; // length of above
+ int issCnPos_; // issuer common name start, -1 is none
+ int issCnLen_; // length of above
byte subjectHash_[SHA_SIZE]; // hash of all Names
byte issuerHash_[SHA_SIZE]; // hash of all Names
byte* signature_;
diff --git a/extra/yassl/taocrypt/src/asn.cpp b/extra/yassl/taocrypt/src/asn.cpp
index d8b133a3f0a..0474e7c21d5 100644
--- a/extra/yassl/taocrypt/src/asn.cpp
+++ b/extra/yassl/taocrypt/src/asn.cpp
@@ -482,8 +482,9 @@ void DH_Decoder::Decode(DH& key)
CertDecoder::CertDecoder(Source& s, bool decode, SignerList* signers,
bool noVerify, CertType ct)
- : BER_Decoder(s), certBegin_(0), sigIndex_(0), sigLength_(0),
- signature_(0), verify_(!noVerify)
+ : BER_Decoder(s), certBegin_(0), sigIndex_(0), sigLength_(0), subCnPos_(-1),
+ subCnLen_(0), issCnPos_(-1), issCnLen_(0), signature_(0),
+ verify_(!noVerify)
{
issuer_[0] = 0;
subject_[0] = 0;
@@ -804,6 +805,13 @@ void CertDecoder::GetName(NameType nt)
case COMMON_NAME:
if (!(ptr = AddTag(ptr, buf_end, "/CN=", 4, strLen)))
return;
+ if (nt == ISSUER) {
+ issCnPos_ = (int)(ptr - strLen - issuer_);
+ issCnLen_ = (int)strLen;
+ } else {
+ subCnPos_ = (int)(ptr - strLen - subject_);
+ subCnLen_ = (int)strLen;
+ }
break;
case SUR_NAME:
if (!(ptr = AddTag(ptr, buf_end, "/SN=", 4, strLen)))
diff --git a/extra/yassl/testsuite/test.hpp b/extra/yassl/testsuite/test.hpp
index 52f6ed79526..5374edd0e2a 100644
--- a/extra/yassl/testsuite/test.hpp
+++ b/extra/yassl/testsuite/test.hpp
@@ -470,10 +470,28 @@ inline void showPeer(SSL* ssl)
char* issuer = X509_NAME_oneline(X509_get_issuer_name(peer), 0, 0);
char* subject = X509_NAME_oneline(X509_get_subject_name(peer), 0, 0);
- printf("peer's cert info:\n issuer : %s\n subject: %s\n", issuer,
- subject);
+ X509_NAME_ENTRY* se = NULL;
+ ASN1_STRING* sd = NULL;
+ char* subCN = NULL;
+
+ X509_NAME* sub = X509_get_subject_name(peer);
+ int lastpos = -1;
+ if (sub)
+ lastpos = X509_NAME_get_index_by_NID(sub, NID_commonName, lastpos);
+ if (lastpos >= 0) {
+ se = X509_NAME_get_entry(sub, lastpos);
+ if (se)
+ sd = X509_NAME_ENTRY_get_data(se);
+ if (sd)
+ subCN = (char*)ASN1_STRING_data(sd);
+ }
+
+ printf("peer's cert info:\n issuer : %s\n subject: %s\n"
+ " subject cn: %s\n", issuer, subject, subCN);
+
free(subject);
free(issuer);
+
}
else
printf("peer has no cert!\n");
diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt
index d7853a46ecb..d0c4768e882 100644
--- a/include/CMakeLists.txt
+++ b/include/CMakeLists.txt
@@ -76,3 +76,9 @@ INSTALL(DIRECTORY . DESTINATION ${INSTALL_INCLUDEDIR}/private COMPONENT Developm
PATTERN CMakeFiles EXCLUDE
PATTERN mysql EXCLUDE
REGEX "\\./(${EXCL_RE}$)" EXCLUDE)
+
+INSTALL(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/. DESTINATION ${INSTALL_INCLUDEDIR}/private COMPONENT Development
+ FILES_MATCHING PATTERN "*.h"
+ PATTERN CMakeFiles EXCLUDE
+ PATTERN mysql EXCLUDE
+ REGEX "\\./(${EXCL_RE}$)" EXCLUDE)
diff --git a/libmysql/CMakeLists.txt b/libmysql/CMakeLists.txt
index 7dfc572b281..417f91c7879 100644
--- a/libmysql/CMakeLists.txt
+++ b/libmysql/CMakeLists.txt
@@ -274,6 +274,25 @@ SET(CLIENT_API_FUNCTIONS
)
IF(CMAKE_SYSTEM_NAME MATCHES "Linux")
+ IF (NOT DISABLE_LIBMYSQLCLIENT_SYMBOL_VERSIONING)
+
+ INCLUDE (CheckCSourceCompiles)
+ FILE(WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/src.ld"
+ "VERSION {\nlibmysqlclient_18 {\nglobal: *;\n};\n}\n")
+ SET(CMAKE_REQUIRED_LIBRARIES "-Wl,src.ld")
+ CHECK_C_SOURCE_COMPILES("int main() { return 0; }"
+ SUPPORTS_VERSION_IN_LINK_SCRIPT)
+ SET(CMAKE_REQUIRED_LIBRARIES)
+
+ IF (NOT SUPPORTS_VERSION_IN_LINK_SCRIPT)
+ # https://sourceware.org/bugzilla/show_bug.cgi?id=16895
+ MESSAGE(SEND_ERROR "Your current linker does not support VERSION "
+ "command in linker scripts like a GNU ld or any compatible linker "
+ "should. Perhaps you're using gold? Either switch to GNU ld compatible "
+ "linker or run cmake with -DDISABLE_LIBMYSQLCLIENT_SYMBOL_VERSIONING=TRUE "
+ "to be able to complete the build")
+ ENDIF (NOT SUPPORTS_VERSION_IN_LINK_SCRIPT)
+
# When building RPM, or DEB package on Debian, use ELF symbol versioning
# for compatibility with distribution packages, so client shared library can
# painlessly replace the one supplied by the distribution.
@@ -358,14 +377,26 @@ IF(CMAKE_SYSTEM_NAME MATCHES "Linux")
make_scrambled_password_323
)
- # Linker script to version symbols in Fedora- and Debian- compatible way, MDEV-5529
- SET(VERSION_SCRIPT_TEMPLATE ${CMAKE_CURRENT_SOURCE_DIR}/libmysql_versions.ld.in)
-
# Generate version script.
# Create semicolon separated lists of functions to export from
# Since RPM packages use separate versioning for 5.1 API
# and 5.5 API (libmysqlclient_16 vs libmysqlclient_18),
# we need 2 lists.
+ SET (VERSION_HEADER
+"VERSION {
+ libmysqlclient_18 {
+ global:")
+ SET (VERSION_FOOTER
+" local:
+ *;
+ };
+
+ libmysqlclient_16 {
+ /* empty here. aliases are added above */
+ };
+}
+")
+
SET (CLIENT_API_5_1_LIST)
SET (CLIENT_API_5_1_ALIASES)
FOREACH (f ${CLIENT_API_FUNCTIONS_5_1} ${CLIENT_API_5_1_EXTRA})
@@ -378,6 +409,13 @@ IF(CMAKE_SYSTEM_NAME MATCHES "Linux")
SET(CLIENT_API_5_5_LIST "${CLIENT_API_5_5_LIST}\t${f};\n")
ENDFOREACH()
+ ELSE (NOT DISABLE_LIBMYSQLCLIENT_SYMBOL_VERSIONING)
+ SET (CLIENT_API_5_1_ALIASES "/* Versioning disabled per user request. MDEV-5982 */")
+ ENDIF (NOT DISABLE_LIBMYSQLCLIENT_SYMBOL_VERSIONING)
+
+ # Linker script to version symbols in Fedora- and Debian- compatible way, MDEV-5529
+ SET(VERSION_SCRIPT_TEMPLATE ${CMAKE_CURRENT_SOURCE_DIR}/libmysql_versions.ld.in)
+
CONFIGURE_FILE(
${VERSION_SCRIPT_TEMPLATE}
${CMAKE_CURRENT_BINARY_DIR}/libmysql_versions.ld
@@ -386,7 +424,7 @@ IF(CMAKE_SYSTEM_NAME MATCHES "Linux")
SET(VERSION_SCRIPT_LINK_FLAGS
"-Wl,${CMAKE_CURRENT_BINARY_DIR}/libmysql_versions.ld")
-ENDIF()
+ENDIF(CMAKE_SYSTEM_NAME MATCHES "Linux")
SET(CLIENT_SOURCES
diff --git a/libmysql/libmysql_versions.ld.in b/libmysql/libmysql_versions.ld.in
index 8d97da5b2eb..0cf5b45cc18 100644
--- a/libmysql/libmysql_versions.ld.in
+++ b/libmysql/libmysql_versions.ld.in
@@ -27,19 +27,7 @@ mysql_get_charset_by_csname = get_charset_by_csname;
mysql_net_realloc = net_realloc;
mysql_client_errors = client_errors;
-VERSION {
-
-libmysqlclient_18 {
- global:
+@VERSION_HEADER@
@CLIENT_API_5_1_LIST@
@CLIENT_API_5_5_LIST@
-
- local:
- *;
-};
-
-libmysqlclient_16 {
- /* empty here. aliases are added above */
-};
-
-}
+@VERSION_FOOTER@
diff --git a/mysql-test/include/ctype_numconv.inc b/mysql-test/include/ctype_numconv.inc
index 1d675a5db6f..6bda2205c0e 100644
--- a/mysql-test/include/ctype_numconv.inc
+++ b/mysql-test/include/ctype_numconv.inc
@@ -1819,6 +1819,12 @@ DROP FUNCTION f1;
DROP TABLE t1;
--echo #
+--echo # MDEV-9662 Assertion `precision || !scale' failed in my_decimal_precision_to_length_no_truncation(uint, uint8, bool)
+--echo #
+SELECT @@collation_connection;
+SELECT CASE 1 WHEN 2 THEN ( - '3' ) END;
+
+--echo #
--echo # MDEV-5702 Incorrect results are returned with NULLIF()
--echo #
CREATE TABLE t1 (d DATE);
diff --git a/mysql-test/include/have_crypt.inc b/mysql-test/include/have_crypt.inc
index cbf0a7ac876..422f8922edc 100644
--- a/mysql-test/include/have_crypt.inc
+++ b/mysql-test/include/have_crypt.inc
@@ -1,4 +1,5 @@
--- require r/have_crypt.require
-disable_query_log;
-show variables like 'have_crypt';
-enable_query_log;
+# encrypt('a') is NULL if crypt(3) is not available
+# encrypt('a') is "*0" in fips mode
+if (`select length(encrypt('a')) > 3 IS NOT TRUE`) {
+ skip No crypt(3);
+}
diff --git a/mysql-test/include/have_des.inc b/mysql-test/include/have_des.inc
new file mode 100644
index 00000000000..5abdaf6e2aa
--- /dev/null
+++ b/mysql-test/include/have_des.inc
@@ -0,0 +1,6 @@
+# in the FIPS mode, OpenSSL disables DES and other weak algorithms
+source include/have_ssl_crypto_functs.inc;
+
+if (`select des_encrypt("a", "b") IS NULL`) {
+ skip DES is disabled (fips mode?);
+}
diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl
index 8ccafec342b..aa46d70cfc5 100755
--- a/mysql-test/mysql-test-run.pl
+++ b/mysql-test/mysql-test-run.pl
@@ -3222,7 +3222,7 @@ sub mysql_install_db {
# Create mtr database
mtr_tofile($bootstrap_sql_file,
- "CREATE DATABASE mtr;\n");
+ "CREATE DATABASE mtr CHARSET=latin1;\n");
# Add help tables and data for warning detection and supression
mtr_tofile($bootstrap_sql_file,
diff --git a/mysql-test/r/alter_table_online.result b/mysql-test/r/alter_table_online.result
index 05d03aeae11..e3f285437a7 100644
--- a/mysql-test/r/alter_table_online.result
+++ b/mysql-test/r/alter_table_online.result
@@ -1,4 +1,3 @@
-drop table if exists t1,t2,t3;
create table t1 (a int not null primary key, b int, c varchar(80), e enum('a','b'));
insert into t1 (a) values (1),(2),(3);
alter online table t1 modify b int default 5;
@@ -62,6 +61,18 @@ create table t3 (a int not null primary key, b int, c varchar(80)) engine=merge
alter online table t3 union=(t1,t2);
ERROR 0A000: LOCK=NONE/SHARED is not supported for this operation. Try LOCK=EXCLUSIVE.
drop table t1,t2,t3;
+create table t1 (i int) partition by hash(i) partitions 2;
+alter online table t1 comment 'test';
+drop table t1;
+create table t1 (a int);
+alter online table t1 modify a int comment 'test';
+drop table t1;
+create table t1 (a int) engine=innodb;
+alter online table t1 modify a int comment 'test';
+drop table t1;
+create table t1 (a int) partition by hash(a) partitions 2;
+alter online table t1 modify a int comment 'test';
+drop table t1;
#
# MDEV-8948 ALTER ... INPLACE does work for BINARY, BLOB
#
diff --git a/mysql-test/r/bigint.result b/mysql-test/r/bigint.result
index cc2ab456833..f21a1a763a3 100644
--- a/mysql-test/r/bigint.result
+++ b/mysql-test/r/bigint.result
@@ -502,3 +502,9 @@ a
SELECT * FROM t1 WHERE a IN (0.8,0.9);
a
DROP TABLE t1;
+#
+# MDEV-9372 select 100 between 1 and 9223372036854775808 returns false
+#
+SELECT 100 BETWEEN 1 AND 9223372036854775808;
+100 BETWEEN 1 AND 9223372036854775808
+1
diff --git a/mysql-test/r/cache_temporal_4265.result b/mysql-test/r/cache_temporal_4265.result
index b8f13e465de..980bb957e19 100644
--- a/mysql-test/r/cache_temporal_4265.result
+++ b/mysql-test/r/cache_temporal_4265.result
@@ -8,4 +8,17 @@ a
Warnings:
Note 1003 2000-01-01
Note 1003 2000-01-06
+set debug_dbug='';
+drop table t1;
+create table t1 (id int not null, ut timestamp(6) not null);
+insert into t1 values(1, '2001-01-01 00:00:00.2');
+insert into t1 values(1, '2001-01-01 00:00:00.1');
+select * from t1;
+id ut
+1 2001-01-01 00:00:00.200000
+1 2001-01-01 00:00:00.100000
+select (select max(m2.ut) from t1 m2 where m1.id <> 0) from t1 m1;
+(select max(m2.ut) from t1 m2 where m1.id <> 0)
+2001-01-01 00:00:00.200000
+2001-01-01 00:00:00.200000
drop table t1;
diff --git a/mysql-test/r/case.result b/mysql-test/r/case.result
index b1e928c5e30..9ceb7efde64 100644
--- a/mysql-test/r/case.result
+++ b/mysql-test/r/case.result
@@ -232,6 +232,19 @@ case t1.f1 when '00:00:00' then 1 end
NULL
drop table t1;
#
+# MDEV-9745 Crash with CASE WHEN TRUE THEN COALESCE(CAST(NULL AS UNSIGNED)) ELSE 4 END
+#
+CREATE TABLE t1 SELECT CASE WHEN TRUE THEN COALESCE(CAST(NULL AS UNSIGNED)) ELSE 4 END AS a;
+DESCRIBE t1;
+Field Type Null Key Default Extra
+a decimal(1,0) YES NULL
+DROP TABLE t1;
+CREATE TABLE t1 SELECT CASE WHEN TRUE THEN COALESCE(CAST(NULL AS UNSIGNED)) ELSE 40 END AS a;
+DESCRIBE t1;
+Field Type Null Key Default Extra
+a decimal(2,0) YES NULL
+DROP TABLE t1;
+#
# Start of 10.1 test
#
#
diff --git a/mysql-test/r/ctype_binary.result b/mysql-test/r/ctype_binary.result
index ac79a158943..512368a2d26 100644
--- a/mysql-test/r/ctype_binary.result
+++ b/mysql-test/r/ctype_binary.result
@@ -2887,6 +2887,15 @@ f1()
DROP FUNCTION f1;
DROP TABLE t1;
#
+# MDEV-9662 Assertion `precision || !scale' failed in my_decimal_precision_to_length_no_truncation(uint, uint8, bool)
+#
+SELECT @@collation_connection;
+@@collation_connection
+binary
+SELECT CASE 1 WHEN 2 THEN ( - '3' ) END;
+CASE 1 WHEN 2 THEN ( - '3' ) END
+NULL
+#
# MDEV-5702 Incorrect results are returned with NULLIF()
#
CREATE TABLE t1 (d DATE);
diff --git a/mysql-test/r/ctype_cp1251.result b/mysql-test/r/ctype_cp1251.result
index 08a840f7749..09344a50ee9 100644
--- a/mysql-test/r/ctype_cp1251.result
+++ b/mysql-test/r/ctype_cp1251.result
@@ -3281,6 +3281,15 @@ f1()
DROP FUNCTION f1;
DROP TABLE t1;
#
+# MDEV-9662 Assertion `precision || !scale' failed in my_decimal_precision_to_length_no_truncation(uint, uint8, bool)
+#
+SELECT @@collation_connection;
+@@collation_connection
+cp1251_general_ci
+SELECT CASE 1 WHEN 2 THEN ( - '3' ) END;
+CASE 1 WHEN 2 THEN ( - '3' ) END
+NULL
+#
# MDEV-5702 Incorrect results are returned with NULLIF()
#
CREATE TABLE t1 (d DATE);
diff --git a/mysql-test/r/ctype_cp850.result b/mysql-test/r/ctype_cp850.result
new file mode 100644
index 00000000000..c028f72b58a
--- /dev/null
+++ b/mysql-test/r/ctype_cp850.result
@@ -0,0 +1,14 @@
+#
+# Start of 5.5 tests
+#
+#
+# MDEV-9862 Illegal mix of collation, when comparing column with CASE expression
+#
+SET NAMES cp850;
+CREATE TABLE t1 (a CHAR(1) CHARACTER SET latin1);
+SELECT a FROM t1 WHERE CASE a WHEN 'aaaa' THEN 'Y' WHEN 'aaaa' THEN 'Y' ELSE NULL END <> a;
+a
+DROP TABLE t1;
+#
+# End of 5.5 tests
+#
diff --git a/mysql-test/r/ctype_latin1.result b/mysql-test/r/ctype_latin1.result
index 48475923138..c6f190101f6 100644
--- a/mysql-test/r/ctype_latin1.result
+++ b/mysql-test/r/ctype_latin1.result
@@ -3563,6 +3563,15 @@ f1()
DROP FUNCTION f1;
DROP TABLE t1;
#
+# MDEV-9662 Assertion `precision || !scale' failed in my_decimal_precision_to_length_no_truncation(uint, uint8, bool)
+#
+SELECT @@collation_connection;
+@@collation_connection
+latin1_swedish_ci
+SELECT CASE 1 WHEN 2 THEN ( - '3' ) END;
+CASE 1 WHEN 2 THEN ( - '3' ) END
+NULL
+#
# MDEV-5702 Incorrect results are returned with NULLIF()
#
CREATE TABLE t1 (d DATE);
diff --git a/mysql-test/r/ctype_ucs.result b/mysql-test/r/ctype_ucs.result
index 56174311bf3..767e034a0e5 100644
--- a/mysql-test/r/ctype_ucs.result
+++ b/mysql-test/r/ctype_ucs.result
@@ -4496,6 +4496,15 @@ f1()
DROP FUNCTION f1;
DROP TABLE t1;
#
+# MDEV-9662 Assertion `precision || !scale' failed in my_decimal_precision_to_length_no_truncation(uint, uint8, bool)
+#
+SELECT @@collation_connection;
+@@collation_connection
+ucs2_general_ci
+SELECT CASE 1 WHEN 2 THEN ( - '3' ) END;
+CASE 1 WHEN 2 THEN ( - '3' ) END
+NULL
+#
# MDEV-5702 Incorrect results are returned with NULLIF()
#
CREATE TABLE t1 (d DATE);
diff --git a/mysql-test/r/ctype_utf8.result b/mysql-test/r/ctype_utf8.result
index 816fe654028..63815bfa9ff 100644
--- a/mysql-test/r/ctype_utf8.result
+++ b/mysql-test/r/ctype_utf8.result
@@ -5338,6 +5338,15 @@ f1()
DROP FUNCTION f1;
DROP TABLE t1;
#
+# MDEV-9662 Assertion `precision || !scale' failed in my_decimal_precision_to_length_no_truncation(uint, uint8, bool)
+#
+SELECT @@collation_connection;
+@@collation_connection
+utf8_general_ci
+SELECT CASE 1 WHEN 2 THEN ( - '3' ) END;
+CASE 1 WHEN 2 THEN ( - '3' ) END
+NULL
+#
# MDEV-5702 Incorrect results are returned with NULLIF()
#
CREATE TABLE t1 (d DATE);
diff --git a/mysql-test/r/fulltext3.result b/mysql-test/r/fulltext3.result
index 4ec48369ad1..c0b871cd5a7 100644
--- a/mysql-test/r/fulltext3.result
+++ b/mysql-test/r/fulltext3.result
@@ -15,3 +15,15 @@ CREATE TABLE t1(a VARCHAR(2) CHARACTER SET big5 COLLATE big5_chinese_ci,
FULLTEXT(a));
INSERT INTO t1 VALUES(0xA3C2);
DROP TABLE t1;
+create table t1 (
+id varchar(255),
+business_name text null collate utf8mb4_unicode_ci,
+street_address text,
+fulltext index ft (business_name),
+fulltext index ft2 (street_address)
+);
+select * from t1 where match (business_name, street_address) against ('some business name and address here');
+ERROR HY000: Can't find FULLTEXT index matching the column list
+select * from t1 where match (business_name, street_address) against ('some business name and address here' in boolean mode);
+id business_name street_address
+drop table t1;
diff --git a/mysql-test/r/func_math.result b/mysql-test/r/func_math.result
index d768672efe4..f8e89dbc1c2 100644
--- a/mysql-test/r/func_math.result
+++ b/mysql-test/r/func_math.result
@@ -667,9 +667,14 @@ ERROR 22003: BIGINT UNSIGNED value is out of range in '(18446744073709551615 DIV
CREATE TABLE t1(a BIGINT, b BIGINT UNSIGNED);
INSERT INTO t1 VALUES(-9223372036854775808, 9223372036854775809);
SELECT -a FROM t1;
-ERROR 22003: BIGINT value is out of range in '-(-9223372036854775808)'
+ERROR 22003: BIGINT value is out of range in '-(`test`.`t1`.`a`)'
SELECT -b FROM t1;
-ERROR 22003: BIGINT value is out of range in '-(9223372036854775809)'
+ERROR 22003: BIGINT value is out of range in '-(`test`.`t1`.`b`)'
+INSERT INTO t1 VALUES(0,0);
+SELECT -a FROM t1;
+ERROR 22003: BIGINT value is out of range in '-(`test`.`t1`.`a`)'
+SELECT -b FROM t1;
+ERROR 22003: BIGINT value is out of range in '-(`test`.`t1`.`b`)'
DROP TABLE t1;
SET @a:=999999999999999999999999999999999999999999999999999999999999999999999999999999999;
SELECT @a + @a;
diff --git a/mysql-test/r/grant5.result b/mysql-test/r/grant5.result
index 2df394c0432..d7f3b6812bb 100644
--- a/mysql-test/r/grant5.result
+++ b/mysql-test/r/grant5.result
@@ -1,2 +1,18 @@
SHOW GRANTS FOR root@invalid_host;
ERROR 42000: There is no such grant defined for user 'root' on host 'invalid_host'
+create user test;
+create user foo;
+create role foo;
+grant foo to test;
+set role foo;
+show grants for test;
+Grants for test@%
+GRANT foo TO 'test'@'%'
+GRANT USAGE ON *.* TO 'test'@'%'
+show grants for foo;
+Grants for foo
+GRANT USAGE ON *.* TO 'foo'
+show grants for foo@'%';
+ERROR 42000: Access denied for user 'test'@'%' to database 'mysql'
+drop user test, foo;
+drop role foo;
diff --git a/mysql-test/r/have_crypt.require b/mysql-test/r/have_crypt.require
deleted file mode 100644
index 739fbb738f0..00000000000
--- a/mysql-test/r/have_crypt.require
+++ /dev/null
@@ -1,2 +0,0 @@
-Variable_name Value
-have_crypt YES
diff --git a/mysql-test/r/insert_innodb.result b/mysql-test/r/insert_innodb.result
new file mode 100644
index 00000000000..ffba9388ec4
--- /dev/null
+++ b/mysql-test/r/insert_innodb.result
@@ -0,0 +1,30 @@
+#
+# BUG#22037930: INSERT IGNORE FAILS TO IGNORE
+# FOREIGN KEY CONSTRAINT
+# Setup.
+CREATE TABLE t1 (fld1 INT PRIMARY KEY) ENGINE=INNODB;
+CREATE TABLE t2 (fld2 INT, FOREIGN KEY (fld2) REFERENCES t1 (fld1))
+ENGINE=INNODB;
+INSERT INTO t1 VALUES(0);
+INSERT INTO t2 VALUES(0);
+# Without fix, an error is reported.
+INSERT IGNORE INTO t2 VALUES(1);
+Warnings:
+Warning 1452 Cannot add or update a child row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`fld2`) REFERENCES `t1` (`fld1`))
+UPDATE IGNORE t2 SET fld2=20 WHERE fld2=0;
+UPDATE IGNORE t1 SET fld1=20 WHERE fld1=0;
+# Test for multi update.
+UPDATE IGNORE t1, t2 SET t2.fld2= t2.fld2 + 3;
+UPDATE IGNORE t1, t2 SET t1.fld1= t1.fld1 + 3;
+# Reports an error since IGNORE is not used.
+INSERT INTO t2 VALUES(1);
+ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`fld2`) REFERENCES `t1` (`fld1`))
+UPDATE t2 SET fld2=20 WHERE fld2=0;
+ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`fld2`) REFERENCES `t1` (`fld1`))
+UPDATE t1 SET fld1=20 WHERE fld1=0;
+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`fld2`) REFERENCES `t1` (`fld1`))
+UPDATE t1, t2 SET t2.fld2= t2.fld2 + 3;
+ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`fld2`) REFERENCES `t1` (`fld1`))
+UPDATE t1, t2 SET t1.fld1= t1.fld1 + 3;
+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`fld2`) REFERENCES `t1` (`fld1`))
+DROP TABLE t2, t1;
diff --git a/mysql-test/r/locale.result b/mysql-test/r/locale.result
index 1335f1ec9d5..c28cedae8b1 100644
--- a/mysql-test/r/locale.result
+++ b/mysql-test/r/locale.result
@@ -90,6 +90,17 @@ SELECT DATE_FORMAT('2001-01-07', '%w %a %W');
DATE_FORMAT('2001-01-07', '%w %a %W')
0 Du Duminică
End of 5.4 tests
+SET NAMES utf8;
+SET lc_time_names=de_AT;
+SELECT monthname('2001-01-01');
+monthname('2001-01-01')
+Jänner
+SELECT monthname('2001-02-01');
+monthname('2001-02-01')
+Februar
+SELECT monthname('2001-03-01');
+monthname('2001-03-01')
+März
#
# Start of 5.6 tests
#
diff --git a/mysql-test/r/mdev6830.result b/mysql-test/r/mdev6830.result
index 0570659e860..d1cf8c98ac1 100644
--- a/mysql-test/r/mdev6830.result
+++ b/mysql-test/r/mdev6830.result
@@ -1,5 +1,4 @@
-drop table if exists t1,t2,t3;
-drop view if exists v2,v3;
+set @@debug_dbug= 'd,opt';
CREATE TABLE t1 (pk INT PRIMARY KEY) ENGINE=MyISAM;
CREATE TABLE t2 (
f1 DATE,
diff --git a/mysql-test/r/mysqld--help,win.rdiff b/mysql-test/r/mysqld--help,win.rdiff
index a09b5603869..85e65bc2441 100644
--- a/mysql-test/r/mysqld--help,win.rdiff
+++ b/mysql-test/r/mysqld--help,win.rdiff
@@ -126,7 +126,7 @@
table-definition-cache 400
-table-open-cache 431
+table-open-cache 2000
- tc-heuristic-recover COMMIT
+ tc-heuristic-recover OFF
thread-cache-size 0
-thread-pool-idle-timeout 60
thread-pool-max-threads 1000
diff --git a/mysql-test/r/mysqld--help.result b/mysql-test/r/mysqld--help.result
index bef03904a72..f6e7c54745f 100644
--- a/mysql-test/r/mysqld--help.result
+++ b/mysql-test/r/mysqld--help.result
@@ -1066,7 +1066,7 @@ The following options may be given as the first argument:
--table-open-cache=#
The number of cached open tables
--tc-heuristic-recover=name
- Decision to use in heuristic recover process. One of:
+ Decision to use in heuristic recover process. One of: OFF,
COMMIT, ROLLBACK
--thread-cache-size=#
How many threads we should keep in a cache for reuse
@@ -1155,10 +1155,8 @@ bulk-insert-buffer-size 8388608
changed-page-bitmaps ON
character-set-client-handshake TRUE
character-set-filesystem binary
-character-set-server latin1
character-sets-dir MYSQL_CHARSETSDIR/
chroot (No default value)
-collation-server latin1_swedish_ci
completion-type NO_CHAIN
concurrent-insert AUTO
console FALSE
@@ -1424,7 +1422,7 @@ sysdate-is-now FALSE
table-cache 431
table-definition-cache 400
table-open-cache 431
-tc-heuristic-recover COMMIT
+tc-heuristic-recover OFF
thread-cache-size 0
thread-pool-idle-timeout 60
thread-pool-max-threads 1000
diff --git a/mysql-test/r/null.result b/mysql-test/r/null.result
index 3da7e4805c2..0d012e283b5 100644
--- a/mysql-test/r/null.result
+++ b/mysql-test/r/null.result
@@ -1556,7 +1556,7 @@ set names utf8;
create table t1 (f1 varchar(10));
insert into t1 values ('2015-12-31');
select power( timestamp( nullif( '2002-09-08', f1 ) ), 24 ) from t1;
-ERROR 22003: DOUBLE value is out of range in 'pow(cast((case when '2002-09-08' = '2015-12-31' then NULL else '2002-09-08' end) as datetime(6)),24)'
+ERROR 22003: DOUBLE value is out of range in 'pow(cast((case when '2002-09-08' = `test`.`t1`.`f1` then NULL else '2002-09-08' end) as datetime(6)),24)'
drop table t1;
CREATE TABLE t1 (f1 INT);
INSERT INTO t1 VALUES (1),(2);
diff --git a/mysql-test/r/openssl_1.result b/mysql-test/r/openssl_1.result
index 1d5c6d179df..852fdee51ee 100644
--- a/mysql-test/r/openssl_1.result
+++ b/mysql-test/r/openssl_1.result
@@ -210,3 +210,12 @@ Ssl_cipher DHE-RSA-AES256-SHA
DROP USER bug42158@localhost;
set global sql_mode=default;
End of 5.1 tests
+/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/;
+/*!40019 SET @@session.max_insert_delayed_threads=0*/;
+/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
+DELIMITER /*!*/;
+DELIMITER ;
+# End of log file
+ROLLBACK /* added by mysqlbinlog */;
+/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
+/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;
diff --git a/mysql-test/r/select_debug.result b/mysql-test/r/select_debug.result
index a056affc2cd..55882ad337a 100644
--- a/mysql-test/r/select_debug.result
+++ b/mysql-test/r/select_debug.result
@@ -6,7 +6,7 @@ insert into t1 values (2,2), (1,1);
create table t2 (a int);
insert into t2 values (2), (3);
set session join_cache_level=3;
-set @@debug_dbug= 'd:t:O,/tmp/trace.out';
+set @@debug_dbug= 'd,opt';
explain select t1.b from t1,t2 where t1.b=t2.a;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 Using where
diff --git a/mysql-test/r/set_password_plugin-9835.result b/mysql-test/r/set_password_plugin-9835.result
new file mode 100644
index 00000000000..3cc723957d8
--- /dev/null
+++ b/mysql-test/r/set_password_plugin-9835.result
@@ -0,0 +1,160 @@
+set global secure_auth=0;
+create user natauth@localhost identified via 'mysql_native_password' using '*94BDCEBE19083CE2A1F959FD02F964C7AF4CFC29';
+create user newpass@localhost identified by password '*94BDCEBE19083CE2A1F959FD02F964C7AF4CFC29';
+create user newpassnat@localhost identified via 'mysql_native_password';
+set password for newpassnat@localhost = '*94BDCEBE19083CE2A1F959FD02F964C7AF4CFC29';
+create user oldauth@localhost identified with 'mysql_old_password' using '378b243e220ca493';
+create user oldpass@localhost identified by password '378b243e220ca493';
+create user oldpassold@localhost identified with 'mysql_old_password';
+set password for oldpassold@localhost = '378b243e220ca493';
+select user, host, password, plugin, authentication_string from mysql.user where user != 'root';
+user host password plugin authentication_string
+natauth localhost *94BDCEBE19083CE2A1F959FD02F964C7AF4CFC29
+newpass localhost *94BDCEBE19083CE2A1F959FD02F964C7AF4CFC29
+newpassnat localhost *94BDCEBE19083CE2A1F959FD02F964C7AF4CFC29
+oldauth localhost 378b243e220ca493
+oldpass localhost 378b243e220ca493
+oldpassold localhost 378b243e220ca493
+connect con,localhost,natauth,test,;
+select current_user();
+current_user()
+natauth@localhost
+disconnect con;
+connect con,localhost,newpass,test,;
+select current_user();
+current_user()
+newpass@localhost
+disconnect con;
+connect con,localhost,newpassnat,test,;
+select current_user();
+current_user()
+newpassnat@localhost
+disconnect con;
+connect con,localhost,oldauth,test,;
+select current_user();
+current_user()
+oldauth@localhost
+disconnect con;
+connect con,localhost,oldpass,test,;
+select current_user();
+current_user()
+oldpass@localhost
+disconnect con;
+connect con,localhost,oldpassold,test,;
+select current_user();
+current_user()
+oldpassold@localhost
+disconnect con;
+connection default;
+flush privileges;
+connect con,localhost,natauth,test,;
+select current_user();
+current_user()
+natauth@localhost
+disconnect con;
+connect con,localhost,newpass,test,;
+select current_user();
+current_user()
+newpass@localhost
+disconnect con;
+connect con,localhost,newpassnat,test,;
+select current_user();
+current_user()
+newpassnat@localhost
+disconnect con;
+connect con,localhost,oldauth,test,;
+select current_user();
+current_user()
+oldauth@localhost
+disconnect con;
+connect con,localhost,oldpass,test,;
+select current_user();
+current_user()
+oldpass@localhost
+disconnect con;
+connect con,localhost,oldpassold,test,;
+select current_user();
+current_user()
+oldpassold@localhost
+disconnect con;
+connection default;
+set password for natauth@localhost = PASSWORD('test2');
+set password for newpass@localhost = PASSWORD('test2');
+set password for newpassnat@localhost = PASSWORD('test2');
+set password for oldauth@localhost = PASSWORD('test2');
+set password for oldpass@localhost = PASSWORD('test2');
+set password for oldpassold@localhost = PASSWORD('test2');
+select user, host, password, plugin, authentication_string from mysql.user where user != 'root';
+user host password plugin authentication_string
+natauth localhost *7CEB3FDE5F7A9C4CE5FBE610D7D8EDA62EBE5F4E
+newpass localhost *7CEB3FDE5F7A9C4CE5FBE610D7D8EDA62EBE5F4E
+newpassnat localhost *7CEB3FDE5F7A9C4CE5FBE610D7D8EDA62EBE5F4E
+oldauth localhost *7CEB3FDE5F7A9C4CE5FBE610D7D8EDA62EBE5F4E
+oldpass localhost *7CEB3FDE5F7A9C4CE5FBE610D7D8EDA62EBE5F4E
+oldpassold localhost *7CEB3FDE5F7A9C4CE5FBE610D7D8EDA62EBE5F4E
+connect con,localhost,natauth,test2,;
+select current_user();
+current_user()
+natauth@localhost
+disconnect con;
+connect con,localhost,newpass,test2,;
+select current_user();
+current_user()
+newpass@localhost
+disconnect con;
+connect con,localhost,newpassnat,test2,;
+select current_user();
+current_user()
+newpassnat@localhost
+disconnect con;
+connect con,localhost,oldauth,test2,;
+select current_user();
+current_user()
+oldauth@localhost
+disconnect con;
+connect con,localhost,oldpass,test2,;
+select current_user();
+current_user()
+oldpass@localhost
+disconnect con;
+connect con,localhost,oldpassold,test2,;
+select current_user();
+current_user()
+oldpassold@localhost
+disconnect con;
+connection default;
+flush privileges;
+connect con,localhost,natauth,test2,;
+select current_user();
+current_user()
+natauth@localhost
+disconnect con;
+connect con,localhost,newpass,test2,;
+select current_user();
+current_user()
+newpass@localhost
+disconnect con;
+connect con,localhost,newpassnat,test2,;
+select current_user();
+current_user()
+newpassnat@localhost
+disconnect con;
+connect con,localhost,oldauth,test2,;
+select current_user();
+current_user()
+oldauth@localhost
+disconnect con;
+connect con,localhost,oldpass,test2,;
+select current_user();
+current_user()
+oldpass@localhost
+disconnect con;
+connect con,localhost,oldpassold,test2,;
+select current_user();
+current_user()
+oldpassold@localhost
+disconnect con;
+connection default;
+drop user natauth@localhost, newpass@localhost, newpassnat@localhost;
+drop user oldauth@localhost, oldpass@localhost, oldpassold@localhost;
+set global secure_auth=default;
diff --git a/mysql-test/r/sp-threads.result b/mysql-test/r/sp-threads.result
index 4ce61c44762..ddf709d462b 100644
--- a/mysql-test/r/sp-threads.result
+++ b/mysql-test/r/sp-threads.result
@@ -32,12 +32,9 @@ update t1, t2 set val= 1 where id1=id2;
call bug9486();
lock tables t2 write;
call bug9486();
-show processlist;
-Id User Host db Command Time State Info Progress
-# root localhost test Sleep # NULL 0.000
-# root localhost test Query # Waiting for table metadata lock update t1, t2 set val= 1 where id1=id2 0.000
-# root localhost test Query # init show processlist 0.000
-# root localhost test Sleep # NULL 0.000
+SELECT state,info FROM information_schema.processlist WHERE id=con1root_id;
+state info
+Waiting for table metadata lock update t1, t2 set val= 1 where id1=id2
unlock tables;
drop procedure bug9486;
drop table t1, t2;
diff --git a/mysql-test/r/ssl_timeout-9836.result b/mysql-test/r/ssl_timeout-9836.result
new file mode 100644
index 00000000000..bc2e19e1475
--- /dev/null
+++ b/mysql-test/r/ssl_timeout-9836.result
@@ -0,0 +1,7 @@
+SET @@net_read_timeout=1;
+SELECT 1;
+1
+1
+SELECT 1;
+1
+1
diff --git a/mysql-test/r/type_date.result b/mysql-test/r/type_date.result
index 54f2aa91f2c..55de3b39f2d 100644
--- a/mysql-test/r/type_date.result
+++ b/mysql-test/r/type_date.result
@@ -439,6 +439,41 @@ select 1 from t1 as t1_0 inner join t1 as t2 on (t1_0.a <=> now()) join t1 on 1;
1
drop table t1;
#
+# MDEV-9521 Least function returns 0000-00-00 for null date columns instead of null
+#
+CREATE TABLE t1 (
+id BIGINT NOT NULL,
+date_debut DATE NOT NULL,
+date_fin DATE DEFAULT NULL);
+CREATE TABLE t2(
+id BIGINT NOT NULL,
+date_debut DATE NOT NULL,
+date_fin DATE DEFAULT NULL);
+INSERT INTO t1 VALUES (1,'2016-01-01','2016-01-31');
+INSERT INTO t1 VALUES (2,'2016-02-01',null);
+INSERT INTO t1 VALUES (3,'2016-03-01','2016-03-31');
+INSERT INTO t1 VALUES (4,'2016-04-01',null);
+INSERT INTO t2 VALUES (1,'2016-01-01','2016-01-31');
+INSERT INTO t2 VALUES (2,'2016-02-01','2016-01-28');
+INSERT INTO t2 VALUES (3,'2016-03-01',null);
+INSERT INTO t2 VALUES (4,'2016-04-01',null);
+SELECT t1.id,
+GREATEST(t2.date_debut, t1.date_debut) AS date_debut,
+LEAST(IFNULL(t2.date_fin, IFNULL(t1.date_fin, NULL)),
+IFNULL(t1.date_fin, IFNULL(t2.date_fin, NULL))) AS date_fin
+FROM t1 LEFT JOIN t2 ON (t1.id=t2.id);
+id date_debut date_fin
+1 2016-01-01 2016-01-31
+2 2016-02-01 2016-01-28
+3 2016-03-01 2016-03-31
+4 2016-04-01 NULL
+DROP TABLE t1,t2;
+SELECT
+LEAST(COALESCE(DATE(NULL), DATE(NULL)), COALESCE(DATE(NULL), DATE(NULL))) AS d0,
+LEAST(IFNULL(DATE(NULL), DATE(NULL)), IFNULL(DATE(NULL), DATE(NULL))) AS d1;
+d0 d1
+NULL NULL
+#
# MDEV-9511 Valgrind warnings 'Invalid read' in Field_newdate::cmp and Field_newdate::val_str
#
CREATE TABLE t1 (f1 DATE, f2 VARCHAR(1));
diff --git a/mysql-test/r/type_timestamp.result b/mysql-test/r/type_timestamp.result
index a579f6930a0..69c9f68811d 100644
--- a/mysql-test/r/type_timestamp.result
+++ b/mysql-test/r/type_timestamp.result
@@ -644,6 +644,15 @@ SELECT MAX(dt) = '2011-01-06 12:34:30' FROM t1;
MAX(dt) = '2011-01-06 12:34:30'
1
DROP TABLE t1;
+#
+# MDEV-9413 "datetime >= coalesce(c1(NULL))" doesn't return expected NULL
+#
+CREATE TABLE t1(c1 TIMESTAMP(6) NULL DEFAULT NULL);
+INSERT INTO t1 VALUES(NULL);
+SELECT c1, '2016-06-13 20:00:00.000003' >= COALESCE( c1 ) FROM t1;
+c1 '2016-06-13 20:00:00.000003' >= COALESCE( c1 )
+NULL NULL
+DROP TABLE t1;
End of 5.5 tests
#
# MDEV-7254: Assigned expression is evaluated twice when updating column TIMESTAMP NOT NULL
diff --git a/mysql-test/r/wait_timeout_not_windows.result b/mysql-test/r/wait_timeout_not_windows.result
new file mode 100644
index 00000000000..867787a8ed3
--- /dev/null
+++ b/mysql-test/r/wait_timeout_not_windows.result
@@ -0,0 +1,4 @@
+set global log_warnings=2;
+set @@wait_timeout=1;
+FOUND /Aborted.*Got timeout reading communication packets/ in mysqld.1.err
+set global log_warnings=@@log_warnings;
diff --git a/mysql-test/suite/binlog/r/binlog_row_binlog.result b/mysql-test/suite/binlog/r/binlog_row_binlog.result
index 181f254cd5d..cb6b344e311 100644
--- a/mysql-test/suite/binlog/r/binlog_row_binlog.result
+++ b/mysql-test/suite/binlog/r/binlog_row_binlog.result
@@ -681,7 +681,7 @@ master-bin.000001 # Query # # COMMIT
master-bin.000001 # Gtid # # GTID #-#-#
master-bin.000001 # Query # # use `test`; CREATE TABLE IF NOT EXISTS `t3` (
`a` int(11) DEFAULT NULL
-)
+) ENGINE=MyISAM
master-bin.000001 # Gtid # # BEGIN GTID #-#-#
master-bin.000001 # Table_map # # table_id: # (mysql.user)
master-bin.000001 # Write_rows_v1 # # table_id: # flags: STMT_END_F
diff --git a/mysql-test/suite/handler/innodb.result b/mysql-test/suite/handler/innodb.result
index 78660b0ef9c..617b74ca714 100644
--- a/mysql-test/suite/handler/innodb.result
+++ b/mysql-test/suite/handler/innodb.result
@@ -543,7 +543,6 @@ optimize table t1;
proceed with the normal connection
handler t1 read next;
c1
-1
handler t1 close;
read the result from the other connection
Table Op Msg_type Msg_text
diff --git a/mysql-test/suite/innodb/r/defrag_mdl-9155.result b/mysql-test/suite/innodb/r/defrag_mdl-9155.result
new file mode 100644
index 00000000000..36cafd305ba
--- /dev/null
+++ b/mysql-test/suite/innodb/r/defrag_mdl-9155.result
@@ -0,0 +1,15 @@
+set global innodb_defragment=1;
+create table t1 (a int not null primary key auto_increment, b varchar(256), key second(a, b)) engine=innodb;
+insert t1 select null, repeat('a', 256) from seq_1_to_100;
+select count(*) from t1;
+count(*)
+100
+start transaction;
+select count(*) from t1;
+count(*)
+100
+optimize table t1;
+Table Op Msg_type Msg_text
+test.t1 optimize status OK
+drop table t1;
+set global innodb_defragment=default;
diff --git a/mysql-test/suite/innodb/r/innodb-corrupted-table.result b/mysql-test/suite/innodb/r/innodb-corrupted-table.result
new file mode 100644
index 00000000000..94203a794f8
--- /dev/null
+++ b/mysql-test/suite/innodb/r/innodb-corrupted-table.result
@@ -0,0 +1,49 @@
+call mtr.add_suppression("Table .* has a primary key in InnoDB data dictionary, but not in MySQL.*");
+call mtr.add_suppression("InnoDB: Table .* contains .* indexes inside InnoDB, which is different from the number of indexes .* defined in the MySQL.*");
+create table t1 (pk int, i int, key(i)) engine=InnoDB;
+insert into t1 values (1,1),(2,2);
+flush tables;
+# Save the .frm file without the PK
+alter table t1 add primary key (pk);
+# Stop the server, replace the frm with the old one and restart the server
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `pk` int(11) DEFAULT NULL,
+ `i` int(11) DEFAULT NULL,
+ KEY `i` (`i`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+Warnings:
+Warning 1082 InnoDB: Table test/t1 has a primary key in InnoDB data dictionary, but not in MySQL!
+Warning 1082 InnoDB: Table test/t1 contains 2 indexes inside InnoDB, which is different from the number of indexes 1 defined in the MySQL
+select * from t1;
+pk i
+1 1
+2 2
+alter table t1 add j int;
+Warnings:
+Warning 1082 InnoDB: Table test/t1 contains 2 indexes inside InnoDB, which is different from the number of indexes 1 defined in the MySQL
+show warnings;
+Level Code Message
+Warning 1082 InnoDB: Table test/t1 contains 2 indexes inside InnoDB, which is different from the number of indexes 1 defined in the MySQL
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `pk` int(11) DEFAULT NULL,
+ `i` int(11) DEFAULT NULL,
+ `j` int(11) DEFAULT NULL,
+ KEY `i` (`i`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+alter table t1 add primary key (pk);
+show warnings;
+Level Code Message
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `pk` int(11) NOT NULL,
+ `i` int(11) DEFAULT NULL,
+ `j` int(11) DEFAULT NULL,
+ PRIMARY KEY (`pk`),
+ KEY `i` (`i`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+drop table t1;
diff --git a/mysql-test/suite/innodb/r/innodb-fk.result b/mysql-test/suite/innodb/r/innodb-fk.result
index c916d665bf0..2eb19764769 100644
--- a/mysql-test/suite/innodb/r/innodb-fk.result
+++ b/mysql-test/suite/innodb/r/innodb-fk.result
@@ -70,6 +70,50 @@ Error 1005 Can't create table `test`.`#sql-temporary` (errno: 150 "Foreign key c
Warning 1215 Cannot add foreign key constraint
drop table t2;
drop table t1;
+CREATE DATABASE kg_test1;
+CREATE DATABASE kg_test2;
+CREATE TABLE `kg_test1`.`group` (
+Id INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+CREATE TABLE `kg_test1`.`person` (
+`Id` INT(11) NOT NULL AUTO_INCREMENT,
+`Name` VARCHAR(50) NOT NULL,
+PRIMARY KEY (`Id`),
+CONSTRAINT `fk_person_group` FOREIGN KEY (`Id`) REFERENCES `group` (`Id`)
+) ENGINE=INNODB DEFAULT CHARSET=utf8;
+show create table `kg_test1`.`person`;
+Table Create Table
+person CREATE TABLE `person` (
+ `Id` int(11) NOT NULL AUTO_INCREMENT,
+ `Name` varchar(50) NOT NULL,
+ PRIMARY KEY (`Id`),
+ CONSTRAINT `fk_person_group` FOREIGN KEY (`Id`) REFERENCES `group` (`Id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8
+CREATE TABLE `kg_test2`.`person2` (
+`Id` INT(11) NOT NULL AUTO_INCREMENT,
+`Name` VARCHAR(50) NOT NULL,
+PRIMARY KEY (`Id`),
+CONSTRAINT `fk_person_group` FOREIGN KEY (`Id`) REFERENCES `group` (`Id`)
+) ENGINE=INNODB DEFAULT CHARSET=utf8;
+ERROR HY000: Can't create table `kg_test2`.`person2` (errno: 150 "Foreign key constraint is incorrectly formed")
+CREATE TABLE `kg_test2`.`person2` (
+`Id` INT(11) NOT NULL AUTO_INCREMENT,
+`Name` VARCHAR(50) NOT NULL,
+PRIMARY KEY (`Id`),
+CONSTRAINT `fk_person_group` FOREIGN KEY (`Id`) REFERENCES `kg_test1`.`group` (`Id`)
+) ENGINE=INNODB DEFAULT CHARSET=utf8;
+show create table `kg_test2`.`person2`;
+Table Create Table
+person2 CREATE TABLE `person2` (
+ `Id` int(11) NOT NULL AUTO_INCREMENT,
+ `Name` varchar(50) NOT NULL,
+ PRIMARY KEY (`Id`),
+ CONSTRAINT `fk_person_group` FOREIGN KEY (`Id`) REFERENCES `kg_test1`.`group` (`Id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8
+SHOW WARNINGS;
+Level Code Message
+DROP DATABASE kg_test2;
+DROP DATABASE kg_test1;
CREATE TABLE `#departaments` (
`id_depart` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id_depart`)
diff --git a/mysql-test/suite/innodb/t/defrag_mdl-9155.test b/mysql-test/suite/innodb/t/defrag_mdl-9155.test
new file mode 100644
index 00000000000..1e1efb9c4c6
--- /dev/null
+++ b/mysql-test/suite/innodb/t/defrag_mdl-9155.test
@@ -0,0 +1,22 @@
+#
+# MDEV-9155 Enabling Defragmenting in 10.1.8 still causes OPTIMIZE TABLE to take metadatalocks
+#
+source include/have_innodb.inc;
+source include/have_sequence.inc;
+
+set global innodb_defragment=1;
+create table t1 (a int not null primary key auto_increment, b varchar(256), key second(a, b)) engine=innodb;
+insert t1 select null, repeat('a', 256) from seq_1_to_100;
+select count(*) from t1;
+
+connect (con1,localhost,root);
+start transaction;
+select count(*) from t1;
+
+connection default;
+optimize table t1;
+
+connection con1;
+drop table t1;
+
+set global innodb_defragment=default;
diff --git a/mysql-test/suite/innodb/t/innodb-corrupted-table.test b/mysql-test/suite/innodb/t/innodb-corrupted-table.test
new file mode 100644
index 00000000000..94c5454429f
--- /dev/null
+++ b/mysql-test/suite/innodb/t/innodb-corrupted-table.test
@@ -0,0 +1,46 @@
+--source include/have_innodb.inc
+--source include/not_embedded.inc
+
+#
+# MDEV-9918: [ERROR] mysqld got signal 11 during ALTER TABLE `name` COLUMN ADD
+#
+
+call mtr.add_suppression("Table .* has a primary key in InnoDB data dictionary, but not in MySQL.*");
+call mtr.add_suppression("InnoDB: Table .* contains .* indexes inside InnoDB, which is different from the number of indexes .* defined in the MySQL.*");
+
+create table t1 (pk int, i int, key(i)) engine=InnoDB;
+insert into t1 values (1,1),(2,2);
+
+--let $datadir= `select @@datadir`
+
+flush tables;
+
+--echo # Save the .frm file without the PK
+
+--copy_file $datadir/test/t1.frm $MYSQLTEST_VARDIR/tmp/t1.frm
+
+alter table t1 add primary key (pk);
+
+--echo # Stop the server, replace the frm with the old one and restart the server
+
+--exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+--shutdown_server 10
+--source include/wait_until_disconnected.inc
+
+--remove_file $datadir/test/t1.frm
+--copy_file $MYSQLTEST_VARDIR/tmp/t1.frm $datadir/test/t1.frm
+
+--exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
+--enable_reconnect
+--source include/wait_until_connected_again.inc
+
+show create table t1;
+select * from t1;
+alter table t1 add j int;
+show warnings;
+show create table t1;
+alter table t1 add primary key (pk);
+show warnings;
+show create table t1;
+# Cleanup
+drop table t1;
diff --git a/mysql-test/suite/innodb/t/innodb-fk.test b/mysql-test/suite/innodb/t/innodb-fk.test
index f7bcbe238dd..17e926e8647 100644
--- a/mysql-test/suite/innodb/t/innodb-fk.test
+++ b/mysql-test/suite/innodb/t/innodb-fk.test
@@ -126,6 +126,47 @@ drop table t2;
drop table t1;
#
+# MDEV-9142 :Adding Constraint with no database reference
+# results in ERROR 1046 (3D000) at line 13: No database selected
+#
+CREATE DATABASE kg_test1;
+CREATE DATABASE kg_test2;
+
+CREATE TABLE `kg_test1`.`group` (
+ Id INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+CREATE TABLE `kg_test1`.`person` (
+`Id` INT(11) NOT NULL AUTO_INCREMENT,
+`Name` VARCHAR(50) NOT NULL,
+PRIMARY KEY (`Id`),
+CONSTRAINT `fk_person_group` FOREIGN KEY (`Id`) REFERENCES `group` (`Id`)
+) ENGINE=INNODB DEFAULT CHARSET=utf8;
+
+show create table `kg_test1`.`person`;
+
+--error 1005
+CREATE TABLE `kg_test2`.`person2` (
+`Id` INT(11) NOT NULL AUTO_INCREMENT,
+`Name` VARCHAR(50) NOT NULL,
+PRIMARY KEY (`Id`),
+CONSTRAINT `fk_person_group` FOREIGN KEY (`Id`) REFERENCES `group` (`Id`)
+) ENGINE=INNODB DEFAULT CHARSET=utf8;
+
+CREATE TABLE `kg_test2`.`person2` (
+`Id` INT(11) NOT NULL AUTO_INCREMENT,
+`Name` VARCHAR(50) NOT NULL,
+PRIMARY KEY (`Id`),
+CONSTRAINT `fk_person_group` FOREIGN KEY (`Id`) REFERENCES `kg_test1`.`group` (`Id`)
+) ENGINE=INNODB DEFAULT CHARSET=utf8;
+
+show create table `kg_test2`.`person2`;
+
+SHOW WARNINGS;
+DROP DATABASE kg_test2;
+DROP DATABASE kg_test1;
+
+#
# MDEV-7627: Some symbols in table name can cause to Error Code: 1050 when created FK
#
diff --git a/mysql-test/suite/plugins/r/simple_password_check.result b/mysql-test/suite/plugins/r/simple_password_check.result
index a0b43a94137..c21298cea33 100644
--- a/mysql-test/suite/plugins/r/simple_password_check.result
+++ b/mysql-test/suite/plugins/r/simple_password_check.result
@@ -147,6 +147,8 @@ grant select on *.* to foo2 identified with mysql_old_password using '2222222222
drop user foo2;
set global strict_password_validation=1;
drop user foo1;
+create role r1;
+drop role r1;
uninstall plugin simple_password_check;
create user foo1 identified by 'pwd';
drop user foo1;
diff --git a/mysql-test/suite/plugins/t/simple_password_check.test b/mysql-test/suite/plugins/t/simple_password_check.test
index 9854f93efe8..bfe3464f5f9 100644
--- a/mysql-test/suite/plugins/t/simple_password_check.test
+++ b/mysql-test/suite/plugins/t/simple_password_check.test
@@ -103,6 +103,12 @@ drop user foo2;
set global strict_password_validation=1;
drop user foo1;
+#
+# MDEV-9940 CREATE ROLE blocked by password validation plugin
+#
+create role r1;
+drop role r1;
+
uninstall plugin simple_password_check;
create user foo1 identified by 'pwd';
diff --git a/mysql-test/suite/rpl/r/create_or_replace_mix.result b/mysql-test/suite/rpl/r/create_or_replace_mix.result
index c5dd67ed65c..c6cce358799 100644
--- a/mysql-test/suite/rpl/r/create_or_replace_mix.result
+++ b/mysql-test/suite/rpl/r/create_or_replace_mix.result
@@ -150,7 +150,7 @@ slave-bin.000001 # Query # # COMMIT
slave-bin.000001 # Gtid # # GTID #-#-#
slave-bin.000001 # Query # # use `test`; CREATE TABLE `t4` (
`a` int(11) DEFAULT NULL
-)
+) ENGINE=MyISAM
slave-bin.000001 # Gtid # # BEGIN GTID #-#-#
slave-bin.000001 # Query # # use `test`; CREATE TABLE `t5` (
`a` int(11) DEFAULT NULL
diff --git a/mysql-test/suite/rpl/r/create_or_replace_row.result b/mysql-test/suite/rpl/r/create_or_replace_row.result
index 4a89a45354d..8f032107db9 100644
--- a/mysql-test/suite/rpl/r/create_or_replace_row.result
+++ b/mysql-test/suite/rpl/r/create_or_replace_row.result
@@ -39,7 +39,7 @@ master-bin.000001 # Query # # use `test`; CREATE OR REPLACE table t1 like t2
master-bin.000001 # Gtid # # GTID #-#-#
master-bin.000001 # Query # # use `test`; CREATE OR REPLACE TABLE `t1` (
`a_in_temporary` int(11) DEFAULT NULL
-)
+) ENGINE=MyISAM
master-bin.000001 # Gtid # # GTID #-#-#
master-bin.000001 # Query # # use `test`; DROP TABLE `t1` /* generated by server */
binlog from server 2
@@ -72,7 +72,7 @@ slave-bin.000001 # Query # # use `test`; CREATE OR REPLACE table t1 like t2
slave-bin.000001 # Gtid # # GTID #-#-#
slave-bin.000001 # Query # # use `test`; CREATE OR REPLACE TABLE `t1` (
`a_in_temporary` int(11) DEFAULT NULL
-)
+) ENGINE=MyISAM
slave-bin.000001 # Gtid # # GTID #-#-#
slave-bin.000001 # Query # # use `test`; DROP TABLE IF EXISTS `t1` /* generated by server */
#
@@ -172,7 +172,7 @@ slave-bin.000001 # Query # # COMMIT
slave-bin.000001 # Gtid # # GTID #-#-#
slave-bin.000001 # Query # # use `test`; CREATE TABLE `t4` (
`a` int(11) DEFAULT NULL
-)
+) ENGINE=MyISAM
slave-bin.000001 # Gtid # # BEGIN GTID #-#-#
slave-bin.000001 # Query # # use `test`; CREATE TABLE `t5` (
`a` int(11) DEFAULT NULL
diff --git a/mysql-test/suite/rpl/r/create_or_replace_statement.result b/mysql-test/suite/rpl/r/create_or_replace_statement.result
index 663557cc1f3..7bdbc64e9f2 100644
--- a/mysql-test/suite/rpl/r/create_or_replace_statement.result
+++ b/mysql-test/suite/rpl/r/create_or_replace_statement.result
@@ -153,7 +153,7 @@ slave-bin.000001 # Query # # COMMIT
slave-bin.000001 # Gtid # # GTID #-#-#
slave-bin.000001 # Query # # use `test`; CREATE TABLE `t4` (
`a` int(11) DEFAULT NULL
-)
+) ENGINE=MyISAM
slave-bin.000001 # Gtid # # BEGIN GTID #-#-#
slave-bin.000001 # Query # # use `test`; CREATE TABLE `t5` (
`a` int(11) DEFAULT NULL
diff --git a/mysql-test/suite/rpl/r/rpl_killed_ddl.result b/mysql-test/suite/rpl/r/rpl_killed_ddl.result
index a02c9b599bf..ed8745ca2c1 100644
--- a/mysql-test/suite/rpl/r/rpl_killed_ddl.result
+++ b/mysql-test/suite/rpl/r/rpl_killed_ddl.result
@@ -56,6 +56,10 @@ CREATE VIEW v1 AS SELECT a FROM t1 WHERE a < 100;
CREATE DATABASE d2;
source include/kill_query.inc;
include/rpl_diff.inc
+ALTER DATABASE d1
+DEFAULT CHARACTER SET = 'utf8';
+source include/kill_query.inc;
+include/rpl_diff.inc
DROP DATABASE d1;
source include/kill_query.inc;
include/rpl_diff.inc
@@ -83,6 +87,9 @@ include/rpl_diff.inc
DROP FUNCTION f1;
source include/kill_query.inc;
include/rpl_diff.inc
+DROP FUNCTION IF EXISTS f2;
+source include/kill_query.inc;
+include/rpl_diff.inc
CREATE PROCEDURE p2 (OUT rows INT)
BEGIN
SELECT COUNT(*) INTO rows FROM t2;
@@ -96,6 +103,9 @@ include/rpl_diff.inc
DROP PROCEDURE p1;
source include/kill_query.inc;
include/rpl_diff.inc
+DROP PROCEDURE IF EXISTS p2;
+source include/kill_query.inc;
+include/rpl_diff.inc
CREATE TABLE t2 (b int);
source include/kill_query.inc;
include/rpl_diff.inc
diff --git a/mysql-test/suite/rpl/r/rpl_row_create_table.result b/mysql-test/suite/rpl/r/rpl_row_create_table.result
index 283e769ce9a..31c4a823f70 100644
--- a/mysql-test/suite/rpl/r/rpl_row_create_table.result
+++ b/mysql-test/suite/rpl/r/rpl_row_create_table.result
@@ -194,7 +194,7 @@ master-bin.000001 # Gtid # # GTID #-#-#
master-bin.000001 # Query # # use `test`; CREATE TABLE `t9` (
`a` int(11) DEFAULT NULL,
`b` int(11) DEFAULT NULL
-)
+) ENGINE=MyISAM
**** On Slave ****
SHOW CREATE TABLE t8;
Table t8
@@ -207,7 +207,7 @@ Table t9
Create Table CREATE TABLE `t9` (
`a` int(11) DEFAULT NULL,
`b` int(11) DEFAULT NULL
-) ENGINE=MEMORY DEFAULT CHARSET=latin1
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE IF EXISTS t1,t2,t3,t4,t5,t6,t7,t8,t9;
STOP SLAVE;
include/wait_for_slave_to_stop.inc
diff --git a/mysql-test/suite/rpl/r/rpl_row_merge_engine.result b/mysql-test/suite/rpl/r/rpl_row_merge_engine.result
index c61167e84e0..3b2e02bf97c 100644
--- a/mysql-test/suite/rpl/r/rpl_row_merge_engine.result
+++ b/mysql-test/suite/rpl/r/rpl_row_merge_engine.result
@@ -4,8 +4,9 @@ CREATE TABLE t1 (a int) ENGINE=MyISAM;
CREATE TABLE t2 (a int) ENGINE=MyISAM;
INSERT INTO t1 VALUES (1), (2), (3);
INSERT INTO t2 VALUES (4), (5), (6);
-CREATE TABLE IF NOT EXISTS t1_merge LIKE t1;
-ALTER TABLE t1_merge ENGINE=MERGE UNION (t2, t1);
+CREATE TEMPORARY TABLE IF NOT EXISTS tt1_merge LIKE t1;
+ALTER TABLE tt1_merge ENGINE=MERGE UNION (t2, t1);
+CREATE TABLE t1_merge LIKE tt1_merge;
include/diff_tables.inc [master:test.t1, slave:test.t1]
include/diff_tables.inc [master:test.t2, slave:test.t2]
UPDATE t1_merge SET a=10 WHERE a=1;
diff --git a/mysql-test/suite/rpl/r/rpl_tmp_table_and_DDL_innodb.result b/mysql-test/suite/rpl/r/rpl_tmp_table_and_DDL_innodb.result
new file mode 100644
index 00000000000..4a5bc3b76e5
--- /dev/null
+++ b/mysql-test/suite/rpl/r/rpl_tmp_table_and_DDL_innodb.result
@@ -0,0 +1,13 @@
+include/master-slave.inc
+[connection master]
+CREATE TEMPORARY TABLE temp_t1 (c1 INT) ENGINE=InnoDB;
+CREATE TEMPORARY TABLE temp_t2 (c1 INT) ENGINE=MyISAM;
+CREATE TABLE t1 LIKE temp_t1;
+CREATE TABLE t2 LIKE temp_t2;
+include/assert.inc ["t1 on master and temp_t1 have the same storage engine"]
+include/assert.inc ["t2 on master and temp_t2 have the same storage engine"]
+include/assert.inc ["t1 on slave and temp_t1 have the same storage engine"]
+include/assert.inc ["t2 on slave and temp_t2 have the same storage engine"]
+DROP TEMPORARY TABLE temp_t1, temp_t2;
+DROP TABLE t1, t2;
+include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_killed_ddl.test b/mysql-test/suite/rpl/t/rpl_killed_ddl.test
index eff0392d5de..a910ab4bc5c 100644
--- a/mysql-test/suite/rpl/t/rpl_killed_ddl.test
+++ b/mysql-test/suite/rpl/t/rpl_killed_ddl.test
@@ -26,10 +26,8 @@
#
# There are some part of the test are temporarily disabled because of
# the following bugs, please enable then once they get fixed:
-# - BUG#44041
-# - BUG#43353
-# - BUG#25705
-# - BUG#44171
+# - BUG#22473427
+# - Bug#22587377
# Temporarily disabled on Windows due to bug #47638
--source include/not_windows.inc
@@ -148,11 +146,9 @@ let $rpl_diff_statement= SELECT schema_name FROM information_schema.schemata
send CREATE DATABASE d2;
source include/kill_query_and_diff_master_slave.inc;
-# Temporarily disabled, see BUG#44041, the ALTER DATABASE can affect the
-# collation of other database on slave
-#send ALTER DATABASE d1
-# DEFAULT CHARACTER SET = 'utf8';
-#source include/kill_query_and_diff_master_slave.inc;
+send ALTER DATABASE d1
+ DEFAULT CHARACTER SET = 'utf8';
+source include/kill_query_and_diff_master_slave.inc;
send DROP DATABASE d1;
source include/kill_query_and_diff_master_slave.inc;
@@ -171,8 +167,8 @@ send CREATE EVENT e2
DO INSERT INTO test.t1 VALUES (2);
source include/kill_query_and_diff_master_slave.inc;
-# Temporarily disabled because of BUG#44171, killing ALTER EVENT can
-# crash the server
+# Temporarily disabled,see Bug#22587377-RPL.RPL_KILLED_DDL
+# FAILS SPORADICALLY ON PB2 IN 5.5 AND 5.6
#send ALTER EVENT e1
# ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 2 DAY;
#source include/kill_query_and_diff_master_slave.inc;
@@ -201,16 +197,8 @@ source include/kill_query_and_diff_master_slave.inc;
# function f2 probably does not exist because the CREATE query was
# killed
-#
-# Temporarily disabled. Because of BUG#43353, KILL the query may
-# result in function not found, and for 5.1, DROP statements will be
-# logged if the function is not found on master, so the following DROP
-# FUNCTION statement may be interrupted and not drop the function on
-# master, but still get logged and executed on slave and cause
-# inconsistence. Also disable the following DROP PROCEDURE IF EXITS
-# below.
-#send DROP FUNCTION IF EXISTS f2;
-#source include/kill_query_and_diff_master_slave.inc;
+send DROP FUNCTION IF EXISTS f2;
+source include/kill_query_and_diff_master_slave.inc;
######## PROCEDURE ########
@@ -231,9 +219,8 @@ source include/kill_query_and_diff_master_slave.inc;
send DROP PROCEDURE p1;
source include/kill_query_and_diff_master_slave.inc;
-# Temporarily disabled because of bug#43353, see comment above for DROP FUNCTION IF EXISTS
-#send DROP PROCEDURE IF EXISTS p2;
-#source include/kill_query_and_diff_master_slave.inc;
+send DROP PROCEDURE IF EXISTS p2;
+source include/kill_query_and_diff_master_slave.inc;
######## TABLE ########
@@ -261,9 +248,10 @@ source include/kill_query_and_diff_master_slave.inc;
######## SERVER ########
-# Tempoarily disabled, see bug#25705
+# Temporarily disabled, see Bug #22473427 - DROP SERVER FAILS
+# AFTER ALTER SERVER+KILL QUERY
-# --let $rpl_diff_statement= SELECT * FROM mysql.server WHERE name like \'s%\'
+# --let $rpl_diff_statement= SELECT * FROM mysql.servers WHERE Server_name like \'s%\'
# send CREATE SERVER s2
# FOREIGN DATA WRAPPER mysql
diff --git a/mysql-test/suite/rpl/t/rpl_row_merge_engine.test b/mysql-test/suite/rpl/t/rpl_row_merge_engine.test
index 5add8dc1cda..dcbb8b891d8 100644
--- a/mysql-test/suite/rpl/t/rpl_row_merge_engine.test
+++ b/mysql-test/suite/rpl/t/rpl_row_merge_engine.test
@@ -20,8 +20,10 @@ CREATE TABLE t1 (a int) ENGINE=MyISAM;
CREATE TABLE t2 (a int) ENGINE=MyISAM;
INSERT INTO t1 VALUES (1), (2), (3);
INSERT INTO t2 VALUES (4), (5), (6);
-CREATE TABLE IF NOT EXISTS t1_merge LIKE t1;
-ALTER TABLE t1_merge ENGINE=MERGE UNION (t2, t1);
+# Changed a little to check also an issue reported on BUG#20574550
+CREATE TEMPORARY TABLE IF NOT EXISTS tt1_merge LIKE t1;
+ALTER TABLE tt1_merge ENGINE=MERGE UNION (t2, t1);
+CREATE TABLE t1_merge LIKE tt1_merge;
--sync_slave_with_master
diff --git a/mysql-test/suite/rpl/t/rpl_tmp_table_and_DDL_innodb.test b/mysql-test/suite/rpl/t/rpl_tmp_table_and_DDL_innodb.test
new file mode 100644
index 00000000000..1a09b685249
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_tmp_table_and_DDL_innodb.test
@@ -0,0 +1,55 @@
+source include/have_innodb.inc;
+source include/have_binlog_format_row.inc;
+source include/master-slave.inc;
+#
+# BUG#20574550
+# CREATE TABLE LIKE <TEMP_TABLE> does not preserve original table storage
+# engine when using row based replication
+#
+--connection master
+
+# Define temp_t1 and temp_t2 storage engines
+--let $engine_temp_t1= InnoDB
+--let $engine_temp_t2= MyISAM
+
+# Create the two temporary tables
+--eval CREATE TEMPORARY TABLE temp_t1 (c1 INT) ENGINE=$engine_temp_t1
+--eval CREATE TEMPORARY TABLE temp_t2 (c1 INT) ENGINE=$engine_temp_t2
+
+# Create t1 and t2 based on temporary tables
+CREATE TABLE t1 LIKE temp_t1;
+CREATE TABLE t2 LIKE temp_t2;
+--sync_slave_with_master
+
+# On master
+--connection master
+# Assert that t1 and t2 have the same storage engines as temp_t1 and temp_t2
+--let $engine_t1= query_get_value(SHOW TABLE STATUS WHERE Name='t1', Engine, 1)
+--let $assert_cond= "$engine_t1" = "$engine_temp_t1"
+--let $assert_text= "t1 on master and temp_t1 have the same storage engine"
+--source include/assert.inc
+
+--let $engine_t2= query_get_value(SHOW TABLE STATUS WHERE Name='t2', Engine, 1)
+--let $assert_cond= "$engine_t2" = "$engine_temp_t2"
+--let $assert_text= "t2 on master and temp_t2 have the same storage engine"
+--source include/assert.inc
+
+# On slave
+--connection slave
+# Assert that t1 and t2 have the same storage engines as temp_t1 and temp_t2
+--let $engine_t1= query_get_value(SHOW TABLE STATUS WHERE Name='t1', Engine, 1)
+--let $assert_cond= "$engine_t1" = "$engine_temp_t1"
+--let $assert_text= "t1 on slave and temp_t1 have the same storage engine"
+--source include/assert.inc
+
+--let $engine_t2= query_get_value(SHOW TABLE STATUS WHERE Name='t2', Engine, 1)
+--let $assert_cond= "$engine_t2" = "$engine_temp_t2"
+--let $assert_text= "t2 on slave and temp_t2 have the same storage engine"
+--source include/assert.inc
+
+# Cleanup
+--connection master
+DROP TEMPORARY TABLE temp_t1, temp_t2;
+DROP TABLE t1, t2;
+--source include/rpl_end.inc
+
diff --git a/mysql-test/suite/sys_vars/r/sysvars_innodb,xtradb.rdiff b/mysql-test/suite/sys_vars/r/sysvars_innodb,xtradb.rdiff
index a9e975313db..002cf66300a 100644
--- a/mysql-test/suite/sys_vars/r/sysvars_innodb,xtradb.rdiff
+++ b/mysql-test/suite/sys_vars/r/sysvars_innodb,xtradb.rdiff
@@ -183,7 +183,7 @@
COMMAND_LINE_ARGUMENT OPTIONAL
+VARIABLE_NAME INNODB_EMPTY_FREE_LIST_ALGORITHM
+SESSION_VALUE NULL
-+GLOBAL_VALUE BACKOFF
++GLOBAL_VALUE LEGACY
+GLOBAL_VALUE_ORIGIN COMPILE-TIME
+DEFAULT_VALUE BACKOFF
+VARIABLE_SCOPE GLOBAL
@@ -571,21 +571,14 @@
NUMERIC_MIN_VALUE NULL
NUMERIC_MAX_VALUE NULL
NUMERIC_BLOCK_SIZE NULL
-@@ -2203,14 +2637,28 @@
+@@ -2217,6 +2651,34 @@
ENUM_VALUE_LIST NULL
READ_ONLY NO
- COMMAND_LINE_ARGUMENT REQUIRED
--VARIABLE_NAME INNODB_TMPDIR
--SESSION_VALUE
--GLOBAL_VALUE
+ COMMAND_LINE_ARGUMENT OPTIONAL
+VARIABLE_NAME INNODB_TRACK_CHANGED_PAGES
+SESSION_VALUE NULL
+GLOBAL_VALUE OFF
- GLOBAL_VALUE_ORIGIN COMPILE-TIME
--DEFAULT_VALUE
--VARIABLE_SCOPE SESSION
--VARIABLE_TYPE VARCHAR
--VARIABLE_COMMENT Directory for temporary non-tablespace files.
++GLOBAL_VALUE_ORIGIN COMPILE-TIME
+DEFAULT_VALUE OFF
+VARIABLE_SCOPE GLOBAL
+VARIABLE_TYPE BOOLEAN
@@ -604,10 +597,16 @@
+VARIABLE_SCOPE GLOBAL
+VARIABLE_TYPE BOOLEAN
+VARIABLE_COMMENT Force log tracker to catch up with checkpoint now
- NUMERIC_MIN_VALUE NULL
- NUMERIC_MAX_VALUE NULL
- NUMERIC_BLOCK_SIZE NULL
-@@ -2294,7 +2742,7 @@
++NUMERIC_MIN_VALUE NULL
++NUMERIC_MAX_VALUE NULL
++NUMERIC_BLOCK_SIZE NULL
++ENUM_VALUE_LIST NULL
++READ_ONLY NO
++COMMAND_LINE_ARGUMENT OPTIONAL
+ VARIABLE_NAME INNODB_TRX_PURGE_VIEW_UPDATE_ONLY_DEBUG
+ SESSION_VALUE NULL
+ GLOBAL_VALUE OFF
+@@ -2294,7 +2756,7 @@
DEFAULT_VALUE OFF
VARIABLE_SCOPE GLOBAL
VARIABLE_TYPE BOOLEAN
@@ -616,7 +615,7 @@
NUMERIC_MIN_VALUE NULL
NUMERIC_MAX_VALUE NULL
NUMERIC_BLOCK_SIZE NULL
-@@ -2315,6 +2763,20 @@
+@@ -2315,6 +2777,20 @@
ENUM_VALUE_LIST NULL
READ_ONLY YES
COMMAND_LINE_ARGUMENT NONE
@@ -637,7 +636,7 @@
VARIABLE_NAME INNODB_USE_MTFLUSH
SESSION_VALUE NULL
GLOBAL_VALUE OFF
-@@ -2329,6 +2791,20 @@
+@@ -2329,6 +2805,20 @@
ENUM_VALUE_LIST NULL
READ_ONLY YES
COMMAND_LINE_ARGUMENT NONE
@@ -658,12 +657,12 @@
VARIABLE_NAME INNODB_USE_SYS_MALLOC
SESSION_VALUE NULL
GLOBAL_VALUE ON
-@@ -2359,12 +2835,12 @@
+@@ -2359,12 +2849,12 @@
COMMAND_LINE_ARGUMENT OPTIONAL
VARIABLE_NAME INNODB_VERSION
SESSION_VALUE NULL
--GLOBAL_VALUE 5.6.29
-+GLOBAL_VALUE 5.6.28-76.1
+-GLOBAL_VALUE 5.6.30
++GLOBAL_VALUE 5.6.29-76.2
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE NULL
VARIABLE_SCOPE GLOBAL
diff --git a/mysql-test/suite/sys_vars/r/sysvars_innodb.result b/mysql-test/suite/sys_vars/r/sysvars_innodb.result
index 0ddc401e618..4f09270a6aa 100644
--- a/mysql-test/suite/sys_vars/r/sysvars_innodb.result
+++ b/mysql-test/suite/sys_vars/r/sysvars_innodb.result
@@ -2359,7 +2359,7 @@ READ_ONLY NO
COMMAND_LINE_ARGUMENT OPTIONAL
VARIABLE_NAME INNODB_VERSION
SESSION_VALUE NULL
-GLOBAL_VALUE 5.6.29
+GLOBAL_VALUE 5.6.30
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE NULL
VARIABLE_SCOPE GLOBAL
diff --git a/mysql-test/suite/sys_vars/t/innodb_buffer_pool_load_now_basic.test b/mysql-test/suite/sys_vars/t/innodb_buffer_pool_load_now_basic.test
index 160b3ba52cc..a0409901865 100644
--- a/mysql-test/suite/sys_vars/t/innodb_buffer_pool_load_now_basic.test
+++ b/mysql-test/suite/sys_vars/t/innodb_buffer_pool_load_now_basic.test
@@ -13,11 +13,19 @@ let $old_status= `SELECT variable_value FROM information_schema.global_status
# A previous test could have run buffer pool dump already;
# in this case we want to make sure that the current time is different
-# from the timestamp in the status variable
-
-let $wait_condition =
- SELECT TRIM(SUBSTR('$old_status', -8)) != DATE_FORMAT(CURTIME(), '%k:%i:%s');
--- source include/wait_condition.inc
+# from the timestamp in the status variable.
+# We should have had a smart wait condition here, like the commented one below,
+# but we can't because of MDEV-9867, so there will be just sleep instead.
+# And it might be not enough to sleep one second, so we'll have to sleep two.
+# let $wait_condition =
+# SELECT TRIM(SUBSTR('$old_status', -8)) != DATE_FORMAT(CURTIME(), '%k:%i:%s');
+# -- source include/wait_condition.inc
+
+if (`SELECT variable_value LIKE '%dump completed at%' FROM information_schema.global_status
+ WHERE LOWER(variable_name) = 'innodb_buffer_pool_dump_status'`)
+{
+ -- sleep 2
+}
# Do the dump
SET GLOBAL innodb_buffer_pool_dump_now = ON;
diff --git a/mysql-test/suite/sys_vars/t/innodb_empty_free_list_algorithm_basic.opt b/mysql-test/suite/sys_vars/t/innodb_empty_free_list_algorithm_basic.opt
new file mode 100644
index 00000000000..c788dc76ac7
--- /dev/null
+++ b/mysql-test/suite/sys_vars/t/innodb_empty_free_list_algorithm_basic.opt
@@ -0,0 +1 @@
+--loose-innodb-buffer-pool-size=20M
diff --git a/mysql-test/t/alter_table_online.test b/mysql-test/t/alter_table_online.test
index 6386a1551e1..22ebadd64f9 100644
--- a/mysql-test/t/alter_table_online.test
+++ b/mysql-test/t/alter_table_online.test
@@ -3,9 +3,7 @@
#
--source include/have_innodb.inc
---disable_warnings
-drop table if exists t1,t2,t3;
---enable_warnings
+--source include/have_partition.inc
#
# Test of things that can be done online
#
@@ -102,6 +100,28 @@ create table t3 (a int not null primary key, b int, c varchar(80)) engine=merge
alter online table t3 union=(t1,t2);
drop table t1,t2,t3;
+#
+# MDEV-9868 Altering a partitioned table comment does a full copy
+#
+create table t1 (i int) partition by hash(i) partitions 2;
+alter online table t1 comment 'test';
+drop table t1;
+
+#
+# MDEV-9168 altering a column comment does a full copy
+#
+create table t1 (a int);
+alter online table t1 modify a int comment 'test';
+drop table t1;
+
+create table t1 (a int) engine=innodb;
+alter online table t1 modify a int comment 'test';
+drop table t1;
+
+create table t1 (a int) partition by hash(a) partitions 2;
+alter online table t1 modify a int comment 'test';
+drop table t1;
+
--echo #
--echo # MDEV-8948 ALTER ... INPLACE does work for BINARY, BLOB
--echo #
diff --git a/mysql-test/t/bigint.test b/mysql-test/t/bigint.test
index 41f33b8a7f2..fb18d60edd9 100644
--- a/mysql-test/t/bigint.test
+++ b/mysql-test/t/bigint.test
@@ -409,3 +409,8 @@ SELECT * FROM t1 WHERE a=0.9;
SELECT * FROM t1 WHERE a IN (0.8,0.9);
DROP TABLE t1;
+
+--echo #
+--echo # MDEV-9372 select 100 between 1 and 9223372036854775808 returns false
+--echo #
+SELECT 100 BETWEEN 1 AND 9223372036854775808;
diff --git a/mysql-test/t/bootstrap.test b/mysql-test/t/bootstrap.test
index 840b9a12cee..35f0a46af70 100644
--- a/mysql-test/t/bootstrap.test
+++ b/mysql-test/t/bootstrap.test
@@ -80,7 +80,7 @@ EOF
--write_file $MYSQLTEST_VARDIR/tmp/bootstrap_plugins.sql
SET SQL_MODE="";
use test;
-create table t1(a int) engine=example;
+create table t1(a int) engine=example charset=latin1;
EOF
--exec $MYSQLD_BOOTSTRAP_CMD --plugin-dir=$PLUGIN_DIR < $MYSQLTEST_VARDIR/tmp/bootstrap_plugins.sql >> $MYSQLTEST_VARDIR/tmp/bootstrap.log 2>&1
--remove_file $MYSQLTEST_VARDIR/tmp/bootstrap_plugins.sql
diff --git a/mysql-test/t/cache_temporal_4265.test b/mysql-test/t/cache_temporal_4265.test
index 6135438f023..c62f3c3c506 100644
--- a/mysql-test/t/cache_temporal_4265.test
+++ b/mysql-test/t/cache_temporal_4265.test
@@ -7,5 +7,16 @@ create table t1 (a date);
insert t1 values ('2000-01-02'), ('2001-02-03'), ('2002-03-04');
set debug_dbug='d,str_to_datetime_warn';
select * from t1 where a > date_add('2000-01-01', interval 5 day);
+set debug_dbug='';
+drop table t1;
+
+#
+# MDEV-9707 MAX(timestamp(6) column) in correlated sub-query returns non-existent row data in original table
+#
+create table t1 (id int not null, ut timestamp(6) not null);
+insert into t1 values(1, '2001-01-01 00:00:00.2');
+insert into t1 values(1, '2001-01-01 00:00:00.1');
+select * from t1;
+select (select max(m2.ut) from t1 m2 where m1.id <> 0) from t1 m1;
drop table t1;
diff --git a/mysql-test/t/case.test b/mysql-test/t/case.test
index 957c4ac5c9d..7cc74c52b28 100644
--- a/mysql-test/t/case.test
+++ b/mysql-test/t/case.test
@@ -194,6 +194,16 @@ select case t1.f1 when '00:00:00' then 1 end from t1;
drop table t1;
--echo #
+--echo # MDEV-9745 Crash with CASE WHEN TRUE THEN COALESCE(CAST(NULL AS UNSIGNED)) ELSE 4 END
+--echo #
+CREATE TABLE t1 SELECT CASE WHEN TRUE THEN COALESCE(CAST(NULL AS UNSIGNED)) ELSE 4 END AS a;
+DESCRIBE t1;
+DROP TABLE t1;
+CREATE TABLE t1 SELECT CASE WHEN TRUE THEN COALESCE(CAST(NULL AS UNSIGNED)) ELSE 40 END AS a;
+DESCRIBE t1;
+DROP TABLE t1;
+
+--echo #
--echo # Start of 10.1 test
--echo #
diff --git a/mysql-test/t/ctype_cp850.test b/mysql-test/t/ctype_cp850.test
new file mode 100644
index 00000000000..358829eb351
--- /dev/null
+++ b/mysql-test/t/ctype_cp850.test
@@ -0,0 +1,16 @@
+--echo #
+--echo # Start of 5.5 tests
+--echo #
+
+--echo #
+--echo # MDEV-9862 Illegal mix of collation, when comparing column with CASE expression
+--echo #
+SET NAMES cp850;
+CREATE TABLE t1 (a CHAR(1) CHARACTER SET latin1);
+SELECT a FROM t1 WHERE CASE a WHEN 'aaaa' THEN 'Y' WHEN 'aaaa' THEN 'Y' ELSE NULL END <> a;
+DROP TABLE t1;
+
+
+--echo #
+--echo # End of 5.5 tests
+--echo #
diff --git a/mysql-test/t/events_2.test b/mysql-test/t/events_2.test
index 7d9ac7c5858..20f17966b29 100644
--- a/mysql-test/t/events_2.test
+++ b/mysql-test/t/events_2.test
@@ -69,10 +69,10 @@ select /*2*/ user, host, db, command, state, info
select release_lock("test_lock2");
drop event закачка;
-# Wait for release_lock("test_lock2") to complete,
+# Wait for get_lock("test_lock2") to complete,
# to avoid polluting the next test information_schema.processlist
let $wait_condition= select count(*) = 0 from information_schema.processlist
- where (state like 'User lock%' AND info like 'select get_lock%');
+ where info='select get_lock("test_lock2", 20)';
--source include/wait_condition.inc
diff --git a/mysql-test/t/fulltext3.test b/mysql-test/t/fulltext3.test
index 1b6a07c540f..66f940b495e 100644
--- a/mysql-test/t/fulltext3.test
+++ b/mysql-test/t/fulltext3.test
@@ -32,3 +32,18 @@ INSERT INTO t1 VALUES(0xA3C2);
DROP TABLE t1;
# End of 5.1 tests
+
+#
+# MDEV-9986 Full-text search of the utf8mb4 column causes crash
+#
+create table t1 (
+ id varchar(255),
+ business_name text null collate utf8mb4_unicode_ci,
+ street_address text,
+ fulltext index ft (business_name),
+ fulltext index ft2 (street_address)
+);
+--error ER_FT_MATCHING_KEY_NOT_FOUND
+select * from t1 where match (business_name, street_address) against ('some business name and address here');
+select * from t1 where match (business_name, street_address) against ('some business name and address here' in boolean mode);
+drop table t1;
diff --git a/mysql-test/t/func_des_encrypt.test b/mysql-test/t/func_des_encrypt.test
index e121aedab06..c9661b81cc0 100644
--- a/mysql-test/t/func_des_encrypt.test
+++ b/mysql-test/t/func_des_encrypt.test
@@ -1,4 +1,4 @@
--- source include/have_ssl_crypto_functs.inc
+-- source include/have_des.inc
# This test can't be in func_encrypt.test, because it requires
# --des-key-file to not be set.
diff --git a/mysql-test/t/func_encrypt.test b/mysql-test/t/func_encrypt.test
index 4eab0ac87e9..ed3e0a7b2d1 100644
--- a/mysql-test/t/func_encrypt.test
+++ b/mysql-test/t/func_encrypt.test
@@ -1,4 +1,4 @@
--- source include/have_ssl_crypto_functs.inc
+-- source include/have_des.inc
--disable_warnings
drop table if exists t1;
diff --git a/mysql-test/t/func_encrypt_ucs2.test b/mysql-test/t/func_encrypt_ucs2.test
index 8b4cd44d354..1242c3b9e6a 100644
--- a/mysql-test/t/func_encrypt_ucs2.test
+++ b/mysql-test/t/func_encrypt_ucs2.test
@@ -1,4 +1,4 @@
--- source include/have_ssl_crypto_functs.inc
+-- source include/have_des.inc
-- source include/have_ucs2.inc
--echo #
diff --git a/mysql-test/t/func_math.test b/mysql-test/t/func_math.test
index b48f4599074..da478080ab4 100644
--- a/mysql-test/t/func_math.test
+++ b/mysql-test/t/func_math.test
@@ -486,6 +486,14 @@ SELECT -a FROM t1;
--error ER_DATA_OUT_OF_RANGE
SELECT -b FROM t1;
+# try with two rows now
+INSERT INTO t1 VALUES(0,0);
+
+--error ER_DATA_OUT_OF_RANGE
+SELECT -a FROM t1;
+--error ER_DATA_OUT_OF_RANGE
+SELECT -b FROM t1;
+
DROP TABLE t1;
# Decimal overflows
diff --git a/mysql-test/t/grant5.test b/mysql-test/t/grant5.test
index db953d97fb3..14f2fd65020 100644
--- a/mysql-test/t/grant5.test
+++ b/mysql-test/t/grant5.test
@@ -5,3 +5,21 @@
#
--error ER_NONEXISTING_GRANT
SHOW GRANTS FOR root@invalid_host;
+
+#
+# MDEV-9580 SHOW GRANTS FOR <current_user> fails
+#
+create user test;
+create user foo;
+create role foo;
+grant foo to test;
+--connect (conn_1, localhost, test,,)
+set role foo;
+show grants for test; # user
+show grants for foo; # role
+--error ER_DBACCESS_DENIED_ERROR
+show grants for foo@'%'; # user
+--connection default
+drop user test, foo;
+drop role foo;
+
diff --git a/mysql-test/t/insert_innodb.test b/mysql-test/t/insert_innodb.test
new file mode 100644
index 00000000000..8c8d2690c11
--- /dev/null
+++ b/mysql-test/t/insert_innodb.test
@@ -0,0 +1,43 @@
+--source include/have_innodb.inc
+
+#
+# MDEV-8979 IGNORE does not ignore the error 1452
+#
+
+--echo #
+--echo # BUG#22037930: INSERT IGNORE FAILS TO IGNORE
+--echo # FOREIGN KEY CONSTRAINT
+
+--echo # Setup.
+CREATE TABLE t1 (fld1 INT PRIMARY KEY) ENGINE=INNODB;
+CREATE TABLE t2 (fld2 INT, FOREIGN KEY (fld2) REFERENCES t1 (fld1))
+ENGINE=INNODB;
+INSERT INTO t1 VALUES(0);
+INSERT INTO t2 VALUES(0);
+
+--echo # Without fix, an error is reported.
+INSERT IGNORE INTO t2 VALUES(1);
+UPDATE IGNORE t2 SET fld2=20 WHERE fld2=0;
+UPDATE IGNORE t1 SET fld1=20 WHERE fld1=0;
+
+--echo # Test for multi update.
+UPDATE IGNORE t1, t2 SET t2.fld2= t2.fld2 + 3;
+UPDATE IGNORE t1, t2 SET t1.fld1= t1.fld1 + 3;
+
+--echo # Reports an error since IGNORE is not used.
+--error ER_NO_REFERENCED_ROW_2
+INSERT INTO t2 VALUES(1);
+
+--error ER_NO_REFERENCED_ROW_2
+UPDATE t2 SET fld2=20 WHERE fld2=0;
+
+--error ER_ROW_IS_REFERENCED_2
+UPDATE t1 SET fld1=20 WHERE fld1=0;
+
+--error ER_NO_REFERENCED_ROW_2
+UPDATE t1, t2 SET t2.fld2= t2.fld2 + 3;
+
+--error ER_ROW_IS_REFERENCED_2
+UPDATE t1, t2 SET t1.fld1= t1.fld1 + 3;
+
+DROP TABLE t2, t1;
diff --git a/mysql-test/t/kill_processlist-6619.test b/mysql-test/t/kill_processlist-6619.test
index 95af83be56d..551d36e03fd 100644
--- a/mysql-test/t/kill_processlist-6619.test
+++ b/mysql-test/t/kill_processlist-6619.test
@@ -23,5 +23,12 @@ SET DEBUG_SYNC='now SIGNAL go';
--error ER_QUERY_INTERRUPTED
reap;
SET DEBUG_SYNC='reset';
+
+# Wait until default connection has reset query string
+let $wait_condition=
+ SELECT COUNT(*) = 1 from information_schema.processlist
+ WHERE info is NULL;
+--source include/wait_condition.inc
+
--replace_column 1 # 3 # 6 # 7 #
SHOW PROCESSLIST;
diff --git a/mysql-test/t/locale.test b/mysql-test/t/locale.test
index 93e347b722d..5d1fd24d750 100644
--- a/mysql-test/t/locale.test
+++ b/mysql-test/t/locale.test
@@ -55,6 +55,14 @@ SELECT DATE_FORMAT('2001-01-06', '%w %a %W');
SELECT DATE_FORMAT('2001-01-07', '%w %a %W');
--echo End of 5.4 tests
+#
+# MDEV-9928 LC_TIME_NAMES=de_AT; unusual name for february
+#
+SET NAMES utf8;
+SET lc_time_names=de_AT;
+SELECT monthname('2001-01-01');
+SELECT monthname('2001-02-01');
+SELECT monthname('2001-03-01');
--echo #
--echo # Start of 5.6 tests
diff --git a/mysql-test/t/mdev6830-master.opt b/mysql-test/t/mdev6830-master.opt
deleted file mode 100644
index 2a8c27d4731..00000000000
--- a/mysql-test/t/mdev6830-master.opt
+++ /dev/null
@@ -1 +0,0 @@
---debug
diff --git a/mysql-test/t/mdev6830.test b/mysql-test/t/mdev6830.test
index 24565d04fed..3898d5bbef6 100644
--- a/mysql-test/t/mdev6830.test
+++ b/mysql-test/t/mdev6830.test
@@ -1,10 +1,10 @@
-
+#
+# MDEV-6830 Server crashes in best_access_path after a sequence of SELECTs invollving a temptable view
+#
--source include/have_debug.inc
---disable_warnings
-drop table if exists t1,t2,t3;
-drop view if exists v2,v3;
---enable_warnings
+set @@debug_dbug= 'd,opt';
+
CREATE TABLE t1 (pk INT PRIMARY KEY) ENGINE=MyISAM;
CREATE TABLE t2 (
diff --git a/mysql-test/t/mysqld--help.test b/mysql-test/t/mysqld--help.test
index d7aba43999e..b37b33fa8a3 100644
--- a/mysql-test/t/mysqld--help.test
+++ b/mysql-test/t/mysqld--help.test
@@ -22,7 +22,7 @@ perl;
log-slow-queries pid-file slow-query-log-file log-basename
datadir slave-load-tmpdir tmpdir socket thread-pool-size
large-files-support lower-case-file-system system-time-zone
- log-tc-size version.*/;
+ collation-server character-set-server log-tc-size version.*/;
# Plugins which may or may not be there:
@plugins=qw/innodb archive blackhole federated partition
diff --git a/mysql-test/t/openssl_1.test b/mysql-test/t/openssl_1.test
index 8c81bdc9bbb..837206e2717 100644
--- a/mysql-test/t/openssl_1.test
+++ b/mysql-test/t/openssl_1.test
@@ -134,7 +134,7 @@ drop table t1;
# verification of servers certificate by setting both ca certificate
# and ca path to NULL
#
---replace_result DHE-RSA-AES256-GCM-SHA384 DHE-RSA-AES256-SHA
+--replace_result DHE-RSA-AES256-GCM-SHA384 DHE-RSA-AES256-SHA DHE-RSA-CHACHA20-POLY1305 DHE-RSA-AES256-SHA
--exec $MYSQL --ssl --ssl-key=$MYSQL_TEST_DIR/std_data/client-key.pem --ssl-cert=$MYSQL_TEST_DIR/std_data/client-cert.pem -e "SHOW STATUS LIKE 'ssl_Cipher'" 2>&1
--echo End of 5.0 tests
@@ -259,7 +259,7 @@ select 'is still running; no cipher request crashed the server' as result from d
GRANT SELECT ON test.* TO bug42158@localhost REQUIRE X509;
FLUSH PRIVILEGES;
connect(con1,localhost,bug42158,,,,,SSL);
---replace_result DHE-RSA-AES256-GCM-SHA384 DHE-RSA-AES256-SHA
+--replace_result DHE-RSA-AES256-GCM-SHA384 DHE-RSA-AES256-SHA DHE-RSA-CHACHA20-POLY1305 DHE-RSA-AES256-SHA
SHOW STATUS LIKE 'Ssl_cipher';
disconnect con1;
connection default;
@@ -268,5 +268,12 @@ DROP USER bug42158@localhost;
set global sql_mode=default;
--echo End of 5.1 tests
+#
+# MDEV-9605 mysqlbinlog does not accept ssl-ca option as expected.
+#
+
+--error 1
+--exec $MYSQL_BINLOG --read-from-remote-server --ssl-ca --user=root --host=localhost nobinlog.111111
+
# Wait till we reached the initial number of concurrent sessions
--source include/wait_until_count_sessions.inc
diff --git a/mysql-test/t/openssl_6975.test b/mysql-test/t/openssl_6975.test
index 88fe17d0621..6e8e03a0a89 100644
--- a/mysql-test/t/openssl_6975.test
+++ b/mysql-test/t/openssl_6975.test
@@ -17,6 +17,7 @@ let $mysql=$MYSQL --ssl-key=$MYSQL_TEST_DIR/std_data/client-key.pem --ssl-cert=$
disable_abort_on_error;
echo TLS1.2 ciphers: user is ok with any cipher;
exec $mysql --ssl-cipher=AES128-SHA256;
+--replace_result DHE-RSA-CHACHA20-POLY1305 DHE-RSA-AES256-GCM-SHA384
exec $mysql --ssl-cipher=TLSv1.2;
echo TLS1.2 ciphers: user requires SSLv3 cipher RC4-SHA;
exec $mysql --user ssl_sslv3 --ssl-cipher=AES128-SHA256;
diff --git a/mysql-test/t/partition_innodb_plugin.test b/mysql-test/t/partition_innodb_plugin.test
index fd6e60c27fb..d25a4b95bf1 100644
--- a/mysql-test/t/partition_innodb_plugin.test
+++ b/mysql-test/t/partition_innodb_plugin.test
@@ -125,12 +125,8 @@ SEND;
UPDATE `t``\""e` SET a = 12 WHERE a = 0;
--echo # default connection
connection default;
-let $wait_timeout= 2;
-let $wait_condition= SELECT 1 FROM INFORMATION_SCHEMA.PROCESSLIST
-WHERE ID = $id_1 AND STATE = 'Searching rows for update';
+let $wait_condition= SELECT COUNT(*)=2 FROM INFORMATION_SCHEMA.INNODB_LOCKS;
--source include/wait_condition.inc
-#--echo # tested wait condition $wait_condition_reps times
-# INNODB_LOCKS only exists in innodb_plugin
--sorted_result
SELECT lock_table, COUNT(*) FROM INFORMATION_SCHEMA.INNODB_LOCKS
GROUP BY lock_table;
diff --git a/mysql-test/t/select_debug.test b/mysql-test/t/select_debug.test
index 4b77f9fd047..49415400db3 100644
--- a/mysql-test/t/select_debug.test
+++ b/mysql-test/t/select_debug.test
@@ -10,7 +10,7 @@ create table t2 (a int);
insert into t2 values (2), (3);
set session join_cache_level=3;
-set @@debug_dbug= 'd:t:O,/tmp/trace.out';
+set @@debug_dbug= 'd,opt';
explain select t1.b from t1,t2 where t1.b=t2.a;
select t1.b from t1,t2 where t1.b=t2.a;
diff --git a/mysql-test/t/set_password_plugin-9835.test b/mysql-test/t/set_password_plugin-9835.test
new file mode 100644
index 00000000000..6afccd74f9d
--- /dev/null
+++ b/mysql-test/t/set_password_plugin-9835.test
@@ -0,0 +1,131 @@
+#
+# MDEV-9835 Valid password is not working after server restart.
+#
+# Various combinations of SET PASSWORD and not-empty mysql.user.plugin field
+#
+--source include/not_embedded.inc
+
+--enable_connect_log
+
+set global secure_auth=0;
+
+# The hash (old and new) is for 'test'
+create user natauth@localhost identified via 'mysql_native_password' using '*94BDCEBE19083CE2A1F959FD02F964C7AF4CFC29';
+
+create user newpass@localhost identified by password '*94BDCEBE19083CE2A1F959FD02F964C7AF4CFC29';
+
+create user newpassnat@localhost identified via 'mysql_native_password';
+set password for newpassnat@localhost = '*94BDCEBE19083CE2A1F959FD02F964C7AF4CFC29';
+
+create user oldauth@localhost identified with 'mysql_old_password' using '378b243e220ca493';
+
+create user oldpass@localhost identified by password '378b243e220ca493';
+
+create user oldpassold@localhost identified with 'mysql_old_password';
+set password for oldpassold@localhost = '378b243e220ca493';
+
+--sorted_result
+select user, host, password, plugin, authentication_string from mysql.user where user != 'root';
+
+--connect(con,localhost,natauth,test,)
+select current_user();
+--disconnect con
+--connect(con,localhost,newpass,test,)
+select current_user();
+--disconnect con
+--connect(con,localhost,newpassnat,test,)
+select current_user();
+--disconnect con
+--connect(con,localhost,oldauth,test,)
+select current_user();
+--disconnect con
+--connect(con,localhost,oldpass,test,)
+select current_user();
+--disconnect con
+--connect(con,localhost,oldpassold,test,)
+select current_user();
+--disconnect con
+
+--connection default
+
+flush privileges;
+
+--connect(con,localhost,natauth,test,)
+select current_user();
+--disconnect con
+--connect(con,localhost,newpass,test,)
+select current_user();
+--disconnect con
+--connect(con,localhost,newpassnat,test,)
+select current_user();
+--disconnect con
+--connect(con,localhost,oldauth,test,)
+select current_user();
+--disconnect con
+--connect(con,localhost,oldpass,test,)
+select current_user();
+--disconnect con
+--connect(con,localhost,oldpassold,test,)
+select current_user();
+--disconnect con
+
+--connection default
+
+# changing to the NEW password hash
+set password for natauth@localhost = PASSWORD('test2');
+set password for newpass@localhost = PASSWORD('test2');
+set password for newpassnat@localhost = PASSWORD('test2');
+set password for oldauth@localhost = PASSWORD('test2');
+set password for oldpass@localhost = PASSWORD('test2');
+set password for oldpassold@localhost = PASSWORD('test2');
+
+--sorted_result
+select user, host, password, plugin, authentication_string from mysql.user where user != 'root';
+
+--connect(con,localhost,natauth,test2,)
+select current_user();
+--disconnect con
+--connect(con,localhost,newpass,test2,)
+select current_user();
+--disconnect con
+--connect(con,localhost,newpassnat,test2,)
+select current_user();
+--disconnect con
+--connect(con,localhost,oldauth,test2,)
+select current_user();
+--disconnect con
+--connect(con,localhost,oldpass,test2,)
+select current_user();
+--disconnect con
+--connect(con,localhost,oldpassold,test2,)
+select current_user();
+--disconnect con
+
+--connection default
+
+flush privileges;
+
+--connect(con,localhost,natauth,test2,)
+select current_user();
+--disconnect con
+--connect(con,localhost,newpass,test2,)
+select current_user();
+--disconnect con
+--connect(con,localhost,newpassnat,test2,)
+select current_user();
+--disconnect con
+--connect(con,localhost,oldauth,test2,)
+select current_user();
+--disconnect con
+--connect(con,localhost,oldpass,test2,)
+select current_user();
+--disconnect con
+--connect(con,localhost,oldpassold,test2,)
+select current_user();
+--disconnect con
+
+--connection default
+drop user natauth@localhost, newpass@localhost, newpassnat@localhost;
+drop user oldauth@localhost, oldpass@localhost, oldpassold@localhost;
+set global secure_auth=default;
+
diff --git a/mysql-test/t/sp-threads.test b/mysql-test/t/sp-threads.test
index e1012e2b72d..7a6d1258331 100644
--- a/mysql-test/t/sp-threads.test
+++ b/mysql-test/t/sp-threads.test
@@ -77,12 +77,15 @@ call bug9486();
connection con2root;
lock tables t2 write;
connection con1root;
+let $con1root_id=`SELECT CONNECTION_ID()`;
send call bug9486();
connection con2root;
---sleep 2
# There should be call statement in locked state.
---replace_column 1 # 3 localhost 6 #
-show processlist;
+let $wait_condition=SELECT COUNT(*)=1 FROM information_schema.processlist WHERE
+ id=$con1root_id AND state='Waiting for table metadata lock';
+--source include/wait_condition.inc
+--replace_result $con1root_id con1root_id
+eval SELECT state,info FROM information_schema.processlist WHERE id=$con1root_id;
unlock tables;
connection con1root;
reap;
diff --git a/mysql-test/t/ssl.test b/mysql-test/t/ssl.test
index 0d14ad82692..21733f7e594 100644
--- a/mysql-test/t/ssl.test
+++ b/mysql-test/t/ssl.test
@@ -11,7 +11,7 @@
connect (ssl_con,localhost,root,,,,,SSL);
# Check ssl turned on
---replace_result DHE-RSA-AES256-GCM-SHA384 DHE-RSA-AES256-SHA
+--replace_result DHE-RSA-AES256-GCM-SHA384 DHE-RSA-AES256-SHA DHE-RSA-CHACHA20-POLY1305 DHE-RSA-AES256-SHA
SHOW STATUS LIKE 'Ssl_cipher';
# Check ssl expiration
@@ -22,7 +22,7 @@ SHOW STATUS LIKE 'Ssl_server_not_after';
-- source include/common-tests.inc
# Check ssl turned on
---replace_result DHE-RSA-AES256-GCM-SHA384 DHE-RSA-AES256-SHA
+--replace_result DHE-RSA-AES256-GCM-SHA384 DHE-RSA-AES256-SHA DHE-RSA-CHACHA20-POLY1305 DHE-RSA-AES256-SHA
SHOW STATUS LIKE 'Ssl_cipher';
#
diff --git a/mysql-test/t/ssl_compress.test b/mysql-test/t/ssl_compress.test
index 5e45e3824a2..28f3453c23e 100644
--- a/mysql-test/t/ssl_compress.test
+++ b/mysql-test/t/ssl_compress.test
@@ -11,7 +11,7 @@
connect (ssl_compress_con,localhost,root,,,,,SSL COMPRESS);
# Check ssl turned on
---replace_result DHE-RSA-AES256-GCM-SHA384 DHE-RSA-AES256-SHA
+--replace_result DHE-RSA-AES256-GCM-SHA384 DHE-RSA-AES256-SHA DHE-RSA-CHACHA20-POLY1305 DHE-RSA-AES256-SHA
SHOW STATUS LIKE 'Ssl_cipher';
# Check compression turned on
@@ -21,7 +21,7 @@ SHOW STATUS LIKE 'Compression';
-- source include/common-tests.inc
# Check ssl turned on
---replace_result DHE-RSA-AES256-GCM-SHA384 DHE-RSA-AES256-SHA
+--replace_result DHE-RSA-AES256-GCM-SHA384 DHE-RSA-AES256-SHA DHE-RSA-CHACHA20-POLY1305 DHE-RSA-AES256-SHA
SHOW STATUS LIKE 'Ssl_cipher';
# Check compression turned on
diff --git a/mysql-test/t/ssl_timeout-9836.opt b/mysql-test/t/ssl_timeout-9836.opt
new file mode 100644
index 00000000000..7a2696875b8
--- /dev/null
+++ b/mysql-test/t/ssl_timeout-9836.opt
@@ -0,0 +1 @@
+--loose-thread-handling=pool-of-threads
diff --git a/mysql-test/t/ssl_timeout-9836.test b/mysql-test/t/ssl_timeout-9836.test
new file mode 100644
index 00000000000..5b57917f3b8
--- /dev/null
+++ b/mysql-test/t/ssl_timeout-9836.test
@@ -0,0 +1,11 @@
+#
+# MDEV-9836 Connection lost when using SSL
+#
+-- source include/have_ssl_communication.inc
+connect(con1,localhost,root,,,,,SSL);
+SET @@net_read_timeout=1;
+SELECT 1;
+# MDEV-9836 - YASSL bug - SSL connection lost if it has been idle, for longer than net_read_timeout
+-- sleep 2
+SELECT 1;
+disconnect con1;
diff --git a/mysql-test/t/ssl_timeout.test b/mysql-test/t/ssl_timeout.test
index 0d96b3f6601..806b928aca0 100644
--- a/mysql-test/t/ssl_timeout.test
+++ b/mysql-test/t/ssl_timeout.test
@@ -7,7 +7,7 @@
connect (ssl_con,localhost,root,,,,,SSL read_timeout=5);
--echo # Check ssl turned on
---replace_result DHE-RSA-AES256-GCM-SHA384 DHE-RSA-AES256-SHA
+--replace_result DHE-RSA-AES256-GCM-SHA384 DHE-RSA-AES256-SHA DHE-RSA-CHACHA20-POLY1305 DHE-RSA-AES256-SHA
SHOW STATUS LIKE 'Ssl_cipher';
# --error CR_SERVER_LOST
diff --git a/mysql-test/t/type_date.test b/mysql-test/t/type_date.test
index 52ca2c85b15..ce76ad410b6 100644
--- a/mysql-test/t/type_date.test
+++ b/mysql-test/t/type_date.test
@@ -386,6 +386,36 @@ select 1 from t1 as t1_0 inner join t1 as t2 on (t1_0.a <=> now()) join t1 on 1;
drop table t1;
--echo #
+--echo # MDEV-9521 Least function returns 0000-00-00 for null date columns instead of null
+--echo #
+CREATE TABLE t1 (
+ id BIGINT NOT NULL,
+ date_debut DATE NOT NULL,
+ date_fin DATE DEFAULT NULL);
+CREATE TABLE t2(
+ id BIGINT NOT NULL,
+ date_debut DATE NOT NULL,
+ date_fin DATE DEFAULT NULL);
+INSERT INTO t1 VALUES (1,'2016-01-01','2016-01-31');
+INSERT INTO t1 VALUES (2,'2016-02-01',null);
+INSERT INTO t1 VALUES (3,'2016-03-01','2016-03-31');
+INSERT INTO t1 VALUES (4,'2016-04-01',null);
+
+INSERT INTO t2 VALUES (1,'2016-01-01','2016-01-31');
+INSERT INTO t2 VALUES (2,'2016-02-01','2016-01-28');
+INSERT INTO t2 VALUES (3,'2016-03-01',null);
+INSERT INTO t2 VALUES (4,'2016-04-01',null);
+SELECT t1.id,
+ GREATEST(t2.date_debut, t1.date_debut) AS date_debut,
+ LEAST(IFNULL(t2.date_fin, IFNULL(t1.date_fin, NULL)),
+ IFNULL(t1.date_fin, IFNULL(t2.date_fin, NULL))) AS date_fin
+FROM t1 LEFT JOIN t2 ON (t1.id=t2.id);
+DROP TABLE t1,t2;
+SELECT
+ LEAST(COALESCE(DATE(NULL), DATE(NULL)), COALESCE(DATE(NULL), DATE(NULL))) AS d0,
+ LEAST(IFNULL(DATE(NULL), DATE(NULL)), IFNULL(DATE(NULL), DATE(NULL))) AS d1;
+
+--echo #
--echo # MDEV-9511 Valgrind warnings 'Invalid read' in Field_newdate::cmp and Field_newdate::val_str
--echo #
CREATE TABLE t1 (f1 DATE, f2 VARCHAR(1));
diff --git a/mysql-test/t/type_timestamp.test b/mysql-test/t/type_timestamp.test
index 6188ed6b4d6..460769f8961 100644
--- a/mysql-test/t/type_timestamp.test
+++ b/mysql-test/t/type_timestamp.test
@@ -445,6 +445,14 @@ SELECT MAX(ts) = '2011-01-06 12:34:30' FROM t1;
SELECT MAX(dt) = '2011-01-06 12:34:30' FROM t1;
DROP TABLE t1;
+--echo #
+--echo # MDEV-9413 "datetime >= coalesce(c1(NULL))" doesn't return expected NULL
+--echo #
+CREATE TABLE t1(c1 TIMESTAMP(6) NULL DEFAULT NULL);
+INSERT INTO t1 VALUES(NULL);
+SELECT c1, '2016-06-13 20:00:00.000003' >= COALESCE( c1 ) FROM t1;
+DROP TABLE t1;
+
--echo End of 5.5 tests
--echo #
diff --git a/mysql-test/t/wait_timeout_not_windows.test b/mysql-test/t/wait_timeout_not_windows.test
new file mode 100644
index 00000000000..de4904fada2
--- /dev/null
+++ b/mysql-test/t/wait_timeout_not_windows.test
@@ -0,0 +1,16 @@
+source include/not_embedded.inc;
+source include/not_windows.inc;
+
+#
+# MDEV-7775 Wrong error message (Unknown error) when idle sessions are killed after wait_timeout
+#
+set global log_warnings=2;
+connect (foo,localhost,root);
+set @@wait_timeout=1;
+sleep 2;
+connection default;
+let SEARCH_FILE=$MYSQLTEST_VARDIR/log/mysqld.1.err;
+let SEARCH_RANGE= -50;
+let SEARCH_PATTERN= Aborted.*Got timeout reading communication packets;
+source include/search_pattern_in_file.inc;
+set global log_warnings=@@log_warnings;
diff --git a/mysql-test/valgrind.supp b/mysql-test/valgrind.supp
index b5c9b62049b..fd5699b04c6 100644
--- a/mysql-test/valgrind.supp
+++ b/mysql-test/valgrind.supp
@@ -1152,6 +1152,13 @@
fun:SSL_library_init
}
+{
+ libcrypto 2.2.1 leak
+ Memcheck:Leak
+ fun:malloc
+ ...
+ fun:ERR_get_state
+}
{
Problem with udf and libresolve
diff --git a/mysys/my_copy.c b/mysys/my_copy.c
index 8af572b5518..bd23dfc48cd 100644
--- a/mysys/my_copy.c
+++ b/mysys/my_copy.c
@@ -18,7 +18,6 @@
#include "mysys_err.h"
#include <my_dir.h> /* for stat */
#include <m_string.h>
-#include "mysys_err.h"
#if defined(HAVE_UTIME_H)
#include <utime.h>
#elif defined(HAVE_SYS_UTIME_H)
diff --git a/plugin/handler_socket/client/hslongrun.cpp b/plugin/handler_socket/client/hslongrun.cpp
index e82c12b166b..b7c02951340 100644
--- a/plugin/handler_socket/client/hslongrun.cpp
+++ b/plugin/handler_socket/client/hslongrun.cpp
@@ -39,7 +39,7 @@ struct auto_mysql : private noncopyable {
mysql_close(db);
}
if ((db = mysql_init(0)) == 0) {
- fatal_exit("failed to initialize mysql client");
+ fatal_abort("failed to initialize mysql client");
}
}
operator MYSQL *() const { return db; }
@@ -870,7 +870,7 @@ mysql_do(MYSQL *db, const char *query)
{
if (mysql_real_query(db, query, strlen(query)) != 0) {
fprintf(stderr, "mysql: e=[%s] q=[%s]\n", mysql_error(db), query);
- fatal_exit("mysql_do");
+ fatal_abort("mysql_do");
}
}
@@ -886,7 +886,7 @@ hs_longrun_init_table(const config& conf, int num_prepare,
if (!mysql_real_connect(db, mysql_host.c_str(), mysql_user.c_str(),
mysql_passwd.c_str(), mysql_dbname.c_str(), mysql_port, 0, 0)) {
fprintf(stderr, "mysql: error=[%s]\n", mysql_error(db));
- fatal_exit("hs_longrun_init_table");
+ fatal_abort("hs_longrun_init_table");
}
mysql_do(db, "drop database if exists hstestdb");
mysql_do(db, "create database hstestdb");
diff --git a/plugin/handler_socket/libhsclient/fatal.cpp b/plugin/handler_socket/libhsclient/fatal.cpp
index 5cdd8879ab1..8e109cf13ba 100644
--- a/plugin/handler_socket/libhsclient/fatal.cpp
+++ b/plugin/handler_socket/libhsclient/fatal.cpp
@@ -18,14 +18,6 @@ namespace dena {
const int opt_syslog = LOG_ERR | LOG_PID | LOG_CONS;
void
-fatal_exit(const std::string& message)
-{
- fprintf(stderr, "FATAL_EXIT: %s\n", message.c_str());
- syslog(opt_syslog, "FATAL_EXIT: %s", message.c_str());
- _exit(1);
-}
-
-void
fatal_abort(const std::string& message)
{
fprintf(stderr, "FATAL_COREDUMP: %s\n", message.c_str());
diff --git a/plugin/handler_socket/libhsclient/fatal.hpp b/plugin/handler_socket/libhsclient/fatal.hpp
index 8a630fab1cb..5eaa3db8687 100644
--- a/plugin/handler_socket/libhsclient/fatal.hpp
+++ b/plugin/handler_socket/libhsclient/fatal.hpp
@@ -13,7 +13,6 @@
namespace dena {
-void fatal_exit(const std::string& message);
void fatal_abort(const std::string& message);
};
diff --git a/plugin/handler_socket/libhsclient/socket.cpp b/plugin/handler_socket/libhsclient/socket.cpp
index cf19d4bbe14..2c93a3b4846 100644
--- a/plugin/handler_socket/libhsclient/socket.cpp
+++ b/plugin/handler_socket/libhsclient/socket.cpp
@@ -43,7 +43,7 @@ socket_args::set(const config& conf)
} else {
const char *nd = node.empty() ? 0 : node.c_str();
if (resolve(nd, port.c_str()) != 0) {
- fatal_exit("getaddrinfo failed: " + node + ":" + port);
+ fatal_abort("getaddrinfo failed: " + node + ":" + port);
}
}
}
diff --git a/plugin/server_audit/server_audit.c b/plugin/server_audit/server_audit.c
index 30b7cdb5dcb..b84f2b94806 100644
--- a/plugin/server_audit/server_audit.c
+++ b/plugin/server_audit/server_audit.c
@@ -97,13 +97,11 @@ static void closelog() {}
#define FLOGGER_NO_PSI
/* How to access the pthread_mutex in mysql_mutex_t */
-//#ifdef SAFE_MUTEX
-//#define mysql_mutex_real_mutex(A) &(A)->m_mutex.mutex
-//#elif defined(MY_PTHREAD_FASTMUTEX)
-//#define mysql_mutex_real_mutex(A) &(A)->m_mutex.mutex
-//#else
+#if defined(SAFE_MUTEX) || defined(MY_PTHREAD_FASTMUTEX)
+#define mysql_mutex_real_mutex(A) &(A)->m_mutex.mutex
+#else
#define mysql_mutex_real_mutex(A) &(A)->m_mutex
-//#endif
+#endif
#define flogger_mutex_init(A,B,C) do{}while(0)
#define flogger_mutex_destroy(A) do{}while(0)
diff --git a/scripts/mysql_system_tables.sql b/scripts/mysql_system_tables.sql
index b878a2e636e..f7d277544de 100644
--- a/scripts/mysql_system_tables.sql
+++ b/scripts/mysql_system_tables.sql
@@ -229,7 +229,7 @@ SET @cmd= "CREATE TABLE IF NOT EXISTS gtid_slave_pos (
sub_id BIGINT UNSIGNED NOT NULL,
server_id INT UNSIGNED NOT NULL,
seq_no BIGINT UNSIGNED NOT NULL,
- PRIMARY KEY (domain_id, sub_id))
+ PRIMARY KEY (domain_id, sub_id)) CHARSET=latin1
COMMENT='Replication slave GTID position'";
SET @str=CONCAT(@cmd, ' ENGINE=', @innodb_or_myisam);
PREPARE stmt FROM @str;
diff --git a/sql/create_options.cc b/sql/create_options.cc
index 66515be05b8..40e4e8b321c 100644
--- a/sql/create_options.cc
+++ b/sql/create_options.cc
@@ -685,20 +685,25 @@ uchar *engine_table_options_frm_image(uchar *buff,
@returns pointer to byte after last recorded in the buffer
*/
-uchar *engine_option_value::frm_read(const uchar *buff, engine_option_value **start,
+uchar *engine_option_value::frm_read(const uchar *buff, const uchar *buff_end,
+ engine_option_value **start,
engine_option_value **end, MEM_ROOT *root)
{
LEX_STRING name, value;
uint len;
+#define need_buff(N) if (buff + (N) >= buff_end) return NULL
+ need_buff(3);
name.length= buff[0];
buff++;
+ need_buff(name.length + 2);
if (!(name.str= strmake_root(root, (const char*)buff, name.length)))
return NULL;
buff+= name.length;
len= uint2korr(buff);
value.length= len & ~FRM_QUOTED_VALUE;
buff+= 2;
+ need_buff(value.length);
if (!(value.str= strmake_root(root, (const char*)buff, value.length)))
return NULL;
buff+= value.length;
@@ -735,8 +740,8 @@ bool engine_table_options_frm_read(const uchar *buff, uint length,
while (buff < buff_end && *buff)
{
- if (!(buff= engine_option_value::frm_read(buff, &share->option_list, &end,
- root)))
+ if (!(buff= engine_option_value::frm_read(buff, buff_end,
+ &share->option_list, &end, root)))
DBUG_RETURN(TRUE);
}
buff++;
@@ -745,7 +750,7 @@ bool engine_table_options_frm_read(const uchar *buff, uint length,
{
while (buff < buff_end && *buff)
{
- if (!(buff= engine_option_value::frm_read(buff,
+ if (!(buff= engine_option_value::frm_read(buff, buff_end,
&share->field[count]->option_list,
&end, root)))
DBUG_RETURN(TRUE);
@@ -757,7 +762,7 @@ bool engine_table_options_frm_read(const uchar *buff, uint length,
{
while (buff < buff_end && *buff)
{
- if (!(buff= engine_option_value::frm_read(buff,
+ if (!(buff= engine_option_value::frm_read(buff, buff_end,
&share->key_info[count].option_list,
&end, root)))
DBUG_RETURN(TRUE);
diff --git a/sql/create_options.h b/sql/create_options.h
index eb21f291ff4..3e7f9ecfabf 100644
--- a/sql/create_options.h
+++ b/sql/create_options.h
@@ -23,7 +23,8 @@
#define SQL_CREATE_OPTIONS_INCLUDED
#include "sql_class.h"
-//#include "handler.h"
+
+enum { ENGINE_OPTION_MAX_LENGTH=32767 };
class engine_option_value: public Sql_alloc
{
@@ -66,7 +67,8 @@ class engine_option_value: public Sql_alloc
link(start, end);
}
}
- static uchar *frm_read(const uchar *buff, engine_option_value **start,
+ static uchar *frm_read(const uchar *buff, const uchar *buff_end,
+ engine_option_value **start,
engine_option_value **end, MEM_ROOT *root);
void link(engine_option_value **start, engine_option_value **end);
uint frm_length();
diff --git a/sql/debug_sync.h b/sql/debug_sync.h
index bf1b3167dbc..25b379e5892 100644
--- a/sql/debug_sync.h
+++ b/sql/debug_sync.h
@@ -44,6 +44,7 @@ extern void debug_sync_end(void);
extern void debug_sync_init_thread(THD *thd);
extern void debug_sync_end_thread(THD *thd);
extern bool debug_sync_set_action(THD *thd, const char *action_str, size_t len);
+extern bool debug_sync_update(THD *thd, char *val_str);
#endif /* defined(ENABLED_DEBUG_SYNC) */
diff --git a/sql/gen_lex_hash.cc b/sql/gen_lex_hash.cc
index c37f4f145cf..3a3273d279b 100644
--- a/sql/gen_lex_hash.cc
+++ b/sql/gen_lex_hash.cc
@@ -310,6 +310,7 @@ void print_find_structs()
add_structs_to_map(root_by_len,max_len);
set_links(root_by_len,max_len);
print_hash_map("sql_functions_map");
+ free(hash_map);
hash_map= 0;
size_hash_map= 0;
@@ -319,6 +320,7 @@ void print_find_structs()
add_structs_to_map(root_by_len2,max_len2);
set_links(root_by_len2,max_len2);
print_hash_map("symbols_map");
+ free(hash_map);
}
diff --git a/sql/handler.cc b/sql/handler.cc
index fb2921f9ba3..1e6e16171e3 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -1,5 +1,5 @@
-/* Copyright (c) 2000, 2013, Oracle and/or its affiliates.
- Copyright (c) 2009, 2013, Monty Program Ab.
+/* Copyright (c) 2000, 2016, Oracle and/or its affiliates.
+ Copyright (c) 2009, 2016, MariaDB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -4200,6 +4200,7 @@ handler::check_if_supported_inplace_alter(TABLE *altered_table,
Alter_inplace_info::ALTER_COLUMN_DEFAULT |
Alter_inplace_info::ALTER_COLUMN_OPTION |
Alter_inplace_info::CHANGE_CREATE_OPTION |
+ Alter_inplace_info::ALTER_PARTITIONED |
Alter_inplace_info::ALTER_RENAME;
/* Is there at least one operation that requires copy algorithm? */
diff --git a/sql/handler.h b/sql/handler.h
index 34b7b147d58..3ffe4d03596 100644
--- a/sql/handler.h
+++ b/sql/handler.h
@@ -1,8 +1,8 @@
#ifndef HANDLER_INCLUDED
#define HANDLER_INCLUDED
/*
- Copyright (c) 2000, 2014, Oracle and/or its affiliates.
- Copyright (c) 2009, 2014, Monty Program Ab.
+ Copyright (c) 2000, 2016, Oracle and/or its affiliates.
+ Copyright (c) 2009, 2016, MariaDB
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
@@ -129,7 +129,7 @@ enum enum_alter_inplace_result {
*/
#define HA_PRIMARY_KEY_REQUIRED_FOR_POSITION (1ULL << 16)
#define HA_CAN_RTREEKEYS (1ULL << 17)
-#define HA_NOT_DELETE_WITH_CACHE (1ULL << 18)
+#define HA_NOT_DELETE_WITH_CACHE (1ULL << 18) /* unused */
/*
The following is we need to a primary key to delete (and update) a row.
If there is no primary key, all columns needs to be read on update and delete
@@ -143,7 +143,7 @@ enum enum_alter_inplace_result {
#define HA_HAS_OLD_CHECKSUM (1ULL << 24)
/* Table data are stored in separate files (for lower_case_table_names) */
#define HA_FILE_BASED (1ULL << 26)
-#define HA_NO_VARCHAR (1ULL << 27)
+#define HA_NO_VARCHAR (1ULL << 27) /* unused */
#define HA_CAN_BIT_FIELD (1ULL << 28) /* supports bit fields */
#define HA_NEED_READ_RANGE_BUFFER (1ULL << 29) /* for read_multi_range */
#define HA_ANY_INDEX_MAY_BE_UNIQUE (1ULL << 30)
@@ -248,6 +248,15 @@ enum enum_alter_inplace_result {
*/
#define HA_CAN_EXPORT (1LL << 45)
+/*
+ Storage engine does not require an exclusive metadata lock
+ on the table during optimize. (TODO and repair?).
+ It can allow other connections to open the table.
+ (it does not necessarily mean that other connections can
+ read or modify the table - this is defined by THR locks and the
+ ::store_lock() method).
+*/
+#define HA_CONCURRENT_OPTIMIZE (1LL << 46)
/*
Set of all binlog flags. Currently only contain the capabilities
@@ -406,7 +415,9 @@ static const uint MYSQL_START_TRANS_OPT_READ_WRITE = 4;
/* Flags for method is_fatal_error */
#define HA_CHECK_DUP_KEY 1
#define HA_CHECK_DUP_UNIQUE 2
+#define HA_CHECK_FK_ERROR 4
#define HA_CHECK_DUP (HA_CHECK_DUP_KEY + HA_CHECK_DUP_UNIQUE)
+#define HA_CHECK_ALL (~0U)
enum legacy_db_type
{
@@ -1929,7 +1940,10 @@ public:
// Virtual columns changed
static const HA_ALTER_FLAGS ALTER_COLUMN_VCOL = 1L << 30;
- // ALTER TABLE for a partitioned table
+ /**
+ ALTER TABLE for a partitioned table. The engine needs to commit
+ online alter of all partitions atomically (using group_commit_ctx)
+ */
static const HA_ALTER_FLAGS ALTER_PARTITIONED = 1L << 31;
/**
@@ -2934,7 +2948,10 @@ public:
((flags & HA_CHECK_DUP_KEY) &&
(error == HA_ERR_FOUND_DUPP_KEY ||
error == HA_ERR_FOUND_DUPP_UNIQUE)) ||
- error == HA_ERR_AUTOINC_ERANGE)
+ error == HA_ERR_AUTOINC_ERANGE ||
+ ((flags & HA_CHECK_FK_ERROR) &&
+ (error == HA_ERR_ROW_IS_REFERENCED ||
+ error == HA_ERR_NO_REFERENCED_ROW)))
return FALSE;
return TRUE;
}
@@ -4269,4 +4286,4 @@ inline const char *table_case_name(HA_CREATE_INFO *info, const char *name)
void print_keydup_error(TABLE *table, KEY *key, const char *msg, myf errflag);
void print_keydup_error(TABLE *table, KEY *key, myf errflag);
-#endif
+#endif /* HANDLER_INCLUDED */
diff --git a/sql/item.cc b/sql/item.cc
index f1362e7e5da..adf70312b37 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -1,5 +1,5 @@
/*
- Copyright (c) 2000, 2014, Oracle and/or its affiliates.
+ Copyright (c) 2000, 2016, Oracle and/or its affiliates.
Copyright (c) 2010, 2016, MariaDB
This program is free software; you can redistribute it and/or modify
@@ -1219,8 +1219,8 @@ Item *Item_param::safe_charset_converter(THD *thd, CHARSET_INFO *tocs)
to it's possible that the converter will not be needed at all:
PREPARE stmt FROM 'SELECT * FROM t1 WHERE field = ?';
- SET @@arg= 1;
- EXECUTE stms USING @arg;
+ SET @arg= 1;
+ EXECUTE stmt USING @arg;
In the above example result_type is STRING_RESULT at prepare time,
and INT_RESULT at execution time.
@@ -3701,7 +3701,7 @@ Item_param::eq(const Item *item, bool binary_cmp) const
void Item_param::print(String *str, enum_query_type query_type)
{
- if (state == NO_VALUE)
+ if (state == NO_VALUE || query_type & QT_NO_DATA_EXPANSION)
{
str->append('?');
}
@@ -6649,7 +6649,8 @@ Item *Item_field::update_value_transformer(THD *thd, uchar *select_arg)
void Item_field::print(String *str, enum_query_type query_type)
{
- if (field && field->table->const_table)
+ if (field && field->table->const_table &&
+ !(query_type & QT_NO_DATA_EXPANSION))
{
print_value(str);
return;
diff --git a/sql/item.h b/sql/item.h
index 6e0a4aa82ce..bef57c4a967 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -2546,7 +2546,7 @@ public:
max_length= 0;
name= name_par ? name_par : (char*) "NULL";
fixed= 1;
- collation.set(cs, DERIVATION_IGNORABLE);
+ collation.set(cs, DERIVATION_IGNORABLE, MY_REPERTOIRE_ASCII);
}
enum Type type() const { return NULL_ITEM; }
bool eq(const Item *item, bool binary_cmp) const { return null_eq(item); }
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index 1ce8bad933b..d745dd8ff73 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -120,10 +120,11 @@ static int cmp_row_type(Item* item1, Item* item2)
static int agg_cmp_type(Item_result *type, Item **items, uint nitems)
{
- uint i;
+ uint unsigned_count= items[0]->unsigned_flag;
type[0]= items[0]->cmp_type();
- for (i= 1 ; i < nitems ; i++)
+ for (uint i= 1 ; i < nitems ; i++)
{
+ unsigned_count+= items[i]->unsigned_flag;
type[0]= item_cmp_type(type[0], items[i]);
/*
When aggregating types of two row expressions we have to check
@@ -135,6 +136,12 @@ static int agg_cmp_type(Item_result *type, Item **items, uint nitems)
if (type[0] == ROW_RESULT && cmp_row_type(items[0], items[i]))
return 1; // error found: invalid usage of rows
}
+ /**
+ If all arguments are of INT type but have different unsigned_flag values,
+ switch to DECIMAL_RESULT.
+ */
+ if (type[0] == INT_RESULT && unsigned_count != nitems && unsigned_count != 0)
+ type[0]= DECIMAL_RESULT;
return 0;
}
@@ -2334,10 +2341,7 @@ bool Item_func_ifnull::date_op(MYSQL_TIME *ltime, uint fuzzydate)
DBUG_ASSERT(fixed == 1);
if (!args[0]->get_date_with_conversion(ltime, fuzzydate & ~TIME_FUZZY_DATES))
return (null_value= false);
- if (!args[1]->get_date_with_conversion(ltime, fuzzydate & ~TIME_FUZZY_DATES))
- return (null_value= false);
- bzero((char*) ltime,sizeof(*ltime));
- return null_value= !(fuzzydate & TIME_FUZZY_DATES);
+ return (null_value= args[1]->get_date_with_conversion(ltime, fuzzydate & ~TIME_FUZZY_DATES));
}
@@ -3367,16 +3371,12 @@ double Item_func_coalesce::real_op()
bool Item_func_coalesce::date_op(MYSQL_TIME *ltime,uint fuzzydate)
{
DBUG_ASSERT(fixed == 1);
- null_value= 0;
for (uint i= 0; i < arg_count; i++)
{
- bool res= args[i]->get_date_with_conversion(ltime,
- fuzzydate & ~TIME_FUZZY_DATES);
- if (!args[i]->null_value)
- return res;
+ if (!args[i]->get_date_with_conversion(ltime, fuzzydate & ~TIME_FUZZY_DATES))
+ return (null_value= false);
}
- bzero((char*) ltime,sizeof(*ltime));
- return null_value|= !(fuzzydate & TIME_FUZZY_DATES);
+ return (null_value= true);
}
diff --git a/sql/item_func.cc b/sql/item_func.cc
index e5c1f4c75f6..6edb276ca20 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -6307,6 +6307,8 @@ bool Item_func_match::fix_index()
for (i=1; i < arg_count; i++)
{
+ if (args[i]->type() != FIELD_ITEM)
+ goto err;
item=(Item_field*)args[i];
for (keynr=0 ; keynr < fts ; keynr++)
{
diff --git a/sql/item_func.h b/sql/item_func.h
index a5f6bf26134..6a1494040c9 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -1,7 +1,7 @@
#ifndef ITEM_FUNC_INCLUDED
#define ITEM_FUNC_INCLUDED
-/* Copyright (c) 2000, 2014, Oracle and/or its affiliates.
- Copyright (c) 2009, 2014, MariaDB
+/* Copyright (c) 2000, 2016, Oracle and/or its affiliates.
+ Copyright (c) 2009, 2016, MariaDB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -210,7 +210,7 @@ public:
char buf[256];
String str(buf, sizeof(buf), system_charset_info);
str.length(0);
- print(&str, QT_ORDINARY);
+ print(&str, QT_NO_DATA_EXPANSION);
my_error(ER_DATA_OUT_OF_RANGE, MYF(0), type_name, str.c_ptr_safe());
}
inline double raise_float_overflow()
@@ -452,7 +452,6 @@ class Item_func_hybrid_field_type: public Item_hybrid_func
}
protected:
Item_result cached_result_type;
-
public:
Item_func_hybrid_field_type(THD *thd):
Item_hybrid_func(thd)
diff --git a/sql/item_geofunc.h b/sql/item_geofunc.h
index b72661fe054..6b991a1b643 100644
--- a/sql/item_geofunc.h
+++ b/sql/item_geofunc.h
@@ -1,8 +1,8 @@
#ifndef ITEM_GEOFUNC_INCLUDED
#define ITEM_GEOFUNC_INCLUDED
-/* Copyright (c) 2000, 2010 Oracle and/or its affiliates.
- Copyright (C) 2011, 2015 MariaDB
+/* Copyright (c) 2000, 2016 Oracle and/or its affiliates.
+ Copyright (C) 2011, 2016, MariaDB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -259,7 +259,7 @@ public:
if (args[i]->fixed && args[i]->field_type() != MYSQL_TYPE_GEOMETRY)
{
String str;
- args[i]->print(&str, QT_ORDINARY);
+ args[i]->print(&str, QT_NO_DATA_EXPANSION);
str.append('\0');
my_error(ER_ILLEGAL_VALUE_FOR_TYPE, MYF(0), "non geometric",
str.ptr());
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index 8bf1521e971..38fc58d00d5 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -814,9 +814,10 @@ String *Item_func_des_encrypt::val_str(String *str)
/* We make good 24-byte (168 bit) key from given plaintext key with MD5 */
bzero((char*) &ivec,sizeof(ivec));
- EVP_BytesToKey(EVP_des_ede3_cbc(),EVP_md5(),NULL,
+ if (!EVP_BytesToKey(EVP_des_ede3_cbc(),EVP_md5(),NULL,
(uchar*) keystr->ptr(), (int) keystr->length(),
- 1, (uchar*) &keyblock,ivec);
+ 1, (uchar*) &keyblock,ivec))
+ goto error;
DES_set_key_unchecked(&keyblock.key1,&keyschedule.ks1);
DES_set_key_unchecked(&keyblock.key2,&keyschedule.ks2);
DES_set_key_unchecked(&keyblock.key3,&keyschedule.ks3);
@@ -909,9 +910,10 @@ String *Item_func_des_decrypt::val_str(String *str)
goto error;
bzero((char*) &ivec,sizeof(ivec));
- EVP_BytesToKey(EVP_des_ede3_cbc(),EVP_md5(),NULL,
+ if (!EVP_BytesToKey(EVP_des_ede3_cbc(),EVP_md5(),NULL,
(uchar*) keystr->ptr(),(int) keystr->length(),
- 1,(uchar*) &keyblock,ivec);
+ 1,(uchar*) &keyblock,ivec))
+ goto error;
// Here we set all 64-bit keys (56 effective) one by one
DES_set_key_unchecked(&keyblock.key1,&keyschedule.ks1);
DES_set_key_unchecked(&keyblock.key2,&keyschedule.ks2);
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index a4c6184f313..ee40df945ed 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -290,7 +290,7 @@ const char *show_comp_option_name[]= {"YES", "NO", "DISABLED"};
static const char *tc_heuristic_recover_names[]=
{
- "COMMIT", "ROLLBACK", NullS
+ "OFF", "COMMIT", "ROLLBACK", NullS
};
static TYPELIB tc_heuristic_recover_typelib=
{
@@ -7039,7 +7039,7 @@ pthread_handler_t handle_connections_shared_memory(void *arg)
thd->security_ctx->host= my_strdup(my_localhost, MYF(0)); /* Host is unknown */
create_new_thread(thd);
connect_number++;
- set_current_thd(thd);
+ set_current_thd(0);
continue;
errorconn:
@@ -9180,6 +9180,7 @@ mysqld_get_one_option(int optid, const struct my_option *opt, char *argument)
log_error_file_ptr= const_cast<char*>("");
break;
case OPT_IGNORE_DB_DIRECTORY:
+ opt_ignore_db_dirs= NULL; // will be set in ignore_db_dirs_process_additions
if (*argument == 0)
ignore_db_dirs_reset();
else
diff --git a/sql/mysqld.h b/sql/mysqld.h
index 30120d66113..594afac521d 100644
--- a/sql/mysqld.h
+++ b/sql/mysqld.h
@@ -1,5 +1,5 @@
-/* Copyright (c) 2006, 2015, Oracle and/or its affiliates.
- Copyright (c) 2010, 2015, MariaDB
+/* Copyright (c) 2006, 2016, Oracle and/or its affiliates.
+ Copyright (c) 2010, 2016, MariaDB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -683,7 +683,12 @@ enum enum_query_type
/// Be more detailed than QT_EXPLAIN.
/// Perhaps we should eventually include QT_ITEM_IDENT_SKIP_CURRENT_DATABASE
/// here, as it would give better readable results
- QT_EXPLAIN_EXTENDED= QT_TO_SYSTEM_CHARSET
+ QT_EXPLAIN_EXTENDED= QT_TO_SYSTEM_CHARSET,
+
+ // If an expression is constant, print the expression, not the value
+ // it evaluates to. Should be used for error messages, so that they
+ // don't reveal values.
+ QT_NO_DATA_EXPANSION= (1 << 9),
};
diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc
index cb356fbdf41..537774aea2a 100644
--- a/sql/opt_subselect.cc
+++ b/sql/opt_subselect.cc
@@ -2251,7 +2251,8 @@ bool optimize_semijoin_nests(JOIN *join, table_map all_table_map)
rows *= join->map2table[tableno]->table->quick_condition_rows;
sjm->rows= MY_MIN(sjm->rows, rows);
}
- memcpy(sjm->positions, join->best_positions + join->const_tables,
+ memcpy((uchar*) sjm->positions,
+ (uchar*) (join->best_positions + join->const_tables),
sizeof(POSITION) * n_tables);
/*
@@ -3354,7 +3355,7 @@ void fix_semijoin_strategies_for_picked_join_order(JOIN *join)
SJ_MATERIALIZATION_INFO *sjm= s->emb_sj_nest->sj_mat_info;
sjm->is_used= TRUE;
sjm->is_sj_scan= FALSE;
- memcpy(pos - sjm->tables + 1, sjm->positions,
+ memcpy((uchar*) (pos - sjm->tables + 1), (uchar*) sjm->positions,
sizeof(POSITION) * sjm->tables);
recalculate_prefix_record_count(join, tablenr - sjm->tables + 1,
tablenr);
@@ -3370,8 +3371,8 @@ void fix_semijoin_strategies_for_picked_join_order(JOIN *join)
sjm->is_used= TRUE;
sjm->is_sj_scan= TRUE;
first= pos->sjmat_picker.sjm_scan_last_inner - sjm->tables + 1;
- memcpy(join->best_positions + first,
- sjm->positions, sizeof(POSITION) * sjm->tables);
+ memcpy((uchar*) (join->best_positions + first),
+ (uchar*) sjm->positions, sizeof(POSITION) * sjm->tables);
recalculate_prefix_record_count(join, first, first + sjm->tables);
join->best_positions[first].sj_strategy= SJ_OPT_MATERIALIZE_SCAN;
join->best_positions[first].n_sj_tables= sjm->tables;
diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt
index 1bd87e0b393..709ac55b28c 100644
--- a/sql/share/errmsg-utf8.txt
+++ b/sql/share/errmsg-utf8.txt
@@ -6136,7 +6136,7 @@ ER_SLAVE_HEARTBEAT_FAILURE
eng "Unexpected master's heartbeat data: %s"
ger "Unerwartete Daten vom Heartbeat des Masters: %s"
ER_SLAVE_HEARTBEAT_VALUE_OUT_OF_RANGE
- eng "The requested value for the heartbeat period is either negative or exceeds the maximum allowed (%s seconds)."
+ eng "The requested value for the heartbeat period is either negative or exceeds the maximum allowed (%u seconds)."
ER_UNUSED_14
eng "You should never see it"
ER_CONFLICT_FN_PARSE_ERROR
@@ -6506,8 +6506,8 @@ ER_PARTITION_EXCHANGE_FOREIGN_KEY
swe "Tabellen att byta ut mot partition har foreign key referenser: '%-.64s'"
ER_NO_SUCH_KEY_VALUE
eng "Key value '%-.192s' was not found in table '%-.192s.%-.192s'"
-ER_RPL_INFO_DATA_TOO_LONG
- eng "Data for column '%s' too long"
+ER_VALUE_TOO_LONG
+ eng "Too long value for '%s'"
ER_NETWORK_READ_EVENT_CHECKSUM_FAILURE
eng "Replication event checksum verification failed while reading from network."
ER_BINLOG_READ_EVENT_CHECKSUM_FAILURE
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index f323c7871c9..95b90c263ee 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -1,5 +1,5 @@
-/* Copyright (c) 2000, 2013, Oracle and/or its affiliates.
- Copyright (c) 2009, 2014, SkySQL Ab.
+/* Copyright (c) 2000, 2016, Oracle and/or its affiliates.
+ Copyright (c) 2009, 2016, MariaDB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -745,9 +745,8 @@ static ACL_USER *find_user_wild(const char *host, const char *user, const char *
static ACL_ROLE *find_acl_role(const char *user);
static ROLE_GRANT_PAIR *find_role_grant_pair(const LEX_STRING *u, const LEX_STRING *h, const LEX_STRING *r);
static ACL_USER_BASE *find_acl_user_base(const char *user, const char *host);
-static bool update_user_table(THD *thd, TABLE *table, const char *host,
- const char *user, const char *new_password,
- uint new_password_len);
+static bool update_user_table(THD *, TABLE *, const char *, const char *, const
+ char *, uint);
static bool acl_load(THD *thd, TABLE_LIST *tables);
static bool grant_load(THD *thd, TABLE_LIST *tables);
static inline void get_grantor(THD *thd, char* grantor);
@@ -1206,7 +1205,6 @@ static bool acl_load(THD *thd, TABLE_LIST *tables)
grant_version++; /* Privileges updated */
init_sql_alloc(&acl_memroot, ACL_ALLOC_BLOCK_SIZE, 0, MYF(0));
- (void) my_init_dynamic_array(&acl_hosts,sizeof(ACL_HOST), 20, 50, MYF(0));
if ((table= tables[HOST_TABLE].table)) // "host" table may not exist (e.g. in MySQL 5.6.7+)
{
if (init_read_record(&read_record_info, thd, table, NULL, 1, 1, FALSE))
@@ -1263,12 +1261,11 @@ static bool acl_load(THD *thd, TABLE_LIST *tables)
}
freeze_size(&acl_hosts);
- (void) my_init_dynamic_array(&acl_users,sizeof(ACL_USER), 50, 100, MYF(0));
- (void) my_hash_init2(&acl_roles,50, &my_charset_utf8_bin,
- 0, 0, 0, (my_hash_get_key) acl_role_get_key, 0,
- (void (*)(void *))free_acl_role, 0);
+ if (init_read_record(&read_record_info, thd, table=tables[USER_TABLE].table,
+ NULL, 1, 1, FALSE))
+ goto end;
+ table->use_all_columns();
- table= tables[USER_TABLE].table,
username_char_length= MY_MIN(table->field[1]->char_length(),
USERNAME_CHAR_LENGTH);
password_length= table->field[2]->field_length /
@@ -1280,10 +1277,6 @@ static bool acl_load(THD *thd, TABLE_LIST *tables)
goto end;
}
- if (init_read_record(&read_record_info, thd, table, NULL, 1, 1, FALSE))
- goto end;
- table->use_all_columns();
-
DBUG_PRINT("info",("user table fields: %d, password length: %d",
table->s->fields, password_length));
@@ -1295,7 +1288,6 @@ static bool acl_load(THD *thd, TABLE_LIST *tables)
mysql_mutex_unlock(&LOCK_global_system_variables);
sql_print_error("Fatal error: mysql.user table is in old format, "
"but server started with --secure-auth option.");
- end_read_record(&read_record_info);
goto end;
}
mysql_user_table_is_in_short_password_format= true;
@@ -1531,7 +1523,6 @@ static bool acl_load(THD *thd, TABLE_LIST *tables)
NULL, 1, 1, FALSE))
goto end;
table->use_all_columns();
- (void) my_init_dynamic_array(&acl_dbs,sizeof(ACL_DB), 50, 100, MYF(0));
while (!(read_record_info.read_record(&read_record_info)))
{
ACL_DB db;
@@ -1593,8 +1584,6 @@ static bool acl_load(THD *thd, TABLE_LIST *tables)
end_read_record(&read_record_info);
freeze_size(&acl_dbs);
- (void) my_init_dynamic_array(&acl_proxy_users, sizeof(ACL_PROXY_USER),
- 50, 100, MYF(0));
if ((table= tables[PROXIES_PRIV_TABLE].table))
{
if (init_read_record(&read_record_info, thd, table,
@@ -1630,10 +1619,7 @@ static bool acl_load(THD *thd, TABLE_LIST *tables)
if (init_read_record(&read_record_info, thd, table, NULL, 1, 1, FALSE))
goto end;
table->use_all_columns();
- /* account for every role mapping */
- (void) my_hash_init2(&acl_roles_mappings, 50, system_charset_info, 0, 0, 0,
- (my_hash_get_key) acl_role_map_get_key, 0, 0, 0);
MEM_ROOT temp_root;
init_alloc_root(&temp_root, ACL_ALLOC_BLOCK_SIZE, 0, MYF(0));
while (!(read_record_info.read_record(&read_record_info)))
@@ -1672,6 +1658,7 @@ static bool acl_load(THD *thd, TABLE_LIST *tables)
return_val= FALSE;
end:
+ end_read_record(&read_record_info);
thd->variables.sql_mode= old_sql_mode;
DBUG_RETURN(return_val);
}
@@ -1688,12 +1675,12 @@ void acl_free(bool end)
delete_dynamic(&acl_proxy_users);
my_hash_free(&acl_check_hosts);
my_hash_free(&acl_roles_mappings);
- plugin_unlock(0, native_password_plugin);
- plugin_unlock(0, old_password_plugin);
if (!end)
acl_cache->clear(1); /* purecov: inspected */
else
{
+ plugin_unlock(0, native_password_plugin);
+ plugin_unlock(0, old_password_plugin);
delete acl_cache;
acl_cache=0;
}
@@ -1755,6 +1742,15 @@ bool acl_reload(THD *thd)
old_acl_roles_mappings= acl_roles_mappings;
old_acl_proxy_users= acl_proxy_users;
old_acl_dbs= acl_dbs;
+ my_init_dynamic_array(&acl_hosts, sizeof(ACL_HOST), 20, 50, MYF(0));
+ my_init_dynamic_array(&acl_users, sizeof(ACL_USER), 50, 100, MYF(0));
+ my_init_dynamic_array(&acl_dbs, sizeof(ACL_DB), 50, 100, MYF(0));
+ my_init_dynamic_array(&acl_proxy_users, sizeof(ACL_PROXY_USER), 50, 100, MYF(0));
+ my_hash_init2(&acl_roles,50, &my_charset_utf8_bin,
+ 0, 0, 0, (my_hash_get_key) acl_role_get_key, 0,
+ (void (*)(void *))free_acl_role, 0);
+ my_hash_init2(&acl_roles_mappings, 50, system_charset_info, 0, 0, 0,
+ (my_hash_get_key) acl_role_map_get_key, 0, 0, 0);
old_mem= acl_memroot;
delete_dynamic(&acl_wild_hosts);
my_hash_free(&acl_check_hosts);
@@ -3462,7 +3458,7 @@ static int replace_user_table(THD *thd, TABLE *table, LEX_USER &combo,
}
if (!old_row_exists || combo.pwtext.length || combo.pwhash.length)
- if (validate_password(&combo))
+ if (!handle_as_role && validate_password(&combo))
goto end;
/* Update table columns with new privileges */
@@ -7647,7 +7643,8 @@ ulong get_column_grant(THD *thd, GRANT_INFO *grant,
if (!grant_column)
priv|= (grant->privilege | grant_table_role->privs);
else
- priv|= (grant->privilege | grant_table->privs | grant_column->rights);
+ priv|= (grant->privilege | grant_table_role->privs |
+ grant_column->rights);
}
}
mysql_rwlock_unlock(&LOCK_grant);
@@ -7777,9 +7774,6 @@ bool mysql_show_grants(THD *thd, LEX_USER *lex_user)
DBUG_RETURN(TRUE);
}
- mysql_rwlock_rdlock(&LOCK_grant);
- mysql_mutex_lock(&acl_cache->lock);
-
if (lex_user->user.str == current_user.str)
{
username= thd->security_ctx->priv_user;
@@ -7797,23 +7791,28 @@ bool mysql_show_grants(THD *thd, LEX_USER *lex_user)
}
else
{
- lex_user= get_current_user(thd, lex_user, false);
+ Security_context *sctx= thd->security_ctx;
+ bool do_check_access;
+
+ lex_user= get_current_user(thd, lex_user);
if (!lex_user)
- {
- mysql_mutex_unlock(&acl_cache->lock);
- mysql_rwlock_unlock(&LOCK_grant);
DBUG_RETURN(TRUE);
- }
if (lex_user->is_role())
{
rolename= lex_user->user.str;
+ do_check_access= strcmp(rolename, sctx->priv_role);
}
else
{
username= lex_user->user.str;
hostname= lex_user->host.str;
+ do_check_access= strcmp(username, sctx->priv_user) ||
+ strcmp(hostname, sctx->priv_host);
}
+
+ if (do_check_access && check_access(thd, SELECT_ACL, "mysql", 0, 0, 1, 0))
+ DBUG_RETURN(TRUE);
}
DBUG_ASSERT(rolename || username);
@@ -7826,14 +7825,11 @@ bool mysql_show_grants(THD *thd, LEX_USER *lex_user)
mysql_show_grants_get_fields(thd, &field_list, buff);
if (protocol->send_result_set_metadata(&field_list,
- Protocol::SEND_NUM_ROWS |
- Protocol::SEND_EOF))
- {
- mysql_mutex_unlock(&acl_cache->lock);
- mysql_rwlock_unlock(&LOCK_grant);
-
+ Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
DBUG_RETURN(TRUE);
- }
+
+ mysql_rwlock_rdlock(&LOCK_grant);
+ mysql_mutex_lock(&acl_cache->lock);
if (username)
{
diff --git a/sql/sql_admin.cc b/sql/sql_admin.cc
index f27cdcc41f2..b974075b442 100644
--- a/sql/sql_admin.cc
+++ b/sql/sql_admin.cc
@@ -381,9 +381,13 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
To allow concurrent execution of read-only operations we acquire
weak metadata lock for them.
*/
- table->mdl_request.set_type((lock_type >= TL_WRITE_ALLOW_WRITE) ?
- MDL_SHARED_NO_READ_WRITE : MDL_SHARED_READ);
+ table->mdl_request.set_type(lex->sql_command == SQLCOM_REPAIR
+ ? MDL_SHARED_NO_READ_WRITE
+ : lock_type >= TL_WRITE_ALLOW_WRITE
+ ? MDL_SHARED_WRITE : MDL_SHARED_READ);
+
/* open only one table from local list of command */
+ while (1)
{
TABLE_LIST *save_next_global, *save_next_local;
save_next_global= table->next_global;
@@ -483,6 +487,20 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
result_code= HA_ADMIN_FAILED;
goto send_result;
}
+
+ if (!table->table || table->mdl_request.type != MDL_SHARED_WRITE ||
+ table->table->file->ha_table_flags() & HA_CONCURRENT_OPTIMIZE)
+ break;
+
+ trans_rollback_stmt(thd);
+ trans_rollback(thd);
+ close_thread_tables(thd);
+ table->table= NULL;
+ thd->mdl_context.release_transactional_locks();
+ table->mdl_request.init(MDL_key::TABLE, table->db, table->table_name,
+ MDL_SHARED_NO_READ_WRITE, MDL_TRANSACTION);
+ }
+
#ifdef WITH_PARTITION_STORAGE_ENGINE
if (table->table)
{
@@ -521,7 +539,6 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
}
}
#endif
- }
DBUG_PRINT("admin", ("table: 0x%lx", (long) table->table));
if (prepare_func)
@@ -622,18 +639,18 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
/*
Close all instances of the table to allow MyISAM "repair"
- to rename files.
+ (which is internally also used from "optimize") to rename files.
@todo: This code does not close all instances of the table.
It only closes instances in other connections, but if this
connection has LOCK TABLE t1 a READ, t1 b WRITE,
both t1 instances will be kept open.
- There is no need to execute this branch for InnoDB, which does
- repair by recreate. There is no need to do it for OPTIMIZE,
- which doesn't move files around.
- Hence, this code should be moved to prepare_for_repair(),
- and executed only for MyISAM engine.
+
+ Note that this code is only executed for engines that request
+ MDL_SHARED_NO_READ_WRITE lock (MDL_SHARED_WRITE cannot be upgraded)
+ by *not* having HA_CONCURRENT_OPTIMIZE table_flag.
*/
- if (lock_type == TL_WRITE && !table->table->s->tmp_table)
+ if (lock_type == TL_WRITE && !table->table->s->tmp_table &&
+ table->mdl_request.type > MDL_SHARED_WRITE)
{
if (wait_while_table_is_used(thd, table->table,
HA_EXTRA_PREPARE_FOR_RENAME))
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 236b68586d5..16773ab3018 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -1973,46 +1973,63 @@ bool THD::notify_shared_lock(MDL_context_owner *ctx_in_use,
{
THD *in_use= ctx_in_use->get_thd();
bool signalled= FALSE;
+ DBUG_ENTER("THD::notify_shared_lock");
+ DBUG_PRINT("enter",("needs_thr_lock_abort: %d", needs_thr_lock_abort));
if ((in_use->system_thread & SYSTEM_THREAD_DELAYED_INSERT) &&
!in_use->killed)
{
- in_use->killed= KILL_CONNECTION;
- mysql_mutex_lock(&in_use->mysys_var->mutex);
- if (in_use->mysys_var->current_cond)
- mysql_cond_broadcast(in_use->mysys_var->current_cond);
- mysql_mutex_unlock(&in_use->mysys_var->mutex);
+ /* This code is similar to kill_delayed_threads() */
+ DBUG_PRINT("info", ("kill delayed thread"));
+ mysql_mutex_lock(&in_use->LOCK_thd_data);
+ if (in_use->killed < KILL_CONNECTION)
+ in_use->killed= KILL_CONNECTION;
+ if (in_use->mysys_var)
+ {
+ mysql_mutex_lock(&in_use->mysys_var->mutex);
+ if (in_use->mysys_var->current_cond)
+ mysql_cond_broadcast(in_use->mysys_var->current_cond);
+
+ /* Abort if about to wait in thr_upgrade_write_delay_lock */
+ in_use->mysys_var->abort= 1;
+ mysql_mutex_unlock(&in_use->mysys_var->mutex);
+ }
+ mysql_mutex_unlock(&in_use->LOCK_thd_data);
signalled= TRUE;
}
if (needs_thr_lock_abort)
{
mysql_mutex_lock(&in_use->LOCK_thd_data);
- for (TABLE *thd_table= in_use->open_tables;
- thd_table ;
- thd_table= thd_table->next)
+ /* If not already dying */
+ if (in_use->killed != KILL_CONNECTION_HARD)
{
- /*
- Check for TABLE::needs_reopen() is needed since in some places we call
- handler::close() for table instance (and set TABLE::db_stat to 0)
- and do not remove such instances from the THD::open_tables
- for some time, during which other thread can see those instances
- (e.g. see partitioning code).
- */
- if (!thd_table->needs_reopen())
+ for (TABLE *thd_table= in_use->open_tables;
+ thd_table ;
+ thd_table= thd_table->next)
{
- signalled|= mysql_lock_abort_for_thread(this, thd_table);
- if (this && WSREP(this) && wsrep_thd_is_BF(this, FALSE))
+ /*
+ Check for TABLE::needs_reopen() is needed since in some
+ places we call handler::close() for table instance (and set
+ TABLE::db_stat to 0) and do not remove such instances from
+ the THD::open_tables for some time, during which other
+ thread can see those instances (e.g. see partitioning code).
+ */
+ if (!thd_table->needs_reopen())
{
- WSREP_DEBUG("remove_table_from_cache: %llu",
- (unsigned long long) this->real_id);
- wsrep_abort_thd((void *)this, (void *)in_use, FALSE);
+ signalled|= mysql_lock_abort_for_thread(this, thd_table);
+ if (this && WSREP(this) && wsrep_thd_is_BF(this, FALSE))
+ {
+ WSREP_DEBUG("remove_table_from_cache: %llu",
+ (unsigned long long) this->real_id);
+ wsrep_abort_thd((void *)this, (void *)in_use, FALSE);
+ }
}
}
}
mysql_mutex_unlock(&in_use->LOCK_thd_data);
}
- return signalled;
+ DBUG_RETURN(signalled);
}
diff --git a/sql/sql_class.h b/sql/sql_class.h
index e1127f77c09..8bfc243977f 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -1,5 +1,5 @@
/*
- Copyright (c) 2000, 2015, Oracle and/or its affiliates.
+ Copyright (c) 2000, 2016, Oracle and/or its affiliates.
Copyright (c) 2009, 2016, MariaDB
This program is free software; you can redistribute it and/or modify
@@ -2193,6 +2193,18 @@ public:
current_stmt_binlog_format == BINLOG_FORMAT_ROW);
return current_stmt_binlog_format == BINLOG_FORMAT_ROW;
}
+ /**
+ Determine if binlogging is disabled for this session
+ @retval 0 if the current statement binlogging is disabled
+ (could be because of binlog closed/binlog option
+ is set to false).
+ @retval 1 if the current statement will be binlogged
+ */
+ inline bool is_current_stmt_binlog_disabled() const
+ {
+ return (!(variables.option_bits & OPTION_BIN_LOG) ||
+ !mysql_bin_log.is_open());
+ }
enum binlog_filter_state
{
diff --git a/sql/sql_connect.cc b/sql/sql_connect.cc
index 7821b96b9bb..80ac420937a 100644
--- a/sql/sql_connect.cc
+++ b/sql/sql_connect.cc
@@ -1165,7 +1165,8 @@ void end_connection(THD *thd)
}
if (!thd->killed && (net->error && net->vio != 0))
- thd->print_aborted_warning(1, ER_THD(thd, ER_UNKNOWN_ERROR));
+ thd->print_aborted_warning(1, thd->get_stmt_da()->is_error()
+ ? thd->get_stmt_da()->message() : ER_THD(thd, ER_UNKNOWN_ERROR));
}
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index 9b4238b513d..fcf8c143ec4 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -1,6 +1,6 @@
/*
- Copyright (c) 2000, 2015, Oracle and/or its affiliates.
- Copyright (c) 2010, 2015, MariaDB
+ Copyright (c) 2000, 2016, Oracle and/or its affiliates.
+ Copyright (c) 2010, 2016, MariaDB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -1623,9 +1623,10 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
else
table->file->insert_id_for_cur_row= insert_id_for_cur_row;
bool is_duplicate_key_error;
- if (table->file->is_fatal_error(error, HA_CHECK_DUP))
+ if (table->file->is_fatal_error(error, HA_CHECK_ALL))
goto err;
- is_duplicate_key_error= table->file->is_fatal_error(error, 0);
+ is_duplicate_key_error=
+ table->file->is_fatal_error(error, HA_CHECK_ALL & ~HA_CHECK_DUP);
if (!is_duplicate_key_error)
{
/*
@@ -1752,7 +1753,7 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
error != HA_ERR_RECORD_IS_THE_SAME)
{
if (info->ignore &&
- !table->file->is_fatal_error(error, HA_CHECK_DUP_KEY))
+ !table->file->is_fatal_error(error, HA_CHECK_ALL))
{
if (!(thd->variables.old_behavior &
OLD_MODE_NO_DUP_KEY_WARNINGS_WITH_IGNORE))
@@ -1882,7 +1883,7 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
{
DEBUG_SYNC(thd, "write_row_noreplace");
if (!info->ignore ||
- table->file->is_fatal_error(error, HA_CHECK_DUP))
+ table->file->is_fatal_error(error, HA_CHECK_ALL))
goto err;
if (!(thd->variables.old_behavior &
OLD_MODE_NO_DUP_KEY_WARNINGS_WITH_IGNORE))
@@ -2012,7 +2013,7 @@ public:
TABLE *table;
mysql_mutex_t mutex;
mysql_cond_t cond, cond_client;
- volatile uint tables_in_use,stacked_inserts;
+ uint tables_in_use, stacked_inserts;
volatile bool status;
bool retry;
/**
@@ -2663,14 +2664,16 @@ static void end_delayed_insert(THD *thd)
void kill_delayed_threads(void)
{
+ DBUG_ENTER("kill_delayed_threads");
mysql_mutex_lock(&LOCK_delayed_insert); // For unlink from list
I_List_iterator<Delayed_insert> it(delayed_threads);
Delayed_insert *di;
while ((di= it++))
{
- di->thd.killed= KILL_CONNECTION;
mysql_mutex_lock(&di->thd.LOCK_thd_data);
+ if (di->thd.killed < KILL_CONNECTION)
+ di->thd.killed= KILL_CONNECTION;
if (di->thd.mysys_var)
{
mysql_mutex_lock(&di->thd.mysys_var->mutex);
@@ -2691,6 +2694,7 @@ void kill_delayed_threads(void)
mysql_mutex_unlock(&di->thd.LOCK_thd_data);
}
mysql_mutex_unlock(&LOCK_delayed_insert); // For unlink from list
+ DBUG_VOID_RETURN;
}
@@ -2895,6 +2899,12 @@ pthread_handler_t handle_delayed_insert(void *arg)
/* Tell client that the thread is initialized */
mysql_cond_signal(&di->cond_client);
+ /*
+ Inform mdl that it needs to call mysql_lock_abort to abort locks
+ for delayed insert.
+ */
+ thd->mdl_context.set_needs_thr_lock_abort(TRUE);
+
di->table->mark_columns_needed_for_insert();
/* Now wait until we get an insert or lock to handle */
@@ -2905,6 +2915,7 @@ pthread_handler_t handle_delayed_insert(void *arg)
if (thd->killed)
{
uint lock_count;
+ DBUG_PRINT("delayed", ("Insert delayed killed"));
/*
Remove this from delay insert list so that no one can request a
table from this
@@ -2915,11 +2926,15 @@ pthread_handler_t handle_delayed_insert(void *arg)
lock_count=di->lock_count();
mysql_mutex_unlock(&LOCK_delayed_insert);
mysql_mutex_lock(&di->mutex);
- if (!lock_count && !di->tables_in_use && !di->stacked_inserts)
+ if (!lock_count && !di->tables_in_use && !di->stacked_inserts &&
+ !thd->lock)
break; // Time to die
}
/* Shouldn't wait if killed or an insert is waiting. */
+ DBUG_PRINT("delayed",
+ ("thd->killed: %d di->status: %d di->stacked_inserts: %d",
+ thd->killed, di->status, di->stacked_inserts));
if (!thd->killed && !di->status && !di->stacked_inserts)
{
struct timespec abstime;
@@ -2959,6 +2974,9 @@ pthread_handler_t handle_delayed_insert(void *arg)
mysql_mutex_unlock(&di->thd.mysys_var->mutex);
mysql_mutex_lock(&di->mutex);
}
+ DBUG_PRINT("delayed",
+ ("thd->killed: %d di->tables_in_use: %d thd->lock: %d",
+ thd->killed, di->tables_in_use, thd->lock != 0));
if (di->tables_in_use && ! thd->lock && !thd->killed)
{
@@ -3019,9 +3037,19 @@ pthread_handler_t handle_delayed_insert(void *arg)
{
DBUG_ENTER("handle_delayed_insert-cleanup");
di->table=0;
- thd->killed= KILL_CONNECTION; // If error
mysql_mutex_unlock(&di->mutex);
+ /*
+ Protect against mdl_locks trying to access open tables
+ We use KILL_CONNECTION_HARD here to ensure that
+ THD::notify_shared_lock() dosn't try to access open tables after
+ this.
+ */
+ mysql_mutex_lock(&thd->LOCK_thd_data);
+ thd->killed= KILL_CONNECTION_HARD; // If error
+ thd->mdl_context.set_needs_thr_lock_abort(0);
+ mysql_mutex_unlock(&thd->LOCK_thd_data);
+
close_thread_tables(thd); // Free the table
thd->mdl_context.release_transactional_locks();
mysql_cond_broadcast(&di->cond_client); // Safety
diff --git a/sql/sql_load.cc b/sql/sql_load.cc
index e102066c0bc..4e6d91b9c1f 100644
--- a/sql/sql_load.cc
+++ b/sql/sql_load.cc
@@ -1,6 +1,6 @@
/*
- Copyright (c) 2000, 2015, Oracle and/or its affiliates.
- Copyright (c) 2010, 2015, MariaDB
+ Copyright (c) 2000, 2016, Oracle and/or its affiliates.
+ Copyright (c) 2010, 2016, MariaDB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -240,6 +240,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
{
DBUG_RETURN(TRUE);
}
+ thd_proc_info(thd, "executing");
/*
Let us emit an error if we are loading data to table which is used
in subselect in SET clause like we do it for INSERT.
diff --git a/sql/sql_locale.cc b/sql/sql_locale.cc
index 5ac069de98b..58443a9a977 100644
--- a/sql/sql_locale.cc
+++ b/sql/sql_locale.cc
@@ -427,7 +427,7 @@ MY_LOCALE my_locale_da_DK
/***** LOCALE BEGIN de_AT: German - Austria *****/
static const char *my_locale_month_names_de_AT[13] =
- {"Jänner","Feber","März","April","Mai","Juni","Juli","August","September","Oktober","November","Dezember", NullS };
+ {"Jänner","Februar","März","April","Mai","Juni","Juli","August","September","Oktober","November","Dezember", NullS };
static const char *my_locale_ab_month_names_de_AT[13] =
{"Jän","Feb","Mär","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez", NullS };
static const char *my_locale_day_names_de_AT[8] =
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 4c8bb05cc39..3c0bf523c2c 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -4939,21 +4939,10 @@ end_with_restore_list:
case SQLCOM_SHOW_GRANTS:
{
LEX_USER *grant_user= lex->grant_user;
- Security_context *sctx= thd->security_ctx;
if (!grant_user)
goto error;
- if (grant_user->user.str && !strcmp(sctx->priv_user, grant_user->user.str) &&
- grant_user->host.str && !strcmp(sctx->priv_host, grant_user->host.str))
- grant_user->user= current_user;
-
- if (grant_user->user.str == current_user.str ||
- grant_user->user.str == current_role.str ||
- grant_user->user.str == current_user_and_current_role.str ||
- !check_access(thd, SELECT_ACL, "mysql", NULL, NULL, 1, 0))
- {
- res = mysql_show_grants(thd, grant_user);
- }
+ res = mysql_show_grants(thd, grant_user);
break;
}
#endif
@@ -6653,6 +6642,7 @@ bool check_global_access(THD *thd, ulong want_access, bool no_errors)
temporary table flag)
@param alter_info [in] Initial list of columns and indexes for the
table to be created
+ @param create_db [in] Database of the created table
@retval
false ok.
@@ -6661,7 +6651,8 @@ bool check_global_access(THD *thd, ulong want_access, bool no_errors)
*/
bool check_fk_parent_table_access(THD *thd,
HA_CREATE_INFO *create_info,
- Alter_info *alter_info)
+ Alter_info *alter_info,
+ const char* create_db)
{
Key *key;
List_iterator<Key> key_iterator(alter_info->key_list);
@@ -6701,10 +6692,28 @@ bool check_fk_parent_table_access(THD *thd,
return true;
}
}
- else if (thd->lex->copy_db_to(&db_name.str, &db_name.length))
- return true;
else
- is_qualified_table_name= false;
+ {
+ if (!thd->db)
+ {
+ db_name.str= (char *) thd->memdup(create_db, strlen(create_db)+1);
+ db_name.length= strlen(create_db);
+ is_qualified_table_name= true;
+
+ if(create_db && check_db_name(&db_name))
+ {
+ my_error(ER_WRONG_DB_NAME, MYF(0), db_name.str);
+ return true;
+ }
+ }
+ else
+ {
+ if (thd->lex->copy_db_to(&db_name.str, &db_name.length))
+ return true;
+ else
+ is_qualified_table_name= false;
+ }
+ }
// if lower_case_table_names is set then convert tablename to lower case.
if (lower_case_table_names)
@@ -8855,7 +8864,7 @@ bool create_table_precheck(THD *thd, TABLE_LIST *tables,
goto err;
}
- if (check_fk_parent_table_access(thd, &lex->create_info, &lex->alter_info))
+ if (check_fk_parent_table_access(thd, &lex->create_info, &lex->alter_info, create_table->db))
goto err;
/*
diff --git a/sql/sql_parse.h b/sql/sql_parse.h
index c3c47567cf5..7a67df55ac3 100644
--- a/sql/sql_parse.h
+++ b/sql/sql_parse.h
@@ -48,7 +48,8 @@ bool create_table_precheck(THD *thd, TABLE_LIST *tables,
TABLE_LIST *create_table);
bool check_fk_parent_table_access(THD *thd,
HA_CREATE_INFO *create_info,
- Alter_info *alter_info);
+ Alter_info *alter_info,
+ const char* create_db);
bool parse_sql(THD *thd, Parser_state *parser_state,
Object_creation_ctx *creation_ctx, bool do_pfs_digest=false);
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index e83f63d1070..9de597eb0e3 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2000, 2015 Oracle and/or its affiliates.
+/* Copyright (c) 2000, 2016 Oracle and/or its affiliates.
Copyright (c) 2009, 2016 MariaDB
This program is free software; you can redistribute it and/or modify
@@ -15821,6 +15821,14 @@ static Field *create_tmp_field_from_item(THD *thd, Item *item, TABLE *table,
Field *UNINIT_VAR(new_field);
MEM_ROOT *mem_root= thd->mem_root;
+ /*
+ To preserve type or DATE/TIME and GEOMETRY fields,
+ they need to be handled separately.
+ */
+ if (item->cmp_type() == TIME_RESULT ||
+ item->field_type() == MYSQL_TYPE_GEOMETRY)
+ new_field= item->tmp_table_field_from_field_type(table, true, false);
+ else
switch (item->result_type()) {
case REAL_RESULT:
new_field= new (mem_root)
@@ -15845,16 +15853,7 @@ static Field *create_tmp_field_from_item(THD *thd, Item *item, TABLE *table,
break;
case STRING_RESULT:
DBUG_ASSERT(item->collation.collation);
-
- /*
- DATE/TIME and GEOMETRY fields have STRING_RESULT result type.
- To preserve type they needed to be handled separately.
- */
- if (item->cmp_type() == TIME_RESULT ||
- item->field_type() == MYSQL_TYPE_GEOMETRY)
- new_field= item->tmp_table_field_from_field_type(table, true, false);
- else
- new_field= item->make_string_field(table);
+ new_field= item->make_string_field(table);
new_field->set_derivation(item->collation.derivation);
break;
case DECIMAL_RESULT:
@@ -24658,33 +24657,53 @@ static void print_join(THD *thd,
/* List is reversed => we should reverse it before using */
List_iterator_fast<TABLE_LIST> ti(*tables);
TABLE_LIST **table;
- uint non_const_tables= 0;
DBUG_ENTER("print_join");
+ /*
+ If the QT_NO_DATA_EXPANSION flag is specified, we print the
+ original table list, including constant tables that have been
+ optimized away, as the constant tables may be referenced in the
+ expression printed by Item_field::print() when this flag is given.
+ Otherwise, only non-const tables are printed.
+
+ Example:
+
+ Original SQL:
+ select * from (select 1) t
+
+ Printed without QT_NO_DATA_EXPANSION:
+ select '1' AS `1` from dual
+
+ Printed with QT_NO_DATA_EXPANSION:
+ select `t`.`1` from (select 1 AS `1`) `t`
+ */
+ const bool print_const_tables= (query_type & QT_NO_DATA_EXPANSION);
+ size_t tables_to_print= 0;
+
for (TABLE_LIST *t= ti++; t ; t= ti++)
{
- /*
- See comment in print_table_array() about the second part of the
- condition
- */
- if (!t->optimized_away && !is_eliminated_table(eliminated_tables, t))
- non_const_tables++;
+ /* See comment in print_table_array() about the second condition */
+ if (print_const_tables || !t->optimized_away)
+ if (!is_eliminated_table(eliminated_tables, t))
+ tables_to_print++;
}
- if (!non_const_tables)
+ if (tables_to_print == 0)
{
str->append(STRING_WITH_LEN("dual"));
DBUG_VOID_RETURN; // all tables were optimized away
}
ti.rewind();
- if (!(table= (TABLE_LIST **)thd->alloc(sizeof(TABLE_LIST*) *
- non_const_tables)))
+ if (!(table= static_cast<TABLE_LIST **>(thd->alloc(sizeof(TABLE_LIST*) *
+ tables_to_print))))
DBUG_VOID_RETURN; // out of memory
- TABLE_LIST *tmp, **t= table + (non_const_tables - 1);
+ TABLE_LIST *tmp, **t= table + (tables_to_print - 1);
while ((tmp= ti++))
{
- if (tmp->optimized_away || is_eliminated_table(eliminated_tables, tmp))
+ if (tmp->optimized_away && !print_const_tables)
+ continue;
+ if (is_eliminated_table(eliminated_tables, tmp))
continue;
*t--= tmp;
}
@@ -24704,7 +24723,7 @@ static void print_join(THD *thd,
*/
if ((*table)->sj_inner_tables)
{
- TABLE_LIST **end= table + non_const_tables;
+ TABLE_LIST **end= table + tables_to_print;
for (TABLE_LIST **t2= table; t2!=end; t2++)
{
if (!(*t2)->sj_inner_tables)
@@ -24717,7 +24736,7 @@ static void print_join(THD *thd,
}
}
print_table_array(thd, eliminated_tables, str, table,
- table + non_const_tables, query_type);
+ table + tables_to_print, query_type);
DBUG_VOID_RETURN;
}
@@ -25132,7 +25151,7 @@ void JOIN::save_query_plan(Join_plan_state *save_to)
}
memcpy((uchar*) save_to->best_positions, (uchar*) best_positions,
sizeof(POSITION) * (table_count + 1));
- memset(best_positions, 0, sizeof(POSITION) * (table_count + 1));
+ memset((uchar*) best_positions, 0, sizeof(POSITION) * (table_count + 1));
/* Save SJM nests */
List_iterator<TABLE_LIST> it(select_lex->sj_nests);
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index dfce503e314..337fb06d4e4 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -1,5 +1,5 @@
/*
- Copyright (c) 2000, 2015, Oracle and/or its affiliates.
+ Copyright (c) 2000, 2016, Oracle and/or its affiliates.
Copyright (c) 2010, 2016, MariaDB
This program is free software; you can redistribute it and/or modify
@@ -5422,6 +5422,9 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table,
/*
We have to write the query before we unlock the tables.
*/
+ if (thd->is_current_stmt_binlog_disabled())
+ goto err;
+
if (thd->is_current_stmt_binlog_format_row())
{
/*
@@ -5492,6 +5495,21 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table,
*/
if (!table->view)
{
+ /*
+ After opening a MERGE table add the children to the query list of
+ tables, so that children tables info can be used on "CREATE TABLE"
+ statement generation by the binary log.
+ Note that placeholders don't have the handler open.
+ */
+ if (table->table->file->extra(HA_EXTRA_ADD_CHILDREN_LIST))
+ goto err;
+
+ /*
+ As the reference table is temporary and may not exist on slave, we must
+ force the ENGINE to be present into CREATE TABLE.
+ */
+ create_info->used_fields|= HA_CREATE_USED_ENGINE;
+
int result __attribute__((unused))=
show_create_table(thd, table, &query, create_info, WITH_DB_NAME);
@@ -8479,7 +8497,7 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
till this point for the alter operation.
*/
if ((alter_info->flags & Alter_info::ADD_FOREIGN_KEY) &&
- check_fk_parent_table_access(thd, create_info, alter_info))
+ check_fk_parent_table_access(thd, create_info, alter_info, new_db))
DBUG_RETURN(true);
/*
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index 43038ba9321..3c0827bb164 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -1,5 +1,5 @@
-/* Copyright (c) 2000, 2013, Oracle and/or its affiliates.
- Copyright (c) 2011, 2015, MariaDB
+/* Copyright (c) 2000, 2016, Oracle and/or its affiliates.
+ Copyright (c) 2011, 2016, MariaDB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -838,7 +838,7 @@ int mysql_update(THD *thd,
error= 0;
}
else if (!ignore ||
- table->file->is_fatal_error(error, HA_CHECK_DUP_KEY))
+ table->file->is_fatal_error(error, HA_CHECK_ALL))
{
/*
If (ignore && error is ignorable) we don't have to
@@ -846,7 +846,7 @@ int mysql_update(THD *thd,
*/
myf flags= 0;
- if (table->file->is_fatal_error(error, HA_CHECK_DUP_KEY))
+ if (table->file->is_fatal_error(error, HA_CHECK_ALL))
flags|= ME_FATALERROR; /* Other handler errors are fatal */
prepare_record_for_error_message(error, table);
@@ -2167,7 +2167,7 @@ int multi_update::send_data(List<Item> &not_used_values)
{
updated--;
if (!ignore ||
- table->file->is_fatal_error(error, HA_CHECK_DUP_KEY))
+ table->file->is_fatal_error(error, HA_CHECK_ALL))
{
/*
If (ignore && error == is ignorable) we don't have to
@@ -2175,7 +2175,7 @@ int multi_update::send_data(List<Item> &not_used_values)
*/
myf flags= 0;
- if (table->file->is_fatal_error(error, HA_CHECK_DUP_KEY))
+ if (table->file->is_fatal_error(error, HA_CHECK_ALL))
flags|= ME_FATALERROR; /* Other handler errors are fatal */
prepare_record_for_error_message(error, table);
@@ -2452,7 +2452,7 @@ int multi_update::do_updates()
local_error != HA_ERR_RECORD_IS_THE_SAME)
{
if (!ignore ||
- table->file->is_fatal_error(local_error, HA_CHECK_DUP_KEY))
+ table->file->is_fatal_error(local_error, HA_CHECK_ALL))
{
err_table= table;
goto err;
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 24dc3c44b0f..e614692bd70 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -99,6 +99,9 @@ int yylex(void *yylval, void *yythd);
MYSQL_YYABORT; \
}
+#define my_yyabort_error(A) \
+ do { my_error A; MYSQL_YYABORT; } while(0)
+
#ifndef DBUG_OFF
#define YYDEBUG 1
#else
@@ -2024,10 +2027,8 @@ query:
{
if (!thd->bootstrap &&
(!(thd->lex->select_lex.options & OPTION_FOUND_COMMENT)))
- {
- my_message(ER_EMPTY_QUERY, ER_THD(thd, ER_EMPTY_QUERY), MYF(0));
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_EMPTY_QUERY, MYF(0)));
+
thd->lex->sql_command= SQLCOM_EMPTY_QUERY;
YYLIP->found_semicolon= NULL;
}
@@ -2210,10 +2211,7 @@ help:
HELP_SYM
{
if (Lex->sphead)
- {
- my_error(ER_SP_BADSTATEMENT, MYF(0), "HELP");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SP_BADSTATEMENT, MYF(0), "HELP"));
}
ident_or_text
{
@@ -2304,13 +2302,9 @@ master_def:
Lex->mi.heartbeat_period= (float) $3->val_real();
if (Lex->mi.heartbeat_period > SLAVE_MAX_HEARTBEAT_PERIOD ||
Lex->mi.heartbeat_period < 0.0)
- {
- const char format[]= "%d";
- char buf[4*sizeof(SLAVE_MAX_HEARTBEAT_PERIOD) + sizeof(format)];
- sprintf(buf, format, SLAVE_MAX_HEARTBEAT_PERIOD);
- my_error(ER_SLAVE_HEARTBEAT_VALUE_OUT_OF_RANGE, MYF(0), buf);
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SLAVE_HEARTBEAT_VALUE_OUT_OF_RANGE, MYF(0),
+ SLAVE_MAX_HEARTBEAT_PERIOD));
+
if (Lex->mi.heartbeat_period > slave_net_timeout)
{
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
@@ -2418,28 +2412,19 @@ master_file_def:
| MASTER_USE_GTID_SYM EQ CURRENT_POS_SYM
{
if (Lex->mi.use_gtid_opt != LEX_MASTER_INFO::LEX_GTID_UNCHANGED)
- {
- my_error(ER_DUP_ARGUMENT, MYF(0), "MASTER_use_gtid");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "MASTER_use_gtid"));
Lex->mi.use_gtid_opt= LEX_MASTER_INFO::LEX_GTID_CURRENT_POS;
}
| MASTER_USE_GTID_SYM EQ SLAVE_POS_SYM
{
if (Lex->mi.use_gtid_opt != LEX_MASTER_INFO::LEX_GTID_UNCHANGED)
- {
- my_error(ER_DUP_ARGUMENT, MYF(0), "MASTER_use_gtid");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "MASTER_use_gtid"));
Lex->mi.use_gtid_opt= LEX_MASTER_INFO::LEX_GTID_SLAVE_POS;
}
| MASTER_USE_GTID_SYM EQ NO_SYM
{
if (Lex->mi.use_gtid_opt != LEX_MASTER_INFO::LEX_GTID_UNCHANGED)
- {
- my_error(ER_DUP_ARGUMENT, MYF(0), "MASTER_use_gtid");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "MASTER_use_gtid"));
Lex->mi.use_gtid_opt= LEX_MASTER_INFO::LEX_GTID_NO;
}
;
@@ -2459,10 +2444,7 @@ connection_name:
Lex->mi.connection_name= $1;
#ifdef HAVE_REPLICATION
if (check_master_connection_name(&$1))
- {
- my_error(ER_WRONG_ARGUMENTS, MYF(0), "MASTER_CONNECTION_NAME");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_WRONG_ARGUMENTS, MYF(0), "MASTER_CONNECTION_NAME"));
#endif
}
;
@@ -2772,10 +2754,7 @@ ev_sql_stmt:
- CREATE PROCEDURE ... BEGIN DROP EVENT ... END|
*/
if (lex->sphead)
- {
- my_error(ER_EVENT_RECURSION_FORBIDDEN, MYF(0));
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_EVENT_RECURSION_FORBIDDEN, MYF(0)));
if (!make_sp_head(thd, lex->event_parse_data->identifier, TYPE_ENUM_PROCEDURE))
MYSQL_YYABORT;
@@ -2814,14 +2793,9 @@ sp_name:
ident '.' ident
{
if (!$1.str || check_db_name(&$1))
- {
- my_error(ER_WRONG_DB_NAME, MYF(0), $1.str);
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_WRONG_DB_NAME, MYF(0), $1.str));
if (check_routine_name(&$3))
- {
MYSQL_YYABORT;
- }
$$= new (thd->mem_root) sp_name($1, $3, true);
if ($$ == NULL)
MYSQL_YYABORT;
@@ -2837,7 +2811,7 @@ sp_name:
}
if (lex->copy_db_to(&db.str, &db.length))
MYSQL_YYABORT;
- $$= new (lex->thd->mem_root) sp_name(db, $1, false);
+ $$= new (thd->mem_root) sp_name(db, $1, false);
if ($$ == NULL)
MYSQL_YYABORT;
$$->init_qname(thd);
@@ -2942,10 +2916,7 @@ sp_param_name_and_type:
sp_pcontext *spc= lex->spcont;
if (spc->find_variable($1, TRUE))
- {
- my_error(ER_SP_DUP_PARAM, MYF(0), $1.str);
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SP_DUP_PARAM, MYF(0), $1.str));
sp_variable *spvar= spc->add_variable(thd, $1);
@@ -3015,17 +2986,9 @@ sp_decls:
shift/reduce conflicts with the wrong result. (And we get
better error handling this way.) */
if (($2.vars || $2.conds) && ($1.curs || $1.hndlrs))
- { /* Variable or condition following cursor or handler */
- my_message(ER_SP_VARCOND_AFTER_CURSHNDLR,
- ER_THD(thd, ER_SP_VARCOND_AFTER_CURSHNDLR), MYF(0));
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SP_VARCOND_AFTER_CURSHNDLR, MYF(0)));
if ($2.curs && $1.hndlrs)
- { /* Cursor following handler */
- my_message(ER_SP_CURSOR_AFTER_HANDLER,
- ER_THD(thd, ER_SP_CURSOR_AFTER_HANDLER), MYF(0));
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SP_CURSOR_AFTER_HANDLER, MYF(0)));
$$.vars= $1.vars + $2.vars;
$$.conds= $1.conds + $2.conds;
$$.hndlrs= $1.hndlrs + $2.hndlrs;
@@ -3092,16 +3055,11 @@ sp_decl:
/* The last instruction is responsible for freeing LEX. */
- sp_instr_set *is= (new (lex->thd->mem_root)
- sp_instr_set(lex->sphead->instructions(),
- pctx,
- var_idx,
- dflt_value_item,
- var_type,
- lex,
- last));
- if (is == NULL ||
- lex->sphead->add_instr(is))
+ sp_instr_set *is= new (thd->mem_root)
+ sp_instr_set(lex->sphead->instructions(),
+ pctx, var_idx, dflt_value_item,
+ var_type, lex, last);
+ if (is == NULL || lex->sphead->add_instr(is))
MYSQL_YYABORT;
}
@@ -3117,10 +3075,7 @@ sp_decl:
sp_pcontext *spc= lex->spcont;
if (spc->find_condition($2, TRUE))
- {
- my_error(ER_SP_DUP_COND, MYF(0), $2.str);
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SP_DUP_COND, MYF(0), $2.str));
if(spc->add_condition(thd, $2, $5))
MYSQL_YYABORT;
$$.vars= $$.hndlrs= $$.curs= 0;
@@ -3139,7 +3094,7 @@ sp_decl:
sp_pcontext *ctx= lex->spcont;
sp_instr_hpush_jump *i=
- new (lex->thd->mem_root) sp_instr_hpush_jump(sp->instructions(),
+ new (thd->mem_root) sp_instr_hpush_jump(sp->instructions(),
ctx, h);
if (i == NULL || sp->add_instr(i))
@@ -3163,7 +3118,7 @@ sp_decl:
if ($2 == sp_handler::CONTINUE)
{
- i= new (lex->thd->mem_root)
+ i= new (thd->mem_root)
sp_instr_hreturn(sp->instructions(), ctx);
if (i == NULL ||
sp->add_instr(i))
@@ -3171,7 +3126,7 @@ sp_decl:
}
else
{ /* EXIT or UNDO handler, just jump to the end of the block */
- i= new (lex->thd->mem_root)
+ i= new (thd->mem_root)
sp_instr_hreturn(sp->instructions(), ctx);
if (i == NULL ||
sp->add_instr(i) ||
@@ -3194,17 +3149,12 @@ sp_decl:
sp_instr_cpush *i;
if (ctx->find_cursor($2, &offp, TRUE))
- {
- my_error(ER_SP_DUP_CURS, MYF(0), $2.str);
- delete $5;
- MYSQL_YYABORT;
- }
- i= new (lex->thd->mem_root)
- sp_instr_cpush(sp->instructions(), ctx, $5,
- ctx->current_cursor_count());
- if (i == NULL ||
- sp->add_instr(i) ||
- ctx->add_cursor($2))
+ my_yyabort_error((ER_SP_DUP_CURS, MYF(0), $2.str));
+
+ i= new (thd->mem_root)
+ sp_instr_cpush(sp->instructions(), ctx, $5,
+ ctx->current_cursor_count());
+ if (i == NULL || sp->add_instr(i) || ctx->add_cursor($2))
MYSQL_YYABORT;
$$.vars= $$.conds= $$.hndlrs= 0;
$$.curs= 1;
@@ -3222,11 +3172,7 @@ sp_cursor_stmt:
DBUG_ASSERT(lex->sql_command == SQLCOM_SELECT);
if (lex->result)
- {
- my_message(ER_SP_BAD_CURSOR_SELECT, ER_THD(thd, ER_SP_BAD_CURSOR_SELECT),
- MYF(0));
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SP_BAD_CURSOR_SELECT, MYF(0)));
lex->sp_lex_in_use= TRUE;
$$= lex;
if (lex->sphead->restore_lex(thd))
@@ -3255,17 +3201,10 @@ sp_hcond_element:
sp_pcontext *ctx= lex->spcont->parent_context();
if (ctx->check_duplicate_handler($1))
- {
- my_message(ER_SP_DUP_HANDLER, ER_THD(thd, ER_SP_DUP_HANDLER), MYF(0));
- MYSQL_YYABORT;
- }
- else
- {
- sp_instr_hpush_jump *i=
- (sp_instr_hpush_jump *)sp->last_instruction();
+ my_yyabort_error((ER_SP_DUP_HANDLER, MYF(0)));
- i->add_condition($1);
- }
+ sp_instr_hpush_jump *i= (sp_instr_hpush_jump *)sp->last_instruction();
+ i->add_condition($1);
}
;
@@ -3273,10 +3212,7 @@ sp_cond:
ulong_num
{ /* mysql errno */
if ($1 == 0)
- {
- my_error(ER_WRONG_VALUE, MYF(0), "CONDITION", "0");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_WRONG_VALUE, MYF(0), "CONDITION", "0"));
$$= new (thd->mem_root) sp_condition_value($1);
if ($$ == NULL)
MYSQL_YYABORT;
@@ -3296,10 +3232,7 @@ sqlstate:
condition.
*/
if (!is_sqlstate_valid(&$3) || is_sqlstate_completion($3.str))
- {
- my_error(ER_SP_BAD_SQLSTATE, MYF(0), $3.str);
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SP_BAD_SQLSTATE, MYF(0), $3.str));
$$= new (thd->mem_root) sp_condition_value($3.str);
if ($$ == NULL)
MYSQL_YYABORT;
@@ -3320,10 +3253,7 @@ sp_hcond:
{
$$= Lex->spcont->find_condition($1, false);
if ($$ == NULL)
- {
- my_error(ER_SP_COND_MISMATCH, MYF(0), $1.str);
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SP_COND_MISMATCH, MYF(0), $1.str));
}
| SQLWARNING_SYM /* SQLSTATEs 01??? */
{
@@ -3364,23 +3294,15 @@ signal_value:
{
LEX *lex= Lex;
sp_condition_value *cond;
+
+ /* SIGNAL foo cannot be used outside of stored programs */
if (lex->spcont == NULL)
- {
- /* SIGNAL foo cannot be used outside of stored programs */
- my_error(ER_SP_COND_MISMATCH, MYF(0), $1.str);
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SP_COND_MISMATCH, MYF(0), $1.str));
cond= lex->spcont->find_condition($1, false);
if (cond == NULL)
- {
- my_error(ER_SP_COND_MISMATCH, MYF(0), $1.str);
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SP_COND_MISMATCH, MYF(0), $1.str));
if (cond->type != sp_condition_value::SQLSTATE)
- {
- my_error(ER_SIGNAL_BAD_CONDITION_TYPE, MYF(0));
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SIGNAL_BAD_CONDITION_TYPE, MYF(0)));
$$= cond;
}
| sqlstate
@@ -3418,11 +3340,8 @@ signal_information_item_list:
info= &thd->m_parser_state->m_yacc.m_set_signal_info;
int index= (int) $3;
if (info->m_item[index] != NULL)
- {
- my_error(ER_DUP_SIGNAL_SET, MYF(0),
- Diag_condition_item_names[index].str);
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_DUP_SIGNAL_SET, MYF(0),
+ Diag_condition_item_names[index].str));
info->m_item[index]= $5;
}
;
@@ -3653,10 +3572,7 @@ sp_decl_idents:
sp_pcontext *spc= lex->spcont;
if (spc->find_variable($1, TRUE))
- {
- my_error(ER_SP_DUP_VAR, MYF(0), $1.str);
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SP_DUP_VAR, MYF(0), $1.str));
spc->add_variable(thd, $1);
$$= 1;
}
@@ -3668,10 +3584,7 @@ sp_decl_idents:
sp_pcontext *spc= lex->spcont;
if (spc->find_variable($3, TRUE))
- {
- my_error(ER_SP_DUP_VAR, MYF(0), $3.str);
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SP_DUP_VAR, MYF(0), $3.str));
spc->add_variable(thd, $3);
$$= $1 + 1;
}
@@ -3729,11 +3642,9 @@ sp_proc_stmt_statement:
sp_head *sp= lex->sphead;
sp->m_flags|= sp_get_flags_for_command(lex);
+ /* "USE db" doesn't work in a procedure */
if (lex->sql_command == SQLCOM_CHANGE_DB)
- { /* "USE db" doesn't work in a procedure */
- my_error(ER_SP_BADSTATEMENT, MYF(0), "USE");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SP_BADSTATEMENT, MYF(0), "USE"));
/*
Don't add an instruction for SET statements, since all
instructions for them were already added during processing
@@ -3743,7 +3654,7 @@ sp_proc_stmt_statement:
lex->var_list.is_empty());
if (lex->sql_command != SQLCOM_SET_OPTION)
{
- sp_instr_stmt *i=new (lex->thd->mem_root)
+ sp_instr_stmt *i=new (thd->mem_root)
sp_instr_stmt(sp->instructions(), lex->spcont, lex);
if (i == NULL)
MYSQL_YYABORT;
@@ -3777,22 +3688,17 @@ sp_proc_stmt_return:
sp_head *sp= lex->sphead;
if (sp->m_type != TYPE_ENUM_FUNCTION)
- {
- my_message(ER_SP_BADRETURN, ER_THD(thd, ER_SP_BADRETURN), MYF(0));
- MYSQL_YYABORT;
- }
- else
- {
- sp_instr_freturn *i;
+ my_yyabort_error((ER_SP_BADRETURN, MYF(0)));
+
+ sp_instr_freturn *i;
- i= new (lex->thd->mem_root)
+ i= new (thd->mem_root)
sp_instr_freturn(sp->instructions(), lex->spcont, $3,
sp->m_return_field_def.sql_type, lex);
- if (i == NULL ||
- sp->add_instr(i))
- MYSQL_YYABORT;
- sp->m_flags|= sp_head::HAS_RETURN;
- }
+ if (i == NULL || sp->add_instr(i))
+ MYSQL_YYABORT;
+ sp->m_flags|= sp_head::HAS_RETURN;
+
if (sp->restore_lex(thd))
MYSQL_YYABORT;
}
@@ -3807,49 +3713,44 @@ sp_proc_stmt_leave:
sp_label *lab= ctx->find_label($2);
if (! lab)
+ my_yyabort_error((ER_SP_LILABEL_MISMATCH, MYF(0), "LEAVE", $2.str));
+
+ sp_instr_jump *i;
+ uint ip= sp->instructions();
+ uint n;
+ /*
+ When jumping to a BEGIN-END block end, the target jump
+ points to the block hpop/cpop cleanup instructions,
+ so we should exclude the block context here.
+ When jumping to something else (i.e., SP_LAB_ITER),
+ there are no hpop/cpop at the jump destination,
+ so we should include the block context here for cleanup.
+ */
+ bool exclusive= (lab->type == sp_label::BEGIN);
+
+ n= ctx->diff_handlers(lab->ctx, exclusive);
+ if (n)
{
- my_error(ER_SP_LILABEL_MISMATCH, MYF(0), "LEAVE", $2.str);
- MYSQL_YYABORT;
+ sp_instr_hpop *hpop= new (thd->mem_root)
+ sp_instr_hpop(ip++, ctx, n);
+ if (hpop == NULL)
+ MYSQL_YYABORT;
+ sp->add_instr(hpop);
}
- else
+ n= ctx->diff_cursors(lab->ctx, exclusive);
+ if (n)
{
- sp_instr_jump *i;
- uint ip= sp->instructions();
- uint n;
- /*
- When jumping to a BEGIN-END block end, the target jump
- points to the block hpop/cpop cleanup instructions,
- so we should exclude the block context here.
- When jumping to something else (i.e., SP_LAB_ITER),
- there are no hpop/cpop at the jump destination,
- so we should include the block context here for cleanup.
- */
- bool exclusive= (lab->type == sp_label::BEGIN);
-
- n= ctx->diff_handlers(lab->ctx, exclusive);
- if (n)
- {
- sp_instr_hpop *hpop= new (lex->thd->mem_root)
- sp_instr_hpop(ip++, ctx, n);
- if (hpop == NULL)
- MYSQL_YYABORT;
- sp->add_instr(hpop);
- }
- n= ctx->diff_cursors(lab->ctx, exclusive);
- if (n)
- {
- sp_instr_cpop *cpop= new (lex->thd->mem_root)
- sp_instr_cpop(ip++, ctx, n);
- if (cpop == NULL)
- MYSQL_YYABORT;
- sp->add_instr(cpop);
- }
- i= new (lex->thd->mem_root) sp_instr_jump(ip, ctx);
- if (i == NULL)
+ sp_instr_cpop *cpop= new (thd->mem_root)
+ sp_instr_cpop(ip++, ctx, n);
+ if (cpop == NULL)
MYSQL_YYABORT;
- sp->push_backpatch(i, lab); /* Jumping forward */
- sp->add_instr(i);
+ sp->add_instr(cpop);
}
+ i= new (thd->mem_root) sp_instr_jump(ip, ctx);
+ if (i == NULL)
+ MYSQL_YYABORT;
+ sp->push_backpatch(i, lab); /* Jumping forward */
+ sp->add_instr(i);
}
;
@@ -3862,40 +3763,35 @@ sp_proc_stmt_iterate:
sp_label *lab= ctx->find_label($2);
if (! lab || lab->type != sp_label::ITERATION)
+ my_yyabort_error((ER_SP_LILABEL_MISMATCH, MYF(0), "ITERATE", $2.str));
+
+ sp_instr_jump *i;
+ uint ip= sp->instructions();
+ uint n;
+
+ n= ctx->diff_handlers(lab->ctx, FALSE); /* Inclusive the dest. */
+ if (n)
{
- my_error(ER_SP_LILABEL_MISMATCH, MYF(0), "ITERATE", $2.str);
- MYSQL_YYABORT;
+ sp_instr_hpop *hpop= new (thd->mem_root)
+ sp_instr_hpop(ip++, ctx, n);
+ if (hpop == NULL ||
+ sp->add_instr(hpop))
+ MYSQL_YYABORT;
}
- else
+ n= ctx->diff_cursors(lab->ctx, FALSE); /* Inclusive the dest. */
+ if (n)
{
- sp_instr_jump *i;
- uint ip= sp->instructions();
- uint n;
-
- n= ctx->diff_handlers(lab->ctx, FALSE); /* Inclusive the dest. */
- if (n)
- {
- sp_instr_hpop *hpop= new (lex->thd->mem_root)
- sp_instr_hpop(ip++, ctx, n);
- if (hpop == NULL ||
- sp->add_instr(hpop))
- MYSQL_YYABORT;
- }
- n= ctx->diff_cursors(lab->ctx, FALSE); /* Inclusive the dest. */
- if (n)
- {
- sp_instr_cpop *cpop= new (lex->thd->mem_root)
- sp_instr_cpop(ip++, ctx, n);
- if (cpop == NULL ||
- sp->add_instr(cpop))
- MYSQL_YYABORT;
- }
- i= new (lex->thd->mem_root)
- sp_instr_jump(ip, ctx, lab->ip); /* Jump back */
- if (i == NULL ||
- sp->add_instr(i))
+ sp_instr_cpop *cpop= new (thd->mem_root)
+ sp_instr_cpop(ip++, ctx, n);
+ if (cpop == NULL ||
+ sp->add_instr(cpop))
MYSQL_YYABORT;
}
+ i= new (thd->mem_root)
+ sp_instr_jump(ip, ctx, lab->ip); /* Jump back */
+ if (i == NULL ||
+ sp->add_instr(i))
+ MYSQL_YYABORT;
}
;
@@ -3908,11 +3804,8 @@ sp_proc_stmt_open:
sp_instr_copen *i;
if (! lex->spcont->find_cursor($2, &offset, false))
- {
- my_error(ER_SP_CURSOR_MISMATCH, MYF(0), $2.str);
- MYSQL_YYABORT;
- }
- i= new (lex->thd->mem_root)
+ my_yyabort_error((ER_SP_CURSOR_MISMATCH, MYF(0), $2.str));
+ i= new (thd->mem_root)
sp_instr_copen(sp->instructions(), lex->spcont, offset);
if (i == NULL ||
sp->add_instr(i))
@@ -3929,11 +3822,8 @@ sp_proc_stmt_fetch:
sp_instr_cfetch *i;
if (! lex->spcont->find_cursor($3, &offset, false))
- {
- my_error(ER_SP_CURSOR_MISMATCH, MYF(0), $3.str);
- MYSQL_YYABORT;
- }
- i= new (lex->thd->mem_root)
+ my_yyabort_error((ER_SP_CURSOR_MISMATCH, MYF(0), $3.str));
+ i= new (thd->mem_root)
sp_instr_cfetch(sp->instructions(), lex->spcont, offset);
if (i == NULL ||
sp->add_instr(i))
@@ -3952,11 +3842,8 @@ sp_proc_stmt_close:
sp_instr_cclose *i;
if (! lex->spcont->find_cursor($2, &offset, false))
- {
- my_error(ER_SP_CURSOR_MISMATCH, MYF(0), $2.str);
- MYSQL_YYABORT;
- }
- i= new (lex->thd->mem_root)
+ my_yyabort_error((ER_SP_CURSOR_MISMATCH, MYF(0), $2.str));
+ i= new (thd->mem_root)
sp_instr_cclose(sp->instructions(), lex->spcont, offset);
if (i == NULL ||
sp->add_instr(i))
@@ -3979,17 +3866,11 @@ sp_fetch_list:
sp_variable *spv;
if (!spc || !(spv = spc->find_variable($1, false)))
- {
- my_error(ER_SP_UNDECLARED_VAR, MYF(0), $1.str);
- MYSQL_YYABORT;
- }
- else
- {
- /* An SP local variable */
- sp_instr_cfetch *i= (sp_instr_cfetch *)sp->last_instruction();
+ my_yyabort_error((ER_SP_UNDECLARED_VAR, MYF(0), $1.str));
- i->add_to_varlist(spv);
- }
+ /* An SP local variable */
+ sp_instr_cfetch *i= (sp_instr_cfetch *)sp->last_instruction();
+ i->add_to_varlist(spv);
}
| sp_fetch_list ',' ident
{
@@ -3999,17 +3880,11 @@ sp_fetch_list:
sp_variable *spv;
if (!spc || !(spv = spc->find_variable($3, false)))
- {
- my_error(ER_SP_UNDECLARED_VAR, MYF(0), $3.str);
- MYSQL_YYABORT;
- }
- else
- {
- /* An SP local variable */
- sp_instr_cfetch *i= (sp_instr_cfetch *)sp->last_instruction();
+ my_yyabort_error((ER_SP_UNDECLARED_VAR, MYF(0), $3.str));
- i->add_to_varlist(spv);
- }
+ /* An SP local variable */
+ sp_instr_cfetch *i= (sp_instr_cfetch *)sp->last_instruction();
+ i->add_to_varlist(spv);
}
;
@@ -4021,7 +3896,7 @@ sp_if:
sp_head *sp= lex->sphead;
sp_pcontext *ctx= lex->spcont;
uint ip= sp->instructions();
- sp_instr_jump_if_not *i= new (lex->thd->mem_root)
+ sp_instr_jump_if_not *i= new (thd->mem_root)
sp_instr_jump_if_not(ip, ctx, $2, lex);
if (i == NULL ||
sp->push_backpatch(i, ctx->push_label(thd, empty_lex_str, 0)) ||
@@ -4229,10 +4104,7 @@ sp_labeled_block:
sp_label *lab= ctx->find_label($1);
if (lab)
- {
- my_error(ER_SP_LABEL_REDEFINE, MYF(0), $1.str);
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SP_LABEL_REDEFINE, MYF(0), $1.str));
lex->name= $1;
}
sp_block_content sp_opt_label
@@ -4240,10 +4112,7 @@ sp_labeled_block:
if ($6.str)
{
if (my_strcasecmp(system_charset_info, $6.str, $5->name.str) != 0)
- {
- my_error(ER_SP_LABEL_MISMATCH, MYF(0), $6.str);
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SP_LABEL_MISMATCH, MYF(0), $6.str));
}
}
;
@@ -4297,7 +4166,7 @@ sp_block_content:
}
if ($2.curs)
{
- i= new (lex->thd->mem_root)
+ i= new (thd->mem_root)
sp_instr_cpop(sp->instructions(), ctx, $2.curs);
if (i == NULL ||
sp->add_instr(i))
@@ -4314,7 +4183,7 @@ loop_body:
LEX *lex= Lex;
uint ip= lex->sphead->instructions();
sp_label *lab= lex->spcont->last_label(); /* Jumping back */
- sp_instr_jump *i= new (lex->thd->mem_root)
+ sp_instr_jump *i= new (thd->mem_root)
sp_instr_jump(ip, lex->spcont, lab->ip);
if (i == NULL ||
lex->sphead->add_instr(i))
@@ -4328,7 +4197,7 @@ while_body:
LEX *lex= Lex;
sp_head *sp= lex->sphead;
uint ip= sp->instructions();
- sp_instr_jump_if_not *i= new (lex->thd->mem_root)
+ sp_instr_jump_if_not *i= new (thd->mem_root)
sp_instr_jump_if_not(ip, lex->spcont, $1, lex);
if (i == NULL ||
/* Jumping forward */
@@ -4344,7 +4213,7 @@ while_body:
LEX *lex= Lex;
uint ip= lex->sphead->instructions();
sp_label *lab= lex->spcont->last_label(); /* Jumping back */
- sp_instr_jump *i= new (lex->thd->mem_root)
+ sp_instr_jump *i= new (thd->mem_root)
sp_instr_jump(ip, lex->spcont, lab->ip);
if (i == NULL ||
lex->sphead->add_instr(i))
@@ -4361,7 +4230,7 @@ repeat_body:
LEX *lex= Lex;
uint ip= lex->sphead->instructions();
sp_label *lab= lex->spcont->last_label(); /* Jumping back */
- sp_instr_jump_if_not *i= new (lex->thd->mem_root)
+ sp_instr_jump_if_not *i= new (thd->mem_root)
sp_instr_jump_if_not(ip, lex->spcont, $4, lab->ip, lex);
if (i == NULL ||
lex->sphead->add_instr(i))
@@ -4382,10 +4251,7 @@ pop_sp_label:
{
if (my_strcasecmp(system_charset_info, $1.str,
lab->name.str) != 0)
- {
- my_error(ER_SP_LABEL_MISMATCH, MYF(0), $1.str);
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SP_LABEL_MISMATCH, MYF(0), $1.str));
}
}
;
@@ -4752,10 +4618,7 @@ opt_ts_nodegroup:
{
LEX *lex= Lex;
if (lex->alter_tablespace_info->nodegroup_id != UNDEF_NODEGROUP)
- {
- my_error(ER_FILEGROUP_OPTION_ONLY_ONCE,MYF(0),"NODEGROUP");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_FILEGROUP_OPTION_ONLY_ONCE,MYF(0),"NODEGROUP"));
lex->alter_tablespace_info->nodegroup_id= $3;
}
;
@@ -4765,10 +4628,7 @@ opt_ts_comment:
{
LEX *lex= Lex;
if (lex->alter_tablespace_info->ts_comment != NULL)
- {
- my_error(ER_FILEGROUP_OPTION_ONLY_ONCE,MYF(0),"COMMENT");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_FILEGROUP_OPTION_ONLY_ONCE,MYF(0),"COMMENT"));
lex->alter_tablespace_info->ts_comment= $3.str;
}
;
@@ -4778,11 +4638,8 @@ opt_ts_engine:
{
LEX *lex= Lex;
if (lex->alter_tablespace_info->storage_engine != NULL)
- {
- my_error(ER_FILEGROUP_OPTION_ONLY_ONCE,MYF(0),
- "STORAGE ENGINE");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_FILEGROUP_OPTION_ONLY_ONCE, MYF(0),
+ "STORAGE ENGINE"));
lex->alter_tablespace_info->storage_engine= $4;
}
;
@@ -4802,10 +4659,7 @@ ts_wait:
{
LEX *lex= Lex;
if (!(lex->alter_tablespace_info->wait_until_completed))
- {
- my_error(ER_FILEGROUP_OPTION_ONLY_ONCE,MYF(0),"NO_WAIT");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_FILEGROUP_OPTION_ONLY_ONCE,MYF(0),"NO_WAIT"));
lex->alter_tablespace_info->wait_until_completed= FALSE;
}
;
@@ -4837,23 +4691,14 @@ size_number:
text_shift_number+=10;
break;
default:
- {
- my_error(ER_WRONG_SIZE_NUMBER, MYF(0));
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_WRONG_SIZE_NUMBER, MYF(0)));
}
if (prefix_number >> 31)
- {
- my_error(ER_SIZE_OVERFLOW_ERROR, MYF(0));
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SIZE_OVERFLOW_ERROR, MYF(0)));
number= prefix_number << text_shift_number;
}
else
- {
- my_error(ER_WRONG_SIZE_NUMBER, MYF(0));
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_WRONG_SIZE_NUMBER, MYF(0)));
$$= number;
}
;
@@ -4967,15 +4812,11 @@ have_partitioning:
#ifdef WITH_PARTITION_STORAGE_ENGINE
LEX_STRING partition_name={C_STRING_WITH_LEN("partition")};
if (!plugin_is_ready(&partition_name, MYSQL_STORAGE_ENGINE_PLUGIN))
- {
- my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0),
- "--skip-partition");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_OPTION_PREVENTS_STATEMENT, MYF(0),
+ "--skip-partition"));
#else
- my_error(ER_FEATURE_DISABLED, MYF(0), "partitioning",
- "--with-plugin-partition");
- MYSQL_YYABORT;
+ my_yyabort_error((ER_FEATURE_DISABLED, MYF(0), "partitioning",
+ "--with-plugin-partition"));
#endif
}
;
@@ -5068,11 +4909,8 @@ part_field_item:
MYSQL_YYABORT;
}
if (part_info->num_columns > MAX_REF_PARTS)
- {
- my_error(ER_TOO_MANY_PARTITION_FUNC_FIELDS_ERROR, MYF(0),
- "list of partition fields");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_TOO_MANY_PARTITION_FUNC_FIELDS_ERROR, MYF(0),
+ "list of partition fields"));
}
;
@@ -5113,10 +4951,7 @@ opt_num_parts:
uint num_parts= $2;
partition_info *part_info= Lex->part_info;
if (num_parts == 0)
- {
- my_error(ER_NO_PARTS_ERROR, MYF(0), "partitions");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_NO_PARTS_ERROR, MYF(0), "partitions"));
part_info->num_parts= num_parts;
part_info->use_default_num_partitions= FALSE;
@@ -5153,11 +4988,8 @@ sub_part_field_item:
MYSQL_YYABORT;
}
if (part_info->subpart_field_list.elements > MAX_REF_PARTS)
- {
- my_error(ER_TOO_MANY_PARTITION_FUNC_FIELDS_ERROR, MYF(0),
- "list of subpartition fields");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_TOO_MANY_PARTITION_FUNC_FIELDS_ERROR, MYF(0),
+ "list of subpartition fields"));
}
;
@@ -5184,10 +5016,7 @@ opt_num_subparts:
uint num_parts= $2;
LEX *lex= Lex;
if (num_parts == 0)
- {
- my_error(ER_NO_PARTS_ERROR, MYF(0), "subpartitions");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_NO_PARTS_ERROR, MYF(0), "subpartitions"));
lex->part_info->num_subparts= num_parts;
lex->part_info->use_default_num_subpartitions= FALSE;
}
@@ -5198,17 +5027,11 @@ part_defs:
{
partition_info *part_info= Lex->part_info;
if (part_info->part_type == RANGE_PARTITION)
- {
- my_error(ER_PARTITIONS_MUST_BE_DEFINED_ERROR, MYF(0),
- "RANGE");
- MYSQL_YYABORT;
- }
- else if (part_info->part_type == LIST_PARTITION)
- {
- my_error(ER_PARTITIONS_MUST_BE_DEFINED_ERROR, MYF(0),
- "LIST");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_PARTITIONS_MUST_BE_DEFINED_ERROR, MYF(0),
+ "RANGE"));
+ if (part_info->part_type == LIST_PARTITION)
+ my_yyabort_error((ER_PARTITIONS_MUST_BE_DEFINED_ERROR, MYF(0),
+ "LIST"));
}
| '(' part_def_list ')'
{
@@ -5278,17 +5101,11 @@ opt_part_values:
if (! lex->is_partition_management())
{
if (part_info->part_type == RANGE_PARTITION)
- {
- my_error(ER_PARTITION_REQUIRES_VALUES_ERROR, MYF(0),
- "RANGE", "LESS THAN");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_PARTITION_REQUIRES_VALUES_ERROR, MYF(0),
+ "RANGE", "LESS THAN"));
if (part_info->part_type == LIST_PARTITION)
- {
- my_error(ER_PARTITION_REQUIRES_VALUES_ERROR, MYF(0),
- "LIST", "IN");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_PARTITION_REQUIRES_VALUES_ERROR, MYF(0),
+ "LIST", "IN"));
}
else
part_info->part_type= HASH_PARTITION;
@@ -5300,11 +5117,8 @@ opt_part_values:
if (! lex->is_partition_management())
{
if (part_info->part_type != RANGE_PARTITION)
- {
- my_error(ER_PARTITION_WRONG_VALUES_ERROR, MYF(0),
- "RANGE", "LESS THAN");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_PARTITION_WRONG_VALUES_ERROR, MYF(0),
+ "RANGE", "LESS THAN"));
}
else
part_info->part_type= RANGE_PARTITION;
@@ -5317,11 +5131,8 @@ opt_part_values:
if (! lex->is_partition_management())
{
if (part_info->part_type != LIST_PARTITION)
- {
- my_error(ER_PARTITION_WRONG_VALUES_ERROR, MYF(0),
- "LIST", "IN");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_PARTITION_WRONG_VALUES_ERROR, MYF(0),
+ "LIST", "IN"));
}
else
part_info->part_type= LIST_PARTITION;
@@ -5919,12 +5730,16 @@ create_table_option:
}
| IDENT_sys equal TEXT_STRING_sys
{
+ if ($3.length > ENGINE_OPTION_MAX_LENGTH)
+ my_yyabort_error((ER_VALUE_TOO_LONG, MYF(0), $1.str));
new (thd->mem_root)
engine_option_value($1, $3, true, &Lex->create_info.option_list,
&Lex->option_list_last);
}
| IDENT_sys equal ident
{
+ if ($3.length > ENGINE_OPTION_MAX_LENGTH)
+ my_yyabort_error((ER_VALUE_TOO_LONG, MYF(0), $1.str));
new (thd->mem_root)
engine_option_value($1, $3, false, &Lex->create_info.option_list,
&Lex->option_list_last);
@@ -5979,10 +5794,7 @@ storage_engines:
else
{
if (thd->variables.sql_mode & MODE_NO_ENGINE_SUBSTITUTION)
- {
- my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0), $1.str);
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_UNKNOWN_STORAGE_ENGINE, MYF(0), $1.str));
$$= 0;
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
ER_UNKNOWN_STORAGE_ENGINE,
@@ -5999,10 +5811,7 @@ known_storage_engines:
if ((plugin= ha_resolve_by_name(thd, &$1, false)))
$$= plugin_hton(plugin);
else
- {
- my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0), $1.str);
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_UNKNOWN_STORAGE_ENGINE, MYF(0), $1.str));
}
;
@@ -6162,10 +5971,7 @@ field_spec:
if (check_string_char_length(&$1, 0, NAME_CHAR_LEN,
system_charset_info, 1))
- {
- my_error(ER_TOO_LONG_IDENT, MYF(0), $1.str);
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_TOO_LONG_IDENT, MYF(0), $1.str));
if (!f)
MYSQL_YYABORT;
@@ -6252,10 +6058,7 @@ parse_vcol_expr:
Prevent the end user from invoking this command.
*/
if (!Lex->parse_vcol_expr)
- {
- my_message(ER_SYNTAX_ERROR, ER_THD(thd, ER_SYNTAX_ERROR), MYF(0));
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SYNTAX_ERROR, MYF(0)));
}
;
@@ -6287,12 +6090,9 @@ field_type:
int err;
ulonglong tmp_length= my_strtoll10(Lex->length, NULL, &err);
if (err || tmp_length > PRECISION_FOR_DOUBLE)
- {
- my_error(ER_WRONG_FIELD_SPEC, MYF(0),
- Lex->last_field->field_name);
- MYSQL_YYABORT;
- }
- else if (tmp_length > PRECISION_FOR_FLOAT)
+ my_yyabort_error((ER_WRONG_FIELD_SPEC, MYF(0),
+ Lex->last_field->field_name));
+ if (tmp_length > PRECISION_FOR_FLOAT)
$$= MYSQL_TYPE_DOUBLE;
Lex->length= 0;
}
@@ -6421,9 +6221,8 @@ field_type:
Lex->last_field->geom_type= $1;
$$=MYSQL_TYPE_GEOMETRY;
#else
- my_error(ER_FEATURE_DISABLED, MYF(0),
- sym_group_geom.name, sym_group_geom.needed_define);
- MYSQL_YYABORT;
+ my_yyabort_error((ER_FEATURE_DISABLED, MYF(0), sym_group_geom.name,
+ sym_group_geom.needed_define));
#endif
}
| MEDIUMBLOB
@@ -6639,24 +6438,22 @@ attribute:
| COLLATE_SYM collation_name
{
if (Lex->charset && !my_charset_same(Lex->charset,$2))
- {
- my_error(ER_COLLATION_CHARSET_MISMATCH, MYF(0),
- $2->name,Lex->charset->csname);
- MYSQL_YYABORT;
- }
- else
- {
- Lex->last_field->charset= $2;
- }
+ my_yyabort_error((ER_COLLATION_CHARSET_MISMATCH, MYF(0),
+ $2->name,Lex->charset->csname));
+ Lex->last_field->charset= $2;
}
| IDENT_sys equal TEXT_STRING_sys
{
+ if ($3.length > ENGINE_OPTION_MAX_LENGTH)
+ my_yyabort_error((ER_VALUE_TOO_LONG, MYF(0), $1.str));
new (thd->mem_root)
engine_option_value($1, $3, true, &Lex->last_field->option_list,
&Lex->option_list_last);
}
| IDENT_sys equal ident
{
+ if ($3.length > ENGINE_OPTION_MAX_LENGTH)
+ my_yyabort_error((ER_VALUE_TOO_LONG, MYF(0), $1.str));
new (thd->mem_root)
engine_option_value($1, $3, false, &Lex->last_field->option_list,
&Lex->option_list_last);
@@ -6710,10 +6507,7 @@ charset_name:
ident_or_text
{
if (!($$=get_charset_by_csname($1.str,MY_CS_PRIMARY,MYF(0))))
- {
- my_error(ER_UNKNOWN_CHARACTER_SET, MYF(0), $1.str);
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_UNKNOWN_CHARACTER_SET, MYF(0), $1.str));
}
| BINARY { $$= &my_charset_bin; }
;
@@ -6733,10 +6527,7 @@ old_or_new_charset_name:
{
if (!($$=get_charset_by_csname($1.str,MY_CS_PRIMARY,MYF(0))) &&
!($$=get_old_charset_by_name($1.str)))
- {
- my_error(ER_UNKNOWN_CHARACTER_SET, MYF(0), $1.str);
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_UNKNOWN_CHARACTER_SET, MYF(0), $1.str));
}
| BINARY { $$= &my_charset_bin; }
;
@@ -6775,10 +6566,7 @@ charset_or_alias:
| UNICODE_SYM
{
if (!($$= get_charset_by_csname("ucs2", MY_CS_PRIMARY,MYF(0))))
- {
- my_error(ER_UNKNOWN_CHARACTER_SET, MYF(0), "ucs2");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_UNKNOWN_CHARACTER_SET, MYF(0), "ucs2"));
}
;
@@ -6994,9 +6782,8 @@ spatial:
#ifdef HAVE_SPATIAL
$$= Key::SPATIAL;
#else
- my_error(ER_FEATURE_DISABLED, MYF(0),
- sym_group_geom.name, sym_group_geom.needed_define);
- MYSQL_YYABORT;
+ my_yyabort_error((ER_FEATURE_DISABLED, MYF(0), sym_group_geom.name,
+ sym_group_geom.needed_define));
#endif
}
;
@@ -7055,12 +6842,16 @@ all_key_opt:
{ Lex->last_key->key_create_info.comment= $2; }
| IDENT_sys equal TEXT_STRING_sys
{
+ if ($3.length > ENGINE_OPTION_MAX_LENGTH)
+ my_yyabort_error((ER_VALUE_TOO_LONG, MYF(0), $1.str));
new (thd->mem_root)
engine_option_value($1, $3, true, &Lex->option_list,
&Lex->option_list_last);
}
| IDENT_sys equal ident
{
+ if ($3.length > ENGINE_OPTION_MAX_LENGTH)
+ my_yyabort_error((ER_VALUE_TOO_LONG, MYF(0), $1.str));
new (thd->mem_root)
engine_option_value($1, $3, false, &Lex->option_list,
&Lex->option_list_last);
@@ -7094,10 +6885,7 @@ fulltext_key_opt:
if (plugin_is_ready(&$3, MYSQL_FTPARSER_PLUGIN))
Lex->last_key->key_create_info.parser_name= $3;
else
- {
- my_error(ER_FUNCTION_NOT_DEFINED, MYF(0), $3.str);
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_FUNCTION_NOT_DEFINED, MYF(0), $3.str));
}
;
@@ -7129,9 +6917,7 @@ key_part:
{
int key_part_len= atoi($3.str);
if (!key_part_len)
- {
- my_error(ER_KEY_PART_0, MYF(0), $1.str);
- }
+ my_yyabort_error((ER_KEY_PART_0, MYF(0), $1.str));
$$= new (thd->mem_root) Key_part_spec($1, (uint) key_part_len);
if ($$ == NULL)
MYSQL_YYABORT;
@@ -7211,10 +6997,7 @@ alter:
{
LEX *lex= Lex;
if (lex->sphead)
- {
- my_error(ER_SP_NO_DROP_SP, MYF(0), "DATABASE");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SP_NO_DROP_SP, MYF(0), "DATABASE"));
lex->sql_command= SQLCOM_ALTER_DB_UPGRADE;
lex->name= $3;
}
@@ -7223,10 +7006,7 @@ alter:
LEX *lex= Lex;
if (lex->sphead)
- {
- my_error(ER_SP_NO_DROP_SP, MYF(0), "PROCEDURE");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SP_NO_DROP_SP, MYF(0), "PROCEDURE"));
bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics));
}
sp_a_chistics
@@ -7241,10 +7021,7 @@ alter:
LEX *lex= Lex;
if (lex->sphead)
- {
- my_error(ER_SP_NO_DROP_SP, MYF(0), "FUNCTION");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SP_NO_DROP_SP, MYF(0), "FUNCTION"));
bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics));
}
sp_a_chistics
@@ -7259,10 +7036,7 @@ alter:
LEX *lex= Lex;
if (lex->sphead)
- {
- my_error(ER_SP_BADSTATEMENT, MYF(0), "ALTER VIEW");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SP_BADSTATEMENT, MYF(0), "ALTER VIEW"));
lex->create_view_mode= VIEW_ALTER;
}
view_tail
@@ -7277,10 +7051,7 @@ alter:
LEX *lex= Lex;
if (lex->sphead)
- {
- my_error(ER_SP_BADSTATEMENT, MYF(0), "ALTER VIEW");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SP_BADSTATEMENT, MYF(0), "ALTER VIEW"));
lex->create_view_algorithm= VIEW_ALGORITHM_INHERIT;
lex->create_view_mode= VIEW_ALTER;
}
@@ -7743,10 +7514,7 @@ alter_list_item:
}
if (check_table_name($3->table.str,$3->table.length, FALSE) ||
($3->db.str && check_db_name(&$3->db)))
- {
- my_error(ER_WRONG_TABLE_NAME, MYF(0), $3->table.str);
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_WRONG_TABLE_NAME, MYF(0), $3->table.str));
lex->name= $3->table;
lex->alter_info.flags|= Alter_info::ALTER_RENAME;
}
@@ -7758,15 +7526,11 @@ alter_list_item:
}
$5= $5 ? $5 : $4;
if (!my_charset_same($4,$5))
- {
- my_error(ER_COLLATION_CHARSET_MISMATCH, MYF(0),
- $5->name, $4->csname);
+ my_yyabort_error((ER_COLLATION_CHARSET_MISMATCH, MYF(0),
+ $5->name, $4->csname));
+ if (Lex->create_info.add_alter_list_item_convert_to_charset($5))
MYSQL_YYABORT;
- }
- LEX *lex= Lex;
- if (lex->create_info.add_alter_list_item_convert_to_charset($5))
- MYSQL_YYABORT;
- lex->alter_info.flags|= Alter_info::ALTER_CONVERT;
+ Lex->alter_info.flags|= Alter_info::ALTER_CONVERT;
}
| create_table_options_space_separated
{
@@ -7807,10 +7571,7 @@ alter_algorithm_option:
| ALGORITHM_SYM opt_equal ident
{
if (Lex->alter_info.set_requested_algorithm(&$3))
- {
- my_error(ER_UNKNOWN_ALTER_ALGORITHM, MYF(0), $3.str);
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_UNKNOWN_ALTER_ALGORITHM, MYF(0), $3.str));
}
;
@@ -7823,10 +7584,7 @@ alter_lock_option:
| LOCK_SYM opt_equal ident
{
if (Lex->alter_info.set_requested_lock(&$3))
- {
- my_error(ER_UNKNOWN_ALTER_LOCK, MYF(0), $3.str);
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_UNKNOWN_ALTER_LOCK, MYF(0), $3.str));
}
;
@@ -8002,11 +7760,7 @@ slave_until:
(lex->mi.relay_log_name || lex->mi.relay_log_pos)) ||
!((lex->mi.log_file_name && lex->mi.pos) ||
(lex->mi.relay_log_name && lex->mi.relay_log_pos)))
- {
- my_message(ER_BAD_SLAVE_UNTIL_COND,
- ER_THD(thd, ER_BAD_SLAVE_UNTIL_COND), MYF(0));
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_BAD_SLAVE_UNTIL_COND, MYF(0)));
}
| UNTIL_SYM MASTER_GTID_POS_SYM EQ TEXT_STRING_sys
{
@@ -8221,10 +7975,7 @@ check: CHECK_SYM
{
LEX* lex= thd->lex;
if (lex->sphead)
- {
- my_error(ER_SP_BADSTATEMENT, MYF(0), "CHECK");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SP_BADSTATEMENT, MYF(0), "CHECK"));
DBUG_ASSERT(!lex->m_sql_cmd);
lex->m_sql_cmd= new (thd->mem_root) Sql_cmd_check_table();
if (lex->m_sql_cmd == NULL)
@@ -8321,9 +8072,9 @@ table_to_table:
{
LEX *lex=Lex;
SELECT_LEX *sl= lex->current_select;
- if (!sl->add_table_to_list(lex->thd, $1,NULL,TL_OPTION_UPDATING,
+ if (!sl->add_table_to_list(thd, $1,NULL,TL_OPTION_UPDATING,
TL_IGNORE, MDL_EXCLUSIVE) ||
- !sl->add_table_to_list(lex->thd, $3,NULL,TL_OPTION_UPDATING,
+ !sl->add_table_to_list(thd, $3,NULL,TL_OPTION_UPDATING,
TL_IGNORE, MDL_EXCLUSIVE))
MYSQL_YYABORT;
}
@@ -8528,18 +8279,11 @@ select_part2:
opt_into
opt_select_lock_type
{
- if ($2 && $10)
- {
- /* double "INTO" clause */
- my_error(ER_WRONG_USAGE, MYF(0), "INTO", "INTO");
- MYSQL_YYABORT;
- }
- if ($9 && ($2 || $10))
- {
- /* "INTO" with "PROCEDURE ANALYSE" */
- my_error(ER_WRONG_USAGE, MYF(0), "PROCEDURE", "INTO");
- MYSQL_YYABORT;
- }
+ if ($2 && $10) /* double "INTO" clause */
+ my_yyabort_error((ER_WRONG_USAGE, MYF(0), "INTO", "INTO"));
+
+ if ($9 && ($2 || $10)) /* "INTO" with "PROCEDURE ANALYSE" */
+ my_yyabort_error((ER_WRONG_USAGE, MYF(0), "PROCEDURE", "INTO"));
}
;
@@ -8596,10 +8340,7 @@ select_options:
| select_option_list
{
if (Select->options & SELECT_DISTINCT && Select->options & SELECT_ALL)
- {
- my_error(ER_WRONG_USAGE, MYF(0), "ALL", "DISTINCT");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_WRONG_USAGE, MYF(0), "ALL", "DISTINCT"));
}
;
@@ -8617,26 +8358,15 @@ select_option:
SQL_CACHE wasn't specified, and only once per query.
*/
if (Lex->current_select != &Lex->select_lex)
- {
- my_error(ER_CANT_USE_OPTION_HERE, MYF(0), "SQL_NO_CACHE");
- MYSQL_YYABORT;
- }
- else if (Lex->select_lex.sql_cache == SELECT_LEX::SQL_CACHE)
- {
- my_error(ER_WRONG_USAGE, MYF(0), "SQL_CACHE", "SQL_NO_CACHE");
- MYSQL_YYABORT;
- }
- else if (Lex->select_lex.sql_cache == SELECT_LEX::SQL_NO_CACHE)
- {
- my_error(ER_DUP_ARGUMENT, MYF(0), "SQL_NO_CACHE");
- MYSQL_YYABORT;
- }
- else
- {
- Lex->safe_to_cache_query=0;
- Lex->select_lex.options&= ~OPTION_TO_QUERY_CACHE;
- Lex->select_lex.sql_cache= SELECT_LEX::SQL_NO_CACHE;
- }
+ my_yyabort_error((ER_CANT_USE_OPTION_HERE, MYF(0), "SQL_NO_CACHE"));
+ if (Lex->select_lex.sql_cache == SELECT_LEX::SQL_CACHE)
+ my_yyabort_error((ER_WRONG_USAGE, MYF(0), "SQL_CACHE", "SQL_NO_CACHE"));
+ if (Lex->select_lex.sql_cache == SELECT_LEX::SQL_NO_CACHE)
+ my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "SQL_NO_CACHE"));
+
+ Lex->safe_to_cache_query=0;
+ Lex->select_lex.options&= ~OPTION_TO_QUERY_CACHE;
+ Lex->select_lex.sql_cache= SELECT_LEX::SQL_NO_CACHE;
}
| SQL_CACHE_SYM
{
@@ -8645,26 +8375,15 @@ select_option:
SQL_NO_CACHE wasn't specified, and only once per query.
*/
if (Lex->current_select != &Lex->select_lex)
- {
- my_error(ER_CANT_USE_OPTION_HERE, MYF(0), "SQL_CACHE");
- MYSQL_YYABORT;
- }
- else if (Lex->select_lex.sql_cache == SELECT_LEX::SQL_NO_CACHE)
- {
- my_error(ER_WRONG_USAGE, MYF(0), "SQL_NO_CACHE", "SQL_CACHE");
- MYSQL_YYABORT;
- }
- else if (Lex->select_lex.sql_cache == SELECT_LEX::SQL_CACHE)
- {
- my_error(ER_DUP_ARGUMENT, MYF(0), "SQL_CACHE");
- MYSQL_YYABORT;
- }
- else
- {
- Lex->safe_to_cache_query=1;
- Lex->select_lex.options|= OPTION_TO_QUERY_CACHE;
- Lex->select_lex.sql_cache= SELECT_LEX::SQL_CACHE;
- }
+ my_yyabort_error((ER_CANT_USE_OPTION_HERE, MYF(0), "SQL_CACHE"));
+ if (Lex->select_lex.sql_cache == SELECT_LEX::SQL_NO_CACHE)
+ my_yyabort_error((ER_WRONG_USAGE, MYF(0), "SQL_NO_CACHE", "SQL_CACHE"));
+ if (Lex->select_lex.sql_cache == SELECT_LEX::SQL_CACHE)
+ my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "SQL_CACHE"));
+
+ Lex->safe_to_cache_query=1;
+ Lex->select_lex.options|= OPTION_TO_QUERY_CACHE;
+ Lex->select_lex.sql_cache= SELECT_LEX::SQL_CACHE;
}
;
@@ -8717,10 +8436,7 @@ select_item:
{
if (Lex->sql_command == SQLCOM_CREATE_VIEW &&
check_column_name($4.str))
- {
- my_error(ER_WRONG_COLUMN_NAME, MYF(0), $4.str);
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_WRONG_COLUMN_NAME, MYF(0), $4.str));
$2->is_autogenerated_name= FALSE;
$2->set_name($4.str, $4.length, system_charset_info);
}
@@ -9462,11 +9178,7 @@ simple_expr:
{
Item_splocal *il= $3->get_item_splocal();
if (il)
- {
-
- my_error(ER_WRONG_COLUMN_NAME, MYF(0), il->my_name()->str);
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_WRONG_COLUMN_NAME, MYF(0), il->my_name()->str));
$$= new (thd->mem_root) Item_default_value(thd, Lex->current_context(),
$3);
if ($$ == NULL)
@@ -10082,9 +9794,8 @@ function_call_conflict:
if ($$ == NULL)
MYSQL_YYABORT;
#else
- my_error(ER_FEATURE_DISABLED, MYF(0),
- sym_group_geom.name, sym_group_geom.needed_define);
- MYSQL_YYABORT;
+ my_yyabort_error((ER_FEATURE_DISABLED, MYF(0), sym_group_geom.name,
+ sym_group_geom.needed_define));
#endif
}
;
@@ -10246,10 +9957,7 @@ function_call_generic:
*/
if (!$1.str || check_db_name(&$1))
- {
- my_error(ER_WRONG_DB_NAME, MYF(0), $1.str);
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_WRONG_DB_NAME, MYF(0), $1.str));
if (check_routine_name(&$3))
{
MYSQL_YYABORT;
@@ -10473,10 +10181,7 @@ variable:
'@'
{
if (! Lex->parsing_options.allows_variable)
- {
- my_error(ER_VIEW_SELECT_VARIABLE, MYF(0));
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_VIEW_SELECT_VARIABLE, MYF(0)));
}
variable_aux
{
@@ -10543,9 +10248,8 @@ opt_gorder_clause:
sel->olap != UNSPECIFIED_OLAP_TYPE &&
(sel->linkage != UNION_TYPE || sel->braces))
{
- my_error(ER_WRONG_USAGE, MYF(0),
- "CUBE/ROLLUP", "ORDER BY");
- MYSQL_YYABORT;
+ my_yyabort_error((ER_WRONG_USAGE, MYF(0),
+ "CUBE/ROLLUP", "ORDER BY"));
}
}
gorder_list;
@@ -10689,7 +10393,7 @@ table_ref:
| join_table
{
LEX *lex= Lex;
- if (!($$= lex->current_select->nest_last_join(lex->thd)))
+ if (!($$= lex->current_select->nest_last_join(thd)))
{
my_parse_error(thd, ER_SYNTAX_ERROR);
MYSQL_YYABORT;
@@ -10913,7 +10617,7 @@ table_factor:
MYSQL_YYABORT;
}
}
- if ($2->init_nested_join(lex->thd))
+ if ($2->init_nested_join(thd))
MYSQL_YYABORT;
$$= 0;
/* incomplete derived tables return NULL, we must be
@@ -10962,7 +10666,7 @@ table_factor:
Table_ident *ti= new (thd->mem_root) Table_ident(unit);
if (ti == NULL)
MYSQL_YYABORT;
- if (!($$= sel->add_table_to_list(lex->thd,
+ if (!($$= sel->add_table_to_list(thd,
ti, $5, 0,
TL_READ, MDL_SHARED_READ)))
@@ -11085,17 +10789,15 @@ select_part2_derived:
select_derived:
get_select_lex
{
- LEX *lex= Lex;
- if ($1->init_nested_join(lex->thd))
+ if ($1->init_nested_join(thd))
MYSQL_YYABORT;
}
derived_table_list
{
- LEX *lex= Lex;
/* for normal joins, $3 != NULL and end_nested_join() != NULL,
for derived tables, both must equal NULL */
- if (!($$= $1->end_nested_join(lex->thd)) && $3)
+ if (!($$= $1->end_nested_join(thd)) && $3)
MYSQL_YYABORT;
if (!$3 && $$)
{
@@ -11139,14 +10841,11 @@ select_derived_init:
LEX *lex= Lex;
if (! lex->parsing_options.allows_derived)
- {
- my_error(ER_VIEW_SELECT_DERIVED, MYF(0));
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_VIEW_SELECT_DERIVED, MYF(0)));
SELECT_LEX *sel= lex->current_select;
TABLE_LIST *embedding;
- if (!sel->embedding || sel->end_nested_join(lex->thd))
+ if (!sel->embedding || sel->end_nested_join(thd))
{
/* we are not in parentheses */
my_parse_error(thd, ER_SYNTAX_ERROR);
@@ -11381,14 +11080,11 @@ olap_opt:
*/
LEX *lex=Lex;
if (lex->current_select->linkage == GLOBAL_OPTIONS_TYPE)
- {
- my_error(ER_WRONG_USAGE, MYF(0), "WITH CUBE",
- "global union parameters");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_WRONG_USAGE, MYF(0), "WITH CUBE",
+ "global union parameters"));
lex->current_select->olap= CUBE_TYPE;
- my_error(ER_NOT_SUPPORTED_YET, MYF(0), "CUBE");
- MYSQL_YYABORT;
+
+ my_yyabort_error((ER_NOT_SUPPORTED_YET, MYF(0), "CUBE"));
}
| WITH_ROLLUP_SYM
{
@@ -11401,11 +11097,8 @@ olap_opt:
*/
LEX *lex= Lex;
if (lex->current_select->linkage == GLOBAL_OPTIONS_TYPE)
- {
- my_error(ER_WRONG_USAGE, MYF(0), "WITH ROLLUP",
- "global union parameters");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_WRONG_USAGE, MYF(0), "WITH ROLLUP",
+ "global union parameters"));
lex->current_select->olap= ROLLUP_TYPE;
}
;
@@ -11470,7 +11163,7 @@ order_clause:
if (!unit->is_union() &&
(first_sl->order_list.elements ||
first_sl->select_limit) &&
- unit->add_fake_select_lex(lex->thd))
+ unit->add_fake_select_lex(thd))
MYSQL_YYABORT;
}
if (sel->master_unit()->is_union() && !sel->braces)
@@ -11587,15 +11280,9 @@ limit_option:
lex->safe_to_cache_query=0;
}
else
- {
- my_error(ER_SP_UNDECLARED_VAR, MYF(0), $1.str);
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SP_UNDECLARED_VAR, MYF(0), $1.str));
if (splocal->type() != Item::INT_ITEM)
- {
- my_error(ER_WRONG_SPVAR_TYPE_IN_LIMIT, MYF(0));
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_WRONG_SPVAR_TYPE_IN_LIMIT, MYF(0)));
splocal->limit_clause_param= TRUE;
$$= splocal;
}
@@ -11708,16 +11395,10 @@ opt_procedure_clause:
LEX *lex=Lex;
if (! lex->parsing_options.allows_select_procedure)
- {
- my_error(ER_VIEW_SELECT_CLAUSE, MYF(0), "PROCEDURE");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_VIEW_SELECT_CLAUSE, MYF(0), "PROCEDURE"));
if (&lex->select_lex != lex->current_select)
- {
- my_error(ER_WRONG_USAGE, MYF(0), "PROCEDURE", "subquery");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_WRONG_USAGE, MYF(0), "PROCEDURE", "subquery"));
lex->proc_list.elements=0;
lex->proc_list.first=0;
lex->proc_list.next= &lex->proc_list.first;
@@ -11726,7 +11407,7 @@ opt_procedure_clause:
NULL, NULL, $2.str);
if (item == NULL)
MYSQL_YYABORT;
- if (add_proc_to_list(lex->thd, item))
+ if (add_proc_to_list(thd, item))
MYSQL_YYABORT;
Lex->uncacheable(UNCACHEABLE_SIDEEFFECT);
@@ -11811,10 +11492,7 @@ select_outvar:
sp_variable *t;
if (!Lex->spcont || !(t= Lex->spcont->find_variable($1, false)))
- {
- my_error(ER_SP_UNDECLARED_VAR, MYF(0), $1.str);
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SP_UNDECLARED_VAR, MYF(0), $1.str));
$$ = Lex->result ? (new (thd->mem_root)
my_var_sp($1, t->offset, t->type,
Lex->sphead)) :
@@ -11831,10 +11509,7 @@ into:
INTO
{
if (! Lex->parsing_options.allows_select_into)
- {
- my_error(ER_VIEW_SELECT_CLAUSE, MYF(0), "INTO");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_VIEW_SELECT_CLAUSE, MYF(0), "INTO"));
}
into_destination
;
@@ -11914,7 +11589,7 @@ drop:
lex->alter_info.reset();
lex->alter_info.flags= Alter_info::ALTER_DROP_INDEX;
lex->alter_info.drop_list.push_back(ad, thd->mem_root);
- if (!lex->current_select->add_table_to_list(lex->thd, $6, NULL,
+ if (!lex->current_select->add_table_to_list(thd, $6, NULL,
TL_OPTION_UPDATING,
TL_READ_NO_INSERT,
MDL_SHARED_UPGRADABLE))
@@ -11931,17 +11606,11 @@ drop:
LEX *lex= thd->lex;
sp_name *spname;
if ($4.str && check_db_name(&$4))
- {
- my_error(ER_WRONG_DB_NAME, MYF(0), $4.str);
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_WRONG_DB_NAME, MYF(0), $4.str));
if (lex->sphead)
- {
- my_error(ER_SP_NO_DROP_SP, MYF(0), "FUNCTION");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SP_NO_DROP_SP, MYF(0), "FUNCTION"));
lex->set_command(SQLCOM_DROP_FUNCTION, $3);
- spname= new (lex->thd->mem_root) sp_name($4, $6, true);
+ spname= new (thd->mem_root) sp_name($4, $6, true);
if (spname == NULL)
MYSQL_YYABORT;
spname->init_qname(thd);
@@ -11953,14 +11622,11 @@ drop:
LEX_STRING db= {0, 0};
sp_name *spname;
if (lex->sphead)
- {
- my_error(ER_SP_NO_DROP_SP, MYF(0), "FUNCTION");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SP_NO_DROP_SP, MYF(0), "FUNCTION"));
if (thd->db && lex->copy_db_to(&db.str, &db.length))
MYSQL_YYABORT;
lex->set_command(SQLCOM_DROP_FUNCTION, $3);
- spname= new (lex->thd->mem_root) sp_name(db, $4, false);
+ spname= new (thd->mem_root) sp_name(db, $4, false);
if (spname == NULL)
MYSQL_YYABORT;
spname->init_qname(thd);
@@ -11970,10 +11636,7 @@ drop:
{
LEX *lex=Lex;
if (lex->sphead)
- {
- my_error(ER_SP_NO_DROP_SP, MYF(0), "PROCEDURE");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SP_NO_DROP_SP, MYF(0), "PROCEDURE"));
lex->set_command(SQLCOM_DROP_PROCEDURE, $3);
lex->spname= $4;
}
@@ -13005,14 +12668,9 @@ opt_format_json:
if (!my_strcasecmp(system_charset_info, $3.str, "JSON"))
Lex->explain_json= true;
else if (!my_strcasecmp(system_charset_info, $3.str, "TRADITIONAL"))
- {
DBUG_ASSERT(Lex->explain_json==false);
- }
else
- {
- my_error(ER_UNKNOWN_EXPLAIN_FORMAT, MYF(0), $3.str);
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_UNKNOWN_EXPLAIN_FORMAT, MYF(0), $3.str));
}
;
@@ -13109,10 +12767,7 @@ flush_option:
{
LEX *lex= Lex;
if (lex->type & REFRESH_RELAY_LOG)
- {
- my_error(ER_WRONG_USAGE, MYF(0), "FLUSH", "RELAY LOGS");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_WRONG_USAGE, MYF(0), "FLUSH", "RELAY LOGS"));
lex->type|= REFRESH_RELAY_LOG;
lex->relay_log_connection_name= lex->mi.connection_name;
}
@@ -13133,10 +12788,7 @@ flush_option:
{
LEX *lex= Lex;
if (lex->type & REFRESH_SLAVE)
- {
- my_error(ER_WRONG_USAGE, MYF(0), "FLUSH","SLAVE");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_WRONG_USAGE, MYF(0), "FLUSH","SLAVE"));
lex->type|= REFRESH_SLAVE;
lex->reset_slave_info.all= false;
}
@@ -13615,19 +13267,13 @@ param_marker:
Lex_input_stream *lip= YYLIP;
Item_param *item;
if (! lex->parsing_options.allows_variable)
- {
- my_error(ER_VIEW_SELECT_VARIABLE, MYF(0));
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_VIEW_SELECT_VARIABLE, MYF(0)));
const char *query_start= lex->sphead ? lex->sphead->m_tmp_query
: thd->query();
item= new (thd->mem_root) Item_param(thd, lip->get_tok_start() -
query_start);
if (!($$= item) || lex->param_list.push_back(item, thd->mem_root))
- {
- my_message(ER_OUT_OF_RESOURCES, ER_THD(thd, ER_OUT_OF_RESOURCES), MYF(0));
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_OUT_OF_RESOURCES, MYF(0)));
}
;
@@ -13825,10 +13471,7 @@ simple_ident:
{
/* We're compiling a stored procedure and found a variable */
if (! lex->parsing_options.allows_variable)
- {
- my_error(ER_VIEW_SELECT_VARIABLE, MYF(0));
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_VIEW_SELECT_VARIABLE, MYF(0)));
Item_splocal *splocal;
splocal= new (thd->mem_root)
@@ -13904,17 +13547,11 @@ simple_ident_q:
if (lex->trg_chistics.event == TRG_EVENT_INSERT &&
!new_row)
- {
- my_error(ER_TRG_NO_SUCH_ROW_IN_TRG, MYF(0), "OLD", "on INSERT");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_TRG_NO_SUCH_ROW_IN_TRG, MYF(0), "OLD", "on INSERT"));
if (lex->trg_chistics.event == TRG_EVENT_DELETE &&
new_row)
- {
- my_error(ER_TRG_NO_SUCH_ROW_IN_TRG, MYF(0), "NEW", "on DELETE");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_TRG_NO_SUCH_ROW_IN_TRG, MYF(0), "NEW", "on DELETE"));
DBUG_ASSERT(!new_row ||
(lex->trg_chistics.event == TRG_EVENT_INSERT ||
@@ -14023,26 +13660,17 @@ field_ident:
{
TABLE_LIST *table= Select->table_list.first;
if (my_strcasecmp(table_alias_charset, $1.str, table->db))
- {
- my_error(ER_WRONG_DB_NAME, MYF(0), $1.str);
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_WRONG_DB_NAME, MYF(0), $1.str));
if (my_strcasecmp(table_alias_charset, $3.str,
table->table_name))
- {
- my_error(ER_WRONG_TABLE_NAME, MYF(0), $3.str);
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_WRONG_TABLE_NAME, MYF(0), $3.str));
$$=$5;
}
| ident '.' ident
{
TABLE_LIST *table= Select->table_list.first;
if (my_strcasecmp(table_alias_charset, $1.str, table->alias))
- {
- my_error(ER_WRONG_TABLE_NAME, MYF(0), $1.str);
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_WRONG_TABLE_NAME, MYF(0), $1.str));
$$=$3;
}
| '.' ident { $$=$2;} /* For Delphi */
@@ -14678,10 +14306,7 @@ set:
{
LEX *lex= Lex;
if (lex->table_or_sp_used())
- {
- my_error(ER_SUBQUERIES_NOT_SUPPORTED, MYF(0), "SET STATEMENT");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SUBQUERIES_NOT_SUPPORTED, MYF(0), "SET STATEMENT"));
lex->stmt_var_list= lex->var_list;
lex->var_list.empty();
}
@@ -15010,10 +14635,7 @@ internal_variable_name:
!my_strcasecmp(system_charset_info, $1.str, "OLD")))
{
if ($1.str[0]=='O' || $1.str[0]=='o')
- {
- my_error(ER_TRG_CANT_CHANGE_ROW, MYF(0), "OLD", "");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_TRG_CANT_CHANGE_ROW, MYF(0), "OLD", ""));
if (lex->trg_chistics.event == TRG_EVENT_DELETE)
{
my_error(ER_TRG_NO_SUCH_ROW_IN_TRG, MYF(0),
@@ -15021,10 +14643,7 @@ internal_variable_name:
MYSQL_YYABORT;
}
if (lex->trg_chistics.action_time == TRG_ACTION_AFTER)
- {
- my_error(ER_TRG_CANT_CHANGE_ROW, MYF(0), "NEW", "after ");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_TRG_CANT_CHANGE_ROW, MYF(0), "NEW", "after "));
/* This special combination will denote field of NEW row */
$$.var= trg_new_row_fake_var;
$$.base_name= $3;
@@ -15116,10 +14735,7 @@ opt_for_user:
LEX_STRING pw= { C_STRING_WITH_LEN("password") };
if (spc && spc->find_variable(pw, false))
- {
- my_error(ER_SP_BAD_VAR_SHADOW, MYF(0), pw.str);
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SP_BAD_VAR_SHADOW, MYF(0), pw.str));
if (!(lex->definer= (LEX_USER*) thd->calloc(sizeof(LEX_USER))))
MYSQL_YYABORT;
lex->definer->user= current_user;
@@ -15172,10 +14788,7 @@ lock:
LEX *lex= Lex;
if (lex->sphead)
- {
- my_error(ER_SP_BADSTATEMENT, MYF(0), "LOCK");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SP_BADSTATEMENT, MYF(0), "LOCK"));
lex->sql_command= SQLCOM_LOCK_TABLES;
}
table_lock_list
@@ -15225,10 +14838,7 @@ unlock:
LEX *lex= Lex;
if (lex->sphead)
- {
- my_error(ER_SP_BADSTATEMENT, MYF(0), "UNLOCK");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SP_BADSTATEMENT, MYF(0), "UNLOCK"));
lex->sql_command= SQLCOM_UNLOCK_TABLES;
}
table_or_tables
@@ -15244,34 +14854,25 @@ handler:
{
LEX *lex= Lex;
if (lex->sphead)
- {
- my_error(ER_SP_BADSTATEMENT, MYF(0), "HANDLER");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SP_BADSTATEMENT, MYF(0), "HANDLER"));
lex->sql_command = SQLCOM_HA_OPEN;
- if (!lex->current_select->add_table_to_list(lex->thd, $2, $4, 0))
+ if (!lex->current_select->add_table_to_list(thd, $2, $4, 0))
MYSQL_YYABORT;
}
| HANDLER_SYM table_ident_nodb CLOSE_SYM
{
LEX *lex= Lex;
if (lex->sphead)
- {
- my_error(ER_SP_BADSTATEMENT, MYF(0), "HANDLER");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SP_BADSTATEMENT, MYF(0), "HANDLER"));
lex->sql_command = SQLCOM_HA_CLOSE;
- if (!lex->current_select->add_table_to_list(lex->thd, $2, 0, 0))
+ if (!lex->current_select->add_table_to_list(thd, $2, 0, 0))
MYSQL_YYABORT;
}
| HANDLER_SYM table_ident_nodb READ_SYM
{
LEX *lex=Lex;
if (lex->sphead)
- {
- my_error(ER_SP_BADSTATEMENT, MYF(0), "HANDLER");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SP_BADSTATEMENT, MYF(0), "HANDLER"));
lex->expr_allows_subselect= FALSE;
lex->sql_command = SQLCOM_HA_READ;
lex->ha_rkey_mode= HA_READ_KEY_EXACT; /* Avoid purify warnings */
@@ -15281,7 +14882,7 @@ handler:
lex->current_select->select_limit= one;
lex->current_select->offset_limit= 0;
lex->limit_rows_examined= 0;
- if (!lex->current_select->add_table_to_list(lex->thd, $2, 0, 0))
+ if (!lex->current_select->add_table_to_list(thd, $2, 0, 0))
MYSQL_YYABORT;
}
handler_read_or_scan opt_where_clause opt_limit_clause
@@ -15487,10 +15088,7 @@ grant_role:
/* trim end spaces (as they'll be lost in mysql.user anyway) */
$1.length= cs->cset->lengthsp(cs, $1.str, $1.length);
if ($1.length == 0)
- {
- my_error(ER_INVALID_ROLE, MYF(0), "");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_INVALID_ROLE, MYF(0), ""));
if (!($$=(LEX_USER*) thd->alloc(sizeof(st_lex_user))))
MYSQL_YYABORT;
$$->user = $1;
@@ -15585,30 +15183,21 @@ require_list_element:
{
LEX *lex=Lex;
if (lex->x509_subject)
- {
- my_error(ER_DUP_ARGUMENT, MYF(0), "SUBJECT");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "SUBJECT"));
lex->x509_subject=$2.str;
}
| ISSUER_SYM TEXT_STRING
{
LEX *lex=Lex;
if (lex->x509_issuer)
- {
- my_error(ER_DUP_ARGUMENT, MYF(0), "ISSUER");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "ISSUER"));
lex->x509_issuer=$2.str;
}
| CIPHER_SYM TEXT_STRING
{
LEX *lex=Lex;
if (lex->ssl_cipher)
- {
- my_error(ER_DUP_ARGUMENT, MYF(0), "CIPHER");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_DUP_ARGUMENT, MYF(0), "CIPHER"));
lex->ssl_cipher=$2.str;
}
;
@@ -15623,11 +15212,7 @@ grant_ident:
if (lex->grant == GLOBAL_ACLS)
lex->grant = DB_ACLS & ~GRANT_ACL;
else if (lex->columns.elements)
- {
- my_message(ER_ILLEGAL_GRANT_FOR_TABLE,
- ER_THD(thd, ER_ILLEGAL_GRANT_FOR_TABLE), MYF(0));
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_ILLEGAL_GRANT_FOR_TABLE, MYF(0)));
}
| ident '.' '*'
{
@@ -15636,11 +15221,7 @@ grant_ident:
if (lex->grant == GLOBAL_ACLS)
lex->grant = DB_ACLS & ~GRANT_ACL;
else if (lex->columns.elements)
- {
- my_message(ER_ILLEGAL_GRANT_FOR_TABLE,
- ER_THD(thd, ER_ILLEGAL_GRANT_FOR_TABLE), MYF(0));
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_ILLEGAL_GRANT_FOR_TABLE, MYF(0)));
}
| '*' '.' '*'
{
@@ -15649,16 +15230,12 @@ grant_ident:
if (lex->grant == GLOBAL_ACLS)
lex->grant= GLOBAL_ACLS & ~GRANT_ACL;
else if (lex->columns.elements)
- {
- my_message(ER_ILLEGAL_GRANT_FOR_TABLE,
- ER_THD(thd, ER_ILLEGAL_GRANT_FOR_TABLE), MYF(0));
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_ILLEGAL_GRANT_FOR_TABLE, MYF(0)));
}
| table_ident
{
LEX *lex=Lex;
- if (!lex->current_select->add_table_to_list(lex->thd, $1,NULL,
+ if (!lex->current_select->add_table_to_list(thd, $1,NULL,
TL_OPTION_UPDATING))
MYSQL_YYABORT;
if (lex->grant == GLOBAL_ACLS)
@@ -16339,10 +15916,7 @@ trigger_tail:
Lex_input_stream *lip= YYLIP;
if (lex->sphead)
- {
- my_error(ER_SP_NO_RECURSIVE_CREATE, MYF(0), "TRIGGER");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SP_NO_RECURSIVE_CREATE, MYF(0), "TRIGGER"));
lex->stmt_definition_begin= $2;
lex->ident.str= $9;
@@ -16399,10 +15973,7 @@ udf_tail2:
if (lex->add_create_options_with_check($2))
MYSQL_YYABORT;
if (is_native_function(thd, & $3))
- {
- my_error(ER_NATIVE_FCT_NAME_COLLISION, MYF(0), $3.str);
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_NATIVE_FCT_NAME_COLLISION, MYF(0), $3.str));
lex->sql_command= SQLCOM_CREATE_FUNCTION;
lex->udf.name= $3;
lex->udf.returns= (Item_result) $5;
@@ -16425,10 +15996,7 @@ sf_tail:
lex->spname= $3;
if (lex->sphead)
- {
- my_error(ER_SP_NO_RECURSIVE_CREATE, MYF(0), "FUNCTION");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SP_NO_RECURSIVE_CREATE, MYF(0), "FUNCTION"));
if (!make_sp_head(thd, $3, TYPE_ENUM_FUNCTION))
MYSQL_YYABORT;
@@ -16472,10 +16040,7 @@ sf_tail:
lex->sql_command= SQLCOM_CREATE_SPFUNCTION;
sp->set_stmt_end(thd);
if (!(sp->m_flags & sp_head::HAS_RETURN))
- {
- my_error(ER_SP_NORETURN, MYF(0), sp->m_qname.str);
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SP_NORETURN, MYF(0), sp->m_qname.str));
if (is_native_function(thd, & sp->m_name))
{
/*
@@ -16522,10 +16087,7 @@ sp_tail:
MYSQL_YYABORT;
if (Lex->sphead)
- {
- my_error(ER_SP_NO_RECURSIVE_CREATE, MYF(0), "PROCEDURE");
- MYSQL_YYABORT;
- }
+ my_yyabort_error((ER_SP_NO_RECURSIVE_CREATE, MYF(0), "PROCEDURE"));
if (!make_sp_head(thd, $3, TYPE_ENUM_PROCEDURE))
MYSQL_YYABORT;
diff --git a/sql/sys_vars.ic b/sql/sys_vars.ic
index 373f5834838..7c62516d52b 100644
--- a/sql/sys_vars.ic
+++ b/sql/sys_vars.ic
@@ -30,6 +30,7 @@
#include "strfunc.h"
#include "tztime.h" // my_tz_find, my_tz_SYSTEM, struct Time_zone
#include "rpl_mi.h" // For Multi-Source Replication
+#include "debug_sync.h"
/*
a set of mostly trivial (as in f(X)=X) defines below to make system variable
@@ -1469,7 +1470,6 @@ public:
}
bool session_update(THD *thd, set_var *var)
{
- extern bool debug_sync_update(THD *thd, char *val_str);
return debug_sync_update(thd, var->save_result.string_value.str);
}
bool global_update(THD *thd, set_var *var)
diff --git a/storage/connect/CMakeLists.txt b/storage/connect/CMakeLists.txt
index f6b42e7f360..db7d178a9e4 100644
--- a/storage/connect/CMakeLists.txt
+++ b/storage/connect/CMakeLists.txt
@@ -45,6 +45,7 @@ add_definitions( -DHUGE_SUPPORT -DZIP_SUPPORT -DPIVOT_SUPPORT )
# OS specific C flags, definitions and source files.
#
IF(UNIX)
+ if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
# Bar: -Wfatal-errors removed (does not present in gcc on solaris10)
if(WITH_WARNINGS)
add_definitions(-Wall -Wextra -Wmissing-declarations)
@@ -71,6 +72,7 @@ IF(UNIX)
#message(STATUS "CONNECT: GCC: Some warnings disabled")
endif(WITH_WARNINGS)
+ endif()
add_definitions( -DUNIX -DLINUX -DUBUNTU )
@@ -126,37 +128,10 @@ IF(WIN32)
OPTION(CONNECT_WITH_MSXML "Compile CONNECT storage engine with MSXML support" ON)
IF(CONNECT_WITH_MSXML)
- find_library(MSXML_LIBRARY
- NAMES msxml6 msxml4 msxml3 msxml2
- PATHS
- "C:/Program Files/Microsoft SDKs/Windows/v7.0A/Lib"
- "C:/Program Files/Microsoft SDKs/Windows/v6.0A/Lib"
- "C:/Program Files (x86)/Microsoft SDKs/Windows/v7.0A/Lib"
- DOC "Specify the MSXML? library here."
- )
- IF(MSXML_LIBRARY MATCHES .*msxml6[.].*)
- add_definitions(-DMSX6 -DDOMDOC_SUPPORT)
- message(STATUS "MSXML library version: msxml6")
- SET(MSXML_FOUND 1)
- SET(CONNECT_SOURCES ${CONNECT_SOURCES} domdoc.cpp domdoc.h)
- ELSEIF(MSXML_LIBRARY MATCHES .*msxml4[.].*)
- add_definitions(-DMSX4 -DDOMDOC_SUPPORT)
- message("MSXML library version: msxml4")
- SET(MSXML_FOUND 1)
- SET(CONNECT_SOURCES ${CONNECT_SOURCES} domdoc.cpp domdoc.h)
- ELSEIF(MSXML_LIBRARY MATCHES .*msxml3[.].*)
- message("MSXML library version: msxml3")
- add_definitions(-DMSX3 -DDOMDOC_SUPPORT)
- SET(MSXML_FOUND 1)
- SET(CONNECT_SOURCES ${CONNECT_SOURCES} domdoc.cpp domdoc.h)
- ELSEIF(MSXML_LIBRARY MATCHES .*msxml2[.].*)
- message("MSXML library version: msxml2")
- add_definitions(-DMXS2 -DDOMDOC_SUPPORT)
- SET(MSXML_FOUND 1)
- SET(CONNECT_SOURCES ${CONNECT_SOURCES} domdoc.cpp domdoc.h)
- ELSE()
- message(STATUS "msxml? library not found")
- ENDIF()
+ add_definitions(-DMSX6 -DDOMDOC_SUPPORT)
+ message(STATUS "MSXML library version: msxml6")
+ SET(MSXML_FOUND 1)
+ SET(CONNECT_SOURCES ${CONNECT_SOURCES} domdoc.cpp domdoc.h)
ENDIF(CONNECT_WITH_MSXML)
ENDIF(WIN32)
@@ -257,6 +232,27 @@ int main() {
ENDIF(UNIX)
ENDIF(CONNECT_WITH_ODBC)
+#
+# JDBC
+#
+
+OPTION(CONNECT_WITH_JDBC "Compile CONNECT storage engine with JDBC support" ON)
+
+IF(CONNECT_WITH_JDBC)
+ # TODO: detect Java SDK and the presence of JDBC connectors
+ # Find required libraries and include directories
+ # Find how to compile and install the JdbcInterface.java class
+
+ IF(JDBC_OK)
+ INCLUDE_DIRECTORIES(${JDBC_INCLUDE_DIR})
+ add_definitions(-DJDBC_SUPPORT)
+ SET(CONNECT_SOURCES ${CONNECT_SOURCES}
+ JdbcInterface.java tabjdbc.cpp jdbconn.cpp jdbccat.h jdbconn.h tabjdbc.h)
+ ELSE()
+ SET(JDBC_LIBRARY "")
+ ENDIF()
+ENDIF(CONNECT_WITH_JDBC)
+
#
# XMAP
@@ -277,5 +273,5 @@ MYSQL_ADD_PLUGIN(connect ${CONNECT_SOURCES}
COMPONENT connect-engine
RECOMPILE_FOR_EMBEDDED
LINK_LIBRARIES ${ZLIB_LIBRARY} ${XML_LIBRARY} ${ICONV_LIBRARY}
- ${ODBC_LIBRARY} ${IPHLPAPI_LIBRARY})
+ ${ODBC_LIBRARY} ${JDBC_LIBRARY} ${IPHLPAPI_LIBRARY})
diff --git a/storage/connect/connect.cc b/storage/connect/connect.cc
index 56a0fc4fd4f..460d47bcf62 100644
--- a/storage/connect/connect.cc
+++ b/storage/connect/connect.cc
@@ -752,7 +752,7 @@ RCODE CntIndexRead(PGLOBAL g, PTDB ptdb, OPVAL op,
return RC_FX;
} else if (x == 2) {
// Remote index
- if (ptdb->ReadKey(g, op, kr))
+ if (op != OP_SAME && ptdb->ReadKey(g, op, kr))
return RC_FX;
goto rnd;
diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc
index 3fa09044a71..4aef3af9946 100644
--- a/storage/connect/ha_connect.cc
+++ b/storage/connect/ha_connect.cc
@@ -21,8 +21,8 @@
based on external data. Principally they are based on plain files of many
different types, but also on collections of such files, collection of tables,
local or remote MySQL/MariaDB tables retrieved via MySQL API,
- ODBC tables retrieving data from other DBMS having an ODBC server, and even
- virtual tables.
+ ODBC/JDBC tables retrieving data from other DBMS having an ODBC/JDBC server,
+ and even virtual tables.
@details
ha_connect will let you create/open/delete tables, the created table can be
@@ -115,9 +115,6 @@
#include "sql_parse.h"
#include "sql_base.h"
#include <sys/stat.h>
-#if defined(NEW_WAY)
-#include "sql_table.h"
-#endif // NEW_WAY
#include "sql_partition.h"
#undef OFFSET
@@ -130,6 +127,9 @@
#if defined(ODBC_SUPPORT)
#include "odbccat.h"
#endif // ODBC_SUPPORT
+#if defined(JDBC_SUPPORT)
+#include "jdbccat.h"
+#endif // JDBC_SUPPORT
#include "xtable.h"
#include "tabmysql.h"
#include "filamdbf.h"
@@ -197,6 +197,7 @@ PQRYRES OEMColumns(PGLOBAL g, PTOS topt, char *tab, char *db, bool info);
PQRYRES VirColumns(PGLOBAL g, bool info);
PQRYRES JSONColumns(PGLOBAL g, char *db, PTOS topt, bool info);
PQRYRES XMLColumns(PGLOBAL g, char *db, char *tab, PTOS topt, bool info);
+int TranslateJDBCType(int stp, int prec, int& len, char& v);
void PushWarning(PGLOBAL g, THD *thd, int level);
bool CheckSelf(PGLOBAL g, TABLE_SHARE *s, const char *host,
const char *db, char *tab, const char *src, int port);
@@ -757,7 +758,7 @@ ha_connect::ha_connect(handlerton *hton, TABLE_SHARE *table_arg)
sdvalout= NULL;
xmod= MODE_ANY;
istable= false;
- *partname= 0;
+ memset(partname, 0, sizeof(partname));
bzero((char*) &xinfo, sizeof(XINFO));
valid_info= false;
valid_query_id= 0;
@@ -1150,7 +1151,7 @@ char *ha_connect::GetRealString(const char *s)
{
char *sv;
- if (IsPartitioned() && s) {
+ if (IsPartitioned() && s && partname && *partname) {
sv= (char*)PlugSubAlloc(xp->g, NULL, 0);
sprintf(sv, s, partname);
PlugSubAlloc(xp->g, NULL, strlen(sv) + 1);
@@ -1173,7 +1174,9 @@ char *ha_connect::GetStringOption(char *opname, char *sdef)
: table->s->connect_string;
if (cnc.length)
- opval= GetRealString(strz(xp->g, cnc));
+ opval= strz(xp->g, cnc);
+ else
+ opval= GetListOption(xp->g, opname, options->oplist);
} else if (!stricmp(opname, "Query_String"))
opval= thd_query_string(table->in_use)->str;
@@ -1756,9 +1759,10 @@ int ha_connect::OpenTable(PGLOBAL g, bool del)
break;
} // endswitch xmode
- if (xmod != MODE_INSERT || tdbp->GetAmType() == TYPE_AM_ODBC
- || tdbp->GetAmType() == TYPE_AM_MYSQL) {
- // Get the list of used fields (columns)
+ if (xmod != MODE_INSERT || tdbp->GetAmType() == TYPE_AM_MYSQL
+ || tdbp->GetAmType() == TYPE_AM_ODBC
+ || tdbp->GetAmType() == TYPE_AM_JDBC) {
+ // Get the list of used fields (columns)
char *p;
unsigned int k1, k2, n1, n2;
Field* *field;
@@ -2075,8 +2079,9 @@ int ha_connect::ScanRecord(PGLOBAL g, uchar *)
continue; // Is a virtual column possible here ???
if ((xmod == MODE_INSERT && tdbp->GetAmType() != TYPE_AM_MYSQL
- && tdbp->GetAmType() != TYPE_AM_ODBC) ||
- bitmap_is_set(table->write_set, fp->field_index)) {
+ && tdbp->GetAmType() != TYPE_AM_ODBC
+ && tdbp->GetAmType() != TYPE_AM_JDBC) ||
+ bitmap_is_set(table->write_set, fp->field_index)) {
for (colp= tp->GetSetCols(); colp; colp= colp->GetNext())
if (!stricmp(colp->GetName(), fp->field_name))
break;
@@ -2286,7 +2291,7 @@ bool ha_connect::MakeKeyWhere(PGLOBAL g, PSTRG qry, OPVAL vop, char q,
op= OP_EQ;
break;
case HA_READ_AFTER_KEY:
- op= (stlen >= len) ? (!i ? OP_GT : OP_LE) : OP_GE;
+ op= (stlen >= len || i > 0) ? (i > 0 ? OP_LE : OP_GT) : OP_GE;
break;
case HA_READ_KEY_OR_NEXT:
op= OP_GE;
@@ -2625,7 +2630,7 @@ PFIL ha_connect::CondFilter(PGLOBAL g, Item *cond)
} // end of CondFilter
/***********************************************************************/
-/* Check the WHERE condition and return a MYSQL/ODBC/WQL filter. */
+/* Check the WHERE condition and return a MYSQL/ODBC/JDBC/WQL filter. */
/***********************************************************************/
PCFIL ha_connect::CheckCond(PGLOBAL g, PCFIL filp, const Item *cond)
{
@@ -2633,8 +2638,8 @@ PCFIL ha_connect::CheckCond(PGLOBAL g, PCFIL filp, const Item *cond)
char *body= filp->Body;
unsigned int i;
bool ismul= false, x= (tty == TYPE_AM_MYX || tty == TYPE_AM_XDBC);
- bool nonul= (tty == TYPE_AM_ODBC && (tdbp->GetMode() == MODE_INSERT ||
- tdbp->GetMode() == MODE_DELETE));
+ bool nonul= ((tty == TYPE_AM_ODBC || tty == TYPE_AM_JDBC) &&
+ (tdbp->GetMode() == MODE_INSERT || tdbp->GetMode() == MODE_DELETE));
OPVAL vop= OP_XX;
if (!cond)
@@ -2956,7 +2961,7 @@ const COND *ha_connect::cond_push(const COND *cond)
bool x= (tty == TYPE_AM_MYX || tty == TYPE_AM_XDBC);
bool b= (tty == TYPE_AM_WMI || tty == TYPE_AM_ODBC ||
tty == TYPE_AM_TBL || tty == TYPE_AM_MYSQL ||
- tty == TYPE_AM_PLG || x);
+ tty == TYPE_AM_PLG || tty == TYPE_AM_JDBC || x);
// Save stack and allocation environment and prepare error return
if (g->jump_level == MAX_JUMP) {
@@ -3121,13 +3126,14 @@ int ha_connect::open(const char *name, int mode, uint test_if_locked)
#if defined(WITH_PARTITION_STORAGE_ENGINE)
if (table->part_info) {
if (GetStringOption("Filename") || GetStringOption("Tabname")
- || GetStringOption("Connect")) {
- strcpy(partname, decode(g, strrchr(name, '#') + 1));
+ || GetStringOption("Connect")) {
+ strncpy(partname, decode(g, strrchr(name, '#') + 1), sizeof(partname) - 1);
// strcpy(partname, table->part_info->curr_part_elem->partition_name);
- part_id= &table->part_info->full_part_field_set;
+// part_id= &table->part_info->full_part_field_set;
} else // Inward table
- strcpy(partname, strrchr(name, slash) + 1);
- part_id= &table->part_info->full_part_field_set; // Temporary
+ strncpy(partname, strrchr(name, slash) + 1, sizeof(partname) - 1);
+
+ part_id= &table->part_info->full_part_field_set; // Temporary
} // endif part_info
#endif // WITH_PARTITION_STORAGE_ENGINE
} else
@@ -4054,7 +4060,7 @@ int ha_connect::delete_all_rows()
} // end of delete_all_rows
-bool ha_connect::check_privileges(THD *thd, PTOS options, char *dbn)
+bool ha_connect::check_privileges(THD *thd, PTOS options, char *dbn, bool quick)
{
const char *db= (dbn && *dbn) ? dbn : NULL;
TABTYPE type=GetRealType(options);
@@ -4081,6 +4087,7 @@ bool ha_connect::check_privileges(THD *thd, PTOS options, char *dbn)
case TAB_VEC:
case TAB_JSON:
if (options->filename && *options->filename) {
+ if (!quick) {
char *s, path[FN_REFLEN], dbpath[FN_REFLEN];
#if defined(__WIN__)
s= "\\";
@@ -4099,13 +4106,14 @@ bool ha_connect::check_privileges(THD *thd, PTOS options, char *dbn)
my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--secure-file-priv");
return true;
} // endif path
-
+ }
} else
return false;
/* Fall through to check FILE_ACL */
case TAB_ODBC:
- case TAB_MYSQL:
+ case TAB_JDBC:
+ case TAB_MYSQL:
case TAB_DIR:
case TAB_MAC:
case TAB_WMI:
@@ -4121,10 +4129,13 @@ bool ha_connect::check_privileges(THD *thd, PTOS options, char *dbn)
Otherwise it's a DML, the table was normally opened, locked,
privilege were already checked, and table->grant.privilege is set.
With SQL SECURITY DEFINER, table->grant.privilege has definer's privileges.
+
+ Unless we're in prelocking mode, in this case table->grant.privilege
+ is only checked in start_stmt(), not in external_lock().
*/
if (!table || !table->mdl_ticket || table->mdl_ticket->get_type() == MDL_EXCLUSIVE)
return check_access(thd, FILE_ACL, db, NULL, NULL, 0, 0);
- if (table->grant.privilege & FILE_ACL)
+ if ((!quick && thd->lex->requires_prelocking()) || table->grant.privilege & FILE_ACL)
return false;
status_var_increment(thd->status_var.access_denied_errors);
my_error(access_denied_error_code(thd->password), MYF(0),
@@ -4308,6 +4319,9 @@ int ha_connect::start_stmt(THD *thd, thr_lock_type lock_type)
PGLOBAL g= GetPlug(thd, xp);
DBUG_ENTER("ha_connect::start_stmt");
+ if (check_privileges(thd, GetTableOptionStruct(), table->s->db.str, true))
+ DBUG_RETURN(HA_ERR_INTERNAL_ERROR);
+
// Action will depend on lock_type
switch (lock_type) {
case TL_WRITE_ALLOW_WRITE:
@@ -4769,7 +4783,11 @@ int ha_connect::delete_or_rename_table(const char *name, const char *to)
DBUG_RETURN(rc);
// Get the share info from the .frm file
- if (!open_table_def(thd, share)) {
+ Dummy_error_handler error_handler;
+ thd->push_internal_handler(&error_handler);
+ bool got_error= open_table_def(thd, share);
+ thd->pop_internal_handler();
+ if (!got_error) {
// Now we can work
if ((pos= share->option_struct)) {
if (check_privileges(thd, pos, db))
@@ -4782,12 +4800,6 @@ int ha_connect::delete_or_rename_table(const char *name, const char *to)
} // endif open_table_def
-// This below was done to avoid DBUG_ASSERT in some case that
-// we don't know anymore what they were. It was suppressed because
-// it did cause assertion in other cases (see MDEV-7935)
-// } else // Avoid infamous DBUG_ASSERT
-// thd->get_stmt_da()->reset_diagnostics_area();
-
free_table_share(share);
} else // Temporary file
ok= true;
@@ -5121,11 +5133,18 @@ static int connect_assisted_discovery(handlerton *, THD* thd,
int port= 0, hdr= 0, mxr= 0, mxe= 0, rc= 0;
int cop __attribute__((unused))= 0, lrecl= 0;
#if defined(ODBC_SUPPORT)
- POPARM sop = NULL;
- char *ucnc = NULL;
+ POPARM sop= NULL;
+ char *ucnc= NULL;
bool cnc= false;
int cto= -1, qto= -1;
#endif // ODBC_SUPPORT
+#if defined(JDBC_SUPPORT)
+ PJPARM sjp= NULL;
+ char *jpath= NULL;
+ char *driver= NULL;
+ char *url= NULL;
+ char *tabtyp = NULL;
+#endif // JDBC_SUPPORT
uint tm, fnc= FNC_NO, supfnc= (FNC_NO | FNC_COL);
bool bif, ok= false, dbf= false;
TABTYPE ttp= TAB_UNDEF;
@@ -5136,15 +5155,10 @@ static int connect_assisted_discovery(handlerton *, THD* thd,
PDBUSER dup= PlgGetUser(g);
PCATLG cat= (dup) ? dup->Catalog : NULL;
PTOS topt= table_s->option_struct;
-#if defined(NEW_WAY)
-//CHARSET_INFO *cs;
- Alter_info alter_info;
-#else // !NEW_WAY
char buf[1024];
String sql(buf, sizeof(buf), system_charset_info);
sql.copy(STRING_WITH_LEN("CREATE TABLE whatever ("), system_charset_info);
-#endif // !NEW_WAY
if (!g)
return HA_ERR_INTERNAL_ERROR;
@@ -5192,6 +5206,12 @@ static int connect_assisted_discovery(handlerton *, THD* thd,
if ((ucnc= GetListOption(g, "UseDSN", topt->oplist)))
cnc= (!*ucnc || *ucnc == 'y' || *ucnc == 'Y' || atoi(ucnc) != 0);
#endif
+#if defined(JDBC_SUPPORT)
+ jpath= GetListOption(g, "Jpath", topt->oplist, NULL);
+ driver= GetListOption(g, "Driver", topt->oplist, NULL);
+ url= GetListOption(g, "URL", topt->oplist, NULL);
+ tabtyp = GetListOption(g, "Tabtype", topt->oplist, NULL);
+#endif // JDBC_SUPPORT
mxe= atoi(GetListOption(g,"maxerr", topt->oplist, "0"));
#if defined(PROMPT_OK)
cop= atoi(GetListOption(g, "checkdsn", topt->oplist, "0"));
@@ -5252,44 +5272,62 @@ static int connect_assisted_discovery(handlerton *, THD* thd,
} else if (ttp != TAB_ODBC || !(fnc & (FNC_TABLE | FNC_COL)))
tab= table_s->table_name.str; // Default value
-#if defined(NEW_WAY)
-// add_option(thd, create_info, "tabname", tab);
-#endif // NEW_WAY
} // endif tab
- switch (ttp) {
+ switch (ttp) {
#if defined(ODBC_SUPPORT)
- case TAB_ODBC:
- dsn= strz(g, create_info->connect_string);
+ case TAB_ODBC:
+ dsn= strz(g, create_info->connect_string);
- if (fnc & (FNC_DSN | FNC_DRIVER)) {
- ok= true;
+ if (fnc & (FNC_DSN | FNC_DRIVER)) {
+ ok= true;
#if defined(PROMPT_OK)
- } else if (!stricmp(thd->main_security_ctx.host, "localhost")
- && cop == 1) {
- if ((dsn = ODBCCheckConnection(g, dsn, cop)) != NULL) {
- thd->make_lex_string(&create_info->connect_string, dsn, strlen(dsn));
- ok= true;
- } // endif dsn
+ } else if (!stricmp(thd->main_security_ctx.host, "localhost")
+ && cop == 1) {
+ if ((dsn = ODBCCheckConnection(g, dsn, cop)) != NULL) {
+ thd->make_lex_string(&create_info->connect_string, dsn, strlen(dsn));
+ ok= true;
+ } // endif dsn
#endif // PROMPT_OK
- } else if (!dsn) {
- sprintf(g->Message, "Missing %s connection string", topt->type);
- } else {
- // Store ODBC additional parameters
- sop= (POPARM)PlugSubAlloc(g, NULL, sizeof(ODBCPARM));
- sop->User= (char*)user;
- sop->Pwd= (char*)pwd;
- sop->Cto= cto;
- sop->Qto= qto;
- sop->UseCnc= cnc;
- ok= true;
- } // endif's
-
- supfnc |= (FNC_TABLE | FNC_DSN | FNC_DRIVER);
- break;
+ } else if (!dsn) {
+ sprintf(g->Message, "Missing %s connection string", topt->type);
+ } else {
+ // Store ODBC additional parameters
+ sop= (POPARM)PlugSubAlloc(g, NULL, sizeof(ODBCPARM));
+ sop->User= (char*)user;
+ sop->Pwd= (char*)pwd;
+ sop->Cto= cto;
+ sop->Qto= qto;
+ sop->UseCnc= cnc;
+ ok= true;
+ } // endif's
+
+ supfnc |= (FNC_TABLE | FNC_DSN | FNC_DRIVER);
+ break;
#endif // ODBC_SUPPORT
- case TAB_DBF:
+#if defined(JDBC_SUPPORT)
+ case TAB_JDBC:
+ if (fnc & FNC_DRIVER) {
+ ok= true;
+ } else if (!url) {
+ strcpy(g->Message, "Missing URL");
+ } else {
+ // Store ODBC additional parameters
+ sjp= (PJPARM)PlugSubAlloc(g, NULL, sizeof(JDBCPARM));
+ sjp->Driver= driver;
+ sjp->Url= url;
+ sjp->User= (char*)user;
+ sjp->Pwd= (char*)pwd;
+ sjp->Fsize= 0;
+ sjp->Scrollable= false;
+ ok= true;
+ } // endif's
+
+ supfnc |= (FNC_DRIVER | FNC_TABLE);
+ break;
+#endif // JDBC_SUPPORT
+ case TAB_DBF:
dbf= true;
// Passthru
case TAB_CSV:
@@ -5408,7 +5446,7 @@ static int connect_assisted_discovery(handlerton *, THD* thd,
dpath= SetPath(g, table_s->db.str);
- if (src && ttp != TAB_PIVOT && ttp != TAB_ODBC) {
+ if (src && ttp != TAB_PIVOT && ttp != TAB_ODBC && ttp != TAB_JDBC) {
qrp= SrcColumns(g, host, db, user, pwd, src, port);
if (qrp && ttp == TAB_OCCUR)
@@ -5450,7 +5488,38 @@ static int connect_assisted_discovery(handlerton *, THD* thd,
break;
#endif // ODBC_SUPPORT
- case TAB_MYSQL:
+#if defined(JDBC_SUPPORT)
+ case TAB_JDBC:
+ switch (fnc) {
+ case FNC_NO:
+ case FNC_COL:
+ if (src) {
+ qrp= JDBCSrcCols(g, jpath, (char*)src, sjp);
+ src= NULL; // for next tests
+ } else
+ qrp= JDBCColumns(g, jpath, shm, tab, NULL,
+ mxr, fnc == FNC_COL, sjp);
+
+ break;
+ case FNC_TABLE:
+ qrp= JDBCTables(g, dsn, shm, tab, tabtyp, mxr, true, sjp);
+ break;
+#if 0
+ case FNC_DSN:
+ qrp= JDBCDataSources(g, mxr, true);
+ break;
+#endif // 0
+ case FNC_DRIVER:
+ qrp= JDBCDrivers(g, jpath, mxr, true);
+ break;
+ default:
+ sprintf(g->Message, "invalid catfunc %s", fncn);
+ break;
+ } // endswitch info
+
+ break;
+#endif // JDBC_SUPPORT
+ case TAB_MYSQL:
qrp= MyColumns(g, thd, host, db, user, pwd, tab,
NULL, port, fnc == FNC_COL);
break;
@@ -5523,14 +5592,9 @@ static int connect_assisted_discovery(handlerton *, THD* thd,
len= 256; // STRBLK's have 0 length
// Now add the field
-#if defined(NEW_WAY)
- rc= add_fields(g, thd, &alter_info, cnm, typ, len, dec,
- tm, "", flg, dbf, v);
-#else // !NEW_WAY
if (add_field(&sql, cnm, typ, len, dec, NULL, tm,
NULL, NULL, NULL, NULL, flg, dbf, v))
rc= HA_ERR_OUT_OF_MEM;
-#endif // !NEW_WAY
} // endfor crp
} else {
@@ -5553,12 +5617,7 @@ static int connect_assisted_discovery(handlerton *, THD* thd,
cnm= (char*)"noname";
dft= xtra= key= fmt= NULL;
v= ' ';
-#if defined(NEW_WAY)
- rem= "";
-// cs= NULL;
-#else // !NEW_WAY
rem= NULL;
-#endif // !NEW_WAY
for (crp= qrp->Colresp; crp; crp= crp->Next)
switch (crp->Fld) {
@@ -5627,10 +5686,10 @@ static int connect_assisted_discovery(handlerton *, THD* thd,
"Several %s tables found, specify DBNAME", tab);
my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0));
goto err;
- } else if (!schem)
+ } else if (!schem)
schem= crp->Kdata->GetCharValue(i);
- } // endif ttp
+ } // endif ttp
#endif // ODBC_SUPPORT
default:
break; // Ignore
@@ -5679,7 +5738,42 @@ static int connect_assisted_discovery(handlerton *, THD* thd,
} else
#endif // ODBC_SUPPORT
- // Make the arguments as required by add_fields
+#if defined(JDBC_SUPPORT)
+ if (ttp == TAB_JDBC) {
+ int plgtyp;
+
+ // typ must be PLG type, not SQL type
+ if (!(plgtyp= TranslateJDBCType(typ, dec, prec, v))) {
+ if (GetTypeConv() == TPC_SKIP) {
+ // Skip this column
+ sprintf(g->Message, "Column %s skipped (unsupported type %d)",
+ cnm, typ);
+ push_warning(thd, Sql_condition::WARN_LEVEL_WARN, 0, g->Message);
+ continue;
+ } else {
+ sprintf(g->Message, "Unsupported SQL type %d", typ);
+ my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0));
+ goto err;
+ } // endif type_conv
+
+ } else
+ typ= plgtyp;
+
+ switch (typ) {
+ case TYPE_DOUBLE:
+ // Some data sources do not count dec in length (prec)
+ prec += (dec + 2); // To be safe
+ break;
+ case TYPE_DECIM:
+ prec= len;
+ break;
+ default:
+ dec= 0;
+ } // endswitch typ
+
+ } else
+#endif // ODBC_SUPPORT
+ // Make the arguments as required by add_fields
if (typ == TYPE_DOUBLE)
prec= len;
@@ -5687,25 +5781,15 @@ static int connect_assisted_discovery(handlerton *, THD* thd,
prec= 0;
// Now add the field
-#if defined(NEW_WAY)
- rc= add_fields(g, thd, &alter_info, cnm, typ, prec, dec,
- tm, rem, 0, dbf, v);
-#else // !NEW_WAY
if (add_field(&sql, cnm, typ, prec, dec, key, tm, rem, dft, xtra,
fmt, 0, dbf, v))
rc= HA_ERR_OUT_OF_MEM;
-#endif // !NEW_WAY
} // endfor i
} // endif fnc
-#if defined(NEW_WAY)
- rc= init_table_share(thd, table_s, create_info, &alter_info);
-#else // !NEW_WAY
if (!rc)
rc= init_table_share(thd, table_s, create_info, &sql);
-// rc= init_table_share(thd, table_s, create_info, dsn, &sql);
-#endif // !NEW_WAY
g->jump_level--;
return rc;
@@ -6142,7 +6226,7 @@ int ha_connect::create(const char *name, TABLE *table_arg,
strcpy(dbpath, name);
p= strrchr(dbpath, slash);
- strcpy(partname, ++p);
+ strncpy(partname, ++p, sizeof(partname) - 1);
strcat(strcat(strcpy(buf, p), "."), lwt);
*p= 0;
} else {
@@ -6193,7 +6277,7 @@ int ha_connect::create(const char *name, TABLE *table_arg,
#if defined(WITH_PARTITION_STORAGE_ENGINE)
if (part_info && !inward)
- strcpy(partname, decode(g, strrchr(name, '#') + 1));
+ strncpy(partname, decode(g, strrchr(name, '#') + 1), sizeof(partname) - 1);
// strcpy(partname, part_info->curr_part_elem->partition_name);
#endif // WITH_PARTITION_STORAGE_ENGINE
@@ -6234,8 +6318,9 @@ int ha_connect::create(const char *name, TABLE *table_arg,
#if defined(WITH_PARTITION_STORAGE_ENGINE)
if (part_info)
- strcpy(partname,
- decode(g, strrchr(name, (inward ? slash : '#')) + 1));
+ strncpy(partname,
+ decode(g, strrchr(name, (inward ? slash : '#')) + 1),
+ sizeof(partname) - 1);
#endif // WITH_PARTITION_STORAGE_ENGINE
if ((rc= optimize(table->in_use, NULL))) {
diff --git a/storage/connect/ha_connect.h b/storage/connect/ha_connect.h
index 05cc872fa2a..60194ac0e3c 100644
--- a/storage/connect/ha_connect.h
+++ b/storage/connect/ha_connect.h
@@ -536,7 +536,7 @@ private:
DsMrr_impl ds_mrr;
protected:
- bool check_privileges(THD *thd, PTOS options, char *dbn);
+ bool check_privileges(THD *thd, PTOS options, char *dbn, bool quick=false);
MODE CheckMode(PGLOBAL g, THD *thd, MODE newmode, bool *chk, bool *cras);
char *GetDBfromName(const char *name);
@@ -554,7 +554,7 @@ protected:
PVAL sdvalin4; // Used to convert date values
PVAL sdvalout; // Used to convert date values
bool istable; // True for table handler
- char partname[64]; // The partition name
+ char partname[65]; // The partition name
MODE xmod; // Table mode
XINFO xinfo; // The table info structure
bool valid_info; // True if xinfo is valid
diff --git a/storage/connect/jdbccat.h b/storage/connect/jdbccat.h
new file mode 100644
index 00000000000..150197804d5
--- /dev/null
+++ b/storage/connect/jdbccat.h
@@ -0,0 +1,29 @@
+// Timeout and net wait defaults
+#define DEFAULT_LOGIN_TIMEOUT -1 // means do not set
+#define DEFAULT_QUERY_TIMEOUT -1 // means do not set
+
+typedef struct jdbc_parms {
+ int CheckSize(int rows);
+ char *Driver; // JDBC driver
+ char *Url; // Driver URL
+ char *User; // User connect info
+ char *Pwd; // Password connect info
+//int Cto; // Connect timeout
+//int Qto; // Query timeout
+ int Fsize; // Fetch size
+ bool Scrollable; // Scrollable cursor
+} JDBCPARM, *PJPARM;
+
+/***********************************************************************/
+/* JDBC catalog function prototypes. */
+/***********************************************************************/
+#if defined(PROMPT_OK)
+char *JDBCCheckConnection(PGLOBAL g, char *dsn, int cop);
+#endif // PROMPT_OK
+//PQRYRES JDBCDataSources(PGLOBAL g, int maxres, bool info);
+PQRYRES JDBCColumns(PGLOBAL g, char *jpath, char *db, char *table,
+ char *colpat, int maxres, bool info, PJPARM sop);
+PQRYRES JDBCSrcCols(PGLOBAL g, char *jpath, char *src, PJPARM sop);
+PQRYRES JDBCTables(PGLOBAL g, char *jpath, char *db, char *tabpat,
+ char *tabtyp, int maxres, bool info, PJPARM sop);
+PQRYRES JDBCDrivers(PGLOBAL g, char *jpath, int maxres, bool info);
diff --git a/storage/connect/jdbconn.cpp b/storage/connect/jdbconn.cpp
new file mode 100644
index 00000000000..cf744971c9e
--- /dev/null
+++ b/storage/connect/jdbconn.cpp
@@ -0,0 +1,2076 @@
+/************ Jdbconn C++ Functions Source Code File (.CPP) ************/
+/* Name: JDBCONN.CPP Version 1.0 */
+/* */
+/* (C) Copyright to the author Olivier BERTRAND 2016 */
+/* */
+/* This file contains the JDBC connection classes functions. */
+/***********************************************************************/
+
+/***********************************************************************/
+/* Include relevant MariaDB header file. */
+/***********************************************************************/
+#include <my_global.h>
+#include <m_string.h>
+#if defined(__WIN__)
+//nclude <io.h>
+//nclude <fcntl.h>
+#include <direct.h> // for getcwd
+#if defined(__BORLANDC__)
+#define __MFC_COMPAT__ // To define min/max as macro
+#endif
+//#include <windows.h>
+#else
+#if defined(UNIX)
+#include <errno.h>
+#else
+//nclude <io.h>
+#endif
+//nclude <fcntl.h>
+#define NODW
+#endif
+
+/***********************************************************************/
+/* Required objects includes. */
+/***********************************************************************/
+#include "global.h"
+#include "plgdbsem.h"
+#include "xobject.h"
+#include "xtable.h"
+#include "jdbccat.h"
+#include "tabjdbc.h"
+//#include "jdbconn.h"
+//#include "plgcnx.h" // For DB types
+#include "resource.h"
+#include "valblk.h"
+#include "osutil.h"
+
+
+#if defined(__WIN__)
+extern "C" HINSTANCE s_hModule; // Saved module handle
+#endif // __WIN__
+
+int GetConvSize();
+
+/***********************************************************************/
+/* Some macro's (should be defined elsewhere to be more accessible) */
+/***********************************************************************/
+#if defined(_DEBUG)
+#define ASSERT(f) assert(f)
+#define DEBUG_ONLY(f) (f)
+#else // !_DEBUG
+#define ASSERT(f) ((void)0)
+#define DEBUG_ONLY(f) ((void)0)
+#endif // !_DEBUG
+
+/***********************************************************************/
+/* GetJDBCType: returns the SQL_TYPE corresponding to a PLG type. */
+/***********************************************************************/
+static short GetJDBCType(int type)
+{
+ short tp = 0; // NULL
+
+ switch (type) {
+ case TYPE_STRING: tp = 12; break; // VARCHAR
+ case TYPE_SHORT: tp = 5; break; // SMALLINT
+ case TYPE_INT: tp = 4; break; // INTEGER
+ case TYPE_DATE: tp = 93; break; // DATE
+//case TYPE_TIME: tp = 92; break; // TIME
+//case TYPE_TIMESTAMP: tp = 93; break; // TIMESTAMP
+ case TYPE_BIGINT: tp = -5; break; // BIGINT
+ case TYPE_DOUBLE: tp = 8; break; // DOUBLE
+ case TYPE_TINY: tp = -6; break; // TINYINT
+ case TYPE_DECIM: tp = 3; break; // DECIMAL
+ } // endswitch type
+
+ return tp;
+} // end of GetJDBCType
+
+/***********************************************************************/
+/* TranslateJDBCType: translate a JDBC Type to a PLG type. */
+/***********************************************************************/
+int TranslateJDBCType(int stp, int prec, int& len, char& v)
+{
+ int type;
+
+ switch (stp) {
+ case -1: // LONGVARCHAR
+ len = MY_MIN(abs(len), GetConvSize());
+ case 12: // VARCHAR
+ v = 'V';
+ case 1: // CHAR
+ type = TYPE_STRING;
+ break;
+ case 2: // NUMERIC
+ case 3: // DECIMAL
+ type = TYPE_DECIM;
+ break;
+ case 4: // INTEGER
+ type = TYPE_INT;
+ break;
+ case 5: // SMALLINT
+ type = TYPE_SHORT;
+ break;
+ case -6: // TINYINT
+ case -7: // BIT
+ type = TYPE_TINY;
+ break;
+ case 6: // FLOAT
+ case 7: // REAL
+ case 8: // DOUBLE
+ type = TYPE_DOUBLE;
+ break;
+ case 93: // TIMESTAMP
+ type = TYPE_DATE;
+ len = 19 + ((prec) ? (prec+1) : 0);
+ v = 'S';
+ break;
+ case 91: // TYPE_DATE
+ type = TYPE_DATE;
+ len = 10;
+ v = 'D';
+ break;
+ case 92: // TYPE_TIME
+ type = TYPE_DATE;
+ len = 8 + ((prec) ? (prec+1) : 0);
+ v = 'T';
+ break;
+ case -5: // BIGINT
+ type = TYPE_BIGINT;
+ break;
+ case 0: // NULL
+ case -2: // BINARY
+ case -3: // VARBINARY
+ case -4: // LONGVARBINARY
+ default:
+ type = TYPE_ERROR;
+ len = 0;
+ } // endswitch type
+
+ return type;
+} // end of TranslateJDBCType
+
+/***********************************************************************/
+/* Allocate the structure used to refer to the result set. */
+/***********************************************************************/
+static JCATPARM *AllocCatInfo(PGLOBAL g, JCATINFO fid, char *db,
+ char *tab, PQRYRES qrp)
+{
+ size_t m, n;
+ JCATPARM *cap;
+
+#if defined(_DEBUG)
+ assert(qrp);
+#endif
+
+ // Save stack and allocation environment and prepare error return
+ if (g->jump_level == MAX_JUMP) {
+ strcpy(g->Message, MSG(TOO_MANY_JUMPS));
+ return NULL;
+ } // endif jump_level
+
+ if (setjmp(g->jumper[++g->jump_level]) != 0) {
+ printf("%s\n", g->Message);
+ cap = NULL;
+ goto fin;
+ } // endif rc
+
+ m = (size_t)qrp->Maxres;
+ n = (size_t)qrp->Nbcol;
+ cap = (JCATPARM *)PlugSubAlloc(g, NULL, sizeof(JCATPARM));
+ memset(cap, 0, sizeof(JCATPARM));
+ cap->Id = fid;
+ cap->Qrp = qrp;
+ cap->DB = (PUCHAR)db;
+ cap->Tab = (PUCHAR)tab;
+//cap->Vlen = (SQLLEN* *)PlugSubAlloc(g, NULL, n * sizeof(SQLLEN *));
+
+//for (i = 0; i < n; i++)
+// cap->Vlen[i] = (SQLLEN *)PlugSubAlloc(g, NULL, m * sizeof(SQLLEN));
+
+//cap->Status = (UWORD *)PlugSubAlloc(g, NULL, m * sizeof(UWORD));
+
+fin:
+ g->jump_level--;
+ return cap;
+} // end of AllocCatInfo
+
+/***********************************************************************/
+/* JDBCColumns: constructs the result blocks containing all columns */
+/* of a JDBC table that will be retrieved by GetData commands. */
+/***********************************************************************/
+PQRYRES JDBCColumns(PGLOBAL g, char *jpath, char *db, char *table,
+ char *colpat, int maxres, bool info, PJPARM sjp)
+{
+ int buftyp[] = {TYPE_STRING, TYPE_STRING, TYPE_STRING, TYPE_STRING,
+ TYPE_SHORT, TYPE_STRING, TYPE_INT, TYPE_INT,
+ TYPE_SHORT, TYPE_SHORT, TYPE_SHORT, TYPE_STRING};
+ XFLD fldtyp[] = {FLD_CAT, FLD_SCHEM, FLD_TABNAME, FLD_NAME,
+ FLD_TYPE, FLD_TYPENAME, FLD_PREC, FLD_LENGTH,
+ FLD_SCALE, FLD_RADIX, FLD_NULL, FLD_REM};
+ unsigned int length[] = {0, 0, 0, 0, 6, 0, 10, 10, 6, 6, 6, 0};
+ bool b[] = {true, true, false, false, false, false, false, false, true, true, false, true};
+ int i, n, ncol = 12;
+ PCOLRES crp;
+ PQRYRES qrp;
+ JCATPARM *cap;
+ JDBConn *jcp = NULL;
+
+ /************************************************************************/
+ /* Do an evaluation of the result size. */
+ /************************************************************************/
+ if (!info) {
+ jcp = new(g)JDBConn(g, NULL);
+
+ if (jcp->Open(jpath, sjp) != RC_OK) // openReadOnly + noJDBCdialog
+ return NULL;
+
+ if (table && !strchr(table, '%')) {
+ // We fix a MySQL limit because some data sources return 32767
+ n = jcp->GetMaxValue(1); // MAX_COLUMNS_IN_TABLE)
+ maxres = (n > 0) ? MY_MIN(n, 4096) : 4096;
+ } else if (!maxres)
+ maxres = 20000;
+
+ // n = jcp->GetMaxValue(2); MAX_CATALOG_NAME_LEN
+ // length[0] = (n) ? (n + 1) : 0;
+ // n = jcp->GetMaxValue(3); MAX_SCHEMA_NAME_LEN
+ // length[1] = (n) ? (n + 1) : 0;
+ // n = jcp->GetMaxValue(4); MAX_TABLE_NAME_LEN
+ // length[2] = (n) ? (n + 1) : 0;
+ n = jcp->GetMaxValue(5); // MAX_COLUMN_NAME_LEN
+ length[3] = (n > 0) ? (n + 1) : 128;
+ } else { // Info table
+ maxres = 0;
+ length[0] = 128;
+ length[1] = 128;
+ length[2] = 128;
+ length[3] = 128;
+ length[5] = 30;
+ length[11] = 255;
+ } // endif jcp
+
+ if (trace)
+ htrc("JDBCColumns: max=%d len=%d,%d,%d,%d\n",
+ maxres, length[0], length[1], length[2], length[3]);
+
+ /************************************************************************/
+ /* Allocate the structures used to refer to the result set. */
+ /************************************************************************/
+ qrp = PlgAllocResult(g, ncol, maxres, IDS_COLUMNS,
+ buftyp, fldtyp, length, false, true);
+
+ for (i = 0, crp = qrp->Colresp; crp; i++, crp = crp->Next)
+ if (b[i])
+ crp->Kdata->SetNullable(true);
+
+ if (info || !qrp) // Info table
+ return qrp;
+
+ if (trace)
+ htrc("Getting col results ncol=%d\n", qrp->Nbcol);
+
+ if (!(cap = AllocCatInfo(g, CAT_COL, db, table, qrp)))
+ return NULL;
+
+ cap->Pat = (PUCHAR)colpat;
+
+ /************************************************************************/
+ /* Now get the results into blocks. */
+ /************************************************************************/
+ if ((n = jcp->GetCatInfo(cap)) >= 0) {
+ qrp->Nblin = n;
+ // ResetNullValues(cap);
+
+ if (trace)
+ htrc("Columns: NBCOL=%d NBLIN=%d\n", qrp->Nbcol, qrp->Nblin);
+
+ } else
+ qrp = NULL;
+
+ /* Cleanup */
+ jcp->Close();
+
+ /************************************************************************/
+ /* Return the result pointer for use by GetData routines. */
+ /************************************************************************/
+ return qrp;
+} // end of JDBCColumns
+
+/**************************************************************************/
+/* JDBCSrcCols: constructs the result blocks containing the */
+/* description of all the columns of a Srcdef option. */
+/**************************************************************************/
+PQRYRES JDBCSrcCols(PGLOBAL g, char *jpath, char *src, PJPARM sjp)
+{
+ JDBConn *jcp = new(g)JDBConn(g, NULL);
+
+ if (jcp->Open(jpath, sjp))
+ return NULL;
+
+ return jcp->GetMetaData(g, src);
+} // end of JDBCSrcCols
+
+/**************************************************************************/
+/* JDBCTables: constructs the result blocks containing all tables in */
+/* an JDBC database that will be retrieved by GetData commands. */
+/**************************************************************************/
+PQRYRES JDBCTables(PGLOBAL g, char *jpath, char *db, char *tabpat,
+ char *tabtyp, int maxres, bool info, PJPARM sjp)
+{
+ int buftyp[] = {TYPE_STRING, TYPE_STRING, TYPE_STRING,
+ TYPE_STRING, TYPE_STRING};
+ XFLD fldtyp[] = {FLD_CAT, FLD_SCHEM, FLD_NAME, FLD_TYPE, FLD_REM};
+ unsigned int length[] = {0, 0, 0, 16, 0};
+ bool b[] = {true, true, false, false, true};
+ int i, n, ncol = 5;
+ PCOLRES crp;
+ PQRYRES qrp;
+ JCATPARM *cap;
+ JDBConn *jcp = NULL;
+
+ /************************************************************************/
+ /* Do an evaluation of the result size. */
+ /************************************************************************/
+ if (!info) {
+ /**********************************************************************/
+ /* Open the connection with the JDBC data source. */
+ /**********************************************************************/
+ jcp = new(g)JDBConn(g, NULL);
+
+ if (jcp->Open(jpath, sjp) == RC_FX)
+ return NULL;
+
+ if (!maxres)
+ maxres = 10000; // This is completely arbitrary
+
+ n = jcp->GetMaxValue(2); // Max catalog name length
+
+ if (n < 0)
+ return NULL;
+
+ length[0] = (n) ? (n + 1) : 0;
+ n = jcp->GetMaxValue(3); // Max schema name length
+ length[1] = (n) ? (n + 1) : 0;
+ n = jcp->GetMaxValue(4); // Max table name length
+ length[2] = (n) ? (n + 1) : 128;
+ } else {
+ maxres = 0;
+ length[0] = 128;
+ length[1] = 128;
+ length[2] = 128;
+ length[4] = 255;
+ } // endif info
+
+ if (trace)
+ htrc("JDBCTables: max=%d len=%d,%d\n", maxres, length[0], length[1]);
+
+ /************************************************************************/
+ /* Allocate the structures used to refer to the result set. */
+ /************************************************************************/
+ qrp = PlgAllocResult(g, ncol, maxres, IDS_TABLES, buftyp,
+ fldtyp, length, false, true);
+
+ for (i = 0, crp = qrp->Colresp; crp; i++, crp = crp->Next)
+ if (b[i])
+ crp->Kdata->SetNullable(true);
+
+ if (info || !qrp)
+ return qrp;
+
+ if (!(cap = AllocCatInfo(g, CAT_TAB, db, tabpat, qrp)))
+ return NULL;
+
+ cap->Pat = (PUCHAR)tabtyp;
+
+ if (trace)
+ htrc("Getting table results ncol=%d\n", cap->Qrp->Nbcol);
+
+ /************************************************************************/
+ /* Now get the results into blocks. */
+ /************************************************************************/
+ if ((n = jcp->GetCatInfo(cap)) >= 0) {
+ qrp->Nblin = n;
+ // ResetNullValues(cap);
+
+ if (trace)
+ htrc("Tables: NBCOL=%d NBLIN=%d\n", qrp->Nbcol, qrp->Nblin);
+
+ } else
+ qrp = NULL;
+
+ /************************************************************************/
+ /* Close any local connection. */
+ /************************************************************************/
+ jcp->Close();
+
+ /************************************************************************/
+ /* Return the result pointer for use by GetData routines. */
+ /************************************************************************/
+ return qrp;
+} // end of JDBCTables
+
+/*************************************************************************/
+/* JDBCDrivers: constructs the result blocks containing all JDBC */
+/* drivers available on the local host. */
+/* Called with info=true to have result column names. */
+/*************************************************************************/
+PQRYRES JDBCDrivers(PGLOBAL g, char *jpath, int maxres, bool info)
+{
+ int buftyp[] ={TYPE_STRING, TYPE_STRING, TYPE_STRING, TYPE_STRING};
+ XFLD fldtyp[] ={FLD_NAME, FLD_EXTRA, FLD_DEFAULT, FLD_REM };
+ unsigned int length[] ={ 128, 32, 4, 256 };
+ bool b[] ={ false, false, false, true };
+ int i, ncol = 4;
+ PCOLRES crp;
+ PQRYRES qrp;
+ JDBConn *jcp = NULL;
+
+ /************************************************************************/
+ /* Do an evaluation of the result size. */
+ /************************************************************************/
+ if (!info) {
+ jcp = new(g) JDBConn(g, NULL);
+
+ if (jcp->Open(jpath, NULL) != RC_OK)
+ return NULL;
+
+ if (!maxres)
+ maxres = 256; // Estimated max number of drivers
+
+ } else
+ maxres = 0;
+
+ if (trace)
+ htrc("JDBCDrivers: max=%d len=%d\n", maxres, length[0]);
+
+ /************************************************************************/
+ /* Allocate the structures used to refer to the result set. */
+ /************************************************************************/
+ qrp = PlgAllocResult(g, ncol, maxres, 0, buftyp, fldtyp, length, false, true);
+
+ for (i = 0, crp = qrp->Colresp; crp; i++, crp = crp->Next) {
+ if (b[i])
+ crp->Kdata->SetNullable(true);
+
+ switch (i) {
+ case 0: crp->Name = "Name"; break;
+ case 1: crp->Name = "Version"; break;
+ case 2: crp->Name = "Compliant"; break;
+ case 3: crp->Name = "Description"; break;
+ } // endswitch
+
+ } // endfor i
+
+ /************************************************************************/
+ /* Now get the results into blocks. */
+ /************************************************************************/
+ if (!info && qrp && jcp->GetDrivers(qrp))
+ qrp = NULL;
+
+ if (!info)
+ jcp->Close();
+
+ /************************************************************************/
+ /* Return the result pointer for use by GetData routines. */
+ /************************************************************************/
+ return qrp;
+} // end of JDBCDrivers
+
+#if 0
+/*************************************************************************/
+/* JDBCDataSources: constructs the result blocks containing all JDBC */
+/* data sources available on the local host. */
+/* Called with info=true to have result column names. */
+/*************************************************************************/
+PQRYRES JDBCDataSources(PGLOBAL g, int maxres, bool info)
+{
+ int buftyp[] ={ TYPE_STRING, TYPE_STRING };
+ XFLD fldtyp[] ={ FLD_NAME, FLD_REM };
+ unsigned int length[] ={ 0, 256 };
+ bool b[] ={ false, true };
+ int i, n = 0, ncol = 2;
+ PCOLRES crp;
+ PQRYRES qrp;
+ JDBConn *jcp = NULL;
+
+ /************************************************************************/
+ /* Do an evaluation of the result size. */
+ /************************************************************************/
+ if (!info) {
+ jcp = new(g)JDBConn(g, NULL);
+ n = jcp->GetMaxValue(SQL_MAX_DSN_LENGTH);
+ length[0] = (n) ? (n + 1) : 256;
+
+ if (!maxres)
+ maxres = 512; // Estimated max number of data sources
+
+ } else {
+ length[0] = 256;
+ maxres = 0;
+ } // endif info
+
+ if (trace)
+ htrc("JDBCDataSources: max=%d len=%d\n", maxres, length[0]);
+
+ /************************************************************************/
+ /* Allocate the structures used to refer to the result set. */
+ /************************************************************************/
+ qrp = PlgAllocResult(g, ncol, maxres, IDS_DSRC,
+ buftyp, fldtyp, length, false, true);
+
+ for (i = 0, crp = qrp->Colresp; crp; i++, crp = crp->Next)
+ if (b[i])
+ crp->Kdata->SetNullable(true);
+
+ /************************************************************************/
+ /* Now get the results into blocks. */
+ /************************************************************************/
+ if (!info && qrp && jcp->GetDataSources(qrp))
+ qrp = NULL;
+
+ /************************************************************************/
+ /* Return the result pointer for use by GetData routines. */
+ /************************************************************************/
+ return qrp;
+} // end of JDBCDataSources
+
+/**************************************************************************/
+/* PrimaryKeys: constructs the result blocks containing all the */
+/* JDBC catalog information concerning primary keys. */
+/**************************************************************************/
+PQRYRES JDBCPrimaryKeys(PGLOBAL g, JDBConn *op, char *dsn, char *table)
+{
+ static int buftyp[] ={ TYPE_STRING, TYPE_STRING, TYPE_STRING,
+ TYPE_STRING, TYPE_SHORT, TYPE_STRING };
+ static unsigned int length[] ={ 0, 0, 0, 0, 6, 128 };
+ int n, ncol = 5;
+ int maxres;
+ PQRYRES qrp;
+ JCATPARM *cap;
+ JDBConn *jcp = op;
+
+ if (!op) {
+ /**********************************************************************/
+ /* Open the connection with the JDBC data source. */
+ /**********************************************************************/
+ jcp = new(g)JDBConn(g, NULL);
+
+ if (jcp->Open(dsn, 2) < 1) // 2 is openReadOnly
+ return NULL;
+
+ } // endif op
+
+ /************************************************************************/
+ /* Do an evaluation of the result size. */
+ /************************************************************************/
+ n = jcp->GetMaxValue(SQL_MAX_COLUMNS_IN_TABLE);
+ maxres = (n) ? (int)n : 250;
+ n = jcp->GetMaxValue(SQL_MAX_CATALOG_NAME_LEN);
+ length[0] = (n) ? (n + 1) : 128;
+ n = jcp->GetMaxValue(SQL_MAX_SCHEMA_NAME_LEN);
+ length[1] = (n) ? (n + 1) : 128;
+ n = jcp->GetMaxValue(SQL_MAX_TABLE_NAME_LEN);
+ length[2] = (n) ? (n + 1) : 128;
+ n = jcp->GetMaxValue(SQL_MAX_COLUMN_NAME_LEN);
+ length[3] = (n) ? (n + 1) : 128;
+
+ if (trace)
+ htrc("JDBCPrimaryKeys: max=%d len=%d,%d,%d\n",
+ maxres, length[0], length[1], length[2]);
+
+ /************************************************************************/
+ /* Allocate the structure used to refer to the result set. */
+ /************************************************************************/
+ qrp = PlgAllocResult(g, ncol, maxres, IDS_PKEY,
+ buftyp, NULL, length, false, true);
+
+ if (trace)
+ htrc("Getting pkey results ncol=%d\n", qrp->Nbcol);
+
+ cap = AllocCatInfo(g, CAT_KEY, NULL, table, qrp);
+
+ /************************************************************************/
+ /* Now get the results into blocks. */
+ /************************************************************************/
+ if ((n = jcp->GetCatInfo(cap)) >= 0) {
+ qrp->Nblin = n;
+ // ResetNullValues(cap);
+
+ if (trace)
+ htrc("PrimaryKeys: NBCOL=%d NBLIN=%d\n", qrp->Nbcol, qrp->Nblin);
+
+ } else
+ qrp = NULL;
+
+ /************************************************************************/
+ /* Close any local connection. */
+ /************************************************************************/
+ if (!op)
+ jcp->Close();
+
+ /************************************************************************/
+ /* Return the result pointer for use by GetData routines. */
+ /************************************************************************/
+ return qrp;
+} // end of JDBCPrimaryKeys
+
+/**************************************************************************/
+/* Statistics: constructs the result blocks containing statistics */
+/* about one or several tables to be retrieved by GetData commands. */
+/**************************************************************************/
+PQRYRES JDBCStatistics(PGLOBAL g, JDBConn *op, char *dsn, char *pat,
+ int un, int acc)
+{
+ static int buftyp[] ={ TYPE_STRING,
+ TYPE_STRING, TYPE_STRING, TYPE_SHORT, TYPE_STRING,
+ TYPE_STRING, TYPE_SHORT, TYPE_SHORT, TYPE_STRING,
+ TYPE_STRING, TYPE_INT, TYPE_INT, TYPE_STRING };
+ static unsigned int length[] ={ 0, 0, 0, 6, 0, 0, 6, 6, 0, 2, 10, 10, 128 };
+ int n, ncol = 13;
+ int maxres;
+ PQRYRES qrp;
+ JCATPARM *cap;
+ JDBConn *jcp = op;
+
+ if (!op) {
+ /**********************************************************************/
+ /* Open the connection with the JDBC data source. */
+ /**********************************************************************/
+ jcp = new(g)JDBConn(g, NULL);
+
+ if (jcp->Open(dsn, 2) < 1) // 2 is openReadOnly
+ return NULL;
+
+ } // endif op
+
+ /************************************************************************/
+ /* Do an evaluation of the result size. */
+ /************************************************************************/
+ n = 1 + jcp->GetMaxValue(SQL_MAX_COLUMNS_IN_INDEX);
+ maxres = (n) ? (int)n : 32;
+ n = jcp->GetMaxValue(SQL_MAX_SCHEMA_NAME_LEN);
+ length[1] = (n) ? (n + 1) : 128;
+ n = jcp->GetMaxValue(SQL_MAX_TABLE_NAME_LEN);
+ length[2] = length[5] = (n) ? (n + 1) : 128;
+ n = jcp->GetMaxValue(SQL_MAX_CATALOG_NAME_LEN);
+ length[0] = length[4] = (n) ? (n + 1) : length[2];
+ n = jcp->GetMaxValue(SQL_MAX_COLUMN_NAME_LEN);
+ length[7] = (n) ? (n + 1) : 128;
+
+ if (trace)
+ htrc("SemStatistics: max=%d pat=%s\n", maxres, SVP(pat));
+
+ /************************************************************************/
+ /* Allocate the structure used to refer to the result set. */
+ /************************************************************************/
+ qrp = PlgAllocResult(g, ncol, maxres, IDS_STAT,
+ buftyp, NULL, length, false, true);
+
+ if (trace)
+ htrc("Getting stat results ncol=%d\n", qrp->Nbcol);
+
+ cap = AllocCatInfo(g, CAT_STAT, NULL, pat, qrp);
+ cap->Unique = (un < 0) ? SQL_INDEX_UNIQUE : (UWORD)un;
+ cap->Accuracy = (acc < 0) ? SQL_QUICK : (UWORD)acc;
+
+ /************************************************************************/
+ /* Now get the results into blocks. */
+ /************************************************************************/
+ if ((n = jcp->GetCatInfo(cap)) >= 0) {
+ qrp->Nblin = n;
+ // ResetNullValues(cap);
+
+ if (trace)
+ htrc("Statistics: NBCOL=%d NBLIN=%d\n", qrp->Nbcol, qrp->Nblin);
+
+ } else
+ qrp = NULL;
+
+ /************************************************************************/
+ /* Close any local connection. */
+ /************************************************************************/
+ if (!op)
+ jcp->Close();
+
+ /************************************************************************/
+ /* Return the result pointer for use by GetData routines. */
+ /************************************************************************/
+ return qrp;
+} // end of Statistics
+#endif // 0
+
+/***********************************************************************/
+/* JDBConn construction/destruction. */
+/***********************************************************************/
+JDBConn::JDBConn(PGLOBAL g, TDBJDBC *tdbp)
+{
+ m_G = g;
+ m_Tdb = tdbp;
+ jvm = nullptr; // Pointer to the JVM (Java Virtual Machine)
+ env= nullptr; // Pointer to native interface
+ jdi = nullptr; // Pointer to the JdbcInterface class
+ job = nullptr; // The JdbcInterface class object
+ xqid = xuid = xid = grs = readid = fetchid = typid = nullptr;
+ prepid = xpid = pcid = nullptr;
+//m_LoginTimeout = DEFAULT_LOGIN_TIMEOUT;
+//m_QueryTimeout = DEFAULT_QUERY_TIMEOUT;
+//m_UpdateOptions = 0;
+ m_Driver = NULL;
+ m_Url = NULL;
+ m_User = NULL;
+ m_Pwd = NULL;
+ m_Ncol = 0;
+ m_Aff = 0;
+ m_Rows = 0;
+ m_Fetch = 0;
+ m_RowsetSize = 0;
+ m_Updatable = true;
+ m_Transact = false;
+ m_Scrollable = false;
+ m_Full = false;
+ m_Opened = false;
+ m_IDQuoteChar[0] = '"';
+ m_IDQuoteChar[1] = 0;
+ //*m_ErrMsg = '\0';
+} // end of JDBConn
+
+//JDBConn::~JDBConn()
+// {
+//if (Connected())
+// EndCom();
+
+// } // end of ~JDBConn
+
+#if 0
+/***********************************************************************/
+/* Screen for errors. */
+/***********************************************************************/
+bool JDBConn::Check(RETCODE rc)
+{
+ switch (rc) {
+ case SQL_SUCCESS_WITH_INFO:
+ if (trace) {
+ DJX x(rc);
+
+ if (x.BuildErrorMessage(this, m_hstmt))
+ htrc("JDBC Success With Info, hstmt=%p %s\n",
+ m_hstmt, x.GetErrorMessage(0));
+
+ } // endif trace
+
+ // Fall through
+ case SQL_SUCCESS:
+ case SQL_NO_DATA_FOUND:
+ return true;
+ } // endswitch rc
+
+ return false;
+} // end of Check
+
+/***********************************************************************/
+/* Utility routine. */
+/***********************************************************************/
+PSZ JDBConn::GetStringInfo(ushort infotype)
+{
+ //ASSERT(m_hdbc != SQL_NULL_HDBC);
+ char *p, buffer[MAX_STRING_INFO];
+ SWORD result;
+ RETCODE rc;
+
+ rc = SQLGetInfo(m_hdbc, infotype, buffer, sizeof(buffer), &result);
+
+ if (!Check(rc)) {
+ ThrowDJX(rc, "SQLGetInfo"); // Temporary
+ // *buffer = '\0';
+ } // endif rc
+
+ p = PlugDup(m_G, buffer);
+ return p;
+} // end of GetStringInfo
+
+/***********************************************************************/
+/* Utility routines. */
+/***********************************************************************/
+void JDBConn::OnSetOptions(HSTMT hstmt)
+{
+ RETCODE rc;
+ ASSERT(m_hdbc != SQL_NULL_HDBC);
+
+ if ((signed)m_QueryTimeout != -1) {
+ // Attempt to set query timeout. Ignore failure
+ rc = SQLSetStmtOption(hstmt, SQL_QUERY_TIMEOUT, m_QueryTimeout);
+
+ if (!Check(rc))
+ // don't attempt it again
+ m_QueryTimeout = (DWORD)-1;
+
+ } // endif m_QueryTimeout
+
+ if (m_RowsetSize > 0) {
+ // Attempt to set rowset size.
+ // In case of failure reset it to 0 to use Fetch.
+ rc = SQLSetStmtOption(hstmt, SQL_ROWSET_SIZE, m_RowsetSize);
+
+ if (!Check(rc))
+ // don't attempt it again
+ m_RowsetSize = 0;
+
+ } // endif m_RowsetSize
+
+} // end of OnSetOptions
+#endif // 0
+
+/***********************************************************************/
+/* Utility routine. */
+/***********************************************************************/
+int JDBConn::GetMaxValue(int n)
+{
+ jmethodID maxid = env->GetMethodID(jdi, "GetMaxValue", "(I)I");
+
+ if (maxid == nullptr) {
+ strcpy(m_G->Message, "ERROR: method GetMaxValue not found !");
+ return -1;
+ } // endif maxid
+
+ // call method
+ return (int)env->CallIntMethod(job, maxid, n);
+} // end of GetMaxValue
+
+/***********************************************************************/
+/* Open: connect to a data source. */
+/***********************************************************************/
+int JDBConn::Open(PSZ jpath, PJPARM sop)
+{
+ PGLOBAL& g = m_G;
+ PSTRG jpop = new(g) STRING(g, 512, "-Djava.class.path=");
+ char sep;
+
+#if defined(__WIN__)
+ sep = ';';
+#else
+ sep = ':';
+#endif
+
+ if (sop) {
+ m_Driver = sop->Driver;
+ m_Url = sop->Url;
+ m_User = sop->User;
+ m_Pwd = sop->Pwd;
+ m_Scrollable = sop->Scrollable;
+ m_RowsetSize = sop->Fsize;
+ //m_LoginTimeout = sop->Cto;
+ //m_QueryTimeout = sop->Qto;
+ //m_UseCnc = sop->UseCnc;
+ } // endif sop
+
+ //================== prepare loading of Java VM ============================
+ JavaVMInitArgs vm_args; // Initialization arguments
+ JavaVMOption* options = new JavaVMOption[1]; // JVM invocation options
+
+ // where to find java .class
+ jpop->Append(getenv("CLASSPATH"));
+
+ if (jpath) {
+ jpop->Append(sep);
+ jpop->Append(jpath);
+ } // endif jpath
+
+ options[0].optionString = jpop->GetStr();
+//options[1].optionString = "-verbose:jni";
+ vm_args.version = JNI_VERSION_1_6; // minimum Java version
+ vm_args.nOptions = 1; // number of options
+ vm_args.options = options;
+ vm_args.ignoreUnrecognized = false; // invalid options make the JVM init fail
+
+ //=============== load and initialize Java VM and JNI interface =============
+ jint rc = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args); // YES !!
+ delete options; // we then no longer need the initialisation options.
+
+ switch (rc) {
+ case JNI_OK:
+ strcpy(g->Message, "VM successfully created");
+ break;
+ case JNI_ERR:
+ strcpy(g->Message, "Initialising JVM failed: unknown error");
+ return RC_FX;
+ case JNI_EDETACHED:
+ strcpy(g->Message, "Thread detached from the VM");
+ return RC_FX;
+ case JNI_EVERSION:
+ strcpy(g->Message, "JNI version error");
+ return RC_FX;
+ case JNI_ENOMEM:
+ strcpy(g->Message, "Not enough memory");
+ return RC_FX;
+ case JNI_EEXIST:
+ strcpy(g->Message, "VM already created");
+ {
+ JavaVM* jvms[1];
+ jsize jsz;
+
+ rc = JNI_GetCreatedJavaVMs(jvms, 1, &jsz);
+
+ if (rc == JNI_OK && jsz == 1) {
+ JavaVMAttachArgs args;
+
+ args.version = JNI_VERSION_1_6;
+ args.name = NULL;
+ args.group = NULL;
+ jvm = jvms[0];
+ rc = jvm->AttachCurrentThread((void**)&env, &args);
+ } // endif rc
+ } // end of block
+
+ if (rc == JNI_OK)
+ break;
+ else
+ return RC_FX;
+
+ case JNI_EINVAL:
+ strcpy(g->Message, "Invalid arguments");
+ return RC_FX;
+ default:
+ sprintf(g->Message, "Unknown return code %d", rc);
+ return RC_FX;
+ } // endswitch rc
+
+ //=============== Display JVM version =======================================
+//jint ver = env->GetVersion();
+//cout << ((ver>>16)&0x0f) << "."<<(ver&0x0f) << endl;
+
+ // try to find the JdbcInterface class
+ jdi = env->FindClass("JdbcInterface");
+
+ if (jdi == nullptr) {
+ strcpy(g->Message, "ERROR: class JdbcInterface not found !");
+ return RC_FX;
+ } // endif jdi
+
+ // if class found, continue
+ jmethodID ctor = env->GetMethodID(jdi, "<init>", "()V");
+
+ if (ctor == nullptr) {
+ strcpy(g->Message, "ERROR: JdbcInterface constructor not found !");
+ return RC_FX;
+ } else
+ job = env->NewObject(jdi, ctor);
+
+ // If the object is successfully constructed,
+ // we can then search for the method we want to call,
+ // and invoke it for the object:
+ if (job == nullptr) {
+ strcpy(g->Message, "JdbcInterface class object not constructed !");
+ return RC_FX;
+ } // endif job
+
+ if (!sop) // DRIVER catalog table
+ return RC_OK;
+
+ jmethodID cid = env->GetMethodID(jdi, "JdbcConnect", "([Ljava/lang/String;IZ)I");
+
+ if (env->ExceptionCheck()) {
+ strcpy(g->Message, "ERROR: method JdbcConnect() not found!");
+ env->ExceptionDescribe();
+ env->ExceptionClear();
+ return RC_FX;
+ } // endif Check
+
+ // Build the java string array
+ jobjectArray parms = env->NewObjectArray(4, // constructs java array of 4
+ env->FindClass("java/lang/String"), NULL); // Strings
+
+ // change some elements
+ if (m_Driver)
+ env->SetObjectArrayElement(parms, 0, env->NewStringUTF(m_Driver));
+
+ if (m_Url)
+ env->SetObjectArrayElement(parms, 1, env->NewStringUTF(m_Url));
+
+ if (m_User)
+ env->SetObjectArrayElement(parms, 2, env->NewStringUTF(m_User));
+
+ if (m_Pwd)
+ env->SetObjectArrayElement(parms, 3, env->NewStringUTF(m_Pwd));
+
+ // call method
+ rc = env->CallIntMethod(job, cid, parms, m_RowsetSize, m_Scrollable);
+
+ // Not used anymore
+ env->DeleteLocalRef(parms);
+
+ if (rc != (jint)0) {
+ strcpy(g->Message, "Connection failed");
+ return RC_FX;
+ } // endif rc
+
+ typid = env->GetMethodID(jdi, "ColumnType", "(ILjava/lang/String;)I");
+
+ if (env->ExceptionCheck()) {
+ strcpy(g->Message, "ERROR: method ColumnType() not found!");
+ env->ExceptionDescribe();
+ env->ExceptionClear();
+ return RC_FX;
+ } else
+ m_Opened = true;
+
+ return RC_OK;
+} // end of Open
+
+/***********************************************************************/
+/* Execute an SQL command. */
+/***********************************************************************/
+int JDBConn::ExecSQLcommand(char *sql)
+{
+ int rc = RC_NF;
+ jint n;
+ jstring qry;
+ PGLOBAL& g = m_G;
+
+ if (xid == nullptr) {
+ // Get the methods used to execute a query and get the result
+ xid = env->GetMethodID(jdi, "Execute", "(Ljava/lang/String;)I");
+
+ if (xid == nullptr) {
+ strcpy(g->Message, "Cannot find method Execute");
+ return RC_FX;
+ } else
+ grs = env->GetMethodID(jdi, "GetResult", "()I");
+
+ if (grs == nullptr) {
+ strcpy(g->Message, "Cannot find method GetResult");
+ return RC_FX;
+ } // endif grs
+
+ } // endif xid
+
+ qry = env->NewStringUTF(sql);
+ n = env->CallIntMethod(job, xid, qry);
+ env->DeleteLocalRef(qry);
+
+ if (n < 0) {
+ sprintf(g->Message, "Error executing %s", sql);
+ return RC_FX;
+ } // endif n
+
+ if ((m_Ncol = env->CallIntMethod(job, grs))) {
+ strcpy(g->Message, "Result set column number");
+ rc = RC_OK; // A result set was returned
+ } else {
+ m_Aff = (int)n; // Affected rows
+ strcpy(g->Message, "Affected rows");
+ } // endif ncol
+
+ return rc;
+} // end of ExecSQLcommand
+
+/***********************************************************************/
+/* Fetch next row. */
+/***********************************************************************/
+int JDBConn::Fetch(int pos)
+{
+ jint rc;
+
+ if (m_Full) // Result set has one row
+ return 1;
+
+ if (pos) {
+ if (!m_Scrollable) {
+ strcpy(m_G->Message, "Cannot fetch(pos) if FORWARD ONLY");
+ return -1;
+ } else if (fetchid == nullptr) {
+ fetchid = env->GetMethodID(jdi, "Fetch", "(I)Z");
+
+ if (fetchid == nullptr) {
+ strcpy(m_G->Message, "Cannot find method Fetch");
+ return -1;
+ } // endif fetchid
+
+ } // endif's
+
+ if (env->CallBooleanMethod(job, fetchid, pos))
+ rc = m_Rows;
+ else
+ rc = -1;
+
+ } else {
+ if (readid == nullptr) {
+ readid = env->GetMethodID(jdi, "ReadNext", "()I");
+
+ if (readid == nullptr) {
+ strcpy(m_G->Message, "Cannot find method ReadNext");
+ return -1;
+ } // endif readid
+
+ } // endif readid
+
+ rc = env->CallBooleanMethod(job, readid);
+
+ if (rc >= 0) {
+ if (rc == 0)
+ m_Full = (m_Fetch == 1);
+ else
+ m_Fetch++;
+
+ m_Rows += (int)rc;
+ } else
+ strcpy(m_G->Message, "Error fetching next row");
+
+ } // endif pos
+
+ return (int)rc;
+} // end of Fetch
+
+/***********************************************************************/
+/* Restart from beginning of result set */
+/***********************************************************************/
+int JDBConn::Rewind(char *sql)
+{
+ int rbuf = -1;
+
+ if (m_Full)
+ rbuf = m_Rows; // No need to "rewind"
+ else if (m_Scrollable) {
+ if (fetchid == nullptr) {
+ fetchid = env->GetMethodID(jdi, "Fetch", "(I)Z");
+
+ if (fetchid == nullptr) {
+ strcpy(m_G->Message, "Cannot find method Fetch");
+ return -1;
+ } // endif readid
+
+ } // endif readid
+
+ jboolean b = env->CallBooleanMethod(job, fetchid, 0);
+
+ rbuf = m_Rows;
+ } else if (ExecSQLcommand(sql) != RC_FX)
+ rbuf = 0;
+
+ return rbuf;
+} // end of Rewind
+
+/***********************************************************************/
+/* Disconnect connection */
+/***********************************************************************/
+void JDBConn::Close()
+{
+ if (m_Opened) {
+ jint rc;
+ jmethodID did = env->GetMethodID(jdi, "JdbcDisconnect", "()I");
+
+ if (did == nullptr)
+ printf("ERROR: method JdbcDisconnect() not found !");
+ else
+ rc = env->CallIntMethod(job, did);
+
+ rc = jvm->DetachCurrentThread();
+ //rc = jvm->DestroyJavaVM();
+ m_Opened = false;
+ } // endif m_Opened
+
+} // end of Close
+
+/***********************************************************************/
+/* Retrieve and set the column value from the result set. */
+/***********************************************************************/
+void JDBConn::SetColumnValue(int rank, PSZ name, PVAL val)
+{
+ PGLOBAL& g = m_G;
+ jint ctyp;
+ jlong dtv;
+ jstring cn, jn = nullptr;
+ jobject dob;
+ jthrowable exc;
+ jmethodID fldid = nullptr;
+
+ if (rank == 0)
+ if (!name || (jn = env->NewStringUTF(name)) == nullptr) {
+ sprintf(g->Message, "Fail to allocate jstring %s", SVP(name));
+ longjmp(g->jumper[g->jump_level], TYPE_AM_JDBC);
+ } // endif name
+
+ ctyp = env->CallIntMethod(job, typid, rank, jn);
+
+ if ((exc = env->ExceptionOccurred()) != nullptr) {
+ jboolean isCopy = false;
+ jmethodID tid = env->GetMethodID(env->FindClass("java/lang/Object"), "toString", "()Ljava/lang/String;");
+ jstring s = (jstring)env->CallObjectMethod(exc, tid);
+ const char* utf = env->GetStringUTFChars(s, &isCopy);
+ sprintf(g->Message, "SetColumnValue: %s", utf);
+ env->DeleteLocalRef(s);
+ env->ExceptionClear();
+ longjmp(g->jumper[g->jump_level], TYPE_AM_JDBC);
+ } // endif Check
+
+ switch (ctyp) {
+ case 12: // VARCHAR
+ case -1: // LONGVARCHAR
+ case 1: // CHAR
+ fldid = env->GetMethodID(jdi, "StringField",
+ "(ILjava/lang/String;)Ljava/lang/String;");
+
+ if (fldid != nullptr) {
+ cn = (jstring)env->CallObjectMethod(job, fldid, (jint)rank, jn);
+
+ if (cn) {
+ const char *field = env->GetStringUTFChars(cn, (jboolean)false);
+ val->SetValue_psz((PSZ)field);
+ } else {
+ val->Reset();
+ val->SetNull(true);
+ } // endif cn
+
+ } else
+ val->Reset();
+
+ break;
+ case 4: // INTEGER
+ case 5: // SMALLINT
+ case -6: // TINYINT
+ fldid = env->GetMethodID(jdi, "IntField", "(ILjava/lang/String;)I");
+
+ if (fldid != nullptr)
+ val->SetValue((int)env->CallIntMethod(job, fldid, rank, jn));
+ else
+ val->Reset();
+
+ break;
+ case 8: // DOUBLE
+ case 3: // DECIMAL
+ fldid = env->GetMethodID(jdi, "DoubleField", "(ILjava/lang/String;)D");
+
+ if (fldid != nullptr)
+ val->SetValue((double)env->CallDoubleMethod(job, fldid, rank, jn));
+ else
+ val->Reset();
+
+ break;
+ case 7: // REAL
+ case 6: // FLOAT
+ fldid = env->GetMethodID(jdi, "FloatField", "(ILjava/lang/String;)F");
+
+ if (fldid != nullptr)
+ val->SetValue((float)env->CallFloatMethod(job, fldid, rank, jn));
+ else
+ val->Reset();
+
+ break;
+ case 91: // DATE
+ case 92: // TIME
+ case 93: // TIMESTAMP
+ fldid = env->GetMethodID(jdi, "TimestampField",
+ "(ILjava/lang/String;)Ljava/sql/Timestamp;");
+
+ if (fldid != nullptr) {
+ dob = env->CallObjectMethod(job, fldid, (jint)rank, jn);
+
+ if (dob) {
+ jclass jts = env->FindClass("java/sql/Timestamp");
+
+ if (env->ExceptionCheck()) {
+ val->Reset();
+ } else {
+ jmethodID getTime = env->GetMethodID(jts, "getTime", "()J");
+
+ if (getTime != nullptr) {
+ dtv = env->CallLongMethod(dob, getTime);
+ val->SetValue((int)(dtv / 1000));
+ } else
+ val->Reset();
+
+ } // endif check
+
+ } else
+ val->Reset();
+
+ } else
+ val->Reset();
+
+ break;
+ case -5: // BIGINT
+ fldid = env->GetMethodID(jdi, "BigintField", "(ILjava/lang/String;)J");
+
+ if (fldid != nullptr)
+ val->SetValue((long long)env->CallLongMethod(job, fldid, (jint)rank, jn));
+ else
+ val->Reset();
+
+ break;
+ /* case java.sql.Types.SMALLINT:
+ System.out.print(jdi.IntField(i));
+ break;
+ case java.sql.Types.BOOLEAN:
+ System.out.print(jdi.BooleanField(i)); */
+ default:
+ val->Reset();
+ } // endswitch Type
+
+ if (rank == 0)
+ env->DeleteLocalRef(jn);
+
+} // end of SetColumnValue
+
+/***********************************************************************/
+/* Prepare an SQL statement for insert. */
+/***********************************************************************/
+bool JDBConn::PrepareSQL(char *sql)
+{
+ if (prepid == nullptr) {
+ prepid = env->GetMethodID(jdi, "CreatePrepStmt", "(Ljava/lang/String;)Z");
+
+ if (prepid == nullptr) {
+ strcpy(m_G->Message, "Cannot find method CreatePrepStmt");
+ return true;
+ } // endif prepid
+
+ } // endif prepid
+
+ // Create the prepared statement
+ jstring qry = env->NewStringUTF(sql);
+ jboolean b = env->CallBooleanMethod(job, prepid, qry);
+ env->DeleteLocalRef(qry);
+ return (bool)b;
+} // end of PrepareSQL
+
+/***********************************************************************/
+/* Execute an SQL query that returns a result set. */
+/***********************************************************************/
+int JDBConn::ExecuteQuery(char *sql)
+{
+ jint ncol;
+ jstring qry;
+ PGLOBAL& g = m_G;
+
+ if (xqid == nullptr) {
+ // Get the methods used to execute a query and get the result
+ xqid = env->GetMethodID(jdi, "ExecuteQuery", "(Ljava/lang/String;)I");
+
+ if (xqid == nullptr) {
+ strcpy(g->Message, "Cannot find method ExecuteQuery");
+ return RC_FX;
+ } // endif !xqid
+
+ } // endif xqid
+
+ qry = env->NewStringUTF(sql);
+ ncol = env->CallIntMethod(job, xqid, qry);
+ env->DeleteLocalRef(qry);
+
+ if (ncol < 0) {
+ sprintf(g->Message, "Error executing %s: ncol = %d", sql, ncol);
+ return RC_FX;
+ } else {
+ m_Ncol = (int)ncol;
+ m_Aff = 0; // Affected rows
+ } // endif ncol
+
+ return RC_OK;
+} // end of ExecuteQuery
+
+/***********************************************************************/
+/* Execute an SQL query and get the affected rows. */
+/***********************************************************************/
+int JDBConn::ExecuteUpdate(char *sql)
+{
+ jint n;
+ jstring qry;
+ PGLOBAL& g = m_G;
+
+ if (xuid == nullptr) {
+ // Get the methods used to execute a query and get the affected rows
+ xuid = env->GetMethodID(jdi, "ExecuteUpdate", "(Ljava/lang/String;)I");
+
+ if (xuid == nullptr) {
+ strcpy(g->Message, "Cannot find method ExecuteUpdate");
+ return RC_FX;
+ } // endif !xuid
+
+ } // endif xuid
+
+ qry = env->NewStringUTF(sql);
+ n = env->CallIntMethod(job, xuid, qry);
+ env->DeleteLocalRef(qry);
+
+ if (n < 0) {
+ sprintf(g->Message, "Error executing %s: n = %d", sql, n);
+ return RC_FX;
+ } else {
+ m_Ncol = 0;
+ m_Aff = (int)n; // Affected rows
+ } // endif n
+
+ return RC_OK;
+} // end of ExecuteUpdate
+
+/***********************************************************************/
+/* Get the number of lines of the result set. */
+/***********************************************************************/
+int JDBConn::GetResultSize(char *sql, JDBCCOL *colp)
+{
+ int rc, n = 0;
+
+ if ((rc = ExecuteQuery(sql)) != RC_OK)
+ return -1;
+
+ if ((rc = Fetch()) > 0)
+ SetColumnValue(1, NULL, colp->GetValue());
+ else
+ return -2;
+
+ if ((rc = Fetch()) != 0)
+ return -3;
+
+ m_Full = false;
+ return colp->GetIntValue();
+} // end of GetResultSize
+
+/***********************************************************************/
+/* Execute a prepared statement. */
+/***********************************************************************/
+int JDBConn::ExecuteSQL(void)
+{
+ int rc = RC_FX;
+ PGLOBAL& g = m_G;
+
+ if (xpid == nullptr) {
+ // Get the methods used to execute a prepared statement
+ xpid = env->GetMethodID(jdi, "ExecutePrep", "()I");
+
+ if (xpid == nullptr) {
+ strcpy(g->Message, "Cannot find method ExecutePrep");
+ return rc;
+ } // endif xpid
+
+ } // endif xpid
+
+ jint n = env->CallIntMethod(job, xpid);
+
+ switch ((int)n) {
+ case -1:
+ case -2:
+ strcpy(g->Message, "Exception error thrown while executing SQL");
+ break;
+ case -3:
+ strcpy(g->Message, "SQL statement is not prepared");
+ break;
+ default:
+ m_Aff = (int)n;
+ rc = RC_OK;
+ } // endswitch n
+
+ return rc;
+} // end of ExecuteSQL
+
+/***********************************************************************/
+/* Set a parameter for inserting. */
+/***********************************************************************/
+bool JDBConn::SetParam(JDBCCOL *colp)
+{
+ PGLOBAL& g = m_G;
+ int rc = false;
+ PVAL val = colp->GetValue();
+ jint n, i = (jint)colp->GetRank();
+ jshort s;
+ jlong lg;
+//jfloat f;
+ jdouble d;
+ jclass dat;
+ jobject datobj;
+ jstring jst = nullptr;
+ jthrowable exc;
+ jmethodID dtc, setid = nullptr;
+
+ switch (val->GetType()) {
+ case TYPE_STRING:
+ setid = env->GetMethodID(jdi, "SetStringParm", "(ILjava/lang/String;)V");
+
+ if (setid == nullptr) {
+ strcpy(g->Message, "Cannot fing method SetStringParm");
+ return true;
+ } // endif setid
+
+ jst = env->NewStringUTF(val->GetCharValue());
+ env->CallVoidMethod(job, setid, i, jst);
+ break;
+ case TYPE_INT:
+ setid = env->GetMethodID(jdi, "SetIntParm", "(II)V");
+
+ if (setid == nullptr) {
+ strcpy(g->Message, "Cannot fing method SetIntParm");
+ return true;
+ } // endif setid
+
+ n = (jint)val->GetIntValue();
+ env->CallVoidMethod(job, setid, i, n);
+ break;
+ case TYPE_TINY:
+ case TYPE_SHORT:
+ setid = env->GetMethodID(jdi, "SetShortParm", "(IS)V");
+
+ if (setid == nullptr) {
+ strcpy(g->Message, "Cannot fing method SetShortParm");
+ return true;
+ } // endif setid
+
+ s = (jshort)val->GetShortValue();
+ env->CallVoidMethod(job, setid, i, s);
+ break;
+ case TYPE_BIGINT:
+ setid = env->GetMethodID(jdi, "SetBigintParm", "(IJ)V");
+
+ if (setid == nullptr) {
+ strcpy(g->Message, "Cannot fing method SetBigintParm");
+ return true;
+ } // endif setid
+
+ lg = (jlong)val->GetBigintValue();
+ env->CallVoidMethod(job, setid, i, lg);
+ break;
+ case TYPE_DOUBLE:
+ case TYPE_DECIM:
+ setid = env->GetMethodID(jdi, "SetDoubleParm", "(ID)V");
+
+ if (setid == nullptr) {
+ strcpy(g->Message, "Cannot fing method SetDoubleParm");
+ return true;
+ } // endif setid
+
+ d = (jdouble)val->GetFloatValue();
+ env->CallVoidMethod(job, setid, i, d);
+ break;
+ case TYPE_DATE:
+ if ((dat = env->FindClass("java/sql/Timestamp")) == nullptr) {
+ strcpy(g->Message, "Cannot find Timestamp class");
+ return true;
+ } else if (!(dtc = env->GetMethodID(dat, "<init>", "(J)V"))) {
+ strcpy(g->Message, "Cannot find Timestamp class constructor");
+ return true;
+ } // endif's
+
+ lg = (jlong)val->GetBigintValue() * 1000;
+
+ if ((datobj = env->NewObject(dat, dtc, lg)) == nullptr) {
+ strcpy(g->Message, "Cannot make Timestamp object");
+ return true;
+ } else if ((setid = env->GetMethodID(jdi, "SetTimestampParm",
+ "(ILjava/sql/Timestamp;)V")) == nullptr) {
+ strcpy(g->Message, "Cannot find method SetTimestampParm");
+ return true;
+ } // endif setid
+
+ env->CallVoidMethod(job, setid, i, datobj);
+ break;
+ default:
+ sprintf(g->Message, "Parm type %d not supported", val->GetType());
+ return true;
+ } // endswitch Type
+
+ if ((exc = env->ExceptionOccurred()) != nullptr) {
+ jboolean isCopy = false;
+ jmethodID tid = env->GetMethodID(env->FindClass("java/lang/Object"), "toString", "()Ljava/lang/String;");
+ jstring s = (jstring)env->CallObjectMethod(exc, tid);
+ const char* utf = env->GetStringUTFChars(s, &isCopy);
+ sprintf(g->Message, "SetParam: %s", utf);
+ env->DeleteLocalRef(s);
+ env->ExceptionClear();
+ rc = true;
+ } // endif exc
+
+ if (jst)
+ env->DeleteLocalRef(jst);
+
+ return rc;
+ } // end of SetParam
+
+#if 0
+ /***********************************************************************/
+ /* Get the list of Data Sources and set it in qrp. */
+ /***********************************************************************/
+ bool JDBConn::GetDataSources(PQRYRES qrp)
+ {
+ bool rv = false;
+ UCHAR *dsn, *des;
+ UWORD dir = SQL_FETCH_FIRST;
+ SWORD n1, n2, p1, p2;
+ PCOLRES crp1 = qrp->Colresp, crp2 = qrp->Colresp->Next;
+ RETCODE rc;
+
+ n1 = crp1->Clen;
+ n2 = crp2->Clen;
+
+ try {
+ rc = SQLAllocEnv(&m_henv);
+
+ if (!Check(rc))
+ ThrowDJX(rc, "SQLAllocEnv"); // Fatal
+
+ for (int i = 0; i < qrp->Maxres; i++) {
+ dsn = (UCHAR*)crp1->Kdata->GetValPtr(i);
+ des = (UCHAR*)crp2->Kdata->GetValPtr(i);
+ rc = SQLDataSources(m_henv, dir, dsn, n1, &p1, des, n2, &p2);
+
+ if (rc == SQL_NO_DATA_FOUND)
+ break;
+ else if (!Check(rc))
+ ThrowDJX(rc, "SQLDataSources");
+
+ qrp->Nblin++;
+ dir = SQL_FETCH_NEXT;
+ } // endfor i
+
+ }
+ catch (DJX *x) {
+ sprintf(m_G->Message, "%s: %s", x->m_Msg, x->GetErrorMessage(0));
+ rv = true;
+ } // end try/catch
+
+ Close();
+ return rv;
+ } // end of GetDataSources
+#endif // 0
+
+ /***********************************************************************/
+ /* Get the list of Drivers and set it in qrp. */
+ /***********************************************************************/
+ bool JDBConn::GetDrivers(PQRYRES qrp)
+ {
+ PSZ sval;
+ int i, n, size;
+ PCOLRES crp;
+ jstring js;
+ jmethodID gdid = env->GetMethodID(jdi, "GetDrivers", "([Ljava/lang/String;I)I");
+
+ if (env->ExceptionCheck()) {
+ strcpy(m_G->Message, "ERROR: method GetDrivers() not found!");
+ env->ExceptionDescribe();
+ env->ExceptionClear();
+ return true;
+ } // endif Check
+
+ // Build the java string array
+ jobjectArray s = env->NewObjectArray(4 * qrp->Maxres,
+ env->FindClass("java/lang/String"), NULL);
+
+ size = env->CallIntMethod(job, gdid, s, qrp->Maxres);
+
+ for (i = 0, n = 0; i < size; i++) {
+ crp = qrp->Colresp;
+ js = (jstring)env->GetObjectArrayElement(s, n++);
+ sval = (PSZ)env->GetStringUTFChars(js, 0);
+ crp->Kdata->SetValue(sval, i);
+ crp = crp->Next;
+ js = (jstring)env->GetObjectArrayElement(s, n++);
+ sval = (PSZ)env->GetStringUTFChars(js, 0);
+ crp->Kdata->SetValue(sval, i);
+ crp = crp->Next;
+ js = (jstring)env->GetObjectArrayElement(s, n++);
+ sval = (PSZ)env->GetStringUTFChars(js, 0);
+ crp->Kdata->SetValue(sval, i);
+ crp = crp->Next;
+ js = (jstring)env->GetObjectArrayElement(s, n++);
+ sval = (PSZ)env->GetStringUTFChars(js, 0);
+ crp->Kdata->SetValue(sval, i);
+ } // endfor i
+
+ // Not used anymore
+ env->DeleteLocalRef(s);
+
+ qrp->Nblin = size;
+ return false;
+ } // end of GetDrivers
+
+ /**************************************************************************/
+ /* GetMetaData: constructs the result blocks containing the */
+ /* description of all the columns of an SQL command. */
+ /**************************************************************************/
+ PQRYRES JDBConn::GetMetaData(PGLOBAL g, char *src)
+ {
+ static int buftyp[] = {TYPE_STRING, TYPE_INT, TYPE_INT,
+ TYPE_INT, TYPE_INT};
+ static XFLD fldtyp[] = {FLD_NAME, FLD_TYPE, FLD_PREC,
+ FLD_SCALE, FLD_NULL };
+ static unsigned int length[] = {0, 6, 10, 6, 6};
+ const char *name;
+ int len, qcol = 5;
+ PQRYRES qrp = NULL;
+ PCOLRES crp;
+ USHORT i;
+ jint *n;
+ jstring label;
+ jmethodID colid;
+ int rc = ExecSQLcommand(src);
+
+ if (rc == RC_NF) {
+ strcpy(g->Message, "Srcdef is not returning a result set");
+ return NULL;
+ } else if ((rc) == RC_FX) {
+ return NULL;
+ } else if (m_Ncol == 0) {
+ strcpy(g->Message, "Invalid Srcdef");
+ return NULL;
+ } // endif's
+
+ colid = env->GetMethodID(jdi, "ColumnDesc", "(I[I)Ljava/lang/String;");
+
+ if (colid == nullptr) {
+ strcpy(m_G->Message, "ERROR: method ColumnDesc() not found!");
+ return NULL;
+ } // endif colid
+
+ // Build the java string array
+ jintArray val = env->NewIntArray(4);
+
+ if (val == nullptr) {
+ strcpy(m_G->Message, "Cannot allocate jint array");
+ return NULL;
+ } // endif colid
+
+ // Get max column name length
+ len = GetMaxValue(5);
+ length[0] = (len > 0) ? len + 1 : 128;
+
+ /************************************************************************/
+ /* Allocate the structures used to refer to the result set. */
+ /************************************************************************/
+ if (!(qrp = PlgAllocResult(g, qcol, m_Ncol, IDS_COLUMNS + 3,
+ buftyp, fldtyp, length, false, true)))
+ return NULL;
+
+ // Some columns must be renamed
+ for (i = 0, crp = qrp->Colresp; crp; crp = crp->Next)
+ switch (++i) {
+ case 3: crp->Name = "Precision"; break;
+ case 4: crp->Name = "Scale"; break;
+ case 5: crp->Name = "Nullable"; break;
+ } // endswitch i
+
+ /************************************************************************/
+ /* Now get the results into blocks. */
+ /************************************************************************/
+ for (i = 0; i < m_Ncol; i++) {
+ label = (jstring)env->CallObjectMethod(job, colid, i + 1, val);
+ name = env->GetStringUTFChars(label, (jboolean)false);
+ crp = qrp->Colresp; // Column_Name
+ crp->Kdata->SetValue((char*)name, i);
+ n = env->GetIntArrayElements(val, 0);
+ crp = crp->Next; // Data_Type
+ crp->Kdata->SetValue((int)n[0], i);
+ crp = crp->Next; // Precision (length)
+ crp->Kdata->SetValue((int)n[1], i);
+ crp = crp->Next; // Scale
+ crp->Kdata->SetValue((int)n[2], i);
+ crp = crp->Next; // Nullable
+ crp->Kdata->SetValue((int)n[3], i);
+ qrp->Nblin++;
+ } // endfor i
+
+ /* Cleanup */
+ env->ReleaseIntArrayElements(val, n, 0);
+ Close();
+
+ /************************************************************************/
+ /* Return the result pointer for use by GetData routines. */
+ /************************************************************************/
+ return qrp;
+ } // end of GetMetaData
+
+ /***********************************************************************/
+ /* A helper class to split an optionally qualified table name into */
+ /* components. */
+ /* These formats are understood: */
+ /* "CatalogName.SchemaName.TableName" */
+ /* "SchemaName.TableName" */
+ /* "TableName" */
+ /***********************************************************************/
+ class SQLQualifiedName
+ {
+ static const uint max_parts= 3; // Catalog.Schema.Table
+ MYSQL_LEX_STRING m_part[max_parts];
+ char m_buf[512];
+
+ void lex_string_set(MYSQL_LEX_STRING *S, char *str, size_t length)
+ {
+ S->str= str;
+ S->length= length;
+ } // end of lex_string_set
+
+ void lex_string_shorten_down(MYSQL_LEX_STRING *S, size_t offs)
+ {
+ DBUG_ASSERT(offs <= S->length);
+ S->str+= offs;
+ S->length-= offs;
+ } // end of lex_string_shorten_down
+
+ /*********************************************************************/
+ /* Find the rightmost '.' delimiter and return the length */
+ /* of the qualifier, including the rightmost '.' delimier. */
+ /* For example, for the string {"a.b.c",5} it will return 4, */
+ /* which is the length of the qualifier "a.b." */
+ /*********************************************************************/
+ size_t lex_string_find_qualifier(MYSQL_LEX_STRING *S)
+ {
+ size_t i;
+ for (i= S->length; i > 0; i--)
+ {
+ if (S->str[i - 1] == '.')
+ {
+ S->str[i - 1]= '\0';
+ return i;
+ }
+ }
+ return 0;
+ } // end of lex_string_find_qualifier
+
+ public:
+ /*********************************************************************/
+ /* Initialize to the given optionally qualified name. */
+ /* NULL pointer in "name" is supported. */
+ /* name qualifier has precedence over schema. */
+ /*********************************************************************/
+ SQLQualifiedName(JCATPARM *cap)
+ {
+ const char *name = (const char *)cap->Tab;
+ char *db = (char *)cap->DB;
+ size_t len, i;
+
+ // Initialize the parts
+ for (i = 0; i < max_parts; i++)
+ lex_string_set(&m_part[i], NULL, 0);
+
+ if (name) {
+ // Initialize the first (rightmost) part
+ lex_string_set(&m_part[0], m_buf,
+ strmake(m_buf, name, sizeof(m_buf) - 1) - m_buf);
+
+ // Initialize the other parts, if exist.
+ for (i= 1; i < max_parts; i++) {
+ if (!(len= lex_string_find_qualifier(&m_part[i - 1])))
+ break;
+
+ lex_string_set(&m_part[i], m_part[i - 1].str, len - 1);
+ lex_string_shorten_down(&m_part[i - 1], len);
+ } // endfor i
+
+ } // endif name
+
+ // If it was not specified, set schema as the passed db name
+ if (db && !m_part[1].length)
+ lex_string_set(&m_part[1], db, strlen(db));
+
+ } // end of SQLQualifiedName
+
+ char *ptr(uint i)
+ {
+ DBUG_ASSERT(i < max_parts);
+ return (char *)(m_part[i].length ? m_part[i].str : NULL);
+ } // end of ptr
+
+ size_t length(uint i)
+ {
+ DBUG_ASSERT(i < max_parts);
+ return m_part[i].length;
+ } // end of length
+
+ }; // end of class SQLQualifiedName
+
+ /***********************************************************************/
+ /* Allocate recset and call SQLTables, SQLColumns or SQLPrimaryKeys. */
+ /***********************************************************************/
+ int JDBConn::GetCatInfo(JCATPARM *cap)
+ {
+ PGLOBAL& g = m_G;
+ void *buffer;
+ int i;
+ PSZ fnc = "Unknown";
+ uint n, ncol;
+ short len, tp;
+ int crow = 0;
+ PQRYRES qrp = cap->Qrp;
+ PCOLRES crp;
+ jboolean rc = false;
+// HSTMT hstmt = NULL;
+// SQLLEN *vl, *vlen = NULL;
+ PVAL *pval = NULL;
+ char* *pbuf = NULL;
+ jobjectArray parms;
+ jmethodID catid;
+
+ if (qrp->Maxres <= 0)
+ return 0; // 0-sized result"
+
+ SQLQualifiedName name(cap);
+
+ // Build the java string array
+ parms = env->NewObjectArray(4, env->FindClass("java/lang/String"), NULL);
+ env->SetObjectArrayElement(parms, 0, env->NewStringUTF(name.ptr(2)));
+ env->SetObjectArrayElement(parms, 1, env->NewStringUTF(name.ptr(1)));
+ env->SetObjectArrayElement(parms, 2, env->NewStringUTF(name.ptr(0)));
+
+ if (cap->Pat)
+ env->SetObjectArrayElement(parms, 3, env->NewStringUTF((const char*)cap->Pat));
+
+ // Now do call the proper JDBC API
+ switch (cap->Id) {
+ case CAT_COL:
+ fnc = "GetColumns";
+ break;
+ case CAT_TAB:
+ fnc = "GetTables";
+ break;
+#if 0
+ case CAT_KEY:
+ fnc = "SQLPrimaryKeys";
+ rc = SQLPrimaryKeys(hstmt, name.ptr(2), name.length(2),
+ name.ptr(1), name.length(1),
+ name.ptr(0), name.length(0));
+ break;
+ case CAT_STAT:
+ fnc = "SQLStatistics";
+ rc = SQLStatistics(hstmt, name.ptr(2), name.length(2),
+ name.ptr(1), name.length(1),
+ name.ptr(0), name.length(0),
+ cap->Unique, cap->Accuracy);
+ break;
+ case CAT_SPC:
+ ThrowDJX("SQLSpecialColumns not available yet");
+#endif // 0
+ default:
+ sprintf(g->Message, "Invalid SQL function id");
+ return -1;
+ } // endswitch infotype
+
+ catid = env->GetMethodID(jdi, fnc, "([Ljava/lang/String;)I");
+
+ if (catid == nullptr) {
+ sprintf(g->Message, "ERROR: method %s not found !", fnc);
+ return -1;
+ } // endif maxid
+
+ // call method
+ ncol = env->CallIntMethod(job, catid, parms);
+
+ // Not used anymore
+ env->DeleteLocalRef(parms);
+
+ // n because we no more ignore the first column
+ if ((n = qrp->Nbcol) > (int)ncol) {
+ strcpy(g->Message, MSG(COL_NUM_MISM));
+ return -1;
+ } // endif n
+
+ // Unconditional to handle STRBLK's
+ pval = (PVAL *)PlugSubAlloc(g, NULL, n * sizeof(PVAL));
+// vlen = (SQLLEN *)PlugSubAlloc(g, NULL, n * sizeof(SQLLEN));
+ pbuf = (char**)PlugSubAlloc(g, NULL, n * sizeof(char*));
+
+ // Prepare retrieving column values
+ for (n = 0, crp = qrp->Colresp; crp; crp = crp->Next) {
+ if (!(tp = GetJDBCType(crp->Type))) {
+ sprintf(g->Message, MSG(INV_COLUMN_TYPE), crp->Type, crp->Name);
+ return -1;
+ } // endif tp
+
+ if (!(len = GetTypeSize(crp->Type, crp->Length))) {
+ len = 255; // for STRBLK's
+ ((STRBLK*)crp->Kdata)->SetSorted(true);
+ } // endif len
+
+ pval[n] = AllocateValue(g, crp->Type, len);
+
+ if (crp->Type == TYPE_STRING) {
+ pbuf[n] = (char*)PlugSubAlloc(g, NULL, len);
+ buffer = pbuf[n];
+ } else
+ buffer = pval[n]->GetTo_Val();
+
+ n++;
+ } // endfor n
+
+ // Now fetch the result
+ // Extended fetch cannot be used because of STRBLK's
+ for (i = 0; i < qrp->Maxres; i++) {
+ if ((rc = Fetch(0)) == 0)
+ break;
+ else if (rc < 0)
+ return -1;
+
+ for (n = 0, crp = qrp->Colresp; crp; n++, crp = crp->Next) {
+ SetColumnValue(n + 1, nullptr, pval[n]);
+ crp->Kdata->SetValue(pval[n], i);
+ } // endfor n
+
+ } // endfor i
+
+ if (rc == RC_OK)
+ qrp->Truncated = true;
+
+ return i;
+ } // end of GetCatInfo
+
+ /***********************************************************************/
+ /* Allocate a CONNECT result structure from the JDBC result. */
+ /***********************************************************************/
+ PQRYRES JDBConn::AllocateResult(PGLOBAL g)
+ {
+ bool uns;
+ PJDBCCOL colp;
+ PCOLRES *pcrp, crp;
+ PQRYRES qrp;
+
+ if (!m_Rows) {
+ strcpy(g->Message, "Void result");
+ return NULL;
+ } // endif m_Res
+
+ /*********************************************************************/
+ /* Allocate the result storage for future retrieval. */
+ /*********************************************************************/
+ qrp = (PQRYRES)PlugSubAlloc(g, NULL, sizeof(QRYRES));
+ pcrp = &qrp->Colresp;
+ qrp->Continued = FALSE;
+ qrp->Truncated = FALSE;
+ qrp->Info = FALSE;
+ qrp->Suball = TRUE;
+ qrp->BadLines = 0;
+ qrp->Maxsize = m_Rows;
+ qrp->Maxres = m_Rows;
+ qrp->Nbcol = 0;
+ qrp->Nblin = 0;
+ qrp->Cursor = 0;
+
+ for (colp = (PJDBCCOL)m_Tdb->Columns; colp;
+ colp = (PJDBCCOL)colp->GetNext())
+ if (!colp->IsSpecial()) {
+ *pcrp = (PCOLRES)PlugSubAlloc(g, NULL, sizeof(COLRES));
+ crp = *pcrp;
+ pcrp = &crp->Next;
+ memset(crp, 0, sizeof(COLRES));
+ crp->Ncol = ++qrp->Nbcol;
+ crp->Name = colp->GetName();
+ crp->Type = colp->GetResultType();
+ crp->Prec = colp->GetScale();
+ crp->Length = colp->GetLength();
+ crp->Clen = colp->GetValue()->GetClen();
+ uns = colp->IsUnsigned();
+
+ if (!(crp->Kdata = AllocValBlock(g, NULL, crp->Type, m_Rows,
+ crp->Clen, 0, FALSE, TRUE, uns))) {
+ sprintf(g->Message, MSG(INV_RESULT_TYPE),
+ GetFormatType(crp->Type));
+ return NULL;
+ } // endif Kdata
+
+ if (!colp->IsNullable())
+ crp->Nulls = NULL;
+ else {
+ crp->Nulls = (char*)PlugSubAlloc(g, NULL, m_Rows);
+ memset(crp->Nulls, ' ', m_Rows);
+ } // endelse Nullable
+
+ colp->SetCrp(crp);
+ } // endif colp
+
+ *pcrp = NULL;
+ //qrp->Nblin = n;
+ return qrp;
+ } // end of AllocateResult
diff --git a/storage/connect/jdbconn.h b/storage/connect/jdbconn.h
new file mode 100644
index 00000000000..0646fee845b
--- /dev/null
+++ b/storage/connect/jdbconn.h
@@ -0,0 +1,172 @@
+/***********************************************************************/
+/* JDBConn.h : header file for the JDBC connection classes. */
+/***********************************************************************/
+//nclude <windows.h> /* Windows include file */
+//nclude <windowsx.h> /* Message crackers */
+
+/***********************************************************************/
+/* Included C-definition files required by the interface. */
+/***********************************************************************/
+#include "block.h"
+
+/***********************************************************************/
+/* JDBC interface. */
+/***********************************************************************/
+#include <jni.h>
+
+/***********************************************************************/
+/* Constants and defines. */
+/***********************************************************************/
+// Miscellaneous sizing info
+#define MAX_NUM_OF_MSG 10 // Max number of error messages
+//efine MAX_CURRENCY 30 // Max size of Currency($) string
+#define MAX_TNAME_LEN 32 // Max size of table names
+//efine MAX_FNAME_LEN 256 // Max size of field names
+//efine MAX_STRING_INFO 256 // Max size of string from SQLGetInfo
+//efine MAX_DNAME_LEN 256 // Max size of Recordset names
+#define MAX_CONNECT_LEN 512 // Max size of Connect string
+//efine MAX_CURSOR_NAME 18 // Max size of a cursor name
+#define DEFAULT_FIELD_TYPE 0 // TYPE_NULL
+
+#if !defined(__WIN__)
+typedef unsigned char *PUCHAR;
+#endif // !__WIN__
+
+// Field Flags, used to indicate status of fields
+//efine SQL_FIELD_FLAG_DIRTY 0x1
+//efine SQL_FIELD_FLAG_NULL 0x2
+
+// Update options flags
+//efine SQL_SETPOSUPDATES 0x0001
+//efine SQL_POSITIONEDSQL 0x0002
+//efine SQL_GDBOUND 0x0004
+
+enum JCATINFO {
+ CAT_TAB = 1, // JDBC Tables
+ CAT_COL = 2, // JDBC Columns
+ CAT_KEY = 3, // JDBC PrimaryKeys
+//CAT_STAT = 4, // SQLStatistics
+//CAT_SPC = 5 // SQLSpecialColumns
+};
+
+/***********************************************************************/
+/* This structure is used to control the catalog functions. */
+/***********************************************************************/
+typedef struct tagJCATPARM {
+ JCATINFO Id; // Id to indicate function
+ PQRYRES Qrp; // Result set pointer
+ PUCHAR DB; // Database (Schema)
+ PUCHAR Tab; // Table name or pattern
+ PUCHAR Pat; // Table type or column pattern
+} JCATPARM;
+
+// JDBC connection to a data source
+class TDBJDBC;
+class JDBCCOL;
+class JDBConn;
+class TDBXJDC;
+
+/***********************************************************************/
+/* JDBConn class. */
+/***********************************************************************/
+class JDBConn : public BLOCK {
+ friend class TDBJDBC;
+ friend class TDBXJDC;
+//friend PQRYRES GetColumnInfo(PGLOBAL, char*&, char *, int, PVBLK&);
+private:
+ JDBConn(); // Standard (unused) constructor
+
+public:
+ JDBConn(PGLOBAL g, TDBJDBC *tdbp);
+
+ int Open(PSZ jpath, PJPARM sop);
+ int Rewind(char *sql);
+ void Close(void);
+ PQRYRES AllocateResult(PGLOBAL g);
+
+ // Attributes
+public:
+ char *GetQuoteChar(void) { return m_IDQuoteChar; }
+ // Database successfully opened?
+ bool IsOpen(void) { return m_Opened; }
+//PSZ GetStringInfo(ushort infotype);
+ int GetMaxValue(int infotype);
+//PSZ GetConnect(void) { return m_Connect; }
+
+public:
+ // Operations
+ //void SetLoginTimeout(DWORD sec) {m_LoginTimeout = sec;}
+ //void SetQueryTimeout(DWORD sec) {m_QueryTimeout = sec;}
+ //void SetUserName(PSZ user) {m_User = user;}
+ //void SetUserPwd(PSZ pwd) {m_Pwd = pwd;}
+ int GetResultSize(char *sql, JDBCCOL *colp);
+ int ExecuteQuery(char *sql);
+ int ExecuteUpdate(char *sql);
+ int Fetch(int pos = 0);
+ bool PrepareSQL(char *sql);
+ int ExecuteSQL(void);
+ bool SetParam(JDBCCOL *colp);
+ int ExecSQLcommand(char *sql);
+ void SetColumnValue(int rank, PSZ name, PVAL val);
+ int GetCatInfo(JCATPARM *cap);
+ //bool GetDataSources(PQRYRES qrp);
+ bool GetDrivers(PQRYRES qrp);
+ PQRYRES GetMetaData(PGLOBAL g, char *src);
+
+public:
+ // Set special options
+//void OnSetOptions(HSTMT hstmt);
+
+ // Implementation
+public:
+ //virtual ~JDBConn();
+
+ // JDBC operations
+protected:
+//bool Check(RETCODE rc);
+//void ThrowDJX(int rc, PSZ msg/*, HSTMT hstmt = SQL_NULL_HSTMT*/);
+//void ThrowDJX(PSZ msg);
+//void AllocConnect(DWORD dwOptions);
+//void Connect(void);
+//bool DriverConnect(DWORD Options);
+//void VerifyConnect(void);
+//void GetConnectInfo(void);
+//void Free(void);
+
+protected:
+ // Members
+ PGLOBAL m_G;
+ TDBJDBC *m_Tdb;
+ JavaVM *jvm; // Pointer to the JVM (Java Virtual Machine)
+ JNIEnv *env; // Pointer to native interface
+ jclass jdi; // Pointer to the JdbcInterface class
+ jobject job; // The JdbcInterface class object
+ jmethodID xqid; // The ExecuteQuery method ID
+ jmethodID xuid; // The ExecuteUpdate method ID
+ jmethodID xid; // The Execute method ID
+ jmethodID grs; // The GetResult method ID
+ jmethodID readid; // The ReadNext method ID
+ jmethodID fetchid; // The Fetch method ID
+ jmethodID typid; // The ColumnType method ID
+ jmethodID prepid; // The CreatePrepStmt method ID
+ jmethodID xpid; // The ExecutePrep method ID
+ jmethodID pcid; // The ClosePrepStmt method ID
+ //DWORD m_LoginTimeout;
+//DWORD m_QueryTimeout;
+//DWORD m_UpdateOptions;
+ char m_IDQuoteChar[2];
+ PSZ m_Driver;
+ PSZ m_Url;
+ PSZ m_User;
+ PSZ m_Pwd;
+ int m_Ncol;
+ int m_Aff;
+ int m_Rows;
+ int m_Fetch;
+ int m_RowsetSize;
+ jboolean m_Updatable;
+ jboolean m_Transact;
+ jboolean m_Scrollable;
+ bool m_Opened;
+ bool m_Full;
+}; // end of JDBConn class definition
diff --git a/storage/connect/jsonudf.cpp b/storage/connect/jsonudf.cpp
index 25c77cea534..7b82ba2d627 100644
--- a/storage/connect/jsonudf.cpp
+++ b/storage/connect/jsonudf.cpp
@@ -533,7 +533,7 @@ PVAL JSNX::CalculateArray(PGLOBAL g, PJAR arp, int n)
/*********************************************************************************/
my_bool JSNX::CheckPath(PGLOBAL g)
{
- PJVAL val;
+ PJVAL val= NULL;
PJSON row = Row;
for (int i = 0; i < Nod && row; i++) {
@@ -1302,7 +1302,7 @@ static my_bool CalcLen(UDF_ARGS *args, my_bool obj,
{
char fn[_MAX_PATH];
unsigned long i, k, m, n;
- long fl, j = -1;
+ long fl= 0, j = -1;
reslen = args->arg_count + 2;
@@ -2087,7 +2087,7 @@ my_bool json_object_nonull_init(UDF_INIT *initid, UDF_ARGS *args,
char *json_object_nonull(UDF_INIT *initid, UDF_ARGS *args, char *result,
unsigned long *res_length, char *, char *)
{
- char *str;
+ char *str= 0;
PGLOBAL g = (PGLOBAL)initid->ptr;
if (!g->Xchk) {
@@ -2621,7 +2621,7 @@ char *json_item_merge(UDF_INIT *initid, UDF_ARGS *args, char *result,
} // endif Xchk
if (!CheckMemory(g, initid, args, 2, false, false, true)) {
- PJSON top;
+ PJSON top= 0;
PJVAL jvp;
PJSON jsp[2] = {NULL, NULL};
@@ -4721,7 +4721,7 @@ char *jbin_set_item(UDF_INIT *initid, UDF_ARGS *args, char *result,
my_bool b = true;
PJSON jsp;
PJSNX jsx;
- PJVAL jvp;
+ PJVAL jvp= 0;
PBSON bsp = NULL;
PGLOBAL g = (PGLOBAL)initid->ptr;
PGLOBAL gb = GetMemPtr(g, args, 0);
@@ -4742,6 +4742,7 @@ char *jbin_set_item(UDF_INIT *initid, UDF_ARGS *args, char *result,
if (!g->Xchk) {
if (CheckMemory(g, initid, args, 1, true, false, true)) {
PUSH_WARNING("CheckMemory error");
+ goto fin;
} else
jvp = MakeValue(g, args, 0);
diff --git a/storage/connect/maputil.cpp b/storage/connect/maputil.cpp
index c4e016f1511..87263b3adf6 100644
--- a/storage/connect/maputil.cpp
+++ b/storage/connect/maputil.cpp
@@ -190,8 +190,8 @@ bool CloseMemMap(void *memory, size_t dwSize)
{
if (memory) {
// All this must be redesigned
- int rc = msync(memory, dwSize, MS_SYNC);
- return (munmap(memory, dwSize) < 0) ? true : false;
+ int rc = msync((char*)memory, dwSize, MS_SYNC);
+ return (munmap((char*)memory, dwSize) < 0) ? true : false;
} else
return false;
diff --git a/storage/connect/mycat.cc b/storage/connect/mycat.cc
index 97ad980dd6a..da8be207237 100644
--- a/storage/connect/mycat.cc
+++ b/storage/connect/mycat.cc
@@ -80,6 +80,10 @@
#define NODBC
#include "tabodbc.h"
#endif // ODBC_SUPPORT
+#if defined(JDBC_SUPPORT)
+#define NJDBC
+#include "tabjdbc.h"
+#endif // ODBC_SUPPORT
#if defined(PIVOT_SUPPORT)
#include "tabpivot.h"
#endif // PIVOT_SUPPORT
@@ -140,7 +144,10 @@ TABTYPE GetTypeID(const char *type)
#ifdef ODBC_SUPPORT
: (!stricmp(type, "ODBC")) ? TAB_ODBC
#endif
- : (!stricmp(type, "MYSQL")) ? TAB_MYSQL
+#ifdef JDBC_SUPPORT
+ : (!stricmp(type, "JDBC")) ? TAB_JDBC
+#endif
+ : (!stricmp(type, "MYSQL")) ? TAB_MYSQL
: (!stricmp(type, "MYPRX")) ? TAB_MYSQL
: (!stricmp(type, "DIR")) ? TAB_DIR
#ifdef __WIN__
@@ -301,12 +308,12 @@ int GetIndexType(TABTYPE type)
break;
case TAB_MYSQL:
case TAB_ODBC:
- xtyp= 2;
+ case TAB_JDBC:
+ xtyp= 2;
break;
case TAB_VIR:
xtyp= 3;
break;
-// case TAB_ODBC:
default:
xtyp= 0;
break;
@@ -558,6 +565,9 @@ PRELDEF MYCAT::MakeTableDesc(PGLOBAL g, PTABLE tablep, LPCSTR am)
#if defined(ODBC_SUPPORT)
case TAB_ODBC: tdp= new(g) ODBCDEF; break;
#endif // ODBC_SUPPORT
+#if defined(JDBC_SUPPORT)
+ case TAB_JDBC: tdp= new(g)JDBCDEF; break;
+#endif // JDBC_SUPPORT
#if defined(__WIN__)
case TAB_MAC: tdp= new(g) MACDEF; break;
case TAB_WMI: tdp= new(g) WMIDEF; break;
diff --git a/storage/connect/myconn.cpp b/storage/connect/myconn.cpp
index ada0109a820..e9bd64cf8e6 100644
--- a/storage/connect/myconn.cpp
+++ b/storage/connect/myconn.cpp
@@ -959,11 +959,16 @@ void MYSQLC::FreeResult(void)
/***********************************************************************/
/* Place the cursor at the beginning of the result set. */
/***********************************************************************/
-void MYSQLC::Rewind(void)
+int MYSQLC::Rewind(PGLOBAL g, PSZ sql)
{
- if (m_Res)
- DataSeek(0);
+ int rc = RC_OK;
+ if (m_Res)
+ DataSeek(0);
+ else if (sql)
+ rc = ExecSQL(g, sql);
+
+ return rc;
} // end of Rewind
/***********************************************************************/
diff --git a/storage/connect/myconn.h b/storage/connect/myconn.h
index fa34edd804c..79f095f5c93 100644
--- a/storage/connect/myconn.h
+++ b/storage/connect/myconn.h
@@ -80,7 +80,7 @@ class DllItem MYSQLC {
int Fetch(PGLOBAL g, int pos);
char *GetCharField(int i);
int GetFieldLength(int i);
- void Rewind(void);
+ int Rewind(PGLOBAL g, PSZ sql);
void FreeResult(void);
void Close(void);
diff --git a/storage/connect/mysql-test/connect/r/drop-open-error.result b/storage/connect/mysql-test/connect/r/drop-open-error.result
new file mode 100644
index 00000000000..f0ad8553d8b
--- /dev/null
+++ b/storage/connect/mysql-test/connect/r/drop-open-error.result
@@ -0,0 +1,13 @@
+create table t1 (c varchar(8));
+create table tcon engine=connect table_type=mysql CONNECTION='mysql://root@localhost/test/t1' SRCDEF='select c from t1 where c in ("foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar")';
+ERROR HY000: Too long value for 'SRCDEF'
+drop table mdev9949;
+drop table t1;
+select @@secure_file_priv 'must be NULL';
+must be NULL
+NULL
+create table t1 (a char(16)) engine=myisam;
+insert into t1 values('Hello World!');
+create table t2 engine=connect file_name='foo/bar.txt' as select * from t1;
+ERROR HY000: Got error 174 'Open(a+b) error 2 on foo/bar.txt: No such file or directory' from CONNECT
+drop table t1;
diff --git a/storage/connect/mysql-test/connect/r/grant3.result b/storage/connect/mysql-test/connect/r/grant3.result
new file mode 100644
index 00000000000..2f9d37bdb35
--- /dev/null
+++ b/storage/connect/mysql-test/connect/r/grant3.result
@@ -0,0 +1,5 @@
+create table tcon (i int) engine=Connect table_type=DOS file_name='tcon.dos';
+create table tin (i int);
+create trigger tr after insert on tin for each row insert into tcon values (new.i);
+insert into tin values (1);
+drop table tin,tcon;
diff --git a/storage/connect/mysql-test/connect/r/mysql_index.result b/storage/connect/mysql-test/connect/r/mysql_index.result
index 4ebf10802ae..dd1864529ca 100644
--- a/storage/connect/mysql-test/connect/r/mysql_index.result
+++ b/storage/connect/mysql-test/connect/r/mysql_index.result
@@ -112,3 +112,324 @@ id msg
6 Six
DROP TABLE t2;
DROP TABLE t1;
+#
+# Make local FIX table with indices matricule and nom/prenom
+#
+CREATE TABLE t1
+(
+matricule INT(4) KEY NOT NULL field_format='Z',
+nom VARCHAR(16) NOT NULL,
+prenom VARCHAR(20) NOT NULL,
+sexe SMALLINT(1) NOT NULL COMMENT 'sexe 1:M 2:F',
+aanais INT(4) NOT NULL,
+mmnais INT(2) NOT NULL,
+ddentree DATE NOT NULL date_format='YYYYMM',
+ddnom DATE NOT NULL date_format='YYYYMM',
+brut INT(5) NOT NULL,
+net DOUBLE(8,2) NOT NULL,
+service INT(2) NOT NULL,
+sitmat CHAR(1) NOT NULL,
+formation CHAR(5) NOT NULL,
+INDEX NP(nom,prenom)
+) ENGINE=CONNECT TABLE_TYPE=FIX FILE_NAME='emp.txt' ENDING=2;
+#
+# Make MYSQL table with same indices
+#
+CREATE TABLE t2
+(
+matricule INT(4) KEY NOT NULL,
+nom VARCHAR(16) NOT NULL,
+prenom VARCHAR(20) NOT NULL,
+sexe SMALLINT(1) NOT NULL,
+aanais INT(4) NOT NULL,
+mmnais INT(2) NOT NULL,
+ddentree DATE NOT NULL date_format='YYYYMM',
+ddnom DATE NOT NULL date_format='YYYYMM',
+brut INT(5) NOT NULL,
+net DOUBLE(8,2) NOT NULL,
+service INT(2) NOT NULL,
+sitmat CHAR(1) NOT NULL,
+formation CHAR(5) NOT NULL,
+INDEX NP(nom,prenom)
+) ENGINE=CONNECT TABLE_TYPE=MYSQL CONNECTIOn='mysql://root@localhost/test/t1';
+SELECT * FROM t2 limit 10;
+matricule nom prenom sexe aanais mmnais ddentree ddnom brut net service sitmat formation
+5745 ESCOURCHE BENEDICTE 2 1935 7 1962-12-01 1994-05-01 18345 14275.50 0 M TECHN
+9692 VICENTE LAURENCE 2 1941 8 1967-10-01 1989-01-01 16212 13032.80 0 M ANGL
+9146 NICOLAS ROGER 1 1941 6 1964-07-01 1995-02-01 34173 25098.65 0 M SANS
+2985 TESSEREAU MARIE HELENE 2 1941 9 1967-01-01 1990-01-01 19323 14933.78 0 V SANS
+3368 MOGADOR ALAIN 1 1941 1 1961-09-01 1993-11-01 43303 31420.55 0 C SANS
+7394 CHAUSSEE ERIC DENIS 1 1944 9 1965-11-01 1983-12-01 32002 23583.86 0 M ANGL
+4655 MAILLOT GEORGES 1 1945 5 1970-09-01 1986-12-01 24700 18541.64 0 C ANGL
+2825 CAMILLE NADINE 2 1956 9 1994-01-01 1993-01-01 19494 15050.45 0 M SANS
+1460 BRUYERES JEAN MARC 1 1958 8 1984-08-01 1988-05-01 20902 15980.07 0 M SANS
+4974 LONES GERARD 1 1959 10 1979-01-01 1994-12-01 16081 12916.70 0 M SANS
+SELECT matricule, nom, prenom FROM t2 WHERE nom IN ('FOCH','MOGADOR');
+matricule nom prenom
+1977 FOCH BERNADETTE
+5707 FOCH DENIS
+2552 FOCH FRANCK
+2634 FOCH JOCELYNE
+5765 FOCH ROBERT
+4080 FOCH SERGE
+3368 MOGADOR ALAIN
+SELECT matricule, nom, prenom FROM t2 WHERE nom = 'FOCH' OR nom = 'MOGADOR';
+matricule nom prenom
+1977 FOCH BERNADETTE
+5707 FOCH DENIS
+2552 FOCH FRANCK
+2634 FOCH JOCELYNE
+5765 FOCH ROBERT
+4080 FOCH SERGE
+3368 MOGADOR ALAIN
+SELECT matricule, nom, prenom FROM t2 WHERE nom < 'ADDAX';
+matricule nom prenom
+4552 ABBADIE MONIQUE
+307 ABBAYE ANNICK
+6627 ABBAYE GERALD
+7961 ABBE KATIA
+1340 ABBE MICHELE
+9270 ABBE SOPHIE
+2945 ABBEVILLE PASCAL
+8596 ABEBERRY PATRICK
+6399 ABEILLES RENE
+8673 ABEL JEAN PIERRE
+6124 ABELIAS DELIA
+6314 ABERDEN EVELYNE
+895 ABORD CHANTAL
+2728 ABOUT CATHERINE MARIE
+398 ABREUVOIR JEAN LUC
+1122 ACACIAS SERGE
+1644 ACARDIE BEATE
+115 ACHILLE JACQUES
+4038 ADAM JANICK
+3395 ADAM JEAN CLAUDE
+SELECT matricule, nom, prenom FROM t2 WHERE nom <= 'ABEL';
+matricule nom prenom
+4552 ABBADIE MONIQUE
+307 ABBAYE ANNICK
+6627 ABBAYE GERALD
+7961 ABBE KATIA
+1340 ABBE MICHELE
+9270 ABBE SOPHIE
+2945 ABBEVILLE PASCAL
+8596 ABEBERRY PATRICK
+6399 ABEILLES RENE
+8673 ABEL JEAN PIERRE
+SELECT matricule, nom, prenom FROM t2 WHERE nom > 'YVON';
+matricule nom prenom
+9742 YZENGREMER MICHEL
+8738 ZILINA JEAN LOUIS
+5357 ZOLA BERNARD
+5441 ZOLA BRIGITTE
+1325 ZOLA CHRISTINE
+4859 ZORI CATHERINE
+4102 ZOUAVES ALAIN
+SELECT matricule, nom, prenom FROM t2 WHERE nom >= 'YVON';
+matricule nom prenom
+5389 YVON CAROLE
+9742 YZENGREMER MICHEL
+8738 ZILINA JEAN LOUIS
+5357 ZOLA BERNARD
+5441 ZOLA BRIGITTE
+1325 ZOLA CHRISTINE
+4859 ZORI CATHERINE
+4102 ZOUAVES ALAIN
+SELECT matricule, nom, prenom FROM t2 WHERE nom <= 'ABEL' OR nom > 'YVON';
+matricule nom prenom
+4552 ABBADIE MONIQUE
+307 ABBAYE ANNICK
+6627 ABBAYE GERALD
+7961 ABBE KATIA
+1340 ABBE MICHELE
+9270 ABBE SOPHIE
+2945 ABBEVILLE PASCAL
+8596 ABEBERRY PATRICK
+6399 ABEILLES RENE
+8673 ABEL JEAN PIERRE
+9742 YZENGREMER MICHEL
+8738 ZILINA JEAN LOUIS
+5357 ZOLA BERNARD
+5441 ZOLA BRIGITTE
+1325 ZOLA CHRISTINE
+4859 ZORI CATHERINE
+4102 ZOUAVES ALAIN
+SELECT matricule, nom, prenom FROM t2 WHERE nom > 'HELEN' AND nom < 'HEROS';
+matricule nom prenom
+9096 HELENA PHILIPPE
+3309 HELENE ISABELLE
+8365 HELIOTROPES LISE
+4666 HELLEN PIERRE
+5781 HELSINKI DANIELLE
+7626 HENIN PHILIPPE
+4254 HENIN SERGE
+2673 HENNER LILIANE
+9716 HENRI JACQUES
+2085 HEOL GUY PAUL
+2579 HERANDIERE PIERRE
+7093 HERAULTS DANIEL
+4050 HERBILLON FRANCOIS
+9231 HERBILLON MADELEINE
+1291 HERMITAGE XAVIER
+6185 HERMITTE FRANCOIS
+403 HERMITTE PHILIPPE
+9749 HEROLD ISABELLE
+SELECT matricule, nom, prenom FROM t2 WHERE nom BETWEEN 'HELEN' AND 'HEROS';
+matricule nom prenom
+6199 HELEN MARTIAL
+9096 HELENA PHILIPPE
+3309 HELENE ISABELLE
+8365 HELIOTROPES LISE
+4666 HELLEN PIERRE
+5781 HELSINKI DANIELLE
+7626 HENIN PHILIPPE
+4254 HENIN SERGE
+2673 HENNER LILIANE
+9716 HENRI JACQUES
+2085 HEOL GUY PAUL
+2579 HERANDIERE PIERRE
+7093 HERAULTS DANIEL
+4050 HERBILLON FRANCOIS
+9231 HERBILLON MADELEINE
+1291 HERMITAGE XAVIER
+6185 HERMITTE FRANCOIS
+403 HERMITTE PHILIPPE
+9749 HEROLD ISABELLE
+8445 HEROS SYLVIE
+SELECT matricule, nom, prenom FROM t2 WHERE nom BETWEEN 'HELEN' AND 'HEROS' AND prenom = 'PHILIPPE';
+matricule nom prenom
+9096 HELENA PHILIPPE
+7626 HENIN PHILIPPE
+403 HERMITTE PHILIPPE
+SELECT matricule, nom, prenom FROM t2 ORDER BY nom LIMIT 10;
+matricule nom prenom
+4552 ABBADIE MONIQUE
+6627 ABBAYE GERALD
+307 ABBAYE ANNICK
+7961 ABBE KATIA
+1340 ABBE MICHELE
+9270 ABBE SOPHIE
+2945 ABBEVILLE PASCAL
+8596 ABEBERRY PATRICK
+6399 ABEILLES RENE
+8673 ABEL JEAN PIERRE
+SELECT a.nom, a.prenom, b.nom FROM t1 a STRAIGHT_JOIN t2 b ON a.prenom = b.prenom WHERE a.nom = 'FOCH' AND a.nom != b.nom;
+nom prenom nom
+FOCH SERGE ACACIAS
+FOCH ROBERT AGRIANT
+FOCH JOCELYNE ALEXIS
+FOCH DENIS AMBOISE
+FOCH SERGE ANDALUCIA
+FOCH ROBERT ANNECY
+FOCH SERGE ARCACHON
+FOCH JOCELYNE AUGUSTE
+FOCH JOCELYNE BASSE
+FOCH SERGE BEACH
+FOCH FRANCK BEARN
+FOCH SERGE BELLES
+FOCH DENIS BERARD
+FOCH DENIS BERIN
+FOCH BERNADETTE BERTIN
+FOCH DENIS BILLEHOU
+FOCH DENIS BOILEAU
+FOCH BERNADETTE BOISSY
+FOCH ROBERT BONVIN
+FOCH SERGE BOUTON
+FOCH SERGE BREUIL
+FOCH SERGE CARREFOUR
+FOCH JOCELYNE CARRERE
+FOCH JOCELYNE CHAPELLE
+FOCH SERGE CHATEAU
+FOCH ROBERT CHENIER
+FOCH SERGE COLLETTE
+FOCH DENIS CONNE
+FOCH SERGE COOLE
+FOCH DENIS COULOUBRIER
+FOCH DENIS COUTURIER
+FOCH ROBERT CURAT
+FOCH ROBERT DAUDET
+FOCH SERGE ECLUSE
+FOCH SERGE EGUILLON
+FOCH DENIS EPINETTES
+FOCH DENIS FIGOURNAS
+FOCH JOCELYNE FLEMING
+FOCH JOCELYNE GAMBADES
+FOCH ROBERT GIOTERAIE
+FOCH SERGE GOAS
+FOCH ROBERT GRAFFIANE
+FOCH SERGE GREFFIER
+FOCH ROBERT GUILLOTIERE
+FOCH SERGE HENIN
+FOCH BERNADETTE HUNTZIGER
+FOCH FRANCK ILLIERS
+FOCH DENIS ISTANBUL
+FOCH DENIS ITALIE
+FOCH SERGE JARDIN
+FOCH FRANCK JEANPIERRE
+FOCH JOCELYNE KENNEDY
+FOCH FRANCK LABBE
+FOCH DENIS LACATE
+FOCH FRANCK LACOMBE
+FOCH ROBERT LAMOTHE
+FOCH BERNADETTE LATECOERE
+FOCH BERNADETTE LEGER
+FOCH SERGE LEONIE
+FOCH FRANCK LEROY
+FOCH SERGE LOZERE
+FOCH DENIS MAROLLES
+FOCH ROBERT MARRONIERS
+FOCH SERGE MARSAT
+FOCH SERGE MONTAGNE
+FOCH FRANCK MONTALEIGNE
+FOCH DENIS MONTELIER
+FOCH DENIS MONTILS
+FOCH BERNADETTE MONTJUSTIN
+FOCH SERGE MORIZET
+FOCH ROBERT NIMES
+FOCH ROBERT NORD
+FOCH SERGE NOVEMBRE
+FOCH BERNADETTE ONZE
+FOCH SERGE ORANGERIE
+FOCH FRANCK ORVEAU
+FOCH BERNADETTE PALMAROLE
+FOCH JOCELYNE PEYBERT
+FOCH ROBERT PEYNIBLOU
+FOCH ROBERT PIECE
+FOCH JOCELYNE PIED
+FOCH ROBERT PLAGNE
+FOCH SERGE PLAISANCE
+FOCH BERNADETTE PLOUHARNEL
+FOCH DENIS POINTE
+FOCH ROBERT POMMERY
+FOCH JOCELYNE PONTAROUX
+FOCH DENIS PORTO
+FOCH ROBERT PRESIDENT
+FOCH ROBERT PUJADE
+FOCH FRANCK PURPAN
+FOCH ROBERT QUILICHINI
+FOCH DENIS REINOTS
+FOCH DENIS REMPART
+FOCH SERGE RESISTANCE
+FOCH SERGE RESTANQUES
+FOCH ROBERT RIOU
+FOCH FRANCK ROCQUENCOURT
+FOCH ROBERT ROLL
+FOCH ROBERT ROSSA
+FOCH SERGE ROSSAYS
+FOCH DENIS ROUSSIER
+FOCH FRANCK RUSSIE
+FOCH ROBERT SABLONS
+FOCH SERGE SARTRE
+FOCH SERGE SAVIGNAC
+FOCH SERGE SEGUR
+FOCH ROBERT STRASBOURG
+FOCH ROBERT TIRE
+FOCH DENIS TORTE
+FOCH DENIS TOULON
+FOCH ROBERT TUBY
+FOCH DENIS VALMANTE
+FOCH SERGE VANOEL
+FOCH ROBERT VIARMES
+FOCH SERGE WILSON
+DROP TABLE t2;
+DROP TABLE t1;
diff --git a/storage/connect/mysql-test/connect/r/odbc_firebird.result b/storage/connect/mysql-test/connect/r/odbc_firebird.result
index 7688c188f59..b0c2582abeb 100644
--- a/storage/connect/mysql-test/connect/r/odbc_firebird.result
+++ b/storage/connect/mysql-test/connect/r/odbc_firebird.result
@@ -1,58 +1,123 @@
SET NAMES utf8;
CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CONNECTION='Bad connection string';
-ERROR HY000: SQLDriverConnect: [unixODBC][Driver Manager]Data source name not found, and no default driver specified
CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CATFUNC=Sources;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`Name` varchar(256) NOT NULL,
- `Description` varchar(256) NOT NULL
+ `Description` varchar(256) DEFAULT NULL
) ENGINE=CONNECT DEFAULT CHARSET=latin1 `TABLE_TYPE`='ODBC' `CATFUNC`='Sources'
SELECT * FROM t1;
Name Description
-Firebird Firebird
+dBASE Files Microsoft Access dBASE Driver (*.dbf, *.ndx, *.mdx)
+PLUGDB_DEBUG PLUGODBC_Driver
+PLUGDB_ODBC PLUGODBC_Driver
+SafeDB_ODBC SDB_ODBC_Driver
+Firebird Firebird/InterBase(r) driver
+ConnectEngineXLS Microsoft Excel Driver (*.xls)
+Excel Files Microsoft Excel Driver (*.xls, *.xlsx, *.xlsm, *.xlsb)
+MariaODBC MySQL ODBC 5.2a Driver
+MariaODBCbeta MariaDB ODBC 1.0 Driver
+MyODBC MySQL ODBC 5.2a Driver
+MS Access Database Microsoft Access Driver (*.mdb, *.accdb)
+MS Access Db1 Microsoft Access Driver (*.mdb)
+MySQL-ANSI MySQL ODBC 5.3 ANSI Driver
+MySQL-Unicode MySQL ODBC 5.3 Unicode Driver
+Xtreme Sample Database 2008 Microsoft Access Driver (*.mdb)
+PlugDB test PLUGODBC_Driver
+SQLite3 Datasource SQLite3 ODBC Driver
+SQLite Datasource SQLite ODBC Driver
+SQLite UTF-8 Datasource SQLite ODBC (UTF-8) Driver
+ORACLE_TEST Oracle in XE
+ConnectEnginePostgresql PostgreSQL ODBC Driver(ANSI)
+ConnectEngineOracle Oracle in XE
+ConnectEngineSQLServer SQL Server
DROP TABLE t1;
CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CATFUNC=Drivers;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`Description` char(128) NOT NULL,
- `Attributes` varchar(256) NOT NULL
+ `Attributes` varchar(256) DEFAULT NULL
) ENGINE=CONNECT DEFAULT CHARSET=latin1 `TABLE_TYPE`='ODBC' `CATFUNC`='Drivers'
SELECT * FROM t1;
Description Attributes
-Firebird Description=Firebird ODBC Driver in usr;Driver=/usr/local/lib/libOdbcFb.so;Setup=/usr/local/lib/libOdbcFb.so;FileUsage=1;
+SQL Server UsageCount=1;SQLLevel=1;FileUsage=0;DriverODBCVer=03.50;ConnectFunctions=YYY;APILevel=2;CPTimeout=60;
+Microsoft ODBC for Oracle UsageCount=1;SQLLevel=1;FileUsage=0;DriverODBCVer=02.50;ConnectFunctions=YYY;APILevel=1;CPTimeout=120;
+Microsoft Access Driver (*.mdb) UsageCount=1;APILevel=1;ConnectFunctions=YYN;DriverODBCVer=02.50;FileUsage=2;FileExtns=*.mdb;SQLLevel=0;
+Microsoft Access-Treiber (*.mdb) UsageCount=1;APILevel=1;ConnectFunctions=YYN;DriverODBCVer=02.50;FileUsage=2;FileExtns=*.mdb;SQLLevel=0;
+Driver do Microsoft Access (*.mdb) UsageCount=1;APILevel=1;ConnectFunctions=YYN;DriverODBCVer=02.50;FileUsage=2;FileExtns=*.mdb;SQLLevel=0;
+Microsoft dBase Driver (*.dbf) UsageCount=1;APILevel=1;ConnectFunctions=YYN;DriverODBCVer=02.50;FileUsage=1;FileExtns=*.dbf,*.ndx,*.mdx;SQLLevel=0;
+Microsoft dBase-Treiber (*.dbf) UsageCount=1;APILevel=1;ConnectFunctions=YYN;DriverODBCVer=02.50;FileUsage=1;FileExtns=*.dbf,*.ndx,*.mdx;SQLLevel=0;
+Driver do Microsoft dBase (*.dbf) UsageCount=1;APILevel=1;ConnectFunctions=YYN;DriverODBCVer=02.50;FileUsage=1;FileExtns=*.dbf,*.ndx,*.mdx;SQLLevel=0;
+Microsoft Excel Driver (*.xls) UsageCount=1;APILevel=1;ConnectFunctions=YYN;DriverODBCVer=02.50;FileUsage=1;FileExtns=*.xls;SQLLevel=0;
+Microsoft Excel-Treiber (*.xls) UsageCount=1;APILevel=1;ConnectFunctions=YYN;DriverODBCVer=02.50;FileUsage=1;FileExtns=*.xls;SQLLevel=0;
+Driver do Microsoft Excel(*.xls) UsageCount=1;APILevel=1;ConnectFunctions=YYN;DriverODBCVer=02.50;FileUsage=1;FileExtns=*.xls;SQLLevel=0;
+Microsoft Paradox Driver (*.db ) UsageCount=1;APILevel=1;ConnectFunctions=YYN;DriverODBCVer=02.50;FileUsage=1;FileExtns=*.db;SQLLevel=0;
+Microsoft Paradox-Treiber (*.db ) UsageCount=1;APILevel=1;ConnectFunctions=YYN;DriverODBCVer=02.50;FileUsage=1;FileExtns=*.db;SQLLevel=0;
+Driver do Microsoft Paradox (*.db ) UsageCount=1;APILevel=1;ConnectFunctions=YYN;DriverODBCVer=02.50;FileUsage=1;FileExtns=*.db;SQLLevel=0;
+Microsoft Text Driver (*.txt; *.csv) UsageCount=1;APILevel=1;ConnectFunctions=YYN;DriverODBCVer=02.50;FileUsage=1;FileExtns=*.,*.asc,*.csv,*.tab,*.txt,*.csv;SQLLevel=0;
+Microsoft Text-Treiber (*.txt; *.csv) UsageCount=1;APILevel=1;ConnectFunctions=YYN;DriverODBCVer=02.50;FileUsage=1;FileExtns=*.,*.asc,*.csv,*.tab,*.txt,*.csv;SQLLevel=0;
+Driver da Microsoft para arquivos texto (*.txt; *.csv) UsageCount=1;APILevel=1;ConnectFunctions=YYN;DriverODBCVer=02.50;FileUsage=1;FileExtns=*.,*.asc,*.csv,*.tab,*.txt,*.csv;SQLLevel=0;
+Microsoft Visual FoxPro Driver UsageCount=1;APILevel=0;ConnectFunctions=YYN;DriverODBCVer=02.50;FileUsage=1;FileExtns=*.dbf,*.cdx,*.idx,*.fpt;SQLLevel=0;
+Microsoft FoxPro VFP Driver (*.dbf) UsageCount=1;APILevel=0;ConnectFunctions=YYN;DriverODBCVer=02.50;FileUsage=1;FileExtns=*.dbf,*.cdx,*.idx,*.fpt;SQLLevel=0;
+Microsoft dBase VFP Driver (*.dbf) UsageCount=1;APILevel=0;ConnectFunctions=YYN;DriverODBCVer=02.50;FileUsage=1;FileExtns=*.dbf,*.cdx,*.idx,*.fpt;SQLLevel=0;
+Microsoft Visual FoxPro-Treiber UsageCount=1;APILevel=0;ConnectFunctions=YYN;DriverODBCVer=02.50;FileUsage=1;FileExtns=*.dbf,*.cdx,*.idx,*.fpt;SQLLevel=0;
+Driver para o Microsoft Visual FoxPro UsageCount=1;APILevel=0;ConnectFunctions=YYN;DriverODBCVer=02.50;FileUsage=1;FileExtns=*.dbf,*.cdx,*.idx,*.fpt;SQLLevel=0;
+SQL Native Client UsageCount=1;APILevel=2;ConnectFunctions=YYY;CPTimeout=60;DriverODBCVer=09.00;FileUsage=0;SQLLevel=1;
+CR Sybase Wire Protocol ODBC Driver 6.0 UsageCount=1;APILevel=1;ConnectFunctions=YYY;DriverODBCVer=3.52;FileUsage=0;SQLLevel=0;CPTimeout=60;HelpRootDirectory=C:\Program Files\SAP BusinessObjects\SAP BusinessObjects Enterprise XI 4.0\win32_x86\odbc\help;
+CR SQL Server Native Wire Protocol ODBC Driver 6.0 UsageCount=1;APILevel=1;ConnectFunctions=YYY;DriverODBCVer=3.52;FileUsage=0;SQLLevel=1;CPTimeout=60;HelpRootDirectory=C:\Program Files\SAP BusinessObjects\SAP BusinessObjects Enterprise XI 4.0\win32_x86\odbc\help;
+CR SQL Server Classic Wire Protocol ODBC Driver 6.0 UsageCount=1;APILevel=1;ConnectFunctions=YYY;DriverODBCVer=3.52;FileUsage=0;SQLLevel=1;CPTimeout=60;HelpRootDirectory=C:\Program Files\SAP BusinessObjects\SAP BusinessObjects Enterprise XI 4.0\win32_x86\odbc\help;
+CR TextFile ODBC Driver 6.0 UsageCount=1;APILevel=1;ConnectFunctions=YYY;DriverODBCVer=3.52;FileUsage=1;FileExtns=*.*;SQLLevel=0;CPTimeout=60;HelpRootDirectory=C:\Program Files\SAP BusinessObjects\SAP BusinessObjects Enterprise XI 4.0\win32_x86\odbc\help;
+PLUGODBC_Driver UsageCount=1;
+SDB_ODBC_Driver UsageCount=2;
+Microsoft Access Text Driver (*.txt, *.csv) SQLLevel=0;FileExtns=*.txt, *.csv;FileUsage=2;DriverODBCVer=02.50;ConnectFunctions=YYN;APILevel=1;UsageCount=3;
+Microsoft Access dBASE Driver (*.dbf, *.ndx, *.mdx) SQLLevel=0;FileExtns=*.dbf, *.ndx, *.mdx;FileUsage=2;DriverODBCVer=02.50;ConnectFunctions=YYN;APILevel=1;UsageCount=3;
+Microsoft Excel Driver (*.xls, *.xlsx, *.xlsm, *.xlsb) SQLLevel=0;FileExtns=*.xls,*.xlsx, *.xlsb;FileUsage=2;DriverODBCVer=02.50;ConnectFunctions=YYN;APILevel=1;UsageCount=3;
+Microsoft Access Driver (*.mdb, *.accdb) SQLLevel=0;FileExtns=*.mdb,*.accdb;FileUsage=2;DriverODBCVer=02.50;ConnectFunctions=YYN;APILevel=1;UsageCount=3;
+SQLite3 ODBC Driver UsageCount=1;
+SQLite ODBC Driver UsageCount=1;
+SQLite ODBC (UTF-8) Driver UsageCount=1;
+Oracle in XE ConnectionFunctions=YYY;DriverODBCVer=03.51;CPTimeout=60;FileUsage=0;APILevel=1;SQLLevel=1;
+Oracle in instantclient_12_1 APILevel=1;ConnectionFunctions=YYY;CPTimeout=60;DriverODBCVer=03.51;FileUsage=0;SQLLevel=1;
+PostgreSQL ODBC Driver(ANSI) APILevel=1;ConnectFunctions=YYN;DriverODBCVer=09.02.0100;FileUsage=0;SQLLevel=1;
+PostgreSQL ODBC Driver(UNICODE) APILevel=1;ConnectFunctions=YYN;DriverODBCVer=09.02.0100;FileUsage=0;SQLLevel=1;
+SQL Server Native Client 11.0 UsageCount=1;APILevel=2;ConnectFunctions=YYY;CPTimeout=60;DriverODBCVer=03.80;FileUsage=0;SQLLevel=1;
+MariaDB ODBC 1.0 Driver UsageCount=1;
+Firebird/InterBase(r) driver UsageCount=1;FileExtns=*.fdb,*.gdb;APILevel=1;ConnectFunctions=YYY;FileUsage=0;DriverODBCVer=03.51;SQLLevel=1;
+MySQL ODBC 5.3 ANSI Driver UsageCount=1;
+MySQL ODBC 5.3 Unicode Driver UsageCount=1;
DROP TABLE t1;
CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CATFUNC=Tables CONNECTION='Not important';
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `Table_Cat` char(128) NOT NULL,
- `Table_Schema` char(128) NOT NULL,
+ `Table_Cat` char(128) DEFAULT NULL,
+ `Table_Schema` char(128) DEFAULT NULL,
`Table_Name` char(128) NOT NULL,
`Table_Type` char(16) NOT NULL,
- `Remark` char(255) NOT NULL
+ `Remark` char(255) DEFAULT NULL
) ENGINE=CONNECT DEFAULT CHARSET=latin1 CONNECTION='Not important' `TABLE_TYPE`='ODBC' `CATFUNC`='Tables'
DROP TABLE t1;
CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CATFUNC=Columns CONNECTION='Not important';
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `Table_Cat` char(128) NOT NULL,
- `Table_Schema` char(128) NOT NULL,
+ `Table_Cat` char(128) DEFAULT NULL,
+ `Table_Schema` char(128) DEFAULT NULL,
`Table_Name` char(128) NOT NULL,
`Column_Name` char(128) NOT NULL,
`Data_Type` smallint(6) NOT NULL,
`Type_Name` char(30) NOT NULL,
`Column_Size` int(10) NOT NULL,
`Buffer_Length` int(10) NOT NULL,
- `Decimal_Digits` smallint(6) NOT NULL,
- `Radix` smallint(6) NOT NULL,
+ `Decimal_Digits` smallint(6) DEFAULT NULL,
+ `Radix` smallint(6) DEFAULT NULL,
`Nullable` smallint(6) NOT NULL,
- `Remarks` char(255) NOT NULL
+ `Remarks` char(255) DEFAULT NULL
) ENGINE=CONNECT DEFAULT CHARSET=latin1 CONNECTION='Not important' `TABLE_TYPE`='ODBC' `CATFUNC`='Columns'
DROP TABLE t1;
-CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC TABNAME='EMPLOYEE' CONNECTION='DSN=Firebird;UID=SYSDBA;PWD=manager';
+CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC TABNAME='EMPLOYEE' CONNECTION='DSN=Firebird;UID=SYSDBA;PWD=masterkey';
SELECT * FROM t1;
EMP_NO FIRST_NAME LAST_NAME PHONE_EXT HIRE_DATE DEPT_NO JOB_CODE JOB_GRADE JOB_COUNTRY SALARY FULL_NAME
2 Robert Nelson 250 1988-12-28 00:00:00 600 VP 2 USA 105900.00 Nelson, Robert
diff --git a/storage/connect/mysql-test/connect/r/part_table.result b/storage/connect/mysql-test/connect/r/part_table.result
index 122c328fa59..f3a556ae784 100644
--- a/storage/connect/mysql-test/connect/r/part_table.result
+++ b/storage/connect/mysql-test/connect/r/part_table.result
@@ -191,6 +191,31 @@ id msg
35 thirty five
81 big
DROP TABLE t1;
+CREATE TABLE t1 (
+id INT KEY NOT NULL,
+msg VARCHAR(32))
+ENGINE=CONNECT TABLE_TYPE=MYSQL
+OPTION_LIST='connect=mysql://root@localhost/test/xt%s'
+PARTITION BY RANGE COLUMNS(id) (
+PARTITION `1` VALUES LESS THAN(10),
+PARTITION `2` VALUES LESS THAN(50),
+PARTITION `3` VALUES LESS THAN(MAXVALUE));
+Warnings:
+Warning 1105 Data repartition in 1 is unchecked
+Warning 1105 Data repartition in 2 is unchecked
+Warning 1105 Data repartition in 3 is unchecked
+SELECT * FROM t1;
+id msg
+4 four
+7 sept
+1 one
+8 eight
+40 forty
+10 ten
+11 eleven
+35 thirty five
+81 big
+DROP TABLE t1;
DROP TABLE xt1;
DROP TABLE xt2;
DROP TABLE xt3;
diff --git a/storage/connect/mysql-test/connect/std_data/mdev9949.frm b/storage/connect/mysql-test/connect/std_data/mdev9949.frm
new file mode 100644
index 00000000000..56bb9a71263
--- /dev/null
+++ b/storage/connect/mysql-test/connect/std_data/mdev9949.frm
Binary files differ
diff --git a/storage/connect/mysql-test/connect/t/drop-open-error.opt b/storage/connect/mysql-test/connect/t/drop-open-error.opt
new file mode 100644
index 00000000000..22520f0aa99
--- /dev/null
+++ b/storage/connect/mysql-test/connect/t/drop-open-error.opt
@@ -0,0 +1 @@
+--secure-file-priv=""
diff --git a/storage/connect/mysql-test/connect/t/drop-open-error.test b/storage/connect/mysql-test/connect/t/drop-open-error.test
new file mode 100644
index 00000000000..0b73ac98779
--- /dev/null
+++ b/storage/connect/mysql-test/connect/t/drop-open-error.test
@@ -0,0 +1,29 @@
+#
+# tests for the case when open_table_def() fails from inside
+# ha_connect::delete_or_rename_table()
+#
+#
+# MDEV-9949 Connect Engine: long SRCDEF leads to broken table
+#
+let $datadir=`select @@datadir`;
+
+create table t1 (c varchar(8));
+error ER_VALUE_TOO_LONG;
+# 34K SRCDEF line:
+create table tcon engine=connect table_type=mysql CONNECTION='mysql://root@localhost/test/t1' SRCDEF='select c from t1 where c in ("foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar")';
+
+# copy the invalid frm (as created by the statement above before the MDEV-9949 fix)
+copy_file $MTR_SUITE_DIR/std_data/mdev9949.frm $datadir/test/mdev9949.frm;
+drop table mdev9949;
+drop table t1;
+
+#
+# MDEV-7935 CREATE TABLE ... AS SELECT ... can cause a Server crash (Assertion `0' in Protocol::end_statement)
+#
+select @@secure_file_priv 'must be NULL'; # otherwise foo/bar.txt won't be allowed
+create table t1 (a char(16)) engine=myisam;
+insert into t1 values('Hello World!');
+replace_regex @on .*/foo/@on foo/@;
+error ER_GET_ERRMSG;
+create table t2 engine=connect file_name='foo/bar.txt' as select * from t1;
+drop table t1;
diff --git a/storage/connect/mysql-test/connect/t/grant3.test b/storage/connect/mysql-test/connect/t/grant3.test
new file mode 100644
index 00000000000..9f05ca796c5
--- /dev/null
+++ b/storage/connect/mysql-test/connect/t/grant3.test
@@ -0,0 +1,11 @@
+#
+# MDEV-9610 Trigger on normal table can't insert into CONNECT engine table - Access Denied
+#
+create table tcon (i int) engine=Connect table_type=DOS file_name='tcon.dos';
+create table tin (i int);
+create trigger tr after insert on tin for each row insert into tcon values (new.i);
+insert into tin values (1);
+drop table tin,tcon;
+
+let datadir=`select @@datadir`;
+remove_file $datadir/test/tcon.dos;
diff --git a/storage/connect/mysql-test/connect/t/mysql_index.test b/storage/connect/mysql-test/connect/t/mysql_index.test
index 9a162b4d8e3..81fdcad9330 100644
--- a/storage/connect/mysql-test/connect/t/mysql_index.test
+++ b/storage/connect/mysql-test/connect/t/mysql_index.test
@@ -64,3 +64,70 @@ SELECT * FROM t2;
DROP TABLE t2;
DROP TABLE t1;
+
+let $MYSQLD_DATADIR= `select @@datadir`;
+--copy_file $MTR_SUITE_DIR/std_data/emp.txt $MYSQLD_DATADIR/test/emp.txt
+
+--echo #
+--echo # Make local FIX table with indices matricule and nom/prenom
+--echo #
+CREATE TABLE t1
+(
+ matricule INT(4) KEY NOT NULL field_format='Z',
+ nom VARCHAR(16) NOT NULL,
+ prenom VARCHAR(20) NOT NULL,
+ sexe SMALLINT(1) NOT NULL COMMENT 'sexe 1:M 2:F',
+ aanais INT(4) NOT NULL,
+ mmnais INT(2) NOT NULL,
+ ddentree DATE NOT NULL date_format='YYYYMM',
+ ddnom DATE NOT NULL date_format='YYYYMM',
+ brut INT(5) NOT NULL,
+ net DOUBLE(8,2) NOT NULL,
+ service INT(2) NOT NULL,
+ sitmat CHAR(1) NOT NULL,
+ formation CHAR(5) NOT NULL,
+ INDEX NP(nom,prenom)
+) ENGINE=CONNECT TABLE_TYPE=FIX FILE_NAME='emp.txt' ENDING=2;
+
+--echo #
+--echo # Make MYSQL table with same indices
+--echo #
+CREATE TABLE t2
+(
+ matricule INT(4) KEY NOT NULL,
+ nom VARCHAR(16) NOT NULL,
+ prenom VARCHAR(20) NOT NULL,
+ sexe SMALLINT(1) NOT NULL,
+ aanais INT(4) NOT NULL,
+ mmnais INT(2) NOT NULL,
+ ddentree DATE NOT NULL date_format='YYYYMM',
+ ddnom DATE NOT NULL date_format='YYYYMM',
+ brut INT(5) NOT NULL,
+ net DOUBLE(8,2) NOT NULL,
+ service INT(2) NOT NULL,
+ sitmat CHAR(1) NOT NULL,
+ formation CHAR(5) NOT NULL,
+ INDEX NP(nom,prenom)
+) ENGINE=CONNECT TABLE_TYPE=MYSQL CONNECTIOn='mysql://root@localhost/test/t1';
+SELECT * FROM t2 limit 10;
+SELECT matricule, nom, prenom FROM t2 WHERE nom IN ('FOCH','MOGADOR');
+SELECT matricule, nom, prenom FROM t2 WHERE nom = 'FOCH' OR nom = 'MOGADOR';
+SELECT matricule, nom, prenom FROM t2 WHERE nom < 'ADDAX';
+SELECT matricule, nom, prenom FROM t2 WHERE nom <= 'ABEL';
+SELECT matricule, nom, prenom FROM t2 WHERE nom > 'YVON';
+SELECT matricule, nom, prenom FROM t2 WHERE nom >= 'YVON';
+SELECT matricule, nom, prenom FROM t2 WHERE nom <= 'ABEL' OR nom > 'YVON';
+SELECT matricule, nom, prenom FROM t2 WHERE nom > 'HELEN' AND nom < 'HEROS';
+SELECT matricule, nom, prenom FROM t2 WHERE nom BETWEEN 'HELEN' AND 'HEROS';
+SELECT matricule, nom, prenom FROM t2 WHERE nom BETWEEN 'HELEN' AND 'HEROS' AND prenom = 'PHILIPPE';
+SELECT matricule, nom, prenom FROM t2 ORDER BY nom LIMIT 10;
+SELECT a.nom, a.prenom, b.nom FROM t1 a STRAIGHT_JOIN t2 b ON a.prenom = b.prenom WHERE a.nom = 'FOCH' AND a.nom != b.nom;
+
+DROP TABLE t2;
+DROP TABLE t1;
+
+#
+# Clean up
+#
+--remove_file $MYSQLD_DATADIR/test/emp.txt
+--remove_file $MYSQLD_DATADIR/test/emp.fnx
diff --git a/storage/connect/mysql-test/connect/t/odbc_firebird.test b/storage/connect/mysql-test/connect/t/odbc_firebird.test
index c89ffe5dfb2..c9279eec385 100644
--- a/storage/connect/mysql-test/connect/t/odbc_firebird.test
+++ b/storage/connect/mysql-test/connect/t/odbc_firebird.test
@@ -4,7 +4,7 @@ SET NAMES utf8;
# MS ODBC and unixODBC return different error message text,
# so disable displaying error messages
-#--disable_result_log ONCE
+--disable_result_log ONCE
--error ER_UNKNOWN_ERROR
CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CONNECTION='Bad connection string';
@@ -30,6 +30,6 @@ CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC CATFUNC=Columns CONNECTION='Not i
SHOW CREATE TABLE t1;
DROP TABLE t1;
-CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC TABNAME='EMPLOYEE' CONNECTION='DSN=Firebird;UID=SYSDBA;PWD=manager';
+CREATE TABLE t1 ENGINE=CONNECT TABLE_TYPE=ODBC TABNAME='EMPLOYEE' CONNECTION='DSN=Firebird;UID=SYSDBA;PWD=masterkey';
SELECT * FROM t1;
DROP TABLE t1;
diff --git a/storage/connect/mysql-test/connect/t/part_table.test b/storage/connect/mysql-test/connect/t/part_table.test
index d839337ba6f..5edd5766bd6 100644
--- a/storage/connect/mysql-test/connect/t/part_table.test
+++ b/storage/connect/mysql-test/connect/t/part_table.test
@@ -82,6 +82,21 @@ SELECT * FROM t1;
DELETE FROM t1 WHERE id in (60,72);
SELECT * FROM t1;
DROP TABLE t1;
+
+#
+# Using a connection string
+#
+CREATE TABLE t1 (
+id INT KEY NOT NULL,
+msg VARCHAR(32))
+ENGINE=CONNECT TABLE_TYPE=MYSQL
+OPTION_LIST='connect=mysql://root@localhost/test/xt%s'
+PARTITION BY RANGE COLUMNS(id) (
+PARTITION `1` VALUES LESS THAN(10),
+PARTITION `2` VALUES LESS THAN(50),
+PARTITION `3` VALUES LESS THAN(MAXVALUE));
+SELECT * FROM t1;
+DROP TABLE t1;
DROP TABLE xt1;
DROP TABLE xt2;
DROP TABLE xt3;
diff --git a/storage/connect/odbconn.cpp b/storage/connect/odbconn.cpp
index 55ccbdbada1..8b2626fe962 100644
--- a/storage/connect/odbconn.cpp
+++ b/storage/connect/odbconn.cpp
@@ -1458,7 +1458,7 @@ int ODBConn::ExecDirectSQL(char *sql, ODBCCOL *tocols)
n++;
// n can be 0 for query such as Select count(*) from table
- if (n && n != (UWORD)ncol)
+ if (n && n > (UWORD)ncol)
ThrowDBX(MSG(COL_NUM_MISM));
// Now bind the column buffers
diff --git a/storage/connect/plgdbsem.h b/storage/connect/plgdbsem.h
index b57d9e20ceb..910ce97f48a 100644
--- a/storage/connect/plgdbsem.h
+++ b/storage/connect/plgdbsem.h
@@ -77,7 +77,8 @@ enum TABTYPE {TAB_UNDEF = 0, /* Table of undefined type */
TAB_JSON = 23, /* JSON tables */
TAB_JCT = 24, /* Junction tables NIY */
TAB_DMY = 25, /* DMY Dummy tables NIY */
- TAB_NIY = 26}; /* Table not implemented yet */
+ TAB_JDBC = 26, /* Table accessed via JDBC */
+ TAB_NIY = 27}; /* Table not implemented yet */
enum AMT {TYPE_AM_ERROR = 0, /* Type not defined */
TYPE_AM_ROWID = 1, /* ROWID type (special column) */
@@ -109,7 +110,9 @@ enum AMT {TYPE_AM_ERROR = 0, /* Type not defined */
TYPE_AM_DIR = 90, /* DIR access method type no */
TYPE_AM_ODBC = 100, /* ODBC access method type no */
TYPE_AM_XDBC = 101, /* XDBC access method type no */
- TYPE_AM_OEM = 110, /* OEM access method type no */
+ TYPE_AM_JDBC = 102, /* JDBC access method type no */
+ TYPE_AM_XJDC = 103, /* XJDC access method type no */
+ TYPE_AM_OEM = 110, /* OEM access method type no */
TYPE_AM_TBL = 115, /* TBL access method type no */
TYPE_AM_PIVOT = 120, /* PIVOT access method type no */
TYPE_AM_SRC = 121, /* PIVOT multiple column type no */
@@ -146,8 +149,9 @@ enum RECFM {RECFM_NAF = -2, /* Not a file */
RECFM_BIN = 2, /* Binary DOS files (also fixed) */
RECFM_VCT = 3, /* VCT formatted files */
RECFM_ODBC = 4, /* Table accessed via ODBC */
- RECFM_PLG = 5, /* Table accessed via PLGconn */
- RECFM_DBF = 6}; /* DBase formatted file */
+ RECFM_JDBC = 5, /* Table accessed via JDBC */
+ RECFM_PLG = 6, /* Table accessed via PLGconn */
+ RECFM_DBF = 7}; /* DBase formatted file */
enum MISC {DB_TABNO = 1, /* DB routines in Utility Table */
MAX_MULT_KEY = 10, /* Max multiple key number */
diff --git a/storage/connect/plgdbutl.cpp b/storage/connect/plgdbutl.cpp
index 1ec1108c639..d70eeb32a04 100644
--- a/storage/connect/plgdbutl.cpp
+++ b/storage/connect/plgdbutl.cpp
@@ -1102,7 +1102,8 @@ char *GetAmName(PGLOBAL g, AMT am, void *memp)
case TYPE_AM_DOM: strcpy(amn, "DOM"); break;
case TYPE_AM_DIR: strcpy(amn, "DIR"); break;
case TYPE_AM_ODBC: strcpy(amn, "ODBC"); break;
- case TYPE_AM_MAC: strcpy(amn, "MAC"); break;
+ case TYPE_AM_JDBC: strcpy(amn, "JDBC"); break;
+ case TYPE_AM_MAC: strcpy(amn, "MAC"); break;
case TYPE_AM_OEM: strcpy(amn, "OEM"); break;
case TYPE_AM_OUT: strcpy(amn, "OUT"); break;
default: sprintf(amn, "OEM(%d)", am);
diff --git a/storage/connect/reldef.cpp b/storage/connect/reldef.cpp
index e455bc8f1a5..4b9d99bd8c9 100644
--- a/storage/connect/reldef.cpp
+++ b/storage/connect/reldef.cpp
@@ -305,7 +305,7 @@ int TABDEF::GetColCatInfo(PGLOBAL g)
case TAB_OEM:
poff = 0; // Offset represents an independant flag
break;
- default: // VCT PLG ODBC MYSQL WMI...
+ default: // VCT PLG ODBC JDBC MYSQL WMI...
poff = 0; // NA
break;
} // endswitch tc
diff --git a/storage/connect/tabjdbc.cpp b/storage/connect/tabjdbc.cpp
new file mode 100644
index 00000000000..97168646ba0
--- /dev/null
+++ b/storage/connect/tabjdbc.cpp
@@ -0,0 +1,1704 @@
+/************* TabJDBC C++ Program Source Code File (.CPP) *************/
+/* PROGRAM NAME: TABJDBC */
+/* ------------- */
+/* Version 1.0 */
+/* */
+/* COPYRIGHT: */
+/* ---------- */
+/* (C) Copyright to the author Olivier BERTRAND 2016 */
+/* */
+/* WHAT THIS PROGRAM DOES: */
+/* ----------------------- */
+/* This program are the TABJDBC class DB execution routines. */
+/* */
+/* WHAT YOU NEED TO COMPILE THIS PROGRAM: */
+/* -------------------------------------- */
+/* */
+/* REQUIRED FILES: */
+/* --------------- */
+/* TABJDBC.CPP - Source code */
+/* PLGDBSEM.H - DB application declaration file */
+/* TABJDBC.H - TABJDBC classes declaration file */
+/* GLOBAL.H - Global declaration file */
+/* */
+/* REQUIRED LIBRARIES: */
+/* ------------------- */
+/* Large model C library */
+/* */
+/* REQUIRED PROGRAMS: */
+/* ------------------ */
+/* IBM, Borland, GNU or Microsoft C++ Compiler and Linker */
+/* */
+/***********************************************************************/
+
+/***********************************************************************/
+/* Include relevant MariaDB header file. */
+/***********************************************************************/
+#include "my_global.h"
+#include "sql_class.h"
+#if defined(__WIN__)
+#include <io.h>
+#include <fcntl.h>
+#if defined(__BORLANDC__)
+#define __MFC_COMPAT__ // To define min/max as macro
+#endif
+//#include <windows.h>
+#include <sqltypes.h>
+#else
+#if defined(UNIX)
+#include <errno.h>
+#define NODW
+#include "osutil.h"
+#else
+#include <io.h>
+#endif
+#include <fcntl.h>
+#endif
+
+/***********************************************************************/
+/* Include application header files: */
+/* global.h is header containing all global declarations. */
+/* plgdbsem.h is header containing the DB application declarations. */
+/* kindex.h is kindex header that also includes tabdos.h. */
+/* tabJDBC.h is header containing the TABJDBC class declarations. */
+/* JDBConn.h is header containing JDBC connection declarations. */
+/***********************************************************************/
+#include "global.h"
+#include "plgdbsem.h"
+#include "mycat.h"
+#include "xtable.h"
+#include "jdbccat.h"
+#include "tabjdbc.h"
+#include "tabmul.h"
+#include "reldef.h"
+#include "tabcol.h"
+#include "valblk.h"
+#include "ha_connect.h"
+
+#include "sql_string.h"
+
+/***********************************************************************/
+/* DB static variables. */
+/***********************************************************************/
+// int num_read, num_there, num_eq[2], num_nf; // Statistics
+extern int num_read, num_there, num_eq[2]; // Statistics
+
+/***********************************************************************/
+/* External function. */
+/***********************************************************************/
+bool ExactInfo(void);
+
+/* -------------------------- Class JDBCDEF -------------------------- */
+
+/***********************************************************************/
+/* Constructor. */
+/***********************************************************************/
+JDBCDEF::JDBCDEF(void)
+{
+ Jpath = Driver = Url = Tabname = Tabschema = Username = NULL;
+ Password = Tabcat = Tabtype = Srcdef = Qchar = Qrystr = Sep = NULL;
+ Options = Quoted = Maxerr = Maxres = Memory = 0;
+ Scrollable = Xsrc = false;
+} // end of JDBCDEF constructor
+
+/***********************************************************************/
+/* DefineAM: define specific AM block values from JDBC file. */
+/***********************************************************************/
+bool JDBCDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
+{
+ Jpath = GetStringCatInfo(g, "Jpath", "");
+ Driver = GetStringCatInfo(g, "Driver", NULL);
+ Desc = Url = GetStringCatInfo(g, "Url", NULL);
+
+ if (!Url && !Catfunc) {
+ sprintf(g->Message, "Missing URL for JDBC table %s", Name);
+ return true;
+ } // endif Connect
+
+ Tabname = GetStringCatInfo(g, "Name",
+ (Catfunc & (FNC_TABLE | FNC_COL)) ? NULL : Name);
+ Tabname = GetStringCatInfo(g, "Tabname", Tabname);
+ Tabschema = GetStringCatInfo(g, "Dbname", NULL);
+ Tabschema = GetStringCatInfo(g, "Schema", Tabschema);
+ Tabcat = GetStringCatInfo(g, "Qualifier", NULL);
+ Tabcat = GetStringCatInfo(g, "Catalog", Tabcat);
+ Tabtype = GetStringCatInfo(g, "Tabtype", NULL);
+ Username = GetStringCatInfo(g, "User", NULL);
+ Password = GetStringCatInfo(g, "Password", NULL);
+
+ if ((Srcdef = GetStringCatInfo(g, "Srcdef", NULL)))
+ Read_Only = true;
+
+ Qrystr = GetStringCatInfo(g, "Query_String", "?");
+ Sep = GetStringCatInfo(g, "Separator", NULL);
+ Xsrc = GetBoolCatInfo("Execsrc", FALSE);
+ Maxerr = GetIntCatInfo("Maxerr", 0);
+ Maxres = GetIntCatInfo("Maxres", 0);
+ Quoted = GetIntCatInfo("Quoted", 0);
+//Options = JDBConn::noJDBCDialog;
+//Options = JDBConn::noJDBCDialog | JDBConn::useCursorLib;
+//Cto= GetIntCatInfo("ConnectTimeout", DEFAULT_LOGIN_TIMEOUT);
+//Qto= GetIntCatInfo("QueryTimeout", DEFAULT_QUERY_TIMEOUT);
+ Scrollable = GetBoolCatInfo("Scrollable", false);
+ Memory = GetIntCatInfo("Memory", 0);
+ Pseudo = 2; // FILID is Ok but not ROWID
+ return false;
+} // end of DefineAM
+
+/***********************************************************************/
+/* GetTable: makes a new Table Description Block. */
+/***********************************************************************/
+PTDB JDBCDEF::GetTable(PGLOBAL g, MODE m)
+{
+ PTDBASE tdbp = NULL;
+
+ /*********************************************************************/
+ /* Allocate a TDB of the proper type. */
+ /* Column blocks will be allocated only when needed. */
+ /*********************************************************************/
+ if (Xsrc)
+ tdbp = new(g)TDBXJDC(this);
+ else switch (Catfunc) {
+ case FNC_COL:
+ tdbp = new(g)TDBJDBCL(this);
+ break;
+#if 0
+ case FNC_DSN:
+ tdbp = new(g)TDBJSRC(this);
+ break;
+#endif // 0
+ case FNC_TABLE:
+ tdbp = new(g)TDBJTB(this);
+ break;
+ case FNC_DRIVER:
+ tdbp = new(g)TDBJDRV(this);
+ break;
+ default:
+ tdbp = new(g)TDBJDBC(this);
+
+ if (Multiple == 1)
+ tdbp = new(g)TDBMUL(tdbp);
+ else if (Multiple == 2)
+ strcpy(g->Message, "NO_JDBC_MUL");
+
+ } // endswitch Catfunc
+
+ return tdbp;
+} // end of GetTable
+
+/***********************************************************************/
+/* The MySQL and MariaDB JDBC drivers return by default a result set */
+/* containing the entire result of the executed query. This can be an */
+/* issue for big tables and memory error can occur. An alternative is */
+/* to use streaming (reading one row at a time) but to specify this, */
+/* a fech size of the integer min value must be send to the driver. */
+/***********************************************************************/
+int JDBCPARM::CheckSize(int rows)
+{
+ if (Url && rows == 1) {
+ // Are we connected to a MySQL JDBC connector?
+ bool b = (!strncmp(Url, "jdbc:mysql:", 11) ||
+ !strncmp(Url, "jdbc:mariadb:", 13));
+ return b ? INT_MIN32 : rows;
+ } else
+ return rows;
+
+} // end of CheckSize
+
+/* -------------------------- Class TDBJDBC -------------------------- */
+
+/***********************************************************************/
+/* Implementation of the TDBJDBC class. */
+/***********************************************************************/
+TDBJDBC::TDBJDBC(PJDBCDEF tdp) : TDBASE(tdp)
+{
+ Jcp = NULL;
+ Cnp = NULL;
+
+ if (tdp) {
+ Jpath = tdp->Jpath;
+ Ops.Driver = tdp->Driver;
+ Ops.Url = tdp->Url;
+ TableName = tdp->Tabname;
+ Schema = tdp->Tabschema;
+ Ops.User = tdp->Username;
+ Ops.Pwd = tdp->Password;
+ Catalog = tdp->Tabcat;
+ Srcdef = tdp->Srcdef;
+ Qrystr = tdp->Qrystr;
+ Sep = tdp->GetSep();
+ Options = tdp->Options;
+// Ops.Cto = tdp->Cto;
+// Ops.Qto = tdp->Qto;
+ Quoted = MY_MAX(0, tdp->GetQuoted());
+ Rows = tdp->GetElemt();
+ Memory = tdp->Memory;
+ Ops.Scrollable = tdp->Scrollable;
+ } else {
+ Jpath = NULL;
+ TableName = NULL;
+ Schema = NULL;
+ Ops.Driver = NULL;
+ Ops.Url = NULL;
+ Ops.User = NULL;
+ Ops.Pwd = NULL;
+ Catalog = NULL;
+ Srcdef = NULL;
+ Qrystr = NULL;
+ Sep = 0;
+ Options = 0;
+// Ops.Cto = DEFAULT_LOGIN_TIMEOUT;
+// Ops.Qto = DEFAULT_QUERY_TIMEOUT;
+ Quoted = 0;
+ Rows = 0;
+ Memory = 0;
+ Ops.Scrollable = false;
+ } // endif tdp
+
+ Quote = NULL;
+ Query = NULL;
+ Count = NULL;
+//Where = NULL;
+ MulConn = NULL;
+ DBQ = NULL;
+ Qrp = NULL;
+ Fpos = 0;
+ Curpos = 0;
+ AftRows = 0;
+ CurNum = 0;
+ Rbuf = 0;
+ BufSize = 0;
+ Ncol = 0;
+ Nparm = 0;
+ Placed = false;
+ Werr = false;
+ Rerr = false;
+ Ops.Fsize = Ops.CheckSize(Rows);
+} // end of TDBJDBC standard constructor
+
+TDBJDBC::TDBJDBC(PTDBJDBC tdbp) : TDBASE(tdbp)
+{
+ Jcp = tdbp->Jcp; // is that right ?
+ Cnp = tdbp->Cnp;
+ Jpath = tdbp->Jpath;
+ TableName = tdbp->TableName;
+ Schema = tdbp->Schema;
+ Ops = tdbp->Ops;
+ Catalog = tdbp->Catalog;
+ Srcdef = tdbp->Srcdef;
+ Qrystr = tdbp->Qrystr;
+ Memory = tdbp->Memory;
+//Scrollable = tdbp->Scrollable;
+ Quote = tdbp->Quote;
+ Query = tdbp->Query;
+ Count = tdbp->Count;
+//Where = tdbp->Where;
+ MulConn = tdbp->MulConn;
+ DBQ = tdbp->DBQ;
+ Options = tdbp->Options;
+ Quoted = tdbp->Quoted;
+ Rows = tdbp->Rows;
+ Fpos = 0;
+ Curpos = 0;
+ AftRows = 0;
+ CurNum = 0;
+ Rbuf = 0;
+ BufSize = tdbp->BufSize;
+ Nparm = tdbp->Nparm;
+ Qrp = tdbp->Qrp;
+ Placed = false;
+} // end of TDBJDBC copy constructor
+
+// Method
+PTDB TDBJDBC::CopyOne(PTABS t)
+{
+ PTDB tp;
+ PJDBCCOL cp1, cp2;
+ PGLOBAL g = t->G; // Is this really useful ???
+
+ tp = new(g)TDBJDBC(this);
+
+ for (cp1 = (PJDBCCOL)Columns; cp1; cp1 = (PJDBCCOL)cp1->GetNext()) {
+ cp2 = new(g)JDBCCOL(cp1, tp); // Make a copy
+ NewPointer(t, cp1, cp2);
+ } // endfor cp1
+
+ return tp;
+} // end of CopyOne
+
+/***********************************************************************/
+/* Allocate JDBC column description block. */
+/***********************************************************************/
+PCOL TDBJDBC::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n)
+{
+ return new(g)JDBCCOL(cdp, this, cprec, n);
+} // end of MakeCol
+
+/******************************************************************/
+/* Convert an UTF-8 string to latin characters. */
+/******************************************************************/
+int TDBJDBC::Decode(char *txt, char *buf, size_t n)
+{
+ uint dummy_errors;
+ uint32 len= copy_and_convert(buf, n, &my_charset_latin1,
+ txt, strlen(txt),
+ &my_charset_utf8_general_ci,
+ &dummy_errors);
+ buf[len]= '\0';
+ return 0;
+} // end of Decode
+
+/***********************************************************************/
+/* MakeSQL: make the SQL statement use with JDBC connection. */
+/* TODO: when implementing EOM filtering, column only used in local */
+/* filter should be removed from column list. */
+/***********************************************************************/
+bool TDBJDBC::MakeSQL(PGLOBAL g, bool cnt)
+{
+ char *schmp = NULL, *catp = NULL, buf[NAM_LEN * 3];
+ int len;
+ bool oom = false, first = true;
+ PTABLE tablep = To_Table;
+ PCOL colp;
+
+ if (Srcdef) {
+ Query = new(g)STRING(g, 0, Srcdef);
+ return false;
+ } // endif Srcdef
+
+ // Allocate the string used to contain the Query
+ Query = new(g)STRING(g, 1023, "SELECT ");
+
+ if (!cnt) {
+ if (Columns) {
+ // Normal SQL statement to retrieve results
+ for (colp = Columns; colp; colp = colp->GetNext())
+ if (!colp->IsSpecial()) {
+ if (!first)
+ oom |= Query->Append(", ");
+ else
+ first = false;
+
+ // Column name can be encoded in UTF-8
+ Decode(colp->GetName(), buf, sizeof(buf));
+
+ if (Quote) {
+ // Put column name between identifier quotes in case in contains blanks
+ oom |= Query->Append(Quote);
+ oom |= Query->Append(buf);
+ oom |= Query->Append(Quote);
+ } else
+ oom |= Query->Append(buf);
+
+ ((PJDBCCOL)colp)->Rank = ++Ncol;
+ } // endif colp
+
+ } else
+ // !Columns can occur for queries such that sql count(*) from...
+ // for which we will count the rows from sql * from...
+ oom |= Query->Append('*');
+
+ } else
+ // SQL statement used to retrieve the size of the result
+ oom |= Query->Append("count(*)");
+
+ oom |= Query->Append(" FROM ");
+
+ if (Catalog && *Catalog)
+ catp = Catalog;
+
+ if (tablep->GetSchema())
+ schmp = (char*)tablep->GetSchema();
+ else if (Schema && *Schema)
+ schmp = Schema;
+
+ if (catp) {
+ oom |= Query->Append(catp);
+
+ if (schmp) {
+ oom |= Query->Append('.');
+ oom |= Query->Append(schmp);
+ } // endif schmp
+
+ oom |= Query->Append('.');
+ } else if (schmp) {
+ oom |= Query->Append(schmp);
+ oom |= Query->Append('.');
+ } // endif schmp
+
+ // Table name can be encoded in UTF-8
+ Decode(TableName, buf, sizeof(buf));
+
+ if (Quote) {
+ // Put table name between identifier quotes in case in contains blanks
+ oom |= Query->Append(Quote);
+ oom |= Query->Append(buf);
+ oom |= Query->Append(Quote);
+ } else
+ oom |= Query->Append(buf);
+
+ len = Query->GetLength();
+
+ if (To_CondFil) {
+ if (Mode == MODE_READ) {
+ oom |= Query->Append(" WHERE ");
+ oom |= Query->Append(To_CondFil->Body);
+ len = Query->GetLength() + 1;
+ } else
+ len += (strlen(To_CondFil->Body) + 256);
+
+ } else
+ len += ((Mode == MODE_READX) ? 256 : 1);
+
+ if (oom || Query->Resize(len)) {
+ strcpy(g->Message, "MakeSQL: Out of memory");
+ return true;
+ } // endif oom
+
+ if (trace)
+ htrc("Query=%s\n", Query->GetStr());
+
+ return false;
+} // end of MakeSQL
+
+/***********************************************************************/
+/* MakeInsert: make the Insert statement used with JDBC connection. */
+/***********************************************************************/
+bool TDBJDBC::MakeInsert(PGLOBAL g)
+{
+ char *schmp = NULL, *catp = NULL, buf[NAM_LEN * 3];
+ int len = 0;
+ uint pos;
+ bool b = false, oom = false;
+ PTABLE tablep = To_Table;
+ PCOL colp;
+
+ for (colp = Columns; colp; colp = colp->GetNext())
+ if (colp->IsSpecial()) {
+ strcpy(g->Message, "No JDBC special columns");
+ return true;
+ } else {
+ // Column name can be encoded in UTF-8
+ Decode(colp->GetName(), buf, sizeof(buf));
+ len += (strlen(buf) + 6); // comma + quotes + valist
+ ((PJDBCCOL)colp)->Rank = ++Nparm;
+ } // endif colp
+
+ // Below 32 is enough to contain the fixed part of the query
+ if (Catalog && *Catalog)
+ catp = Catalog;
+
+ if (catp)
+ len += strlen(catp) + 1;
+
+ if (tablep->GetSchema())
+ schmp = (char*)tablep->GetSchema();
+ else if (Schema && *Schema)
+ schmp = Schema;
+
+ if (schmp)
+ len += strlen(schmp) + 1;
+
+ // Table name can be encoded in UTF-8
+ Decode(TableName, buf, sizeof(buf));
+ len += (strlen(buf) + 32);
+ Query = new(g)STRING(g, len, "INSERT INTO ");
+
+ if (catp) {
+ oom |= Query->Append(catp);
+
+ if (schmp) {
+ oom |= Query->Append('.');
+ oom |= Query->Append(schmp);
+ } // endif schmp
+
+ oom |= Query->Append('.');
+ } else if (schmp) {
+ oom |= Query->Append(schmp);
+ oom |= Query->Append('.');
+ } // endif schmp
+
+ if (Quote) {
+ // Put table name between identifier quotes in case in contains blanks
+ oom |= Query->Append(Quote);
+ oom |= Query->Append(buf);
+ oom |= Query->Append(Quote);
+ } else
+ oom |= Query->Append(buf);
+
+ oom |= Query->Append('(');
+
+ for (colp = Columns; colp; colp = colp->GetNext()) {
+ if (b)
+ oom |= Query->Append(", ");
+ else
+ b = true;
+
+ // Column name can be in UTF-8 encoding
+ Decode(colp->GetName(), buf, sizeof(buf));
+
+ if (Quote) {
+ // Put column name between identifier quotes in case in contains blanks
+ oom |= Query->Append(Quote);
+ oom |= Query->Append(buf);
+ oom |= Query->Append(Quote);
+ } else
+ oom |= Query->Append(buf);
+
+ } // endfor colp
+
+ if ((oom |= Query->Append(") VALUES ("))) {
+ strcpy(g->Message, "MakeInsert: Out of memory");
+ return true;
+ } else // in case prepared statement fails
+ pos = Query->GetLength();
+
+ // Make prepared statement
+ for (int i = 0; i < Nparm; i++)
+ oom |= Query->Append("?,");
+
+ if (oom) {
+ strcpy(g->Message, "MakeInsert: Out of memory");
+ return true;
+ } else
+ Query->RepLast(')');
+
+ // Now see if we can use prepared statement
+ if (Jcp->PrepareSQL(Query->GetStr()))
+ Query->Truncate(pos); // Restore query to not prepared
+ else
+ Prepared = true;
+
+ return false;
+} // end of MakeInsert
+
+/***********************************************************************/
+/* JDBC Set Parameter function. */
+/***********************************************************************/
+bool TDBJDBC::SetParameters(PGLOBAL g)
+{
+ PJDBCCOL colp;
+
+ for (colp = (PJDBCCOL)Columns; colp; colp = (PJDBCCOL)colp->Next)
+ if (Jcp->SetParam(colp))
+ return true;
+
+ return false;
+} // end of SetParameters
+
+/***********************************************************************/
+/* MakeCommand: make the Update or Delete statement to send to the */
+/* MySQL server. Limited to remote values and filtering. */
+/***********************************************************************/
+bool TDBJDBC::MakeCommand(PGLOBAL g)
+{
+ char *p, *stmt, name[68], *body = NULL, *qc = Jcp->GetQuoteChar();
+ char *qrystr = (char*)PlugSubAlloc(g, NULL, strlen(Qrystr) + 1);
+ bool qtd = Quoted > 0;
+ int i = 0, k = 0;
+
+ // Make a lower case copy of the originale query and change
+ // back ticks to the data source identifier quoting character
+ do {
+ qrystr[i] = (Qrystr[i] == '`') ? *qc : tolower(Qrystr[i]);
+ } while (Qrystr[i++]);
+
+ if (To_CondFil && (p = strstr(qrystr, " where "))) {
+ p[7] = 0; // Remove where clause
+ Qrystr[(p - qrystr) + 7] = 0;
+ body = To_CondFil->Body;
+ stmt = (char*)PlugSubAlloc(g, NULL, strlen(qrystr)
+ + strlen(body) + 64);
+ } else
+ stmt = (char*)PlugSubAlloc(g, NULL, strlen(Qrystr) + 64);
+
+ // Check whether the table name is equal to a keyword
+ // If so, it must be quoted in the original query
+ strlwr(strcat(strcat(strcpy(name, " "), Name), " "));
+
+ if (!strstr(" update delete low_priority ignore quick from ", name))
+ strlwr(strcpy(name, Name)); // Not a keyword
+ else
+ strlwr(strcat(strcat(strcpy(name, qc), Name), qc));
+
+ if ((p = strstr(qrystr, name))) {
+ for (i = 0; i < p - qrystr; i++)
+ stmt[i] = (Qrystr[i] == '`') ? *qc : Qrystr[i];
+
+ stmt[i] = 0;
+ k = i + (int)strlen(Name);
+
+ if (qtd && *(p-1) == ' ')
+ strcat(strcat(strcat(stmt, qc), TableName), qc);
+ else
+ strcat(stmt, TableName);
+
+ i = (int)strlen(stmt);
+
+ do {
+ stmt[i++] = (Qrystr[k] == '`') ? *qc : Qrystr[k];
+ } while (Qrystr[k++]);
+
+ if (body)
+ strcat(stmt, body);
+
+ } else {
+ sprintf(g->Message, "Cannot use this %s command",
+ (Mode == MODE_UPDATE) ? "UPDATE" : "DELETE");
+ return NULL;
+ } // endif p
+
+ Query = new(g)STRING(g, 0, stmt);
+ return (!Query->GetSize());
+} // end of MakeCommand
+
+/***********************************************************************/
+/* ResetSize: call by TDBMUL when calculating size estimate. */
+/***********************************************************************/
+void TDBJDBC::ResetSize(void)
+{
+ MaxSize = -1;
+
+ if (Jcp && Jcp->IsOpen())
+ Jcp->Close();
+
+} // end of ResetSize
+
+/***********************************************************************/
+/* JDBC Cardinality: returns table size in number of rows. */
+/***********************************************************************/
+int TDBJDBC::Cardinality(PGLOBAL g)
+{
+ if (!g)
+ return (Mode == MODE_ANY && !Srcdef) ? 1 : 0;
+
+#if 0
+ if (Cardinal < 0 && Mode == MODE_ANY && !Srcdef && ExactInfo()) {
+ // Info command, we must return the exact table row number
+ char qry[96], tbn[64];
+ JDBConn *jcp = new(g)JDBConn(g, this);
+
+ if (jcp->Open(Jpath, &Ops) == RC_FX)
+ return -1;
+
+ // Table name can be encoded in UTF-8
+ Decode(TableName, tbn, sizeof(tbn));
+ strcpy(qry, "SELECT COUNT(*) FROM ");
+
+ if (Quote)
+ strcat(strcat(strcat(qry, Quote), tbn), Quote);
+ else
+ strcat(qry, tbn);
+
+ // Allocate a Count(*) column (must not use the default constructor)
+ Cnp = new(g)JDBCCOL;
+ Cnp->InitValue(g);
+
+ if ((Cardinal = jcp->GetResultSize(qry, Cnp)) < 0)
+ return -3;
+
+ jcp->Close();
+ } else
+#endif // 0
+ Cardinal = 10; // To make MariaDB happy
+
+ return Cardinal;
+} // end of Cardinality
+
+/***********************************************************************/
+/* JDBC GetMaxSize: returns table size estimate in number of lines. */
+/***********************************************************************/
+int TDBJDBC::GetMaxSize(PGLOBAL g)
+{
+ if (MaxSize < 0) {
+ if (Mode == MODE_DELETE)
+ // Return 0 in mode DELETE in case of delete all.
+ MaxSize = 0;
+ else if (!Cardinality(NULL))
+ MaxSize = 10; // To make MySQL happy
+ else if ((MaxSize = Cardinality(g)) < 0)
+ MaxSize = 12; // So we can see an error occured
+
+ } // endif MaxSize
+
+ return MaxSize;
+} // end of GetMaxSize
+
+/***********************************************************************/
+/* Return max size value. */
+/***********************************************************************/
+int TDBJDBC::GetProgMax(PGLOBAL g)
+{
+ return GetMaxSize(g);
+} // end of GetProgMax
+
+/***********************************************************************/
+/* JDBC Access Method opening routine. */
+/* New method now that this routine is called recursively (last table */
+/* first in reverse order): index blocks are immediately linked to */
+/* join block of next table if it exists or else are discarted. */
+/***********************************************************************/
+bool TDBJDBC::OpenDB(PGLOBAL g)
+{
+ bool rc = true;
+
+ if (trace)
+ htrc("JDBC OpenDB: tdbp=%p tdb=R%d use=%d mode=%d\n",
+ this, Tdb_No, Use, Mode);
+
+ if (Use == USE_OPEN) {
+ /*******************************************************************/
+ /* Table already open, just replace it at its beginning. */
+ /*******************************************************************/
+ if (Memory == 1) {
+ if ((Qrp = Jcp->AllocateResult(g)))
+ Memory = 2; // Must be filled
+ else
+ Memory = 0; // Allocation failed, don't use it
+
+ } else if (Memory == 2)
+ Memory = 3; // Ok to use memory result
+
+ if (Memory < 3) {
+ // Method will depend on cursor type
+ if ((Rbuf = Jcp->Rewind(Query->GetStr())) < 0)
+ if (Mode != MODE_READX) {
+ Jcp->Close();
+ return true;
+ } else
+ Rbuf = 0;
+
+ } else
+ Rbuf = Qrp->Nblin;
+
+ CurNum = 0;
+ Fpos = 0;
+ Curpos = 1;
+ return false;
+ } // endif use
+
+ /*********************************************************************/
+ /* Open an JDBC connection for this table. */
+ /* Note: this may not be the proper way to do. Perhaps it is better */
+ /* to test whether a connection is already open for this datasource */
+ /* and if so to allocate just a new result set. But this only for */
+ /* drivers allowing concurency in getting results ??? */
+ /*********************************************************************/
+ if (!Jcp)
+ Jcp = new(g)JDBConn(g, this);
+ else if (Jcp->IsOpen())
+ Jcp->Close();
+
+ if (Jcp->Open(Jpath, &Ops) == RC_FX)
+ return true;
+ else if (Quoted)
+ Quote = Jcp->GetQuoteChar();
+
+ Use = USE_OPEN; // Do it now in case we are recursively called
+
+ /*********************************************************************/
+ /* Make the command and allocate whatever is used for getting results. */
+ /*********************************************************************/
+ if (Mode == MODE_READ || Mode == MODE_READX) {
+ if (Memory > 1 && !Srcdef) {
+ int n;
+
+ if (!MakeSQL(g, true)) {
+ // Allocate a Count(*) column
+ Cnp = new(g)JDBCCOL;
+ Cnp->InitValue(g);
+
+ if ((n = Jcp->GetResultSize(Query->GetStr(), Cnp)) < 0) {
+ sprintf(g->Message, "Cannot get result size rc=%d", n);
+ return true;
+ } else if (n) {
+ Jcp->m_Rows = n;
+
+ if ((Qrp = Jcp->AllocateResult(g)))
+ Memory = 2; // Must be filled
+ else {
+ strcpy(g->Message, "Result set memory allocation failed");
+ return true;
+ } // endif n
+
+ } else // Void result
+ Memory = 0;
+
+ Jcp->m_Rows = 0;
+ } else
+ return true;
+
+ } // endif Memory
+
+ if (!(rc = MakeSQL(g, false))) {
+// for (PJDBCCOL colp = (PJDBCCOL)Columns; colp; colp = (PJDBCCOL)colp->GetNext())
+// if (!colp->IsSpecial())
+// colp->AllocateBuffers(g, Rows);
+
+ rc = (Mode == MODE_READ)
+ ? (Jcp->ExecuteQuery(Query->GetStr()) != RC_OK)
+ : false;
+ } // endif rc
+
+ } else if (Mode == MODE_INSERT) {
+#if 0
+ if (!(rc = MakeInsert(g))) {
+ if (Nparm != Jcp->PrepareSQL(Query->GetStr())) {
+ strcpy(g->Message, MSG(PARM_CNT_MISS));
+ rc = true;
+ } else
+ rc = BindParameters(g);
+
+ } // endif rc
+#endif // 0
+ rc = MakeInsert(g);
+ } else if (Mode == MODE_UPDATE || Mode == MODE_DELETE) {
+ rc = false; // wait for CheckCond before calling MakeCommand(g);
+ } else
+ sprintf(g->Message, "Invalid mode %d", Mode);
+
+ if (rc) {
+ Jcp->Close();
+ return true;
+ } // endif rc
+
+ /*********************************************************************/
+ /* Reset statistics values. */
+ /*********************************************************************/
+ num_read = num_there = num_eq[0] = num_eq[1] = 0;
+ return false;
+} // end of OpenDB
+
+/***********************************************************************/
+/* GetRecpos: return the position of last read record. */
+/***********************************************************************/
+int TDBJDBC::GetRecpos(void)
+{
+ return Fpos;
+} // end of GetRecpos
+
+/***********************************************************************/
+/* SetRecpos: set the position of next read record. */
+/***********************************************************************/
+bool TDBJDBC::SetRecpos(PGLOBAL g, int recpos)
+{
+ if (Jcp->m_Full) {
+ Fpos = 0;
+// CurNum = 0;
+ CurNum = 1;
+ } else if (Memory == 3) {
+// Fpos = recpos;
+// CurNum = -1;
+ Fpos = 0;
+ CurNum = recpos;
+ } else if (Ops.Scrollable) {
+ // Is new position in the current row set?
+// if (recpos >= Curpos && recpos < Curpos + Rbuf) {
+// CurNum = recpos - Curpos;
+// Fpos = 0;
+ if (recpos > 0 && recpos <= Rbuf) {
+ CurNum = recpos;
+ Fpos = recpos;
+ } else {
+ strcpy(g->Message, "Scrolling out of row set NIY");
+ return true;
+ } // endif recpos
+
+ } else {
+ strcpy(g->Message, "This action requires a scrollable cursor");
+ return true;
+ } // endif's
+
+ // Indicate the table position was externally set
+ Placed = true;
+ return false;
+} // end of SetRecpos
+
+/***********************************************************************/
+/* Data Base indexed read routine for JDBC access method. */
+/***********************************************************************/
+bool TDBJDBC::ReadKey(PGLOBAL g, OPVAL op, const key_range *kr)
+{
+ char c = Quote ? *Quote : 0;
+ int rc, oldlen = Query->GetLength();
+ PHC hc = To_Def->GetHandler();
+
+ if (!(kr || hc->end_range) || op == OP_NEXT ||
+ Mode == MODE_UPDATE || Mode == MODE_DELETE) {
+ if (!kr && Mode == MODE_READX) {
+ // This is a false indexed read
+ rc = Jcp->ExecuteQuery((char*)Query->GetStr());
+ Mode = MODE_READ;
+ Rows = 1; // ???
+ return (rc != RC_OK);
+ } // endif key
+
+ return false;
+ } else {
+ if (hc->MakeKeyWhere(g, Query, op, c, kr))
+ return true;
+
+ if (To_CondFil) {
+ if (To_CondFil->Idx != hc->active_index) {
+ To_CondFil->Idx = hc->active_index;
+ To_CondFil->Body= (char*)PlugSubAlloc(g, NULL, 0);
+ *To_CondFil->Body= 0;
+
+ if ((To_CondFil = hc->CheckCond(g, To_CondFil, To_CondFil->Cond)))
+ PlugSubAlloc(g, NULL, strlen(To_CondFil->Body) + 1);
+
+ } // endif active_index
+
+ if (To_CondFil)
+ if (Query->Append(" AND ") || Query->Append(To_CondFil->Body)) {
+ strcpy(g->Message, "Readkey: Out of memory");
+ return true;
+ } // endif Append
+
+ } // endif To_Condfil
+
+ Mode = MODE_READ;
+ } // endif's op
+
+ if (trace)
+ htrc("JDBC ReadKey: Query=%s\n", Query->GetStr());
+
+ rc = Jcp->ExecuteQuery((char*)Query->GetStr());
+ Query->Truncate(oldlen);
+ Rows = 1; // ???
+ return (rc != RC_OK);
+} // end of ReadKey
+
+/***********************************************************************/
+/* Data Base read routine for JDBC access method. */
+/***********************************************************************/
+int TDBJDBC::ReadDB(PGLOBAL g)
+{
+ int rc;
+
+ if (trace > 1)
+ htrc("JDBC ReadDB: R%d Mode=%d key=%p link=%p Kindex=%p\n",
+ GetTdb_No(), Mode, To_Key_Col, To_Link, To_Kindex);
+
+ if (Mode == MODE_UPDATE || Mode == MODE_DELETE) {
+ if (!Query && MakeCommand(g))
+ return RC_FX;
+
+ // Send the UPDATE/DELETE command to the remote table
+ rc = Jcp->ExecuteUpdate(Query->GetStr());
+
+ if (rc == RC_OK) {
+ AftRows = Jcp->m_Aff;
+ return RC_EF; // Nothing else to do
+ } else {
+ Werr = true;
+ return RC_FX;
+ } // endif rc
+
+ } // endif Mode
+
+ if (To_Kindex) {
+ // Direct access of JDBC tables is not implemented
+ strcpy(g->Message, "No JDBC direct access");
+ return RC_FX;
+ } // endif To_Kindex
+
+ /*********************************************************************/
+ /* Now start the reading process. */
+ /* Here is the place to fetch the line(s). */
+ /*********************************************************************/
+ if (Placed) {
+ if (Fpos && CurNum >= 0)
+ Rbuf = Jcp->Fetch((Curpos = Fpos));
+ else
+ Fpos = CurNum;
+
+ rc = (Rbuf > 0) ? RC_OK : (Rbuf == 0) ? RC_EF : RC_FX;
+ Placed = false;
+ } else {
+ if (Memory != 3) {
+ if (++CurNum >= Rbuf) {
+ Rbuf = Jcp->Fetch();
+ Curpos = Fpos + 1;
+ CurNum = 0;
+ } // endif CurNum
+
+ rc = (Rbuf > 0) ? RC_OK : (Rbuf == 0) ? RC_EF : RC_FX;
+ } else // Getting result from memory
+ rc = (Fpos < Qrp->Nblin) ? RC_OK : RC_EF;
+
+ if (rc == RC_OK) {
+ if (Memory == 2)
+ Qrp->Nblin++;
+
+ Fpos++; // Used for memory and pos
+ } // endif rc
+
+ } // endif placed
+
+ if (trace > 1)
+ htrc(" Read: Rbuf=%d rc=%d\n", Rbuf, rc);
+
+ return rc;
+} // end of ReadDB
+
+/***********************************************************************/
+/* Data Base Insert write routine for JDBC access method. */
+/***********************************************************************/
+int TDBJDBC::WriteDB(PGLOBAL g)
+{
+ int rc;
+
+ if (Prepared) {
+ if (SetParameters(g)) {
+ Werr = true;
+ rc = RC_FX;
+ } else if ((rc = Jcp->ExecuteSQL()) == RC_OK)
+ AftRows += Jcp->m_Aff;
+ else
+ Werr = true;
+
+ return rc;
+ } // endif Prepared
+
+ // Statement was not prepared, we must construct and execute
+ // an insert query for each line to insert
+ uint len = Query->GetLength();
+ char buf[64];
+ bool oom = false;
+
+ // Make the Insert command value list
+ for (PCOL colp = Columns; colp; colp = colp->GetNext()) {
+ if (!colp->GetValue()->IsNull()) {
+ char *s = colp->GetValue()->GetCharString(buf);
+
+ if (colp->GetResultType() == TYPE_STRING)
+ oom |= Query->Append_quoted(s);
+ else if (colp->GetResultType() == TYPE_DATE) {
+ DTVAL *dtv = (DTVAL*)colp->GetValue();
+
+ if (dtv->IsFormatted())
+ oom |= Query->Append_quoted(s);
+ else
+ oom |= Query->Append(s);
+
+ } else
+ oom |= Query->Append(s);
+
+ } else
+ oom |= Query->Append("NULL");
+
+ oom |= Query->Append(',');
+ } // endfor colp
+
+ if (unlikely(oom)) {
+ strcpy(g->Message, "WriteDB: Out of memory");
+ return RC_FX;
+ } // endif oom
+
+ Query->RepLast(')');
+ rc = Jcp->ExecuteUpdate(Query->GetStr());
+ Query->Truncate(len); // Restore query
+
+ if (rc == RC_OK)
+ AftRows += Jcp->m_Aff;
+ else
+ Werr = true;
+
+ return rc;
+} // end of WriteDB
+
+/***********************************************************************/
+/* Data Base delete line routine for JDBC access method. */
+/***********************************************************************/
+int TDBJDBC::DeleteDB(PGLOBAL g, int irc)
+{
+ if (irc == RC_FX) {
+ if (!Query && MakeCommand(g))
+ return RC_FX;
+
+ // Send the DELETE (all) command to the remote table
+ if (Jcp->ExecuteUpdate(Query->GetStr()) == RC_OK) {
+ AftRows = Jcp->m_Aff;
+ sprintf(g->Message, "%s: %d affected rows", TableName, AftRows);
+
+ if (trace)
+ htrc("%s\n", g->Message);
+
+ PushWarning(g, this, 0); // 0 means a Note
+ return RC_OK; // This is a delete all
+ } else
+ return RC_FX; // Error
+
+ } else
+ return RC_OK; // Ignore
+
+} // end of DeleteDB
+
+/***********************************************************************/
+/* Data Base close routine for JDBC access method. */
+/***********************************************************************/
+void TDBJDBC::CloseDB(PGLOBAL g)
+{
+ //if (To_Kindex) {
+ // To_Kindex->Close();
+ // To_Kindex = NULL;
+ // } // endif
+
+ if (Jcp)
+ Jcp->Close();
+
+ if (trace)
+ htrc("JDBC CloseDB: closing %s\n", Name);
+
+ if (!Werr &&
+ (Mode == MODE_INSERT || Mode == MODE_UPDATE || Mode == MODE_DELETE)) {
+ sprintf(g->Message, "%s: %d affected rows", TableName, AftRows);
+
+ if (trace)
+ htrc("%s\n", g->Message);
+
+ PushWarning(g, this, 0); // 0 means a Note
+ } // endif Mode
+
+ Prepared = false;
+} // end of CloseDB
+
+/* --------------------------- JDBCCOL ------------------------------- */
+
+/***********************************************************************/
+/* JDBCCOL public constructor. */
+/***********************************************************************/
+JDBCCOL::JDBCCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am)
+ : COLBLK(cdp, tdbp, i)
+{
+ if (cprec) {
+ Next = cprec->GetNext();
+ cprec->SetNext(this);
+ } else {
+ Next = tdbp->GetColumns();
+ tdbp->SetColumns(this);
+ } // endif cprec
+
+ // Set additional JDBC access method information for column.
+ Crp = NULL;
+ //Long = cdp->GetLong();
+ Long = Precision;
+ //strcpy(F_Date, cdp->F_Date);
+ To_Val = NULL;
+//Slen = 0;
+//StrLen = &Slen;
+//Sqlbuf = NULL;
+ Bufp = NULL;
+ Blkp = NULL;
+ Rank = 0; // Not known yet
+
+ if (trace)
+ htrc(" making new %sCOL C%d %s at %p\n", am, Index, Name, this);
+
+} // end of JDBCCOL constructor
+
+/***********************************************************************/
+/* JDBCCOL private constructor. */
+/***********************************************************************/
+JDBCCOL::JDBCCOL(void) : COLBLK()
+{
+ Crp = NULL;
+ Buf_Type = TYPE_INT; // This is a count(*) column
+ // Set additional Dos access method information for column.
+ Long = sizeof(int);
+ To_Val = NULL;
+//Slen = 0;
+//StrLen = &Slen;
+//Sqlbuf = NULL;
+ Bufp = NULL;
+ Blkp = NULL;
+ Rank = 1;
+} // end of JDBCCOL constructor
+
+/***********************************************************************/
+/* JDBCCOL constructor used for copying columns. */
+/* tdbp is the pointer to the new table descriptor. */
+/***********************************************************************/
+JDBCCOL::JDBCCOL(JDBCCOL *col1, PTDB tdbp) : COLBLK(col1, tdbp)
+{
+ Crp = col1->Crp;
+ Long = col1->Long;
+ //strcpy(F_Date, col1->F_Date);
+ To_Val = col1->To_Val;
+//Slen = col1->Slen;
+//StrLen = col1->StrLen;
+//Sqlbuf = col1->Sqlbuf;
+ Bufp = col1->Bufp;
+ Blkp = col1->Blkp;
+ Rank = col1->Rank;
+} // end of JDBCCOL copy constructor
+
+/***********************************************************************/
+/* SetBuffer: prepare a column block for write operation. */
+/***********************************************************************/
+bool JDBCCOL::SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check)
+{
+ if (!(To_Val = value)) {
+ sprintf(g->Message, MSG(VALUE_ERROR), Name);
+ return true;
+ } else if (Buf_Type == value->GetType()) {
+ // Values are of the (good) column type
+ if (Buf_Type == TYPE_DATE) {
+ // If any of the date values is formatted
+ // output format must be set for the receiving table
+ if (GetDomain() || ((DTVAL *)value)->IsFormatted())
+ goto newval; // This will make a new value;
+
+ } else if (Buf_Type == TYPE_DOUBLE)
+ // Float values must be written with the correct (column) precision
+ // Note: maybe this should be forced by ShowValue instead of this ?
+ value->SetPrec(GetScale());
+
+ Value = value; // Directly access the external value
+ } else {
+ // Values are not of the (good) column type
+ if (check) {
+ sprintf(g->Message, MSG(TYPE_VALUE_ERR), Name,
+ GetTypeName(Buf_Type), GetTypeName(value->GetType()));
+ return true;
+ } // endif check
+
+ newval:
+ if (InitValue(g)) // Allocate the matching value block
+ return true;
+
+ } // endif's Value, Buf_Type
+
+ // Because Colblk's have been made from a copy of the original TDB in
+ // case of Update, we must reset them to point to the original one.
+ if (To_Tdb->GetOrig())
+ To_Tdb = (PTDB)To_Tdb->GetOrig();
+
+ // Set the Column
+ Status = (ok) ? BUF_EMPTY : BUF_NO;
+ return false;
+} // end of SetBuffer
+
+/***********************************************************************/
+/* ReadColumn: when SQLFetch is used there is nothing to do as the */
+/* column buffer was bind to the record set. This is also the case */
+/* when calculating MaxSize (Bufp is NULL even when Rows is not). */
+/***********************************************************************/
+void JDBCCOL::ReadColumn(PGLOBAL g)
+{
+ PTDBJDBC tdbp = (PTDBJDBC)To_Tdb;
+ int i = tdbp->Fpos - 1, n = tdbp->CurNum;
+
+ if (tdbp->Memory == 3) {
+ // Get the value from the stored memory
+ if (Crp->Nulls && Crp->Nulls[i] == '*') {
+ Value->Reset();
+ Value->SetNull(true);
+ } else {
+ Value->SetValue_pvblk(Crp->Kdata, i);
+ Value->SetNull(false);
+ } // endif Nulls
+
+ return;
+ } // endif Memory
+
+ /*********************************************************************/
+ /* Get the column value. */
+ /*********************************************************************/
+ tdbp->Jcp->SetColumnValue(Rank, Name, Value);
+
+ if (tdbp->Memory != 2)
+ return;
+
+ /*********************************************************************/
+ /* Fill the allocated result structure. */
+ /*********************************************************************/
+ if (Value->IsNull()) {
+ if (Crp->Nulls)
+ Crp->Nulls[i] = '*'; // Null value
+
+ Crp->Kdata->Reset(i);
+ } else
+ Crp->Kdata->SetValue(Value, i);
+
+} // end of ReadColumn
+
+#if 0
+/***********************************************************************/
+/* AllocateBuffers: allocate the extended buffer for SQLExtendedFetch */
+/* or Fetch. Note: we use Long+1 here because JDBC must have space */
+/* for the ending null character. */
+/***********************************************************************/
+void JDBCCOL::AllocateBuffers(PGLOBAL g, int rows)
+{
+ if (Buf_Type == TYPE_DATE)
+ Sqlbuf = (TIMESTAMP_STRUCT*)PlugSubAlloc(g, NULL,
+ sizeof(TIMESTAMP_STRUCT));
+
+ if (!rows)
+ return;
+
+ if (Buf_Type == TYPE_DATE)
+ Bufp = PlugSubAlloc(g, NULL, rows * sizeof(TIMESTAMP_STRUCT));
+ else {
+ Blkp = AllocValBlock(g, NULL, Buf_Type, rows, GetBuflen(),
+ GetScale(), true, false, false);
+ Bufp = Blkp->GetValPointer();
+ } // endelse
+
+ if (rows > 1)
+ StrLen = (SQLLEN *)PlugSubAlloc(g, NULL, rows * sizeof(SQLLEN));
+
+} // end of AllocateBuffers
+
+/***********************************************************************/
+/* Returns the buffer to use for Fetch or Extended Fetch. */
+/***********************************************************************/
+void *JDBCCOL::GetBuffer(DWORD rows)
+{
+ if (rows && To_Tdb) {
+ assert(rows == (DWORD)((TDBJDBC*)To_Tdb)->Rows);
+ return Bufp;
+ } else
+ return (Buf_Type == TYPE_DATE) ? Sqlbuf : Value->GetTo_Val();
+
+} // end of GetBuffer
+
+/***********************************************************************/
+/* Returns the buffer length to use for Fetch or Extended Fetch. */
+/***********************************************************************/
+SWORD JDBCCOL::GetBuflen(void)
+{
+ SWORD flen;
+
+ switch (Buf_Type) {
+ case TYPE_DATE:
+ flen = (SWORD)sizeof(TIMESTAMP_STRUCT);
+ break;
+ case TYPE_STRING:
+ case TYPE_DECIM:
+ flen = (SWORD)Value->GetClen() + 1;
+ break;
+ default:
+ flen = (SWORD)Value->GetClen();
+ } // endswitch Buf_Type
+
+ return flen;
+} // end of GetBuflen
+#endif // 0
+
+/***********************************************************************/
+/* WriteColumn: make sure the bind buffer is updated. */
+/***********************************************************************/
+void JDBCCOL::WriteColumn(PGLOBAL g)
+{
+ /*********************************************************************/
+ /* Do convert the column value if necessary. */
+ /*********************************************************************/
+ if (Value != To_Val)
+ Value->SetValue_pval(To_Val, FALSE); // Convert the inserted value
+
+#if 0
+ if (Buf_Type == TYPE_DATE) {
+ struct tm tm, *dbtime = ((DTVAL*)Value)->GetGmTime(&tm);
+
+ Sqlbuf->second = dbtime->tm_sec;
+ Sqlbuf->minute = dbtime->tm_min;
+ Sqlbuf->hour = dbtime->tm_hour;
+ Sqlbuf->day = dbtime->tm_mday;
+ Sqlbuf->month = dbtime->tm_mon + 1;
+ Sqlbuf->year = dbtime->tm_year + 1900;
+ Sqlbuf->fraction = 0;
+ } else if (Buf_Type == TYPE_DECIM) {
+ // Some data sources require local decimal separator
+ char *p, sep = ((PTDBJDBC)To_Tdb)->Sep;
+
+ if (sep && (p = strchr(Value->GetCharValue(), '.')))
+ *p = sep;
+
+ } // endif Buf_Type
+
+ if (Nullable)
+ *StrLen = (Value->IsNull()) ? SQL_NULL_DATA :
+ (IsTypeChar(Buf_Type)) ? SQL_NTS : 0;
+#endif // 0
+} // end of WriteColumn
+
+/* -------------------------- Class TDBXJDC -------------------------- */
+
+/***********************************************************************/
+/* Implementation of the TDBXJDC class. */
+/***********************************************************************/
+TDBXJDC::TDBXJDC(PJDBCDEF tdp) : TDBJDBC(tdp)
+{
+ Cmdlist = NULL;
+ Cmdcol = NULL;
+ Mxr = tdp->Maxerr;
+ Nerr = 0;
+} // end of TDBXJDC constructor
+
+/***********************************************************************/
+/* Allocate XSRC column description block. */
+/***********************************************************************/
+PCOL TDBXJDC::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n)
+{
+ PJSRCCOL colp = new(g)JSRCCOL(cdp, this, cprec, n);
+
+ if (!colp->Flag)
+ Cmdcol = colp->GetName();
+
+ return colp;
+} // end of MakeCol
+
+/***********************************************************************/
+/* MakeCMD: make the SQL statement to send to JDBC connection. */
+/***********************************************************************/
+PCMD TDBXJDC::MakeCMD(PGLOBAL g)
+{
+ PCMD xcmd = NULL;
+
+ if (To_CondFil) {
+ if (Cmdcol) {
+ if (!stricmp(Cmdcol, To_CondFil->Body) &&
+ (To_CondFil->Op == OP_EQ || To_CondFil->Op == OP_IN)) {
+ xcmd = To_CondFil->Cmds;
+ } else
+ strcpy(g->Message, "Invalid command specification filter");
+
+ } else
+ strcpy(g->Message, "No command column in select list");
+
+ } else if (!Srcdef)
+ strcpy(g->Message, "No Srcdef default command");
+ else
+ xcmd = new(g) CMD(g, Srcdef);
+
+ return xcmd;
+} // end of MakeCMD
+
+#if 0
+/***********************************************************************/
+/* JDBC Bind Parameter function. */
+/***********************************************************************/
+bool TDBXJDC::BindParameters(PGLOBAL g)
+{
+ PJDBCCOL colp;
+
+ for (colp = (PJDBCCOL)Columns; colp; colp = (PJDBCCOL)colp->Next) {
+ colp->AllocateBuffers(g, 0);
+
+ if (Jcp->BindParam(colp))
+ return true;
+
+ } // endfor colp
+
+ return false;
+} // end of BindParameters
+#endif // 0
+
+/***********************************************************************/
+/* XDBC GetMaxSize: returns table size (not always one row). */
+/***********************************************************************/
+int TDBXJDC::GetMaxSize(PGLOBAL g)
+{
+ if (MaxSize < 0)
+ MaxSize = 2; // Just a guess
+
+ return MaxSize;
+} // end of GetMaxSize
+
+/***********************************************************************/
+/* JDBC Access Method opening routine. */
+/* New method now that this routine is called recursively (last table */
+/* first in reverse order): index blocks are immediately linked to */
+/* join block of next table if it exists or else are discarted. */
+/***********************************************************************/
+bool TDBXJDC::OpenDB(PGLOBAL g)
+{
+ bool rc = false;
+
+ if (trace)
+ htrc("JDBC OpenDB: tdbp=%p tdb=R%d use=%d mode=%d\n",
+ this, Tdb_No, Use, Mode);
+
+ if (Use == USE_OPEN) {
+ strcpy(g->Message, "Multiple execution is not allowed");
+ return true;
+ } // endif use
+
+ /*********************************************************************/
+ /* Open an JDBC connection for this table. */
+ /* Note: this may not be the proper way to do. Perhaps it is better */
+ /* to test whether a connection is already open for this datasource */
+ /* and if so to allocate just a new result set. But this only for */
+ /* drivers allowing concurency in getting results ??? */
+ /*********************************************************************/
+ if (!Jcp) {
+ Jcp = new(g) JDBConn(g, this);
+ } else if (Jcp->IsOpen())
+ Jcp->Close();
+
+ if (Jcp->Open(Jpath, &Ops) == RC_FX)
+ return true;
+
+ Use = USE_OPEN; // Do it now in case we are recursively called
+
+ if (Mode != MODE_READ && Mode != MODE_READX) {
+ strcpy(g->Message, "No INSERT/DELETE/UPDATE of XJDBC tables");
+ return true;
+ } // endif Mode
+
+ /*********************************************************************/
+ /* Get the command to execute. */
+ /*********************************************************************/
+ if (!(Cmdlist = MakeCMD(g))) {
+ Jcp->Close();
+ return true;
+ } // endif Query
+
+ Rows = 1;
+ return false;
+} // end of OpenDB
+
+/***********************************************************************/
+/* ReadDB: Data Base read routine for xdbc access method. */
+/***********************************************************************/
+int TDBXJDC::ReadDB(PGLOBAL g)
+{
+ if (Cmdlist) {
+ int rc;
+
+ if (!Query)
+ Query = new(g) STRING(g, 0, Cmdlist->Cmd);
+ else
+ Query->Set(Cmdlist->Cmd);
+
+ if ((rc = Jcp->ExecSQLcommand(Query->GetStr())) == RC_FX)
+ Nerr++;
+
+ if (rc == RC_NF)
+ AftRows = Jcp->m_Aff;
+ else if (rc == RC_OK)
+ AftRows = Jcp->m_Ncol;
+
+ Fpos++; // Used for progress info
+ Cmdlist = (Nerr > Mxr) ? NULL : Cmdlist->Next;
+ return RC_OK;
+ } else
+ return RC_EF;
+
+} // end of ReadDB
+
+/***********************************************************************/
+/* Data Base write line routine for JDBC access method. */
+/***********************************************************************/
+int TDBXJDC::WriteDB(PGLOBAL g)
+{
+ strcpy(g->Message, "Execsrc tables are read only");
+ return RC_FX;
+} // end of DeleteDB
+
+/***********************************************************************/
+/* Data Base delete line routine for JDBC access method. */
+/***********************************************************************/
+int TDBXJDC::DeleteDB(PGLOBAL g, int irc)
+{
+ strcpy(g->Message, "NO_XJDBC_DELETE");
+ return RC_FX;
+} // end of DeleteDB
+
+/* --------------------------- JSRCCOL ------------------------------- */
+
+/***********************************************************************/
+/* JSRCCOL public constructor. */
+/***********************************************************************/
+JSRCCOL::JSRCCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am)
+ : JDBCCOL(cdp, tdbp, cprec, i, am)
+{
+ // Set additional JDBC access method information for column.
+ Flag = cdp->GetOffset();
+} // end of JSRCCOL constructor
+
+/***********************************************************************/
+/* ReadColumn: set column value according to Flag. */
+/***********************************************************************/
+void JSRCCOL::ReadColumn(PGLOBAL g)
+{
+ PTDBXJDC tdbp = (PTDBXJDC)To_Tdb;
+
+ switch (Flag) {
+ case 0: Value->SetValue_psz(tdbp->Query->GetStr()); break;
+ case 1: Value->SetValue(tdbp->AftRows); break;
+ case 2: Value->SetValue_psz(g->Message); break;
+ default: Value->SetValue_psz("Invalid Flag"); break;
+ } // endswitch Flag
+
+} // end of ReadColumn
+
+/***********************************************************************/
+/* WriteColumn: Should never be called. */
+/***********************************************************************/
+void JSRCCOL::WriteColumn(PGLOBAL g)
+{
+ // Should never be called
+} // end of WriteColumn
+
+/* ---------------------------TDBJDRV class -------------------------- */
+
+/***********************************************************************/
+/* GetResult: Get the list of JDBC drivers. */
+/***********************************************************************/
+PQRYRES TDBJDRV::GetResult(PGLOBAL g)
+{
+ return JDBCDrivers(g, Jpath, Maxres, false);
+} // end of GetResult
+
+/* ---------------------------TDBJTB class --------------------------- */
+
+/***********************************************************************/
+/* TDBJTB class constructor. */
+/***********************************************************************/
+TDBJTB::TDBJTB(PJDBCDEF tdp) : TDBJDRV(tdp)
+{
+ Jpath = tdp->Jpath;
+ Schema = tdp->Tabschema;
+ Tab = tdp->Tabname;
+ Tabtype = tdp->Tabtype;
+ Ops.Driver = tdp->Driver;
+ Ops.Url = tdp->Url;
+ Ops.User = tdp->Username;
+ Ops.Pwd = tdp->Password;
+} // end of TDBJTB constructor
+
+/***********************************************************************/
+/* GetResult: Get the list of JDBC tables. */
+/***********************************************************************/
+PQRYRES TDBJTB::GetResult(PGLOBAL g)
+{
+ return JDBCTables(g, Jpath, Schema, Tab, Tabtype, Maxres, false, &Ops);
+} // end of GetResult
+
+/* --------------------------TDBJDBCL class -------------------------- */
+
+/***********************************************************************/
+/* GetResult: Get the list of JDBC table columns. */
+/***********************************************************************/
+PQRYRES TDBJDBCL::GetResult(PGLOBAL g)
+{
+ return JDBCColumns(g, Jpath, Schema, Tab, NULL, Maxres, false, &Ops);
+} // end of GetResult
+
+#if 0
+/* ---------------------------TDBJSRC class -------------------------- */
+
+/***********************************************************************/
+/* GetResult: Get the list of JDBC data sources. */
+/***********************************************************************/
+PQRYRES TDBJSRC::GetResult(PGLOBAL g)
+{
+ return JDBCDataSources(g, Maxres, false);
+} // end of GetResult
+
+/* ------------------------ End of TabJDBC --------------------------- */
+#endif // 0
diff --git a/storage/connect/tabjdbc.h b/storage/connect/tabjdbc.h
new file mode 100644
index 00000000000..b6cf91e28b8
--- /dev/null
+++ b/storage/connect/tabjdbc.h
@@ -0,0 +1,348 @@
+/*************** Tabjdbc H Declares Source Code File (.H) **************/
+/* Name: TABJDBC.H Version 1.0 */
+/* */
+/* (C) Copyright to the author Olivier BERTRAND 2016 */
+/* */
+/* This file contains the TDBJDBC classes declares. */
+/***********************************************************************/
+#include "colblk.h"
+#include "resource.h"
+
+typedef class JDBCDEF *PJDBCDEF;
+typedef class TDBJDBC *PTDBJDBC;
+typedef class JDBCCOL *PJDBCCOL;
+typedef class TDBXJDC *PTDBXJDC;
+typedef class JSRCCOL *PJSRCCOL;
+//typedef class TDBOIF *PTDBOIF;
+//typedef class OIFCOL *POIFCOL;
+//typedef class TDBJSRC *PTDBJSRC;
+
+/***********************************************************************/
+/* JDBC table. */
+/***********************************************************************/
+class DllExport JDBCDEF : public TABDEF { /* Logical table description */
+ friend class TDBJDBC;
+ friend class TDBXJDC;
+ friend class TDBJDRV;
+ friend class TDBJTB;
+public:
+ // Constructor
+ JDBCDEF(void);
+
+ // Implementation
+ virtual const char *GetType(void) { return "JDBC"; }
+ PSZ GetJpath(void) { return Jpath; }
+ PSZ GetTabname(void) { return Tabname; }
+ PSZ GetTabschema(void) { return Tabschema; }
+ PSZ GetTabcat(void) { return Tabcat; }
+ PSZ GetSrcdef(void) { return Srcdef; }
+ char GetSep(void) { return (Sep) ? *Sep : 0; }
+ int GetQuoted(void) { return Quoted; }
+//int GetCatver(void) { return Catver; }
+ int GetOptions(void) { return Options; }
+
+ // Methods
+ virtual int Indexable(void) { return 2; }
+ virtual bool DefineAM(PGLOBAL g, LPCSTR am, int poff);
+ virtual PTDB GetTable(PGLOBAL g, MODE m);
+
+protected:
+ // Members
+ PSZ Jpath; /* Java class path */
+ PSZ Driver; /* JDBC driver */
+ PSZ Url; /* JDBC driver URL */
+ PSZ Tabname; /* External table name */
+ PSZ Tabschema; /* External table schema */
+ PSZ Username; /* User connect name */
+ PSZ Password; /* Password connect info */
+ PSZ Tabcat; /* External table catalog */
+ PSZ Tabtype; /* External table type */
+ PSZ Srcdef; /* The source table SQL definition */
+ PSZ Qchar; /* Identifier quoting character */
+ PSZ Qrystr; /* The original query */
+ PSZ Sep; /* Decimal separator */
+ int Options; /* Open connection options */
+//int Cto; /* Open connection timeout */
+//int Qto; /* Query (command) timeout */
+ int Quoted; /* Identifier quoting level */
+ int Maxerr; /* Maxerr for an Exec table */
+ int Maxres; /* Maxres for a catalog table */
+ int Memory; /* Put result set in memory */
+ bool Scrollable; /* Use scrollable cursor */
+ bool Xsrc; /* Execution type */
+}; // end of JDBCDEF
+
+#if !defined(NJDBC)
+#include "JDBConn.h"
+
+/***********************************************************************/
+/* This is the JDBC Access Method class declaration for files from */
+/* other DB drivers to be accessed via JDBC. */
+/***********************************************************************/
+class TDBJDBC : public TDBASE {
+ friend class JDBCCOL;
+ friend class JDBConn;
+public:
+ // Constructor
+ TDBJDBC(PJDBCDEF tdp = NULL);
+ TDBJDBC(PTDBJDBC tdbp);
+
+ // Implementation
+ virtual AMT GetAmType(void) { return TYPE_AM_JDBC; }
+ virtual PTDB Duplicate(PGLOBAL g) { return (PTDB)new(g)TDBJDBC(this); }
+
+ // Methods
+ virtual PTDB CopyOne(PTABS t);
+ virtual int GetRecpos(void);
+ virtual bool SetRecpos(PGLOBAL g, int recpos);
+//virtual PSZ GetFile(PGLOBAL g);
+//virtual void SetFile(PGLOBAL g, PSZ fn);
+ virtual void ResetSize(void);
+ //virtual int GetAffectedRows(void) {return AftRows;}
+ virtual PSZ GetServer(void) { return "JDBC"; }
+ virtual int Indexable(void) { return 2; }
+
+ // Database routines
+ virtual PCOL MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n);
+ virtual int Cardinality(PGLOBAL g);
+ virtual int GetMaxSize(PGLOBAL g);
+ virtual int GetProgMax(PGLOBAL g);
+ virtual bool OpenDB(PGLOBAL g);
+ virtual int ReadDB(PGLOBAL g);
+ virtual int WriteDB(PGLOBAL g);
+ virtual int DeleteDB(PGLOBAL g, int irc);
+ virtual void CloseDB(PGLOBAL g);
+ virtual bool ReadKey(PGLOBAL g, OPVAL op, const key_range *kr);
+
+protected:
+ // Internal functions
+ int Decode(char *utf, char *buf, size_t n);
+ bool MakeSQL(PGLOBAL g, bool cnt);
+ bool MakeInsert(PGLOBAL g);
+ bool MakeCommand(PGLOBAL g);
+ //bool MakeFilter(PGLOBAL g, bool c);
+ bool SetParameters(PGLOBAL g);
+ //char *MakeUpdate(PGLOBAL g);
+ //char *MakeDelete(PGLOBAL g);
+
+ // Members
+ JDBConn *Jcp; // Points to a JDBC connection class
+ JDBCCOL *Cnp; // Points to count(*) column
+ JDBCPARM Ops; // Additional parameters
+ PSTRG Query; // Constructed SQL query
+ char *Jpath; // Java class path
+ char *TableName; // Points to JDBC table name
+ char *Schema; // Points to JDBC table Schema
+ char *User; // User connect info
+ char *Pwd; // Password connect info
+ char *Catalog; // Points to JDBC table Catalog
+ char *Srcdef; // The source table SQL definition
+ char *Count; // Points to count(*) SQL statement
+//char *Where; // Points to local where clause
+ char *Quote; // The identifier quoting character
+ char *MulConn; // Used for multiple JDBC tables
+ char *DBQ; // The address part of Connect string
+ char *Qrystr; // The original query
+ char Sep; // The decimal separator
+ int Options; // Connect options
+//int Cto; // Connect timeout
+//int Qto; // Query timeout
+ int Quoted; // The identifier quoting level
+ int Fpos; // Position of last read record
+ int Curpos; // Cursor position of last fetch
+ int AftRows; // The number of affected rows
+ int Rows; // Rowset size
+ int CurNum; // Current buffer line number
+ int Rbuf; // Number of lines read in buffer
+ int BufSize; // Size of connect string buffer
+ int Ncol; // The column number
+ int Nparm; // The number of statement parameters
+ int Memory; // 0: No 1: Alloc 2: Put 3: Get
+//bool Scrollable; // Use scrollable cursor --> in Ops
+ bool Placed; // True for position reading
+ bool Prepared; // True when using prepared statement
+ bool Werr; // Write error
+ bool Rerr; // Rewind error
+ PQRYRES Qrp; // Points to storage result
+}; // end of class TDBJDBC
+
+/***********************************************************************/
+/* Class JDBCCOL: JDBC access method column descriptor. */
+/* This A.M. is used for JDBC tables. */
+/***********************************************************************/
+class JDBCCOL : public COLBLK {
+ friend class TDBJDBC;
+public:
+ // Constructors
+ JDBCCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am = "JDBC");
+ JDBCCOL(JDBCCOL *colp, PTDB tdbp); // Constructor used in copy process
+
+ // Implementation
+ virtual int GetAmType(void) { return TYPE_AM_JDBC; }
+//SQLLEN *GetStrLen(void) { return StrLen; }
+ int GetRank(void) { return Rank; }
+//PVBLK GetBlkp(void) {return Blkp;}
+ void SetCrp(PCOLRES crp) { Crp = crp; }
+
+ // Methods
+ virtual bool SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check);
+ virtual void ReadColumn(PGLOBAL g);
+ virtual void WriteColumn(PGLOBAL g);
+//void AllocateBuffers(PGLOBAL g, int rows);
+//void *GetBuffer(DWORD rows);
+//SWORD GetBuflen(void);
+ // void Print(PGLOBAL g, FILE *, uint);
+
+protected:
+ // Constructor used by GetMaxSize
+ JDBCCOL(void);
+
+ // Members
+ //TIMESTAMP_STRUCT *Sqlbuf; // To get SQL_TIMESTAMP's
+ PCOLRES Crp; // To storage result
+ void *Bufp; // To extended buffer
+ PVBLK Blkp; // To Value Block
+ //char F_Date[12]; // Internal Date format
+ PVAL To_Val; // To value used for Insert
+//SQLLEN *StrLen; // As returned by JDBC
+//SQLLEN Slen; // Used with Fetch
+ int Rank; // Rank (position) number in the query
+}; // end of class JDBCCOL
+
+/***********************************************************************/
+/* This is the JDBC Access Method class declaration that send */
+/* commands to be executed by other DB JDBC drivers. */
+/***********************************************************************/
+class TDBXJDC : public TDBJDBC {
+ friend class JSRCCOL;
+ friend class JDBConn;
+public:
+ // Constructors
+ TDBXJDC(PJDBCDEF tdp = NULL);
+
+ // Implementation
+ virtual AMT GetAmType(void) {return TYPE_AM_XDBC;}
+
+ // Methods
+ //virtual int GetRecpos(void);
+ //virtual PSZ GetFile(PGLOBAL g);
+ //virtual void SetFile(PGLOBAL g, PSZ fn);
+ //virtual void ResetSize(void);
+ //virtual int GetAffectedRows(void) {return AftRows;}
+ //virtual PSZ GetServer(void) {return "JDBC";}
+
+ // Database routines
+ virtual PCOL MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n);
+ //virtual int GetProgMax(PGLOBAL g);
+ virtual int GetMaxSize(PGLOBAL g);
+ virtual bool OpenDB(PGLOBAL g);
+ virtual int ReadDB(PGLOBAL g);
+ virtual int WriteDB(PGLOBAL g);
+ virtual int DeleteDB(PGLOBAL g, int irc);
+ //virtual void CloseDB(PGLOBAL g);
+
+protected:
+ // Internal functions
+ PCMD MakeCMD(PGLOBAL g);
+ //bool BindParameters(PGLOBAL g);
+
+ // Members
+ PCMD Cmdlist; // The commands to execute
+ char *Cmdcol; // The name of the Xsrc command column
+ int Mxr; // Maximum errors before closing
+ int Nerr; // Number of errors so far
+}; // end of class TDBXJDC
+
+/***********************************************************************/
+/* Used by table in source execute mode. */
+/***********************************************************************/
+class JSRCCOL : public JDBCCOL {
+ friend class TDBXJDC;
+public:
+ // Constructors
+ JSRCCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am = "JDBC");
+
+ // Implementation
+ //virtual int GetAmType(void) {return TYPE_AM_JDBC;}
+
+ // Methods
+ virtual void ReadColumn(PGLOBAL g);
+ virtual void WriteColumn(PGLOBAL g);
+ // void Print(PGLOBAL g, FILE *, uint);
+
+protected:
+ // Members
+ char *Buffer; // To get returned message
+ int Flag; // Column content desc
+}; // end of class JSRCCOL
+
+/***********************************************************************/
+/* This is the class declaration for the Drivers catalog table. */
+/***********************************************************************/
+class TDBJDRV : public TDBCAT {
+public:
+ // Constructor
+ TDBJDRV(PJDBCDEF tdp) : TDBCAT(tdp) {Maxres = tdp->Maxres; Jpath = tdp->Jpath;}
+
+protected:
+ // Specific routines
+ virtual PQRYRES GetResult(PGLOBAL g);
+
+ // Members
+ int Maxres; // Returned lines limit
+ char *Jpath; // Java class path
+}; // end of class TDBJDRV
+
+/***********************************************************************/
+/* This is the class declaration for the tables catalog table. */
+/***********************************************************************/
+class TDBJTB : public TDBJDRV {
+public:
+ // Constructor
+ TDBJTB(PJDBCDEF tdp);
+
+protected:
+ // Specific routines
+ virtual PQRYRES GetResult(PGLOBAL g);
+
+ // Members
+ char *Jpath; // Points to Java classpath
+ char *Schema; // Points to schema name or NULL
+ char *Tab; // Points to JDBC table name or pattern
+ char *Tabtype; // Points to JDBC table type
+ JDBCPARM Ops; // Additional parameters
+}; // end of class TDBJTB
+
+/***********************************************************************/
+/* This is the class declaration for the columns catalog table. */
+/***********************************************************************/
+class TDBJDBCL : public TDBJTB {
+public:
+ // Constructor
+ TDBJDBCL(PJDBCDEF tdp) : TDBJTB(tdp) {}
+
+protected:
+ // Specific routines
+ virtual PQRYRES GetResult(PGLOBAL g);
+
+ // No additional Members
+}; // end of class TDBJCL
+
+#if 0
+/***********************************************************************/
+/* This is the class declaration for the Data Sources catalog table. */
+/***********************************************************************/
+class TDBJSRC : public TDBJDRV {
+public:
+ // Constructor
+ TDBJSRC(PJDBCDEF tdp) : TDBJDRV(tdp) {}
+
+protected:
+ // Specific routines
+ virtual PQRYRES GetResult(PGLOBAL g);
+
+ // No additional Members
+}; // end of class TDBJSRC
+#endif // 0
+
+#endif // !NJDBC
diff --git a/storage/connect/tabmysql.cpp b/storage/connect/tabmysql.cpp
index 47497f465e3..98a476bf94f 100644
--- a/storage/connect/tabmysql.cpp
+++ b/storage/connect/tabmysql.cpp
@@ -19,7 +19,7 @@
/* --------------- */
/* TABMYSQL.CPP - Source code */
/* PLGDBSEM.H - DB application declaration file */
-/* TABMYSQL.H - TABODBC classes declaration file */
+/* TABMYSQL.H - TABMYSQL classes declaration file */
/* GLOBAL.H - Global declaration file */
/* */
/* REQUIRED LIBRARIES: */
@@ -857,7 +857,9 @@ bool TDBMYSQL::OpenDB(PGLOBAL g)
/*******************************************************************/
/* Table already open, just replace it at its beginning. */
/*******************************************************************/
- Myc.Rewind();
+ if (Myc.Rewind(g, (Mode == MODE_READX) ? Query->GetStr() : NULL) != RC_OK)
+ return true;
+
N = -1;
return false;
} // endif use
diff --git a/storage/connect/tabodbc.cpp b/storage/connect/tabodbc.cpp
index c555f2a5abb..5fd0534210d 100644
--- a/storage/connect/tabodbc.cpp
+++ b/storage/connect/tabodbc.cpp
@@ -97,8 +97,8 @@ ODBCDEF::ODBCDEF(void)
{
Connect = Tabname = Tabschema = Username = Password = NULL;
Tabcat = Srcdef = Qchar = Qrystr = Sep = NULL;
- Catver = Options = Cto = Qto = Quoted = Maxerr = Maxres = 0;
- Scrollable = Memory = Xsrc = UseCnc = false;
+ Catver = Options = Cto = Qto = Quoted = Maxerr = Maxres = Memory = 0;
+ Scrollable = Xsrc = UseCnc = false;
} // end of ODBCDEF constructor
/***********************************************************************/
@@ -1009,7 +1009,7 @@ bool TDBODBC::SetRecpos(PGLOBAL g, int recpos)
} // end of SetRecpos
/***********************************************************************/
-/* Data Base indexed read routine for MYSQL access method. */
+/* Data Base indexed read routine for ODBC access method. */
/***********************************************************************/
bool TDBODBC::ReadKey(PGLOBAL g, OPVAL op, const key_range *kr)
{
@@ -1028,7 +1028,7 @@ bool TDBODBC::ReadKey(PGLOBAL g, OPVAL op, const key_range *kr)
return false;
} else {
- if (To_Def->GetHandler()->MakeKeyWhere(g, Query, op, c, kr))
+ if (hc->MakeKeyWhere(g, Query, op, c, kr))
return true;
if (To_CondFil) {
diff --git a/storage/connect/xindex.cpp b/storage/connect/xindex.cpp
index a2d75cec8ab..69aa7e2c20e 100755
--- a/storage/connect/xindex.cpp
+++ b/storage/connect/xindex.cpp
@@ -1279,7 +1279,7 @@ bool XINDEX::MapInit(PGLOBAL g)
IOFF *noff = (IOFF*)mbase;
// Position the memory base at the offset of this index
- mbase += noff[id].Low;
+ mbase += noff[id].v.Low;
} // endif id
// Now start the mapping process.
@@ -2347,10 +2347,10 @@ bool XFILE::Open(PGLOBAL g, char *filename, int id, MODE mode)
return true;
} // endif
- NewOff.Low = (int)ftell(Xfile);
+ NewOff.v.Low = (int)ftell(Xfile);
if (trace)
- htrc("XFILE Open: NewOff.Low=%d\n", NewOff.Low);
+ htrc("XFILE Open: NewOff.v.Low=%d\n", NewOff.v.Low);
} else if (mode == MODE_WRITE) {
if (id >= 0) {
@@ -2358,10 +2358,10 @@ bool XFILE::Open(PGLOBAL g, char *filename, int id, MODE mode)
memset(noff, 0, sizeof(noff));
Write(g, noff, sizeof(IOFF), MAX_INDX, rc);
fseek(Xfile, 0, SEEK_END);
- NewOff.Low = (int)ftell(Xfile);
+ NewOff.v.Low = (int)ftell(Xfile);
if (trace)
- htrc("XFILE Open: NewOff.Low=%d\n", NewOff.Low);
+ htrc("XFILE Open: NewOff.v.Low=%d\n", NewOff.v.Low);
} // endif id
@@ -2373,10 +2373,10 @@ bool XFILE::Open(PGLOBAL g, char *filename, int id, MODE mode)
} // endif MAX_INDX
if (trace)
- htrc("XFILE Open: noff[%d].Low=%d\n", id, noff[id].Low);
+ htrc("XFILE Open: noff[%d].v.Low=%d\n", id, noff[id].v.Low);
// Position the cursor at the offset of this index
- if (fseek(Xfile, noff[id].Low, SEEK_SET)) {
+ if (fseek(Xfile, noff[id].v.Low, SEEK_SET)) {
sprintf(g->Message, MSG(FUNC_ERRNO), errno, "Xseek");
return true;
} // endif
@@ -2566,14 +2566,14 @@ bool XHUGE::Open(PGLOBAL g, char *filename, int id, MODE mode)
return true;
} // endif
- NewOff.Low = (int)rc;
- NewOff.High = (int)high;
+ NewOff.v.Low = (int)rc;
+ NewOff.v.High = (int)high;
} else if (mode == MODE_WRITE) {
if (id >= 0) {
// New not sep index file. Write the header.
memset(noff, 0, sizeof(noff));
rc = WriteFile(Hfile, noff, sizeof(noff), &drc, NULL);
- NewOff.Low = (int)drc;
+ NewOff.v.Low = (int)drc;
} // endif id
} else if (mode == MODE_READ && id >= 0) {
@@ -2586,8 +2586,8 @@ bool XHUGE::Open(PGLOBAL g, char *filename, int id, MODE mode)
} // endif rc
// Position the cursor at the offset of this index
- rc = SetFilePointer(Hfile, noff[id].Low,
- (PLONG)&noff[id].High, FILE_BEGIN);
+ rc = SetFilePointer(Hfile, noff[id].v.Low,
+ (PLONG)&noff[id].v.High, FILE_BEGIN);
if (rc == INVALID_SET_FILE_POINTER) {
sprintf(g->Message, MSG(FUNC_ERRNO), GetLastError(), "SetFilePointer");
@@ -2649,7 +2649,7 @@ bool XHUGE::Open(PGLOBAL g, char *filename, int id, MODE mode)
if (id >= 0) {
// New not sep index file. Write the header.
memset(noff, 0, sizeof(noff));
- NewOff.Low = write(Hfile, &noff, sizeof(noff));
+ NewOff.v.Low = write(Hfile, &noff, sizeof(noff));
} // endif id
if (trace)
diff --git a/storage/connect/xindex.h b/storage/connect/xindex.h
index 51b678992ea..ef2e934e5ee 100644
--- a/storage/connect/xindex.h
+++ b/storage/connect/xindex.h
@@ -66,9 +66,9 @@ typedef struct index_def : public BLOCK {
typedef struct index_off {
union {
#if defined(WORDS_BIGENDIAN)
- struct {int High; int Low;};
+ struct {int High; int Low;} v;
#else // !WORDS_BIGENDIAN
- struct {int Low; int High;};
+ struct {int Low; int High;} v;
#endif //!WORDS_BIGENDIAN
longlong Val; // File position
}; // end of union
diff --git a/storage/federatedx/ha_federatedx.cc b/storage/federatedx/ha_federatedx.cc
index 890d1bff292..aae26758c78 100644
--- a/storage/federatedx/ha_federatedx.cc
+++ b/storage/federatedx/ha_federatedx.cc
@@ -1319,7 +1319,7 @@ bool ha_federatedx::create_where_from_key(String *to,
break;
}
DBUG_PRINT("info", ("federatedx HA_READ_AFTER_KEY %d", i));
- if (store_length >= length) /* end key */
+ if (store_length >= length || i > 0) /* end key */
{
if (emit_key_part_name(&tmp, key_part))
goto err;
diff --git a/storage/innobase/dict/dict0boot.cc b/storage/innobase/dict/dict0boot.cc
index 0dff05567d7..80724372f27 100644
--- a/storage/innobase/dict/dict0boot.cc
+++ b/storage/innobase/dict/dict0boot.cc
@@ -468,7 +468,7 @@ dict_boot(void)
} else {
ib_logf(IB_LOG_LEVEL_WARN,
"Change buffer not empty when --innodb-read-only "
- "is set! but srv_force_recovery = %d, ignoring.",
+ "is set! but srv_force_recovery = %lu, ignoring.",
srv_force_recovery);
}
}
diff --git a/storage/innobase/dict/dict0crea.cc b/storage/innobase/dict/dict0crea.cc
index 4a8dcd2f840..a5af8208135 100644
--- a/storage/innobase/dict/dict0crea.cc
+++ b/storage/innobase/dict/dict0crea.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1996, 2014, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -1187,7 +1187,7 @@ dict_create_index_step(
>= UNIV_FORMAT_B);
node->index = dict_index_get_if_in_cache_low(index_id);
- ut_a(err == DB_SUCCESS ? node->index != NULL : node->index == NULL);
+ ut_a((node->index == NULL) == (err != DB_SUCCESS));
if (err != DB_SUCCESS) {
diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc
index 4458315b014..1bf15e7b639 100644
--- a/storage/innobase/fil/fil0fil.cc
+++ b/storage/innobase/fil/fil0fil.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1995, 2015, Oracle and/or its affiliates.
+Copyright (c) 1995, 2016, Oracle and/or its affiliates.
Copyright (c) 2013, 2016, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
@@ -3193,8 +3193,6 @@ fil_create_link_file(
const char* tablename, /*!< in: tablename */
const char* filepath) /*!< in: pathname of tablespace */
{
- os_file_t file;
- ibool success;
dberr_t err = DB_SUCCESS;
char* link_filepath;
char* prev_filepath = fil_read_link_file(tablename);
@@ -3212,16 +3210,25 @@ fil_create_link_file(
}
link_filepath = fil_make_isl_name(tablename);
- /* Note that OS_FILE_READ_WRITE_CACHED used here to avoid
- unnecessary errors on O_DIRECT, link files are not really
- a data files. */
- file = os_file_create_simple_no_error_handling(
- innodb_file_data_key, link_filepath,
- OS_FILE_CREATE, OS_FILE_READ_WRITE_CACHED, &success, 0);
- if (!success) {
- /* The following call will print an error message */
- ulint error = os_file_get_last_error(true);
+ /** Check if the file already exists. */
+ FILE* file = NULL;
+ ibool exists;
+ os_file_type_t ftype;
+
+ bool success = os_file_status(link_filepath, &exists, &ftype);
+
+ ulint error = 0;
+ if (success && !exists) {
+ file = fopen(link_filepath, "w");
+ if (file == NULL) {
+ /* This call will print its own error message */
+ error = os_file_get_last_error(true);
+ }
+ } else {
+ error = OS_FILE_ALREADY_EXISTS;
+ }
+ if (error != 0) {
ut_print_timestamp(stderr);
fputs(" InnoDB: Cannot create file ", stderr);
@@ -3246,13 +3253,17 @@ fil_create_link_file(
return(err);
}
- if (!os_file_write(link_filepath, file, filepath, 0,
- strlen(filepath))) {
+ ulint rbytes = fwrite(filepath, 1, strlen(filepath), file);
+ if (rbytes != strlen(filepath)) {
+ os_file_get_last_error(true);
+ ib_logf(IB_LOG_LEVEL_ERROR,
+ "cannot write link file "
+ "%s",filepath);
err = DB_ERROR;
}
/* Close the file, we only need it at startup */
- os_file_close(file);
+ fclose(file);
mem_free(link_filepath);
@@ -5297,12 +5308,15 @@ retry:
os_offset_t offset
= ((os_offset_t) (start_page_no - file_start_page_no))
* page_size;
+
+ const char* name = node->name == NULL ? space->name : node->name;
+
#ifdef UNIV_HOTBACKUP
- success = os_file_write(node->name, node->handle, buf,
+ success = os_file_write(name, node->handle, buf,
offset, page_size * n_pages);
#else
success = os_aio(OS_FILE_WRITE, 0, OS_AIO_SYNC,
- node->name, node->handle, buf,
+ name, node->handle, buf,
offset, page_size * n_pages, page_size,
node, NULL, 0);
#endif /* UNIV_HOTBACKUP */
@@ -5939,30 +5953,22 @@ fil_io(
ut_a(byte_offset % OS_FILE_LOG_BLOCK_SIZE == 0);
ut_a((len % OS_FILE_LOG_BLOCK_SIZE) == 0);
+ const char* name = node->name == NULL ? space->name : node->name;
+
#ifdef UNIV_HOTBACKUP
/* In mysqlbackup do normal i/o, not aio */
if (type == OS_FILE_READ) {
ret = os_file_read(node->handle, buf, offset, len);
} else {
ut_ad(!srv_read_only_mode);
- ret = os_file_write(node->name, node->handle, buf,
+ ret = os_file_write(name, node->handle, buf,
offset, len);
}
#else
/* Queue the aio request */
- ret = os_aio(
- type,
- is_log,
- mode | wake_later,
- node->name,
- node->handle,
- buf,
- offset,
- len,
- zip_size ? zip_size : UNIV_PAGE_SIZE,
- node,
- message,
- write_size);
+ ret = os_aio(type, is_log, mode | wake_later, name, node->handle, buf,
+ offset, len, zip_size ? zip_size : UNIV_PAGE_SIZE, node,
+ message, write_size);
#endif /* UNIV_HOTBACKUP */
diff --git a/storage/innobase/fts/fts0fts.cc b/storage/innobase/fts/fts0fts.cc
index ee06f9432b8..95740da78d5 100644
--- a/storage/innobase/fts/fts0fts.cc
+++ b/storage/innobase/fts/fts0fts.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2011, 2015, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2011, 2016, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -260,16 +260,18 @@ static const char* fts_config_table_insert_values_sql =
"INSERT INTO \"%s\" VALUES ('"
FTS_TABLE_STATE "', '0');\n";
-/****************************************************************//**
-Run SYNC on the table, i.e., write out data from the cache to the
+/** Run SYNC on the table, i.e., write out data from the cache to the
FTS auxiliary INDEX table and clear the cache at the end.
-@return DB_SUCCESS if all OK */
+@param[in,out] sync sync state
+@param[in] unlock_cache whether unlock cache lock when write node
+@param[in] wait whether wait when a sync is in progress
+@return DB_SUCCESS if all OK */
static
dberr_t
fts_sync(
-/*=====*/
- fts_sync_t* sync) /*!< in: sync state */
- __attribute__((nonnull));
+ fts_sync_t* sync,
+ bool unlock_cache,
+ bool wait);
/****************************************************************//**
Release all resources help by the words rb tree e.g., the node ilist. */
@@ -653,6 +655,7 @@ fts_cache_create(
mem_heap_zalloc(heap, sizeof(fts_sync_t)));
cache->sync->table = table;
+ cache->sync->event = os_event_create();
/* Create the index cache vector that will hold the inverted indexes. */
cache->indexes = ib_vector_create(
@@ -1207,6 +1210,7 @@ fts_cache_destroy(
mutex_free(&cache->optimize_lock);
mutex_free(&cache->deleted_lock);
mutex_free(&cache->doc_id_lock);
+ os_event_free(cache->sync->event);
if (cache->stopword_info.cached_stopword) {
rbt_free(cache->stopword_info.cached_stopword);
@@ -1435,7 +1439,7 @@ fts_cache_add_doc(
ib_vector_last(word->nodes));
}
- if (fts_node == NULL
+ if (fts_node == NULL || fts_node->synced
|| fts_node->ilist_size > FTS_ILIST_MAX_SIZE
|| doc_id < fts_node->last_doc_id) {
@@ -2886,35 +2890,28 @@ fts_doc_ids_free(
}
/*********************************************************************//**
-Do commit-phase steps necessary for the insertion of a new row.
-@return DB_SUCCESS or error code */
-static __attribute__((nonnull, warn_unused_result))
-dberr_t
+Do commit-phase steps necessary for the insertion of a new row. */
+void
fts_add(
/*====*/
fts_trx_table_t*ftt, /*!< in: FTS trx table */
fts_trx_row_t* row) /*!< in: row */
{
dict_table_t* table = ftt->table;
- dberr_t error = DB_SUCCESS;
doc_id_t doc_id = row->doc_id;
ut_a(row->state == FTS_INSERT || row->state == FTS_MODIFY);
fts_add_doc_by_id(ftt, doc_id, row->fts_indexes);
- if (error == DB_SUCCESS) {
- mutex_enter(&table->fts->cache->deleted_lock);
- ++table->fts->cache->added;
- mutex_exit(&table->fts->cache->deleted_lock);
+ mutex_enter(&table->fts->cache->deleted_lock);
+ ++table->fts->cache->added;
+ mutex_exit(&table->fts->cache->deleted_lock);
- if (!DICT_TF2_FLAG_IS_SET(table, DICT_TF2_FTS_HAS_DOC_ID)
- && doc_id >= table->fts->cache->next_doc_id) {
- table->fts->cache->next_doc_id = doc_id + 1;
- }
+ if (!DICT_TF2_FLAG_IS_SET(table, DICT_TF2_FTS_HAS_DOC_ID)
+ && doc_id >= table->fts->cache->next_doc_id) {
+ table->fts->cache->next_doc_id = doc_id + 1;
}
-
- return(error);
}
/*********************************************************************//**
@@ -3025,7 +3022,7 @@ fts_modify(
error = fts_delete(ftt, row);
if (error == DB_SUCCESS) {
- error = fts_add(ftt, row);
+ fts_add(ftt, row);
}
return(error);
@@ -3114,7 +3111,7 @@ fts_commit_table(
switch (row->state) {
case FTS_INSERT:
- error = fts_add(ftt, row);
+ fts_add(ftt, row);
break;
case FTS_MODIFY:
@@ -3554,16 +3551,34 @@ fts_add_doc_by_id(
get_doc->index_cache,
doc_id, doc.tokens);
+ bool need_sync = false;
+ if ((cache->total_size > fts_max_cache_size / 10
+ || fts_need_sync)
+ && !cache->sync->in_progress) {
+ need_sync = true;
+ }
+
rw_lock_x_unlock(&table->fts->cache->lock);
DBUG_EXECUTE_IF(
"fts_instrument_sync",
- fts_sync(cache->sync);
+ fts_optimize_request_sync_table(table);
+ os_event_wait(cache->sync->event);
+ );
+
+ DBUG_EXECUTE_IF(
+ "fts_instrument_sync_debug",
+ fts_sync(cache->sync, true, true);
);
- if (cache->total_size > fts_max_cache_size
- || fts_need_sync) {
- fts_sync(cache->sync);
+ DEBUG_SYNC_C("fts_instrument_sync_request");
+ DBUG_EXECUTE_IF(
+ "fts_instrument_sync_request",
+ fts_optimize_request_sync_table(table);
+ );
+
+ if (need_sync) {
+ fts_optimize_request_sync_table(table);
}
mtr_start(&mtr);
@@ -3934,16 +3949,17 @@ fts_sync_add_deleted_cache(
return(error);
}
-/*********************************************************************//**
-Write the words and ilist to disk.
+/** Write the words and ilist to disk.
+@param[in,out] trx transaction
+@param[in] index_cache index cache
+@param[in] unlock_cache whether unlock cache when write node
@return DB_SUCCESS if all went well else error code */
static __attribute__((nonnull, warn_unused_result))
dberr_t
fts_sync_write_words(
-/*=================*/
- trx_t* trx, /*!< in: transaction */
- fts_index_cache_t*
- index_cache) /*!< in: index cache */
+ trx_t* trx,
+ fts_index_cache_t* index_cache,
+ bool unlock_cache)
{
fts_table_t fts_table;
ulint n_nodes = 0;
@@ -3951,8 +3967,8 @@ fts_sync_write_words(
const ib_rbt_node_t* rbt_node;
dberr_t error = DB_SUCCESS;
ibool print_error = FALSE;
-#ifdef FTS_DOC_STATS_DEBUG
dict_table_t* table = index_cache->index->table;
+#ifdef FTS_DOC_STATS_DEBUG
ulint n_new_words = 0;
#endif /* FTS_DOC_STATS_DEBUG */
@@ -3965,7 +3981,7 @@ fts_sync_write_words(
since we want to free the memory used during caching. */
for (rbt_node = rbt_first(index_cache->words);
rbt_node;
- rbt_node = rbt_first(index_cache->words)) {
+ rbt_node = rbt_next(index_cache->words, rbt_node)) {
ulint i;
ulint selected;
@@ -3998,27 +4014,47 @@ fts_sync_write_words(
}
#endif /* FTS_DOC_STATS_DEBUG */
- n_nodes += ib_vector_size(word->nodes);
-
- /* We iterate over all the nodes even if there was an error,
- this is to free the memory of the fts_node_t elements. */
+ /* We iterate over all the nodes even if there was an error */
for (i = 0; i < ib_vector_size(word->nodes); ++i) {
fts_node_t* fts_node = static_cast<fts_node_t*>(
ib_vector_get(word->nodes, i));
+ if (fts_node->synced) {
+ continue;
+ } else {
+ fts_node->synced = true;
+ }
+
+ /*FIXME: we need to handle the error properly. */
if (error == DB_SUCCESS) {
+ if (unlock_cache) {
+ rw_lock_x_unlock(
+ &table->fts->cache->lock);
+ }
error = fts_write_node(
trx,
&index_cache->ins_graph[selected],
&fts_table, &word->text, fts_node);
- }
- ut_free(fts_node->ilist);
- fts_node->ilist = NULL;
+ DEBUG_SYNC_C("fts_write_node");
+ DBUG_EXECUTE_IF("fts_write_node_crash",
+ DBUG_SUICIDE(););
+
+ DBUG_EXECUTE_IF("fts_instrument_sync_sleep",
+ os_thread_sleep(1000000);
+ );
+
+ if (unlock_cache) {
+ rw_lock_x_lock(
+ &table->fts->cache->lock);
+ }
+ }
}
+ n_nodes += ib_vector_size(word->nodes);
+
if (error != DB_SUCCESS && !print_error) {
ut_print_timestamp(stderr);
fprintf(stderr, " InnoDB: Error (%s) writing "
@@ -4027,9 +4063,6 @@ fts_sync_write_words(
print_error = TRUE;
}
-
- /* NOTE: We are responsible for free'ing the node */
- ut_free(rbt_remove_node(index_cache->words, rbt_node));
}
#ifdef FTS_DOC_STATS_DEBUG
@@ -4330,7 +4363,7 @@ fts_sync_index(
ut_ad(rbt_validate(index_cache->words));
- error = fts_sync_write_words(trx, index_cache);
+ error = fts_sync_write_words(sync->trx, index_cache, sync->unlock_cache);
#ifdef FTS_DOC_STATS_DEBUG
/* FTS_RESOLVE: the word counter info in auxiliary table "DOC_ID"
@@ -4346,6 +4379,36 @@ fts_sync_index(
return(error);
}
+/** Check if index cache has been synced completely
+@param[in,out] sync sync state
+@param[in,out] index_cache index cache
+@return true if index is synced, otherwise false. */
+static
+bool
+fts_sync_index_check(
+ fts_sync_t* sync,
+ fts_index_cache_t* index_cache)
+{
+ const ib_rbt_node_t* rbt_node;
+
+ for (rbt_node = rbt_first(index_cache->words);
+ rbt_node != NULL;
+ rbt_node = rbt_next(index_cache->words, rbt_node)) {
+
+ fts_tokenizer_word_t* word;
+ word = rbt_value(fts_tokenizer_word_t, rbt_node);
+
+ fts_node_t* fts_node;
+ fts_node = static_cast<fts_node_t*>(ib_vector_last(word->nodes));
+
+ if (!fts_node->synced) {
+ return(false);
+ }
+ }
+
+ return(true);
+}
+
/*********************************************************************//**
Commit the SYNC, change state of processed doc ids etc.
@return DB_SUCCESS if all OK */
@@ -4422,21 +4485,53 @@ fts_sync_rollback(
trx_t* trx = sync->trx;
fts_cache_t* cache = sync->table->fts->cache;
+ for (ulint i = 0; i < ib_vector_size(cache->indexes); ++i) {
+ ulint j;
+ fts_index_cache_t* index_cache;
+
+ index_cache = static_cast<fts_index_cache_t*>(
+ ib_vector_get(cache->indexes, i));
+
+ for (j = 0; fts_index_selector[j].value; ++j) {
+
+ if (index_cache->ins_graph[j] != NULL) {
+
+ fts_que_graph_free_check_lock(
+ NULL, index_cache,
+ index_cache->ins_graph[j]);
+
+ index_cache->ins_graph[j] = NULL;
+ }
+
+ if (index_cache->sel_graph[j] != NULL) {
+
+ fts_que_graph_free_check_lock(
+ NULL, index_cache,
+ index_cache->sel_graph[j]);
+
+ index_cache->sel_graph[j] = NULL;
+ }
+ }
+ }
+
rw_lock_x_unlock(&cache->lock);
fts_sql_rollback(trx);
trx_free_for_background(trx);
}
-/****************************************************************//**
-Run SYNC on the table, i.e., write out data from the cache to the
+/** Run SYNC on the table, i.e., write out data from the cache to the
FTS auxiliary INDEX table and clear the cache at the end.
+@param[in,out] sync sync state
+@param[in] unlock_cache whether unlock cache lock when write node
+@param[in] wait whether wait when a sync is in progress
@return DB_SUCCESS if all OK */
static
dberr_t
fts_sync(
-/*=====*/
- fts_sync_t* sync) /*!< in: sync state */
+ fts_sync_t* sync,
+ bool unlock_cache,
+ bool wait)
{
ulint i;
dberr_t error = DB_SUCCESS;
@@ -4444,8 +4539,35 @@ fts_sync(
rw_lock_x_lock(&cache->lock);
+ /* Check if cache is being synced.
+ Note: we release cache lock in fts_sync_write_words() to
+ avoid long wait for the lock by other threads. */
+ while (sync->in_progress) {
+ rw_lock_x_unlock(&cache->lock);
+
+ if (wait) {
+ os_event_wait(sync->event);
+ } else {
+ return(DB_SUCCESS);
+ }
+
+ rw_lock_x_lock(&cache->lock);
+ }
+
+ sync->unlock_cache = unlock_cache;
+ sync->in_progress = true;
+
+ DEBUG_SYNC_C("fts_sync_begin");
fts_sync_begin(sync);
+begin_sync:
+ if (cache->total_size > fts_max_cache_size) {
+ /* Avoid the case: sync never finish when
+ insert/update keeps comming. */
+ ut_ad(sync->unlock_cache);
+ sync->unlock_cache = false;
+ }
+
for (i = 0; i < ib_vector_size(cache->indexes); ++i) {
fts_index_cache_t* index_cache;
@@ -4460,21 +4582,43 @@ fts_sync(
if (error != DB_SUCCESS && !sync->interrupted) {
- break;
+ goto end_sync;
}
}
DBUG_EXECUTE_IF("fts_instrument_sync_interrupted",
sync->interrupted = true;
error = DB_INTERRUPTED;
+ goto end_sync;
);
+ /* Make sure all the caches are synced. */
+ for (i = 0; i < ib_vector_size(cache->indexes); ++i) {
+ fts_index_cache_t* index_cache;
+
+ index_cache = static_cast<fts_index_cache_t*>(
+ ib_vector_get(cache->indexes, i));
+
+ if (index_cache->index->to_be_dropped
+ || fts_sync_index_check(sync, index_cache)) {
+ continue;
+ }
+
+ goto begin_sync;
+ }
+
+end_sync:
if (error == DB_SUCCESS && !sync->interrupted) {
error = fts_sync_commit(sync);
} else {
fts_sync_rollback(sync);
}
+ rw_lock_x_lock(&cache->lock);
+ sync->in_progress = false;
+ os_event_set(sync->event);
+ rw_lock_x_unlock(&cache->lock);
+
/* We need to check whether an optimize is required, for that
we make copies of the two variables that control the trigger. These
variables can change behind our back and we don't want to hold the
@@ -4489,21 +4633,25 @@ fts_sync(
return(error);
}
-/****************************************************************//**
-Run SYNC on the table, i.e., write out data from the cache to the
-FTS auxiliary INDEX table and clear the cache at the end. */
+/** Run SYNC on the table, i.e., write out data from the cache to the
+FTS auxiliary INDEX table and clear the cache at the end.
+@param[in,out] table fts table
+@param[in] unlock_cache whether unlock cache when write node
+@param[in] wait whether wait for existing sync to finish
+@return DB_SUCCESS on success, error code on failure. */
UNIV_INTERN
dberr_t
fts_sync_table(
-/*===========*/
- dict_table_t* table) /*!< in: table */
+ dict_table_t* table,
+ bool unlock_cache,
+ bool wait)
{
dberr_t err = DB_SUCCESS;
ut_ad(table->fts);
if (!dict_table_is_discarded(table) && table->fts->cache) {
- err = fts_sync(table->fts->cache->sync);
+ err = fts_sync(table->fts->cache->sync, unlock_cache, wait);
}
return(err);
diff --git a/storage/innobase/fts/fts0opt.cc b/storage/innobase/fts/fts0opt.cc
index 00b3b4682c3..ccb7090c61d 100644
--- a/storage/innobase/fts/fts0opt.cc
+++ b/storage/innobase/fts/fts0opt.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2007, 2015, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2007, 2016, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -87,6 +87,7 @@ enum fts_msg_type_t {
FTS_MSG_DEL_TABLE, /*!< Remove a table from the optimize
threads work queue */
+ FTS_MSG_SYNC_TABLE /*!< Sync fts cache of a table */
};
/** Compressed list of words that have been read from FTS INDEX
@@ -2652,6 +2653,39 @@ fts_optimize_remove_table(
os_event_free(event);
}
+/** Send sync fts cache for the table.
+@param[in] table table to sync */
+UNIV_INTERN
+void
+fts_optimize_request_sync_table(
+ dict_table_t* table)
+{
+ fts_msg_t* msg;
+ table_id_t* table_id;
+
+ /* if the optimize system not yet initialized, return */
+ if (!fts_optimize_wq) {
+ return;
+ }
+
+ /* FTS optimizer thread is already exited */
+ if (fts_opt_start_shutdown) {
+ ib_logf(IB_LOG_LEVEL_INFO,
+ "Try to sync table %s after FTS optimize"
+ " thread exiting.", table->name);
+ return;
+ }
+
+ msg = fts_optimize_create_msg(FTS_MSG_SYNC_TABLE, NULL);
+
+ table_id = static_cast<table_id_t*>(
+ mem_heap_alloc(msg->heap, sizeof(table_id_t)));
+ *table_id = table->id;
+ msg->ptr = table_id;
+
+ ib_wqueue_add(fts_optimize_wq, msg, msg->heap);
+}
+
/**********************************************************************//**
Find the slot for a particular table.
@return slot if found else NULL. */
@@ -2932,6 +2966,25 @@ fts_optimize_need_sync(
}
#endif
+/** Sync fts cache of a table
+@param[in] table_id table id */
+void
+fts_optimize_sync_table(
+ table_id_t table_id)
+{
+ dict_table_t* table = NULL;
+
+ table = dict_table_open_on_id(table_id, FALSE, DICT_TABLE_OP_NORMAL);
+
+ if (table) {
+ if (dict_table_has_fts_index(table) && table->fts->cache) {
+ fts_sync_table(table, true, false);
+ }
+
+ dict_table_close(table, FALSE, FALSE);
+ }
+}
+
/**********************************************************************//**
Optimize all FTS tables.
@return Dummy return */
@@ -3053,6 +3106,11 @@ fts_optimize_thread(
((fts_msg_del_t*) msg->ptr)->event);
break;
+ case FTS_MSG_SYNC_TABLE:
+ fts_optimize_sync_table(
+ *static_cast<table_id_t*>(msg->ptr));
+ break;
+
default:
ut_error;
}
@@ -3079,26 +3137,7 @@ fts_optimize_thread(
ib_vector_get(tables, i));
if (slot->state != FTS_STATE_EMPTY) {
- dict_table_t* table = NULL;
-
- /*slot->table may be freed, so we try to open
- table by slot->table_id.*/
- table = dict_table_open_on_id(
- slot->table_id, FALSE,
- DICT_TABLE_OP_NORMAL);
-
- if (table) {
-
- if (dict_table_has_fts_index(table)) {
- fts_sync_table(table);
- }
-
- if (table->fts) {
- fts_free(table);
- }
-
- dict_table_close(table, FALSE, FALSE);
- }
+ fts_optimize_sync_table(slot->table_id);
}
}
}
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index d9c2cef7d07..04c573f8426 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2000, 2015, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2000, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2008, 2009 Google Inc.
Copyright (c) 2009, Percona Inc.
Copyright (c) 2012, Facebook Inc.
@@ -2736,7 +2736,7 @@ ha_innobase::ha_innobase(
:handler(hton, table_arg),
int_table_flags(HA_REC_NOT_IN_SEQ |
HA_NULL_IN_KEY | HA_CAN_VIRTUAL_COLUMNS |
- HA_CAN_INDEX_BLOBS |
+ HA_CAN_INDEX_BLOBS | HA_CONCURRENT_OPTIMIZE |
HA_CAN_SQL_HANDLER |
HA_PRIMARY_KEY_REQUIRED_FOR_POSITION |
HA_PRIMARY_KEY_IN_READ_INDEX |
@@ -3817,6 +3817,14 @@ innobase_change_buffering_inited_ok:
innobase_open_files = tc_size;
}
}
+
+ if (innobase_open_files > (long) tc_size) {
+ fprintf(stderr,
+ "innodb_open_files should not be greater"
+ " than the open_files_limit.\n");
+ innobase_open_files = tc_size;
+ }
+
srv_max_n_open_files = (ulint) innobase_open_files;
srv_innodb_status = (ibool) innobase_create_status_file;
@@ -5944,20 +5952,14 @@ table_opened:
prebuilt->clust_index_was_generated = FALSE;
if (UNIV_UNLIKELY(primary_key >= MAX_KEY)) {
- sql_print_error("Table %s has a primary key in "
- "InnoDB data dictionary, but not "
- "in MySQL!", name);
+ ib_table->dict_frm_mismatch = DICT_FRM_NO_PK;
/* This mismatch could cause further problems
if not attended, bring this to the user's attention
by printing a warning in addition to log a message
in the errorlog */
- push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
- ER_NO_SUCH_INDEX,
- "InnoDB: Table %s has a "
- "primary key in InnoDB data "
- "dictionary, but not in "
- "MySQL!", name);
+
+ ib_push_frm_error(thd, ib_table, table, 0, true);
/* If primary_key >= MAX_KEY, its (primary_key)
value could be out of bound if continue to index
@@ -6004,27 +6006,14 @@ table_opened:
}
} else {
if (primary_key != MAX_KEY) {
- sql_print_error(
- "Table %s has no primary key in InnoDB data "
- "dictionary, but has one in MySQL! If you "
- "created the table with a MySQL version < "
- "3.23.54 and did not define a primary key, "
- "but defined a unique key with all non-NULL "
- "columns, then MySQL internally treats that "
- "key as the primary key. You can fix this "
- "error by dump + DROP + CREATE + reimport "
- "of the table.", name);
+
+ ib_table->dict_frm_mismatch = DICT_NO_PK_FRM_HAS;
/* This mismatch could cause further problems
if not attended, bring this to the user attention
by printing a warning in addition to log a message
in the errorlog */
- push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
- ER_NO_SUCH_INDEX,
- "InnoDB: Table %s has no "
- "primary key in InnoDB data "
- "dictionary, but has one in "
- "MySQL!", name);
+ ib_push_frm_error(thd, ib_table, table, 0, true);
}
prebuilt->clust_index_was_generated = TRUE;
@@ -13494,12 +13483,8 @@ ha_innobase::info_low(
}
if (table->s->keys != num_innodb_index) {
- sql_print_error("InnoDB: Table %s contains %lu "
- "indexes inside InnoDB, which "
- "is different from the number of "
- "indexes %u defined in the MySQL ",
- ib_table->name, num_innodb_index,
- table->s->keys);
+ ib_table->dict_frm_mismatch = DICT_FRM_INCONSISTENT_KEYS;
+ ib_push_frm_error(user_thd, ib_table, table, num_innodb_index, true);
}
if (!(flag & HA_STATUS_NO_LOCK)) {
@@ -13519,15 +13504,8 @@ ha_innobase::info_low(
dict_index_t* index = innobase_get_index(i);
if (index == NULL) {
- sql_print_error("Table %s contains fewer "
- "indexes inside InnoDB than "
- "are defined in the MySQL "
- ".frm file. Have you mixed up "
- ".frm files from different "
- "installations? See "
- REFMAN
- "innodb-troubleshooting.html\n",
- ib_table->name);
+ ib_table->dict_frm_mismatch = DICT_FRM_INCONSISTENT_KEYS;
+ ib_push_frm_error(user_thd, ib_table, table, num_innodb_index, true);
break;
}
@@ -13742,7 +13720,7 @@ ha_innobase::optimize(
if (innodb_optimize_fulltext_only) {
if (prebuilt->table->fts && prebuilt->table->fts->cache
&& !dict_table_is_discarded(prebuilt->table)) {
- fts_sync_table(prebuilt->table);
+ fts_sync_table(prebuilt->table, false, true);
fts_optimize_table(prebuilt->table);
}
return(HA_ADMIN_OK);
@@ -20627,3 +20605,96 @@ ib_push_warning(
my_free(buf);
va_end(args);
}
+
+/********************************************************************//**
+Helper function to push frm mismatch error to error log and
+if needed to sql-layer. */
+UNIV_INTERN
+void
+ib_push_frm_error(
+/*==============*/
+ THD* thd, /*!< in: MySQL thd */
+ dict_table_t* ib_table, /*!< in: InnoDB table */
+ TABLE* table, /*!< in: MySQL table */
+ ulint n_keys, /*!< in: InnoDB #keys */
+ bool push_warning) /*!< in: print warning ? */
+{
+ switch (ib_table->dict_frm_mismatch) {
+ case DICT_FRM_NO_PK:
+ sql_print_error("Table %s has a primary key in "
+ "InnoDB data dictionary, but not "
+ "in MySQL!"
+ " Have you mixed up "
+ ".frm files from different "
+ "installations? See "
+ REFMAN
+ "innodb-troubleshooting.html\n",
+ ib_table->name);
+
+ if (push_warning) {
+ push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
+ ER_NO_SUCH_INDEX,
+ "InnoDB: Table %s has a "
+ "primary key in InnoDB data "
+ "dictionary, but not in "
+ "MySQL!", ib_table->name);
+ }
+ break;
+ case DICT_NO_PK_FRM_HAS:
+ sql_print_error(
+ "Table %s has no primary key in InnoDB data "
+ "dictionary, but has one in MySQL! If you "
+ "created the table with a MySQL version < "
+ "3.23.54 and did not define a primary key, "
+ "but defined a unique key with all non-NULL "
+ "columns, then MySQL internally treats that "
+ "key as the primary key. You can fix this "
+ "error by dump + DROP + CREATE + reimport "
+ "of the table.", ib_table->name);
+
+ if (push_warning) {
+ push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
+ ER_NO_SUCH_INDEX,
+ "InnoDB: Table %s has no "
+ "primary key in InnoDB data "
+ "dictionary, but has one in "
+ "MySQL!",
+ ib_table->name);
+ }
+ break;
+
+ case DICT_FRM_INCONSISTENT_KEYS:
+ sql_print_error("InnoDB: Table %s contains %lu "
+ "indexes inside InnoDB, which "
+ "is different from the number of "
+ "indexes %u defined in the MySQL "
+ " Have you mixed up "
+ ".frm files from different "
+ "installations? See "
+ REFMAN
+ "innodb-troubleshooting.html\n",
+ ib_table->name, n_keys,
+ table->s->keys);
+
+ if (push_warning) {
+ push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
+ ER_NO_SUCH_INDEX,
+ "InnoDB: Table %s contains %lu "
+ "indexes inside InnoDB, which "
+ "is different from the number of "
+ "indexes %u defined in the MySQL ",
+ ib_table->name, n_keys,
+ table->s->keys);
+ }
+ break;
+
+ case DICT_FRM_CONSISTENT:
+ default:
+ sql_print_error("InnoDB: Table %s is consistent "
+ "on InnoDB data dictionary and MySQL "
+ " FRM file.",
+ ib_table->name);
+ ut_error;
+ break;
+ }
+}
diff --git a/storage/innobase/handler/ha_innodb.h b/storage/innobase/handler/ha_innodb.h
index 4f4a0b2f999..107e90b1080 100644
--- a/storage/innobase/handler/ha_innodb.h
+++ b/storage/innobase/handler/ha_innodb.h
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 2000, 2012, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2013, SkySQL Ab. All Rights Reserved.
+Copyright (c) 2013, 2016, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -675,3 +675,16 @@ innobase_copy_frm_flags_from_table_share(
/*=====================================*/
dict_table_t* innodb_table, /*!< in/out: InnoDB table */
const TABLE_SHARE* table_share); /*!< in: table share */
+
+/********************************************************************//**
+Helper function to push frm mismatch error to error log and
+if needed to sql-layer. */
+UNIV_INTERN
+void
+ib_push_frm_error(
+/*==============*/
+ THD* thd, /*!< in: MySQL thd */
+ dict_table_t* ib_table, /*!< in: InnoDB table */
+ TABLE* table, /*!< in: MySQL table */
+ ulint n_keys, /*!< in: InnoDB #keys */
+ bool push_warning); /*!< in: print warning ? */
diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc
index c6e5f457f13..f5db3775909 100644
--- a/storage/innobase/handler/handler0alter.cc
+++ b/storage/innobase/handler/handler0alter.cc
@@ -459,6 +459,20 @@ ha_innobase::check_if_supported_inplace_alter(
}
}
+ ulint n_indexes = UT_LIST_GET_LEN((prebuilt->table)->indexes);
+
+ /* If InnoDB dictionary and MySQL frm file are not consistent
+ use "Copy" method. */
+ if (prebuilt->table->dict_frm_mismatch) {
+
+ ha_alter_info->unsupported_reason = innobase_get_err_msg(
+ ER_NO_SUCH_INDEX);
+ ib_push_frm_error(user_thd, prebuilt->table, altered_table,
+ n_indexes, true);
+
+ DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED);
+ }
+
/* We should be able to do the operation in-place.
See if we can do it online (LOCK=NONE). */
bool online = true;
diff --git a/storage/innobase/include/dict0mem.h b/storage/innobase/include/dict0mem.h
index 53a5d6cb08b..eb2a7968bc4 100644
--- a/storage/innobase/include/dict0mem.h
+++ b/storage/innobase/include/dict0mem.h
@@ -2,7 +2,7 @@
Copyright (c) 1996, 2015, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2012, Facebook Inc.
-Copyright (c) 2013, 2015, MariaDB Corporation.
+Copyright (c) 2013, 2016, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -1009,6 +1009,18 @@ if table->memcached_sync_count == DICT_TABLE_IN_DDL means there's DDL running on
the table, DML from memcached will be blocked. */
#define DICT_TABLE_IN_DDL -1
+/** These are used when MySQL FRM and InnoDB data dictionary are
+in inconsistent state. */
+typedef enum {
+ DICT_FRM_CONSISTENT = 0, /*!< Consistent state */
+ DICT_FRM_NO_PK = 1, /*!< MySQL has no primary key
+ but InnoDB dictionary has
+ non-generated one. */
+ DICT_NO_PK_FRM_HAS = 2, /*!< MySQL has primary key but
+ InnoDB dictionary has not. */
+ DICT_FRM_INCONSISTENT_KEYS = 3 /*!< Key count mismatch */
+} dict_frm_t;
+
/** Data structure for a database table. Most fields will be
initialized to 0, NULL or FALSE in dict_mem_table_create(). */
struct dict_table_t{
@@ -1069,6 +1081,10 @@ struct dict_table_t{
/*!< True if the table belongs to a system
database (mysql, information_schema or
performance_schema) */
+ dict_frm_t dict_frm_mismatch;
+ /*!< !DICT_FRM_CONSISTENT==0 if data
+ dictionary information and
+ MySQL FRM information mismatch. */
#ifndef UNIV_HOTBACKUP
hash_node_t name_hash; /*!< hash chain node */
hash_node_t id_hash; /*!< hash chain node */
diff --git a/storage/innobase/include/fts0fts.h b/storage/innobase/include/fts0fts.h
index d54ed281d9a..9f7b0216d9b 100644
--- a/storage/innobase/include/fts0fts.h
+++ b/storage/innobase/include/fts0fts.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2011, 2015, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2011, 2016, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -724,6 +724,13 @@ fts_optimize_remove_table(
/*======================*/
dict_table_t* table); /*!< in: table to remove */
+/** Send sync fts cache for the table.
+@param[in] table table to sync */
+UNIV_INTERN
+void
+fts_optimize_request_sync_table(
+ dict_table_t* table);
+
/**********************************************************************//**
Signal the optimize thread to prepare for shutdown. */
UNIV_INTERN
@@ -826,15 +833,18 @@ fts_drop_index_split_tables(
dict_index_t* index) /*!< in: fts instance */
__attribute__((nonnull, warn_unused_result));
-/****************************************************************//**
-Run SYNC on the table, i.e., write out data from the cache to the
-FTS auxiliary INDEX table and clear the cache at the end. */
+/** Run SYNC on the table, i.e., write out data from the cache to the
+FTS auxiliary INDEX table and clear the cache at the end.
+@param[in,out] table fts table
+@param[in] unlock_cache whether unlock cache when write node
+@param[in] wait whether wait for existing sync to finish
+@return DB_SUCCESS on success, error code on failure. */
UNIV_INTERN
dberr_t
fts_sync_table(
-/*===========*/
- dict_table_t* table) /*!< in: table */
- __attribute__((nonnull));
+ dict_table_t* table,
+ bool unlock_cache,
+ bool wait);
/****************************************************************//**
Free the query graph but check whether dict_sys->mutex is already
diff --git a/storage/innobase/include/fts0types.h b/storage/innobase/include/fts0types.h
index 64677428331..e495fe72a60 100644
--- a/storage/innobase/include/fts0types.h
+++ b/storage/innobase/include/fts0types.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2007, 2011, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2007, 2016, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -122,7 +122,11 @@ struct fts_sync_t {
doc_id_t max_doc_id; /*!< The doc id at which the cache was
noted as being full, we use this to
set the upper_limit field */
- ib_time_t start_time; /*!< SYNC start time */
+ ib_time_t start_time; /*!< SYNC start time */
+ bool in_progress; /*!< flag whether sync is in progress.*/
+ bool unlock_cache; /*!< flag whether unlock cache when
+ write fts node */
+ os_event_t event; /*!< sync finish event */
};
/** The cache for the FTS system. It is a memory-based inverted index
@@ -165,7 +169,6 @@ struct fts_cache_t {
objects, they are recreated after
a SYNC is completed */
-
ib_alloc_t* self_heap; /*!< This heap is the heap out of
which an instance of the cache itself
was created. Objects created using
@@ -212,6 +215,7 @@ struct fts_node_t {
ulint ilist_size_alloc;
/*!< Allocated size of ilist in
bytes */
+ bool synced; /*!< flag whether the node is synced */
};
/** A tokenizer word. Contains information about one word. */
diff --git a/storage/innobase/include/os0file.h b/storage/innobase/include/os0file.h
index dff5ebd524c..dd6fd8f9940 100644
--- a/storage/innobase/include/os0file.h
+++ b/storage/innobase/include/os0file.h
@@ -128,10 +128,7 @@ enum os_file_create_t {
#define OS_FILE_READ_ONLY 333
#define OS_FILE_READ_WRITE 444
#define OS_FILE_READ_ALLOW_DELETE 555 /* for mysqlbackup */
-#define OS_FILE_READ_WRITE_CACHED 666 /* OS_FILE_READ_WRITE but never
- O_DIRECT. Only for
- os_file_create_simple_no_error_handling
- currently. */
+
/* Options for file_create */
#define OS_FILE_AIO 61
#define OS_FILE_NORMAL 62
diff --git a/storage/innobase/include/os0sync.h b/storage/innobase/include/os0sync.h
index e192a3a6c94..95e724ec48e 100644
--- a/storage/innobase/include/os0sync.h
+++ b/storage/innobase/include/os0sync.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1995, 2015, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2008, Google Inc.
Portions of this file contain modifications contributed and copyrighted by
@@ -466,28 +466,7 @@ amount to decrement. */
# define os_atomic_decrement_uint64(ptr, amount) \
os_atomic_decrement(ptr, amount)
-# if defined(HAVE_IB_GCC_ATOMIC_TEST_AND_SET)
-
-/** Do an atomic test-and-set.
-@param[in,out] ptr Memory location to set to non-zero
-@return the previous value */
-inline
-lock_word_t
-os_atomic_test_and_set(volatile lock_word_t* ptr)
-{
- return(__atomic_test_and_set(ptr, __ATOMIC_ACQUIRE));
-}
-
-/** Do an atomic clear.
-@param[in,out] ptr Memory location to set to zero */
-inline
-void
-os_atomic_clear(volatile lock_word_t* ptr)
-{
- __atomic_clear(ptr, __ATOMIC_RELEASE);
-}
-
-# elif defined(HAVE_ATOMIC_BUILTINS)
+# if defined(IB_STRONG_MEMORY_MODEL)
/** Do an atomic test and set.
@param[in,out] ptr Memory location to set to non-zero
@@ -516,6 +495,27 @@ os_atomic_clear(volatile lock_word_t* ptr)
return(__sync_lock_test_and_set(ptr, 0));
}
+# elif defined(HAVE_IB_GCC_ATOMIC_TEST_AND_SET)
+
+/** Do an atomic test-and-set.
+@param[in,out] ptr Memory location to set to non-zero
+@return the previous value */
+inline
+lock_word_t
+os_atomic_test_and_set(volatile lock_word_t* ptr)
+{
+ return(__atomic_test_and_set(ptr, __ATOMIC_ACQUIRE));
+}
+
+/** Do an atomic clear.
+@param[in,out] ptr Memory location to set to zero */
+inline
+void
+os_atomic_clear(volatile lock_word_t* ptr)
+{
+ __atomic_clear(ptr, __ATOMIC_RELEASE);
+}
+
# else
# error "Unsupported platform"
diff --git a/storage/innobase/include/univ.i b/storage/innobase/include/univ.i
index c2451fa8c21..56a257241d9 100644
--- a/storage/innobase/include/univ.i
+++ b/storage/innobase/include/univ.i
@@ -45,7 +45,7 @@ Created 1/20/1994 Heikki Tuuri
#define INNODB_VERSION_MAJOR 5
#define INNODB_VERSION_MINOR 6
-#define INNODB_VERSION_BUGFIX 29
+#define INNODB_VERSION_BUGFIX 30
/* The following is the InnoDB version as shown in
SELECT plugin_version FROM information_schema.plugins;
diff --git a/storage/innobase/os/os0file.cc b/storage/innobase/os/os0file.cc
index 3a0bd1fc328..f71a4cf125c 100644
--- a/storage/innobase/os/os0file.cc
+++ b/storage/innobase/os/os0file.cc
@@ -1350,8 +1350,7 @@ os_file_create_simple_func(
access = GENERIC_READ;
- } else if (access_type == OS_FILE_READ_WRITE
- || access_type == OS_FILE_READ_WRITE_CACHED) {
+ } else if (access_type == OS_FILE_READ_WRITE) {
access = GENERIC_READ | GENERIC_WRITE;
} else {
ib_logf(IB_LOG_LEVEL_ERROR,
@@ -1455,8 +1454,7 @@ os_file_create_simple_func(
#ifdef USE_FILE_LOCK
if (!srv_read_only_mode
&& *success
- && (access_type == OS_FILE_READ_WRITE
- || access_type == OS_FILE_READ_WRITE_CACHED)
+ && (access_type == OS_FILE_READ_WRITE)
&& os_file_lock(file, name)) {
*success = FALSE;
@@ -1470,31 +1468,6 @@ os_file_create_simple_func(
return(file);
}
-/** Disable OS I/O caching on the file if the file type and server
-configuration requires it.
-@param file handle to the file
-@param name name of the file, for diagnostics
-@param mode_str operation on the file, for diagnostics
-@param type OS_LOG_FILE or OS_DATA_FILE
-@param access_type if OS_FILE_READ_WRITE_CACHED, then caching will be disabled
-unconditionally, ignored otherwise */
-static
-void
-os_file_set_nocache_if_needed(os_file_t file, const char* name,
- const char *mode_str, ulint type,
- ulint access_type)
-{
- if (srv_read_only_mode || access_type == OS_FILE_READ_WRITE_CACHED) {
- return;
- }
-
- if (type == OS_DATA_FILE
- && (srv_unix_file_flush_method == SRV_UNIX_O_DIRECT
- || (srv_unix_file_flush_method == SRV_UNIX_O_DIRECT_NO_FSYNC))) {
- os_file_set_nocache(file, name, mode_str);
- }
-}
-
/****************************************************************//**
NOTE! Use the corresponding macro
os_file_create_simple_no_error_handling(), not directly this function!
@@ -1550,8 +1523,7 @@ os_file_create_simple_no_error_handling_func(
access = GENERIC_READ;
} else if (srv_read_only_mode) {
access = GENERIC_READ;
- } else if (access_type == OS_FILE_READ_WRITE
- || access_type == OS_FILE_READ_WRITE_CACHED) {
+ } else if (access_type == OS_FILE_READ_WRITE) {
access = GENERIC_READ | GENERIC_WRITE;
} else if (access_type == OS_FILE_READ_ALLOW_DELETE) {
@@ -1623,8 +1595,7 @@ os_file_create_simple_no_error_handling_func(
} else {
ut_a(access_type == OS_FILE_READ_WRITE
- || access_type == OS_FILE_READ_ALLOW_DELETE
- || access_type == OS_FILE_READ_WRITE_CACHED);
+ || access_type == OS_FILE_READ_ALLOW_DELETE);
create_flag = O_RDWR;
}
@@ -1656,16 +1627,18 @@ os_file_create_simple_no_error_handling_func(
/* This function is always called for data files, we should disable
OS caching (O_DIRECT) here as we do in os_file_create_func(), so
we open the same file in the same mode, see man page of open(2). */
- if (*success) {
- os_file_set_nocache_if_needed(file, name, mode_str,
- OS_DATA_FILE, access_type);
+ if (!srv_read_only_mode
+ && *success
+ && (srv_unix_file_flush_method == SRV_UNIX_O_DIRECT
+ || srv_unix_file_flush_method == SRV_UNIX_O_DIRECT_NO_FSYNC)) {
+
+ os_file_set_nocache(file, name, mode_str);
}
#ifdef USE_FILE_LOCK
if (!srv_read_only_mode
&& *success
- && (access_type == OS_FILE_READ_WRITE
- || access_type == OS_FILE_READ_WRITE_CACHED)
+ && (access_type == OS_FILE_READ_WRITE)
&& os_file_lock(file, name)) {
*success = FALSE;
@@ -2033,9 +2006,13 @@ os_file_create_func(
} while (retry);
/* We disable OS caching (O_DIRECT) only on data files */
+ if (!srv_read_only_mode
+ && *success
+ && type != OS_LOG_FILE
+ && (srv_unix_file_flush_method == SRV_UNIX_O_DIRECT
+ || srv_unix_file_flush_method == SRV_UNIX_O_DIRECT_NO_FSYNC)) {
- if (*success) {
- os_file_set_nocache_if_needed(file, name, mode_str, type, 0);
+ os_file_set_nocache(file, name, mode_str);
}
#ifdef USE_FILE_LOCK
diff --git a/storage/innobase/row/row0merge.cc b/storage/innobase/row/row0merge.cc
index 294facf9723..9b5b1574280 100644
--- a/storage/innobase/row/row0merge.cc
+++ b/storage/innobase/row/row0merge.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2005, 2015, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2005, 2016, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -2169,7 +2169,8 @@ wait_again:
if (max_doc_id && err == DB_SUCCESS) {
/* Sync fts cache for other fts indexes to keep all
fts indexes consistent in sync_doc_id. */
- err = fts_sync_table(const_cast<dict_table_t*>(new_table));
+ err = fts_sync_table(const_cast<dict_table_t*>(new_table),
+ false, true);
if (err == DB_SUCCESS) {
fts_update_next_doc_id(
diff --git a/storage/myisam/ft_boolean_search.c b/storage/myisam/ft_boolean_search.c
index 6befe3b2d7a..766f8411ca1 100644
--- a/storage/myisam/ft_boolean_search.c
+++ b/storage/myisam/ft_boolean_search.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -197,7 +197,8 @@ static int ftb_query_add_word(MYSQL_FTPARSER_PARAM *param,
ftbw= (FTB_WORD *)alloc_root(&ftb_param->ftb->mem_root,
sizeof(FTB_WORD) +
(info->trunc ? HA_MAX_KEY_BUFF :
- word_len * ftb_param->ftb->charset->mbmaxlen +
+ (word_len + 1) *
+ ftb_param->ftb->charset->mbmaxlen +
HA_FT_WLEN +
ftb_param->ftb->info->s->rec_reflength));
ftbw->len= word_len + 1;
diff --git a/storage/myisammrg/ha_myisammrg.cc b/storage/myisammrg/ha_myisammrg.cc
index 05d5ef1d6ca..bb2ba283f36 100644
--- a/storage/myisammrg/ha_myisammrg.cc
+++ b/storage/myisammrg/ha_myisammrg.cc
@@ -1,4 +1,5 @@
/* Copyright (c) 2000, 2011, Oracle and/or its affiliates
+ Copyright (c) 2009, 2016, MariaDB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/storage/oqgraph/ha_oqgraph.cc b/storage/oqgraph/ha_oqgraph.cc
index de92da57b56..bafa2ad20f2 100644
--- a/storage/oqgraph/ha_oqgraph.cc
+++ b/storage/oqgraph/ha_oqgraph.cc
@@ -1136,6 +1136,10 @@ int ha_oqgraph::info(uint flag)
int ha_oqgraph::extra(enum ha_extra_function operation)
{
+ if (graph->get_thd() != ha_thd()) {
+ DBUG_PRINT( "oq-debug", ("rnd_pos g->table->in_use: 0x%lx <-- current_thd 0x%lx", (long) graph->get_thd(), (long) current_thd));
+ graph->set_thd(current_thd);
+ }
return edges->file->extra(operation);
}
diff --git a/storage/oqgraph/oqgraph_judy.cc b/storage/oqgraph/oqgraph_judy.cc
index 020cab57ed2..44c7e28e268 100644
--- a/storage/oqgraph/oqgraph_judy.cc
+++ b/storage/oqgraph/oqgraph_judy.cc
@@ -23,6 +23,28 @@
*/
#include "oqgraph_judy.h"
+
+/*
+ Currently the only active code that can return error is:
+ judy_bitset::reset()/J1U()
+ judy_bitset::setbit()/J1S()
+
+ In most cases errors are either about wrong parameters passed to Judy
+ functions or internal structures corruption. These definitely deserve
+ abnormal process termination instead of exit() as it is done by original
+ JUDYERROR.
+
+ TODO: there's one exception that should be handled properly though: OOM.
+*/
+#include <stdio.h>
+#define JUDYERROR(CallerFile, CallerLine, JudyFunc, JudyErrno, JudyErrID) \
+ { \
+ (void) fprintf(stderr, "File '%s', line %d: %s(), " \
+ "JU_ERRNO_* == %d, ID == %d\n", \
+ CallerFile, CallerLine, \
+ JudyFunc, JudyErrno, JudyErrID); \
+ abort(); \
+ }
#include <Judy.h>
void open_query::judy_bitset::clear()
diff --git a/storage/sequence/mysql-test/sequence/group_by.result b/storage/sequence/mysql-test/sequence/group_by.result
index b3b56338aef..2941e85c1f4 100644
--- a/storage/sequence/mysql-test/sequence/group_by.result
+++ b/storage/sequence/mysql-test/sequence/group_by.result
@@ -66,6 +66,11 @@ id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY seq_1_to_15_step_2 index NULL PRIMARY 8 NULL # Using index
1 PRIMARY <derived2> ALL NULL NULL NULL NULL # Using join buffer (flat, BNL join)
2 DERIVED NULL NULL NULL NULL NULL NULL # Storage engine handles GROUP BY
+create view v1 as select count(*) from seq_1_to_15_step_2;
+select * from v1;
+count(*)
+8
+drop view v1;
#
# The engine can't optimize the following queries
#
diff --git a/storage/sequence/mysql-test/sequence/group_by.test b/storage/sequence/mysql-test/sequence/group_by.test
index b2e04037a8b..b3f4ab58771 100644
--- a/storage/sequence/mysql-test/sequence/group_by.test
+++ b/storage/sequence/mysql-test/sequence/group_by.test
@@ -30,6 +30,10 @@ select * from seq_1_to_15_step_2, (select count(*) from seq_1_to_15_step_2) as t
--replace_column 9 #
explain select * from seq_1_to_15_step_2, (select count(*) from seq_1_to_15_step_2) as t1;
+create view v1 as select count(*) from seq_1_to_15_step_2;
+select * from v1;
+drop view v1;
+
--echo #
--echo # The engine can't optimize the following queries
--echo #
diff --git a/storage/spider/hs_client/fatal.cpp b/storage/spider/hs_client/fatal.cpp
index bec031153e4..260a2e75372 100644
--- a/storage/spider/hs_client/fatal.cpp
+++ b/storage/spider/hs_client/fatal.cpp
@@ -26,26 +26,6 @@ const int opt_syslog = LOG_ERR | LOG_PID | LOG_CONS;
*/
void
-fatal_exit(const String& message)
-{
- fprintf(stderr, "FATAL_EXIT: %s\n", message.ptr());
-/*
- syslog(opt_syslog, "FATAL_EXIT: %s", message.ptr());
-*/
- _exit(1);
-}
-
-void
-fatal_exit(const char *message)
-{
- fprintf(stderr, "FATAL_EXIT: %s\n", message);
-/*
- syslog(opt_syslog, "FATAL_EXIT: %s", message);
-*/
- _exit(1);
-}
-
-void
fatal_abort(const String& message)
{
fprintf(stderr, "FATAL_COREDUMP: %s\n", message.ptr());
diff --git a/storage/spider/hs_client/fatal.hpp b/storage/spider/hs_client/fatal.hpp
index a75c56bddad..e1190ae49c1 100644
--- a/storage/spider/hs_client/fatal.hpp
+++ b/storage/spider/hs_client/fatal.hpp
@@ -22,8 +22,6 @@
namespace dena {
-void fatal_exit(const String& message);
-void fatal_exit(const char *message);
void fatal_abort(const String& message);
void fatal_abort(const char *message);
diff --git a/storage/spider/hs_client/socket.cpp b/storage/spider/hs_client/socket.cpp
index 2082d1f024e..c61b39d140f 100644
--- a/storage/spider/hs_client/socket.cpp
+++ b/storage/spider/hs_client/socket.cpp
@@ -67,7 +67,7 @@ socket_args::set(const config& conf)
message.append(node);
message.q_append(":", sizeof(":") - 1);
message.append(port);
- fatal_exit(message);
+ fatal_abort(message);
}
}
}
diff --git a/storage/spider/spd_conn.cc b/storage/spider/spd_conn.cc
index c5c47064403..2f7fdb62ad4 100644
--- a/storage/spider/spd_conn.cc
+++ b/storage/spider/spd_conn.cc
@@ -2706,7 +2706,7 @@ void *spider_bg_sts_action(
SPIDER_TRX *trx;
int error_num = 0, roop_count;
ha_spider spider;
-#ifdef _MSC_VER
+#if defined(_MSC_VER) || defined(__SUNPRO_CC)
int *need_mons;
SPIDER_CONN **conns;
uint *conn_link_idx;
@@ -2733,7 +2733,7 @@ void *spider_bg_sts_action(
my_thread_init();
DBUG_ENTER("spider_bg_sts_action");
/* init start */
-#ifdef _MSC_VER
+#if defined(_MSC_VER) || defined(__SUNPRO_CC)
#if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET)
if (!(need_mons = (int *)
spider_bulk_malloc(spider_current_trx, 21, MYF(MY_WME),
@@ -2777,7 +2777,7 @@ void *spider_bg_sts_action(
share->bg_sts_init = FALSE;
pthread_mutex_unlock(&share->sts_mutex);
my_thread_end();
-#ifdef _MSC_VER
+#if defined(_MSC_VER) || defined(__SUNPRO_CC)
spider_free(NULL, need_mons, MYF(MY_WME));
#endif
DBUG_RETURN(NULL);
@@ -2801,7 +2801,7 @@ void *spider_bg_sts_action(
my_pthread_setspecific_ptr(THR_THD, NULL);
#endif
my_thread_end();
-#ifdef _MSC_VER
+#if defined(_MSC_VER) || defined(__SUNPRO_CC)
spider_free(NULL, need_mons, MYF(MY_WME));
#endif
DBUG_RETURN(NULL);
@@ -2866,7 +2866,7 @@ void *spider_bg_sts_action(
my_pthread_setspecific_ptr(THR_THD, NULL);
#endif
my_thread_end();
-#ifdef _MSC_VER
+#if defined(_MSC_VER) || defined(__SUNPRO_CC)
spider_free(NULL, need_mons, MYF(MY_WME));
#endif
DBUG_RETURN(NULL);
@@ -2897,7 +2897,7 @@ void *spider_bg_sts_action(
my_pthread_setspecific_ptr(THR_THD, NULL);
#endif
my_thread_end();
-#ifdef _MSC_VER
+#if defined(_MSC_VER) || defined(__SUNPRO_CC)
spider_free(NULL, need_mons, MYF(MY_WME));
#endif
DBUG_RETURN(NULL);
@@ -3088,7 +3088,7 @@ void *spider_bg_crd_action(
int error_num = 0, roop_count;
ha_spider spider;
TABLE table;
-#ifdef _MSC_VER
+#if defined(_MSC_VER) || defined(__SUNPRO_CC)
int *need_mons;
SPIDER_CONN **conns;
uint *conn_link_idx;
@@ -3115,7 +3115,7 @@ void *spider_bg_crd_action(
my_thread_init();
DBUG_ENTER("spider_bg_crd_action");
/* init start */
-#ifdef _MSC_VER
+#if defined(_MSC_VER) || defined(__SUNPRO_CC)
#if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET)
if (!(need_mons = (int *)
spider_bulk_malloc(spider_current_trx, 22, MYF(MY_WME),
@@ -3159,7 +3159,7 @@ void *spider_bg_crd_action(
share->bg_crd_init = FALSE;
pthread_mutex_unlock(&share->crd_mutex);
my_thread_end();
-#ifdef _MSC_VER
+#if defined(_MSC_VER) || defined(__SUNPRO_CC)
spider_free(NULL, need_mons, MYF(MY_WME));
#endif
DBUG_RETURN(NULL);
@@ -3183,7 +3183,7 @@ void *spider_bg_crd_action(
my_pthread_setspecific_ptr(THR_THD, NULL);
#endif
my_thread_end();
-#ifdef _MSC_VER
+#if defined(_MSC_VER) || defined(__SUNPRO_CC)
spider_free(NULL, need_mons, MYF(MY_WME));
#endif
DBUG_RETURN(NULL);
@@ -3252,7 +3252,7 @@ void *spider_bg_crd_action(
my_pthread_setspecific_ptr(THR_THD, NULL);
#endif
my_thread_end();
-#ifdef _MSC_VER
+#if defined(_MSC_VER) || defined(__SUNPRO_CC)
spider_free(NULL, need_mons, MYF(MY_WME));
#endif
DBUG_RETURN(NULL);
@@ -3283,7 +3283,7 @@ void *spider_bg_crd_action(
my_pthread_setspecific_ptr(THR_THD, NULL);
#endif
my_thread_end();
-#ifdef _MSC_VER
+#if defined(_MSC_VER) || defined(__SUNPRO_CC)
spider_free(NULL, need_mons, MYF(MY_WME));
#endif
DBUG_RETURN(NULL);
@@ -3417,7 +3417,7 @@ int spider_create_mon_threads(
{
char link_idx_str[SPIDER_SQL_INT_LEN];
int link_idx_str_length;
-#ifdef _MSC_VER
+#if defined(_MSC_VER) || defined(__SUNPRO_CC)
spider_string conv_name_str(share->table_name_length +
SPIDER_SQL_INT_LEN + 1);
conv_name_str.set_charset(system_charset_info);
@@ -3748,7 +3748,7 @@ int spider_conn_first_link_idx(
int roop_count, active_links = 0;
longlong balance_total = 0, balance_val;
double rand_val;
-#ifdef _MSC_VER
+#if defined(_MSC_VER) || defined(__SUNPRO_CC)
int *link_idxs, link_idx;
long *balances;
#else
@@ -3756,7 +3756,7 @@ int spider_conn_first_link_idx(
long balances[link_count];
#endif
DBUG_ENTER("spider_conn_first_link_idx");
-#ifdef _MSC_VER
+#if defined(_MSC_VER) || defined(__SUNPRO_CC)
if (!(link_idxs = (int *)
spider_bulk_malloc(spider_current_trx, 24, MYF(MY_WME),
&link_idxs, sizeof(int) * link_count,
@@ -3782,7 +3782,7 @@ int spider_conn_first_link_idx(
if (active_links == 0)
{
DBUG_PRINT("info",("spider all links are failed"));
-#ifdef _MSC_VER
+#if defined(_MSC_VER) || defined(__SUNPRO_CC)
spider_free(spider_current_trx, link_idxs, MYF(MY_WME));
#endif
DBUG_RETURN(-1);
@@ -3811,7 +3811,7 @@ int spider_conn_first_link_idx(
}
DBUG_PRINT("info",("spider first link_idx=%d", link_idxs[roop_count]));
-#ifdef _MSC_VER
+#if defined(_MSC_VER) || defined(__SUNPRO_CC)
link_idx = link_idxs[roop_count];
spider_free(spider_current_trx, link_idxs, MYF(MY_WME));
DBUG_RETURN(link_idx);
diff --git a/storage/spider/spd_db_conn.cc b/storage/spider/spd_db_conn.cc
index 9f46e55ca09..c29172a474a 100644
--- a/storage/spider/spd_db_conn.cc
+++ b/storage/spider/spd_db_conn.cc
@@ -9294,7 +9294,7 @@ int spider_db_udf_ping_table(
{
int init_sql_alloc_size =
spider_param_init_sql_alloc_size(trx->thd, share->init_sql_alloc_size);
-#ifdef _MSC_VER
+#if defined(_MSC_VER) || defined(__SUNPRO_CC)
spider_string sql_str(init_sql_alloc_size);
sql_str.set_charset(system_charset_info);
spider_string where_str(init_sql_alloc_size);
@@ -9517,7 +9517,7 @@ int spider_db_udf_ping_table_mon_next(
SPIDER_SHARE *share = table_mon->share;
int init_sql_alloc_size =
spider_param_init_sql_alloc_size(thd, share->init_sql_alloc_size);
-#ifdef _MSC_VER
+#if defined(_MSC_VER) || defined(__SUNPRO_CC)
spider_string sql_str(init_sql_alloc_size);
sql_str.set_charset(thd->variables.character_set_client);
#else
diff --git a/storage/spider/spd_ping_table.cc b/storage/spider/spd_ping_table.cc
index 41c5c240dd3..f59f7760359 100644
--- a/storage/spider/spd_ping_table.cc
+++ b/storage/spider/spd_ping_table.cc
@@ -241,7 +241,7 @@ void spider_release_ping_table_mon_list(
DBUG_PRINT("info", ("spider link_idx=%d", link_idx));
link_idx_str_length = my_sprintf(link_idx_str, (link_idx_str, "%010d",
link_idx));
-#ifdef _MSC_VER
+#if defined(_MSC_VER) || defined(__SUNPRO_CC)
spider_string conv_name_str(conv_name_length + link_idx_str_length + 1);
conv_name_str.set_charset(system_charset_info);
#else
@@ -1362,7 +1362,7 @@ int spider_ping_table_mon_from_table(
link_idx_str_length = my_sprintf(link_idx_str, (link_idx_str, "%010d",
link_idx));
-#ifdef _MSC_VER
+#if defined(_MSC_VER) || defined(__SUNPRO_CC)
spider_string conv_name_str(conv_name_length + link_idx_str_length + 1);
conv_name_str.set_charset(system_charset_info);
*((char *)(conv_name_str.ptr() + conv_name_length + link_idx_str_length)) =
diff --git a/storage/spider/spd_table.cc b/storage/spider/spd_table.cc
index fa712575610..54dd1089b7e 100644
--- a/storage/spider/spd_table.cc
+++ b/storage/spider/spd_table.cc
@@ -3703,7 +3703,7 @@ int spider_create_conn_keys(
#if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET)
char *tmp_hs_r_name, *tmp_hs_w_name;
#endif
-#ifdef _MSC_VER
+#if defined(_MSC_VER) || defined(__SUNPRO_CC)
uint *conn_keys_lengths;
#if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET)
uint *hs_r_conn_keys_lengths;
@@ -3717,7 +3717,7 @@ int spider_create_conn_keys(
#endif
#endif
DBUG_ENTER("spider_create_conn_keys");
-#ifdef _MSC_VER
+#if defined(_MSC_VER) || defined(__SUNPRO_CC)
if (!(conn_keys_lengths =
(uint *) spider_bulk_alloc_mem(spider_current_trx, 44,
__func__, __FILE__, __LINE__, MYF(MY_WME),
@@ -3806,7 +3806,7 @@ int spider_create_conn_keys(
#endif
NullS))
) {
-#ifdef _MSC_VER
+#if defined(_MSC_VER) || defined(__SUNPRO_CC)
spider_free(spider_current_trx, conn_keys_lengths, MYF(MY_WME));
#endif
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
@@ -3823,7 +3823,7 @@ int spider_create_conn_keys(
sizeof(uint) * share->all_link_count);
#endif
-#ifdef _MSC_VER
+#if defined(_MSC_VER) || defined(__SUNPRO_CC)
spider_free(spider_current_trx, conn_keys_lengths, MYF(MY_WME));
#endif
@@ -4676,7 +4676,7 @@ SPIDER_SHARE *spider_get_share(
share->link_count, SPIDER_LINK_STATUS_OK);
if (search_link_idx == -1)
{
-#ifdef _MSC_VER
+#if defined(_MSC_VER) || defined(__SUNPRO_CC)
char *db, *table_name;
if (!(db = (char *)
spider_bulk_malloc(spider_current_trx, 48, MYF(MY_WME),
@@ -4702,7 +4702,7 @@ SPIDER_SHARE *spider_get_share(
table_name[table_share->table_name.length] = '\0';
my_printf_error(ER_SPIDER_ALL_LINKS_FAILED_NUM,
ER_SPIDER_ALL_LINKS_FAILED_STR, MYF(0), db, table_name);
-#ifdef _MSC_VER
+#if defined(_MSC_VER) || defined(__SUNPRO_CC)
spider_free(spider->trx, db, MYF(MY_WME));
#endif
*error_num = ER_SPIDER_ALL_LINKS_FAILED_NUM;
@@ -5100,7 +5100,7 @@ SPIDER_SHARE *spider_get_share(
share->link_count, SPIDER_LINK_STATUS_OK);
if (search_link_idx == -1)
{
-#ifdef _MSC_VER
+#if defined(_MSC_VER) || defined(__SUNPRO_CC)
char *db, *table_name;
if (!(db = (char *)
spider_bulk_malloc(spider_current_trx, 50, MYF(MY_WME),
@@ -5123,7 +5123,7 @@ SPIDER_SHARE *spider_get_share(
table_name[table_share->table_name.length] = '\0';
my_printf_error(ER_SPIDER_ALL_LINKS_FAILED_NUM,
ER_SPIDER_ALL_LINKS_FAILED_STR, MYF(0), db, table_name);
-#ifdef _MSC_VER
+#if defined(_MSC_VER) || defined(__SUNPRO_CC)
spider_free(spider->trx, db, MYF(MY_WME));
#endif
*error_num = ER_SPIDER_ALL_LINKS_FAILED_NUM;
diff --git a/storage/spider/spd_trx.cc b/storage/spider/spd_trx.cc
index d7127fa0084..18b6fd5ec89 100644
--- a/storage/spider/spd_trx.cc
+++ b/storage/spider/spd_trx.cc
@@ -3710,7 +3710,7 @@ int spider_check_trx_and_get_conn(
{
TABLE *table = spider->get_table();
TABLE_SHARE *table_share = table->s;
-#ifdef _MSC_VER
+#if defined(_MSC_VER) || defined(__SUNPRO_CC)
char *db, *table_name;
if (!(db = (char *)
spider_bulk_malloc(spider_current_trx, 57, MYF(MY_WME),
@@ -3732,7 +3732,7 @@ int spider_check_trx_and_get_conn(
table_name[table_share->table_name.length] = '\0';
my_printf_error(ER_SPIDER_ALL_LINKS_FAILED_NUM,
ER_SPIDER_ALL_LINKS_FAILED_STR, MYF(0), db, table_name);
-#ifdef _MSC_VER
+#if defined(_MSC_VER) || defined(__SUNPRO_CC)
spider_free(trx, db, MYF(MY_WME));
#endif
DBUG_RETURN(ER_SPIDER_ALL_LINKS_FAILED_NUM);
@@ -3869,7 +3869,7 @@ int spider_check_trx_and_get_conn(
{
TABLE *table = spider->get_table();
TABLE_SHARE *table_share = table->s;
-#ifdef _MSC_VER
+#if defined(_MSC_VER) || defined(__SUNPRO_CC)
char *db, *table_name;
if (!(db = (char *)
spider_bulk_malloc(spider_current_trx, 57, MYF(MY_WME),
@@ -3891,7 +3891,7 @@ int spider_check_trx_and_get_conn(
table_name[table_share->table_name.length] = '\0';
my_printf_error(ER_SPIDER_LINK_MON_JUST_NG_NUM,
ER_SPIDER_LINK_MON_JUST_NG_STR, MYF(0), db, table_name);
-#ifdef _MSC_VER
+#if defined(_MSC_VER) || defined(__SUNPRO_CC)
spider_free(trx, db, MYF(MY_WME));
#endif
DBUG_RETURN(ER_SPIDER_LINK_MON_JUST_NG_NUM);
@@ -4015,7 +4015,7 @@ int spider_check_trx_and_get_conn(
{
TABLE *table = spider->get_table();
TABLE_SHARE *table_share = table->s;
-#ifdef _MSC_VER
+#if defined(_MSC_VER) || defined(__SUNPRO_CC)
char *db, *table_name;
if (!(db = (char *)
spider_bulk_malloc(spider_current_trx, 57, MYF(MY_WME),
@@ -4037,7 +4037,7 @@ int spider_check_trx_and_get_conn(
table_name[table_share->table_name.length] = '\0';
my_printf_error(ER_SPIDER_LINK_MON_JUST_NG_NUM,
ER_SPIDER_LINK_MON_JUST_NG_STR, MYF(0), db, table_name);
-#ifdef _MSC_VER
+#if defined(_MSC_VER) || defined(__SUNPRO_CC)
spider_free(trx, db, MYF(MY_WME));
#endif
DBUG_RETURN(ER_SPIDER_LINK_MON_JUST_NG_NUM);
diff --git a/storage/tokudb/PerconaFT/cmake_modules/TokuSetupCompiler.cmake b/storage/tokudb/PerconaFT/cmake_modules/TokuSetupCompiler.cmake
index f25206d8861..40ccbcc0aed 100644
--- a/storage/tokudb/PerconaFT/cmake_modules/TokuSetupCompiler.cmake
+++ b/storage/tokudb/PerconaFT/cmake_modules/TokuSetupCompiler.cmake
@@ -74,8 +74,8 @@ set_cflags_if_supported(
if (CMAKE_CXX_FLAGS MATCHES -fno-implicit-templates)
# must append this because mysql sets -fno-implicit-templates and we need to override it
- check_cxx_compiler_flag(-fimplicit-templates HAVE_CXX_-fimplicit-templates)
- if (HAVE_CXX_-fimplicit-templates)
+ check_cxx_compiler_flag(-fimplicit-templates HAVE_CXX_IMPLICIT_TEMPLATES)
+ if (HAVE_CXX_IMPLICIT_TEMPLATES)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fimplicit-templates")
endif ()
endif()
diff --git a/storage/tokudb/mysql-test/tokudb/r/cluster_filter_unpack_varchar.result b/storage/tokudb/mysql-test/tokudb/r/cluster_filter_unpack_varchar.result
index d3273437f77..9faf04b6a10 100644
--- a/storage/tokudb/mysql-test/tokudb/r/cluster_filter_unpack_varchar.result
+++ b/storage/tokudb/mysql-test/tokudb/r/cluster_filter_unpack_varchar.result
@@ -182,14 +182,14 @@ a b c d e f
3 30 200 2000 20000 200000
explain select * from t1 where b > "0";
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 index b b NULL NULL NULL; Using where; Using index
+1 SIMPLE t1 # b b NULL NULL NULL; Using where; Using index
select * from t1 where b > "0";
a b c d e f
2 20 100 1000 10000 100000
3 30 200 2000 20000 200000
explain select * from t1 where d > "0";
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 index d d NULL NULL NULL; Using where; Using index
+1 SIMPLE t1 # d d NULL NULL NULL; Using where; Using index
select * from t1 where d > "0";
a b c d e f
2 20 100 1000 10000 100000
diff --git a/storage/tokudb/mysql-test/tokudb/t/cluster_filter_unpack_varchar.test b/storage/tokudb/mysql-test/tokudb/t/cluster_filter_unpack_varchar.test
index 3a30919a8ff..f3e494e0dd4 100644
--- a/storage/tokudb/mysql-test/tokudb/t/cluster_filter_unpack_varchar.test
+++ b/storage/tokudb/mysql-test/tokudb/t/cluster_filter_unpack_varchar.test
@@ -82,11 +82,11 @@ alter table t1 add key d(d,a) clustering=yes, add key b(b) clustering=yes;
explain select * from t1 where c > "0";
select * from t1 where c > "0";
---replace_column 7 NULL 9 NULL;
+--replace_column 4 # 7 NULL 9 NULL;
explain select * from t1 where b > "0";
select * from t1 where b > "0";
---replace_column 7 NULL 9 NULL;
+--replace_column 4 # 7 NULL 9 NULL;
explain select * from t1 where d > "0";
select * from t1 where d > "0";
diff --git a/storage/xtradb/buf/buf0dump.cc b/storage/xtradb/buf/buf0dump.cc
index 7bce480e652..a68bb8a1344 100644
--- a/storage/xtradb/buf/buf0dump.cc
+++ b/storage/xtradb/buf/buf0dump.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2011, 2012, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2011, 2015, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -163,6 +163,25 @@ buf_load_status(
va_end(ap);
}
+/** Returns the directory path where the buffer pool dump file will be created.
+@return directory path */
+static
+const char*
+get_buf_dump_dir()
+{
+ const char* dump_dir;
+
+ /* The dump file should be created in the default data directory if
+ innodb_data_home_dir is set as an empty string. */
+ if (strcmp(srv_data_home, "") == 0) {
+ dump_dir = fil_path_to_mysql_datadir;
+ } else {
+ dump_dir = srv_data_home;
+ }
+
+ return(dump_dir);
+}
+
/*****************************************************************//**
Perform a buffer pool dump into the file specified by
innodb_buffer_pool_filename. If any errors occur then the value of
@@ -186,7 +205,7 @@ buf_dump(
int ret;
ut_snprintf(full_filename, sizeof(full_filename),
- "%s%c%s", srv_data_home, SRV_PATH_SEPARATOR,
+ "%s%c%s", get_buf_dump_dir(), SRV_PATH_SEPARATOR,
srv_buf_dump_filename);
ut_snprintf(tmp_filename, sizeof(tmp_filename),
@@ -471,7 +490,7 @@ buf_load()
buf_load_abort_flag = FALSE;
ut_snprintf(full_filename, sizeof(full_filename),
- "%s%c%s", srv_data_home, SRV_PATH_SEPARATOR,
+ "%s%c%s", get_buf_dump_dir(), SRV_PATH_SEPARATOR,
srv_buf_dump_filename);
buf_load_status(STATUS_NOTICE,
diff --git a/storage/xtradb/buf/buf0flu.cc b/storage/xtradb/buf/buf0flu.cc
index 5d64b75784a..2440637ccca 100644
--- a/storage/xtradb/buf/buf0flu.cc
+++ b/storage/xtradb/buf/buf0flu.cc
@@ -72,12 +72,6 @@ UNIV_INTERN mysql_pfs_key_t buf_page_cleaner_thread_key;
UNIV_INTERN mysql_pfs_key_t buf_lru_manager_thread_key;
#endif /* UNIV_PFS_THREAD */
-/** If LRU list of a buf_pool is less than this size then LRU eviction
-should not happen. This is because when we do LRU flushing we also put
-the blocks on free list. If LRU list is very small then we can end up
-in thrashing. */
-#define BUF_LRU_MIN_LEN 256
-
/* @} */
/******************************************************************//**
diff --git a/storage/xtradb/dict/dict0boot.cc b/storage/xtradb/dict/dict0boot.cc
index 59f210fcab9..138d3131e09 100644
--- a/storage/xtradb/dict/dict0boot.cc
+++ b/storage/xtradb/dict/dict0boot.cc
@@ -474,7 +474,7 @@ dict_boot(void)
} else {
ib_logf(IB_LOG_LEVEL_WARN,
"Change buffer not empty when --innodb-read-only "
- "is set! but srv_force_recovery = %d, ignoring.",
+ "is set! but srv_force_recovery = %lu, ignoring.",
srv_force_recovery);
}
}
diff --git a/storage/xtradb/dict/dict0dict.cc b/storage/xtradb/dict/dict0dict.cc
index 206038d36c9..a147fbbc671 100644
--- a/storage/xtradb/dict/dict0dict.cc
+++ b/storage/xtradb/dict/dict0dict.cc
@@ -1116,7 +1116,7 @@ dict_init(void)
&dict_operation_lock, SYNC_DICT_OPERATION);
if (!srv_read_only_mode) {
- dict_foreign_err_file = os_file_create_tmpfile();
+ dict_foreign_err_file = os_file_create_tmpfile(NULL);
ut_a(dict_foreign_err_file);
mutex_create(dict_foreign_err_mutex_key,
diff --git a/storage/xtradb/dict/dict0stats.cc b/storage/xtradb/dict/dict0stats.cc
index 12ead09d829..5c283f693d5 100644
--- a/storage/xtradb/dict/dict0stats.cc
+++ b/storage/xtradb/dict/dict0stats.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2009, 2014, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2009, 2015, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -1488,7 +1488,6 @@ on the leaf page.
when comparing records
@param[out] n_diff number of distinct records
@param[out] n_external_pages number of external pages
-@param[in,out] mtr mini-transaction
@return number of distinct records on the leaf page */
static
void
@@ -1496,8 +1495,7 @@ dict_stats_analyze_index_below_cur(
const btr_cur_t* cur,
ulint n_prefix,
ib_uint64_t* n_diff,
- ib_uint64_t* n_external_pages,
- mtr_t* mtr)
+ ib_uint64_t* n_external_pages)
{
dict_index_t* index;
ulint space;
@@ -1511,6 +1509,7 @@ dict_stats_analyze_index_below_cur(
ulint* offsets2;
ulint* offsets_rec;
ulint size;
+ mtr_t mtr;
index = btr_cur_get_index(cur);
@@ -1549,12 +1548,14 @@ dict_stats_analyze_index_below_cur(
function without analyzing any leaf pages */
*n_external_pages = 0;
+ mtr_start(&mtr);
+
/* descend to the leaf level on the B-tree */
for (;;) {
block = buf_page_get_gen(space, zip_size, page_no, RW_S_LATCH,
NULL /* no guessed block */,
- BUF_GET, __FILE__, __LINE__, mtr);
+ BUF_GET, __FILE__, __LINE__, &mtr);
page = buf_block_get_frame(block);
@@ -1576,6 +1577,8 @@ dict_stats_analyze_index_below_cur(
ut_a(*n_diff > 0);
if (*n_diff == 1) {
+ mtr_commit(&mtr);
+
/* page has all keys equal and the end of the page
was reached by dict_stats_scan_page(), no need to
descend to the leaf level */
@@ -1600,7 +1603,7 @@ dict_stats_analyze_index_below_cur(
}
/* make sure we got a leaf page as a result from the above loop */
- ut_ad(btr_page_get_level(page, mtr) == 0);
+ ut_ad(btr_page_get_level(page, &mtr) == 0);
/* scan the leaf page and find the number of distinct keys,
when looking only at the first n_prefix columns; also estimate
@@ -1617,6 +1620,7 @@ dict_stats_analyze_index_below_cur(
__func__, page_no, n_diff);
#endif
+ mtr_commit(&mtr);
mem_heap_free(heap);
}
@@ -1826,8 +1830,7 @@ dict_stats_analyze_index_for_n_prefix(
dict_stats_analyze_index_below_cur(btr_pcur_get_btr_cur(&pcur),
n_prefix,
&n_diff_on_leaf_page,
- &n_external_pages,
- mtr);
+ &n_external_pages);
/* We adjust n_diff_on_leaf_page here to avoid counting
one record twice - once as the last on some page and once
diff --git a/storage/xtradb/fil/fil0fil.cc b/storage/xtradb/fil/fil0fil.cc
index 80312d97e01..e77c97ead5b 100644
--- a/storage/xtradb/fil/fil0fil.cc
+++ b/storage/xtradb/fil/fil0fil.cc
@@ -5328,12 +5328,15 @@ retry:
os_offset_t offset
= ((os_offset_t) (start_page_no - file_start_page_no))
* page_size;
+
+ const char* name = node->name == NULL ? space->name : node->name;
+
#ifdef UNIV_HOTBACKUP
- success = os_file_write(node->name, node->handle, buf,
+ success = os_file_write(name, node->handle, buf,
offset, page_size * n_pages);
#else
success = os_aio(OS_FILE_WRITE, 0, OS_AIO_SYNC,
- node->name, node->handle, buf,
+ name, node->handle, buf,
offset, page_size * n_pages, page_size,
node, NULL, space_id, NULL, 0);
#endif /* UNIV_HOTBACKUP */
@@ -5997,22 +6000,12 @@ _fil_io(
}
}
+ const char* name = node->name == NULL ? space->name : node->name;
+
/* Queue the aio request */
- ret = os_aio(
- type,
- is_log,
- mode | wake_later,
- node->name,
- node->handle,
- buf,
- offset,
- len,
- zip_size ? zip_size : UNIV_PAGE_SIZE,
- node,
- message,
- space_id,
- trx,
- write_size);
+ ret = os_aio(type, is_log, mode | wake_later, name, node->handle, buf,
+ offset, len, zip_size ? zip_size : UNIV_PAGE_SIZE, node,
+ message, space_id, trx, write_size);
#else
/* In mysqlbackup do normal i/o, not aio */
@@ -6020,7 +6013,7 @@ _fil_io(
ret = os_file_read(node->handle, buf, offset, len);
} else {
ut_ad(!srv_read_only_mode);
- ret = os_file_write(node->name, node->handle, buf,
+ ret = os_file_write(name, node->handle, buf,
offset, len);
}
#endif /* !UNIV_HOTBACKUP */
diff --git a/storage/xtradb/fts/fts0opt.cc b/storage/xtradb/fts/fts0opt.cc
index 0703b050848..00b3b4682c3 100644
--- a/storage/xtradb/fts/fts0opt.cc
+++ b/storage/xtradb/fts/fts0opt.cc
@@ -580,7 +580,7 @@ fts_zip_read_word(
#ifdef UNIV_DEBUG
ulint i;
#endif
- byte len = 0;
+ short len = 0;
void* null = NULL;
byte* ptr = word->f_str;
int flush = Z_NO_FLUSH;
@@ -590,7 +590,7 @@ fts_zip_read_word(
return(NULL);
}
- zip->zp->next_out = &len;
+ zip->zp->next_out = reinterpret_cast<byte*>(&len);
zip->zp->avail_out = sizeof(len);
while (zip->status == Z_OK && zip->zp->avail_out > 0) {
@@ -688,11 +688,12 @@ fts_fetch_index_words(
fts_zip_t* zip = static_cast<fts_zip_t*>(user_arg);
que_node_t* exp = sel_node->select_list;
dfield_t* dfield = que_node_get_val(exp);
- byte len = (byte) dfield_get_len(dfield);
+ short len = static_cast<short>(dfield_get_len(dfield));
void* data = dfield_get_data(dfield);
/* Skip the duplicate words. */
- if (zip->word.f_len == len && !memcmp(zip->word.f_str, data, len)) {
+ if (zip->word.f_len == static_cast<ulint>(len)
+ && !memcmp(zip->word.f_str, data, len)) {
return(TRUE);
}
@@ -706,7 +707,7 @@ fts_fetch_index_words(
ut_a(zip->zp->next_in == NULL);
/* The string is prefixed by len. */
- zip->zp->next_in = &len;
+ zip->zp->next_in = reinterpret_cast<byte*>(&len);
zip->zp->avail_in = sizeof(len);
/* Compress the word, create output blocks as necessary. */
diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc
index 065f1bd2ca0..2406ed96716 100644
--- a/storage/xtradb/handler/ha_innodb.cc
+++ b/storage/xtradb/handler/ha_innodb.cc
@@ -617,7 +617,6 @@ ib_cb_t innodb_api_cb[] = {
(ib_cb_t) ib_trx_read_only
};
-
static void innodb_remember_check_sysvar_funcs();
mysql_var_check_func check_sysvar_enum;
@@ -652,6 +651,67 @@ ha_create_table_option innodb_table_option_list[]=
HA_TOPTION_END
};
+/**
+ Test a file path whether it is same as mysql data directory path.
+
+ @param path null terminated character string
+
+ @return
+ @retval TRUE The path is different from mysql data directory.
+ @retval FALSE The path is same as mysql data directory.
+*/
+static bool is_mysql_datadir_path(const char *path)
+{
+ if (path == NULL)
+ return false;
+
+ char mysql_data_dir[FN_REFLEN], path_dir[FN_REFLEN];
+ convert_dirname(path_dir, path, NullS);
+ convert_dirname(mysql_data_dir, mysql_unpacked_real_data_home, NullS);
+ size_t mysql_data_home_len= dirname_length(mysql_data_dir);
+ size_t path_len = dirname_length(path_dir);
+
+ if (path_len < mysql_data_home_len)
+ return true;
+
+ if (!lower_case_file_system)
+ return(memcmp(mysql_data_dir, path_dir, mysql_data_home_len));
+
+ return(files_charset_info->coll->strnncoll(files_charset_info,
+ (uchar *) path_dir, path_len,
+ (uchar *) mysql_data_dir,
+ mysql_data_home_len,
+ TRUE));
+}
+
+
+static int mysql_tmpfile_path(const char *path, const char *prefix)
+{
+ DBUG_ASSERT(path != NULL);
+ DBUG_ASSERT((strlen(path) + strlen(prefix)) <= FN_REFLEN);
+
+ char filename[FN_REFLEN];
+ File fd = create_temp_file(filename, path, prefix,
+#ifdef __WIN__
+ O_BINARY | O_TRUNC | O_SEQUENTIAL |
+ O_SHORT_LIVED |
+#endif /* __WIN__ */
+ O_CREAT | O_EXCL | O_RDWR | O_TEMPORARY,
+ MYF(MY_WME));
+ if (fd >= 0) {
+#ifndef __WIN__
+ /*
+ This can be removed once the following bug is fixed:
+ Bug #28903 create_temp_file() doesn't honor O_TEMPORARY option
+ (file not removed) (Unix)
+ */
+ unlink(filename);
+#endif /* !__WIN__ */
+ }
+
+ return fd;
+}
+
/*************************************************************//**
Check whether valid argument given to innodb_ft_*_stopword_table.
This function is registered as a callback with MySQL.
@@ -667,6 +727,108 @@ innodb_stopword_table_validate(
for update function */
struct st_mysql_value* value); /*!< in: incoming string */
+/** Validate passed-in "value" is a valid directory name.
+This function is registered as a callback with MySQL.
+@param[in,out] thd thread handle
+@param[in] var pointer to system variable
+@param[out] save immediate result for update
+@param[in] value incoming string
+@return 0 for valid name */
+static
+int
+innodb_tmpdir_validate(
+ THD* thd,
+ struct st_mysql_sys_var* var,
+ void* save,
+ struct st_mysql_value* value)
+{
+
+ char* alter_tmp_dir;
+ char* innodb_tmp_dir;
+ char buff[OS_FILE_MAX_PATH];
+ int len = sizeof(buff);
+ char tmp_abs_path[FN_REFLEN + 2];
+
+ ut_ad(save != NULL);
+ ut_ad(value != NULL);
+
+ if (check_global_access(thd, FILE_ACL)) {
+ push_warning_printf(
+ thd, Sql_condition::WARN_LEVEL_WARN,
+ ER_WRONG_ARGUMENTS,
+ "InnoDB: FILE Permissions required");
+ *static_cast<const char**>(save) = NULL;
+ return(1);
+ }
+
+ alter_tmp_dir = (char*) value->val_str(value, buff, &len);
+
+ if (!alter_tmp_dir) {
+ *static_cast<const char**>(save) = alter_tmp_dir;
+ return(0);
+ }
+
+ if (strlen(alter_tmp_dir) > FN_REFLEN) {
+ push_warning_printf(
+ thd, Sql_condition::WARN_LEVEL_WARN,
+ ER_WRONG_ARGUMENTS,
+ "Path length should not exceed %d bytes", FN_REFLEN);
+ *static_cast<const char**>(save) = NULL;
+ return(1);
+ }
+
+ my_realpath(tmp_abs_path, alter_tmp_dir, 0);
+ size_t tmp_abs_len = strlen(tmp_abs_path);
+
+ if (my_access(tmp_abs_path, F_OK)) {
+
+ push_warning_printf(
+ thd, Sql_condition::WARN_LEVEL_WARN,
+ ER_WRONG_ARGUMENTS,
+ "InnoDB: Path doesn't exist.");
+ *static_cast<const char**>(save) = NULL;
+ return(1);
+ } else if (my_access(tmp_abs_path, R_OK | W_OK)) {
+ push_warning_printf(
+ thd, Sql_condition::WARN_LEVEL_WARN,
+ ER_WRONG_ARGUMENTS,
+ "InnoDB: Server doesn't have permission in "
+ "the given location.");
+ *static_cast<const char**>(save) = NULL;
+ return(1);
+ }
+
+ MY_STAT stat_info_dir;
+
+ if (my_stat(tmp_abs_path, &stat_info_dir, MYF(0))) {
+ if ((stat_info_dir.st_mode & S_IFDIR) != S_IFDIR) {
+
+ push_warning_printf(
+ thd, Sql_condition::WARN_LEVEL_WARN,
+ ER_WRONG_ARGUMENTS,
+ "Given path is not a directory. ");
+ *static_cast<const char**>(save) = NULL;
+ return(1);
+ }
+ }
+
+ if (!is_mysql_datadir_path(tmp_abs_path)) {
+
+ push_warning_printf(
+ thd, Sql_condition::WARN_LEVEL_WARN,
+ ER_WRONG_ARGUMENTS,
+ "InnoDB: Path Location should not be same as "
+ "mysql data directory location.");
+ *static_cast<const char**>(save) = NULL;
+ return(1);
+ }
+
+ innodb_tmp_dir = static_cast<char*>(
+ thd_memdup(thd, tmp_abs_path, tmp_abs_len + 1));
+ *static_cast<const char**>(save) = innodb_tmp_dir;
+ return(0);
+}
+
/** "GEN_CLUST_INDEX" is the name reserved for InnoDB default
system clustered index when there is no primary key. */
const char innobase_index_reserve_name[] = "GEN_CLUST_INDEX";
@@ -796,6 +958,11 @@ static MYSQL_THDVAR_BOOL(fake_changes, PLUGIN_VAR_OPCMDARG,
"This is to cause replication prefetch IO. ATTENTION: the transaction started after enabled is affected.",
NULL, NULL, FALSE);
+static MYSQL_THDVAR_STR(tmpdir,
+ PLUGIN_VAR_OPCMDARG|PLUGIN_VAR_MEMALLOC,
+ "Directory for temporary non-tablespace files.",
+ innodb_tmpdir_validate, NULL, NULL);
+
static ibool innodb_have_lzo=IF_LZO(1, 0);
static ibool innodb_have_lz4=IF_LZ4(1, 0);
static ibool innodb_have_lzma=IF_LZMA(1, 0);
@@ -1492,6 +1659,28 @@ normalize_table_name_low(
ibool set_lower_case); /* in: TRUE if we want to set
name to lower case */
+/*************************************************************//**
+Checks if buffer pool is big enough to enable backoff algorithm.
+InnoDB empty free list algorithm backoff requires free pages
+from LRU for the best performance.
+buf_LRU_buf_pool_running_out cancels query if 1/4 of
+buffer pool belongs to LRU or freelist.
+At the same time buf_flush_LRU_list_batch
+keeps up to BUF_LRU_MIN_LEN in LRU.
+In order to avoid deadlock baclkoff requires buffer pool
+to be at least 4*BUF_LRU_MIN_LEN,
+but flush peformance is bad because of trashing
+and additional BUF_LRU_MIN_LEN pages are requested.
+@return true if it's possible to enable backoff. */
+static
+bool
+innodb_empty_free_list_algorithm_backoff_allowed(
+ srv_empty_free_list_t
+ algorithm, /*!< in: desired algorithm
+ from srv_empty_free_list_t */
+ long long buf_pool_pages); /*!< in: total number
+ of pages inside buffer pool */
+
#ifdef NOT_USED
/*************************************************************//**
Removes old archived transaction log files.
@@ -1780,6 +1969,26 @@ thd_supports_xa(
return(THDVAR(thd, support_xa));
}
+/** Get the value of innodb_tmpdir.
+@param[in] thd thread handle, or NULL to query
+ the global innodb_tmpdir.
+@retval NULL if innodb_tmpdir="" */
+UNIV_INTERN
+const char*
+thd_innodb_tmpdir(
+ THD* thd)
+{
+#ifdef UNIV_SYNC_DEBUG
+ ut_ad(!sync_thread_levels_nonempty_trx(false));
+#endif /* UNIV_SYNC_DEBUG */
+
+ const char* tmp_dir = THDVAR(thd, tmpdir);
+ if (tmp_dir != NULL && *tmp_dir == '\0') {
+ tmp_dir = NULL;
+ }
+
+ return(tmp_dir);
+}
/******************************************************************//**
Check the status of fake changes mode (innodb_fake_changes)
@return true if fake change mode is enabled. */
@@ -2360,13 +2569,14 @@ innobase_get_lower_case_table_names(void)
return(lower_case_table_names);
}
-/*********************************************************************//**
-Creates a temporary file.
+/** Create a temporary file in the location specified by the parameter
+path. If the path is null, then it will be created in tmpdir.
+@param[in] path location for creating temporary file
@return temporary file descriptor, or < 0 on error */
UNIV_INTERN
int
-innobase_mysql_tmpfile(void)
-/*========================*/
+innobase_mysql_tmpfile(
+ const char* path)
{
#ifdef WITH_INNODB_DISALLOW_WRITES
os_event_wait(srv_allow_writes_event);
@@ -2379,7 +2589,11 @@ innobase_mysql_tmpfile(void)
return(-1);
);
- fd = mysql_tmpfile("ib");
+ if (path == NULL) {
+ fd = mysql_tmpfile("ib");
+ } else {
+ fd = mysql_tmpfile_path(path, "ib");
+ }
if (fd >= 0) {
/* Copy the file descriptor, so that the additional resources
@@ -2922,7 +3136,7 @@ ha_innobase::ha_innobase(
:handler(hton, table_arg),
int_table_flags(HA_REC_NOT_IN_SEQ |
HA_NULL_IN_KEY | HA_CAN_VIRTUAL_COLUMNS |
- HA_CAN_INDEX_BLOBS |
+ HA_CAN_INDEX_BLOBS | HA_CONCURRENT_OPTIMIZE |
HA_CAN_SQL_HANDLER |
HA_PRIMARY_KEY_REQUIRED_FOR_POSITION |
HA_PRIMARY_KEY_IN_READ_INDEX |
@@ -3408,6 +3622,13 @@ ha_innobase::reset_template(void)
ut_ad(prebuilt->magic_n == ROW_PREBUILT_ALLOCATED);
ut_ad(prebuilt->magic_n2 == prebuilt->magic_n);
+ /* Force table to be freed in close_thread_table(). */
+ DBUG_EXECUTE_IF("free_table_in_fts_query",
+ if (prebuilt->in_fts_query) {
+ table->m_needs_reopen = true;
+ }
+ );
+
prebuilt->keep_other_fields_on_keyread = 0;
prebuilt->read_just_key = 0;
prebuilt->in_fts_query = 0;
@@ -4076,6 +4297,22 @@ innobase_change_buffering_inited_ok:
#ifdef HAVE_POSIX_FALLOCATE
srv_use_posix_fallocate = (ibool) innobase_use_fallocate;
#endif
+
+ /* Do not enable backoff algorithm for small buffer pool. */
+ if (!innodb_empty_free_list_algorithm_backoff_allowed(
+ static_cast<srv_empty_free_list_t>(
+ srv_empty_free_list_algorithm),
+ innobase_buffer_pool_size / srv_page_size)) {
+ sql_print_information(
+ "InnoDB: innodb_empty_free_list_algorithm "
+ "has been changed to legacy "
+ "because of small buffer pool size. "
+ "In order to use backoff, "
+ "increase buffer pool at least up to 20MB.\n");
+ srv_empty_free_list_algorithm
+ = SRV_EMPTY_FREE_LIST_LEGACY;
+ }
+
srv_use_atomic_writes = (ibool) innobase_use_atomic_writes;
if (innobase_use_atomic_writes) {
ib_logf(IB_LOG_LEVEL_INFO, "using atomic writes.");
@@ -5718,7 +5955,7 @@ building based on the assumption that there is no concurrent
index creation/drop and DMLs that requires index lookup. All table
handle will be closed before the index creation/drop.
@return TRUE if index translation table built successfully */
-static
+UNIV_INTERN
ibool
innobase_build_index_translation(
/*=============================*/
@@ -6270,20 +6507,14 @@ table_opened:
prebuilt->clust_index_was_generated = FALSE;
if (UNIV_UNLIKELY(primary_key >= MAX_KEY)) {
- sql_print_error("Table %s has a primary key in "
- "InnoDB data dictionary, but not "
- "in MySQL!", name);
+ ib_table->dict_frm_mismatch = DICT_FRM_NO_PK;
/* This mismatch could cause further problems
if not attended, bring this to the user's attention
by printing a warning in addition to log a message
in the errorlog */
- push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
- ER_NO_SUCH_INDEX,
- "InnoDB: Table %s has a "
- "primary key in InnoDB data "
- "dictionary, but not in "
- "MySQL!", name);
+
+ ib_push_frm_error(thd, ib_table, table, 0, true);
/* If primary_key >= MAX_KEY, its (primary_key)
value could be out of bound if continue to index
@@ -6330,27 +6561,14 @@ table_opened:
}
} else {
if (primary_key != MAX_KEY) {
- sql_print_error(
- "Table %s has no primary key in InnoDB data "
- "dictionary, but has one in MySQL! If you "
- "created the table with a MySQL version < "
- "3.23.54 and did not define a primary key, "
- "but defined a unique key with all non-NULL "
- "columns, then MySQL internally treats that "
- "key as the primary key. You can fix this "
- "error by dump + DROP + CREATE + reimport "
- "of the table.", name);
+
+ ib_table->dict_frm_mismatch = DICT_NO_PK_FRM_HAS;
/* This mismatch could cause further problems
if not attended, bring this to the user attention
by printing a warning in addition to log a message
in the errorlog */
- push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
- ER_NO_SUCH_INDEX,
- "InnoDB: Table %s has no "
- "primary key in InnoDB data "
- "dictionary, but has one in "
- "MySQL!", name);
+ ib_push_frm_error(thd, ib_table, table, 0, true);
}
prebuilt->clust_index_was_generated = TRUE;
@@ -13960,12 +14178,8 @@ ha_innobase::info_low(
}
if (table->s->keys != num_innodb_index) {
- sql_print_error("InnoDB: Table %s contains %lu "
- "indexes inside InnoDB, which "
- "is different from the number of "
- "indexes %u defined in the MySQL ",
- ib_table->name, num_innodb_index,
- table->s->keys);
+ ib_table->dict_frm_mismatch = DICT_FRM_INCONSISTENT_KEYS;
+ ib_push_frm_error(user_thd, ib_table, table, num_innodb_index, true);
}
if (!(flag & HA_STATUS_NO_LOCK)) {
@@ -13985,15 +14199,8 @@ ha_innobase::info_low(
dict_index_t* index = innobase_get_index(i);
if (index == NULL) {
- sql_print_error("Table %s contains fewer "
- "indexes inside InnoDB than "
- "are defined in the MySQL "
- ".frm file. Have you mixed up "
- ".frm files from different "
- "installations? See "
- REFMAN
- "innodb-troubleshooting.html\n",
- ib_table->name);
+ ib_table->dict_frm_mismatch = DICT_FRM_INCONSISTENT_KEYS;
+ ib_push_frm_error(user_thd, ib_table, table, num_innodb_index, true);
break;
}
@@ -18762,8 +18969,6 @@ innobase_fts_close_ranking(
{
fts_result_t* result;
- ((NEW_FT_INFO*) fts_hdl)->ft_prebuilt->in_fts_query = false;
-
result = ((NEW_FT_INFO*) fts_hdl)->ft_result;
fts_query_free_result(result);
@@ -19473,6 +19678,7 @@ static int innobase_wsrep_get_checkpoint(handlerton* hton, XID* xid)
return 0;
}
+
static void
wsrep_fake_trx_id(
/*==================*/
@@ -19488,6 +19694,88 @@ wsrep_fake_trx_id(
#endif /* WITH_WSREP */
+
+/*************************************************************//**
+Empty free list algorithm.
+Checks if buffer pool is big enough to enable backoff algorithm.
+InnoDB empty free list algorithm backoff requires free pages
+from LRU for the best performance.
+buf_LRU_buf_pool_running_out cancels query if 1/4 of
+buffer pool belongs to LRU or freelist.
+At the same time buf_flush_LRU_list_batch
+keeps up to BUF_LRU_MIN_LEN in LRU.
+In order to avoid deadlock baclkoff requires buffer pool
+to be at least 4*BUF_LRU_MIN_LEN,
+but flush peformance is bad because of trashing
+and additional BUF_LRU_MIN_LEN pages are requested.
+@return true if it's possible to enable backoff. */
+static
+bool
+innodb_empty_free_list_algorithm_backoff_allowed(
+ srv_empty_free_list_t algorithm, /*!< in: desired algorithm
+ from srv_empty_free_list_t */
+ long long buf_pool_pages) /*!< in: total number
+ of pages inside buffer pool */
+{
+ return(buf_pool_pages >= BUF_LRU_MIN_LEN * (4 + 1)
+ || algorithm != SRV_EMPTY_FREE_LIST_BACKOFF);
+}
+
+/*************************************************************//**
+Empty free list algorithm. This function is registered as
+a callback with MySQL.
+@return 0 for valid algorithm */
+static
+int
+innodb_srv_empty_free_list_algorithm_validate(
+/*===========================*/
+ THD* thd, /*!< in: thread handle */
+ struct st_mysql_sys_var* var, /*!< in: pointer to system
+ variable */
+ void* save, /*!< out: immediate result
+ for update function */
+ struct st_mysql_value* value) /*!< in: incoming string */
+{
+ const char* algorithm_name;
+ char buff[STRING_BUFFER_USUAL_SIZE];
+ int len = sizeof(buff);
+ ulint algo;
+ srv_empty_free_list_t algorithm;
+
+ algorithm_name = value->val_str(value, buff, &len);
+
+ if (!algorithm_name) {
+ return(1);
+ }
+
+ for (algo = 0; algo < array_elements(
+ innodb_empty_free_list_algorithm_names
+ ) - 1;
+ algo++) {
+ if (!innobase_strcasecmp(
+ algorithm_name,
+ innodb_empty_free_list_algorithm_names[algo]))
+ break;
+ }
+
+ if (algo == array_elements( innodb_empty_free_list_algorithm_names) - 1)
+ return(1);
+
+ algorithm = static_cast<srv_empty_free_list_t>(algo);
+ if (!innodb_empty_free_list_algorithm_backoff_allowed(
+ algorithm,
+ innobase_buffer_pool_size / srv_page_size)) {
+ sql_print_warning(
+ "InnoDB: innodb_empty_free_list_algorithm "
+ "= 'backoff' requires at least"
+ " 20MB buffer pool.\n");
+ return(1);
+ }
+
+ *reinterpret_cast<ulong*>(save) = static_cast<ulong>(algorithm);
+ return(0);
+}
+
/* plugin options */
static MYSQL_SYSVAR_ENUM(checksum_algorithm, srv_checksum_algorithm,
@@ -20038,7 +20326,7 @@ static MYSQL_SYSVAR_ENUM(empty_free_list_algorithm,
"The algorithm to use for empty free list handling. Allowed values: "
"LEGACY: Original Oracle MySQL 5.6 handling with single page flushes; "
"BACKOFF: (default) Wait until cleaner produces a free page.",
- NULL, NULL, SRV_EMPTY_FREE_LIST_BACKOFF,
+ innodb_srv_empty_free_list_algorithm_validate, NULL, SRV_EMPTY_FREE_LIST_BACKOFF,
&innodb_empty_free_list_algorithm_typelib);
static MYSQL_SYSVAR_LONG(buffer_pool_instances, innobase_buffer_pool_instances,
@@ -21078,6 +21366,7 @@ static struct st_mysql_sys_var* innobase_system_variables[]= {
MYSQL_SYSVAR(corrupt_table_action),
MYSQL_SYSVAR(fake_changes),
MYSQL_SYSVAR(locking_fake_changes),
+ MYSQL_SYSVAR(tmpdir),
MYSQL_SYSVAR(use_stacktrace),
MYSQL_SYSVAR(force_primary_key),
MYSQL_SYSVAR(fatal_semaphore_wait_threshold),
@@ -21822,3 +22111,96 @@ ib_push_warning(
my_free(buf);
va_end(args);
}
+
+/********************************************************************//**
+Helper function to push frm mismatch error to error log and
+if needed to sql-layer. */
+UNIV_INTERN
+void
+ib_push_frm_error(
+/*==============*/
+ THD* thd, /*!< in: MySQL thd */
+ dict_table_t* ib_table, /*!< in: InnoDB table */
+ TABLE* table, /*!< in: MySQL table */
+ ulint n_keys, /*!< in: InnoDB #keys */
+ bool push_warning) /*!< in: print warning ? */
+{
+ switch (ib_table->dict_frm_mismatch) {
+ case DICT_FRM_NO_PK:
+ sql_print_error("Table %s has a primary key in "
+ "InnoDB data dictionary, but not "
+ "in MySQL!"
+ " Have you mixed up "
+ ".frm files from different "
+ "installations? See "
+ REFMAN
+ "innodb-troubleshooting.html\n",
+ ib_table->name);
+
+ if (push_warning) {
+ push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
+ ER_NO_SUCH_INDEX,
+ "InnoDB: Table %s has a "
+ "primary key in InnoDB data "
+ "dictionary, but not in "
+ "MySQL!", ib_table->name);
+ }
+ break;
+ case DICT_NO_PK_FRM_HAS:
+ sql_print_error(
+ "Table %s has no primary key in InnoDB data "
+ "dictionary, but has one in MySQL! If you "
+ "created the table with a MySQL version < "
+ "3.23.54 and did not define a primary key, "
+ "but defined a unique key with all non-NULL "
+ "columns, then MySQL internally treats that "
+ "key as the primary key. You can fix this "
+ "error by dump + DROP + CREATE + reimport "
+ "of the table.", ib_table->name);
+
+ if (push_warning) {
+ push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
+ ER_NO_SUCH_INDEX,
+ "InnoDB: Table %s has no "
+ "primary key in InnoDB data "
+ "dictionary, but has one in "
+ "MySQL!",
+ ib_table->name);
+ }
+ break;
+
+ case DICT_FRM_INCONSISTENT_KEYS:
+ sql_print_error("InnoDB: Table %s contains %lu "
+ "indexes inside InnoDB, which "
+ "is different from the number of "
+ "indexes %u defined in the MySQL "
+ " Have you mixed up "
+ ".frm files from different "
+ "installations? See "
+ REFMAN
+ "innodb-troubleshooting.html\n",
+ ib_table->name, n_keys,
+ table->s->keys);
+
+ if (push_warning) {
+ push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
+ ER_NO_SUCH_INDEX,
+ "InnoDB: Table %s contains %lu "
+ "indexes inside InnoDB, which "
+ "is different from the number of "
+ "indexes %u defined in the MySQL ",
+ ib_table->name, n_keys,
+ table->s->keys);
+ }
+ break;
+
+ case DICT_FRM_CONSISTENT:
+ default:
+ sql_print_error("InnoDB: Table %s is consistent "
+ "on InnoDB data dictionary and MySQL "
+ " FRM file.",
+ ib_table->name);
+ ut_error;
+ break;
+ }
+}
diff --git a/storage/xtradb/handler/ha_innodb.h b/storage/xtradb/handler/ha_innodb.h
index 2027a593140..ea4be1fb2e0 100644
--- a/storage/xtradb/handler/ha_innodb.h
+++ b/storage/xtradb/handler/ha_innodb.h
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 2000, 2012, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2013, 2014, SkySQL Ab. All Rights Reserved.
+Copyright (c) 2013, 2016, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -696,3 +696,39 @@ innobase_copy_frm_flags_from_table_share(
/*=====================================*/
dict_table_t* innodb_table, /*!< in/out: InnoDB table */
const TABLE_SHARE* table_share); /*!< in: table share */
+
+/*******************************************************************//**
+This function builds a translation table in INNOBASE_SHARE
+structure for fast index location with mysql array number from its
+table->key_info structure. This also provides the necessary translation
+between the key order in mysql key_info and Innodb ib_table->indexes if
+they are not fully matched with each other.
+Note we do not have any mutex protecting the translation table
+building based on the assumption that there is no concurrent
+index creation/drop and DMLs that requires index lookup. All table
+handle will be closed before the index creation/drop.
+@return TRUE if index translation table built successfully */
+UNIV_INTERN
+ibool
+innobase_build_index_translation(
+/*=============================*/
+ const TABLE* table, /*!< in: table in MySQL data
+ dictionary */
+ dict_table_t* ib_table, /*!< in: table in Innodb data
+ dictionary */
+ INNOBASE_SHARE* share); /*!< in/out: share structure
+ where index translation table
+ will be constructed in. */
+
+/********************************************************************//**
+Helper function to push frm mismatch error to error log and
+if needed to sql-layer. */
+UNIV_INTERN
+void
+ib_push_frm_error(
+/*==============*/
+ THD* thd, /*!< in: MySQL thd */
+ dict_table_t* ib_table, /*!< in: InnoDB table */
+ TABLE* table, /*!< in: MySQL table */
+ ulint n_keys, /*!< in: InnoDB #keys */
+ bool push_warning); /*!< in: print warning ? */
diff --git a/storage/xtradb/handler/handler0alter.cc b/storage/xtradb/handler/handler0alter.cc
index ea02463010c..1e57f6c5293 100644
--- a/storage/xtradb/handler/handler0alter.cc
+++ b/storage/xtradb/handler/handler0alter.cc
@@ -463,6 +463,20 @@ ha_innobase::check_if_supported_inplace_alter(
}
}
+ ulint n_indexes = UT_LIST_GET_LEN((prebuilt->table)->indexes);
+
+ /* If InnoDB dictionary and MySQL frm file are not consistent
+ use "Copy" method. */
+ if (prebuilt->table->dict_frm_mismatch) {
+
+ ha_alter_info->unsupported_reason = innobase_get_err_msg(
+ ER_NO_SUCH_INDEX);
+ ib_push_frm_error(user_thd, prebuilt->table, altered_table,
+ n_indexes, true);
+
+ DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED);
+ }
+
/* We should be able to do the operation in-place.
See if we can do it online (LOCK=NONE). */
bool online = true;
@@ -2777,6 +2791,10 @@ prepare_inplace_alter_table_dict(
ctx->num_to_add_index = ha_alter_info->index_add_count;
+ ut_ad(ctx->prebuilt->trx->mysql_thd != NULL);
+ const char* path = thd_innodb_tmpdir(
+ ctx->prebuilt->trx->mysql_thd);
+
index_defs = innobase_create_key_defs(
ctx->heap, ha_alter_info, altered_table, ctx->num_to_add_index,
num_fts_index,
@@ -3130,8 +3148,10 @@ prepare_inplace_alter_table_dict(
error = DB_OUT_OF_MEMORY;
goto error_handling;);
rw_lock_x_lock(&ctx->add_index[a]->lock);
+
bool ok = row_log_allocate(ctx->add_index[a],
- NULL, true, NULL, NULL);
+ NULL, true, NULL,
+ NULL, path);
rw_lock_x_unlock(&ctx->add_index[a]->lock);
if (!ok) {
@@ -3157,7 +3177,7 @@ prepare_inplace_alter_table_dict(
clust_index, ctx->new_table,
!(ha_alter_info->handler_flags
& Alter_inplace_info::ADD_PK_INDEX),
- ctx->add_cols, ctx->col_map);
+ ctx->add_cols, ctx->col_map, path);
rw_lock_x_unlock(&clust_index->lock);
if (!ok) {
@@ -4159,6 +4179,7 @@ ok_exit:
files and merge sort. */
DBUG_EXECUTE_IF("innodb_OOM_inplace_alter",
error = DB_OUT_OF_MEMORY; goto oom;);
+
error = row_merge_build_indexes(
prebuilt->trx,
prebuilt->table, ctx->new_table,
@@ -6194,6 +6215,21 @@ foreign_fail:
row_mysql_unlock_data_dictionary(trx);
trx_free_for_mysql(trx);
+ /* Rebuild index translation table now for temporary tables if we are
+ restoring secondary keys, as ha_innobase::open will not be called for
+ the next access. */
+ if (dict_table_is_temporary(ctx0->new_table)
+ && ctx0->num_to_add_index > 0) {
+ ut_ad(!ctx0->num_to_drop_index);
+ ut_ad(!ctx0->num_to_drop_fk);
+ if (!innobase_build_index_translation(altered_table,
+ ctx0->new_table,
+ share)) {
+ MONITOR_ATOMIC_DEC(MONITOR_PENDING_ALTER_TABLE);
+ DBUG_RETURN(true);
+ }
+ }
+
/* TODO: The following code could be executed
while allowing concurrent access to the table
(MDL downgrade). */
diff --git a/storage/xtradb/include/buf0flu.h b/storage/xtradb/include/buf0flu.h
index 87ce7d88bdf..c8a329251fa 100644
--- a/storage/xtradb/include/buf0flu.h
+++ b/storage/xtradb/include/buf0flu.h
@@ -312,6 +312,12 @@ buf_flush_flush_list_in_progress(void)
/*==================================*/
__attribute__((warn_unused_result));
+/** If LRU list of a buf_pool is less than this size then LRU eviction
+should not happen. This is because when we do LRU flushing we also put
+the blocks on free list. If LRU list is very small then we can end up
+in thrashing. */
+#define BUF_LRU_MIN_LEN 256
+
/******************************************************************//**
Start a buffer flush batch for LRU or flush list */
ibool
diff --git a/storage/xtradb/include/dict0mem.h b/storage/xtradb/include/dict0mem.h
index 9c43829cecf..a55d5316969 100644
--- a/storage/xtradb/include/dict0mem.h
+++ b/storage/xtradb/include/dict0mem.h
@@ -2,7 +2,7 @@
Copyright (c) 1996, 2015, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2012, Facebook Inc.
-Copyright (c) 2013, 2015, MariaDB Corporation.
+Copyright (c) 2013, 2016, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -1025,6 +1025,18 @@ if table->memcached_sync_count == DICT_TABLE_IN_DDL means there's DDL running on
the table, DML from memcached will be blocked. */
#define DICT_TABLE_IN_DDL -1
+/** These are used when MySQL FRM and InnoDB data dictionary are
+in inconsistent state. */
+typedef enum {
+ DICT_FRM_CONSISTENT = 0, /*!< Consistent state */
+ DICT_FRM_NO_PK = 1, /*!< MySQL has no primary key
+ but InnoDB dictionary has
+ non-generated one. */
+ DICT_NO_PK_FRM_HAS = 2, /*!< MySQL has primary key but
+ InnoDB dictionary has not. */
+ DICT_FRM_INCONSISTENT_KEYS = 3 /*!< Key count mismatch */
+} dict_frm_t;
+
/** Data structure for a database table. Most fields will be
initialized to 0, NULL or FALSE in dict_mem_table_create(). */
struct dict_table_t{
@@ -1085,6 +1097,10 @@ struct dict_table_t{
/*!< True if the table belongs to a system
database (mysql, information_schema or
performance_schema) */
+ dict_frm_t dict_frm_mismatch;
+ /*!< !DICT_FRM_CONSISTENT==0 if data
+ dictionary information and
+ MySQL FRM information mismatch. */
#ifndef UNIV_HOTBACKUP
hash_node_t name_hash; /*!< hash chain node */
hash_node_t id_hash; /*!< hash chain node */
diff --git a/storage/xtradb/include/ha_prototypes.h b/storage/xtradb/include/ha_prototypes.h
index a9c003d5bb1..212a47a7a9b 100644
--- a/storage/xtradb/include/ha_prototypes.h
+++ b/storage/xtradb/include/ha_prototypes.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2006, 2014, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2006, 2015, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -356,6 +356,15 @@ thd_supports_xa(
THD* thd); /*!< in: thread handle, or NULL to query
the global innodb_supports_xa */
+/** Get status of innodb_tmpdir.
+@param[in] thd thread handle, or NULL to query
+ the global innodb_tmpdir.
+@retval NULL if innodb_tmpdir="" */
+UNIV_INTERN
+const char*
+thd_innodb_tmpdir(
+ THD* thd);
+
/******************************************************************//**
Check the status of fake changes mode (innodb_fake_changes)
@return true if fake change mode is enabled. */
diff --git a/storage/xtradb/include/os0file.h b/storage/xtradb/include/os0file.h
index c15d896caa6..c890f96b0e1 100644
--- a/storage/xtradb/include/os0file.h
+++ b/storage/xtradb/include/os0file.h
@@ -457,14 +457,19 @@ UNIV_INTERN
void
os_io_init_simple(void);
/*===================*/
-/***********************************************************************//**
-Creates a temporary file. This function is like tmpfile(3), but
-the temporary file is created in the MySQL temporary directory.
-@return temporary file handle, or NULL on error */
+
+/** Create a temporary file. This function is like tmpfile(3), but
+the temporary file is created in the given parameter path. If the path
+is null then it will create the file in the mysql server configuration
+parameter (--tmpdir).
+@param[in] path location for creating temporary file
+@return temporary file handle, or NULL on error */
+UNIV_INTERN
FILE*
-os_file_create_tmpfile(void);
-/*========================*/
+os_file_create_tmpfile(
+ const char* path);
+
#endif /* !UNIV_HOTBACKUP */
/***********************************************************************//**
The os_file_opendir() function opens a directory stream corresponding to the
@@ -1314,14 +1319,14 @@ os_file_get_status(
file can be opened in RW mode */
#if !defined(UNIV_HOTBACKUP)
-/*********************************************************************//**
-Creates a temporary file that will be deleted on close.
-This function is defined in ha_innodb.cc.
-@return temporary file descriptor, or < 0 on error */
+/** Create a temporary file in the location specified by the parameter
+path. If the path is null, then it will be created in tmpdir.
+@param[in] path location for creating temporary file
+@return temporary file descriptor, or < 0 on error */
UNIV_INTERN
int
-innobase_mysql_tmpfile(void);
-/*========================*/
+innobase_mysql_tmpfile(
+ const char* path);
#endif /* !UNIV_HOTBACKUP */
diff --git a/storage/xtradb/include/row0log.h b/storage/xtradb/include/row0log.h
index f105838eece..e127504c484 100644
--- a/storage/xtradb/include/row0log.h
+++ b/storage/xtradb/include/row0log.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2011, 2014, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2011, 2015, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -55,8 +55,9 @@ row_log_allocate(
const dtuple_t* add_cols,
/*!< in: default values of
added columns, or NULL */
- const ulint* col_map)/*!< in: mapping of old column
+ const ulint* col_map,/*!< in: mapping of old column
numbers to new ones, or NULL if !table */
+ const char* path) /*!< in: where to create temporary file */
__attribute__((nonnull(1), warn_unused_result));
/******************************************************//**
diff --git a/storage/xtradb/include/row0merge.h b/storage/xtradb/include/row0merge.h
index 3e3459b8703..53164b5197f 100644
--- a/storage/xtradb/include/row0merge.h
+++ b/storage/xtradb/include/row0merge.h
@@ -1,7 +1,7 @@
/*****************************************************************************
-Copyright (c) 2005, 2014, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2015, MariaDB Corporation.
+Copyright (c) 2005, 2015, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2015, 2016, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -187,14 +187,14 @@ void
row_merge_drop_temp_indexes(void);
/*=============================*/
-/*********************************************************************//**
-Creates temporary merge files, and if UNIV_PFS_IO defined, register
-the file descriptor with Performance Schema.
+/** Create temporary merge files in the given paramater path, and if
+UNIV_PFS_IO defined, register the file descriptor with Performance Schema.
+@param[in] path location for creating temporary merge files.
@return File descriptor */
UNIV_INTERN
int
-row_merge_file_create_low(void)
-/*===========================*/
+row_merge_file_create_low(
+ const char* path)
__attribute__((warn_unused_result));
/*********************************************************************//**
Destroy a merge file. And de-register the file from Performance Schema
@@ -372,15 +372,17 @@ row_merge_buf_empty(
/*================*/
row_merge_buf_t* buf) /*!< in,own: sort buffer */
__attribute__((warn_unused_result, nonnull));
-/*********************************************************************//**
-Create a merge file.
+
+/** Create a merge file in the given location.
+@param[out] merge_file merge file structure
+@param[in] path location for creating temporary file
@return file descriptor, or -1 on failure */
UNIV_INTERN
int
row_merge_file_create(
-/*==================*/
- merge_file_t* merge_file) /*!< out: merge file structure */
- __attribute__((nonnull));
+ merge_file_t* merge_file,
+ const char* path);
+
/*********************************************************************//**
Merge disk files.
@return DB_SUCCESS or error code */
diff --git a/storage/xtradb/include/univ.i b/storage/xtradb/include/univ.i
index f4a0da12476..b0fe3f020d2 100644
--- a/storage/xtradb/include/univ.i
+++ b/storage/xtradb/include/univ.i
@@ -45,10 +45,10 @@ Created 1/20/1994 Heikki Tuuri
#define INNODB_VERSION_MAJOR 5
#define INNODB_VERSION_MINOR 6
-#define INNODB_VERSION_BUGFIX 28
+#define INNODB_VERSION_BUGFIX 29
#ifndef PERCONA_INNODB_VERSION
-#define PERCONA_INNODB_VERSION 76.1
+#define PERCONA_INNODB_VERSION 76.2
#endif
/* Enable UNIV_LOG_ARCHIVE in XtraDB */
diff --git a/storage/xtradb/lock/lock0lock.cc b/storage/xtradb/lock/lock0lock.cc
index c3044daafad..7364c10c08e 100644
--- a/storage/xtradb/lock/lock0lock.cc
+++ b/storage/xtradb/lock/lock0lock.cc
@@ -639,7 +639,7 @@ lock_sys_create(
lock_sys->rec_num = 0;
if (!srv_read_only_mode) {
- lock_latest_err_file = os_file_create_tmpfile();
+ lock_latest_err_file = os_file_create_tmpfile(NULL);
ut_a(lock_latest_err_file);
}
}
diff --git a/storage/xtradb/os/os0file.cc b/storage/xtradb/os/os0file.cc
index 2bb094e115d..4010ef10359 100644
--- a/storage/xtradb/os/os0file.cc
+++ b/storage/xtradb/os/os0file.cc
@@ -991,19 +991,21 @@ os_io_init_simple(void)
#endif
}
-/***********************************************************************//**
-Creates a temporary file. This function is like tmpfile(3), but
-the temporary file is created in the MySQL temporary directory.
-@return temporary file handle, or NULL on error */
+/** Create a temporary file. This function is like tmpfile(3), but
+the temporary file is created in the given parameter path. If the path
+is null then it will create the file in the mysql server configuration
+parameter (--tmpdir).
+@param[in] path location for creating temporary file
+@return temporary file handle, or NULL on error */
UNIV_INTERN
FILE*
-os_file_create_tmpfile(void)
-/*========================*/
+os_file_create_tmpfile(
+ const char* path)
{
- FILE* file = NULL;
- int fd;
WAIT_ALLOW_WRITES();
- fd = innobase_mysql_tmpfile();
+
+ FILE* file = NULL;
+ int fd = innobase_mysql_tmpfile(path);
ut_ad(!srv_read_only_mode);
@@ -4067,7 +4069,7 @@ os_aio_native_aio_supported(void)
return(FALSE);
} else if (!srv_read_only_mode) {
/* Now check if tmpdir supports native aio ops. */
- fd = innobase_mysql_tmpfile();
+ fd = innobase_mysql_tmpfile(NULL);
if (fd < 0) {
ib_logf(IB_LOG_LEVEL_WARN,
diff --git a/storage/xtradb/row/row0ftsort.cc b/storage/xtradb/row/row0ftsort.cc
index c7a5b51ef55..ac0dc844b1b 100644
--- a/storage/xtradb/row/row0ftsort.cc
+++ b/storage/xtradb/row/row0ftsort.cc
@@ -1,7 +1,7 @@
/*****************************************************************************
-Copyright (c) 2010, 2014, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2015, MariaDB Corporation.
+Copyright (c) 2010, 2015, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2015, 2016, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -240,6 +240,9 @@ row_fts_psort_info_init(
crypt_data = NULL;
}
+ ut_ad(trx->mysql_thd != NULL);
+ const char* path = thd_innodb_tmpdir(trx->mysql_thd);
+
/* There will be FTS_NUM_AUX_INDEX number of "sort buckets" for
each parallel sort thread. Each "sort bucket" holds records for
a particular "FTS index partition" */
@@ -261,8 +264,8 @@ row_fts_psort_info_init(
psort_info[j].merge_buf[i] = row_merge_buf_create(
dup->index);
- if (row_merge_file_create(psort_info[j].merge_file[i])
- < 0) {
+ if (row_merge_file_create(psort_info[j].merge_file[i],
+ path) < 0) {
goto func_exit;
}
@@ -662,6 +665,11 @@ fts_parallel_tokenization(
dberr_t error = DB_SUCCESS;
fil_space_crypt_t* crypt_data = NULL;
+ ut_ad(psort_info->psort_common->trx->mysql_thd != NULL);
+
+ const char* path = thd_innodb_tmpdir(
+ psort_info->psort_common->trx->mysql_thd);
+
ut_ad(psort_info);
buf = psort_info->merge_buf;
@@ -905,7 +913,7 @@ exit:
continue;
}
- tmpfd[i] = row_merge_file_create_low();
+ tmpfd[i] = row_merge_file_create_low(path);
if (tmpfd[i] < 0) {
error = DB_OUT_OF_MEMORY;
goto func_exit;
diff --git a/storage/xtradb/row/row0log.cc b/storage/xtradb/row/row0log.cc
index b0c6f881f81..f0b200459dd 100644
--- a/storage/xtradb/row/row0log.cc
+++ b/storage/xtradb/row/row0log.cc
@@ -198,8 +198,25 @@ struct row_log_t {
or by index->lock X-latch only */
row_log_buf_t head; /*!< reader context; protected by MDL only;
modifiable by row_log_apply_ops() */
+ const char* path; /*!< where to create temporary file during
+ log operation */
};
+/** Create the file or online log if it does not exist.
+@param[in,out] log online rebuild log
+@return file descriptor. */
+static __attribute__((warn_unused_result))
+int
+row_log_tmpfile(
+ row_log_t* log)
+{
+ DBUG_ENTER("row_log_tmpfile");
+ if (log->fd < 0) {
+ log->fd = row_merge_file_create_low(log->path);
+ }
+
+ DBUG_RETURN(log->fd);
+}
/** Allocate the memory for the log buffer.
@param[in,out] log_buf Buffer used for log operation
@@ -344,6 +361,12 @@ row_log_online_op(
log->tail.buf, avail_size);
}
UNIV_MEM_ASSERT_RW(log->tail.block, srv_sort_buf_size);
+
+ if (row_log_tmpfile(log) < 0) {
+ log->error = DB_OUT_OF_MEMORY;
+ goto err_exit;
+ }
+
ret = os_file_write(
"(modification log)",
OS_FILE_FROM_FD(log->fd),
@@ -454,6 +477,12 @@ row_log_table_close_func(
log->tail.buf, avail);
}
UNIV_MEM_ASSERT_RW(log->tail.block, srv_sort_buf_size);
+
+ if (row_log_tmpfile(log) < 0) {
+ log->error = DB_OUT_OF_MEMORY;
+ goto err_exit;
+ }
+
ret = os_file_write(
"(modification log)",
OS_FILE_FROM_FD(log->fd),
@@ -473,6 +502,7 @@ write_failed:
log->tail.total += size;
UNIV_MEM_INVALID(log->tail.buf, sizeof log->tail.buf);
+err_exit:
mutex_exit(&log->mutex);
os_atomic_increment_ulint(&onlineddl_rowlog_rows, 1);
@@ -2544,7 +2574,8 @@ corruption:
if (index->online_log->head.blocks) {
#ifdef HAVE_FTRUNCATE
/* Truncate the file in order to save space. */
- if (ftruncate(index->online_log->fd, 0) == -1) {
+ if (index->online_log->fd != -1
+ && ftruncate(index->online_log->fd, 0) == -1) {
perror("ftruncate");
}
#endif /* HAVE_FTRUNCATE */
@@ -2860,8 +2891,9 @@ row_log_allocate(
const dtuple_t* add_cols,
/*!< in: default values of
added columns, or NULL */
- const ulint* col_map)/*!< in: mapping of old column
+ const ulint* col_map,/*!< in: mapping of old column
numbers to new ones, or NULL if !table */
+ const char* path) /*!< in: where to create temporary file */
{
row_log_t* log;
DBUG_ENTER("row_log_allocate");
@@ -2880,11 +2912,7 @@ row_log_allocate(
DBUG_RETURN(false);
}
- log->fd = row_merge_file_create_low();
- if (log->fd < 0) {
- ut_free(log);
- DBUG_RETURN(false);
- }
+ log->fd = -1;
mutex_create(index_online_log_key, &log->mutex,
SYNC_INDEX_ONLINE_LOG);
log->blobs = NULL;
@@ -2899,6 +2927,7 @@ row_log_allocate(
log->tail.block = log->head.block = NULL;
log->head.blocks = log->head.bytes = 0;
log->head.total = 0;
+ log->path = path;
dict_index_set_online_status(index, ONLINE_INDEX_CREATION);
index->online_log = log;
@@ -3376,7 +3405,8 @@ corruption:
if (index->online_log->head.blocks) {
#ifdef HAVE_FTRUNCATE
/* Truncate the file in order to save space. */
- if (ftruncate(index->online_log->fd, 0) == -1) {
+ if (index->online_log->fd != -1
+ && ftruncate(index->online_log->fd, 0) == -1) {
perror("ftruncate");
}
#endif /* HAVE_FTRUNCATE */
diff --git a/storage/xtradb/row/row0merge.cc b/storage/xtradb/row/row0merge.cc
index 8d7fcd7388c..b45c7f2171b 100644
--- a/storage/xtradb/row/row0merge.cc
+++ b/storage/xtradb/row/row0merge.cc
@@ -1389,47 +1389,95 @@ row_merge_write_eof(
return(&block[0]);
}
-/********************************************************************//**
-Reads clustered index of the table and create temporary files
+/** Create a temporary file if it has not been created already.
+@param[in,out] tmpfd temporary file handle
+@param[in] path path to create temporary file
+@return file descriptor, or -1 on failure */
+static __attribute__((warn_unused_result))
+int
+row_merge_tmpfile_if_needed(
+ int* tmpfd,
+ const char* path)
+{
+ if (*tmpfd < 0) {
+ *tmpfd = row_merge_file_create_low(path);
+ }
+
+ return(*tmpfd);
+}
+
+/** Create a temporary file for merge sort if it was not created already.
+@param[in,out] file merge file structure
+@param[in,out] tmpfd temporary file structure
+@param[in] nrec number of records in the file
+@param[in] path path to create temporary files
+@return file descriptor, or -1 on failure */
+static __attribute__((warn_unused_result))
+int
+row_merge_file_create_if_needed(
+ merge_file_t* file,
+ int* tmpfd,
+ ulint nrec,
+ const char* path)
+{
+ ut_ad(file->fd < 0 || *tmpfd >=0);
+ if (file->fd < 0 && row_merge_file_create(file, path) >= 0) {
+ if (row_merge_tmpfile_if_needed(tmpfd, path) < 0) {
+ return(-1);
+ }
+
+ file->n_rec = nrec;
+ }
+
+ ut_ad(file->fd < 0 || *tmpfd >=0);
+ return(file->fd);
+}
+
+/** Reads clustered index of the table and create temporary files
containing the index entries for the indexes to be built.
-@return DB_SUCCESS or error */
+@param[in] trx transaction
+@param[in,out] table MySQL table object, for reporting erroneous
+ records
+@param[in] old_table table where rows are read from
+@param[in] new_table table where indexes are created; identical to
+ old_table unless creating a PRIMARY KEY
+@param[in] online true if creating indexes online
+@param[in] index indexes to be created
+@param[in] fts_sort_idx full-text index to be created, or NULL
+@param[in] psort_info parallel sort info for fts_sort_idx creation,
+ or NULL
+@param[in] files temporary files
+@param[in] key_numbers MySQL key numbers to create
+@param[in] n_index number of indexes to create
+@param[in] add_cols default values of added columns, or NULL
+@param[in] col_map mapping of old column numbers to new ones, or
+ NULL if old_table == new_table
+@param[in] add_autoinc number of added AUTO_INCREMENT columns, or
+ ULINT_UNDEFINED if none is added
+@param[in,out] sequence autoinc sequence
+@param[in,out] block file buffer
+@param[in,out] tmpfd temporary file handle
+return DB_SUCCESS or error */
static __attribute__((nonnull(1,2,3,4,6,9,10,16), warn_unused_result))
dberr_t
row_merge_read_clustered_index(
-/*===========================*/
- trx_t* trx, /*!< in: transaction */
- struct TABLE* table, /*!< in/out: MySQL table object,
- for reporting erroneous records */
- const dict_table_t* old_table,/*!< in: table where rows are
- read from */
- const dict_table_t* new_table,/*!< in: table where indexes are
- created; identical to old_table
- unless creating a PRIMARY KEY */
- bool online, /*!< in: true if creating indexes
- online */
- dict_index_t** index, /*!< in: indexes to be created */
+ trx_t* trx,
+ struct TABLE* table,
+ const dict_table_t* old_table,
+ const dict_table_t* new_table,
+ bool online,
+ dict_index_t** index,
dict_index_t* fts_sort_idx,
- /*!< in: full-text index to be created,
- or NULL */
fts_psort_t* psort_info,
- /*!< in: parallel sort info for
- fts_sort_idx creation, or NULL */
- merge_file_t* files, /*!< in: temporary files */
+ merge_file_t* files,
const ulint* key_numbers,
- /*!< in: MySQL key numbers to create */
- ulint n_index,/*!< in: number of indexes to create */
+ ulint n_index,
const dtuple_t* add_cols,
- /*!< in: default values of
- added columns, or NULL */
- const ulint* col_map,/*!< in: mapping of old column
- numbers to new ones, or NULL
- if old_table == new_table */
+ const ulint* col_map,
ulint add_autoinc,
- /*!< in: number of added
- AUTO_INCREMENT column, or
- ULINT_UNDEFINED if none is added */
- ib_sequence_t& sequence,/*!< in/out: autoinc sequence */
- row_merge_block_t* block, /*!< in/out: file buffer */
+ ib_sequence_t& sequence,
+ row_merge_block_t* block,
+ int* tmpfd,
float pct_cost, /*!< in: percent of task weight
out of total alter job */
fil_space_crypt_t* crypt_data,/*!< in: crypt data or NULL */
@@ -1477,6 +1525,9 @@ row_merge_read_clustered_index(
DEBUG_FTS_SORT_PRINT("FTS_SORT: Start Create Index\n");
#endif
+ ut_ad(trx->mysql_thd != NULL);
+ const char* path = thd_innodb_tmpdir(trx->mysql_thd);
+
/* Create and initialize memory for record buffers */
merge_buf = static_cast<row_merge_buf_t**>(
@@ -1954,13 +2005,26 @@ write_buffers:
dict_index_get_lock(buf->index));
}
- row_merge_buf_write(buf, file, block);
+ if (buf->n_tuples > 0) {
- if (!row_merge_write(file->fd, file->offset++, block,
- crypt_data, crypt_block, new_table->space)) {
- err = DB_TEMP_FILE_WRITE_FAILURE;
- trx->error_key_num = i;
- break;
+ if (row_merge_file_create_if_needed(
+ file, tmpfd, buf->n_tuples, path) < 0) {
+ err = DB_OUT_OF_MEMORY;
+ trx->error_key_num = i;
+ break;
+ }
+
+ ut_ad(file->n_rec > 0);
+
+ row_merge_buf_write(buf, file, block);
+
+ if (!row_merge_write(file->fd, file->offset++,
+ block, crypt_data, crypt_block,
+ new_table->space)) {
+ err = DB_TEMP_FILE_WRITE_FAILURE;
+ trx->error_key_num = i;
+ break;
+ }
}
UNIV_MEM_INVALID(&block[0], srv_sort_buf_size);
@@ -2016,6 +2080,7 @@ write_buffers:
func_exit:
mtr_commit(&mtr);
+
mem_heap_free(row_heap);
if (nonnull) {
@@ -3344,14 +3409,15 @@ row_merge_drop_temp_indexes(void)
trx_free_for_background(trx);
}
-/*********************************************************************//**
-Creates temporary merge files, and if UNIV_PFS_IO defined, register
-the file descriptor with Performance Schema.
-@return file descriptor, or -1 on failure */
+
+/** Create temporary merge files in the given paramater path, and if
+UNIV_PFS_IO defined, register the file descriptor with Performance Schema.
+@param[in] path location for creating temporary merge files.
+@return File descriptor */
UNIV_INTERN
int
-row_merge_file_create_low(void)
-/*===========================*/
+row_merge_file_create_low(
+ const char* path)
{
int fd;
#ifdef UNIV_PFS_IO
@@ -3365,7 +3431,7 @@ row_merge_file_create_low(void)
"Innodb Merge Temp File",
__FILE__, __LINE__);
#endif
- fd = innobase_mysql_tmpfile();
+ fd = innobase_mysql_tmpfile(path);
#ifdef UNIV_PFS_IO
register_pfs_file_open_end(locker, fd);
#endif
@@ -3378,16 +3444,18 @@ row_merge_file_create_low(void)
return(fd);
}
-/*********************************************************************//**
-Create a merge file.
+
+/** Create a merge file in the given location.
+@param[out] merge_file merge file structure
+@param[in] path location for creating temporary file
@return file descriptor, or -1 on failure */
UNIV_INTERN
int
row_merge_file_create(
-/*==================*/
- merge_file_t* merge_file) /*!< out: merge file structure */
+ merge_file_t* merge_file,
+ const char* path)
{
- merge_file->fd = row_merge_file_create_low();
+ merge_file->fd = row_merge_file_create_low(path);
merge_file->offset = 0;
merge_file->n_rec = 0;
@@ -3958,10 +4026,6 @@ row_merge_build_indexes(
total_dynamic_cost = COST_BUILD_INDEX_DYNAMIC * n_indexes;
for (i = 0; i < n_indexes; i++) {
- if (row_merge_file_create(&merge_files[i]) < 0) {
- error = DB_OUT_OF_MEMORY;
- goto func_exit;
- }
if (indexes[i]->type & DICT_FTS) {
ibool opt_doc_id_size = FALSE;
@@ -3990,13 +4054,6 @@ row_merge_build_indexes(
}
}
- tmpfd = row_merge_file_create_low();
-
- if (tmpfd < 0) {
- error = DB_OUT_OF_MEMORY;
- goto func_exit;
- }
-
/* Reset the MySQL row buffer that is used when reporting
duplicate keys. */
innobase_rec_reset(table);
@@ -4025,7 +4082,7 @@ row_merge_build_indexes(
trx, table, old_table, new_table, online, indexes,
fts_sort_idx, psort_info, merge_files, key_numbers,
n_indexes, add_cols, col_map,
- add_autoinc, sequence, block, pct_cost,
+ add_autoinc, sequence, block, &tmpfd, pct_cost,
crypt_data, crypt_block);
pct_progress += pct_cost;
@@ -4119,7 +4176,7 @@ wait_again:
#ifdef FTS_INTERNAL_DIAG_PRINT
DEBUG_FTS_SORT_PRINT("FTS_SORT: Complete Insert\n");
#endif
- } else if (UNIV_LIKELY(merge_files[i].n_rec)) {
+ } else if (merge_files[i].fd != -1) {
char buf[3 * NAME_LEN];
char *bufend;
row_merge_dup_t dup = {
diff --git a/storage/xtradb/srv/srv0srv.cc b/storage/xtradb/srv/srv0srv.cc
index 794b119a090..c98bfc85086 100644
--- a/storage/xtradb/srv/srv0srv.cc
+++ b/storage/xtradb/srv/srv0srv.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1995, 2015, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2008, 2009 Google Inc.
Copyright (c) 2009, Percona Inc.
Copyright (c) 2013, 2014, SkySQL Ab. All Rights Reserved.
@@ -2243,6 +2243,8 @@ exit_func:
/*********************************************************************//**
A thread which prints warnings about semaphore waits which have lasted
too long. These can be used to track bugs which cause hangs.
+Note: In order to make sync_arr_wake_threads_if_sema_free work as expected,
+we should avoid waiting any mutexes in this function!
@return a dummy parameter */
extern "C" UNIV_INTERN
os_thread_ret_t
@@ -2282,23 +2284,21 @@ loop:
/* Try to track a strange bug reported by Harald Fuchs and others,
where the lsn seems to decrease at times */
- /* We have to use nowait to ensure we don't block */
- new_lsn= log_get_lsn_nowait();
-
- if (new_lsn && new_lsn < old_lsn) {
- ut_print_timestamp(stderr);
- fprintf(stderr,
- " InnoDB: Error: old log sequence number " LSN_PF
- " was greater\n"
- "InnoDB: than the new log sequence number " LSN_PF "!\n"
- "InnoDB: Please submit a bug report"
- " to http://bugs.mysql.com\n",
- old_lsn, new_lsn);
- ut_ad(0);
- }
+ if (log_peek_lsn(&new_lsn)) {
+ if (new_lsn < old_lsn) {
+ ut_print_timestamp(stderr);
+ fprintf(stderr,
+ " InnoDB: Error: old log sequence number " LSN_PF
+ " was greater\n"
+ "InnoDB: than the new log sequence number " LSN_PF "!\n"
+ "InnoDB: Please submit a bug report"
+ " to http://bugs.mysql.com\n",
+ old_lsn, new_lsn);
+ ut_ad(0);
+ }
- if (new_lsn)
old_lsn = new_lsn;
+ }
if (difftime(time(NULL), srv_last_monitor_time) > 60) {
/* We referesh InnoDB Monitor values so that averages are
diff --git a/storage/xtradb/srv/srv0start.cc b/storage/xtradb/srv/srv0start.cc
index 17f9e53e76f..2455dc1c9a9 100644
--- a/storage/xtradb/srv/srv0start.cc
+++ b/storage/xtradb/srv/srv0start.cc
@@ -2000,7 +2000,7 @@ innobase_start_or_create_for_mysql(void)
}
} else {
srv_monitor_file_name = NULL;
- srv_monitor_file = os_file_create_tmpfile();
+ srv_monitor_file = os_file_create_tmpfile(NULL);
if (!srv_monitor_file) {
return(DB_ERROR);
@@ -2010,7 +2010,7 @@ innobase_start_or_create_for_mysql(void)
mutex_create(srv_dict_tmpfile_mutex_key,
&srv_dict_tmpfile_mutex, SYNC_DICT_OPERATION);
- srv_dict_tmpfile = os_file_create_tmpfile();
+ srv_dict_tmpfile = os_file_create_tmpfile(NULL);
if (!srv_dict_tmpfile) {
return(DB_ERROR);
@@ -2019,7 +2019,7 @@ innobase_start_or_create_for_mysql(void)
mutex_create(srv_misc_tmpfile_mutex_key,
&srv_misc_tmpfile_mutex, SYNC_ANY_LATCH);
- srv_misc_tmpfile = os_file_create_tmpfile();
+ srv_misc_tmpfile = os_file_create_tmpfile(NULL);
if (!srv_misc_tmpfile) {
return(DB_ERROR);
diff --git a/support-files/compiler_warnings.supp b/support-files/compiler_warnings.supp
index 61c6b483aa9..68f1470b214 100644
--- a/support-files/compiler_warnings.supp
+++ b/support-files/compiler_warnings.supp
@@ -178,10 +178,10 @@ jemalloc/src/jemalloc\.c: set but not used
#
# Connect engine
#
-storage/connect/ha_connect\.cc: might be clobbered by ~longjmp~
-storage/connect/connect\.cc: might be clobbered by ~longjmp~
+storage/connect/ha_connect\.cc: might be clobbered by .*longjmp
+storage/connect/connect\.cc: might be clobbered by .*longjmp
storage/connect/filamvct\.cpp: ignoring return value of
-storage/connect/filamvct\.cpp: might be clobbered by
+storage/connect/filamvct\.cpp: might be clobbered by .*longjmp
storage/connect/xindex\.cpp: ignoring return value of
storage/connect/value\.cpp: always false
diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c
index bde146b2f21..62bf1a57d13 100644
--- a/tests/mysql_client_test.c
+++ b/tests/mysql_client_test.c
@@ -2142,7 +2142,7 @@ static void test_ps_conj_select()
"(2, 'hh', 'hh'), (1, 'ii', 'ii'), (2, 'ii', 'ii')");
myquery(rc);
- strmov(query, "select id1, value1 from t1 where id1= ? or "
+ strmov(query, "SELECT id1, value1 from t1 where id1= ? or "
"CONVERT(value1 USING utf8)= ?");
stmt= mysql_simple_prepare(mysql, query);
check_stmt(stmt);
@@ -2310,7 +2310,7 @@ static void test_ps_query_cache()
return;
}
- rc= mysql_query(mysql, "SET SQL_MODE=''");
+ rc= mysql_set_character_set(mysql, "utf8");
myquery(rc);
/* prepare the table */
@@ -2362,6 +2362,8 @@ static void test_ps_query_cache()
}
rc= mysql_query(lmysql, "SET SQL_MODE=''");
myquery(rc);
+ rc= mysql_set_character_set(lmysql, "utf8");
+ myquery(rc);
if (!opt_silent)
fprintf(stdout, "OK");
@@ -16709,7 +16711,7 @@ static void test_bug30472()
/* Switch client character set. */
- DIE_IF(mysql_set_character_set(&con, "utf8"));
+ DIE_IF(mysql_set_character_set(&con, "latin2"));
/* Retrieve character set information. */
@@ -16725,10 +16727,10 @@ static void test_bug30472()
2) new character set is different from the original one.
*/
- DIE_UNLESS(strcmp(character_set_name_2, "utf8") == 0);
- DIE_UNLESS(strcmp(character_set_client_2, "utf8") == 0);
- DIE_UNLESS(strcmp(character_set_results_2, "utf8") == 0);
- DIE_UNLESS(strcmp(collation_connnection_2, "utf8_general_ci") == 0);
+ DIE_UNLESS(strcmp(character_set_name_2, "latin2") == 0);
+ DIE_UNLESS(strcmp(character_set_client_2, "latin2") == 0);
+ DIE_UNLESS(strcmp(character_set_results_2, "latin2") == 0);
+ DIE_UNLESS(strcmp(collation_connnection_2, "latin2_general_ci") == 0);
DIE_UNLESS(strcmp(character_set_name_1, character_set_name_2) != 0);
DIE_UNLESS(strcmp(character_set_client_1, character_set_client_2) != 0);