summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
Diffstat (limited to 'sql')
-rw-r--r--sql/events.cc14
-rw-r--r--sql/field.cc526
-rw-r--r--sql/field.h138
-rw-r--r--sql/filesort.cc24
-rw-r--r--sql/ha_partition.cc4
-rw-r--r--sql/handler.cc19
-rw-r--r--sql/item.cc259
-rw-r--r--sql/item.h344
-rw-r--r--sql/item_cmpfunc.h12
-rw-r--r--sql/item_func.cc6
-rw-r--r--sql/item_func.h17
-rw-r--r--sql/item_jsonfunc.cc2
-rw-r--r--sql/item_row.h10
-rw-r--r--sql/item_subselect.cc6
-rw-r--r--sql/item_subselect.h13
-rw-r--r--sql/item_sum.cc8
-rw-r--r--sql/item_sum.h12
-rw-r--r--sql/item_xmlfunc.cc20
-rw-r--r--sql/log.cc24
-rw-r--r--sql/mysqld.cc35
-rw-r--r--sql/opt_range.cc28
-rw-r--r--sql/opt_subselect.cc945
-rw-r--r--sql/opt_subselect.h11
-rw-r--r--sql/opt_sum.cc2
-rw-r--r--sql/procedure.h10
-rw-r--r--sql/rpl_mi.cc6
-rw-r--r--sql/rpl_record.cc8
-rw-r--r--sql/sp.cc2
-rw-r--r--sql/sp_head.cc5
-rw-r--r--sql/sql_analyse.cc47
-rw-r--r--sql/sql_base.cc41
-rw-r--r--sql/sql_binlog.cc2
-rw-r--r--sql/sql_class.cc8
-rw-r--r--sql/sql_cte.cc2
-rw-r--r--sql/sql_delete.cc2
-rw-r--r--sql/sql_derived.cc211
-rw-r--r--sql/sql_handler.cc2
-rw-r--r--sql/sql_insert.cc33
-rw-r--r--sql/sql_lex.cc152
-rw-r--r--sql/sql_lex.h29
-rw-r--r--sql/sql_list.h2
-rw-r--r--sql/sql_parse.cc5
-rw-r--r--sql/sql_partition.cc13
-rw-r--r--sql/sql_prepare.cc6
-rw-r--r--sql/sql_priv.h4
-rw-r--r--sql/sql_repl.cc3
-rw-r--r--sql/sql_select.cc601
-rw-r--r--sql/sql_select.h28
-rw-r--r--sql/sql_show.cc6
-rw-r--r--sql/sql_table.cc16
-rw-r--r--sql/sql_trigger.cc6
-rw-r--r--sql/sql_type.cc595
-rw-r--r--sql/sql_type.h341
-rw-r--r--sql/sql_update.cc35
-rw-r--r--sql/sys_vars.cc1
-rw-r--r--sql/table.cc597
-rw-r--r--sql/table.h28
-rw-r--r--sql/unireg.cc47
-rw-r--r--sql/unireg.h5
59 files changed, 3574 insertions, 1804 deletions
diff --git a/sql/events.cc b/sql/events.cc
index 6a8695843a3..49ac4b71100 100644
--- a/sql/events.cc
+++ b/sql/events.cc
@@ -401,7 +401,7 @@ Events::create_event(THD *thd, Event_parse_data *parse_data)
my_message_sql(ER_STARTUP,
"Event Error: An error occurred while creating query "
"string, before writing it into binary log.",
- MYF(ME_NOREFRESH));
+ MYF(ME_ERROR_LOG));
ret= true;
}
else
@@ -926,7 +926,7 @@ Events::init(THD *thd, bool opt_noacl_or_bootstrap)
my_message(ER_STARTUP,
"Event Scheduler: An error occurred when initializing "
"system tables. Disabling the Event Scheduler.",
- MYF(ME_NOREFRESH));
+ MYF(ME_ERROR_LOG));
/* Disable the scheduler since the system tables are not up to date */
opt_event_scheduler= EVENTS_OFF;
goto end;
@@ -948,7 +948,7 @@ Events::init(THD *thd, bool opt_noacl_or_bootstrap)
{
my_message_sql(ER_STARTUP,
"Event Scheduler: Error while loading from mysql.event table.",
- MYF(ME_NOREFRESH));
+ MYF(ME_ERROR_LOG));
res= TRUE; /* fatal error: request unireg_abort */
goto end;
}
@@ -1165,7 +1165,7 @@ Events::load_events_from_db(THD *thd)
{
my_message_sql(ER_STARTUP,
"Event Scheduler: Failed to open table mysql.event",
- MYF(ME_NOREFRESH));
+ MYF(ME_ERROR_LOG));
DBUG_RETURN(TRUE);
}
@@ -1191,7 +1191,7 @@ Events::load_events_from_db(THD *thd)
"Event Scheduler: "
"Error while loading events from mysql.event. "
"The table probably contains bad data or is corrupted",
- MYF(ME_NOREFRESH));
+ MYF(ME_ERROR_LOG));
delete et;
goto end;
}
@@ -1230,9 +1230,9 @@ Events::load_events_from_db(THD *thd)
}
my_printf_error(ER_STARTUP,
"Event Scheduler: Loaded %d event%s",
- MYF(ME_NOREFRESH |
+ MYF(ME_ERROR_LOG |
(global_system_variables.log_warnings) ?
- ME_JUST_INFO: 0),
+ ME_NOTE: 0),
count, (count == 1) ? "" : "s");
ret= FALSE;
diff --git a/sql/field.cc b/sql/field.cc
index 6fbe92e76fe..735c46be582 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -62,8 +62,12 @@ const char field_separator=',';
#define BLOB_PACK_LENGTH_TO_MAX_LENGH(arg) \
((ulong) ((1LL << MY_MIN(arg, 4) * 8) - 1))
-#define ASSERT_COLUMN_MARKED_FOR_READ DBUG_ASSERT(!table || (!table->read_set || bitmap_is_set(table->read_set, field_index)))
-#define ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED DBUG_ASSERT(is_stat_field || !table || (!table->write_set || bitmap_is_set(table->write_set, field_index) || (table->vcol_set && bitmap_is_set(table->vcol_set, field_index))))
+#define ASSERT_COLUMN_MARKED_FOR_READ \
+ DBUG_ASSERT(!table || !table->read_set || \
+ bitmap_is_set(table->read_set, field_index))
+#define ASSERT_COLUMN_MARKED_FOR_WRITE \
+ DBUG_ASSERT(is_stat_field || !table || !table->write_set || \
+ bitmap_is_set(table->write_set, field_index))
#define FLAGSTR(S,F) ((S) & (F) ? #F " " : "")
@@ -80,15 +84,14 @@ const int FIELDTYPE_LAST= 254;
const int FIELDTYPE_NUM= FIELDTYPE_TEAR_FROM + (FIELDTYPE_LAST -
FIELDTYPE_TEAR_TO);
-static inline int field_type2index (enum_field_types field_type)
+static inline int merge_type2index(enum_field_types merge_type)
{
- DBUG_ASSERT(real_type_to_type(field_type) < FIELDTYPE_TEAR_FROM ||
- real_type_to_type(field_type) > FIELDTYPE_TEAR_TO);
- DBUG_ASSERT(field_type <= FIELDTYPE_LAST);
- field_type= real_type_to_type(field_type);
- if (field_type < FIELDTYPE_TEAR_FROM)
- return field_type;
- return FIELDTYPE_TEAR_FROM + (field_type - FIELDTYPE_TEAR_TO) - 1;
+ DBUG_ASSERT(merge_type < FIELDTYPE_TEAR_FROM ||
+ merge_type > FIELDTYPE_TEAR_TO);
+ DBUG_ASSERT(merge_type <= FIELDTYPE_LAST);
+ if (merge_type < FIELDTYPE_TEAR_FROM)
+ return merge_type;
+ return FIELDTYPE_TEAR_FROM + (merge_type - FIELDTYPE_TEAR_TO) - 1;
}
@@ -913,31 +916,37 @@ static enum_field_types field_types_merge_rules [FIELDTYPE_NUM][FIELDTYPE_NUM]=
}
};
-/**
- Return type of which can carry value of both given types in UNION result.
-
- @param a type for merging
- @param b type for merging
-
- @return
- type of field
-*/
-
-enum_field_types Field::field_type_merge(enum_field_types a,
- enum_field_types b)
-{
- return field_types_merge_rules[field_type2index(a)]
- [field_type2index(b)];
-}
const Type_handler *
Type_handler::aggregate_for_result_traditional(const Type_handler *a,
const Type_handler *b)
{
- enum_field_types ta= a->real_field_type();
- enum_field_types tb= b->real_field_type();
- return
- Type_handler::get_handler_by_real_type(Field::field_type_merge(ta, tb));
+ if (a == b)
+ {
+ /*
+ If two traditional handlers are equal, quickly return "a".
+ Some handlers (e.g. Type_handler_bool) pretend to be traditional,
+ but in fact they are not traditional in full extent, they are
+ only sub-types for now (and don't have a corresponding Field_xxx yet).
+ Here we preserve such handlers during aggregation.
+ As a result, COALESCE(true,true) preserves the "boolean" data type.
+
+ Need to do this conversion for deprecated data types,
+ similar to what field_type_merge_rules[][] does.
+ */
+ switch (a->field_type()) {
+ case MYSQL_TYPE_DECIMAL: return &type_handler_newdecimal;
+ case MYSQL_TYPE_DATE: return &type_handler_newdate;
+ case MYSQL_TYPE_VAR_STRING: return &type_handler_varchar;
+ default: break;
+ }
+ return a;
+ }
+ enum_field_types ta= a->traditional_merge_field_type();
+ enum_field_types tb= b->traditional_merge_field_type();
+ enum_field_types res= field_types_merge_rules[merge_type2index(ta)]
+ [merge_type2index(tb)];
+ return Type_handler::get_handler_by_real_type(res);
}
@@ -2033,7 +2042,7 @@ longlong Field::convert_decimal2longlong(const my_decimal *val,
int Field_int::store_decimal(const my_decimal *val)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
+ ASSERT_COLUMN_MARKED_FOR_WRITE;
int err= 0;
longlong i= convert_decimal2longlong(val, unsigned_flag, &err);
return MY_TEST(err | store(i, unsigned_flag));
@@ -2201,7 +2210,7 @@ void Field_num::make_send_field(Send_field *field)
int Field_str::store_decimal(const my_decimal *d)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
+ ASSERT_COLUMN_MARKED_FOR_WRITE;
double val;
/* TODO: use decimal2string? */
int err= warn_if_overflow(my_decimal2double(E_DEC_FATAL_ERROR &
@@ -2273,7 +2282,7 @@ bool Field::get_date(MYSQL_TIME *ltime,ulonglong fuzzydate)
int Field::store_time_dec(const MYSQL_TIME *ltime, uint dec)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
+ ASSERT_COLUMN_MARKED_FOR_WRITE;
char buff[MAX_DATE_STRING_REP_LENGTH];
uint length= (uint) my_TIME_to_str(ltime, buff, dec);
/* Avoid conversion when field character set is ASCII compatible */
@@ -2331,6 +2340,36 @@ Field *Field::new_key_field(MEM_ROOT *root, TABLE *new_table,
}
+/**
+ Create field for temporary table from given field.
+
+ @param thd Thread handler
+ @param table Temporary table
+ @param maybe_null_arg If the result field should be NULL-able,
+ even if the original field is NOT NULL, e.g. for:
+ - OUTER JOIN fields
+ - WITH ROLLUP fields
+ - arguments of aggregate functions, e.g. SUM(column1)
+ @retval NULL, on error
+ @retval pointer to the new field created, on success.
+*/
+
+Field *Field::create_tmp_field(MEM_ROOT *mem_root, TABLE *new_table,
+ bool maybe_null_arg)
+{
+ Field *new_field;
+
+ if ((new_field= make_new_field(mem_root, new_table, new_table == table)))
+ {
+ new_field->init_for_tmp_table(this, new_table);
+ new_field->flags|= flags & NO_DEFAULT_VALUE_FLAG;
+ if (maybe_null_arg)
+ new_field->flags&= ~NOT_NULL_FLAG; // Because of outer join
+ }
+ return new_field;
+}
+
+
/* This is used to generate a field in TABLE from TABLE_SHARE */
Field *Field::clone(MEM_ROOT *root, TABLE *new_table)
@@ -2500,7 +2539,7 @@ void Field_decimal::overflow(bool negative)
int Field_decimal::store(const char *from_arg, size_t len, CHARSET_INFO *cs)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
+ ASSERT_COLUMN_MARKED_FOR_WRITE;
char buff[STRING_BUFFER_USUAL_SIZE];
String tmp(buff,sizeof(buff), &my_charset_bin);
const uchar *from= (uchar*) from_arg;
@@ -2866,7 +2905,7 @@ int Field_decimal::store(const char *from_arg, size_t len, CHARSET_INFO *cs)
int Field_decimal::store(double nr)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
+ ASSERT_COLUMN_MARKED_FOR_WRITE;
if (unsigned_flag && nr < 0)
{
overflow(1);
@@ -2904,7 +2943,7 @@ int Field_decimal::store(double nr)
int Field_decimal::store(longlong nr, bool unsigned_val)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
+ ASSERT_COLUMN_MARKED_FOR_WRITE;
char buff[22];
uint length, int_part;
char fyllchar;
@@ -3125,7 +3164,7 @@ void Field_new_decimal::set_value_on_overflow(my_decimal *decimal_value,
bool Field_new_decimal::store_value(const my_decimal *decimal_value,
int *native_error)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
+ ASSERT_COLUMN_MARKED_FOR_WRITE;
int error= 0;
DBUG_ENTER("Field_new_decimal::store_value");
#ifndef DBUG_OFF
@@ -3183,7 +3222,7 @@ bool Field_new_decimal::store_value(const my_decimal *decimal_value)
int Field_new_decimal::store(const char *from, size_t length,
CHARSET_INFO *charset_arg)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
+ ASSERT_COLUMN_MARKED_FOR_WRITE;
my_decimal decimal_value;
THD *thd= get_thd();
DBUG_ENTER("Field_new_decimal::store(char*)");
@@ -3267,7 +3306,7 @@ int Field_new_decimal::store(const char *from, size_t length,
int Field_new_decimal::store(double nr)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
+ ASSERT_COLUMN_MARKED_FOR_WRITE;
my_decimal decimal_value;
int err;
THD *thd= get_thd();
@@ -3292,7 +3331,7 @@ int Field_new_decimal::store(double nr)
int Field_new_decimal::store(longlong nr, bool unsigned_val)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
+ ASSERT_COLUMN_MARKED_FOR_WRITE;
my_decimal decimal_value;
int err;
@@ -3314,7 +3353,7 @@ int Field_new_decimal::store(longlong nr, bool unsigned_val)
int Field_new_decimal::store_decimal(const my_decimal *decimal_value)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
+ ASSERT_COLUMN_MARKED_FOR_WRITE;
return store_value(decimal_value);
}
@@ -3573,7 +3612,7 @@ int Field_int::store_time_dec(const MYSQL_TIME *ltime, uint dec_arg)
int Field_tiny::store(const char *from,size_t len,CHARSET_INFO *cs)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
+ ASSERT_COLUMN_MARKED_FOR_WRITE;
int error;
longlong rnd;
@@ -3585,7 +3624,7 @@ int Field_tiny::store(const char *from,size_t len,CHARSET_INFO *cs)
int Field_tiny::store(double nr)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
+ ASSERT_COLUMN_MARKED_FOR_WRITE;
int error= 0;
nr=rint(nr);
if (unsigned_flag)
@@ -3628,7 +3667,7 @@ int Field_tiny::store(double nr)
int Field_tiny::store(longlong nr, bool unsigned_val)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
+ ASSERT_COLUMN_MARKED_FOR_WRITE;
int error= 0;
if (unsigned_flag)
@@ -3733,7 +3772,7 @@ void Field_tiny::sql_type(String &res) const
int Field_short::store(const char *from,size_t len,CHARSET_INFO *cs)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
+ ASSERT_COLUMN_MARKED_FOR_WRITE;
int store_tmp;
int error;
longlong rnd;
@@ -3747,7 +3786,7 @@ int Field_short::store(const char *from,size_t len,CHARSET_INFO *cs)
int Field_short::store(double nr)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
+ ASSERT_COLUMN_MARKED_FOR_WRITE;
int error= 0;
int16 res;
nr=rint(nr);
@@ -3792,7 +3831,7 @@ int Field_short::store(double nr)
int Field_short::store(longlong nr, bool unsigned_val)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
+ ASSERT_COLUMN_MARKED_FOR_WRITE;
int error= 0;
int16 res;
@@ -3907,7 +3946,7 @@ void Field_short::sql_type(String &res) const
int Field_medium::store(const char *from,size_t len,CHARSET_INFO *cs)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
+ ASSERT_COLUMN_MARKED_FOR_WRITE;
int store_tmp;
int error;
longlong rnd;
@@ -3921,7 +3960,7 @@ int Field_medium::store(const char *from,size_t len,CHARSET_INFO *cs)
int Field_medium::store(double nr)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
+ ASSERT_COLUMN_MARKED_FOR_WRITE;
int error= 0;
nr=rint(nr);
if (unsigned_flag)
@@ -3967,7 +4006,7 @@ int Field_medium::store(double nr)
int Field_medium::store(longlong nr, bool unsigned_val)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
+ ASSERT_COLUMN_MARKED_FOR_WRITE;
int error= 0;
if (unsigned_flag)
@@ -4105,7 +4144,7 @@ void Field_medium::sql_type(String &res) const
int Field_long::store(const char *from,size_t len,CHARSET_INFO *cs)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
+ ASSERT_COLUMN_MARKED_FOR_WRITE;
long store_tmp;
int error;
longlong rnd;
@@ -4119,7 +4158,7 @@ int Field_long::store(const char *from,size_t len,CHARSET_INFO *cs)
int Field_long::store(double nr)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
+ ASSERT_COLUMN_MARKED_FOR_WRITE;
int error= 0;
int32 res;
nr=rint(nr);
@@ -4164,7 +4203,7 @@ int Field_long::store(double nr)
int Field_long::store(longlong nr, bool unsigned_val)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
+ ASSERT_COLUMN_MARKED_FOR_WRITE;
int error= 0;
int32 res;
@@ -4278,7 +4317,7 @@ void Field_long::sql_type(String &res) const
int Field_longlong::store(const char *from,size_t len,CHARSET_INFO *cs)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
+ ASSERT_COLUMN_MARKED_FOR_WRITE;
int error= 0;
char *end;
ulonglong tmp;
@@ -4301,7 +4340,7 @@ int Field_longlong::store(const char *from,size_t len,CHARSET_INFO *cs)
int Field_longlong::store(double nr)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
+ ASSERT_COLUMN_MARKED_FOR_WRITE;
Converter_double_to_longlong conv(nr, unsigned_flag);
if (unlikely(conv.error()))
@@ -4314,7 +4353,7 @@ int Field_longlong::store(double nr)
int Field_longlong::store(longlong nr, bool unsigned_val)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
+ ASSERT_COLUMN_MARKED_FOR_WRITE;
int error= 0;
if (unlikely(nr < 0)) // Only possible error
@@ -4425,7 +4464,7 @@ void Field_longlong::sql_type(String &res) const
void Field_longlong::set_max()
{
- ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
+ ASSERT_COLUMN_MARKED_FOR_WRITE;
set_notnull();
int8store(ptr, unsigned_flag ? ULONGLONG_MAX : LONGLONG_MAX);
}
@@ -4462,7 +4501,7 @@ int Field_float::store(const char *from,size_t len,CHARSET_INFO *cs)
int Field_float::store(double nr)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
+ ASSERT_COLUMN_MARKED_FOR_WRITE;
int error= truncate_double(&nr, field_length,
not_fixed ? NOT_FIXED_DEC : dec,
unsigned_flag, FLT_MAX);
@@ -4641,7 +4680,7 @@ int Field_double::store(const char *from,size_t len,CHARSET_INFO *cs)
int Field_double::store(double nr)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
+ ASSERT_COLUMN_MARKED_FOR_WRITE;
int error= truncate_double(&nr, field_length,
not_fixed ? NOT_FIXED_DEC : dec,
unsigned_flag, DBL_MAX);
@@ -5026,7 +5065,7 @@ int Field_timestamp::store_TIME_with_warning(THD *thd, MYSQL_TIME *l_time,
int was_cut,
bool have_smth_to_conv)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
+ ASSERT_COLUMN_MARKED_FOR_WRITE;
uint error = 0;
my_time_t timestamp;
@@ -5501,7 +5540,7 @@ void Field_timestampf::store_TIME(my_time_t timestamp, ulong sec_part)
void Field_timestampf::set_max()
{
DBUG_ENTER("Field_timestampf::set_max");
- ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
+ ASSERT_COLUMN_MARKED_FOR_WRITE;
DBUG_ASSERT(dec == TIME_SECOND_PART_DIGITS);
set_notnull();
@@ -5577,7 +5616,7 @@ int Field_temporal_with_date::store_TIME_with_warning(MYSQL_TIME *ltime,
Sql_condition::enum_warning_level trunc_level= Sql_condition::WARN_LEVEL_WARN;
int ret= 2;
- ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
+ ASSERT_COLUMN_MARKED_FOR_WRITE;
if (was_cut == 0 && have_smth_to_conv == 0) // special case: zero date
{
@@ -5760,7 +5799,7 @@ int Field_time::store_TIME_with_warning(MYSQL_TIME *ltime,
int was_cut,
int have_smth_to_conv)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
+ ASSERT_COLUMN_MARKED_FOR_WRITE;
if (!have_smth_to_conv)
{
@@ -6226,7 +6265,7 @@ bool Field_timef::get_date(MYSQL_TIME *ltime, ulonglong fuzzydate)
int Field_year::store(const char *from, size_t len,CHARSET_INFO *cs)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
+ ASSERT_COLUMN_MARKED_FOR_WRITE;
char *end;
int error;
longlong nr= cs->cset->strntoull10rnd(cs, from, len, 0, &end, &error);
@@ -6274,7 +6313,7 @@ int Field_year::store(double nr)
int Field_year::store(longlong nr, bool unsigned_val)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
+ ASSERT_COLUMN_MARKED_FOR_WRITE;
if (nr < 0 || (nr >= 100 && nr <= 1900) || nr > 2155)
{
*ptr= 0;
@@ -6966,7 +7005,7 @@ Field_longstr::report_if_important_data(const char *pstr, const char *end,
int Field_string::store(const char *from, size_t length,CHARSET_INFO *cs)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
+ ASSERT_COLUMN_MARKED_FOR_WRITE;
uint copy_length;
int rc;
@@ -7012,7 +7051,7 @@ int Field_str::store(longlong nr, bool unsigned_val)
int Field_str::store(double nr)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
+ ASSERT_COLUMN_MARKED_FOR_WRITE;
char buff[DOUBLE_TO_STRING_CONVERSION_BUFFER_SIZE];
uint local_char_length= MY_MIN(sizeof(buff),
field_length / field_charset->mbmaxlen);
@@ -7266,11 +7305,12 @@ void Field_string::sql_type(String &res) const
size_t length;
length= cs->cset->snprintf(cs,(char*) res.ptr(),
- res.alloced_length(), "%s(%d)",
+ res.alloced_length(), "%s(%d)%s",
(type() == MYSQL_TYPE_VAR_STRING ?
(has_charset() ? "varchar" : "varbinary") :
(has_charset() ? "char" : "binary")),
- (int) field_length / charset()->mbmaxlen);
+ (int) field_length / charset()->mbmaxlen,
+ type() == MYSQL_TYPE_VAR_STRING ? "/*old*/" : "");
res.length(length);
if ((thd->variables.sql_mode & (MODE_MYSQL323 | MODE_MYSQL40)) &&
has_charset() && (charset()->state & MY_CS_BINSORT))
@@ -7515,7 +7555,7 @@ int Field_varstring::save_field_metadata(uchar *metadata_ptr)
int Field_varstring::store(const char *from,size_t length,CHARSET_INFO *cs)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
+ ASSERT_COLUMN_MARKED_FOR_WRITE;
uint copy_length;
int rc;
@@ -8053,7 +8093,7 @@ String *Field_longstr::uncompress(String *val_buffer, String *val_ptr,
int Field_varstring_compressed::store(const char *from, size_t length,
CHARSET_INFO *cs)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
+ ASSERT_COLUMN_MARKED_FOR_WRITE;
uint compressed_length;
int rc= compress((char*) get_data(), field_length, from, (uint) length,
Field_varstring_compressed::max_display_length(),
@@ -8185,7 +8225,7 @@ int Field_blob::copy_value(Field_blob *from)
int Field_blob::store(const char *from,size_t length,CHARSET_INFO *cs)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
+ ASSERT_COLUMN_MARKED_FOR_WRITE;
size_t copy_length, new_length;
uint copy_len;
char *tmp;
@@ -8667,7 +8707,7 @@ uint Field_blob::is_equal(Create_field *new_field)
int Field_blob_compressed::store(const char *from, size_t length,
CHARSET_INFO *cs)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
+ ASSERT_COLUMN_MARKED_FOR_WRITE;
uint compressed_length;
uint max_length= max_data_length();
uint to_length= (uint) MY_MIN(max_length,
@@ -9010,7 +9050,7 @@ void Field_enum::store_type(ulonglong value)
int Field_enum::store(const char *from,size_t length,CHARSET_INFO *cs)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
+ ASSERT_COLUMN_MARKED_FOR_WRITE;
int err= 0;
char buff[STRING_BUFFER_USUAL_SIZE];
String tmpstr(buff,sizeof(buff), &my_charset_bin);
@@ -9062,7 +9102,7 @@ int Field_enum::store(double nr)
int Field_enum::store(longlong nr, bool unsigned_val)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
+ ASSERT_COLUMN_MARKED_FOR_WRITE;
int error= 0;
if ((ulonglong) nr > typelib->count || nr == 0)
{
@@ -9193,7 +9233,7 @@ Field *Field_enum::make_new_field(MEM_ROOT *root, TABLE *new_table,
int Field_set::store(const char *from,size_t length,CHARSET_INFO *cs)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
+ ASSERT_COLUMN_MARKED_FOR_WRITE;
bool got_warning= 0;
int err= 0;
char *not_used;
@@ -9233,7 +9273,7 @@ int Field_set::store(const char *from,size_t length,CHARSET_INFO *cs)
int Field_set::store(longlong nr, bool unsigned_val)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
+ ASSERT_COLUMN_MARKED_FOR_WRITE;
int error= 0;
ulonglong max_nr;
@@ -9612,7 +9652,7 @@ uint Field_bit::is_equal(Create_field *new_field)
int Field_bit::store(const char *from, size_t length, CHARSET_INFO *cs)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
+ ASSERT_COLUMN_MARKED_FOR_WRITE;
int delta;
for (; length && !*from; from++, length--) // skip left 0's
@@ -10048,7 +10088,7 @@ Field_bit_as_char::Field_bit_as_char(uchar *ptr_arg, uint32 len_arg,
int Field_bit_as_char::store(const char *from, size_t length, CHARSET_INFO *cs)
{
- ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
+ ASSERT_COLUMN_MARKED_FOR_WRITE;
int delta;
uchar bits= (uchar) (field_length & 7);
@@ -10542,319 +10582,85 @@ uint pack_length_to_packflag(uint type)
}
-Field *make_field(TABLE_SHARE *share,
- MEM_ROOT *mem_root,
- uchar *ptr, uint32 field_length,
- uchar *null_pos, uchar null_bit,
- uint pack_flag,
- const Type_handler *handler,
- CHARSET_INFO *field_charset,
- Field::geometry_type geom_type, uint srid,
- Field::utype unireg_check,
- TYPELIB *interval,
- const LEX_CSTRING *field_name,
- uint32 flags)
+uint Column_definition_attributes::pack_flag_to_pack_length() const
{
- uchar *UNINIT_VAR(bit_ptr);
- uchar UNINIT_VAR(bit_offset);
+ uint type= f_packtype(pack_flag); // 0..15
+ DBUG_ASSERT(type < 16);
+ switch (type) {
+ case MYSQL_TYPE_TINY: return 1;
+ case MYSQL_TYPE_SHORT: return 2;
+ case MYSQL_TYPE_LONG: return 4;
+ case MYSQL_TYPE_LONGLONG: return 8;
+ case MYSQL_TYPE_INT24: return 3;
+ }
+ return 0; // This should not happen
+}
+
+Field *Column_definition_attributes::make_field(TABLE_SHARE *share,
+ MEM_ROOT *mem_root,
+ const Record_addr *rec,
+ const Type_handler *handler,
+ const LEX_CSTRING *field_name,
+ uint32 flags)
+ const
+{
+ DBUG_ASSERT(length <= UINT_MAX32);
DBUG_PRINT("debug", ("field_type: %s, field_length: %u, interval: %p, pack_flag: %s%s%s%s%s",
- handler->name().ptr(), field_length, interval,
+ handler->name().ptr(), (uint) length, interval,
FLAGSTR(pack_flag, FIELDFLAG_BINARY),
FLAGSTR(pack_flag, FIELDFLAG_INTERVAL),
FLAGSTR(pack_flag, FIELDFLAG_NUMBER),
FLAGSTR(pack_flag, FIELDFLAG_PACK),
FLAGSTR(pack_flag, FIELDFLAG_BLOB)));
- if (handler == &type_handler_row)
- {
- DBUG_ASSERT(field_length == 0);
- DBUG_ASSERT(f_maybe_null(pack_flag));
- return new (mem_root) Field_row(ptr, field_name);
- }
-
- if (handler->real_field_type() == MYSQL_TYPE_BIT && !f_bit_as_char(pack_flag))
- {
- bit_ptr= null_pos;
- bit_offset= null_bit;
- if (f_maybe_null(pack_flag)) // if null field
- {
- bit_ptr+= (null_bit == 7); // shift bit_ptr and bit_offset
- bit_offset= (bit_offset + 1) & 7;
- }
- }
-
- if (!f_maybe_null(pack_flag))
- {
- null_pos=0;
- null_bit=0;
- }
- else
- {
- null_bit= ((uchar) 1) << null_bit;
- }
-
-
- if (f_is_alpha(pack_flag))
- {
- if (!f_is_packed(pack_flag))
- {
- enum_field_types field_type= handler->real_field_type();
- if (field_type == MYSQL_TYPE_STRING ||
- field_type == MYSQL_TYPE_DECIMAL || // 3.23 or 4.0 string
- field_type == MYSQL_TYPE_VAR_STRING)
- return new (mem_root)
- Field_string(ptr,field_length,null_pos,null_bit,
- unireg_check, field_name,
- field_charset);
- if (field_type == MYSQL_TYPE_VARCHAR)
- {
- if (unireg_check == Field::TMYSQL_COMPRESSED)
- return new (mem_root)
- Field_varstring_compressed(
- ptr, field_length,
- HA_VARCHAR_PACKLENGTH(field_length),
- null_pos, null_bit,
- unireg_check, field_name,
- share, field_charset, zlib_compression_method);
-
- return new (mem_root)
- Field_varstring(ptr,field_length,
- HA_VARCHAR_PACKLENGTH(field_length),
- null_pos,null_bit,
- unireg_check, field_name,
- share,
- field_charset);
- }
- return 0; // Error
- }
-
- // MYSQL_TYPE_VAR_STRING is handled above
- DBUG_ASSERT(f_packtype(pack_flag) != MYSQL_TYPE_VAR_STRING);
- const Type_handler *tmp;
- tmp= Type_handler::get_handler_by_real_type((enum_field_types)
- f_packtype(pack_flag));
- uint pack_length= tmp->calc_pack_length(field_length);
-
-#ifdef HAVE_SPATIAL
- if (f_is_geom(pack_flag))
- {
- status_var_increment(current_thd->status_var.feature_gis);
- return new (mem_root)
- Field_geom(ptr,null_pos,null_bit,
- unireg_check, field_name, share,
- pack_length, geom_type, srid);
- }
-#endif
- if (f_is_blob(pack_flag))
- {
- if (unireg_check == Field::TMYSQL_COMPRESSED)
- return new (mem_root)
- Field_blob_compressed(ptr, null_pos, null_bit,
- unireg_check, field_name, share,
- pack_length, field_charset, zlib_compression_method);
-
- return new (mem_root)
- Field_blob(ptr,null_pos,null_bit,
- unireg_check, field_name, share,
- pack_length, field_charset);
- }
- if (interval)
- {
- if (f_is_enum(pack_flag))
- return new (mem_root)
- Field_enum(ptr,field_length,null_pos,null_bit,
- unireg_check, field_name,
- pack_length, interval, field_charset);
- else
- return new (mem_root)
- Field_set(ptr,field_length,null_pos,null_bit,
- unireg_check, field_name,
- pack_length, interval, field_charset);
- }
- }
-
- switch (handler->real_field_type()) {
- case MYSQL_TYPE_DECIMAL:
- return new (mem_root)
- Field_decimal(ptr,field_length,null_pos,null_bit,
- unireg_check, field_name,
- f_decimals(pack_flag),
- f_is_zerofill(pack_flag) != 0,
- f_is_dec(pack_flag) == 0);
- case MYSQL_TYPE_NEWDECIMAL:
- return new (mem_root)
- Field_new_decimal(ptr,field_length,null_pos,null_bit,
- unireg_check, field_name,
- f_decimals(pack_flag),
- f_is_zerofill(pack_flag) != 0,
- f_is_dec(pack_flag) == 0);
- case MYSQL_TYPE_FLOAT:
- {
- int decimals= f_decimals(pack_flag);
- if (decimals == FLOATING_POINT_DECIMALS)
- decimals= NOT_FIXED_DEC;
- return new (mem_root)
- Field_float(ptr,field_length,null_pos,null_bit,
- unireg_check, field_name,
- decimals,
- f_is_zerofill(pack_flag) != 0,
- f_is_dec(pack_flag)== 0);
- }
- case MYSQL_TYPE_DOUBLE:
- {
- int decimals= f_decimals(pack_flag);
- if (decimals == FLOATING_POINT_DECIMALS)
- decimals= NOT_FIXED_DEC;
- return new (mem_root)
- Field_double(ptr,field_length,null_pos,null_bit,
- unireg_check, field_name,
- decimals,
- f_is_zerofill(pack_flag) != 0,
- f_is_dec(pack_flag)== 0);
- }
- case MYSQL_TYPE_TINY:
- return new (mem_root)
- Field_tiny(ptr,field_length,null_pos,null_bit,
- unireg_check, field_name,
- f_is_zerofill(pack_flag) != 0,
- f_is_dec(pack_flag) == 0);
- case MYSQL_TYPE_SHORT:
- return new (mem_root)
- Field_short(ptr,field_length,null_pos,null_bit,
- unireg_check, field_name,
- f_is_zerofill(pack_flag) != 0,
- f_is_dec(pack_flag) == 0);
- case MYSQL_TYPE_INT24:
- return new (mem_root)
- Field_medium(ptr,field_length,null_pos,null_bit,
- unireg_check, field_name,
- f_is_zerofill(pack_flag) != 0,
- f_is_dec(pack_flag) == 0);
- case MYSQL_TYPE_LONG:
- return new (mem_root)
- Field_long(ptr,field_length,null_pos,null_bit,
- unireg_check, field_name,
- f_is_zerofill(pack_flag) != 0,
- f_is_dec(pack_flag) == 0);
- case MYSQL_TYPE_LONGLONG:
- if (flags & (VERS_SYS_START_FLAG|VERS_SYS_END_FLAG))
- {
- return new (mem_root)
- Field_vers_trx_id(ptr, field_length, null_pos, null_bit,
- unireg_check, field_name,
- f_is_zerofill(pack_flag) != 0,
- f_is_dec(pack_flag) == 0);
- }
- else
- {
- return new (mem_root)
- Field_longlong(ptr,field_length,null_pos,null_bit,
- unireg_check, field_name,
- f_is_zerofill(pack_flag) != 0,
- f_is_dec(pack_flag) == 0);
- }
- case MYSQL_TYPE_TIMESTAMP:
- {
- uint dec= field_length > MAX_DATETIME_WIDTH ?
- field_length - MAX_DATETIME_WIDTH - 1: 0;
- return new_Field_timestamp(mem_root, ptr, null_pos, null_bit, unireg_check,
- field_name, share, dec);
- }
- case MYSQL_TYPE_TIMESTAMP2:
- {
- uint dec= field_length > MAX_DATETIME_WIDTH ?
- field_length - MAX_DATETIME_WIDTH - 1: 0;
- return new (mem_root)
- Field_timestampf(ptr, null_pos, null_bit, unireg_check,
- field_name, share, dec);
- }
- case MYSQL_TYPE_YEAR:
- return new (mem_root)
- Field_year(ptr,field_length,null_pos,null_bit,
- unireg_check, field_name);
- case MYSQL_TYPE_DATE:
- return new (mem_root)
- Field_date(ptr,null_pos,null_bit,
- unireg_check, field_name);
- case MYSQL_TYPE_NEWDATE:
- return new (mem_root)
- Field_newdate(ptr,null_pos,null_bit,
- unireg_check, field_name);
- case MYSQL_TYPE_TIME:
- {
- uint dec= field_length > MIN_TIME_WIDTH ?
- field_length - MIN_TIME_WIDTH - 1: 0;
- return new_Field_time(mem_root, ptr, null_pos, null_bit, unireg_check,
- field_name, dec);
- }
- case MYSQL_TYPE_TIME2:
- {
- uint dec= field_length > MIN_TIME_WIDTH ?
- field_length - MIN_TIME_WIDTH - 1: 0;
- return new (mem_root)
- Field_timef(ptr, null_pos, null_bit, unireg_check,
- field_name, dec);
- }
- case MYSQL_TYPE_DATETIME:
- {
- uint dec= field_length > MAX_DATETIME_WIDTH ?
- field_length - MAX_DATETIME_WIDTH - 1: 0;
- return new_Field_datetime(mem_root, ptr, null_pos, null_bit, unireg_check,
- field_name, dec);
- }
- case MYSQL_TYPE_DATETIME2:
- {
- uint dec= field_length > MAX_DATETIME_WIDTH ?
- field_length - MAX_DATETIME_WIDTH - 1: 0;
- return new (mem_root)
- Field_datetimef(ptr, null_pos, null_bit, unireg_check,
- field_name, dec);
- }
- case MYSQL_TYPE_NULL:
- return new (mem_root)
- Field_null(ptr, field_length, unireg_check, field_name,
- field_charset);
- case MYSQL_TYPE_BIT:
- return (f_bit_as_char(pack_flag) ?
- new (mem_root)
- Field_bit_as_char(ptr, field_length, null_pos, null_bit,
- unireg_check, field_name) :
- new (mem_root)
- Field_bit(ptr, field_length, null_pos, null_bit, bit_ptr,
- bit_offset, unireg_check, field_name));
-
- default: // Impossible (Wrong version)
- break;
- }
- return 0;
+ Record_addr addr(rec->ptr(), f_maybe_null(pack_flag) ? rec->null() :
+ Bit_addr());
+ /*
+ Special code for the BIT-alike data types
+ who store data bits together with NULL-bits.
+ */
+ Bit_addr bit(rec->null());
+ if (f_maybe_null(pack_flag))
+ bit.inc();
+ return handler->make_table_field_from_def(share, mem_root, field_name,
+ addr, bit, this, flags);
}
+
bool Field_vers_trx_id::test_if_equality_guarantees_uniqueness(const Item* item) const
{
return item->type() == Item::DATE_ITEM;
}
+Column_definition_attributes::Column_definition_attributes(const Field *field)
+ :length(field->field_length),
+ unireg_check(field->unireg_check),
+ interval(NULL),
+ charset(field->charset()), // May be NULL ptr
+ srid(0),
+ geom_type(Field::GEOM_GEOMETRY),
+ pack_flag(0)
+{}
+
+
/** Create a field suitable for create of table. */
Column_definition::Column_definition(THD *thd, Field *old_field,
Field *orig_field)
+ :Column_definition_attributes(old_field)
{
on_update= NULL;
field_name= old_field->field_name;
- length= old_field->field_length;
flags= old_field->flags;
- unireg_check=old_field->unireg_check;
pack_length=old_field->pack_length();
key_length= old_field->key_length();
set_handler(old_field->type_handler());
- charset= old_field->charset(); // May be NULL ptr
comment= old_field->comment;
decimals= old_field->decimals();
vcol_info= old_field->vcol_info;
option_list= old_field->option_list;
- pack_flag= 0;
compression_method_ptr= 0;
versioning= VERSIONING_NOT_SET;
invisible= old_field->invisible;
diff --git a/sql/field.h b/sql/field.h
index 2079c90037a..b6f28808e2e 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -467,31 +467,6 @@ inline bool is_temporal_type_with_date(enum_field_types type)
}
-/**
- Convert temporal real types as retuned by field->real_type()
- to field type as returned by field->type().
-
- @param real_type Real type.
- @retval Field type.
-*/
-inline enum_field_types real_type_to_type(enum_field_types real_type)
-{
- switch (real_type)
- {
- case MYSQL_TYPE_TIME2:
- return MYSQL_TYPE_TIME;
- case MYSQL_TYPE_DATETIME2:
- return MYSQL_TYPE_DATETIME;
- case MYSQL_TYPE_TIMESTAMP2:
- return MYSQL_TYPE_TIMESTAMP;
- case MYSQL_TYPE_NEWDATE:
- return MYSQL_TYPE_DATE;
- /* Note: NEWDECIMAL is a type, not only a real_type */
- default: return real_type;
- }
-}
-
-
enum enum_vcol_info_type
{
VCOL_GENERATED_VIRTUAL, VCOL_GENERATED_STORED,
@@ -875,7 +850,6 @@ public:
{
return type_handler()->cmp_type();
}
- static enum_field_types field_type_merge(enum_field_types, enum_field_types);
virtual bool eq(Field *field)
{
return (ptr == field->ptr && null_ptr == field->null_ptr &&
@@ -1240,6 +1214,12 @@ public:
virtual Field *new_key_field(MEM_ROOT *root, TABLE *new_table,
uchar *new_ptr, uint32 length,
uchar *new_null_ptr, uint new_null_bit);
+ Field *create_tmp_field(MEM_ROOT *root, TABLE *new_table,
+ bool maybe_null_arg);
+ Field *create_tmp_field(MEM_ROOT *root, TABLE *new_table)
+ {
+ return create_tmp_field(root, new_table, maybe_null());
+ }
Field *clone(MEM_ROOT *mem_root, TABLE *new_table);
Field *clone(MEM_ROOT *mem_root, TABLE *new_table, my_ptrdiff_t diff,
bool stat_flag= FALSE);
@@ -1400,7 +1380,19 @@ public:
orig_table= table= table_arg;
set_table_name(&table_arg->alias);
}
-
+ virtual void init_for_tmp_table(Field *org_field, TABLE *new_table)
+ {
+ init(new_table);
+ orig_table= org_field->orig_table;
+ vcol_info= 0;
+ cond_selectivity= 1.0;
+ next_equal_field= NULL;
+ option_list= NULL;
+ option_struct= NULL;
+ if (org_field->type() == MYSQL_TYPE_VAR_STRING ||
+ org_field->type() == MYSQL_TYPE_VARCHAR)
+ new_table->s->db_create_options|= HA_OPTION_PACK_RECORD;
+ }
/* maximum possible display length */
virtual uint32 max_display_length() const= 0;
/**
@@ -2391,6 +2383,11 @@ public:
if (dec_arg >= FLOATING_POINT_DECIMALS)
dec_arg= NOT_FIXED_DEC;
}
+ void init_for_tmp_table(Field *org_field, TABLE *new_table)
+ {
+ Field::init_for_tmp_table(org_field, new_table);
+ not_fixed= true;
+ }
const Type_handler *type_handler() const { return &type_handler_double; }
enum ha_base_keytype key_type() const { return HA_KEYTYPE_DOUBLE; }
int store(const char *to,size_t length,CHARSET_INFO *charset);
@@ -4194,21 +4191,53 @@ public:
extern const LEX_CSTRING null_clex_str;
-Field *make_field(TABLE_SHARE *share, MEM_ROOT *mem_root,
- uchar *ptr, uint32 field_length,
- uchar *null_pos, uchar null_bit,
- uint pack_flag, const Type_handler *handler,
- CHARSET_INFO *cs,
- Field::geometry_type geom_type, uint srid,
- Field::utype unireg_check,
- TYPELIB *interval, const LEX_CSTRING *field_name,
- uint32 flags);
+class Column_definition_attributes
+{
+public:
+ /*
+ At various stages in execution this can be length of field in bytes or
+ max number of characters.
+ */
+ ulonglong length;
+ Field::utype unireg_check;
+ TYPELIB *interval; // Which interval to use
+ CHARSET_INFO *charset;
+ uint32 srid;
+ Field::geometry_type geom_type;
+ uint pack_flag;
+ Column_definition_attributes()
+ :length(0),
+ unireg_check(Field::NONE),
+ interval(NULL),
+ charset(&my_charset_bin),
+ srid(0),
+ geom_type(Field::GEOM_GEOMETRY),
+ pack_flag(0)
+ { }
+ Column_definition_attributes(const Field *field);
+ Field *make_field(TABLE_SHARE *share, MEM_ROOT *mem_root,
+ const Record_addr *rec,
+ const Type_handler *handler,
+ const LEX_CSTRING *field_name,
+ uint32 flags) const;
+ uint temporal_dec(uint intlen) const
+ {
+ return (uint) (length > intlen ? length - intlen - 1 : 0);
+ }
+ uint pack_flag_to_pack_length() const;
+ void frm_pack_basic(uchar *buff) const;
+ void frm_pack_charset(uchar *buff) const;
+ void frm_unpack_basic(const uchar *buff);
+ bool frm_unpack_charset(TABLE_SHARE *share, const uchar *buff);
+};
+
/*
Create field class for CREATE TABLE
*/
class Column_definition: public Sql_alloc,
- public Type_handler_hybrid_field_type
+ public Type_handler_hybrid_field_type,
+ public Column_definition_attributes
{
/**
Create "interval" from "interval_list".
@@ -4263,11 +4292,6 @@ public:
WITHOUT_VERSIONING
};
Item *on_update; // ON UPDATE NOW()
- /*
- At various stages in execution this can be length of field in bytes or
- max number of characters.
- */
- ulonglong length;
field_visibility_t invisible;
/*
The value of `length' as set by parser: is the number of characters
@@ -4275,15 +4299,9 @@ public:
*/
uint32 char_length;
uint decimals, flags, pack_length, key_length;
- Field::utype unireg_check;
- TYPELIB *interval; // Which interval to use
List<String> interval_list;
- CHARSET_INFO *charset;
- uint32 srid;
- Field::geometry_type geom_type;
engine_option_value *option_list;
- uint pack_flag;
/*
This is additinal data provided for any computed(virtual) field.
@@ -4301,11 +4319,9 @@ public:
:Type_handler_hybrid_field_type(&type_handler_null),
compression_method_ptr(0),
comment(null_clex_str),
- on_update(NULL), length(0), invisible(VISIBLE), decimals(0),
- flags(0), pack_length(0), key_length(0), unireg_check(Field::NONE),
- interval(0), charset(&my_charset_bin),
- srid(0), geom_type(Field::GEOM_GEOMETRY),
- option_list(NULL), pack_flag(0),
+ on_update(NULL), invisible(VISIBLE), decimals(0),
+ flags(0), pack_length(0), key_length(0),
+ option_list(NULL),
vcol_info(0), default_value(0), check_constraint(0),
versioning(VERSIONING_NOT_SET)
{
@@ -4435,20 +4451,18 @@ public:
}
Field *make_field(TABLE_SHARE *share, MEM_ROOT *mem_root,
- uchar *ptr, uchar *null_pos, uchar null_bit,
+ const Record_addr *addr,
const LEX_CSTRING *field_name_arg) const
{
- return ::make_field(share, mem_root, ptr,
- (uint32)length, null_pos, null_bit,
- pack_flag, type_handler(), charset,
- geom_type, srid, unireg_check, interval,
- field_name_arg, flags);
+ return Column_definition_attributes::make_field(share, mem_root, addr,
+ type_handler(),
+ field_name_arg, flags);
}
Field *make_field(TABLE_SHARE *share, MEM_ROOT *mem_root,
const LEX_CSTRING *field_name_arg) const
{
- return make_field(share, mem_root, (uchar *) 0, (uchar *) "", 0,
- field_name_arg);
+ Record_addr addr(true);
+ return make_field(share, mem_root, &addr, field_name_arg);
}
/* Return true if default is an expression that must be saved explicitely */
bool has_default_expression();
@@ -4770,7 +4784,7 @@ bool check_expression(Virtual_column_info *vcol, LEX_CSTRING *name,
#define FIELDFLAG_DEC_SHIFT 8
#define FIELDFLAG_MAX_DEC 63U
-#define MTYP_TYPENR(type) (type & 127U) /* Remove bits from type */
+#define MTYP_TYPENR(type) ((type) & 127U) // Remove bits from type
#define f_is_dec(x) ((x) & FIELDFLAG_DECIMAL)
#define f_is_num(x) ((x) & FIELDFLAG_NUMBER)
diff --git a/sql/filesort.cc b/sql/filesort.cc
index b2c88cda7b3..e62c4a9780d 100644
--- a/sql/filesort.cc
+++ b/sql/filesort.cc
@@ -258,7 +258,7 @@ SORT_INFO *filesort(THD *thd, TABLE *table, Filesort *filesort,
}
if (memory_available < min_sort_memory)
{
- my_error(ER_OUT_OF_SORTMEMORY,MYF(ME_ERROR + ME_FATALERROR));
+ my_error(ER_OUT_OF_SORTMEMORY,MYF(ME_ERROR_LOG + ME_FATAL));
goto err;
}
tracker->report_sort_buffer_size(sort->sort_buffer_size());
@@ -710,7 +710,7 @@ static ha_rows find_all_keys(THD *thd, Sort_param *param, SQL_SELECT *select,
uchar *ref_pos, *next_pos, ref_buff[MAX_REFLENGTH];
TABLE *sort_form;
handler *file;
- MY_BITMAP *save_read_set, *save_write_set, *save_vcol_set;
+ MY_BITMAP *save_read_set, *save_write_set;
Item *sort_cond;
ha_rows retval;
DBUG_ENTER("find_all_keys");
@@ -745,13 +745,11 @@ static ha_rows find_all_keys(THD *thd, Sort_param *param, SQL_SELECT *select,
/* Remember original bitmaps */
save_read_set= sort_form->read_set;
save_write_set= sort_form->write_set;
- save_vcol_set= sort_form->vcol_set;
/* Set up temporary column read map for columns used by sort */
DBUG_ASSERT(save_read_set != &sort_form->tmp_set);
bitmap_clear_all(&sort_form->tmp_set);
- sort_form->column_bitmaps_set(&sort_form->tmp_set, &sort_form->tmp_set,
- &sort_form->tmp_set);
+ sort_form->column_bitmaps_set(&sort_form->tmp_set, &sort_form->tmp_set);
register_used_fields(param);
if (quick_select)
select->quick->add_used_key_part_to_set();
@@ -809,16 +807,12 @@ static ha_rows find_all_keys(THD *thd, Sort_param *param, SQL_SELECT *select,
*/
MY_BITMAP *tmp_read_set= sort_form->read_set;
MY_BITMAP *tmp_write_set= sort_form->write_set;
- MY_BITMAP *tmp_vcol_set= sort_form->vcol_set;
if (select->cond->with_subquery())
- sort_form->column_bitmaps_set(save_read_set, save_write_set,
- save_vcol_set);
+ sort_form->column_bitmaps_set(save_read_set, save_write_set);
write_record= (select->skip_record(thd) > 0);
if (select->cond->with_subquery())
- sort_form->column_bitmaps_set(tmp_read_set,
- tmp_write_set,
- tmp_vcol_set);
+ sort_form->column_bitmaps_set(tmp_read_set, tmp_write_set);
}
else
write_record= true;
@@ -864,7 +858,7 @@ static ha_rows find_all_keys(THD *thd, Sort_param *param, SQL_SELECT *select,
}
/* Signal we should use orignal column read and write maps */
- sort_form->column_bitmaps_set(save_read_set, save_write_set, save_vcol_set);
+ sort_form->column_bitmaps_set(save_read_set, save_write_set);
if (unlikely(thd->is_error()))
DBUG_RETURN(HA_POS_ERROR);
@@ -872,8 +866,8 @@ static ha_rows find_all_keys(THD *thd, Sort_param *param, SQL_SELECT *select,
DBUG_PRINT("test",("error: %d indexpos: %d",error,indexpos));
if (unlikely(error != HA_ERR_END_OF_FILE))
{
- file->print_error(error,MYF(ME_ERROR | ME_WAITTANG)); // purecov: inspected
- DBUG_RETURN(HA_POS_ERROR); /* purecov: inspected */
+ file->print_error(error,MYF(ME_ERROR_LOG));
+ DBUG_RETURN(HA_POS_ERROR);
}
if (indexpos && idx &&
write_keys(param, fs_info, idx, buffpek_pointers, tempfile))
@@ -885,7 +879,7 @@ static ha_rows find_all_keys(THD *thd, Sort_param *param, SQL_SELECT *select,
DBUG_RETURN(retval);
err:
- sort_form->column_bitmaps_set(save_read_set, save_write_set, save_vcol_set);
+ sort_form->column_bitmaps_set(save_read_set, save_write_set);
DBUG_RETURN(HA_POS_ERROR);
} /* find_all_keys */
diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc
index 0775d67a592..58247234eec 100644
--- a/sql/ha_partition.cc
+++ b/sql/ha_partition.cc
@@ -6808,7 +6808,7 @@ FT_INFO *ha_partition::ft_init_ext(uint flags, uint inx, String *key)
sizeof(FT_INFO *) * m_tot_parts,
NullS)))
{
- my_error(ER_OUT_OF_RESOURCES, MYF(ME_FATALERROR));
+ my_error(ER_OUT_OF_RESOURCES, MYF(ME_FATAL));
DBUG_RETURN(NULL);
}
ft_target->part_ft_info= tmp_ft_info;
@@ -10647,8 +10647,6 @@ int ha_partition::check_misplaced_rows(uint read_part_id, bool do_repair)
{
/* Only need to read the partitioning fields. */
bitmap_union(table->read_set, &m_part_info->full_part_field_set);
- if (table->vcol_set)
- bitmap_union(table->vcol_set, &m_part_info->full_part_field_set);
}
if ((result= m_file[read_part_id]->ha_rnd_init(1)))
diff --git a/sql/handler.cc b/sql/handler.cc
index 07459d4cd8c..b77b2a3fa2c 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -295,7 +295,7 @@ handler *get_ha_partition(partition_info *part_info)
}
else
{
- my_error(ER_OUTOFMEMORY, MYF(ME_FATALERROR),
+ my_error(ER_OUTOFMEMORY, MYF(ME_FATAL),
static_cast<int>(sizeof(ha_partition)));
}
DBUG_RETURN(((handler*) partition));
@@ -2543,7 +2543,7 @@ int ha_delete_table(THD *thd, handlerton *table_type, const char *path,
dummy_share.table_name= *alias;
dummy_table.alias.set(alias->str, alias->length, table_alias_charset);
file->change_table_ptr(&dummy_table, &dummy_share);
- file->print_error(error, MYF(intercept ? ME_JUST_WARNING : 0));
+ file->print_error(error, MYF(intercept ? ME_WARNING : 0));
}
if (intercept)
error= 0;
@@ -3561,7 +3561,7 @@ void handler::print_error(int error, myf errflag)
if (ha_thd()->transaction_rollback_request)
{
/* Ensure this becomes a true error */
- errflag&= ~(ME_JUST_WARNING | ME_JUST_INFO);
+ errflag&= ~(ME_WARNING | ME_NOTE);
}
int textno= -1; // impossible value
@@ -3696,14 +3696,14 @@ void handler::print_error(int error, myf errflag)
{
textno=ER_RECORD_FILE_FULL;
/* Write the error message to error log */
- errflag|= ME_NOREFRESH;
+ errflag|= ME_ERROR_LOG;
break;
}
case HA_ERR_INDEX_FILE_FULL:
{
textno=ER_INDEX_FILE_FULL;
/* Write the error message to error log */
- errflag|= ME_NOREFRESH;
+ errflag|= ME_ERROR_LOG;
break;
}
case HA_ERR_LOCK_WAIT_TIMEOUT:
@@ -3830,14 +3830,14 @@ void handler::print_error(int error, myf errflag)
if (unlikely(fatal_error))
{
/* Ensure this becomes a true error */
- errflag&= ~(ME_JUST_WARNING | ME_JUST_INFO);
+ errflag&= ~(ME_WARNING | ME_NOTE);
if ((debug_assert_if_crashed_table ||
global_system_variables.log_warnings > 1))
{
/*
Log error to log before we crash or if extended warnings are requested
*/
- errflag|= ME_NOREFRESH;
+ errflag|= ME_ERROR_LOG;
}
}
@@ -4009,7 +4009,8 @@ static bool update_frm_version(TABLE *table)
int4store(version, MYSQL_VERSION_ID);
- if ((result= (int)mysql_file_pwrite(file, (uchar*) version, 4, 51L, MYF_RW)))
+ if ((result= (int)mysql_file_pwrite(file, (uchar*) version, 4, 51L,
+ MYF(MY_WME+MY_NABP))))
goto err;
table->s->mysql_version= MYSQL_VERSION_ID;
@@ -4929,7 +4930,7 @@ int ha_create_table(THD *thd, const char *path,
{
if (!thd->is_error())
my_error(ER_CANT_CREATE_TABLE, MYF(0), db, table_name, error);
- table.file->print_error(error, MYF(ME_JUST_WARNING));
+ table.file->print_error(error, MYF(ME_WARNING));
PSI_CALL_drop_table_share(temp_table, share.db.str, (uint)share.db.length,
share.table_name.str, (uint)share.table_name.length);
}
diff --git a/sql/item.cc b/sql/item.cc
index dac68d1a4c7..0a7972b6617 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -930,12 +930,15 @@ bool Item_field::register_field_in_read_map(void *arg)
{
TABLE *table= (TABLE *) arg;
int res= 0;
+ if (table && table != field->table)
+ return res;
+
if (field->vcol_info &&
- !bitmap_fast_test_and_set(field->table->vcol_set, field->field_index))
+ !bitmap_fast_test_and_set(field->table->read_set, field->field_index))
{
res= field->vcol_info->expr->walk(&Item::register_field_in_read_map,1,arg);
}
- if (field->table == table || !table)
+ else
bitmap_set_bit(field->table->read_set, field->field_index);
return res;
}
@@ -7599,6 +7602,231 @@ Item *Item_field::update_value_transformer(THD *thd, uchar *select_arg)
}
+/**
+ @brief
+ Prepare AND/OR formula for extraction of a pushable condition
+
+ @param checker the checker callback function to be applied to the nodes
+ of the tree of the object
+ @param arg parameter to be passed to the checker
+
+ @details
+ This method recursively traverses this AND/OR condition and for each
+ subformula of the condition it checks whether it can be usable for the
+ extraction of a pushable condition. The criteria of pushability of
+ a subformula is checked by the callback function 'checker' with one
+ parameter arg. The subformulas that are not usable are marked with
+ the flag NO_EXTRACTION_FL.
+ @note
+ This method is called before any call of build_pushable_cond.
+ The flag NO_EXTRACTION_FL set in a subformula allows to avoid building
+ clones for the subformulas that are not used in the pushable condition.
+ @note
+ This method is called for pushdown conditions into materialized
+ derived tables/views optimization.
+ Item::pushable_cond_checker_for_derived() is passed as the actual callback
+ function.
+ Also it is called for pushdown conditions in materialized IN subqueries.
+ Item::pushable_cond_checker_for_subquery is passed as the actual
+ callback function.
+*/
+
+void Item::check_pushable_cond(Pushdown_checker checker, uchar *arg)
+{
+ clear_extraction_flag();
+ if (type() == Item::COND_ITEM)
+ {
+ bool and_cond= ((Item_cond*) this)->functype() == Item_func::COND_AND_FUNC;
+ List_iterator<Item> li(*((Item_cond*) this)->argument_list());
+ uint count= 0;
+ Item *item;
+ while ((item=li++))
+ {
+ item->check_pushable_cond(checker, arg);
+ if (item->get_extraction_flag() != NO_EXTRACTION_FL)
+ count++;
+ else if (!and_cond)
+ break;
+ }
+ if ((and_cond && count == 0) || item)
+ {
+ set_extraction_flag(NO_EXTRACTION_FL);
+ if (and_cond)
+ li.rewind();
+ while ((item= li++))
+ item->clear_extraction_flag();
+ }
+ }
+ else if (!((this->*checker) (arg)))
+ set_extraction_flag(NO_EXTRACTION_FL);
+}
+
+
+/**
+ @brief
+ Build condition extractable from this condition for pushdown
+
+ @param thd the thread handle
+ @param checker the checker callback function to be applied to the
+ equal items of multiple equality items
+ @param arg parameter to be passed to the checker
+
+ @details
+ This method finds out what condition that can be pushed down can be
+ extracted from this condition. If such condition C exists the
+ method builds the item for it. The method uses the flag NO_EXTRACTION_FL
+ set by the preliminary call of the method check_pushable_cond() to figure
+ out whether a subformula is pushable or not.
+ In the case when this item is a multiple equality a checker method is
+ called to find the equal fields to build a new equality that can be
+ pushed down.
+ @note
+ The built condition C is always implied by the condition cond
+ (cond => C). The method tries to build the most restrictive such
+ condition (i.e. for any other condition C' such that cond => C'
+ we have C => C').
+ @note
+ The build item is not ready for usage: substitution for the field items
+ has to be done and it has to be re-fixed.
+ @note
+ This method is called for pushdown conditions into materialized
+ derived tables/views optimization.
+ Item::pushable_equality_checker_for_derived() is passed as the actual
+ callback function.
+ Also it is called for pushdown conditions into materialized IN subqueries.
+ Item::pushable_equality_checker_for_subquery() is passed as the actual
+ callback function.
+
+ @retval
+ the built condition pushable into if such a condition exists
+ NULL if there is no such a condition
+*/
+
+Item *Item::build_pushable_cond(THD *thd,
+ Pushdown_checker checker,
+ uchar *arg)
+{
+ bool is_multiple_equality= type() == Item::FUNC_ITEM &&
+ ((Item_func*) this)->functype() == Item_func::MULT_EQUAL_FUNC;
+
+ if (get_extraction_flag() == NO_EXTRACTION_FL)
+ return 0;
+
+ if (type() == Item::COND_ITEM)
+ {
+ bool cond_and= false;
+ Item_cond *new_cond;
+ if (((Item_cond*) this)->functype() == Item_func::COND_AND_FUNC)
+ {
+ cond_and= true;
+ new_cond= new (thd->mem_root) Item_cond_and(thd);
+ }
+ else
+ new_cond= new (thd->mem_root) Item_cond_or(thd);
+ if (!new_cond)
+ return 0;
+ List_iterator<Item> li(*((Item_cond*) this)->argument_list());
+ Item *item;
+ bool is_fix_needed= false;
+
+ while ((item=li++))
+ {
+ if (item->get_extraction_flag() == NO_EXTRACTION_FL)
+ {
+ if (!cond_and)
+ return 0;
+ continue;
+ }
+ Item *fix= item->build_pushable_cond(thd, checker, arg);
+ if (!fix && !cond_and)
+ return 0;
+ if (!fix)
+ continue;
+
+ if (fix->type() == Item::COND_ITEM &&
+ ((Item_cond*) fix)->functype() == Item_func::COND_AND_FUNC)
+ is_fix_needed= true;
+
+ if (new_cond->argument_list()->push_back(fix, thd->mem_root))
+ return 0;
+ }
+ if (is_fix_needed && new_cond->fix_fields(thd, 0))
+ return 0;
+
+ switch (new_cond->argument_list()->elements)
+ {
+ case 0:
+ return 0;
+ case 1:
+ return new_cond->argument_list()->head();
+ default:
+ return new_cond;
+ }
+ }
+ else if (is_multiple_equality)
+ {
+ Item *new_cond= NULL;
+ int i= 0;
+ Item_equal *item_equal= (Item_equal *) this;
+ Item *left_item = item_equal->get_const();
+ Item_equal_fields_iterator it(*item_equal);
+ Item *item;
+ Item *right_item;
+ if (!left_item)
+ {
+ while ((item=it++))
+ {
+ left_item= ((item->*checker) (arg)) ? item : NULL;
+ if (left_item)
+ break;
+ }
+ }
+ if (!left_item)
+ return 0;
+ while ((item=it++))
+ {
+ right_item= ((item->*checker) (arg)) ? item : NULL;
+ if (!right_item)
+ continue;
+ Item_func_eq *eq= 0;
+ Item *left_item_clone= left_item->build_clone(thd);
+ Item *right_item_clone= item->build_clone(thd);
+ if (left_item_clone && right_item_clone)
+ {
+ left_item_clone->set_item_equal(NULL);
+ right_item_clone->set_item_equal(NULL);
+ eq= new (thd->mem_root) Item_func_eq(thd, right_item_clone,
+ left_item_clone);
+ }
+ if (eq)
+ {
+ i++;
+ switch (i)
+ {
+ case 1:
+ new_cond= eq;
+ break;
+ case 2:
+ new_cond= new (thd->mem_root) Item_cond_and(thd, new_cond, eq);
+ break;
+ default:
+ if (((Item_cond_and*)new_cond)->argument_list()->push_back(eq,
+ thd->mem_root))
+ return 0;
+ break;
+ }
+ }
+ }
+ if (new_cond && new_cond->fix_fields(thd, &new_cond))
+ return 0;
+ return new_cond;
+ }
+ else if (get_extraction_flag() != NO_EXTRACTION_FL)
+ return build_clone(thd);
+ return 0;
+}
+
+
static
Item *get_field_item_for_having(THD *thd, Item *item, st_select_lex *sel)
{
@@ -7718,18 +7946,18 @@ Item *Item_direct_view_ref::derived_field_transformer_for_where(THD *thd,
}
static
-Grouping_tmp_field *find_matching_grouping_field(Item *item,
- st_select_lex *sel)
+Field_pair *find_matching_grouping_field(Item *item,
+ st_select_lex *sel)
{
DBUG_ASSERT(item->type() == Item::FIELD_ITEM ||
(item->type() == Item::REF_ITEM &&
((Item_ref *) item)->ref_type() == Item_ref::VIEW_REF));
- List_iterator<Grouping_tmp_field> li(sel->grouping_tmp_fields);
- Grouping_tmp_field *gr_field;
+ List_iterator<Field_pair> li(sel->grouping_tmp_fields);
+ Field_pair *gr_field;
Item_field *field_item= (Item_field *) (item->real_item());
while ((gr_field= li++))
{
- if (field_item->field == gr_field->tmp_field)
+ if (field_item->field == gr_field->field)
return gr_field;
}
Item_equal *item_equal= item->get_item_equal();
@@ -7743,7 +7971,7 @@ Grouping_tmp_field *find_matching_grouping_field(Item *item,
li.rewind();
while ((gr_field= li++))
{
- if (field_item->field == gr_field->tmp_field)
+ if (field_item->field == gr_field->field)
return gr_field;
}
}
@@ -7752,26 +7980,25 @@ Grouping_tmp_field *find_matching_grouping_field(Item *item,
}
-Item *Item_field::derived_grouping_field_transformer_for_where(THD *thd,
- uchar *arg)
+Item *Item_field::grouping_field_transformer_for_where(THD *thd, uchar *arg)
{
st_select_lex *sel= (st_select_lex *)arg;
- Grouping_tmp_field *gr_field= find_matching_grouping_field(this, sel);
+ Field_pair *gr_field= find_matching_grouping_field(this, sel);
if (gr_field)
- return gr_field->producing_item->build_clone(thd);
+ return gr_field->corresponding_item->build_clone(thd);
return this;
}
Item *
-Item_direct_view_ref::derived_grouping_field_transformer_for_where(THD *thd,
- uchar *arg)
+Item_direct_view_ref::grouping_field_transformer_for_where(THD *thd,
+ uchar *arg)
{
if (!item_equal)
return this;
st_select_lex *sel= (st_select_lex *)arg;
- Grouping_tmp_field *gr_field= find_matching_grouping_field(this, sel);
- return gr_field->producing_item->build_clone(thd);
+ Field_pair *gr_field= find_matching_grouping_field(this, sel);
+ return gr_field->corresponding_item->build_clone(thd);
}
void Item_field::print(String *str, enum_query_type query_type)
diff --git a/sql/item.h b/sql/item.h
index 10ce987e289..94f1f6abdb4 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -99,7 +99,9 @@ class sp_head;
class Protocol;
struct TABLE_LIST;
void item_init(void); /* Init item functions */
+class Item_result_field;
class Item_field;
+class Item_ref;
class Item_param;
class user_var_entry;
class JOIN;
@@ -595,6 +597,7 @@ typedef bool (Item::*Item_processor) (void *arg);
typedef bool (Item::*Item_analyzer) (uchar **argp);
typedef Item* (Item::*Item_transformer) (THD *thd, uchar *arg);
typedef void (*Cond_traverser) (const Item *item, void *arg);
+typedef bool (Item::*Pushdown_checker) (uchar *arg);
struct st_cond_statistic;
@@ -627,6 +630,71 @@ public:
String_copier_for_item(THD *thd): m_thd(thd) { }
};
+
+/**
+ A helper class describing what kind of Item created a temporary field.
+ - If m_field is set, then the temporary field was created from Field
+ (e.g. when the Item was Item_field, or Item_ref pointing to Item_field)
+ - If m_default_field is set, then there is a usable DEFAULT value.
+ (e.g. when the Item is Item_field)
+ - If m_item_result_field is set, then the temporary field was created
+ from certain sub-types of Item_result_field (e.g. Item_func)
+ See create_tmp_field() in sql_select.cc for details.
+*/
+
+class Tmp_field_src
+{
+ Field *m_field;
+ Field *m_default_field;
+ Item_result_field *m_item_result_field;
+public:
+ Tmp_field_src()
+ :m_field(0),
+ m_default_field(0),
+ m_item_result_field(0)
+ { }
+ Field *field() const { return m_field; }
+ Field *default_field() const { return m_default_field; }
+ Item_result_field *item_result_field() const { return m_item_result_field; }
+ void set_field(Field *field) { m_field= field; }
+ void set_default_field(Field *field) { m_default_field= field; }
+ void set_item_result_field(Item_result_field *item)
+ { m_item_result_field= item; }
+};
+
+
+/**
+ Parameters for create_tmp_field_ex().
+ See create_tmp_field() in sql_select.cc for details.
+*/
+
+class Tmp_field_param
+{
+ bool m_group;
+ bool m_modify_item;
+ bool m_table_cant_handle_bit_fields;
+ bool m_make_copy_field;
+public:
+ Tmp_field_param(bool group,
+ bool modify_item,
+ bool table_cant_handle_bit_fields,
+ bool make_copy_field)
+ :m_group(group),
+ m_modify_item(modify_item),
+ m_table_cant_handle_bit_fields(table_cant_handle_bit_fields),
+ m_make_copy_field(make_copy_field)
+ { }
+ bool group() const { return m_group; }
+ bool modify_item() const { return m_modify_item; }
+ bool table_cant_handle_bit_fields() const
+ { return m_table_cant_handle_bit_fields; }
+ bool make_copy_field() const { return m_make_copy_field; }
+ void set_modify_item(bool to) { m_modify_item= to; }
+};
+
+
+/****************************************************************************/
+
class Item: public Value_source,
public Type_all_attributes
{
@@ -659,7 +727,7 @@ public:
SUBSELECT_ITEM, ROW_ITEM, CACHE_ITEM, TYPE_HOLDER,
PARAM_ITEM, TRIGGER_FIELD_ITEM, DECIMAL_ITEM,
XPATH_NODESET, XPATH_NODESET_CMP,
- VIEW_FIXER_ITEM, EXPR_CACHE_ITEM,
+ EXPR_CACHE_ITEM,
DATE_ITEM};
enum cond_result { COND_UNDEF,COND_OK,COND_TRUE,COND_FALSE };
@@ -706,6 +774,24 @@ protected:
return h->make_and_init_table_field(&name, Record_addr(maybe_null),
*this, table);
}
+ /**
+ Create a temporary field for a simple Item, which does not
+ need any special action after the field creation:
+ - is not an Item_field descendant (and not a reference to Item_field)
+ - is not an Item_result_field descendant
+ - does not need to copy any DEFAULT value to the result Field
+ - does not need to set Field::is_created_from_null_item for the result
+ See create_tmp_field_ex() for details on parameters and return values.
+ */
+ Field *create_tmp_field_ex_simple(TABLE *table,
+ Tmp_field_src *src,
+ const Tmp_field_param *param)
+ {
+ DBUG_ASSERT(!param->make_copy_field());
+ DBUG_ASSERT(!is_result_field());
+ DBUG_ASSERT(type() != NULL_ITEM);
+ return tmp_table_field_from_field_type(table);
+ }
Field *create_tmp_field_int(TABLE *table, uint convert_int_length);
void push_note_converted_to_negative_complement(THD *thd);
@@ -882,6 +968,21 @@ public:
return type_handler()->field_type();
}
virtual const Type_handler *type_handler() const= 0;
+ /**
+ Detects if an Item has a fixed data type which is known
+ even before fix_fields().
+ Currently it's important only to find Items with a fixed boolean
+ data type. More item types can be marked in the future as having
+ a fixed data type (e.g. all literals, all fixed type functions, etc).
+
+ @retval NULL if the Item type is not known before fix_fields()
+ @retval the pointer to the data type handler, if the data type
+ is known before fix_fields().
+ */
+ virtual const Type_handler *fixed_type_handler() const
+ {
+ return NULL;
+ }
const Type_handler *type_handler_for_comparison() const
{
return type_handler()->type_handler_for_comparison();
@@ -1304,6 +1405,14 @@ public:
a constant expression. Used in the optimizer to propagate basic constants.
*/
virtual bool basic_const_item() const { return 0; }
+ /*
+ Test if "this" is an ORDER position (rather than an expression).
+ Notes:
+ - can be called before fix_fields().
+ - local SP variables (even of integer types) are always expressions, not
+ positions. (And they can't be used before fix_fields is called for them).
+ */
+ virtual bool is_order_clause_position() const { return false; }
/* cloning of constant items (0 if it is not const) */
virtual Item *clone_item(THD *thd) { return 0; }
virtual Item* build_clone(THD *thd) { return get_copy(thd); }
@@ -1588,10 +1697,9 @@ public:
set field of temporary table for Item which can be switched on temporary
table during query processing (grouping and so on)
*/
- virtual void set_result_field(Field *field) {}
virtual bool is_result_field() { return 0; }
- virtual bool is_bool_type() { return false; }
virtual bool is_json_type() { return false; }
+ virtual bool is_bool_literal() const { return false; }
/* This is to handle printing of default values */
virtual bool need_parentheses_in_default() { return false; }
virtual void save_in_result_field(bool no_conversions) {}
@@ -1697,7 +1805,15 @@ public:
or can be converted to such an exression using equalities.
Not to be used for AND/OR formulas.
*/
- virtual bool excl_dep_on_grouping_fields(st_select_lex *sel) { return false; }
+ virtual bool excl_dep_on_grouping_fields(st_select_lex *sel)
+ { return false; }
+ /*
+ TRUE if the expression depends only on fields from the left part of
+ IN subquery or can be converted to such an expression using equalities.
+ Not to be used for AND/OR formulas.
+ */
+ virtual bool excl_dep_on_in_subq_left_part(Item_in_subselect *subq_pred)
+ { return false; }
virtual bool switch_to_nullable_fields_processor(void *arg) { return 0; }
virtual bool find_function_processor (void *arg) { return 0; }
@@ -1857,11 +1973,17 @@ public:
return Type_handler::type_handler_long_or_longlong(max_char_length());
}
- virtual Field *create_tmp_field(bool group, TABLE *table)
- {
- return tmp_table_field_from_field_type(table);
- }
-
+ /**
+ Create field for temporary table.
+ @param table Temporary table
+ @param [OUT] src Who created the fields
+ @param param Create parameters
+ @retval NULL (on error)
+ @retval a pointer to a newly create Field (on success)
+ */
+ virtual Field *create_tmp_field_ex(TABLE *table,
+ Tmp_field_src *src,
+ const Tmp_field_param *param)= 0;
virtual Item_field *field_for_view_update() { return 0; }
virtual Item *neg_transformer(THD *thd) { return NULL; }
@@ -1873,8 +1995,12 @@ public:
{ return this; }
virtual Item *derived_field_transformer_for_where(THD *thd, uchar *arg)
{ return this; }
- virtual Item *derived_grouping_field_transformer_for_where(THD *thd,
- uchar *arg)
+ virtual Item *grouping_field_transformer_for_where(THD *thd, uchar *arg)
+ { return this; }
+ /* Now is not used. */
+ virtual Item *in_subq_field_transformer_for_where(THD *thd, uchar *arg)
+ { return this; }
+ virtual Item *in_subq_field_transformer_for_having(THD *thd, uchar *arg)
{ return this; }
virtual Item *in_predicate_to_in_subs_transformer(THD *thd, uchar *arg)
{ return this; }
@@ -2071,6 +2197,33 @@ public:
{
marker &= ~EXTRACTION_MASK;
}
+ void check_pushable_cond(Pushdown_checker excl_dep_func, uchar *arg);
+ bool pushable_cond_checker_for_derived(uchar *arg)
+ {
+ return excl_dep_on_table(*((table_map *)arg));
+ }
+ bool pushable_cond_checker_for_subquery(uchar *arg)
+ {
+ return excl_dep_on_in_subq_left_part((Item_in_subselect *)arg);
+ }
+ Item *get_corresponding_field_in_insubq(Item_in_subselect *subq_pred);
+ Item *build_pushable_cond(THD *thd,
+ Pushdown_checker checker,
+ uchar *arg);
+ /*
+ Checks if this item depends only on the arg table
+ */
+ bool pushable_equality_checker_for_derived(uchar *arg)
+ {
+ return (used_tables() == *((table_map *)arg));
+ }
+ /*
+ Checks if this item consists in the left part of arg IN subquery predicate
+ */
+ bool pushable_equality_checker_for_subquery(uchar *arg)
+ {
+ return get_corresponding_field_in_insubq((Item_in_subselect *)arg);
+ }
};
MEM_ROOT *get_thd_memroot(THD *thd);
@@ -2199,6 +2352,17 @@ protected:
}
return true;
}
+ bool excl_dep_on_in_subq_left_part(Item_in_subselect *subq_pred)
+ {
+ for (uint i= 0; i < arg_count; i++)
+ {
+ if (args[i]->const_item())
+ continue;
+ if (!args[i]->excl_dep_on_in_subq_left_part(subq_pred))
+ return false;
+ }
+ return true;
+ }
public:
Item_args(void)
:args(NULL), arg_count(0)
@@ -2370,16 +2534,15 @@ protected:
value == ((Item_basic_value*)item)->val_int() &&
(value >= 0 || item->unsigned_flag == unsigned_flag);
}
+ Field *create_tmp_field_ex(TABLE *table, Tmp_field_src *src,
+ const Tmp_field_param *param);
};
class Item_basic_constant :public Item_basic_value
{
- table_map used_table_map;
public:
- Item_basic_constant(THD *thd): Item_basic_value(thd), used_table_map(0) {};
- void set_used_tables(table_map map) { used_table_map= map; }
- table_map used_tables() const { return used_table_map; }
+ Item_basic_constant(THD *thd): Item_basic_value(thd) {};
bool check_vcol_func_processor(void *arg) { return FALSE;}
virtual Item_basic_constant *make_string_literal_concat(THD *thd,
const LEX_CSTRING *)
@@ -2451,6 +2614,11 @@ public:
inline bool const_item() const;
+ Field *create_tmp_field_ex(TABLE *table, Tmp_field_src *src,
+ const Tmp_field_param *param)
+ {
+ return create_tmp_field_ex_simple(table, src, param);
+ }
inline int save_in_field(Field *field, bool no_conversions);
inline bool send(Protocol *protocol, st_value *buffer);
bool check_vcol_func_processor(void *arg)
@@ -2554,6 +2722,20 @@ public:
*/
Field *create_field_for_create_select(TABLE *table)
{ return create_table_field_from_handler(table); }
+
+ bool is_valid_limit_clause_variable_with_error() const
+ {
+ /*
+ In case if the variable has an anchored data type, e.g.:
+ DECLARE a TYPE OF t1.a;
+ type_handler() is set to &type_handler_null and this
+ function detects such variable as not valid in LIMIT.
+ */
+ if (type_handler()->is_limit_clause_valid_type())
+ return true;
+ my_error(ER_WRONG_SPVAR_TYPE_IN_LIMIT, MYF(0));
+ return false;
+ }
};
@@ -2729,6 +2911,16 @@ public:
return TRUE;
}
+ Field *create_tmp_field_ex(TABLE *table, Tmp_field_src *src,
+ const Tmp_field_param *param)
+ {
+ /*
+ We can get to here when using a CURSOR for a query with NAME_CONST():
+ DECLARE c CURSOR FOR SELECT NAME_CONST('x','y') FROM t1;
+ OPEN c;
+ */
+ return create_tmp_field_ex_simple(table, src, param);
+ }
int save_in_field(Field *field, bool no_conversions)
{
return value_item->save_in_field(field, no_conversions);
@@ -2774,13 +2966,15 @@ public:
{}
~Item_result_field() {} /* Required with gcc 2.95 */
Field *get_tmp_table_field() { return result_field; }
+ Field *create_tmp_field_ex(TABLE *table, Tmp_field_src *src,
+ const Tmp_field_param *param);
+ void get_tmp_field_src(Tmp_field_src *src, const Tmp_field_param *param);
/*
This implementation of used_tables() used by Item_avg_field and
Item_variance_field which work when only temporary table left, so theu
return table map of the temporary table.
*/
table_map used_tables() const { return 1; }
- void set_result_field(Field *field) { result_field= field; }
bool is_result_field() { return true; }
void save_in_result_field(bool no_conversions)
{
@@ -2873,6 +3067,12 @@ public:
Type_std_attributes::set(par_field->type_std_attributes());
}
enum Type type() const { return FIELD_ITEM; }
+ Field *create_tmp_field_ex(TABLE *table, Tmp_field_src *src,
+ const Tmp_field_param *param)
+ {
+ DBUG_ASSERT(0);
+ return 0;
+ }
double val_real() { return field->val_real(); }
longlong val_int() { return field->val_int(); }
String *val_str(String *str) { return field->val_str(str); }
@@ -2988,6 +3188,11 @@ public:
return &type_handler_null;
return field->type_handler();
}
+ Field *create_tmp_field_from_item_field(TABLE *new_table,
+ Item_ref *orig_item,
+ const Tmp_field_param *param);
+ Field *create_tmp_field_ex(TABLE *table, Tmp_field_src *src,
+ const Tmp_field_param *param);
TYPELIB *get_typelib() const { return field->get_typelib(); }
enum_monotonicity_info get_monotonicity_info() const
{
@@ -3005,13 +3210,7 @@ public:
TABLE *tab= field->table;
tab->covering_keys.intersect(field->part_of_key);
if (tab->read_set)
- bitmap_fast_test_and_set(tab->read_set, field->field_index);
- /*
- Do not mark a self-referecing virtual column.
- Such virtual columns are reported as invalid.
- */
- if (field->vcol_info && tab->vcol_set)
- tab->mark_virtual_col(field);
+ tab->mark_column_with_deps(field);
}
}
void update_used_tables()
@@ -3088,10 +3287,13 @@ public:
virtual Item *update_value_transformer(THD *thd, uchar *select_arg);
Item *derived_field_transformer_for_having(THD *thd, uchar *arg);
Item *derived_field_transformer_for_where(THD *thd, uchar *arg);
- Item *derived_grouping_field_transformer_for_where(THD *thd, uchar *arg);
+ Item *grouping_field_transformer_for_where(THD *thd, uchar *arg);
+ Item *in_subq_field_transformer_for_where(THD *thd, uchar *arg);
+ Item *in_subq_field_transformer_for_having(THD *thd, uchar *arg);
virtual void print(String *str, enum_query_type query_type);
bool excl_dep_on_table(table_map tab_map);
bool excl_dep_on_grouping_fields(st_select_lex *sel);
+ bool excl_dep_on_in_subq_left_part(Item_in_subselect *subq_pred);
bool cleanup_excluding_fields_processor(void *arg)
{ return field ? 0 : cleanup_processor(arg); }
bool cleanup_excluding_const_fields_processor(void *arg)
@@ -3237,6 +3439,12 @@ public:
{
return result_field->type();
}
+ Field *create_tmp_field_ex(TABLE *table, Tmp_field_src *src,
+ const Tmp_field_param *param)
+ {
+ DBUG_ASSERT(0);
+ return NULL;
+ }
void save_in_result_field(bool no_conversions)
{
save_in_field(result_field, no_conversions);
@@ -3462,6 +3670,13 @@ public:
return item_type;
}
+ bool is_order_clause_position() const
+ {
+ DBUG_ASSERT(fixed || state == NO_VALUE);
+ return state == SHORT_DATA_VALUE &&
+ type_handler()->is_order_clause_position_type();
+ }
+
double val_real()
{
return can_return_value() ? value.val_real() : 0e0;
@@ -3655,8 +3870,6 @@ public:
enum Type type() const { return INT_ITEM; }
const Type_handler *type_handler() const
{ return type_handler_long_or_longlong(); }
- Field *create_tmp_field(bool group, TABLE *table)
- { return tmp_table_field_from_field_type(table); }
Field *create_field_for_create_select(TABLE *table)
{ return tmp_table_field_from_field_type(table); }
longlong val_int() { DBUG_ASSERT(fixed == 1); return value; }
@@ -3666,6 +3879,7 @@ public:
String *val_str(String*);
int save_in_field(Field *field, bool no_conversions);
bool basic_const_item() const { return 1; }
+ bool is_order_clause_position() const { return true; }
Item *clone_item(THD *thd);
virtual void print(String *str, enum_query_type query_type);
Item *neg(THD *thd);
@@ -3688,8 +3902,13 @@ class Item_bool :public Item_int
public:
Item_bool(THD *thd, const char *str_arg, longlong i):
Item_int(thd, str_arg, i, 1) {}
- bool is_bool_type() { return true; }
+ Item_bool(THD *thd, bool i) :Item_int(thd, (longlong) i, 1) { }
+ bool is_bool_literal() const { return true; }
Item *neg_transformer(THD *thd);
+ const Type_handler *type_handler() const
+ { return &type_handler_bool; }
+ const Type_handler *fixed_type_handler() const
+ { return &type_handler_bool; }
};
@@ -4785,6 +5004,8 @@ public:
Field *get_tmp_table_field()
{ return result_field ? result_field : (*ref)->get_tmp_table_field(); }
Item *get_tmp_table_item(THD *thd);
+ Field *create_tmp_field_ex(TABLE *table, Tmp_field_src *src,
+ const Tmp_field_param *param);
table_map used_tables() const;
void update_used_tables();
COND *build_equal_items(THD *thd, COND_EQUAL *inherited,
@@ -4914,6 +5135,8 @@ public:
}
bool excl_dep_on_grouping_fields(st_select_lex *sel)
{ return (*ref)->excl_dep_on_grouping_fields(sel); }
+ bool excl_dep_on_in_subq_left_part(Item_in_subselect *subq_pred)
+ { return (*ref)->excl_dep_on_in_subq_left_part(subq_pred); }
bool cleanup_excluding_fields_processor(void *arg)
{
Item *item= real_item();
@@ -5220,10 +5443,12 @@ public:
}
bool excl_dep_on_table(table_map tab_map);
bool excl_dep_on_grouping_fields(st_select_lex *sel);
+ bool excl_dep_on_in_subq_left_part(Item_in_subselect *subq_pred);
Item *derived_field_transformer_for_having(THD *thd, uchar *arg);
Item *derived_field_transformer_for_where(THD *thd, uchar *arg);
- Item *derived_grouping_field_transformer_for_where(THD *thd,
- uchar *arg);
+ Item *grouping_field_transformer_for_where(THD *thd, uchar *arg);
+ Item *in_subq_field_transformer_for_where(THD *thd, uchar *arg);
+ Item *in_subq_field_transformer_for_having(THD *thd, uchar *arg);
void save_val(Field *to)
{
@@ -5522,6 +5747,12 @@ public:
const Type_handler *type_handler() const
{ return Type_handler_hybrid_field_type::type_handler(); }
+ Field *create_tmp_field_ex(TABLE *table, Tmp_field_src *src,
+ const Tmp_field_param *param)
+ {
+ DBUG_ASSERT(0);
+ return NULL;
+ }
void make_send_field(THD *thd, Send_field *field)
{ item->make_send_field(thd, field); }
table_map used_tables() const { return (table_map) 1L; }
@@ -6023,12 +6254,15 @@ protected:
cache_value() will set this flag to TRUE.
*/
bool value_cached;
+
+ table_map used_table_map;
public:
Item_cache(THD *thd):
Item_basic_constant(thd),
Type_handler_hybrid_field_type(&type_handler_string),
example(0), cached_field(0),
- value_cached(0)
+ value_cached(0),
+ used_table_map(0)
{
fixed= 1;
maybe_null= 1;
@@ -6039,7 +6273,8 @@ protected:
Item_basic_constant(thd),
Type_handler_hybrid_field_type(handler),
example(0), cached_field(0),
- value_cached(0)
+ value_cached(0),
+ used_table_map(0)
{
fixed= 1;
maybe_null= 1;
@@ -6056,6 +6291,9 @@ public:
cached_field= ((Item_field *)item)->field;
return 0;
};
+
+ void set_used_tables(table_map map) { used_table_map= map; }
+ table_map used_tables() const { return used_table_map; }
enum Type type() const { return CACHE_ITEM; }
const Type_handler *type_handler() const
@@ -6142,7 +6380,11 @@ public:
{ return convert_to_basic_const_item(thd); }
Item *derived_field_transformer_for_where(THD *thd, uchar *arg)
{ return convert_to_basic_const_item(thd); }
- Item *derived_grouping_field_transformer_for_where(THD *thd, uchar *arg)
+ Item *grouping_field_transformer_for_where(THD *thd, uchar *arg)
+ { return convert_to_basic_const_item(thd); }
+ Item *in_subq_field_transformer_for_where(THD *thd, uchar *arg)
+ { return convert_to_basic_const_item(thd); }
+ Item *in_subq_field_transformer_for_having(THD *thd, uchar *arg)
{ return convert_to_basic_const_item(thd); }
};
@@ -6465,7 +6707,8 @@ public:
my_decimal *val_decimal(my_decimal *);
String *val_str(String*);
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate);
- Field *create_tmp_field(bool group, TABLE *table)
+ Field *create_tmp_field_ex(TABLE *table, Tmp_field_src *src,
+ const Tmp_field_param *param)
{
return Item_type_holder::real_type_handler()->
make_and_init_table_field(&name, Record_addr(maybe_null),
@@ -6605,4 +6848,39 @@ inline void Virtual_column_info::print(String* str)
expr->print_for_table_def(str);
}
+inline bool TABLE::mark_column_with_deps(Field *field)
+{
+ bool res;
+ if (!(res= bitmap_fast_test_and_set(read_set, field->field_index)))
+ {
+ if (field->vcol_info)
+ mark_virtual_column_deps(field);
+ }
+ return res;
+}
+
+inline bool TABLE::mark_virtual_column_with_deps(Field *field)
+{
+ bool res;
+ DBUG_ASSERT(field->vcol_info);
+ if (!(res= bitmap_fast_test_and_set(read_set, field->field_index)))
+ mark_virtual_column_deps(field);
+ return res;
+}
+
+inline void TABLE::mark_virtual_column_deps(Field *field)
+{
+ DBUG_ASSERT(field->vcol_info);
+ DBUG_ASSERT(field->vcol_info->expr);
+ field->vcol_info->expr->walk(&Item::register_field_in_read_map, 1, 0);
+}
+
+inline void TABLE::use_all_stored_columns()
+{
+ bitmap_set_all(read_set);
+ if (Field **vf= vfield)
+ for (; *vf; vf++)
+ bitmap_clear_bit(read_set, (*vf)->field_index);
+}
+
#endif /* SQL_ITEM_INCLUDED */
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index 30d682f05aa..1cdc48c8962 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -215,8 +215,8 @@ public:
Item_bool_func(THD *thd, Item *a, Item *b, Item *c): Item_int_func(thd, a, b, c) {}
Item_bool_func(THD *thd, List<Item> &list): Item_int_func(thd, list) { }
Item_bool_func(THD *thd, Item_bool_func *item) :Item_int_func(thd, item) {}
- const Type_handler *type_handler() const { return &type_handler_long; }
- bool is_bool_type() { return true; }
+ const Type_handler *type_handler() const { return &type_handler_bool; }
+ const Type_handler *fixed_type_handler() const { return &type_handler_bool; }
virtual CHARSET_INFO *compare_collation() const { return NULL; }
void fix_length_and_dec() { decimals=0; max_length=1; }
uint decimal_precision() const { return 1; }
@@ -1272,7 +1272,11 @@ public:
{ reset_first_arg_if_needed(); return this; }
Item *derived_field_transformer_for_where(THD *thd, uchar *arg)
{ reset_first_arg_if_needed(); return this; }
- Item *derived_grouping_field_transformer_for_where(THD *thd, uchar *arg)
+ Item *grouping_field_transformer_for_where(THD *thd, uchar *arg)
+ { reset_first_arg_if_needed(); return this; }
+ Item *in_subq_field_transformer_for_where(THD *thd, uchar *arg)
+ { reset_first_arg_if_needed(); return this; }
+ Item *in_subq_field_transformer_for_having(THD *thd, uchar *arg)
{ reset_first_arg_if_needed(); return this; }
};
@@ -3135,6 +3139,8 @@ public:
{
return used_tables() & tab_map;
}
+ bool excl_dep_on_in_subq_left_part(Item_in_subselect *subq_pred);
+
friend class Item_equal_fields_iterator;
bool count_sargable_conds(void *arg);
friend class Item_equal_iterator<List_iterator_fast,Item>;
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 567c813de3c..5567e733288 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -3723,7 +3723,7 @@ longlong Item_master_pos_wait::val_int()
connection_name.length= con->length();
if (check_master_connection_name(&connection_name))
{
- my_error(ER_WRONG_ARGUMENTS, MYF(ME_JUST_WARNING),
+ my_error(ER_WRONG_ARGUMENTS, MYF(ME_WARNING),
"MASTER_CONNECTION_NAME");
goto err;
}
@@ -4434,7 +4434,7 @@ user_var_entry *get_variable(HASH *hash, LEX_CSTRING *name,
if (!my_hash_inited(hash))
return 0;
if (!(entry = (user_var_entry*) my_malloc(size,
- MYF(MY_WME | ME_FATALERROR |
+ MYF(MY_WME | ME_FATAL |
MY_THREAD_SPECIFIC))))
return 0;
entry->name.str=(char*) entry+ ALIGN_SIZE(sizeof(user_var_entry))+
@@ -4688,7 +4688,7 @@ update_hash(user_var_entry *entry, bool set_null, void *ptr, size_t length,
entry->value=0;
entry->value= (char*) my_realloc(entry->value, length,
MYF(MY_ALLOW_ZERO_PTR | MY_WME |
- ME_FATALERROR |
+ ME_FATAL |
MY_THREAD_SPECIFIC));
if (!entry->value)
return 1;
diff --git a/sql/item_func.h b/sql/item_func.h
index 049ef82f71e..a6fcf8f4870 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -335,6 +335,11 @@ public:
return Item_args::excl_dep_on_grouping_fields(sel);
}
+ bool excl_dep_on_in_subq_left_part(Item_in_subselect *subq_pred)
+ {
+ return Item_args::excl_dep_on_in_subq_left_part(subq_pred);
+ }
+
/*
We assume the result of any function that has a TIMESTAMP argument to be
timezone-dependent, since a TIMESTAMP value in both numeric and string
@@ -2359,8 +2364,8 @@ public:
Item_func_user_var(THD *thd, Item_func_user_var *item)
:Item_hybrid_func(thd, item),
m_var_entry(item->m_var_entry), name(item->name) { }
- Field *create_tmp_field(bool group, TABLE *table)
- { return create_table_field_from_handler(table); }
+ Field *create_tmp_field_ex(TABLE *table, Tmp_field_src *src,
+ const Tmp_field_param *param);
Field *create_field_for_create_select(TABLE *table)
{ return create_table_field_from_handler(table); }
bool check_vcol_func_processor(void *arg);
@@ -2535,6 +2540,12 @@ public:
{
return 0;
}
+ Field *create_tmp_field_ex(TABLE *table, Tmp_field_src *src,
+ const Tmp_field_param *param)
+ {
+ DBUG_ASSERT(0);
+ return NULL;
+ }
/* We should return something different from FIELD_ITEM here */
enum Type type() const { return STRING_ITEM;}
double val_real();
@@ -2840,6 +2851,8 @@ public:
const Type_handler *type_handler() const;
+ Field *create_tmp_field_ex(TABLE *table, Tmp_field_src *src,
+ const Tmp_field_param *param);
Field *create_field_for_create_select(TABLE *table)
{
return result_type() != STRING_RESULT ?
diff --git a/sql/item_jsonfunc.cc b/sql/item_jsonfunc.cc
index e67357000da..a45baec8e92 100644
--- a/sql/item_jsonfunc.cc
+++ b/sql/item_jsonfunc.cc
@@ -1397,7 +1397,7 @@ null_return:
static int append_json_value(String *str, Item *item, String *tmp_val)
{
- if (item->is_bool_type())
+ if (item->type_handler()->is_bool_type())
{
longlong v_int= item->val_int();
const char *t_f;
diff --git a/sql/item_row.h b/sql/item_row.h
index e0d54403730..73b198625ce 100644
--- a/sql/item_row.h
+++ b/sql/item_row.h
@@ -56,6 +56,11 @@ public:
bool with_subquery() const { DBUG_ASSERT(fixed); return m_with_subquery; }
enum Type type() const { return ROW_ITEM; };
const Type_handler *type_handler() const { return &type_handler_row; }
+ Field *create_tmp_field_ex(TABLE *table, Tmp_field_src *src,
+ const Tmp_field_param *param)
+ {
+ return NULL; // Check with Vicentiu why it's called for Item_row
+ }
void illegal_method_call(const char *);
bool is_null() { return null_value; }
void make_send_field(THD *thd, Send_field *)
@@ -134,6 +139,11 @@ public:
return Item_args::excl_dep_on_grouping_fields(sel);
}
+ bool excl_dep_on_in_subq_left_part(Item_in_subselect *subq_pred)
+ {
+ return Item_args::excl_dep_on_in_subq_left_part(subq_pred);
+ }
+
bool check_vcol_func_processor(void *arg) {return FALSE; }
Item *get_copy(THD *thd)
{ return get_item_copy<Item_row>(thd, this); }
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index 4280a67e356..048ec6a4fa1 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -5783,14 +5783,14 @@ Ordered_key::cmp_keys_by_row_data(ha_rows a, ha_rows b)
if (unlikely((error= tbl->file->ha_rnd_pos(tbl->record[0], rowid_a))))
{
/* purecov: begin inspected */
- tbl->file->print_error(error, MYF(ME_FATALERROR)); // Sets fatal_error
+ tbl->file->print_error(error, MYF(ME_FATAL)); // Sets fatal_error
return 0;
/* purecov: end */
}
if (unlikely((error= tbl->file->ha_rnd_pos(tbl->record[1], rowid_b))))
{
/* purecov: begin inspected */
- tbl->file->print_error(error, MYF(ME_FATALERROR)); // Sets fatal_error
+ tbl->file->print_error(error, MYF(ME_FATAL)); // Sets fatal_error
return 0;
/* purecov: end */
}
@@ -5872,7 +5872,7 @@ int Ordered_key::cmp_key_with_search_key(rownum_t row_num)
if (unlikely((error= tbl->file->ha_rnd_pos(tbl->record[0], cur_rowid))))
{
/* purecov: begin inspected */
- tbl->file->print_error(error, MYF(ME_FATALERROR)); // Sets fatal_error
+ tbl->file->print_error(error, MYF(ME_FATAL)); // Sets fatal_error
return 0;
/* purecov: end */
}
diff --git a/sql/item_subselect.h b/sql/item_subselect.h
index dfe3287615b..fa5cbe8c424 100644
--- a/sql/item_subselect.h
+++ b/sql/item_subselect.h
@@ -33,6 +33,7 @@ class subselect_hash_sj_engine;
class Item_bool_func2;
class Comp_creator;
class With_element;
+class Field_pair;
typedef class st_select_lex SELECT_LEX;
@@ -570,6 +571,8 @@ public:
*/
bool is_registered_semijoin;
+ List<Field_pair> corresponding_fields;
+
/*
Used to determine how this subselect item is represented in the item tree,
in case there is a need to locate it there and replace with something else.
@@ -741,6 +744,8 @@ public:
return 0;
};
+ bool pushdown_cond_for_in_subquery(THD *thd, Item *cond);
+
friend class Item_ref_null_helper;
friend class Item_is_not_null_test;
friend class Item_in_optimizer;
@@ -852,7 +857,6 @@ protected:
void set_row(List<Item> &item_list, Item_cache **row);
};
-
class subselect_single_select_engine: public subselect_engine
{
bool prepared; /* simple subselect is prepared */
@@ -886,9 +890,10 @@ public:
friend class subselect_hash_sj_engine;
friend class Item_in_subselect;
- friend bool setup_jtbm_semi_joins(JOIN *join, List<TABLE_LIST> *join_list,
- Item **join_where);
-
+ friend bool execute_degenerate_jtbm_semi_join(THD *thd,
+ TABLE_LIST *tbl,
+ Item_in_subselect *subq_pred,
+ List<Item> &eq_list);
};
diff --git a/sql/item_sum.cc b/sql/item_sum.cc
index a47f3ad941d..c206e71ed9a 100644
--- a/sql/item_sum.cc
+++ b/sql/item_sum.cc
@@ -1236,9 +1236,11 @@ Field *Item_sum_hybrid::create_tmp_field(bool group, TABLE *table)
if (args[0]->type() == Item::FIELD_ITEM)
{
Field *field= ((Item_field*) args[0])->field;
- if ((field= create_tmp_field_from_field(table->in_use, field, &name,
- table, NULL)))
- field->flags&= ~NOT_NULL_FLAG;
+ if ((field= field->create_tmp_field(table->in_use->mem_root, table, true)))
+ {
+ DBUG_ASSERT((field->flags & NOT_NULL_FLAG) == 0);
+ field->field_name= name;
+ }
DBUG_RETURN(field);
}
DBUG_RETURN(tmp_table_field_from_field_type(table));
diff --git a/sql/item_sum.h b/sql/item_sum.h
index b66f6ab6143..b0dea818f01 100644
--- a/sql/item_sum.h
+++ b/sql/item_sum.h
@@ -510,7 +510,12 @@ public:
}
virtual void make_unique() { force_copy_fields= TRUE; }
Item *get_tmp_table_item(THD *thd);
- Field *create_tmp_field(bool group, TABLE *table);
+ virtual Field *create_tmp_field(bool group, TABLE *table);
+ Field *create_tmp_field_ex(TABLE *table, Tmp_field_src *src,
+ const Tmp_field_param *param)
+ {
+ return create_tmp_field(param->group(), table);
+ }
virtual bool collect_outer_ref_processor(void *param);
bool init_sum_func_check(THD *thd);
bool check_sum_func(THD *thd, Item **ref);
@@ -1383,6 +1388,11 @@ public:
fixed= true;
}
table_map used_tables() const { return (table_map) 1L; }
+ Field *create_tmp_field_ex(TABLE *table, Tmp_field_src *src,
+ const Tmp_field_param *param)
+ {
+ return create_tmp_field_ex_simple(table, src, param);
+ }
void save_in_result_field(bool no_conversions) { DBUG_ASSERT(0); }
bool check_vcol_func_processor(void *arg)
{
diff --git a/sql/item_xmlfunc.cc b/sql/item_xmlfunc.cc
index 63cc07fa34c..b38e06b3778 100644
--- a/sql/item_xmlfunc.cc
+++ b/sql/item_xmlfunc.cc
@@ -187,6 +187,12 @@ public:
nodeset->length(0);
}
enum Type type() const { return XPATH_NODESET; }
+ Field *create_tmp_field_ex(TABLE *table, Tmp_field_src *src,
+ const Tmp_field_param *param)
+ {
+ DBUG_ASSERT(0);
+ return NULL;
+ }
String *val_str(String *str)
{
prepare_nodes();
@@ -592,7 +598,12 @@ public:
{
return mark_unsupported_function(func_name(), arg, VCOL_IMPOSSIBLE);
}
-
+ Field *create_tmp_field_ex(TABLE *table, Tmp_field_src *src,
+ const Tmp_field_param *param)
+ {
+ DBUG_ASSERT(0);
+ return NULL;
+ }
longlong val_int()
{
Item_func *comp= (Item_func*)args[1];
@@ -844,7 +855,9 @@ String *Item_nodeset_func_elementbyindex::val_nodeset(String *nodeset)
flt->pos,
size);
int index= (int) (args[1]->val_int()) - 1;
- if (index >= 0 && (flt->pos == (uint) index || args[1]->is_bool_type()))
+ if (index >= 0 &&
+ (flt->pos == (uint) index ||
+ (args[1]->type_handler()->is_bool_type())))
((XPathFilter*)nodeset)->append_element(flt->num, pos++);
}
return nodeset;
@@ -1792,7 +1805,8 @@ my_xpath_parse_AxisSpecifier_NodeTest_opt_Predicate_list(MY_XPATH *xpath)
xpath->item= nodeset2bool(xpath, xpath->item);
- if (xpath->item->is_bool_type())
+ const Type_handler *fh;
+ if ((fh= xpath->item->fixed_type_handler()) && fh->is_bool_type())
{
xpath->context= new (xpath->thd->mem_root)
Item_nodeset_func_predicate(xpath->thd, prev_context,
diff --git a/sql/log.cc b/sql/log.cc
index ff4b0366b43..afd6c90e386 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -2181,16 +2181,16 @@ void MYSQL_BIN_LOG::set_write_error(THD *thd, bool is_transactional)
{
if (is_transactional)
{
- my_message(ER_TRANS_CACHE_FULL, ER_THD(thd, ER_TRANS_CACHE_FULL), MYF(MY_WME));
+ my_message(ER_TRANS_CACHE_FULL, ER_THD(thd, ER_TRANS_CACHE_FULL), MYF(0));
}
else
{
- my_message(ER_STMT_CACHE_FULL, ER_THD(thd, ER_STMT_CACHE_FULL), MYF(MY_WME));
+ my_message(ER_STMT_CACHE_FULL, ER_THD(thd, ER_STMT_CACHE_FULL), MYF(0));
}
}
else
{
- my_error(ER_ERROR_ON_WRITE, MYF(MY_WME), name, errno);
+ my_error(ER_ERROR_ON_WRITE, MYF(0), name, errno);
}
DBUG_VOID_RETURN;
@@ -2647,7 +2647,7 @@ bool MYSQL_LOG::open(
#endif
if ((file= mysql_file_open(log_file_key, log_file_name, open_flags,
- MYF(MY_WME | ME_WAITTANG))) < 0)
+ MYF(MY_WME))) < 0)
goto err;
if (is_fifo)
@@ -2789,7 +2789,7 @@ int MYSQL_LOG::generate_new_name(char *new_name, const char *log_name,
{
THD *thd= current_thd;
if (unlikely(thd))
- my_error(ER_NO_UNIQUE_LOGFILE, MYF(ME_FATALERROR), log_name);
+ my_error(ER_NO_UNIQUE_LOGFILE, MYF(ME_FATAL), log_name);
sql_print_error(ER_DEFAULT(ER_NO_UNIQUE_LOGFILE), log_name);
return 1;
}
@@ -4625,7 +4625,7 @@ int MYSQL_BIN_LOG::open_purge_index_file(bool destroy)
if (!my_b_inited(&purge_index_file))
{
if ((file= my_open(purge_index_file_name, O_RDWR | O_CREAT | O_BINARY,
- MYF(MY_WME | ME_WAITTANG))) < 0 ||
+ MYF(MY_WME))) < 0 ||
init_io_cache(&purge_index_file, file, IO_SIZE,
(destroy ? WRITE_CACHE : READ_CACHE),
0, 0, MYF(MY_WME | MY_NABP | MY_WAIT_IF_FULL)))
@@ -5194,7 +5194,7 @@ int MYSQL_BIN_LOG::new_file_impl(bool need_lock)
close_on_error= TRUE;
my_printf_error(ER_ERROR_ON_WRITE,
ER_THD_OR_DEFAULT(current_thd, ER_CANT_OPEN_FILE),
- MYF(ME_FATALERROR), name, errno);
+ MYF(ME_FATAL), name, errno);
goto end;
}
bytes_written += r.data_written;
@@ -5263,7 +5263,7 @@ int MYSQL_BIN_LOG::new_file_impl(bool need_lock)
/* handle reopening errors */
if (unlikely(error))
{
- my_error(ER_CANT_OPEN_FILE, MYF(ME_FATALERROR), file_to_open, error);
+ my_error(ER_CANT_OPEN_FILE, MYF(ME_FATAL), file_to_open, error);
close_on_error= TRUE;
}
@@ -7745,10 +7745,10 @@ MYSQL_BIN_LOG::write_transaction_to_binlog_events(group_commit_entry *entry)
switch (entry->error)
{
case ER_ERROR_ON_WRITE:
- my_error(ER_ERROR_ON_WRITE, MYF(ME_NOREFRESH), name, entry->commit_errno);
+ my_error(ER_ERROR_ON_WRITE, MYF(ME_ERROR_LOG), name, entry->commit_errno);
break;
case ER_ERROR_ON_READ:
- my_error(ER_ERROR_ON_READ, MYF(ME_NOREFRESH),
+ my_error(ER_ERROR_ON_READ, MYF(ME_ERROR_LOG),
entry->error_cache->file_name, entry->commit_errno);
break;
default:
@@ -7759,7 +7759,7 @@ MYSQL_BIN_LOG::write_transaction_to_binlog_events(group_commit_entry *entry)
*/
my_printf_error(entry->error,
"Error writing transaction to binary log: %d",
- MYF(ME_NOREFRESH), entry->error);
+ MYF(ME_ERROR_LOG), entry->error);
}
/*
@@ -7982,7 +7982,7 @@ MYSQL_BIN_LOG::trx_group_commit_leader(group_commit_entry *leader)
when the transaction has been safely committed in the engine.
*/
leader->cache_mngr->delayed_error= true;
- my_error(ER_ERROR_ON_WRITE, MYF(ME_NOREFRESH), name, errno);
+ my_error(ER_ERROR_ON_WRITE, MYF(ME_ERROR_LOG), name, errno);
check_purge= false;
}
/* In case of binlog rotate, update the correct current binlog offset. */
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index dab0fab35e0..ce14dc678c6 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -2786,9 +2786,10 @@ static void network_init(void)
*/
if (mysqld_unix_port[0] && !opt_bootstrap)
{
+ size_t port_len;
DBUG_PRINT("general",("UNIX Socket is %s",mysqld_unix_port));
- if (strlen(mysqld_unix_port) > (sizeof(UNIXaddr.sun_path) - 1))
+ if ((port_len= strlen(mysqld_unix_port)) > sizeof(UNIXaddr.sun_path) - 1)
{
sql_print_error("The socket file path is too long (> %u): %s",
(uint) sizeof(UNIXaddr.sun_path) - 1, mysqld_unix_port);
@@ -2806,14 +2807,26 @@ static void network_init(void)
bzero((char*) &UNIXaddr, sizeof(UNIXaddr));
UNIXaddr.sun_family = AF_UNIX;
strmov(UNIXaddr.sun_path, mysqld_unix_port);
- (void) unlink(mysqld_unix_port);
+#if defined(__linux__)
+ /* Abstract socket */
+ if (mysqld_unix_port[0] == '@')
+ {
+ UNIXaddr.sun_path[0]= '\0';
+ port_len+= offsetof(struct sockaddr_un, sun_path);
+ }
+ else
+#endif
+ {
+ (void) unlink(mysqld_unix_port);
+ port_len= sizeof(UNIXaddr);
+ }
arg= 1;
(void) mysql_socket_setsockopt(unix_sock,SOL_SOCKET,SO_REUSEADDR,
(char*)&arg, sizeof(arg));
umask(0);
if (mysql_socket_bind(unix_sock,
reinterpret_cast<struct sockaddr *>(&UNIXaddr),
- sizeof(UNIXaddr)) < 0)
+ port_len) < 0)
{
sql_perror("Can't start server : Bind on unix socket"); /* purecov: tested */
sql_print_error("Do you already have another mysqld server running on socket: %s ?",mysqld_unix_port);
@@ -3647,7 +3660,7 @@ extern "C" void my_message_sql(uint error, const char *str, myf MyFlags);
void my_message_sql(uint error, const char *str, myf MyFlags)
{
- THD *thd= current_thd;
+ THD *thd= MyFlags & ME_ERROR_LOG_ONLY ? NULL : current_thd;
Sql_condition::enum_warning_level level;
sql_print_message_func func;
DBUG_ENTER("my_message_sql");
@@ -3656,13 +3669,15 @@ void my_message_sql(uint error, const char *str, myf MyFlags)
DBUG_ASSERT(str != NULL);
DBUG_ASSERT(error != 0);
+ DBUG_ASSERT((MyFlags & ~(ME_BELL | ME_ERROR_LOG | ME_ERROR_LOG_ONLY |
+ ME_NOTE | ME_WARNING | ME_FATAL)) == 0);
- if (MyFlags & ME_JUST_INFO)
+ if (MyFlags & ME_NOTE)
{
level= Sql_condition::WARN_LEVEL_NOTE;
func= sql_print_information;
}
- else if (MyFlags & ME_JUST_WARNING)
+ else if (MyFlags & ME_WARNING)
{
level= Sql_condition::WARN_LEVEL_WARN;
func= sql_print_warning;
@@ -3675,7 +3690,7 @@ void my_message_sql(uint error, const char *str, myf MyFlags)
if (likely(thd))
{
- if (unlikely(MyFlags & ME_FATALERROR))
+ if (unlikely(MyFlags & ME_FATAL))
thd->is_fatal_error= 1;
(void) thd->raise_condition(error, NULL, level, str);
}
@@ -3685,7 +3700,7 @@ void my_message_sql(uint error, const char *str, myf MyFlags)
/* When simulating OOM, skip writing to error log to avoid mtr errors */
DBUG_EXECUTE_IF("simulate_out_of_memory", DBUG_VOID_RETURN;);
- if (unlikely(!thd) || thd->log_all_errors || (MyFlags & ME_NOREFRESH))
+ if (unlikely(!thd) || thd->log_all_errors || (MyFlags & ME_ERROR_LOG))
(*func)("%s: %s", my_progname_short, str); /* purecov: inspected */
DBUG_VOID_RETURN;
}
@@ -9800,10 +9815,10 @@ static int get_options(int *argc_ptr, char ***argv_ptr)
errors.
*/
if (global_system_variables.log_warnings >= 10)
- my_global_flags= MY_WME | ME_JUST_INFO;
+ my_global_flags= MY_WME | ME_NOTE;
/* Log all errors not handled by thd->handle_error() to my_message_sql() */
if (global_system_variables.log_warnings >= 11)
- my_global_flags|= ME_NOREFRESH;
+ my_global_flags|= ME_ERROR_LOG;
if (my_assert_on_error)
debug_assert_if_crashed_table= 1;
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index 8422917065f..6f761c9c5d3 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -1479,7 +1479,6 @@ int QUICK_RANGE_SELECT::init_ror_merged_scan(bool reuse_handler,
{
handler *save_file= file, *org_file;
THD *thd= head->in_use;
- MY_BITMAP * const save_vcol_set= head->vcol_set;
MY_BITMAP * const save_read_set= head->read_set;
MY_BITMAP * const save_write_set= head->write_set;
DBUG_ENTER("QUICK_RANGE_SELECT::init_ror_merged_scan");
@@ -1537,14 +1536,14 @@ end:
org_file= head->file;
head->file= file;
- head->column_bitmaps_set_no_signal(&column_bitmap, &column_bitmap, &column_bitmap);
+ head->column_bitmaps_set_no_signal(&column_bitmap, &column_bitmap);
head->prepare_for_keyread(index, &column_bitmap);
head->prepare_for_position();
head->file= org_file;
/* Restore head->read_set (and write_set) to what they had before the call */
- head->column_bitmaps_set(save_read_set, save_write_set, save_vcol_set);
+ head->column_bitmaps_set(save_read_set, save_write_set);
if (reset())
{
@@ -1559,7 +1558,7 @@ end:
DBUG_RETURN(0);
failure:
- head->column_bitmaps_set(save_read_set, save_write_set, save_vcol_set);
+ head->column_bitmaps_set(save_read_set, save_write_set);
delete file;
file= save_file;
DBUG_RETURN(1);
@@ -8118,7 +8117,7 @@ Item_bool_func::get_mm_leaf(RANGE_OPT_PARAM *param,
else if (type == GT_FUNC &&
(field->type() != FIELD_TYPE_BIT) &&
!((Field_num*)field)->unsigned_flag &&
- !((Item_int*)value)->unsigned_flag &&
+ !value->unsigned_flag &&
(value->val_int() < 0))
type= GE_FUNC;
}
@@ -8165,7 +8164,7 @@ Item_bool_func::get_mm_leaf(RANGE_OPT_PARAM *param,
value->result_type() == INT_RESULT &&
((field->type() == FIELD_TYPE_BIT ||
((Field_num *) field)->unsigned_flag) &&
- !((Item_int*) value)->unsigned_flag))
+ !value->unsigned_flag))
{
longlong item_val= value->val_int();
if (item_val < 0)
@@ -11350,7 +11349,6 @@ int QUICK_RANGE_SELECT::reset()
HANDLER_BUFFER empty_buf;
MY_BITMAP * const save_read_set= head->read_set;
MY_BITMAP * const save_write_set= head->write_set;
- MY_BITMAP * const save_vcol_set= head->vcol_set;
DBUG_ENTER("QUICK_RANGE_SELECT::reset");
last_range= NULL;
cur_range= (QUICK_RANGE**) ranges.buffer;
@@ -11364,8 +11362,7 @@ int QUICK_RANGE_SELECT::reset()
}
if (in_ror_merged_scan)
- head->column_bitmaps_set_no_signal(&column_bitmap, &column_bitmap,
- &column_bitmap);
+ head->column_bitmaps_set_no_signal(&column_bitmap, &column_bitmap);
if (file->inited == handler::NONE)
{
@@ -11411,8 +11408,7 @@ int QUICK_RANGE_SELECT::reset()
err:
/* Restore bitmaps set on entry */
if (in_ror_merged_scan)
- head->column_bitmaps_set_no_signal(save_read_set, save_write_set,
- save_vcol_set);
+ head->column_bitmaps_set_no_signal(save_read_set, save_write_set);
DBUG_RETURN(error);
}
@@ -11443,16 +11439,13 @@ int QUICK_RANGE_SELECT::get_next()
MY_BITMAP * const save_read_set= head->read_set;
MY_BITMAP * const save_write_set= head->write_set;
- MY_BITMAP * const save_vcol_set= head->vcol_set;
/*
We don't need to signal the bitmap change as the bitmap is always the
same for this head->file
*/
- head->column_bitmaps_set_no_signal(&column_bitmap, &column_bitmap,
- &column_bitmap);
+ head->column_bitmaps_set_no_signal(&column_bitmap, &column_bitmap);
result= file->multi_range_read_next(&dummy);
- head->column_bitmaps_set_no_signal(save_read_set, save_write_set,
- save_vcol_set);
+ head->column_bitmaps_set_no_signal(save_read_set, save_write_set);
DBUG_RETURN(result);
}
@@ -13027,7 +13020,8 @@ check_group_min_max_predicates(Item *cond, Item_field *min_max_arg_item,
if (args[0] && args[1]) // this is a binary function or BETWEEN
{
- DBUG_ASSERT(pred->is_bool_type());
+ DBUG_ASSERT(pred->fixed_type_handler());
+ DBUG_ASSERT(pred->fixed_type_handler()->is_bool_type());
Item_bool_func *bool_func= (Item_bool_func*) pred;
Field *field= min_max_arg_item->field;
if (!args[2]) // this is a binary function
diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc
index 1cfdcc9c9b2..7f7bb07d279 100644
--- a/sql/opt_subselect.cc
+++ b/sql/opt_subselect.cc
@@ -5442,31 +5442,453 @@ int select_value_catcher::send_data(List<Item> &items)
}
-/*
- Setup JTBM join tabs for execution
+/**
+ @brief
+ Conjugate conditions after optimize_cond() call
+
+ @param thd the thread handle
+ @param cond the condition where to attach new conditions
+ @param cond_eq IN/OUT the multiple equalities of cond
+ @param new_conds IN/OUT the list of conditions needed to add
+ @param cond_value the returned value of the condition
+
+ @details
+ The method creates new condition through conjunction of cond and
+ the conditions from new_conds list.
+ The method is called after optimize_cond() for cond. The result
+ of the conjunction should be the same as if it was done before the
+ the optimize_cond() call.
+
+ @retval NULL if an error occurs
+ @retval otherwise the created condition
+*/
+
+Item *and_new_conditions_to_optimized_cond(THD *thd, Item *cond,
+ COND_EQUAL **cond_eq,
+ List<Item> &new_conds,
+ Item::cond_result *cond_value)
+{
+ COND_EQUAL new_cond_equal;
+ Item *item;
+ Item_equal *equality;
+ bool is_simplified_cond= false;
+ List_iterator<Item> li(new_conds);
+ List_iterator_fast<Item_equal> it(new_cond_equal.current_level);
+
+ /*
+ Creates multiple equalities new_cond_equal from new_conds list
+ equalities. If multiple equality can't be created or the condition
+ from new_conds list isn't an equality the method leaves it in new_conds
+ list.
+
+ The equality can't be converted into the multiple equality if it
+ is a knowingly false or true equality.
+ For example, (3 = 1) equality.
+ */
+ while ((item=li++))
+ {
+ if (item->type() == Item::FUNC_ITEM &&
+ ((Item_func *) item)->functype() == Item_func::EQ_FUNC &&
+ check_simple_equality(thd,
+ Item::Context(Item::ANY_SUBST,
+ ((Item_func_equal *)item)->compare_type_handler(),
+ ((Item_func_equal *)item)->compare_collation()),
+ ((Item_func *)item)->arguments()[0]->real_item(),
+ ((Item_func *)item)->arguments()[1]->real_item(),
+ &new_cond_equal))
+ li.remove();
+ }
+
+ it.rewind();
+ if (cond && cond->type() == Item::COND_ITEM &&
+ ((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC)
+ {
+ /*
+ cond is an AND-condition.
+ The method conjugates the AND-condition cond, created multiple
+ equalities new_cond_equal and remain conditions from new_conds.
+
+ First, the method disjoins multiple equalities of cond and
+ merges new_cond_equal multiple equalities with these equalities.
+ It checks if after the merge the multiple equalities are knowingly
+ true or false equalities.
+ It attaches to cond the conditions from new_conds list and the result
+ of the merge of multiple equalities. The multiple equalities are
+ attached only to the upper level of AND-condition cond. So they
+ should be pushed down to the inner levels of cond AND-condition
+ if needed. It is done by propagate_new_equalities().
+ */
+ COND_EQUAL *cond_equal= &((Item_cond_and *) cond)->m_cond_equal;
+ List<Item_equal> *cond_equalities= &cond_equal->current_level;
+ List<Item> *and_args= ((Item_cond_and *)cond)->argument_list();
+ and_args->disjoin((List<Item> *) cond_equalities);
+ and_args->append(&new_conds);
+
+ while ((equality= it++))
+ {
+ equality->upper_levels= 0;
+ equality->merge_into_list(thd, cond_equalities, false, false);
+ }
+ List_iterator_fast<Item_equal> ei(*cond_equalities);
+ while ((equality= ei++))
+ {
+ if (equality->const_item() && !equality->val_int())
+ is_simplified_cond= true;
+ equality->fixed= 0;
+ if (equality->fix_fields(thd, NULL))
+ return NULL;
+ }
+
+ and_args->append((List<Item> *) cond_equalities);
+ *cond_eq= &((Item_cond_and *) cond)->m_cond_equal;
+
+ propagate_new_equalities(thd, cond, cond_equalities,
+ cond_equal->upper_levels,
+ &is_simplified_cond);
+ cond= cond->propagate_equal_fields(thd,
+ Item::Context_boolean(),
+ cond_equal);
+ }
+ else
+ {
+ /*
+ cond isn't AND-condition or is NULL.
+ There can be several cases:
+
+ 1. cond is a multiple equality.
+ In this case cond is merged with the multiple equalities of
+ new_cond_equal.
+ The new condition is created with the conjunction of new_conds
+ list conditions and the result of merge of multiple equalities.
+ 2. cond is NULL
+ The new condition is created from the conditions of new_conds
+ list and multiple equalities from new_cond_equal.
+ 3. Otherwise
+ In this case the new condition is created from cond, remain conditions
+ from new_conds list and created multiple equalities from
+ new_cond_equal.
+ */
+ List<Item> new_conds_list;
+ /* Flag is set to true if cond is a multiple equality */
+ bool is_mult_eq= (cond && cond->type() == Item::FUNC_ITEM &&
+ ((Item_func*) cond)->functype() == Item_func::MULT_EQUAL_FUNC);
+
+ if (cond && !is_mult_eq &&
+ new_conds_list.push_back(cond, thd->mem_root))
+ return NULL;
+
+ if (new_conds.elements > 0)
+ {
+ li.rewind();
+ while ((item=li++))
+ {
+ if (item->fix_fields_if_needed(thd, NULL))
+ return NULL;
+ if (item->const_item() && !item->val_int())
+ is_simplified_cond= true;
+ }
+
+ if (new_conds.elements > 1)
+ new_conds_list.append(&new_conds);
+ else
+ {
+ li.rewind();
+ item= li++;
+ if (new_conds_list.push_back(item, thd->mem_root))
+ return NULL;
+ }
+ }
+
+ if (new_cond_equal.current_level.elements > 0)
+ {
+ if (is_mult_eq)
+ {
+ Item_equal *eq_cond= (Item_equal *)cond;
+ eq_cond->upper_levels= 0;
+ eq_cond->merge_into_list(thd, &new_cond_equal.current_level,
+ false, false);
+
+ while ((equality= it++))
+ {
+ if (equality->const_item() && !equality->val_int())
+ is_simplified_cond= true;
+ }
+
+ if (new_cond_equal.current_level.elements +
+ new_conds_list.elements == 1)
+ {
+ it.rewind();
+ equality= it++;
+ equality->fixed= 0;
+ if (equality->fix_fields(thd, NULL))
+ return NULL;
+ }
+ *cond_eq= &new_cond_equal;
+ }
+ new_conds_list.append((List<Item> *)&new_cond_equal.current_level);
+ }
+
+ if (new_conds_list.elements > 1)
+ {
+ Item_cond_and *and_cond=
+ new (thd->mem_root) Item_cond_and(thd, new_conds_list);
+
+ and_cond->m_cond_equal.copy(new_cond_equal);
+ cond= (Item *)and_cond;
+ *cond_eq= &((Item_cond_and *)cond)->m_cond_equal;
+ }
+ else
+ {
+ List_iterator_fast<Item> iter(new_conds_list);
+ cond= iter++;
+ }
+
+ if (cond->fix_fields_if_needed(thd, NULL))
+ return NULL;
+
+ if (new_cond_equal.current_level.elements > 0)
+ cond= cond->propagate_equal_fields(thd,
+ Item::Context_boolean(),
+ &new_cond_equal);
+ }
+
+ /*
+ If it was found that some of the created condition parts are knowingly
+ true or false equalities the method calls removes_eq_cond() to remove them
+ from cond and set the cond_value to the appropriate value.
+ */
+ if (is_simplified_cond)
+ cond= cond->remove_eq_conds(thd, cond_value, true);
+ return cond;
+}
+
+
+/**
+ @brief Materialize a degenerate jtbm semi join
+
+ @param thd thread handler
+ @param tbl table list for the target jtbm semi join table
+ @param subq_pred IN subquery predicate with the degenerate jtbm semi join
+ @param eq_list IN/OUT the list where to add produced equalities
+
+ @details
+ The method materializes the degenerate jtbm semi join for the
+ subquery from the IN subquery predicate subq_pred taking table
+ as the target for materialization.
+ Any degenerate table is guaranteed to produce 0 or 1 record.
+ Examples of both cases:
+
+ select * from ot where col in (select ... from it where 2>3)
+ select * from ot where col in (select MY_MIN(it.key) from it)
+
+ in this case, there is no necessity to create a temp.table for
+ materialization.
+ We now just need to
+ 1. Check whether 1 or 0 records are produced, setup this as a
+ constant join tab.
+ 2. Create a dummy temporary table, because all of the join
+ optimization code relies on TABLE object being present.
+
+ In the case when materialization produces one row the function
+ additionally creates equalities between the expressions from the
+ left part of the IN subquery predicate and the corresponding
+ columns of the produced row. These equalities are added to the
+ list eq_list. They are supposed to be conjuncted with the condition
+ of the WHERE clause.
+
+ @retval TRUE if an error occurs
+ @retval FALSE otherwise
+*/
+
+bool execute_degenerate_jtbm_semi_join(THD *thd,
+ TABLE_LIST *tbl,
+ Item_in_subselect *subq_pred,
+ List<Item> &eq_list)
+{
+ DBUG_ENTER("execute_degenerate_jtbm_semi_join");
+ select_value_catcher *new_sink;
+
+ DBUG_ASSERT(subq_pred->engine->engine_type() ==
+ subselect_engine::SINGLE_SELECT_ENGINE);
+ subselect_single_select_engine *engine=
+ (subselect_single_select_engine*)subq_pred->engine;
+ if (!(new_sink= new (thd->mem_root) select_value_catcher(thd, subq_pred)))
+ DBUG_RETURN(TRUE);
+ if (new_sink->setup(&engine->select_lex->join->fields_list) ||
+ engine->select_lex->join->change_result(new_sink, NULL) ||
+ engine->exec())
+ {
+ DBUG_RETURN(TRUE);
+ }
+ subq_pred->is_jtbm_const_tab= TRUE;
+
+ if (new_sink->assigned)
+ {
+ /*
+ Subselect produced one row, which is saved in new_sink->row.
+ Save "left_expr[i] == row[i]" equalities into the eq_list.
+ */
+ subq_pred->jtbm_const_row_found= TRUE;
+
+ Item *eq_cond;
+ for (uint i= 0; i < subq_pred->left_expr->cols(); i++)
+ {
+ eq_cond=
+ new (thd->mem_root) Item_func_eq(thd,
+ subq_pred->left_expr->element_index(i),
+ new_sink->row[i]);
+ if (!eq_cond || eq_list.push_back(eq_cond, thd->mem_root))
+ DBUG_RETURN(TRUE);
+ }
+ }
+ else
+ {
+ /* Subselect produced no rows. Just set the flag */
+ subq_pred->jtbm_const_row_found= FALSE;
+ }
+
+ TABLE *dummy_table;
+ if (!(dummy_table= create_dummy_tmp_table(thd)))
+ DBUG_RETURN(TRUE);
+ tbl->table= dummy_table;
+ tbl->table->pos_in_table_list= tbl;
+ /*
+ Note: the table created above may be freed by:
+ 1. JOIN_TAB::cleanup(), when the parent join is a regular join.
+ 2. cleanup_empty_jtbm_semi_joins(), when the parent join is a
+ degenerate join (e.g. one with "Impossible where").
+ */
+ setup_table_map(tbl->table, tbl, tbl->jtbm_table_no);
+ DBUG_RETURN(FALSE);
+}
+
+
+/**
+ @brief
+ Execute degenerate jtbm semi joins before optimize_cond() for parent
+
+ @param join the parent join for jtbm semi joins
+ @param join_list the list of tables where jtbm semi joins are processed
+ @param eq_list IN/OUT the list where to add equalities produced after
+ materialization of single-row degenerate jtbm semi joins
+
+ @details
+ The method traverses join_list trying to find any degenerate jtbm semi
+ joins for subqueries of IN predicates. For each degenerate jtbm
+ semi join execute_degenerate_jtbm_semi_join() is called. As a result
+ of this call new equalities that substitute for single-row materialized
+ jtbm semi join are added to eq_list.
+
+ In the case when a table is nested in another table 'nested_join' the
+ method is recursively called for the join_list of the 'nested_join' trying
+ to find in the list any degenerate jtbm semi joins. Currently a jtbm semi
+ join may occur in a mergeable semi join nest.
+
+ @retval TRUE if an error occurs
+ @retval FALSE otherwise
*/
-bool setup_jtbm_semi_joins(JOIN *join, List<TABLE_LIST> *join_list,
- Item **join_where)
+bool setup_degenerate_jtbm_semi_joins(JOIN *join,
+ List<TABLE_LIST> *join_list,
+ List<Item> &eq_list)
+{
+ TABLE_LIST *table;
+ NESTED_JOIN *nested_join;
+ List_iterator<TABLE_LIST> li(*join_list);
+ THD *thd= join->thd;
+ DBUG_ENTER("setup_degenerate_jtbm_semi_joins");
+
+ while ((table= li++))
+ {
+ Item_in_subselect *subq_pred;
+
+ if ((subq_pred= table->jtbm_subselect))
+ {
+ JOIN *subq_join= subq_pred->unit->first_select()->join;
+
+ if (!subq_join->tables_list || !subq_join->table_count)
+ {
+ if (execute_degenerate_jtbm_semi_join(thd,
+ table,
+ subq_pred,
+ eq_list))
+ DBUG_RETURN(TRUE);
+ join->is_orig_degenerated= true;
+ }
+ }
+ if ((nested_join= table->nested_join))
+ {
+ if (setup_degenerate_jtbm_semi_joins(join,
+ &nested_join->join_list,
+ eq_list))
+ DBUG_RETURN(TRUE);
+ }
+ }
+ DBUG_RETURN(FALSE);
+}
+
+
+/**
+ @brief
+ Optimize jtbm semi joins for materialization
+
+ @param join the parent join for jtbm semi joins
+ @param join_list the list of TABLE_LIST objects where jtbm semi join
+ can occur
+ @param eq_list IN/OUT the list where to add produced equalities
+
+ @details
+ This method is called by the optimizer after the call of
+ optimize_cond() for parent select.
+ The method traverses join_list trying to find any jtbm semi joins for
+ subqueries from IN predicates and optimizes them.
+ After the optimization some of jtbm semi joins may become degenerate.
+ For example the subquery 'SELECT MAX(b) FROM t2' from the query
+
+ SELECT * FROM t1 WHERE 4 IN (SELECT MAX(b) FROM t2);
+
+ will become degenerate if there is an index on t2.b.
+ If a subquery becomes degenerate it is handled by the function
+ execute_degenerate_jtbm_semi_join().
+
+ Otherwise the method creates a temporary table in which the subquery
+ of the jtbm semi join will be materialied.
+
+ The function saves the equalities between all pairs of the expressions
+ from the left part of the IN subquery predicate and the corresponding
+ columns of the subquery from the predicate in eq_list appending them
+ to the list. The equalities of eq_list will be later conjucted with the
+ condition of the WHERE clause.
+
+ In the case when a table is nested in another table 'nested_join' the
+ method is recursively called for the join_list of the 'nested_join' trying
+ to find in the list any degenerate jtbm semi joins. Currently a jtbm semi
+ join may occur in a mergeable semi join nest.
+
+ @retval TRUE if an error occurs
+ @retval FALSE otherwise
+*/
+
+bool setup_jtbm_semi_joins(JOIN *join, List<TABLE_LIST> *join_list,
+ List<Item> &eq_list)
{
TABLE_LIST *table;
NESTED_JOIN *nested_join;
List_iterator<TABLE_LIST> li(*join_list);
THD *thd= join->thd;
DBUG_ENTER("setup_jtbm_semi_joins");
-
+
while ((table= li++))
{
- Item_in_subselect *item;
+ Item_in_subselect *subq_pred;
- if ((item= table->jtbm_subselect))
+ if ((subq_pred= table->jtbm_subselect))
{
- Item_in_subselect *subq_pred= item;
double rows;
double read_time;
/*
- Perform optimization of the subquery, so that we know estmated
+ Perform optimization of the subquery, so that we know estimated
- cost of materialization process
- how many records will be in the materialized temp.table
*/
@@ -5479,102 +5901,36 @@ bool setup_jtbm_semi_joins(JOIN *join, List<TABLE_LIST> *join_list,
if (!subq_join->tables_list || !subq_join->table_count)
{
- /*
- A special case; subquery's join is degenerate, and it either produces
- 0 or 1 record. Examples of both cases:
-
- select * from ot where col in (select ... from it where 2>3)
- select * from ot where col in (select MY_MIN(it.key) from it)
-
- in this case, the subquery predicate has not been setup for
- materialization. In particular, there is no materialized temp.table.
- We'll now need to
- 1. Check whether 1 or 0 records are produced, setup this as a
- constant join tab.
- 2. Create a dummy temporary table, because all of the join
- optimization code relies on TABLE object being present (here we
- follow a bad tradition started by derived tables)
- */
- DBUG_ASSERT(subq_pred->engine->engine_type() ==
- subselect_engine::SINGLE_SELECT_ENGINE);
- subselect_single_select_engine *engine=
- (subselect_single_select_engine*)subq_pred->engine;
- select_value_catcher *new_sink;
- if (!(new_sink=
- new (thd->mem_root) select_value_catcher(thd, subq_pred)))
- DBUG_RETURN(TRUE);
- if (new_sink->setup(&engine->select_lex->join->fields_list) ||
- engine->select_lex->join->change_result(new_sink, NULL) ||
- engine->exec())
- {
+ if (!join->is_orig_degenerated &&
+ execute_degenerate_jtbm_semi_join(thd, table, subq_pred,
+ eq_list))
DBUG_RETURN(TRUE);
- }
- subq_pred->is_jtbm_const_tab= TRUE;
-
- if (new_sink->assigned)
- {
- subq_pred->jtbm_const_row_found= TRUE;
- /*
- Subselect produced one row, which is saved in new_sink->row.
- Inject "left_expr[i] == row[i] equalities into parent's WHERE.
- */
- Item *eq_cond;
- for (uint i= 0; i < subq_pred->left_expr->cols(); i++)
- {
- eq_cond= new (thd->mem_root)
- Item_func_eq(thd, subq_pred->left_expr->element_index(i),
- new_sink->row[i]);
- if (!eq_cond)
- DBUG_RETURN(1);
-
- if (!((*join_where)= and_items(thd, *join_where, eq_cond)) ||
- (*join_where)->fix_fields(thd, join_where))
- DBUG_RETURN(1);
- }
- }
- else
- {
- /* Subselect produced no rows. Just set the flag, */
- subq_pred->jtbm_const_row_found= FALSE;
- }
-
- /* Set up a dummy TABLE*, optimizer code needs JOIN_TABs to have TABLE */
- TABLE *dummy_table;
- if (!(dummy_table= create_dummy_tmp_table(thd)))
- DBUG_RETURN(1);
- table->table= dummy_table;
- table->table->pos_in_table_list= table;
- /*
- Note: the table created above may be freed by:
- 1. JOIN_TAB::cleanup(), when the parent join is a regular join.
- 2. cleanup_empty_jtbm_semi_joins(), when the parent join is a
- degenerate join (e.g. one with "Impossible where").
- */
- setup_table_map(table->table, table, table->jtbm_table_no);
}
else
{
DBUG_ASSERT(subq_pred->test_set_strategy(SUBS_MATERIALIZATION));
subq_pred->is_jtbm_const_tab= FALSE;
subselect_hash_sj_engine *hash_sj_engine=
- ((subselect_hash_sj_engine*)item->engine);
+ ((subselect_hash_sj_engine*)subq_pred->engine);
table->table= hash_sj_engine->tmp_table;
table->table->pos_in_table_list= table;
setup_table_map(table->table, table, table->jtbm_table_no);
- Item *sj_conds= hash_sj_engine->semi_join_conds;
-
- (*join_where)= and_items(thd, *join_where, sj_conds);
- (*join_where)->fix_fields_if_needed(thd, join_where);
+ List_iterator<Item> li(*hash_sj_engine->semi_join_conds->argument_list());
+ Item *item;
+ while ((item=li++))
+ {
+ if (eq_list.push_back(item, thd->mem_root))
+ DBUG_RETURN(TRUE);
+ }
}
table->table->maybe_null= MY_TEST(join->mixed_implicit_grouping);
}
-
if ((nested_join= table->nested_join))
{
- if (setup_jtbm_semi_joins(join, &nested_join->join_list, join_where))
+ if (setup_jtbm_semi_joins(join, &nested_join->join_list, eq_list))
DBUG_RETURN(TRUE);
}
}
@@ -5969,3 +6325,418 @@ bool JOIN::choose_tableless_subquery_plan()
exec_const_cond= conds;
return FALSE;
}
+
+
+/*
+ Check if the item exists in the fields list of the left part of
+ the IN subquery predicate subq_pred and returns its corresponding
+ item from the select of the right part of subq_pred.
+*/
+Item *Item::get_corresponding_field_in_insubq(Item_in_subselect *subq_pred)
+{
+ DBUG_ASSERT(type() == Item::FIELD_ITEM ||
+ (type() == Item::REF_ITEM &&
+ ((Item_ref *) this)->ref_type() == Item_ref::VIEW_REF));
+
+ List_iterator<Field_pair> it(subq_pred->corresponding_fields);
+ Field_pair *ret;
+ Item_field *field_item= (Item_field *) (real_item());
+ while ((ret= it++))
+ {
+ if (field_item->field == ret->field)
+ return ret->corresponding_item;
+ }
+ return NULL;
+}
+
+
+bool Item_field::excl_dep_on_in_subq_left_part(Item_in_subselect *subq_pred)
+{
+ if (((Item *)this)->get_corresponding_field_in_insubq(subq_pred))
+ return true;
+ if (item_equal)
+ {
+ Item_equal_fields_iterator it(*item_equal);
+ Item *equal_item;
+ while ((equal_item= it++))
+ {
+ if (equal_item->const_item())
+ continue;
+ if (equal_item->get_corresponding_field_in_insubq(subq_pred))
+ return true;
+ }
+ }
+ return false;
+}
+
+
+bool Item_direct_view_ref::excl_dep_on_in_subq_left_part(Item_in_subselect *subq_pred)
+{
+ if (item_equal)
+ {
+ DBUG_ASSERT(real_item()->type() == Item::FIELD_ITEM);
+ if (((Item *)this)->get_corresponding_field_in_insubq(subq_pred))
+ return true;
+ }
+ return (*ref)->excl_dep_on_in_subq_left_part(subq_pred);
+}
+
+
+bool Item_equal::excl_dep_on_in_subq_left_part(Item_in_subselect *subq_pred)
+{
+ Item *left_item = get_const();
+ Item_equal_fields_iterator it(*this);
+ Item *item;
+ if (!left_item)
+ {
+ while ((item=it++))
+ {
+ if (item->excl_dep_on_in_subq_left_part(subq_pred))
+ {
+ left_item= item;
+ break;
+ }
+ }
+ }
+ if (!left_item)
+ return false;
+ while ((item=it++))
+ {
+ if (item->excl_dep_on_in_subq_left_part(subq_pred))
+ return true;
+ }
+ return false;
+}
+
+
+/**
+ @brief
+ Get corresponding item from the select of the right part of IN subquery
+
+ @param thd the thread handle
+ @param item the item from the left part of subq_pred for which
+ corresponding item should be found
+ @param subq_pred the IN subquery predicate
+
+ @details
+ This method looks through the fields of the select of the right part of
+ the IN subquery predicate subq_pred trying to find the corresponding
+ item 'new_item' for item. If item has equal items it looks through
+ the fields of the select of the right part of subq_pred for each equal
+ item trying to find the corresponding item.
+ The method assumes that the given item is either a field item or
+ a reference to a field item.
+
+ @retval <item*> reference to the corresponding item
+ @retval NULL if item was not found
+*/
+
+static
+Item *get_corresponding_item(THD *thd, Item *item,
+ Item_in_subselect *subq_pred)
+{
+ DBUG_ASSERT(item->type() == Item::FIELD_ITEM ||
+ (item->type() == Item::REF_ITEM &&
+ ((Item_ref *) item)->ref_type() == Item_ref::VIEW_REF));
+
+ Item *corresonding_item;
+ Item_equal *item_equal= item->get_item_equal();
+
+ if (item_equal)
+ {
+ Item_equal_fields_iterator it(*item_equal);
+ Item *equal_item;
+ while ((equal_item= it++))
+ {
+ corresonding_item=
+ equal_item->get_corresponding_field_in_insubq(subq_pred);
+ if (corresonding_item)
+ return corresonding_item;
+ }
+ return NULL;
+ }
+ else
+ return item->get_corresponding_field_in_insubq(subq_pred);
+}
+
+
+Item *Item_field::in_subq_field_transformer_for_where(THD *thd, uchar *arg)
+{
+ Item_in_subselect *subq_pred= (Item_in_subselect *)arg;
+ Item *producing_item= get_corresponding_item(thd, this, subq_pred);
+ if (producing_item)
+ return producing_item->build_clone(thd);
+ return this;
+}
+
+
+Item *Item_direct_view_ref::in_subq_field_transformer_for_where(THD *thd,
+ uchar *arg)
+{
+ if (item_equal)
+ {
+ Item_in_subselect *subq_pred= (Item_in_subselect *)arg;
+ Item *producing_item= get_corresponding_item(thd, this, subq_pred);
+ DBUG_ASSERT (producing_item != NULL);
+ return producing_item->build_clone(thd);
+ }
+ return this;
+}
+
+
+/**
+ @brief
+ Transforms item so it can be pushed into the IN subquery HAVING clause
+
+ @param thd the thread handle
+ @param in_item the item for which pushable item should be created
+ @param subq_pred the IN subquery predicate
+
+ @details
+ This method finds for in_item that is a field from the left part of the
+ IN subquery predicate subq_pred its corresponding item from the right part
+ of subq_pred.
+ If corresponding item is found, a shell for this item is created.
+ This shell can be pushed into the HAVING part of subq_pred select.
+
+ @retval <item*> reference to the created corresponding item shell for in_item
+ @retval NULL if mistake occurs
+*/
+
+static Item*
+get_corresponding_item_for_in_subq_having(THD *thd, Item *in_item,
+ Item_in_subselect *subq_pred)
+{
+ Item *new_item= get_corresponding_item(thd, in_item, subq_pred);
+
+ if (new_item)
+ {
+ Item_ref *ref=
+ new (thd->mem_root) Item_ref(thd,
+ &subq_pred->unit->first_select()->context,
+ NullS, NullS,
+ &new_item->name);
+ if (!ref)
+ DBUG_ASSERT(0);
+ return ref;
+ }
+ return new_item;
+}
+
+
+Item *Item_field::in_subq_field_transformer_for_having(THD *thd, uchar *arg)
+{
+ return get_corresponding_item_for_in_subq_having(thd, this,
+ (Item_in_subselect *)arg);
+}
+
+
+Item *Item_direct_view_ref::in_subq_field_transformer_for_having(THD *thd,
+ uchar *arg)
+{
+ if (!item_equal)
+ return this;
+ else
+ {
+ Item *new_item= get_corresponding_item_for_in_subq_having(thd, this,
+ (Item_in_subselect *)arg);
+ if (!new_item)
+ return this;
+ return new_item;
+ }
+}
+
+
+/**
+ @brief
+ Find fields that are used in the GROUP BY of the select
+
+ @param thd the thread handle
+ @param sel the select of the IN subquery predicate
+ @param fields fields of the left part of the IN subquery predicate
+ @param grouping_list GROUP BY clause
+
+ @details
+ This method traverses fields which are used in the GROUP BY of
+ sel and saves them with their corresponding items from fields.
+*/
+
+bool grouping_fields_in_the_in_subq_left_part(THD *thd,
+ st_select_lex *sel,
+ List<Field_pair> *fields,
+ ORDER *grouping_list)
+{
+ DBUG_ENTER("grouping_fields_in_the_in_subq_left_part");
+ sel->grouping_tmp_fields.empty();
+ List_iterator<Field_pair> it(*fields);
+ Field_pair *item;
+ while ((item= it++))
+ {
+ for (ORDER *ord= grouping_list; ord; ord= ord->next)
+ {
+ if ((*ord->item)->eq(item->corresponding_item, 0))
+ {
+ if (sel->grouping_tmp_fields.push_back(item, thd->mem_root))
+ DBUG_RETURN(TRUE);
+ }
+ }
+ }
+ DBUG_RETURN(FALSE);
+}
+
+
+/**
+ @brief
+ Extract condition that can be pushed into select of this IN subquery
+
+ @param thd the thread handle
+ @param cond current condition
+
+ @details
+ This function builds the most restrictive condition depending only on
+ the list of fields of the left part of this IN subquery predicate
+ (directly or indirectly through equality) that can be extracted from the
+ given condition cond and pushes it into this IN subquery.
+
+ Example of the transformation:
+
+ SELECT * FROM t1
+ WHERE a>3 AND b>10 AND
+ (a,b) IN (SELECT x,MAX(y) FROM t2 GROUP BY x);
+
+ =>
+
+ SELECT * FROM t1
+ WHERE a>3 AND b>10 AND
+ (a,b) IN (SELECT x,max(y)
+ FROM t2
+ WHERE x>3
+ GROUP BY x
+ HAVING MAX(y)>10);
+
+
+ In details:
+ 1. Check what pushable formula can be extracted from cond
+ 2. Build a clone PC of the formula that can be extracted
+ (the clone is built only if the extracted formula is a AND subformula
+ of cond or conjunction of such subformulas)
+ 3. If there is no HAVING clause prepare PC to be conjuncted with
+ WHERE clause of this subquery. Otherwise do 4-7.
+ 4. Check what formula PC_where can be extracted from PC to be pushed
+ into the WHERE clause of the subquery
+ 5. Build PC_where and if PC_where is a conjunct(s) of PC remove it from PC
+ getting PC_having
+ 6. Prepare PC_where to be conjuncted with the WHERE clause of
+ the IN subquery
+ 7. Prepare PC_having to be conjuncted with the HAVING clause of
+ the IN subquery
+
+ @note
+ This method is similar to pushdown_cond_for_derived()
+
+ @retval TRUE if an error occurs
+ @retval FALSE otherwise
+*/
+
+bool Item_in_subselect::pushdown_cond_for_in_subquery(THD *thd, Item *cond)
+{
+ DBUG_ENTER("Item_in_subselect::pushdown_cond_for_in_subquery");
+ Item *remaining_cond= NULL;
+
+ if (!cond)
+ DBUG_RETURN(FALSE);
+
+ st_select_lex *sel = unit->first_select();
+
+ if (is_jtbm_const_tab)
+ DBUG_RETURN(FALSE);
+
+ if (!sel->cond_pushdown_is_allowed())
+ DBUG_RETURN(FALSE);
+
+ /*
+ Create a list of Field_pair items for this IN subquery.
+ It consists of the pairs of fields from the left part of this IN subquery
+ predicate 'left_part' and the respective fields from the select of the
+ right part of the IN subquery 'sel' (the field from left_part with the
+ corresponding field from the sel projection list).
+ Attach this list to the IN subquery.
+ */
+ corresponding_fields.empty();
+ List_iterator_fast<Item> it(sel->join->fields_list);
+ Item *item;
+ for (uint i= 0; i < left_expr->cols(); i++)
+ {
+ item= it++;
+ Item *elem= left_expr->element_index(i);
+
+ if (elem->real_item()->type() != Item::FIELD_ITEM)
+ continue;
+
+ if (corresponding_fields.push_back(
+ new Field_pair(((Item_field *)(elem->real_item()))->field,
+ item)))
+ DBUG_RETURN(TRUE);
+ }
+
+ /* 1. Check what pushable formula can be extracted from cond */
+ Item *extracted_cond;
+ cond->check_pushable_cond(&Item::pushable_cond_checker_for_subquery,
+ (uchar *)this);
+ /* 2. Build a clone PC of the formula that can be extracted */
+ extracted_cond=
+ cond->build_pushable_cond(thd,
+ &Item::pushable_equality_checker_for_subquery,
+ (uchar *)this);
+ /* Nothing to push */
+ if (!extracted_cond)
+ {
+ DBUG_RETURN(FALSE);
+ }
+
+ /* Collect fields that are used in the GROUP BY of sel */
+ st_select_lex *save_curr_select= thd->lex->current_select;
+ if (sel->have_window_funcs())
+ {
+ if (sel->group_list.first || sel->join->implicit_grouping)
+ goto exit;
+ ORDER *common_partition_fields=
+ sel->find_common_window_func_partition_fields(thd);
+ if (!common_partition_fields)
+ goto exit;
+
+ if (grouping_fields_in_the_in_subq_left_part(thd, sel, &corresponding_fields,
+ common_partition_fields))
+ DBUG_RETURN(TRUE);
+ }
+ else if (grouping_fields_in_the_in_subq_left_part(thd, sel,
+ &corresponding_fields,
+ sel->group_list.first))
+ DBUG_RETURN(TRUE);
+
+ /* Do 4-6 */
+ sel->pushdown_cond_into_where_clause(thd, extracted_cond,
+ &remaining_cond,
+ &Item::in_subq_field_transformer_for_where,
+ (uchar *) this);
+ if (!remaining_cond)
+ goto exit;
+ /*
+ 7. Prepare PC_having to be conjuncted with the HAVING clause of
+ the IN subquery
+ */
+ remaining_cond=
+ remaining_cond->transform(thd,
+ &Item::in_subq_field_transformer_for_having,
+ (uchar *)this);
+ if (!remaining_cond)
+ goto exit;
+
+ remaining_cond->walk(&Item::cleanup_excluding_const_fields_processor,
+ 0, 0);
+ sel->cond_pushed_into_having= remaining_cond;
+
+exit:
+ thd->lex->current_select= save_curr_select;
+ DBUG_RETURN(FALSE);
+}
diff --git a/sql/opt_subselect.h b/sql/opt_subselect.h
index 9cb19e0cc6c..031118288b9 100644
--- a/sql/opt_subselect.h
+++ b/sql/opt_subselect.h
@@ -26,8 +26,15 @@ int check_and_do_in_subquery_rewrites(JOIN *join);
bool convert_join_subqueries_to_semijoins(JOIN *join);
int pull_out_semijoin_tables(JOIN *join);
bool optimize_semijoin_nests(JOIN *join, table_map all_table_map);
-bool setup_jtbm_semi_joins(JOIN *join, List<TABLE_LIST> *join_list,
- Item **join_where);
+Item *and_new_conditions_to_optimized_cond(THD *thd, Item *cond,
+ COND_EQUAL **cond_eq,
+ List<Item> &new_conds,
+ Item::cond_result *cond_value);
+bool setup_degenerate_jtbm_semi_joins(JOIN *join,
+ List<TABLE_LIST> *join_list,
+ List<Item> &eq_list);
+bool setup_jtbm_semi_joins(JOIN *join, List<TABLE_LIST> *join_list,
+ List<Item> &eq_list);
void cleanup_empty_jtbm_semi_joins(JOIN *join, List<TABLE_LIST> *join_list);
// used by Loose_scan_opt
diff --git a/sql/opt_sum.cc b/sql/opt_sum.cc
index 82946709166..ecede5903a2 100644
--- a/sql/opt_sum.cc
+++ b/sql/opt_sum.cc
@@ -318,7 +318,7 @@ int opt_sum_query(THD *thd,
error= tl->table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
if (unlikely(error))
{
- tl->table->file->print_error(error, MYF(ME_FATALERROR));
+ tl->table->file->print_error(error, MYF(ME_FATAL));
DBUG_RETURN(error);
}
count*= tl->table->file->stats.records;
diff --git a/sql/procedure.h b/sql/procedure.h
index 1ece31223ad..8826b397fb2 100644
--- a/sql/procedure.h
+++ b/sql/procedure.h
@@ -44,6 +44,16 @@ public:
this->name.length= strlen(name_par);
}
enum Type type() const { return Item::PROC_ITEM; }
+ Field *create_tmp_field_ex(TABLE *table, Tmp_field_src *src,
+ const Tmp_field_param *param)
+ {
+ /*
+ We can get to here when using a CURSOR for a query with PROCEDURE:
+ DECLARE c CURSOR FOR SELECT * FROM t1 PROCEDURE analyse();
+ OPEN c;
+ */
+ return create_tmp_field_ex_simple(table, src, param);
+ }
virtual void set(double nr)=0;
virtual void set(const char *str,uint length,CHARSET_INFO *cs)=0;
virtual void set(longlong nr)=0;
diff --git a/sql/rpl_mi.cc b/sql/rpl_mi.cc
index 6f659aa12ad..897d4394525 100644
--- a/sql/rpl_mi.cc
+++ b/sql/rpl_mi.cc
@@ -1091,7 +1091,7 @@ bool Master_info_index::init_all_master_info()
if ((index_file_nr= my_open(index_file_name,
O_RDWR | O_CREAT | O_BINARY ,
- MYF(MY_WME | ME_NOREFRESH))) < 0 ||
+ MYF(MY_WME | ME_ERROR_LOG))) < 0 ||
my_sync(index_file_nr, MYF(MY_WME)) ||
init_io_cache(&index_file, index_file_nr,
IO_SIZE, READ_CACHE,
@@ -1307,7 +1307,7 @@ Master_info *get_master_info(const LEX_CSTRING *connection_name,
if (warning != Sql_condition::WARN_LEVEL_NOTE)
my_error(WARN_NO_MASTER_INFO,
MYF(warning == Sql_condition::WARN_LEVEL_WARN ?
- ME_JUST_WARNING : 0),
+ ME_WARNING : 0),
(int) connection_name->length, connection_name->str);
mysql_mutex_unlock(&LOCK_active_mi);
DBUG_RETURN(0);
@@ -1377,7 +1377,7 @@ Master_info_index::get_master_info(const LEX_CSTRING *connection_name,
if (!mi && warning != Sql_condition::WARN_LEVEL_NOTE)
{
my_error(WARN_NO_MASTER_INFO,
- MYF(warning == Sql_condition::WARN_LEVEL_WARN ? ME_JUST_WARNING :
+ MYF(warning == Sql_condition::WARN_LEVEL_WARN ? ME_WARNING :
0),
(int) connection_name->length,
connection_name->str);
diff --git a/sql/rpl_record.cc b/sql/rpl_record.cc
index db579a63ce0..94c1f08e4e3 100644
--- a/sql/rpl_record.cc
+++ b/sql/rpl_record.cc
@@ -497,7 +497,9 @@ int prepare_record(TABLE *const table, const uint skip, const bool check)
DBUG_RETURN(0);
}
/**
- Fills @c table->record[0] with computed values of extra persistent column which are present on slave but not on master.
+ Fills @c table->record[0] with computed values of extra persistent column
+ which are present on slave but not on master.
+
@param table Table whose record[0] buffer is prepared.
@param master_cols No of columns on master
@returns 0 on success
@@ -514,10 +516,8 @@ int fill_extra_persistent_columns(TABLE *table, int master_cols)
vfield= *vfield_ptr;
if (vfield->field_index >= master_cols && vfield->stored_in_db())
{
- /*Set bitmap for writing*/
- bitmap_set_bit(table->vcol_set, vfield->field_index);
+ bitmap_set_bit(table->write_set, vfield->field_index);
error= vfield->vcol_info->expr->save_in_field(vfield,0);
- bitmap_clear_bit(table->vcol_set, vfield->field_index);
}
}
return error;
diff --git a/sql/sp.cc b/sql/sp.cc
index af86737ebb9..723f30ec85d 100644
--- a/sql/sp.cc
+++ b/sql/sp.cc
@@ -1468,7 +1468,7 @@ log:
log_query.ptr(), log_query.length(),
FALSE, FALSE, FALSE, 0))
{
- my_error(ER_ERROR_ON_WRITE, MYF(MY_WME), "binary log", -1);
+ my_error(ER_ERROR_ON_WRITE, MYF(0), "binary log", -1);
goto done;
}
thd->variables.sql_mode= 0;
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index 3a9e83d9d09..ea3ddcf617d 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -75,9 +75,8 @@ sp_map_item_type(const Type_handler *handler)
{
if (handler == &type_handler_row)
return Item::ROW_ITEM;
- enum_field_types type= real_type_to_type(handler->real_field_type());
- switch (type) {
+ switch (handler->real_field_type()) {
case MYSQL_TYPE_BIT:
case MYSQL_TYPE_TINY:
case MYSQL_TYPE_SHORT:
@@ -4573,7 +4572,7 @@ sp_instr_set_case_expr::exec_core(THD *thd, uint *nextp)
thd->spcont->set_case_expr(thd, m_case_expr_id, &null_item))
{
/* If this also failed, we have to abort. */
- my_error(ER_OUT_OF_RESOURCES, MYF(ME_FATALERROR));
+ my_error(ER_OUT_OF_RESOURCES, MYF(ME_FATAL));
}
}
else
diff --git a/sql/sql_analyse.cc b/sql/sql_analyse.cc
index 6626a054052..0990379add7 100644
--- a/sql/sql_analyse.cc
+++ b/sql/sql_analyse.cc
@@ -68,6 +68,25 @@ int compare_decimal2(int* len, const char *s, const char *t)
}
+static bool
+prepare_param(THD *thd, Item **item, const char *proc_name, uint pos)
+{
+ if ((*item)->fix_fields_if_needed(thd, item))
+ {
+ DBUG_PRINT("info", ("fix_fields() for the parameter %u failed", pos));
+ return true;
+ }
+ if ((*item)->type_handler()->result_type() != INT_RESULT ||
+ !(*item)->basic_const_item() ||
+ (*item)->val_real() < 0)
+ {
+ my_error(ER_WRONG_PARAMETERS_TO_PROCEDURE, MYF(0), proc_name);
+ return true;
+ }
+ return false;
+}
+
+
Procedure *
proc_analyse_init(THD *thd, ORDER *param, select_result *result,
List<Item> &field_list)
@@ -88,17 +107,8 @@ proc_analyse_init(THD *thd, ORDER *param, select_result *result,
else if (param->next)
{
// first parameter
- if ((*param->item)->fix_fields_if_needed(thd, param->item))
- {
- DBUG_PRINT("info", ("fix_fields() for the first parameter failed"));
- goto err;
- }
- if ((*param->item)->type() != Item::INT_ITEM ||
- (*param->item)->val_real() < 0)
- {
- my_error(ER_WRONG_PARAMETERS_TO_PROCEDURE, MYF(0), proc_name);
+ if (prepare_param(thd, param->item, proc_name, 0))
goto err;
- }
pc->max_tree_elements = (uint) (*param->item)->val_int();
param = param->next;
if (param->next) // no third parameter possible
@@ -107,25 +117,12 @@ proc_analyse_init(THD *thd, ORDER *param, select_result *result,
goto err;
}
// second parameter
- if ((*param->item)->fix_fields_if_needed(thd, param->item))
- {
- DBUG_PRINT("info", ("fix_fields() for the second parameter failed"));
+ if (prepare_param(thd, param->item, proc_name, 1))
goto err;
- }
- if ((*param->item)->type() != Item::INT_ITEM ||
- (*param->item)->val_real() < 0)
- {
- my_error(ER_WRONG_PARAMETERS_TO_PROCEDURE, MYF(0), proc_name);
- goto err;
- }
pc->max_treemem = (uint) (*param->item)->val_int();
}
- else if ((*param->item)->type() != Item::INT_ITEM ||
- (*param->item)->val_real() < 0)
- {
- my_error(ER_WRONG_PARAMETERS_TO_PROCEDURE, MYF(0), proc_name);
+ else if (prepare_param(thd, param->item, proc_name, 0))
goto err;
- }
// if only one parameter was given, it will be the value of max_tree_elements
else
{
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 80939cbe59b..00f45b1edf1 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -5412,43 +5412,27 @@ static void update_field_dependencies(THD *thd, Field *field, TABLE *table)
DBUG_ENTER("update_field_dependencies");
if (should_mark_column(thd->column_usage))
{
- MY_BITMAP *bitmap;
-
/*
We always want to register the used keys, as the column bitmap may have
been set for all fields (for example for view).
*/
-
table->covering_keys.intersect(field->part_of_key);
- if (field->vcol_info)
- table->mark_virtual_col(field);
-
if (thd->column_usage == MARK_COLUMNS_READ)
- bitmap= table->read_set;
+ {
+ if (table->mark_column_with_deps(field))
+ DBUG_VOID_RETURN; // Field was already marked
+ }
else
- bitmap= table->write_set;
-
- /*
- The test-and-set mechanism in the bitmap is not reliable during
- multi-UPDATE statements under MARK_COLUMNS_READ mode
- (thd->column_usage == MARK_COLUMNS_READ), as this bitmap contains
- only those columns that are used in the SET clause. I.e they are being
- set here. See multi_update::prepare()
- */
- if (bitmap_fast_test_and_set(bitmap, field->field_index))
{
- if (thd->column_usage == MARK_COLUMNS_WRITE)
+ if (bitmap_fast_test_and_set(table->write_set, field->field_index))
{
DBUG_PRINT("warning", ("Found duplicated field"));
thd->dup_field= field;
+ DBUG_VOID_RETURN;
}
- else
- {
- DBUG_PRINT("note", ("Field found before"));
- }
- DBUG_VOID_RETURN;
}
+
table->used_fields++;
}
if (table->get_fields_in_item_tree)
@@ -7864,18 +7848,9 @@ insert_fields(THD *thd, Name_resolution_context *context, const char *db_name,
if ((field= field_iterator.field()))
{
- /* Mark fields as used to allow storage engine to optimze access */
- bitmap_set_bit(field->table->read_set, field->field_index);
- /*
- Mark virtual fields for write and others that the virtual fields
- depend on for read.
- */
- if (field->vcol_info)
- field->table->mark_virtual_col(field);
+ field->table->mark_column_with_deps(field);
if (table)
- {
table->covering_keys.intersect(field->part_of_key);
- }
if (tables->is_natural_join)
{
TABLE *field_table;
diff --git a/sql/sql_binlog.cc b/sql/sql_binlog.cc
index 00270fb6f32..1fa3cca7c27 100644
--- a/sql/sql_binlog.cc
+++ b/sql/sql_binlog.cc
@@ -173,7 +173,7 @@ void mysql_client_binlog_statement(THD* thd)
*/
if (!(rli && buf))
{
- my_error(ER_OUTOFMEMORY, MYF(ME_FATALERROR), 1); /* needed 1 bytes */
+ my_error(ER_OUTOFMEMORY, MYF(ME_FATAL), 1); /* needed 1 bytes */
goto end;
}
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index d2e4f66dd59..df9c60ba6f0 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -1500,7 +1500,7 @@ bool THD::set_db(const LEX_CSTRING *new_db)
const char *tmp= NULL;
if (new_db->str)
{
- if (!(tmp= my_strndup(new_db->str, new_db->length, MYF(MY_WME | ME_FATALERROR))))
+ if (!(tmp= my_strndup(new_db->str, new_db->length, MYF(MY_WME | ME_FATAL))))
result= 1;
}
@@ -2659,7 +2659,7 @@ CHANGED_TABLE_LIST* THD::changed_table_dup(const char *key, size_t key_length)
key_length + 1);
if (!new_table)
{
- my_error(EE_OUTOFMEMORY, MYF(ME_BELL+ME_FATALERROR),
+ my_error(EE_OUTOFMEMORY, MYF(ME_FATAL),
ALIGN_SIZE(sizeof(TABLE_LIST)) + key_length + 1);
set_killed(KILL_CONNECTION);
return 0;
@@ -3316,7 +3316,7 @@ int select_export::send_data(List<Item> &items)
set_if_smaller(estimated_bytes, UINT_MAX32);
if (cvt_str.realloc((uint32) estimated_bytes))
{
- my_error(ER_OUTOFMEMORY, MYF(ME_FATALERROR), (uint32) estimated_bytes);
+ my_error(ER_OUTOFMEMORY, MYF(ME_FATAL), (uint32) estimated_bytes);
goto err;
}
@@ -3574,7 +3574,7 @@ int select_singlerow_subselect::send_data(List<Item> &items)
if (it->assigned())
{
my_message(ER_SUBQUERY_NO_1_ROW, ER_THD(thd, ER_SUBQUERY_NO_1_ROW),
- MYF(current_thd->lex->ignore ? ME_JUST_WARNING : 0));
+ MYF(current_thd->lex->ignore ? ME_WARNING : 0));
DBUG_RETURN(1);
}
if (unit->offset_limit_cnt)
diff --git a/sql/sql_cte.cc b/sql/sql_cte.cc
index 97bbf8f73bd..693ea9f0c5b 100644
--- a/sql/sql_cte.cc
+++ b/sql/sql_cte.cc
@@ -764,7 +764,7 @@ bool With_element::set_unparsed_spec(THD *thd, char *spec_start, char *spec_end)
if (!unparsed_spec.str)
{
- my_error(ER_OUTOFMEMORY, MYF(ME_FATALERROR),
+ my_error(ER_OUTOFMEMORY, MYF(ME_FATAL),
static_cast<int>(unparsed_spec.length));
return true;
}
diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc
index b6ca2e956cb..096d5b15af1 100644
--- a/sql/sql_delete.cc
+++ b/sql/sql_delete.cc
@@ -766,7 +766,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
else
{
table->file->print_error(error,
- MYF(thd->lex->ignore ? ME_JUST_WARNING : 0));
+ MYF(thd->lex->ignore ? ME_WARNING : 0));
if (thd->is_error())
{
error= 1;
diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc
index 6a2e956fbf3..39630293c20 100644
--- a/sql/sql_derived.cc
+++ b/sql/sql_derived.cc
@@ -1239,25 +1239,61 @@ bool mysql_derived_reinit(THD *thd, LEX *lex, TABLE_LIST *derived)
/**
@brief
- Extract the condition depended on derived table/view and pushed it there
+ Extract condition that can be pushed into a derived table/view
- @param thd The thread handle
- @param cond The condition from which to extract the pushed condition
- @param derived The reference to the derived table/view
+ @param thd the thread handle
+ @param cond current condition
+ @param derived the reference to the derived table/view
@details
- This functiom builds the most restrictive condition depending only on
- the derived table/view that can be extracted from the condition cond.
- The built condition is pushed into the having clauses of the
- selects contained in the query specifying the derived table/view.
- The function also checks for each select whether any condition depending
- only on grouping fields can be extracted from the pushed condition.
- If so, it pushes the condition over grouping fields into the where
- clause of the select.
-
- @retval
- true if an error is reported
- false otherwise
+ This function builds the most restrictive condition depending only on
+ the derived table/view (directly or indirectly through equality) that
+ can be extracted from the given condition cond and pushes it into the
+ derived table/view.
+
+ Example of the transformation:
+
+ SELECT *
+ FROM t1,
+ (
+ SELECT x,MAX(y) AS max_y
+ FROM t2
+ GROUP BY x
+ ) AS d_tab
+ WHERE d_tab.x>1 AND d_tab.max_y<30;
+
+ =>
+
+ SELECT *
+ FROM t1,
+ (
+ SELECT x,z,MAX(y) AS max_y
+ FROM t2
+ WHERE x>1
+ HAVING max_y<30
+ GROUP BY x
+ ) AS d_tab
+ WHERE d_tab.x>1 AND d_tab.max_y<30;
+
+ In details:
+ 1. Check what pushable formula can be extracted from cond
+ 2. Build a clone PC of the formula that can be extracted
+ (the clone is built only if the extracted formula is a AND subformula
+ of cond or conjunction of such subformulas)
+ Do for every select specifying derived table/view:
+ 3. If there is no HAVING clause prepare PC to be conjuncted with
+ WHERE clause of the select. Otherwise do 4-7.
+ 4. Check what formula PC_where can be extracted from PC to be pushed
+ into the WHERE clause of the select
+ 5. Build PC_where and if PC_where is a conjunct(s) of PC remove it from PC
+ getting PC_having
+ 6. Prepare PC_where to be conjuncted with the WHERE clause of the select
+ 7. Prepare PC_having to be conjuncted with the HAVING clause of the select
+ @note
+ This method is similar to pushdown_cond_for_in_subquery()
+
+ @retval TRUE if an error occurs
+ @retval FALSE otherwise
*/
bool pushdown_cond_for_derived(THD *thd, Item *cond, TABLE_LIST *derived)
@@ -1297,63 +1333,25 @@ bool pushdown_cond_for_derived(THD *thd, Item *cond, TABLE_LIST *derived)
if (!some_select_allows_cond_pushdown)
DBUG_RETURN(false);
- /*
- Build the most restrictive condition extractable from 'cond'
- that can be pushed into the derived table 'derived'.
- All subexpressions of this condition are cloned from the
- subexpressions of 'cond'.
- This condition has to be fixed yet.
- */
+ /* 1. Check what pushable formula can be extracted from cond */
Item *extracted_cond;
- derived->check_pushable_cond_for_table(cond);
- extracted_cond= derived->build_pushable_cond_for_table(thd, cond);
+ cond->check_pushable_cond(&Item::pushable_cond_checker_for_derived,
+ (uchar *)(&derived->table->map));
+ /* 2. Build a clone PC of the formula that can be extracted */
+ extracted_cond=
+ cond->build_pushable_cond(thd,
+ &Item::pushable_equality_checker_for_derived,
+ ((uchar *)&derived->table->map));
if (!extracted_cond)
{
/* Nothing can be pushed into the derived table */
DBUG_RETURN(false);
}
- /* Push extracted_cond into every select of the unit specifying 'derived' */
+
st_select_lex *save_curr_select= thd->lex->current_select;
for (; sl; sl= sl->next_select())
{
Item *extracted_cond_copy;
- if (!sl->cond_pushdown_is_allowed())
- continue;
- thd->lex->current_select= sl;
- if (sl->have_window_funcs())
- {
- if (sl->join->group_list || sl->join->implicit_grouping)
- continue;
- ORDER *common_partition_fields=
- sl->find_common_window_func_partition_fields(thd);
- if (!common_partition_fields)
- continue;
- extracted_cond_copy= !sl->next_select() ?
- extracted_cond :
- extracted_cond->build_clone(thd);
- if (!extracted_cond_copy)
- continue;
-
- Item *cond_over_partition_fields;;
- sl->collect_grouping_fields(thd, common_partition_fields);
- sl->check_cond_extraction_for_grouping_fields(extracted_cond_copy,
- derived);
- cond_over_partition_fields=
- sl->build_cond_for_grouping_fields(thd, extracted_cond_copy, true);
- if (cond_over_partition_fields)
- cond_over_partition_fields= cond_over_partition_fields->transform(thd,
- &Item::derived_grouping_field_transformer_for_where,
- (uchar*) sl);
- if (cond_over_partition_fields)
- {
- cond_over_partition_fields->walk(
- &Item::cleanup_excluding_const_fields_processor, 0, 0);
- sl->cond_pushed_into_where= cond_over_partition_fields;
- }
-
- continue;
- }
-
/*
For each select of the unit except the last one
create a clone of extracted_cond
@@ -1364,73 +1362,44 @@ bool pushdown_cond_for_derived(THD *thd, Item *cond, TABLE_LIST *derived)
if (!extracted_cond_copy)
continue;
- if (!sl->join->group_list && !sl->with_sum_func)
- {
- /* extracted_cond_copy is pushed into where of sl */
- extracted_cond_copy= extracted_cond_copy->transform(thd,
- &Item::derived_field_transformer_for_where,
- (uchar*) sl);
- if (extracted_cond_copy)
- {
- extracted_cond_copy->walk(
- &Item::cleanup_excluding_const_fields_processor, 0, 0);
- sl->cond_pushed_into_where= extracted_cond_copy;
- }
-
- continue;
- }
-
- /*
- Figure out what can be extracted from the pushed condition
- that could be pushed into the where clause of sl
- */
- Item *cond_over_grouping_fields;
- sl->collect_grouping_fields(thd, sl->join->group_list);
- sl->check_cond_extraction_for_grouping_fields(extracted_cond_copy,
- derived);
- cond_over_grouping_fields=
- sl->build_cond_for_grouping_fields(thd, extracted_cond_copy, true);
-
- /*
- Transform the references to the 'derived' columns from the condition
- pushed into the where clause of sl to make them usable in the new context
- */
- if (cond_over_grouping_fields)
- cond_over_grouping_fields= cond_over_grouping_fields->transform(thd,
- &Item::derived_grouping_field_transformer_for_where,
- (uchar*) sl);
-
- if (cond_over_grouping_fields)
+ /* Collect fields that are used in the GROUP BY of sl */
+ if (sl->have_window_funcs())
{
- /*
- In extracted_cond_copy remove top conjuncts that
- has been pushed into the where clause of sl
- */
- extracted_cond_copy= remove_pushed_top_conjuncts(thd, extracted_cond_copy);
-
- cond_over_grouping_fields->walk(
- &Item::cleanup_excluding_const_fields_processor, 0, 0);
- sl->cond_pushed_into_where= cond_over_grouping_fields;
-
- if (!extracted_cond_copy)
+ if (sl->group_list.first || sl->join->implicit_grouping)
+ continue;
+ ORDER *common_partition_fields=
+ sl->find_common_window_func_partition_fields(thd);
+ if (!common_partition_fields)
continue;
+ sl->collect_grouping_fields(thd, common_partition_fields);
}
+ else
+ sl->collect_grouping_fields(thd, sl->group_list.first);
+
+ Item *remaining_cond= NULL;
+ /* Do 4-6 */
+ sl->pushdown_cond_into_where_clause(thd, extracted_cond_copy,
+ &remaining_cond,
+ &Item::derived_field_transformer_for_where,
+ (uchar *) sl);
+ if (!remaining_cond)
+ continue;
/*
- Transform the references to the 'derived' columns from the condition
- pushed into the having clause of sl to make them usable in the new context
+ 7. Prepare PC_having to be conjuncted with the HAVING clause of
+ the select
*/
- extracted_cond_copy= extracted_cond_copy->transform(thd,
- &Item::derived_field_transformer_for_having,
- (uchar*) sl);
- if (!extracted_cond_copy)
+ remaining_cond=
+ remaining_cond->transform(thd,
+ &Item::derived_field_transformer_for_having,
+ (uchar *) sl);
+ if (!remaining_cond)
continue;
- extracted_cond_copy->walk(&Item::cleanup_excluding_const_fields_processor,
- 0, 0);
- sl->cond_pushed_into_having= extracted_cond_copy;
+ remaining_cond->walk(&Item::cleanup_excluding_const_fields_processor,
+ 0, 0);
+ sl->cond_pushed_into_having= remaining_cond;
}
thd->lex->current_select= save_curr_select;
DBUG_RETURN(false);
}
-
diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc
index c2f161d507d..7c2ccf1b155 100644
--- a/sql/sql_handler.cc
+++ b/sql/sql_handler.cc
@@ -433,8 +433,6 @@ bool mysql_ha_open(THD *thd, TABLE_LIST *tables, SQL_HANDLER *reopen)
/* Always read all columns */
table->read_set= &table->s->all_set;
- if (table->vcol_set)
- table->vcol_set= &table->s->all_set;
/* Restore the state. */
thd->set_open_tables(backup_open_tables);
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index a60a6f2975e..6eefa322bf2 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -1719,7 +1719,7 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
*/
if (info->ignore)
{
- table->file->print_error(error, MYF(ME_JUST_WARNING));
+ table->file->print_error(error, MYF(ME_WARNING));
goto ok_or_after_trg_err; /* Ignoring a not fatal error, return 0 */
}
goto err;
@@ -1844,7 +1844,7 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
{
if (!(thd->variables.old_behavior &
OLD_MODE_NO_DUP_KEY_WARNINGS_WITH_IGNORE))
- table->file->print_error(error, MYF(ME_JUST_WARNING));
+ table->file->print_error(error, MYF(ME_WARNING));
goto ok_or_after_trg_err;
}
goto err;
@@ -2026,7 +2026,7 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
goto err;
if (!(thd->variables.old_behavior &
OLD_MODE_NO_DUP_KEY_WARNINGS_WITH_IGNORE))
- table->file->print_error(error, MYF(ME_JUST_WARNING));
+ table->file->print_error(error, MYF(ME_WARNING));
table->file->restore_auto_increment(prev_insert_id);
goto ok_or_after_trg_err;
}
@@ -2360,7 +2360,7 @@ bool delayed_get_table(THD *thd, MDL_request *grl_protection_request,
di->thd.set_db(&table_list->db);
di->thd.set_query(my_strndup(table_list->table_name.str,
table_list->table_name.length,
- MYF(MY_WME | ME_FATALERROR)),
+ MYF(MY_WME | ME_FATAL)),
table_list->table_name.length, system_charset_info);
if (di->thd.db.str == NULL || di->thd.query() == NULL)
{
@@ -2392,7 +2392,7 @@ bool delayed_get_table(THD *thd, MDL_request *grl_protection_request,
mysql_mutex_unlock(&di->mutex);
di->unlock();
delete di;
- my_error(ER_CANT_CREATE_THREAD, MYF(ME_FATALERROR), error);
+ my_error(ER_CANT_CREATE_THREAD, MYF(ME_FATAL), error);
goto end_create;
}
@@ -2605,10 +2605,6 @@ TABLE *Delayed_insert::get_local_table(THD* client_thd)
share->default_fields)
{
bool error_reported= FALSE;
- if (unlikely(!(copy->def_vcol_set=
- (MY_BITMAP*) alloc_root(client_thd->mem_root,
- sizeof(MY_BITMAP)))))
- goto error;
if (unlikely(parse_vcol_defs(client_thd, client_thd->mem_root, copy,
&error_reported)))
goto error;
@@ -2627,15 +2623,6 @@ TABLE *Delayed_insert::get_local_table(THD* client_thd)
copy->def_write_set.bitmap= ((my_bitmap_map*)
(bitmap + share->column_bitmap_size));
bitmaps_used= 2;
- if (share->virtual_fields)
- {
- my_bitmap_init(copy->def_vcol_set,
- (my_bitmap_map*) (bitmap +
- bitmaps_used*share->column_bitmap_size),
- share->fields, FALSE);
- bitmaps_used++;
- copy->vcol_set= copy->def_vcol_set;
- }
if (share->default_fields || share->default_expressions)
{
my_bitmap_init(&copy->has_value_set,
@@ -3261,7 +3248,7 @@ bool Delayed_insert::handle_inserts(void)
or if another thread is removing the current table definition
from the table cache.
*/
- my_error(ER_DELAYED_CANT_CHANGE_LOCK, MYF(ME_FATALERROR | ME_NOREFRESH),
+ my_error(ER_DELAYED_CANT_CHANGE_LOCK, MYF(ME_FATAL | ME_ERROR_LOG),
table->s->table_name.str);
goto err;
}
@@ -3434,7 +3421,7 @@ bool Delayed_insert::handle_inserts(void)
{
/* This is not known to happen. */
my_error(ER_DELAYED_CANT_CHANGE_LOCK,
- MYF(ME_FATALERROR | ME_NOREFRESH),
+ MYF(ME_FATAL | ME_ERROR_LOG),
table->s->table_name.str);
goto err;
}
@@ -4081,9 +4068,9 @@ void select_insert::abort_result_set() {
Field *Item::create_field_for_create_select(TABLE *table)
{
- Field *def_field, *tmp_field;
- return ::create_tmp_field(table->in_use, table, this, type(),
- (Item ***) 0, &tmp_field, &def_field, 0, 0, 0, 0);
+ static Tmp_field_param param(false, false, false, false);
+ Tmp_field_src src;
+ return create_tmp_field_ex(table, &src, &param);
}
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 39cf4cd1e46..9922bdf7e59 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -2906,8 +2906,7 @@ void st_select_lex::print_order(String *str,
else
{
/* replace numeric reference with equivalent for ORDER constant */
- if (order->item[0]->type() == Item::INT_ITEM &&
- order->item[0]->basic_const_item())
+ if (order->item[0]->is_order_clause_position())
{
/* make it expression instead of integer constant */
str->append(STRING_WITH_LEN("''"));
@@ -4349,7 +4348,7 @@ void SELECT_LEX::update_used_tables()
tab->covering_keys= tab->s->keys_for_keyread;
tab->covering_keys.intersect(tab->keys_in_use_for_query);
/*
- View/derived was merged. Need to recalculate read_set/vcol_set
+ View/derived was merged. Need to recalculate read_set
bitmaps here. For example:
CREATE VIEW v1 AS SELECT f1,f2,f3 FROM t1;
SELECT f1 FROM v1;
@@ -4358,8 +4357,6 @@ void SELECT_LEX::update_used_tables()
be in the read_set.
*/
bitmap_clear_all(tab->read_set);
- if (tab->vcol_set)
- bitmap_clear_all(tab->vcol_set);
break;
}
}
@@ -6960,11 +6957,9 @@ Item *LEX::create_item_limit(THD *thd, const Lex_ident_cli_st *ca)
#endif
safe_to_cache_query= 0;
- if (unlikely(item->type() != Item::INT_ITEM))
- {
- my_error(ER_WRONG_SPVAR_TYPE_IN_LIMIT, MYF(0));
+ if (!item->is_valid_limit_clause_variable_with_error())
return NULL;
- }
+
item->limit_clause_param= true;
return item;
}
@@ -6994,11 +6989,8 @@ Item *LEX::create_item_limit(THD *thd,
if (unlikely(!(item= create_item_spvar_row_field(thd, rh, &sa, &sb, spv,
ca->pos(), cb->end()))))
return NULL;
- if (unlikely(item->type() != Item::INT_ITEM))
- {
- my_error(ER_WRONG_SPVAR_TYPE_IN_LIMIT, MYF(0));
+ if (!item->is_valid_limit_clause_variable_with_error())
return NULL;
- }
item->limit_clause_param= true;
return item;
}
@@ -7369,8 +7361,8 @@ void st_select_lex::collect_grouping_fields(THD *thd,
{
if ((*ord->item)->eq((Item*)item, 0))
{
- Grouping_tmp_field *grouping_tmp_field=
- new Grouping_tmp_field(master_unit()->derived->table->field[i], item);
+ Field_pair *grouping_tmp_field=
+ new Field_pair(master_unit()->derived->table->field[i], item);
grouping_tmp_fields.push_back(grouping_tmp_field);
}
}
@@ -7401,8 +7393,7 @@ void st_select_lex::collect_grouping_fields(THD *thd,
*/
void
-st_select_lex::check_cond_extraction_for_grouping_fields(Item *cond,
- TABLE_LIST *derived)
+st_select_lex::check_cond_extraction_for_grouping_fields(Item *cond)
{
cond->clear_extraction_flag();
if (cond->type() == Item::COND_ITEM)
@@ -7415,7 +7406,7 @@ st_select_lex::check_cond_extraction_for_grouping_fields(Item *cond,
Item *item;
while ((item=li++))
{
- check_cond_extraction_for_grouping_fields(item, derived);
+ check_cond_extraction_for_grouping_fields(item);
if (item->get_extraction_flag() != NO_EXTRACTION_FL)
{
count++;
@@ -7464,7 +7455,7 @@ st_select_lex::check_cond_extraction_for_grouping_fields(Item *cond,
to figure out whether a subformula depends only on these fields or not.
@note
The built condition C is always implied by the condition cond
- (cond => C). The method tries to build the most restictive such
+ (cond => C). The method tries to build the least restictive such
condition (i.e. for any other condition C' such that cond => C'
we have C => C').
@note
@@ -7890,6 +7881,129 @@ Item *Lex_trim_st::make_item_func_trim(THD *thd) const
}
+/**
+ @brief
+ Extract from given item a condition pushable into WHERE clause
+
+ @param thd the thread handle
+ @param cond the item to extract a condition to be pushed
+ into WHERE
+ @param remaining_cond the condition that will remain of cond after
+ the pushdown of its parts into the WHERE clause
+ @param transformer the transformer callback function to be
+ applied to the condition so it can be pushed
+ down into the WHERE clause of this select
+ @param arg parameter to be passed to the transformer
+
+ @details
+ This method checks if cond entirely or its parts can be
+ pushed into the WHERE clause of this select and prepares it for pushing.
+
+ First it checks wherever this select doesn't have any aggregation function
+ in its projection and GROUP BY clause. If so cond can be entirely
+ pushed into the WHERE clause of this select but before its fields should
+ be transformed with transformer_for_where to make it pushable.
+
+ Otherwise the method checks wherever any condition depending only on
+ grouping fields can be extracted from cond. If there is any it prepares it
+ for pushing using grouping_field_transformer_for_where and if it happens to
+ be a conjunct of cond it removes it from cond. It saves the result of
+ removal in remaining_cond.
+ The extracted condition is saved in cond_pushed_into_where of this select.
+
+ @note
+ When looking for pushable condition the method considers only the grouping
+ fields from the list grouping_tmp_fields whose elements are of the type
+ Field_pair. This list must be prepared before the call of the
+ function.
+
+ @note
+ This method is called for pushdown conditions into materialized
+ derived tables/views optimization.
+ Item::derived_field_transformer_for_where is passed as the actual
+ callback function.
+ Also it is called for pushdown conditions into materialized IN subqueries.
+ Item::in_subq_field_transformer_for_where is passed as the actual
+ callback function.
+*/
+
+void st_select_lex::pushdown_cond_into_where_clause(THD *thd, Item *cond,
+ Item **remaining_cond,
+ Item_transformer transformer,
+ uchar *arg)
+{
+ if (!cond_pushdown_is_allowed())
+ return;
+ thd->lex->current_select= this;
+ if (have_window_funcs())
+ {
+ Item *cond_over_partition_fields;
+ check_cond_extraction_for_grouping_fields(cond);
+ cond_over_partition_fields=
+ build_cond_for_grouping_fields(thd, cond, true);
+ if (cond_over_partition_fields)
+ cond_over_partition_fields= cond_over_partition_fields->transform(thd,
+ &Item::grouping_field_transformer_for_where,
+ (uchar*) this);
+ if (cond_over_partition_fields)
+ {
+ cond_over_partition_fields->walk(
+ &Item::cleanup_excluding_const_fields_processor, 0, 0);
+ cond_pushed_into_where= cond_over_partition_fields;
+ }
+
+ return;
+ }
+
+ if (!join->group_list && !with_sum_func)
+ {
+ cond=
+ cond->transform(thd, transformer, arg);
+ if (cond)
+ {
+ cond->walk(
+ &Item::cleanup_excluding_const_fields_processor, 0, 0);
+ cond_pushed_into_where= cond;
+ }
+
+ return;
+ }
+
+ /*
+ Figure out what can be extracted from cond
+ that could be pushed into the WHERE clause of this select
+ */
+ Item *cond_over_grouping_fields;
+ check_cond_extraction_for_grouping_fields(cond);
+ cond_over_grouping_fields=
+ build_cond_for_grouping_fields(thd, cond, true);
+
+ /*
+ Transform the references to the columns from the cond
+ pushed into the WHERE clause of this select to make them usable in
+ the new context
+ */
+ if (cond_over_grouping_fields)
+ cond_over_grouping_fields= cond_over_grouping_fields->transform(thd,
+ &Item::grouping_field_transformer_for_where,
+ (uchar*) this);
+
+ if (cond_over_grouping_fields)
+ {
+
+ /*
+ In cond remove top conjuncts that has been pushed into the WHERE
+ clause of this select
+ */
+ cond= remove_pushed_top_conjuncts(thd, cond);
+
+ cond_over_grouping_fields->walk(
+ &Item::cleanup_excluding_const_fields_processor, 0, 0);
+ cond_pushed_into_where= cond_over_grouping_fields;
+ }
+
+ *remaining_cond= cond;
+}
Item *LEX::make_item_func_call_generic(THD *thd, Lex_ident_cli_st *cdb,
Lex_ident_cli_st *cname, List<Item> *args)
{
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 70caa3b92b9..ebf643a5aa1 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -904,19 +904,19 @@ typedef Bounds_checked_array<Item*> Ref_ptr_array;
/*
- Structure which consists of the field and the item which
- produces this field.
+ Structure which consists of the field and the item that
+ corresponds to this field.
*/
-
-class Grouping_tmp_field :public Sql_alloc
+class Field_pair :public Sql_alloc
{
public:
- Field *tmp_field;
- Item *producing_item;
- Grouping_tmp_field(Field *fld, Item *item)
- :tmp_field(fld), producing_item(item) {}
+ Field *field;
+ Item *corresponding_item;
+ Field_pair(Field *fld, Item *item)
+ :field(fld), corresponding_item(item) {}
};
+
/*
SELECT_LEX - store information of parsed SELECT statment
*/
@@ -1135,7 +1135,8 @@ public:
nesting_map name_visibility_map;
table_map with_dep;
- List<Grouping_tmp_field> grouping_tmp_fields;
+ /* the structure to store fields that are used in the GROUP BY of this select */
+ List<Field_pair> grouping_tmp_fields;
/* it is for correct printing SELECT options */
thr_lock_type lock_type;
@@ -1340,9 +1341,8 @@ public:
With_element *find_table_def_in_with_clauses(TABLE_LIST *table);
bool check_unrestricted_recursive(bool only_standard_compliant);
bool check_subqueries_with_recursive_references();
- void collect_grouping_fields(THD *thd, ORDER *grouping_list);
- void check_cond_extraction_for_grouping_fields(Item *cond,
- TABLE_LIST *derived);
+ void collect_grouping_fields(THD *thd, ORDER *grouping_list);
+ void check_cond_extraction_for_grouping_fields(Item *cond);
Item *build_cond_for_grouping_fields(THD *thd, Item *cond,
bool no_to_clones);
@@ -1368,6 +1368,11 @@ public:
bool cond_pushdown_is_allowed() const
{ return !olap && !explicit_limit && !tvc; }
+ void pushdown_cond_into_where_clause(THD *thd, Item *extracted_cond,
+ Item **remaining_cond,
+ Item_transformer transformer,
+ uchar *arg);
+
private:
bool m_non_agg_field_used;
bool m_agg_func_used;
diff --git a/sql/sql_list.h b/sql/sql_list.h
index 0219c226803..9f4eaae43f1 100644
--- a/sql/sql_list.h
+++ b/sql/sql_list.h
@@ -608,7 +608,7 @@ struct ilink
struct ilink **prev,*next;
static void *operator new(size_t size) throw ()
{
- return (void*)my_malloc((uint)size, MYF(MY_WME | MY_FAE | ME_FATALERROR));
+ return (void*)my_malloc((uint)size, MYF(MY_WME | MY_FAE | ME_FATAL));
}
static void operator delete(void* ptr_arg, size_t)
{
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index a1307fb0b09..a722bebe7bc 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -7519,7 +7519,7 @@ bool check_stack_overrun(THD *thd, long margin,
if (ebuff) {
my_snprintf(ebuff, MYSQL_ERRMSG_SIZE, ER_THD(thd, ER_STACK_OVERRUN_NEED_MORE),
stack_used, my_thread_stack_size, margin);
- my_message(ER_STACK_OVERRUN_NEED_MORE, ebuff, MYF(ME_FATALERROR));
+ my_message(ER_STACK_OVERRUN_NEED_MORE, ebuff, MYF(ME_FATAL));
delete [] ebuff;
}
return 1;
@@ -9716,8 +9716,9 @@ Item *negate_expression(THD *thd, Item *expr)
{
/* it is NOT(NOT( ... )) */
Item *arg= ((Item_func *) expr)->arguments()[0];
+ const Type_handler *fh= arg->fixed_type_handler();
enum_parsing_place place= thd->lex->current_select->parsing_place;
- if (arg->is_bool_type() || place == IN_WHERE || place == IN_HAVING)
+ if ((fh && fh->is_bool_type()) || place == IN_WHERE || place == IN_HAVING)
return arg;
/*
if it is not boolean function then we have to emulate value of
diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc
index ffe632d5409..54907c0edbc 100644
--- a/sql/sql_partition.cc
+++ b/sql/sql_partition.cc
@@ -525,15 +525,10 @@ static bool create_full_part_field_array(THD *thd, TABLE *table,
full_part_field_array may be NULL if storage engine supports native
partitioning.
*/
- table->vcol_set= table->read_set= &part_info->full_part_field_set;
+ table->read_set= &part_info->full_part_field_set;
if ((ptr= part_info->full_part_field_array))
for (; *ptr; ptr++)
- {
- if ((*ptr)->vcol_info)
- table->mark_virtual_col(*ptr);
- else
- bitmap_fast_test_and_set(table->read_set, (*ptr)->field_index);
- }
+ table->mark_column_with_deps(*ptr);
table->default_column_bitmaps();
end:
@@ -2644,7 +2639,7 @@ char *generate_partition_syntax(THD *thd, partition_info *part_info,
default:
DBUG_ASSERT(0);
/* We really shouldn't get here, no use in continuing from here */
- my_error(ER_OUT_OF_RESOURCES, MYF(ME_FATALERROR));
+ my_error(ER_OUT_OF_RESOURCES, MYF(ME_FATAL));
DBUG_RETURN(NULL);
}
if (part_info->part_type == VERSIONING_PARTITION)
@@ -5991,7 +5986,7 @@ static bool mysql_change_partitions(ALTER_PARTITION_PARAM_TYPE *lpt)
lpt->pack_frm_data,
lpt->pack_frm_len))))
{
- file->print_error(error, MYF(error != ER_OUTOFMEMORY ? 0 : ME_FATALERROR));
+ file->print_error(error, MYF(error != ER_OUTOFMEMORY ? 0 : ME_FATAL));
}
if (mysql_trans_commit_alter_copy_data(thd))
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index fd526f9a660..8d8047601d5 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -1514,7 +1514,7 @@ static int mysql_test_select(Prepared_statement *stmt,
if (!lex->result && !(lex->result= new (stmt->mem_root) select_send(thd)))
{
- my_error(ER_OUTOFMEMORY, MYF(ME_FATALERROR),
+ my_error(ER_OUTOFMEMORY, MYF(ME_FATAL),
static_cast<int>(sizeof(select_send)));
goto error;
}
@@ -2084,7 +2084,7 @@ static bool mysql_test_multidelete(Prepared_statement *stmt,
if (add_item_to_list(thd, new (thd->mem_root)
Item_null(thd)))
{
- my_error(ER_OUTOFMEMORY, MYF(ME_FATALERROR), 0);
+ my_error(ER_OUTOFMEMORY, MYF(ME_FATAL), 0);
goto error;
}
@@ -4716,7 +4716,7 @@ bool Prepared_statement::execute(String *expanded_query, bool open_cursor)
alloc_query(thd, (char*) expanded_query->ptr(),
expanded_query->length()))
{
- my_error(ER_OUTOFMEMORY, MYF(ME_FATALERROR), expanded_query->length());
+ my_error(ER_OUTOFMEMORY, MYF(ME_FATAL), expanded_query->length());
goto error;
}
/*
diff --git a/sql/sql_priv.h b/sql/sql_priv.h
index e48b6195bb7..4e82b6a5d3a 100644
--- a/sql/sql_priv.h
+++ b/sql/sql_priv.h
@@ -228,6 +228,7 @@
#define OPTIMIZER_SWITCH_ORDERBY_EQ_PROP (1ULL << 29)
#define OPTIMIZER_SWITCH_COND_PUSHDOWN_FOR_DERIVED (1ULL << 30)
#define OPTIMIZER_SWITCH_SPLIT_MATERIALIZED (1ULL << 31)
+#define OPTIMIZER_SWITCH_COND_PUSHDOWN_FOR_SUBQUERY (1ULL << 32)
#define OPTIMIZER_SWITCH_DEFAULT (OPTIMIZER_SWITCH_INDEX_MERGE | \
OPTIMIZER_SWITCH_INDEX_MERGE_UNION | \
@@ -254,7 +255,8 @@
OPTIMIZER_SWITCH_EXISTS_TO_IN | \
OPTIMIZER_SWITCH_ORDERBY_EQ_PROP | \
OPTIMIZER_SWITCH_COND_PUSHDOWN_FOR_DERIVED | \
- OPTIMIZER_SWITCH_SPLIT_MATERIALIZED)
+ OPTIMIZER_SWITCH_SPLIT_MATERIALIZED | \
+ OPTIMIZER_SWITCH_COND_PUSHDOWN_FOR_SUBQUERY)
/*
Replication uses 8 bytes to store SQL_MODE in the binary log. The day you
diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc
index f01ec789186..aa07dc07aa2 100644
--- a/sql/sql_repl.cc
+++ b/sql/sql_repl.cc
@@ -3840,8 +3840,7 @@ int reset_master(THD* thd, rpl_gtid *init_state, uint32 init_state_len,
if (!mysql_bin_log.is_open())
{
my_message(ER_FLUSH_MASTER_BINLOG_CLOSED,
- ER_THD(thd, ER_FLUSH_MASTER_BINLOG_CLOSED),
- MYF(ME_BELL+ME_WAITTANG));
+ ER_THD(thd, ER_FLUSH_MASTER_BINLOG_CLOSED), MYF(0));
return 1;
}
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 52041cca0d6..652949201f0 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -1636,13 +1636,32 @@ JOIN::optimize_inner()
if (arena)
thd->restore_active_arena(arena, &backup);
}
-
+
if (optimize_constant_subqueries())
DBUG_RETURN(1);
- if (setup_jtbm_semi_joins(this, join_list, &conds))
+ List<Item> eq_list;
+
+ if (setup_degenerate_jtbm_semi_joins(this, join_list, eq_list))
DBUG_RETURN(1);
+ if (eq_list.elements != 0)
+ {
+ Item *new_cond;
+
+ if (eq_list.elements == 1)
+ new_cond= eq_list.pop();
+ else
+ new_cond= new (thd->mem_root) Item_cond_and(thd, eq_list);
+
+ if (new_cond &&
+ ((new_cond->fix_fields(thd, &new_cond) ||
+ !(conds= and_items(thd, conds, new_cond)) ||
+ conds->fix_fields(thd, &conds))))
+ DBUG_RETURN(TRUE);
+ }
+ eq_list.empty();
+
if (select_lex->cond_pushed_into_where)
{
conds= and_conds(thd, conds, select_lex->cond_pushed_into_where);
@@ -1665,6 +1684,32 @@ JOIN::optimize_inner()
&cond_value, &cond_equal, OPT_LINK_EQUAL_FIELDS);
if (thd->lex->sql_command == SQLCOM_SELECT &&
+ optimizer_flag(thd, OPTIMIZER_SWITCH_COND_PUSHDOWN_FOR_SUBQUERY))
+ {
+ TABLE_LIST *tbl;
+ List_iterator_fast<TABLE_LIST> li(select_lex->leaf_tables);
+ while ((tbl= li++))
+ if (tbl->jtbm_subselect)
+ {
+ if (tbl->jtbm_subselect->pushdown_cond_for_in_subquery(thd, conds))
+ DBUG_RETURN(1);
+ }
+ }
+
+ if (setup_jtbm_semi_joins(this, join_list, eq_list))
+ DBUG_RETURN(1);
+
+ if (eq_list.elements != 0)
+ {
+ conds= and_new_conditions_to_optimized_cond(thd, conds, &cond_equal,
+ eq_list, &cond_value);
+
+ if (!conds &&
+ cond_value != Item::COND_FALSE && cond_value != Item::COND_TRUE)
+ DBUG_RETURN(TRUE);
+ }
+
+ if (thd->lex->sql_command == SQLCOM_SELECT &&
optimizer_flag(thd, OPTIMIZER_SWITCH_COND_PUSHDOWN_FOR_DERIVED))
{
TABLE_LIST *tbl;
@@ -1702,7 +1747,7 @@ JOIN::optimize_inner()
if (select_lex->handle_derived(thd->lex, DT_OPTIMIZE))
DBUG_RETURN(1);
}
-
+
if (unlikely(thd->is_error()))
{
error= 1;
@@ -1972,7 +2017,7 @@ int JOIN::optimize_stage2()
if (!conds && outer_join)
{
/* Handle the case where we have an OUTER JOIN without a WHERE */
- conds= new (thd->mem_root) Item_int(thd, (longlong) 1,1); // Always true
+ conds= new (thd->mem_root) Item_bool(thd, true); // Always true
}
if (impossible_where)
@@ -2111,7 +2156,7 @@ int JOIN::optimize_stage2()
if (conds && const_table_map != found_const_table_map &&
(select_options & SELECT_DESCRIBE))
{
- conds=new (thd->mem_root) Item_int(thd, (longlong) 0, 1); // Always false
+ conds=new (thd->mem_root) Item_bool(thd, false); // Always false
}
/* Cache constant expressions in WHERE, HAVING, ON clauses. */
@@ -2400,7 +2445,7 @@ int JOIN::optimize_stage2()
having= having->remove_eq_conds(thd, &select_lex->having_value, true);
if (select_lex->having_value == Item::COND_FALSE)
{
- having= new (thd->mem_root) Item_int(thd, (longlong) 0,1);
+ having= new (thd->mem_root) Item_bool(thd, false);
zero_result_cause= "Impossible HAVING noticed after reading const tables";
error= 0;
select_lex->mark_const_derived(zero_result_cause);
@@ -4761,7 +4806,7 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list,
if (join->cond_value == Item::COND_FALSE)
{
join->impossible_where= true;
- conds= new (join->thd->mem_root) Item_int(join->thd, (longlong) 0, 1);
+ conds= new (join->thd->mem_root) Item_bool(join->thd, false);
}
join->cond_equal= NULL;
@@ -10503,7 +10548,7 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
below to check if we should use 'quick' instead.
*/
DBUG_PRINT("info", ("Item_int"));
- tmp= new (thd->mem_root) Item_int(thd, (longlong) 1, 1); // Always true
+ tmp= new (thd->mem_root) Item_bool(thd, true); // Always true
}
}
@@ -13438,9 +13483,9 @@ finish:
FALSE otherwise
*/
-static bool check_simple_equality(THD *thd, const Item::Context &ctx,
- Item *left_item, Item *right_item,
- COND_EQUAL *cond_equal)
+bool check_simple_equality(THD *thd, const Item::Context &ctx,
+ Item *left_item, Item *right_item,
+ COND_EQUAL *cond_equal)
{
Item *orig_left_item= left_item;
Item *orig_right_item= right_item;
@@ -13893,7 +13938,7 @@ COND *Item_cond_and::build_equal_items(THD *thd,
if (!cond_args->elements &&
!cond_equal.current_level.elements &&
!eq_list.elements)
- return new (thd->mem_root) Item_int(thd, (longlong) 1, 1);
+ return new (thd->mem_root) Item_bool(thd, true);
List_iterator_fast<Item_equal> it(cond_equal.current_level);
while ((item_equal= it++))
@@ -14000,7 +14045,7 @@ COND *Item_func_eq::build_equal_items(THD *thd,
Item_equal *item_equal;
int n= cond_equal.current_level.elements + eq_list.elements;
if (n == 0)
- return new (thd->mem_root) Item_int(thd, (longlong) 1, 1);
+ return new (thd->mem_root) Item_bool(thd, true);
else if (n == 1)
{
if ((item_equal= cond_equal.current_level.pop()))
@@ -14390,7 +14435,7 @@ Item *eliminate_item_equal(THD *thd, COND *cond, COND_EQUAL *upper_levels,
List<Item> eq_list;
Item_func_eq *eq_item= 0;
if (((Item *) item_equal)->const_item() && !item_equal->val_int())
- return new (thd->mem_root) Item_int(thd, (longlong) 0, 1);
+ return new (thd->mem_root) Item_bool(thd, false);
Item *item_const= item_equal->get_const();
Item_equal_fields_iterator it(*item_equal);
Item *head;
@@ -14398,7 +14443,7 @@ Item *eliminate_item_equal(THD *thd, COND *cond, COND_EQUAL *upper_levels,
Item *current_sjm_head= NULL;
DBUG_ASSERT(!cond ||
- cond->type() == Item::INT_ITEM ||
+ cond->is_bool_literal() ||
(cond->type() == Item::FUNC_ITEM &&
((Item_func *) cond)->functype() == Item_func::EQ_FUNC) ||
(cond->type() == Item::COND_ITEM &&
@@ -14519,13 +14564,13 @@ Item *eliminate_item_equal(THD *thd, COND *cond, COND_EQUAL *upper_levels,
cond AND eq_1 AND eq_2 AND eq_3 AND ...
- 'cond' is a parameter for this function, which may be NULL, an Item_int(1),
+ 'cond' is a parameter for this function, which may be NULL, an Item_bool(1),
or an Item_func_eq or an Item_cond_and.
We want to return a well-formed condition: no nested Item_cond_and objects,
or Item_cond_and with a single child:
- if 'cond' is an Item_cond_and, we add eq_i as its tail
- - if 'cond' is Item_int(1), we return eq_i
+ - if 'cond' is Item_bool(1), we return eq_i
- otherwise, we create our own Item_cond_and and put 'cond' at the front of
it.
- if we have only one condition to return, we don't create an Item_cond_and
@@ -14537,10 +14582,10 @@ Item *eliminate_item_equal(THD *thd, COND *cond, COND_EQUAL *upper_levels,
switch (eq_list.elements)
{
case 0:
- res= cond ? cond : new (thd->mem_root) Item_int(thd, (longlong) 1, 1);
+ res= cond ? cond : new (thd->mem_root) Item_bool(thd, true);
break;
case 1:
- if (!cond || cond->type() == Item::INT_ITEM)
+ if (!cond || cond->is_bool_literal())
res= eq_item;
break;
default:
@@ -14682,7 +14727,7 @@ static COND* substitute_for_best_equal_field(THD *thd, JOIN_TAB *context_tab,
eq_cond= 0;
break;
}
- else if (eq_cond->type() == Item::INT_ITEM && !eq_cond->val_bool())
+ else if (eq_cond->is_bool_literal() && !eq_cond->val_bool())
{
/*
This occurs when eliminate_item_equal() founds that cond is
@@ -14707,7 +14752,7 @@ static COND* substitute_for_best_equal_field(THD *thd, JOIN_TAB *context_tab,
else
{
/* Do not add an equality condition if it's always true */
- if (eq_cond->type() != Item::INT_ITEM &&
+ if (!eq_cond->is_bool_literal() &&
cond_list->push_front(eq_cond, thd->mem_root))
eq_cond= 0;
}
@@ -16307,7 +16352,7 @@ Item_func_isnull::remove_eq_conds(THD *thd, Item::cond_result *cond_value,
*/
- Item *item0= new(thd->mem_root) Item_int(thd, (longlong) 0, 1);
+ Item *item0= new(thd->mem_root) Item_bool(thd, false);
Item *eq_cond= new(thd->mem_root) Item_func_eq(thd, args[0], item0);
if (!eq_cond)
return this;
@@ -16537,60 +16582,6 @@ const_expression_in_where(COND *cond, Item *comp_item, Field *comp_field,
Create internal temporary table
****************************************************************************/
-/**
- Create field for temporary table from given field.
-
- @param thd Thread handler
- @param org_field field from which new field will be created
- @param name New field name
- @param table Temporary table
- @param item !=NULL if item->result_field should point to new field.
- This is relevant for how fill_record() is going to work:
- If item != NULL then fill_record() will update
- the record in the original table.
- If item == NULL then fill_record() will update
- the temporary table
-
- @retval
- NULL on error
- @retval
- new_created field
-*/
-
-Field *create_tmp_field_from_field(THD *thd, Field *org_field,
- LEX_CSTRING *name, TABLE *table,
- Item_field *item)
-{
- Field *new_field;
-
- new_field= org_field->make_new_field(thd->mem_root, table,
- table == org_field->table);
- if (new_field)
- {
- new_field->init(table);
- new_field->orig_table= org_field->orig_table;
- if (item)
- item->result_field= new_field;
- else
- new_field->field_name= *name;
- new_field->flags|= org_field->flags & NO_DEFAULT_VALUE_FLAG;
- if (org_field->maybe_null() || (item && item->maybe_null))
- new_field->flags&= ~NOT_NULL_FLAG; // Because of outer join
- if (org_field->type() == MYSQL_TYPE_VAR_STRING ||
- org_field->type() == MYSQL_TYPE_VARCHAR)
- table->s->db_create_options|= HA_OPTION_PACK_RECORD;
- else if (org_field->type() == FIELD_TYPE_DOUBLE)
- ((Field_double *) new_field)->not_fixed= TRUE;
- new_field->vcol_info= 0;
- new_field->cond_selectivity= 1.0;
- new_field->next_equal_field= NULL;
- new_field->option_list= NULL;
- new_field->option_struct= NULL;
- }
- return new_field;
-}
-
-
Field *Item::create_tmp_field_int(TABLE *table, uint convert_int_length)
{
const Type_handler *h= &type_handler_long;
@@ -16631,57 +16622,6 @@ Field *Item_sum::create_tmp_field(bool group, TABLE *table)
}
-static void create_tmp_field_from_item_finalize(THD *thd,
- Field *new_field,
- Item *item,
- Item ***copy_func,
- bool modify_item)
-{
- if (copy_func &&
- (item->is_result_field() ||
- (item->real_item()->is_result_field())))
- *((*copy_func)++) = item; // Save for copy_funcs
- if (modify_item)
- item->set_result_field(new_field);
- if (item->type() == Item::NULL_ITEM)
- new_field->is_created_from_null_item= TRUE;
-}
-
-
-/**
- Create field for temporary table using type of given item.
-
- @param thd Thread handler
- @param item Item to create a field for
- @param table Temporary table
- @param copy_func If set and item is a function, store copy of
- item in this array
- @param modify_item 1 if item->result_field should point to new
- item. This is relevent for how fill_record()
- is going to work:
- If modify_item is 1 then fill_record() will
- update the record in the original table.
- If modify_item is 0 then fill_record() will
- update the temporary table
-
- @retval
- 0 on error
- @retval
- new_created field
-*/
-
-static Field *create_tmp_field_from_item(THD *thd, Item *item, TABLE *table,
- Item ***copy_func, bool modify_item)
-{
- Field *UNINIT_VAR(new_field);
- DBUG_ASSERT(thd == table->in_use);
- if ((new_field= item->create_tmp_field(false, table)))
- create_tmp_field_from_item_finalize(thd, new_field, item,
- copy_func, modify_item);
- return new_field;
-}
-
-
/**
Create field for information schema table.
@@ -16719,19 +16659,206 @@ Field *Item::create_field_for_schema(THD *thd, TABLE *table)
/**
+ Create a temporary field for Item_field (or its descendant),
+ either direct or referenced by an Item_ref.
+*/
+Field *
+Item_field::create_tmp_field_from_item_field(TABLE *new_table,
+ Item_ref *orig_item,
+ const Tmp_field_param *param)
+{
+ DBUG_ASSERT(!is_result_field());
+ Field *result;
+ /*
+ If item have to be able to store NULLs but underlaid field can't do it,
+ create_tmp_field_from_field() can't be used for tmp field creation.
+ */
+ if (((maybe_null && in_rollup) ||
+ (new_table->in_use->create_tmp_table_for_derived && /* for mat. view/dt */
+ orig_item && orig_item->maybe_null)) &&
+ !field->maybe_null())
+ {
+ /*
+ The item the ref points to may have maybe_null flag set while
+ the ref doesn't have it. This may happen for outer fields
+ when the outer query decided at some point after name resolution phase
+ that this field might be null. Take this into account here.
+ */
+ Record_addr rec(orig_item ? orig_item->maybe_null : maybe_null);
+ const Type_handler *handler= type_handler()->
+ type_handler_for_tmp_table(this);
+ result= handler->make_and_init_table_field(&name, rec, *this, new_table);
+ }
+ else if (param->table_cant_handle_bit_fields() &&
+ field->type() == MYSQL_TYPE_BIT)
+ {
+ const Type_handler *handler= type_handler_long_or_longlong();
+ result= handler->make_and_init_table_field(&name,
+ Record_addr(maybe_null),
+ *this, new_table);
+ }
+ else
+ {
+ LEX_CSTRING *tmp= orig_item ? &orig_item->name : &name;
+ bool tmp_maybe_null= param->modify_item() ? maybe_null :
+ field->maybe_null();
+ result= field->create_tmp_field(new_table->in_use->mem_root, new_table,
+ tmp_maybe_null);
+ if (result)
+ result->field_name= *tmp;
+ }
+ if (result && param->modify_item())
+ result_field= result;
+ return result;
+}
+
+
+Field *Item_field::create_tmp_field_ex(TABLE *table,
+ Tmp_field_src *src,
+ const Tmp_field_param *param)
+{
+ DBUG_ASSERT(!is_result_field());
+ Field *result;
+ src->set_field(field);
+ if (!(result= create_tmp_field_from_item_field(table, NULL, param)))
+ return NULL;
+ /*
+ Fields that are used as arguments to the DEFAULT() function already have
+ their data pointers set to the default value during name resolution. See
+ Item_default_value::fix_fields.
+ */
+ if (type() != Item::DEFAULT_VALUE_ITEM && field->eq_def(result))
+ src->set_default_field(field);
+ return result;
+}
+
+
+Field *Item_ref::create_tmp_field_ex(TABLE *table,
+ Tmp_field_src *src,
+ const Tmp_field_param *param)
+{
+ Item *item= real_item();
+ DBUG_ASSERT(is_result_field());
+ if (item->type() == Item::FIELD_ITEM)
+ {
+ Field *result;
+ Item_field *field= (Item_field*) item;
+ Tmp_field_param prm2(*param);
+ prm2.set_modify_item(false);
+ src->set_field(field->field);
+ if (!(result= field->create_tmp_field_from_item_field(table, this, &prm2)))
+ return NULL;
+ if (param->modify_item())
+ result_field= result;
+ return result;
+ }
+ return Item_result_field::create_tmp_field_ex(table, src, param);
+}
+
+
+void Item_result_field::get_tmp_field_src(Tmp_field_src *src,
+ const Tmp_field_param *param)
+{
+ if (param->make_copy_field())
+ {
+ DBUG_ASSERT(result_field);
+ src->set_field(result_field);
+ }
+ else
+ {
+ src->set_item_result_field(this); // Save for copy_funcs
+ }
+}
+
+
+Field *Item_result_field::create_tmp_field_ex(TABLE *table,
+ Tmp_field_src *src,
+ const Tmp_field_param *param)
+{
+ /*
+ Possible Item types:
+ - Item_cache_wrapper (only for CREATE..SELECT ?)
+ - Item_func
+ - Item_subselect
+ */
+ DBUG_ASSERT(is_result_field());
+ DBUG_ASSERT(type() != NULL_ITEM);
+ get_tmp_field_src(src, param);
+ Field *result;
+ if ((result= tmp_table_field_from_field_type(table)) && param->modify_item())
+ result_field= result;
+ return result;
+}
+
+
+Field *Item_func_user_var::create_tmp_field_ex(TABLE *table,
+ Tmp_field_src *src,
+ const Tmp_field_param *param)
+{
+ DBUG_ASSERT(is_result_field());
+ DBUG_ASSERT(type() != NULL_ITEM);
+ get_tmp_field_src(src, param);
+ Field *result;
+ if ((result= create_table_field_from_handler(table)) && param->modify_item())
+ result_field= result;
+ return result;
+}
+
+
+Field *Item_func_sp::create_tmp_field_ex(TABLE *table,
+ Tmp_field_src *src,
+ const Tmp_field_param *param)
+{
+ Field *result;
+ get_tmp_field_src(src, param);
+ if ((result= sp_result_field->create_tmp_field(table->in_use->mem_root,
+ table)))
+ {
+ result->field_name= name;
+ if (param->modify_item())
+ result_field= result;
+ }
+ return result;
+}
+
+
+Field *Item_basic_value::create_tmp_field_ex(TABLE *table,
+ Tmp_field_src *src,
+ const Tmp_field_param *param)
+{
+ /*
+ create_tmp_field_ex() for this type of Items is called for:
+ - CREATE TABLE ... SELECT
+ - In ORDER BY: SELECT max(a) FROM t1 GROUP BY a ORDER BY 'const';
+ - In CURSORS:
+ DECLARE c CURSOR FOR SELECT 'test';
+ OPEN c;
+ */
+ DBUG_ASSERT(!param->make_copy_field());
+ DBUG_ASSERT(!is_result_field());
+ Field *result;
+ if ((result= tmp_table_field_from_field_type(table)))
+ {
+ if (type() == Item::NULL_ITEM) // Item_null or Item_param
+ result->is_created_from_null_item= true;
+ }
+ return result;
+}
+
+
+/**
Create field for temporary table.
- @param thd Thread handler
- @param table Temporary table
- @param item Item to create a field for
- @param type Type of item (normally item->type)
- @param copy_func If set and item is a function, store copy of item
+ @param table Temporary table
+ @param item Item to create a field for
+ @param type Type of item (normally item->type)
+ @param copy_func If set and item is a function, store copy of item
in this array
@param from_field if field will be created using other field as example,
pointer example field will be written here
- @param default_field If field has a default value field, store it here
- @param group 1 if we are going to do a relative group by on result
- @param modify_item 1 if item->result_field should point to new item.
+ @param default_field If field has a default value field, store it here
+ @param group 1 if we are going to do a relative group by on result
+ @param modify_item 1 if item->result_field should point to new item.
This is relevent for how fill_record() is going to
work:
If modify_item is 1 then fill_record() will update
@@ -16740,172 +16867,28 @@ Field *Item::create_field_for_schema(THD *thd, TABLE *table)
the temporary table
@retval
- 0 on error
+ 0 on error
@retval
new_created field
+ Create a temporary field for Item_field (or its descendant),
+ either direct or referenced by an Item_ref.
*/
-
-Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
+Field *create_tmp_field(TABLE *table, Item *item,
Item ***copy_func, Field **from_field,
Field **default_field,
bool group, bool modify_item,
bool table_cant_handle_bit_fields,
bool make_copy_field)
{
- Field *result;
- Item::Type orig_type= type;
- Item *orig_item= 0;
-
- DBUG_ASSERT(thd == table->in_use);
-
- if (type != Item::FIELD_ITEM &&
- item->real_item()->type() == Item::FIELD_ITEM)
- {
- orig_item= item;
- item= item->real_item();
- type= Item::FIELD_ITEM;
- }
-
- switch (type) {
- case Item::TYPE_HOLDER:
- case Item::SUM_FUNC_ITEM:
- {
- result= item->create_tmp_field(group, table);
- if (!result)
- my_error(ER_OUT_OF_RESOURCES, MYF(ME_FATALERROR));
- return result;
- }
- case Item::FIELD_ITEM:
- case Item::DEFAULT_VALUE_ITEM:
- case Item::INSERT_VALUE_ITEM:
- case Item::TRIGGER_FIELD_ITEM:
- {
- Item_field *field= (Item_field*) item;
- bool orig_modify= modify_item;
- if (orig_type == Item::REF_ITEM)
- modify_item= 0;
- /*
- If item have to be able to store NULLs but underlaid field can't do it,
- create_tmp_field_from_field() can't be used for tmp field creation.
- */
- if (((field->maybe_null && field->in_rollup) ||
- (thd->create_tmp_table_for_derived && /* for mat. view/dt */
- orig_item && orig_item->maybe_null)) &&
- !field->field->maybe_null())
- {
- bool save_maybe_null= FALSE;
- /*
- The item the ref points to may have maybe_null flag set while
- the ref doesn't have it. This may happen for outer fields
- when the outer query decided at some point after name resolution phase
- that this field might be null. Take this into account here.
- */
- if (orig_item)
- {
- save_maybe_null= item->maybe_null;
- item->maybe_null= orig_item->maybe_null;
- }
- result= create_tmp_field_from_item(thd, item, table, NULL,
- modify_item);
- *from_field= field->field;
- if (result && modify_item)
- field->result_field= result;
- if (orig_item)
- item->maybe_null= save_maybe_null;
- }
- else if (table_cant_handle_bit_fields && field->field->type() ==
- MYSQL_TYPE_BIT)
- {
- const Type_handler *handler= item->type_handler_long_or_longlong();
- *from_field= field->field;
- if ((result=
- handler->make_and_init_table_field(&item->name,
- Record_addr(item->maybe_null),
- *item, table)))
- create_tmp_field_from_item_finalize(thd, result, item,
- copy_func, modify_item);
- if (result && modify_item)
- field->result_field= result;
- }
- else
- {
- LEX_CSTRING *tmp= orig_item ? &orig_item->name : &item->name;
- result= create_tmp_field_from_field(thd, (*from_field= field->field),
- tmp, table,
- modify_item ? field :
- NULL);
- }
-
- if (orig_type == Item::REF_ITEM && orig_modify)
- ((Item_ref*)orig_item)->set_result_field(result);
- /*
- Fields that are used as arguments to the DEFAULT() function already have
- their data pointers set to the default value during name resolution. See
- Item_default_value::fix_fields.
- */
- if (orig_type != Item::DEFAULT_VALUE_ITEM && field->field->eq_def(result))
- *default_field= field->field;
- return result;
- }
- /* Fall through */
- case Item::FUNC_ITEM:
- if (((Item_func *) item)->functype() == Item_func::FUNC_SP)
- {
- Item_func_sp *item_func_sp= (Item_func_sp *) item;
- Field *sp_result_field= item_func_sp->get_sp_result_field();
-
- if (make_copy_field)
- {
- DBUG_ASSERT(item_func_sp->result_field);
- *from_field= item_func_sp->result_field;
- }
- else
- {
- *((*copy_func)++)= item;
- }
- Field *result_field=
- create_tmp_field_from_field(thd,
- sp_result_field,
- &item_func_sp->name,
- table,
- NULL);
-
- if (modify_item)
- item->set_result_field(result_field);
-
- return result_field;
- }
-
- /* Fall through */
- case Item::COND_ITEM:
- case Item::FIELD_AVG_ITEM:
- case Item::FIELD_STD_ITEM:
- case Item::SUBSELECT_ITEM:
- /* The following can only happen with 'CREATE TABLE ... SELECT' */
- case Item::PROC_ITEM:
- case Item::INT_ITEM:
- case Item::REAL_ITEM:
- case Item::DECIMAL_ITEM:
- case Item::STRING_ITEM:
- case Item::DATE_ITEM:
- case Item::REF_ITEM:
- case Item::NULL_ITEM:
- case Item::VARBIN_ITEM:
- case Item::CACHE_ITEM:
- case Item::WINDOW_FUNC_ITEM: // psergey-winfunc:
- case Item::EXPR_CACHE_ITEM:
- case Item::PARAM_ITEM:
- if (make_copy_field)
- {
- DBUG_ASSERT(((Item_result_field*)item)->result_field);
- *from_field= ((Item_result_field*)item)->result_field;
- }
- return create_tmp_field_from_item(thd, item, table,
- (make_copy_field ? 0 : copy_func),
- modify_item);
- default: // Dosen't have to be stored
- return 0;
- }
+ Tmp_field_src src;
+ Tmp_field_param prm(group, modify_item, table_cant_handle_bit_fields,
+ make_copy_field);
+ Field *result= item->create_tmp_field_ex(table, &src, &prm);
+ *from_field= src.field();
+ *default_field= src.default_field();
+ if (src.item_result_field())
+ *((*copy_func)++)= src.item_result_field();
+ return result;
}
/*
@@ -16921,7 +16904,7 @@ setup_tmp_table_column_bitmaps(TABLE *table, uchar *bitmaps, uint field_count)
{
uint bitmap_size= bitmap_buffer_size(field_count);
- DBUG_ASSERT(table->s->virtual_fields == 0 && table->def_vcol_set == 0);
+ DBUG_ASSERT(table->s->virtual_fields == 0);
my_bitmap_init(&table->def_read_set, (my_bitmap_map*) bitmaps, field_count,
FALSE);
@@ -17216,7 +17199,7 @@ create_tmp_table(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields,
{
Item *tmp_item;
Field *new_field=
- create_tmp_field(thd, table, arg, arg->type(), &copy_func,
+ create_tmp_field(table, arg, &copy_func,
tmp_from_field, &default_field[fieldnr],
group != 0,not_all_columns,
distinct, false);
@@ -17266,7 +17249,7 @@ create_tmp_table(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields,
else
{
/*
- The last parameter to create_tmp_field() is a bit tricky:
+ The last parameter to create_tmp_field_ex() is a bit tricky:
We need to set it to 0 in union, to get fill_record() to modify the
temporary table.
@@ -17280,7 +17263,7 @@ create_tmp_table(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields,
*/
Field *new_field= (param->schema_table) ?
item->create_field_for_schema(thd, table) :
- create_tmp_field(thd, table, item, type, &copy_func,
+ create_tmp_field(table, item, &copy_func,
tmp_from_field, &default_field[fieldnr],
group != 0,
!force_copy_fields &&
@@ -17294,8 +17277,7 @@ create_tmp_table(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields,
*/
item->marker == 4 || param->bit_fields_as_long,
force_copy_fields);
-
- if (unlikely(!new_field))
+ if (!new_field)
{
if (unlikely(thd->is_fatal_error))
goto err; // Got OOM
@@ -17876,12 +17858,10 @@ bool Virtual_tmp_table::add(List<Spvar_definition> &field_list)
while ((cdef= it++))
{
Field *tmp;
- if (!(tmp= cdef->make_field(s, in_use->mem_root, 0,
- (uchar*) (f_maybe_null(cdef->pack_flag) ? "" : 0),
- f_maybe_null(cdef->pack_flag) ? 1 : 0,
- &cdef->field_name)))
+ Record_addr addr(f_maybe_null(cdef->pack_flag));
+ if (!(tmp= cdef->make_field(s, in_use->mem_root, &addr, &cdef->field_name)))
DBUG_RETURN(true);
- add(tmp);
+ add(tmp);
}
DBUG_RETURN(false);
}
@@ -18424,7 +18404,7 @@ create_internal_tmp_table_from_heap(THD *thd, TABLE *table,
We don't want this error to be converted to a warning, e.g. in case of
INSERT IGNORE ... SELECT.
*/
- table->file->print_error(error, MYF(ME_FATALERROR));
+ table->file->print_error(error, MYF(ME_FATAL));
DBUG_RETURN(1);
}
new_table= *table;
@@ -22579,7 +22559,7 @@ static int remove_dup_with_compare(THD *thd, TABLE *table, Field **first_field,
if (unlikely(copy_blobs(first_field)))
{
my_message(ER_OUTOFMEMORY, ER_THD(thd,ER_OUTOFMEMORY),
- MYF(ME_FATALERROR));
+ MYF(ME_FATAL));
error=0;
goto err;
}
@@ -22854,12 +22834,7 @@ find_order_in_list(THD *thd, Ref_ptr_array ref_pointer_array,
uint counter;
enum_resolution_type resolution;
- /*
- Local SP variables may be int but are expressions, not positions.
- (And they can't be used before fix_fields is called for them).
- */
- if (order_item->type() == Item::INT_ITEM && order_item->basic_const_item() &&
- !from_window_spec)
+ if (order_item->is_order_clause_position() && !from_window_spec)
{ /* Order by position */
uint count;
if (order->counter_used)
@@ -23480,7 +23455,7 @@ void calc_group_buffer(TMP_TABLE_PARAM *param, ORDER *group)
{
/*
Group strings are taken as varstrings and require an length field.
- A field is not yet created by create_tmp_field()
+ A field is not yet created by create_tmp_field_ex()
and the sizes should match up.
*/
key_length+= group_item->max_length + HA_KEY_BLOB_LENGTH;
@@ -23490,7 +23465,7 @@ void calc_group_buffer(TMP_TABLE_PARAM *param, ORDER *group)
default:
/* This case should never be choosen */
DBUG_ASSERT(0);
- my_error(ER_OUT_OF_RESOURCES, MYF(ME_FATALERROR));
+ my_error(ER_OUT_OF_RESOURCES, MYF(ME_FATAL));
}
}
parts++;
diff --git a/sql/sql_select.h b/sql/sql_select.h
index 2cc47f6ec3b..4140a0293f8 100644
--- a/sql/sql_select.h
+++ b/sql/sql_select.h
@@ -1473,6 +1473,11 @@ public:
Dynamic_array<KEYUSE_EXT> *ext_keyuses_for_splitting;
JOIN_TAB *sort_and_group_aggr_tab;
+ /*
+ Flag is set to true if select_lex was found to be degenerated before
+ the optimize_cond() call in JOIN::optimize_inner() method.
+ */
+ bool is_orig_degenerated;
JOIN(THD *thd_arg, List<Item> &fields_arg, ulonglong select_options_arg,
select_result *result_arg)
@@ -1568,6 +1573,7 @@ public:
emb_sjm_nest= NULL;
sjm_lookup_tables= 0;
sjm_scan_tables= 0;
+ is_orig_degenerated= false;
}
/* True if the plan guarantees that it will be returned zero or one row */
@@ -1747,6 +1753,7 @@ public:
bool fix_all_splittings_in_plan();
bool transform_in_predicates_into_in_subq(THD *thd);
+ bool add_equalities_to_where_condition(THD *thd, List<Item> &eq_list);
private:
/**
Create a temporary table to be used for processing DISTINCT/ORDER
@@ -1811,10 +1818,6 @@ bool setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param,
void copy_fields(TMP_TABLE_PARAM *param);
bool copy_funcs(Item **func_ptr, const THD *thd);
uint find_shortest_key(TABLE *table, const key_map *usable_keys);
-Field* create_tmp_field_from_field(THD *thd, Field* org_field,
- LEX_CSTRING *name, TABLE *table,
- Item_field *item);
-
bool is_indexed_agg_distinct(JOIN *join, List<Item_field> *out_args);
/* functions from opt_sum.cc */
@@ -2066,12 +2069,6 @@ bool mysql_select(THD *thd,
void free_underlaid_joins(THD *thd, SELECT_LEX *select);
bool mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit,
select_result *result);
-Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
- Item ***copy_func, Field **from_field,
- Field **def_field,
- bool group, bool modify_item,
- bool table_cant_handle_bit_fields,
- bool make_copy_field);
/*
General routine to change field->ptr of a NULL-terminated array of Field
@@ -2339,7 +2336,7 @@ Item_equal *find_item_equal(COND_EQUAL *cond_equal, Field *field,
extern bool test_if_ref(Item *,
Item_field *left_item,Item *right_item);
-inline bool optimizer_flag(THD *thd, uint flag)
+inline bool optimizer_flag(THD *thd, ulonglong flag)
{
return (thd->variables.optimizer_switch & flag);
}
@@ -2455,4 +2452,13 @@ int create_sort_index(THD *thd, JOIN *join, JOIN_TAB *tab, Filesort *fsort);
JOIN_TAB *first_explain_order_tab(JOIN* join);
JOIN_TAB *next_explain_order_tab(JOIN* join, JOIN_TAB* tab);
+bool check_simple_equality(THD *thd, const Item::Context &ctx,
+ Item *left_item, Item *right_item,
+ COND_EQUAL *cond_equal);
+
+void propagate_new_equalities(THD *thd, Item *cond,
+ List<Item_equal> *new_equalities,
+ COND_EQUAL *inherited,
+ bool *is_simplifiable_cond);
+
#endif /* SQL_SELECT_INCLUDED */
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index 224e6f0e411..4923c628bf9 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -1034,9 +1034,9 @@ find_files(THD *thd, Dynamic_array<LEX_CSTRING*> *files, LEX_CSTRING *db,
if (!(dirp = my_dir(path, MY_THREAD_SPECIFIC | (db ? 0 : MY_WANT_STAT))))
{
if (my_errno == ENOENT)
- my_error(ER_BAD_DB_ERROR, MYF(ME_BELL | ME_WAITTANG), db->str);
+ my_error(ER_BAD_DB_ERROR, MYF(0), db->str);
else
- my_error(ER_CANT_READ_DIR, MYF(ME_BELL | ME_WAITTANG), path, my_errno);
+ my_error(ER_CANT_READ_DIR, MYF(0), path, my_errno);
DBUG_RETURN(FIND_FILES_DIR);
}
@@ -7329,7 +7329,7 @@ static int get_schema_partitions_record(THD *thd, TABLE_LIST *tables,
break;
default:
DBUG_ASSERT(0);
- my_error(ER_OUT_OF_RESOURCES, MYF(ME_FATALERROR));
+ my_error(ER_OUT_OF_RESOURCES, MYF(ME_FATAL));
DBUG_RETURN(1);
}
table->field[7]->set_notnull();
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 6835d92773c..4ac8b102d79 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -10202,10 +10202,7 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to,
alter_table_manage_keys(to, from->file->indexes_are_disabled(), keys_onoff);
- /* Set read map for all fields in from table */
from->default_column_bitmaps();
- bitmap_set_all(from->read_set);
- from->file->column_bitmaps_signal();
/* We can abort alter table for any table type */
thd->abort_on_warning= !ignore && thd->is_strict_mode();
@@ -10235,7 +10232,11 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to,
if (def->field == from->found_next_number_field)
thd->variables.sql_mode|= MODE_NO_AUTO_VALUE_ON_ZERO;
}
- (copy_end++)->set(*ptr,def->field,0);
+ if (!(*ptr)->vcol_info)
+ {
+ bitmap_set_bit(from->read_set, def->field->field_index);
+ (copy_end++)->set(*ptr,def->field,0);
+ }
}
else
{
@@ -10304,6 +10305,11 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to,
from_row_end= from->vers_end_field();
}
+ if (from_row_end)
+ bitmap_set_bit(from->read_set, from_row_end->field_index);
+
+ from->file->column_bitmaps_signal();
+
THD_STAGE_INFO(thd, stage_copy_to_tmp_table);
/* Tell handler that we have values for all columns in the to table */
to->use_all_columns();
@@ -10653,7 +10659,7 @@ bool mysql_checksum_table(THD *thd, TABLE_LIST *tables,
ha_checksum crc= 0;
uchar null_mask=256 - (1 << t->s->last_null_bit_pos);
- t->use_all_columns();
+ t->use_all_stored_columns();
if (t->file->ha_rnd_init(1))
protocol->store_null();
diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc
index df3a2dc9c04..7db4c6c3821 100644
--- a/sql/sql_trigger.cc
+++ b/sql/sql_trigger.cc
@@ -2311,12 +2311,10 @@ void Table_triggers_list::mark_fields_used(trg_event_type event)
if (trg_field->field_idx != (uint)-1)
{
DBUG_PRINT("info", ("marking field: %d", trg_field->field_idx));
- bitmap_set_bit(trigger_table->read_set, trg_field->field_idx);
if (trg_field->get_settable_routine_parameter())
bitmap_set_bit(trigger_table->write_set, trg_field->field_idx);
- if (trigger_table->field[trg_field->field_idx]->vcol_info)
- trigger_table->mark_virtual_col(trigger_table->
- field[trg_field->field_idx]);
+ trigger_table->mark_column_with_deps(
+ trigger_table->field[trg_field->field_idx]);
}
}
}
diff --git a/sql/sql_type.cc b/sql/sql_type.cc
index 22eebaf6a38..1bedec8af7a 100644
--- a/sql/sql_type.cc
+++ b/sql/sql_type.cc
@@ -26,6 +26,7 @@ Type_handler_row type_handler_row;
Type_handler_null type_handler_null;
+Type_handler_bool type_handler_bool;
Type_handler_tiny type_handler_tiny;
Type_handler_short type_handler_short;
Type_handler_long type_handler_long;
@@ -443,6 +444,7 @@ const Name
Type_handler_set::m_name_set(STRING_WITH_LEN("set"));
const Name
+ Type_handler_bool::m_name_bool(STRING_WITH_LEN("boolean")),
Type_handler_tiny::m_name_tiny(STRING_WITH_LEN("tinyint")),
Type_handler_short::m_name_short(STRING_WITH_LEN("smallint")),
Type_handler_long::m_name_int(STRING_WITH_LEN("int")),
@@ -2007,8 +2009,8 @@ Field *Type_handler_tiny::make_table_field(const LEX_CSTRING *name,
TABLE *table) const
{
return new (table->in_use->mem_root)
- Field_tiny(addr.ptr, attr.max_char_length(),
- addr.null_ptr, addr.null_bit,
+ Field_tiny(addr.ptr(), attr.max_char_length(),
+ addr.null_ptr(), addr.null_bit(),
Field::NONE, name, 0/*zerofill*/, attr.unsigned_flag);
}
@@ -2020,8 +2022,8 @@ Field *Type_handler_short::make_table_field(const LEX_CSTRING *name,
{
return new (table->in_use->mem_root)
- Field_short(addr.ptr, attr.max_char_length(),
- addr.null_ptr, addr.null_bit,
+ Field_short(addr.ptr(), attr.max_char_length(),
+ addr.null_ptr(), addr.null_bit(),
Field::NONE, name, 0/*zerofill*/, attr.unsigned_flag);
}
@@ -2032,8 +2034,8 @@ Field *Type_handler_int24::make_table_field(const LEX_CSTRING *name,
TABLE *table) const
{
return new (table->in_use->mem_root)
- Field_medium(addr.ptr, attr.max_char_length(),
- addr.null_ptr, addr.null_bit,
+ Field_medium(addr.ptr(), attr.max_char_length(),
+ addr.null_ptr(), addr.null_bit(),
Field::NONE, name,
0/*zerofill*/, attr.unsigned_flag);
}
@@ -2045,8 +2047,8 @@ Field *Type_handler_long::make_table_field(const LEX_CSTRING *name,
TABLE *table) const
{
return new (table->in_use->mem_root)
- Field_long(addr.ptr, attr.max_char_length(),
- addr.null_ptr, addr.null_bit,
+ Field_long(addr.ptr(), attr.max_char_length(),
+ addr.null_ptr(), addr.null_bit(),
Field::NONE, name, 0/*zerofill*/, attr.unsigned_flag);
}
@@ -2057,8 +2059,8 @@ Field *Type_handler_longlong::make_table_field(const LEX_CSTRING *name,
TABLE *table) const
{
return new (table->in_use->mem_root)
- Field_longlong(addr.ptr, attr.max_char_length(),
- addr.null_ptr, addr.null_bit,
+ Field_longlong(addr.ptr(), attr.max_char_length(),
+ addr.null_ptr(), addr.null_bit(),
Field::NONE, name,
0/*zerofill*/, attr.unsigned_flag);
}
@@ -2070,8 +2072,8 @@ Field *Type_handler_vers_trx_id::make_table_field(const LEX_CSTRING *name,
TABLE *table) const
{
return new (table->in_use->mem_root)
- Field_vers_trx_id(addr.ptr, attr.max_char_length(),
- addr.null_ptr, addr.null_bit,
+ Field_vers_trx_id(addr.ptr(), attr.max_char_length(),
+ addr.null_ptr(), addr.null_bit(),
Field::NONE, name,
0/*zerofill*/, attr.unsigned_flag);
}
@@ -2083,8 +2085,8 @@ Field *Type_handler_float::make_table_field(const LEX_CSTRING *name,
TABLE *table) const
{
return new (table->in_use->mem_root)
- Field_float(addr.ptr, attr.max_char_length(),
- addr.null_ptr, addr.null_bit,
+ Field_float(addr.ptr(), attr.max_char_length(),
+ addr.null_ptr(), addr.null_bit(),
Field::NONE, name,
(uint8) attr.decimals, 0/*zerofill*/, attr.unsigned_flag);
}
@@ -2096,8 +2098,8 @@ Field *Type_handler_double::make_table_field(const LEX_CSTRING *name,
TABLE *table) const
{
return new (table->in_use->mem_root)
- Field_double(addr.ptr, attr.max_char_length(),
- addr.null_ptr, addr.null_bit,
+ Field_double(addr.ptr(), attr.max_char_length(),
+ addr.null_ptr(), addr.null_bit(),
Field::NONE, name,
(uint8) attr.decimals, 0/*zerofill*/, attr.unsigned_flag);
}
@@ -2118,7 +2120,8 @@ Type_handler_olddecimal::make_table_field(const LEX_CSTRING *name,
*/
DBUG_ASSERT(0);
return new (table->in_use->mem_root)
- Field_decimal(addr.ptr, attr.max_length, addr.null_ptr, addr.null_bit,
+ Field_decimal(addr.ptr(), attr.max_length,
+ addr.null_ptr(), addr.null_bit(),
Field::NONE, name, (uint8) attr.decimals,
0/*zerofill*/,attr.unsigned_flag);
}
@@ -2165,7 +2168,7 @@ Type_handler_newdecimal::make_table_field(const LEX_CSTRING *name,
len= required_length;
}
return new (table->in_use->mem_root)
- Field_new_decimal(addr.ptr, len, addr.null_ptr, addr.null_bit,
+ Field_new_decimal(addr.ptr(), len, addr.null_ptr(), addr.null_bit(),
Field::NONE, name,
dec, 0/*zerofill*/, attr.unsigned_flag);
}
@@ -2177,7 +2180,8 @@ Field *Type_handler_year::make_table_field(const LEX_CSTRING *name,
TABLE *table) const
{
return new (table->in_use->mem_root)
- Field_year(addr.ptr, attr.max_length, addr.null_ptr, addr.null_bit,
+ Field_year(addr.ptr(), attr.max_length,
+ addr.null_ptr(), addr.null_bit(),
Field::NONE, name);
}
@@ -2189,7 +2193,7 @@ Field *Type_handler_null::make_table_field(const LEX_CSTRING *name,
{
return new (table->in_use->mem_root)
- Field_null(addr.ptr, attr.max_length,
+ Field_null(addr.ptr(), attr.max_length,
Field::NONE, name, attr.collation.collation);
}
@@ -2201,7 +2205,7 @@ Field *Type_handler_timestamp::make_table_field(const LEX_CSTRING *name,
{
return new_Field_timestamp(table->in_use->mem_root,
- addr.ptr, addr.null_ptr, addr.null_bit,
+ addr.ptr(), addr.null_ptr(), addr.null_bit(),
Field::NONE, name, table->s, attr.decimals);
}
@@ -2217,7 +2221,7 @@ Field *Type_handler_timestamp2::make_table_field(const LEX_CSTRING *name,
make_table_field() for make_field() purposes in field.cc.
*/
return new_Field_timestamp(table->in_use->mem_root,
- addr.ptr, addr.null_ptr, addr.null_bit,
+ addr.ptr(), addr.null_ptr(), addr.null_bit(),
Field::NONE, name, table->s, attr.decimals);
}
@@ -2229,7 +2233,7 @@ Field *Type_handler_newdate::make_table_field(const LEX_CSTRING *name,
{
return new (table->in_use->mem_root)
- Field_newdate(addr.ptr, addr.null_ptr, addr.null_bit,
+ Field_newdate(addr.ptr(), addr.null_ptr(), addr.null_bit(),
Field::NONE, name);
}
@@ -2246,7 +2250,7 @@ Field *Type_handler_date::make_table_field(const LEX_CSTRING *name,
*/
DBUG_ASSERT(0);
return new (table->in_use->mem_root)
- Field_date(addr.ptr, addr.null_ptr, addr.null_bit,
+ Field_date(addr.ptr(), addr.null_ptr(), addr.null_bit(),
Field::NONE, name);
}
@@ -2258,7 +2262,7 @@ Field *Type_handler_time::make_table_field(const LEX_CSTRING *name,
{
return new_Field_time(table->in_use->mem_root,
- addr.ptr, addr.null_ptr, addr.null_bit,
+ addr.ptr(), addr.null_ptr(), addr.null_bit(),
Field::NONE, name, attr.decimals);
}
@@ -2275,7 +2279,7 @@ Field *Type_handler_time2::make_table_field(const LEX_CSTRING *name,
make_table_field() for make_field() purposes in field.cc.
*/
return new_Field_time(table->in_use->mem_root,
- addr.ptr, addr.null_ptr, addr.null_bit,
+ addr.ptr(), addr.null_ptr(), addr.null_bit(),
Field::NONE, name, attr.decimals);
}
@@ -2287,7 +2291,7 @@ Field *Type_handler_datetime::make_table_field(const LEX_CSTRING *name,
{
return new_Field_datetime(table->in_use->mem_root,
- addr.ptr, addr.null_ptr, addr.null_bit,
+ addr.ptr(), addr.null_ptr(), addr.null_bit(),
Field::NONE, name, attr.decimals);
}
@@ -2302,7 +2306,7 @@ Field *Type_handler_datetime2::make_table_field(const LEX_CSTRING *name,
make_table_field() for make_field() purposes in field.cc.
*/
return new_Field_datetime(table->in_use->mem_root,
- addr.ptr, addr.null_ptr, addr.null_bit,
+ addr.ptr(), addr.null_ptr(), addr.null_bit(),
Field::NONE, name, attr.decimals);
}
@@ -2314,8 +2318,8 @@ Field *Type_handler_bit::make_table_field(const LEX_CSTRING *name,
{
return new (table->in_use->mem_root)
- Field_bit_as_char(addr.ptr, attr.max_length,
- addr.null_ptr, addr.null_bit,
+ Field_bit_as_char(addr.ptr(), attr.max_length,
+ addr.null_ptr(), addr.null_bit(),
Field::NONE, name);
}
@@ -2327,7 +2331,8 @@ Field *Type_handler_string::make_table_field(const LEX_CSTRING *name,
{
return new (table->in_use->mem_root)
- Field_string(addr.ptr, attr.max_length, addr.null_ptr, addr.null_bit,
+ Field_string(addr.ptr(), attr.max_length,
+ addr.null_ptr(), addr.null_bit(),
Field::NONE, name, attr.collation);
}
@@ -2339,9 +2344,9 @@ Field *Type_handler_varchar::make_table_field(const LEX_CSTRING *name,
{
return new (table->in_use->mem_root)
- Field_varstring(addr.ptr, attr.max_length,
+ Field_varstring(addr.ptr(), attr.max_length,
HA_VARCHAR_PACKLENGTH(attr.max_length),
- addr.null_ptr, addr.null_bit,
+ addr.null_ptr(), addr.null_bit(),
Field::NONE, name,
table->s, attr.collation);
}
@@ -2354,7 +2359,7 @@ Field *Type_handler_tiny_blob::make_table_field(const LEX_CSTRING *name,
{
return new (table->in_use->mem_root)
- Field_blob(addr.ptr, addr.null_ptr, addr.null_bit,
+ Field_blob(addr.ptr(), addr.null_ptr(), addr.null_bit(),
Field::NONE, name, table->s,
1, attr.collation);
}
@@ -2367,7 +2372,7 @@ Field *Type_handler_blob::make_table_field(const LEX_CSTRING *name,
{
return new (table->in_use->mem_root)
- Field_blob(addr.ptr, addr.null_ptr, addr.null_bit,
+ Field_blob(addr.ptr(), addr.null_ptr(), addr.null_bit(),
Field::NONE, name, table->s,
2, attr.collation);
}
@@ -2381,7 +2386,7 @@ Type_handler_medium_blob::make_table_field(const LEX_CSTRING *name,
{
return new (table->in_use->mem_root)
- Field_blob(addr.ptr, addr.null_ptr, addr.null_bit,
+ Field_blob(addr.ptr(), addr.null_ptr(), addr.null_bit(),
Field::NONE, name, table->s,
3, attr.collation);
}
@@ -2394,7 +2399,7 @@ Field *Type_handler_long_blob::make_table_field(const LEX_CSTRING *name,
{
return new (table->in_use->mem_root)
- Field_blob(addr.ptr, addr.null_ptr, addr.null_bit,
+ Field_blob(addr.ptr(), addr.null_ptr(), addr.null_bit(),
Field::NONE, name, table->s,
4, attr.collation);
}
@@ -2408,7 +2413,7 @@ Field *Type_handler_geometry::make_table_field(const LEX_CSTRING *name,
TABLE *table) const
{
return new (table->in_use->mem_root)
- Field_geom(addr.ptr, addr.null_ptr, addr.null_bit,
+ Field_geom(addr.ptr(), addr.null_ptr(), addr.null_bit(),
Field::NONE, name, table->s, 4,
(Field::geometry_type) attr.uint_geometry_type(),
0);
@@ -2424,7 +2429,8 @@ Field *Type_handler_enum::make_table_field(const LEX_CSTRING *name,
TYPELIB *typelib= attr.get_typelib();
DBUG_ASSERT(typelib);
return new (table->in_use->mem_root)
- Field_enum(addr.ptr, attr.max_length, addr.null_ptr, addr.null_bit,
+ Field_enum(addr.ptr(), attr.max_length,
+ addr.null_ptr(), addr.null_bit(),
Field::NONE, name,
get_enum_pack_length(typelib->count), typelib,
attr.collation);
@@ -2440,7 +2446,8 @@ Field *Type_handler_set::make_table_field(const LEX_CSTRING *name,
TYPELIB *typelib= attr.get_typelib();
DBUG_ASSERT(typelib);
return new (table->in_use->mem_root)
- Field_set(addr.ptr, attr.max_length, addr.null_ptr, addr.null_bit,
+ Field_set(addr.ptr(), attr.max_length,
+ addr.null_ptr(), addr.null_bit(),
Field::NONE, name,
get_enum_pack_length(typelib->count), typelib,
attr.collation);
@@ -2824,8 +2831,21 @@ bool Type_handler_typelib::
TYPELIB *typelib= NULL;
for (uint i= 0; i < nitems; i++)
{
- if ((typelib= items[i]->get_typelib()))
- break;
+ TYPELIB *typelib2;
+ if ((typelib2= items[i]->get_typelib()))
+ {
+ if (typelib)
+ {
+ /*
+ Two ENUM/SET columns found. We convert such combinations to VARCHAR.
+ This may change in the future to preserve ENUM/SET
+ if typelib definitions are equal.
+ */
+ handler->set_handler(&type_handler_varchar);
+ return func->aggregate_attributes_string(func_name, items, nitems);
+ }
+ typelib= typelib2;
+ }
}
DBUG_ASSERT(typelib); // There must be at least one typelib
func->set_typelib(typelib);
@@ -2983,6 +3003,13 @@ bool Type_handler_int_result::
}
+bool Type_handler_bool::
+ Item_sum_hybrid_fix_length_and_dec(Item_sum_hybrid *func) const
+{
+ return Item_sum_hybrid_fix_length_and_dec_numeric(func, &type_handler_bool);
+}
+
+
bool Type_handler_real_result::
Item_sum_hybrid_fix_length_and_dec(Item_sum_hybrid *func) const
{
@@ -5787,6 +5814,490 @@ void Type_handler_geometry::Item_param_set_param_func(Item_param *param,
/***************************************************************************/
+Field *Type_handler_row::
+ make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root,
+ const LEX_CSTRING *name,
+ const Record_addr &rec, const Bit_addr &bit,
+ const Column_definition_attributes *attr,
+ uint32 flags) const
+{
+ DBUG_ASSERT(attr->length == 0);
+ DBUG_ASSERT(f_maybe_null(attr->pack_flag));
+ return new (mem_root) Field_row(rec.ptr(), name);
+}
+
+
+Field *Type_handler_olddecimal::
+ make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root,
+ const LEX_CSTRING *name,
+ const Record_addr &rec, const Bit_addr &bit,
+ const Column_definition_attributes *attr,
+ uint32 flags) const
+{
+ return new (mem_root)
+ Field_decimal(rec.ptr(), (uint32) attr->length,
+ rec.null_ptr(), rec.null_bit(),
+ attr->unireg_check, name,
+ f_decimals(attr->pack_flag),
+ f_is_zerofill(attr->pack_flag) != 0,
+ f_is_dec(attr->pack_flag) == 0);
+}
+
+
+Field *Type_handler_newdecimal::
+ make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root,
+ const LEX_CSTRING *name,
+ const Record_addr &rec, const Bit_addr &bit,
+ const Column_definition_attributes *attr,
+ uint32 flags) const
+{
+ return new (mem_root)
+ Field_new_decimal(rec.ptr(), (uint32) attr->length,
+ rec.null_ptr(), rec.null_bit(),
+ attr->unireg_check, name,
+ f_decimals(attr->pack_flag),
+ f_is_zerofill(attr->pack_flag) != 0,
+ f_is_dec(attr->pack_flag) == 0);
+}
+
+
+Field *Type_handler_float::
+ make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root,
+ const LEX_CSTRING *name,
+ const Record_addr &rec, const Bit_addr &bit,
+ const Column_definition_attributes *attr,
+ uint32 flags) const
+{
+ int decimals= f_decimals(attr->pack_flag);
+ if (decimals == FLOATING_POINT_DECIMALS)
+ decimals= NOT_FIXED_DEC;
+ return new (mem_root)
+ Field_float(rec.ptr(), (uint32) attr->length,
+ rec.null_ptr(), rec.null_bit(),
+ attr->unireg_check, name, decimals,
+ f_is_zerofill(attr->pack_flag) != 0,
+ f_is_dec(attr->pack_flag)== 0);
+}
+
+
+Field *Type_handler_double::
+ make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root,
+ const LEX_CSTRING *name,
+ const Record_addr &rec, const Bit_addr &bit,
+ const Column_definition_attributes *attr,
+ uint32 flags) const
+{
+ int decimals= f_decimals(attr->pack_flag);
+ if (decimals == FLOATING_POINT_DECIMALS)
+ decimals= NOT_FIXED_DEC;
+ return new (mem_root)
+ Field_double(rec.ptr(), (uint32) attr->length,
+ rec.null_ptr(), rec.null_bit(),
+ attr->unireg_check, name, decimals,
+ f_is_zerofill(attr->pack_flag) != 0,
+ f_is_dec(attr->pack_flag)== 0);
+}
+
+
+Field *Type_handler_tiny::
+ make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root,
+ const LEX_CSTRING *name,
+ const Record_addr &rec, const Bit_addr &bit,
+ const Column_definition_attributes *attr,
+ uint32 flags) const
+{
+ return new (mem_root)
+ Field_tiny(rec.ptr(), (uint32) attr->length, rec.null_ptr(), rec.null_bit(),
+ attr->unireg_check, name,
+ f_is_zerofill(attr->pack_flag) != 0,
+ f_is_dec(attr->pack_flag) == 0);
+}
+
+
+Field *Type_handler_short::
+ make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root,
+ const LEX_CSTRING *name,
+ const Record_addr &rec, const Bit_addr &bit,
+ const Column_definition_attributes *attr,
+ uint32 flags) const
+{
+ return new (mem_root)
+ Field_short(rec.ptr(), (uint32) attr->length,
+ rec.null_ptr(), rec.null_bit(),
+ attr->unireg_check, name,
+ f_is_zerofill(attr->pack_flag) != 0,
+ f_is_dec(attr->pack_flag) == 0);
+}
+
+
+Field *Type_handler_int24::
+ make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root,
+ const LEX_CSTRING *name,
+ const Record_addr &rec, const Bit_addr &bit,
+ const Column_definition_attributes *attr,
+ uint32 flags) const
+{
+ return new (mem_root)
+ Field_medium(rec.ptr(), (uint32) attr->length,
+ rec.null_ptr(), rec.null_bit(),
+ attr->unireg_check, name,
+ f_is_zerofill(attr->pack_flag) != 0,
+ f_is_dec(attr->pack_flag) == 0);
+}
+
+
+Field *Type_handler_long::
+ make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root,
+ const LEX_CSTRING *name,
+ const Record_addr &rec, const Bit_addr &bit,
+ const Column_definition_attributes *attr,
+ uint32 flags) const
+{
+ return new (mem_root)
+ Field_long(rec.ptr(), (uint32) attr->length, rec.null_ptr(), rec.null_bit(),
+ attr->unireg_check, name,
+ f_is_zerofill(attr->pack_flag) != 0,
+ f_is_dec(attr->pack_flag) == 0);
+}
+
+
+Field *Type_handler_longlong::
+ make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root,
+ const LEX_CSTRING *name,
+ const Record_addr &rec, const Bit_addr &bit,
+ const Column_definition_attributes *attr,
+ uint32 flags) const
+{
+ if (flags & (VERS_SYS_START_FLAG|VERS_SYS_END_FLAG))
+ return new (mem_root)
+ Field_vers_trx_id(rec.ptr(), (uint32) attr->length,
+ rec.null_ptr(), rec.null_bit(),
+ attr->unireg_check, name,
+ f_is_zerofill(attr->pack_flag) != 0,
+ f_is_dec(attr->pack_flag) == 0);
+ return new (mem_root)
+ Field_longlong(rec.ptr(), (uint32) attr->length,
+ rec.null_ptr(), rec.null_bit(),
+ attr->unireg_check, name,
+ f_is_zerofill(attr->pack_flag) != 0,
+ f_is_dec(attr->pack_flag) == 0);
+}
+
+
+Field *Type_handler_timestamp::
+ make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root,
+ const LEX_CSTRING *name,
+ const Record_addr &rec, const Bit_addr &bit,
+ const Column_definition_attributes *attr,
+ uint32 flags) const
+{
+ return new_Field_timestamp(mem_root,
+ rec.ptr(), rec.null_ptr(), rec.null_bit(),
+ attr->unireg_check, name, share,
+ attr->temporal_dec(MAX_DATETIME_WIDTH));
+}
+
+
+Field *Type_handler_timestamp2::
+ make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root,
+ const LEX_CSTRING *name,
+ const Record_addr &rec, const Bit_addr &bit,
+ const Column_definition_attributes *attr,
+ uint32 flags) const
+{
+ return new (mem_root)
+ Field_timestampf(rec.ptr(), rec.null_ptr(), rec.null_bit(),
+ attr->unireg_check,
+ name, share, attr->temporal_dec(MAX_DATETIME_WIDTH));
+}
+
+
+Field *Type_handler_year::
+ make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root,
+ const LEX_CSTRING *name,
+ const Record_addr &rec, const Bit_addr &bit,
+ const Column_definition_attributes *attr,
+ uint32 flags) const
+{
+ return new (mem_root)
+ Field_year(rec.ptr(), (uint32) attr->length, rec.null_ptr(), rec.null_bit(),
+ attr->unireg_check, name);
+}
+
+
+Field *Type_handler_date::
+ make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root,
+ const LEX_CSTRING *name,
+ const Record_addr &rec, const Bit_addr &bit,
+ const Column_definition_attributes *attr,
+ uint32 flags) const
+{
+ return new (mem_root)
+ Field_date(rec.ptr(),rec.null_ptr(),rec.null_bit(),
+ attr->unireg_check, name);
+}
+
+
+Field *Type_handler_newdate::
+ make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root,
+ const LEX_CSTRING *name,
+ const Record_addr &rec, const Bit_addr &bit,
+ const Column_definition_attributes *attr,
+ uint32 flags) const
+{
+ return new (mem_root)
+ Field_newdate(rec.ptr(), rec.null_ptr(), rec.null_bit(),
+ attr->unireg_check, name);
+}
+
+
+Field *Type_handler_time::
+ make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root,
+ const LEX_CSTRING *name,
+ const Record_addr &rec, const Bit_addr &bit,
+ const Column_definition_attributes *attr,
+ uint32 flags) const
+{
+ return new_Field_time(mem_root, rec.ptr(), rec.null_ptr(), rec.null_bit(),
+ attr->unireg_check, name,
+ attr->temporal_dec(MIN_TIME_WIDTH));
+}
+
+
+Field *Type_handler_time2::
+ make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root,
+ const LEX_CSTRING *name,
+ const Record_addr &rec, const Bit_addr &bit,
+ const Column_definition_attributes *attr,
+ uint32 flags) const
+{
+ return new (mem_root)
+ Field_timef(rec.ptr(), rec.null_ptr(), rec.null_bit(),
+ attr->unireg_check, name,
+ attr->temporal_dec(MIN_TIME_WIDTH));
+}
+
+
+Field *Type_handler_datetime::
+ make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root,
+ const LEX_CSTRING *name,
+ const Record_addr &rec, const Bit_addr &bit,
+ const Column_definition_attributes *attr,
+ uint32 flags) const
+{
+ return new_Field_datetime(mem_root, rec.ptr(), rec.null_ptr(), rec.null_bit(),
+ attr->unireg_check, name,
+ attr->temporal_dec(MAX_DATETIME_WIDTH));
+}
+
+
+Field *Type_handler_datetime2::
+ make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root,
+ const LEX_CSTRING *name,
+ const Record_addr &rec, const Bit_addr &bit,
+ const Column_definition_attributes *attr,
+ uint32 flags) const
+{
+ return new (mem_root)
+ Field_datetimef(rec.ptr(), rec.null_ptr(), rec.null_bit(),
+ attr->unireg_check, name,
+ attr->temporal_dec(MAX_DATETIME_WIDTH));
+}
+
+
+Field *Type_handler_null::
+ make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root,
+ const LEX_CSTRING *name,
+ const Record_addr &rec, const Bit_addr &bit,
+ const Column_definition_attributes *attr,
+ uint32 flags) const
+{
+ return new (mem_root)
+ Field_null(rec.ptr(), (uint32) attr->length, attr->unireg_check,
+ name, attr->charset);
+}
+
+
+Field *Type_handler_bit::
+ make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root,
+ const LEX_CSTRING *name,
+ const Record_addr &rec, const Bit_addr &bit,
+ const Column_definition_attributes *attr,
+ uint32 flags) const
+{
+ return f_bit_as_char(attr->pack_flag) ?
+ new (mem_root) Field_bit_as_char(rec.ptr(), (uint32) attr->length,
+ rec.null_ptr(), rec.null_bit(),
+ attr->unireg_check, name) :
+ new (mem_root) Field_bit(rec.ptr(), (uint32) attr->length,
+ rec.null_ptr(), rec.null_bit(),
+ bit.ptr(), bit.offs(), attr->unireg_check, name);
+}
+
+
+#ifdef HAVE_SPATIAL
+Field *Type_handler_geometry::
+ make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root,
+ const LEX_CSTRING *name,
+ const Record_addr &rec, const Bit_addr &bit,
+ const Column_definition_attributes *attr,
+ uint32 flags) const
+{
+ status_var_increment(current_thd->status_var.feature_gis);
+ return new (mem_root)
+ Field_geom(rec.ptr(), rec.null_ptr(), rec.null_bit(),
+ attr->unireg_check, name, share,
+ attr->pack_flag_to_pack_length(), attr->geom_type, attr->srid);
+}
+#endif
+
+
+Field *Type_handler_string::
+ make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root,
+ const LEX_CSTRING *name,
+ const Record_addr &rec, const Bit_addr &bit,
+ const Column_definition_attributes *attr,
+ uint32 flags) const
+{
+ return new (mem_root)
+ Field_string(rec.ptr(), (uint32) attr->length,
+ rec.null_ptr(), rec.null_bit(),
+ attr->unireg_check, name, attr->charset);
+}
+
+
+Field *Type_handler_varchar::
+ make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root,
+ const LEX_CSTRING *name,
+ const Record_addr &rec, const Bit_addr &bit,
+ const Column_definition_attributes *attr,
+ uint32 flags) const
+{
+ if (attr->unireg_check == Field::TMYSQL_COMPRESSED)
+ return new (mem_root)
+ Field_varstring_compressed(rec.ptr(), (uint32) attr->length,
+ HA_VARCHAR_PACKLENGTH((uint32) attr->length),
+ rec.null_ptr(), rec.null_bit(),
+ attr->unireg_check, name, share, attr->charset,
+ zlib_compression_method);
+ return new (mem_root)
+ Field_varstring(rec.ptr(), (uint32) attr->length,
+ HA_VARCHAR_PACKLENGTH((uint32) attr->length),
+ rec.null_ptr(), rec.null_bit(),
+ attr->unireg_check, name, share, attr->charset);
+}
+
+
+Field *Type_handler_blob_common::
+ make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root,
+ const LEX_CSTRING *name,
+ const Record_addr &rec, const Bit_addr &bit,
+ const Column_definition_attributes *attr,
+ uint32 flags) const
+{
+ if (attr->unireg_check == Field::TMYSQL_COMPRESSED)
+ return new (mem_root)
+ Field_blob_compressed(rec.ptr(), rec.null_ptr(), rec.null_bit(),
+ attr->unireg_check, name, share,
+ attr->pack_flag_to_pack_length(), attr->charset,
+ zlib_compression_method);
+ return new (mem_root)
+ Field_blob(rec.ptr(), rec.null_ptr(), rec.null_bit(),
+ attr->unireg_check, name, share,
+ attr->pack_flag_to_pack_length(), attr->charset);
+}
+
+
+Field *Type_handler_enum::
+ make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root,
+ const LEX_CSTRING *name,
+ const Record_addr &rec, const Bit_addr &bit,
+ const Column_definition_attributes *attr,
+ uint32 flags) const
+{
+ return new (mem_root)
+ Field_enum(rec.ptr(), (uint32) attr->length, rec.null_ptr(), rec.null_bit(),
+ attr->unireg_check, name, attr->pack_flag_to_pack_length(),
+ attr->interval, attr->charset);
+}
+
+
+Field *Type_handler_set::
+ make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root,
+ const LEX_CSTRING *name,
+ const Record_addr &rec, const Bit_addr &bit,
+ const Column_definition_attributes *attr,
+ uint32 flags) const
+{
+ return new (mem_root)
+ Field_set(rec.ptr(), (uint32) attr->length, rec.null_ptr(), rec.null_bit(),
+ attr->unireg_check, name, attr->pack_flag_to_pack_length(),
+ attr->interval, attr->charset);
+}
+
+
+/***************************************************************************/
+
+void Type_handler::
+ Column_definition_attributes_frm_pack(const Column_definition_attributes *def,
+ uchar *buff) const
+{
+ def->frm_pack_basic(buff);
+ def->frm_pack_charset(buff);
+}
+
+
+#ifdef HAVE_SPATIAL
+void Type_handler_geometry::
+ Column_definition_attributes_frm_pack(const Column_definition_attributes *def,
+ uchar *buff) const
+{
+ def->frm_pack_basic(buff);
+ buff[11]= 0;
+ buff[14]= (uchar) def->geom_type;
+}
+#endif
+
+
+/***************************************************************************/
+
+bool Type_handler::
+ Column_definition_attributes_frm_unpack(Column_definition_attributes *attr,
+ TABLE_SHARE *share,
+ const uchar *buffer,
+ LEX_CUSTRING *gis_options)
+ const
+{
+ attr->frm_unpack_basic(buffer);
+ return attr->frm_unpack_charset(share, buffer);
+}
+
+
+#ifdef HAVE_SPATIAL
+bool Type_handler_geometry::
+ Column_definition_attributes_frm_unpack(Column_definition_attributes *attr,
+ TABLE_SHARE *share,
+ const uchar *buffer,
+ LEX_CUSTRING *gis_options)
+ const
+{
+ uint gis_opt_read, gis_length, gis_decimals;
+ Field_geom::storage_type st_type;
+ attr->frm_unpack_basic(buffer);
+ // charset and geometry_type share the same byte in frm
+ attr->geom_type= (Field::geometry_type) buffer[14];
+ gis_opt_read= gis_field_options_read(gis_options->str,
+ gis_options->length,
+ &st_type, &gis_length,
+ &gis_decimals, &attr->srid);
+ gis_options->str+= gis_opt_read;
+ gis_options->length-= gis_opt_read;
+ return false;
+}
+#endif
+
+/***************************************************************************/
+
bool Type_handler::Vers_history_point_resolve_unit(THD *thd,
Vers_history_point *point)
const
diff --git a/sql/sql_type.h b/sql/sql_type.h
index 1ddcef2da61..ad554a91024 100644
--- a/sql/sql_type.h
+++ b/sql/sql_type.h
@@ -28,6 +28,7 @@
class Field;
class Column_definition;
+class Column_definition_attributes;
class Item;
class Item_param;
class Item_cache;
@@ -886,28 +887,67 @@ public:
};
-class Record_addr
+class Bit_addr
{
-public:
- uchar *ptr; // Position to field in record
/**
- Byte where the @c NULL bit is stored inside a record. If this Field is a
- @c NOT @c NULL field, this member is @c NULL.
+ Byte where the bit is stored inside a record.
+ If the corresponding Field is a NOT NULL field, this member is NULL.
*/
- uchar *null_ptr;
- uchar null_bit; // Bit used to test null bit
+ uchar *m_ptr;
+ /**
+ Offset of the bit inside m_ptr[0], in the range 0..7.
+ */
+ uchar m_offs;
+public:
+ Bit_addr()
+ :m_ptr(NULL),
+ m_offs(0)
+ { }
+ Bit_addr(uchar *ptr, uchar offs)
+ :m_ptr(ptr), m_offs(offs)
+ {
+ DBUG_ASSERT(ptr || offs == 0);
+ DBUG_ASSERT(offs < 8);
+ }
+ Bit_addr(bool maybe_null)
+ :m_ptr(maybe_null ? (uchar *) "" : NULL),
+ m_offs(0)
+ { }
+ uchar *ptr() const { return m_ptr; }
+ uchar offs() const { return m_offs; }
+ uchar bit() const { return m_ptr ? ((uchar) 1) << m_offs : 0; }
+ void inc()
+ {
+ DBUG_ASSERT(m_ptr);
+ m_ptr+= (m_offs == 7);
+ m_offs= (m_offs + 1) & 7;
+ }
+};
+
+
+class Record_addr
+{
+ uchar *m_ptr; // Position of the field in the record
+ Bit_addr m_null; // Position and offset of the null bit
+public:
Record_addr(uchar *ptr_arg,
uchar *null_ptr_arg,
uchar null_bit_arg)
- :ptr(ptr_arg),
- null_ptr(null_ptr_arg),
- null_bit(null_bit_arg)
+ :m_ptr(ptr_arg),
+ m_null(null_ptr_arg, null_bit_arg)
+ { }
+ Record_addr(uchar *ptr, const Bit_addr &null)
+ :m_ptr(ptr),
+ m_null(null)
{ }
Record_addr(bool maybe_null)
- :ptr(NULL),
- null_ptr(maybe_null ? (uchar*) "" : 0),
- null_bit(0)
+ :m_ptr(NULL),
+ m_null(maybe_null)
{ }
+ uchar *ptr() const { return m_ptr; }
+ const Bit_addr &null() const { return m_null; }
+ uchar *null_ptr() const { return m_null.ptr(); }
+ uchar null_bit() const { return m_null.bit(); }
};
@@ -1049,6 +1089,28 @@ public:
virtual const Name name() const= 0;
virtual enum_field_types field_type() const= 0;
virtual enum_field_types real_field_type() const { return field_type(); }
+ /**
+ Type code which is used for merging of traditional data types for result
+ (for UNION and for hybrid functions such as COALESCE).
+ Mapping can be done both ways: old->new, new->old, depending
+ on the particular data type implementation:
+ - type_handler_var_string (MySQL-4.1 old VARCHAR) is converted to
+ new VARCHAR before merging.
+ field_type_merge_rules[][] returns new VARCHAR.
+ - type_handler_newdate is converted to old DATE before merging.
+ field_type_merge_rules[][] returns NEWDATE.
+ - Temporal type_handler_xxx2 (new MySQL-5.6 types) are converted to
+ corresponding old type codes before merging (e.g. TIME2->TIME).
+ field_type_merge_rules[][] returns old type codes (e.g. TIME).
+ Then old types codes are supposed to convert to new type codes somehow,
+ but they do not. So UNION and COALESCE create old columns.
+ This is a bug and should be fixed eventually.
+ */
+ virtual enum_field_types traditional_merge_field_type() const
+ {
+ DBUG_ASSERT(is_traditional_type());
+ return field_type();
+ }
virtual Item_result result_type() const= 0;
virtual Item_result cmp_type() const= 0;
virtual enum_mysql_timestamp_type mysql_timestamp_type() const
@@ -1059,6 +1121,14 @@ public:
{
return false;
}
+ virtual bool is_order_clause_position_type() const
+ {
+ return false;
+ }
+ virtual bool is_limit_clause_valid_type() const
+ {
+ return false;
+ }
/**
Check whether a field type can be partially indexed by a key.
@param type field type
@@ -1123,6 +1193,7 @@ public:
virtual bool can_return_text() const { return true; }
virtual bool can_return_date() const { return true; }
virtual bool can_return_time() const { return true; }
+ virtual bool is_bool_type() const { return false; }
virtual bool is_general_purpose_string_type() const { return false; }
virtual uint Item_time_precision(Item *item) const;
virtual uint Item_datetime_precision(Item *item) const;
@@ -1208,6 +1279,23 @@ public:
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
+ virtual Field *
+ make_table_field_from_def(TABLE_SHARE *share,
+ MEM_ROOT *mem_root,
+ const LEX_CSTRING *name,
+ const Record_addr &addr,
+ const Bit_addr &bit,
+ const Column_definition_attributes *attr,
+ uint32 flags) const= 0;
+ virtual void
+ Column_definition_attributes_frm_pack(const Column_definition_attributes *at,
+ uchar *buff) const;
+ virtual bool
+ Column_definition_attributes_frm_unpack(Column_definition_attributes *attr,
+ TABLE_SHARE *share,
+ const uchar *buffer,
+ LEX_CUSTRING *gis_options) const;
+
virtual void make_sort_key(uchar *to, Item *item,
const SORT_FIELD_ATTR *sort_field,
Sort_param *param) const= 0;
@@ -1497,6 +1585,13 @@ public:
DBUG_ASSERT(0);
return NULL;
}
+ Field *make_table_field_from_def(TABLE_SHARE *share,
+ MEM_ROOT *mem_root,
+ const LEX_CSTRING *name,
+ const Record_addr &addr,
+ const Bit_addr &bit,
+ const Column_definition_attributes *attr,
+ uint32 flags) const;
void make_sort_key(uchar *to, Item *item,
const SORT_FIELD_ATTR *sort_field,
Sort_param *param) const
@@ -2038,6 +2133,8 @@ class Type_handler_int_result: public Type_handler_numeric
public:
Item_result result_type() const { return INT_RESULT; }
Item_result cmp_type() const { return INT_RESULT; }
+ bool is_order_clause_position_type() const { return true; }
+ bool is_limit_clause_valid_type() const { return true; }
virtual ~Type_handler_int_result() {}
const Type_handler *type_handler_for_comparison() const;
bool subquery_type_allows_materialization(const Item *inner,
@@ -2357,6 +2454,13 @@ public:
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
+ Field *make_table_field_from_def(TABLE_SHARE *share,
+ MEM_ROOT *mem_root,
+ const LEX_CSTRING *name,
+ const Record_addr &addr,
+ const Bit_addr &bit,
+ const Column_definition_attributes *attr,
+ uint32 flags) const;
void Item_param_set_param_func(Item_param *param,
uchar **pos, ulong len) const;
};
@@ -2391,6 +2495,13 @@ public:
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
+ Field *make_table_field_from_def(TABLE_SHARE *share,
+ MEM_ROOT *mem_root,
+ const LEX_CSTRING *name,
+ const Record_addr &addr,
+ const Bit_addr &bit,
+ const Column_definition_attributes *attr,
+ uint32 flags) const;
void Item_param_set_param_func(Item_param *param,
uchar **pos, ulong len) const;
};
@@ -2425,11 +2536,28 @@ public:
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
+ Field *make_table_field_from_def(TABLE_SHARE *share,
+ MEM_ROOT *mem_root,
+ const LEX_CSTRING *name,
+ const Record_addr &addr,
+ const Bit_addr &bit,
+ const Column_definition_attributes *attr,
+ uint32 flags) const;
void Item_param_set_param_func(Item_param *param,
uchar **pos, ulong len) const;
};
+class Type_handler_bool: public Type_handler_long
+{
+ static const Name m_name_bool;
+public:
+ const Name name() const { return m_name_bool; }
+ bool is_bool_type() const { return true; }
+ bool Item_sum_hybrid_fix_length_and_dec(Item_sum_hybrid *) const;
+};
+
+
class Type_handler_longlong: public Type_handler_general_purpose_int
{
static const Name m_name_longlong;
@@ -2463,6 +2591,13 @@ public:
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
+ Field *make_table_field_from_def(TABLE_SHARE *share,
+ MEM_ROOT *mem_root,
+ const LEX_CSTRING *name,
+ const Record_addr &addr,
+ const Bit_addr &bit,
+ const Column_definition_attributes *attr,
+ uint32 flags) const;
void Item_param_set_param_func(Item_param *param,
uchar **pos, ulong len) const;
};
@@ -2508,6 +2643,13 @@ public:
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
+ Field *make_table_field_from_def(TABLE_SHARE *share,
+ MEM_ROOT *mem_root,
+ const LEX_CSTRING *name,
+ const Record_addr &addr,
+ const Bit_addr &bit,
+ const Column_definition_attributes *attr,
+ uint32 flags) const;
};
@@ -2535,6 +2677,13 @@ public:
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
+ Field *make_table_field_from_def(TABLE_SHARE *share,
+ MEM_ROOT *mem_root,
+ const LEX_CSTRING *name,
+ const Record_addr &addr,
+ const Bit_addr &bit,
+ const Column_definition_attributes *attr,
+ uint32 flags) const;
Item_cache *Item_get_cache(THD *thd, const Item *item) const;
bool Item_get_date(Item *item, MYSQL_TIME *ltime, ulonglong fuzzydate) const;
};
@@ -2577,6 +2726,13 @@ public:
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
+ Field *make_table_field_from_def(TABLE_SHARE *share,
+ MEM_ROOT *mem_root,
+ const LEX_CSTRING *name,
+ const Record_addr &addr,
+ const Bit_addr &bit,
+ const Column_definition_attributes *attr,
+ uint32 flags) const;
bool Vers_history_point_resolve_unit(THD *thd, Vers_history_point *p) const;
};
@@ -2607,6 +2763,13 @@ public:
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
+ Field *make_table_field_from_def(TABLE_SHARE *share,
+ MEM_ROOT *mem_root,
+ const LEX_CSTRING *name,
+ const Record_addr &addr,
+ const Bit_addr &bit,
+ const Column_definition_attributes *attr,
+ uint32 flags) const;
void Item_param_set_param_func(Item_param *param,
uchar **pos, ulong len) const;
};
@@ -2639,6 +2802,13 @@ public:
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
+ Field *make_table_field_from_def(TABLE_SHARE *share,
+ MEM_ROOT *mem_root,
+ const LEX_CSTRING *name,
+ const Record_addr &addr,
+ const Bit_addr &bit,
+ const Column_definition_attributes *attr,
+ uint32 flags) const;
void Item_param_set_param_func(Item_param *param,
uchar **pos, ulong len) const;
};
@@ -2722,6 +2892,13 @@ public:
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
+ Field *make_table_field_from_def(TABLE_SHARE *share,
+ MEM_ROOT *mem_root,
+ const LEX_CSTRING *name,
+ const Record_addr &addr,
+ const Bit_addr &bit,
+ const Column_definition_attributes *attr,
+ uint32 flags) const;
};
@@ -2741,6 +2918,13 @@ public:
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
+ Field *make_table_field_from_def(TABLE_SHARE *share,
+ MEM_ROOT *mem_root,
+ const LEX_CSTRING *name,
+ const Record_addr &addr,
+ const Bit_addr &bit,
+ const Column_definition_attributes *attr,
+ uint32 flags) const;
};
@@ -2803,6 +2987,13 @@ public:
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
+ Field *make_table_field_from_def(TABLE_SHARE *share,
+ MEM_ROOT *mem_root,
+ const LEX_CSTRING *name,
+ const Record_addr &addr,
+ const Bit_addr &bit,
+ const Column_definition_attributes *attr,
+ uint32 flags) const;
};
@@ -2822,6 +3013,13 @@ public:
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
+ Field *make_table_field_from_def(TABLE_SHARE *share,
+ MEM_ROOT *mem_root,
+ const LEX_CSTRING *name,
+ const Record_addr &addr,
+ const Bit_addr &bit,
+ const Column_definition_attributes *attr,
+ uint32 flags) const;
};
@@ -2883,6 +3081,13 @@ public:
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
+ Field *make_table_field_from_def(TABLE_SHARE *share,
+ MEM_ROOT *mem_root,
+ const LEX_CSTRING *name,
+ const Record_addr &addr,
+ const Bit_addr &bit,
+ const Column_definition_attributes *attr,
+ uint32 flags) const;
};
@@ -2902,6 +3107,13 @@ public:
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
+ Field *make_table_field_from_def(TABLE_SHARE *share,
+ MEM_ROOT *mem_root,
+ const LEX_CSTRING *name,
+ const Record_addr &addr,
+ const Bit_addr &bit,
+ const Column_definition_attributes *attr,
+ uint32 flags) const;
};
@@ -2965,6 +3177,13 @@ public:
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
+ Field *make_table_field_from_def(TABLE_SHARE *share,
+ MEM_ROOT *mem_root,
+ const LEX_CSTRING *name,
+ const Record_addr &addr,
+ const Bit_addr &bit,
+ const Column_definition_attributes *attr,
+ uint32 flags) const;
};
@@ -2986,6 +3205,13 @@ public:
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
+ Field *make_table_field_from_def(TABLE_SHARE *share,
+ MEM_ROOT *mem_root,
+ const LEX_CSTRING *name,
+ const Record_addr &addr,
+ const Bit_addr &bit,
+ const Column_definition_attributes *attr,
+ uint32 flags) const;
};
@@ -3010,6 +3236,13 @@ public:
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
+ Field *make_table_field_from_def(TABLE_SHARE *share,
+ MEM_ROOT *mem_root,
+ const LEX_CSTRING *name,
+ const Record_addr &addr,
+ const Bit_addr &bit,
+ const Column_definition_attributes *attr,
+ uint32 flags) const;
};
@@ -3041,6 +3274,13 @@ public:
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
+ Field *make_table_field_from_def(TABLE_SHARE *share,
+ MEM_ROOT *mem_root,
+ const LEX_CSTRING *name,
+ const Record_addr &addr,
+ const Bit_addr &bit,
+ const Column_definition_attributes *attr,
+ uint32 flags) const;
};
@@ -3079,6 +3319,13 @@ public:
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
+ Field *make_table_field_from_def(TABLE_SHARE *share,
+ MEM_ROOT *mem_root,
+ const LEX_CSTRING *name,
+ const Record_addr &addr,
+ const Bit_addr &bit,
+ const Column_definition_attributes *attr,
+ uint32 flags) const;
};
@@ -3115,6 +3362,13 @@ public:
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
+ Field *make_table_field_from_def(TABLE_SHARE *share,
+ MEM_ROOT *mem_root,
+ const LEX_CSTRING *name,
+ const Record_addr &addr,
+ const Bit_addr &bit,
+ const Column_definition_attributes *attr,
+ uint32 flags) const;
};
@@ -3127,6 +3381,10 @@ public:
const Name name() const { return m_name_var_string; }
enum_field_types field_type() const { return MYSQL_TYPE_VAR_STRING; }
enum_field_types real_field_type() const { return MYSQL_TYPE_STRING; }
+ enum_field_types traditional_merge_field_type() const
+ {
+ return MYSQL_TYPE_VARCHAR;
+ }
const Type_handler *type_handler_for_tmp_table(const Item *item) const
{
return varstring_type_handler(item);
@@ -3173,6 +3431,13 @@ public:
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
+ Field *make_table_field_from_def(TABLE_SHARE *share,
+ MEM_ROOT *mem_root,
+ const LEX_CSTRING *name,
+ const Record_addr &addr,
+ const Bit_addr &bit,
+ const Column_definition_attributes *attr,
+ uint32 flags) const;
bool adjust_spparam_type(Spvar_definition *def, Item *from) const;
};
@@ -3216,6 +3481,13 @@ public:
Item **items, uint nitems) const;
void Item_param_setup_conversion(THD *thd, Item_param *) const;
+ Field *make_table_field_from_def(TABLE_SHARE *share,
+ MEM_ROOT *mem_root,
+ const LEX_CSTRING *name,
+ const Record_addr &addr,
+ const Bit_addr &bit,
+ const Column_definition_attributes *attr,
+ uint32 flags) const;
};
@@ -3317,6 +3589,14 @@ public:
const st_value *value) const;
Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const;
+ void
+ Column_definition_attributes_frm_pack(const Column_definition_attributes *at,
+ uchar *buff) const;
+ bool
+ Column_definition_attributes_frm_unpack(Column_definition_attributes *attr,
+ TABLE_SHARE *share,
+ const uchar *buffer,
+ LEX_CUSTRING *gis_options) const;
bool Column_definition_fix_attributes(Column_definition *c) const;
bool Column_definition_prepare_stage1(THD *thd,
MEM_ROOT *mem_root,
@@ -3331,6 +3611,14 @@ public:
const Type_all_attributes &attr,
TABLE *table) const;
+ Field *make_table_field_from_def(TABLE_SHARE *share,
+ MEM_ROOT *mem_root,
+ const LEX_CSTRING *name,
+ const Record_addr &addr,
+ const Bit_addr &bit,
+ const Column_definition_attributes *attr,
+ uint32 flags) const;
+
bool can_return_int() const { return false; }
bool can_return_decimal() const { return false; }
bool can_return_real() const { return false; }
@@ -3402,7 +3690,11 @@ class Type_handler_enum: public Type_handler_typelib
public:
virtual ~Type_handler_enum() {}
const Name name() const { return m_name_enum; }
- virtual enum_field_types real_field_type() const { return MYSQL_TYPE_ENUM; }
+ enum_field_types real_field_type() const { return MYSQL_TYPE_ENUM; }
+ enum_field_types traditional_merge_field_type() const
+ {
+ return MYSQL_TYPE_ENUM;
+ }
uint32 calc_pack_length(uint32 length) const;
Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const;
@@ -3414,6 +3706,13 @@ public:
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
+ Field *make_table_field_from_def(TABLE_SHARE *share,
+ MEM_ROOT *mem_root,
+ const LEX_CSTRING *name,
+ const Record_addr &addr,
+ const Bit_addr &bit,
+ const Column_definition_attributes *attr,
+ uint32 flags) const;
};
@@ -3423,7 +3722,11 @@ class Type_handler_set: public Type_handler_typelib
public:
virtual ~Type_handler_set() {}
const Name name() const { return m_name_set; }
- virtual enum_field_types real_field_type() const { return MYSQL_TYPE_SET; }
+ enum_field_types real_field_type() const { return MYSQL_TYPE_SET; }
+ enum_field_types traditional_merge_field_type() const
+ {
+ return MYSQL_TYPE_SET;
+ }
uint32 calc_pack_length(uint32 length) const;
Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const;
@@ -3435,6 +3738,13 @@ public:
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
+ Field *make_table_field_from_def(TABLE_SHARE *share,
+ MEM_ROOT *mem_root,
+ const LEX_CSTRING *name,
+ const Record_addr &addr,
+ const Bit_addr &bit,
+ const Column_definition_attributes *attr,
+ uint32 flags) const;
};
@@ -3541,6 +3851,7 @@ extern MYSQL_PLUGIN_IMPORT Type_handler_medium_blob type_handler_medium_blob;
extern MYSQL_PLUGIN_IMPORT Type_handler_long_blob type_handler_long_blob;
extern MYSQL_PLUGIN_IMPORT Type_handler_blob type_handler_blob;
+extern MYSQL_PLUGIN_IMPORT Type_handler_bool type_handler_bool;
extern MYSQL_PLUGIN_IMPORT Type_handler_tiny type_handler_tiny;
extern MYSQL_PLUGIN_IMPORT Type_handler_short type_handler_short;
extern MYSQL_PLUGIN_IMPORT Type_handler_int24 type_handler_int24;
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index c0fa2b4d7fe..b56f7383837 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -974,7 +974,7 @@ update_begin:
myf flags= 0;
if (table->file->is_fatal_error(error, HA_CHECK_ALL))
- flags|= ME_FATALERROR; /* Other handler errors are fatal */
+ flags|= ME_FATAL; /* Other handler errors are fatal */
prepare_record_for_error_message(error, table);
table->file->print_error(error,MYF(flags));
@@ -1085,7 +1085,7 @@ update_begin:
{
/* purecov: begin inspected */
prepare_record_for_error_message(loc_error, table);
- table->file->print_error(loc_error,MYF(ME_FATALERROR));
+ table->file->print_error(loc_error,MYF(ME_FATAL));
error= 1;
/* purecov: end */
}
@@ -2245,11 +2245,11 @@ int multi_update::prepare2(JOIN *join)
{
if (item_rowid_table(*it2) != tbl)
continue;
- Item *fld= new (thd->mem_root)
- Item_field(thd, (*it)->get_tmp_table_field());
+ Item_field *fld= new (thd->mem_root)
+ Item_field(thd, (*it)->get_tmp_table_field());
if (!fld)
return 1;
- fld->set_result_field((*it2)->get_tmp_table_field());
+ fld->result_field= (*it2)->get_tmp_table_field();
*it2= fld;
}
}
@@ -2381,7 +2381,7 @@ int multi_update::send_data(List<Item> &not_used_values)
myf flags= 0;
if (table->file->is_fatal_error(error, HA_CHECK_ALL))
- flags|= ME_FATALERROR; /* Other handler errors are fatal */
+ flags|= ME_FATAL; /* Other handler errors are fatal */
prepare_record_for_error_message(error, table);
table->file->print_error(error,MYF(flags));
@@ -2536,17 +2536,10 @@ int multi_update::do_updates()
not its dependencies
*/
while(TABLE *tbl= check_opt_it++)
- {
- if (tbl->vcol_set)
- {
- bitmap_clear_all(tbl->vcol_set);
- for (Field **vf= tbl->vfield; *vf; vf++)
- {
+ if (Field **vf= tbl->vfield)
+ for (; *vf; vf++)
if (bitmap_is_set(tbl->read_set, (*vf)->field_index))
- tbl->mark_virtual_col(*vf);
- }
- }
- }
+ (*vf)->vcol_info->expr->walk(&Item::register_field_in_read_map, 1, 0);
for (cur_table= update_tables; cur_table; cur_table= cur_table->next_local)
{
@@ -2636,10 +2629,10 @@ int multi_update::do_updates()
uint field_num= 0;
do
{
- if (unlikely((local_error=
- tbl->file->ha_rnd_pos(tbl->record[0],
- (uchar *) tmp_table->
- field[field_num]->ptr))))
+ String rowid;
+ tmp_table->field[field_num]->val_str(&rowid);
+ if (unlikely((local_error= tbl->file->ha_rnd_pos(tbl->record[0],
+ (uchar*)rowid.ptr()))))
{
err_table= tbl;
goto err;
@@ -2756,7 +2749,7 @@ int multi_update::do_updates()
err:
{
prepare_record_for_error_message(local_error, err_table);
- err_table->file->print_error(local_error,MYF(ME_FATALERROR));
+ err_table->file->print_error(local_error,MYF(ME_FATAL));
}
err2:
diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc
index ccb7d3b29ed..658bb0e2d1c 100644
--- a/sql/sys_vars.cc
+++ b/sql/sys_vars.cc
@@ -2483,6 +2483,7 @@ export const char *optimizer_switch_names[]=
"orderby_uses_equalities",
"condition_pushdown_for_derived",
"split_materialized",
+ "condition_pushdown_for_subquery",
"default",
NullS
};
diff --git a/sql/table.cc b/sql/table.cc
index 58e0c0a9189..fc53ac9d821 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -915,6 +915,54 @@ static uint upgrade_collation(ulong mysql_version, uint cs_number)
}
+void Column_definition_attributes::frm_pack_basic(uchar *buff) const
+{
+ int2store(buff + 3, length);
+ int2store(buff + 8, pack_flag);
+ buff[10]= (uchar) unireg_check;
+}
+
+
+void Column_definition_attributes::frm_unpack_basic(const uchar *buff)
+{
+ length= uint2korr(buff + 3);
+ pack_flag= uint2korr(buff + 8);
+ unireg_check= (Field::utype) MTYP_TYPENR((uint) buff[10]);
+}
+
+
+void Column_definition_attributes::frm_pack_charset(uchar *buff) const
+{
+ buff[11]= (uchar) (charset->number >> 8);
+ buff[14]= (uchar) charset->number;
+}
+
+
+bool Column_definition_attributes::frm_unpack_charset(TABLE_SHARE *share,
+ const uchar *buff)
+{
+ uint cs_org= buff[14] + (((uint) buff[11]) << 8);
+ uint cs_new= upgrade_collation(share->mysql_version, cs_org);
+ if (cs_org != cs_new)
+ share->incompatible_version|= HA_CREATE_USED_CHARSET;
+ if (cs_new && !(charset= get_charset(cs_new, MYF(0))))
+ {
+ const char *csname= get_charset_name((uint) cs_new);
+ char tmp[10];
+ if (!csname || csname[0] =='?')
+ {
+ my_snprintf(tmp, sizeof(tmp), "#%u", cs_new);
+ csname= tmp;
+ }
+ my_printf_error(ER_UNKNOWN_COLLATION,
+ "Unknown collation '%s' in table '%-.64s' definition",
+ MYF(0), csname, share->table_name.str);
+ return true;
+ }
+ return false;
+}
+
+
/*
In MySQL 5.7 the null bits for not stored virtual fields are last.
Calculate the position for these bits
@@ -1145,6 +1193,38 @@ end:
DBUG_RETURN(res);
}
+
+static const Type_handler *old_frm_type_handler(uint pack_flag,
+ uint interval_nr)
+{
+ enum_field_types field_type= (enum_field_types) f_packtype(pack_flag);
+ DBUG_ASSERT(field_type < 16);
+
+ if (!f_is_alpha(pack_flag))
+ return Type_handler::get_handler_by_real_type(field_type);
+
+ if (!f_is_packed(pack_flag))
+ {
+ if (field_type == MYSQL_TYPE_DECIMAL) // 3.23 or 4.0 string
+ return &type_handler_string;
+ if (field_type == MYSQL_TYPE_VARCHAR) // Since mysql-5.0
+ return &type_handler_varchar;
+ return NULL; // Error (bad frm?)
+ }
+
+ if (f_is_blob(pack_flag))
+ return &type_handler_blob; // QQ: exact type??
+
+ if (interval_nr)
+ {
+ if (f_is_enum(pack_flag))
+ return &type_handler_enum;
+ return &type_handler_set;
+ }
+ return Type_handler::get_handler_by_real_type(field_type);
+}
+
+
/**
Read data from a binary .frm file image into a TABLE_SHARE
@@ -1191,8 +1271,7 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
size_t UNINIT_VAR(options_len);
uchar *vcol_screen_pos;
const uchar *options= 0;
- size_t UNINIT_VAR(gis_options_len);
- const uchar *gis_options= 0;
+ LEX_CUSTRING gis_options= { NULL, 0};
KEY first_keyinfo;
uint len;
uint ext_key_parts= 0;
@@ -1288,10 +1367,10 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
case EXTRA2_GIS:
#ifdef HAVE_SPATIAL
{
- if (gis_options)
+ if (gis_options.str)
goto err;
- gis_options= extra2;
- gis_options_len= length;
+ gis_options.str= extra2;
+ gis_options.length= length;
}
#endif /*HAVE_SPATIAL*/
break;
@@ -1782,82 +1861,19 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
for (i=0 ; i < share->fields; i++, strpos+=field_pack_length, field_ptr++)
{
- uint pack_flag, interval_nr, unireg_type, recpos, field_length;
- uint vcol_info_length=0;
- uint vcol_expr_length=0;
- enum_field_types field_type;
- CHARSET_INFO *charset=NULL;
- Field::geometry_type geom_type= Field::GEOM_GEOMETRY;
+ uint interval_nr= 0, recpos;
LEX_CSTRING comment;
LEX_CSTRING name;
Virtual_column_info *vcol_info= 0;
- uint gis_length, gis_decimals, srid= 0;
- Field::utype unireg_check;
const Type_handler *handler;
uint32 flags= 0;
+ Column_definition_attributes attr;
if (new_frm_ver >= 3)
{
/* new frm file in 4.1 */
- field_length= uint2korr(strpos+3);
recpos= uint3korr(strpos+5);
- pack_flag= uint2korr(strpos+8);
- unireg_type= (uint) strpos[10];
- interval_nr= (uint) strpos[12];
uint comment_length=uint2korr(strpos+15);
- field_type=(enum_field_types) (uint) strpos[13];
-
- /* charset and geometry_type share the same byte in frm */
- if (field_type == MYSQL_TYPE_GEOMETRY)
- {
-#ifdef HAVE_SPATIAL
- uint gis_opt_read;
- Field_geom::storage_type st_type;
- geom_type= (Field::geometry_type) strpos[14];
- charset= &my_charset_bin;
- gis_opt_read= gis_field_options_read(gis_options, gis_options_len,
- &st_type, &gis_length, &gis_decimals, &srid);
- gis_options+= gis_opt_read;
- gis_options_len-= gis_opt_read;
-#else
- goto err;
-#endif
- }
- else
- {
- uint cs_org= strpos[14] + (((uint) strpos[11]) << 8);
- uint cs_new= upgrade_collation(share->mysql_version, cs_org);
- if (cs_org != cs_new)
- share->incompatible_version|= HA_CREATE_USED_CHARSET;
- if (!cs_new)
- charset= &my_charset_bin;
- else if (!(charset= get_charset(cs_new, MYF(0))))
- {
- const char *csname= get_charset_name((uint) cs_new);
- char tmp[10];
- if (!csname || csname[0] =='?')
- {
- my_snprintf(tmp, sizeof(tmp), "#%u", cs_new);
- csname= tmp;
- }
- my_printf_error(ER_UNKNOWN_COLLATION,
- "Unknown collation '%s' in table '%-.64s' definition",
- MYF(0), csname, share->table_name.str);
- goto err;
- }
- }
-
- if ((uchar)field_type == (uchar)MYSQL_TYPE_VIRTUAL)
- {
- DBUG_ASSERT(interval_nr); // Expect non-null expression
- /*
- MariaDB version 10.0 version.
- The interval_id byte in the .frm file stores the length of the
- expression statement for a virtual column.
- */
- vcol_info_length= interval_nr;
- interval_nr= 0;
- }
if (!comment_length)
{
@@ -1871,32 +1887,20 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
comment_pos+= comment_length;
}
- if (unireg_type & MYSQL57_GENERATED_FIELD)
+ if ((uchar) strpos[13] == (uchar) MYSQL_TYPE_VIRTUAL)
{
- unireg_type&= MYSQL57_GENERATED_FIELD;
-
/*
- MySQL 5.7 generated fields
-
- byte 1 = 1
- byte 2,3 = expr length
- byte 4 = stored_in_db
- byte 5.. = expr
+ MariaDB version 10.0 version.
+ The interval_id byte in the .frm file stores the length of the
+ expression statement for a virtual column.
*/
- if ((uint)(vcol_screen_pos)[0] != 1)
- goto err;
- vcol_info= new (&share->mem_root) Virtual_column_info();
- vcol_info_length= uint2korr(vcol_screen_pos + 1);
- DBUG_ASSERT(vcol_info_length);
- vcol_info->stored_in_db= vcol_screen_pos[3];
- vcol_info->utf8= 0;
- vcol_screen_pos+= vcol_info_length + MYSQL57_GCOL_HEADER_SIZE;;
- share->virtual_fields++;
- vcol_info_length= 0;
- }
+ uint vcol_info_length= (uint) strpos[12];
- if (vcol_info_length)
- {
+ DBUG_ASSERT(vcol_info_length); // Expect non-null expression
+
+ attr.frm_unpack_basic(strpos);
+ if (attr.frm_unpack_charset(share, strpos))
+ goto err;
/*
Old virtual field information before 10.2
@@ -1910,7 +1914,9 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
vcol_info= new (&share->mem_root) Virtual_column_info();
bool opt_interval_id= (uint)vcol_screen_pos[0] == 2;
- field_type= (enum_field_types) (uchar) vcol_screen_pos[1];
+ enum_field_types ftype= (enum_field_types) (uchar) vcol_screen_pos[1];
+ if (!(handler= Type_handler::get_handler_by_real_type(ftype)))
+ goto err;
if (opt_interval_id)
interval_nr= (uint)vcol_screen_pos[3];
else if ((uint)vcol_screen_pos[0] != 1)
@@ -1918,26 +1924,63 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
bool stored= vcol_screen_pos[2] & 1;
vcol_info->stored_in_db= stored;
vcol_info->set_vcol_type(stored ? VCOL_GENERATED_STORED : VCOL_GENERATED_VIRTUAL);
- vcol_expr_length= vcol_info_length -
- (uint)(FRM_VCOL_OLD_HEADER_SIZE(opt_interval_id));
+ uint vcol_expr_length= vcol_info_length -
+ (uint)(FRM_VCOL_OLD_HEADER_SIZE(opt_interval_id));
vcol_info->utf8= 0; // before 10.2.1 the charset was unknown
int2store(vcol_screen_pos+1, vcol_expr_length); // for parse_vcol_defs()
vcol_screen_pos+= vcol_info_length;
share->virtual_fields++;
}
+ else
+ {
+ interval_nr= (uint) strpos[12];
+ enum_field_types field_type= (enum_field_types) strpos[13];
+ if (!(handler= Type_handler::get_handler_by_real_type(field_type)))
+ goto err; // Not supported field type
+ if (handler->Column_definition_attributes_frm_unpack(&attr, share,
+ strpos,
+ &gis_options))
+ goto err;
+ }
+
+ if (((uint) strpos[10]) & MYSQL57_GENERATED_FIELD)
+ {
+ attr.unireg_check= Field::NONE;
+
+ /*
+ MySQL 5.7 generated fields
+
+ byte 1 = 1
+ byte 2,3 = expr length
+ byte 4 = stored_in_db
+ byte 5.. = expr
+ */
+ if ((uint)(vcol_screen_pos)[0] != 1)
+ goto err;
+ vcol_info= new (&share->mem_root) Virtual_column_info();
+ uint vcol_info_length= uint2korr(vcol_screen_pos + 1);
+ DBUG_ASSERT(vcol_info_length);
+ vcol_info->stored_in_db= vcol_screen_pos[3];
+ vcol_info->utf8= 0;
+ vcol_screen_pos+= vcol_info_length + MYSQL57_GCOL_HEADER_SIZE;;
+ share->virtual_fields++;
+ }
}
else
{
- field_length= (uint) strpos[3];
+ attr.length= (uint) strpos[3];
recpos= uint2korr(strpos+4),
- pack_flag= uint2korr(strpos+6);
- pack_flag&= ~FIELDFLAG_NO_DEFAULT; // Safety for old files
- unireg_type= (uint) strpos[8];
+ attr.pack_flag= uint2korr(strpos+6);
+ attr.pack_flag&= ~FIELDFLAG_NO_DEFAULT; // Safety for old files
+ attr.unireg_check= (Field::utype) MTYP_TYPENR((uint) strpos[8]);
interval_nr= (uint) strpos[10];
/* old frm file */
- field_type= (enum_field_types) f_packtype(pack_flag);
- if (f_is_binary(pack_flag))
+ enum_field_types ftype= (enum_field_types) f_packtype(attr.pack_flag);
+ if (!(handler= Type_handler::get_handler_by_real_type(ftype)))
+ goto err; // Not supported field type
+
+ if (f_is_binary(attr.pack_flag))
{
/*
Try to choose the best 4.1 type:
@@ -1945,26 +1988,26 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
try to find a binary collation for character set.
- for other types (e.g. BLOB) just use my_charset_bin.
*/
- if (!f_is_blob(pack_flag))
+ if (!f_is_blob(attr.pack_flag))
{
// 3.23 or 4.0 string
- if (!(charset= get_charset_by_csname(share->table_charset->csname,
- MY_CS_BINSORT, MYF(0))))
- charset= &my_charset_bin;
+ if (!(attr.charset= get_charset_by_csname(share->table_charset->csname,
+ MY_CS_BINSORT, MYF(0))))
+ attr.charset= &my_charset_bin;
}
- else
- charset= &my_charset_bin;
}
else
- charset= share->table_charset;
+ attr.charset= share->table_charset;
bzero((char*) &comment, sizeof(comment));
+ if ((!(handler= old_frm_type_handler(attr.pack_flag, interval_nr))))
+ goto err; // Not supported field type
}
/* Remove >32 decimals from old files */
if (share->mysql_version < 100200)
- pack_flag&= ~FIELDFLAG_LONG_DECIMAL;
+ attr.pack_flag&= ~FIELDFLAG_LONG_DECIMAL;
- if (interval_nr && charset->mbminlen > 1)
+ if (interval_nr && attr.charset->mbminlen > 1)
{
/* Unescape UCS2 intervals from HEX notation */
TYPELIB *interval= share->intervals + interval_nr - 1;
@@ -1972,17 +2015,18 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
}
#ifndef TO_BE_DELETED_ON_PRODUCTION
- if (field_type == MYSQL_TYPE_NEWDECIMAL && !share->mysql_version)
+ if (handler->real_field_type() == MYSQL_TYPE_NEWDECIMAL &&
+ !share->mysql_version)
{
/*
Fix pack length of old decimal values from 5.0.3 -> 5.0.4
The difference is that in the old version we stored precision
in the .frm table while we now store the display_length
*/
- uint decimals= f_decimals(pack_flag);
- field_length= my_decimal_precision_to_length(field_length,
- decimals,
- f_is_dec(pack_flag) == 0);
+ uint decimals= f_decimals(attr.pack_flag);
+ attr.length=
+ my_decimal_precision_to_length((uint) attr.length, decimals,
+ f_is_dec(attr.pack_flag) == 0);
sql_print_error("Found incompatible DECIMAL field '%s' in %s; "
"Please do \"ALTER TABLE '%s' FORCE\" to fix it!",
share->fieldnames.type_names[i], share->table_name.str,
@@ -2013,7 +2057,7 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
if (flags & VERS_SYSTEM_FIELD)
{
- switch (field_type)
+ switch (handler->real_field_type())
{
case MYSQL_TYPE_TIMESTAMP2:
case MYSQL_TYPE_DATETIME2:
@@ -2035,22 +2079,17 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
}
/* Convert pre-10.2.2 timestamps to use Field::default_value */
- unireg_check= (Field::utype) MTYP_TYPENR(unireg_type);
name.str= fieldnames.type_names[i];
name.length= strlen(name.str);
- if (!(handler= Type_handler::get_handler_by_real_type(field_type)))
- goto err; // Not supported field type
+ attr.interval= interval_nr ? share->intervals + interval_nr - 1 : NULL;
+ Record_addr addr(record + recpos, null_pos, null_bit_pos);
*field_ptr= reg_field=
- make_field(share, &share->mem_root, record+recpos, (uint32) field_length,
- null_pos, null_bit_pos, pack_flag, handler, charset,
- geom_type, srid, unireg_check,
- (interval_nr ? share->intervals+interval_nr-1 : NULL),
- &name, flags);
+ attr.make_field(share, &share->mem_root, &addr, handler, &name, flags);
if (!reg_field) // Not supported field type
goto err;
- if (unireg_check == Field::TIMESTAMP_DNUN_FIELD ||
- unireg_check == Field::TIMESTAMP_DN_FIELD)
+ if (attr.unireg_check == Field::TIMESTAMP_DNUN_FIELD ||
+ attr.unireg_check == Field::TIMESTAMP_DN_FIELD)
{
reg_field->default_value= new (&share->mem_root) Virtual_column_info();
reg_field->default_value->set_vcol_type(VCOL_DEFAULT);
@@ -2074,10 +2113,11 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
status_var_increment(thd->status_var.feature_invisible_columns);
if (!reg_field->invisible)
share->visible_fields++;
- if (field_type == MYSQL_TYPE_BIT && !f_bit_as_char(pack_flag))
+ if (handler->real_field_type() == MYSQL_TYPE_BIT &&
+ !f_bit_as_char(attr.pack_flag))
{
null_bits_are_used= 1;
- if ((null_bit_pos+= field_length & 7) > 7)
+ if ((null_bit_pos+= (uint) (attr.length & 7)) > 7)
{
null_pos++;
null_bit_pos-= 8;
@@ -2100,7 +2140,7 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
}
}
- if (f_no_default(pack_flag))
+ if (f_no_default(attr.pack_flag))
reg_field->flags|= NO_DEFAULT_VALUE_FLAG;
if (reg_field->unireg_check == Field::NEXT_NUMBER)
@@ -2978,7 +3018,7 @@ static bool fix_and_check_vcol_expr(THD *thd, TABLE *table,
of the statement because the field item does not have a field
pointer at that time
*/
- myf warn= table->s->frm_version < FRM_VER_EXPRESSSIONS ? ME_JUST_WARNING : 0;
+ myf warn= table->s->frm_version < FRM_VER_EXPRESSSIONS ? ME_WARNING : 0;
my_error(ER_VIRTUAL_COLUMN_FUNCTION_IS_NOT_ALLOWED, MYF(warn),
"AUTO_INCREMENT", vcol->get_vcol_type_name(), res.name);
if (!warn)
@@ -3425,17 +3465,6 @@ partititon_err:
(my_bitmap_map*) bitmaps, share->fields, FALSE);
bitmaps+= bitmap_size;
- /* Don't allocate vcol_bitmap if we don't need it */
- if (share->virtual_fields)
- {
- if (!(outparam->def_vcol_set= (MY_BITMAP*)
- alloc_root(&outparam->mem_root, sizeof(*outparam->def_vcol_set))))
- goto err;
- my_bitmap_init(outparam->def_vcol_set,
- (my_bitmap_map*) bitmaps, share->fields, FALSE);
- bitmaps+= bitmap_size;
- }
-
my_bitmap_init(&outparam->has_value_set,
(my_bitmap_map*) bitmaps, share->fields, FALSE);
bitmaps+= bitmap_size;
@@ -3628,7 +3657,7 @@ void open_table_error(TABLE_SHARE *share, enum open_frm_error error,
int db_errno)
{
char buff[FN_REFLEN];
- const myf errortype= ME_ERROR+ME_WAITTANG; // Write fatals error to log
+ const myf errortype= ME_ERROR_LOG; // Write fatals error to log
DBUG_ENTER("open_table_error");
DBUG_PRINT("info", ("error: %d db_errno: %d", error, db_errno));
@@ -5209,7 +5238,7 @@ int TABLE_LIST::view_check_option(THD *thd, bool ignore_failure)
main_view->db.str);
const char *name_table= (main_view->view ? main_view->view_name.str :
main_view->table_name.str);
- my_error(ER_VIEW_CHECK_FAILED, MYF(ignore_failure ? ME_JUST_WARNING : 0),
+ my_error(ER_VIEW_CHECK_FAILED, MYF(ignore_failure ? ME_WARNING : 0),
name_db, name_table);
return ignore_failure ? VIEW_CHECK_SKIP : VIEW_CHECK_ERROR;
}
@@ -5241,7 +5270,7 @@ int TABLE::verify_constraints(bool ignore_failure)
in_use->is_error())
{
my_error(ER_CONSTRAINT_FAILED,
- MYF(ignore_failure ? ME_JUST_WARNING : 0), (*chk)->name.str,
+ MYF(ignore_failure ? ME_WARNING : 0), (*chk)->name.str,
s->db.str, s->table_name.str);
return ignore_failure ? VIEW_CHECK_SKIP : VIEW_CHECK_ERROR;
}
@@ -6239,13 +6268,12 @@ void TABLE::clear_column_bitmaps()
Reset column read/write usage. It's identical to:
bitmap_clear_all(&table->def_read_set);
bitmap_clear_all(&table->def_write_set);
- if (s->virtual_fields) bitmap_clear_all(table->def_vcol_set);
The code assumes that the bitmaps are allocated after each other, as
guaranteed by open_table_from_share()
*/
bzero((char*) def_read_set.bitmap,
s->column_bitmap_size * (s->virtual_fields ? 3 : 2));
- column_bitmaps_set(&def_read_set, &def_write_set, def_vcol_set);
+ column_bitmaps_set(&def_read_set, &def_write_set);
rpl_write_set= 0; // Safety
}
@@ -6393,11 +6421,7 @@ void TABLE::mark_columns_needed_for_delete()
for (reg_field= field ; *reg_field ; reg_field++)
{
if ((*reg_field)->flags & PART_KEY_FLAG)
- {
- bitmap_set_bit(read_set, (*reg_field)->field_index);
- if ((*reg_field)->vcol_info)
- mark_virtual_col(*reg_field);
- }
+ mark_column_with_deps(*reg_field);
}
need_signal= true;
}
@@ -6476,13 +6500,7 @@ void TABLE::mark_columns_needed_for_update()
if (any_written && !all_read)
{
for (KEY_PART_INFO *kp= k->key_part; kp < kpend; kp++)
- {
- int idx= kp->fieldnr - 1;
- if (bitmap_fast_test_and_set(read_set, idx))
- continue;
- if (field[idx]->vcol_info)
- mark_virtual_col(field[idx]);
- }
+ mark_column_with_deps(field[kp->fieldnr - 1]);
}
}
need_signal= true;
@@ -6679,49 +6697,12 @@ void TABLE::mark_columns_per_binlog_row_image()
DBUG_ASSERT(FALSE);
}
}
- /*
- We have to ensure that all virtual columns that are part of read set
- are calculated.
- */
- if (vcol_set)
- bitmap_union(vcol_set, read_set);
file->column_bitmaps_signal();
}
DBUG_VOID_RETURN;
}
-/*
- @brief Mark a column as virtual used by the query
-
- @param field the field for the column to be marked
-
- @details
- The function marks the column for 'field' as virtual (computed)
- in the bitmap vcol_set.
- If the column is marked for the first time the expression to compute
- the column is traversed and all columns that are occurred there are
- marked in the read_set of the table.
-
- @retval
- TRUE if column is marked for the first time
- @retval
- FALSE otherwise
-*/
-
-bool TABLE::mark_virtual_col(Field *field)
-{
- bool res;
- DBUG_ASSERT(field->vcol_info);
- if (!(res= bitmap_fast_test_and_set(vcol_set, field->field_index)))
- {
- Item *vcol_item= field->vcol_info->expr;
- DBUG_ASSERT(vcol_item);
- vcol_item->walk(&Item::register_field_in_read_map, 1, 0);
- }
- return res;
-}
-
/*
@brief Mark virtual columns for update/insert commands
@@ -6763,12 +6744,12 @@ bool TABLE::mark_virtual_columns_for_write(bool insert_fl
{
tmp_vfield= *vfield_ptr;
if (bitmap_is_set(write_set, tmp_vfield->field_index))
- bitmap_updated|= mark_virtual_col(tmp_vfield);
+ bitmap_updated|= mark_virtual_column_with_deps(tmp_vfield);
else if (tmp_vfield->vcol_info->stored_in_db ||
(tmp_vfield->flags & (PART_KEY_FLAG | FIELD_IN_PART_FUNC_FLAG)))
{
bitmap_set_bit(write_set, tmp_vfield->field_index);
- mark_virtual_col(tmp_vfield);
+ mark_virtual_column_with_deps(tmp_vfield);
bitmap_updated= true;
}
}
@@ -6858,8 +6839,6 @@ void TABLE::mark_columns_used_by_check_constraints(void)
void TABLE::mark_check_constraint_columns_for_read(void)
{
bitmap_union(read_set, s->check_set);
- if (vcol_set)
- bitmap_union(vcol_set, s->check_set);
}
@@ -7558,6 +7537,20 @@ public:
}
};
+
+/*
+ to satisfy ASSERT_COLUMN_MARKED_FOR_WRITE Field's assert we temporarily
+ mark field for write before storing the generated value in it
+*/
+#ifndef DBUG_OFF
+#define DBUG_FIX_WRITE_SET(f) bool _write_set_fixed= !bitmap_fast_test_and_set(write_set, (f)->field_index)
+#define DBUG_RESTORE_WRITE_SET(f) if (_write_set_fixed) bitmap_clear_bit(write_set, (f)->field_index)
+#else
+#define DBUG_FIX_WRITE_SET(f)
+#define DBUG_RESTORE_WRITE_SET(f)
+#endif
+
+
/*
@brief Compute values for virtual columns used in query
@@ -7621,16 +7614,16 @@ int TABLE::update_virtual_fields(handler *h, enum_vcol_update_mode update_mode)
switch (update_mode) {
case VCOL_UPDATE_FOR_READ:
update= (!vcol_info->stored_in_db &&
- bitmap_is_set(vcol_set, vf->field_index));
+ bitmap_is_set(read_set, vf->field_index));
swap_values= 1;
break;
case VCOL_UPDATE_FOR_DELETE:
case VCOL_UPDATE_FOR_WRITE:
- update= bitmap_is_set(vcol_set, vf->field_index);
+ update= bitmap_is_set(read_set, vf->field_index);
break;
case VCOL_UPDATE_FOR_REPLACE:
update= ((!vcol_info->stored_in_db && (vf->flags & PART_KEY_FLAG) &&
- bitmap_is_set(vcol_set, vf->field_index)) ||
+ bitmap_is_set(read_set, vf->field_index)) ||
update_all_columns);
if (update && (vf->flags & BLOB_FLAG))
{
@@ -7649,7 +7642,7 @@ int TABLE::update_virtual_fields(handler *h, enum_vcol_update_mode update_mode)
case VCOL_UPDATE_INDEXED_FOR_UPDATE:
/* Read indexed fields that was not updated in VCOL_UPDATE_FOR_READ */
update= (!vcol_info->stored_in_db && (vf->flags & PART_KEY_FLAG) &&
- !bitmap_is_set(vcol_set, vf->field_index));
+ !bitmap_is_set(read_set, vf->field_index));
swap_values= 1;
break;
}
@@ -7658,8 +7651,10 @@ int TABLE::update_virtual_fields(handler *h, enum_vcol_update_mode update_mode)
{
int field_error __attribute__((unused)) = 0;
/* Compute the actual value of the virtual fields */
+ DBUG_FIX_WRITE_SET(vf);
if (vcol_info->expr->save_in_field(vf, 0))
field_error= error= 1;
+ DBUG_RESTORE_WRITE_SET(vf);
DBUG_PRINT("info", ("field '%s' - updated error: %d",
vf->field_name.str, field_error));
if (swap_values && (vf->flags & BLOB_FLAG))
@@ -7693,7 +7688,9 @@ int TABLE::update_virtual_field(Field *vf)
in_use->set_n_backup_active_arena(expr_arena, &backup_arena);
bitmap_clear_all(&tmp_set);
vf->vcol_info->expr->walk(&Item::update_vcol_processor, 0, &tmp_set);
+ DBUG_FIX_WRITE_SET(vf);
vf->vcol_info->expr->save_in_field(vf, 0);
+ DBUG_RESTORE_WRITE_SET(vf);
in_use->restore_active_arena(expr_arena, &backup_arena);
DBUG_RETURN(in_use->is_error());
}
@@ -8349,200 +8346,6 @@ double KEY::actual_rec_per_key(uint i)
}
-/**
- @brief
- Mark subformulas of a condition unusable for the condition pushed into table
-
- @param cond The condition whose subformulas are to be marked
-
- @details
- This method recursively traverses the AND-OR condition cond and for each subformula
- of the codition it checks whether it can be usable for the extraction of a condition
- that can be pushed into this table. The subformulas that are not usable are
- marked with the flag NO_EXTRACTION_FL.
- @note
- This method is called before any call of TABLE_LIST::build_pushable_cond_for_table.
- The flag NO_EXTRACTION_FL set in a subformula allows to avoid building clone
- for the subformula when extracting the pushable condition.
-*/
-
-void TABLE_LIST::check_pushable_cond_for_table(Item *cond)
-{
- table_map tab_map= table->map;
- cond->clear_extraction_flag();
- if (cond->type() == Item::COND_ITEM)
- {
- bool and_cond= ((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC;
- List_iterator<Item> li(*((Item_cond*) cond)->argument_list());
- uint count= 0;
- Item *item;
- while ((item=li++))
- {
- check_pushable_cond_for_table(item);
- if (item->get_extraction_flag() != NO_EXTRACTION_FL)
- count++;
- else if (!and_cond)
- break;
- }
- if ((and_cond && count == 0) || item)
- {
- cond->set_extraction_flag(NO_EXTRACTION_FL);
- if (and_cond)
- li.rewind();
- while ((item= li++))
- item->clear_extraction_flag();
- }
- }
- else if (!cond->excl_dep_on_table(tab_map))
- cond->set_extraction_flag(NO_EXTRACTION_FL);
-}
-
-
-/**
- @brief
- Build condition extractable from the given one depended only on this table
-
- @param thd The thread handle
- @param cond The condition from which the pushable one is to be extracted
-
- @details
- For the given condition cond this method finds out what condition depended
- only on this table can be extracted from cond. If such condition C exists
- the method builds the item for it.
- The method uses the flag NO_EXTRACTION_FL set by the preliminary call of
- the method TABLE_LIST::check_pushable_cond_for_table to figure out whether
- a subformula depends only on this table or not.
- @note
- The built condition C is always implied by the condition cond
- (cond => C). The method tries to build the most restictive such
- condition (i.e. for any other condition C' such that cond => C'
- we have C => C').
- @note
- The build item is not ready for usage: substitution for the field items
- has to be done and it has to be re-fixed.
-
- @retval
- the built condition pushable into this table if such a condition exists
- NULL if there is no such a condition
-*/
-
-Item* TABLE_LIST::build_pushable_cond_for_table(THD *thd, Item *cond)
-{
- table_map tab_map= table->map;
- bool is_multiple_equality= cond->type() == Item::FUNC_ITEM &&
- ((Item_func*) cond)->functype() == Item_func::MULT_EQUAL_FUNC;
- if (cond->get_extraction_flag() == NO_EXTRACTION_FL)
- return 0;
- if (cond->type() == Item::COND_ITEM)
- {
- bool cond_and= false;
- Item_cond *new_cond;
- if (((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC)
- {
- cond_and= true;
- new_cond=new (thd->mem_root) Item_cond_and(thd);
- }
- else
- new_cond= new (thd->mem_root) Item_cond_or(thd);
- if (!new_cond)
- return 0;
- List_iterator<Item> li(*((Item_cond*) cond)->argument_list());
- Item *item;
- bool is_fix_needed= false;
- while ((item=li++))
- {
- if (item->get_extraction_flag() == NO_EXTRACTION_FL)
- {
- if (!cond_and)
- return 0;
- continue;
- }
- Item *fix= build_pushable_cond_for_table(thd, item);
- if (!fix && !cond_and)
- return 0;
- if (!fix)
- continue;
-
- if (fix->type() == Item::COND_ITEM &&
- ((Item_cond*) fix)->functype() == Item_func::COND_AND_FUNC)
- is_fix_needed= true;
-
- new_cond->argument_list()->push_back(fix, thd->mem_root);
- }
- if (is_fix_needed && new_cond->fix_fields(thd, 0))
- return 0;
-
- switch (new_cond->argument_list()->elements)
- {
- case 0:
- return 0;
- case 1:
- return new_cond->argument_list()->head();
- default:
- return new_cond;
- }
- }
- else if (is_multiple_equality)
- {
- if (!(cond->used_tables() & tab_map))
- return 0;
- Item *new_cond= NULL;
- int i= 0;
- Item_equal *item_equal= (Item_equal *) cond;
- Item *left_item = item_equal->get_const();
- Item_equal_fields_iterator it(*item_equal);
- Item *item;
- if (!left_item)
- {
- while ((item=it++))
- if (item->used_tables() == tab_map)
- {
- left_item= item;
- break;
- }
- }
- if (!left_item)
- return 0;
- while ((item=it++))
- {
- if (!(item->used_tables() == tab_map))
- continue;
- Item_func_eq *eq= 0;
- Item *left_item_clone= left_item->build_clone(thd);
- Item *right_item_clone= item->build_clone(thd);
- if (left_item_clone && right_item_clone)
- {
- left_item_clone->set_item_equal(NULL);
- right_item_clone->set_item_equal(NULL);
- eq= new (thd->mem_root) Item_func_eq(thd, right_item_clone,
- left_item_clone);
- }
- if (eq)
- {
- i++;
- switch (i)
- {
- case 1:
- new_cond= eq;
- break;
- case 2:
- new_cond= new (thd->mem_root) Item_cond_and(thd, new_cond, eq);
- break;
- default:
- ((Item_cond_and*)new_cond)->argument_list()->push_back(eq,
- thd->mem_root);
- }
- }
- }
- if (new_cond)
- new_cond->fix_fields(thd, &new_cond);
- return new_cond;
- }
- else if (cond->get_extraction_flag() != NO_EXTRACTION_FL)
- return cond->build_clone(thd);
- return 0;
-}
-
LEX_CSTRING *fk_option_name(enum_fk_option opt)
{
static LEX_CSTRING names[]=
diff --git a/sql/table.h b/sql/table.h
index ea00441fb5e..785fd9f3427 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -1150,8 +1150,6 @@ public:
MY_BITMAP cond_set; /* used to mark fields from sargable conditions*/
/* Active column sets */
MY_BITMAP *read_set, *write_set, *rpl_write_set;
- /* Set if using virtual fields */
- MY_BITMAP *vcol_set, *def_vcol_set;
/* On INSERT: fields that the user specified a value for */
MY_BITMAP has_value_set;
@@ -1372,7 +1370,9 @@ public:
void mark_columns_needed_for_delete(void);
void mark_columns_needed_for_insert(void);
void mark_columns_per_binlog_row_image(void);
- bool mark_virtual_col(Field *field);
+ inline bool mark_column_with_deps(Field *field);
+ inline bool mark_virtual_column_with_deps(Field *field);
+ inline void mark_virtual_column_deps(Field *field);
bool mark_virtual_columns_for_write(bool insert_fl);
bool check_virtual_columns_marked_for_read();
bool check_virtual_columns_marked_for_write();
@@ -1394,39 +1394,21 @@ public:
if (file)
file->column_bitmaps_signal();
}
- inline void column_bitmaps_set(MY_BITMAP *read_set_arg,
- MY_BITMAP *write_set_arg,
- MY_BITMAP *vcol_set_arg)
- {
- read_set= read_set_arg;
- write_set= write_set_arg;
- vcol_set= vcol_set_arg;
- if (file)
- file->column_bitmaps_signal();
- }
inline void column_bitmaps_set_no_signal(MY_BITMAP *read_set_arg,
MY_BITMAP *write_set_arg)
{
read_set= read_set_arg;
write_set= write_set_arg;
}
- inline void column_bitmaps_set_no_signal(MY_BITMAP *read_set_arg,
- MY_BITMAP *write_set_arg,
- MY_BITMAP *vcol_set_arg)
- {
- read_set= read_set_arg;
- write_set= write_set_arg;
- vcol_set= vcol_set_arg;
- }
inline void use_all_columns()
{
column_bitmaps_set(&s->all_set, &s->all_set);
}
+ inline void use_all_stored_columns();
inline void default_column_bitmaps()
{
read_set= &def_read_set;
write_set= &def_write_set;
- vcol_set= def_vcol_set; /* Note that this may be 0 */
rpl_write_set= 0;
}
/** Should this instance of the table be reopened? */
@@ -2596,8 +2578,6 @@ struct TABLE_LIST
return false;
}
void set_lock_type(THD* thd, enum thr_lock_type lock);
- void check_pushable_cond_for_table(Item *cond);
- Item *build_pushable_cond_for_table(THD *thd, Item *cond);
private:
bool prep_check_option(THD *thd, uint8 check_opt_type);
diff --git a/sql/unireg.cc b/sql/unireg.cc
index 6540e11578b..4692b2d74d1 100644
--- a/sql/unireg.cc
+++ b/sql/unireg.cc
@@ -897,32 +897,12 @@ static bool pack_fields(uchar **buff_arg, List<Create_field> &create_fields,
while ((field=it++))
{
uint recpos;
- int2store(buff+3, field->length);
/* The +1 is here becasue the col offset in .frm file have offset 1 */
recpos= field->offset+1 + (uint) data_offset;
int3store(buff+5,recpos);
- int2store(buff+8,field->pack_flag);
- buff[10]= (uchar) field->unireg_check;
buff[12]= (uchar) field->interval_id;
- buff[13]= (uchar) field->real_field_type();
- if (field->real_field_type() == MYSQL_TYPE_GEOMETRY)
- {
- buff[11]= 0;
- buff[14]= (uchar) field->geom_type;
-#ifndef HAVE_SPATIAL
- DBUG_ASSERT(0); // Should newer happen
-#endif
- }
- else if (field->charset)
- {
- buff[11]= (uchar) (field->charset->number >> 8);
- buff[14]= (uchar) field->charset->number;
- }
- else
- {
- buff[11]= buff[14]= 0; // Numerical
- }
-
+ buff[13]= (uchar) field->type_handler()->real_field_type();
+ field->type_handler()->Column_definition_attributes_frm_pack(field, buff);
int2store(buff+15, field->comment.length);
comment_length+= field->comment.length;
set_if_bigger(int_count,field->interval_id);
@@ -1043,21 +1023,16 @@ static bool make_empty_rec(THD *thd, uchar *buff, uint table_options,
thd->count_cuted_fields= CHECK_FIELD_WARN; // To find wrong default values
while ((field=it++))
{
+ Record_addr addr(buff + field->offset + data_offset,
+ null_pos + null_count / 8, null_count & 7);
+ Column_definition_attributes tmp(*field);
+ tmp.interval= field->save_interval ?
+ field->save_interval : field->interval;
/* regfield don't have to be deleted as it's allocated on THD::mem_root */
- Field *regfield= make_field(&share, thd->mem_root,
- buff+field->offset + data_offset,
- (uint32)field->length,
- null_pos + null_count / 8,
- null_count & 7,
- field->pack_flag,
- field->type_handler(),
- field->charset,
- field->geom_type, field->srid,
- field->unireg_check,
- field->save_interval ? field->save_interval
- : field->interval,
- &field->field_name,
- field->flags);
+ Field *regfield= tmp.make_field(&share, thd->mem_root, &addr,
+ field->type_handler(),
+ &field->field_name,
+ field->flags);
if (!regfield)
{
error= 1;
diff --git a/sql/unireg.h b/sql/unireg.h
index 88d0c882824..6f224ab4894 100644
--- a/sql/unireg.h
+++ b/sql/unireg.h
@@ -56,11 +56,6 @@
#endif
#define ER_THD_OR_DEFAULT(thd,X) ((thd) ? ER_THD(thd, (X)) : ER_DEFAULT(X))
-
-#define ME_INFO (ME_HOLDTANG | ME_NOREFRESH)
-#define ME_ERROR (ME_BELL | ME_NOREFRESH)
-#define MYF_RW MYF(MY_WME+MY_NABP) /* Vid my_read & my_write */
-
#define SPECIAL_USE_LOCKS 1 /* Lock used databases */
#define SPECIAL_NO_NEW_FUNC 2 /* Skip new functions */
#define SPECIAL_SKIP_SHOW_DB 4 /* Don't allow 'show db' */