mirror of
https://github.com/MariaDB/server.git
synced 2026-05-04 22:25:32 +02:00
MDEV-27744 LPAD in vcol created in ORACLE mode makes table corrupted in non-ORACLE
The crash happened with an indexed virtual column whose value is evaluated using a function that has a different meaning in sql_mode='' vs sql_mode=ORACLE: - DECODE() - LTRIM() - RTRIM() - LPAD() - RPAD() - REPLACE() - SUBSTR() For example: CREATE TABLE t1 ( b VARCHAR(1), g CHAR(1) GENERATED ALWAYS AS (SUBSTR(b,0,0)) VIRTUAL, KEY g(g) ); So far we had replacement XXX_ORACLE() functions for all mentioned function, e.g. SUBSTR_ORACLE() for SUBSTR(). So it was possible to correctly re-parse SUBSTR_ORACLE() even in sql_mode=''. But it was not possible to re-parse the MariaDB version of SUBSTR() after switching to sql_mode=ORACLE. It was erroneously mis-interpreted as SUBSTR_ORACLE(). As a result, this combination worked fine: SET sql_mode=ORACLE; CREATE TABLE t1 ... g CHAR(1) GENERATED ALWAYS AS (SUBSTR(b,0,0)) VIRTUAL, ...; INSERT ... FLUSH TABLES; SET sql_mode=''; INSERT ... But the other way around it crashed: SET sql_mode=''; CREATE TABLE t1 ... g CHAR(1) GENERATED ALWAYS AS (SUBSTR(b,0,0)) VIRTUAL, ...; INSERT ... FLUSH TABLES; SET sql_mode=ORACLE; INSERT ... At CREATE time, SUBSTR was instantiated as Item_func_substr and printed in the FRM file as substr(). At re-open time with sql_mode=ORACLE, "substr()" was erroneously instantiated as Item_func_substr_oracle. Fix: The fix proposes a symmetric solution. It provides a way to re-parse reliably all sql_mode dependent functions to their original CREATE TABLE time meaning, no matter what the open-time sql_mode is. We take advantage of the same idea we previously used to resolve sql_mode dependent data types. Now all sql_mode dependent functions are printed by SHOW using a schema qualifier when the current sql_mode differs from the function sql_mode: SET sql_mode=''; CREATE TABLE t1 ... SUBSTR(a,b,c) ..; SET sql_mode=ORACLE; SHOW CREATE TABLE t1; -> mariadb_schema.substr(a,b,c) SET sql_mode=ORACLE; CREATE TABLE t2 ... SUBSTR(a,b,c) ..; SET sql_mode=''; SHOW CREATE TABLE t1; -> oracle_schema.substr(a,b,c) Old replacement names like substr_oracle() are still understood for backward compatibility and used in FRM files (for downgrade compatibility), but they are not printed by SHOW any more.
This commit is contained in:
parent
228b7e4db5
commit
2b6d241ee4
34 changed files with 3754 additions and 126 deletions
|
|
@ -56,8 +56,40 @@ protected:
|
|||
bool check_argument_types_can_return_date(uint start, uint end) const;
|
||||
bool check_argument_types_can_return_time(uint start, uint end) const;
|
||||
void print_cast_temporal(String *str, enum_query_type query_type);
|
||||
|
||||
void print_schema_qualified_name(String *to,
|
||||
const LEX_CSTRING &schema_name,
|
||||
const char *function_name) const
|
||||
{
|
||||
// e.g. oracle_schema.func()
|
||||
to->append(schema_name);
|
||||
to->append('.');
|
||||
to->append(function_name);
|
||||
}
|
||||
|
||||
void print_sql_mode_qualified_name(String *to,
|
||||
enum_query_type query_type,
|
||||
const char *function_name) const
|
||||
{
|
||||
const Schema *func_schema= schema();
|
||||
if (!func_schema || func_schema == Schema::find_implied(current_thd))
|
||||
to->append(function_name);
|
||||
else
|
||||
print_schema_qualified_name(to, func_schema->name(), function_name);
|
||||
}
|
||||
|
||||
void print_sql_mode_qualified_name(String *to, enum_query_type query_type)
|
||||
const
|
||||
{
|
||||
return print_sql_mode_qualified_name(to, query_type, func_name());
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
// Print an error message for a builtin-schema qualified function call
|
||||
static void wrong_param_count_error(const LEX_CSTRING &schema_name,
|
||||
const LEX_CSTRING &func_name);
|
||||
|
||||
table_map not_null_tables_cache;
|
||||
|
||||
enum Functype { UNKNOWN_FUNC,EQ_FUNC,EQUAL_FUNC,NE_FUNC,LT_FUNC,LE_FUNC,
|
||||
|
|
@ -179,7 +211,13 @@ public:
|
|||
List<Item> &fields, uint flags);
|
||||
virtual void print(String *str, enum_query_type query_type);
|
||||
void print_op(String *str, enum_query_type query_type);
|
||||
void print_args(String *str, uint from, enum_query_type query_type);
|
||||
void print_args(String *str, uint from, enum_query_type query_type) const;
|
||||
void print_args_parenthesized(String *str, enum_query_type query_type) const
|
||||
{
|
||||
str->append('(');
|
||||
print_args(str, 0, query_type);
|
||||
str->append(')');
|
||||
}
|
||||
bool is_null() {
|
||||
update_null_value();
|
||||
return null_value;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue