mirror of
https://github.com/MariaDB/server.git
synced 2025-08-01 03:47:19 +03:00
mysql cli: fix USE command quoting
* use proper sql quoting rules for USE, while preserving as much of historical behavior as possible * short commands (\u) behave as before
This commit is contained in:
@ -245,7 +245,8 @@ static void end_pager();
|
|||||||
static void init_tee(const char *);
|
static void init_tee(const char *);
|
||||||
static void end_tee();
|
static void end_tee();
|
||||||
static const char* construct_prompt();
|
static const char* construct_prompt();
|
||||||
static char *get_arg(char *line, my_bool get_next_arg);
|
enum get_arg_mode { CHECK, GET, GET_NEXT};
|
||||||
|
static char *get_arg(char *line, get_arg_mode mode);
|
||||||
static void init_username();
|
static void init_username();
|
||||||
static void add_int_to_prompt(int toadd);
|
static void add_int_to_prompt(int toadd);
|
||||||
static int get_result_width(MYSQL_RES *res);
|
static int get_result_width(MYSQL_RES *res);
|
||||||
@ -2223,7 +2224,7 @@ static COMMANDS *find_command(char *name)
|
|||||||
if (!my_strnncoll(&my_charset_latin1, (uchar*) name, len,
|
if (!my_strnncoll(&my_charset_latin1, (uchar*) name, len,
|
||||||
(uchar*) commands[i].name, len) &&
|
(uchar*) commands[i].name, len) &&
|
||||||
(commands[i].name[len] == '\0') &&
|
(commands[i].name[len] == '\0') &&
|
||||||
(!end || commands[i].takes_params))
|
(!end || (commands[i].takes_params && get_arg(name, CHECK))))
|
||||||
{
|
{
|
||||||
index= i;
|
index= i;
|
||||||
break;
|
break;
|
||||||
@ -3143,7 +3144,7 @@ com_charset(String *buffer __attribute__((unused)), char *line)
|
|||||||
char buff[256], *param;
|
char buff[256], *param;
|
||||||
CHARSET_INFO * new_cs;
|
CHARSET_INFO * new_cs;
|
||||||
strmake_buf(buff, line);
|
strmake_buf(buff, line);
|
||||||
param= get_arg(buff, 0);
|
param= get_arg(buff, GET);
|
||||||
if (!param || !*param)
|
if (!param || !*param)
|
||||||
{
|
{
|
||||||
return put_info("Usage: \\C charset_name | charset charset_name",
|
return put_info("Usage: \\C charset_name | charset charset_name",
|
||||||
@ -4228,12 +4229,12 @@ com_connect(String *buffer, char *line)
|
|||||||
#ifdef EXTRA_DEBUG
|
#ifdef EXTRA_DEBUG
|
||||||
tmp[1]= 0;
|
tmp[1]= 0;
|
||||||
#endif
|
#endif
|
||||||
tmp= get_arg(buff, 0);
|
tmp= get_arg(buff, GET);
|
||||||
if (tmp && *tmp)
|
if (tmp && *tmp)
|
||||||
{
|
{
|
||||||
my_free(current_db);
|
my_free(current_db);
|
||||||
current_db= my_strdup(tmp, MYF(MY_WME));
|
current_db= my_strdup(tmp, MYF(MY_WME));
|
||||||
tmp= get_arg(buff, 1);
|
tmp= get_arg(buff, GET_NEXT);
|
||||||
if (tmp)
|
if (tmp)
|
||||||
{
|
{
|
||||||
my_free(current_host);
|
my_free(current_host);
|
||||||
@ -4336,7 +4337,7 @@ com_delimiter(String *buffer __attribute__((unused)), char *line)
|
|||||||
char buff[256], *tmp;
|
char buff[256], *tmp;
|
||||||
|
|
||||||
strmake_buf(buff, line);
|
strmake_buf(buff, line);
|
||||||
tmp= get_arg(buff, 0);
|
tmp= get_arg(buff, GET);
|
||||||
|
|
||||||
if (!tmp || !*tmp)
|
if (!tmp || !*tmp)
|
||||||
{
|
{
|
||||||
@ -4367,7 +4368,7 @@ com_use(String *buffer __attribute__((unused)), char *line)
|
|||||||
|
|
||||||
bzero(buff, sizeof(buff));
|
bzero(buff, sizeof(buff));
|
||||||
strmake_buf(buff, line);
|
strmake_buf(buff, line);
|
||||||
tmp= get_arg(buff, 0);
|
tmp= get_arg(buff, GET);
|
||||||
if (!tmp || !*tmp)
|
if (!tmp || !*tmp)
|
||||||
{
|
{
|
||||||
put_info("USE must be followed by a database name", INFO_ERROR);
|
put_info("USE must be followed by a database name", INFO_ERROR);
|
||||||
@ -4452,23 +4453,22 @@ com_nowarnings(String *buffer __attribute__((unused)),
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Gets argument from a command on the command line. If get_next_arg is
|
Gets argument from a command on the command line. If mode is not GET_NEXT,
|
||||||
not defined, skips the command and returns the first argument. The
|
skips the command and returns the first argument. The line is modified by
|
||||||
line is modified by adding zero to the end of the argument. If
|
adding zero to the end of the argument. If mode is GET_NEXT, then the
|
||||||
get_next_arg is defined, then the function searches for end of string
|
function searches for end of string first, after found, returns the next
|
||||||
first, after found, returns the next argument and adds zero to the
|
argument and adds zero to the end. If you ever wish to use this feature,
|
||||||
end. If you ever wish to use this feature, remember to initialize all
|
remember to initialize all items in the array to zero first.
|
||||||
items in the array to zero first.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
char *get_arg(char *line, my_bool get_next_arg)
|
static char *get_arg(char *line, get_arg_mode mode)
|
||||||
{
|
{
|
||||||
char *ptr, *start;
|
char *ptr, *start;
|
||||||
my_bool quoted= 0, valid_arg= 0;
|
bool short_cmd= false;
|
||||||
char qtype= 0;
|
char qtype= 0;
|
||||||
|
|
||||||
ptr= line;
|
ptr= line;
|
||||||
if (get_next_arg)
|
if (mode == GET_NEXT)
|
||||||
{
|
{
|
||||||
for (; *ptr; ptr++) ;
|
for (; *ptr; ptr++) ;
|
||||||
if (*(ptr + 1))
|
if (*(ptr + 1))
|
||||||
@ -4479,7 +4479,7 @@ char *get_arg(char *line, my_bool get_next_arg)
|
|||||||
/* skip leading white spaces */
|
/* skip leading white spaces */
|
||||||
while (my_isspace(charset_info, *ptr))
|
while (my_isspace(charset_info, *ptr))
|
||||||
ptr++;
|
ptr++;
|
||||||
if (*ptr == '\\') // short command was used
|
if ((short_cmd= *ptr == '\\')) // short command was used
|
||||||
ptr+= 2;
|
ptr+= 2;
|
||||||
else
|
else
|
||||||
while (*ptr &&!my_isspace(charset_info, *ptr)) // skip command
|
while (*ptr &&!my_isspace(charset_info, *ptr)) // skip command
|
||||||
@ -4492,24 +4492,28 @@ char *get_arg(char *line, my_bool get_next_arg)
|
|||||||
if (*ptr == '\'' || *ptr == '\"' || *ptr == '`')
|
if (*ptr == '\'' || *ptr == '\"' || *ptr == '`')
|
||||||
{
|
{
|
||||||
qtype= *ptr;
|
qtype= *ptr;
|
||||||
quoted= 1;
|
|
||||||
ptr++;
|
ptr++;
|
||||||
}
|
}
|
||||||
for (start=ptr ; *ptr; ptr++)
|
for (start=ptr ; *ptr; ptr++)
|
||||||
{
|
{
|
||||||
if (*ptr == '\\' && ptr[1]) // escaped character
|
if ((*ptr == '\\' && ptr[1]) || // escaped character
|
||||||
|
(!short_cmd && qtype && *ptr == qtype && ptr[1] == qtype)) // quote
|
||||||
{
|
{
|
||||||
// Remove the backslash
|
// Remove (or skip) the backslash (or a second quote)
|
||||||
strmov_overlapp(ptr, ptr+1);
|
if (mode != CHECK)
|
||||||
|
strmov_overlapp(ptr, ptr+1);
|
||||||
|
else
|
||||||
|
ptr++;
|
||||||
}
|
}
|
||||||
else if ((!quoted && *ptr == ' ') || (quoted && *ptr == qtype))
|
else if (*ptr == (qtype ? qtype : ' '))
|
||||||
{
|
{
|
||||||
*ptr= 0;
|
qtype= 0;
|
||||||
|
if (mode != CHECK)
|
||||||
|
*ptr= 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
valid_arg= ptr != start;
|
return ptr != start && !qtype ? start : NullS;
|
||||||
return valid_arg ? start : NullS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -512,6 +512,14 @@ DROP DATABASE connected_db;
|
|||||||
create database `aa``bb````cc`;
|
create database `aa``bb````cc`;
|
||||||
DATABASE()
|
DATABASE()
|
||||||
aa`bb``cc
|
aa`bb``cc
|
||||||
|
DATABASE()
|
||||||
|
test
|
||||||
|
DATABASE()
|
||||||
|
aa`bb``cc
|
||||||
|
DATABASE()
|
||||||
|
test
|
||||||
|
DATABASE()
|
||||||
|
aa`bb``cc
|
||||||
drop database `aa``bb````cc`;
|
drop database `aa``bb````cc`;
|
||||||
a
|
a
|
||||||
>>\ndelimiter\n<<
|
>>\ndelimiter\n<<
|
||||||
|
@ -586,8 +586,16 @@ DROP DATABASE connected_db;
|
|||||||
# USE and names with backticks
|
# USE and names with backticks
|
||||||
#
|
#
|
||||||
--write_file $MYSQLTEST_VARDIR/tmp/backticks.sql
|
--write_file $MYSQLTEST_VARDIR/tmp/backticks.sql
|
||||||
|
\u aa`bb``cc
|
||||||
|
SELECT DATABASE();
|
||||||
|
USE test
|
||||||
|
SELECT DATABASE();
|
||||||
USE aa`bb``cc
|
USE aa`bb``cc
|
||||||
SELECT DATABASE();
|
SELECT DATABASE();
|
||||||
|
USE test
|
||||||
|
SELECT DATABASE();
|
||||||
|
USE `aa``bb````cc`
|
||||||
|
SELECT DATABASE();
|
||||||
EOF
|
EOF
|
||||||
create database `aa``bb````cc`;
|
create database `aa``bb````cc`;
|
||||||
--exec $MYSQL < $MYSQLTEST_VARDIR/tmp/backticks.sql
|
--exec $MYSQL < $MYSQLTEST_VARDIR/tmp/backticks.sql
|
||||||
|
Reference in New Issue
Block a user