mirror of
https://github.com/MariaDB/server.git
synced 2026-10-23 18:49:29 +03:00
allocate Sql_path in one memory chunk, not one per schema
because it's always allocated and freed as a whole, there is no operation "replace one name in the middle of the path" this needed a reworked parser to create the whole list of names, not append one name at a time. Fixed a bug where Sql_path::from_text() pretended it can take a string in any charset, but was always implicitly assuming it's in my_charset_utf8mb3_general_ci.
This commit is contained in:
@@ -425,63 +425,63 @@ SELECT @@global.path;
|
||||
@@global.path
|
||||
`.`,`sys`
|
||||
SET PATH '`';
|
||||
ERROR 42000: Variable 'path' can't be set to the value of '`'
|
||||
ERROR 42000: Variable 'PATH' can't be set to the value of '`'
|
||||
SET PATH '"';
|
||||
ERROR 42000: Variable 'path' can't be set to the value of '"'
|
||||
ERROR 42000: Variable 'PATH' can't be set to the value of '"'
|
||||
SET PATH '`a';
|
||||
ERROR 42000: Variable 'path' can't be set to the value of '`a'
|
||||
ERROR 42000: Variable 'PATH' can't be set to the value of '`a'
|
||||
SET PATH '"a';
|
||||
ERROR 42000: Variable 'path' can't be set to the value of '"a'
|
||||
ERROR 42000: Variable 'PATH' can't be set to the value of '"a'
|
||||
SET PATH 'a`';
|
||||
ERROR 42000: Variable 'path' can't be set to the value of 'a`'
|
||||
ERROR 42000: Variable 'PATH' can't be set to the value of 'a`'
|
||||
SET PATH 'a"';
|
||||
ERROR 42000: Variable 'path' can't be set to the value of 'a"'
|
||||
ERROR 42000: Variable 'PATH' can't be set to the value of 'a"'
|
||||
SET PATH '"d"';
|
||||
ERROR 42000: Variable 'path' can't be set to the value of '"d"'
|
||||
ERROR 42000: Variable 'PATH' can't be set to the value of '"d"'
|
||||
SET PATH '`aaa';
|
||||
ERROR 42000: Variable 'path' can't be set to the value of '`aaa'
|
||||
ERROR 42000: Variable 'PATH' can't be set to the value of '`aaa'
|
||||
SET PATH 'aaa`';
|
||||
ERROR 42000: Variable 'path' can't be set to the value of 'aaa`'
|
||||
ERROR 42000: Variable 'PATH' can't be set to the value of 'aaa`'
|
||||
SET PATH '"aaa';
|
||||
ERROR 42000: Variable 'path' can't be set to the value of '"aaa'
|
||||
ERROR 42000: Variable 'PATH' can't be set to the value of '"aaa'
|
||||
SET PATH 'aaa"';
|
||||
ERROR 42000: Variable 'path' can't be set to the value of 'aaa"'
|
||||
ERROR 42000: Variable 'PATH' can't be set to the value of 'aaa"'
|
||||
SET PATH '`aaa"';
|
||||
ERROR 42000: Variable 'path' can't be set to the value of '`aaa"'
|
||||
ERROR 42000: Variable 'PATH' can't be set to the value of '`aaa"'
|
||||
SET PATH '"aaa`';
|
||||
ERROR 42000: Variable 'path' can't be set to the value of '"aaa`'
|
||||
ERROR 42000: Variable 'PATH' can't be set to the value of '"aaa`'
|
||||
SET PATH '"ggg,hhh';
|
||||
ERROR 42000: Variable 'path' can't be set to the value of '"ggg,hhh'
|
||||
ERROR 42000: Variable 'PATH' can't be set to the value of '"ggg,hhh'
|
||||
SET PATH 'ggg",hhh';
|
||||
ERROR 42000: Variable 'path' can't be set to the value of 'ggg",hhh'
|
||||
ERROR 42000: Variable 'PATH' can't be set to the value of 'ggg",hhh'
|
||||
SET PATH '"ggg",hhh';
|
||||
ERROR 42000: Variable 'path' can't be set to the value of '"ggg",hhh'
|
||||
ERROR 42000: Variable 'PATH' can't be set to the value of '"ggg",hhh'
|
||||
SET PATH 'hhh,`iii`,jjj,"kkk",lll';
|
||||
ERROR 42000: Variable 'path' can't be set to the value of 'hhh,`iii`,jjj,"kkk",lll'
|
||||
ERROR 42000: Variable 'PATH' can't be set to the value of 'hhh,`iii`,jjj,"kkk",lll'
|
||||
SET PATH 'hello,world,deadpool,wolverine,aaa,deadpool,ccc';
|
||||
ERROR 42000: Variable 'path' can't be set to the value of 'deadpool'
|
||||
ERROR 42000: Variable 'PATH' can't be set to the value of 'hello,world,deadpool,wolverine,aaa,deadpool,ccc'
|
||||
SET PATH '`,Ɣ';
|
||||
ERROR 42000: Variable 'path' can't be set to the value of '`,Ɣ'
|
||||
ERROR 42000: Variable 'PATH' can't be set to the value of '`,Ɣ'
|
||||
SET PATH '",Ɣ';
|
||||
ERROR 42000: Variable 'path' can't be set to the value of '",Ɣ'
|
||||
ERROR 42000: Variable 'PATH' can't be set to the value of '",Ɣ'
|
||||
SET PATH 'Ɣ,`';
|
||||
ERROR 42000: Variable 'path' can't be set to the value of 'Ɣ,`'
|
||||
ERROR 42000: Variable 'PATH' can't be set to the value of 'Ɣ,`'
|
||||
SET PATH 'Ɣ,"';
|
||||
ERROR 42000: Variable 'path' can't be set to the value of 'Ɣ,"'
|
||||
ERROR 42000: Variable 'PATH' can't be set to the value of 'Ɣ,"'
|
||||
SET PATH '`Œ';
|
||||
ERROR 42000: Variable 'path' can't be set to the value of '`Œ'
|
||||
ERROR 42000: Variable 'PATH' can't be set to the value of '`Œ'
|
||||
SET PATH '"c';
|
||||
ERROR 42000: Variable 'path' can't be set to the value of '"c'
|
||||
ERROR 42000: Variable 'PATH' can't be set to the value of '"c'
|
||||
SET PATH 'Œ`';
|
||||
ERROR 42000: Variable 'path' can't be set to the value of 'Œ`'
|
||||
ERROR 42000: Variable 'PATH' can't be set to the value of 'Œ`'
|
||||
SET PATH 'Œ"';
|
||||
ERROR 42000: Variable 'path' can't be set to the value of 'Œ"'
|
||||
ERROR 42000: Variable 'PATH' can't be set to the value of 'Œ"'
|
||||
SET PATH '`Œ"';
|
||||
ERROR 42000: Variable 'path' can't be set to the value of '`Œ"'
|
||||
ERROR 42000: Variable 'PATH' can't be set to the value of '`Œ"'
|
||||
SET PATH '"Œ`';
|
||||
ERROR 42000: Variable 'path' can't be set to the value of '"Œ`'
|
||||
ERROR 42000: Variable 'PATH' can't be set to the value of '"Œ`'
|
||||
SET PATH '"Ɣ"';
|
||||
ERROR 42000: Variable 'path' can't be set to the value of '"Ɣ"'
|
||||
ERROR 42000: Variable 'PATH' can't be set to the value of '"Ɣ"'
|
||||
SELECT @@path;
|
||||
@@path
|
||||
`.`,`sys`
|
||||
@@ -492,8 +492,10 @@ SET PATH ' ';
|
||||
SET PATH ' ';
|
||||
SET PATH ',';
|
||||
SET PATH '``';
|
||||
ERROR 42000: Incorrect database name ''
|
||||
SET sql_mode=ANSI_QUOTES;
|
||||
SET PATH '""';
|
||||
ERROR 42000: Incorrect database name ''
|
||||
SET sql_mode=DEFAULT;
|
||||
#
|
||||
# Escaping backticks
|
||||
@@ -507,9 +509,9 @@ SELECT @@path;
|
||||
@@path
|
||||
`a```
|
||||
SET PATH '``a`';
|
||||
ERROR 42000: Variable 'path' can't be set to the value of '``a`'
|
||||
ERROR 42000: Incorrect database name ''
|
||||
SET PATH '`a``';
|
||||
ERROR 42000: Variable 'path' can't be set to the value of '`a``'
|
||||
ERROR 42000: Variable 'PATH' can't be set to the value of '`a``'
|
||||
SET GLOBAL PATH=DEFAULT;
|
||||
SET @@path=DEFAULT;
|
||||
#
|
||||
@@ -520,7 +522,7 @@ SELECT @@path;
|
||||
@@path
|
||||
`a`,`b`,`c`,`d`,`e`,`f`,`g`,`h`,`i`,`j`,`k`,`l`,`m`,`n`,`o`,`p`
|
||||
SET PATH 'a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q';
|
||||
ERROR HY000: Too long value for 'path'
|
||||
ERROR HY000: Too long value for 'PATH'
|
||||
SELECT @@path;
|
||||
@@path
|
||||
`a`,`b`,`c`,`d`,`e`,`f`,`g`,`h`,`i`,`j`,`k`,`l`,`m`,`n`,`o`,`p`
|
||||
|
||||
@@ -324,9 +324,11 @@ SELECT @@path;
|
||||
SET PATH ' ';
|
||||
SET PATH ' ';
|
||||
SET PATH ',';
|
||||
SET PATH '``';
|
||||
|
||||
--Error ER_WRONG_DB_NAME
|
||||
SET PATH '``';
|
||||
SET sql_mode=ANSI_QUOTES;
|
||||
--Error ER_WRONG_DB_NAME
|
||||
SET PATH '""';
|
||||
SET sql_mode=DEFAULT;
|
||||
|
||||
@@ -338,7 +340,7 @@ SELECT @@path;
|
||||
SET PATH '`a```';
|
||||
SELECT @@path;
|
||||
|
||||
--error ER_WRONG_VALUE_FOR_VAR
|
||||
--error ER_WRONG_DB_NAME
|
||||
SET PATH '``a`';
|
||||
--error ER_WRONG_VALUE_FOR_VAR
|
||||
SET PATH '`a``';
|
||||
|
||||
@@ -766,7 +766,7 @@ Sp_handler::db_find_routine(THD *thd, const Database_qualified_name *name,
|
||||
if (!table->field[MYSQL_PROC_FIELD_PATH]->val_str(&sql_path_str))
|
||||
sql_path_str.set(STRING_WITH_LEN("CURRENT_SCHEMA"), system_charset_info);
|
||||
|
||||
sql_path.from_text(thd, sql_path_str.charset(), sql_path_str.to_lex_cstring());
|
||||
sql_path.from_text(thd, sql_path_str.to_lex_cstring());
|
||||
creation_ctx= Stored_routine_creation_ctx::load_from_db(thd, name, table);
|
||||
|
||||
trans_commited= 1;
|
||||
|
||||
347
sql/sql_path.cc
347
sql/sql_path.cc
@@ -14,7 +14,7 @@ Sql_path::Sql_path() : m_count(0)
|
||||
|
||||
Sql_path& Sql_path::operator=(const Sql_path &rhs)
|
||||
{
|
||||
set(current_thd, rhs);
|
||||
set(rhs);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@ bool Sql_path::try_resolve_in_schema(THD *thd, const Lex_ident_db_normalized &sc
|
||||
/*
|
||||
[schema] '.' routine_name
|
||||
*/
|
||||
name->m_db= Lex_ident_db_normalized(thd->strmake(schema.str, schema.length),
|
||||
name->m_db= Lex_ident_db_normalized(thd->strmake(schema.str, schema.length),
|
||||
schema.length);
|
||||
*resolved= true;
|
||||
return false;
|
||||
@@ -147,21 +147,21 @@ bool Sql_path::resolve(THD *thd, sp_head *caller, sp_name *name,
|
||||
for (size_t i= 0; i < m_count; i++)
|
||||
{
|
||||
Lex_ident_db schema= m_schemas[i];
|
||||
|
||||
|
||||
// Resolve CURRENT_SCHEMA if needed
|
||||
schema= resolve_current_schema(thd, caller, schema);
|
||||
if (!schema.str)
|
||||
continue; // CURRENT_SCHEMA resolution failed, skip this entry
|
||||
|
||||
|
||||
/*
|
||||
Schemas are already normalized when added to the path, except for
|
||||
Schemas are already normalized when added to the path, except for
|
||||
CURRENT_SCHEMA which was resolved above. We can use them directly.
|
||||
*/
|
||||
const Lex_ident_db_normalized dbn(schema.str, schema.length);
|
||||
|
||||
|
||||
if (try_resolve_in_schema(thd, dbn, name, sph, pkgname, &resolved))
|
||||
return true;
|
||||
|
||||
|
||||
if (resolved)
|
||||
break;
|
||||
}
|
||||
@@ -172,11 +172,8 @@ bool Sql_path::resolve(THD *thd, sp_head *caller, sp_name *name,
|
||||
|
||||
void Sql_path::free()
|
||||
{
|
||||
for (size_t i= 0; i < m_count; i++)
|
||||
{
|
||||
my_free((void*)m_schemas[i].str);
|
||||
}
|
||||
|
||||
if (m_count)
|
||||
my_free(const_cast<char*>(m_schemas[0].str));
|
||||
m_count= 0;
|
||||
}
|
||||
|
||||
@@ -184,8 +181,9 @@ void Sql_path::free()
|
||||
bool Sql_path::init()
|
||||
{
|
||||
free();
|
||||
add_schema_direct(cur_schema.str, cur_schema.length);
|
||||
|
||||
char *buf= my_strndup(key_memory_Sys_var_charptr_value,
|
||||
cur_schema.str, cur_schema.length, MYF(MY_WME));
|
||||
m_schemas[m_count++]= {buf, cur_schema.length};
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -196,89 +194,40 @@ bool Sql_path::is_cur_schema(const LEX_CSTRING &schema) const
|
||||
}
|
||||
|
||||
|
||||
bool Sql_path::add_schema_direct(const char *schema_str, size_t schema_len)
|
||||
bool Sql_path::add_schema(char **to)
|
||||
{
|
||||
if (unlikely(m_count >= array_elements(m_schemas)))
|
||||
{
|
||||
my_error(ER_VALUE_TOO_LONG , MYF(0), "path");
|
||||
return true;
|
||||
}
|
||||
const Lex_ident_db &dbn= m_schemas[m_count];
|
||||
m_schemas[m_count].length= *to - m_schemas[m_count].str;
|
||||
*(*to)++= 0;
|
||||
|
||||
char *tmp= my_strndup(key_memory_Sys_var_charptr_value,
|
||||
schema_str, schema_len,
|
||||
MYF(MY_WME));
|
||||
m_schemas[m_count++]= {tmp, schema_len};
|
||||
return false;
|
||||
}
|
||||
// Validate
|
||||
if (Lex_ident_db::check_name_with_error(dbn))
|
||||
goto err;
|
||||
|
||||
|
||||
bool Sql_path::add_schema(THD *thd, const char *schema_str, size_t schema_len)
|
||||
{
|
||||
DBUG_ASSERT(schema_str);
|
||||
|
||||
if (unlikely(m_count >= array_elements(m_schemas)))
|
||||
{
|
||||
my_error(ER_VALUE_TOO_LONG , MYF(0), "path");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (is_cur_schema({schema_str, schema_len}))
|
||||
return add_schema_direct(schema_str, schema_len);
|
||||
|
||||
// Step 1: Process backticks in-place using a local buffer
|
||||
char local_buf[NAME_LEN * 3]; // Sufficient for any schema name
|
||||
if (schema_len >= sizeof(local_buf))
|
||||
{
|
||||
my_error(ER_VALUE_TOO_LONG, MYF(0), "path");
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t processed_len = 0;
|
||||
for (size_t i = 0; i < schema_len; i++)
|
||||
{
|
||||
if (schema_str[i] == '`' && i + 1 < schema_len)
|
||||
i++; // Skip first backtick of double backtick
|
||||
local_buf[processed_len++] = schema_str[i];
|
||||
}
|
||||
local_buf[processed_len] = '\0';
|
||||
|
||||
// Step 2: Normalize the processed string
|
||||
Lex_ident_db_normalized dbn = thd->to_ident_db_normalized_with_error(
|
||||
Lex_cstring(local_buf, processed_len));
|
||||
if (!dbn.str)
|
||||
return true;
|
||||
|
||||
// Step 3: Check for duplicates
|
||||
// Check for duplicates
|
||||
for (size_t i = 0; i < m_count; i++)
|
||||
{
|
||||
if (unlikely(m_schemas[i].length == dbn.length &&
|
||||
!memcmp(m_schemas[i].str, dbn.str, dbn.length)))
|
||||
{
|
||||
my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), "path", dbn.str);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (dbn.streq(m_schemas[i]))
|
||||
goto err;
|
||||
|
||||
// Step 4: Make persistent copy and store
|
||||
char *persistent_copy = my_strndup(key_memory_Sys_var_charptr_value,
|
||||
dbn.str, dbn.length, MYF(MY_WME));
|
||||
if (unlikely(!persistent_copy))
|
||||
return true;
|
||||
|
||||
m_schemas[m_count++] = {persistent_copy, dbn.length};
|
||||
m_count++;
|
||||
return false;
|
||||
err:
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void Sql_path::set(THD *thd, const Sql_path &rhs)
|
||||
void Sql_path::set(const Sql_path &rhs)
|
||||
{
|
||||
free();
|
||||
|
||||
for (size_t i= 0; i < rhs.m_count; i++)
|
||||
if ((m_count= rhs.m_count))
|
||||
{
|
||||
if (add_schema(thd, rhs.m_schemas[i].str,
|
||||
rhs.m_schemas[i].length))
|
||||
break;
|
||||
auto rbuf= rhs.m_schemas[0].str;
|
||||
auto rend= rhs.m_schemas[m_count-1].str + rhs.m_schemas[m_count-1].length;
|
||||
auto buf= (const char*)my_memdup(key_memory_Sys_var_charptr_value, rbuf,
|
||||
rend - rbuf + 1, MYF(MY_WME));
|
||||
for (size_t i= 0; i < rhs.m_count; i++)
|
||||
m_schemas[i]= { rhs.m_schemas[i].str - rbuf + buf, rhs.m_schemas[i].length };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -293,165 +242,127 @@ void Sql_path::set(Sql_path &&rhs)
|
||||
}
|
||||
|
||||
|
||||
bool Sql_path::from_text(THD *thd, CHARSET_INFO *cs, const LEX_CSTRING &text)
|
||||
bool Sql_path::from_text(THD *thd, const LEX_CSTRING &text)
|
||||
{
|
||||
enum tokenize_state
|
||||
{
|
||||
START, QUOTED_TOKEN_DOUBLE='"', QUOTED_TOKEN_BACKTICK='`', UNQUOTED_TOKEN, END
|
||||
} state= START;
|
||||
|
||||
const bool ansi_quotes= thd ? thd->variables.sql_mode & MODE_ANSI_QUOTES
|
||||
: false;
|
||||
|
||||
CHARSET_INFO *cs= &my_charset_utf8mb3_general_ci; // as in make_ident_casedn()
|
||||
DBUG_ASSERT(cs->cset->casedn_multiply(cs) == 1);
|
||||
DBUG_ASSERT(text.str);
|
||||
char *buf= (char*)my_malloc(key_memory_Sys_var_charptr_value,
|
||||
text.length + 1, MYF(MY_WME));
|
||||
if (!buf)
|
||||
return true;
|
||||
|
||||
char *curr= buf, *to= buf, *end;
|
||||
|
||||
if (lower_case_table_names > 0)
|
||||
end= buf + cs->cset->casedn(cs, text.str, text.length, buf, text.length);
|
||||
else
|
||||
{
|
||||
memcpy(buf, text.str, text.length);
|
||||
end= buf + text.length;
|
||||
}
|
||||
|
||||
free();
|
||||
|
||||
enum class tokenize_state
|
||||
while (curr < end)
|
||||
{
|
||||
START,
|
||||
QUOTED_TOKEN_DOUBLE,
|
||||
QUOTED_TOKEN_BACKTICK,
|
||||
UNQUOTED_TOKEN,
|
||||
END
|
||||
} state= tokenize_state::START;
|
||||
|
||||
auto *curr= text.str;
|
||||
auto *end= curr + text.length;
|
||||
auto token_start= curr;
|
||||
auto token_end= curr;
|
||||
auto last_non_space= curr;
|
||||
const bool ansi_quotes= thd ?
|
||||
thd->variables.sql_mode & MODE_ANSI_QUOTES : false;
|
||||
|
||||
while (curr != end)
|
||||
{
|
||||
auto len = my_ismbchar(cs, curr, end - 1);
|
||||
if (len)
|
||||
{
|
||||
if (state == tokenize_state::START)
|
||||
{
|
||||
state= tokenize_state::UNQUOTED_TOKEN;
|
||||
token_start= curr;
|
||||
}
|
||||
|
||||
curr += len;
|
||||
last_non_space= curr - 1;
|
||||
if (curr < end)
|
||||
continue;
|
||||
}
|
||||
else if (unlikely(!ansi_quotes && *curr == '"' &&
|
||||
state != tokenize_state::QUOTED_TOKEN_BACKTICK))
|
||||
{
|
||||
/*
|
||||
ANSI_QUOTES is not set, only allow double quotes within backticks.
|
||||
*/
|
||||
my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), "path", text.str);
|
||||
return true;
|
||||
}
|
||||
auto len = cs->charlen(curr, end);
|
||||
|
||||
switch (state)
|
||||
{
|
||||
case tokenize_state::START:
|
||||
if (*curr == '`' || (ansi_quotes && *curr == '"'))
|
||||
{
|
||||
state= *curr == '`' ? tokenize_state::QUOTED_TOKEN_BACKTICK :
|
||||
tokenize_state::QUOTED_TOKEN_DOUBLE;
|
||||
token_start= ++curr;
|
||||
}
|
||||
else if (*curr == ',' || my_isspace(cs, (uchar) *curr))
|
||||
{
|
||||
case START:
|
||||
if (*curr == ',' || my_isspace(cs, (uchar) *curr))
|
||||
curr++;
|
||||
}
|
||||
else
|
||||
{
|
||||
state= tokenize_state::UNQUOTED_TOKEN;
|
||||
last_non_space= token_start= curr++;
|
||||
}
|
||||
break;
|
||||
case tokenize_state::QUOTED_TOKEN_BACKTICK:
|
||||
if (*curr == '`')
|
||||
{
|
||||
if (curr + 1 < end && curr[1] == '`')
|
||||
if (m_count >= array_elements(m_schemas))
|
||||
{
|
||||
/* Looked-ahead and found double backtick */
|
||||
curr += 2;
|
||||
last_non_space= curr - 1;
|
||||
my_error(ER_VALUE_TOO_LONG, MYF(0), "PATH");
|
||||
goto err;
|
||||
}
|
||||
m_schemas[m_count].str= to;
|
||||
if (*curr == '`' || (*curr == '"' && ansi_quotes))
|
||||
state= (tokenize_state) *curr++;
|
||||
else if (*curr == '"')
|
||||
goto err_bad_val;
|
||||
else
|
||||
{
|
||||
state= tokenize_state::END;
|
||||
token_end= last_non_space + 1;
|
||||
curr++;
|
||||
state= UNQUOTED_TOKEN;
|
||||
while (len--)
|
||||
*to++= *curr++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!my_isspace(cs, (uchar) *curr))
|
||||
last_non_space= curr;
|
||||
curr++;
|
||||
}
|
||||
break;
|
||||
case tokenize_state::QUOTED_TOKEN_DOUBLE:
|
||||
if (*curr == '"')
|
||||
case QUOTED_TOKEN_BACKTICK:
|
||||
case QUOTED_TOKEN_DOUBLE:
|
||||
if (*curr == state)
|
||||
{
|
||||
state= tokenize_state::END;
|
||||
token_end= last_non_space + 1;
|
||||
curr++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!my_isspace(cs, (uchar) *curr))
|
||||
last_non_space= curr;
|
||||
curr++;
|
||||
if (curr >= end || *curr != state)
|
||||
{
|
||||
state= END;
|
||||
if (add_schema(&to))
|
||||
goto err_bad_val;
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (len--)
|
||||
*to++= *curr++;
|
||||
break;
|
||||
case tokenize_state::UNQUOTED_TOKEN:
|
||||
case UNQUOTED_TOKEN:
|
||||
if (*curr == ',' || my_isspace(cs, (uchar) *curr))
|
||||
{
|
||||
state= *curr++ == ',' ? START : END;
|
||||
if (add_schema(&to))
|
||||
goto err_bad_val;
|
||||
break;
|
||||
}
|
||||
else if (*curr == '`' || *curr == '"')
|
||||
goto err_bad_val;
|
||||
else
|
||||
while (len--)
|
||||
*to++= *curr++;
|
||||
break;
|
||||
case END:
|
||||
if (*curr == ',')
|
||||
{
|
||||
state= tokenize_state::END;
|
||||
token_end= last_non_space + 1;
|
||||
curr++;
|
||||
}
|
||||
else if (unlikely(*curr == '`' || *curr == '"'))
|
||||
{
|
||||
my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), "path", text.str);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!my_isspace(cs, (uchar) *curr))
|
||||
last_non_space= curr;
|
||||
curr++;
|
||||
}
|
||||
break;
|
||||
case tokenize_state::END:
|
||||
state= START;
|
||||
else if (!my_isspace(cs, (uchar) *curr))
|
||||
goto err_bad_val;
|
||||
curr++;
|
||||
break;
|
||||
}
|
||||
|
||||
if (state == tokenize_state::END)
|
||||
{
|
||||
if (token_end > token_start)
|
||||
{
|
||||
if (unlikely(add_schema(thd, token_start,
|
||||
(size_t)(token_end - token_start))))
|
||||
return true;
|
||||
}
|
||||
|
||||
state= tokenize_state::START;
|
||||
}
|
||||
}
|
||||
|
||||
if (state == tokenize_state::UNQUOTED_TOKEN)
|
||||
switch (state)
|
||||
{
|
||||
token_end= last_non_space + 1;
|
||||
auto len= (size_t)(token_end - token_start);
|
||||
|
||||
if (len && add_schema(thd, token_start, len))
|
||||
return true;
|
||||
case START:
|
||||
case END:
|
||||
break;
|
||||
case QUOTED_TOKEN_BACKTICK:
|
||||
case QUOTED_TOKEN_DOUBLE:
|
||||
goto err_bad_val;
|
||||
case UNQUOTED_TOKEN:
|
||||
if (add_schema(&to))
|
||||
goto err_bad_val;
|
||||
break;
|
||||
}
|
||||
else if (unlikely(state == tokenize_state::QUOTED_TOKEN_BACKTICK ||
|
||||
state == tokenize_state::QUOTED_TOKEN_DOUBLE))
|
||||
{
|
||||
/*
|
||||
Unclosed quoted string.
|
||||
*/
|
||||
my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), "path", text.str);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
if (!m_count)
|
||||
my_free(buf);
|
||||
return false;
|
||||
|
||||
err_bad_val:
|
||||
my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), "PATH", text.str);
|
||||
err:
|
||||
m_count= 0;
|
||||
my_free(buf);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -518,7 +429,7 @@ size_t Sql_path::print(char *dst, size_t nbytes_available) const
|
||||
|
||||
if (dst < start + nbytes_available)
|
||||
*dst= '\0';
|
||||
|
||||
|
||||
return dst - start;
|
||||
}
|
||||
|
||||
@@ -546,7 +457,7 @@ LEX_CSTRING Sql_path::lex_cstring(MEM_ROOT *mem_root) const
|
||||
Sql_path_instant_set::Sql_path_instant_set(THD *thd, const LEX_CSTRING &str)
|
||||
: m_thd(thd), m_path(std::move(thd->variables.path))
|
||||
{
|
||||
if (thd->variables.path.from_text(thd, system_charset_info, str))
|
||||
if (thd->variables.path.from_text(thd, str))
|
||||
{
|
||||
thd->variables.path.set(std::move(m_path));
|
||||
m_thd= NULL;
|
||||
@@ -556,7 +467,7 @@ Sql_path_instant_set::Sql_path_instant_set(THD *thd, const LEX_CSTRING &str)
|
||||
Sql_path_instant_set::Sql_path_instant_set(THD *thd, const Sql_path &new_path)
|
||||
: m_thd(thd), m_path(std::move(thd->variables.path))
|
||||
{
|
||||
thd->variables.path.set(thd, new_path);
|
||||
thd->variables.path.set(new_path);
|
||||
}
|
||||
|
||||
Sql_path_instant_set::~Sql_path_instant_set()
|
||||
|
||||
@@ -49,10 +49,9 @@ public:
|
||||
/*
|
||||
Set the variable to the value of rhs, making a copy of the buffer
|
||||
|
||||
@param thd The thread handle
|
||||
@param rhs The path variable to copy from
|
||||
*/
|
||||
void set(THD *thd, const Sql_path &rhs);
|
||||
void set(const Sql_path &rhs);
|
||||
/*
|
||||
Set the variable to the value of rhs, moving the buffer
|
||||
|
||||
@@ -63,11 +62,12 @@ public:
|
||||
/*
|
||||
Parse a string and set the path variable to the parsed value
|
||||
|
||||
The string is in my_charset_utf8mb3_general_ci.
|
||||
|
||||
@param thd The thread handle
|
||||
@param cs The character set of the string
|
||||
@param str The string to parse
|
||||
*/
|
||||
bool from_text(THD *thd, CHARSET_INFO *cs, const LEX_CSTRING &str);
|
||||
bool from_text(THD *thd, const LEX_CSTRING &str);
|
||||
/*
|
||||
Get the number of bytes needed to print the path variable
|
||||
|
||||
@@ -103,19 +103,7 @@ protected:
|
||||
bool *resolved) const;
|
||||
|
||||
private:
|
||||
/*
|
||||
Add a schema to the path variable
|
||||
|
||||
@param thd The thread handle
|
||||
@param schema_str The schema name
|
||||
@param schema_len The length of the schema name
|
||||
|
||||
@return true if the schema could not be added
|
||||
*/
|
||||
bool add_schema(THD *thd, const char *schema_str, size_t schema_len);
|
||||
|
||||
bool add_schema_direct(const char *schema_str, size_t schema_len);
|
||||
|
||||
bool add_schema(char **to);
|
||||
bool is_cur_schema(const LEX_CSTRING &schema) const;
|
||||
};
|
||||
|
||||
|
||||
@@ -1946,8 +1946,9 @@ bool Table_triggers_list::check_n_load(THD *thd, const LEX_CSTRING *db,
|
||||
continue;
|
||||
}
|
||||
|
||||
if (sp->m_sql_path.from_text(thd, sql_path))
|
||||
goto err_with_lex_cleanup;
|
||||
sp->m_sql_mode= sql_mode;
|
||||
sp->m_sql_path.from_text(thd, system_charset_info, sql_path);
|
||||
sp->set_creation_ctx(creation_ctx);
|
||||
|
||||
if (!trg_definer || !trg_definer->length)
|
||||
|
||||
@@ -3097,7 +3097,7 @@ private:
|
||||
String *value, buffer;
|
||||
if (!(value= item->val_str_ascii(&buffer)))
|
||||
return true;
|
||||
return path->from_text(thd, value->charset(), value->to_lex_cstring());
|
||||
return path->from_text(thd, value->to_lex_cstring());
|
||||
}
|
||||
|
||||
static const uchar *make_value_ptr(THD *thd, const Sql_path &path)
|
||||
@@ -3125,7 +3125,7 @@ private:
|
||||
|
||||
void session_save_default(THD *thd, set_var *var) override
|
||||
{
|
||||
thd->variables.path.set(thd, global_system_variables.path);
|
||||
thd->variables.path.set(global_system_variables.path);
|
||||
}
|
||||
|
||||
void global_save_default(THD *thd, set_var *var) override
|
||||
|
||||
Reference in New Issue
Block a user