As of version 10.3.1, Item_func_case (when handling a simple CASE) stores the predicant argument (in the args[] array) after the WHEN..THEN arguments and before the ELSE argument.
For example, this expression:
CASE pred WHEN search1 THEN res1 WHEN search2 THEN res2 ELSE resE END
stores the arguments as follows:
args[0]=search1
args[1]=res1
args[2]=search2
args[3]=res2
args[4]=pred
args[6]=resE
Under terms of this task we'll do the following:
1. Change Item_func_case to store the arguments in the order of their appearance in the parser: the predicant argument in args[0], followed by the WHEN..THEN..ELSE arguments
2. Split Item_func_case into two separate classes Item_func_case_simple and Item_func_case_searched (for CASE expressions with and without predicant respectively).
3. Change the constructors of the affected classes just to accept a List<Item> argument (without additional first_expr_arg and else_expr_arg.
Advantages:
a. #1 and #3 will help to simplify the code in sql_yacc_ora.yy
| DECODE_SYM '(' expr ',' decode_when_list ')'
{
// 30 lines of the code, extracting {{else_expr_arg}} from the list.
}
to something as simple as:
| DECODE_SYM '(' expr ',' decode_when_list ')'
{
$5->push_front($3, thd->mem_root);
if (!($$= new (thd->mem_root) Item_func_case_simple(thd, *$5)))
MYSQL_YYABORT;
}
b. #1 and #3 will help to implement MDEV-13863 easier. MDEV-13836 will introduce a new class Item_func_decode_oracle. Without #1, we'd have to use the same complex code from sql_yacc_ora.yy, now for both DECODE() and DECODE_ORACLE().
c. #2 will slightly reduce the memory size required to handle searched CASE expression, because only Item_func_case_simple will need to derive from Predicant_to_list_comparator
d. #2 will make the code more readable by removing a lot of if statements like this:
if (first_expr_num != -1)
{
...
}
else
{
...
}
as the branches for the searched and the simple CASE expressions will reside in methods of different classes.
e. #1 will make it easier to debug the code in gdb, as printing the arguments in their syntactic order will be much easier than now.
Attachments
Issue Links
blocks
MDEV-13863sql_mode=ORACLE: DECODE does not treat two NULLs as equivalent
As of version {{10.3.1}}, {{Item_func_case}} (when handling a simple {{CASE}}) stores the predicant argument (in the {{args[]}} array) after the {{WHEN..THEN}} arguments and before the {{ELSE}} argument.
For example, this expression:
{code:sql}
CASE pred WHEN search1 THEN res1 WHEN search2 THEN res2 ELSE resE END
{code}
stores the arguments as follows:
- args[0]=search1
- args[1]=res1
- args[2]=search2
- args[3]=res2
- args[4]=pred
- args[6]=resE
Under terms of this task we'll do the following:
1. Change {{Item_func_case}} to store the arguments in the order of their appearance in the parser: the predicant argument in args[0], followed by the {{WHEN..THEN..ELSE}} arguments
2. Split {{Item_func_case}} into two separate classes {{Item_func_case_simple}} and {{Item_func_case_searched}} (for {{CASE}} expressions with and without predicant respectively).
3. Change the constructors of the affected classes just to accept a {{List<Item>}} argument (without additional {{first_expr_arg}} and {{else_expr_arg}}.
Advantages:
a. #1 and #3 will help to simplify the code in {{sql_yacc_ora.yy}}
{code:cpp}
| DECODE_SYM '(' expr ',' decode_when_list ')'
{
// 30 lines of the code, extracting {{else_expr_arg}} from the list.
}
{code}
to something as simple as:
{code:cpp}
| DECODE_SYM '(' expr ',' decode_when_list ')'
{
$5->push_front($3, thd->mem_root);
if (!($$= new (thd->mem_root) Item_func_case_simple(thd, *$5)))
MYSQL_YYABORT;
}
{code}
b. #1 and #3 will help to implement MDEV-13863 easier. MDEV-13836 will introduce a new class {{Item_func_decode_oracle}}. Without #1, we'd have to use the same complex code from {{sql_yacc_ora.yy}}, now for both {{DECODE()}} and {{DECODE_ORACLE()}}.
c. #2 will slightly reduce the memory size required to handle searched {{CASE}} expression, because only {{Item_func_case_simple}} will need to derive from {{Predicant_to_list_comparator}}
d. #2 will make the code more readable by removing a lot of {{if}} statements like this:
{code:cpp}
if (first_expr_num != -1)
{
...
}
else
{
...
}
{code}
as the branches for the searched and the simple {{CASE}} expressions will reside in methods of different classes.
e. #1 will make it easier to debug the code in {{gdb}}, as printing the arguments in their syntactic order will be much easier than now.
As of version {{10.3.1}}, {{Item_func_case}} (when handling a simple {{CASE}}) stores the predicant argument (in the {{args[]}} array) after the {{WHEN..THEN}} arguments and before the {{ELSE}} argument.
For example, this expression:
{code:sql}
CASE pred WHEN search1 THEN res1 WHEN search2 THEN res2 ELSE resE END
{code}
stores the arguments as follows:
- args[0]=search1
- args[1]=res1
- args[2]=search2
- args[3]=res2
- args[4]=pred
- args[6]=resE
Under terms of this task we'll do the following:
1. Change {{Item_func_case}} to store the arguments in the order of their appearance in the parser: the predicant argument in {{args[0]}}, followed by the {{WHEN..THEN..ELSE}} arguments
2. Split {{Item_func_case}} into two separate classes {{Item_func_case_simple}} and {{Item_func_case_searched}} (for {{CASE}} expressions with and without predicant respectively).
3. Change the constructors of the affected classes just to accept a {{List<Item>}} argument (without additional {{first_expr_arg}} and {{else_expr_arg}}.
Advantages:
a. #1 and #3 will help to simplify the code in {{sql_yacc_ora.yy}}
{code:cpp}
| DECODE_SYM '(' expr ',' decode_when_list ')'
{
// 30 lines of the code, extracting {{else_expr_arg}} from the list.
}
{code}
to something as simple as:
{code:cpp}
| DECODE_SYM '(' expr ',' decode_when_list ')'
{
$5->push_front($3, thd->mem_root);
if (!($$= new (thd->mem_root) Item_func_case_simple(thd, *$5)))
MYSQL_YYABORT;
}
{code}
b. #1 and #3 will help to implement MDEV-13863 easier. MDEV-13836 will introduce a new class {{Item_func_decode_oracle}}. Without #1, we'd have to use the same complex code from {{sql_yacc_ora.yy}}, now for both {{DECODE()}} and {{DECODE_ORACLE()}}.
c. #2 will slightly reduce the memory size required to handle searched {{CASE}} expression, because only {{Item_func_case_simple}} will need to derive from {{Predicant_to_list_comparator}}
d. #2 will make the code more readable by removing a lot of {{if}} statements like this:
{code:cpp}
if (first_expr_num != -1)
{
...
}
else
{
...
}
{code}
as the branches for the searched and the simple {{CASE}} expressions will reside in methods of different classes.
e. #1 will make it easier to debug the code in {{gdb}}, as printing the arguments in their syntactic order will be much easier than now.
Pushed to bb-10.2-ext and 10.3