Commit 2175bfce authored by Sergei Golubchik's avatar Sergei Golubchik

Crude "auto-load-data-local-infile" mode

Disable LOAD DATA LOCAL INFILE suport by default and
auto-enable it for the duration of one query, if the query
string starts with the word "load". In all other cases the application
should enable LOAD DATA LOCAL INFILE support explicitly.
parent 21f90371
...@@ -256,9 +256,15 @@ IF(HAVE_GGDB3) ...@@ -256,9 +256,15 @@ IF(HAVE_GGDB3)
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -ggdb3") SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -ggdb3")
ENDIF() ENDIF()
OPTION(ENABLED_LOCAL_INFILE SET(ENABLED_LOCAL_INFILE "AUTO" CACHE STRING "If we should should enable LOAD DATA LOCAL by default (OFF/ON/AUTO)")
"If we should should enable LOAD DATA LOCAL by default" ${IF_WIN})
MARK_AS_ADVANCED(ENABLED_LOCAL_INFILE) 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) OPTION(WITH_FAST_MUTEXES "Compile with fast mutexes" OFF)
MARK_AS_ADVANCED(WITH_FAST_MUTEXES) MARK_AS_ADVANCED(WITH_FAST_MUTEXES)
......
...@@ -6045,7 +6045,6 @@ void do_connect(struct st_command *command) ...@@ -6045,7 +6045,6 @@ void do_connect(struct st_command *command)
#endif #endif
if (opt_compress || con_compress) if (opt_compress || con_compress)
mysql_options(con_slot->mysql, MYSQL_OPT_COMPRESS, NullS); 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, mysql_options(con_slot->mysql, MYSQL_SET_CHARSET_NAME,
charset_info->csname); charset_info->csname);
if (opt_charsets_dir) if (opt_charsets_dir)
...@@ -9110,7 +9109,6 @@ int main(int argc, char **argv) ...@@ -9110,7 +9109,6 @@ int main(int argc, char **argv)
(void *) &opt_connect_timeout); (void *) &opt_connect_timeout);
if (opt_compress) if (opt_compress)
mysql_options(con->mysql,MYSQL_OPT_COMPRESS,NullS); 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, mysql_options(con->mysql, MYSQL_SET_CHARSET_NAME,
charset_info->csname); charset_info->csname);
if (opt_charsets_dir) if (opt_charsets_dir)
......
...@@ -94,7 +94,6 @@ IF(FEATURE_SET) ...@@ -94,7 +94,6 @@ IF(FEATURE_SET)
ENDFOREACH() ENDFOREACH()
ENDIF() ENDIF()
OPTION(ENABLED_LOCAL_INFILE "" ON)
IF(RPM) IF(RPM)
SET(WITH_SSL system CACHE STRING "") SET(WITH_SSL system CACHE STRING "")
SET(WITH_ZLIB system CACHE STRING "") SET(WITH_ZLIB system CACHE STRING "")
......
...@@ -530,7 +530,11 @@ ...@@ -530,7 +530,11 @@
/* /*
MySQL features 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 ENABLED_PROFILING 1
#cmakedefine EXTRA_DEBUG 1 #cmakedefine EXTRA_DEBUG 1
#cmakedefine BACKUP_TEST 1 #cmakedefine BACKUP_TEST 1
......
...@@ -274,7 +274,7 @@ typedef struct st_mysql ...@@ -274,7 +274,7 @@ typedef struct st_mysql
/* session-wide random string */ /* session-wide random string */
char scramble[SCRAMBLE_LENGTH+1]; char scramble[SCRAMBLE_LENGTH+1];
my_bool unused1; my_bool auto_local_infile;
void *unused2, *unused3, *unused4, *unused5; void *unused2, *unused3, *unused4, *unused5;
LIST *stmts; /* list of all statements */ LIST *stmts; /* list of all statements */
......
...@@ -341,7 +341,7 @@ typedef struct st_mysql ...@@ -341,7 +341,7 @@ typedef struct st_mysql
my_bool free_me; my_bool free_me;
my_bool reconnect; my_bool reconnect;
char scramble[20 +1]; char scramble[20 +1];
my_bool unused1; my_bool auto_local_infile;
void *unused2, *unused3, *unused4, *unused5; void *unused2, *unused3, *unused4, *unused5;
LIST *stmts; LIST *stmts;
const struct st_mysql_methods *methods; const struct st_mysql_methods *methods;
......
...@@ -587,3 +587,29 @@ a ...@@ -587,3 +587,29 @@ a
2 2
drop table "a1\""b1"; drop table "a1\""b1";
set sql_mode=default; 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;
...@@ -656,3 +656,25 @@ show create table "a1\""b1"; ...@@ -656,3 +656,25 @@ show create table "a1\""b1";
select * from "a1\""b1"; select * from "a1\""b1";
drop table "a1\""b1"; drop table "a1\""b1";
set sql_mode=default; 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;
...@@ -115,6 +115,12 @@ my_bool net_flush(NET *net); ...@@ -115,6 +115,12 @@ my_bool net_flush(NET *net);
#include <my_context.h> #include <my_context.h>
#include <mysql_async.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 native_password_plugin_name "mysql_native_password"
#define old_password_plugin_name "mysql_old_password" #define old_password_plugin_name "mysql_old_password"
...@@ -1765,8 +1771,10 @@ mysql_init(MYSQL *mysql) ...@@ -1765,8 +1771,10 @@ mysql_init(MYSQL *mysql)
--enable-local-infile --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->options.client_flag|= CLIENT_LOCAL_FILES;
mysql->auto_local_infile= ENABLED_LOCAL_INFILE == LOCAL_INFILE_MODE_AUTO
? WAIT_FOR_QUERY : ALWAYS_ACCEPT;
#endif #endif
#ifdef HAVE_SMEM #ifdef HAVE_SMEM
...@@ -3951,8 +3959,14 @@ static my_bool cli_read_query_result(MYSQL *mysql) ...@@ -3951,8 +3959,14 @@ static my_bool cli_read_query_result(MYSQL *mysql)
ulong field_count; ulong field_count;
MYSQL_DATA *fields; MYSQL_DATA *fields;
ulong length; ulong length;
#ifdef MYSQL_CLIENT
my_bool can_local_infile= mysql->auto_local_infile != WAIT_FOR_QUERY;
#endif
DBUG_ENTER("cli_read_query_result"); 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) if ((length = cli_safe_read(mysql)) == packet_error)
DBUG_RETURN(1); DBUG_RETURN(1);
free_old_query(mysql); /* Free old result */ free_old_query(mysql); /* Free old result */
...@@ -3989,7 +4003,8 @@ static my_bool cli_read_query_result(MYSQL *mysql) ...@@ -3989,7 +4003,8 @@ static my_bool cli_read_query_result(MYSQL *mysql)
{ {
int error; 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); set_mysql_error(mysql, CR_MALFORMED_PACKET, unknown_sqlstate);
DBUG_RETURN(1); DBUG_RETURN(1);
...@@ -4027,6 +4042,13 @@ int STDCALL ...@@ -4027,6 +4042,13 @@ int STDCALL
mysql_send_query(MYSQL* mysql, const char* query, ulong length) mysql_send_query(MYSQL* mysql, const char* query, ulong length)
{ {
DBUG_ENTER("mysql_send_query"); 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)); 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) ...@@ -4241,10 +4263,12 @@ mysql_options(MYSQL *mysql,enum mysql_option option, const void *arg)
mysql->options.protocol=MYSQL_PROTOCOL_PIPE; /* Force named pipe */ mysql->options.protocol=MYSQL_PROTOCOL_PIPE; /* Force named pipe */
break; break;
case MYSQL_OPT_LOCAL_INFILE: /* Allow LOAD DATA LOCAL ?*/ 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; mysql->options.client_flag|= CLIENT_LOCAL_FILES;
else else
mysql->options.client_flag&= ~CLIENT_LOCAL_FILES; mysql->options.client_flag&= ~CLIENT_LOCAL_FILES;
mysql->auto_local_infile= arg && *(uint*)arg == LOCAL_INFILE_MODE_AUTO
? WAIT_FOR_QUERY : ALWAYS_ACCEPT;
break; break;
case MYSQL_INIT_COMMAND: case MYSQL_INIT_COMMAND:
add_init_command(&mysql->options,arg); add_init_command(&mysql->options,arg);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment