summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt10
-rw-r--r--client/mysqltest.cc2
-rw-r--r--cmake/build_configurations/mysql_release.cmake1
-rw-r--r--config.h.cmake6
-rw-r--r--include/mysql.h2
-rw-r--r--include/mysql.h.pp2
-rw-r--r--mysql-test/disabled.def1
-rw-r--r--mysql-test/r/mysql.result26
-rw-r--r--mysql-test/t/mysql.test22
-rw-r--r--mysys/my_file.c7
-rw-r--r--sql-common/client.c30
11 files changed, 94 insertions, 15 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 3b270208a2d..92c1f9ef060 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -264,9 +264,15 @@ IF(HAVE_GGDB3)
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -ggdb3")
ENDIF(HAVE_GGDB3)
-OPTION(ENABLED_LOCAL_INFILE
- "If we should should enable LOAD DATA LOCAL by default" ${IF_WIN})
+SET(ENABLED_LOCAL_INFILE "AUTO" CACHE STRING "If we should should enable LOAD DATA LOCAL by default (OFF/ON/AUTO)")
MARK_AS_ADVANCED(ENABLED_LOCAL_INFILE)
+IF (ENABLED_LOCAL_INFILE MATCHES "^(0|FALSE)$")
+ SET(ENABLED_LOCAL_INFILE OFF)
+ELSEIF(ENABLED_LOCAL_INFILE MATCHES "^(1|TRUE)$")
+ SET(ENABLED_LOCAL_INFILE ON)
+ELSEIF (NOT ENABLED_LOCAL_INFILE MATCHES "^(ON|OFF|AUTO)$")
+ MESSAGE(FATAL_ERROR "ENABLED_LOCAL_INFILE must be one of OFF, ON, AUTO")
+ENDIF()
OPTION(WITH_FAST_MUTEXES "Compile with fast mutexes" OFF)
MARK_AS_ADVANCED(WITH_FAST_MUTEXES)
diff --git a/client/mysqltest.cc b/client/mysqltest.cc
index 77ce8d6dc8a..7ec2a62dcf7 100644
--- a/client/mysqltest.cc
+++ b/client/mysqltest.cc
@@ -6105,7 +6105,6 @@ void do_connect(struct st_command *command)
#endif
if (opt_compress || con_compress)
mysql_options(con_slot->mysql, MYSQL_OPT_COMPRESS, NullS);
- mysql_options(con_slot->mysql, MYSQL_OPT_LOCAL_INFILE, 0);
mysql_options(con_slot->mysql, MYSQL_SET_CHARSET_NAME,
charset_info->csname);
if (opt_charsets_dir)
@@ -9211,7 +9210,6 @@ int main(int argc, char **argv)
(void *) &opt_connect_timeout);
if (opt_compress)
mysql_options(con->mysql,MYSQL_OPT_COMPRESS,NullS);
- mysql_options(con->mysql, MYSQL_OPT_LOCAL_INFILE, 0);
mysql_options(con->mysql, MYSQL_SET_CHARSET_NAME,
charset_info->csname);
if (opt_charsets_dir)
diff --git a/cmake/build_configurations/mysql_release.cmake b/cmake/build_configurations/mysql_release.cmake
index 78314342426..b82b87b6237 100644
--- a/cmake/build_configurations/mysql_release.cmake
+++ b/cmake/build_configurations/mysql_release.cmake
@@ -96,7 +96,6 @@ IF(FEATURE_SET)
ENDFOREACH()
ENDIF()
-OPTION(ENABLED_LOCAL_INFILE "" ON)
IF(RPM)
SET(WITH_SSL system CACHE STRING "")
SET(WITH_ZLIB system CACHE STRING "")
diff --git a/config.h.cmake b/config.h.cmake
index e039cf12fca..c22638a6cc0 100644
--- a/config.h.cmake
+++ b/config.h.cmake
@@ -536,7 +536,11 @@
/*
MySQL features
*/
-#cmakedefine ENABLED_LOCAL_INFILE 1
+#define LOCAL_INFILE_MODE_OFF 0
+#define LOCAL_INFILE_MODE_ON 1
+#define LOCAL_INFILE_MODE_AUTO 2
+#define ENABLED_LOCAL_INFILE LOCAL_INFILE_MODE_@ENABLED_LOCAL_INFILE@
+
#cmakedefine ENABLED_PROFILING 1
#cmakedefine EXTRA_DEBUG 1
#cmakedefine BACKUP_TEST 1
diff --git a/include/mysql.h b/include/mysql.h
index f088ad668a1..fc814787c22 100644
--- a/include/mysql.h
+++ b/include/mysql.h
@@ -283,7 +283,7 @@ typedef struct st_mysql
/* session-wide random string */
char scramble[SCRAMBLE_LENGTH+1];
- my_bool unused1;
+ my_bool auto_local_infile;
void *unused2, *unused3, *unused4, *unused5;
LIST *stmts; /* list of all statements */
diff --git a/include/mysql.h.pp b/include/mysql.h.pp
index a593f526c6e..f891ad6f2c9 100644
--- a/include/mysql.h.pp
+++ b/include/mysql.h.pp
@@ -354,7 +354,7 @@ typedef struct st_mysql
my_bool free_me;
my_bool reconnect;
char scramble[20 +1];
- my_bool unused1;
+ my_bool auto_local_infile;
void *unused2, *unused3, *unused4, *unused5;
LIST *stmts;
const struct st_mysql_methods *methods;
diff --git a/mysql-test/disabled.def b/mysql-test/disabled.def
index 17bc921ab66..9292081b45e 100644
--- a/mysql-test/disabled.def
+++ b/mysql-test/disabled.def
@@ -19,3 +19,4 @@ ssl_crl : broken upstream
ssl_crl_clrpath : broken upstream
file_contents : MDEV-6526 these files are not installed anymore
lowercase_fs_on : lower_case_table_names=0 is not an error until 10.1
+partition_open_files_limit : open_files_limit check broken by MDEV-18360
diff --git a/mysql-test/r/mysql.result b/mysql-test/r/mysql.result
index 8a24128daa2..ffa5d020153 100644
--- a/mysql-test/r/mysql.result
+++ b/mysql-test/r/mysql.result
@@ -587,3 +587,29 @@ a
2
drop table "a1\""b1";
set sql_mode=default;
+create table t1 (a text);
+select count(*) from t1;
+count(*)
+41
+truncate table t1;
+select count(*) from t1;
+count(*)
+41
+truncate table t1;
+select count(*) from t1;
+count(*)
+0
+truncate table t1;
+select count(*) from t1;
+count(*)
+0
+truncate table t1;
+select count(*) from t1;
+count(*)
+41
+truncate table t1;
+select count(*) from t1;
+count(*)
+0
+truncate table t1;
+drop table t1;
diff --git a/mysql-test/t/mysql.test b/mysql-test/t/mysql.test
index 60dc16bfac7..a8e0a0094e4 100644
--- a/mysql-test/t/mysql.test
+++ b/mysql-test/t/mysql.test
@@ -656,3 +656,25 @@ show create table "a1\""b1";
select * from "a1\""b1";
drop table "a1\""b1";
set sql_mode=default;
+
+#
+# mysql --local-infile
+#
+--let $ldli = load data local infile '$MYSQLTEST_VARDIR/tmp/bug.sql' into table test.t1;
+create table t1 (a text);
+--exec $MYSQL -e "$ldli"
+select count(*) from t1; truncate table t1;
+--exec $MYSQL --enable-local-infile -e "$ldli"
+select count(*) from t1; truncate table t1;
+--error 1
+--exec $MYSQL --disable-local-infile -e "$ldli"
+select count(*) from t1; truncate table t1;
+--error 1
+--exec $MYSQL -e "/*q*/$ldli"
+select count(*) from t1; truncate table t1;
+--exec $MYSQL --enable-local-infile -e "/*q*/$ldli"
+select count(*) from t1; truncate table t1;
+--error 1
+--exec $MYSQL --disable-local-infile -e "/*q*/$ldli"
+select count(*) from t1; truncate table t1;
+drop table t1;
diff --git a/mysys/my_file.c b/mysys/my_file.c
index a23ab487d00..23226595b2e 100644
--- a/mysys/my_file.c
+++ b/mysys/my_file.c
@@ -52,10 +52,9 @@ static uint set_max_open_files(uint max_file_limit)
DBUG_PRINT("info", ("rlim_cur: %u rlim_max: %u",
(uint) rlimit.rlim_cur,
(uint) rlimit.rlim_max));
- if ((ulonglong) rlimit.rlim_cur == (ulonglong) RLIM_INFINITY)
- rlimit.rlim_cur = max_file_limit;
- if (rlimit.rlim_cur >= max_file_limit)
- DBUG_RETURN(rlimit.rlim_cur); /* purecov: inspected */
+ if ((ulonglong) rlimit.rlim_cur == (ulonglong) RLIM_INFINITY ||
+ rlimit.rlim_cur >= max_file_limit)
+ DBUG_RETURN(max_file_limit);
rlimit.rlim_cur= rlimit.rlim_max= max_file_limit;
if (setrlimit(RLIMIT_NOFILE, &rlimit))
max_file_limit= old_cur; /* Use original value */
diff --git a/sql-common/client.c b/sql-common/client.c
index d78e6167809..4bebf9ec63e 100644
--- a/sql-common/client.c
+++ b/sql-common/client.c
@@ -110,6 +110,12 @@ my_bool net_flush(NET *net);
#include <my_context.h>
#include <mysql_async.h>
+typedef enum {
+ ALWAYS_ACCEPT, /* heuristics is disabled, use CLIENT_LOCAL_FILES */
+ WAIT_FOR_QUERY, /* heuristics is enabled, not sending files */
+ ACCEPT_FILE_REQUEST /* heuristics is enabled, ready to send a file */
+} auto_local_infile_state;
+
#define native_password_plugin_name "mysql_native_password"
#define old_password_plugin_name "mysql_old_password"
@@ -1632,8 +1638,10 @@ mysql_init(MYSQL *mysql)
--enable-local-infile
*/
-#if defined(ENABLED_LOCAL_INFILE) && !defined(MYSQL_SERVER)
+#if ENABLED_LOCAL_INFILE && !defined(MYSQL_SERVER)
mysql->options.client_flag|= CLIENT_LOCAL_FILES;
+ mysql->auto_local_infile= ENABLED_LOCAL_INFILE == LOCAL_INFILE_MODE_AUTO
+ ? WAIT_FOR_QUERY : ALWAYS_ACCEPT;
#endif
#ifdef HAVE_SMEM
@@ -3999,8 +4007,14 @@ static my_bool cli_read_query_result(MYSQL *mysql)
ulong field_count;
MYSQL_DATA *fields;
ulong length;
+#ifdef MYSQL_CLIENT
+ my_bool can_local_infile= mysql->auto_local_infile != WAIT_FOR_QUERY;
+#endif
DBUG_ENTER("cli_read_query_result");
+ if (mysql->auto_local_infile == ACCEPT_FILE_REQUEST)
+ mysql->auto_local_infile= WAIT_FOR_QUERY;
+
if ((length = cli_safe_read(mysql)) == packet_error)
DBUG_RETURN(1);
free_old_query(mysql); /* Free old result */
@@ -4037,7 +4051,8 @@ get_info:
{
int error;
- if (!(mysql->options.client_flag & CLIENT_LOCAL_FILES))
+ if (!(mysql->options.client_flag & CLIENT_LOCAL_FILES) ||
+ !can_local_infile)
{
set_mysql_error(mysql, CR_MALFORMED_PACKET, unknown_sqlstate);
DBUG_RETURN(1);
@@ -4075,6 +4090,13 @@ int STDCALL
mysql_send_query(MYSQL* mysql, const char* query, ulong length)
{
DBUG_ENTER("mysql_send_query");
+ if (mysql->options.client_flag & CLIENT_LOCAL_FILES &&
+ mysql->auto_local_infile == WAIT_FOR_QUERY &&
+ (*query == 'l' || *query == 'L'))
+ {
+ if (strncasecmp(query, STRING_WITH_LEN("load")) == 0)
+ mysql->auto_local_infile= ACCEPT_FILE_REQUEST;
+ }
DBUG_RETURN(simple_command(mysql, COM_QUERY, (uchar*) query, length, 1));
}
@@ -4288,10 +4310,12 @@ mysql_options(MYSQL *mysql,enum mysql_option option, const void *arg)
mysql->options.protocol=MYSQL_PROTOCOL_PIPE; /* Force named pipe */
break;
case MYSQL_OPT_LOCAL_INFILE: /* Allow LOAD DATA LOCAL ?*/
- if (!arg || MY_TEST(*(uint*) arg))
+ if (!arg || *(uint*) arg)
mysql->options.client_flag|= CLIENT_LOCAL_FILES;
else
mysql->options.client_flag&= ~CLIENT_LOCAL_FILES;
+ mysql->auto_local_infile= arg && *(uint*)arg == LOCAL_INFILE_MODE_AUTO
+ ? WAIT_FOR_QUERY : ALWAYS_ACCEPT;
break;
case MYSQL_INIT_COMMAND:
add_init_command(&mysql->options,arg);