Commit 02a72cf8 authored by Alexander Barkov's avatar Alexander Barkov

MDEV-10596 Allow VARCHAR and VARCHAR2 without length as a data type of routine...

MDEV-10596 Allow VARCHAR and VARCHAR2 without length as a data type of routine parameters and in RETURN clause
parent ec527fac
......@@ -652,19 +652,19 @@ Pos Instruction
0 set total@4 0
1 set ia@5 1
2 set [upper_bound]@6 a@0
3 jump_if_not 17(17) (ia@5 <= [upper_bound]@6)
4 set total@4 (total@4 + 1000)
3 jump_if_not 17(17) ia@5 <= [upper_bound]@6
4 set total@4 total@4 + 1000
5 set ib@7 1
6 set [upper_bound]@8 b@2
7 jump_if_not 15(15) (ib@7 <= [upper_bound]@8)
8 set total@4 (total@4 + 1)
9 jump_if_not 11(0) (ib@7 = limitb@3)
7 jump_if_not 15(15) ib@7 <= [upper_bound]@8
8 set total@4 total@4 + 1
9 jump_if_not 11(0) ib@7 = limitb@3
10 jump 15
11 jump_if_not 13(0) (ia@5 = limita@1)
11 jump_if_not 13(0) ia@5 = limita@1
12 jump 17
13 set ib@7 (ib@7 + 1)
13 set ib@7 ib@7 + 1
14 jump 7
15 set ia@5 (ia@5 + 1)
15 set ia@5 ia@5 + 1
16 jump 3
17 freturn 3 total@4
SELECT f1(2, 1, 2, 2) FROM DUAL;
......@@ -699,13 +699,13 @@ Pos Instruction
0 set total@1 0
1 set i@2 1
2 set [upper_bound]@3 a@0
3 jump_if_not 11(11) (i@2 <= [upper_bound]@3)
4 set total@1 (total@1 + 1000)
5 jump_if_not 8(8) (i@2 = 5)
6 set i@2 (i@2 + 1)
3 jump_if_not 11(11) i@2 <= [upper_bound]@3
4 set total@1 total@1 + 1000
5 jump_if_not 8(8) i@2 = 5
6 set i@2 i@2 + 1
7 jump 3
8 set total@1 (total@1 + 1)
9 set i@2 (i@2 + 1)
8 set total@1 total@1 + 1
9 set i@2 i@2 + 1
10 jump 3
11 freturn 3 total@1
SELECT f1(3), f1(4), f1(5), f1(6) FROM DUAL;
......@@ -736,18 +736,18 @@ Pos Instruction
0 set total@1 0
1 set i@2 1
2 set [upper_bound]@3 a@0
3 jump_if_not 16(16) (i@2 <= [upper_bound]@3)
3 jump_if_not 16(16) i@2 <= [upper_bound]@3
4 set j@4 1
5 set [upper_bound]@5 2
6 jump_if_not 14(14) (j@4 <= [upper_bound]@5)
7 set total@1 (total@1 + 1000)
8 jump_if_not 11(11) (i@2 = 5)
9 set i@2 (i@2 + 1)
6 jump_if_not 14(14) j@4 <= [upper_bound]@5
7 set total@1 total@1 + 1000
8 jump_if_not 11(11) i@2 = 5
9 set i@2 i@2 + 1
10 jump 3
11 set total@1 (total@1 + 1)
12 set j@4 (j@4 + 1)
11 set total@1 total@1 + 1
12 set j@4 j@4 + 1
13 jump 6
14 set i@2 (i@2 + 1)
14 set i@2 i@2 + 1
15 jump 3
16 freturn 3 total@1
SELECT f1(3), f1(4), f1(5), f1(6) FROM DUAL;
......@@ -779,18 +779,18 @@ Pos Instruction
0 set total@1 0
1 set j@2 1
2 set [upper_bound]@3 2
3 jump_if_not 16(16) (j@2 <= [upper_bound]@3)
3 jump_if_not 16(16) j@2 <= [upper_bound]@3
4 set i@4 1
5 set [upper_bound]@5 a@0
6 jump_if_not 14(14) (i@4 <= [upper_bound]@5)
7 set total@1 (total@1 + 1000)
8 jump_if_not 11(11) (i@4 = 5)
9 set i@4 (i@4 + 1)
6 jump_if_not 14(14) i@4 <= [upper_bound]@5
7 set total@1 total@1 + 1000
8 jump_if_not 11(11) i@4 = 5
9 set i@4 i@4 + 1
10 jump 6
11 set total@1 (total@1 + 1)
12 set i@4 (i@4 + 1)
11 set total@1 total@1 + 1
12 set i@4 i@4 + 1
13 jump 6
14 set j@2 (j@2 + 1)
14 set j@2 j@2 + 1
15 jump 3
16 freturn 3 total@1
SELECT f1(3), f1(4), f1(5), f1(6) FROM DUAL;
......@@ -815,12 +815,12 @@ Pos Instruction
0 set total@1 0
1 set i@2 1
2 set [upper_bound]@3 a@0
3 jump_if_not 10(10) (i@2 <= [upper_bound]@3)
4 jump_if_not 7(0) (i@2 = 5)
5 set i@2 (i@2 + 1)
3 jump_if_not 10(10) i@2 <= [upper_bound]@3
4 jump_if_not 7(0) i@2 = 5
5 set i@2 i@2 + 1
6 jump 3
7 set total@1 (total@1 + 1)
8 set i@2 (i@2 + 1)
7 set total@1 total@1 + 1
8 set i@2 i@2 + 1
9 jump 3
10 freturn 3 total@1
SELECT f1(3), f1(4), f1(5), f1(6) FROM DUAL;
......
SET sql_mode=ORACLE;
#
# MDEV-10596 Allow VARCHAR and VARCHAR2 without length as a data type of routine parameters and in RETURN clause
#
CREATE FUNCTION f1(param CHAR) RETURN CHAR AS BEGIN RETURN param; END;;
SHOW CREATE FUNCTION f1;
Function sql_mode Create Function character_set_client collation_connection Database Collation
f1 PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ORACLE,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS,NO_AUTO_CREATE_USER CREATE DEFINER="root"@"localhost" FUNCTION "f1"(param CHAR) RETURN varchar(2000) CHARSET latin1
AS BEGIN RETURN param; END latin1 latin1_swedish_ci latin1_swedish_ci
SELECT LENGTH(f1(REPEAT('a',2000)));;
LENGTH(f1(REPEAT('a',2000)))
2000
CREATE TABLE t1 AS SELECT f1(REPEAT('a',2000)) AS a;;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE "t1" (
"a" text DEFAULT NULL
)
DROP TABLE t1;
DROP FUNCTION f1;
CREATE FUNCTION f1(param NCHAR) RETURN NCHAR AS BEGIN RETURN param; END;;
SHOW CREATE FUNCTION f1;
Function sql_mode Create Function character_set_client collation_connection Database Collation
f1 PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ORACLE,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS,NO_AUTO_CREATE_USER CREATE DEFINER="root"@"localhost" FUNCTION "f1"(param NCHAR) RETURN varchar(2000) CHARSET utf8
AS BEGIN RETURN param; END latin1 latin1_swedish_ci latin1_swedish_ci
SELECT LENGTH(f1(REPEAT('a',2000)));;
LENGTH(f1(REPEAT('a',2000)))
2000
CREATE TABLE t1 AS SELECT f1(REPEAT('a',2000)) AS a;;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE "t1" (
"a" text CHARACTER SET utf8 DEFAULT NULL
)
DROP TABLE t1;
DROP FUNCTION f1;
CREATE FUNCTION f1(param BINARY) RETURN BINARY AS BEGIN RETURN param; END;;
SHOW CREATE FUNCTION f1;
Function sql_mode Create Function character_set_client collation_connection Database Collation
f1 PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ORACLE,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS,NO_AUTO_CREATE_USER CREATE DEFINER="root"@"localhost" FUNCTION "f1"(param BINARY) RETURN varbinary(2000)
AS BEGIN RETURN param; END latin1 latin1_swedish_ci latin1_swedish_ci
SELECT LENGTH(f1(REPEAT('a',2000)));;
LENGTH(f1(REPEAT('a',2000)))
2000
CREATE TABLE t1 AS SELECT f1(REPEAT('a',2000)) AS a;;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE "t1" (
"a" blob DEFAULT NULL
)
DROP TABLE t1;
DROP FUNCTION f1;
CREATE FUNCTION f1(param VARCHAR) RETURN VARCHAR AS BEGIN RETURN param; END;;
SHOW CREATE FUNCTION f1;
Function sql_mode Create Function character_set_client collation_connection Database Collation
f1 PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ORACLE,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS,NO_AUTO_CREATE_USER CREATE DEFINER="root"@"localhost" FUNCTION "f1"(param VARCHAR) RETURN varchar(4000) CHARSET latin1
AS BEGIN RETURN param; END latin1 latin1_swedish_ci latin1_swedish_ci
SELECT LENGTH(f1(REPEAT('a',4000)));;
LENGTH(f1(REPEAT('a',4000)))
4000
CREATE TABLE t1 AS SELECT f1(REPEAT('a',4000)) AS a;;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE "t1" (
"a" text DEFAULT NULL
)
DROP TABLE t1;
DROP FUNCTION f1;
CREATE FUNCTION f1(param VARCHAR2) RETURN VARCHAR2 AS BEGIN RETURN param; END;;
SHOW CREATE FUNCTION f1;
Function sql_mode Create Function character_set_client collation_connection Database Collation
f1 PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ORACLE,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS,NO_AUTO_CREATE_USER CREATE DEFINER="root"@"localhost" FUNCTION "f1"(param VARCHAR2) RETURN varchar(4000) CHARSET latin1
AS BEGIN RETURN param; END latin1 latin1_swedish_ci latin1_swedish_ci
SELECT LENGTH(f1(REPEAT('a',4000)));;
LENGTH(f1(REPEAT('a',4000)))
4000
CREATE TABLE t1 AS SELECT f1(REPEAT('a',4000)) AS a;;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE "t1" (
"a" text DEFAULT NULL
)
DROP TABLE t1;
DROP FUNCTION f1;
CREATE FUNCTION f1(param NVARCHAR) RETURN NVARCHAR AS BEGIN RETURN param; END;;
SHOW CREATE FUNCTION f1;
Function sql_mode Create Function character_set_client collation_connection Database Collation
f1 PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ORACLE,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS,NO_AUTO_CREATE_USER CREATE DEFINER="root"@"localhost" FUNCTION "f1"(param NVARCHAR) RETURN varchar(4000) CHARSET utf8
AS BEGIN RETURN param; END latin1 latin1_swedish_ci latin1_swedish_ci
SELECT LENGTH(f1(REPEAT('a',4000)));;
LENGTH(f1(REPEAT('a',4000)))
4000
CREATE TABLE t1 AS SELECT f1(REPEAT('a',4000)) AS a;;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE "t1" (
"a" text CHARACTER SET utf8 DEFAULT NULL
)
DROP TABLE t1;
DROP FUNCTION f1;
CREATE FUNCTION f1(param VARBINARY) RETURN VARBINARY AS BEGIN RETURN param; END;;
SHOW CREATE FUNCTION f1;
Function sql_mode Create Function character_set_client collation_connection Database Collation
f1 PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ORACLE,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS,NO_AUTO_CREATE_USER CREATE DEFINER="root"@"localhost" FUNCTION "f1"(param VARBINARY) RETURN varbinary(4000)
AS BEGIN RETURN param; END latin1 latin1_swedish_ci latin1_swedish_ci
SELECT LENGTH(f1(REPEAT('a',4000)));;
LENGTH(f1(REPEAT('a',4000)))
4000
CREATE TABLE t1 AS SELECT f1(REPEAT('a',4000)) AS a;;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE "t1" (
"a" blob DEFAULT NULL
)
DROP TABLE t1;
DROP FUNCTION f1;
CREATE FUNCTION f1(param RAW) RETURN RAW AS BEGIN RETURN param; END;;
SHOW CREATE FUNCTION f1;
Function sql_mode Create Function character_set_client collation_connection Database Collation
f1 PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ORACLE,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS,NO_AUTO_CREATE_USER CREATE DEFINER="root"@"localhost" FUNCTION "f1"(param RAW) RETURN varbinary(4000)
AS BEGIN RETURN param; END latin1 latin1_swedish_ci latin1_swedish_ci
SELECT LENGTH(f1(REPEAT('a',4000)));;
LENGTH(f1(REPEAT('a',4000)))
4000
CREATE TABLE t1 AS SELECT f1(REPEAT('a',4000)) AS a;;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE "t1" (
"a" blob DEFAULT NULL
)
DROP TABLE t1;
DROP FUNCTION f1;
--eval CREATE FUNCTION f1(param $type) RETURN $type AS BEGIN RETURN param; END;
SHOW CREATE FUNCTION f1;
--eval SELECT LENGTH(f1(REPEAT('a',$length)));
--eval CREATE TABLE t1 AS SELECT f1(REPEAT('a',$length)) AS a;
SHOW CREATE TABLE t1;
DROP TABLE t1;
DROP FUNCTION f1;
SET sql_mode=ORACLE;
--echo #
--echo # MDEV-10596 Allow VARCHAR and VARCHAR2 without length as a data type of routine parameters and in RETURN clause
--echo #
--let type = CHAR
--let length = 2000
--source sp-param.inc
--let type = NCHAR
--let length = 2000
--source sp-param.inc
--let type = BINARY
--let length = 2000
--source sp-param.inc
--let type = VARCHAR
--let length = 4000
--source sp-param.inc
--let type = VARCHAR2
--let length = 4000
--source sp-param.inc
--let type = NVARCHAR
--let length = 4000
--source sp-param.inc
--let type = VARBINARY
--let length = 4000
--source sp-param.inc
--let type = RAW
--let length = 4000
--source sp-param.inc
......@@ -1007,6 +1007,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
wild_and_where
field_length opt_field_length opt_field_length_default_1
colon_with_pos
opt_field_length_default_sp_param_char
opt_field_length_default_sp_param_varchar
%type <const_simple_string>
opt_place
......@@ -1017,6 +1019,14 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%type <field_type> int_type real_type
%type <Lex_field_type> type_with_opt_collate field_type
sp_param_type_with_opt_collate
sp_param_field_type
sp_param_field_type_string
field_type_numeric
field_type_string
field_type_lob
field_type_temporal
field_type_misc
%type <Lex_dyncol_type> opt_dyncol_type dyncol_type
numeric_dyncol_type temporal_dyncol_type string_dyncol_type
......@@ -2267,7 +2277,7 @@ sp_param_name:
;
sp_param_name_and_type:
sp_param_name type_with_opt_collate
sp_param_name sp_param_type_with_opt_collate
{
if (Lex->sp_param_fill_definition($$= $1))
MYSQL_YYABORT;
......@@ -2286,7 +2296,7 @@ sp_pdparams:
;
sp_pdparam:
sp_param_name sp_opt_inout type_with_opt_collate
sp_param_name sp_opt_inout sp_param_type_with_opt_collate
{
$1->mode= $2;
if (Lex->sp_param_fill_definition($1))
......@@ -5611,6 +5621,24 @@ column_default_expr:
;
field_type:
field_type_numeric
| field_type_temporal
| field_type_string
| field_type_lob
| field_type_misc
;
sp_param_field_type:
field_type_numeric
| field_type_temporal
| sp_param_field_type_string
| field_type_lob
| field_type_misc
;
field_type_numeric:
int_type opt_field_length field_options { $$.set($1, $2); }
| real_type opt_precision field_options { $$.set($1, $2); }
| FLOAT_SYM float_options field_options
......@@ -5641,7 +5669,24 @@ field_type:
{
$$.set(MYSQL_TYPE_TINY, "1");
}
| char opt_field_length_default_1 opt_binary
| DECIMAL_SYM float_options field_options
{ $$.set(MYSQL_TYPE_NEWDECIMAL, $2);}
| NUMBER_SYM float_options field_options
{
if ($2.length() != 0)
$$.set(MYSQL_TYPE_NEWDECIMAL, $2);
else
$$.set(MYSQL_TYPE_DOUBLE);
}
| NUMERIC_SYM float_options field_options
{ $$.set(MYSQL_TYPE_NEWDECIMAL, $2);}
| FIXED_SYM float_options field_options
{ $$.set(MYSQL_TYPE_NEWDECIMAL, $2);}
;
field_type_string:
char opt_field_length_default_1 opt_binary
{
$$.set(MYSQL_TYPE_STRING, $2);
}
......@@ -5678,7 +5723,52 @@ field_type:
Lex->charset= &my_charset_bin;
$$.set(MYSQL_TYPE_VARCHAR, $2);
}
| YEAR_SYM opt_field_length field_options
;
sp_param_field_type_string:
char opt_field_length_default_sp_param_char opt_binary
{
$$.set(MYSQL_TYPE_VARCHAR, $2);
}
| nchar opt_field_length_default_sp_param_char opt_bin_mod
{
$$.set(MYSQL_TYPE_VARCHAR, $2);
bincmp_collation(national_charset_info, $3);
}
| BINARY opt_field_length_default_sp_param_char
{
Lex->charset=&my_charset_bin;
$$.set(MYSQL_TYPE_VARCHAR, $2);
}
| varchar opt_field_length_default_sp_param_varchar opt_binary
{
$$.set(MYSQL_TYPE_VARCHAR, $2);
}
| VARCHAR2 opt_field_length_default_sp_param_varchar opt_binary
{
$$.set(MYSQL_TYPE_VARCHAR, $2);
}
| nvarchar opt_field_length_default_sp_param_varchar opt_bin_mod
{
$$.set(MYSQL_TYPE_VARCHAR, $2);
bincmp_collation(national_charset_info, $3);
}
| VARBINARY opt_field_length_default_sp_param_varchar
{
Lex->charset= &my_charset_bin;
$$.set(MYSQL_TYPE_VARCHAR, $2);
}
| RAW opt_field_length_default_sp_param_varchar
{
Lex->charset= &my_charset_bin;
$$.set(MYSQL_TYPE_VARCHAR, $2);
}
;
field_type_temporal:
YEAR_SYM opt_field_length field_options
{
if ($2)
{
......@@ -5722,7 +5812,11 @@ field_type:
| DATETIME opt_field_length
{ $$.set(opt_mysql56_temporal_format ?
MYSQL_TYPE_DATETIME2 : MYSQL_TYPE_DATETIME, $2); }
| TINYBLOB
;
field_type_lob:
TINYBLOB
{
Lex->charset=&my_charset_bin;
$$.set(MYSQL_TYPE_TINY_BLOB);
......@@ -5770,25 +5864,16 @@ field_type:
{ $$.set(MYSQL_TYPE_LONG_BLOB); }
| CLOB opt_binary
{ $$.set(MYSQL_TYPE_LONG_BLOB); }
| DECIMAL_SYM float_options field_options
{ $$.set(MYSQL_TYPE_NEWDECIMAL, $2);}
| NUMBER_SYM float_options field_options
{
if ($2.length() != 0)
$$.set(MYSQL_TYPE_NEWDECIMAL, $2);
else
$$.set(MYSQL_TYPE_DOUBLE);
}
| NUMERIC_SYM float_options field_options
{ $$.set(MYSQL_TYPE_NEWDECIMAL, $2);}
| FIXED_SYM float_options field_options
{ $$.set(MYSQL_TYPE_NEWDECIMAL, $2);}
| ENUM '(' string_list ')' opt_binary
| LONG_SYM opt_binary
{ $$.set(MYSQL_TYPE_MEDIUM_BLOB); }
;
field_type_misc:
ENUM '(' string_list ')' opt_binary
{ $$.set(MYSQL_TYPE_ENUM); }
| SET '(' string_list ')' opt_binary
{ $$.set(MYSQL_TYPE_SET); }
| LONG_SYM opt_binary
{ $$.set(MYSQL_TYPE_MEDIUM_BLOB); }
;
spatial_type:
......@@ -5894,6 +5979,33 @@ opt_field_length_default_1:
/* empty */ { $$= (char*) "1"; }
| field_length { $$= $1; }
/*
In sql_mode=ORACLE, a VARCHAR with no length is used
in SP parameters and return values and it's translated to VARCHAR(4000),
where 4000 is the maximum possible size for VARCHAR.
In MariaDB the limit for VARCHAR is 65535 bytes.
We could translate VARCHAR with no length to VARCHAR(65535), but
it would mean that for multi-byte character sets we'd have to translate
VARCHAR to MEDIUMTEXT, to guarantee 65535 characters.
Also we could translate VARCHAR to VARCHAR(16383), where 16383 is
the maximum possible length in characters in case of mbmaxlen=4
(e.g. utf32, utf16, utf8mb4). However, we'll have character sets with
mbmaxlen=5 soon (e.g. gb18030).
Let's translate VARCHAR to VARCHAR(4000), which covert all possible Oracle
values.
*/
opt_field_length_default_sp_param_varchar:
/* empty */ { $$= (char*) "4000"; }
| field_length { $$= $1; }
opt_field_length_default_sp_param_char:
/* empty */ { $$= (char*) "2000"; }
| field_length { $$= $1; }
opt_precision:
/* empty */ { $$.set(0, 0); }
| precision { $$= $1; }
......@@ -6001,6 +6113,19 @@ type_with_opt_collate:
}
;
sp_param_type_with_opt_collate:
sp_param_field_type opt_collate
{
$$= $1;
if ($2)
{
if (!(Lex->charset= merge_charset_and_collation(Lex->charset, $2)))
MYSQL_YYABORT;
}
Lex->last_field->set_attributes($1, Lex->charset);
}
;
charset:
CHAR_SYM SET {}
| CHARSET {}
......@@ -16116,7 +16241,7 @@ sf_tail:
lex->init_last_field(&lex->sphead->m_return_field_def, NULL,
thd->variables.collation_database);
}
type_with_opt_collate /* $8 */
sp_param_type_with_opt_collate /* $8 */
{ /* $9 */
if (Lex->sphead->fill_field_definition(thd, Lex->last_field))
MYSQL_YYABORT;
......
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