mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
MDEV-13003 - Oracle compatibility : Replace function
This commit is contained in:
committed by
Alexander Barkov
parent
1a9e13d622
commit
c9981fbee2
32
mysql-test/suite/compat/oracle/r/func_replace.result
Normal file
32
mysql-test/suite/compat/oracle/r/func_replace.result
Normal file
@ -0,0 +1,32 @@
|
||||
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;
|
22
mysql-test/suite/compat/oracle/t/func_replace.test
Normal file
22
mysql-test/suite/compat/oracle/t/func_replace.test
Normal file
@ -0,0 +1,22 @@
|
||||
#
|
||||
# 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 @@ protected:
|
||||
};
|
||||
|
||||
|
||||
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 @@ redo:
|
||||
}
|
||||
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 @@ public:
|
||||
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 ')'
|
||||
|
Reference in New Issue
Block a user