MDEV-8912 Wrong metadata or type for @c:=string_or_blob_field

This commit is contained in:
Alexander Barkov 2015-10-07 20:19:29 +04:00
commit 8777724901
11 changed files with 439 additions and 113 deletions

View file

@ -3231,5 +3231,170 @@ NULL
DROP TABLE t2;
DROP TABLE t1;
#
# MDEV-8912 Wrong metadata or type for @c:=string_or_blob_field
#
CREATE TABLE t1 (c1 TINYBLOB, c2 BLOB, c3 MEDIUMBLOB, c4 LONGBLOB);
CREATE TABLE t2 AS
SELECT
@c1:=c1 AS c1,
@c2:=c2 AS c2,
@c3:=c3 AS c3,
@c4:=c4 AS c4
FROM t1;
SHOW CREATE TABLE t2;
Table Create Table
t2 CREATE TABLE `t2` (
`c1` varbinary(255) DEFAULT NULL,
`c2` blob,
`c3` mediumblob,
`c4` longblob
) ENGINE=MyISAM DEFAULT CHARSET=latin1
SELECT
@c1:=c1 AS c1,
@c2:=c2 AS c2,
@c3:=c3 AS c3,
@c4:=c4 AS c4
FROM t1;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
def c1 253 255 0 Y 128 31 63
def c2 252 65535 0 Y 128 31 63
def c3 250 16777215 0 Y 128 31 63
def c4 251 4294967295 0 Y 128 31 63
c1 c2 c3 c4
DROP TABLE t2;
DROP TABLE t1;
CREATE TABLE t1 (c1 CHAR(1), c2 CHAR(255)) CHARACTER SET latin1;
CREATE TABLE t2 AS
SELECT
@c1:=c1 AS c1,
@c2:=c2 AS c2
FROM t1;
SHOW CREATE TABLE t2;
Table Create Table
t2 CREATE TABLE `t2` (
`c1` varchar(1) DEFAULT NULL,
`c2` varchar(255) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
SELECT
@c1:=c1 AS c1,
@c2:=c2 AS c2
FROM t1;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
def c1 253 1 0 Y 0 31 8
def c2 253 255 0 Y 0 31 8
c1 c2
DROP TABLE t2;
DROP TABLE t1;
CREATE TABLE t1 (c1 CHAR(1), c2 CHAR(255)) CHARACTER SET utf8;
CREATE TABLE t2 AS
SELECT
@c1:=c1 AS c1,
@c2:=c2 AS c2
FROM t1;
SHOW CREATE TABLE t2;
Table Create Table
t2 CREATE TABLE `t2` (
`c1` varchar(1) CHARACTER SET utf8 DEFAULT NULL,
`c2` varchar(255) CHARACTER SET utf8 DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
SELECT
@c1:=c1 AS c1,
@c2:=c2 AS c2
FROM t1;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
def c1 253 1 0 Y 0 31 8
def c2 253 255 0 Y 0 31 8
c1 c2
DROP TABLE t2;
DROP TABLE t1;
CREATE TABLE t1 (c1 VARCHAR(1), c2 VARCHAR(255), c3 VARCHAR(20000)) CHARACTER SET latin1;
CREATE TABLE t2 AS
SELECT
@c:=c1 AS c1,
@c:=c2 AS c2,
@c:=c3 AS c3
FROM t1;
SHOW CREATE TABLE t2;
Table Create Table
t2 CREATE TABLE `t2` (
`c1` varchar(1) DEFAULT NULL,
`c2` varchar(255) DEFAULT NULL,
`c3` text
) ENGINE=MyISAM DEFAULT CHARSET=latin1
SELECT
@c:=c1 AS c1,
@c:=c2 AS c2,
@c:=c3 AS c3
FROM t1;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
def c1 253 1 0 Y 0 31 8
def c2 253 255 0 Y 0 31 8
def c3 252 20000 0 Y 0 31 8
c1 c2 c3
DROP TABLE t2;
DROP TABLE t1;
CREATE TABLE t1 (c1 VARCHAR(1), c2 VARCHAR(255), c3 VARCHAR(20000)) CHARACTER SET utf8;
CREATE TABLE t2 AS
SELECT
@c:=c1 AS c1,
@c:=c2 AS c2,
@c:=c3 AS c3
FROM t1;
SHOW CREATE TABLE t2;
Table Create Table
t2 CREATE TABLE `t2` (
`c1` varchar(1) CHARACTER SET utf8 DEFAULT NULL,
`c2` varchar(255) CHARACTER SET utf8 DEFAULT NULL,
`c3` text CHARACTER SET utf8
) ENGINE=MyISAM DEFAULT CHARSET=latin1
SELECT
@c:=c1 AS c1,
@c:=c2 AS c2,
@c:=c3 AS c3
FROM t1;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
def c1 253 1 0 Y 0 31 8
def c2 253 255 0 Y 0 31 8
def c3 252 60000 0 Y 0 31 8
c1 c2 c3
DROP TABLE t2;
DROP TABLE t1;
CREATE TABLE t1 (c1 ENUM('a')) CHARACTER SET latin1;
CREATE TABLE t2 AS
SELECT
@c:=c1 AS c1
FROM t1;
SHOW CREATE TABLE t2;
Table Create Table
t2 CREATE TABLE `t2` (
`c1` varchar(1) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
SELECT
@c:=c1 AS c1
FROM t1;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
def c1 253 1 0 Y 0 0 8
c1
DROP TABLE t2;
DROP TABLE t1;
CREATE TABLE t1 (c1 ENUM('a')) CHARACTER SET utf8;
CREATE TABLE t2 AS
SELECT
@c:=c1 AS c1
FROM t1;
SHOW CREATE TABLE t2;
Table Create Table
t2 CREATE TABLE `t2` (
`c1` varchar(1) CHARACTER SET utf8 DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
SELECT
@c:=c1 AS c1
FROM t1;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
def c1 253 1 0 Y 0 0 8
c1
DROP TABLE t2;
DROP TABLE t1;
#
# End of 10.1 tests
#

View file

@ -299,6 +299,140 @@ DROP TABLE t2;
DROP TABLE t1;
--echo #
--echo # MDEV-8912 Wrong metadata or type for @c:=string_or_blob_field
--echo #
CREATE TABLE t1 (c1 TINYBLOB, c2 BLOB, c3 MEDIUMBLOB, c4 LONGBLOB);
CREATE TABLE t2 AS
SELECT
@c1:=c1 AS c1,
@c2:=c2 AS c2,
@c3:=c3 AS c3,
@c4:=c4 AS c4
FROM t1;
SHOW CREATE TABLE t2;
--disable_ps_protocol
--enable_metadata
SELECT
@c1:=c1 AS c1,
@c2:=c2 AS c2,
@c3:=c3 AS c3,
@c4:=c4 AS c4
FROM t1;
--disable_metadata
--enable_ps_protocol
DROP TABLE t2;
DROP TABLE t1;
CREATE TABLE t1 (c1 CHAR(1), c2 CHAR(255)) CHARACTER SET latin1;
CREATE TABLE t2 AS
SELECT
@c1:=c1 AS c1,
@c2:=c2 AS c2
FROM t1;
SHOW CREATE TABLE t2;
--disable_ps_protocol
--enable_metadata
SELECT
@c1:=c1 AS c1,
@c2:=c2 AS c2
FROM t1;
--disable_metadata
--enable_ps_protocol
DROP TABLE t2;
DROP TABLE t1;
CREATE TABLE t1 (c1 CHAR(1), c2 CHAR(255)) CHARACTER SET utf8;
CREATE TABLE t2 AS
SELECT
@c1:=c1 AS c1,
@c2:=c2 AS c2
FROM t1;
SHOW CREATE TABLE t2;
--disable_ps_protocol
--enable_metadata
SELECT
@c1:=c1 AS c1,
@c2:=c2 AS c2
FROM t1;
--disable_metadata
--enable_ps_protocol
DROP TABLE t2;
DROP TABLE t1;
CREATE TABLE t1 (c1 VARCHAR(1), c2 VARCHAR(255), c3 VARCHAR(20000)) CHARACTER SET latin1;
CREATE TABLE t2 AS
SELECT
@c:=c1 AS c1,
@c:=c2 AS c2,
@c:=c3 AS c3
FROM t1;
SHOW CREATE TABLE t2;
--disable_ps_protocol
--enable_metadata
SELECT
@c:=c1 AS c1,
@c:=c2 AS c2,
@c:=c3 AS c3
FROM t1;
--disable_metadata
--enable_ps_protocol
DROP TABLE t2;
DROP TABLE t1;
CREATE TABLE t1 (c1 VARCHAR(1), c2 VARCHAR(255), c3 VARCHAR(20000)) CHARACTER SET utf8;
CREATE TABLE t2 AS
SELECT
@c:=c1 AS c1,
@c:=c2 AS c2,
@c:=c3 AS c3
FROM t1;
SHOW CREATE TABLE t2;
--disable_ps_protocol
--enable_metadata
SELECT
@c:=c1 AS c1,
@c:=c2 AS c2,
@c:=c3 AS c3
FROM t1;
--disable_metadata
--enable_ps_protocol
DROP TABLE t2;
DROP TABLE t1;
CREATE TABLE t1 (c1 ENUM('a')) CHARACTER SET latin1;
CREATE TABLE t2 AS
SELECT
@c:=c1 AS c1
FROM t1;
SHOW CREATE TABLE t2;
--disable_ps_protocol
--enable_metadata
SELECT
@c:=c1 AS c1
FROM t1;
--disable_metadata
--enable_ps_protocol
DROP TABLE t2;
DROP TABLE t1;
CREATE TABLE t1 (c1 ENUM('a')) CHARACTER SET utf8;
CREATE TABLE t2 AS
SELECT
@c:=c1 AS c1
FROM t1;
SHOW CREATE TABLE t2;
--disable_ps_protocol
--enable_metadata
SELECT
@c:=c1 AS c1
FROM t1;
--disable_metadata
--enable_ps_protocol
DROP TABLE t2;
DROP TABLE t1;
--echo #
--echo # End of 10.1 tests
--echo #

View file

@ -5565,7 +5565,9 @@ Field *Item::make_string_field(TABLE *table)
\# Created field
*/
Field *Item::tmp_table_field_from_field_type(TABLE *table, bool fixed_length)
Field *Item::tmp_table_field_from_field_type(TABLE *table,
bool fixed_length,
bool set_blob_packlength)
{
/*
The field functions defines a field to be not null if null_ptr is not 0
@ -5663,12 +5665,9 @@ Field *Item::tmp_table_field_from_field_type(TABLE *table, bool fixed_length)
case MYSQL_TYPE_MEDIUM_BLOB:
case MYSQL_TYPE_LONG_BLOB:
case MYSQL_TYPE_BLOB:
if (this->type() == Item::TYPE_HOLDER)
field= new (mem_root)
Field_blob(max_length, maybe_null, name, collation.collation, 1);
else
field= new (mem_root)
Field_blob(max_length, maybe_null, name, collation.collation);
field= new (mem_root)
Field_blob(max_length, maybe_null, name,
collation.collation, set_blob_packlength);
break; // Blob handled outside of case
#ifdef HAVE_SPATIAL
case MYSQL_TYPE_GEOMETRY:
@ -9551,7 +9550,7 @@ Field *Item_type_holder::make_field_by_type(TABLE *table)
default:
break;
}
return tmp_table_field_from_field_type(table, 0);
return tmp_table_field_from_field_type(table, false, true);
}

View file

@ -1023,6 +1023,8 @@ public:
virtual Field *get_tmp_table_field() { return 0; }
/* This is also used to create fields in CREATE ... SELECT: */
virtual Field *tmp_table_field(TABLE *t_arg) { return 0; }
virtual Field *create_field_for_create_select(THD *thd, TABLE *table);
virtual Field *create_field_for_schema(THD *thd, TABLE *table);
virtual const char *full_name() const { return name ? name : "???"; }
const char *field_name_or_null()
{ return real_item()->type() == Item::FIELD_ITEM ? name : NULL; }
@ -1626,7 +1628,9 @@ public:
// used in row subselects to get value of elements
virtual void bring_value() {}
Field *tmp_table_field_from_field_type(TABLE *table, bool fixed_length);
Field *tmp_table_field_from_field_type(TABLE *table,
bool fixed_length,
bool set_blob_packlength);
virtual Item_field *field_for_view_update() { return 0; }
virtual Item *neg_transformer(THD *thd) { return NULL; }
@ -3190,6 +3194,8 @@ public:
{ max_length= length; }
enum Type type() const { return TYPE_HOLDER; }
enum_field_types field_type() const { return MYSQL_TYPE_BLOB; }
Field *create_field_for_schema(THD *thd, TABLE *table)
{ return tmp_table_field_from_field_type(table, false, true); }
};
@ -3384,7 +3390,7 @@ public:
my_decimal *val_decimal(my_decimal *decimal_value)
{ return val_decimal_from_date(decimal_value); }
Field *tmp_table_field(TABLE *table)
{ return tmp_table_field_from_field_type(table, 0); }
{ return tmp_table_field_from_field_type(table, false, false); }
int save_in_field(Field *field, bool no_conversions)
{ return save_date_in_field(field); }
};

View file

@ -2266,7 +2266,7 @@ uint Item_func_case_abbreviation2::decimal_precision2(Item **args) const
Field *Item_func_ifnull::tmp_table_field(TABLE *table)
{
return tmp_table_field_from_field_type(table, 0);
return tmp_table_field_from_field_type(table, false, false);
}
double

View file

@ -4729,15 +4729,15 @@ user_var_entry *get_variable(HASH *hash, LEX_STRING &name,
void Item_func_set_user_var::cleanup()
{
Item_func::cleanup();
entry= NULL;
m_var_entry= NULL;
}
bool Item_func_set_user_var::set_entry(THD *thd, bool create_if_not_exists)
{
if (entry && thd->thread_id == entry_thread_id)
if (m_var_entry && thd->thread_id == entry_thread_id)
goto end; // update entry->update_query_id for PS
if (!(entry= get_variable(&thd->user_vars, name, create_if_not_exists)))
if (!(m_var_entry= get_variable(&thd->user_vars, name, create_if_not_exists)))
{
entry_thread_id= 0;
return TRUE;
@ -4749,7 +4749,7 @@ bool Item_func_set_user_var::set_entry(THD *thd, bool create_if_not_exists)
is different from query_id).
*/
end:
entry->update_query_id= thd->query_id;
m_var_entry->update_query_id= thd->query_id;
return FALSE;
}
@ -4781,11 +4781,12 @@ bool Item_func_set_user_var::fix_fields(THD *thd, Item **ref)
and the variable has previously been initialized.
*/
null_item= (args[0]->type() == NULL_ITEM);
if (!entry->charset() || !null_item)
entry->set_charset(args[0]->collation.derivation == DERIVATION_NUMERIC ?
default_charset() : args[0]->collation.collation);
collation.set(entry->charset(), DERIVATION_IMPLICIT);
cached_result_type= args[0]->result_type();
if (!m_var_entry->charset() || !null_item)
m_var_entry->set_charset(args[0]->collation.derivation == DERIVATION_NUMERIC ?
default_charset() : args[0]->collation.collation);
collation.set(m_var_entry->charset(), DERIVATION_IMPLICIT);
set_handler_by_result_type(args[0]->result_type(),
max_length, collation.collation);
if (thd->lex->current_select)
{
/*
@ -4954,8 +4955,8 @@ Item_func_set_user_var::update_hash(void *ptr, uint length,
result type of the variable
*/
if ((null_value= args[0]->null_value) && null_item)
res_type= entry->type; // Don't change type of item
if (::update_hash(entry, (null_value= args[0]->null_value),
res_type= m_var_entry->type; // Don't change type of item
if (::update_hash(m_var_entry, (null_value= args[0]->null_value),
ptr, length, res_type, cs, unsigned_arg))
{
null_value= 1;
@ -5108,7 +5109,7 @@ Item_func_set_user_var::check(bool use_result_field)
if (use_result_field && !result_field)
use_result_field= FALSE;
switch (cached_result_type) {
switch (Item_func_set_user_var::result_type()) {
case REAL_RESULT:
{
save_result.vreal= use_result_field ? result_field->val_real() :
@ -5201,7 +5202,7 @@ Item_func_set_user_var::update()
bool res= 0;
DBUG_ENTER("Item_func_set_user_var::update");
switch (cached_result_type) {
switch (Item_func_set_user_var::result_type()) {
case REAL_RESULT:
{
res= update_hash((void*) &save_result.vreal,sizeof(save_result.vreal),
@ -5248,7 +5249,7 @@ double Item_func_set_user_var::val_real()
DBUG_ASSERT(fixed == 1);
check(0);
update(); // Store expression
return entry->val_real(&null_value);
return m_var_entry->val_real(&null_value);
}
longlong Item_func_set_user_var::val_int()
@ -5256,7 +5257,7 @@ longlong Item_func_set_user_var::val_int()
DBUG_ASSERT(fixed == 1);
check(0);
update(); // Store expression
return entry->val_int(&null_value);
return m_var_entry->val_int(&null_value);
}
String *Item_func_set_user_var::val_str(String *str)
@ -5264,7 +5265,7 @@ String *Item_func_set_user_var::val_str(String *str)
DBUG_ASSERT(fixed == 1);
check(0);
update(); // Store expression
return entry->val_str(&null_value, str, decimals);
return m_var_entry->val_str(&null_value, str, decimals);
}
@ -5273,7 +5274,7 @@ my_decimal *Item_func_set_user_var::val_decimal(my_decimal *val)
DBUG_ASSERT(fixed == 1);
check(0);
update(); // Store expression
return entry->val_decimal(&null_value, val);
return m_var_entry->val_decimal(&null_value, val);
}
@ -5282,7 +5283,7 @@ double Item_func_set_user_var::val_result()
DBUG_ASSERT(fixed == 1);
check(TRUE);
update(); // Store expression
return entry->val_real(&null_value);
return m_var_entry->val_real(&null_value);
}
longlong Item_func_set_user_var::val_int_result()
@ -5290,7 +5291,7 @@ longlong Item_func_set_user_var::val_int_result()
DBUG_ASSERT(fixed == 1);
check(TRUE);
update(); // Store expression
return entry->val_int(&null_value);
return m_var_entry->val_int(&null_value);
}
bool Item_func_set_user_var::val_bool_result()
@ -5298,7 +5299,7 @@ bool Item_func_set_user_var::val_bool_result()
DBUG_ASSERT(fixed == 1);
check(TRUE);
update(); // Store expression
return entry->val_int(&null_value) != 0;
return m_var_entry->val_int(&null_value) != 0;
}
String *Item_func_set_user_var::str_result(String *str)
@ -5306,7 +5307,7 @@ String *Item_func_set_user_var::str_result(String *str)
DBUG_ASSERT(fixed == 1);
check(TRUE);
update(); // Store expression
return entry->val_str(&null_value, str, decimals);
return m_var_entry->val_str(&null_value, str, decimals);
}
@ -5315,7 +5316,7 @@ my_decimal *Item_func_set_user_var::val_decimal_result(my_decimal *val)
DBUG_ASSERT(fixed == 1);
check(TRUE);
update(); // Store expression
return entry->val_decimal(&null_value, val);
return m_var_entry->val_decimal(&null_value, val);
}
@ -5430,7 +5431,7 @@ int Item_func_set_user_var::save_in_field(Field *field, bool no_conversions,
CHARSET_INFO *cs= collation.collation;
char buff[MAX_FIELD_WIDTH]; // Alloc buffer for small columns
str_value.set_quick(buff, sizeof(buff), cs);
result= entry->val_str(&null_value, &str_value, decimals);
result= m_var_entry->val_str(&null_value, &str_value, decimals);
if (null_value)
{
@ -5446,7 +5447,7 @@ int Item_func_set_user_var::save_in_field(Field *field, bool no_conversions,
}
else if (result_type() == REAL_RESULT)
{
double nr= entry->val_real(&null_value);
double nr= m_var_entry->val_real(&null_value);
if (null_value)
return set_field_to_null(field);
field->set_notnull();
@ -5455,7 +5456,7 @@ int Item_func_set_user_var::save_in_field(Field *field, bool no_conversions,
else if (result_type() == DECIMAL_RESULT)
{
my_decimal decimal_value;
my_decimal *val= entry->val_decimal(&null_value, &decimal_value);
my_decimal *val= m_var_entry->val_decimal(&null_value, &decimal_value);
if (null_value)
return set_field_to_null(field);
field->set_notnull();
@ -5463,7 +5464,7 @@ int Item_func_set_user_var::save_in_field(Field *field, bool no_conversions,
}
else
{
longlong nr= entry->val_int(&null_value);
longlong nr= m_var_entry->val_int(&null_value);
if (null_value)
return set_field_to_null_with_conversions(field, no_conversions);
field->set_notnull();
@ -5478,36 +5479,36 @@ Item_func_get_user_var::val_str(String *str)
{
DBUG_ASSERT(fixed == 1);
DBUG_ENTER("Item_func_get_user_var::val_str");
if (!var_entry)
if (!m_var_entry)
DBUG_RETURN((String*) 0); // No such variable
DBUG_RETURN(var_entry->val_str(&null_value, str, decimals));
DBUG_RETURN(m_var_entry->val_str(&null_value, str, decimals));
}
double Item_func_get_user_var::val_real()
{
DBUG_ASSERT(fixed == 1);
if (!var_entry)
if (!m_var_entry)
return 0.0; // No such variable
return (var_entry->val_real(&null_value));
return (m_var_entry->val_real(&null_value));
}
my_decimal *Item_func_get_user_var::val_decimal(my_decimal *dec)
{
DBUG_ASSERT(fixed == 1);
if (!var_entry)
if (!m_var_entry)
return 0;
return var_entry->val_decimal(&null_value, dec);
return m_var_entry->val_decimal(&null_value, dec);
}
longlong Item_func_get_user_var::val_int()
{
DBUG_ASSERT(fixed == 1);
if (!var_entry)
if (!m_var_entry)
return 0; // No such variable
return (var_entry->val_int(&null_value));
return (m_var_entry->val_int(&null_value));
}
@ -5660,21 +5661,20 @@ void Item_func_get_user_var::fix_length_and_dec()
decimals=NOT_FIXED_DEC;
max_length=MAX_BLOB_WIDTH;
error= get_var_with_binlog(thd, thd->lex->sql_command, name, &var_entry);
error= get_var_with_binlog(thd, thd->lex->sql_command, name, &m_var_entry);
/*
If the variable didn't exist it has been created as a STRING-type.
'var_entry' is NULL only if there occured an error during the call to
'm_var_entry' is NULL only if there occured an error during the call to
get_var_with_binlog.
*/
if (!error && var_entry)
if (!error && m_var_entry)
{
m_cached_result_type= var_entry->type;
unsigned_flag= var_entry->unsigned_flag;
max_length= var_entry->length;
collation.set(var_entry->charset(), DERIVATION_IMPLICIT);
switch (m_cached_result_type) {
unsigned_flag= m_var_entry->unsigned_flag;
max_length= m_var_entry->length;
collation.set(m_var_entry->charset(), DERIVATION_IMPLICIT);
set_handler_by_result_type(m_var_entry->type);
switch (Item_func_get_user_var::result_type()) {
case REAL_RESULT:
fix_char_length(DBL_DIG + 8);
break;
@ -5684,6 +5684,7 @@ void Item_func_get_user_var::fix_length_and_dec()
break;
case STRING_RESULT:
max_length= MAX_BLOB_WIDTH - 1;
set_handler_by_field_type(MYSQL_TYPE_MEDIUM_BLOB);
break;
case DECIMAL_RESULT:
fix_char_length(DECIMAL_MAX_STR_LENGTH);
@ -5699,7 +5700,7 @@ void Item_func_get_user_var::fix_length_and_dec()
{
collation.set(&my_charset_bin, DERIVATION_IMPLICIT);
null_value= 1;
m_cached_result_type= STRING_RESULT;
set_handler_by_field_type(MYSQL_TYPE_LONG_BLOB);
max_length= MAX_BLOB_WIDTH;
}
}
@ -5707,13 +5708,8 @@ void Item_func_get_user_var::fix_length_and_dec()
bool Item_func_get_user_var::const_item() const
{
return (!var_entry || current_thd->query_id != var_entry->update_query_id);
}
enum Item_result Item_func_get_user_var::result_type() const
{
return m_cached_result_type;
return (!m_var_entry ||
current_thd->query_id != m_var_entry->update_query_id);
}

View file

@ -175,6 +175,12 @@ public:
friend class udf_handler;
Field *tmp_table_field() { return result_field; }
Field *tmp_table_field(TABLE *t_arg);
Field *create_field_for_create_select(THD *thd, TABLE *table)
{
return result_type() != STRING_RESULT ?
tmp_table_field(table) :
tmp_table_field_from_field_type(table, false, false);
}
Item *get_tmp_table_item(THD *thd);
my_decimal *val_decimal(my_decimal *);
@ -1618,10 +1624,39 @@ public:
class user_var_entry;
class Item_func_set_user_var :public Item_func
/**
A class to set and get user variables
*/
class Item_func_user_var :public Item_func,
public Type_handler_hybrid_field_type
{
protected:
user_var_entry *m_var_entry;
public:
LEX_STRING name; // keep it public
Item_func_user_var(THD *thd, LEX_STRING a)
:Item_func(thd), m_var_entry(NULL), name(a) { }
Item_func_user_var(THD *thd, LEX_STRING a, Item *b)
:Item_func(thd, b), m_var_entry(NULL), name(a) { }
Item_func_user_var(THD *thd, Item_func_user_var *item)
:Item_func(thd, item),
m_var_entry(item->m_var_entry), name(item->name)
{
set_handler_by_result_type(item->result_type());
}
enum Item_result cmp_type() const
{ return Type_handler_hybrid_field_type::cmp_type(); }
enum Item_result result_type() const
{ return Type_handler_hybrid_field_type::result_type(); }
enum_field_types field_type() const
{ return Type_handler_hybrid_field_type::field_type(); }
bool check_vcol_func_processor(uchar *int_arg) { return true; }
};
class Item_func_set_user_var :public Item_func_user_var
{
enum Item_result cached_result_type;
user_var_entry *entry;
/*
The entry_thread_id variable is used:
1) to skip unnecessary updates of the entry field (see above);
@ -1646,17 +1681,15 @@ class Item_func_set_user_var :public Item_func
} save_result;
public:
LEX_STRING name; // keep it public
Item_func_set_user_var(THD *thd, LEX_STRING a, Item *b):
Item_func(thd, b), cached_result_type(INT_RESULT),
entry(NULL), entry_thread_id(0), name(a)
Item_func_user_var(thd, a, b),
entry_thread_id(0)
{}
Item_func_set_user_var(THD *thd, Item_func_set_user_var *item)
:Item_func(thd, item), cached_result_type(item->cached_result_type),
entry(item->entry), entry_thread_id(item->entry_thread_id),
:Item_func_user_var(thd, item),
entry_thread_id(item->entry_thread_id),
value(item->value), decimal_buff(item->decimal_buff),
null_item(item->null_item), save_result(item->save_result),
name(item->name)
null_item(item->null_item), save_result(item->save_result)
{}
enum Functype functype() const { return SUSERVAR_FUNC; }
@ -1677,9 +1710,14 @@ public:
bool check(bool use_result_field);
void save_item_result(Item *item);
bool update();
enum Item_result result_type () const { return cached_result_type; }
bool fix_fields(THD *thd, Item **ref);
void fix_length_and_dec();
Field *create_field_for_create_select(THD *thd, TABLE *table)
{
return result_type() != STRING_RESULT ?
tmp_table_field(table) :
tmp_table_field_from_field_type(table, false, true);
}
table_map used_tables() const
{
return Item_func::used_tables() | RAND_TABLE_BIT;
@ -1702,20 +1740,15 @@ public:
bool register_field_in_bitmap(uchar *arg);
bool set_entry(THD *thd, bool create_if_not_exists);
void cleanup();
bool check_vcol_func_processor(uchar *int_arg) {return TRUE;}
};
class Item_func_get_user_var :public Item_func,
class Item_func_get_user_var :public Item_func_user_var,
private Settable_routine_parameter
{
user_var_entry *var_entry;
Item_result m_cached_result_type;
public:
LEX_STRING name; // keep it public
Item_func_get_user_var(THD *thd, LEX_STRING a):
Item_func(thd), m_cached_result_type(STRING_RESULT), name(a) {}
Item_func_user_var(thd, a) {}
enum Functype functype() const { return GUSERVAR_FUNC; }
LEX_STRING get_name() { return name; }
double val_real();
@ -1724,7 +1757,6 @@ public:
String *val_str(String* str);
void fix_length_and_dec();
virtual void print(String *str, enum_query_type query_type);
enum Item_result result_type() const;
/*
We must always return variables as strings to guard against selects of type
select @t1:=1,@t1,@t:="hello",@t from foo where (@t1:= t2.b)
@ -1742,7 +1774,6 @@ public:
{
return this;
}
bool check_vcol_func_processor(uchar *int_arg) { return TRUE;}
};

View file

@ -501,7 +501,7 @@ public:
my_decimal *val_decimal(my_decimal *decimal_value)
{ return val_decimal_from_date(decimal_value); }
Field *tmp_table_field(TABLE *table)
{ return tmp_table_field_from_field_type(table, 0); }
{ return tmp_table_field_from_field_type(table, false, false); }
int save_in_field(Field *field, bool no_conversions)
{ return save_date_in_field(field); }
void fix_length_and_dec();

View file

@ -3866,6 +3866,14 @@ void select_insert::abort_result_set() {
CREATE TABLE (SELECT) ...
***************************************************************************/
Field *Item::create_field_for_create_select(THD *thd, TABLE *table)
{
Field *def_field, *tmp_field;
return create_tmp_field(thd, table, this, type(),
(Item ***) 0, &tmp_field, &def_field, 0, 0, 0, 0, 0);
}
/**
Create table from lists of fields and items (or just return TABLE
object for pre-opened existing table).
@ -3920,7 +3928,6 @@ static TABLE *create_table_from_items(THD *thd,
/* Add selected items to field list */
List_iterator_fast<Item> it(*items);
Item *item;
Field *tmp_field;
DBUG_ENTER("create_table_from_items");
tmp_table.alias= 0;
@ -3938,18 +3945,7 @@ static TABLE *create_table_from_items(THD *thd,
while ((item=it++))
{
Create_field *cr_field;
Field *field, *def_field;
if (item->type() == Item::FUNC_ITEM)
{
if (item->result_type() != STRING_RESULT)
field= item->tmp_table_field(&tmp_table);
else
field= item->tmp_table_field_from_field_type(&tmp_table, 0);
}
else
field= create_tmp_field(thd, &tmp_table, item, item->type(),
(Item ***) 0, &tmp_field, &def_field, 0, 0, 0, 0,
0);
Field *field= item->create_field_for_create_select(thd, &tmp_table);
if (!field ||
!(cr_field= (new (thd->mem_root)
Create_field(thd, field,

View file

@ -15866,7 +15866,7 @@ static Field *create_tmp_field_from_item(THD *thd, Item *item, TABLE *table,
*/
if (item->cmp_type() == TIME_RESULT ||
item->field_type() == MYSQL_TYPE_GEOMETRY)
new_field= item->tmp_table_field_from_field_type(table, 1);
new_field= item->tmp_table_field_from_field_type(table, true, false);
/*
Make sure that the blob fits into a Field_varstring which has
2-byte lenght.
@ -15918,23 +15918,21 @@ static Field *create_tmp_field_from_item(THD *thd, Item *item, TABLE *table,
new_created field
*/
Field *create_tmp_field_for_schema(THD *thd, Item *item, TABLE *table)
Field *Item::create_field_for_schema(THD *thd, TABLE *table)
{
if (item->field_type() == MYSQL_TYPE_VARCHAR)
if (field_type() == MYSQL_TYPE_VARCHAR)
{
Field *field;
if (item->max_length > MAX_FIELD_VARCHARLENGTH)
field= new Field_blob(item->max_length, item->maybe_null,
item->name, item->collation.collation);
if (max_length > MAX_FIELD_VARCHARLENGTH)
field= new Field_blob(max_length, maybe_null, name, collation.collation);
else
field= new Field_varstring(item->max_length, item->maybe_null,
item->name,
table->s, item->collation.collation);
field= new Field_varstring(max_length, maybe_null, name,
table->s, collation.collation);
if (field)
field->init(table);
return field;
}
return item->tmp_table_field_from_field_type(table, 0);
return tmp_table_field_from_field_type(table, false, false);
}
@ -16475,7 +16473,7 @@ create_tmp_table(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields,
key over a bit field as heap tables can't handle that.
*/
Field *new_field= (param->schema_table) ?
create_tmp_field_for_schema(thd, item, table) :
item->create_field_for_schema(thd, table) :
create_tmp_field(thd, table, item, type, &copy_func,
tmp_from_field, &default_field[fieldnr],
group != 0,

View file

@ -44,10 +44,9 @@ static Type_handler_geometry type_handler_geometry;
/**
This method is used by:
- Item_func_set_user_var
- Item_func_get_user_var
- Item_user_var_as_out_param
- Item_func_udf_str
- Item_user_var_as_out_param::field_type()
- Item_func_udf_str::field_type()
- Item_empty_string::make_field()
TODO: type_handler_adjusted_to_max_octet_length() and string_type_handler()
provide very similar functionality, to properly choose between
@ -69,7 +68,9 @@ Type_handler::string_type_handler(uint max_octet_length) const
/**
This method is used by Item_sum_hybrid, e.g. MAX(item), MIN(item).
This method is used by:
- Item_sum_hybrid, e.g. MAX(item), MIN(item).
- Item_func_set_user_var
*/
const Type_handler *
Type_handler_string_result::type_handler_adjusted_to_max_octet_length(
@ -94,7 +95,7 @@ Type_handler_hybrid_field_type::get_handler_by_result_type(Item_result type)
case REAL_RESULT: return &type_handler_double;
case INT_RESULT: return &type_handler_longlong;
case DECIMAL_RESULT: return &type_handler_newdecimal;
case STRING_RESULT: return &type_handler_string;
case STRING_RESULT: return &type_handler_long_blob;
case TIME_RESULT:
case ROW_RESULT:
DBUG_ASSERT(0);