summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergei Golubchik <serg@mariadb.org>2014-11-08 17:37:19 +0100
committerSergei Golubchik <serg@mariadb.org>2014-12-04 16:09:34 +0100
commit227510e039b4ec6bff3096a4b9b39847551dab1a (patch)
tree2c40cbba45ca53e688d3f5cd388dbcd032c82984
parentd1522af72dad1965b8a8a37415545014ba743f49 (diff)
downloadmariadb-git-227510e039b4ec6bff3096a4b9b39847551dab1a.tar.gz
parser cleanup: don't store field properties in LEX, use Create_field directly
length/dec/charset are still in LEX, because they're also used for CAST and dynamic columns. also 1. fix "MDEV-7041 COLLATION(CAST('a' AS CHAR BINARY)) returns a wrong result" 2. allow BINARY modifier in stored function RETURN clause 3. allow "COLLATION without CHARSET" in SP/SF (parameters, RETURN, DECLARE) 4. print correct variable name in error messages for stored routine parameters
-rw-r--r--mysql-test/r/cast.result23
-rw-r--r--mysql-test/r/ctype_ucs.result9
-rw-r--r--mysql-test/r/sp-error.result2
-rw-r--r--mysql-test/r/sp-ucs2.result6
-rw-r--r--mysql-test/r/sp.result24
-rw-r--r--mysql-test/suite/funcs_1/r/storedproc.result27
-rw-r--r--mysql-test/suite/funcs_1/t/storedproc.test1
-rw-r--r--mysql-test/t/cast.test16
-rw-r--r--mysql-test/t/ctype_ucs.test11
-rw-r--r--mysql-test/t/sp-error.test7
-rw-r--r--mysql-test/t/sp-ucs2.test6
-rw-r--r--mysql-test/t/sp.test33
-rw-r--r--sql/field.cc280
-rw-r--r--sql/field.h21
-rw-r--r--sql/item_create.cc9
-rw-r--r--sql/item_timefunc.cc8
-rw-r--r--sql/my_decimal.cc2
-rw-r--r--sql/my_decimal.h2
-rw-r--r--sql/share/errmsg-utf8.txt4
-rw-r--r--sql/sp_head.cc19
-rw-r--r--sql/sp_pcontext.cc7
-rw-r--r--sql/sp_pcontext.h14
-rw-r--r--sql/sql_lex.h27
-rw-r--r--sql/sql_parse.cc122
-rw-r--r--sql/sql_parse.h11
-rw-r--r--sql/sql_plugin.cc4
-rw-r--r--sql/sql_table.cc12
-rw-r--r--sql/sql_yacc.yy519
-rw-r--r--sql/table.cc6
-rw-r--r--storage/perfschema/pfs_digest.cc3
30 files changed, 572 insertions, 663 deletions
diff --git a/mysql-test/r/cast.result b/mysql-test/r/cast.result
index c81af134add..29f5f0cf2d5 100644
--- a/mysql-test/r/cast.result
+++ b/mysql-test/r/cast.result
@@ -796,3 +796,26 @@ DATE("foo")
NULL
Warnings:
Warning 1292 Incorrect datetime value: 'foo'
+create table t1 (a int, b char(5) as (cast("a" as char(10) binary) + a) );
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` char(5) AS (cast("a" as char(10) binary) + a) VIRTUAL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
+select collation(cast("a" as char(10) binary));
+collation(cast("a" as char(10) binary))
+latin1_bin
+select collation(cast("a" as char(10) charset utf8 binary));
+collation(cast("a" as char(10) charset utf8 binary))
+utf8_bin
+select collation(cast("a" as char(10) ascii binary));
+collation(cast("a" as char(10) ascii binary))
+latin1_bin
+select collation(cast("a" as char(10) binary charset utf8));
+collation(cast("a" as char(10) binary charset utf8))
+utf8_bin
+select collation(cast("a" as char(10) binary ascii));
+collation(cast("a" as char(10) binary ascii))
+latin1_bin
diff --git a/mysql-test/r/ctype_ucs.result b/mysql-test/r/ctype_ucs.result
index 3250d3cb838..740319a9dcd 100644
--- a/mysql-test/r/ctype_ucs.result
+++ b/mysql-test/r/ctype_ucs.result
@@ -5535,3 +5535,12 @@ a aa
#
# End of 10.0 tests
#
+select collation(cast("a" as char(10) unicode binary));
+collation(cast("a" as char(10) unicode binary))
+ucs2_bin
+select collation(cast("a" as char(10) binary unicode));
+collation(cast("a" as char(10) binary unicode))
+ucs2_bin
+#
+# End of 10.1 tests
+#
diff --git a/mysql-test/r/sp-error.result b/mysql-test/r/sp-error.result
index 71fab8c9654..7569673c68c 100644
--- a/mysql-test/r/sp-error.result
+++ b/mysql-test/r/sp-error.result
@@ -1411,7 +1411,7 @@ end|
ERROR 0A000: Not allowed to return a result set from a function
drop function if exists bug20701;
create function bug20701() returns varchar(25) binary return "test";
-ERROR 42000: This version of MariaDB doesn't yet support 'return value collation'
+drop function bug20701;
create function bug20701() returns varchar(25) return "test";
drop function bug20701;
create procedure proc_26503_error_1()
diff --git a/mysql-test/r/sp-ucs2.result b/mysql-test/r/sp-ucs2.result
index 605fe4ed151..c7a3ed6e46a 100644
--- a/mysql-test/r/sp-ucs2.result
+++ b/mysql-test/r/sp-ucs2.result
@@ -106,20 +106,20 @@ RETURNS VARCHAR(64) CHARACTER SET ucs2
BEGIN
RETURN 'str';
END|
-ERROR 42000: This version of MariaDB doesn't yet support 'COLLATE with no CHARACTER SET in SP parameters, RETURNS, DECLARE'
+ERROR 42000: COLLATION 'ucs2_unicode_ci' is not valid for CHARACTER SET 'latin1'
CREATE FUNCTION f(f1 VARCHAR(64) CHARACTER SET ucs2)
RETURNS VARCHAR(64) COLLATE ucs2_unicode_ci
BEGIN
RETURN 'str';
END|
-ERROR 42000: This version of MariaDB doesn't yet support 'COLLATE with no CHARACTER SET in SP parameters, RETURNS, DECLARE'
+ERROR 42000: COLLATION 'ucs2_unicode_ci' is not valid for CHARACTER SET 'latin1'
CREATE FUNCTION f(f1 VARCHAR(64) CHARACTER SET ucs2)
RETURNS VARCHAR(64) CHARACTER SET ucs2
BEGIN
DECLARE f2 VARCHAR(64) COLLATE ucs2_unicode_ci;
RETURN 'str';
END|
-ERROR 42000: This version of MariaDB doesn't yet support 'COLLATE with no CHARACTER SET in SP parameters, RETURNS, DECLARE'
+ERROR 42000: COLLATION 'ucs2_unicode_ci' is not valid for CHARACTER SET 'latin1'
SET NAMES utf8;
DROP FUNCTION IF EXISTS bug48766;
CREATE FUNCTION bug48766 ()
diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result
index 56d8ea62f44..4fa43e82a1d 100644
--- a/mysql-test/r/sp.result
+++ b/mysql-test/r/sp.result
@@ -3548,7 +3548,10 @@ begin
set f1= concat( 'hello', f1 );
return f1;
end|
-ERROR 42000: This version of MariaDB doesn't yet support 'return value collation'
+select collation(bug9048("foo"))|
+collation(bug9048("foo"))
+latin1_bin
+drop function bug9048|
drop procedure if exists bug12849_1|
create procedure bug12849_1(inout x char) select x into x|
set @var='a'|
@@ -7858,3 +7861,22 @@ v1
DROP PROCEDURE p1;
DROP TABLE t1;
# End of 5.5 test
+CREATE FUNCTION f(f1 VARCHAR(64) COLLATE latin1_german2_ci)
+RETURNS VARCHAR(64)
+BEGIN
+RETURN 'str';
+END|
+DROP FUNCTION f|
+CREATE FUNCTION f(f1 VARCHAR(64))
+RETURNS VARCHAR(64) COLLATE latin1_german2_ci
+BEGIN
+RETURN 'str';
+END|
+DROP FUNCTION f|
+CREATE FUNCTION f(f1 VARCHAR(64))
+RETURNS VARCHAR(64)
+BEGIN
+DECLARE f2 VARCHAR(64) COLLATE latin1_german2_ci;
+RETURN 'str';
+END|
+DROP FUNCTION f|
diff --git a/mysql-test/suite/funcs_1/r/storedproc.result b/mysql-test/suite/funcs_1/r/storedproc.result
index 4ec9bfbd512..f316bdb7ba2 100644
--- a/mysql-test/suite/funcs_1/r/storedproc.result
+++ b/mysql-test/suite/funcs_1/r/storedproc.result
@@ -142,7 +142,7 @@ BEGIN
SET @v1 = f1;
SELECT @v1;
END//
-ERROR 42000: Too big precision 256 specified for ''. Maximum is 65.
+ERROR 42000: Too big precision 256 specified for 'f1'. Maximum is 65.
DROP PROCEDURE IF EXISTS sp1//
Warnings:
Note 1305 PROCEDURE db_storedproc.sp1 does not exist
@@ -152,7 +152,7 @@ BEGIN
SET @v1 = f1;
SELECT @v1;
END//
-ERROR 42000: Too big precision 66 specified for ''. Maximum is 65.
+ERROR 42000: Too big precision 66 specified for 'f1'. Maximum is 65.
DROP PROCEDURE IF EXISTS sp1//
Warnings:
Note 1305 PROCEDURE db_storedproc.sp1 does not exist
@@ -1407,12 +1407,12 @@ BEGIN
SELECT f1;
END//
Warnings:
-Note 1291 Column '' has duplicated value 'value1' in ENUM
+Note 1291 Column 'f1' has duplicated value 'value1' in ENUM
CALL sp1( "value1" );
f1
value1
Warnings:
-Note 1291 Column '' has duplicated value 'value1' in ENUM
+Note 1291 Column 'f1' has duplicated value 'value1' in ENUM
SHOW PROCEDURE STATUS WHERE db = 'db_storedproc';
Db Name Type Definer Modified Created Security_type Comment character_set_client collation_connection Database Collation
db_storedproc sp1 PROCEDURE root@localhost <modified> <created> INVOKER this is simple latin1 latin1_swedish_ci latin1_swedish_ci
@@ -1423,12 +1423,12 @@ BEGIN
SELECT f1;
END//
Warnings:
-Note 1291 Column '' has duplicated value 'value1' in SET
+Note 1291 Column 'f1' has duplicated value 'value1' in SET
CALL sp1( "value1, value1" );
f1
value1
Warnings:
-Note 1291 Column '' has duplicated value 'value1' in SET
+Note 1291 Column 'f1' has duplicated value 'value1' in SET
Warning 1265 Data truncated for column 'f1' at row 1
SHOW PROCEDURE STATUS WHERE db = 'db_storedproc';
Db Name Type Definer Modified Created Security_type Comment character_set_client collation_connection Database Collation
@@ -1440,12 +1440,12 @@ BEGIN
SELECT f1;
END//
Warnings:
-Note 1291 Column '' has duplicated value 'value1' in ENUM
+Note 1291 Column 'f1' has duplicated value 'value1' in ENUM
CALL sp1( "value1" );
f1
value1
Warnings:
-Note 1291 Column '' has duplicated value 'value1' in ENUM
+Note 1291 Column 'f1' has duplicated value 'value1' in ENUM
SHOW PROCEDURE STATUS WHERE db = 'db_storedproc';
Db Name Type Definer Modified Created Security_type Comment character_set_client collation_connection Database Collation
db_storedproc sp1 PROCEDURE root@localhost <modified> <created> INVOKER this is simple latin1 latin1_swedish_ci latin1_swedish_ci
@@ -1548,7 +1548,7 @@ BEGIN
SET f1 = 1000000 + f1;
RETURN f1;
END//
-ERROR 42000: Too big scale 31 specified for ''. Maximum is 30.
+ERROR 42000: Too big scale 31 specified for 'f1'. Maximum is 30.
SELECT fn1( 1.3326e+8 );
ERROR 42000: FUNCTION db_storedproc.fn1 does not exist
CREATE FUNCTION fn1( f1 DECIMAL(63, 30) ) RETURNS DECIMAL(63, 30)
@@ -1570,7 +1570,7 @@ BEGIN
RETURN f1;
END//
Warnings:
-Note 1291 Column '' has duplicated value 'value1' in ENUM
+Note 1291 Column 'f1' has duplicated value 'value1' in ENUM
SELECT fn1( "value1" );
fn1( "value1" )
1.000000000000000000000000000000
@@ -1584,7 +1584,7 @@ BEGIN
RETURN f1;
END//
Warnings:
-Note 1291 Column '' has duplicated value 'value1' in SET
+Note 1291 Column 'f1' has duplicated value 'value1' in SET
SELECT fn1( "value1, value1" );
fn1( "value1, value1" )
1.000000000000000000000000000000
@@ -3119,10 +3119,7 @@ return f1;
DROP FUNCTION IF EXISTS fn1;
CREATE FUNCTION fn1(f1 char binary ) returns char binary
return f1;
-ERROR 42000: This version of MariaDB doesn't yet support 'return value collation'
DROP FUNCTION IF EXISTS fn1;
-Warnings:
-Note 1305 FUNCTION db_storedproc.fn1 does not exist
CREATE FUNCTION fn1(f1 char ascii ) returns char ascii
return f1;
DROP FUNCTION IF EXISTS fn1;
@@ -5836,7 +5833,7 @@ fetch cur1 into e;
SELECT x, y, z, a, b, c, d, e;
close cur1;
END//
-ERROR 42000: Too big scale 255 specified for ''. Maximum is 30.
+ERROR 42000: Too big scale 255 specified for 'b'. Maximum is 30.
CALL sp6();
ERROR 42000: PROCEDURE db_storedproc.sp6 does not exist
DROP PROCEDURE IF EXISTS sp6;
diff --git a/mysql-test/suite/funcs_1/t/storedproc.test b/mysql-test/suite/funcs_1/t/storedproc.test
index 69406a57a00..ff417957c85 100644
--- a/mysql-test/suite/funcs_1/t/storedproc.test
+++ b/mysql-test/suite/funcs_1/t/storedproc.test
@@ -2155,7 +2155,6 @@ CREATE FUNCTION fn1(f1 char ) returns char
return f1;
DROP FUNCTION IF EXISTS fn1;
---error ER_NOT_SUPPORTED_YET
CREATE FUNCTION fn1(f1 char binary ) returns char binary
return f1;
diff --git a/mysql-test/t/cast.test b/mysql-test/t/cast.test
index b6c37cacd8a..58f91571ebb 100644
--- a/mysql-test/t/cast.test
+++ b/mysql-test/t/cast.test
@@ -456,3 +456,19 @@ SELECT CAST(TIME('10:20:30') AS DATE) + INTERVAL 1 DAY;
SET SQL_MODE=ALLOW_INVALID_DATES;
SELECT DATE("foo");
+#
+# CAST and field definition using same fields in LEX
+#
+create table t1 (a int, b char(5) as (cast("a" as char(10) binary) + a) );
+show create table t1;
+drop table t1;
+
+#
+# CAST (... BINARY)
+#
+select collation(cast("a" as char(10) binary));
+select collation(cast("a" as char(10) charset utf8 binary));
+select collation(cast("a" as char(10) ascii binary));
+select collation(cast("a" as char(10) binary charset utf8));
+select collation(cast("a" as char(10) binary ascii));
+
diff --git a/mysql-test/t/ctype_ucs.test b/mysql-test/t/ctype_ucs.test
index 33d41e9bc4c..1dee393b90b 100644
--- a/mysql-test/t/ctype_ucs.test
+++ b/mysql-test/t/ctype_ucs.test
@@ -914,7 +914,16 @@ SELECT CONCAT(CONVERT('pi=' USING ucs2),PI()) AS PI;
SET NAMES utf8, character_set_connection=ucs2;
SELECT 'a','aa';
-
--echo #
--echo # End of 10.0 tests
--echo #
+
+#
+# CAST (... BINARY)
+#
+select collation(cast("a" as char(10) unicode binary));
+select collation(cast("a" as char(10) binary unicode));
+
+--echo #
+--echo # End of 10.1 tests
+--echo #
diff --git a/mysql-test/t/sp-error.test b/mysql-test/t/sp-error.test
index 711e639191e..a16ef1205b9 100644
--- a/mysql-test/t/sp-error.test
+++ b/mysql-test/t/sp-error.test
@@ -2051,13 +2051,8 @@ delimiter ;|
--disable_warnings
drop function if exists bug20701;
--enable_warnings
-#
-# This was disabled in 5.1.12. See bug #20701
-# When collation support in SP is implemented, then this test should
-# be removed.
-#
---error ER_NOT_SUPPORTED_YET
create function bug20701() returns varchar(25) binary return "test";
+drop function bug20701;
create function bug20701() returns varchar(25) return "test";
drop function bug20701;
diff --git a/mysql-test/t/sp-ucs2.test b/mysql-test/t/sp-ucs2.test
index f6f70c3c103..3532169e5a1 100644
--- a/mysql-test/t/sp-ucs2.test
+++ b/mysql-test/t/sp-ucs2.test
@@ -114,7 +114,7 @@ DROP FUNCTION f1|
#
# COLLATE with no CHARACTER SET in IN param
#
---error ER_NOT_SUPPORTED_YET
+--error ER_COLLATION_CHARSET_MISMATCH
CREATE FUNCTION f(f1 VARCHAR(64) COLLATE ucs2_unicode_ci)
RETURNS VARCHAR(64) CHARACTER SET ucs2
BEGIN
@@ -125,7 +125,7 @@ END|
#
# COLLATE with no CHARACTER SET in RETURNS
#
---error ER_NOT_SUPPORTED_YET
+--error ER_COLLATION_CHARSET_MISMATCH
CREATE FUNCTION f(f1 VARCHAR(64) CHARACTER SET ucs2)
RETURNS VARCHAR(64) COLLATE ucs2_unicode_ci
BEGIN
@@ -136,7 +136,7 @@ END|
#
# COLLATE with no CHARACTER SET in DECLARE
#
---error ER_NOT_SUPPORTED_YET
+--error ER_COLLATION_CHARSET_MISMATCH
CREATE FUNCTION f(f1 VARCHAR(64) CHARACTER SET ucs2)
RETURNS VARCHAR(64) CHARACTER SET ucs2
BEGIN
diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test
index 5179bb1b03d..3f635acaac9 100644
--- a/mysql-test/t/sp.test
+++ b/mysql-test/t/sp.test
@@ -4355,17 +4355,14 @@ begin
return f1;
end|
drop function bug9048|
-#
-# This was disabled in 5.1.12. See bug #20701
-# When collation support in SP is implemented, then this test should
-# be removed.
-#
---error ER_NOT_SUPPORTED_YET
+
create function bug9048(f1 char binary) returns char binary
begin
set f1= concat( 'hello', f1 );
return f1;
end|
+select collation(bug9048("foo"))|
+drop function bug9048|
# Bug #12849 Stored Procedure: Crash on procedure call with CHAR type
# 'INOUT' parameter
@@ -9303,3 +9300,27 @@ DROP PROCEDURE p1;
DROP TABLE t1;
--echo # End of 5.5 test
+
+DELIMITER |;
+CREATE FUNCTION f(f1 VARCHAR(64) COLLATE latin1_german2_ci)
+ RETURNS VARCHAR(64)
+BEGIN
+ RETURN 'str';
+END|
+DROP FUNCTION f|
+
+CREATE FUNCTION f(f1 VARCHAR(64))
+ RETURNS VARCHAR(64) COLLATE latin1_german2_ci
+BEGIN
+ RETURN 'str';
+END|
+DROP FUNCTION f|
+
+CREATE FUNCTION f(f1 VARCHAR(64))
+ RETURNS VARCHAR(64)
+BEGIN
+ DECLARE f2 VARCHAR(64) COLLATE latin1_german2_ci;
+ RETURN 'str';
+END|
+DROP FUNCTION f|
+DELIMITER ;|
diff --git a/sql/field.cc b/sql/field.cc
index 7467aa63a26..a9bd1fe2dc0 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -9163,96 +9163,100 @@ void Create_field::init_for_tmp_table(enum_field_types sql_type_arg,
}
-/**
- Initialize field definition for create.
-
- @param thd Thread handle
- @param fld_name Field name
- @param fld_type Field type
- @param fld_length Field length
- @param fld_decimals Decimal (if any)
- @param fld_type_modifier Additional type information
- @param fld_default_value Field default value (if any)
- @param fld_on_update_value The value of ON UPDATE clause
- @param fld_comment Field comment
- @param fld_change Field change
- @param fld_interval_list Interval list (if any)
- @param fld_charset Field charset
- @param fld_geom_type Field geometry type (if any)
- @param fld_vcol_info Virtual column data
+static inline bool is_item_func(Item* x)
+{
+ return x != NULL && x->type() == Item::FUNC_ITEM;
+}
- @retval
- FALSE on success
- @retval
- TRUE on error
-*/
-bool Create_field::init(THD *thd, char *fld_name, enum_field_types fld_type,
- char *fld_length, char *fld_decimals,
- uint fld_type_modifier, Item *fld_default_value,
- Item *fld_on_update_value, LEX_STRING *fld_comment,
- char *fld_change, List<String> *fld_interval_list,
- CHARSET_INFO *fld_charset, uint fld_geom_type,
- Virtual_column_info *fld_vcol_info,
- engine_option_value *create_opt, bool check_exists)
+bool Create_field::check(THD *thd)
{
+ const uint conditional_type_modifiers= AUTO_INCREMENT_FLAG;
uint sign_len, allowed_type_modifier= 0;
ulong max_field_charlength= MAX_FIELD_CHARLENGTH;
- const bool on_update_is_function=
- (fld_on_update_value != NULL &&
- fld_on_update_value->type() == Item::FUNC_ITEM);
+ DBUG_ENTER("Create_field::check");
+
+ if (vcol_info)
+ {
+ vcol_info->set_field_type(sql_type);
+ sql_type= (enum enum_field_types)MYSQL_TYPE_VIRTUAL;
+ }
+
+ if (length > MAX_FIELD_BLOBLENGTH)
+ {
+ my_error(ER_TOO_BIG_DISPLAYWIDTH, MYF(0), field_name, MAX_FIELD_BLOBLENGTH);
+ DBUG_RETURN(1);
+ }
+
+ if (decimals >= NOT_FIXED_DEC)
+ {
+ my_error(ER_TOO_BIG_SCALE, MYF(0), decimals, field_name,
+ static_cast<ulong>(NOT_FIXED_DEC - 1));
+ DBUG_RETURN(TRUE);
+ }
- DBUG_ENTER("Create_field::init()");
+ if (def)
+ {
+ /*
+ Default value should be literal => basic constants =>
+ no need fix_fields()
- field= 0;
- field_name= fld_name;
- flags= fld_type_modifier;
- option_list= create_opt;
+ We allow only one function as part of default value -
+ NOW() as default for TIMESTAMP and DATETIME type.
+ */
+ if (def->type() == Item::FUNC_ITEM &&
+ (static_cast<Item_func*>(def)->functype() != Item_func::NOW_FUNC ||
+ (mysql_type_to_time_type(sql_type) != MYSQL_TIMESTAMP_DATETIME) ||
+ def->decimals < length))
+ {
+ my_error(ER_INVALID_DEFAULT, MYF(0), field_name);
+ DBUG_RETURN(1);
+ }
+ else if (def->type() == Item::NULL_ITEM)
+ {
+ def= 0;
+ if ((flags & (NOT_NULL_FLAG | AUTO_INCREMENT_FLAG)) == NOT_NULL_FLAG)
+ {
+ my_error(ER_INVALID_DEFAULT, MYF(0), field_name);
+ DBUG_RETURN(1);
+ }
+ }
+ else if (flags & AUTO_INCREMENT_FLAG)
+ {
+ my_error(ER_INVALID_DEFAULT, MYF(0), field_name);
+ DBUG_RETURN(1);
+ }
+ }
- if (fld_default_value != NULL && fld_default_value->type() == Item::FUNC_ITEM)
+ if (is_item_func(def))
{
/* There is a function default for insertions. */
def= NULL;
- unireg_check= (on_update_is_function ?
+ unireg_check= (is_item_func(on_update) ?
Field::TIMESTAMP_DNUN_FIELD : // for insertions and for updates.
Field::TIMESTAMP_DN_FIELD); // only for insertions.
}
else
{
/* No function default for insertions. Either NULL or a constant. */
- def= fld_default_value;
- if (on_update_is_function)
+ if (is_item_func(on_update))
unireg_check= Field::TIMESTAMP_UN_FIELD; // function default for updates
else
- unireg_check= ((fld_type_modifier & AUTO_INCREMENT_FLAG) != 0 ?
+ unireg_check= ((flags & AUTO_INCREMENT_FLAG) ?
Field::NEXT_NUMBER : // Automatic increment.
Field::NONE);
}
- decimals= fld_decimals ? (uint)atoi(fld_decimals) : 0;
- if (decimals >= NOT_FIXED_DEC)
+ if (on_update &&
+ (mysql_type_to_time_type(sql_type) != MYSQL_TIMESTAMP_DATETIME ||
+ on_update->decimals < length))
{
- my_error(ER_TOO_BIG_SCALE, MYF(0), decimals, fld_name,
- static_cast<ulong>(NOT_FIXED_DEC - 1));
- DBUG_RETURN(TRUE);
+ my_error(ER_INVALID_ON_UPDATE, MYF(0), field_name);
+ DBUG_RETURN(1);
}
- sql_type= fld_type;
- length= 0;
- change= fld_change;
- interval= 0;
- pack_length= key_length= 0;
- charset= fld_charset;
- geom_type= (Field::geometry_type) fld_geom_type;
- interval_list.empty();
-
- comment= *fld_comment;
- vcol_info= fld_vcol_info;
- create_if_not_exists= check_exists;
- stored_in_db= TRUE;
-
/* Initialize data for a computed field */
- if ((uchar)fld_type == (uchar)MYSQL_TYPE_VIRTUAL)
+ if (sql_type == MYSQL_TYPE_VIRTUAL)
{
DBUG_ASSERT(vcol_info && vcol_info->expr_item);
stored_in_db= vcol_info->is_stored();
@@ -9272,56 +9276,42 @@ bool Create_field::init(THD *thd, char *fld_name, enum_field_types fld_type,
Field::vcol_info. It is is always NULL for a column that is not
computed.
*/
- sql_type= fld_type= vcol_info->get_real_type();
+ sql_type= vcol_info->get_real_type();
}
/*
Set NO_DEFAULT_VALUE_FLAG if this field doesn't have a default value and
it is NOT NULL, not an AUTO_INCREMENT field and not a TIMESTAMP.
*/
- if (!fld_default_value && !(fld_type_modifier & AUTO_INCREMENT_FLAG) &&
- (fld_type_modifier & NOT_NULL_FLAG) && !is_timestamp_type(fld_type))
+ if (!def && unireg_check == Field::NONE &&
+ (flags & NOT_NULL_FLAG) && !is_timestamp_type(sql_type))
flags|= NO_DEFAULT_VALUE_FLAG;
- if (fld_length != NULL)
- {
- errno= 0;
- length= strtoul(fld_length, NULL, 10);
- if ((errno != 0) || (length > MAX_FIELD_BLOBLENGTH))
- {
- my_error(ER_TOO_BIG_DISPLAYWIDTH, MYF(0), fld_name, MAX_FIELD_BLOBLENGTH);
- DBUG_RETURN(TRUE);
- }
-
- if (length == 0)
- fld_length= NULL; /* purecov: inspected */
- }
+ sign_len= flags & UNSIGNED_FLAG ? 0 : 1;
- sign_len= fld_type_modifier & UNSIGNED_FLAG ? 0 : 1;
-
- switch (fld_type) {
+ switch (sql_type) {
case MYSQL_TYPE_TINY:
- if (!fld_length)
+ if (!length)
length= MAX_TINYINT_WIDTH+sign_len;
allowed_type_modifier= AUTO_INCREMENT_FLAG;
break;
case MYSQL_TYPE_SHORT:
- if (!fld_length)
+ if (!length)
length= MAX_SMALLINT_WIDTH+sign_len;
allowed_type_modifier= AUTO_INCREMENT_FLAG;
break;
case MYSQL_TYPE_INT24:
- if (!fld_length)
+ if (!length)
length= MAX_MEDIUMINT_WIDTH+sign_len;
allowed_type_modifier= AUTO_INCREMENT_FLAG;
break;
case MYSQL_TYPE_LONG:
- if (!fld_length)
+ if (!length)
length= MAX_INT_WIDTH+sign_len;
allowed_type_modifier= AUTO_INCREMENT_FLAG;
break;
case MYSQL_TYPE_LONGLONG:
- if (!fld_length)
+ if (!length)
length= MAX_BIGINT_WIDTH;
allowed_type_modifier= AUTO_INCREMENT_FLAG;
break;
@@ -9331,18 +9321,17 @@ bool Create_field::init(THD *thd, char *fld_name, enum_field_types fld_type,
my_decimal_trim(&length, &decimals);
if (length > DECIMAL_MAX_PRECISION)
{
- my_error(ER_TOO_BIG_PRECISION, MYF(0), static_cast<int>(length),
- fld_name, static_cast<ulong>(DECIMAL_MAX_PRECISION));
+ my_error(ER_TOO_BIG_PRECISION, MYF(0), length, field_name,
+ DECIMAL_MAX_PRECISION);
DBUG_RETURN(TRUE);
}
if (length < decimals)
{
- my_error(ER_M_BIGGER_THAN_D, MYF(0), fld_name);
+ my_error(ER_M_BIGGER_THAN_D, MYF(0), field_name);
DBUG_RETURN(TRUE);
}
length=
- my_decimal_precision_to_length(length, decimals,
- fld_type_modifier & UNSIGNED_FLAG);
+ my_decimal_precision_to_length(length, decimals, flags & UNSIGNED_FLAG);
pack_length=
my_decimal_get_binary_size(length, decimals);
break;
@@ -9360,11 +9349,11 @@ bool Create_field::init(THD *thd, char *fld_name, enum_field_types fld_type,
case MYSQL_TYPE_LONG_BLOB:
case MYSQL_TYPE_MEDIUM_BLOB:
case MYSQL_TYPE_GEOMETRY:
- if (fld_default_value)
+ if (def)
{
/* Allow empty as default value. */
String str,*res;
- res= fld_default_value->val_str(&str);
+ res= def->val_str(&str);
/*
A default other than '' is always an error, and any non-NULL
specified default is an error in strict mode.
@@ -9372,7 +9361,7 @@ bool Create_field::init(THD *thd, char *fld_name, enum_field_types fld_type,
if (res->length() || thd->is_strict_mode())
{
my_error(ER_BLOB_CANT_HAVE_DEFAULT, MYF(0),
- fld_name); /* purecov: inspected */
+ field_name); /* purecov: inspected */
DBUG_RETURN(TRUE);
}
else
@@ -9383,39 +9372,21 @@ bool Create_field::init(THD *thd, char *fld_name, enum_field_types fld_type,
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
ER_BLOB_CANT_HAVE_DEFAULT,
ER(ER_BLOB_CANT_HAVE_DEFAULT),
- fld_name);
+ field_name);
}
def= 0;
}
flags|= BLOB_FLAG;
break;
case MYSQL_TYPE_YEAR:
- if (!fld_length || length != 2)
+ if (!length || length != 2)
length= 4; /* Default length */
flags|= ZEROFILL_FLAG | UNSIGNED_FLAG;
break;
case MYSQL_TYPE_FLOAT:
/* change FLOAT(precision) to FLOAT or DOUBLE */
allowed_type_modifier= AUTO_INCREMENT_FLAG;
- if (fld_length && !fld_decimals)
- {
- uint tmp_length= length;
- if (tmp_length > PRECISION_FOR_DOUBLE)
- {
- my_error(ER_WRONG_FIELD_SPEC, MYF(0), fld_name);
- DBUG_RETURN(TRUE);
- }
- else if (tmp_length > PRECISION_FOR_FLOAT)
- {
- sql_type= MYSQL_TYPE_DOUBLE;
- length= MAX_DOUBLE_STR_LENGTH;
- }
- else
- length= MAX_FLOAT_STR_LENGTH;
- decimals= NOT_FIXED_DEC;
- break;
- }
- if (!fld_length && !fld_decimals)
+ if (!length && !decimals)
{
length= MAX_FLOAT_STR_LENGTH;
decimals= NOT_FIXED_DEC;
@@ -9423,13 +9394,13 @@ bool Create_field::init(THD *thd, char *fld_name, enum_field_types fld_type,
if (length < decimals &&
decimals != NOT_FIXED_DEC)
{
- my_error(ER_M_BIGGER_THAN_D, MYF(0), fld_name);
+ my_error(ER_M_BIGGER_THAN_D, MYF(0), field_name);
DBUG_RETURN(TRUE);
}
break;
case MYSQL_TYPE_DOUBLE:
allowed_type_modifier= AUTO_INCREMENT_FLAG;
- if (!fld_length && !fld_decimals)
+ if (!length && !decimals)
{
length= DBL_DIG+7;
decimals= NOT_FIXED_DEC;
@@ -9437,7 +9408,7 @@ bool Create_field::init(THD *thd, char *fld_name, enum_field_types fld_type,
if (length < decimals &&
decimals != NOT_FIXED_DEC)
{
- my_error(ER_M_BIGGER_THAN_D, MYF(0), fld_name);
+ my_error(ER_M_BIGGER_THAN_D, MYF(0), field_name);
DBUG_RETURN(TRUE);
}
break;
@@ -9445,7 +9416,7 @@ bool Create_field::init(THD *thd, char *fld_name, enum_field_types fld_type,
case MYSQL_TYPE_TIMESTAMP2:
if (length > MAX_DATETIME_PRECISION)
{
- my_error(ER_TOO_BIG_PRECISION, MYF(0), length, fld_name,
+ my_error(ER_TOO_BIG_PRECISION, MYF(0), length, field_name,
MAX_DATETIME_PRECISION);
DBUG_RETURN(TRUE);
}
@@ -9463,7 +9434,7 @@ bool Create_field::init(THD *thd, char *fld_name, enum_field_types fld_type,
case MYSQL_TYPE_TIME2:
if (length > MAX_DATETIME_PRECISION)
{
- my_error(ER_TOO_BIG_PRECISION, MYF(0), length, fld_name,
+ my_error(ER_TOO_BIG_PRECISION, MYF(0), length, field_name,
MAX_DATETIME_PRECISION);
DBUG_RETURN(TRUE);
}
@@ -9473,50 +9444,29 @@ bool Create_field::init(THD *thd, char *fld_name, enum_field_types fld_type,
case MYSQL_TYPE_DATETIME2:
if (length > MAX_DATETIME_PRECISION)
{
- my_error(ER_TOO_BIG_PRECISION, MYF(0), length, fld_name,
+ my_error(ER_TOO_BIG_PRECISION, MYF(0), length, field_name,
MAX_DATETIME_PRECISION);
DBUG_RETURN(TRUE);
}
length+= MAX_DATETIME_WIDTH + (length ? 1 : 0);
break;
case MYSQL_TYPE_SET:
- {
- pack_length= get_set_pack_length(fld_interval_list->elements);
-
- List_iterator<String> it(*fld_interval_list);
- String *tmp;
- while ((tmp= it++))
- interval_list.push_back(tmp);
- /*
- Set fake length to 1 to pass the below conditions.
- Real length will be set in mysql_prepare_table()
- when we know the character set of the column
- */
- length= 1;
- break;
- }
+ pack_length= get_set_pack_length(interval_list.elements);
+ break;
case MYSQL_TYPE_ENUM:
- {
- /* Should be safe. */
- pack_length= get_enum_pack_length(fld_interval_list->elements);
-
- List_iterator<String> it(*fld_interval_list);
- String *tmp;
- while ((tmp= it++))
- interval_list.push_back(tmp);
- length= 1; /* See comment for MYSQL_TYPE_SET above. */
- break;
- }
+ /* Should be safe. */
+ pack_length= get_enum_pack_length(interval_list.elements);
+ break;
case MYSQL_TYPE_VAR_STRING:
DBUG_ASSERT(0); /* Impossible. */
break;
case MYSQL_TYPE_BIT:
{
- if (!fld_length)
+ if (!length)
length= 1;
if (length > MAX_BIT_FIELD_LENGTH)
{
- my_error(ER_TOO_BIG_DISPLAYWIDTH, MYF(0), fld_name,
+ my_error(ER_TOO_BIG_DISPLAYWIDTH, MYF(0), field_name,
static_cast<ulong>(MAX_BIT_FIELD_LENGTH));
DBUG_RETURN(TRUE);
}
@@ -9525,37 +9475,35 @@ bool Create_field::init(THD *thd, char *fld_name, enum_field_types fld_type,
}
case MYSQL_TYPE_DECIMAL:
DBUG_ASSERT(0); /* Was obsolete */
- }
+ }
/* Remember the value of length */
char_length= length;
if (!(flags & BLOB_FLAG) &&
- ((length > max_field_charlength && fld_type != MYSQL_TYPE_SET &&
- fld_type != MYSQL_TYPE_ENUM &&
- (fld_type != MYSQL_TYPE_VARCHAR || fld_default_value)) ||
- ((length == 0) &&
- fld_type != MYSQL_TYPE_STRING &&
- fld_type != MYSQL_TYPE_VARCHAR && fld_type != MYSQL_TYPE_GEOMETRY)))
- {
- my_error((fld_type == MYSQL_TYPE_VAR_STRING ||
- fld_type == MYSQL_TYPE_VARCHAR ||
- fld_type == MYSQL_TYPE_STRING) ? ER_TOO_BIG_FIELDLENGTH :
+ ((length > max_field_charlength &&
+ (sql_type != MYSQL_TYPE_VARCHAR || def)) ||
+ (length == 0 &&
+ sql_type != MYSQL_TYPE_ENUM && sql_type != MYSQL_TYPE_SET &&
+ sql_type != MYSQL_TYPE_STRING && sql_type != MYSQL_TYPE_VARCHAR &&
+ sql_type != MYSQL_TYPE_GEOMETRY)))
+ {
+ my_error((sql_type == MYSQL_TYPE_VAR_STRING ||
+ sql_type == MYSQL_TYPE_VARCHAR ||
+ sql_type == MYSQL_TYPE_STRING) ? ER_TOO_BIG_FIELDLENGTH :
ER_TOO_BIG_DISPLAYWIDTH,
MYF(0),
- fld_name, max_field_charlength); /* purecov: inspected */
+ field_name, max_field_charlength); /* purecov: inspected */
DBUG_RETURN(TRUE);
}
- fld_type_modifier&= AUTO_INCREMENT_FLAG;
- if ((~allowed_type_modifier) & fld_type_modifier)
+ if ((~allowed_type_modifier) & flags & conditional_type_modifiers)
{
- my_error(ER_WRONG_FIELD_SPEC, MYF(0), fld_name);
+ my_error(ER_WRONG_FIELD_SPEC, MYF(0), field_name);
DBUG_RETURN(TRUE);
}
DBUG_RETURN(FALSE); /* success */
}
-
enum_field_types get_blob_type_from_length(ulong length)
{
enum_field_types type;
diff --git a/sql/field.h b/sql/field.h
index dabb6c6b0e0..c813fa2d48e 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -2835,13 +2835,13 @@ public:
const char *change; // If done with alter table
const char *after; // Put column after this one
LEX_STRING comment; // Comment for field
- Item *def; // Default value
+ Item *def, *on_update; // Default value
enum enum_field_types sql_type;
/*
At various stages in execution this can be length of field in bytes or
max number of characters.
*/
- ulong length;
+ ulonglong length;
/*
The value of `length' as set by parser: is the number of characters
for most of the types, or of bytes for BLOBs or numeric types.
@@ -2877,9 +2877,13 @@ public:
*/
bool stored_in_db;
- Create_field() :after(0), option_list(NULL), option_struct(NULL),
- create_if_not_exists(FALSE)
- {}
+ Create_field() :after(0), pack_length(0), key_length(0), interval(0),
+ field(0), option_list(NULL), option_struct(NULL),
+ create_if_not_exists(false), stored_in_db(true)
+ {
+ interval_list.empty();
+ }
+
Create_field(Field *field, Field *orig_field);
/* Used to make a clone of this object for ALTER/CREATE TABLE */
Create_field *clone(MEM_ROOT *mem_root) const;
@@ -2891,12 +2895,7 @@ public:
bool maybe_null, bool is_unsigned,
uint pack_length = ~0U);
- bool init(THD *thd, char *field_name, enum_field_types type, char *length,
- char *decimals, uint type_modifier, Item *default_value,
- Item *on_update_value, LEX_STRING *comment, char *change,
- List<String> *interval_list, CHARSET_INFO *cs,
- uint uint_geom_type, Virtual_column_info *vcol_info,
- engine_option_value *option_list, bool check_exists);
+ bool check(THD *thd);
bool field_flags_are_binary()
{
diff --git a/sql/item_create.cc b/sql/item_create.cc
index 65678ebe1b7..a53a369de12 100644
--- a/sql/item_create.cc
+++ b/sql/item_create.cc
@@ -53,13 +53,12 @@ static const char* item_name(Item *a, String *str)
static void wrong_precision_error(uint errcode, Item *a,
- ulonglong number, ulong maximum)
+ ulonglong number, uint maximum)
{
char buff[1024];
String buf(buff, sizeof(buff), system_charset_info);
- my_error(errcode, MYF(0), (uint) MY_MIN(number, UINT_MAX32),
- item_name(a, &buf), maximum);
+ my_error(errcode, MYF(0), number, item_name(a, &buf), maximum);
}
@@ -87,9 +86,9 @@ bool get_length_and_scale(ulonglong length, ulonglong decimals,
return 1;
}
- *out_length= (ulong) length;
*out_decimals= (uint) decimals;
- my_decimal_trim(out_length, out_decimals);
+ my_decimal_trim(&length, out_decimals);
+ *out_length= (ulong) length;
if (*out_length < *out_decimals)
{
diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc
index 389d9d5380c..c9d99908014 100644
--- a/sql/item_timefunc.cc
+++ b/sql/item_timefunc.cc
@@ -1628,8 +1628,8 @@ bool Item_func_curtime::fix_fields(THD *thd, Item **items)
{
if (decimals > TIME_SECOND_PART_DIGITS)
{
- my_error(ER_TOO_BIG_PRECISION, MYF(0), decimals, func_name(),
- TIME_SECOND_PART_DIGITS);
+ my_error(ER_TOO_BIG_PRECISION, MYF(0), static_cast<ulonglong>(decimals),
+ func_name(), TIME_SECOND_PART_DIGITS);
return 1;
}
return Item_timefunc::fix_fields(thd, items);
@@ -1690,8 +1690,8 @@ bool Item_func_now::fix_fields(THD *thd, Item **items)
{
if (decimals > TIME_SECOND_PART_DIGITS)
{
- my_error(ER_TOO_BIG_PRECISION, MYF(0), decimals, func_name(),
- TIME_SECOND_PART_DIGITS);
+ my_error(ER_TOO_BIG_PRECISION, MYF(0), static_cast<ulonglong>(decimals),
+ func_name(), TIME_SECOND_PART_DIGITS);
return 1;
}
return Item_temporal_func::fix_fields(thd, items);
diff --git a/sql/my_decimal.cc b/sql/my_decimal.cc
index c11bf671cb1..d4f1ae19bc6 100644
--- a/sql/my_decimal.cc
+++ b/sql/my_decimal.cc
@@ -335,7 +335,7 @@ my_decimal *date2my_decimal(MYSQL_TIME *ltime, my_decimal *dec)
}
-void my_decimal_trim(ulong *precision, uint *scale)
+void my_decimal_trim(ulonglong *precision, uint *scale)
{
if (!(*precision) && !(*scale))
{
diff --git a/sql/my_decimal.h b/sql/my_decimal.h
index fa85b41d70c..a2cce862f1a 100644
--- a/sql/my_decimal.h
+++ b/sql/my_decimal.h
@@ -486,7 +486,7 @@ int my_decimal_intg(const my_decimal *a)
}
-void my_decimal_trim(ulong *precision, uint *scale);
+void my_decimal_trim(ulonglong *precision, uint *scale);
#endif /*my_decimal_h*/
diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt
index 2bc7bb1c7a7..653f053ba38 100644
--- a/sql/share/errmsg-utf8.txt
+++ b/sql/share/errmsg-utf8.txt
@@ -5472,8 +5472,8 @@ ER_TOO_BIG_SCALE 42000 S1009
eng "Too big scale %u specified for '%-.192s'. Maximum is %lu."
ger "Zu großer Skalierungsfaktor %u für '%-.192s' angegeben. Maximum ist %lu"
ER_TOO_BIG_PRECISION 42000 S1009
- eng "Too big precision %u specified for '%-.192s'. Maximum is %lu."
- ger "Zu große Genauigkeit %u für '%-.192s' angegeben. Maximum ist %lu"
+ eng "Too big precision %llu specified for '%-.192s'. Maximum is %u."
+ ger "Zu große Genauigkeit %llu für '%-.192s' angegeben. Maximum ist %u"
ER_M_BIGGER_THAN_D 42000 S1009
eng "For float(M,D), double(M,D) or decimal(M,D), M must be >= D (column '%-.192s')."
ger "Für FLOAT(M,D), DOUBLE(M,D) oder DECIMAL(M,D) muss M >= D sein (Feld '%-.192s')"
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index 21f8726eb34..9f42e83d7f2 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -2216,16 +2216,6 @@ sp_head::reset_lex(THD *thd)
sublex->trg_table_fields.empty();
sublex->sp_lex_in_use= FALSE;
- /* Reset type info. */
-
- sublex->charset= NULL;
- sublex->length= NULL;
- sublex->dec= NULL;
- sublex->interval_list.empty();
- sublex->type= 0;
- sublex->uint_geom_type= 0;
- sublex->vcol_info= 0;
-
/* Reset part of parser state which needs this. */
thd->m_parser_state->m_yacc.reset_before_substatement();
@@ -2351,16 +2341,9 @@ sp_head::fill_field_definition(THD *thd, LEX *lex,
enum enum_field_types field_type,
Create_field *field_def)
{
- LEX_STRING cmt = { 0, 0 };
uint unused1= 0;
- if (field_def->init(thd, (char*) "", field_type, lex->length, lex->dec,
- lex->type, (Item*) 0, (Item*) 0, &cmt, 0,
- &lex->interval_list,
- lex->charset ? lex->charset :
- thd->variables.collation_database,
- lex->uint_geom_type,
- lex->vcol_info, NULL, FALSE))
+ if (field_def->check(thd))
return TRUE;
if (field_def->interval_list.elements)
diff --git a/sql/sp_pcontext.cc b/sql/sp_pcontext.cc
index 11954921e06..6afca24231b 100644
--- a/sql/sp_pcontext.cc
+++ b/sql/sp_pcontext.cc
@@ -183,13 +183,10 @@ sp_variable *sp_pcontext::find_variable(uint offset) const
}
-sp_variable *sp_pcontext::add_variable(THD *thd,
- LEX_STRING name,
- enum enum_field_types type,
- sp_variable::enum_mode mode)
+sp_variable *sp_pcontext::add_variable(THD *thd, LEX_STRING name)
{
sp_variable *p=
- new (thd->mem_root) sp_variable(name, type,mode, current_var_count());
+ new (thd->mem_root) sp_variable(name, current_var_count());
if (!p)
return NULL;
diff --git a/sql/sp_pcontext.h b/sql/sp_pcontext.h
index 4d8623108aa..efe9531c3a0 100644
--- a/sql/sp_pcontext.h
+++ b/sql/sp_pcontext.h
@@ -63,12 +63,11 @@ public:
Create_field field_def;
public:
- sp_variable(LEX_STRING _name, enum_field_types _type, enum_mode _mode,
- uint _offset)
+ sp_variable(LEX_STRING _name, uint _offset)
:Sql_alloc(),
name(_name),
- type(_type),
- mode(_mode),
+ type(MYSQL_TYPE_NULL),
+ mode(MODE_IN),
offset(_offset),
default_value(NULL)
{ }
@@ -340,14 +339,9 @@ public:
///
/// @param thd Thread context.
/// @param name Name of the SP-variable.
- /// @param type Type of the SP-variable.
- /// @param mode Mode of the SP-variable.
///
/// @return instance of newly added SP-variable.
- sp_variable *add_variable(THD *thd,
- LEX_STRING name,
- enum enum_field_types type,
- sp_variable::enum_mode mode);
+ sp_variable *add_variable(THD *thd, LEX_STRING name);
/// Retrieve full type information about SP-variables in this parsing
/// context and its children.
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index d1aa2464210..0240f338da3 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -125,6 +125,7 @@ struct LEX_TYPE
#if MYSQL_LEX
#include "item_func.h" /* Cast_target used in sql_yacc.h */
#include "sql_get_diagnostics.h" /* Types used in sql_yacc.h */
+#include "sp_pcontext.h"
#include "sql_yacc.h"
#define LEX_YYSTYPE YYSTYPE *
#else
@@ -2380,7 +2381,10 @@ struct LEX: public Query_tables_list
/* Query Plan Footprint of a currently running select */
Explain_query *explain;
- char *length,*dec,*change;
+ // type information
+ char *length,*dec;
+ CHARSET_INFO *charset;
+
LEX_STRING name;
char *help_arg;
char *backup_dir; /* For RESTORE/BACKUP */
@@ -2389,18 +2393,15 @@ struct LEX: public Query_tables_list
String *wild; /* Wildcard in SHOW {something} LIKE 'wild'*/
sql_exchange *exchange;
select_result *result;
- Item *default_value, *on_update_value;
LEX_STRING comment, ident;
LEX_USER *grant_user;
XID *xid;
THD *thd;
- Virtual_column_info *vcol_info;
/* maintain a list of used plugins for this LEX */
DYNAMIC_ARRAY plugins;
plugin_ref plugins_static_buffer[INITIAL_LEX_PLUGIN_LIST_SIZE];
- CHARSET_INFO *charset;
bool text_string_is_7bit;
/** SELECT of CREATE VIEW statement */
@@ -2422,7 +2423,6 @@ struct LEX: public Query_tables_list
List<Key_part_spec> col_list;
List<Key_part_spec> ref_list;
- List<String> interval_list;
List<LEX_USER> users_list;
List<LEX_COLUMN> columns;
List<Item> *insert_list,field_list,value_list,update_list;
@@ -2512,7 +2512,6 @@ struct LEX: public Query_tables_list
uint profile_query_id;
uint profile_options;
- uint uint_geom_type;
uint grant, grant_tot_col, which_columns;
enum Foreign_key::fk_match_opt fk_match_option;
enum Foreign_key::fk_option fk_update_opt;
@@ -2623,9 +2622,17 @@ struct LEX: public Query_tables_list
};
/**
- Collects create options for Field and KEY
+ Collects create options for KEY
*/
- engine_option_value *option_list, *option_list_last;
+ engine_option_value *option_list;
+
+ /**
+ Helper pointer to the end of the list when parsing options for
+ LEX::create_info.option_list (for table)
+ LEX::last_field->option_list (for fields)
+ LEX::option_list (for indexes)
+ */
+ engine_option_value *option_list_last;
/**
During name resolution search only in the table list given by
@@ -2806,6 +2813,10 @@ struct LEX: public Query_tables_list
int print_explain(select_result_sink *output, uint8 explain_flags,
bool is_analyze, bool *printed_anything);
void restore_set_statement_var();
+
+ void init_last_field(Create_field *field, const char *name, CHARSET_INFO *cs);
+ void set_last_field_type(enum enum_field_types type);
+ bool set_bincmp(CHARSET_INFO *cs, bool bin);
};
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 63a1d69a083..360360d4425 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -7097,113 +7097,6 @@ bool mysql_test_parse_for_slave(THD *thd, char *rawbuf, uint length)
#endif
-
-/**
- Store field definition for create.
-
- @return
- Return 0 if ok
-*/
-
-bool add_field_to_list(THD *thd, LEX_STRING *field_name, enum_field_types type,
- char *length, char *decimals,
- uint type_modifier,
- Item *default_value, Item *on_update_value,
- LEX_STRING *comment,
- char *change,
- List<String> *interval_list, CHARSET_INFO *cs,
- uint uint_geom_type,
- Virtual_column_info *vcol_info,
- engine_option_value *create_options)
-{
- register Create_field *new_field;
- LEX *lex= thd->lex;
- uint8 datetime_precision= length ? atoi(length) : 0;
- DBUG_ENTER("add_field_to_list");
-
- if (check_string_char_length(field_name, "", NAME_CHAR_LEN,
- system_charset_info, 1))
- {
- my_error(ER_TOO_LONG_IDENT, MYF(0), field_name->str); /* purecov: inspected */
- DBUG_RETURN(1); /* purecov: inspected */
- }
- if (type_modifier & PRI_KEY_FLAG)
- {
- Key *key;
- lex->col_list.push_back(new Key_part_spec(*field_name, 0));
- key= new Key(Key::PRIMARY, null_lex_str,
- &default_key_create_info,
- 0, lex->col_list, NULL, lex->check_exists);
- lex->alter_info.key_list.push_back(key);
- lex->col_list.empty();
- }
- if (type_modifier & (UNIQUE_FLAG | UNIQUE_KEY_FLAG))
- {
- Key *key;
- lex->col_list.push_back(new Key_part_spec(*field_name, 0));
- key= new Key(Key::UNIQUE, null_lex_str,
- &default_key_create_info, 0,
- lex->col_list, NULL, lex->check_exists);
- lex->alter_info.key_list.push_back(key);
- lex->col_list.empty();
- }
-
- if (default_value)
- {
- /*
- Default value should be literal => basic constants =>
- no need fix_fields()
-
- We allow only one function as part of default value -
- NOW() as default for TIMESTAMP and DATETIME type.
- */
- if (default_value->type() == Item::FUNC_ITEM &&
- (static_cast<Item_func*>(default_value)->functype() !=
- Item_func::NOW_FUNC ||
- (mysql_type_to_time_type(type) != MYSQL_TIMESTAMP_DATETIME) ||
- default_value->decimals < datetime_precision))
- {
- my_error(ER_INVALID_DEFAULT, MYF(0), field_name->str);
- DBUG_RETURN(1);
- }
- else if (default_value->type() == Item::NULL_ITEM)
- {
- default_value= 0;
- if ((type_modifier & (NOT_NULL_FLAG | AUTO_INCREMENT_FLAG)) ==
- NOT_NULL_FLAG)
- {
- my_error(ER_INVALID_DEFAULT, MYF(0), field_name->str);
- DBUG_RETURN(1);
- }
- }
- else if (type_modifier & AUTO_INCREMENT_FLAG)
- {
- my_error(ER_INVALID_DEFAULT, MYF(0), field_name->str);
- DBUG_RETURN(1);
- }
- }
-
- if (on_update_value &&
- (mysql_type_to_time_type(type) != MYSQL_TIMESTAMP_DATETIME ||
- on_update_value->decimals < datetime_precision))
- {
- my_error(ER_INVALID_ON_UPDATE, MYF(0), field_name->str);
- DBUG_RETURN(1);
- }
-
- if (!(new_field= new Create_field()) ||
- new_field->init(thd, field_name->str, type, length, decimals, type_modifier,
- default_value, on_update_value, comment, change,
- interval_list, cs, uint_geom_type, vcol_info,
- create_options, lex->check_exists))
- DBUG_RETURN(1);
-
- lex->alter_info.create_list.push_back(new_field);
- lex->last_field=new_field;
- DBUG_RETURN(0);
-}
-
-
/** Store position for column in ALTER TABLE .. ADD column. */
void store_position_for_column(const char *name)
@@ -9138,3 +9031,18 @@ merge_charset_and_collation(CHARSET_INFO *cs, CHARSET_INFO *cl)
}
return cs;
}
+
+/** find a collation with binary comparison rules
+*/
+CHARSET_INFO *find_bin_collation(CHARSET_INFO *cs)
+{
+ const char *csname= cs->csname;
+ cs= get_charset_by_csname(csname, MY_CS_BINSORT, MYF(0));
+ if (!cs)
+ {
+ char tmp[65];
+ strxnmov(tmp, sizeof(tmp)-1, csname, "_bin", NULL);
+ my_error(ER_UNKNOWN_COLLATION, MYF(0), tmp);
+ }
+ return cs;
+}
diff --git a/sql/sql_parse.h b/sql/sql_parse.h
index da024a5e746..0620e278b79 100644
--- a/sql/sql_parse.h
+++ b/sql/sql_parse.h
@@ -73,6 +73,7 @@ bool check_string_char_length(LEX_STRING *str, const char *err_msg,
uint max_char_length, CHARSET_INFO *cs,
bool no_error);
CHARSET_INFO* merge_charset_and_collation(CHARSET_INFO *cs, CHARSET_INFO *cl);
+CHARSET_INFO *find_bin_collation(CHARSET_INFO *cs);
bool check_host_name(LEX_STRING *str);
bool check_identifier_name(LEX_STRING *str, uint max_char_length,
uint err_code, const char *param_for_err_msg);
@@ -104,16 +105,6 @@ bool append_file_to_dir(THD *thd, const char **filename_ptr,
const char *table_name);
void execute_init_command(THD *thd, LEX_STRING *init_command,
mysql_rwlock_t *var_lock);
-bool add_field_to_list(THD *thd, LEX_STRING *field_name, enum enum_field_types type,
- char *length, char *decimal,
- uint type_modifier,
- Item *default_value, Item *on_update_value,
- LEX_STRING *comment,
- char *change, List<String> *interval_list,
- CHARSET_INFO *cs,
- uint uint_geom_type,
- Virtual_column_info *vcol_info,
- engine_option_value *create_options);
bool add_to_list(THD *thd, SQL_I_List<ORDER> &list, Item *group, bool asc);
void add_join_on(TABLE_LIST *b,Item *expr);
void add_join_natural(TABLE_LIST *a,TABLE_LIST *b,List<String> *using_fields,
diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc
index 1874fb5e66d..343527ab030 100644
--- a/sql/sql_plugin.cc
+++ b/sql/sql_plugin.cc
@@ -3077,7 +3077,9 @@ void plugin_thdvar_init(THD *thd)
intern_plugin_unlock(NULL, old_table_plugin);
intern_plugin_unlock(NULL, old_tmp_table_plugin);
mysql_mutex_unlock(&LOCK_plugin);
- } else {
+ }
+ else
+ {
thd->variables.table_plugin= NULL;
thd->variables.tmp_table_plugin= NULL;
}
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index c29394ed88d..12f30d9fd6e 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -3248,18 +3248,10 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
*/
sql_field->length= sql_field->char_length;
/* Set field charset. */
- save_cs= sql_field->charset= get_sql_field_charset(sql_field,
- create_info);
+ save_cs= sql_field->charset= get_sql_field_charset(sql_field, create_info);
if ((sql_field->flags & BINCMP_FLAG) &&
- !(sql_field->charset= get_charset_by_csname(sql_field->charset->csname,
- MY_CS_BINSORT,MYF(0))))
- {
- char tmp[65];
- strmake(strmake(tmp, save_cs->csname, sizeof(tmp)-4),
- STRING_WITH_LEN("_bin"));
- my_error(ER_UNKNOWN_COLLATION, MYF(0), tmp);
+ !(sql_field->charset= find_bin_collation(sql_field->charset)))
DBUG_RETURN(TRUE);
- }
/*
Convert the default value from client character
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 52b7db7e617..8a56a86f1bf 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -45,7 +45,6 @@
#include "lex_symbol.h"
#include "item_create.h"
#include "sp_head.h"
-#include "sp_pcontext.h"
#include "sp_rcontext.h"
#include "sp.h"
#include "sql_show.h"
@@ -731,7 +730,6 @@ static bool add_create_index_prepare (LEX *lex, Table_ident *table)
lex->alter_info.reset();
lex->alter_info.flags= Alter_info::ALTER_ADD_INDEX;
lex->col_list.empty();
- lex->change= NullS;
lex->option_list= NULL;
return FALSE;
}
@@ -862,6 +860,85 @@ static bool sp_create_assignment_instr(THD *thd, bool no_lookahead)
}
+static void add_key_to_list(LEX *lex, LEX_STRING *field_name,
+ enum Key::Keytype type)
+{
+ Key *key;
+ lex->col_list.push_back(new Key_part_spec(*field_name, 0));
+ key= new Key(type, null_lex_str,
+ &default_key_create_info, 0,
+ lex->col_list, NULL, lex->check_exists);
+ lex->alter_info.key_list.push_back(key);
+ lex->col_list.empty();
+}
+
+void LEX::init_last_field(Create_field *field, const char *name, CHARSET_INFO *cs)
+{
+ last_field= field;
+
+ field->field_name= name;
+ field->flags= 0;
+ field->def= 0;
+ field->on_update= 0;
+ field->sql_type= MYSQL_TYPE_NULL;
+ field->change= 0;
+ field->geom_type= Field::GEOM_GEOMETRY;
+ field->comment= null_lex_str;
+ field->vcol_info= 0;
+ field->interval_list.empty();
+
+ /* reset LEX fields that are used in Create_field::set_and_check() */
+ length= 0;
+ dec= 0;
+ charset= cs;
+}
+
+void LEX::set_last_field_type(enum enum_field_types type)
+{
+ last_field->sql_type= type;
+ last_field->create_if_not_exists= check_exists;
+ last_field->charset= charset;
+
+ if (length)
+ {
+ int err;
+ last_field->length= my_strtoll10(length, NULL, &err);
+ if (err)
+ last_field->length= ~0ULL; // safety
+ }
+ else
+ last_field->length= 0;
+
+ last_field->decimals= dec ? (uint)atoi(dec) : 0;
+}
+
+bool LEX::set_bincmp(CHARSET_INFO *cs, bool bin)
+{
+ /*
+ if charset is NULL - we're parsing a field declaration.
+ we cannot call find_bin_collation for a field here, because actual
+ field charset is determined in get_sql_field_charset() much later.
+ so we only set a flag.
+ */
+ if (!charset)
+ {
+ charset= cs;
+ last_field->flags|= bin ? BINCMP_FLAG : 0;
+ return false;
+ }
+
+ charset= bin ? find_bin_collation(cs ? cs : charset)
+ : cs ? cs : charset;
+ return charset == NULL;
+}
+
+#define bincmp_collation(X,Y) \
+ do \
+ { \
+ if (Lex->set_bincmp(X,Y)) \
+ MYSQL_YYABORT; \
+ } while(0)
+
%}
%union {
int num;
@@ -871,7 +948,6 @@ static bool sp_create_assignment_instr(THD *thd, bool no_lookahead)
LEX_STRING lex_str;
LEX_STRING *lex_str_ptr;
LEX_SYMBOL symbol;
- LEX_TYPE lex_type;
Table_ident *table;
char *simple_string;
Item *item;
@@ -888,6 +964,8 @@ static bool sp_create_assignment_instr(THD *thd, bool no_lookahead)
enum enum_var_type var_type;
Key::Keytype key_type;
enum ha_key_alg key_alg;
+ enum enum_field_types field_type;
+ enum Field::geometry_type geom_type;
handlerton *db_type;
enum row_type row_type;
enum ha_rkey_function ha_rkey_mode;
@@ -907,12 +985,14 @@ static bool sp_create_assignment_instr(THD *thd, bool no_lookahead)
class sp_label *splabel;
LEX *lex;
class my_var *myvar;
- sp_head *sphead;
+ class sp_head *sphead;
+ class sp_variable *spvar;
struct p_elem_val *p_elem_value;
enum index_hint_type index_hint;
enum enum_filetype filetype;
enum Foreign_key::fk_option m_fk_option;
enum enum_yes_no_unknown m_yes_no_unk;
+ enum sp_variable::enum_mode spvar_mode;
Diag_condition_item_name diag_condition_item_name;
Diagnostics_information::Which_area diag_area;
Diagnostics_information *diag_info;
@@ -1643,14 +1723,16 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%type <string>
text_string hex_or_bin_String opt_gconcat_separator
-%type <lex_type> field_def
+%type <field_type> type_with_opt_collate int_type real_type field_type
+
+%type <geom_type> spatial_type
%type <num>
- type type_with_opt_collate int_type real_type order_dir lock_option
+ order_dir lock_option
udf_type opt_if_exists opt_local opt_table_options table_options
table_option opt_if_not_exists create_or_replace opt_no_write_to_binlog
opt_temporary all_or_any opt_distinct
- opt_ignore_leaves fulltext_options spatial_type union_option
+ opt_ignore_leaves fulltext_options union_option
opt_not opt_union_order_or_limit
union_opt select_derived_init transaction_access_mode_types
opt_natural_language_mode opt_query_expansion
@@ -1659,7 +1741,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
optional_flush_tables_arguments opt_dyncol_type dyncol_type
opt_time_precision kill_type kill_option int_num
opt_default_time_precision
- case_stmt_body
+ case_stmt_body opt_bin_mod
/*
Bit field of MYSQL_START_TRANS_OPT_* flags.
@@ -1763,6 +1845,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%type <charset>
opt_collate
charset_name
+ charset_or_alias
charset_name_or_default
old_or_new_charset_name
old_or_new_charset_name_or_default
@@ -1805,10 +1888,10 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
select_item_list select_item values_list no_braces
opt_limit_clause delete_limit_clause fields opt_values values
procedure_list procedure_list2 procedure_item
- handler
+ field_def handler opt_generated_always
opt_precision opt_ignore opt_column opt_restrict
grant revoke set lock unlock string_list field_options field_option
- field_opt_list opt_binary ascii unicode table_lock_list table_lock
+ field_opt_list opt_binary table_lock_list table_lock
ref_list opt_match_clause opt_on_update_delete use
opt_delete_options opt_delete_option varchar nchar nvarchar
opt_outer table_list table_name table_alias_ref_list table_alias_ref
@@ -1863,12 +1946,14 @@ END_OF_INPUT
%type <NONE> sp_proc_stmt_open sp_proc_stmt_fetch sp_proc_stmt_close
%type <NONE> case_stmt_specification
-%type <num> sp_decl_idents sp_opt_inout sp_handler_type sp_hcond_list
+%type <num> sp_decl_idents sp_handler_type sp_hcond_list
%type <spcondvalue> sp_cond sp_hcond sqlstate signal_value opt_signal_value
%type <spblock> sp_decls sp_decl
%type <lex> sp_cursor_stmt
%type <spname> sp_name
%type <splabel> sp_block_content
+%type <spvar> sp_param_name_and_type
+%type <spvar_mode> sp_opt_inout
%type <index_hint> index_hint_type
%type <num> index_hint_clause normal_join inner_join
%type <filetype> data_or_xml
@@ -2379,7 +2464,6 @@ create:
MYSQL_YYABORT;
lex->alter_info.reset();
lex->col_list.empty();
- lex->change=NullS;
bzero((char*) &lex->create_info,sizeof(lex->create_info));
/*
For CREATE TABLE we should not open the table even if it exists.
@@ -2836,33 +2920,12 @@ sp_fdparam_list:
;
sp_fdparams:
- sp_fdparams ',' sp_fdparam
- | sp_fdparam
- ;
-
-sp_init_param:
- /* Empty */
- {
- LEX *lex= Lex;
-
- lex->length= 0;
- lex->dec= 0;
- lex->type= 0;
-
- lex->default_value= 0;
- lex->on_update_value= 0;
-
- lex->comment= null_lex_str;
- lex->charset= NULL;
-
- lex->interval_list.empty();
- lex->uint_geom_type= 0;
- lex->vcol_info= 0;
- }
+ sp_fdparams ',' sp_param_name_and_type
+ | sp_param_name_and_type
;
-sp_fdparam:
- ident sp_init_param type_with_opt_collate
+sp_param_name_and_type:
+ ident
{
LEX *lex= Lex;
sp_pcontext *spc= lex->spcont;
@@ -2873,19 +2936,27 @@ sp_fdparam:
MYSQL_YYABORT;
}
- sp_variable *spvar= spc->add_variable(thd,
- $1,
- (enum enum_field_types) $3,
- sp_variable::MODE_IN);
+ sp_variable *spvar= spc->add_variable(thd, $1);
- if (lex->sphead->fill_field_definition(thd, lex,
- (enum enum_field_types) $3,
- &spvar->field_def))
+ lex->init_last_field(&spvar->field_def, $1.str,
+ thd->variables.collation_database);
+ $<spvar>$= spvar;
+ }
+ type_with_opt_collate
+ {
+ LEX *lex= Lex;
+ sp_variable *spvar= $<spvar>2;
+
+ spvar->type= $3;
+ if (lex->sphead->fill_field_definition(thd, lex, $3,
+ lex->last_field))
{
MYSQL_YYABORT;
}
spvar->field_def.field_name= spvar->name.str;
spvar->field_def.pack_flag |= FIELDFLAG_MAYBE_NULL;
+
+ $$= spvar;
}
;
@@ -2901,30 +2972,7 @@ sp_pdparams:
;
sp_pdparam:
- sp_opt_inout sp_init_param ident type_with_opt_collate
- {
- LEX *lex= Lex;
- sp_pcontext *spc= lex->spcont;
-
- if (spc->find_variable($3, TRUE))
- {
- my_error(ER_SP_DUP_PARAM, MYF(0), $3.str);
- MYSQL_YYABORT;
- }
- sp_variable *spvar= spc->add_variable(thd,
- $3,
- (enum enum_field_types) $4,
- (sp_variable::enum_mode) $1);
-
- if (lex->sphead->fill_field_definition(thd, lex,
- (enum enum_field_types) $4,
- &spvar->field_def))
- {
- MYSQL_YYABORT;
- }
- spvar->field_def.field_name= spvar->name.str;
- spvar->field_def.pack_flag |= FIELDFLAG_MAYBE_NULL;
- }
+ sp_opt_inout sp_param_name_and_type { $2->mode=$1; }
;
sp_opt_inout:
@@ -2978,9 +3026,17 @@ sp_decl:
DECLARE_SYM sp_decl_idents
{
LEX *lex= Lex;
+ sp_pcontext *pctx= lex->spcont;
+
+ // get the last variable:
+ uint num_vars= pctx->context_var_count();
+ uint var_idx= pctx->var_context2runtime(num_vars - 1);
+ sp_variable *spvar= pctx->find_variable(var_idx);
lex->sphead->reset_lex(thd);
- lex->spcont->declare_var_boundary($2);
+ pctx->declare_var_boundary($2);
+ thd->lex->init_last_field(&spvar->field_def, spvar->name.str,
+ thd->variables.collation_database);
}
type_with_opt_collate
sp_opt_default
@@ -2988,7 +3044,7 @@ sp_decl:
LEX *lex= Lex;
sp_pcontext *pctx= lex->spcont;
uint num_vars= pctx->context_var_count();
- enum enum_field_types var_type= (enum enum_field_types) $4;
+ enum enum_field_types var_type= $4;
Item *dflt_value_item= $5;
if (!dflt_value_item)
@@ -3003,12 +3059,17 @@ sp_decl:
{
uint var_idx= pctx->var_context2runtime(i);
sp_variable *spvar= pctx->find_variable(var_idx);
+ bool last= i == num_vars - 1;
if (!spvar)
MYSQL_YYABORT;
+ if (!last)
+ spvar->field_def= *lex->last_field;
+
spvar->type= var_type;
spvar->default_value= dflt_value_item;
+ spvar->field_def.field_name= spvar->name.str;
if (lex->sphead->fill_field_definition(thd, lex, var_type,
&spvar->field_def))
@@ -3016,7 +3077,6 @@ sp_decl:
MYSQL_YYABORT;
}
- spvar->field_def.field_name= spvar->name.str;
spvar->field_def.pack_flag |= FIELDFLAG_MAYBE_NULL;
/* The last instruction is responsible for freeing LEX. */
@@ -3027,7 +3087,7 @@ sp_decl:
dflt_value_item,
var_type,
lex,
- (i == num_vars - 1));
+ last);
if (is == NULL ||
lex->sphead->add_instr(is))
MYSQL_YYABORT;
@@ -3581,10 +3641,7 @@ sp_decl_idents:
my_error(ER_SP_DUP_VAR, MYF(0), $1.str);
MYSQL_YYABORT;
}
- spc->add_variable(thd,
- $1,
- MYSQL_TYPE_DECIMAL,
- sp_variable::MODE_IN);
+ spc->add_variable(thd, $1);
$$= 1;
}
| sp_decl_idents ',' ident
@@ -3599,10 +3656,7 @@ sp_decl_idents:
my_error(ER_SP_DUP_VAR, MYF(0), $3.str);
MYSQL_YYABORT;
}
- spc->add_variable(thd,
- $3,
- MYSQL_TYPE_DECIMAL,
- sp_variable::MODE_IN);
+ spc->add_variable(thd, $3);
$$= $1 + 1;
}
;
@@ -6038,58 +6092,62 @@ field_spec:
field_ident
{
LEX *lex=Lex;
- lex->length=lex->dec=0;
- lex->type=0;
- lex->default_value= lex->on_update_value= 0;
- lex->comment=null_lex_str;
- lex->charset=NULL;
- lex->vcol_info= 0;
- lex->option_list= NULL;
+ Create_field *f= new Create_field();
+
+ if (check_string_char_length(&$1, "", NAME_CHAR_LEN,
+ system_charset_info, 1))
+ {
+ my_error(ER_TOO_LONG_IDENT, MYF(0), $1.str);
+ MYSQL_YYABORT;
+ }
+
+ if (!f)
+ MYSQL_YYABORT;
+
+ lex->init_last_field(f, $1.str, NULL);
}
+ field_type { Lex->set_last_field_type($3); }
field_def
{
LEX *lex=Lex;
- if (add_field_to_list(lex->thd, &$1, $3.type,
- $3.length, $3.dec, lex->type,
- lex->default_value, lex->on_update_value,
- &lex->comment,
- lex->change, &lex->interval_list, $3.charset,
- lex->uint_geom_type,
- lex->vcol_info, lex->option_list))
+ Create_field *f= lex->last_field;
+
+ if (f->check(thd))
MYSQL_YYABORT;
+
+ lex->alter_info.create_list.push_back(f);
+
+ if (f->flags & PRI_KEY_FLAG)
+ add_key_to_list(lex, &$1, Key::PRIMARY);
+ else if (f->flags & (UNIQUE_FLAG | UNIQUE_KEY_FLAG))
+ add_key_to_list(lex, &$1, Key::UNIQUE);
}
;
field_def:
- type opt_attribute
- { $$.set($1, Lex->length, Lex->dec, Lex->charset); }
- | type opt_generated_always AS
- { $<lex_type>$.set($1, Lex->length, Lex->dec, Lex->charset); }
- '(' virtual_column_func ')' vcol_opt_specifier vcol_opt_attribute
- {
- $$= $<lex_type>4;
- Lex->vcol_info->set_field_type($$.type);
- $$.type= (enum enum_field_types)MYSQL_TYPE_VIRTUAL;
- }
+ opt_attribute
+ | opt_generated_always AS
+ '(' virtual_column_func ')'
+ vcol_opt_specifier vcol_opt_attribute
;
opt_generated_always:
- /* empty */
+ /* empty */ {}
| GENERATED_SYM ALWAYS_SYM {}
;
vcol_opt_specifier:
/* empty */
{
- Lex->vcol_info->set_stored_in_db_flag(FALSE);
+ Lex->last_field->vcol_info->set_stored_in_db_flag(FALSE);
}
| VIRTUAL_SYM
{
- Lex->vcol_info->set_stored_in_db_flag(FALSE);
+ Lex->last_field->vcol_info->set_stored_in_db_flag(FALSE);
}
| PERSISTENT_SYM
{
- Lex->vcol_info->set_stored_in_db_flag(TRUE);
+ Lex->last_field->vcol_info->set_stored_in_db_flag(TRUE);
}
;
@@ -6107,16 +6165,16 @@ vcol_attribute:
UNIQUE_SYM
{
LEX *lex=Lex;
- lex->type|= UNIQUE_FLAG;
+ lex->last_field->flags|= UNIQUE_FLAG;
lex->alter_info.flags|= Alter_info::ALTER_ADD_INDEX;
}
| UNIQUE_SYM KEY_SYM
{
LEX *lex=Lex;
- lex->type|= UNIQUE_KEY_FLAG;
+ lex->last_field->flags|= UNIQUE_FLAG;
lex->alter_info.flags|= Alter_info::ALTER_ADD_INDEX;
}
- | COMMENT_SYM TEXT_STRING_sys { Lex->comment= $2; }
+ | COMMENT_SYM TEXT_STRING_sys { Lex->last_field->comment= $2; }
;
parse_vcol_expr:
@@ -6138,23 +6196,41 @@ parse_vcol_expr:
virtual_column_func:
remember_name expr remember_end
{
- Lex->vcol_info= new Virtual_column_info();
- if (!Lex->vcol_info)
+ Virtual_column_info *v= new Virtual_column_info();
+ if (!v)
{
mem_alloc_error(sizeof(Virtual_column_info));
MYSQL_YYABORT;
}
uint expr_len= (uint)($3 - $1) - 1;
- Lex->vcol_info->expr_str.str= (char* ) thd->memdup($1 + 1, expr_len);
- Lex->vcol_info->expr_str.length= expr_len;
- Lex->vcol_info->expr_item= $2;
+ v->expr_str.str= (char* ) thd->memdup($1 + 1, expr_len);
+ v->expr_str.length= expr_len;
+ v->expr_item= $2;
+ Lex->last_field->vcol_info= v;
}
;
-type:
+field_type:
int_type opt_field_length field_options { $$=$1; }
| real_type opt_precision field_options { $$=$1; }
- | FLOAT_SYM float_options field_options { $$=MYSQL_TYPE_FLOAT; }
+ | FLOAT_SYM float_options field_options
+ {
+ $$=MYSQL_TYPE_FLOAT;
+ if (Lex->length && !Lex->dec)
+ {
+ int err;
+ ulonglong tmp_length= my_strtoll10(Lex->length, NULL, &err);
+ if (err || tmp_length > PRECISION_FOR_DOUBLE)
+ {
+ my_error(ER_WRONG_FIELD_SPEC, MYF(0),
+ Lex->last_field->field_name);
+ MYSQL_YYABORT;
+ }
+ else if (tmp_length > PRECISION_FOR_FLOAT)
+ $$= MYSQL_TYPE_DOUBLE;
+ Lex->length= 0;
+ }
+ }
| BIT_SYM
{
Lex->length= (char*) "1";
@@ -6186,13 +6262,13 @@ type:
| nchar field_length opt_bin_mod
{
$$=MYSQL_TYPE_STRING;
- Lex->charset=national_charset_info;
+ bincmp_collation(national_charset_info, $3);
}
| nchar opt_bin_mod
{
Lex->length= (char*) "1";
$$=MYSQL_TYPE_STRING;
- Lex->charset=national_charset_info;
+ bincmp_collation(national_charset_info, $2);
}
| BINARY field_length
{
@@ -6212,7 +6288,7 @@ type:
| nvarchar field_length opt_bin_mod
{
$$= MYSQL_TYPE_VARCHAR;
- Lex->charset=national_charset_info;
+ bincmp_collation(national_charset_info, $3);
}
| VARBINARY field_length
{
@@ -6252,9 +6328,9 @@ type:
/*
Unlike other types TIMESTAMP fields are NOT NULL by default.
*/
- Lex->type|= NOT_NULL_FLAG;
- $$= opt_mysql56_temporal_format ?
- MYSQL_TYPE_TIMESTAMP2 : MYSQL_TYPE_TIMESTAMP;
+ Lex->last_field->flags|= NOT_NULL_FLAG;
+ $$= opt_mysql56_temporal_format ? MYSQL_TYPE_TIMESTAMP2
+ : MYSQL_TYPE_TIMESTAMP;
}
}
| DATETIME opt_field_length
@@ -6274,7 +6350,7 @@ type:
{
#ifdef HAVE_SPATIAL
Lex->charset=&my_charset_bin;
- Lex->uint_geom_type= (uint)$1;
+ Lex->last_field->geom_type= $1;
$$=MYSQL_TYPE_GEOMETRY;
#else
my_error(ER_FEATURE_DISABLED, MYF(0),
@@ -6313,20 +6389,16 @@ type:
{ $$=MYSQL_TYPE_NEWDECIMAL;}
| FIXED_SYM float_options field_options
{ $$=MYSQL_TYPE_NEWDECIMAL;}
- | ENUM
- {Lex->interval_list.empty();}
- '(' string_list ')' opt_binary
+ | ENUM '(' string_list ')' opt_binary
{ $$=MYSQL_TYPE_ENUM; }
- | SET
- { Lex->interval_list.empty();}
- '(' string_list ')' opt_binary
+ | SET '(' string_list ')' opt_binary
{ $$=MYSQL_TYPE_SET; }
| LONG_SYM opt_binary
{ $$=MYSQL_TYPE_MEDIUM_BLOB; }
| SERIAL_SYM
{
$$=MYSQL_TYPE_LONGLONG;
- Lex->type|= (AUTO_INCREMENT_FLAG | NOT_NULL_FLAG | UNSIGNED_FLAG |
+ Lex->last_field->flags|= (AUTO_INCREMENT_FLAG | NOT_NULL_FLAG | UNSIGNED_FLAG |
UNIQUE_FLAG);
}
;
@@ -6419,8 +6491,8 @@ field_opt_list:
field_option:
SIGNED_SYM {}
- | UNSIGNED { Lex->type|= UNSIGNED_FLAG;}
- | ZEROFILL { Lex->type|= UNSIGNED_FLAG | ZEROFILL_FLAG; }
+ | UNSIGNED { Lex->last_field->flags|= UNSIGNED_FLAG;}
+ | ZEROFILL { Lex->last_field->flags|= UNSIGNED_FLAG | ZEROFILL_FLAG; }
;
field_length:
@@ -6450,42 +6522,42 @@ opt_attribute_list:
;
attribute:
- NULL_SYM { Lex->type&= ~ NOT_NULL_FLAG; }
- | not NULL_SYM { Lex->type|= NOT_NULL_FLAG; }
- | DEFAULT now_or_signed_literal { Lex->default_value=$2; }
+ NULL_SYM { Lex->last_field->flags&= ~ NOT_NULL_FLAG; }
+ | not NULL_SYM { Lex->last_field->flags|= NOT_NULL_FLAG; }
+ | DEFAULT now_or_signed_literal { Lex->last_field->def= $2; }
| ON UPDATE_SYM NOW_SYM opt_default_time_precision
{
Item *item= new (thd->mem_root) Item_func_now_local($4);
if (item == NULL)
MYSQL_YYABORT;
- Lex->on_update_value= item;
+ Lex->last_field->on_update= item;
}
- | AUTO_INC { Lex->type|= AUTO_INCREMENT_FLAG | NOT_NULL_FLAG; }
+ | AUTO_INC { Lex->last_field->flags|= AUTO_INCREMENT_FLAG | NOT_NULL_FLAG; }
| SERIAL_SYM DEFAULT VALUE_SYM
{
LEX *lex=Lex;
- lex->type|= AUTO_INCREMENT_FLAG | NOT_NULL_FLAG | UNIQUE_FLAG;
+ lex->last_field->flags|= AUTO_INCREMENT_FLAG | NOT_NULL_FLAG | UNIQUE_FLAG;
lex->alter_info.flags|= Alter_info::ALTER_ADD_INDEX;
}
| opt_primary KEY_SYM
{
LEX *lex=Lex;
- lex->type|= PRI_KEY_FLAG | NOT_NULL_FLAG;
+ lex->last_field->flags|= PRI_KEY_FLAG | NOT_NULL_FLAG;
lex->alter_info.flags|= Alter_info::ALTER_ADD_INDEX;
}
| UNIQUE_SYM
{
LEX *lex=Lex;
- lex->type|= UNIQUE_FLAG;
+ lex->last_field->flags|= UNIQUE_FLAG;
lex->alter_info.flags|= Alter_info::ALTER_ADD_INDEX;
}
| UNIQUE_SYM KEY_SYM
{
LEX *lex=Lex;
- lex->type|= UNIQUE_KEY_FLAG;
+ lex->last_field->flags|= UNIQUE_KEY_FLAG;
lex->alter_info.flags|= Alter_info::ALTER_ADD_INDEX;
}
- | COMMENT_SYM TEXT_STRING_sys { Lex->comment= $2; }
+ | COMMENT_SYM TEXT_STRING_sys { Lex->last_field->comment= $2; }
| COLLATE_SYM collation_name
{
if (Lex->charset && !my_charset_same(Lex->charset,$2))
@@ -6496,52 +6568,46 @@ attribute:
}
else
{
- Lex->charset=$2;
+ Lex->last_field->charset= $2;
}
}
| IDENT_sys equal TEXT_STRING_sys
{
new (thd->mem_root)
- engine_option_value($1, $3, true, &Lex->option_list,
+ engine_option_value($1, $3, true, &Lex->last_field->option_list,
&Lex->option_list_last);
}
| IDENT_sys equal ident
{
new (thd->mem_root)
- engine_option_value($1, $3, false, &Lex->option_list,
+ engine_option_value($1, $3, false, &Lex->last_field->option_list,
&Lex->option_list_last);
}
| IDENT_sys equal real_ulonglong_num
{
new (thd->mem_root)
- engine_option_value($1, $3, &Lex->option_list,
+ engine_option_value($1, $3, &Lex->last_field->option_list,
&Lex->option_list_last, thd->mem_root);
}
| IDENT_sys equal DEFAULT
{
new (thd->mem_root)
- engine_option_value($1, &Lex->option_list, &Lex->option_list_last);
+ engine_option_value($1, &Lex->last_field->option_list, &Lex->option_list_last);
}
;
type_with_opt_collate:
- type opt_collate
+ field_type opt_collate
{
$$= $1;
- if (Lex->charset) /* Lex->charset is scanned in "type" */
+ if ($2)
{
if (!(Lex->charset= merge_charset_and_collation(Lex->charset, $2)))
MYSQL_YYABORT;
}
- else if ($2)
- {
- my_error(ER_NOT_SUPPORTED_YET, MYF(0),
- "COLLATE with no CHARACTER SET "
- "in SP parameters, RETURNS, DECLARE");
- MYSQL_YYABORT;
- }
+ Lex->set_last_field_type($1);
}
;
@@ -6625,62 +6691,30 @@ opt_default:
| DEFAULT {}
;
-
-ascii:
- ASCII_SYM { Lex->charset= &my_charset_latin1; }
- | BINARY ASCII_SYM
- {
- Lex->charset= &my_charset_latin1_bin;
- }
- | ASCII_SYM BINARY
+charset_or_alias:
+ charset charset_name { $$= $2; }
+ | ASCII_SYM { $$= &my_charset_latin1; }
+ | UNICODE_SYM
{
- Lex->charset= &my_charset_latin1_bin;
- }
- ;
-
-unicode:
- UNICODE_SYM
- {
- if (!(Lex->charset=get_charset_by_csname("ucs2",
- MY_CS_PRIMARY,MYF(0))))
+ if (!($$= get_charset_by_csname("ucs2", MY_CS_PRIMARY,MYF(0))))
{
my_error(ER_UNKNOWN_CHARACTER_SET, MYF(0), "ucs2");
MYSQL_YYABORT;
}
}
- | UNICODE_SYM BINARY
- {
- if (!(Lex->charset= mysqld_collation_get_by_name("ucs2_bin")))
- MYSQL_YYABORT;
- }
- | BINARY UNICODE_SYM
- {
- if (!(Lex->charset= mysqld_collation_get_by_name("ucs2_bin")))
- MYSQL_YYABORT;
- }
;
opt_binary:
- /* empty */ { Lex->charset=NULL; }
- | ascii
- | unicode
- | BYTE_SYM { Lex->charset=&my_charset_bin; }
- | charset charset_name opt_bin_mod { Lex->charset=$2; }
- | BINARY
- {
- Lex->charset= NULL;
- Lex->type|= BINCMP_FLAG;
- }
- | BINARY charset charset_name
- {
- Lex->charset= $3;
- Lex->type|= BINCMP_FLAG;
- }
+ /* empty */ { bincmp_collation(NULL, false); }
+ | BYTE_SYM { bincmp_collation(&my_charset_bin, false); }
+ | charset_or_alias opt_bin_mod { bincmp_collation($1, $2); }
+ | BINARY { bincmp_collation(NULL, true); }
+ | BINARY charset_or_alias { bincmp_collation($2, true); }
;
opt_bin_mod:
- /* empty */ { }
- | BINARY { Lex->type|= BINCMP_FLAG; }
+ /* empty */ { $$= false; }
+ | BINARY { $$= true; }
;
ws_nweights:
@@ -7051,8 +7085,8 @@ opt_component:
;
string_list:
- text_string { Lex->interval_list.push_back($1); }
- | string_list ',' text_string { Lex->interval_list.push_back($3); };
+ text_string { Lex->last_field->interval_list.push_back($1); }
+ | string_list ',' text_string { Lex->last_field->interval_list.push_back($3); };
/*
** Alter table
@@ -7522,7 +7556,6 @@ add_column:
ADD opt_column opt_if_not_exists
{
LEX *lex=Lex;
- lex->change=0;
lex->alter_info.flags|= Alter_info::ALTER_ADD_COLUMN;
}
;
@@ -7542,44 +7575,17 @@ alter_list_item:
Lex->alter_info.flags|= Alter_info::ALTER_ADD_COLUMN |
Alter_info::ALTER_ADD_INDEX;
}
- | CHANGE opt_column opt_if_exists field_ident
- {
- LEX *lex=Lex;
- lex->change= $4.str;
- lex->alter_info.flags|= Alter_info::ALTER_CHANGE_COLUMN;
- lex->option_list= NULL;
- }
- field_spec opt_place
+ | CHANGE opt_column opt_if_exists field_ident field_spec opt_place
{
+ Lex->alter_info.flags|= Alter_info::ALTER_CHANGE_COLUMN;
Lex->create_last_non_select_table= Lex->last_table();
+ Lex->last_field->change= $4.str;
}
- | MODIFY_SYM opt_column opt_if_exists field_ident
- {
- LEX *lex=Lex;
- lex->length=lex->dec=0; lex->type=0;
- lex->default_value= lex->on_update_value= 0;
- lex->comment=null_lex_str;
- lex->charset= NULL;
- lex->alter_info.flags|= Alter_info::ALTER_CHANGE_COLUMN;
- lex->vcol_info= 0;
- lex->option_list= NULL;
- }
- field_def
- {
- LEX *lex=Lex;
- if (add_field_to_list(lex->thd,&$4,
- $6.type,
- $6.length, $6.dec, lex->type,
- lex->default_value, lex->on_update_value,
- &lex->comment,
- $4.str, &lex->interval_list, $6.charset,
- lex->uint_geom_type,
- lex->vcol_info, lex->option_list))
- MYSQL_YYABORT;
- }
- opt_place
+ | MODIFY_SYM opt_column opt_if_exists field_spec opt_place
{
+ Lex->alter_info.flags|= Alter_info::ALTER_CHANGE_COLUMN;
Lex->create_last_non_select_table= Lex->last_table();
+ Lex->last_field->change= Lex->last_field->field_name;
}
| DROP opt_column opt_if_exists field_ident opt_restrict
{
@@ -9083,7 +9089,9 @@ dyncol_type:
$$= DYN_COL_DECIMAL;
Lex->charset= NULL;
}
- | char opt_binary
+ | char
+ { Lex->charset= thd->variables.collation_connection; }
+ opt_binary
{
LEX *lex= Lex;
$$= DYN_COL_STRING;
@@ -10414,7 +10422,9 @@ in_sum_expr:
cast_type:
BINARY opt_field_length
{ $$=ITEM_CAST_CHAR; Lex->charset= &my_charset_bin; Lex->dec= 0; }
- | CHAR_SYM opt_field_length opt_binary
+ | CHAR_SYM opt_field_length
+ { Lex->charset= thd->variables.collation_connection; }
+ opt_binary
{ $$=ITEM_CAST_CHAR; Lex->dec= 0; }
| NCHAR_SYM opt_field_length
{ $$=ITEM_CAST_CHAR; Lex->charset= national_charset_info; Lex->dec=0; }
@@ -13259,8 +13269,7 @@ opt_ignore_lines:
;
lines_or_rows:
- LINES { }
-
+ LINES { }
| ROWS_SYM { }
;
@@ -16233,31 +16242,13 @@ sf_tail:
RETURNS_SYM /* $9 */
{ /* $10 */
LEX *lex= Lex;
- lex->charset= NULL;
- lex->length= lex->dec= NULL;
- lex->interval_list.empty();
- lex->type= 0;
- lex->vcol_info= 0;
+ lex->init_last_field(&lex->sphead->m_return_field_def, NULL,
+ thd->variables.collation_database);
}
type_with_opt_collate /* $11 */
{ /* $12 */
- LEX *lex= Lex;
- sp_head *sp= lex->sphead;
- /*
- This was disabled in 5.1.12. See bug #20701
- When collation support in SP is implemented, then this test
- should be removed.
- */
- if (($11 == MYSQL_TYPE_STRING || $11 == MYSQL_TYPE_VARCHAR)
- && (lex->type & BINCMP_FLAG))
- {
- my_error(ER_NOT_SUPPORTED_YET, MYF(0), "return value collation");
- MYSQL_YYABORT;
- }
-
- if (sp->fill_field_definition(thd, lex,
- (enum enum_field_types) $11,
- &sp->m_return_field_def))
+ if (Lex->sphead->fill_field_definition(thd, Lex, $11,
+ Lex->last_field))
MYSQL_YYABORT;
}
sp_c_chistics /* $13 */
diff --git a/sql/table.cc b/sql/table.cc
index 0e616bea6ef..50d331c49b3 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -2395,6 +2395,7 @@ bool unpack_vcol_info_from_frm(THD *thd,
Query_arena *backup_stmt_arena_ptr;
Query_arena backup_arena;
Query_arena *vcol_arena= 0;
+ Create_field vcol_storage; // placeholder for vcol_info
Parser_state parser_state;
LEX *old_lex= thd->lex;
LEX lex;
@@ -2458,7 +2459,8 @@ bool unpack_vcol_info_from_frm(THD *thd,
if (init_lex_with_single_table(thd, table, &lex))
goto err;
- thd->lex->parse_vcol_expr= TRUE;
+ lex.parse_vcol_expr= TRUE;
+ lex.last_field= &vcol_storage;
/*
Step 3: Use the parser to build an Item object from vcol_expr_str.
@@ -2468,7 +2470,7 @@ bool unpack_vcol_info_from_frm(THD *thd,
goto err;
}
/* From now on use vcol_info generated by the parser. */
- field->vcol_info= thd->lex->vcol_info;
+ field->vcol_info= vcol_storage.vcol_info;
/* Validate the Item tree. */
if (fix_vcol_expr(thd, table, field))
diff --git a/storage/perfschema/pfs_digest.cc b/storage/perfschema/pfs_digest.cc
index bafc22e4b75..1fbf72c19c8 100644
--- a/storage/perfschema/pfs_digest.cc
+++ b/storage/perfschema/pfs_digest.cc
@@ -22,6 +22,8 @@
This code needs extra visibility in the lexer structures
*/
+#define MYSQL_LEX 1
+
#include "my_global.h"
#include "my_sys.h"
#include "pfs_instr.h"
@@ -35,7 +37,6 @@
#include <string.h>
/* Generated code */
-#include "../sql/sql_yacc.h"
#include "../storage/perfschema/pfs_lex_token.h"
/* Name pollution from sql/sql_lex.h */