mirror of
https://github.com/MariaDB/server.git
synced 2025-07-04 01:23:45 +03:00
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
This commit is contained in:
@ -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
|
||||
|
@ -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
|
||||
#
|
||||
|
@ -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()
|
||||
|
@ -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 ()
|
||||
|
@ -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|
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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));
|
||||
|
||||
|
@ -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 #
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -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 ;|
|
||||
|
274
sql/field.cc
274
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
|
||||
|
||||
@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)
|
||||
static inline bool is_item_func(Item* x)
|
||||
{
|
||||
return x != NULL && x->type() == Item::FUNC_ITEM;
|
||||
}
|
||||
|
||||
|
||||
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");
|
||||
|
||||
DBUG_ENTER("Create_field::init()");
|
||||
if (vcol_info)
|
||||
{
|
||||
vcol_info->set_field_type(sql_type);
|
||||
sql_type= (enum enum_field_types)MYSQL_TYPE_VIRTUAL;
|
||||
}
|
||||
|
||||
field= 0;
|
||||
field_name= fld_name;
|
||||
flags= fld_type_modifier;
|
||||
option_list= create_opt;
|
||||
if (length > MAX_FIELD_BLOBLENGTH)
|
||||
{
|
||||
my_error(ER_TOO_BIG_DISPLAYWIDTH, MYF(0), field_name, MAX_FIELD_BLOBLENGTH);
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
|
||||
if (fld_default_value != NULL && fld_default_value->type() == Item::FUNC_ITEM)
|
||||
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);
|
||||
}
|
||||
|
||||
if (def)
|
||||
{
|
||||
/*
|
||||
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 (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 (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);
|
||||
}
|
||||
sign_len= flags & UNSIGNED_FLAG ? 0 : 1;
|
||||
|
||||
if (length == 0)
|
||||
fld_length= NULL; /* purecov: inspected */
|
||||
}
|
||||
|
||||
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;
|
||||
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. */
|
||||
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);
|
||||
}
|
||||
@ -9530,32 +9480,30 @@ bool Create_field::init(THD *thd, char *fld_name, enum_field_types fld_type,
|
||||
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)))
|
||||
((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((fld_type == MYSQL_TYPE_VAR_STRING ||
|
||||
fld_type == MYSQL_TYPE_VARCHAR ||
|
||||
fld_type == MYSQL_TYPE_STRING) ? ER_TOO_BIG_FIELDLENGTH :
|
||||
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;
|
||||
|
21
sql/field.h
21
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()
|
||||
{
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
@ -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))
|
||||
{
|
||||
|
@ -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*/
|
||||
|
@ -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')"
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
};
|
||||
|
||||
|
||||
|
122
sql/sql_parse.cc
122
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;
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
517
sql/sql_yacc.yy
517
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_fdparams ',' sp_param_name_and_type
|
||||
| sp_param_name_and_type
|
||||
;
|
||||
|
||||
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_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
|
||||
charset_or_alias:
|
||||
charset charset_name { $$= $2; }
|
||||
| ASCII_SYM { $$= &my_charset_latin1; }
|
||||
| UNICODE_SYM
|
||||
{
|
||||
Lex->charset= &my_charset_latin1_bin;
|
||||
}
|
||||
| ASCII_SYM BINARY
|
||||
{
|
||||
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; }
|
||||
@ -13260,7 +13270,6 @@ opt_ignore_lines:
|
||||
|
||||
lines_or_rows:
|
||||
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 */
|
||||
|
@ -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))
|
||||
|
@ -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 */
|
||||
|
Reference in New Issue
Block a user