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/r/mysql.result26
-rw-r--r--mysql-test/t/mysql.test22
-rw-r--r--sql-common/client.c30
9 files changed, 90 insertions, 11 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index b15512683fa..bc4c4e4f103 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -256,9 +256,15 @@ IF(HAVE_GGDB3)
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -ggdb3")
ENDIF()
-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 2b7401878ef..842bde3b99e 100644
--- a/client/mysqltest.cc
+++ b/client/mysqltest.cc
@@ -6045,7 +6045,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)
@@ -9110,7 +9109,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 39ad0e68d35..a464631e9a2 100644
--- a/cmake/build_configurations/mysql_release.cmake
+++ b/cmake/build_configurations/mysql_release.cmake
@@ -94,7 +94,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 99a2ebdd093..271d77f2e5a 100644
--- a/config.h.cmake
+++ b/config.h.cmake
@@ -530,7 +530,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 2f205ec6463..1ed6ffe67c8 100644
--- a/include/mysql.h
+++ b/include/mysql.h
@@ -274,7 +274,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 4f7407095c9..8bff18d7bb0 100644
--- a/include/mysql.h.pp
+++ b/include/mysql.h.pp
@@ -341,7 +341,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/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 87756768c7f..f526a3fea91 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/sql-common/client.c b/sql-common/client.c
index 952b6a199ee..bec778e7d51 100644
--- a/sql-common/client.c
+++ b/sql-common/client.c
@@ -115,6 +115,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"
@@ -1765,8 +1771,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
@@ -3951,8 +3959,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 */
@@ -3989,7 +4003,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);
@@ -4027,6 +4042,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));
}
@@ -4241,10 +4263,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 || 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);