From 700513a41a06b504a24020ab9e5216450f01e01f Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 12 Feb 2002 08:24:40 -0600 Subject: [PATCH 01/11] mysqldump.c: Changed C++ style comments to ANSI C style. client/mysqldump.c: Changed C++ style comments to ANSI C style. BitKeeper/etc/logging_ok: Logging to logging@openlogging.org accepted --- BitKeeper/etc/logging_ok | 1 + client/mysqldump.c | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok index e9dc3e56d39..58c1d7f91eb 100644 --- a/BitKeeper/etc/logging_ok +++ b/BitKeeper/etc/logging_ok @@ -9,3 +9,4 @@ miguel@light.local monty@donna.mysql.fi monty@bitch.mysql.fi mwagner@cash.mwagner.org +jorge@linux.jorge.mysql.com diff --git a/client/mysqldump.c b/client/mysqldump.c index 8020fa58304..b1d3195eba9 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -1192,7 +1192,7 @@ static void dumpTable(uint numFields, char *table) fputs(");\n", md_result_file); } - //XML - close table tag and supress regular output + /*XML - close table tag and supress regular output*/ if (opt_xml) fprintf(md_result_file, "\t\n", table); else if (extended_insert && row_break) @@ -1295,7 +1295,7 @@ static int dump_databases(char **db_names) int result=0; for ( ; *db_names ; db_names++) { - //XML edit - add database element + /*XML edit - add database element*/ if (opt_xml) fprintf(md_result_file, "<%s>\n", *db_names); if (dump_all_tables_in_db(*db_names)) From 67d8e882415c8c83a6179d5ab344a364fa3e9679 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 13 Feb 2002 17:49:21 +0200 Subject: [PATCH 02/11] Don't print out 'got signal' if not using --warnings --- sql/mysqld.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index a7c59dc3c7f..8b13ad4e526 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -683,8 +683,9 @@ pthread_handler_decl(kill_server_thread,arg __attribute__((unused))) static sig_handler print_signal_warning(int sig) { - sql_print_error("Warning: Got signal %d from thread %d", - sig,my_thread_id()); + if (opt_warnings) + sql_print_error("Warning: Got signal %d from thread %d", + sig,my_thread_id()); #ifdef DONT_REMEMBER_SIGNAL sigset(sig,print_signal_warning); /* int. thread system calls */ #endif From 33d2d76549f8ccf037f733c61e2b9c17500fe738 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 13 Feb 2002 21:53:26 +0200 Subject: [PATCH 03/11] Made LOAD DATA LOCAL INFILE more secure Docs/manual.texi: Changelog sql/sql_yacc.yy: optimization BitKeeper/etc/logging_ok: Logging to logging@openlogging.org accepted --- BitKeeper/etc/logging_ok | 1 + Docs/manual.texi | 6 ++++++ acconfig.h | 3 +++ client/client_priv.h | 2 +- client/mysql.cc | 13 +++++++++--- configure.in | 12 +++++++++-- include/mysql.h | 3 ++- libmysql/libmysql.c | 44 ++++++++++++++++++++++++++++++++-------- sql/mysql_priv.h | 2 +- sql/mysqld.cc | 7 ++++++- sql/sql_load.cc | 2 +- sql/sql_parse.cc | 9 +++++++- sql/sql_yacc.yy | 16 ++++++++------- 13 files changed, 93 insertions(+), 27 deletions(-) diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok index e9dc3e56d39..19a311081c8 100644 --- a/BitKeeper/etc/logging_ok +++ b/BitKeeper/etc/logging_ok @@ -9,3 +9,4 @@ miguel@light.local monty@donna.mysql.fi monty@bitch.mysql.fi mwagner@cash.mwagner.org +monty@tik.mysql.fi diff --git a/Docs/manual.texi b/Docs/manual.texi index a705340fe86..eb727cef882 100644 --- a/Docs/manual.texi +++ b/Docs/manual.texi @@ -46892,6 +46892,12 @@ not yet 100% confident in this code. @item Fixed unlikely caching bug when doing a join without keys. In this case the last used field for a table always returned @code{NULL}. +@item +Added options to make @code{LOAD DATA LOCAL INFILE} more secure. +@item +MySQL binary release 3.23.48 for Linux contained a new glibc library, which +has serious problems under high load and RedHat 7.2. The 3.23.49 binary +release doesn't have this problem. @end itemize @node News-3.23.48, News-3.23.47, News-3.23.49, News-3.23.x diff --git a/acconfig.h b/acconfig.h index be4461da7fd..3cea5bf4b73 100644 --- a/acconfig.h +++ b/acconfig.h @@ -21,6 +21,9 @@ /* Version of .frm files */ #undef DOT_FRM_VERSION +/* If LOAD DATA LOCAL INFILE should be enabled by default */ +#undef ENABLED_LOCAL_INFILE + /* READLINE: */ #undef FIONREAD_IN_SYS_IOCTL diff --git a/client/client_priv.h b/client/client_priv.h index 261367f7176..56eaf311070 100644 --- a/client/client_priv.h +++ b/client/client_priv.h @@ -30,4 +30,4 @@ enum options { OPT_CHARSETS_DIR=256, OPT_DEFAULT_CHARSET, OPT_LOW_PRIORITY, OPT_AUTO_REPAIR, OPT_COMPRESS, OPT_DROP, OPT_LOCKS, OPT_KEYWORDS, OPT_DELAYED, OPT_OPTIMIZE, OPT_FTB, OPT_LTB, OPT_ENC, OPT_O_ENC, OPT_ESC, OPT_TABLES, - OPT_MASTER_DATA, OPT_AUTOCOMMIT}; + OPT_MASTER_DATA, OPT_AUTOCOMMIT, OPT_LOCAL_INFILE}; diff --git a/client/mysql.cc b/client/mysql.cc index 5ae8df39863..cfe6d823cac 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -34,7 +34,7 @@ #include "my_readline.h" #include -const char *VER="11.15"; +const char *VER="11.16"; /* Don't try to make a nice table if the data is too big */ #define MAX_COLUMN_LENGTH 1024 @@ -113,10 +113,10 @@ static MYSQL mysql; /* The connection */ static bool info_flag=0,ignore_errors=0,wait_flag=0,quick=0, connected=0,opt_raw_data=0,unbuffered=0,output_tables=0, no_rehash=0,skip_updates=0,safe_updates=0,one_database=0, - opt_compress=0, + opt_compress=0, using_opt_local_infile=0, vertical=0,skip_line_numbers=0,skip_column_names=0,opt_html=0, opt_nopager=1, opt_outfile=0, no_named_cmds=1; -static uint verbose=0,opt_silent=0,opt_mysql_port=0; +static uint verbose=0,opt_silent=0,opt_mysql_port=0, opt_local_infile=0; static my_string opt_mysql_unix_port=0; static int connect_flag=CLIENT_INTERACTIVE; static char *current_host,*current_db,*current_user=0,*opt_password=0, @@ -394,6 +394,7 @@ static struct option long_options[] = {"html", no_argument, 0, 'H'}, {"host", required_argument, 0, 'h'}, {"ignore-spaces", no_argument, 0, 'i'}, + {"local-infile", optional_argument, 0, OPT_LOCAL_INFILE}, {"no-auto-rehash",no_argument, 0, 'A'}, {"no-named-commands", no_argument, 0, 'g'}, {"no-tee", no_argument, 0, OPT_NOTEE}, @@ -693,6 +694,10 @@ static int get_options(int argc, char **argv) case 'C': opt_compress=1; break; + case OPT_LOCAL_INFILE: + using_opt_local_infile=1; + opt_local_infile= test(!optarg || atoi(optarg)>0); + break; case 'L': skip_line_numbers=1; break; @@ -2105,6 +2110,8 @@ sql_real_connect(char *host,char *database,char *user,char *password, } if (opt_compress) mysql_options(&mysql,MYSQL_OPT_COMPRESS,NullS); + if (using_opt_local_infile) + mysql_options(&mysql,MYSQL_OPT_LOCAL_INFILE, (char*) &opt_local_infile); #ifdef HAVE_OPENSSL if (opt_use_ssl) mysql_ssl_set(&mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca, diff --git a/configure.in b/configure.in index 33d6443275d..f11e2354dfd 100644 --- a/configure.in +++ b/configure.in @@ -4,7 +4,7 @@ dnl Process this file with autoconf to produce a configure script. AC_INIT(sql/mysqld.cc) AC_CANONICAL_SYSTEM # The Docs Makefile.am parses this line! -AM_INIT_AUTOMAKE(mysql, 3.23.48) +AM_INIT_AUTOMAKE(mysql, 3.23.49) AM_CONFIG_HEADER(config.h) PROTOCOL_VERSION=10 @@ -518,7 +518,7 @@ AC_ARG_ENABLE(thread-safe-client, [ THREAD_SAFE_CLIENT=no ] ) -# Make thread safe client +# compile with strings functions in assembler AC_ARG_ENABLE(assembler, [ --enable-assembler Use assembler versions of some string functions if available.], @@ -583,6 +583,14 @@ AC_ARG_WITH(mysqld-user, ) AC_SUBST(MYSQLD_USER) +# compile with strings functions in assembler +AC_ARG_ENABLE(local-infile, + [ --enable-local-infile + If LOAD DATA LOCAL INFILE is enabled by default.], + [ ENABLED_LOCAL_INFILE=$enablewal ], + [ ENABLED_LOCAL_INFILE=no ] + ) + # Use Paul Eggerts macros from GNU tar to check for large file support. MYSQL_SYS_LARGEFILE diff --git a/include/mysql.h b/include/mysql.h index bd54be0bc22..0bd5b7092b8 100644 --- a/include/mysql.h +++ b/include/mysql.h @@ -143,7 +143,8 @@ struct st_mysql_options { enum mysql_option { MYSQL_OPT_CONNECT_TIMEOUT, MYSQL_OPT_COMPRESS, MYSQL_OPT_NAMED_PIPE, MYSQL_INIT_COMMAND, MYSQL_READ_DEFAULT_FILE, MYSQL_READ_DEFAULT_GROUP, - MYSQL_SET_CHARSET_DIR, MYSQL_SET_CHARSET_NAME}; + MYSQL_SET_CHARSET_DIR, MYSQL_SET_CHARSET_NAME, + MYSQL_OPT_LOCAL_INFILE}; enum mysql_status { MYSQL_STATUS_READY,MYSQL_STATUS_GET_RESULT, MYSQL_STATUS_USE_RESULT}; diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index 8a73f694e41..b632595bad9 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -61,7 +61,7 @@ static my_bool mysql_client_init=0; uint mysql_port=0; my_string mysql_unix_port=0; -#define CLIENT_CAPABILITIES (CLIENT_LONG_PASSWORD | CLIENT_LONG_FLAG | CLIENT_LOCAL_FILES | CLIENT_TRANSACTIONS) +#define CLIENT_CAPABILITIES (CLIENT_LONG_PASSWORD | CLIENT_LONG_FLAG | CLIENT_TRANSACTIONS) #ifdef __WIN__ #define CONNECT_TIMEOUT 20 @@ -671,11 +671,12 @@ mysql_free_result(MYSQL_RES *result) ****************************************************************************/ static const char *default_options[]= -{"port","socket","compress","password","pipe", "timeout", "user", - "init-command", "host", "database", "debug", "return-found-rows", - "ssl-key" ,"ssl-cert" ,"ssl-ca" ,"ssl-capath", - "character-set-dir", "default-character-set", "interactive-timeout", - "connect_timeout", +{ + "port","socket","compress","password","pipe", "timeout", "user", + "init-command", "host", "database", "debug", "return-found-rows", + "ssl-key" ,"ssl-cert" ,"ssl-ca" ,"ssl-capath", + "character-set-dir", "default-character-set", "interactive-timeout", + "connect-timeout", "local-infile", "disable-local-infile", NullS }; @@ -710,6 +711,9 @@ static void mysql_read_default_options(struct st_mysql_options *options, opt_arg=end+1; *end=0; /* Remove '=' */ } + /* Change all '_' in variable name to '-' */ + for (end= *option ; (end= strcend(end,'_')) ; ) + *end= '-'; switch (find_type(*option+2,&option_types,2)) { case 1: /* port */ if (opt_arg) @@ -807,7 +811,16 @@ static void mysql_read_default_options(struct st_mysql_options *options, options->charset_name = my_strdup(opt_arg, MYF(MY_WME)); break; case 19: /* Interactive-timeout */ - options->client_flag|=CLIENT_INTERACTIVE; + options->client_flag|= CLIENT_INTERACTIVE; + break; + case 21: + if (!opt_arg || atoi(opt_arg) != 0) + options->client_flag|= CLIENT_LOCAL_FILES; + else + options->client_flag&= ~CLIENT_LOCAL_FILES; + break; + case 22: + options->client_flag&= CLIENT_LOCAL_FILES; break; default: DBUG_PRINT("warning",("unknown option: %s",option[0])); @@ -1006,6 +1019,14 @@ mysql_init(MYSQL *mysql) if (!((mysql)->client_flag & CLIENT_IGNORE_SIGPIPE)) (void) signal(SIGPIPE,pipe_sig_handler); #endif + +/* + Only enable LOAD DATA INFILE by default if configured with + --with-enabled-local-inflile +*/ +#ifdef ENABLED_LOCAL_INFILE + mysql->options.client_flag|= CLIENT_LOCAL_FILES; +#endif return mysql; } @@ -1453,7 +1474,6 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, if (mysql->options.use_ssl) client_flag|=CLIENT_SSL; #endif /* HAVE_OPENSSL */ - if (db) client_flag|=CLIENT_CONNECT_WITH_DB; #ifdef HAVE_COMPRESS @@ -2267,11 +2287,17 @@ mysql_options(MYSQL *mysql,enum mysql_option option, const char *arg) mysql->options.connect_timeout= *(uint*) arg; break; case MYSQL_OPT_COMPRESS: - mysql->options.compress=1; /* Remember for connect */ + mysql->options.compress= 1; /* Remember for connect */ break; case MYSQL_OPT_NAMED_PIPE: mysql->options.named_pipe=1; /* Force named pipe */ break; + case MYSQL_OPT_LOCAL_INFILE: /* Allow LOAD DATA LOCAL ?*/ + if (!arg || test(*(uint*) arg)) + mysql->client_flag|= CLIENT_LOCAL_FILES; + else + mysql->client_flag&= ~CLIENT_LOCAL_FILES; + break; case MYSQL_INIT_COMMAND: my_free(mysql->options.init_command,MYF(MY_ALLOW_ZERO_PTR)); mysql->options.init_command=my_strdup(arg,MYF(MY_WME)); diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index a569fecfc9d..072cbf540af 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -524,7 +524,7 @@ extern pthread_cond_t COND_refresh,COND_thread_count, COND_binlog_update, COND_slave_stopped, COND_slave_start; extern pthread_attr_t connection_attrib; extern bool opt_endinfo, using_udf_functions, locked_in_memory, - opt_using_transactions, use_temp_pool; + opt_using_transactions, use_temp_pool, opt_local_infile; extern char f_fyllchar; extern ulong ha_read_count, ha_write_count, ha_delete_count, ha_update_count, ha_read_key_count, ha_read_next_count, ha_read_prev_count, diff --git a/sql/mysqld.cc b/sql/mysqld.cc index a7c59dc3c7f..72a8f74ee38 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -287,6 +287,7 @@ ulong bytes_sent = 0L, bytes_received = 0L; bool opt_endinfo,using_udf_functions,low_priority_updates, locked_in_memory; bool opt_using_transactions, using_update_log, opt_warnings=0; +bool opt_local_infile; bool volatile abort_loop,select_thread_in_use,grant_option; bool volatile ready_to_exit,shutdown_in_progress; ulong refresh_version=1L,flush_version=1L; /* Increments on each reload */ @@ -2612,7 +2613,7 @@ enum options { OPT_SKIP_STACK_TRACE, OPT_SKIP_SYMLINKS, OPT_MAX_BINLOG_DUMP_EVENTS, OPT_SPORADIC_BINLOG_DUMP_FAIL, OPT_SAFE_USER_CREATE, OPT_SQL_MODE, - OPT_SLAVE_SKIP_ERRORS + OPT_SLAVE_SKIP_ERRORS, OPT_LOCAL_INFILE }; static struct option long_options[] = { @@ -2676,6 +2677,7 @@ static struct option long_options[] = { {"init-file", required_argument, 0, (int) OPT_INIT_FILE}, {"log", optional_argument, 0, 'l'}, {"language", required_argument, 0, 'L'}, + {"local-infile", optional_argument, 0, (int) OPT_LOCAL_INFILE}, {"log-bin", optional_argument, 0, (int) OPT_BIN_LOG}, {"log-bin-index", required_argument, 0, (int) OPT_BIN_LOG_INDEX}, {"log-isam", optional_argument, 0, (int) OPT_ISAM_LOG}, @@ -3468,6 +3470,9 @@ static void get_options(int argc,char **argv) case 'P': mysql_port= (unsigned int) atoi(optarg); break; + case OPT_LOCAL_INFILE: + opt_local_infile= test(optarg || atoi(optarg) != 0); + break; case OPT_SLAVE_SKIP_ERRORS: init_slave_skip_errors(optarg); break; diff --git a/sql/sql_load.cc b/sql/sql_load.cc index 9d3b899d31b..dd8487ceecc 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -132,7 +132,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, if (read_file_from_client && handle_duplicates == DUP_ERROR) handle_duplicates=DUP_IGNORE; - if (read_file_from_client && (thd->client_capabilities & CLIENT_LOCAL_FILES)) + if (read_file_from_client) { char tmp [FN_REFLEN+1],*end; DBUG_PRINT("info",("reading local file")); diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 48b48dc77a7..9b439081d50 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1796,13 +1796,20 @@ mysql_execute_command(void) { uint privilege= (lex->duplicates == DUP_REPLACE ? INSERT_ACL | UPDATE_ACL | DELETE_ACL : INSERT_ACL); - if (!(lex->local_file && (thd->client_capabilities & CLIENT_LOCAL_FILES))) + + if (!lex->local_file) { if (check_access(thd,privilege | FILE_ACL,tables->db)) goto error; } else { + if (!(thd->client_capabilities & CLIENT_LOCAL_FILES) || + ! opt_local_infile) + { + send_error(&thd->net,ER_NOT_ALLOWED_COMMAND); + goto error; + } if (check_access(thd,privilege,tables->db,&tables->grant.privilege) || grant_option && check_grant(thd,privilege,tables)) goto error; diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 42872399dec..08fab22629a 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -2356,8 +2356,9 @@ use: USE_SYM ident load: LOAD DATA_SYM load_data_lock opt_local INFILE TEXT_STRING { - Lex->sql_command= SQLCOM_LOAD; - Lex->local_file= $4; + LEX *lex= Lex; + lex->sql_command= SQLCOM_LOAD; + lex->local_file= $4; if (!(Lex->exchange= new sql_exchange($6.str,0))) YYABORT; Lex->field_list.empty(); @@ -2643,11 +2644,12 @@ set: SET opt_option { THD *thd=current_thd; - Lex->sql_command= SQLCOM_SET_OPTION; - Lex->options=thd->options; - Lex->select_limit=thd->default_select_limit; - Lex->gemini_spin_retries=thd->gemini_spin_retries; - Lex->tx_isolation=thd->tx_isolation; + LEX *lex= &thd->lex; + lex->sql_command= SQLCOM_SET_OPTION; + lex->options=thd->options; + lex->select_limit=thd->default_select_limit; + lex->gemini_spin_retries=thd->gemini_spin_retries; + lex->tx_isolation=thd->tx_isolation; } option_value_list From a0ea16f1c25508100df3bf4afb390ce368b5b86f Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 13 Feb 2002 22:01:41 +0200 Subject: [PATCH 04/11] Fix for LOAD DATA LOCAL INFILE patch --- libmysql/libmysql.c | 4 ++-- sql/mysqld.cc | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index b632595bad9..c75bb0ad462 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -2294,9 +2294,9 @@ mysql_options(MYSQL *mysql,enum mysql_option option, const char *arg) break; case MYSQL_OPT_LOCAL_INFILE: /* Allow LOAD DATA LOCAL ?*/ if (!arg || test(*(uint*) arg)) - mysql->client_flag|= CLIENT_LOCAL_FILES; + mysql->options.client_flag|= CLIENT_LOCAL_FILES; else - mysql->client_flag&= ~CLIENT_LOCAL_FILES; + mysql->options.client_flag&= ~CLIENT_LOCAL_FILES; break; case MYSQL_INIT_COMMAND: my_free(mysql->options.init_command,MYF(MY_ALLOW_ZERO_PTR)); diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 9eb4e8cf967..09c05a6463f 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -287,7 +287,7 @@ ulong bytes_sent = 0L, bytes_received = 0L; bool opt_endinfo,using_udf_functions,low_priority_updates, locked_in_memory; bool opt_using_transactions, using_update_log, opt_warnings=0; -bool opt_local_infile; +bool opt_local_infile=1; bool volatile abort_loop,select_thread_in_use,grant_option; bool volatile ready_to_exit,shutdown_in_progress; ulong refresh_version=1L,flush_version=1L; /* Increments on each reload */ @@ -3472,7 +3472,7 @@ static void get_options(int argc,char **argv) mysql_port= (unsigned int) atoi(optarg); break; case OPT_LOCAL_INFILE: - opt_local_infile= test(optarg || atoi(optarg) != 0); + opt_local_infile= test(!optarg || atoi(optarg) != 0); break; case OPT_SLAVE_SKIP_ERRORS: init_slave_skip_errors(optarg); From 26b57d2a157a240a06b5e99181d7d314a1c61ad2 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 13 Feb 2002 22:01:43 +0200 Subject: [PATCH 05/11] Use NAMES_SEP_CHAR also for enums (Fix for supportwizard) sql/unireg.cc: Use NAMES_SEP_CHAR also for enums sql/unireg.h: cleanup --- sql/unireg.cc | 4 ++-- sql/unireg.h | 5 ----- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/sql/unireg.cc b/sql/unireg.cc index 0bfc462f01a..f7b040adebe 100644 --- a/sql/unireg.cc +++ b/sql/unireg.cc @@ -486,11 +486,11 @@ static bool pack_fields(File file,List &create_fields) if (field->interval_id > int_count) { int_count=field->interval_id; - tmp.append('\377'); + tmp.append(NAMES_SEP_CHAR); for (const char **pos=field->interval->type_names ; *pos ; pos++) { tmp.append(*pos); - tmp.append('\377'); + tmp.append(NAMES_SEP_CHAR); } tmp.append('\0'); // End of intervall } diff --git a/sql/unireg.h b/sql/unireg.h index 159832295fd..f8f5edd5156 100644 --- a/sql/unireg.h +++ b/sql/unireg.h @@ -70,11 +70,6 @@ #define FERR -1 /* Error from my_functions */ #define CREATE_MODE 0 /* Default mode on new files */ #define NAMES_SEP_CHAR '\377' /* Char to sep. names */ -#ifdef MSDOS -#define EXTRA_FIELD_CHAR (char) '\234' /* Interchangebly with '#' */ -#else -#define EXTRA_FIELD_CHAR '#' /* Interchangebly with '#' */ -#endif #define READ_RECORD_BUFFER (uint) (IO_SIZE*8) /* Pointer_buffer_size */ #define DISK_BUFFER_SIZE (uint) (IO_SIZE*16) /* Size of diskbuffer */ From 74e8b0a60dfebe216ec5782f331b32bbdbd4b798 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 14 Feb 2002 00:00:09 +0200 Subject: [PATCH 06/11] ha_innobase.cc: DROP DATABASE required that the database name is in lower case to work; put it always to lower case in innobase_drop_database sql/ha_innobase.cc: DROP DATABASE required that the database name is in lower case to work; put it always to lower case in innobase_drop_database BitKeeper/etc/logging_ok: Logging to logging@openlogging.org accepted --- BitKeeper/etc/logging_ok | 1 + sql/ha_innobase.cc | 13 +++++++++++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok index a520b05f376..03e5543a92f 100644 --- a/BitKeeper/etc/logging_ok +++ b/BitKeeper/etc/logging_ok @@ -11,3 +11,4 @@ mwagner@cash.mwagner.org paul@central.snake.net sasha@mysql.sashanet.com serg@serg.mysql.com +heikki@hundin.mysql.fi diff --git a/sql/ha_innobase.cc b/sql/ha_innobase.cc index 9a4dc070978..fe91a6f630c 100644 --- a/sql/ha_innobase.cc +++ b/sql/ha_innobase.cc @@ -85,7 +85,7 @@ long innobase_mirrored_log_groups, innobase_log_files_in_group, char *innobase_data_home_dir, *innobase_data_file_path; char *innobase_log_group_home_dir, *innobase_log_arch_dir; char *innobase_unix_file_flush_method; -my_bool innobase_flush_log_at_trx_commit, innobase_log_archive, +bool innobase_flush_log_at_trx_commit, innobase_log_archive, innobase_use_native_aio, innobase_fast_shutdown; /* innobase_data_file_path=ibdata:15,idata2:1,... */ @@ -2804,6 +2804,16 @@ innobase_drop_database( namebuf[len] = '/'; namebuf[len + 1] = '\0'; +#ifdef __WIN__ + /* Put to lower case */ + + ptr = namebuf; + + while (*ptr != '\0') { + *ptr = tolower(*ptr); + ptr++; + } +#endif trx = trx_allocate_for_mysql(); error = row_drop_database_for_mysql(namebuf, trx); @@ -2954,7 +2964,6 @@ ha_innobase::records_in_range( my_free((char*) key_val_buff2, MYF(0)); - DBUG_RETURN((ha_rows) n_rows); } From 01f1db421f3d8fca547500eff34feafe132d6332 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 14 Feb 2002 02:41:29 +0200 Subject: [PATCH 07/11] changed bool -> my_bool --- sql/ha_innobase.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/ha_innobase.cc b/sql/ha_innobase.cc index fe91a6f630c..cbc78bbd6fc 100644 --- a/sql/ha_innobase.cc +++ b/sql/ha_innobase.cc @@ -85,7 +85,7 @@ long innobase_mirrored_log_groups, innobase_log_files_in_group, char *innobase_data_home_dir, *innobase_data_file_path; char *innobase_log_group_home_dir, *innobase_log_arch_dir; char *innobase_unix_file_flush_method; -bool innobase_flush_log_at_trx_commit, innobase_log_archive, +my_bool innobase_flush_log_at_trx_commit, innobase_log_archive, innobase_use_native_aio, innobase_fast_shutdown; /* innobase_data_file_path=ibdata:15,idata2:1,... */ From 5c08b0fbabd600d54305462bf004845c2f5e7c68 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 14 Feb 2002 03:45:45 +0200 Subject: [PATCH 08/11] row0mysql.c, sql_db.cc: Try to make sure DROP DATABASE does not cause a deadlock because we now let InnoDB wait MySQL does not have open handles to tables we drop sql/sql_db.cc: Try to make sure DROP DATABASE does not cause a deadlock because we now let InnoDB wait MySQL does not have open handles to tables we drop innobase/row/row0mysql.c: Try to make sure DROP DATABASE does not cause a deadlock because we now let InnoDB wait MySQL does not have open handles to tables we drop --- innobase/row/row0mysql.c | 18 +++++++++++++++++- sql/sql_db.cc | 10 ++++++++-- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/innobase/row/row0mysql.c b/innobase/row/row0mysql.c index 7b036ca4e00..45c59ff2c38 100644 --- a/innobase/row/row0mysql.c +++ b/innobase/row/row0mysql.c @@ -1802,6 +1802,7 @@ row_drop_database_for_mysql( char* name, /* in: database name which ends to '/' */ trx_t* trx) /* in: transaction handle */ { + dict_table_t* table; char* table_name; int err = DB_SUCCESS; @@ -1812,12 +1813,27 @@ row_drop_database_for_mysql( trx->op_info = "dropping database"; trx_start_if_not_started(trx); - +loop: mutex_enter(&(dict_sys->mutex)); while (table_name = dict_get_first_table_name_in_db(name)) { ut_a(memcmp(table_name, name, strlen(name)) == 0); + table = dict_table_get_low(table_name); + + ut_a(table); + + /* Wait until MySQL does not have any queries running on + the table */ + + if (table->n_mysql_handles_opened > 0) { + mutex_exit(&(dict_sys->mutex)); + + os_thread_sleep(100000); + + goto loop; + } + err = row_drop_table_for_mysql(table_name, trx, TRUE); mem_free(table_name); diff --git a/sql/sql_db.cc b/sql/sql_db.cc index 358850dbd10..1e798a392b1 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -164,8 +164,6 @@ void mysql_rm_db(THD *thd,char *db,bool if_exists) } remove_db_from_cache(db); - ha_drop_database(path); - if ((deleted=mysql_rm_known_files(thd, dirp, path,0)) >= 0) { if (!thd->query) @@ -191,6 +189,14 @@ void mysql_rm_db(THD *thd,char *db,bool if_exists) exit: VOID(pthread_mutex_unlock(&LOCK_open)); VOID(pthread_mutex_unlock(&LOCK_mysql_create_db)); + + /* It seems MySQL may call this function when there still are queries + running on tables of the database. Since InnoDB waits until the + queries have ended, we have to call ha_drop_database outside + the above two mutexes to avoid deadlocks. */ + + ha_drop_database(path); + DBUG_VOID_RETURN; } From 199e17e577163252c0ba5ecec4f4a655e621ce00 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 14 Feb 2002 10:24:27 +0200 Subject: [PATCH 09/11] dict0dict.h, dict0dict.c, row0mysql.c, ha_innobase.cc: Add some more safety if MySQL tries to drop a table on which there are open handles sql/ha_innobase.cc: Add some more safety if MySQL tries to drop a table on which there are open handles innobase/row/row0mysql.c: Add some more safety if MySQL tries to drop a table on which there are open handles innobase/dict/dict0dict.c: Add some more safety if MySQL tries to drop a table on which there are open handles innobase/include/dict0dict.h: Add some more safety if MySQL tries to drop a table on which there are open handles --- innobase/dict/dict0dict.c | 50 +++++++++++++++++++++++++----------- innobase/include/dict0dict.h | 17 +++++++----- innobase/row/row0mysql.c | 22 ++++++++++++++-- sql/ha_innobase.cc | 5 +++- 4 files changed, 69 insertions(+), 25 deletions(-) diff --git a/innobase/dict/dict0dict.c b/innobase/dict/dict0dict.c index 95f9b54c914..56bdf83aa4d 100644 --- a/innobase/dict/dict0dict.c +++ b/innobase/dict/dict0dict.c @@ -195,21 +195,6 @@ dict_mutex_exit_for_mysql(void) mutex_exit(&(dict_sys->mutex)); } -/************************************************************************ -Increments the count of open MySQL handles to a table. */ - -void -dict_table_increment_handle_count( -/*==============================*/ - dict_table_t* table) /* in: table */ -{ - mutex_enter(&(dict_sys->mutex)); - - table->n_mysql_handles_opened++; - - mutex_exit(&(dict_sys->mutex)); -} - /************************************************************************ Decrements the count of open MySQL handles to a table. */ @@ -495,6 +480,41 @@ dict_table_get( return(table); } +/************************************************************************** +Returns a table object and increments MySQL open handle count on the table. +*/ + +dict_table_t* +dict_table_get_and_increment_handle_count( +/*======================================*/ + /* out: table, NULL if does not exist */ + char* table_name, /* in: table name */ + trx_t* trx) /* in: transaction handle or NULL */ +{ + dict_table_t* table; + + UT_NOT_USED(trx); + + mutex_enter(&(dict_sys->mutex)); + + table = dict_table_get_low(table_name); + + if (table != NULL) { + + table->n_mysql_handles_opened++; + } + + mutex_exit(&(dict_sys->mutex)); + + if (table != NULL) { + if (!table->stat_initialized) { + dict_update_statistics(table); + } + } + + return(table); +} + /************************************************************************** Adds a table object to the dictionary cache. */ diff --git a/innobase/include/dict0dict.h b/innobase/include/dict0dict.h index 79d67ecae15..0f6f516c2cb 100644 --- a/innobase/include/dict0dict.h +++ b/innobase/include/dict0dict.h @@ -26,13 +26,6 @@ Created 1/8/1996 Heikki Tuuri #include "ut0byte.h" #include "trx0types.h" -/************************************************************************ -Increments the count of open MySQL handles to a table. */ - -void -dict_table_increment_handle_count( -/*==============================*/ - dict_table_t* table); /* in: table */ /************************************************************************ Decrements the count of open MySQL handles to a table. */ @@ -195,6 +188,16 @@ dict_table_get( char* table_name, /* in: table name */ trx_t* trx); /* in: transaction handle */ /************************************************************************** +Returns a table object and increments MySQL open handle count on the table. +*/ + +dict_table_t* +dict_table_get_and_increment_handle_count( +/*======================================*/ + /* out: table, NULL if does not exist */ + char* table_name, /* in: table name */ + trx_t* trx); /* in: transaction handle or NULL */ +/************************************************************************** Returns a table object, based on table id, and memoryfixes it. */ dict_table_t* diff --git a/innobase/row/row0mysql.c b/innobase/row/row0mysql.c index 45c59ff2c38..8357ebe7b96 100644 --- a/innobase/row/row0mysql.c +++ b/innobase/row/row0mysql.c @@ -273,8 +273,6 @@ row_create_prebuilt( ulint ref_len; ulint i; - dict_table_increment_handle_count(table); - heap = mem_heap_create(128); prebuilt = mem_heap_alloc(heap, sizeof(row_prebuilt_t)); @@ -1466,6 +1464,13 @@ loop: table = dict_table_get_low(drop->table_name); mutex_exit(&(dict_sys->mutex)); + if (table == NULL) { + /* If for some reason the table has already been dropped + through some other mechanism, do not try to drop it */ + + goto already_dropped; + } + if (table->n_mysql_handles_opened > 0) { return(n_tables + n_tables_dropped); @@ -1475,10 +1480,16 @@ loop: row_drop_table_for_mysql_in_background(drop->table_name); +already_dropped: mutex_enter(&kernel_mutex); UT_LIST_REMOVE(row_mysql_drop_list, row_mysql_drop_list, drop); + ut_print_timestamp(stderr); + fprintf(stderr, + " InnoDB: Dropped table %s in background drop queue.\n", + drop->table_name); + mem_free(drop->table_name); mem_free(drop); @@ -1741,6 +1752,13 @@ row_drop_table_for_mysql( if (table->n_mysql_handles_opened > 0) { + ut_print_timestamp(stderr); + fprintf(stderr, + " InnoDB: Warning: MySQL is trying to drop table %s\n" + "InnoDB: though there are still open handles to it.\n" + "InnoDB: Adding the table to the background drop queue.\n", + table->name); + row_add_table_to_background_drop_list(table); err = DB_SUCCESS; diff --git a/sql/ha_innobase.cc b/sql/ha_innobase.cc index cbc78bbd6fc..2cdf15ce974 100644 --- a/sql/ha_innobase.cc +++ b/sql/ha_innobase.cc @@ -981,7 +981,10 @@ ha_innobase::open( /* Get pointer to a table object in InnoDB dictionary cache */ - if (NULL == (ib_table = dict_table_get(norm_name, NULL))) { + ib_table = dict_table_get_and_increment_handle_count( + norm_name, NULL); + + if (NULL == ib_table) { fprintf(stderr, "InnoDB: Error: cannot find table %s from the internal data dictionary\n" From ce81db2e0df94c6dbc27bb804cf453456cf3a67d Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 14 Feb 2002 11:30:14 +0200 Subject: [PATCH 10/11] row0mysql.c: Add a warning to drop database wait if there are still open handles on a table innobase/row/row0mysql.c: Add a warning to drop database wait if there are still open handles on a table --- innobase/row/row0mysql.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/innobase/row/row0mysql.c b/innobase/row/row0mysql.c index 8357ebe7b96..c4a844b3fa9 100644 --- a/innobase/row/row0mysql.c +++ b/innobase/row/row0mysql.c @@ -1847,7 +1847,15 @@ loop: if (table->n_mysql_handles_opened > 0) { mutex_exit(&(dict_sys->mutex)); - os_thread_sleep(100000); + ut_print_timestamp(stderr); + fprintf(stderr, + " InnoDB: Warning: MySQL is trying to drop database %s\n" + "InnoDB: though there are still open handles to table %s.\n", + name, table_name); + + os_thread_sleep(1000000); + + mem_free(table_name); goto loop; } From 48664555589674457880e1b202c0339ea3b15180 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 14 Feb 2002 15:04:14 +0200 Subject: [PATCH 11/11] Don't give warnings for empty statements with comments --- Docs/manual.texi | 3 +++ mysql-test/t/comments.test | 3 ++- sql/mysql_priv.h | 3 ++- sql/sql_lex.cc | 2 ++ sql/sql_lex.h | 2 +- sql/sql_parse.cc | 4 ++++ sql/sql_yacc.yy | 12 ++++++++++-- 7 files changed, 24 insertions(+), 5 deletions(-) diff --git a/Docs/manual.texi b/Docs/manual.texi index eb727cef882..a93d5b2194b 100644 --- a/Docs/manual.texi +++ b/Docs/manual.texi @@ -46890,6 +46890,9 @@ not yet 100% confident in this code. @appendixsubsec Changes in release 3.23.49 @itemize @bullet @item +Don't give warning for statement that is only a comment; This is needed for +@code{mysqldump --disable-keys} to work. +@item Fixed unlikely caching bug when doing a join without keys. In this case the last used field for a table always returned @code{NULL}. @item diff --git a/mysql-test/t/comments.test b/mysql-test/t/comments.test index a85419c0295..2fc6237907c 100644 --- a/mysql-test/t/comments.test +++ b/mysql-test/t/comments.test @@ -5,7 +5,7 @@ select 1+2/*hello*/+3; select 1 /* long multi line comment */; -!$1065 /* empty query */; +!$1065 ; select 1 /*!32301 +1 */; select 1 /*!52301 +1 */; select 1--1; @@ -15,3 +15,4 @@ select 1 --2 +1; select 1 # The rest of the row will be ignored ; +/* line with only comment */; diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 072cbf540af..657ca3274cd 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -158,7 +158,8 @@ void kill_one_thread(THD *thd, ulong id); #define OPTION_LOW_PRIORITY_UPDATES 8192 #define OPTION_WARNINGS 16384 #define OPTION_AUTO_IS_NULL 32768 -#define OPTION_SAFE_UPDATES 65536L*2 +#define OPTION_FOUND_COMMENT 65536L +#define OPTION_SAFE_UPDATES OPTION_FOUND_COMMENT*2 #define OPTION_BUFFER_RESULT OPTION_SAFE_UPDATES*2 #define OPTION_BIN_LOG OPTION_BUFFER_RESULT*2 #define OPTION_NOT_AUTO_COMMIT OPTION_BIN_LOG*2 diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 7c3b933bbd7..a3c3db8947e 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -734,6 +734,7 @@ int yylex(void *arg) return(TEXT_STRING); case STATE_COMMENT: // Comment + lex->options|= OPTION_FOUND_COMMENT; while ((c = yyGet()) != '\n' && c) ; yyUnget(); // Safety against eof state = STATE_START; // Try again @@ -745,6 +746,7 @@ int yylex(void *arg) break; } yySkip(); // Skip '*' + lex->options|= OPTION_FOUND_COMMENT; if (yyPeek() == '!') // MySQL command in comment { ulong version=MYSQL_VERSION_ID; diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 7555d605e35..2b889d356bb 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -53,7 +53,7 @@ enum enum_sql_command { SQLCOM_BEGIN, SQLCOM_LOAD_MASTER_TABLE, SQLCOM_CHANGE_MASTER, SQLCOM_RENAME_TABLE, SQLCOM_BACKUP_TABLE, SQLCOM_RESTORE_TABLE, SQLCOM_RESET, SQLCOM_PURGE, SQLCOM_SHOW_BINLOGS, - SQLCOM_SHOW_OPEN_TABLES, SQLCOM_DO, + SQLCOM_SHOW_OPEN_TABLES, SQLCOM_DO, SQLCOM_EMPTY_QUERY, SQLCOM_END }; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 9b439081d50..fa4a4fd4f3b 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1181,6 +1181,10 @@ mysql_execute_command(void) res=mysql_do(thd, *lex->insert_list); break; + case SQLCOM_EMPTY_QUERY: + send_ok(&thd->net); + break; + case SQLCOM_PURGE: { if (check_process_priv(thd)) diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 08fab22629a..54a03d4a714 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -544,9 +544,17 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); query: END_OF_INPUT { - if (!current_thd->bootstrap) + THD *thd=current_thd; + if (!thd->bootstrap && + (!(thd->lex.options & OPTION_FOUND_COMMENT))) + { send_error(¤t_thd->net,ER_EMPTY_QUERY); - YYABORT; + YYABORT; + } + else + { + thd->lex.sql_command = SQLCOM_EMPTY_QUERY; + } } | verb_clause END_OF_INPUT {}