1
0
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:
Sergei Golubchik
2014-11-08 17:37:19 +01:00
parent d1522af72d
commit 227510e039
30 changed files with 573 additions and 664 deletions

View File

@ -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

View File

@ -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
#

View File

@ -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()

View File

@ -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 ()

View File

@ -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|

View File

@ -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;

View File

@ -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;

View File

@ -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));

View File

@ -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 #

View File

@ -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;

View File

@ -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

View File

@ -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 ;|

View File

@ -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;

View File

@ -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()
{

View File

@ -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)
{

View File

@ -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);

View File

@ -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))
{

View File

@ -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*/

View File

@ -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')"

View File

@ -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)

View File

@ -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;

View File

@ -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.

View File

@ -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);
};

View File

@ -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;
}

View File

@ -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,

View File

@ -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;
}

View File

@ -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

View File

@ -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 */

View File

@ -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))

View File

@ -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 */