Skip to content

Commit

Permalink
MDEV-15739 sql_mode=ORACLE: Make LPAD and RPAD return NULL instead of…
Browse files Browse the repository at this point in the history
… empty string
  • Loading branch information
halfspawn authored and abarkov committed Apr 3, 2018
1 parent 1eee986 commit 94ecd23
Show file tree
Hide file tree
Showing 4 changed files with 246 additions and 8 deletions.
71 changes: 71 additions & 0 deletions mysql-test/suite/compat/oracle/r/func_pad.result
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
SET sql_mode=ORACLE;
#
# MDEV-15739 - sql_mode=ORACLE: Make LPAD and RPAD return NULL instead of empty string
#
SELECT RPAD('a',0), RPAD('abc',1), RPAD('abc',2) ;
RPAD('a',0) RPAD('abc',1) RPAD('abc',2)
NULL a ab
SELECT RPAD('a',0,'.'), RPAD('abc',1,'.'), RPAD('abc',2,'.') ;
RPAD('a',0,'.') RPAD('abc',1,'.') RPAD('abc',2,'.')
NULL a ab
SELECT LPAD('a',0), LPAD('abc',1), LPAD('abc',2) ;
LPAD('a',0) LPAD('abc',1) LPAD('abc',2)
NULL a ab
SELECT LPAD('a',0,'.'), LPAD('abc',1,'.'), LPAD('abc',2,'.') ;
LPAD('a',0,'.') LPAD('abc',1,'.') LPAD('abc',2,'.')
NULL a ab
CREATE TABLE t1 (c1 VARCHAR(10),c2 INTEGER, c3 VARCHAR(10), ord INTEGER);
INSERT INTO t1 VALUES ('a',1,null,1);
INSERT INTO t1 VALUES ('a',null,'.',2);
INSERT INTO t1 VALUES (null,1,'.',3);
INSERT INTO t1 VALUES ('a',-1,'.',4);
INSERT INTO t1 VALUES ('a',0,'.',5);
INSERT INTO t1 VALUES ('a',1,'.',6);
INSERT INTO t1 VALUES ('a',2,'.',7);
SELECT LPAD(c1,c2,c3), LPAD(c1,c2) FROM t1 ORDER BY ord;
LPAD(c1,c2,c3) LPAD(c1,c2)
NULL a
NULL NULL
NULL NULL
NULL NULL
NULL NULL
a a
.a a
SELECT RPAD(c1,c2,c3), RPAD(c1,c2) FROM t1 ORDER BY ord;
RPAD(c1,c2,c3) RPAD(c1,c2)
NULL a
NULL NULL
NULL NULL
NULL NULL
NULL NULL
a a
a. a
EXPLAIN EXTENDED SELECT RPAD('a',0,'.'), LPAD('a',0,'.'), LPAD(c1,c2,c3), LPAD(c1,c2), RPAD(c1,c2,c3), RPAD(c1,c2) FROM t1 ORDER BY ord;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 7 100.00 Using filesort
Warnings:
Note 1003 select rpad_oracle('a',0,'.') AS "RPAD('a',0,'.')",lpad_oracle('a',0,'.') AS "LPAD('a',0,'.')",lpad_oracle("test"."t1"."c1","test"."t1"."c2","test"."t1"."c3") AS "LPAD(c1,c2,c3)",lpad_oracle("test"."t1"."c1","test"."t1"."c2") AS "LPAD(c1,c2)",rpad_oracle("test"."t1"."c1","test"."t1"."c2","test"."t1"."c3") AS "RPAD(c1,c2,c3)",rpad_oracle("test"."t1"."c1","test"."t1"."c2") AS "RPAD(c1,c2)" from "test"."t1" order by "test"."t1"."ord"
CREATE VIEW v1 AS SELECT RPAD('a',0,'.') AS "C1", LPAD('a',0,'.') AS "C2", LPAD(c1,c2,c3) AS "C3", LPAD(c1,c2) AS "C4", RPAD(c1,c2,c3) AS "C5", RPAD(c1,c2) AS "C6" FROM t1 ORDER BY ord;
SHOW CREATE VIEW v1;
View Create View character_set_client collation_connection
v1 CREATE VIEW "v1" AS select rpad_oracle('a',0,'.') AS "C1",lpad_oracle('a',0,'.') AS "C2",lpad_oracle("t1"."c1","t1"."c2","t1"."c3") AS "C3",lpad_oracle("t1"."c1","t1"."c2") AS "C4",rpad_oracle("t1"."c1","t1"."c2","t1"."c3") AS "C5",rpad_oracle("t1"."c1","t1"."c2") AS "C6" from "t1" order by "t1"."ord" latin1 latin1_swedish_ci
SELECT * FROM v1;
C1 C2 C3 C4 C5 C6
NULL NULL NULL a NULL a
NULL NULL NULL NULL NULL NULL
NULL NULL NULL NULL NULL NULL
NULL NULL NULL NULL NULL NULL
NULL NULL NULL NULL NULL NULL
NULL NULL a a a a
NULL NULL .a a a. a
SELECT c1||'-'||c2||'-'||c3||'-'||c4||'-'||c5||'-'||c6 FROM v1;
c1||'-'||c2||'-'||c3||'-'||c4||'-'||c5||'-'||c6
---a--a
-----
-----
-----
-----
--a-a-a-a
--.a- a-a.-a
DROP VIEW v1;
DROP TABLE t1;
31 changes: 31 additions & 0 deletions mysql-test/suite/compat/oracle/t/func_pad.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
SET sql_mode=ORACLE;

--echo #
--echo # MDEV-15739 - sql_mode=ORACLE: Make LPAD and RPAD return NULL instead of empty string
--echo #

SELECT RPAD('a',0), RPAD('abc',1), RPAD('abc',2) ;
SELECT RPAD('a',0,'.'), RPAD('abc',1,'.'), RPAD('abc',2,'.') ;
SELECT LPAD('a',0), LPAD('abc',1), LPAD('abc',2) ;
SELECT LPAD('a',0,'.'), LPAD('abc',1,'.'), LPAD('abc',2,'.') ;

CREATE TABLE t1 (c1 VARCHAR(10),c2 INTEGER, c3 VARCHAR(10), ord INTEGER);
INSERT INTO t1 VALUES ('a',1,null,1);
INSERT INTO t1 VALUES ('a',null,'.',2);
INSERT INTO t1 VALUES (null,1,'.',3);
INSERT INTO t1 VALUES ('a',-1,'.',4);
INSERT INTO t1 VALUES ('a',0,'.',5);
INSERT INTO t1 VALUES ('a',1,'.',6);
INSERT INTO t1 VALUES ('a',2,'.',7);

SELECT LPAD(c1,c2,c3), LPAD(c1,c2) FROM t1 ORDER BY ord;
SELECT RPAD(c1,c2,c3), RPAD(c1,c2) FROM t1 ORDER BY ord;

EXPLAIN EXTENDED SELECT RPAD('a',0,'.'), LPAD('a',0,'.'), LPAD(c1,c2,c3), LPAD(c1,c2), RPAD(c1,c2,c3), RPAD(c1,c2) FROM t1 ORDER BY ord;

CREATE VIEW v1 AS SELECT RPAD('a',0,'.') AS "C1", LPAD('a',0,'.') AS "C2", LPAD(c1,c2,c3) AS "C3", LPAD(c1,c2) AS "C4", RPAD(c1,c2,c3) AS "C5", RPAD(c1,c2) AS "C6" FROM t1 ORDER BY ord;
SHOW CREATE VIEW v1;
SELECT * FROM v1;
SELECT c1||'-'||c2||'-'||c3||'-'||c4||'-'||c5||'-'||c6 FROM v1;
DROP VIEW v1;
DROP TABLE t1;
112 changes: 104 additions & 8 deletions sql/item_create.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2195,13 +2195,30 @@ class Create_func_lpad : public Create_native_func
{
public:
virtual Item *create_native(THD *thd, LEX_CSTRING *name,
List<Item> *item_list);

List<Item> *item_list)
{
return thd->variables.sql_mode & MODE_ORACLE ?
create_native_oracle(thd, name, item_list) :
create_native_std(thd, name, item_list);
}
static Create_func_lpad s_singleton;

protected:
Create_func_lpad() {}
virtual ~Create_func_lpad() {}
Item *create_native_std(THD *thd, LEX_CSTRING *name, List<Item> *items);
Item *create_native_oracle(THD *thd, LEX_CSTRING *name, List<Item> *items);
};


class Create_func_lpad_oracle : public Create_func_lpad
{
public:
Item *create_native(THD *thd, LEX_CSTRING *name, List<Item> *item_list)
{
return create_native_oracle(thd, name, item_list);
}
static Create_func_lpad_oracle s_singleton;
};


Expand Down Expand Up @@ -2648,13 +2665,30 @@ class Create_func_rpad : public Create_native_func
{
public:
virtual Item *create_native(THD *thd, LEX_CSTRING *name,
List<Item> *item_list);

List<Item> *item_list)
{
return thd->variables.sql_mode & MODE_ORACLE ?
create_native_oracle(thd, name, item_list) :
create_native_std(thd, name, item_list);
}
static Create_func_rpad s_singleton;

protected:
Create_func_rpad() {}
virtual ~Create_func_rpad() {}
Item *create_native_std(THD *thd, LEX_CSTRING *name, List<Item> *items);
Item *create_native_oracle(THD *thd, LEX_CSTRING *name, List<Item> *items);
};


class Create_func_rpad_oracle : public Create_func_rpad
{
public:
Item *create_native(THD *thd, LEX_CSTRING *name, List<Item> *item_list)
{
return create_native_oracle(thd, name, item_list);
}
static Create_func_rpad_oracle s_singleton;
};


Expand Down Expand Up @@ -5810,9 +5844,11 @@ Create_func_log2::create_1_arg(THD *thd, Item *arg1)

Create_func_lpad Create_func_lpad::s_singleton;

Create_func_lpad_oracle Create_func_lpad_oracle::s_singleton;

Item*
Create_func_lpad::create_native(THD *thd, LEX_CSTRING *name,
List<Item> *item_list)
Create_func_lpad::create_native_std(THD *thd, LEX_CSTRING *name,
List<Item> *item_list)
{
Item *func= NULL;
int arg_count= item_list ? item_list->elements : 0;
Expand Down Expand Up @@ -5842,6 +5878,34 @@ Create_func_lpad::create_native(THD *thd, LEX_CSTRING *name,
}


Item*
Create_func_lpad::create_native_oracle(THD *thd, LEX_CSTRING *name,
List<Item> *item_list)
{
int arg_count= item_list ? item_list->elements : 0;
switch (arg_count) {
case 2:
{
Item *param_1= item_list->pop();
Item *param_2= item_list->pop();
return new (thd->mem_root) Item_func_lpad_oracle(thd, param_1, param_2);
}
case 3:
{
Item *param_1= item_list->pop();
Item *param_2= item_list->pop();
Item *param_3= item_list->pop();
return new (thd->mem_root) Item_func_lpad_oracle(thd, param_1,
param_2, param_3);
}
default:
my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name->str);
break;
}
return NULL;
}


Create_func_ltrim Create_func_ltrim::s_singleton;

Item*
Expand Down Expand Up @@ -6316,9 +6380,11 @@ Create_func_round::create_native(THD *thd, LEX_CSTRING *name,

Create_func_rpad Create_func_rpad::s_singleton;

Create_func_rpad_oracle Create_func_rpad_oracle::s_singleton;

Item*
Create_func_rpad::create_native(THD *thd, LEX_CSTRING *name,
List<Item> *item_list)
Create_func_rpad::create_native_std(THD *thd, LEX_CSTRING *name,
List<Item> *item_list)
{
Item *func= NULL;
int arg_count= item_list ? item_list->elements : 0;
Expand Down Expand Up @@ -6348,6 +6414,34 @@ Create_func_rpad::create_native(THD *thd, LEX_CSTRING *name,
}


Item*
Create_func_rpad::create_native_oracle(THD *thd, LEX_CSTRING *name,
List<Item> *item_list)
{
int arg_count= item_list ? item_list->elements : 0;
switch (arg_count) {
case 2:
{
Item *param_1= item_list->pop();
Item *param_2= item_list->pop();
return new (thd->mem_root) Item_func_rpad_oracle(thd, param_1, param_2);
}
case 3:
{
Item *param_1= item_list->pop();
Item *param_2= item_list->pop();
Item *param_3= item_list->pop();
return new (thd->mem_root) Item_func_rpad_oracle(thd, param_1,
param_2, param_3);
}
default:
my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name->str);
break;
}
return NULL;
}


Create_func_rtrim Create_func_rtrim::s_singleton;

Item*
Expand Down Expand Up @@ -7021,6 +7115,7 @@ static Native_func_registry func_array[] =
{ { STRING_WITH_LEN("LOG2") }, BUILDER(Create_func_log2)},
{ { STRING_WITH_LEN("LOWER") }, BUILDER(Create_func_lcase)},
{ { STRING_WITH_LEN("LPAD") }, BUILDER(Create_func_lpad)},
{ { STRING_WITH_LEN("LPAD_ORACLE") }, BUILDER(Create_func_lpad_oracle)},
{ { 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)},
Expand Down Expand Up @@ -7086,6 +7181,7 @@ static Native_func_registry func_array[] =
{ { STRING_WITH_LEN("REVERSE") }, BUILDER(Create_func_reverse)},
{ { STRING_WITH_LEN("ROUND") }, BUILDER(Create_func_round)},
{ { STRING_WITH_LEN("RPAD") }, BUILDER(Create_func_rpad)},
{ { STRING_WITH_LEN("RPAD_ORACLE") }, BUILDER(Create_func_rpad_oracle)},
{ { 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)},
Expand Down
40 changes: 40 additions & 0 deletions sql/item_strfunc.h
Original file line number Diff line number Diff line change
Expand Up @@ -1120,6 +1120,26 @@ class Item_func_rpad :public Item_func_pad
};


class Item_func_rpad_oracle :public Item_func_rpad
{
String *make_empty_result()
{ null_value= 1; return NULL; }
public:
Item_func_rpad_oracle(THD *thd, Item *arg1, Item *arg2, Item *arg3):
Item_func_rpad(thd, arg1, arg2, arg3) {}
Item_func_rpad_oracle(THD *thd, Item *arg1, Item *arg2):
Item_func_rpad(thd, arg1, arg2) {}
void fix_length_and_dec()
{
Item_func_rpad::fix_length_and_dec();
maybe_null= true;
}
const char *func_name() const { return "rpad_oracle"; }
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_rpad_oracle>(thd, this); }
};


class Item_func_lpad :public Item_func_pad
{
public:
Expand All @@ -1134,6 +1154,26 @@ class Item_func_lpad :public Item_func_pad
};


class Item_func_lpad_oracle :public Item_func_lpad
{
String *make_empty_result()
{ null_value= 1; return NULL; }
public:
Item_func_lpad_oracle(THD *thd, Item *arg1, Item *arg2, Item *arg3):
Item_func_lpad(thd, arg1, arg2, arg3) {}
Item_func_lpad_oracle(THD *thd, Item *arg1, Item *arg2):
Item_func_lpad(thd, arg1, arg2) {}
void fix_length_and_dec()
{
Item_func_lpad::fix_length_and_dec();
maybe_null= true;
}
const char *func_name() const { return "lpad_oracle"; }
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_lpad_oracle>(thd, this); }
};


class Item_func_conv :public Item_str_func
{
public:
Expand Down

0 comments on commit 94ecd23

Please sign in to comment.