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
|
class Create_func_reverse : public Create_func_arg1
|
||||||
{
|
{
|
||||||
public:
|
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;
|
Create_func_reverse Create_func_reverse::s_singleton;
|
||||||
|
|
||||||
Item*
|
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("CENTROID") }, GEOM_BUILDER(Create_func_centroid)},
|
||||||
{ { C_STRING_WITH_LEN("CHARACTER_LENGTH") }, BUILDER(Create_func_char_length)},
|
{ { 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("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("COERCIBILITY") }, BUILDER(Create_func_coercibility)},
|
||||||
{ { C_STRING_WITH_LEN("COLUMN_CHECK") }, BUILDER(Create_func_dyncol_check)},
|
{ { C_STRING_WITH_LEN("COLUMN_CHECK") }, BUILDER(Create_func_dyncol_check)},
|
||||||
{ { C_STRING_WITH_LEN("COLUMN_EXISTS") }, BUILDER(Create_func_dyncol_exists)},
|
{ { 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("CONV") }, BUILDER(Create_func_conv)},
|
||||||
{ { C_STRING_WITH_LEN("CONVERT_TZ") }, BUILDER(Create_func_convert_tz)},
|
{ { 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("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("COS") }, BUILDER(Create_func_cos)},
|
||||||
{ { C_STRING_WITH_LEN("COT") }, BUILDER(Create_func_cot)},
|
{ { C_STRING_WITH_LEN("COT") }, BUILDER(Create_func_cot)},
|
||||||
{ { C_STRING_WITH_LEN("CRC32") }, BUILDER(Create_func_crc32)},
|
{ { 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("RADIANS") }, BUILDER(Create_func_radians)},
|
||||||
{ { C_STRING_WITH_LEN("RAND") }, BUILDER(Create_func_rand)},
|
{ { C_STRING_WITH_LEN("RAND") }, BUILDER(Create_func_rand)},
|
||||||
{ { C_STRING_WITH_LEN("RELEASE_LOCK") }, BUILDER(Create_func_release_lock)},
|
{ { 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("REVERSE") }, BUILDER(Create_func_reverse)},
|
||||||
{ { C_STRING_WITH_LEN("ROUND") }, BUILDER(Create_func_round)},
|
{ { C_STRING_WITH_LEN("ROUND") }, BUILDER(Create_func_round)},
|
||||||
{ { C_STRING_WITH_LEN("RPAD") }, BUILDER(Create_func_rpad)},
|
{ { 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
|
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);
|
DBUG_ASSERT(fixed == 1);
|
||||||
String *res,*res2,*res3;
|
String *res,*res2,*res3;
|
||||||
@ -1225,8 +1226,11 @@ String *Item_func_replace::val_str(String *str)
|
|||||||
goto null;
|
goto null;
|
||||||
res2=args[1]->val_str(&tmp_value);
|
res2=args[1]->val_str(&tmp_value);
|
||||||
if (args[1]->null_value)
|
if (args[1]->null_value)
|
||||||
|
{
|
||||||
|
if (!empty_string_for_null)
|
||||||
goto null;
|
goto null;
|
||||||
|
res2= empty_string_for_null;
|
||||||
|
}
|
||||||
res->set_charset(collation.collation);
|
res->set_charset(collation.collation);
|
||||||
|
|
||||||
#ifdef USE_MB
|
#ifdef USE_MB
|
||||||
@ -1244,7 +1248,11 @@ String *Item_func_replace::val_str(String *str)
|
|||||||
return res;
|
return res;
|
||||||
#endif
|
#endif
|
||||||
if (!(res3=args[2]->val_str(&tmp_value2)))
|
if (!(res3=args[2]->val_str(&tmp_value2)))
|
||||||
|
{
|
||||||
|
if (!empty_string_for_null)
|
||||||
goto null;
|
goto null;
|
||||||
|
res3= empty_string_for_null;
|
||||||
|
}
|
||||||
from_length= res2->length();
|
from_length= res2->length();
|
||||||
to_length= res3->length();
|
to_length= res3->length();
|
||||||
|
|
||||||
@ -1327,6 +1335,9 @@ redo:
|
|||||||
}
|
}
|
||||||
while ((offset=res->strstr(*res2,(uint) offset)) >= 0);
|
while ((offset=res->strstr(*res2,(uint) offset)) >= 0);
|
||||||
}
|
}
|
||||||
|
if (empty_string_for_null && !res->length())
|
||||||
|
goto null;
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
|
|
||||||
null:
|
null:
|
||||||
|
@ -359,14 +359,28 @@ class Item_func_replace :public Item_str_func
|
|||||||
public:
|
public:
|
||||||
Item_func_replace(THD *thd, Item *org, Item *find, Item *replace):
|
Item_func_replace(THD *thd, Item *org, Item *find, Item *replace):
|
||||||
Item_str_func(thd, org, find, 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();
|
void fix_length_and_dec();
|
||||||
|
String *val_str_internal(String *str, String *empty_string_for_null);
|
||||||
const char *func_name() const { return "replace"; }
|
const char *func_name() const { return "replace"; }
|
||||||
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
|
Item *get_copy(THD *thd, MEM_ROOT *mem_root)
|
||||||
{ return get_item_copy<Item_func_replace>(thd, mem_root, this); }
|
{ 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
|
class Item_func_regexp_replace :public Item_str_func
|
||||||
{
|
{
|
||||||
Regexp_processor_pcre re;
|
Regexp_processor_pcre re;
|
||||||
|
@ -7161,3 +7161,14 @@ bool LEX::add_grant_command(THD *thd, enum_sql_command sql_command_arg,
|
|||||||
type= type_arg;
|
type= type_arg;
|
||||||
return false;
|
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,
|
const LEX_CSTRING *field_name,
|
||||||
uint pos_in_q, uint length_in_q);
|
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
|
Create a my_var instance for a ROW field variable that was used
|
||||||
as an OUT SP parameter: CALL p1(var.field);
|
as an OUT SP parameter: CALL p1(var.field);
|
||||||
|
@ -10083,8 +10083,7 @@ function_call_conflict:
|
|||||||
}
|
}
|
||||||
| REPLACE '(' expr ',' expr ',' expr ')'
|
| REPLACE '(' expr ',' expr ',' expr ')'
|
||||||
{
|
{
|
||||||
$$= new (thd->mem_root) Item_func_replace(thd, $3, $5, $7);
|
if (!($$= Lex->make_item_func_replace(thd, $3, $5, $7)))
|
||||||
if ($$ == NULL)
|
|
||||||
MYSQL_YYABORT;
|
MYSQL_YYABORT;
|
||||||
}
|
}
|
||||||
| REVERSE_SYM '(' expr ')'
|
| REVERSE_SYM '(' expr ')'
|
||||||
|
@ -10120,8 +10120,7 @@ function_call_conflict:
|
|||||||
}
|
}
|
||||||
| REPLACE '(' expr ',' expr ',' expr ')'
|
| REPLACE '(' expr ',' expr ',' expr ')'
|
||||||
{
|
{
|
||||||
$$= new (thd->mem_root) Item_func_replace(thd, $3, $5, $7);
|
if (!($$= Lex->make_item_func_replace(thd, $3, $5, $7)))
|
||||||
if ($$ == NULL)
|
|
||||||
MYSQL_YYABORT;
|
MYSQL_YYABORT;
|
||||||
}
|
}
|
||||||
| REVERSE_SYM '(' expr ')'
|
| REVERSE_SYM '(' expr ')'
|
||||||
|
Reference in New Issue
Block a user