Commit c9981fbe authored by halfspawn's avatar halfspawn Committed by Alexander Barkov

MDEV-13003 - Oracle compatibility : Replace function

parent 1a9e13d6
SET sql_mode=ORACLE;
#
# MDEV-13003 - Oracle compatibility : Replace function
#
SELECT REPLACE(null,'a','b') ;
REPLACE(null,'a','b')
NULL
SELECT REPLACE('ab',null,'b') ;
REPLACE('ab',null,'b')
ab
SELECT REPLACE('ab','a',null) ;
REPLACE('ab','a',null)
b
SELECT REPLACE('ab',null,null) ;
REPLACE('ab',null,null)
ab
SELECT REPLACE('aaa','a',null) ;
REPLACE('aaa','a',null)
NULL
EXPLAIN EXTENDED SELECT REPLACE('ab','a',null) ;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
Note 1003 select replace_oracle('ab','a',NULL) AS "REPLACE('ab','a',null)"
CREATE VIEW v1 AS SELECT REPLACE('ab','a',null) ;
SHOW CREATE VIEW v1;
View Create View character_set_client collation_connection
v1 CREATE VIEW "v1" AS select replace_oracle('ab','a',NULL) AS "REPLACE('ab','a',null)" latin1 latin1_swedish_ci
SELECT * FROM v1;
REPLACE('ab','a',null)
b
DROP VIEW v1;
#
# Testing replace with null args
#
SET sql_mode=ORACLE;
--echo #
--echo # MDEV-13003 - Oracle compatibility : Replace function
--echo #
SELECT REPLACE(null,'a','b') ;
SELECT REPLACE('ab',null,'b') ;
SELECT REPLACE('ab','a',null) ;
SELECT REPLACE('ab',null,null) ;
SELECT REPLACE('aaa','a',null) ;
EXPLAIN EXTENDED SELECT REPLACE('ab','a',null) ;
CREATE VIEW v1 AS SELECT REPLACE('ab','a',null) ;
SHOW CREATE VIEW v1;
SELECT * FROM v1;
DROP VIEW v1;
......@@ -2624,6 +2624,19 @@ class Create_func_release_lock : public Create_func_arg1
};
class Create_func_replace_oracle : public Create_func_arg3
{
public:
virtual Item *create_3_arg(THD *thd, Item *arg1, Item *arg2, Item *arg3);
static Create_func_replace_oracle s_singleton;
protected:
Create_func_replace_oracle() {}
virtual ~Create_func_replace_oracle() {}
};
class Create_func_reverse : public Create_func_arg1
{
public:
......@@ -6214,6 +6227,16 @@ Create_func_release_lock::create_1_arg(THD *thd, Item *arg1)
}
Create_func_replace_oracle Create_func_replace_oracle::s_singleton;
Item*
Create_func_replace_oracle::create_3_arg(THD *thd, Item *arg1, Item *arg2,
Item *arg3)
{
return new (thd->mem_root) Item_func_replace_oracle(thd, arg1, arg2, arg3);
}
Create_func_reverse Create_func_reverse::s_singleton;
Item*
......@@ -6802,6 +6825,7 @@ static Native_func_registry func_array[] =
{ { C_STRING_WITH_LEN("CENTROID") }, GEOM_BUILDER(Create_func_centroid)},
{ { C_STRING_WITH_LEN("CHARACTER_LENGTH") }, BUILDER(Create_func_char_length)},
{ { C_STRING_WITH_LEN("CHAR_LENGTH") }, BUILDER(Create_func_char_length)},
{ { C_STRING_WITH_LEN("CHR") }, BUILDER(Create_func_chr)},
{ { C_STRING_WITH_LEN("COERCIBILITY") }, BUILDER(Create_func_coercibility)},
{ { C_STRING_WITH_LEN("COLUMN_CHECK") }, BUILDER(Create_func_dyncol_check)},
{ { C_STRING_WITH_LEN("COLUMN_EXISTS") }, BUILDER(Create_func_dyncol_exists)},
......@@ -6815,7 +6839,6 @@ static Native_func_registry func_array[] =
{ { C_STRING_WITH_LEN("CONV") }, BUILDER(Create_func_conv)},
{ { C_STRING_WITH_LEN("CONVERT_TZ") }, BUILDER(Create_func_convert_tz)},
{ { C_STRING_WITH_LEN("CONVEXHULL") }, GEOM_BUILDER(Create_func_convexhull)},
{ { C_STRING_WITH_LEN("CHR") }, BUILDER(Create_func_chr)},
{ { C_STRING_WITH_LEN("COS") }, BUILDER(Create_func_cos)},
{ { C_STRING_WITH_LEN("COT") }, BUILDER(Create_func_cot)},
{ { C_STRING_WITH_LEN("CRC32") }, BUILDER(Create_func_crc32)},
......@@ -6990,6 +7013,8 @@ static Native_func_registry func_array[] =
{ { C_STRING_WITH_LEN("RADIANS") }, BUILDER(Create_func_radians)},
{ { C_STRING_WITH_LEN("RAND") }, BUILDER(Create_func_rand)},
{ { C_STRING_WITH_LEN("RELEASE_LOCK") }, BUILDER(Create_func_release_lock)},
{ { C_STRING_WITH_LEN("REPLACE_ORACLE") },
BUILDER(Create_func_replace_oracle)},
{ { C_STRING_WITH_LEN("REVERSE") }, BUILDER(Create_func_reverse)},
{ { C_STRING_WITH_LEN("ROUND") }, BUILDER(Create_func_round)},
{ { C_STRING_WITH_LEN("RPAD") }, BUILDER(Create_func_rpad)},
......
......@@ -1205,7 +1205,8 @@ void Item_func_reverse::fix_length_and_dec()
Fix that this works with binary strings when using USE_MB
*/
String *Item_func_replace::val_str(String *str)
String *Item_func_replace::val_str_internal(String *str,
String *empty_string_for_null)
{
DBUG_ASSERT(fixed == 1);
String *res,*res2,*res3;
......@@ -1225,8 +1226,11 @@ String *Item_func_replace::val_str(String *str)
goto null;
res2=args[1]->val_str(&tmp_value);
if (args[1]->null_value)
goto null;
{
if (!empty_string_for_null)
goto null;
res2= empty_string_for_null;
}
res->set_charset(collation.collation);
#ifdef USE_MB
......@@ -1244,7 +1248,11 @@ String *Item_func_replace::val_str(String *str)
return res;
#endif
if (!(res3=args[2]->val_str(&tmp_value2)))
goto null;
{
if (!empty_string_for_null)
goto null;
res3= empty_string_for_null;
}
from_length= res2->length();
to_length= res3->length();
......@@ -1327,6 +1335,9 @@ String *Item_func_replace::val_str(String *str)
}
while ((offset=res->strstr(*res2,(uint) offset)) >= 0);
}
if (empty_string_for_null && !res->length())
goto null;
return res;
null:
......
......@@ -359,14 +359,28 @@ class Item_func_replace :public Item_str_func
public:
Item_func_replace(THD *thd, Item *org, Item *find, Item *replace):
Item_str_func(thd, org, find, replace) {}
String *val_str(String *);
String *val_str(String *to) { return val_str_internal(to, NULL); };
void fix_length_and_dec();
String *val_str_internal(String *str, String *empty_string_for_null);
const char *func_name() const { return "replace"; }
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
{ return get_item_copy<Item_func_replace>(thd, mem_root, this); }
};
class Item_func_replace_oracle :public Item_func_replace
{
String tmp_emtpystr;
public:
Item_func_replace_oracle(THD *thd, Item *org, Item *find, Item *replace):
Item_func_replace(thd, org, find, replace) {}
String *val_str(String *to) { return val_str_internal(to, &tmp_emtpystr); };
const char *func_name() const { return "replace_oracle"; }
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
{ return get_item_copy<Item_func_replace_oracle>(thd, mem_root, this); }
};
class Item_func_regexp_replace :public Item_str_func
{
Regexp_processor_pcre re;
......
......@@ -7161,3 +7161,14 @@ bool LEX::add_grant_command(THD *thd, enum_sql_command sql_command_arg,
type= type_arg;
return false;
}
Item *LEX::make_item_func_replace(THD *thd,
Item *org,
Item *find,
Item *replace)
{
return (thd->variables.sql_mode & MODE_ORACLE) ?
new (thd->mem_root) Item_func_replace_oracle(thd, org, find, replace) :
new (thd->mem_root) Item_func_replace(thd, org, find, replace);
}
......@@ -3357,6 +3357,8 @@ struct LEX: public Query_tables_list
const LEX_CSTRING *field_name,
uint pos_in_q, uint length_in_q);
Item *make_item_func_replace(THD *thd, Item *org, Item *find, Item *replace);
/*
Create a my_var instance for a ROW field variable that was used
as an OUT SP parameter: CALL p1(var.field);
......
......@@ -10083,8 +10083,7 @@ function_call_conflict:
}
| REPLACE '(' expr ',' expr ',' expr ')'
{
$$= new (thd->mem_root) Item_func_replace(thd, $3, $5, $7);
if ($$ == NULL)
if (!($$= Lex->make_item_func_replace(thd, $3, $5, $7)))
MYSQL_YYABORT;
}
| REVERSE_SYM '(' expr ')'
......
......@@ -10120,8 +10120,7 @@ function_call_conflict:
}
| REPLACE '(' expr ',' expr ',' expr ')'
{
$$= new (thd->mem_root) Item_func_replace(thd, $3, $5, $7);
if ($$ == NULL)
if (!($$= Lex->make_item_func_replace(thd, $3, $5, $7)))
MYSQL_YYABORT;
}
| REVERSE_SYM '(' expr ')'
......
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