Commit 209375fd authored by halfspawn's avatar halfspawn Committed by Alexander Barkov

MDEV-15664 : sql_mode=ORACLE: Make TRIM return NULL instead of empty string

parent 4faf34ad
......@@ -1336,6 +1336,11 @@ CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW SET @@NEW.a=0;
ERROR HY000: Unknown structured system variable or ROW routine variable 'NEW'
DROP TABLE t1;
#
# MDEV-15664 sql_mode=ORACLE: Make TRIM return NULL instead of empty string
#
CREATE TABLE trim_oracle (trim_oracle int);
DROP TABLE trim_oracle;
#
# MDEV-15615 Unexpected syntax error instead of "Unknown system variable" inside an SP
#
BEGIN NOT ATOMIC
......
SET sql_mode=ORACLE;
#
# MDEV-15664 sql_mode=ORACLE: Make TRIM return NULL instead of empty string
#
SELECT TRIM('abc'), TRIM('abc ')||'.', '.'||TRIM(' abc ')||'.', TRIM(' '), TRIM(NULL), TRIM(SPACE(0)),TRIM(SPACE(10)) FROM dual;
TRIM('abc') TRIM('abc ')||'.' '.'||TRIM(' abc ')||'.' TRIM(' ') TRIM(NULL) TRIM(SPACE(0)) TRIM(SPACE(10))
abc abc. .abc. NULL NULL NULL NULL
SELECT TRIM(TRAILING 'abc' FROM 'abc');
TRIM(TRAILING 'abc' FROM 'abc')
NULL
SELECT TRIM(TRAILING 'abc' FROM 'abc ');
TRIM(TRAILING 'abc' FROM 'abc ')
abc
SELECT TRIM(TRAILING 'abc' FROM ' abc');
TRIM(TRAILING 'abc' FROM ' abc')
SELECT TRIM(LEADING 'abc' FROM 'abc');
TRIM(LEADING 'abc' FROM 'abc')
NULL
SELECT TRIM(LEADING 'abc' FROM 'abc ');
TRIM(LEADING 'abc' FROM 'abc ')
SELECT TRIM(LEADING 'abc' FROM ' abc');
TRIM(LEADING 'abc' FROM ' abc')
abc
SELECT TRIM(BOTH 'abc' FROM 'abc');
TRIM(BOTH 'abc' FROM 'abc')
NULL
SELECT TRIM(BOTH 'abc' FROM 'abc ');
TRIM(BOTH 'abc' FROM 'abc ')
SELECT TRIM(BOTH 'abc' FROM ' abc');
TRIM(BOTH 'abc' FROM ' abc')
SELECT RTRIM('abc'), RTRIM('abc ')||'.', RTRIM(' abc ')||'.', RTRIM(' '), RTRIM(NULL), RTRIM(SPACE(0)),RTRIM(SPACE(10)) FROM dual;
RTRIM('abc') RTRIM('abc ')||'.' RTRIM(' abc ')||'.' RTRIM(' ') RTRIM(NULL) RTRIM(SPACE(0)) RTRIM(SPACE(10))
abc abc. abc. NULL NULL NULL NULL
SELECT LTRIM('abc'), LTRIM('abc '), LTRIM(' abc '), LTRIM(' '), LTRIM(NULL), LTRIM(SPACE(0)),LTRIM(SPACE(10)) FROM dual;
LTRIM('abc') LTRIM('abc ') LTRIM(' abc ') LTRIM(' ') LTRIM(NULL) LTRIM(SPACE(0)) LTRIM(SPACE(10))
abc abc abc NULL NULL NULL NULL
CREATE TABLE t1 (c1 VARCHAR(10),ord INTEGER);
INSERT INTO t1 VALUES ('abc',1);
INSERT INTO t1 VALUES (SPACE(0),2);
INSERT INTO t1 VALUES ('',3);
INSERT INTO t1 VALUES (' ',4);
INSERT INTO t1 VALUES (' ',5);
INSERT INTO t1 VALUES (' a ',6);
INSERT INTO t1 VALUES ('aa',7);
INSERT INTO t1 VALUES ('aabb',8);
INSERT INTO t1 VALUES ('bbaa',9);
INSERT INTO t1 VALUES ('aabbaa',10);
SELECT ord,'['||c1||']','.'||COALESCE(TRIM(LEADING 'a' FROM c1),'NULL')||'.' FROM t1 ORDER BY ord;
ord '['||c1||']' '.'||COALESCE(TRIM(LEADING 'a' FROM c1),'NULL')||'.'
1 [abc] .bc.
2 [] .NULL.
3 [] .NULL.
4 [ ] . .
5 [ ] . .
6 [ a ] . a .
7 [aa] .NULL.
8 [aabb] .bb.
9 [bbaa] .bbaa.
10 [aabbaa] .bbaa.
SELECT ord,'['||c1||']','.'||COALESCE(TRIM(TRAILING 'a' FROM c1),'NULL')||'.' FROM t1 ORDER BY ord;
ord '['||c1||']' '.'||COALESCE(TRIM(TRAILING 'a' FROM c1),'NULL')||'.'
1 [abc] .abc.
2 [] .NULL.
3 [] .NULL.
4 [ ] . .
5 [ ] . .
6 [ a ] . a .
7 [aa] .NULL.
8 [aabb] .aabb.
9 [bbaa] .bb.
10 [aabbaa] .aabb.
SELECT ord,'['||c1||']','.'||COALESCE(TRIM(BOTH 'a' FROM c1),'NULL')||'.' FROM t1 ORDER BY ord;
ord '['||c1||']' '.'||COALESCE(TRIM(BOTH 'a' FROM c1),'NULL')||'.'
1 [abc] .bc.
2 [] .NULL.
3 [] .NULL.
4 [ ] . .
5 [ ] . .
6 [ a ] . a .
7 [aa] .NULL.
8 [aabb] .bb.
9 [bbaa] .bb.
10 [aabbaa] .bb.
SELECT ord,'['||c1||']',COALESCE(LTRIM(c1),'NULL') FROM t1 ORDER BY ord;
ord '['||c1||']' COALESCE(LTRIM(c1),'NULL')
1 [abc] abc
2 [] NULL
3 [] NULL
4 [ ] NULL
5 [ ] NULL
6 [ a ] a
7 [aa] aa
8 [aabb] aabb
9 [bbaa] bbaa
10 [aabbaa] aabbaa
SELECT ord,'['||c1||']',COALESCE(RTRIM(c1),'NULL')||'.' FROM t1 ORDER BY ord;
ord '['||c1||']' COALESCE(RTRIM(c1),'NULL')||'.'
1 [abc] abc.
2 [] NULL.
3 [] NULL.
4 [ ] NULL.
5 [ ] NULL.
6 [ a ] a.
7 [aa] aa.
8 [aabb] aabb.
9 [bbaa] bbaa.
10 [aabbaa] aabbaa.
EXPLAIN EXTENDED SELECT TRIM('abc'),
TRIM(BOTH 'a' FROM 'abc'),
TRIM(LEADING 'a' FROM 'abc'),
TRIM(TRAILING 'a' FROM 'abc') ;
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 trim_oracle('abc') AS "TRIM('abc')",trim_oracle(both 'a' from 'abc') AS "TRIM(BOTH 'a' FROM 'abc')",trim_oracle(leading 'a' from 'abc') AS "TRIM(LEADING 'a' FROM 'abc')",trim_oracle(trailing 'a' from 'abc') AS "TRIM(TRAILING 'a' FROM 'abc')"
EXPLAIN EXTENDED SELECT RTRIM('abc'),
LTRIM('abc');
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 rtrim_oracle('abc') AS "RTRIM('abc')",ltrim_oracle('abc') AS "LTRIM('abc')"
CREATE VIEW v1 AS SELECT ord,TRIM('abc'),RTRIM('abc'),LTRIM('abc'),
'['||c1||']',
TRIM(LEADING 'a' FROM c1),
TRIM(TRAILING 'a' FROM c1),
TRIM(BOTH 'a' FROM c1),
LTRIM(c1),
RTRIM(c1)
FROM t1 ORDER BY ord ;
SHOW CREATE VIEW v1;
View Create View character_set_client collation_connection
v1 CREATE VIEW "v1" AS select "t1"."ord" AS "ord",trim_oracle('abc') AS "TRIM('abc')",rtrim_oracle('abc') AS "RTRIM('abc')",ltrim_oracle('abc') AS "LTRIM('abc')",concat_operator_oracle(concat_operator_oracle('[',"t1"."c1"),']') AS "'['||c1||']'",trim_oracle(leading 'a' from "t1"."c1") AS "TRIM(LEADING 'a' FROM c1)",trim_oracle(trailing 'a' from "t1"."c1") AS "TRIM(TRAILING 'a' FROM c1)",trim_oracle(both 'a' from "t1"."c1") AS "TRIM(BOTH 'a' FROM c1)",ltrim_oracle("t1"."c1") AS "LTRIM(c1)",rtrim_oracle("t1"."c1") AS "RTRIM(c1)" from "t1" order by "t1"."ord" latin1 latin1_swedish_ci
SELECT * FROM v1;
ord TRIM('abc') RTRIM('abc') LTRIM('abc') '['||c1||']' TRIM(LEADING 'a' FROM c1) TRIM(TRAILING 'a' FROM c1) TRIM(BOTH 'a' FROM c1) LTRIM(c1) RTRIM(c1)
1 abc abc abc [abc] bc abc bc abc abc
2 abc abc abc [] NULL NULL NULL NULL NULL
3 abc abc abc [] NULL NULL NULL NULL NULL
4 abc abc abc [ ] NULL NULL
5 abc abc abc [ ] NULL NULL
6 abc abc abc [ a ] a a a a a
7 abc abc abc [aa] NULL NULL NULL aa aa
8 abc abc abc [aabb] bb aabb bb aabb aabb
9 abc abc abc [bbaa] bbaa bb bb bbaa bbaa
10 abc abc abc [aabbaa] bbaa aabb bb aabbaa aabbaa
DROP VIEW v1;
DROP TABLE t1;
CREATE TABLE t1 (c1 VARCHAR(10) NOT NULL);
CREATE TABLE t2 AS SELECT TRIM(LEADING 'a' FROM c1) AS C1,
TRIM(TRAILING 'a' FROM c1) AS C2,
TRIM(BOTH 'a' FROM c1) AS C3,
LTRIM(c1) AS C4,
RTRIM(c1) AS C5
FROM t1;
SHOW CREATE TABLE t2;
Table Create Table
t2 CREATE TABLE "t2" (
"C1" varchar(10) DEFAULT NULL,
"C2" varchar(10) DEFAULT NULL,
"C3" varchar(10) DEFAULT NULL,
"C4" varchar(10) DEFAULT NULL,
"C5" varchar(10) DEFAULT NULL
)
DROP TABLE t2;
DROP TABLE t1;
CREATE TABLE trim_oracle (trim_oracle int);
DROP TABLE trim_oracle;
SET sql_mode=ORACLE;
--echo #
--echo # MDEV-15664 sql_mode=ORACLE: Make TRIM return NULL instead of empty string
--echo #
SELECT TRIM('abc'), TRIM('abc ')||'.', '.'||TRIM(' abc ')||'.', TRIM(' '), TRIM(NULL), TRIM(SPACE(0)),TRIM(SPACE(10)) FROM dual;
SELECT TRIM(TRAILING 'abc' FROM 'abc');
SELECT TRIM(TRAILING 'abc' FROM 'abc ');
SELECT TRIM(TRAILING 'abc' FROM ' abc');
SELECT TRIM(LEADING 'abc' FROM 'abc');
SELECT TRIM(LEADING 'abc' FROM 'abc ');
SELECT TRIM(LEADING 'abc' FROM ' abc');
SELECT TRIM(BOTH 'abc' FROM 'abc');
SELECT TRIM(BOTH 'abc' FROM 'abc ');
SELECT TRIM(BOTH 'abc' FROM ' abc');
SELECT RTRIM('abc'), RTRIM('abc ')||'.', RTRIM(' abc ')||'.', RTRIM(' '), RTRIM(NULL), RTRIM(SPACE(0)),RTRIM(SPACE(10)) FROM dual;
SELECT LTRIM('abc'), LTRIM('abc '), LTRIM(' abc '), LTRIM(' '), LTRIM(NULL), LTRIM(SPACE(0)),LTRIM(SPACE(10)) FROM dual;
CREATE TABLE t1 (c1 VARCHAR(10),ord INTEGER);
INSERT INTO t1 VALUES ('abc',1);
INSERT INTO t1 VALUES (SPACE(0),2);
INSERT INTO t1 VALUES ('',3);
INSERT INTO t1 VALUES (' ',4);
INSERT INTO t1 VALUES (' ',5);
INSERT INTO t1 VALUES (' a ',6);
INSERT INTO t1 VALUES ('aa',7);
INSERT INTO t1 VALUES ('aabb',8);
INSERT INTO t1 VALUES ('bbaa',9);
INSERT INTO t1 VALUES ('aabbaa',10);
SELECT ord,'['||c1||']','.'||COALESCE(TRIM(LEADING 'a' FROM c1),'NULL')||'.' FROM t1 ORDER BY ord;
SELECT ord,'['||c1||']','.'||COALESCE(TRIM(TRAILING 'a' FROM c1),'NULL')||'.' FROM t1 ORDER BY ord;
SELECT ord,'['||c1||']','.'||COALESCE(TRIM(BOTH 'a' FROM c1),'NULL')||'.' FROM t1 ORDER BY ord;
SELECT ord,'['||c1||']',COALESCE(LTRIM(c1),'NULL') FROM t1 ORDER BY ord;
SELECT ord,'['||c1||']',COALESCE(RTRIM(c1),'NULL')||'.' FROM t1 ORDER BY ord;
EXPLAIN EXTENDED SELECT TRIM('abc'),
TRIM(BOTH 'a' FROM 'abc'),
TRIM(LEADING 'a' FROM 'abc'),
TRIM(TRAILING 'a' FROM 'abc') ;
EXPLAIN EXTENDED SELECT RTRIM('abc'),
LTRIM('abc');
CREATE VIEW v1 AS SELECT ord,TRIM('abc'),RTRIM('abc'),LTRIM('abc'),
'['||c1||']',
TRIM(LEADING 'a' FROM c1),
TRIM(TRAILING 'a' FROM c1),
TRIM(BOTH 'a' FROM c1),
LTRIM(c1),
RTRIM(c1)
FROM t1 ORDER BY ord ;
SHOW CREATE VIEW v1;
SELECT * FROM v1;
DROP VIEW v1;
DROP TABLE t1;
CREATE TABLE t1 (c1 VARCHAR(10) NOT NULL);
CREATE TABLE t2 AS SELECT TRIM(LEADING 'a' FROM c1) AS C1,
TRIM(TRAILING 'a' FROM c1) AS C2,
TRIM(BOTH 'a' FROM c1) AS C3,
LTRIM(c1) AS C4,
RTRIM(c1) AS C5
FROM t1;
SHOW CREATE TABLE t2;
DROP TABLE t2;
DROP TABLE t1;
CREATE TABLE trim_oracle (trim_oracle int);
DROP TABLE trim_oracle;
......@@ -1360,6 +1360,13 @@ CREATE TABLE t1 (a INT);
CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW SET @@NEW.a=0;
DROP TABLE t1;
--echo #
--echo # MDEV-15664 sql_mode=ORACLE: Make TRIM return NULL instead of empty string
--echo #
CREATE TABLE trim_oracle (trim_oracle int);
DROP TABLE trim_oracle;
--echo #
--echo # MDEV-15615 Unexpected syntax error instead of "Unknown system variable" inside an SP
--echo #
......
......@@ -2218,6 +2218,19 @@ class Create_func_ltrim : public Create_func_arg1
};
class Create_func_ltrim_oracle : public Create_func_arg1
{
public:
virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_ltrim_oracle s_singleton;
protected:
Create_func_ltrim_oracle() {}
virtual ~Create_func_ltrim_oracle() {}
};
class Create_func_makedate : public Create_func_arg2
{
public:
......@@ -2658,6 +2671,19 @@ class Create_func_rtrim : public Create_func_arg1
};
class Create_func_rtrim_oracle : public Create_func_arg1
{
public:
virtual Item *create_1_arg(THD *thd, Item *arg1);
static Create_func_rtrim_oracle s_singleton;
protected:
Create_func_rtrim_oracle() {}
virtual ~Create_func_rtrim_oracle() {}
};
class Create_func_sec_to_time : public Create_func_arg1
{
public:
......@@ -5821,7 +5847,16 @@ Create_func_ltrim Create_func_ltrim::s_singleton;
Item*
Create_func_ltrim::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_ltrim(thd, arg1);
return Lex_trim(TRIM_LEADING, arg1).make_item_func_trim(thd);
}
Create_func_ltrim_oracle Create_func_ltrim_oracle::s_singleton;
Item*
Create_func_ltrim_oracle::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_ltrim_oracle(thd, arg1);
}
......@@ -6318,7 +6353,16 @@ Create_func_rtrim Create_func_rtrim::s_singleton;
Item*
Create_func_rtrim::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_rtrim(thd, arg1);
return Lex_trim(TRIM_TRAILING, arg1).make_item_func_trim(thd);
}
Create_func_rtrim_oracle Create_func_rtrim_oracle::s_singleton;
Item*
Create_func_rtrim_oracle::create_1_arg(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_rtrim_oracle(thd, arg1);
}
......@@ -6978,6 +7022,7 @@ static Native_func_registry func_array[] =
{ { STRING_WITH_LEN("LOWER") }, BUILDER(Create_func_lcase)},
{ { STRING_WITH_LEN("LPAD") }, BUILDER(Create_func_lpad)},
{ { STRING_WITH_LEN("LTRIM") }, BUILDER(Create_func_ltrim)},
{ { STRING_WITH_LEN("LTRIM_ORACLE") }, BUILDER(Create_func_ltrim_oracle)},
{ { STRING_WITH_LEN("MAKEDATE") }, BUILDER(Create_func_makedate)},
{ { STRING_WITH_LEN("MAKETIME") }, BUILDER(Create_func_maketime)},
{ { STRING_WITH_LEN("MAKE_SET") }, BUILDER(Create_func_make_set)},
......@@ -7042,6 +7087,7 @@ static Native_func_registry func_array[] =
{ { STRING_WITH_LEN("ROUND") }, BUILDER(Create_func_round)},
{ { STRING_WITH_LEN("RPAD") }, BUILDER(Create_func_rpad)},
{ { STRING_WITH_LEN("RTRIM") }, BUILDER(Create_func_rtrim)},
{ { STRING_WITH_LEN("RTRIM_ORACLE") }, BUILDER(Create_func_rtrim_oracle)},
{ { STRING_WITH_LEN("SEC_TO_TIME") }, BUILDER(Create_func_sec_to_time)},
{ { STRING_WITH_LEN("SHA") }, BUILDER(Create_func_sha)},
{ { STRING_WITH_LEN("SHA1") }, BUILDER(Create_func_sha)},
......
......@@ -2116,6 +2116,7 @@ void Item_func_trim::print(String *str, enum_query_type query_type)
return;
}
str->append(Item_func_trim::func_name());
str->append(func_name_ext());
str->append('(');
str->append(mode_name());
str->append(' ');
......
......@@ -539,6 +539,9 @@ class Item_func_trim :public Item_str_func
String remove;
String *trimmed_value(String *res, uint32 offset, uint32 length)
{
if (length == 0)
return make_empty_result();
tmp_value.set(*res, offset, length);
/*
Make sure to return correct charset and collation:
......@@ -552,6 +555,7 @@ class Item_func_trim :public Item_str_func
{
return trimmed_value(res, 0, res->length());
}
virtual const char *func_name_ext() const { return ""; }
public:
Item_func_trim(THD *thd, Item *a, Item *b): Item_str_func(thd, a, b) {}
Item_func_trim(THD *thd, Item *a): Item_str_func(thd, a) {}
......@@ -565,6 +569,27 @@ class Item_func_trim :public Item_str_func
};
class Item_func_trim_oracle :public Item_func_trim
{
protected:
String *make_empty_result()
{ null_value= 1; return NULL; }
const char *func_name_ext() const { return "_oracle"; }
public:
Item_func_trim_oracle(THD *thd, Item *a, Item *b):
Item_func_trim(thd, a, b) {}
Item_func_trim_oracle(THD *thd, Item *a): Item_func_trim(thd, a) {}
const char *func_name() const { return "trim_oracle"; }
void fix_length_and_dec()
{
Item_func_trim::fix_length_and_dec();
maybe_null= true;
}
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_trim_oracle>(thd, this); }
};
class Item_func_ltrim :public Item_func_trim
{
public:
......@@ -578,6 +603,27 @@ class Item_func_ltrim :public Item_func_trim
};
class Item_func_ltrim_oracle :public Item_func_ltrim
{
protected:
String *make_empty_result()
{ null_value= 1; return NULL; }
const char *func_name_ext() const { return "_oracle"; }
public:
Item_func_ltrim_oracle(THD *thd, Item *a, Item *b):
Item_func_ltrim(thd, a, b) {}
Item_func_ltrim_oracle(THD *thd, Item *a): Item_func_ltrim(thd, a) {}
const char *func_name() const { return "ltrim_oracle"; }
void fix_length_and_dec()
{
Item_func_ltrim::fix_length_and_dec();
maybe_null= true;
}
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_ltrim_oracle>(thd, this); }
};
class Item_func_rtrim :public Item_func_trim
{
public:
......@@ -591,6 +637,26 @@ class Item_func_rtrim :public Item_func_trim
};
class Item_func_rtrim_oracle :public Item_func_rtrim
{
protected:
String *make_empty_result()
{ null_value= 1; return NULL; }
const char *func_name_ext() const { return "_oracle"; }
public:
Item_func_rtrim_oracle(THD *thd, Item *a, Item *b):
Item_func_rtrim(thd, a, b) {}
Item_func_rtrim_oracle(THD *thd, Item *a): Item_func_rtrim(thd, a) {}
const char *func_name() const { return "rtrim_oracle"; }
void fix_length_and_dec()
{
Item_func_rtrim::fix_length_and_dec();
maybe_null= true;
}
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_rtrim_oracle>(thd, this); }
};
/*
Item_func_password -- new (4.1.1) PASSWORD() function implementation.
Returns strcat('*', octet2hex(sha1(sha1(password)))). '*' stands for new
......
......@@ -771,6 +771,7 @@ static SYMBOL sql_functions[] = {
{ "SYSDATE", SYM(SYSDATE)},
{ "SYSTEM_USER", SYM(USER_SYM)},
{ "TRIM", SYM(TRIM)},
{ "TRIM_ORACLE", SYM(TRIM_ORACLE)},
{ "VARIANCE", SYM(VARIANCE_SYM)},
{ "VAR_POP", SYM(VARIANCE_SYM)},
{ "VAR_SAMP", SYM(VAR_SAMP_SYM)},
......
......@@ -7702,3 +7702,64 @@ bool SELECT_LEX::vers_push_field(THD *thd, TABLE_LIST *table, const LEX_CSTRING
return false;
}
Item *Lex_trim_st::make_item_func_trim_std(THD *thd) const
{
if (m_remove)
{
switch (m_spec) {
case TRIM_BOTH:
return new (thd->mem_root) Item_func_trim(thd, m_source, m_remove);
case TRIM_LEADING:
return new (thd->mem_root) Item_func_ltrim(thd, m_source, m_remove);
case TRIM_TRAILING:
return new (thd->mem_root) Item_func_rtrim(thd, m_source, m_remove);
}
}
switch (m_spec) {
case TRIM_BOTH:
return new (thd->mem_root) Item_func_trim(thd, m_source);
case TRIM_LEADING:
return new (thd->mem_root) Item_func_ltrim(thd, m_source);
case TRIM_TRAILING:
return new (thd->mem_root) Item_func_rtrim(thd, m_source);
}
DBUG_ASSERT(0);
return NULL;
}
Item *Lex_trim_st::make_item_func_trim_oracle(THD *thd) const
{
if (m_remove)
{
switch (m_spec) {
case TRIM_BOTH:
return new (thd->mem_root) Item_func_trim_oracle(thd, m_source, m_remove);
case TRIM_LEADING:
return new (thd->mem_root) Item_func_ltrim_oracle(thd, m_source, m_remove);
case TRIM_TRAILING:
return new (thd->mem_root) Item_func_rtrim_oracle(thd, m_source, m_remove);
}
}
switch (m_spec) {
case TRIM_BOTH:
return new (thd->mem_root) Item_func_trim_oracle(thd, m_source);
case TRIM_LEADING:
return new (thd->mem_root) Item_func_ltrim_oracle(thd, m_source);
case TRIM_TRAILING:
return new (thd->mem_root) Item_func_rtrim_oracle(thd, m_source);
}
DBUG_ASSERT(0);
return NULL;
}
Item *Lex_trim_st::make_item_func_trim(THD *thd) const
{
return (thd->variables.sql_mode & MODE_ORACLE) ?
make_item_func_trim_oracle(thd) :
make_item_func_trim_std(thd);
}
......@@ -788,6 +788,7 @@ Virtual_column_info *add_virtual_expression(THD *thd, Item *expr)
Lex_dyncol_type_st Lex_dyncol_type;
Lex_for_loop_st for_loop;
Lex_for_loop_bounds_st for_loop_bounds;
Lex_trim_st trim;
struct
{
LEX_CSTRING name;
......@@ -1555,6 +1556,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
%token TRIGGERS_SYM
%token TRIGGER_SYM /* SQL-2003-R */
%token TRIM /* SQL-2003-N */
%token TRIM_ORACLE
%token TRUE_SYM /* SQL-2003-R */
%token TRUNCATE_SYM
%token TYPES_SYM
......@@ -1988,6 +1990,7 @@ END_OF_INPUT
%type <spvar> sp_param_name sp_param_name_and_type
%type <for_loop> sp_for_loop_index_and_bounds
%type <for_loop_bounds> sp_for_loop_bounds
%type <trim> trim_operands
%type <num> opt_sp_for_loop_direction
%type <spvar_mode> sp_opt_inout
%type <index_hint> index_hint_type
......@@ -9896,6 +9899,17 @@ dyncall_create_list:
}
;
trim_operands:
expr { $$.set(TRIM_BOTH, $1); }
| LEADING expr FROM expr { $$.set(TRIM_LEADING, $2, $4); }
| TRAILING expr FROM expr { $$.set(TRIM_TRAILING, $2, $4); }
| BOTH expr FROM expr { $$.set(TRIM_BOTH, $2, $4); }
| LEADING FROM expr { $$.set(TRIM_LEADING, $3); }
| TRAILING FROM expr { $$.set(TRIM_TRAILING, $3); }
| BOTH FROM expr { $$.set(TRIM_BOTH, $3); }
| expr FROM expr { $$.set(TRIM_BOTH, $1, $3); }
;
/*
Expressions that the parser allows in a column DEFAULT clause
without parentheses. These expressions cannot end with a COLLATE clause.
......@@ -10239,52 +10253,9 @@ function_call_keyword:
{
$$= $1;
}
| TRIM '(' expr ')'
{
$$= new (thd->mem_root) Item_func_trim(thd, $3);
if ($$ == NULL)
MYSQL_YYABORT;
}
| TRIM '(' LEADING expr FROM expr ')'
{
$$= new (thd->mem_root) Item_func_ltrim(thd, $6, $4);
if ($$ == NULL)
MYSQL_YYABORT;
}
| TRIM '(' TRAILING expr FROM expr ')'
{
$$= new (thd->mem_root) Item_func_rtrim(thd, $6, $4);
if ($$ == NULL)
MYSQL_YYABORT;
}
| TRIM '(' BOTH expr FROM expr ')'
{
$$= new (thd->mem_root) Item_func_trim(thd, $6, $4);
if ($$ == NULL)
MYSQL_YYABORT;
}
| TRIM '(' LEADING FROM expr ')'
| TRIM '(' trim_operands ')'
{
$$= new (thd->mem_root) Item_func_ltrim(thd, $5);
if ($$ == NULL)
MYSQL_YYABORT;
}
| TRIM '(' TRAILING FROM expr ')'
{
$$= new (thd->mem_root) Item_func_rtrim(thd, $5);
if ($$ == NULL)
MYSQL_YYABORT;
}
| TRIM '(' BOTH FROM expr ')'
{
$$= new (thd->mem_root) Item_func_trim(thd, $5);
if ($$ == NULL)
MYSQL_YYABORT;
}
| TRIM '(' expr FROM expr ')'
{
$$= new (thd->mem_root) Item_func_trim(thd, $5, $3);
if ($$ == NULL)
if (!($$= $3.make_item_func_trim(thd)))
MYSQL_YYABORT;
}
| USER_SYM '(' ')'
......@@ -10463,6 +10434,11 @@ function_call_nonkeyword:
if ($$ == NULL)
MYSQL_YYABORT;
}
| TRIM_ORACLE '(' trim_operands ')'
{
if (!($$= $3.make_item_func_trim_oracle(thd)))
MYSQL_YYABORT;
}
| UTC_DATE_SYM optional_braces
{
$$= new (thd->mem_root) Item_func_curdate_utc(thd);
......@@ -15764,6 +15740,7 @@ keyword_sp_not_data_type:
| TRANSACTION_SYM {}
| TRANSACTIONAL_SYM {}
| TRIGGERS_SYM {}
| TRIM_ORACLE {}
| TIMESTAMP_ADD {}
| TIMESTAMP_DIFF {}
| TYPES_SYM {}
......
......@@ -180,6 +180,7 @@ void ORAerror(THD *thd, const char *s)
Lex_dyncol_type_st Lex_dyncol_type;
Lex_for_loop_st for_loop;
Lex_for_loop_bounds_st for_loop_bounds;
Lex_trim_st trim;
struct
{
LEX_CSTRING name;
......@@ -945,6 +946,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
%token TRIGGERS_SYM
%token TRIGGER_SYM /* SQL-2003-R */
%token TRIM /* SQL-2003-N */
%token TRIM_ORACLE
%token TRUE_SYM /* SQL-2003-R */
%token TRUNCATE_SYM
%token TYPES_SYM
......@@ -1405,6 +1407,7 @@ END_OF_INPUT
%type <spvar> sp_param_name sp_param_name_and_type
%type <for_loop> sp_for_loop_index_and_bounds
%type <for_loop_bounds> sp_for_loop_bounds
%type <trim> trim_operands
%type <num> opt_sp_for_loop_direction
%type <spvar_mode> sp_opt_inout
%type <index_hint> index_hint_type
......@@ -9675,6 +9678,17 @@ explicit_cursor_attr:
}
;
trim_operands:
expr { $$.set(TRIM_BOTH, $1); }
| LEADING expr FROM expr { $$.set(TRIM_LEADING, $2, $4); }
| TRAILING expr FROM expr { $$.set(TRIM_TRAILING, $2, $4); }
| BOTH expr FROM expr { $$.set(TRIM_BOTH, $2, $4); }
| LEADING FROM expr { $$.set(TRIM_LEADING, $3); }
| TRAILING FROM expr { $$.set(TRIM_TRAILING, $3); }
| BOTH FROM expr { $$.set(TRIM_BOTH, $3); }
| expr FROM expr { $$.set(TRIM_BOTH, $1, $3); }
;
/*
Expressions that the parser allows in a column DEFAULT clause
without parentheses. These expressions cannot end with a COLLATE clause.
......@@ -10040,52 +10054,9 @@ function_call_keyword:
if ($$ == NULL)
MYSQL_YYABORT;
}
| TRIM '(' expr ')'
{
$$= new (thd->mem_root) Item_func_trim(thd, $3);
if ($$ == NULL)
MYSQL_YYABORT;
}
| TRIM '(' LEADING expr FROM expr ')'
{
$$= new (thd->mem_root) Item_func_ltrim(thd, $6, $4);
if ($$ == NULL)
MYSQL_YYABORT;
}
| TRIM '(' TRAILING expr FROM expr ')'
{
$$= new (thd->mem_root) Item_func_rtrim(thd, $6, $4);
if ($$ == NULL)
MYSQL_YYABORT;
}
| TRIM '(' BOTH expr FROM expr ')'
{
$$= new (thd->mem_root) Item_func_trim(thd, $6, $4);
if ($$ == NULL)
MYSQL_YYABORT;
}
| TRIM '(' LEADING FROM expr ')'
| TRIM '(' trim_operands ')'
{
$$= new (thd->mem_root) Item_func_ltrim(thd, $5);
if ($$ == NULL)
MYSQL_YYABORT;
}
| TRIM '(' TRAILING FROM expr ')'
{
$$= new (thd->mem_root) Item_func_rtrim(thd, $5);
if ($$ == NULL)
MYSQL_YYABORT;
}
| TRIM '(' BOTH FROM expr ')'
{
$$= new (thd->mem_root) Item_func_trim(thd, $5);
if ($$ == NULL)
MYSQL_YYABORT;
}
| TRIM '(' expr FROM expr ')'
{
$$= new (thd->mem_root) Item_func_trim(thd, $5, $3);
if ($$ == NULL)
if (!($$= $3.make_item_func_trim(thd)))
MYSQL_YYABORT;
}
| USER_SYM '(' ')'
......@@ -10246,6 +10217,11 @@ function_call_nonkeyword:
if ($$ == NULL)
MYSQL_YYABORT;
}
| TRIM_ORACLE '(' trim_operands ')'
{
if (!($$= $3.make_item_func_trim_oracle(thd)))
MYSQL_YYABORT;
}
| UTC_DATE_SYM optional_braces
{
$$= new (thd->mem_root) Item_func_curdate_utc(thd);
......@@ -15572,6 +15548,7 @@ keyword_sp_not_data_type:
| TRANSACTION_SYM {}
| TRANSACTIONAL_SYM {}
| TRIGGERS_SYM {}
| TRIM_ORACLE {}
| TIMESTAMP_ADD {}
| TIMESTAMP_DIFF {}
| TYPES_SYM {}
......
......@@ -723,6 +723,37 @@ struct Lex_for_loop_st
};
enum trim_spec { TRIM_LEADING, TRIM_TRAILING, TRIM_BOTH };
struct Lex_trim_st
{
Item *m_remove;
Item *m_source;
trim_spec m_spec;
public:
void set(trim_spec spec, Item *remove, Item *source)
{
m_spec= spec;
m_remove= remove;
m_source= source;
}
void set(trim_spec spec, Item *source)
{
set(spec, NULL, source);
}
Item *make_item_func_trim_std(THD *thd) const;
Item *make_item_func_trim_oracle(THD *thd) const;
Item *make_item_func_trim(THD *thd) const;
};
class Lex_trim: public Lex_trim_st
{
public:
Lex_trim(trim_spec spec, Item *source) { set(spec, source); }
};
struct Lex_string_with_pos_st: public LEX_CSTRING
{
const char *m_pos;
......
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