diff --git a/mysql-test/suite/compat/oracle/r/empty-string.result b/mysql-test/suite/compat/oracle/r/empty-string.result
new file mode 100644
index 0000000..4560492
--- /dev/null
+++ b/mysql-test/suite/compat/oracle/r/empty-string.result
@@ -0,0 +1,294 @@
+use test;
+#
+# MDEV-10574 sql_mode=ORACLE: IS NULL and empty strings
+#
+set session character_set_connection=latin2;
+set session character_set_client=cp1250;
+Test litteral
+SET sql_mode=ORACLE;
+select '',charset(''), null, charset(null), cast(null as varchar(10)), charset(cast(null as varchar(10))), 'x', charset('x');
+NULL	charset('')	NULL	charset(null)	cast(null as varchar(10))	charset(cast(null as varchar(10)))	x	charset('x')
+NULL	latin2	NULL	binary	NULL	latin2	x	latin2
+SET sql_mode=default;
+select '',charset(''), null, charset(null), cast(null as char(10)), charset(cast(null as char(10))), 'x', charset('x');
+	charset('')	NULL	charset(null)	cast(null as char(10))	charset(cast(null as char(10)))	x	charset('x')
+	latin2	NULL	binary	NULL	latin2	x	latin2
+Test NCHAR litteral
+SET sql_mode=ORACLE;
+select N'',charset(N''), N'x', charset(N'x');
+NULL	charset(N'')	x	charset(N'x')
+NULL	utf8	x	utf8
+SET sql_mode=default;
+select N'',charset(N''), N'x', charset(N'x');
+	charset(N'')	x	charset(N'x')
+	utf8	x	utf8
+Test charset prefix litteral
+SET sql_mode=ORACLE;
+select _cp1250 '',charset(_cp1250 ''), _cp1250 'x', charset(_cp1250 'x');
+NULL	charset(_cp1250 '')	x	charset(_cp1250 'x')
+NULL	cp1250	x	cp1250
+SET sql_mode=default;
+select _cp1250 '',charset(_cp1250 ''), _cp1250 'x', charset(_cp1250 'x');
+	charset(_cp1250 '')	x	charset(_cp1250 'x')
+	cp1250	x	cp1250
+SET sql_mode=ORACLE;
+Test of basic string function that must return null with '' in input
+select nvl(ascii(''),-1) from dual;
+nvl(ascii(''),-1)
+-1
+select nvl(cast('' as int),-1) from dual;
+nvl(cast('' as int),-1)
+-1
+select concat('','x'),nvl(concat('',''),'is null') from dual;
+concat('','x')	nvl(concat('',''),'is null')
+x	is null
+select nvl(instr('abc',''),-1) from dual;
+nvl(instr('abc',''),-1)
+-1
+select nvl(instr('',''),-1) from dual;
+nvl(instr('',''),-1)
+-1
+select nvl(instr('','b'),-1) from dual;
+nvl(instr('','b'),-1)
+-1
+select nvl(left('a',0),'is null') from dual;
+nvl(left('a',0),'is null')
+is null
+select nvl(length(''),-1) from dual;
+nvl(length(''),-1)
+-1
+select nvl(lpad('',10,' '),'is null'),
+nvl(lpad('',10,''),'is null'),
+nvl(lpad('x',10,''),'is null'),
+nvl(lpad('x',0,' '),'is null')
+from dual;
+nvl(lpad('',10,' '),'is null')	nvl(lpad('',10,''),'is null')	nvl(lpad('x',10,''),'is null')	nvl(lpad('x',0,' '),'is null')
+is null	is null	is null	is null
+select nvl(mid('abc',1,0),'is null') from dual;
+nvl(mid('abc',1,0),'is null')
+is null
+select nvl(mid('abc',10,1),'is null') from dual;
+nvl(mid('abc',10,1),'is null')
+is null
+select nvl(right('a',0),'is null') from dual;
+nvl(right('a',0),'is null')
+is null
+select nvl(rpad('',10,' '),'is null'),
+nvl(rpad('',10,''),'is null'),
+nvl(rpad('x',10,''),'is null'),
+nvl(rpad('x',0,' '),'is null')
+from dual;
+nvl(rpad('',10,' '),'is null')	nvl(rpad('',10,''),'is null')	nvl(rpad('x',10,''),'is null')	nvl(rpad('x',0,' '),'is null')
+is null	is null	is null	is null
+select nvl(replace('abc','a',''),'is null'),
+nvl(replace('abc','','x'),'is null'),
+nvl(replace('','a','b'),'is null'),
+nvl(replace('','','b'),'is null'),
+nvl(replace('','',''),'is null'),
+nvl(replace('aaa','a',null),'is null')
+from dual;
+nvl(replace('abc','a',''),'is null')	nvl(replace('abc','','x'),'is null')	nvl(replace('','a','b'),'is null')	nvl(replace('','','b'),'is null')	nvl(replace('','',''),'is null')	nvl(replace('aaa','a',null),'is null')
+bc	abc	is null	is null	is null	is null
+select nvl(substr('abc',1,0),'is null'),
+nvl(substr('abc',10,2),'is null'),
+nvl(substr('abc',0,2),'is null')
+from dual;
+nvl(substr('abc',1,0),'is null')	nvl(substr('abc',10,2),'is null')	nvl(substr('abc',0,2),'is null')
+is null	is null	ab
+Test substr with start at 0
+select nvl(substr('abc',0,0),'is null'),
+nvl(substr('abc',0,2),'is null'),
+nvl(substr('',0,2),'is null')
+from dual;
+nvl(substr('abc',0,0),'is null')	nvl(substr('abc',0,2),'is null')	nvl(substr('',0,2),'is null')
+is null	ab	is null
+select nvl(trim(''),'is null'),
+nvl(rtrim(''),'is null'),
+nvl(ltrim(''),'is null') from dual;
+nvl(trim(''),'is null')	nvl(rtrim(''),'is null')	nvl(ltrim(''),'is null')
+is null	is null	is null
+Test default on column
+create table t1 (c1 varchar(10) default '');
+show create table t1;
+Table	Create Table
+t1	CREATE TABLE "t1" (
+  "c1" varchar(10) DEFAULT NULL
+)
+drop table t1;
+Test on table
+create table t1(sqlmode varchar(10),ord int,act varchar(10),c1 varchar(10),c2 varchar(10), c3 varchar(10), i1 int,i2 int);
+insert into t1 values ('ORACLE',1,'substr','abc', null,null, 0,    2);
+insert into t1 values ('ORACLE',0,'substr','abc', null,null, 0,    0);
+insert into t1 values ('ORACLE',2,'substr',''   , null,null, 0,    2);
+insert into t1 values ('ORACLE',3,'substr','abc', null,null, 0,    2);
+insert into t1 values ('ORACLE',4,'substr','abc', null,null, 10,   2);
+insert into t1 values ('ORACLE',5,'substr','abc', null,null, 1,    0);
+insert into t1 values ('ORACLE',1,'lpad',  '',    ' ', null, 10,   null);
+insert into t1 values ('ORACLE',2,'lpad',  '',    '',  null, 10,   null);
+insert into t1 values ('ORACLE',3,'lpad',  'x',   '',  null, 10,   null);
+insert into t1 values ('ORACLE',3,'lpad',  'x',   ' ', null,  0,    null);
+insert into t1 values ('ORACLE',1,'rpad',  '',    ' ', null, 10,   null);
+insert into t1 values ('ORACLE',3,'rpad',  '',    '',  null, 10,   null);
+insert into t1 values ('ORACLE',4,'rpad',  'x',   '',  null, 10,   null);
+insert into t1 values ('ORACLE',3,'rpad',  'x',   ' ', null,  0,    null);
+insert into t1 values ('ORACLE',1,'trim',  '',    null,null, null, null);
+insert into t1 values ('ORACLE',1,'rtrim', '',    null,null, null, null);
+insert into t1 values ('ORACLE',1,'ltrim', '',    null,null, null, null);
+insert into t1 values ('ORACLE',1,'length','',    null,null, null, null);
+insert into t1 values ('ORACLE',1,'instr', 'abc', '',  null, null, null);
+insert into t1 values ('ORACLE',2,'instr', '',    '',  null, null, null);
+insert into t1 values ('ORACLE',2,'instr', '',    'b', null, null, null);
+insert into t1 values ('ORACLE',1,'ascii', '',    null,null, null, null);
+insert into t1 values ('ORACLE',1,'cast',  '',    null,null, null, null);
+insert into t1 values ('ORACLE',1,'concat','',    '',  null, null, null);
+insert into t1 values ('ORACLE',1,'replace','aa', 'a', null, null, null);
+insert into t1 values ('ORACLE',1,'replace','aax','a', 'c' , null, null);
+insert into t1 values ('ORACLE',1,'replace',null, 'a', 'c' , null, null);
+set sql_mode=default;
+insert into t1 values ('DEFAULT',1,'concat','',    '',  '',  null, null);
+set sql_mode=oracle;
+select sqlmode||' '||act||'('||c1||','||i1||','||i2||')',nvl(substr(c1,i1,i2),'is null')  from t1 where act='substr' and sqlmode='ORACLE' order by ord;
+sqlmode||' '||act||'('||c1||','||i1||','||i2||')'	nvl(substr(c1,i1,i2),'is null')
+ORACLE substr(abc,0,0)	is null
+ORACLE substr(abc,0,2)	ab
+ORACLE substr(,0,2)	is null
+ORACLE substr(abc,0,2)	ab
+ORACLE substr(abc,10,2)	is null
+ORACLE substr(abc,1,0)	is null
+select sqlmode||' '||act||'('||c1||','||i1||','||c2||')',nvl(lpad(c1,i1,c2),'is null')    from t1 where act='lpad'   and sqlmode='ORACLE' order by ord;
+sqlmode||' '||act||'('||c1||','||i1||','||c2||')'	nvl(lpad(c1,i1,c2),'is null')
+ORACLE lpad(,10, )	is null
+ORACLE lpad(,10,)	is null
+ORACLE lpad(x,10,)	is null
+ORACLE lpad(x,0, )	is null
+select sqlmode||' '||act||'('||c1||','||i1||','||c2||')',nvl(rpad(c1,i1,c2),'is null')    from t1 where act='rpad'   and sqlmode='ORACLE' order by ord;
+sqlmode||' '||act||'('||c1||','||i1||','||c2||')'	nvl(rpad(c1,i1,c2),'is null')
+ORACLE rpad(,10, )	is null
+ORACLE rpad(,10,)	is null
+ORACLE rpad(x,0, )	is null
+ORACLE rpad(x,10,)	is null
+select sqlmode||' '||act||'('||c1||')',nvl(trim(c1),'is null')                            from t1 where act='trim'   and sqlmode='ORACLE' order by ord;
+sqlmode||' '||act||'('||c1||')'	nvl(trim(c1),'is null')
+ORACLE trim()	is null
+select sqlmode||' '||act||'('||c1||')',nvl(ltrim(c1),'is null')                           from t1 where act='ltrim'  and sqlmode='ORACLE' order by ord;
+sqlmode||' '||act||'('||c1||')'	nvl(ltrim(c1),'is null')
+ORACLE ltrim()	is null
+select sqlmode||' '||act||'('||c1||')',nvl(rtrim(c1),'is null')                           from t1 where act='rtrim'  and sqlmode='ORACLE' order by ord;
+sqlmode||' '||act||'('||c1||')'	nvl(rtrim(c1),'is null')
+ORACLE rtrim()	is null
+select sqlmode||' '||act||'('||c1||')',nvl(length(c1),-1)                                 from t1 where act='length' and sqlmode='ORACLE' order by ord;
+sqlmode||' '||act||'('||c1||')'	nvl(length(c1),-1)
+ORACLE length()	-1
+select sqlmode||' '||act||'('||c1||','||c2||')',nvl(instr(c1,c2),'is null')               from t1 where act='instr'  and sqlmode='ORACLE' order by ord;
+sqlmode||' '||act||'('||c1||','||c2||')'	nvl(instr(c1,c2),'is null')
+ORACLE instr(abc,)	is null
+ORACLE instr(,)	is null
+ORACLE instr(,b)	is null
+select sqlmode||' '||act||'('||c1||')',nvl(ascii(c1),-1)                                  from t1 where act='ascii'  and sqlmode='ORACLE' order by ord;
+sqlmode||' '||act||'('||c1||')'	nvl(ascii(c1),-1)
+ORACLE ascii()	-1
+select sqlmode||' '||act||'('||c1||')',nvl(cast(c1 as int),-1)                            from t1 where act='cast'   and sqlmode='ORACLE' order by ord;
+sqlmode||' '||act||'('||c1||')'	nvl(cast(c1 as int),-1)
+ORACLE cast()	-1
+select sqlmode||' '||act||'('||c1||','||c2||')',nvl(concat(c1,c2),'is null')              from t1 where act='concat' and sqlmode='ORACLE' order by ord;
+sqlmode||' '||act||'('||c1||','||c2||')'	nvl(concat(c1,c2),'is null')
+ORACLE concat(,)	is null
+select sqlmode||' '||act||'('||c1||','||c2||','||c3||')',nvl(replace(c1,c2,c3),'is null') from t1 where act='replace' and sqlmode='ORACLE' order by ord;
+sqlmode||' '||act||'('||c1||','||c2||','||c3||')'	nvl(replace(c1,c2,c3),'is null')
+ORACLE replace(aa,a,)	is null
+ORACLE replace(aax,a,c)	ccx
+ORACLE replace(,a,c)	is null
+rpad/lpad with 2 args
+select rpad('x',10),length(rpad('x',10)),
+lpad('y',15),length(lpad('y',15));
+rpad('x',10)	length(rpad('x',10))	lpad('y',15)	length(lpad('y',15))
+x         	10	              y	15
+rpad/lpad with 3 args
+select rpad('x',10,'.'),length(rpad('x',10,'.')),
+lpad('y',15,'.'),length(lpad('y',15,'.'));
+rpad('x',10,'.')	length(rpad('x',10,'.'))	lpad('y',15,'.')	length(lpad('y',15,'.'))
+x.........	10	..............y	15
+set sql_mode=default;
+select rpad('x',10,'.'),length(rpad('x',10,'.')),
+lpad('y',15,'.'),length(lpad('y',15,'.'));
+rpad('x',10,'.')	length(rpad('x',10,'.'))	lpad('y',15,'.')	length(lpad('y',15,'.'))
+x.........	10	..............y	15
+set sql_mode=oracle;
+Check parameter rpad / lpad
+select rpad('x');
+ERROR 42000: Incorrect parameter count in the call to native function 'rpad'
+select rpad('x',2,'.','z');
+ERROR 42000: Incorrect parameter count in the call to native function 'rpad'
+select lpad('x');
+ERROR 42000: Incorrect parameter count in the call to native function 'lpad'
+select lpad('x',2,'.','z');
+ERROR 42000: Incorrect parameter count in the call to native function 'lpad'
+select sqlmode||' '||act||'('||c1||','||i1||')',nvl(lpad(c1,i1),'is null'),length(lpad(c1,i1))
+from t1 where act='lpad'   and sqlmode='ORACLE' order by ord;
+sqlmode||' '||act||'('||c1||','||i1||')'	nvl(lpad(c1,i1),'is null')	length(lpad(c1,i1))
+ORACLE lpad(,10)	is null	NULL
+ORACLE lpad(,10)	is null	NULL
+ORACLE lpad(x,10)	         x	10
+ORACLE lpad(x,0)	is null	NULL
+select sqlmode||' '||act||'('||c1||','||i1||')',nvl(rpad(c1,i1),'is null'),length(rpad(c1,i1))
+from t1 where act='rpad'   and sqlmode='ORACLE' order by ord;
+sqlmode||' '||act||'('||c1||','||i1||')'	nvl(rpad(c1,i1),'is null')	length(rpad(c1,i1))
+ORACLE rpad(,10)	is null	NULL
+ORACLE rpad(,10)	is null	NULL
+ORACLE rpad(x,0)	is null	NULL
+ORACLE rpad(x,10)	x         	10
+select count(*) from t1 where c1='';
+count(*)
+0
+select count(*) from t1 where c1!='';
+count(*)
+0
+select count(*) from t1 where c1 is null;
+count(*)
+15
+select count(*) from t1 where c1 is not null;
+count(*)
+13
+select count(*) from t1 where c2 is null;
+count(*)
+19
+select count(*) from t1 where c2 is not null;
+count(*)
+9
+select count(*) from t1 where c1=c2;
+count(*)
+1
+select count(*) from t1 where c1!=c2;
+count(*)
+4
+Ways to select null and empty string in Oracle mode
+select * from t1 where substr(c1,1) is null and sqlmode='DEFAULT';
+sqlmode	ord	act	c1	c2	c3	i1	i2
+DEFAULT	1	concat				NULL	NULL
+select * from t1 where trim(c1) is null and sqlmode='DEFAULT';
+sqlmode	ord	act	c1	c2	c3	i1	i2
+DEFAULT	1	concat				NULL	NULL
+select * from t1 where rtrim(c1) is null and sqlmode='DEFAULT';
+sqlmode	ord	act	c1	c2	c3	i1	i2
+DEFAULT	1	concat				NULL	NULL
+select * from t1 where ltrim(c1) is null and sqlmode='DEFAULT';
+sqlmode	ord	act	c1	c2	c3	i1	i2
+DEFAULT	1	concat				NULL	NULL
+Ways to only select empty string in Oracle mode
+select * from t1 where length(c1)=0 and sqlmode='DEFAULT';
+sqlmode	ord	act	c1	c2	c3	i1	i2
+DEFAULT	1	concat				NULL	NULL
+select * from t1 where ascii(c1)=0 and sqlmode='DEFAULT';
+sqlmode	ord	act	c1	c2	c3	i1	i2
+DEFAULT	1	concat				NULL	NULL
+length() semantic on oracle is equal to char_length()
+create oracle lengthb function similar to length()
+set sql_mode=default;
+select length('a'), length(_ucs2 'a'), char_length('a'), char_length(_ucs2 'a'),lengthb('a'), lengthb(_ucs2 'a');
+length('a')	length(_ucs2 'a')	char_length('a')	char_length(_ucs2 'a')	lengthb('a')	lengthb(_ucs2 'a')
+1	2	1	1	1	2
+set sql_mode=oracle;
+select length('a'), length(_ucs2 'a'), char_length('a'), char_length(_ucs2 'a'),lengthb('a'), lengthb(_ucs2 'a');
+length('a')	length(_ucs2 'a')	char_length('a')	char_length(_ucs2 'a')	lengthb('a')	lengthb(_ucs2 'a')
+1	1	1	1	1	2
+drop table t1;
diff --git a/mysql-test/suite/compat/oracle/r/func_concat.result b/mysql-test/suite/compat/oracle/r/func_concat.result
index 230b36b..565fcae 100644
--- a/mysql-test/suite/compat/oracle/r/func_concat.result
+++ b/mysql-test/suite/compat/oracle/r/func_concat.result
@@ -11,13 +11,13 @@ Warnings:
 Note	1003	select concat_operator_oracle(concat_operator_oracle(concat_operator_oracle('a','b'),'c')) AS "CONCAT('a'||'b'||'c')"
 SELECT ''   || '';
 ''   || ''
-
+NULL
 SELECT ''   || 'b';
 ''   || 'b'
 b
 SELECT ''   || NULL;
 ''   || NULL
-
+NULL
 SELECT 'a'  || '';
 'a'  || ''
 a
@@ -29,7 +29,7 @@ SELECT 'a'  || NULL;
 a
 SELECT NULL || '';
 NULL || ''
-
+NULL
 SELECT NULL || 'b';
 NULL || 'b'
 b
@@ -38,13 +38,13 @@ NULL || NULL
 NULL
 SELECT ''   || ''    || '';
 ''   || ''    || ''
-
+NULL
 SELECT ''   || ''    || 'c';
 ''   || ''    || 'c'
 c
 SELECT ''   || ''    || NULL;
 ''   || ''    || NULL
-
+NULL
 SELECT ''   || 'b'   || '';
 ''   || 'b'   || ''
 b
@@ -56,13 +56,13 @@ SELECT ''   || 'b'   || NULL;
 b
 SELECT ''   || NULL  || '';
 ''   || NULL  || ''
-
+NULL
 SELECT ''   || NULL  || 'c';
 ''   || NULL  || 'c'
 c
 SELECT ''   || NULL  || NULL;
 ''   || NULL  || NULL
-
+NULL
 SELECT 'a'  || ''    || '';
 'a'  || ''    || ''
 a
@@ -92,13 +92,13 @@ SELECT 'a'  || NULL  || NULL;
 a
 SELECT NULL || ''    || '';
 NULL || ''    || ''
-
+NULL
 SELECT NULL || ''    || 'c';
 NULL || ''    || 'c'
 c
 SELECT NULL || ''    || NULL;
 NULL || ''    || NULL
-
+NULL
 SELECT NULL || 'b'   || '';
 NULL || 'b'   || ''
 b
@@ -110,7 +110,7 @@ NULL || 'b'   || NULL
 b
 SELECT NULL || NULL  || '';
 NULL || NULL  || ''
-
+NULL
 SELECT NULL || NULL  || 'c';
 NULL || NULL  || 'c'
 c
@@ -148,58 +148,58 @@ INSERT INTO t1 VALUES (NULL, NULL, NULL);
 SELECT LENGTH(a||b||c), a||b||c FROM t1 ORDER BY a,b,c;
 LENGTH(a||b||c)	a||b||c
 NULL	NULL
-0	
+NULL	NULL
+NULL	NULL
+NULL	NULL
+NULL	NULL
+NULL	NULL
+NULL	NULL
+NULL	NULL
 1	c
-0	
-0	
 1	c
-1	b
-1	b
-2	bc
-0	
-0	
 1	c
-0	
-0	
 1	c
 1	b
 1	b
+1	b
+1	b
+2	bc
 2	bc
 1	a
 1	a
-2	ac
 1	a
 1	a
 2	ac
+2	ac
 2	ab
 2	ab
 3	abc
 SELECT LENGTH(CONCAT(a||b||c)), CONCAT(a||b||c) FROM t1 ORDER BY a,b,c;
 LENGTH(CONCAT(a||b||c))	CONCAT(a||b||c)
 NULL	NULL
-0	
+NULL	NULL
+NULL	NULL
+NULL	NULL
+NULL	NULL
+NULL	NULL
+NULL	NULL
+NULL	NULL
 1	c
-0	
-0	
 1	c
-1	b
-1	b
-2	bc
-0	
-0	
 1	c
-0	
-0	
 1	c
 1	b
 1	b
+1	b
+1	b
+2	bc
 2	bc
 1	a
 1	a
-2	ac
 1	a
 1	a
 2	ac
+2	ac
 2	ab
 2	ab
 3	abc
diff --git a/mysql-test/suite/compat/oracle/t/empty-string.test b/mysql-test/suite/compat/oracle/t/empty-string.test
new file mode 100644
index 0000000..e9e0ebc
--- /dev/null
+++ b/mysql-test/suite/compat/oracle/t/empty-string.test
@@ -0,0 +1,184 @@
+use test;
+--echo #
+--echo # MDEV-10574 sql_mode=ORACLE: IS NULL and empty strings
+--echo #
+set session character_set_connection=latin2;
+set session character_set_client=cp1250;
+--echo Test litteral
+SET sql_mode=ORACLE;
+select '',charset(''), null, charset(null), cast(null as varchar(10)), charset(cast(null as varchar(10))), 'x', charset('x');
+SET sql_mode=default;
+select '',charset(''), null, charset(null), cast(null as char(10)), charset(cast(null as char(10))), 'x', charset('x');
+
+--echo Test NCHAR litteral
+SET sql_mode=ORACLE;
+select N'',charset(N''), N'x', charset(N'x');
+SET sql_mode=default;
+select N'',charset(N''), N'x', charset(N'x');
+
+--echo Test charset prefix litteral
+SET sql_mode=ORACLE;
+select _cp1250 '',charset(_cp1250 ''), _cp1250 'x', charset(_cp1250 'x');
+SET sql_mode=default;
+select _cp1250 '',charset(_cp1250 ''), _cp1250 'x', charset(_cp1250 'x');
+
+SET sql_mode=ORACLE;
+--echo Test of basic string function that must return null with '' in input
+
+select nvl(ascii(''),-1) from dual;
+select nvl(cast('' as int),-1) from dual;
+select concat('','x'),nvl(concat('',''),'is null') from dual;
+select nvl(instr('abc',''),-1) from dual;
+select nvl(instr('',''),-1) from dual;
+select nvl(instr('','b'),-1) from dual;
+select nvl(left('a',0),'is null') from dual;
+select nvl(length(''),-1) from dual;
+
+select nvl(lpad('',10,' '),'is null'),
+       nvl(lpad('',10,''),'is null'),
+       nvl(lpad('x',10,''),'is null'),
+       nvl(lpad('x',0,' '),'is null')
+  from dual;
+
+select nvl(mid('abc',1,0),'is null') from dual;
+select nvl(mid('abc',10,1),'is null') from dual;
+select nvl(right('a',0),'is null') from dual;
+
+select nvl(rpad('',10,' '),'is null'),
+       nvl(rpad('',10,''),'is null'),
+       nvl(rpad('x',10,''),'is null'),
+       nvl(rpad('x',0,' '),'is null')
+  from dual;
+
+select nvl(replace('abc','a',''),'is null'),
+       nvl(replace('abc','','x'),'is null'),
+       nvl(replace('','a','b'),'is null'),
+       nvl(replace('','','b'),'is null'),
+       nvl(replace('','',''),'is null'),
+       nvl(replace('aaa','a',null),'is null')
+  from dual;
+
+select nvl(substr('abc',1,0),'is null'),
+       nvl(substr('abc',10,2),'is null'),
+       nvl(substr('abc',0,2),'is null')
+  from dual;
+
+--echo Test substr with start at 0
+select nvl(substr('abc',0,0),'is null'),
+       nvl(substr('abc',0,2),'is null'),
+       nvl(substr('',0,2),'is null')
+  from dual;
+
+select nvl(trim(''),'is null'),
+       nvl(rtrim(''),'is null'),
+       nvl(ltrim(''),'is null') from dual;
+
+--echo Test default on column
+create table t1 (c1 varchar(10) default '');
+show create table t1;
+drop table t1;
+
+--echo Test on table
+create table t1(sqlmode varchar(10),ord int,act varchar(10),c1 varchar(10),c2 varchar(10), c3 varchar(10), i1 int,i2 int);
+insert into t1 values ('ORACLE',1,'substr','abc', null,null, 0,    2);
+insert into t1 values ('ORACLE',0,'substr','abc', null,null, 0,    0);
+insert into t1 values ('ORACLE',2,'substr',''   , null,null, 0,    2);
+insert into t1 values ('ORACLE',3,'substr','abc', null,null, 0,    2);
+insert into t1 values ('ORACLE',4,'substr','abc', null,null, 10,   2);
+insert into t1 values ('ORACLE',5,'substr','abc', null,null, 1,    0);
+insert into t1 values ('ORACLE',1,'lpad',  '',    ' ', null, 10,   null);
+insert into t1 values ('ORACLE',2,'lpad',  '',    '',  null, 10,   null);
+insert into t1 values ('ORACLE',3,'lpad',  'x',   '',  null, 10,   null);
+insert into t1 values ('ORACLE',3,'lpad',  'x',   ' ', null,  0,    null);
+insert into t1 values ('ORACLE',1,'rpad',  '',    ' ', null, 10,   null);
+insert into t1 values ('ORACLE',3,'rpad',  '',    '',  null, 10,   null);
+insert into t1 values ('ORACLE',4,'rpad',  'x',   '',  null, 10,   null);
+insert into t1 values ('ORACLE',3,'rpad',  'x',   ' ', null,  0,    null);
+insert into t1 values ('ORACLE',1,'trim',  '',    null,null, null, null);
+insert into t1 values ('ORACLE',1,'rtrim', '',    null,null, null, null);
+insert into t1 values ('ORACLE',1,'ltrim', '',    null,null, null, null);
+insert into t1 values ('ORACLE',1,'length','',    null,null, null, null);
+insert into t1 values ('ORACLE',1,'instr', 'abc', '',  null, null, null);
+insert into t1 values ('ORACLE',2,'instr', '',    '',  null, null, null);
+insert into t1 values ('ORACLE',2,'instr', '',    'b', null, null, null);
+insert into t1 values ('ORACLE',1,'ascii', '',    null,null, null, null);
+insert into t1 values ('ORACLE',1,'cast',  '',    null,null, null, null);
+insert into t1 values ('ORACLE',1,'concat','',    '',  null, null, null);
+insert into t1 values ('ORACLE',1,'replace','aa', 'a', null, null, null);
+insert into t1 values ('ORACLE',1,'replace','aax','a', 'c' , null, null);
+insert into t1 values ('ORACLE',1,'replace',null, 'a', 'c' , null, null);
+set sql_mode=default;
+insert into t1 values ('DEFAULT',1,'concat','',    '',  '',  null, null);
+set sql_mode=oracle;
+
+select sqlmode||' '||act||'('||c1||','||i1||','||i2||')',nvl(substr(c1,i1,i2),'is null')  from t1 where act='substr' and sqlmode='ORACLE' order by ord;
+select sqlmode||' '||act||'('||c1||','||i1||','||c2||')',nvl(lpad(c1,i1,c2),'is null')    from t1 where act='lpad'   and sqlmode='ORACLE' order by ord;
+select sqlmode||' '||act||'('||c1||','||i1||','||c2||')',nvl(rpad(c1,i1,c2),'is null')    from t1 where act='rpad'   and sqlmode='ORACLE' order by ord;
+select sqlmode||' '||act||'('||c1||')',nvl(trim(c1),'is null')                            from t1 where act='trim'   and sqlmode='ORACLE' order by ord;
+select sqlmode||' '||act||'('||c1||')',nvl(ltrim(c1),'is null')                           from t1 where act='ltrim'  and sqlmode='ORACLE' order by ord;
+select sqlmode||' '||act||'('||c1||')',nvl(rtrim(c1),'is null')                           from t1 where act='rtrim'  and sqlmode='ORACLE' order by ord;
+select sqlmode||' '||act||'('||c1||')',nvl(length(c1),-1)                                 from t1 where act='length' and sqlmode='ORACLE' order by ord;
+select sqlmode||' '||act||'('||c1||','||c2||')',nvl(instr(c1,c2),'is null')               from t1 where act='instr'  and sqlmode='ORACLE' order by ord;
+select sqlmode||' '||act||'('||c1||')',nvl(ascii(c1),-1)                                  from t1 where act='ascii'  and sqlmode='ORACLE' order by ord;
+select sqlmode||' '||act||'('||c1||')',nvl(cast(c1 as int),-1)                            from t1 where act='cast'   and sqlmode='ORACLE' order by ord;
+select sqlmode||' '||act||'('||c1||','||c2||')',nvl(concat(c1,c2),'is null')              from t1 where act='concat' and sqlmode='ORACLE' order by ord;
+select sqlmode||' '||act||'('||c1||','||c2||','||c3||')',nvl(replace(c1,c2,c3),'is null') from t1 where act='replace' and sqlmode='ORACLE' order by ord;
+
+
+--echo rpad/lpad with 2 args
+select rpad('x',10),length(rpad('x',10)),
+       lpad('y',15),length(lpad('y',15));
+
+--echo rpad/lpad with 3 args
+select rpad('x',10,'.'),length(rpad('x',10,'.')),
+       lpad('y',15,'.'),length(lpad('y',15,'.'));
+set sql_mode=default;
+select rpad('x',10,'.'),length(rpad('x',10,'.')),
+       lpad('y',15,'.'),length(lpad('y',15,'.'));
+
+set sql_mode=oracle;
+--echo Check parameter rpad / lpad
+--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT
+select rpad('x');
+--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT
+select rpad('x',2,'.','z');
+
+--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT
+select lpad('x');
+--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT
+select lpad('x',2,'.','z');
+
+select sqlmode||' '||act||'('||c1||','||i1||')',nvl(lpad(c1,i1),'is null'),length(lpad(c1,i1))
+  from t1 where act='lpad'   and sqlmode='ORACLE' order by ord;
+select sqlmode||' '||act||'('||c1||','||i1||')',nvl(rpad(c1,i1),'is null'),length(rpad(c1,i1))
+  from t1 where act='rpad'   and sqlmode='ORACLE' order by ord;
+
+select count(*) from t1 where c1='';
+select count(*) from t1 where c1!='';
+select count(*) from t1 where c1 is null;
+select count(*) from t1 where c1 is not null;
+select count(*) from t1 where c2 is null;
+select count(*) from t1 where c2 is not null;
+select count(*) from t1 where c1=c2;
+select count(*) from t1 where c1!=c2;
+
+--echo Ways to select null and empty string in Oracle mode
+select * from t1 where substr(c1,1) is null and sqlmode='DEFAULT';
+select * from t1 where trim(c1) is null and sqlmode='DEFAULT';
+select * from t1 where rtrim(c1) is null and sqlmode='DEFAULT';
+select * from t1 where ltrim(c1) is null and sqlmode='DEFAULT';
+
+--echo Ways to only select empty string in Oracle mode
+select * from t1 where length(c1)=0 and sqlmode='DEFAULT';
+select * from t1 where ascii(c1)=0 and sqlmode='DEFAULT';
+
+--echo length() semantic on oracle is equal to char_length()
+--echo create oracle lengthb function similar to length()
+set sql_mode=default;
+select length('a'), length(_ucs2 'a'), char_length('a'), char_length(_ucs2 'a'),lengthb('a'), lengthb(_ucs2 'a');
+set sql_mode=oracle;
+select length('a'), length(_ucs2 'a'), char_length('a'), char_length(_ucs2 'a'),lengthb('a'), lengthb(_ucs2 'a');
+
+drop table t1;
+
+
diff --git a/sql/item_create.cc b/sql/item_create.cc
index 6eb0aac..2d0bbdc 100644
--- a/sql/item_create.cc
+++ b/sql/item_create.cc
@@ -461,7 +461,6 @@ class Create_func_binlog_gtid_pos : public Create_func_arg2
   virtual ~Create_func_binlog_gtid_pos() {}
 };
 
-
 class Create_func_bit_count : public Create_func_arg1
 {
 public:
@@ -515,6 +514,19 @@ class Create_func_centroid : public Create_func_arg1
 };
 
 
+class Create_func_chr : public Create_func_arg1
+{
+public:
+  virtual Item *create_1_arg(THD *thd, Item *arg1);
+
+  static Create_func_chr s_singleton;
+
+protected:
+  Create_func_chr() {}
+  virtual ~Create_func_chr() {}
+};
+
+
 class Create_func_convexhull : public Create_func_arg1
 {
 public:
@@ -2151,6 +2163,18 @@ class Create_func_length : public Create_func_arg1
   virtual ~Create_func_length() {}
 };
 
+class Create_func_lengthb : public Create_func_arg1
+{
+public:
+  virtual Item *create_1_arg(THD *thd, Item *arg1);
+
+  static Create_func_lengthb s_singleton;
+
+protected:
+  Create_func_lengthb() {}
+  virtual ~Create_func_lengthb() {}
+};
+
 
 #ifndef DBUG_OFF
 class Create_func_like_range_min : public Create_func_arg2
@@ -2258,10 +2282,10 @@ class Create_func_log2 : public Create_func_arg1
 };
 
 
-class Create_func_lpad : public Create_func_arg3
+class Create_func_lpad : public Create_native_func
 {
 public:
-  virtual Item *create_3_arg(THD *thd, Item *arg1, Item *arg2, Item *arg3);
+  virtual Item *create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
 
   static Create_func_lpad s_singleton;
 
@@ -2684,10 +2708,10 @@ class Create_func_round : public Create_native_func
 };
 
 
-class Create_func_rpad : public Create_func_arg3
+class Create_func_rpad : public Create_native_func
 {
 public:
-  virtual Item *create_3_arg(THD *thd, Item *arg1, Item *arg2, Item *arg3);
+  virtual Item *create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
 
   static Create_func_rpad s_singleton;
 
@@ -3746,7 +3770,6 @@ Create_func_binlog_gtid_pos::create_2_arg(THD *thd, Item *arg1, Item *arg2)
   return new (thd->mem_root) Item_func_binlog_gtid_pos(thd, arg1, arg2);
 }
 
-
 Create_func_bit_count Create_func_bit_count::s_singleton;
 
 Item*
@@ -3784,6 +3807,18 @@ Create_func_centroid::create_1_arg(THD *thd, Item *arg1)
 }
 
 
+Create_func_chr Create_func_chr::s_singleton;
+
+Item*
+Create_func_chr::create_1_arg(THD *thd, Item *arg1)
+{
+  List<Item> list;
+  list.empty();
+  list.push_front(arg1);
+  return new (thd->mem_root) Item_func_char(thd, list);
+}
+
+
 Create_func_convexhull Create_func_convexhull::s_singleton;
 
 Item*
@@ -5645,9 +5680,19 @@ Create_func_length Create_func_length::s_singleton;
 Item*
 Create_func_length::create_1_arg(THD *thd, Item *arg1)
 {
-  return new (thd->mem_root) Item_func_length(thd, arg1);
+  if (thd->variables.sql_mode & MODE_ORACLE)
+    return new (thd->mem_root) Item_func_char_length(thd, arg1);
+  else
+    return new (thd->mem_root) Item_func_length(thd, arg1);
 }
 
+Create_func_lengthb Create_func_lengthb::s_singleton;
+
+Item*
+Create_func_lengthb::create_1_arg(THD *thd, Item *arg1)
+{
+  return new (thd->mem_root) Item_func_length(thd, arg1);
+}
 
 #ifndef DBUG_OFF
 Create_func_like_range_min Create_func_like_range_min::s_singleton;
@@ -5789,9 +5834,37 @@ Create_func_log2::create_1_arg(THD *thd, Item *arg1)
 Create_func_lpad Create_func_lpad::s_singleton;
 
 Item*
-Create_func_lpad::create_3_arg(THD *thd, Item *arg1, Item *arg2, Item *arg3)
+Create_func_lpad::create_native(THD *thd, LEX_STRING name,
+                                List<Item> *item_list)
 {
-  return new (thd->mem_root) Item_func_lpad(thd, arg1, arg2, arg3);
+  Item *func= NULL;
+  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();
+    Item *param_3= new (thd->mem_root) Item_string(thd,
+                                                   param_1->collation.collation,
+                                                   " ", 1);
+    func= new (thd->mem_root) Item_func_lpad(thd, param_1, param_2, param_3);
+    break;
+  }
+  case 3:
+  {
+    Item *param_1= item_list->pop();
+    Item *param_2= item_list->pop();
+    Item *param_3= item_list->pop();
+    func= new (thd->mem_root) Item_func_lpad(thd, param_1, param_2, param_3);
+    break;
+  }
+  default:
+    my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name.str);
+    break;
+  }
+
+  return func;
 }
 
 
@@ -6251,9 +6324,37 @@ Create_func_round::create_native(THD *thd, LEX_STRING name,
 Create_func_rpad Create_func_rpad::s_singleton;
 
 Item*
-Create_func_rpad::create_3_arg(THD *thd, Item *arg1, Item *arg2, Item *arg3)
+Create_func_rpad::create_native(THD *thd, LEX_STRING name,
+                                List<Item> *item_list)
 {
-  return new (thd->mem_root) Item_func_rpad(thd, arg1, arg2, arg3);
+  Item *func= NULL;
+  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();
+    Item *param_3= new (thd->mem_root) Item_string(thd,
+                                                   param_1->collation.collation,
+                                                   " ", 1);
+    func= new (thd->mem_root) Item_func_rpad(thd, param_1, param_2, param_3);
+    break;
+  }
+  case 3:
+  {
+    Item *param_1= item_list->pop();
+    Item *param_2= item_list->pop();
+    Item *param_3= item_list->pop();
+    func= new (thd->mem_root) Item_func_rpad(thd, param_1, param_2, param_3);
+    break;
+  }
+  default:
+    my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name.str);
+    break;
+  }
+
+  return func;
 }
 
 
@@ -6777,6 +6878,7 @@ 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)},
@@ -6875,6 +6977,7 @@ static Native_func_registry func_array[] =
   { { C_STRING_WITH_LEN("LCASE") }, BUILDER(Create_func_lcase)},
   { { C_STRING_WITH_LEN("LEAST") }, BUILDER(Create_func_least)},
   { { C_STRING_WITH_LEN("LENGTH") }, BUILDER(Create_func_length)},
+  { { C_STRING_WITH_LEN("LENGTHB") }, BUILDER(Create_func_lengthb)},
 #ifndef DBUG_OFF
   { { C_STRING_WITH_LEN("LIKE_RANGE_MIN") }, BUILDER(Create_func_like_range_min)},
   { { C_STRING_WITH_LEN("LIKE_RANGE_MAX") }, BUILDER(Create_func_like_range_max)},
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index 215bc28..7b07c72 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -94,6 +94,31 @@ String *Item_func::val_str_from_val_str_ascii(String *str, String *str2)
   return str2;
 }
 
+/**
+    Sets the result value of the function an empty string, using the current
+    character set. No memory is allocated.
+    Sets result value to null when sql_mode=oracle.
+    @retval A pointer to the str_value member.
+  */
+String *Item_str_func::make_empty_result()
+{
+  /*
+    Reset string length to an empty string. We don't use str_value.set() as
+    we don't want to free and potentially have to reallocate the buffer
+    for each call.
+  */
+  str_value.set_charset(collation.collation);
+  if (! (current_thd->variables.sql_mode & MODE_ORACLE))
+  {
+    str_value.length(0);
+    return &str_value;
+  }
+  else
+  {
+    null_value= 1;
+    return NULL;
+  }
+}
 
 bool Item_str_func::fix_fields(THD *thd, Item **ref)
 {
@@ -1199,8 +1224,23 @@ void Item_func_reverse::fix_length_and_dec()
 
 String *Item_func_replace::val_str(String *str)
 {
+
+  if (args[1]->null_value)
+  {
+    null_value= 1;
+    return 0;
+  }
+  return replace_value(str,
+                       args[1]->val_str(&tmp_value),
+                       args[2]->val_str(&tmp_value2));
+}
+
+
+String *Item_func_replace::replace_value(String *str, String *res2,
+                                         String *res3)
+{
   DBUG_ASSERT(fixed == 1);
-  String *res,*res2,*res3;
+  String *res;
   int offset;
   uint from_length,to_length;
   bool alloced=0;
@@ -1215,9 +1255,6 @@ String *Item_func_replace::val_str(String *str)
   res=args[0]->val_str(str);
   if (args[0]->null_value)
     goto null;
-  res2=args[1]->val_str(&tmp_value);
-  if (args[1]->null_value)
-    goto null;
 
   res->set_charset(collation.collation);
 
@@ -1235,7 +1272,7 @@ String *Item_func_replace::val_str(String *str)
   if (binary_cmp && (offset=res->strstr(*res2)) < 0)
     return res;
 #endif
-  if (!(res3=args[2]->val_str(&tmp_value2)))
+  if (!res3)
     goto null;
   from_length= res2->length();
   to_length=   res3->length();
@@ -1343,6 +1380,18 @@ void Item_func_replace::fix_length_and_dec()
 }
 
 
+String *Item_func_replace_oracle::val_str(String *str)
+{
+  String * res;
+  if (res = replace_value(str,
+            args[1]->is_null() ? &tmp_emtpystr : args[1]->val_str(&tmp_value2),
+            args[2]->is_null() ? &tmp_emtpystr : args[2]->val_str(&tmp_value3)))
+    return (res->length() == 0) ? make_empty_result () : res;
+  else
+    return 0;
+}
+
+
 /*********************************************************************/
 void Item_func_regexp_replace::fix_length_and_dec()
 {
@@ -1741,10 +1790,14 @@ void Item_func_right::fix_length_and_dec()
 
 String *Item_func_substr::val_str(String *str)
 {
+  return substr_value(str, args[1]->val_int());
+}
+
+
+String *Item_func_substr::substr_value(String *str, longlong start)
+{
   DBUG_ASSERT(fixed == 1);
   String *res  = args[0]->val_str(str);
-  /* must be longlong to avoid truncation */
-  longlong start= args[1]->val_int();
   /* Assumes that the maximum length of a String is < INT_MAX32. */
   /* Limit so that code sees out-of-bound value properly. */
   longlong length= arg_count == 3 ? args[2]->val_int() : INT_MAX32;
@@ -1813,6 +1866,43 @@ void Item_func_substr::fix_length_and_dec()
   max_length*= collation.collation->mbmaxlen;
 }
 
+String *Item_func_substr_oracle::val_str(String *str)
+{
+  longlong start= args[1]->val_int();
+  return Item_func_substr::substr_value(str, start == 0 ? 1 : start);
+}
+
+
+void Item_func_substr_oracle::fix_length_and_dec()
+{
+  max_length= args[0]->max_length;
+
+  agg_arg_charsets_for_string_result(collation, args, 1);
+  DBUG_ASSERT(collation.collation != NULL);
+  if (args[1]->const_item())
+  {
+    int32 start= (int32) args[1]->val_int();
+    if (start == 0)
+      start= 1;
+
+    if (args[1]->null_value)
+      max_length= 0;
+    else if (start < 0)
+      max_length= ((uint)(-start) > max_length) ? 0 : (uint)(-start);
+    else
+      max_length-= MY_MIN((uint)(start - 1), max_length);
+  }
+  if (arg_count == 3 && args[2]->const_item())
+  {
+    int32 length= (int32) args[2]->val_int();
+    if (args[2]->null_value || length <= 0)
+      max_length= 0; /* purecov: inspected */
+    else
+      set_if_smaller(max_length, (uint) length);
+  }
+  max_length*= collation.collation->mbmaxlen;
+}
+
 
 void Item_func_substr_index::fix_length_and_dec()
 { 
@@ -3192,6 +3282,10 @@ String *Item_func_rpad::val_str(String *str)
   if (!res || args[1]->null_value || !rpad || 
       ((count < 0) && !args[1]->unsigned_flag))
     goto err;
+
+  if (count == 0)
+    return make_empty_result();
+
   null_value=0;
   /* Assumes that the maximum length of a String is < INT_MAX32. */
   /* Set here so that rest of code sees out-of-bound value as such. */
@@ -3299,6 +3393,10 @@ String *Item_func_lpad::val_str(String *str)
   if (!res || args[1]->null_value || !pad ||  
       ((count < 0) && !args[1]->unsigned_flag))
     goto err;  
+
+  if (count == 0)
+    return make_empty_result();
+
   null_value=0;
   /* Assumes that the maximum length of a String is < INT_MAX32. */
   /* Set here so that rest of code sees out-of-bound value as such. */
diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h
index 58bd6c9..660c294 100644
--- a/sql/item_strfunc.h
+++ b/sql/item_strfunc.h
@@ -37,17 +37,7 @@ class Item_str_func :public Item_func
      character set. No memory is allocated.
      @retval A pointer to the str_value member.
    */
-  String *make_empty_result()
-  {
-    /*
-      Reset string length to an empty string. We don't use str_value.set() as
-      we don't want to free and potentially have to reallocate the buffer
-      for each call.
-    */
-    str_value.length(0);
-    str_value.set_charset(collation.collation);
-    return &str_value; 
-  }
+  String *make_empty_result();
 public:
   Item_str_func(THD *thd): Item_func(thd) { decimals=NOT_FIXED_DEC; }
   Item_str_func(THD *thd, Item *a): Item_func(thd, a) {decimals=NOT_FIXED_DEC; }
@@ -364,11 +354,26 @@ class Item_func_replace :public Item_str_func
     Item_str_func(thd, org, find, replace) {}
   String *val_str(String *);
   void fix_length_and_dec();
+  String * replace_value(String *str, String *res2, String *res3);
   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_value2, tmp_value3, 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 *);
+  void fix_args(THD *thd, Item *org, Item *find, Item *replace);
+  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
 {
@@ -496,14 +501,28 @@ class Item_func_substr :public Item_str_func
   String tmp_value;
 public:
   Item_func_substr(THD *thd, Item *a, Item *b): Item_str_func(thd, a, b) {}
-  Item_func_substr(THD *thd, Item *a, Item *b, Item *c): Item_str_func(thd, a, b, c) {}
+  Item_func_substr(THD *thd, Item *a, Item *b, Item *c) : Item_str_func(thd, a, b, c) {}
   String *val_str(String *);
   void fix_length_and_dec();
+  String * substr_value(String *str, longlong start);
   const char *func_name() const { return "substr"; }
   Item *get_copy(THD *thd, MEM_ROOT *mem_root)
   { return get_item_copy<Item_func_substr>(thd, mem_root, this); }
 };
 
+class Item_func_substr_oracle :public Item_func_substr
+{
+public:
+  Item_func_substr_oracle(THD *thd, Item *a, Item *b):
+                         Item_func_substr(thd, a, b) {}
+  Item_func_substr_oracle(THD *thd, Item *a, Item *b, Item *c):
+                         Item_func_substr(thd, a, b, c) {}
+  String *val_str(String *);
+  void fix_length_and_dec();
+  const char *func_name() const { return "substr_oracle"; }
+  Item *get_copy(THD *thd, MEM_ROOT *mem_root)
+  { return get_item_copy<Item_func_substr_oracle>(thd, mem_root, this); }
+};
 
 class Item_func_substr_index :public Item_str_func
 {
@@ -527,6 +546,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:
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index 3aa6f53..5ae7e55 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -734,6 +734,19 @@ static void set_param_str(Item_param *param, uchar **pos, ulong len)
   *pos+= length;
 }
 
+static void set_param_str_oracle(Item_param *param, uchar **pos, ulong len)
+{
+  ulong length= get_param_length(pos, len);
+  if (length == 0)
+    param->set_null();
+  else
+  {
+    if (length > len)
+      length= len;
+    param->set_str((const char *)*pos, length);
+    *pos+= length;
+  }
+}
 
 #undef get_param_length
 
@@ -806,7 +819,10 @@ static void setup_one_conversion_function(THD *thd, Item_param *param,
       param->value.cs_info.final_character_set_of_str_value=
         String::needs_conversion(0, fromcs, tocs, &dummy_offset) ?
         tocs : fromcs;
-      param->set_param_func= set_param_str;
+      if (thd->variables.sql_mode & MODE_ORACLE)
+        param->set_param_func= set_param_str_oracle;
+      else
+        param->set_param_func= set_param_str;
       /*
         Exact value of max_length is not known unless data is converted to
         charset of connection, so we have to set it later.
diff --git a/sql/sql_yacc_ora.yy b/sql/sql_yacc_ora.yy
index 0064a3a..0db79b1 100644
--- a/sql/sql_yacc_ora.yy
+++ b/sql/sql_yacc_ora.yy
@@ -9966,25 +9966,25 @@ function_call_nonkeyword:
           }
         | SUBSTRING '(' expr ',' expr ',' expr ')'
           {
-            $$= new (thd->mem_root) Item_func_substr(thd, $3, $5, $7);
+            $$= new (thd->mem_root) Item_func_substr_oracle(thd, $3, $5, $7);
             if ($$ == NULL)
               MYSQL_YYABORT;
           }
         | SUBSTRING '(' expr ',' expr ')'
           {
-            $$= new (thd->mem_root) Item_func_substr(thd, $3, $5);
+            $$= new (thd->mem_root) Item_func_substr_oracle(thd, $3, $5);
             if ($$ == NULL)
               MYSQL_YYABORT;
           }
         | SUBSTRING '(' expr FROM expr FOR_SYM expr ')'
           {
-            $$= new (thd->mem_root) Item_func_substr(thd, $3, $5, $7);
+            $$= new (thd->mem_root) Item_func_substr_oracle(thd, $3, $5, $7);
             if ($$ == NULL)
               MYSQL_YYABORT;
           }
         | SUBSTRING '(' expr FROM expr ')'
           {
-            $$= new (thd->mem_root) Item_func_substr(thd, $3, $5);
+            $$= new (thd->mem_root) Item_func_substr_oracle(thd, $3, $5);
             if ($$ == NULL)
               MYSQL_YYABORT;
           }
@@ -10196,7 +10196,7 @@ function_call_conflict:
           }
         | REPLACE '(' expr ',' expr ',' expr ')'
           {
-            $$= new (thd->mem_root) Item_func_replace(thd, $3, $5, $7);
+            $$= new (thd->mem_root) Item_func_replace_oracle(thd, $3, $5, $7);
             if ($$ == NULL)
               MYSQL_YYABORT;
           }
@@ -13992,28 +13992,38 @@ text_literal:
           {
             LEX_STRING tmp;
             CHARSET_INFO *cs_con= thd->variables.collation_connection;
-            CHARSET_INFO *cs_cli= thd->variables.character_set_client;
-            uint repertoire= $1.repertoire(cs_cli);
-            if (thd->charset_is_collation_connection ||
-                (repertoire == MY_REPERTOIRE_ASCII &&
-                 my_charset_is_ascii_based(cs_con)))
-              tmp= $1;
+            if ($1.length == 0)
+              $$= new (thd->mem_root) Item_null(thd, 0, cs_con);
             else
             {
-              if (thd->convert_string(&tmp, cs_con, $1.str, $1.length, cs_cli))
-                MYSQL_YYABORT;
+              CHARSET_INFO *cs_cli= thd->variables.character_set_client;
+              uint repertoire= $1.repertoire(cs_cli);
+              if (thd->charset_is_collation_connection ||
+                  (repertoire == MY_REPERTOIRE_ASCII &&
+                   my_charset_is_ascii_based(cs_con)))
+                tmp= $1;
+              else
+              {
+                if (thd->convert_string(&tmp, cs_con, $1.str, $1.length,
+                                        cs_cli))
+                  MYSQL_YYABORT;
+              }
+
+              $$= new (thd->mem_root) Item_string(thd, tmp.str, tmp.length,
+                                                  cs_con,
+                                                  DERIVATION_COERCIBLE,
+                                                  repertoire);
             }
-            $$= new (thd->mem_root) Item_string(thd, tmp.str, tmp.length,
-                                                cs_con,
-                                                DERIVATION_COERCIBLE,
-                                                repertoire);
             if ($$ == NULL)
               MYSQL_YYABORT;
           }
         | NCHAR_STRING
           {
             DBUG_ASSERT(my_charset_is_ascii_based(national_charset_info));
-            $$= new (thd->mem_root) Item_string(thd, $1.str, $1.length,
+            if ($1.length == 0)
+              $$= new (thd->mem_root) Item_null(thd, 0, national_charset_info);
+            else
+              $$= new (thd->mem_root) Item_string(thd, $1.str, $1.length,
                                                   national_charset_info,
                                                   DERIVATION_COERCIBLE,
                                                   $1.repertoire());
@@ -14022,26 +14032,50 @@ text_literal:
           }
         | UNDERSCORE_CHARSET TEXT_STRING
           {
-            $$= new (thd->mem_root) Item_string_with_introducer(thd, $2.str,
-                                                                $2.length, $1);
+            if ($2.length == 0)
+              $$= new (thd->mem_root) Item_null(thd, 0, $1);
+            else
+              $$= new (thd->mem_root) Item_string_with_introducer(thd, $2.str,
+                                                                  $2.length,
+                                                                  $1);
             if ($$ == NULL)
               MYSQL_YYABORT;
           }
         | text_literal TEXT_STRING_literal
           {
             Item_string* item= (Item_string*) $1;
-            item->append($2.str, $2.length);
-            if (!(item->collation.repertoire & MY_REPERTOIRE_EXTENDED))
+            if (item->type() != Item::NULL_ITEM)
             {
-              /*
-                 If the string has been pure ASCII so far,
-                 check the new part.
-              */
-              CHARSET_INFO *cs= thd->variables.collation_connection;
-              item->collation.repertoire|= my_string_repertoire(cs,
-                                                                $2.str,
-                                                                $2.length);
+              item->append($2.str, $2.length);
+              if (!(item->collation.repertoire & MY_REPERTOIRE_EXTENDED))
+              {
+                /*
+                    If the string has been pure ASCII so far,
+                    check the new part.
+                */
+                CHARSET_INFO *cs= thd->variables.collation_connection;
+                item->collation.repertoire|= my_string_repertoire(cs,
+                                                                  $2.str,
+                                                                  $2.length);
+              }
+            }
+            else
+            {
+              if ($2.length == 0)
+                $$= $1;
+              else
+              {
+                CHARSET_INFO *cs_con= thd->variables.collation_connection;
+                CHARSET_INFO *cs_cli= thd->variables.character_set_client;
+                uint repertoire=my_string_repertoire(cs_cli, $2.str, $2.length);
+                $$= new (thd->mem_root) Item_string(thd, $2.str, $2.length,
+                                                    $1->collation.collation,
+                                                    DERIVATION_COERCIBLE,
+                                                    repertoire);
+              }
             }
+            if ($$ == NULL)
+              MYSQL_YYABORT;
           }
         ;
 
