summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorKristofer Pettersson <kristofer.pettersson@sun.com>2009-03-06 11:49:39 +0100
committerKristofer Pettersson <kristofer.pettersson@sun.com>2009-03-06 11:49:39 +0100
commit55c779cdbf0e402338bb32253a2fc1db7fa02129 (patch)
treea2136f93bb28c0e655cf133c9245ead5bf039ae9 /sql
parentac821c65701d38ced2d3167cf9c54559599d4f52 (diff)
parentb4fdb8aec14b533db4a5ea2f99c1a9f3ce07946c (diff)
downloadmariadb-git-55c779cdbf0e402338bb32253a2fc1db7fa02129.tar.gz
Manual merge
Diffstat (limited to 'sql')
-rw-r--r--sql/examples/ha_tina.cc101
-rw-r--r--sql/field.cc4
-rw-r--r--sql/ha_federated.cc8
-rw-r--r--sql/ha_innodb.cc25
-rw-r--r--sql/handler.cc49
-rw-r--r--sql/handler.h1
-rw-r--r--sql/item.cc132
-rw-r--r--sql/item.h5
-rw-r--r--sql/item_cmpfunc.cc30
-rw-r--r--sql/item_cmpfunc.h6
-rw-r--r--sql/item_func.cc28
-rw-r--r--sql/item_func.h6
-rw-r--r--sql/item_strfunc.cc6
-rw-r--r--sql/item_strfunc.h5
-rw-r--r--sql/item_sum.cc37
-rw-r--r--sql/item_sum.h25
-rw-r--r--sql/item_timefunc.cc54
-rw-r--r--sql/item_timefunc.h20
-rw-r--r--sql/log.cc213
-rw-r--r--sql/log_event.cc49
-rw-r--r--sql/log_event.h22
-rw-r--r--sql/my_decimal.cc2
-rw-r--r--sql/mysql_priv.h17
-rw-r--r--sql/mysqld.cc96
-rw-r--r--sql/nt_servc.cc12
-rw-r--r--sql/nt_servc.h14
-rw-r--r--sql/opt_range.cc62
-rw-r--r--sql/opt_sum.cc6
-rw-r--r--sql/parse_file.cc98
-rw-r--r--sql/parse_file.h6
-rw-r--r--sql/protocol.cc22
-rw-r--r--sql/set_var.cc74
-rw-r--r--sql/set_var.h47
-rw-r--r--sql/sql_acl.cc149
-rw-r--r--sql/sql_base.cc5
-rw-r--r--sql/sql_cache.cc24
-rw-r--r--sql/sql_class.cc15
-rw-r--r--sql/sql_class.h14
-rw-r--r--sql/sql_cursor.cc18
-rw-r--r--sql/sql_db.cc2
-rw-r--r--sql/sql_handler.cc15
-rw-r--r--sql/sql_locale.cc436
-rw-r--r--sql/sql_parse.cc53
-rw-r--r--sql/sql_select.cc184
-rw-r--r--sql/sql_select.h15
-rw-r--r--sql/sql_show.cc73
-rw-r--r--sql/sql_string.cc19
-rw-r--r--sql/sql_table.cc17
-rw-r--r--sql/sql_trigger.cc8
-rw-r--r--sql/sql_update.cc28
-rw-r--r--sql/sql_view.cc46
-rw-r--r--sql/sql_yacc.yy5
-rw-r--r--sql/structs.h2
-rw-r--r--sql/table.h1
-rw-r--r--sql/tztime.cc22
-rw-r--r--sql/tztime.h3
-rw-r--r--sql/unireg.cc30
57 files changed, 1718 insertions, 748 deletions
diff --git a/sql/examples/ha_tina.cc b/sql/examples/ha_tina.cc
index 0b57fe86e62..aaaa3b8ffb4 100644
--- a/sql/examples/ha_tina.cc
+++ b/sql/examples/ha_tina.cc
@@ -416,37 +416,96 @@ int ha_tina::find_current_row(byte *buf)
if ((end_ptr= find_eoln(share->mapped_file, current_position, share->file_stat.st_size)) == 0)
DBUG_RETURN(HA_ERR_END_OF_FILE);
+ /*
+ Parse the line obtained using the following algorithm
+
+ BEGIN
+ 1) Store the EOL (end of line) for the current row
+ 2) Until all the fields in the current query have not been
+ filled
+ 2.1) If the current character begins with a quote
+ 2.1.1) Until EOL has not been reached
+ a) If end of current field is reached, move
+ to next field and jump to step 2.3
+ b) If current character begins with \\ handle
+ \\n, \\r, \\, \\"
+ c) else append the current character into the buffer
+ before checking that EOL has not been reached.
+ 2.2) If the current character does not begin with a quote
+ 2.2.1) Until EOL has not been reached
+ a) If the end of field has been reached move to the
+ next field and jump to step 2.3
+ b) append the current character into the buffer
+ 2.3) Store the current field value and jump to 2)
+ TERMINATE
+ */
+
for (Field **field=table->field ; *field ; field++)
{
buffer.length(0);
- mapped_ptr++; // Increment past the first quote
- for(;mapped_ptr != end_ptr; mapped_ptr++)
+ /* Handle the case where the first character begins with a quote */
+ if (*mapped_ptr == '"')
{
- //Need to convert line feeds!
- if (*mapped_ptr == '"' &&
- (((mapped_ptr[1] == ',') && (mapped_ptr[2] == '"')) || (mapped_ptr == end_ptr -1 )))
+ /* Increment past the first quote */
+ mapped_ptr++;
+ /* Loop through the row to extract the values for the current field */
+ for(; mapped_ptr != end_ptr; mapped_ptr++)
{
- mapped_ptr += 2; // Move past the , and the "
- break;
- }
- if (*mapped_ptr == '\\' && mapped_ptr != (end_ptr - 1))
- {
- mapped_ptr++;
- if (*mapped_ptr == 'r')
- buffer.append('\r');
- else if (*mapped_ptr == 'n' )
- buffer.append('\n');
- else if ((*mapped_ptr == '\\') || (*mapped_ptr == '"'))
- buffer.append(*mapped_ptr);
- else /* This could only happed with an externally created file */
+ /* check for end of the current field */
+ if (*mapped_ptr == '"' &&
+ (mapped_ptr[1] == ',' || mapped_ptr == end_ptr -1 ))
{
- buffer.append('\\');
+ /* Move past the , and the " */
+ mapped_ptr += 2;
+ break;
+ }
+ if (*mapped_ptr == '\\' && mapped_ptr != (end_ptr - 1))
+ {
+ mapped_ptr++;
+ if (*mapped_ptr == 'r')
+ buffer.append('\r');
+ else if (*mapped_ptr == 'n' )
+ buffer.append('\n');
+ else if ((*mapped_ptr == '\\') || (*mapped_ptr == '"'))
+ buffer.append(*mapped_ptr);
+ else /* This could only happed with an externally created file */
+ {
+ buffer.append('\\');
+ buffer.append(*mapped_ptr);
+ }
+ }
+ else
+ {
+ /*
+ If no last quote was found, but the end of row has been reached
+ it implies that there has been error.
+ */
+ if (mapped_ptr == end_ptr -1)
+ DBUG_RETURN(HA_ERR_END_OF_FILE);
+ /* Store current character in the buffer for the field */
buffer.append(*mapped_ptr);
}
- }
- else
+ }
+ }
+ else
+ {
+ /* Handle the case where the current row does not start with quotes */
+
+ /* Loop through the row to extract the values for the current field */
+ for (; mapped_ptr != end_ptr; mapped_ptr++)
+ {
+ /* check for end of current field */
+ if (*mapped_ptr == ',')
+ {
+ /* Increment past the current comma */
+ mapped_ptr++;
+ break;
+ }
+ /* store the current character in the buffer for the field */
buffer.append(*mapped_ptr);
+ }
}
+ /* Store the field value from the buffer */
(*field)->store(buffer.ptr(), buffer.length(), buffer.charset());
}
next_position= (end_ptr - share->mapped_file)+1;
diff --git a/sql/field.cc b/sql/field.cc
index 3d3f698f912..f8ab4b852ec 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -3473,7 +3473,7 @@ int Field_longlong::store(double nr)
error= 1;
}
else
- res=(longlong) (ulonglong) nr;
+ res=(longlong) double2ulonglong(nr);
}
else
{
@@ -5372,6 +5372,7 @@ int Field_newdate::store_time(MYSQL_TIME *ltime, timestamp_type time_type)
{
char buff[MAX_DATE_STRING_REP_LENGTH];
String str(buff, sizeof(buff), &my_charset_latin1);
+ tmp= 0;
make_date((DATE_TIME_FORMAT *) 0, ltime, &str);
set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED,
str.ptr(), str.length(), MYSQL_TIMESTAMP_DATE, 1);
@@ -5608,6 +5609,7 @@ int Field_datetime::store_time(MYSQL_TIME *ltime,timestamp_type time_type)
{
char buff[MAX_DATE_STRING_REP_LENGTH];
String str(buff, sizeof(buff), &my_charset_latin1);
+ tmp= 0;
make_datetime((DATE_TIME_FORMAT *) 0, ltime, &str);
set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED,
str.ptr(), str.length(), MYSQL_TIMESTAMP_DATETIME,1);
diff --git a/sql/ha_federated.cc b/sql/ha_federated.cc
index b4788dd9c87..d4144a41a2a 100644
--- a/sql/ha_federated.cc
+++ b/sql/ha_federated.cc
@@ -1320,6 +1320,14 @@ static FEDERATED_SHARE *get_share(const char *table_name, TABLE *table)
thr_lock_init(&share->lock);
pthread_mutex_init(&share->mutex, MY_MUTEX_INIT_FAST);
}
+ else
+ {
+ /*
+ Free tmp_share.scheme allocated in the parse_url()
+ as we found share in the hash and tmp_share isn't needed anymore.
+ */
+ my_free((gptr) tmp_share.scheme, MYF(MY_ALLOW_ZERO_PTR));
+ }
share->use_count++;
pthread_mutex_unlock(&federated_mutex);
diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc
index 1c0f8a6e9b3..3bae0da3e02 100644
--- a/sql/ha_innodb.cc
+++ b/sql/ha_innodb.cc
@@ -524,6 +524,20 @@ convert_error_code_to_mysql(
mark_transaction_to_rollback(thd, TRUE);
return(HA_ERR_LOCK_TABLE_FULL);
+ } else if (error == DB_TOO_MANY_CONCURRENT_TRXS) {
+
+ /* Once MySQL add the appropriate code to errmsg.txt then
+ we can get rid of this #ifdef. NOTE: The code checked by
+ the #ifdef is the suggested name for the error condition
+ and the actual error code name could very well be different.
+ This will require some monitoring, ie. the status
+ of this request on our part.*/
+#ifdef ER_TOO_MANY_CONCURRENT_TRXS
+ return(ER_TOO_MANY_CONCURRENT_TRXS);
+#else
+ return(HA_ERR_RECORD_FILE_FULL);
+#endif
+
} else if (error == DB_UNSUPPORTED) {
return(HA_ERR_UNSUPPORTED);
@@ -2158,6 +2172,14 @@ ha_innobase::open(
UT_NOT_USED(test_if_locked);
thd = current_thd;
+
+ /* Under some cases MySQL seems to call this function while
+ holding btr_search_latch. This breaks the latching order as
+ we acquire dict_sys->mutex below and leads to a deadlock. */
+ if (thd != NULL) {
+ innobase_release_temporary_latches(thd);
+ }
+
normalize_table_name(norm_name, name);
user_thd = NULL;
@@ -3723,7 +3745,6 @@ convert_search_mode_to_innobase(
case HA_READ_MBR_WITHIN:
case HA_READ_MBR_DISJOINT:
case HA_READ_MBR_EQUAL:
- my_error(ER_TABLE_CANT_HANDLE_SPKEYS, MYF(0));
return(PAGE_CUR_UNSUPP);
/* do not use "default:" in order to produce a gcc warning:
enumeration value '...' not handled in switch
@@ -5204,7 +5225,7 @@ ha_innobase::records_in_range(
mode2);
} else {
- n_rows = 0;
+ n_rows = HA_POS_ERROR;
}
dtuple_free_for_mysql(heap1);
diff --git a/sql/handler.cc b/sql/handler.cc
index 67ec5f3e759..71d184ad84b 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -1957,8 +1957,53 @@ bool handler::get_error_message(int error, String* buf)
}
+/**
+ Check for incompatible collation changes.
+
+ @retval
+ HA_ADMIN_NEEDS_UPGRADE Table may have data requiring upgrade.
+ @retval
+ 0 No upgrade required.
+*/
+
+int handler::check_collation_compatibility()
+{
+ ulong mysql_version= table->s->mysql_version;
+
+ if (mysql_version < 50048)
+ {
+ KEY *key= table->key_info;
+ KEY *key_end= key + table->s->keys;
+ for (; key < key_end; key++)
+ {
+ KEY_PART_INFO *key_part= key->key_part;
+ KEY_PART_INFO *key_part_end= key_part + key->key_parts;
+ for (; key_part < key_part_end; key_part++)
+ {
+ if (!key_part->fieldnr)
+ continue;
+ Field *field= table->field[key_part->fieldnr - 1];
+ uint cs_number= field->charset()->number;
+ if (mysql_version < 50048 &&
+ (cs_number == 11 || /* ascii_general_ci - bug #29499, bug #27562 */
+ cs_number == 41 || /* latin7_general_ci - bug #29461 */
+ cs_number == 42 || /* latin7_general_cs - bug #29461 */
+ cs_number == 20 || /* latin7_estonian_cs - bug #29461 */
+ cs_number == 21 || /* latin2_hungarian_ci - bug #29461 */
+ cs_number == 22 || /* koi8u_general_ci - bug #29461 */
+ cs_number == 23 || /* cp1251_ukrainian_ci - bug #29461 */
+ cs_number == 26)) /* cp1250_general_ci - bug #29461 */
+ return HA_ADMIN_NEEDS_UPGRADE;
+ }
+ }
+ }
+ return 0;
+}
+
+
int handler::ha_check_for_upgrade(HA_CHECK_OPT *check_opt)
{
+ int error;
KEY *keyinfo, *keyend;
KEY_PART_INFO *keypart, *keypartend;
@@ -1987,6 +2032,10 @@ int handler::ha_check_for_upgrade(HA_CHECK_OPT *check_opt)
}
if (table->s->frm_version != FRM_VER_TRUE_VARCHAR)
return HA_ADMIN_NEEDS_ALTER;
+
+ if ((error= check_collation_compatibility()))
+ return error;
+
return check_for_upgrade(check_opt);
}
diff --git a/sql/handler.h b/sql/handler.h
index aa3377c3868..8706aae5fce 100644
--- a/sql/handler.h
+++ b/sql/handler.h
@@ -787,6 +787,7 @@ protected:
virtual int check_for_upgrade(HA_CHECK_OPT *check_opt)
{ return 0; }
public:
+ int check_collation_compatibility();
int ha_check_for_upgrade(HA_CHECK_OPT *check_opt);
int check_old_types();
/* to be actually called to get 'check()' functionality*/
diff --git a/sql/item.cc b/sql/item.cc
index 182f4abdfe6..f32828629cf 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -321,7 +321,7 @@ int Item::save_time_in_field(Field *field)
{
MYSQL_TIME ltime;
if (get_time(&ltime))
- return set_field_to_null(field);
+ return set_field_to_null_with_conversions(field, 0);
field->set_notnull();
return field->store_time(&ltime, MYSQL_TIMESTAMP_TIME);
}
@@ -331,7 +331,7 @@ int Item::save_date_in_field(Field *field)
{
MYSQL_TIME ltime;
if (get_date(&ltime, TIME_FUZZY_DATE))
- return set_field_to_null(field);
+ return set_field_to_null_with_conversions(field, 0);
field->set_notnull();
return field->store_time(&ltime, MYSQL_TIMESTAMP_DATETIME);
}
@@ -1243,13 +1243,26 @@ Item::Type Item_name_const::type() const
valid_args guarantees value_item->basic_const_item(); if type is
FUNC_ITEM, then we have a fudged item_func_neg() on our hands
and return the underlying type.
+ For Item_func_set_collation()
+ e.g. NAME_CONST('name', 'value' COLLATE collation) we return its
+ 'value' argument type.
*/
- return valid_args ?
- (((value_item->type() == FUNC_ITEM) &&
- (((Item_func *) value_item)->functype() == Item_func::NEG_FUNC)) ?
- ((Item_func *) value_item)->key_item()->type() :
- value_item->type()) :
- NULL_ITEM;
+ if (!valid_args)
+ return NULL_ITEM;
+ Item::Type value_type= value_item->type();
+ if (value_type == FUNC_ITEM)
+ {
+ /*
+ The second argument of NAME_CONST('name', 'value') must be
+ a simple constant item or a NEG_FUNC/COLLATE_FUNC.
+ */
+ DBUG_ASSERT(((Item_func *) value_item)->functype() ==
+ Item_func::NEG_FUNC ||
+ ((Item_func *) value_item)->functype() ==
+ Item_func::COLLATE_FUNC);
+ return ((Item_func *) value_item)->key_item()->type();
+ }
+ return value_type;
}
@@ -1595,42 +1608,11 @@ bool agg_item_collations_for_comparison(DTCollation &c, const char *fname,
}
-/*
- Collect arguments' character sets together.
- We allow to apply automatic character set conversion in some cases.
- The conditions when conversion is possible are:
- - arguments A and B have different charsets
- - A wins according to coercibility rules
- (i.e. a column is stronger than a string constant,
- an explicit COLLATE clause is stronger than a column)
- - character set of A is either superset for character set of B,
- or B is a string constant which can be converted into the
- character set of A without data loss.
-
- If all of the above is true, then it's possible to convert
- B into the character set of A, and then compare according
- to the collation of A.
-
- For functions with more than two arguments:
- collect(A,B,C) ::= collect(collect(A,B),C)
-
- Since this function calls THD::change_item_tree() on the passed Item **
- pointers, it is necessary to pass the original Item **'s, not copies.
- Otherwise their values will not be properly restored (see BUG#20769).
- If the items are not consecutive (eg. args[2] and args[5]), use the
- item_sep argument, ie.
-
- agg_item_charsets(coll, fname, &args[2], 2, flags, 3)
-
-*/
-
-bool agg_item_charsets(DTCollation &coll, const char *fname,
- Item **args, uint nargs, uint flags, int item_sep)
+bool agg_item_set_converter(DTCollation &coll, const char *fname,
+ Item **args, uint nargs, uint flags, int item_sep)
{
Item **arg, *safe_args[2];
- if (agg_item_collations(coll, fname, args, nargs, flags, item_sep))
- return TRUE;
/*
For better error reporting: save the first and the second argument.
@@ -1711,6 +1693,46 @@ bool agg_item_charsets(DTCollation &coll, const char *fname,
}
+/*
+ Collect arguments' character sets together.
+ We allow to apply automatic character set conversion in some cases.
+ The conditions when conversion is possible are:
+ - arguments A and B have different charsets
+ - A wins according to coercibility rules
+ (i.e. a column is stronger than a string constant,
+ an explicit COLLATE clause is stronger than a column)
+ - character set of A is either superset for character set of B,
+ or B is a string constant which can be converted into the
+ character set of A without data loss.
+
+ If all of the above is true, then it's possible to convert
+ B into the character set of A, and then compare according
+ to the collation of A.
+
+ For functions with more than two arguments:
+
+ collect(A,B,C) ::= collect(collect(A,B),C)
+
+ Since this function calls THD::change_item_tree() on the passed Item **
+ pointers, it is necessary to pass the original Item **'s, not copies.
+ Otherwise their values will not be properly restored (see BUG#20769).
+ If the items are not consecutive (eg. args[2] and args[5]), use the
+ item_sep argument, ie.
+
+ agg_item_charsets(coll, fname, &args[2], 2, flags, 3)
+
+*/
+
+bool agg_item_charsets(DTCollation &coll, const char *fname,
+ Item **args, uint nargs, uint flags, int item_sep)
+{
+ if (agg_item_collations(coll, fname, args, nargs, flags, item_sep))
+ return TRUE;
+
+ return agg_item_set_converter(coll, fname, args, nargs, flags, item_sep);
+}
+
+
void Item_ident_for_show::make_field(Send_field *tmp_field)
{
tmp_field->table_name= tmp_field->org_table_name= table_name;
@@ -2041,6 +2063,12 @@ bool Item_field::val_bool_result()
}
+bool Item_field::is_null_result()
+{
+ return (null_value=result_field->is_null());
+}
+
+
bool Item_field::eq(const Item *item, bool binary_cmp) const
{
Item *real_item= ((Item *) item)->real_item();
@@ -2991,7 +3019,7 @@ bool Item_param::convert_str_value(THD *thd)
str_value.set_charset(value.cs_info.final_character_set_of_str_value);
/* Here str_value is guaranteed to be in final_character_set_of_str_value */
- max_length= str_value.length();
+ max_length= str_value.numchars() * str_value.charset()->mbmaxlen;
decimals= 0;
/*
str_value_ptr is returned from val_str(). It must be not alloced
@@ -4950,6 +4978,9 @@ int Item_hex_string::save_in_field(Field *field, bool no_conversions)
ulonglong nr;
uint32 length= str_value.length();
+ if (!length)
+ return 1;
+
if (length > 8)
{
nr= field->flags & UNSIGNED_FLAG ? ULONGLONG_MAX : LONGLONG_MAX;
@@ -5626,6 +5657,15 @@ double Item_ref::val_result()
}
+bool Item_ref::is_null_result()
+{
+ if (result_field)
+ return (null_value=result_field->is_null());
+
+ return is_null();
+}
+
+
longlong Item_ref::val_int_result()
{
if (result_field)
@@ -5731,7 +5771,9 @@ String *Item_ref::val_str(String* tmp)
bool Item_ref::is_null()
{
DBUG_ASSERT(fixed);
- return (*ref)->is_null();
+ bool tmp=(*ref)->is_null_result();
+ null_value=(*ref)->null_value;
+ return tmp;
}
@@ -6792,7 +6834,7 @@ enum_field_types Item_type_holder::get_real_type(Item *item)
*/
Item_sum *item_sum= (Item_sum *) item;
if (item_sum->keep_field_type())
- return get_real_type(item_sum->args[0]);
+ return get_real_type(item_sum->get_arg(0));
break;
}
case FUNC_ITEM:
@@ -7056,7 +7098,7 @@ void Item_type_holder::get_full_info(Item *item)
if (item->type() == Item::SUM_FUNC_ITEM &&
(((Item_sum*)item)->sum_func() == Item_sum::MAX_FUNC ||
((Item_sum*)item)->sum_func() == Item_sum::MIN_FUNC))
- item = ((Item_sum*)item)->args[0];
+ item = ((Item_sum*)item)->get_arg(0);
/*
We can have enum/set type after merging only if we have one enum|set
field (or MIN|MAX(enum|set field)) and number of NULL fields
diff --git a/sql/item.h b/sql/item.h
index 250bb3f67ef..852b0fcc1ba 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -652,6 +652,7 @@ public:
virtual my_decimal *val_decimal_result(my_decimal *val)
{ return val_decimal(val); }
virtual bool val_bool_result() { return val_bool(); }
+ virtual bool is_null_result() { return is_null(); }
/* bit map of tables used by item */
virtual table_map used_tables() const { return (table_map) 0L; }
@@ -1168,6 +1169,8 @@ bool agg_item_collations(DTCollation &c, const char *name,
Item **items, uint nitems, uint flags, int item_sep);
bool agg_item_collations_for_comparison(DTCollation &c, const char *name,
Item **items, uint nitems, uint flags);
+bool agg_item_set_converter(DTCollation &coll, const char *fname,
+ Item **args, uint nargs, uint flags, int item_sep);
bool agg_item_charsets(DTCollation &c, const char *name,
Item **items, uint nitems, uint flags, int item_sep);
@@ -1301,6 +1304,7 @@ public:
String *str_result(String* tmp);
my_decimal *val_decimal_result(my_decimal *);
bool val_bool_result();
+ bool is_null_result();
bool send(Protocol *protocol, String *str_arg);
void reset_field(Field *f);
bool fix_fields(THD *, Item **);
@@ -1942,6 +1946,7 @@ public:
String *str_result(String* tmp);
my_decimal *val_decimal_result(my_decimal *);
bool val_bool_result();
+ bool is_null_result();
bool send(Protocol *prot, String *tmp);
void make_field(Send_field *field);
bool fix_fields(THD *, Item **);
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index 0410c781590..01d3e9bed52 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -490,7 +490,8 @@ int Arg_comparator::set_compare_func(Item_bool_func2 *item, Item_result type)
my_error(ER_OPERAND_COLUMNS, MYF(0), (*a)->element_index(i)->cols());
return 1;
}
- comparators[i].set_cmp_func(owner, (*a)->addr(i), (*b)->addr(i));
+ if (comparators[i].set_cmp_func(owner, (*a)->addr(i), (*b)->addr(i)))
+ return 1;
}
break;
}
@@ -745,11 +746,11 @@ Arg_comparator::can_compare_as_dates(Item *a, Item *b, ulonglong *const_value)
obtained value
*/
-ulonglong
+longlong
get_time_value(THD *thd, Item ***item_arg, Item **cache_arg,
Item *warn_item, bool *is_null)
{
- ulonglong value;
+ longlong value;
Item *item= **item_arg;
MYSQL_TIME ltime;
@@ -761,7 +762,7 @@ get_time_value(THD *thd, Item ***item_arg, Item **cache_arg,
else
{
*is_null= item->get_time(&ltime);
- value= !*is_null ? TIME_to_ulonglong_datetime(&ltime) : 0;
+ value= !*is_null ? (longlong) TIME_to_ulonglong_datetime(&ltime) : 0;
}
/*
Do not cache GET_USER_VAR() function as its const_item() may return TRUE
@@ -835,6 +836,16 @@ int Arg_comparator::set_cmp_func(Item_bool_func2 *owner_arg,
get_value_func= &get_time_value;
return 0;
}
+ else if (type == STRING_RESULT &&
+ (*a)->result_type() == STRING_RESULT &&
+ (*b)->result_type() == STRING_RESULT)
+ {
+ DTCollation coll;
+ coll.set((*a)->collation.collation);
+ if (agg_item_set_converter(coll, owner_arg->func_name(),
+ b, 1, MY_COLL_CMP_CONV, 1))
+ return 1;
+ }
return set_compare_func(owner_arg, type);
}
@@ -886,11 +897,11 @@ void Arg_comparator::set_datetime_cmp_func(Item **a1, Item **b1)
obtained value
*/
-ulonglong
+longlong
get_datetime_value(THD *thd, Item ***item_arg, Item **cache_arg,
Item *warn_item, bool *is_null)
{
- ulonglong value= 0;
+ longlong value= 0;
String buf, *str= 0;
Item *item= **item_arg;
@@ -925,7 +936,7 @@ get_datetime_value(THD *thd, Item ***item_arg, Item **cache_arg,
enum_field_types f_type= warn_item->field_type();
timestamp_type t_type= f_type ==
MYSQL_TYPE_DATE ? MYSQL_TIMESTAMP_DATE : MYSQL_TIMESTAMP_DATETIME;
- value= get_date_from_str(thd, str, t_type, warn_item->name, &error);
+ value= (longlong) get_date_from_str(thd, str, t_type, warn_item->name, &error);
/*
If str did not contain a valid date according to the current
SQL_MODE, get_date_from_str() has already thrown a warning,
@@ -979,7 +990,7 @@ get_datetime_value(THD *thd, Item ***item_arg, Item **cache_arg,
int Arg_comparator::compare_datetime()
{
bool a_is_null, b_is_null;
- ulonglong a_value, b_value;
+ longlong a_value, b_value;
/* Get DATE/DATETIME/TIME value of the 'a' item. */
a_value= (*get_value_func)(thd, &a, &a_cache, *b, &a_is_null);
@@ -1434,7 +1445,8 @@ bool Item_in_optimizer::fix_left(THD *thd, Item **ref)
}
not_null_tables_cache= args[0]->not_null_tables();
with_sum_func= args[0]->with_sum_func;
- const_item_cache= args[0]->const_item();
+ if ((const_item_cache= args[0]->const_item()))
+ cache->store(args[0]);
return 0;
}
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index 1bd60ff37d9..db831c7030c 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -42,8 +42,8 @@ class Arg_comparator: public Sql_alloc
bool is_nulls_eq; // TRUE <=> compare for the EQUAL_FUNC
enum enum_date_cmp_type { CMP_DATE_DFLT= 0, CMP_DATE_WITH_DATE,
CMP_DATE_WITH_STR, CMP_STR_WITH_DATE };
- ulonglong (*get_value_func)(THD *thd, Item ***item_arg, Item **cache_arg,
- Item *warn_item, bool *is_null);
+ longlong (*get_value_func)(THD *thd, Item ***item_arg, Item **cache_arg,
+ Item *warn_item, bool *is_null);
public:
DTCollation cmp_collation;
@@ -1028,7 +1028,7 @@ public:
*/
class cmp_item_datetime :public cmp_item
{
- ulonglong value;
+ longlong value;
public:
THD *thd;
/* Item used for issuing warnings. */
diff --git a/sql/item_func.cc b/sql/item_func.cc
index e663e1fcf83..55324923fe2 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -1316,8 +1316,10 @@ my_decimal *Item_func_div::decimal_op(my_decimal *decimal_value)
void Item_func_div::result_precision()
{
- uint arg_prec= args[0]->decimal_precision() + prec_increment;
- uint precision=min(arg_prec, DECIMAL_MAX_PRECISION);
+ uint precision=min(args[0]->decimal_precision() +
+ args[1]->decimals + prec_increment,
+ DECIMAL_MAX_PRECISION);
+
/* Integer operations keep unsigned_flag if one of arguments is unsigned */
if (result_type() == INT_RESULT)
unsigned_flag= args[0]->unsigned_flag | args[1]->unsigned_flag;
@@ -2273,7 +2275,7 @@ void Item_func_min_max::fix_length_and_dec()
uint Item_func_min_max::cmp_datetimes(ulonglong *value)
{
- ulonglong min_max;
+ longlong min_max;
uint min_max_idx= 0;
LINT_INIT(min_max);
@@ -2281,7 +2283,7 @@ uint Item_func_min_max::cmp_datetimes(ulonglong *value)
{
Item **arg= args + i;
bool is_null;
- ulonglong res= get_datetime_value(thd, &arg, 0, datetime_item, &is_null);
+ longlong res= get_datetime_value(thd, &arg, 0, datetime_item, &is_null);
if ((null_value= args[i]->null_value))
return 0;
if (i == 0 || (res < min_max ? cmp_sign : -cmp_sign) > 0)
@@ -4283,6 +4285,15 @@ my_decimal *Item_func_set_user_var::val_decimal_result(my_decimal *val)
}
+bool Item_func_set_user_var::is_null_result()
+{
+ DBUG_ASSERT(fixed == 1);
+ check(TRUE);
+ update(); // Store expression
+ return is_null();
+}
+
+
void Item_func_set_user_var::print(String *str)
{
str->append(STRING_WITH_LEN("(@"));
@@ -4950,7 +4961,10 @@ bool Item_func_match::fix_fields(THD *thd, Item **ref)
if (item->type() == Item::REF_ITEM)
args[i]= item= *((Item_ref *)item)->ref;
if (item->type() != Item::FIELD_ITEM)
- key=NO_SUCH_KEY;
+ {
+ my_error(ER_WRONG_ARGUMENTS, MYF(0), "AGAINST");
+ return TRUE;
+ }
}
/*
Check that all columns come from the same table.
@@ -5022,7 +5036,9 @@ bool Item_func_match::fix_index()
for (keynr=0 ; keynr < table->s->keys ; keynr++)
{
if ((table->key_info[keynr].flags & HA_FULLTEXT) &&
- (table->s->keys_in_use.is_set(keynr)))
+ (flags & FT_BOOL ? table->keys_in_use_for_query.is_set(keynr) :
+ table->s->keys_in_use.is_set(keynr)))
+
{
ft_to_key[fts]=keynr;
ft_cnt[fts]=0;
diff --git a/sql/item_func.h b/sql/item_func.h
index 6dcf32cba07..7e15a536cf2 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -351,7 +351,10 @@ public:
Item_func_unsigned(Item *a) :Item_func_signed(a) {}
const char *func_name() const { return "cast_as_unsigned"; }
void fix_length_and_dec()
- { max_length=args[0]->max_length; unsigned_flag=1; }
+ {
+ max_length= min(args[0]->max_length, DECIMAL_MAX_PRECISION + 2);
+ unsigned_flag=1;
+ }
longlong val_int();
void print(String *str);
};
@@ -1299,6 +1302,7 @@ public:
longlong val_int_result();
String *str_result(String *str);
my_decimal *val_decimal_result(my_decimal *);
+ bool is_null_result();
bool update_hash(void *ptr, uint length, enum Item_result type,
CHARSET_INFO *cs, Derivation dv, bool unsigned_arg);
bool send(Protocol *protocol, String *str_arg);
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index d1e3f45bba1..34f974042a5 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -1696,6 +1696,12 @@ Item *Item_func_sysconst::safe_charset_converter(CHARSET_INFO *tocs)
Item_string *conv;
uint conv_errors;
String tmp, cstr, *ostr= val_str(&tmp);
+ if (null_value)
+ {
+ Item *null_item= new Item_null((char *) fully_qualified_func_name());
+ null_item->collation.set (tocs);
+ return null_item;
+ }
cstr.copy(ostr->ptr(), ostr->length(), ostr->charset(), tocs, &conv_errors);
if (conv_errors ||
!(conv= new Item_static_string_func(fully_qualified_func_name(),
diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h
index 3648438a69b..23ac20a4017 100644
--- a/sql/item_strfunc.h
+++ b/sql/item_strfunc.h
@@ -516,8 +516,9 @@ public:
{
collation.set(default_charset());
uint char_length= args[0]->max_length/args[0]->collation.collation->mbmaxlen;
- max_length= ((char_length + (char_length-args[0]->decimals)/3) *
- collation.collation->mbmaxlen);
+ uint max_sep_count= char_length/3 + (decimals ? 1 : 0) + /*sign*/1;
+ max_length= (char_length + max_sep_count + decimals) *
+ collation.collation->mbmaxlen;
}
const char *func_name() const { return "format"; }
void print(String *);
diff --git a/sql/item_sum.cc b/sql/item_sum.cc
index 91320d6b56b..d33d92a5238 100644
--- a/sql/item_sum.cc
+++ b/sql/item_sum.cc
@@ -370,6 +370,10 @@ Item_sum::Item_sum(List<Item> &list) :arg_count(list.elements),
args[i++]= item;
}
}
+ if (!(orig_args= (Item **) sql_alloc(sizeof(Item *) * arg_count)))
+ {
+ args= NULL;
+ }
mark_as_sum_func();
list.empty(); // Fields are used
}
@@ -380,18 +384,28 @@ Item_sum::Item_sum(List<Item> &list) :arg_count(list.elements),
*/
Item_sum::Item_sum(THD *thd, Item_sum *item):
- Item_result_field(thd, item), arg_count(item->arg_count),
+ Item_result_field(thd, item),
aggr_sel(item->aggr_sel),
nest_level(item->nest_level), aggr_level(item->aggr_level),
- quick_group(item->quick_group), used_tables_cache(item->used_tables_cache),
+ quick_group(item->quick_group),
+ arg_count(item->arg_count), orig_args(NULL),
+ used_tables_cache(item->used_tables_cache),
forced_const(item->forced_const)
{
if (arg_count <= 2)
+ {
args=tmp_args;
+ orig_args=tmp_orig_args;
+ }
else
+ {
if (!(args= (Item**) thd->alloc(sizeof(Item*)*arg_count)))
return;
+ if (!(orig_args= (Item**) thd->alloc(sizeof(Item*)*arg_count)))
+ return;
+ }
memcpy(args, item->args, sizeof(Item*)*arg_count);
+ memcpy(orig_args, item->orig_args, sizeof(Item*)*arg_count);
}
@@ -426,12 +440,13 @@ void Item_sum::make_field(Send_field *tmp_field)
void Item_sum::print(String *str)
{
+ Item **pargs= orig_args;
str->append(func_name());
for (uint i=0 ; i < arg_count ; i++)
{
if (i)
str->append(',');
- args[i]->print(str);
+ pargs[i]->print(str);
}
str->append(')');
}
@@ -532,6 +547,13 @@ void Item_sum::update_used_tables ()
}
+Item *Item_sum::set_arg(int i, THD *thd, Item *new_val)
+{
+ thd->change_item_tree(args + i, new_val);
+ return new_val;
+}
+
+
String *
Item_sum_num::val_str(String *str)
{
@@ -583,6 +605,7 @@ Item_sum_num::fix_fields(THD *thd, Item **ref)
if (check_sum_func(thd, ref))
return TRUE;
+ memcpy (orig_args, args, sizeof (Item *) * arg_count);
fixed= 1;
return FALSE;
}
@@ -670,6 +693,7 @@ Item_sum_hybrid::fix_fields(THD *thd, Item **ref)
if (check_sum_func(thd, ref))
return TRUE;
+ orig_args[0]= args[0];
fixed= 1;
return FALSE;
}
@@ -3107,6 +3131,12 @@ Item_func_group_concat(Name_resolution_context *context_arg,
sizeof(ORDER*)*arg_count_order)))
return;
+ if (!(orig_args= (Item **) sql_alloc(sizeof(Item *) * arg_count)))
+ {
+ args= NULL;
+ return;
+ }
+
order= (ORDER**)(args + arg_count);
/* fill args items of show and sort */
@@ -3334,6 +3364,7 @@ Item_func_group_concat::fix_fields(THD *thd, Item **ref)
if (check_sum_func(thd, ref))
return TRUE;
+ memcpy (orig_args, args, sizeof (Item *) * arg_count);
fixed= 1;
return FALSE;
}
diff --git a/sql/item_sum.h b/sql/item_sum.h
index d39fc96e254..51a1eff9bbf 100644
--- a/sql/item_sum.h
+++ b/sql/item_sum.h
@@ -228,10 +228,8 @@ public:
VARIANCE_FUNC, SUM_BIT_FUNC, UDF_SUM_FUNC, GROUP_CONCAT_FUNC
};
- Item **args, *tmp_args[2];
Item **ref_by; /* pointer to a ref to the object used to register it */
Item_sum *next; /* next in the circular chain of registered objects */
- uint arg_count;
Item_sum *in_sum_func; /* embedding set function if any */
st_select_lex * aggr_sel; /* select where the function is aggregated */
int8 nest_level; /* number of the nesting level of the set function */
@@ -248,24 +246,32 @@ public:
List<Item_field> outer_fields;
protected:
+ uint arg_count;
+ Item **args, *tmp_args[2];
+ /*
+ Copy of the arguments list to hold the original set of arguments.
+ Used in EXPLAIN EXTENDED instead of the current argument list because
+ the current argument list can be altered by usage of temporary tables.
+ */
+ Item **orig_args, *tmp_orig_args[2];
table_map used_tables_cache;
bool forced_const;
public:
void mark_as_sum_func();
- Item_sum() :arg_count(0), quick_group(1), forced_const(FALSE)
+ Item_sum() :quick_group(1), arg_count(0), forced_const(FALSE)
{
mark_as_sum_func();
}
- Item_sum(Item *a) :args(tmp_args), arg_count(1), quick_group(1),
- forced_const(FALSE)
+ Item_sum(Item *a) :quick_group(1), arg_count(1), args(tmp_args),
+ orig_args(tmp_orig_args), forced_const(FALSE)
{
args[0]=a;
mark_as_sum_func();
}
- Item_sum( Item *a, Item *b ) :args(tmp_args), arg_count(2), quick_group(1),
- forced_const(FALSE)
+ Item_sum( Item *a, Item *b ) :quick_group(1), arg_count(2), args(tmp_args),
+ orig_args(tmp_orig_args), forced_const(FALSE)
{
args[0]=a; args[1]=b;
mark_as_sum_func();
@@ -374,6 +380,10 @@ public:
bool register_sum_func(THD *thd, Item **ref);
st_select_lex *depended_from()
{ return (nest_level == aggr_level ? 0 : aggr_sel); }
+
+ Item *get_arg(int i) { return args[i]; }
+ Item *set_arg(int i, THD *thd, Item *new_val);
+ uint get_arg_count() { return arg_count; }
};
@@ -981,6 +991,7 @@ public:
if (udf.fix_fields(thd, this, this->arg_count, this->args))
return TRUE;
+ memcpy (orig_args, args, sizeof (Item *) * arg_count);
return check_sum_func(thd, ref);
}
enum Sumfunctype sum_func () const { return UDF_SUM_FUNC; }
diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc
index 0cb3c963dad..38d9d62bd99 100644
--- a/sql/item_timefunc.cc
+++ b/sql/item_timefunc.cc
@@ -1036,12 +1036,25 @@ longlong Item_func_month::val_int()
}
+void Item_func_monthname::fix_length_and_dec()
+{
+ THD* thd= current_thd;
+ CHARSET_INFO *cs= thd->variables.collation_connection;
+ uint32 repertoire= my_charset_repertoire(cs);
+ locale= thd->variables.lc_time_names;
+ collation.set(cs, DERIVATION_COERCIBLE, repertoire);
+ decimals=0;
+ max_length= locale->max_month_name_length * collation.collation->mbmaxlen;
+ maybe_null=1;
+}
+
+
String* Item_func_monthname::val_str(String* str)
{
DBUG_ASSERT(fixed == 1);
const char *month_name;
- uint month= (uint) val_int();
- THD *thd= current_thd;
+ uint month= (uint) val_int();
+ uint err;
if (null_value || !month)
{
@@ -1049,8 +1062,9 @@ String* Item_func_monthname::val_str(String* str)
return (String*) 0;
}
null_value=0;
- month_name= thd->variables.lc_time_names->month_names->type_names[month-1];
- str->set(month_name, strlen(month_name), system_charset_info);
+ month_name= locale->month_names->type_names[month-1];
+ str->copy(month_name, strlen(month_name), &my_charset_utf8_bin,
+ collation.collation, &err);
return str;
}
@@ -1169,19 +1183,32 @@ longlong Item_func_weekday::val_int()
odbc_type) + test(odbc_type);
}
+void Item_func_dayname::fix_length_and_dec()
+{
+ THD* thd= current_thd;
+ CHARSET_INFO *cs= thd->variables.collation_connection;
+ uint32 repertoire= my_charset_repertoire(cs);
+ locale= thd->variables.lc_time_names;
+ collation.set(cs, DERIVATION_COERCIBLE, repertoire);
+ decimals=0;
+ max_length= locale->max_day_name_length * collation.collation->mbmaxlen;
+ maybe_null=1;
+}
+
String* Item_func_dayname::val_str(String* str)
{
DBUG_ASSERT(fixed == 1);
uint weekday=(uint) val_int(); // Always Item_func_daynr()
const char *day_name;
- THD *thd= current_thd;
+ uint err;
if (null_value)
return (String*) 0;
- day_name= thd->variables.lc_time_names->day_names->type_names[weekday];
- str->set(day_name, strlen(day_name), system_charset_info);
+ day_name= locale->day_names->type_names[weekday];
+ str->copy(day_name, strlen(day_name), &my_charset_utf8_bin,
+ collation.collation, &err);
return str;
}
@@ -2550,6 +2577,8 @@ void Item_char_typecast::fix_length_and_dec()
and thus avoid unnecessary character set conversion.
- If the argument is not a number, then from_cs is set to
the argument's charset.
+
+ Note (TODO): we could use repertoire technique here.
*/
from_cs= (args[0]->result_type() == INT_RESULT ||
args[0]->result_type() == DECIMAL_RESULT ||
@@ -2557,12 +2586,13 @@ void Item_char_typecast::fix_length_and_dec()
(cast_cs->mbminlen == 1 ? cast_cs : &my_charset_latin1) :
args[0]->collation.collation;
charset_conversion= (cast_cs->mbmaxlen > 1) ||
- !my_charset_same(from_cs, cast_cs) &&
- from_cs != &my_charset_bin &&
- cast_cs != &my_charset_bin;
+ (!my_charset_same(from_cs, cast_cs) &&
+ from_cs != &my_charset_bin &&
+ cast_cs != &my_charset_bin);
collation.set(cast_cs, DERIVATION_IMPLICIT);
- char_length= (cast_length >= 0) ? cast_length :
- args[0]->max_length/from_cs->mbmaxlen;
+ char_length= (cast_length >= 0) ?
+ cast_length :
+ args[0]->max_length / args[0]->collation.collation->mbmaxlen;
max_length= char_length * cast_cs->mbmaxlen;
}
diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h
index 7960c03d2e5..2c99d6044af 100644
--- a/sql/item_timefunc.h
+++ b/sql/item_timefunc.h
@@ -108,18 +108,13 @@ public:
class Item_func_monthname :public Item_func_month
{
+ MY_LOCALE *locale;
public:
Item_func_monthname(Item *a) :Item_func_month(a) {}
const char *func_name() const { return "monthname"; }
String *val_str(String *str);
enum Item_result result_type () const { return STRING_RESULT; }
- void fix_length_and_dec()
- {
- collation.set(&my_charset_bin);
- decimals=0;
- max_length=10*my_charset_bin.mbmaxlen;
- maybe_null=1;
- }
+ void fix_length_and_dec();
};
@@ -272,18 +267,13 @@ public:
class Item_func_dayname :public Item_func_weekday
{
+ MY_LOCALE *locale;
public:
Item_func_dayname(Item *a) :Item_func_weekday(a,0) {}
const char *func_name() const { return "dayname"; }
String *val_str(String *str);
enum Item_result result_type () const { return STRING_RESULT; }
- void fix_length_and_dec()
- {
- collation.set(&my_charset_bin);
- decimals=0;
- max_length=9*MY_CHARSET_BIN_MB_MAXLEN;
- maybe_null=1;
- }
+ void fix_length_and_dec();
};
@@ -408,6 +398,8 @@ public:
{
return save_time_in_field(field);
}
+ longlong val_int() { return val_int_from_decimal(); }
+ bool result_as_longlong() { return TRUE; }
};
diff --git a/sql/log.cc b/sql/log.cc
index 5a1cfe46686..c411f7c8238 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -417,6 +417,7 @@ MYSQL_LOG::MYSQL_LOG()
index_file_name[0] = 0;
bzero((char*) &log_file,sizeof(log_file));
bzero((char*) &index_file, sizeof(index_file));
+ bzero((char*) &purge_temp, sizeof(purge_temp));
}
/* this is called only once */
@@ -1059,10 +1060,10 @@ err:
IMPLEMENTATION
- Protects index file with LOCK_index
+ - Read the next file name from the index file and store in rli->linfo
- Delete relevant relay log files
- Copy all file names after these ones to the front of the index file
- If the OS has truncate, truncate the file, else fill it with \n'
- - Read the next file name from the index file and store in rli->linfo
RETURN VALUES
0 ok
@@ -1076,6 +1077,7 @@ err:
int MYSQL_LOG::purge_first_log(struct st_relay_log_info* rli, bool included)
{
int error;
+ char *to_purge_if_included= NULL;
DBUG_ENTER("purge_first_log");
DBUG_ASSERT(is_open());
@@ -1083,36 +1085,20 @@ int MYSQL_LOG::purge_first_log(struct st_relay_log_info* rli, bool included)
DBUG_ASSERT(!strcmp(rli->linfo.log_file_name,rli->event_relay_log_name));
pthread_mutex_lock(&LOCK_index);
- pthread_mutex_lock(&rli->log_space_lock);
- rli->relay_log.purge_logs(rli->group_relay_log_name, included,
- 0, 0, &rli->log_space_total);
- // Tell the I/O thread to take the relay_log_space_limit into account
- rli->ignore_log_space_limit= 0;
- pthread_mutex_unlock(&rli->log_space_lock);
+ to_purge_if_included= my_strdup(rli->group_relay_log_name, MYF(0));
/*
- Ok to broadcast after the critical region as there is no risk of
- the mutex being destroyed by this thread later - this helps save
- context switches
- */
- pthread_cond_broadcast(&rli->log_space_cond);
-
- /*
Read the next log file name from the index file and pass it back to
- the caller
- If included is true, we want the first relay log;
- otherwise we want the one after event_relay_log_name.
+ the caller.
*/
- if ((included && (error=find_log_pos(&rli->linfo, NullS, 0))) ||
- (!included &&
- ((error=find_log_pos(&rli->linfo, rli->event_relay_log_name, 0)) ||
- (error=find_next_log(&rli->linfo, 0)))))
+ if((error=find_log_pos(&rli->linfo, rli->event_relay_log_name, 0)) ||
+ (error=find_next_log(&rli->linfo, 0)))
{
char buff[22];
sql_print_error("next log error: %d offset: %s log: %s included: %d",
error,
llstr(rli->linfo.index_file_offset,buff),
- rli->group_relay_log_name,
+ rli->event_relay_log_name,
included);
goto err;
}
@@ -1140,7 +1126,42 @@ int MYSQL_LOG::purge_first_log(struct st_relay_log_info* rli, bool included)
/* Store where we are in the new file for the execution thread */
flush_relay_log_info(rli);
+ DBUG_EXECUTE_IF("crash_before_purge_logs", abort(););
+
+ pthread_mutex_lock(&rli->log_space_lock);
+ rli->relay_log.purge_logs(to_purge_if_included, included,
+ 0, 0, &rli->log_space_total);
+ // Tell the I/O thread to take the relay_log_space_limit into account
+ rli->ignore_log_space_limit= 0;
+ pthread_mutex_unlock(&rli->log_space_lock);
+
+ /*
+ Ok to broadcast after the critical region as there is no risk of
+ the mutex being destroyed by this thread later - this helps save
+ context switches
+ */
+ pthread_cond_broadcast(&rli->log_space_cond);
+
+ /*
+ * Need to update the log pos because purge logs has been called
+ * after fetching initially the log pos at the begining of the method.
+ */
+ if((error=find_log_pos(&rli->linfo, rli->event_relay_log_name, 0)))
+ {
+ char buff[22];
+ sql_print_error("next log error: %d offset: %s log: %s included: %d",
+ error,
+ llstr(rli->linfo.index_file_offset,buff),
+ rli->group_relay_log_name,
+ included);
+ goto err;
+ }
+
+ /* If included was passed, rli->linfo should be the first entry. */
+ DBUG_ASSERT(!included || rli->linfo.index_file_start_offset == 0);
+
err:
+ my_free(to_purge_if_included, MYF(0));
pthread_mutex_unlock(&LOCK_index);
DBUG_RETURN(error);
}
@@ -1199,8 +1220,36 @@ int MYSQL_LOG::purge_logs(const char *to_log,
if (need_mutex)
pthread_mutex_lock(&LOCK_index);
- if ((error=find_log_pos(&log_info, to_log, 0 /*no mutex*/)))
+ if ((error=find_log_pos(&log_info, to_log, 0 /*no mutex*/)))
+ {
+ sql_print_error("MYSQL_LOG::purge_logs was called with file %s not "
+ "listed in the index.", to_log);
goto err;
+ }
+
+ /*
+ For crash recovery reasons the index needs to be updated before
+ any files are deleted. Move files to be deleted into a temp file
+ to be processed after the index is updated.
+ */
+ if (!my_b_inited(&purge_temp))
+ {
+ if ((error=open_cached_file(&purge_temp, mysql_tmpdir, TEMP_PREFIX,
+ DISK_BUFFER_SIZE, MYF(MY_WME))))
+ {
+ sql_print_error("MYSQL_LOG::purge_logs failed to open purge_temp");
+ goto err;
+ }
+ }
+ else
+ {
+ if ((error=reinit_io_cache(&purge_temp, WRITE_CACHE, 0, 0, 1)))
+ {
+ sql_print_error("MYSQL_LOG::purge_logs failed to reinit purge_temp "
+ "for write");
+ goto err;
+ }
+ }
/*
File name exists in index file; delete until we find this file
@@ -1211,6 +1260,59 @@ int MYSQL_LOG::purge_logs(const char *to_log,
while ((strcmp(to_log,log_info.log_file_name) || (exit_loop=included)) &&
!log_in_use(log_info.log_file_name))
{
+ if ((error=my_b_write(&purge_temp, (byte*)log_info.log_file_name,
+ strlen(log_info.log_file_name))) ||
+ (error=my_b_write(&purge_temp, (byte*)"\n", 1)))
+ {
+ sql_print_error("MYSQL_LOG::purge_logs failed to copy %s to purge_temp",
+ log_info.log_file_name);
+ goto err;
+ }
+
+ if (find_next_log(&log_info, 0) || exit_loop)
+ break;
+ }
+
+ /* We know how many files to delete. Update index file. */
+ if ((error=update_log_index(&log_info, need_update_threads)))
+ {
+ sql_print_error("MSYQL_LOG::purge_logs failed to update the index file");
+ goto err;
+ }
+
+ DBUG_EXECUTE_IF("crash_after_update_index", abort(););
+
+ /* Switch purge_temp for read. */
+ if ((error=reinit_io_cache(&purge_temp, READ_CACHE, 0, 0, 0)))
+ {
+ sql_print_error("MSYQL_LOG::purge_logs failed to reinit purge_temp "
+ "for read");
+ goto err;
+ }
+
+ /* Read each entry from purge_temp and delete the file. */
+ for (;;)
+ {
+ uint length;
+
+ if ((length=my_b_gets(&purge_temp, log_info.log_file_name,
+ FN_REFLEN)) <= 1)
+ {
+ if (purge_temp.error)
+ {
+ error= purge_temp.error;
+ sql_print_error("MSYQL_LOG::purge_logs error %d reading from "
+ "purge_temp", error);
+ goto err;
+ }
+
+ /* Reached EOF */
+ break;
+ }
+
+ /* Get rid of the trailing '\n' */
+ log_info.log_file_name[length-1]= 0;
+
MY_STAT s;
if (!my_stat(log_info.log_file_name, &s, MYF(0)))
{
@@ -1304,17 +1406,10 @@ int MYSQL_LOG::purge_logs(const char *to_log,
}
}
}
- if (find_next_log(&log_info, 0) || exit_loop)
- break;
}
-
- /*
- If we get killed -9 here, the sysadmin would have to edit
- the log index file after restart - otherwise, this should be safe
- */
- error= update_log_index(&log_info, need_update_threads);
err:
+ close_cached_file(&purge_temp);
if (need_mutex)
pthread_mutex_unlock(&LOCK_index);
DBUG_RETURN(error);
@@ -1326,7 +1421,6 @@ err:
SYNOPSIS
purge_logs_before_date()
- thd Thread pointer
before_date Delete all log files before given date.
NOTES
@@ -1343,6 +1437,7 @@ err:
int MYSQL_LOG::purge_logs_before_date(time_t purge_time)
{
int error;
+ char to_log[FN_REFLEN];
LOG_INFO log_info;
MY_STAT stat_area;
THD *thd= current_thd;
@@ -1350,12 +1445,8 @@ int MYSQL_LOG::purge_logs_before_date(time_t purge_time)
DBUG_ENTER("purge_logs_before_date");
pthread_mutex_lock(&LOCK_index);
+ to_log[0]= 0;
- /*
- Delete until we find curren file
- or a file that is used or a file
- that is older than purge_time.
- */
if ((error=find_log_pos(&log_info, NullS, 0 /*no mutex*/)))
goto err;
@@ -1405,54 +1496,18 @@ int MYSQL_LOG::purge_logs_before_date(time_t purge_time)
}
else
{
- if (stat_area.st_mtime >= purge_time)
+ if (stat_area.st_mtime < purge_time)
+ strmake(to_log,
+ log_info.log_file_name,
+ sizeof(log_info.log_file_name));
+ else
break;
- if (my_delete(log_info.log_file_name, MYF(0)))
- {
- if (my_errno == ENOENT)
- {
- /* It's not fatal even if we can't delete a log file */
- if (thd)
- {
- push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
- ER_LOG_PURGE_NO_FILE, ER(ER_LOG_PURGE_NO_FILE),
- log_info.log_file_name);
- }
- sql_print_information("Failed to delete file '%s'",
- log_info.log_file_name);
- my_errno= 0;
- }
- else
- {
- if (thd)
- {
- push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
- ER_BINLOG_PURGE_FATAL_ERR,
- "a problem with deleting %s; "
- "consider examining correspondence "
- "of your binlog index file "
- "to the actual binlog files",
- log_info.log_file_name);
- }
- else
- {
- sql_print_information("Failed to delete log file '%s'",
- log_info.log_file_name);
- }
- error= LOG_INFO_FATAL;
- goto err;
- }
- }
}
if (find_next_log(&log_info, 0))
break;
}
- /*
- If we get killed -9 here, the sysadmin would have to edit
- the log index file after restart - otherwise, this should be safe
- */
- error= update_log_index(&log_info, 1);
+ error= (to_log[0] ? purge_logs(to_log, 1, 0, 1, (ulonglong *) 0) : 0);
err:
pthread_mutex_unlock(&LOCK_index);
diff --git a/sql/log_event.cc b/sql/log_event.cc
index ef419aaee40..ba282fd8e59 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -976,7 +976,7 @@ void Log_event::print_header(FILE* file, PRINT_EVENT_INFO* print_event_info)
fputc('#', file);
print_timestamp(file);
- fprintf(file, " server id %d end_log_pos %s ", server_id,
+ fprintf(file, " server id %lu end_log_pos %s ", (ulong) server_id,
llstr(log_pos,llbuff));
/* mysqlbinlog --hexdump */
@@ -1117,6 +1117,11 @@ void Query_log_event::pack_info(Protocol *protocol)
static void write_str_with_code_and_len(char **dst, const char *src,
int len, uint code)
{
+ /*
+ only 1 byte to store the length of catalog, so it should not
+ surpass 255
+ */
+ DBUG_ASSERT(len <= 255);
DBUG_ASSERT(src);
*((*dst)++)= code;
*((*dst)++)= (uchar) len;
@@ -1136,16 +1141,8 @@ static void write_str_with_code_and_len(char **dst, const char *src,
bool Query_log_event::write(IO_CACHE* file)
{
- uchar buf[QUERY_HEADER_LEN+
- 1+4+ // code of flags2 and flags2
- 1+8+ // code of sql_mode and sql_mode
- 1+1+FN_REFLEN+ // code of catalog and catalog length and catalog
- 1+4+ // code of autoinc and the 2 autoinc variables
- 1+6+ // code of charset and charset
- 1+1+MAX_TIME_ZONE_NAME_LENGTH+ // code of tz and tz length and tz name
- 1+2+ // code of lc_time_names and lc_time_names_number
- 1+2 // code of charset_database and charset_database_number
- ], *start, *start_of_status;
+ uchar buf[QUERY_HEADER_LEN + MAX_SIZE_LOG_EVENT_STATUS];
+ uchar *start, *start_of_status;
ulong event_length;
if (!query)
@@ -1251,10 +1248,8 @@ bool Query_log_event::write(IO_CACHE* file)
{
/* In the TZ sys table, column Name is of length 64 so this should be ok */
DBUG_ASSERT(time_zone_len <= MAX_TIME_ZONE_NAME_LENGTH);
- *start++= Q_TIME_ZONE_CODE;
- *start++= time_zone_len;
- memcpy(start, time_zone_str, time_zone_len);
- start+= time_zone_len;
+ write_str_with_code_and_len((char **)(&start),
+ time_zone_str, time_zone_len, Q_TIME_ZONE_CODE);
}
if (lc_time_names_number)
{
@@ -1270,7 +1265,17 @@ bool Query_log_event::write(IO_CACHE* file)
int2store(start, charset_database_number);
start+= 2;
}
+ if (table_map_for_update)
+ {
+ *start++= Q_TABLE_MAP_FOR_UPDATE_CODE;
+ int8store(start, table_map_for_update);
+ start+= 8;
+ }
/*
+ NOTE: When adding new status vars, please don't forget to update
+ the MAX_SIZE_LOG_EVENT_STATUS in log_event.h and update function
+ code_name in this file.
+
Here there could be code like
if (command-line-option-which-says-"log_this_variable" && inited)
{
@@ -1348,7 +1353,8 @@ Query_log_event::Query_log_event(THD* thd_arg, const char* query_arg,
auto_increment_increment(thd_arg->variables.auto_increment_increment),
auto_increment_offset(thd_arg->variables.auto_increment_offset),
lc_time_names_number(thd_arg->variables.lc_time_names->number),
- charset_database_number(0)
+ charset_database_number(0),
+ table_map_for_update((ulonglong)thd_arg->table_map_for_update)
{
time_t end_time;
@@ -1471,6 +1477,7 @@ code_name(int code)
case Q_CATALOG_NZ_CODE: return "Q_CATALOG_NZ_CODE";
case Q_LC_TIME_NAMES_CODE: return "Q_LC_TIME_NAMES_CODE";
case Q_CHARSET_DATABASE_CODE: return "Q_CHARSET_DATABASE_CODE";
+ case Q_TABLE_MAP_FOR_UPDATE_CODE: return "Q_TABLE_MAP_FOR_UPDATE_CODE";
}
sprintf(buf, "CODE#%d", code);
return buf;
@@ -1507,7 +1514,8 @@ Query_log_event::Query_log_event(const char* buf, uint event_len,
db(NullS), catalog_len(0), status_vars_len(0),
flags2_inited(0), sql_mode_inited(0), charset_inited(0),
auto_increment_increment(1), auto_increment_offset(1),
- time_zone_len(0), lc_time_names_number(0), charset_database_number(0)
+ time_zone_len(0), lc_time_names_number(0), charset_database_number(0),
+ table_map_for_update(0)
{
ulong data_len;
uint32 tmp;
@@ -1649,6 +1657,11 @@ Query_log_event::Query_log_event(const char* buf, uint event_len,
charset_database_number= uint2korr(pos);
pos+= 2;
break;
+ case Q_TABLE_MAP_FOR_UPDATE_CODE:
+ CHECK_SPACE(pos, end, 8);
+ table_map_for_update= uint8korr(pos);
+ pos+= 8;
+ break;
default:
/* That's why you must write status vars in growing order of code */
DBUG_PRINT("info",("Query_log_event has unknown status vars (first has\
@@ -2036,6 +2049,8 @@ int Query_log_event::exec_event(struct st_relay_log_info* rli,
else
thd->variables.collation_database= thd->db_charset;
+ thd->table_map_for_update= (table_map)table_map_for_update;
+
/* Execute the query (note that we bypass dispatch_command()) */
const char* found_semicolon= NULL;
mysql_parse(thd, thd->query, thd->query_length, &found_semicolon);
diff --git a/sql/log_event.h b/sql/log_event.h
index 5b065a33dd1..6ccbf8e4d5c 100644
--- a/sql/log_event.h
+++ b/sql/log_event.h
@@ -204,12 +204,15 @@ struct sql_ex_info
packet (i.e. a query) sent from client to master;
First, an auxiliary log_event status vars estimation:
*/
-#define MAX_SIZE_LOG_EVENT_STATUS (4 /* flags2 */ + \
- 8 /* sql mode */ + \
- 1 + 1 + 255 /* catalog */ + \
- 4 /* autoinc */ + \
- 6 /* charset */ + \
- MAX_TIME_ZONE_NAME_LENGTH)
+#define MAX_SIZE_LOG_EVENT_STATUS (1 + 4 /* type, flags2 */ + \
+ 1 + 8 /* type, sql_mode */ + \
+ 1 + 1 + 255 /* type, length, catalog */ + \
+ 1 + 4 /* type, auto_increment */ + \
+ 1 + 6 /* type, charset */ + \
+ 1 + 1 + 255 /* type, length, time_zone */ + \
+ 1 + 2 /* type, lc_time_names_number */ + \
+ 1 + 2 /* type, charset_database_number */ + \
+ 1 + 8 /* type, table_map_for_update */)
#define MAX_LOG_EVENT_HEADER ( /* in order of Query_log_event::write */ \
LOG_EVENT_HEADER_LEN + /* write_header */ \
QUERY_HEADER_LEN + /* write_data */ \
@@ -273,6 +276,8 @@ struct sql_ex_info
#define Q_LC_TIME_NAMES_CODE 7
#define Q_CHARSET_DATABASE_CODE 8
+
+#define Q_TABLE_MAP_FOR_UPDATE_CODE 9
/* Intvar event post-header */
#define I_TYPE_OFFSET 0
@@ -800,6 +805,11 @@ public:
const char *time_zone_str;
uint lc_time_names_number; /* 0 means en_US */
uint charset_database_number;
+ /*
+ map for tables that will be updated for a multi-table update query
+ statement, for other query statements, this will be zero.
+ */
+ ulonglong table_map_for_update;
#ifndef MYSQL_CLIENT
diff --git a/sql/my_decimal.cc b/sql/my_decimal.cc
index 31a5b09370a..a235edbd73c 100644
--- a/sql/my_decimal.cc
+++ b/sql/my_decimal.cc
@@ -216,7 +216,7 @@ my_decimal *date2my_decimal(MYSQL_TIME *ltime, my_decimal *dec)
date = (ltime->year*100L + ltime->month)*100L + ltime->day;
if (ltime->time_type > MYSQL_TIMESTAMP_DATE)
date= ((date*100L + ltime->hour)*100L+ ltime->minute)*100L + ltime->second;
- if (int2my_decimal(E_DEC_FATAL_ERROR, date, FALSE, dec))
+ if (int2my_decimal(E_DEC_FATAL_ERROR, ltime->neg ? -date : date, FALSE, dec))
return dec;
if (ltime->second_part)
{
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index 1568f042b7e..b855af9a8d3 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -132,15 +132,20 @@ typedef struct my_locale_st
TYPELIB *ab_month_names;
TYPELIB *day_names;
TYPELIB *ab_day_names;
+ uint max_month_name_length;
+ uint max_day_name_length;
#ifdef __cplusplus
my_locale_st(uint number_par,
const char *name_par, const char *descr_par, bool is_ascii_par,
TYPELIB *month_names_par, TYPELIB *ab_month_names_par,
- TYPELIB *day_names_par, TYPELIB *ab_day_names_par) :
+ TYPELIB *day_names_par, TYPELIB *ab_day_names_par,
+ uint max_month_name_length_par, uint max_day_name_length_par) :
number(number_par),
name(name_par), description(descr_par), is_ascii(is_ascii_par),
month_names(month_names_par), ab_month_names(ab_month_names_par),
- day_names(day_names_par), ab_day_names(ab_day_names_par)
+ day_names(day_names_par), ab_day_names(ab_day_names_par),
+ max_month_name_length(max_month_name_length_par),
+ max_day_name_length(max_day_name_length_par)
{}
#endif
} MY_LOCALE;
@@ -435,6 +440,7 @@ MY_LOCALE *my_locale_by_number(uint number);
#define UNCACHEABLE_PREPARE 16
/* For uncorrelated SELECT in an UNION with some correlated SELECTs */
#define UNCACHEABLE_UNITED 32
+#define UNCACHEABLE_CHECKOPTION 64
/* Used to check GROUP BY list in the MODE_ONLY_FULL_GROUP_BY mode */
#define UNDEF_POS (-1)
@@ -645,6 +651,8 @@ struct Query_cache_query_flags
unsigned int client_long_flag:1;
unsigned int client_protocol_41:1;
unsigned int more_results_exists:1;
+ unsigned int in_trans:1;
+ unsigned int autocommit:1;
unsigned int pkt_nr;
uint character_set_client_num;
uint character_set_results_num;
@@ -977,6 +985,7 @@ int fill_schema_column_privileges(THD *thd, TABLE_LIST *tables, COND *cond);
bool get_schema_tables_result(JOIN *join,
enum enum_schema_table_state executed_place);
enum enum_schema_tables get_schema_table_idx(ST_SCHEMA_TABLE *schema_table);
+bool schema_table_store_record(THD *thd, TABLE *table);
#define is_schema_db(X) \
!my_strcasecmp(system_charset_info, INFORMATION_SCHEMA_NAME.str, (X))
@@ -1556,8 +1565,8 @@ void make_date(const DATE_TIME_FORMAT *format, const MYSQL_TIME *l_time,
String *str);
void make_time(const DATE_TIME_FORMAT *format, const MYSQL_TIME *l_time,
String *str);
-ulonglong get_datetime_value(THD *thd, Item ***item_arg, Item **cache_arg,
- Item *warn_item, bool *is_null);
+longlong get_datetime_value(THD *thd, Item ***item_arg, Item **cache_arg,
+ Item *warn_item, bool *is_null);
int test_if_number(char *str,int *res,bool allow_wildcards);
void change_byte(byte *,uint,char,char);
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index c3e5449b22b..fcde4e2b626 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -186,39 +186,41 @@ int initgroups(const char *,unsigned int);
#ifdef HAVE_FP_EXCEPT // Fix type conflict
typedef fp_except fp_except_t;
#endif
+#endif /* __FreeBSD__ && HAVE_IEEEFP_H */
+#ifdef HAVE_SYS_FPU_H
+/* for IRIX to use set_fpc_csr() */
+#include <sys/fpu.h>
+#endif
+inline void setup_fpu()
+{
+#if defined(__FreeBSD__) && defined(HAVE_IEEEFP_H)
/* We can't handle floating point exceptions with threads, so disable
this on freebsd
+ Don't fall for overflow, underflow,divide-by-zero or loss of precision
*/
-
-inline void set_proper_floating_point_mode()
-{
- /* Don't fall for overflow, underflow,divide-by-zero or loss of precision */
#if defined(__i386__)
fpsetmask(~(FP_X_INV | FP_X_DNML | FP_X_OFL | FP_X_UFL | FP_X_DZ |
FP_X_IMP));
#else
- fpsetmask(~(FP_X_INV | FP_X_OFL | FP_X_UFL | FP_X_DZ |
- FP_X_IMP));
-#endif
-}
-#elif defined(__sgi)
-/* for IRIX to use set_fpc_csr() */
-#include <sys/fpu.h>
+ fpsetmask(~(FP_X_INV | FP_X_OFL | FP_X_UFL | FP_X_DZ |
+ FP_X_IMP));
+#endif /* __i386__ */
+#endif /* __FreeBSD__ && HAVE_IEEEFP_H */
-inline void set_proper_floating_point_mode()
-{
+#ifdef HAVE_FESETROUND
+ /* Set FPU rounding mode to "round-to-nearest" */
+ fesetround(FE_TONEAREST);
+#endif /* HAVE_FESETROUND */
+
+#if defined(__sgi) && defined(HAVE_SYS_FPU_H)
/* Enable denormalized DOUBLE values support for IRIX */
- {
- union fpc_csr n;
- n.fc_word = get_fpc_csr();
- n.fc_struct.flush = 0;
- set_fpc_csr(n.fc_word);
- }
+ union fpc_csr n;
+ n.fc_word = get_fpc_csr();
+ n.fc_struct.flush = 0;
+ set_fpc_csr(n.fc_word);
+#endif
}
-#else
-#define set_proper_floating_point_mode()
-#endif /* __FreeBSD__ && HAVE_IEEEFP_H */
} /* cplusplus */
@@ -3035,12 +3037,14 @@ static int init_common_variables(const char *conf_file_name, int argc,
sys_init_connect.value_length= strlen(opt_init_connect);
else
sys_init_connect.value=my_strdup("",MYF(0));
+ sys_init_connect.is_os_charset= TRUE;
sys_init_slave.value_length= 0;
if ((sys_init_slave.value= opt_init_slave))
sys_init_slave.value_length= strlen(opt_init_slave);
else
sys_init_slave.value=my_strdup("",MYF(0));
+ sys_init_slave.is_os_charset= TRUE;
if (use_temp_pool && bitmap_init(&temp_pool,0,1024,1))
return 1;
@@ -3277,7 +3281,7 @@ static int init_server_components()
query_cache_init();
query_cache_resize(query_cache_size);
randominit(&sql_rand,(ulong) server_start_time,(ulong) server_start_time/2);
- set_proper_floating_point_mode();
+ setup_fpu();
init_thr_lock();
#ifdef HAVE_REPLICATION
init_slave_list();
@@ -3615,6 +3619,44 @@ void decrement_handler_count()
#ifndef EMBEDDED_LIBRARY
+#ifndef DBUG_OFF
+/*
+ Debugging helper function to keep the locale database
+ (see sql_locale.cc) and max_month_name_length and
+ max_day_name_length variable values in consistent state.
+*/
+static void test_lc_time_sz()
+{
+ DBUG_ENTER("test_lc_time_sz");
+ for (MY_LOCALE **loc= my_locales; *loc; loc++)
+ {
+ uint max_month_len= 0;
+ uint max_day_len = 0;
+ for (const char **month= (*loc)->month_names->type_names; *month; month++)
+ {
+ set_if_bigger(max_month_len,
+ my_numchars_mb(&my_charset_utf8_general_ci,
+ *month, *month + strlen(*month)));
+ }
+ for (const char **day= (*loc)->day_names->type_names; *day; day++)
+ {
+ set_if_bigger(max_day_len,
+ my_numchars_mb(&my_charset_utf8_general_ci,
+ *day, *day + strlen(*day)));
+ }
+ if ((*loc)->max_month_name_length != max_month_len ||
+ (*loc)->max_day_name_length != max_day_len)
+ {
+ DBUG_PRINT("Wrong max day name(or month name) length for locale:",
+ ("%s", (*loc)->name));
+ DBUG_ASSERT(0);
+ }
+ }
+ DBUG_VOID_RETURN;
+}
+#endif//DBUG_OFF
+
+
#ifdef __WIN__
int win_main(int argc, char **argv)
#else
@@ -3710,6 +3752,10 @@ int main(int argc, char **argv)
openlog(libwrapName, LOG_PID, LOG_AUTH);
#endif
+#ifndef DBUG_OFF
+ test_lc_time_sz();
+#endif
+
/*
We have enough space for fiddling with the argv, continue
*/
@@ -3840,6 +3886,9 @@ we force server id to 2, but this MySQL server will not act as a slave.");
: mysqld_unix_port),
mysqld_port,
MYSQL_COMPILATION_COMMENT);
+#if defined(_WIN32) && !defined(EMBEDDED_LIBRARY)
+ Service.SetRunning();
+#endif
#if defined(__NT__) || defined(HAVE_SMEM)
handle_connections_methods();
@@ -6573,6 +6622,7 @@ struct show_var_st status_vars[]= {
{"Qcache_queries_in_cache", (char*) &query_cache.queries_in_cache, SHOW_LONG_CONST},
{"Qcache_total_blocks", (char*) &query_cache.total_blocks, SHOW_LONG_CONST},
#endif /*HAVE_QUERY_CACHE*/
+ {"Queries", (char*) 0, SHOW_QUERIES},
{"Questions", (char*) offsetof(STATUS_VAR, questions),
SHOW_LONG_STATUS},
diff --git a/sql/nt_servc.cc b/sql/nt_servc.cc
index a04f284a3de..e570898f373 100644
--- a/sql/nt_servc.cc
+++ b/sql/nt_servc.cc
@@ -245,10 +245,6 @@ void NTService::ServiceMain(DWORD argc, LPTSTR *argv)
if (!pService->StartService())
goto error;
- // Check that the service is now running.
- if (!pService->SetStatus(SERVICE_RUNNING,NO_ERROR, 0, 0, 0))
- goto error;
-
// wait for exit event
WaitForSingleObject (pService->hExitEvent, INFINITE);
@@ -264,6 +260,14 @@ error:
return;
}
+
+void NTService::SetRunning()
+{
+ if (pService)
+ pService->SetStatus(SERVICE_RUNNING,NO_ERROR, 0, 0, 0);
+}
+
+
/* ------------------------------------------------------------------------
StartService() - starts the appliaction thread
-------------------------------------------------------------------------- */
diff --git a/sql/nt_servc.h b/sql/nt_servc.h
index a3c12569114..9b689e434e1 100644
--- a/sql/nt_servc.h
+++ b/sql/nt_servc.h
@@ -56,7 +56,19 @@ class NTService
BOOL IsService(LPCSTR ServiceName);
BOOL got_service_option(char **argv, char *service_option);
BOOL is_super_user();
- void Stop(void); //to be called from app. to stop service
+
+ /*
+ SetRunning() is to be called by the application
+ when initialization completes and it can accept
+ stop request
+ */
+ void SetRunning(void);
+
+ /*
+ Stop() is to be called by the application to stop
+ the service
+ */
+ void Stop(void);
protected:
LPSTR ServiceName;
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index 204ebdb6f33..018fc8a9d44 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -1109,6 +1109,9 @@ QUICK_INDEX_MERGE_SELECT::~QUICK_INDEX_MERGE_SELECT()
quick->file= NULL;
quick_selects.delete_elements();
delete pk_quick_select;
+ /* It's ok to call the next two even if they are already deinitialized */
+ end_read_record(&read_record);
+ free_io_cache(head);
free_root(&alloc,MYF(0));
DBUG_VOID_RETURN;
}
@@ -7735,7 +7738,7 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree)
DBUG_RETURN(NULL);
/* The argument of MIN/MAX. */
- Item *expr= min_max_item->args[0]->real_item();
+ Item *expr= min_max_item->get_arg(0)->real_item();
if (expr->type() == Item::FIELD_ITEM) /* Is it an attribute? */
{
if (! min_max_arg_item)
@@ -7772,32 +7775,37 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree)
*/
KEY *cur_index_info= table->key_info;
KEY *cur_index_info_end= cur_index_info + table->s->keys;
- KEY_PART_INFO *cur_part= NULL;
- KEY_PART_INFO *end_part; /* Last part for loops. */
- /* Last index part. */
- KEY_PART_INFO *last_part= NULL;
- KEY_PART_INFO *first_non_group_part= NULL;
- KEY_PART_INFO *first_non_infix_part= NULL;
- uint key_infix_parts= 0;
- uint cur_group_key_parts= 0;
- uint cur_group_prefix_len= 0;
/* Cost-related variables for the best index so far. */
double best_read_cost= DBL_MAX;
ha_rows best_records= 0;
SEL_ARG *best_index_tree= NULL;
ha_rows best_quick_prefix_records= 0;
uint best_param_idx= 0;
- double cur_read_cost= DBL_MAX;
- ha_rows cur_records;
+
+ const uint pk= param->table->s->primary_key;
SEL_ARG *cur_index_tree= NULL;
ha_rows cur_quick_prefix_records= 0;
uint cur_param_idx=MAX_KEY;
- key_map cur_used_key_parts;
- uint pk= param->table->s->primary_key;
for (uint cur_index= 0 ; cur_index_info != cur_index_info_end ;
cur_index_info++, cur_index++)
{
+ KEY_PART_INFO *cur_part;
+ KEY_PART_INFO *end_part; /* Last part for loops. */
+ /* Last index part. */
+ KEY_PART_INFO *last_part;
+ KEY_PART_INFO *first_non_group_part;
+ KEY_PART_INFO *first_non_infix_part;
+ uint key_infix_parts;
+ uint cur_group_key_parts= 0;
+ uint cur_group_prefix_len= 0;
+ double cur_read_cost;
+ ha_rows cur_records;
+ key_map used_key_parts_map;
+ uint cur_key_infix_len= 0;
+ byte cur_key_infix[MAX_KEY_LENGTH];
+ uint cur_used_key_parts;
+
/* Check (B1) - if current index is covering. */
if (!table->used_keys.is_set(cur_index))
goto next_index;
@@ -7876,7 +7884,7 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree)
else if (join->select_distinct)
{
select_items_it.rewind();
- cur_used_key_parts.clear_all();
+ used_key_parts_map.clear_all();
uint max_key_part= 0;
while ((item= select_items_it++))
{
@@ -7887,13 +7895,13 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree)
Check if this attribute was already present in the select list.
If it was present, then its corresponding key part was alredy used.
*/
- if (cur_used_key_parts.is_set(key_part_nr))
+ if (used_key_parts_map.is_set(key_part_nr))
continue;
if (key_part_nr < 1 || key_part_nr > join->fields_list.elements)
goto next_index;
cur_part= cur_index_info->key_part + key_part_nr - 1;
cur_group_prefix_len+= cur_part->store_length;
- cur_used_key_parts.set_bit(key_part_nr);
+ used_key_parts_map.set_bit(key_part_nr);
++cur_group_key_parts;
max_key_part= max(max_key_part,key_part_nr);
}
@@ -7905,7 +7913,7 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree)
*/
ulonglong all_parts, cur_parts;
all_parts= (1<<max_key_part) - 1;
- cur_parts= cur_used_key_parts.to_ulonglong() >> 1;
+ cur_parts= used_key_parts_map.to_ulonglong() >> 1;
if (all_parts != cur_parts)
goto next_index;
}
@@ -7955,7 +7963,8 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree)
&dummy);
if (!get_constant_key_infix(cur_index_info, index_range_tree,
first_non_group_part, min_max_arg_part,
- last_part, thd, key_infix, &key_infix_len,
+ last_part, thd, cur_key_infix,
+ &cur_key_infix_len,
&first_non_infix_part))
goto next_index;
}
@@ -8007,9 +8016,9 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree)
}
/* If we got to this point, cur_index_info passes the test. */
- key_infix_parts= key_infix_len ?
+ key_infix_parts= cur_key_infix_len ?
(first_non_infix_part - first_non_group_part) : 0;
- used_key_parts= cur_group_key_parts + key_infix_parts;
+ cur_used_key_parts= cur_group_key_parts + key_infix_parts;
/* Compute the cost of using this index. */
if (tree)
@@ -8021,7 +8030,7 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree)
cur_quick_prefix_records= check_quick_select(param, cur_param_idx,
cur_index_tree);
}
- cost_group_min_max(table, cur_index_info, used_key_parts,
+ cost_group_min_max(table, cur_index_info, cur_used_key_parts,
cur_group_key_parts, tree, cur_index_tree,
cur_quick_prefix_records, have_min, have_max,
&cur_read_cost, &cur_records);
@@ -8032,7 +8041,6 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree)
*/
if (cur_read_cost < best_read_cost - (DBL_EPSILON * cur_read_cost))
{
- DBUG_ASSERT(tree != 0 || cur_param_idx == MAX_KEY);
index_info= cur_index_info;
index= cur_index;
best_read_cost= cur_read_cost;
@@ -8042,11 +8050,13 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree)
best_param_idx= cur_param_idx;
group_key_parts= cur_group_key_parts;
group_prefix_len= cur_group_prefix_len;
+ key_infix_len= cur_key_infix_len;
+ if (key_infix_len)
+ memcpy (key_infix, cur_key_infix, sizeof (key_infix));
+ used_key_parts= cur_used_key_parts;
}
- next_index:
- cur_group_key_parts= 0;
- cur_group_prefix_len= 0;
+ next_index:;
}
if (!index_info) /* No usable index found. */
DBUG_RETURN(NULL);
diff --git a/sql/opt_sum.cc b/sql/opt_sum.cc
index 3fc62d05ae5..39db1344588 100644
--- a/sql/opt_sum.cc
+++ b/sql/opt_sum.cc
@@ -160,7 +160,7 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds)
to the number of rows in the tables if this number is exact and
there are no outer joins.
*/
- if (!conds && !((Item_sum_count*) item)->args[0]->maybe_null &&
+ if (!conds && !((Item_sum_count*) item)->get_arg(0)->maybe_null &&
!outer_tables && is_exact_count)
{
((Item_sum_count*) item)->make_const(count);
@@ -176,7 +176,7 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds)
parts of the key is found in the COND, then we can use
indexes to find the key.
*/
- Item *expr=item_sum->args[0];
+ Item *expr=item_sum->get_arg(0);
if (expr->real_item()->type() == Item::FIELD_ITEM)
{
byte key_buff[MAX_KEY_LENGTH];
@@ -319,7 +319,7 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds)
parts of the key is found in the COND, then we can use
indexes to find the key.
*/
- Item *expr=item_sum->args[0];
+ Item *expr=item_sum->get_arg(0);
if (expr->real_item()->type() == Item::FIELD_ITEM)
{
byte key_buff[MAX_KEY_LENGTH];
diff --git a/sql/parse_file.cc b/sql/parse_file.cc
index 2b947fcac4f..c4b07ed9dac 100644
--- a/sql/parse_file.cc
+++ b/sql/parse_file.cc
@@ -88,7 +88,6 @@ write_escaped_string(IO_CACHE *file, LEX_STRING *val_s)
file pointer to IO_CACHE structure for writing
base pointer to data structure
parameter pointer to parameter descriptor
- old_version for returning back old version number value
RETURN
FALSE - OK
@@ -96,8 +95,7 @@ write_escaped_string(IO_CACHE *file, LEX_STRING *val_s)
*/
static my_bool
-write_parameter(IO_CACHE *file, gptr base, File_option *parameter,
- ulonglong *old_version)
+write_parameter(IO_CACHE *file, gptr base, File_option *parameter)
{
char num_buf[20]; // buffer for numeric operations
// string for numeric operations
@@ -125,15 +123,6 @@ write_parameter(IO_CACHE *file, gptr base, File_option *parameter,
DBUG_RETURN(TRUE);
break;
}
- case FILE_OPTIONS_REV:
- {
- ulonglong *val_i= (ulonglong *)(base + parameter->offset);
- *old_version= (*val_i)++;
- num.set(*val_i, &my_charset_bin);
- if (my_b_append(file, (const byte *)num.ptr(), num.length()))
- DBUG_RETURN(TRUE);
- break;
- }
case FILE_OPTIONS_TIMESTAMP:
{
/* string have to be allocated already */
@@ -205,7 +194,6 @@ write_parameter(IO_CACHE *file, gptr base, File_option *parameter,
base base address for parameter reading (structure like
TABLE)
parameters parameters description
- max_versions number of versions to save
RETURN
FALSE - OK
@@ -215,13 +203,11 @@ write_parameter(IO_CACHE *file, gptr base, File_option *parameter,
my_bool
sql_create_definition_file(const LEX_STRING *dir, const LEX_STRING *file_name,
const LEX_STRING *type,
- gptr base, File_option *parameters,
- uint max_versions)
+ gptr base, File_option *parameters)
{
File handler;
IO_CACHE file;
char path[FN_REFLEN+1]; // +1 to put temporary file name for sure
- ulonglong old_version= ULONGLONG_MAX;
int path_end;
File_option *param;
DBUG_ENTER("sql_create_definition_file");
@@ -255,7 +241,7 @@ sql_create_definition_file(const LEX_STRING *dir, const LEX_STRING *file_name,
if (my_b_append(&file, (const byte *)param->name.str,
param->name.length) ||
my_b_append(&file, (const byte *)STRING_WITH_LEN("=")) ||
- write_parameter(&file, base, param, &old_version) ||
+ write_parameter(&file, base, param) ||
my_b_append(&file, (const byte *)STRING_WITH_LEN("\n")))
goto err_w_cache;
}
@@ -263,61 +249,17 @@ sql_create_definition_file(const LEX_STRING *dir, const LEX_STRING *file_name,
if (end_io_cache(&file))
goto err_w_file;
+ if (opt_sync_frm) {
+ if (my_sync(handler, MYF(MY_WME)))
+ goto err_w_file;
+ }
+
if (my_close(handler, MYF(MY_WME)))
{
DBUG_RETURN(TRUE);
}
path[path_end]='\0';
-#ifdef FRM_ARCHIVE
- // archive copies management: disabled unused feature (see bug #17823).
- if (!access(path, F_OK))
- {
- if (old_version != ULONGLONG_MAX && max_versions != 0)
- {
- // save backup
- char path_arc[FN_REFLEN];
- // backup old version
- char path_to[FN_REFLEN];
-
- // check archive directory existence
- fn_format(path_arc, "arc", dir->str, "", MY_UNPACK_FILENAME);
- if (access(path_arc, F_OK))
- {
- if (my_mkdir(path_arc, 0777, MYF(MY_WME)))
- {
- DBUG_RETURN(TRUE);
- }
- }
-
- my_snprintf(path_to, FN_REFLEN, "%s/%s-%04lu",
- path_arc, file_name->str, (ulong) old_version);
- if (my_rename(path, path_to, MYF(MY_WME)))
- {
- DBUG_RETURN(TRUE);
- }
-
- // remove very old version
- if (old_version > max_versions)
- {
- my_snprintf(path_to, FN_REFLEN, "%s/%s-%04lu",
- path_arc, file_name->str,
- (ulong)(old_version - max_versions));
- if (!access(path_arc, F_OK) && my_delete(path_to, MYF(MY_WME)))
- {
- DBUG_RETURN(TRUE);
- }
- }
- }
- else
- {
- if (my_delete(path, MYF(MY_WME))) // no backups
- {
- DBUG_RETURN(TRUE);
- }
- }
- }
-#endif//FRM_ARCHIVE
{
// rename temporary file
@@ -346,8 +288,6 @@ err_w_file:
schema name of given schema
old_name original file name
new_name new file name
- revision revision number
- num_view_backups number of backups
RETURN
0 - OK
@@ -356,8 +296,7 @@ err_w_file:
*/
my_bool rename_in_schema_file(THD *thd,
const char *schema, const char *old_name,
- const char *new_name, ulonglong revision,
- uint num_view_backups)
+ const char *new_name)
{
char old_path[FN_REFLEN], new_path[FN_REFLEN], arc_path[FN_REFLEN];
@@ -376,23 +315,6 @@ my_bool rename_in_schema_file(THD *thd,
strxnmov(arc_path, FN_REFLEN, mysql_data_home, "/", schema, "/arc", NullS);
(void) unpack_filename(arc_path, arc_path);
-#ifdef FRM_ARCHIVE
- if (revision > 0 && !access(arc_path, F_OK))
- {
- ulonglong limit= ((revision > num_view_backups) ?
- revision - num_view_backups : 0);
- for (; revision > limit ; revision--)
- {
- my_snprintf(old_path, FN_REFLEN, "%s/%s%s-%04lu",
- arc_path, old_name, reg_ext, (ulong)revision);
- (void) unpack_filename(old_path, old_path);
- my_snprintf(new_path, FN_REFLEN, "%s/%s%s-%04lu",
- arc_path, new_name, reg_ext, (ulong)revision);
- (void) unpack_filename(new_path, new_path);
- my_rename(old_path, new_path, MYF(0));
- }
- }
-#else//FRM_ARCHIVE
{ // remove obsolete 'arc' directory and files if any
MY_DIR *new_dirp;
if ((new_dirp = my_dir(arc_path, MYF(MY_DONT_SORT))))
@@ -401,7 +323,6 @@ my_bool rename_in_schema_file(THD *thd,
(void) mysql_rm_arc_files(thd, new_dirp, arc_path);
}
}
-#endif//FRM_ARCHIVE
return 0;
}
@@ -838,7 +759,6 @@ File_parser::parse(gptr base, MEM_ROOT *mem_root,
break;
}
case FILE_OPTIONS_ULONGLONG:
- case FILE_OPTIONS_REV:
if (!(eol= strchr(ptr, '\n')))
{
my_error(ER_FPARSER_ERROR_IN_PARAMETER, MYF(0),
diff --git a/sql/parse_file.h b/sql/parse_file.h
index ec920b58667..ad7d1629e0a 100644
--- a/sql/parse_file.h
+++ b/sql/parse_file.h
@@ -23,7 +23,6 @@ enum file_opt_type {
FILE_OPTIONS_STRING, /* String (LEX_STRING) */
FILE_OPTIONS_ESTRING, /* Escaped string (LEX_STRING) */
FILE_OPTIONS_ULONGLONG, /* ulonglong parameter (ulonglong) */
- FILE_OPTIONS_REV, /* Revision version number (ulonglong) */
FILE_OPTIONS_TIMESTAMP, /* timestamp (LEX_STRING have to be
allocated with length 20 (19+1) */
FILE_OPTIONS_STRLIST, /* list of escaped strings
@@ -81,11 +80,10 @@ File_parser *sql_parse_prepare(const LEX_STRING *file_name,
my_bool
sql_create_definition_file(const LEX_STRING *dir, const LEX_STRING *file_name,
const LEX_STRING *type,
- gptr base, File_option *parameters, uint versions);
+ gptr base, File_option *parameters);
my_bool rename_in_schema_file(THD *thd,
const char *schema, const char *old_name,
- const char *new_name, ulonglong revision,
- uint num_view_backups);
+ const char *new_name);
class File_parser: public Sql_alloc
{
diff --git a/sql/protocol.cc b/sql/protocol.cc
index ff58d96f59b..2309bac88a9 100644
--- a/sql/protocol.cc
+++ b/sql/protocol.cc
@@ -616,7 +616,8 @@ bool Protocol::send_fields(List<Item> *list, uint flags)
else
{
/* With conversion */
- uint max_char_len;
+ ulonglong max_length;
+ uint32 field_length;
int2store(pos, thd_charset->number);
/*
For TEXT/BLOB columns, field_length describes the maximum data
@@ -627,12 +628,21 @@ bool Protocol::send_fields(List<Item> *list, uint flags)
char_count * mbmaxlen, where character count is taken from the
definition of the column. In other words, the maximum number
of characters here is limited by the column definition.
+
+ When one has a LONG TEXT column with a single-byte
+ character set, and the connection character set is multi-byte, the
+ client may get fields longer than UINT_MAX32, due to
+ <character set column> -> <character set connection> conversion.
+ In that case column max length does not fit into the 4 bytes
+ reserved for it in the protocol.
*/
- max_char_len= (field.type >= (int) MYSQL_TYPE_TINY_BLOB &&
- field.type <= (int) MYSQL_TYPE_BLOB) ?
- field.length / item->collation.collation->mbminlen :
- field.length / item->collation.collation->mbmaxlen;
- int4store(pos+2, max_char_len * thd_charset->mbmaxlen);
+ max_length= (field.type >= MYSQL_TYPE_TINY_BLOB &&
+ field.type <= MYSQL_TYPE_BLOB) ?
+ field.length / item->collation.collation->mbminlen :
+ field.length / item->collation.collation->mbmaxlen;
+ max_length*= thd_charset->mbmaxlen;
+ field_length= (max_length > UINT_MAX32) ? UINT_MAX32 : max_length;
+ int4store(pos + 2, field_length);
}
pos[6]= field.type;
int2store(pos+7,field.flags);
diff --git a/sql/set_var.cc b/sql/set_var.cc
index 6bc19f2e6eb..a29abe6581f 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -138,7 +138,7 @@ sys_var_thd_ulong sys_auto_increment_offset("auto_increment_offset",
sys_var_bool_ptr sys_automatic_sp_privileges("automatic_sp_privileges",
&sp_automatic_privileges);
-sys_var_const_str sys_basedir("basedir", mysql_home);
+sys_var_const_os_str sys_basedir("basedir", mysql_home);
sys_var_long_ptr sys_binlog_cache_size("binlog_cache_size",
&binlog_cache_size);
sys_var_thd_ulong sys_bulk_insert_buff_size("bulk_insert_buffer_size",
@@ -151,6 +151,8 @@ sys_var_character_set_client sys_character_set_client("character_set_client");
sys_var_character_set_connection sys_character_set_connection("character_set_connection");
sys_var_character_set_results sys_character_set_results("character_set_results");
sys_var_character_set_filesystem sys_character_set_filesystem("character_set_filesystem");
+sys_var_const_os_str sys_character_sets_dir("character_sets_dir",
+ mysql_charsets_dir);
sys_var_thd_ulong sys_completion_type("completion_type",
&SV::completion_type,
check_completion_type,
@@ -162,7 +164,7 @@ sys_var_long_ptr sys_concurrent_insert("concurrent_insert",
&myisam_concurrent_insert);
sys_var_long_ptr sys_connect_timeout("connect_timeout",
&connect_timeout);
-sys_var_const_str sys_datadir("datadir", mysql_real_data_home);
+sys_var_const_os_str sys_datadir("datadir", mysql_real_data_home);
sys_var_enum sys_delay_key_write("delay_key_write",
&delay_key_write_options,
&delay_key_write_typelib,
@@ -311,6 +313,7 @@ sys_var_thd_ulong sys_optimizer_prune_level("optimizer_prune_level",
&SV::optimizer_prune_level);
sys_var_thd_ulong sys_optimizer_search_depth("optimizer_search_depth",
&SV::optimizer_search_depth);
+sys_var_const_os_str sys_plugin_dir("plugin_dir", opt_plugin_dir);
sys_var_thd_ulong sys_preload_buff_size("preload_buffer_size",
&SV::preload_buff_size);
sys_var_thd_ulong sys_read_buff_size("read_buffer_size",
@@ -338,7 +341,7 @@ sys_var_thd_ulong sys_query_alloc_block_size("query_alloc_block_size",
sys_var_thd_ulong sys_query_prealloc_size("query_prealloc_size",
&SV::query_prealloc_size,
0, fix_thd_mem_root);
-sys_var_readonly sys_tmpdir("tmpdir", OPT_GLOBAL, SHOW_CHAR, get_tmpdir);
+sys_var_readonly_os sys_tmpdir("tmpdir", OPT_GLOBAL, SHOW_CHAR, get_tmpdir);
sys_var_thd_ulong sys_trans_alloc_block_size("transaction_alloc_block_size",
&SV::trans_alloc_block_size,
0, fix_trans_mem_root);
@@ -363,9 +366,11 @@ sys_var_bool_ptr sys_secure_auth("secure_auth", &opt_secure_auth);
sys_var_const_str_ptr sys_secure_file_priv("secure_file_priv",
&opt_secure_file_priv);
sys_var_long_ptr sys_server_id("server_id", &server_id, fix_server_id);
+#ifdef HAVE_REPLICATION
sys_var_bool_ptr sys_slave_compressed_protocol("slave_compressed_protocol",
&opt_slave_compressed_protocol);
-#ifdef HAVE_REPLICATION
+sys_var_const_os_str_ptr sys_slave_load_tmpdir("slave_load_tmpdir",
+ &slave_load_tmpdir);
sys_var_long_ptr sys_slave_net_timeout("slave_net_timeout",
&slave_net_timeout);
sys_var_long_ptr sys_slave_trans_retries("slave_transaction_retries",
@@ -380,17 +385,17 @@ sys_var_thd_sql_mode sys_sql_mode("sql_mode",
#ifdef HAVE_OPENSSL
extern char *opt_ssl_ca, *opt_ssl_capath, *opt_ssl_cert, *opt_ssl_cipher,
*opt_ssl_key;
-sys_var_const_str_ptr sys_ssl_ca("ssl_ca", &opt_ssl_ca);
-sys_var_const_str_ptr sys_ssl_capath("ssl_capath", &opt_ssl_capath);
-sys_var_const_str_ptr sys_ssl_cert("ssl_cert", &opt_ssl_cert);
-sys_var_const_str_ptr sys_ssl_cipher("ssl_cipher", &opt_ssl_cipher);
-sys_var_const_str_ptr sys_ssl_key("ssl_key", &opt_ssl_key);
+sys_var_const_os_str_ptr sys_ssl_ca("ssl_ca", &opt_ssl_ca);
+sys_var_const_os_str_ptr sys_ssl_capath("ssl_capath", &opt_ssl_capath);
+sys_var_const_os_str_ptr sys_ssl_cert("ssl_cert", &opt_ssl_cert);
+sys_var_const_os_str_ptr sys_ssl_cipher("ssl_cipher", &opt_ssl_cipher);
+sys_var_const_os_str_ptr sys_ssl_key("ssl_key", &opt_ssl_key);
#else
-sys_var_const_str sys_ssl_ca("ssl_ca", NULL);
-sys_var_const_str sys_ssl_capath("ssl_capath", NULL);
-sys_var_const_str sys_ssl_cert("ssl_cert", NULL);
-sys_var_const_str sys_ssl_cipher("ssl_cipher", NULL);
-sys_var_const_str sys_ssl_key("ssl_key", NULL);
+sys_var_const_os_str sys_ssl_ca("ssl_ca", NULL);
+sys_var_const_os_str sys_ssl_capath("ssl_capath", NULL);
+sys_var_const_os_str sys_ssl_cert("ssl_cert", NULL);
+sys_var_const_os_str sys_ssl_cipher("ssl_cipher", NULL);
+sys_var_const_os_str sys_ssl_key("ssl_key", NULL);
#endif
sys_var_thd_enum
sys_updatable_views_with_limit("updatable_views_with_limit",
@@ -460,6 +465,14 @@ sys_var_long_ptr sys_innodb_commit_concurrency("innodb_commit_concurrency",
sys_var_long_ptr sys_innodb_flush_log_at_trx_commit(
"innodb_flush_log_at_trx_commit",
&srv_flush_log_at_trx_commit);
+sys_var_const_os_str_ptr sys_innodb_data_file_path("innodb_data_file_path",
+ &innobase_data_file_path);
+sys_var_const_os_str_ptr sys_innodb_data_home_dir("innodb_data_home_dir",
+ &innobase_data_home_dir);
+sys_var_const_os_str_ptr sys_innodb_log_arch_dir("innodb_log_arch_dir",
+ &innobase_log_arch_dir);
+sys_var_const_os_str_ptr sys_innodb_log_group_home_dir("innodb_log_group_home_dir",
+ &innobase_log_group_home_dir);
#endif
/* Condition pushdown to storage engine */
@@ -844,7 +857,7 @@ struct show_var_st init_vars[]= {
{sys_character_set_results.name,(char*) &sys_character_set_results, SHOW_SYS},
{sys_character_set_server.name, (char*) &sys_character_set_server,SHOW_SYS},
{sys_charset_system.name, (char*) &sys_charset_system, SHOW_SYS},
- {"character_sets_dir", mysql_charsets_dir, SHOW_CHAR},
+ {sys_character_sets_dir.name, (char *) &sys_character_sets_dir, SHOW_SYS},
{sys_collation_connection.name,(char*) &sys_collation_connection, SHOW_SYS},
{sys_collation_database.name,(char*) &sys_collation_database, SHOW_SYS},
{sys_collation_server.name,(char*) &sys_collation_server, SHOW_SYS},
@@ -905,8 +918,8 @@ struct show_var_st init_vars[]= {
{"innodb_checksums", (char*) &innobase_use_checksums, SHOW_MY_BOOL},
{sys_innodb_commit_concurrency.name, (char*) &sys_innodb_commit_concurrency, SHOW_SYS},
{sys_innodb_concurrency_tickets.name, (char*) &sys_innodb_concurrency_tickets, SHOW_SYS},
- {"innodb_data_file_path", (char*) &innobase_data_file_path, SHOW_CHAR_PTR},
- {"innodb_data_home_dir", (char*) &innobase_data_home_dir, SHOW_CHAR_PTR},
+ {sys_innodb_data_file_path.name, (char*) &sys_innodb_data_file_path, SHOW_SYS},
+ {sys_innodb_data_home_dir.name, (char*) &sys_innodb_data_home_dir, SHOW_SYS},
{"innodb_adaptive_hash_index", (char*) &innobase_adaptive_hash_index, SHOW_MY_BOOL},
{"innodb_doublewrite", (char*) &innobase_use_doublewrite, SHOW_MY_BOOL},
{sys_innodb_fast_shutdown.name,(char*) &sys_innodb_fast_shutdown, SHOW_SYS},
@@ -917,12 +930,12 @@ struct show_var_st init_vars[]= {
{"innodb_force_recovery", (char*) &innobase_force_recovery, SHOW_LONG },
{"innodb_lock_wait_timeout", (char*) &innobase_lock_wait_timeout, SHOW_LONG },
{"innodb_locks_unsafe_for_binlog", (char*) &innobase_locks_unsafe_for_binlog, SHOW_MY_BOOL},
- {"innodb_log_arch_dir", (char*) &innobase_log_arch_dir, SHOW_CHAR_PTR},
+ {sys_innodb_log_arch_dir.name, (char*) &sys_innodb_log_arch_dir, SHOW_SYS},
{"innodb_log_archive", (char*) &innobase_log_archive, SHOW_MY_BOOL},
{"innodb_log_buffer_size", (char*) &innobase_log_buffer_size, SHOW_LONG },
{"innodb_log_file_size", (char*) &innobase_log_file_size, SHOW_LONGLONG},
{"innodb_log_files_in_group", (char*) &innobase_log_files_in_group, SHOW_LONG},
- {"innodb_log_group_home_dir", (char*) &innobase_log_group_home_dir, SHOW_CHAR_PTR},
+ {sys_innodb_log_group_home_dir.name, (char*) &sys_innodb_log_group_home_dir, SHOW_SYS},
{sys_innodb_max_dirty_pages_pct.name, (char*) &sys_innodb_max_dirty_pages_pct, SHOW_SYS},
{sys_innodb_max_purge_lag.name, (char*) &sys_innodb_max_purge_lag, SHOW_SYS},
{"innodb_mirrored_log_groups", (char*) &innobase_mirrored_log_groups, SHOW_LONG},
@@ -1026,7 +1039,7 @@ struct show_var_st init_vars[]= {
{sys_optimizer_search_depth.name,(char*) &sys_optimizer_search_depth,
SHOW_SYS},
{"pid_file", (char*) pidfile_name, SHOW_CHAR},
- {"plugin_dir", (char*) opt_plugin_dir, SHOW_CHAR},
+ {sys_plugin_dir.name, (char*) &sys_plugin_dir, SHOW_SYS},
{"port", (char*) &mysqld_port, SHOW_INT},
{sys_preload_buff_size.name, (char*) &sys_preload_buff_size, SHOW_SYS},
{"protocol_version", (char*) &protocol_version, SHOW_INT},
@@ -1068,7 +1081,7 @@ struct show_var_st init_vars[]= {
#ifdef HAVE_REPLICATION
{sys_slave_compressed_protocol.name,
(char*) &sys_slave_compressed_protocol, SHOW_SYS},
- {"slave_load_tmpdir", (char*) &slave_load_tmpdir, SHOW_CHAR_PTR},
+ {sys_slave_load_tmpdir.name,(char*) &sys_slave_load_tmpdir, SHOW_SYS},
{sys_slave_net_timeout.name,(char*) &sys_slave_net_timeout, SHOW_SYS},
{"slave_skip_errors", (char*) &slave_error_mask, SHOW_SLAVE_SKIP_ERRORS},
{sys_slave_trans_retries.name,(char*) &sys_slave_trans_retries, SHOW_SYS},
@@ -1175,6 +1188,7 @@ bool update_sys_var_str(sys_var_str *var_str, rw_lock_t *var_mutex,
old_value= var_str->value;
var_str->value= res;
var_str->value_length= new_length;
+ var_str->is_os_charset= FALSE;
rw_unlock(var_mutex);
my_free(old_value, MYF(MY_ALLOW_ZERO_PTR));
return 0;
@@ -1914,11 +1928,11 @@ Item *sys_var::item(THD *thd, enum_var_type var_type, LEX_STRING *base)
char *str= (char*) value_ptr(thd, var_type, base);
if (str)
tmp= new Item_string(str, strlen(str),
- system_charset_info, DERIVATION_SYSCONST);
+ charset(thd), DERIVATION_SYSCONST);
else
{
tmp= new Item_null();
- tmp->collation.set(system_charset_info, DERIVATION_SYSCONST);
+ tmp->collation.set(charset(thd), DERIVATION_SYSCONST);
}
pthread_mutex_unlock(&LOCK_global_system_variables);
return tmp;
@@ -1930,6 +1944,13 @@ Item *sys_var::item(THD *thd, enum_var_type var_type, LEX_STRING *base)
}
+CHARSET_INFO *sys_var::charset(THD *thd)
+{
+ return is_os_charset ? thd->variables.character_set_filesystem :
+ system_charset_info;
+}
+
+
bool sys_var_thd_enum::update(THD *thd, set_var *var)
{
if (var->type == OPT_GLOBAL)
@@ -3454,6 +3475,7 @@ int set_var_password::check(THD *thd)
#ifndef NO_EMBEDDED_ACCESS_CHECKS
if (!user->host.str)
{
+ DBUG_ASSERT(thd->security_ctx->priv_host);
if (*thd->security_ctx->priv_host != 0)
{
user->host.str= (char *) thd->security_ctx->priv_host;
@@ -3465,6 +3487,12 @@ int set_var_password::check(THD *thd)
user->host.length= 1;
}
}
+ if (!user->user.str)
+ {
+ DBUG_ASSERT(thd->security_ctx->priv_user);
+ user->user.str= (char *) thd->security_ctx->priv_user;
+ user->user.length= strlen(thd->security_ctx->priv_user);
+ }
/* Returns 1 as the function sends error to client */
return check_change_password(thd, user->host.str, user->user.str,
password, strlen(password)) ? 1 : 0;
diff --git a/sql/set_var.h b/sql/set_var.h
index c37cc400e43..f43d3b75cee 100644
--- a/sql/set_var.h
+++ b/sql/set_var.h
@@ -46,9 +46,17 @@ public:
sys_after_update_func after_update;
bool no_support_one_shot;
+ /*
+ true if the value is in character_set_filesystem,
+ false otherwise.
+ Note that we can't use a pointer to the charset as the system var is
+ instantiated in global scope and the charset pointers are initialized
+ later.
+ */
+ bool is_os_charset;
sys_var(const char *name_arg, sys_after_update_func func= NULL)
:name(name_arg), after_update(func)
- , no_support_one_shot(1)
+ , no_support_one_shot(1), is_os_charset(FALSE)
{}
virtual ~sys_var() {}
virtual bool check(THD *thd, set_var *var);
@@ -68,6 +76,7 @@ public:
Item *item(THD *thd, enum_var_type type, LEX_STRING *base);
virtual bool is_struct() { return 0; }
virtual bool is_readonly() const { return 0; }
+ CHARSET_INFO *charset(THD *thd);
};
@@ -247,6 +256,17 @@ public:
};
+class sys_var_const_os_str: public sys_var_const_str
+{
+public:
+ sys_var_const_os_str(const char *name_arg, const char *value_arg)
+ :sys_var_const_str(name_arg, value_arg)
+ {
+ is_os_charset= TRUE;
+ }
+};
+
+
class sys_var_const_str_ptr :public sys_var
{
public:
@@ -276,6 +296,17 @@ public:
};
+class sys_var_const_os_str_ptr :public sys_var_const_str_ptr
+{
+public:
+ sys_var_const_os_str_ptr(const char *name_arg, char **value_arg)
+ :sys_var_const_str_ptr(name_arg, value_arg)
+ {
+ is_os_charset= TRUE;
+ }
+};
+
+
class sys_var_enum :public sys_var
{
uint *value;
@@ -791,6 +822,20 @@ public:
bool is_readonly() const { return 1; }
};
+
+class sys_var_readonly_os: public sys_var_readonly
+{
+public:
+ sys_var_readonly_os(const char *name_arg, enum_var_type type,
+ SHOW_TYPE show_type_arg,
+ sys_value_ptr_func value_ptr_func_arg)
+ :sys_var_readonly(name_arg, type, show_type_arg, value_ptr_func_arg)
+ {
+ is_os_charset= TRUE;
+ }
+};
+
+
class sys_var_thd_time_zone :public sys_var_thd
{
public:
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index df5e844749f..c59c42d512a 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -3866,6 +3866,11 @@ bool check_grant_all_columns(THD *thd, ulong want_access_arg,
Security_context *sctx= thd->security_ctx;
ulong want_access= want_access_arg;
const char *table_name= NULL;
+ /*
+ Flag that gets set if privilege checking has to be performed on column
+ level.
+ */
+ bool using_column_privileges= FALSE;
if (grant_option)
{
@@ -3909,6 +3914,8 @@ bool check_grant_all_columns(THD *thd, ulong want_access_arg,
GRANT_COLUMN *grant_column=
column_hash_search(grant_table, field_name,
(uint) strlen(field_name));
+ if (grant_column)
+ using_column_privileges= TRUE;
if (!grant_column || (~grant_column->rights & want_access))
goto err;
}
@@ -3924,12 +3931,21 @@ err:
char command[128];
get_privilege_desc(command, sizeof(command), want_access);
- my_error(ER_COLUMNACCESS_DENIED_ERROR, MYF(0),
- command,
- sctx->priv_user,
- sctx->host_or_ip,
- fields->name(),
- table_name);
+ /*
+ Do not give an error message listing a column name unless the user has
+ privilege to see all columns.
+ */
+ if (using_column_privileges)
+ my_error(ER_TABLEACCESS_DENIED_ERROR, MYF(0),
+ command, sctx->priv_user,
+ sctx->host_or_ip, table_name);
+ else
+ my_error(ER_COLUMNACCESS_DENIED_ERROR, MYF(0),
+ command,
+ sctx->priv_user,
+ sctx->host_or_ip,
+ fields->name(),
+ table_name);
return 1;
}
@@ -5953,10 +5969,12 @@ int wild_case_compare(CHARSET_INFO *cs, const char *str,const char *wildstr)
}
-void update_schema_privilege(TABLE *table, char *buff, const char* db,
- const char* t_name, const char* column,
- uint col_length, const char *priv,
- uint priv_length, const char* is_grantable)
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
+static bool update_schema_privilege(THD *thd, TABLE *table, char *buff,
+ const char* db, const char* t_name,
+ const char* column, uint col_length,
+ const char *priv, uint priv_length,
+ const char* is_grantable)
{
int i= 2;
CHARSET_INFO *cs= system_charset_info;
@@ -5970,13 +5988,15 @@ void update_schema_privilege(TABLE *table, char *buff, const char* db,
table->field[i++]->store(column, col_length, cs);
table->field[i++]->store(priv, priv_length, cs);
table->field[i]->store(is_grantable, strlen(is_grantable), cs);
- table->file->write_row(table->record[0]);
+ return schema_table_store_record(thd, table);
}
+#endif
int fill_schema_user_privileges(THD *thd, TABLE_LIST *tables, COND *cond)
{
#ifndef NO_EMBEDDED_ACCESS_CHECKS
+ int error= 0;
uint counter;
ACL_USER *acl_user;
ulong want_access;
@@ -6010,8 +6030,14 @@ int fill_schema_user_privileges(THD *thd, TABLE_LIST *tables, COND *cond)
strxmov(buff,"'",user,"'@'",host,"'",NullS);
if (!(want_access & ~GRANT_ACL))
- update_schema_privilege(table, buff, 0, 0, 0, 0,
- STRING_WITH_LEN("USAGE"), is_grantable);
+ {
+ if (update_schema_privilege(thd, table, buff, 0, 0, 0, 0,
+ STRING_WITH_LEN("USAGE"), is_grantable))
+ {
+ error= 1;
+ goto err;
+ }
+ }
else
{
uint priv_id;
@@ -6019,16 +6045,22 @@ int fill_schema_user_privileges(THD *thd, TABLE_LIST *tables, COND *cond)
for (priv_id=0, j = SELECT_ACL;j <= GLOBAL_ACLS; priv_id++,j <<= 1)
{
if (test_access & j)
- update_schema_privilege(table, buff, 0, 0, 0, 0,
- command_array[priv_id],
- command_lengths[priv_id], is_grantable);
+ {
+ if (update_schema_privilege(thd, table, buff, 0, 0, 0, 0,
+ command_array[priv_id],
+ command_lengths[priv_id], is_grantable))
+ {
+ error= 1;
+ goto err;
+ }
+ }
}
}
}
-
+err:
pthread_mutex_unlock(&acl_cache->lock);
- DBUG_RETURN(0);
+ DBUG_RETURN(error);
#else
return(0);
#endif
@@ -6038,6 +6070,7 @@ int fill_schema_user_privileges(THD *thd, TABLE_LIST *tables, COND *cond)
int fill_schema_schema_privileges(THD *thd, TABLE_LIST *tables, COND *cond)
{
#ifndef NO_EMBEDDED_ACCESS_CHECKS
+ int error= 0;
uint counter;
ACL_DB *acl_db;
ulong want_access;
@@ -6075,24 +6108,36 @@ int fill_schema_schema_privileges(THD *thd, TABLE_LIST *tables, COND *cond)
}
strxmov(buff,"'",user,"'@'",host,"'",NullS);
if (!(want_access & ~GRANT_ACL))
- update_schema_privilege(table, buff, acl_db->db, 0, 0,
- 0, STRING_WITH_LEN("USAGE"), is_grantable);
+ {
+ if (update_schema_privilege(thd, table, buff, acl_db->db, 0, 0,
+ 0, STRING_WITH_LEN("USAGE"), is_grantable))
+ {
+ error= 1;
+ goto err;
+ }
+ }
else
{
int cnt;
ulong j,test_access= want_access & ~GRANT_ACL;
for (cnt=0, j = SELECT_ACL; j <= DB_ACLS; cnt++,j <<= 1)
if (test_access & j)
- update_schema_privilege(table, buff, acl_db->db, 0, 0, 0,
- command_array[cnt], command_lengths[cnt],
- is_grantable);
+ {
+ if (update_schema_privilege(thd, table, buff, acl_db->db, 0, 0, 0,
+ command_array[cnt], command_lengths[cnt],
+ is_grantable))
+ {
+ error= 1;
+ goto err;
+ }
+ }
}
}
}
-
+err:
pthread_mutex_unlock(&acl_cache->lock);
- DBUG_RETURN(0);
+ DBUG_RETURN(error);
#else
return (0);
#endif
@@ -6102,6 +6147,7 @@ int fill_schema_schema_privileges(THD *thd, TABLE_LIST *tables, COND *cond)
int fill_schema_table_privileges(THD *thd, TABLE_LIST *tables, COND *cond)
{
#ifndef NO_EMBEDDED_ACCESS_CHECKS
+ int error= 0;
uint index;
char buff[100];
TABLE *table= tables->table;
@@ -6141,8 +6187,15 @@ int fill_schema_table_privileges(THD *thd, TABLE_LIST *tables, COND *cond)
strxmov(buff, "'", user, "'@'", host, "'", NullS);
if (!test_access)
- update_schema_privilege(table, buff, grant_table->db, grant_table->tname,
- 0, 0, STRING_WITH_LEN("USAGE"), is_grantable);
+ {
+ if (update_schema_privilege(thd, table, buff, grant_table->db,
+ grant_table->tname, 0, 0,
+ STRING_WITH_LEN("USAGE"), is_grantable))
+ {
+ error= 1;
+ goto err;
+ }
+ }
else
{
ulong j;
@@ -6150,17 +6203,24 @@ int fill_schema_table_privileges(THD *thd, TABLE_LIST *tables, COND *cond)
for (cnt= 0, j= SELECT_ACL; j <= TABLE_ACLS; cnt++, j<<= 1)
{
if (test_access & j)
- update_schema_privilege(table, buff, grant_table->db,
- grant_table->tname, 0, 0, command_array[cnt],
- command_lengths[cnt], is_grantable);
+ {
+ if (update_schema_privilege(thd, table, buff, grant_table->db,
+ grant_table->tname, 0, 0,
+ command_array[cnt],
+ command_lengths[cnt], is_grantable))
+ {
+ error= 1;
+ goto err;
+ }
+ }
}
}
- }
+ }
}
-
+err:
rw_unlock(&LOCK_grant);
- DBUG_RETURN(0);
+ DBUG_RETURN(error);
#else
return (0);
#endif
@@ -6170,6 +6230,7 @@ int fill_schema_table_privileges(THD *thd, TABLE_LIST *tables, COND *cond)
int fill_schema_column_privileges(THD *thd, TABLE_LIST *tables, COND *cond)
{
#ifndef NO_EMBEDDED_ACCESS_CHECKS
+ int error= 0;
uint index;
char buff[100];
TABLE *table= tables->table;
@@ -6219,22 +6280,28 @@ int fill_schema_column_privileges(THD *thd, TABLE_LIST *tables, COND *cond)
GRANT_COLUMN *grant_column = (GRANT_COLUMN*)
hash_element(&grant_table->hash_columns,col_index);
if ((grant_column->rights & j) && (table_access & j))
- update_schema_privilege(table, buff, grant_table->db,
- grant_table->tname,
- grant_column->column,
- grant_column->key_length,
- command_array[cnt],
- command_lengths[cnt], is_grantable);
+ {
+ if (update_schema_privilege(thd, table, buff, grant_table->db,
+ grant_table->tname,
+ grant_column->column,
+ grant_column->key_length,
+ command_array[cnt],
+ command_lengths[cnt], is_grantable))
+ {
+ error= 1;
+ goto err;
+ }
+ }
}
}
}
}
}
}
-
+err:
rw_unlock(&LOCK_grant);
- DBUG_RETURN(0);
+ DBUG_RETURN(error);
#else
return (0);
#endif
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 873a3eac24e..781bbc0a553 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -2102,7 +2102,10 @@ bool reopen_table(TABLE *table,bool locked)
for (key=0 ; key < table->s->keys ; key++)
{
for (part=0 ; part < table->key_info[key].usable_key_parts ; part++)
+ {
table->key_info[key].key_part[part].field->table= table;
+ table->key_info[key].key_part[part].field->orig_table= table;
+ }
}
if (table->triggers)
table->triggers->set_table(table);
@@ -5476,7 +5479,7 @@ insert_fields(THD *thd, Name_resolution_context *context, const char *db_name,
#ifndef NO_EMBEDDED_ACCESS_CHECKS
/* Ensure that we have access rights to all fields to be inserted. */
- if (!((table && (table->grant.privilege & SELECT_ACL) ||
+ if (!((table && !tables->view && (table->grant.privilege & SELECT_ACL) ||
tables->view && (tables->grant.privilege & SELECT_ACL))) &&
!any_privileges)
{
diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc
index b4fe1e65bbc..4a060ba7178 100644
--- a/sql/sql_cache.cc
+++ b/sql/sql_cache.cc
@@ -747,7 +747,12 @@ void query_cache_end_of_result(THD *thd)
if (thd->net.query_cache_query == 0)
DBUG_VOID_RETURN;
- if (thd->killed)
+ /*
+ Check if the NET layer raised a unreported error -- my_error() and
+ as a consequence query_cache_abort() haven't been called. Abort the
+ cached result as it might be only partially complete.
+ */
+ if (thd->killed || thd->net.report_error)
{
query_cache_abort(&thd->net);
DBUG_VOID_RETURN;
@@ -896,6 +901,8 @@ void Query_cache::store_query(THD *thd, TABLE_LIST *tables_used)
CLIENT_PROTOCOL_41);
flags.more_results_exists= test(thd->server_status &
SERVER_MORE_RESULTS_EXISTS);
+ flags.in_trans= test(thd->server_status & SERVER_STATUS_IN_TRANS);
+ flags.autocommit= test(thd->server_status & SERVER_STATUS_AUTOCOMMIT);
flags.pkt_nr= net->pkt_nr;
flags.character_set_client_num=
thd->variables.character_set_client->number;
@@ -916,7 +923,7 @@ void Query_cache::store_query(THD *thd, TABLE_LIST *tables_used)
DBUG_PRINT("qcache", ("long %d, 4.1: %d, more results %d, pkt_nr: %d, \
CS client: %u, CS result: %u, CS conn: %u, limit: %lu, TZ: 0x%lx, \
sql mode: 0x%lx, sort len: %lu, conncat len: %lu, div_precision: %lu, \
-def_week_frmt: %lu",
+def_week_frmt: %lu, in_trans: %d, autocommit: %d",
(int)flags.client_long_flag,
(int)flags.client_protocol_41,
(int)flags.more_results_exists,
@@ -930,7 +937,10 @@ def_week_frmt: %lu",
flags.max_sort_length,
flags.group_concat_max_len,
flags.div_precision_increment,
- flags.default_week_format));
+ flags.default_week_format,
+ (int)flags.in_trans,
+ (int)flags.autocommit));
+
/*
Make InnoDB to release the adaptive hash index latch before
acquiring the query cache mutex.
@@ -1191,6 +1201,8 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length)
CLIENT_PROTOCOL_41);
flags.more_results_exists= test(thd->server_status &
SERVER_MORE_RESULTS_EXISTS);
+ flags.in_trans= test(thd->server_status & SERVER_STATUS_IN_TRANS);
+ flags.autocommit= test(thd->server_status & SERVER_STATUS_AUTOCOMMIT);
flags.pkt_nr= thd->net.pkt_nr;
flags.character_set_client_num= thd->variables.character_set_client->number;
flags.character_set_results_num=
@@ -1209,7 +1221,7 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length)
DBUG_PRINT("qcache", ("long %d, 4.1: %d, more results %d, pkt_nr: %d, \
CS client: %u, CS result: %u, CS conn: %u, limit: %lu, TZ: 0x%lx, \
sql mode: 0x%lx, sort len: %lu, conncat len: %lu, div_precision: %lu, \
-def_week_frmt: %lu",
+def_week_frmt: %lu, in_trans: %d, autocommit: %d",
(int)flags.client_long_flag,
(int)flags.client_protocol_41,
(int)flags.more_results_exists,
@@ -1223,7 +1235,9 @@ def_week_frmt: %lu",
flags.max_sort_length,
flags.group_concat_max_len,
flags.div_precision_increment,
- flags.default_week_format));
+ flags.default_week_format,
+ (int)flags.in_trans,
+ (int)flags.autocommit));
memcpy((void *)(sql + (tot_length - QUERY_CACHE_FLAGS_SIZE)),
&flags, QUERY_CACHE_FLAGS_SIZE);
query_block = (Query_cache_block *) hash_search(&queries, (byte*) sql,
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index e00323ebab1..88b7dfb46d7 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -172,7 +172,9 @@ THD::THD()
/* statement id */ 0),
Open_tables_state(refresh_version),
lock_id(&main_lock_id),
- user_time(0), in_sub_stmt(0), global_read_lock(0), is_fatal_error(0),
+ user_time(0), in_sub_stmt(0),
+ table_map_for_update(0),
+ global_read_lock(0), is_fatal_error(0),
transaction_rollback_request(0), is_fatal_sub_stmt_error(0),
rand_used(0), time_zone_used(0),
last_insert_id_used(0), last_insert_id_used_bin_log(0), insert_id_used(0),
@@ -397,6 +399,10 @@ void THD::init_for_queries()
void THD::change_user(void)
{
+ pthread_mutex_lock(&LOCK_status);
+ add_to_status(&global_status_var, &status_var);
+ pthread_mutex_unlock(&LOCK_status);
+
cleanup();
cleanup_done= 0;
init();
@@ -653,6 +659,8 @@ void THD::cleanup_after_query()
free_items();
/* Reset where. */
where= THD::DEFAULT_WHERE;
+ /* reset table map for multi-table update */
+ table_map_for_update= 0;
}
@@ -1049,6 +1057,11 @@ bool select_send::send_data(List<Item> &items)
my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
break;
}
+ /*
+ Reset buffer to its original state, as it may have been altered in
+ Item::send().
+ */
+ buffer.set(buff, sizeof(buff), &my_charset_bin);
}
thd->sent_row_count++;
if (!thd->vio_ok())
diff --git a/sql/sql_class.h b/sql/sql_class.h
index c8d42d44df7..3e3dfcd08fa 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -205,6 +205,13 @@ class MYSQL_LOG: public TC_LOG
time_t last_time,query_start;
IO_CACHE log_file;
IO_CACHE index_file;
+ /*
+ purge_temp is a temp file used in purge_logs so that the index file
+ can be updated before deleting files from disk, yielding better crash
+ recovery. It is created on demand the first time purge_logs is called
+ and then reused for subsequent calls. It is cleaned up in cleanup().
+ */
+ IO_CACHE purge_temp;
char *name;
char time_buff[20],db[NAME_LEN+1];
char log_file_name[FN_REFLEN],index_file_name[FN_REFLEN];
@@ -1351,6 +1358,13 @@ public:
Note: in the parser, stmt_arena == thd, even for PS/SP.
*/
Query_arena *stmt_arena;
+
+ /*
+ map for tables that will be updated for a multi-table update query
+ statement, for other query statements, this will be zero.
+ */
+ table_map table_map_for_update;
+
/*
next_insert_id is set on SET INSERT_ID= #. This is used as the next
generated auto_increment value in handler.cc
diff --git a/sql/sql_cursor.cc b/sql/sql_cursor.cc
index 16567765ba6..83c60814cf3 100644
--- a/sql/sql_cursor.cc
+++ b/sql/sql_cursor.cc
@@ -85,6 +85,7 @@ class Materialized_cursor: public Server_side_cursor
List<Item> item_list;
ulong fetch_limit;
ulong fetch_count;
+ bool is_rnd_inited;
public:
Materialized_cursor(select_result *result, TABLE *table);
@@ -191,7 +192,11 @@ int mysql_open_cursor(THD *thd, uint flags, select_result *result,
such command is SHOW VARIABLES or SHOW STATUS.
*/
if (rc)
+ {
+ if (result_materialize->materialized_cursor)
+ delete result_materialize->materialized_cursor;
goto err_open;
+ }
if (sensitive_cursor->is_open())
{
@@ -532,7 +537,8 @@ Materialized_cursor::Materialized_cursor(select_result *result_arg,
:Server_side_cursor(&table_arg->mem_root, result_arg),
table(table_arg),
fetch_limit(0),
- fetch_count(0)
+ fetch_count(0),
+ is_rnd_inited(0)
{
fake_unit.init_query();
fake_unit.thd= table->in_use;
@@ -589,11 +595,12 @@ int Materialized_cursor::open(JOIN *join __attribute__((unused)))
THD *thd= fake_unit.thd;
int rc;
Query_arena backup_arena;
-
thd->set_n_backup_active_arena(this, &backup_arena);
/* Create a list of fields and start sequential scan */
- rc= (result->prepare(item_list, &fake_unit) ||
- table->file->ha_rnd_init(TRUE));
+ rc= result->prepare(item_list, &fake_unit);
+ if (!rc && !(rc= table->file->ha_rnd_init(TRUE)))
+ is_rnd_inited= 1;
+
thd->restore_active_arena(this, &backup_arena);
if (rc == 0)
{
@@ -673,7 +680,8 @@ void Materialized_cursor::close()
{
/* Free item_list items */
free_items();
- (void) table->file->ha_rnd_end();
+ if (is_rnd_inited)
+ (void) table->file->ha_rnd_end();
/*
We need to grab table->mem_root to prevent free_tmp_table from freeing:
the cursor object was allocated in this memory.
diff --git a/sql/sql_db.cc b/sql/sql_db.cc
index 8fbb407555a..c3cf7429222 100644
--- a/sql/sql_db.cc
+++ b/sql/sql_db.cc
@@ -909,7 +909,6 @@ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *db,
/* .frm archive:
Those archives are obsolete, but following code should
exist to remove existent "arc" directories.
- See #ifdef FRM_ARCHIVE directives for obsolete code.
*/
char newpath[FN_REFLEN];
MY_DIR *new_dirp;
@@ -1069,7 +1068,6 @@ static my_bool rm_dir_w_symlink(const char *org_path, my_bool send_error)
NOTE
A support of "arc" directories is obsolete, however this
function should exist to remove existent "arc" directories.
- See #ifdef FRM_ARCHIVE directives for obsolete code.
*/
long mysql_rm_arc_files(THD *thd, MY_DIR *dirp, const char *org_path)
{
diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc
index 822f2b2c419..f58a4ec4921 100644
--- a/sql/sql_handler.cc
+++ b/sql/sql_handler.cc
@@ -151,6 +151,9 @@ static void mysql_ha_close_table(THD *thd, TABLE_LIST *tables)
}
VOID(pthread_mutex_unlock(&LOCK_open));
}
+
+ /* Mark table as closed, ready for re-open if necessary. */
+ tables->table= NULL;
}
/*
@@ -168,8 +171,7 @@ static void mysql_ha_close_table(THD *thd, TABLE_LIST *tables)
'reopen' is set when a handler table is to be re-opened. In this case,
'tables' is the pointer to the hashed TABLE_LIST object which has been
saved on the original open.
- 'reopen' is also used to suppress the sending of an 'ok' message or
- error messages.
+ 'reopen' is also used to suppress the sending of an 'ok' message.
RETURN
FALSE OK
@@ -205,8 +207,7 @@ bool mysql_ha_open(THD *thd, TABLE_LIST *tables, bool reopen)
strlen(tables->alias) + 1))
{
DBUG_PRINT("info",("duplicate '%s'", tables->alias));
- if (! reopen)
- my_error(ER_NONUNIQ_TABLE, MYF(0), tables->alias);
+ my_error(ER_NONUNIQ_TABLE, MYF(0), tables->alias);
goto err;
}
}
@@ -251,8 +252,7 @@ bool mysql_ha_open(THD *thd, TABLE_LIST *tables, bool reopen)
/* There can be only one table in '*tables'. */
if (! (tables->table->file->table_flags() & HA_CAN_SQL_HANDLER))
{
- if (! reopen)
- my_error(ER_ILLEGAL_HA, MYF(0), tables->alias);
+ my_error(ER_ILLEGAL_HA, MYF(0), tables->alias);
goto err;
}
@@ -464,8 +464,7 @@ retry:
if (need_reopen)
{
- mysql_ha_close_table(thd, tables);
- hash_tables->table= NULL;
+ mysql_ha_close_table(thd, hash_tables);
/*
The lock might have been aborted, we need to manually reset
thd->some_tables_deleted because handler's tables are closed
diff --git a/sql/sql_locale.cc b/sql/sql_locale.cc
index 4e61c664106..3def9864c29 100644
--- a/sql/sql_locale.cc
+++ b/sql/sql_locale.cc
@@ -49,7 +49,9 @@ MY_LOCALE my_locale_ar_AE
&my_locale_typelib_month_names_ar_AE,
&my_locale_typelib_ab_month_names_ar_AE,
&my_locale_typelib_day_names_ar_AE,
- &my_locale_typelib_ab_day_names_ar_AE
+ &my_locale_typelib_ab_day_names_ar_AE,
+ 6,
+ 8
);
/***** LOCALE END ar_AE *****/
@@ -79,7 +81,9 @@ MY_LOCALE my_locale_ar_BH
&my_locale_typelib_month_names_ar_BH,
&my_locale_typelib_ab_month_names_ar_BH,
&my_locale_typelib_day_names_ar_BH,
- &my_locale_typelib_ab_day_names_ar_BH
+ &my_locale_typelib_ab_day_names_ar_BH,
+ 6,
+ 8
);
/***** LOCALE END ar_BH *****/
@@ -109,7 +113,9 @@ MY_LOCALE my_locale_ar_JO
&my_locale_typelib_month_names_ar_JO,
&my_locale_typelib_ab_month_names_ar_JO,
&my_locale_typelib_day_names_ar_JO,
- &my_locale_typelib_ab_day_names_ar_JO
+ &my_locale_typelib_ab_day_names_ar_JO,
+ 12,
+ 8
);
/***** LOCALE END ar_JO *****/
@@ -139,7 +145,9 @@ MY_LOCALE my_locale_ar_SA
&my_locale_typelib_month_names_ar_SA,
&my_locale_typelib_ab_month_names_ar_SA,
&my_locale_typelib_day_names_ar_SA,
- &my_locale_typelib_ab_day_names_ar_SA
+ &my_locale_typelib_ab_day_names_ar_SA,
+ 12,
+ 8
);
/***** LOCALE END ar_SA *****/
@@ -169,7 +177,9 @@ MY_LOCALE my_locale_ar_SY
&my_locale_typelib_month_names_ar_SY,
&my_locale_typelib_ab_month_names_ar_SY,
&my_locale_typelib_day_names_ar_SY,
- &my_locale_typelib_ab_day_names_ar_SY
+ &my_locale_typelib_ab_day_names_ar_SY,
+ 12,
+ 8
);
/***** LOCALE END ar_SY *****/
@@ -199,7 +209,9 @@ MY_LOCALE my_locale_be_BY
&my_locale_typelib_month_names_be_BY,
&my_locale_typelib_ab_month_names_be_BY,
&my_locale_typelib_day_names_be_BY,
- &my_locale_typelib_ab_day_names_be_BY
+ &my_locale_typelib_ab_day_names_be_BY,
+ 10,
+ 10
);
/***** LOCALE END be_BY *****/
@@ -229,7 +241,9 @@ MY_LOCALE my_locale_bg_BG
&my_locale_typelib_month_names_bg_BG,
&my_locale_typelib_ab_month_names_bg_BG,
&my_locale_typelib_day_names_bg_BG,
- &my_locale_typelib_ab_day_names_bg_BG
+ &my_locale_typelib_ab_day_names_bg_BG,
+ 9,
+ 10
);
/***** LOCALE END bg_BG *****/
@@ -259,7 +273,9 @@ MY_LOCALE my_locale_ca_ES
&my_locale_typelib_month_names_ca_ES,
&my_locale_typelib_ab_month_names_ca_ES,
&my_locale_typelib_day_names_ca_ES,
- &my_locale_typelib_ab_day_names_ca_ES
+ &my_locale_typelib_ab_day_names_ca_ES,
+ 8,
+ 9
);
/***** LOCALE END ca_ES *****/
@@ -289,7 +305,9 @@ MY_LOCALE my_locale_cs_CZ
&my_locale_typelib_month_names_cs_CZ,
&my_locale_typelib_ab_month_names_cs_CZ,
&my_locale_typelib_day_names_cs_CZ,
- &my_locale_typelib_ab_day_names_cs_CZ
+ &my_locale_typelib_ab_day_names_cs_CZ,
+ 8,
+ 7
);
/***** LOCALE END cs_CZ *****/
@@ -319,7 +337,9 @@ MY_LOCALE my_locale_da_DK
&my_locale_typelib_month_names_da_DK,
&my_locale_typelib_ab_month_names_da_DK,
&my_locale_typelib_day_names_da_DK,
- &my_locale_typelib_ab_day_names_da_DK
+ &my_locale_typelib_ab_day_names_da_DK,
+ 9,
+ 7
);
/***** LOCALE END da_DK *****/
@@ -349,7 +369,9 @@ MY_LOCALE my_locale_de_AT
&my_locale_typelib_month_names_de_AT,
&my_locale_typelib_ab_month_names_de_AT,
&my_locale_typelib_day_names_de_AT,
- &my_locale_typelib_ab_day_names_de_AT
+ &my_locale_typelib_ab_day_names_de_AT,
+ 9,
+ 10
);
/***** LOCALE END de_AT *****/
@@ -379,7 +401,9 @@ MY_LOCALE my_locale_de_DE
&my_locale_typelib_month_names_de_DE,
&my_locale_typelib_ab_month_names_de_DE,
&my_locale_typelib_day_names_de_DE,
- &my_locale_typelib_ab_day_names_de_DE
+ &my_locale_typelib_ab_day_names_de_DE,
+ 9,
+ 10
);
/***** LOCALE END de_DE *****/
@@ -409,7 +433,9 @@ MY_LOCALE my_locale_en_US
&my_locale_typelib_month_names_en_US,
&my_locale_typelib_ab_month_names_en_US,
&my_locale_typelib_day_names_en_US,
- &my_locale_typelib_ab_day_names_en_US
+ &my_locale_typelib_ab_day_names_en_US,
+ 9,
+ 9
);
/***** LOCALE END en_US *****/
@@ -439,7 +465,9 @@ MY_LOCALE my_locale_es_ES
&my_locale_typelib_month_names_es_ES,
&my_locale_typelib_ab_month_names_es_ES,
&my_locale_typelib_day_names_es_ES,
- &my_locale_typelib_ab_day_names_es_ES
+ &my_locale_typelib_ab_day_names_es_ES,
+ 10,
+ 9
);
/***** LOCALE END es_ES *****/
@@ -469,7 +497,9 @@ MY_LOCALE my_locale_et_EE
&my_locale_typelib_month_names_et_EE,
&my_locale_typelib_ab_month_names_et_EE,
&my_locale_typelib_day_names_et_EE,
- &my_locale_typelib_ab_day_names_et_EE
+ &my_locale_typelib_ab_day_names_et_EE,
+ 9,
+ 9
);
/***** LOCALE END et_EE *****/
@@ -499,7 +529,9 @@ MY_LOCALE my_locale_eu_ES
&my_locale_typelib_month_names_eu_ES,
&my_locale_typelib_ab_month_names_eu_ES,
&my_locale_typelib_day_names_eu_ES,
- &my_locale_typelib_ab_day_names_eu_ES
+ &my_locale_typelib_ab_day_names_eu_ES,
+ 9,
+ 10
);
/***** LOCALE END eu_ES *****/
@@ -529,7 +561,9 @@ MY_LOCALE my_locale_fi_FI
&my_locale_typelib_month_names_fi_FI,
&my_locale_typelib_ab_month_names_fi_FI,
&my_locale_typelib_day_names_fi_FI,
- &my_locale_typelib_ab_day_names_fi_FI
+ &my_locale_typelib_ab_day_names_fi_FI,
+ 9,
+ 11
);
/***** LOCALE END fi_FI *****/
@@ -559,7 +593,9 @@ MY_LOCALE my_locale_fo_FO
&my_locale_typelib_month_names_fo_FO,
&my_locale_typelib_ab_month_names_fo_FO,
&my_locale_typelib_day_names_fo_FO,
- &my_locale_typelib_ab_day_names_fo_FO
+ &my_locale_typelib_ab_day_names_fo_FO,
+ 9,
+ 12
);
/***** LOCALE END fo_FO *****/
@@ -589,7 +625,9 @@ MY_LOCALE my_locale_fr_FR
&my_locale_typelib_month_names_fr_FR,
&my_locale_typelib_ab_month_names_fr_FR,
&my_locale_typelib_day_names_fr_FR,
- &my_locale_typelib_ab_day_names_fr_FR
+ &my_locale_typelib_ab_day_names_fr_FR,
+ 9,
+ 8
);
/***** LOCALE END fr_FR *****/
@@ -619,7 +657,9 @@ MY_LOCALE my_locale_gl_ES
&my_locale_typelib_month_names_gl_ES,
&my_locale_typelib_ab_month_names_gl_ES,
&my_locale_typelib_day_names_gl_ES,
- &my_locale_typelib_ab_day_names_gl_ES
+ &my_locale_typelib_ab_day_names_gl_ES,
+ 8,
+ 8
);
/***** LOCALE END gl_ES *****/
@@ -649,7 +689,9 @@ MY_LOCALE my_locale_gu_IN
&my_locale_typelib_month_names_gu_IN,
&my_locale_typelib_ab_month_names_gu_IN,
&my_locale_typelib_day_names_gu_IN,
- &my_locale_typelib_ab_day_names_gu_IN
+ &my_locale_typelib_ab_day_names_gu_IN,
+ 10,
+ 8
);
/***** LOCALE END gu_IN *****/
@@ -679,7 +721,9 @@ MY_LOCALE my_locale_he_IL
&my_locale_typelib_month_names_he_IL,
&my_locale_typelib_ab_month_names_he_IL,
&my_locale_typelib_day_names_he_IL,
- &my_locale_typelib_ab_day_names_he_IL
+ &my_locale_typelib_ab_day_names_he_IL,
+ 7,
+ 5
);
/***** LOCALE END he_IL *****/
@@ -709,7 +753,9 @@ MY_LOCALE my_locale_hi_IN
&my_locale_typelib_month_names_hi_IN,
&my_locale_typelib_ab_month_names_hi_IN,
&my_locale_typelib_day_names_hi_IN,
- &my_locale_typelib_ab_day_names_hi_IN
+ &my_locale_typelib_ab_day_names_hi_IN,
+ 7,
+ 9
);
/***** LOCALE END hi_IN *****/
@@ -739,7 +785,9 @@ MY_LOCALE my_locale_hr_HR
&my_locale_typelib_month_names_hr_HR,
&my_locale_typelib_ab_month_names_hr_HR,
&my_locale_typelib_day_names_hr_HR,
- &my_locale_typelib_ab_day_names_hr_HR
+ &my_locale_typelib_ab_day_names_hr_HR,
+ 8,
+ 11
);
/***** LOCALE END hr_HR *****/
@@ -769,7 +817,9 @@ MY_LOCALE my_locale_hu_HU
&my_locale_typelib_month_names_hu_HU,
&my_locale_typelib_ab_month_names_hu_HU,
&my_locale_typelib_day_names_hu_HU,
- &my_locale_typelib_ab_day_names_hu_HU
+ &my_locale_typelib_ab_day_names_hu_HU,
+ 10,
+ 9
);
/***** LOCALE END hu_HU *****/
@@ -799,7 +849,9 @@ MY_LOCALE my_locale_id_ID
&my_locale_typelib_month_names_id_ID,
&my_locale_typelib_ab_month_names_id_ID,
&my_locale_typelib_day_names_id_ID,
- &my_locale_typelib_ab_day_names_id_ID
+ &my_locale_typelib_ab_day_names_id_ID,
+ 9,
+ 6
);
/***** LOCALE END id_ID *****/
@@ -829,7 +881,9 @@ MY_LOCALE my_locale_is_IS
&my_locale_typelib_month_names_is_IS,
&my_locale_typelib_ab_month_names_is_IS,
&my_locale_typelib_day_names_is_IS,
- &my_locale_typelib_ab_day_names_is_IS
+ &my_locale_typelib_ab_day_names_is_IS,
+ 9,
+ 12
);
/***** LOCALE END is_IS *****/
@@ -859,7 +913,9 @@ MY_LOCALE my_locale_it_CH
&my_locale_typelib_month_names_it_CH,
&my_locale_typelib_ab_month_names_it_CH,
&my_locale_typelib_day_names_it_CH,
- &my_locale_typelib_ab_day_names_it_CH
+ &my_locale_typelib_ab_day_names_it_CH,
+ 9,
+ 9
);
/***** LOCALE END it_CH *****/
@@ -889,7 +945,9 @@ MY_LOCALE my_locale_ja_JP
&my_locale_typelib_month_names_ja_JP,
&my_locale_typelib_ab_month_names_ja_JP,
&my_locale_typelib_day_names_ja_JP,
- &my_locale_typelib_ab_day_names_ja_JP
+ &my_locale_typelib_ab_day_names_ja_JP,
+ 3,
+ 3
);
/***** LOCALE END ja_JP *****/
@@ -919,7 +977,9 @@ MY_LOCALE my_locale_ko_KR
&my_locale_typelib_month_names_ko_KR,
&my_locale_typelib_ab_month_names_ko_KR,
&my_locale_typelib_day_names_ko_KR,
- &my_locale_typelib_ab_day_names_ko_KR
+ &my_locale_typelib_ab_day_names_ko_KR,
+ 3,
+ 3
);
/***** LOCALE END ko_KR *****/
@@ -949,7 +1009,9 @@ MY_LOCALE my_locale_lt_LT
&my_locale_typelib_month_names_lt_LT,
&my_locale_typelib_ab_month_names_lt_LT,
&my_locale_typelib_day_names_lt_LT,
- &my_locale_typelib_ab_day_names_lt_LT
+ &my_locale_typelib_ab_day_names_lt_LT,
+ 9,
+ 14
);
/***** LOCALE END lt_LT *****/
@@ -979,7 +1041,9 @@ MY_LOCALE my_locale_lv_LV
&my_locale_typelib_month_names_lv_LV,
&my_locale_typelib_ab_month_names_lv_LV,
&my_locale_typelib_day_names_lv_LV,
- &my_locale_typelib_ab_day_names_lv_LV
+ &my_locale_typelib_ab_day_names_lv_LV,
+ 10,
+ 11
);
/***** LOCALE END lv_LV *****/
@@ -1009,7 +1073,9 @@ MY_LOCALE my_locale_mk_MK
&my_locale_typelib_month_names_mk_MK,
&my_locale_typelib_ab_month_names_mk_MK,
&my_locale_typelib_day_names_mk_MK,
- &my_locale_typelib_ab_day_names_mk_MK
+ &my_locale_typelib_ab_day_names_mk_MK,
+ 9,
+ 10
);
/***** LOCALE END mk_MK *****/
@@ -1039,7 +1105,9 @@ MY_LOCALE my_locale_mn_MN
&my_locale_typelib_month_names_mn_MN,
&my_locale_typelib_ab_month_names_mn_MN,
&my_locale_typelib_day_names_mn_MN,
- &my_locale_typelib_ab_day_names_mn_MN
+ &my_locale_typelib_ab_day_names_mn_MN,
+ 18,
+ 6
);
/***** LOCALE END mn_MN *****/
@@ -1069,7 +1137,9 @@ MY_LOCALE my_locale_ms_MY
&my_locale_typelib_month_names_ms_MY,
&my_locale_typelib_ab_month_names_ms_MY,
&my_locale_typelib_day_names_ms_MY,
- &my_locale_typelib_ab_day_names_ms_MY
+ &my_locale_typelib_ab_day_names_ms_MY,
+ 9,
+ 6
);
/***** LOCALE END ms_MY *****/
@@ -1099,7 +1169,9 @@ MY_LOCALE my_locale_nb_NO
&my_locale_typelib_month_names_nb_NO,
&my_locale_typelib_ab_month_names_nb_NO,
&my_locale_typelib_day_names_nb_NO,
- &my_locale_typelib_ab_day_names_nb_NO
+ &my_locale_typelib_ab_day_names_nb_NO,
+ 9,
+ 7
);
/***** LOCALE END nb_NO *****/
@@ -1129,7 +1201,9 @@ MY_LOCALE my_locale_nl_NL
&my_locale_typelib_month_names_nl_NL,
&my_locale_typelib_ab_month_names_nl_NL,
&my_locale_typelib_day_names_nl_NL,
- &my_locale_typelib_ab_day_names_nl_NL
+ &my_locale_typelib_ab_day_names_nl_NL,
+ 9,
+ 9
);
/***** LOCALE END nl_NL *****/
@@ -1159,7 +1233,9 @@ MY_LOCALE my_locale_pl_PL
&my_locale_typelib_month_names_pl_PL,
&my_locale_typelib_ab_month_names_pl_PL,
&my_locale_typelib_day_names_pl_PL,
- &my_locale_typelib_ab_day_names_pl_PL
+ &my_locale_typelib_ab_day_names_pl_PL,
+ 11,
+ 12
);
/***** LOCALE END pl_PL *****/
@@ -1189,7 +1265,9 @@ MY_LOCALE my_locale_pt_BR
&my_locale_typelib_month_names_pt_BR,
&my_locale_typelib_ab_month_names_pt_BR,
&my_locale_typelib_day_names_pt_BR,
- &my_locale_typelib_ab_day_names_pt_BR
+ &my_locale_typelib_ab_day_names_pt_BR,
+ 9,
+ 7
);
/***** LOCALE END pt_BR *****/
@@ -1219,7 +1297,9 @@ MY_LOCALE my_locale_pt_PT
&my_locale_typelib_month_names_pt_PT,
&my_locale_typelib_ab_month_names_pt_PT,
&my_locale_typelib_day_names_pt_PT,
- &my_locale_typelib_ab_day_names_pt_PT
+ &my_locale_typelib_ab_day_names_pt_PT,
+ 9,
+ 7
);
/***** LOCALE END pt_PT *****/
@@ -1249,7 +1329,9 @@ MY_LOCALE my_locale_ro_RO
&my_locale_typelib_month_names_ro_RO,
&my_locale_typelib_ab_month_names_ro_RO,
&my_locale_typelib_day_names_ro_RO,
- &my_locale_typelib_ab_day_names_ro_RO
+ &my_locale_typelib_ab_day_names_ro_RO,
+ 10,
+ 8
);
/***** LOCALE END ro_RO *****/
@@ -1279,7 +1361,9 @@ MY_LOCALE my_locale_ru_RU
&my_locale_typelib_month_names_ru_RU,
&my_locale_typelib_ab_month_names_ru_RU,
&my_locale_typelib_day_names_ru_RU,
- &my_locale_typelib_ab_day_names_ru_RU
+ &my_locale_typelib_ab_day_names_ru_RU,
+ 8,
+ 11
);
/***** LOCALE END ru_RU *****/
@@ -1309,7 +1393,9 @@ MY_LOCALE my_locale_ru_UA
&my_locale_typelib_month_names_ru_UA,
&my_locale_typelib_ab_month_names_ru_UA,
&my_locale_typelib_day_names_ru_UA,
- &my_locale_typelib_ab_day_names_ru_UA
+ &my_locale_typelib_ab_day_names_ru_UA,
+ 8,
+ 11
);
/***** LOCALE END ru_UA *****/
@@ -1339,7 +1425,9 @@ MY_LOCALE my_locale_sk_SK
&my_locale_typelib_month_names_sk_SK,
&my_locale_typelib_ab_month_names_sk_SK,
&my_locale_typelib_day_names_sk_SK,
- &my_locale_typelib_ab_day_names_sk_SK
+ &my_locale_typelib_ab_day_names_sk_SK,
+ 9,
+ 8
);
/***** LOCALE END sk_SK *****/
@@ -1369,7 +1457,9 @@ MY_LOCALE my_locale_sl_SI
&my_locale_typelib_month_names_sl_SI,
&my_locale_typelib_ab_month_names_sl_SI,
&my_locale_typelib_day_names_sl_SI,
- &my_locale_typelib_ab_day_names_sl_SI
+ &my_locale_typelib_ab_day_names_sl_SI,
+ 9,
+ 10
);
/***** LOCALE END sl_SI *****/
@@ -1399,7 +1489,9 @@ MY_LOCALE my_locale_sq_AL
&my_locale_typelib_month_names_sq_AL,
&my_locale_typelib_ab_month_names_sq_AL,
&my_locale_typelib_day_names_sq_AL,
- &my_locale_typelib_ab_day_names_sq_AL
+ &my_locale_typelib_ab_day_names_sq_AL,
+ 7,
+ 10
);
/***** LOCALE END sq_AL *****/
@@ -1429,7 +1521,9 @@ MY_LOCALE my_locale_sr_YU
&my_locale_typelib_month_names_sr_YU,
&my_locale_typelib_ab_month_names_sr_YU,
&my_locale_typelib_day_names_sr_YU,
- &my_locale_typelib_ab_day_names_sr_YU
+ &my_locale_typelib_ab_day_names_sr_YU,
+ 9,
+ 10
);
/***** LOCALE END sr_YU *****/
@@ -1459,7 +1553,9 @@ MY_LOCALE my_locale_sv_SE
&my_locale_typelib_month_names_sv_SE,
&my_locale_typelib_ab_month_names_sv_SE,
&my_locale_typelib_day_names_sv_SE,
- &my_locale_typelib_ab_day_names_sv_SE
+ &my_locale_typelib_ab_day_names_sv_SE,
+ 9,
+ 7
);
/***** LOCALE END sv_SE *****/
@@ -1489,7 +1585,9 @@ MY_LOCALE my_locale_ta_IN
&my_locale_typelib_month_names_ta_IN,
&my_locale_typelib_ab_month_names_ta_IN,
&my_locale_typelib_day_names_ta_IN,
- &my_locale_typelib_ab_day_names_ta_IN
+ &my_locale_typelib_ab_day_names_ta_IN,
+ 10,
+ 8
);
/***** LOCALE END ta_IN *****/
@@ -1519,7 +1617,9 @@ MY_LOCALE my_locale_te_IN
&my_locale_typelib_month_names_te_IN,
&my_locale_typelib_ab_month_names_te_IN,
&my_locale_typelib_day_names_te_IN,
- &my_locale_typelib_ab_day_names_te_IN
+ &my_locale_typelib_ab_day_names_te_IN,
+ 10,
+ 9
);
/***** LOCALE END te_IN *****/
@@ -1549,7 +1649,9 @@ MY_LOCALE my_locale_th_TH
&my_locale_typelib_month_names_th_TH,
&my_locale_typelib_ab_month_names_th_TH,
&my_locale_typelib_day_names_th_TH,
- &my_locale_typelib_ab_day_names_th_TH
+ &my_locale_typelib_ab_day_names_th_TH,
+ 10,
+ 8
);
/***** LOCALE END th_TH *****/
@@ -1579,7 +1681,9 @@ MY_LOCALE my_locale_tr_TR
&my_locale_typelib_month_names_tr_TR,
&my_locale_typelib_ab_month_names_tr_TR,
&my_locale_typelib_day_names_tr_TR,
- &my_locale_typelib_ab_day_names_tr_TR
+ &my_locale_typelib_ab_day_names_tr_TR,
+ 7,
+ 9
);
/***** LOCALE END tr_TR *****/
@@ -1609,7 +1713,9 @@ MY_LOCALE my_locale_uk_UA
&my_locale_typelib_month_names_uk_UA,
&my_locale_typelib_ab_month_names_uk_UA,
&my_locale_typelib_day_names_uk_UA,
- &my_locale_typelib_ab_day_names_uk_UA
+ &my_locale_typelib_ab_day_names_uk_UA,
+ 8,
+ 9
);
/***** LOCALE END uk_UA *****/
@@ -1639,7 +1745,9 @@ MY_LOCALE my_locale_ur_PK
&my_locale_typelib_month_names_ur_PK,
&my_locale_typelib_ab_month_names_ur_PK,
&my_locale_typelib_day_names_ur_PK,
- &my_locale_typelib_ab_day_names_ur_PK
+ &my_locale_typelib_ab_day_names_ur_PK,
+ 6,
+ 6
);
/***** LOCALE END ur_PK *****/
@@ -1669,7 +1777,9 @@ MY_LOCALE my_locale_vi_VN
&my_locale_typelib_month_names_vi_VN,
&my_locale_typelib_ab_month_names_vi_VN,
&my_locale_typelib_day_names_vi_VN,
- &my_locale_typelib_ab_day_names_vi_VN
+ &my_locale_typelib_ab_day_names_vi_VN,
+ 16,
+ 11
);
/***** LOCALE END vi_VN *****/
@@ -1699,7 +1809,9 @@ MY_LOCALE my_locale_zh_CN
&my_locale_typelib_month_names_zh_CN,
&my_locale_typelib_ab_month_names_zh_CN,
&my_locale_typelib_day_names_zh_CN,
- &my_locale_typelib_ab_day_names_zh_CN
+ &my_locale_typelib_ab_day_names_zh_CN,
+ 3,
+ 3
);
/***** LOCALE END zh_CN *****/
@@ -1729,7 +1841,9 @@ MY_LOCALE my_locale_zh_TW
&my_locale_typelib_month_names_zh_TW,
&my_locale_typelib_ab_month_names_zh_TW,
&my_locale_typelib_day_names_zh_TW,
- &my_locale_typelib_ab_day_names_zh_TW
+ &my_locale_typelib_ab_day_names_zh_TW,
+ 3,
+ 2
);
/***** LOCALE END zh_TW *****/
@@ -1743,7 +1857,9 @@ MY_LOCALE my_locale_ar_DZ
&my_locale_typelib_month_names_ar_BH,
&my_locale_typelib_ab_month_names_ar_BH,
&my_locale_typelib_day_names_ar_BH,
- &my_locale_typelib_ab_day_names_ar_BH
+ &my_locale_typelib_ab_day_names_ar_BH,
+ 6,
+ 8
);
/***** LOCALE END ar_DZ *****/
@@ -1757,7 +1873,9 @@ MY_LOCALE my_locale_ar_EG
&my_locale_typelib_month_names_ar_BH,
&my_locale_typelib_ab_month_names_ar_BH,
&my_locale_typelib_day_names_ar_BH,
- &my_locale_typelib_ab_day_names_ar_BH
+ &my_locale_typelib_ab_day_names_ar_BH,
+ 6,
+ 8
);
/***** LOCALE END ar_EG *****/
@@ -1771,7 +1889,9 @@ MY_LOCALE my_locale_ar_IN
&my_locale_typelib_month_names_ar_BH,
&my_locale_typelib_ab_month_names_ar_BH,
&my_locale_typelib_day_names_ar_BH,
- &my_locale_typelib_ab_day_names_ar_BH
+ &my_locale_typelib_ab_day_names_ar_BH,
+ 6,
+ 8
);
/***** LOCALE END ar_IN *****/
@@ -1785,7 +1905,9 @@ MY_LOCALE my_locale_ar_IQ
&my_locale_typelib_month_names_ar_BH,
&my_locale_typelib_ab_month_names_ar_BH,
&my_locale_typelib_day_names_ar_BH,
- &my_locale_typelib_ab_day_names_ar_BH
+ &my_locale_typelib_ab_day_names_ar_BH,
+ 6,
+ 8
);
/***** LOCALE END ar_IQ *****/
@@ -1799,7 +1921,9 @@ MY_LOCALE my_locale_ar_KW
&my_locale_typelib_month_names_ar_BH,
&my_locale_typelib_ab_month_names_ar_BH,
&my_locale_typelib_day_names_ar_BH,
- &my_locale_typelib_ab_day_names_ar_BH
+ &my_locale_typelib_ab_day_names_ar_BH,
+ 6,
+ 8
);
/***** LOCALE END ar_KW *****/
@@ -1813,7 +1937,9 @@ MY_LOCALE my_locale_ar_LB
&my_locale_typelib_month_names_ar_JO,
&my_locale_typelib_ab_month_names_ar_JO,
&my_locale_typelib_day_names_ar_JO,
- &my_locale_typelib_ab_day_names_ar_JO
+ &my_locale_typelib_ab_day_names_ar_JO,
+ 12,
+ 8
);
/***** LOCALE END ar_LB *****/
@@ -1827,7 +1953,9 @@ MY_LOCALE my_locale_ar_LY
&my_locale_typelib_month_names_ar_BH,
&my_locale_typelib_ab_month_names_ar_BH,
&my_locale_typelib_day_names_ar_BH,
- &my_locale_typelib_ab_day_names_ar_BH
+ &my_locale_typelib_ab_day_names_ar_BH,
+ 6,
+ 8
);
/***** LOCALE END ar_LY *****/
@@ -1841,7 +1969,9 @@ MY_LOCALE my_locale_ar_MA
&my_locale_typelib_month_names_ar_BH,
&my_locale_typelib_ab_month_names_ar_BH,
&my_locale_typelib_day_names_ar_BH,
- &my_locale_typelib_ab_day_names_ar_BH
+ &my_locale_typelib_ab_day_names_ar_BH,
+ 6,
+ 8
);
/***** LOCALE END ar_MA *****/
@@ -1855,7 +1985,9 @@ MY_LOCALE my_locale_ar_OM
&my_locale_typelib_month_names_ar_BH,
&my_locale_typelib_ab_month_names_ar_BH,
&my_locale_typelib_day_names_ar_BH,
- &my_locale_typelib_ab_day_names_ar_BH
+ &my_locale_typelib_ab_day_names_ar_BH,
+ 6,
+ 8
);
/***** LOCALE END ar_OM *****/
@@ -1869,7 +2001,9 @@ MY_LOCALE my_locale_ar_QA
&my_locale_typelib_month_names_ar_BH,
&my_locale_typelib_ab_month_names_ar_BH,
&my_locale_typelib_day_names_ar_BH,
- &my_locale_typelib_ab_day_names_ar_BH
+ &my_locale_typelib_ab_day_names_ar_BH,
+ 6,
+ 8
);
/***** LOCALE END ar_QA *****/
@@ -1883,7 +2017,9 @@ MY_LOCALE my_locale_ar_SD
&my_locale_typelib_month_names_ar_BH,
&my_locale_typelib_ab_month_names_ar_BH,
&my_locale_typelib_day_names_ar_BH,
- &my_locale_typelib_ab_day_names_ar_BH
+ &my_locale_typelib_ab_day_names_ar_BH,
+ 6,
+ 8
);
/***** LOCALE END ar_SD *****/
@@ -1897,7 +2033,9 @@ MY_LOCALE my_locale_ar_TN
&my_locale_typelib_month_names_ar_BH,
&my_locale_typelib_ab_month_names_ar_BH,
&my_locale_typelib_day_names_ar_BH,
- &my_locale_typelib_ab_day_names_ar_BH
+ &my_locale_typelib_ab_day_names_ar_BH,
+ 6,
+ 8
);
/***** LOCALE END ar_TN *****/
@@ -1911,7 +2049,9 @@ MY_LOCALE my_locale_ar_YE
&my_locale_typelib_month_names_ar_BH,
&my_locale_typelib_ab_month_names_ar_BH,
&my_locale_typelib_day_names_ar_BH,
- &my_locale_typelib_ab_day_names_ar_BH
+ &my_locale_typelib_ab_day_names_ar_BH,
+ 6,
+ 8
);
/***** LOCALE END ar_YE *****/
@@ -1925,7 +2065,9 @@ MY_LOCALE my_locale_de_BE
&my_locale_typelib_month_names_de_DE,
&my_locale_typelib_ab_month_names_de_DE,
&my_locale_typelib_day_names_de_DE,
- &my_locale_typelib_ab_day_names_de_DE
+ &my_locale_typelib_ab_day_names_de_DE,
+ 9,
+ 10
);
/***** LOCALE END de_BE *****/
@@ -1939,7 +2081,9 @@ MY_LOCALE my_locale_de_CH
&my_locale_typelib_month_names_de_DE,
&my_locale_typelib_ab_month_names_de_DE,
&my_locale_typelib_day_names_de_DE,
- &my_locale_typelib_ab_day_names_de_DE
+ &my_locale_typelib_ab_day_names_de_DE,
+ 9,
+ 10
);
/***** LOCALE END de_CH *****/
@@ -1953,7 +2097,9 @@ MY_LOCALE my_locale_de_LU
&my_locale_typelib_month_names_de_DE,
&my_locale_typelib_ab_month_names_de_DE,
&my_locale_typelib_day_names_de_DE,
- &my_locale_typelib_ab_day_names_de_DE
+ &my_locale_typelib_ab_day_names_de_DE,
+ 9,
+ 10
);
/***** LOCALE END de_LU *****/
@@ -1967,7 +2113,9 @@ MY_LOCALE my_locale_en_AU
&my_locale_typelib_month_names_en_US,
&my_locale_typelib_ab_month_names_en_US,
&my_locale_typelib_day_names_en_US,
- &my_locale_typelib_ab_day_names_en_US
+ &my_locale_typelib_ab_day_names_en_US,
+ 9,
+ 9
);
/***** LOCALE END en_AU *****/
@@ -1981,7 +2129,9 @@ MY_LOCALE my_locale_en_CA
&my_locale_typelib_month_names_en_US,
&my_locale_typelib_ab_month_names_en_US,
&my_locale_typelib_day_names_en_US,
- &my_locale_typelib_ab_day_names_en_US
+ &my_locale_typelib_ab_day_names_en_US,
+ 9,
+ 9
);
/***** LOCALE END en_CA *****/
@@ -1995,7 +2145,9 @@ MY_LOCALE my_locale_en_GB
&my_locale_typelib_month_names_en_US,
&my_locale_typelib_ab_month_names_en_US,
&my_locale_typelib_day_names_en_US,
- &my_locale_typelib_ab_day_names_en_US
+ &my_locale_typelib_ab_day_names_en_US,
+ 9,
+ 9
);
/***** LOCALE END en_GB *****/
@@ -2009,7 +2161,9 @@ MY_LOCALE my_locale_en_IN
&my_locale_typelib_month_names_en_US,
&my_locale_typelib_ab_month_names_en_US,
&my_locale_typelib_day_names_en_US,
- &my_locale_typelib_ab_day_names_en_US
+ &my_locale_typelib_ab_day_names_en_US,
+ 9,
+ 9
);
/***** LOCALE END en_IN *****/
@@ -2023,7 +2177,9 @@ MY_LOCALE my_locale_en_NZ
&my_locale_typelib_month_names_en_US,
&my_locale_typelib_ab_month_names_en_US,
&my_locale_typelib_day_names_en_US,
- &my_locale_typelib_ab_day_names_en_US
+ &my_locale_typelib_ab_day_names_en_US,
+ 9,
+ 9
);
/***** LOCALE END en_NZ *****/
@@ -2037,7 +2193,9 @@ MY_LOCALE my_locale_en_PH
&my_locale_typelib_month_names_en_US,
&my_locale_typelib_ab_month_names_en_US,
&my_locale_typelib_day_names_en_US,
- &my_locale_typelib_ab_day_names_en_US
+ &my_locale_typelib_ab_day_names_en_US,
+ 9,
+ 9
);
/***** LOCALE END en_PH *****/
@@ -2051,7 +2209,9 @@ MY_LOCALE my_locale_en_ZA
&my_locale_typelib_month_names_en_US,
&my_locale_typelib_ab_month_names_en_US,
&my_locale_typelib_day_names_en_US,
- &my_locale_typelib_ab_day_names_en_US
+ &my_locale_typelib_ab_day_names_en_US,
+ 9,
+ 9
);
/***** LOCALE END en_ZA *****/
@@ -2065,7 +2225,9 @@ MY_LOCALE my_locale_en_ZW
&my_locale_typelib_month_names_en_US,
&my_locale_typelib_ab_month_names_en_US,
&my_locale_typelib_day_names_en_US,
- &my_locale_typelib_ab_day_names_en_US
+ &my_locale_typelib_ab_day_names_en_US,
+ 9,
+ 9
);
/***** LOCALE END en_ZW *****/
@@ -2079,7 +2241,9 @@ MY_LOCALE my_locale_es_AR
&my_locale_typelib_month_names_es_ES,
&my_locale_typelib_ab_month_names_es_ES,
&my_locale_typelib_day_names_es_ES,
- &my_locale_typelib_ab_day_names_es_ES
+ &my_locale_typelib_ab_day_names_es_ES,
+ 10,
+ 9
);
/***** LOCALE END es_AR *****/
@@ -2093,7 +2257,9 @@ MY_LOCALE my_locale_es_BO
&my_locale_typelib_month_names_es_ES,
&my_locale_typelib_ab_month_names_es_ES,
&my_locale_typelib_day_names_es_ES,
- &my_locale_typelib_ab_day_names_es_ES
+ &my_locale_typelib_ab_day_names_es_ES,
+ 10,
+ 9
);
/***** LOCALE END es_BO *****/
@@ -2107,7 +2273,9 @@ MY_LOCALE my_locale_es_CL
&my_locale_typelib_month_names_es_ES,
&my_locale_typelib_ab_month_names_es_ES,
&my_locale_typelib_day_names_es_ES,
- &my_locale_typelib_ab_day_names_es_ES
+ &my_locale_typelib_ab_day_names_es_ES,
+ 10,
+ 9
);
/***** LOCALE END es_CL *****/
@@ -2121,7 +2289,9 @@ MY_LOCALE my_locale_es_CO
&my_locale_typelib_month_names_es_ES,
&my_locale_typelib_ab_month_names_es_ES,
&my_locale_typelib_day_names_es_ES,
- &my_locale_typelib_ab_day_names_es_ES
+ &my_locale_typelib_ab_day_names_es_ES,
+ 10,
+ 9
);
/***** LOCALE END es_CO *****/
@@ -2135,7 +2305,9 @@ MY_LOCALE my_locale_es_CR
&my_locale_typelib_month_names_es_ES,
&my_locale_typelib_ab_month_names_es_ES,
&my_locale_typelib_day_names_es_ES,
- &my_locale_typelib_ab_day_names_es_ES
+ &my_locale_typelib_ab_day_names_es_ES,
+ 10,
+ 9
);
/***** LOCALE END es_CR *****/
@@ -2149,7 +2321,9 @@ MY_LOCALE my_locale_es_DO
&my_locale_typelib_month_names_es_ES,
&my_locale_typelib_ab_month_names_es_ES,
&my_locale_typelib_day_names_es_ES,
- &my_locale_typelib_ab_day_names_es_ES
+ &my_locale_typelib_ab_day_names_es_ES,
+ 10,
+ 9
);
/***** LOCALE END es_DO *****/
@@ -2163,7 +2337,9 @@ MY_LOCALE my_locale_es_EC
&my_locale_typelib_month_names_es_ES,
&my_locale_typelib_ab_month_names_es_ES,
&my_locale_typelib_day_names_es_ES,
- &my_locale_typelib_ab_day_names_es_ES
+ &my_locale_typelib_ab_day_names_es_ES,
+ 10,
+ 9
);
/***** LOCALE END es_EC *****/
@@ -2177,7 +2353,9 @@ MY_LOCALE my_locale_es_GT
&my_locale_typelib_month_names_es_ES,
&my_locale_typelib_ab_month_names_es_ES,
&my_locale_typelib_day_names_es_ES,
- &my_locale_typelib_ab_day_names_es_ES
+ &my_locale_typelib_ab_day_names_es_ES,
+ 10,
+ 9
);
/***** LOCALE END es_GT *****/
@@ -2191,7 +2369,9 @@ MY_LOCALE my_locale_es_HN
&my_locale_typelib_month_names_es_ES,
&my_locale_typelib_ab_month_names_es_ES,
&my_locale_typelib_day_names_es_ES,
- &my_locale_typelib_ab_day_names_es_ES
+ &my_locale_typelib_ab_day_names_es_ES,
+ 10,
+ 9
);
/***** LOCALE END es_HN *****/
@@ -2205,7 +2385,9 @@ MY_LOCALE my_locale_es_MX
&my_locale_typelib_month_names_es_ES,
&my_locale_typelib_ab_month_names_es_ES,
&my_locale_typelib_day_names_es_ES,
- &my_locale_typelib_ab_day_names_es_ES
+ &my_locale_typelib_ab_day_names_es_ES,
+ 10,
+ 9
);
/***** LOCALE END es_MX *****/
@@ -2219,7 +2401,9 @@ MY_LOCALE my_locale_es_NI
&my_locale_typelib_month_names_es_ES,
&my_locale_typelib_ab_month_names_es_ES,
&my_locale_typelib_day_names_es_ES,
- &my_locale_typelib_ab_day_names_es_ES
+ &my_locale_typelib_ab_day_names_es_ES,
+ 10,
+ 9
);
/***** LOCALE END es_NI *****/
@@ -2233,7 +2417,9 @@ MY_LOCALE my_locale_es_PA
&my_locale_typelib_month_names_es_ES,
&my_locale_typelib_ab_month_names_es_ES,
&my_locale_typelib_day_names_es_ES,
- &my_locale_typelib_ab_day_names_es_ES
+ &my_locale_typelib_ab_day_names_es_ES,
+ 10,
+ 9
);
/***** LOCALE END es_PA *****/
@@ -2247,7 +2433,9 @@ MY_LOCALE my_locale_es_PE
&my_locale_typelib_month_names_es_ES,
&my_locale_typelib_ab_month_names_es_ES,
&my_locale_typelib_day_names_es_ES,
- &my_locale_typelib_ab_day_names_es_ES
+ &my_locale_typelib_ab_day_names_es_ES,
+ 10,
+ 9
);
/***** LOCALE END es_PE *****/
@@ -2261,7 +2449,9 @@ MY_LOCALE my_locale_es_PR
&my_locale_typelib_month_names_es_ES,
&my_locale_typelib_ab_month_names_es_ES,
&my_locale_typelib_day_names_es_ES,
- &my_locale_typelib_ab_day_names_es_ES
+ &my_locale_typelib_ab_day_names_es_ES,
+ 10,
+ 9
);
/***** LOCALE END es_PR *****/
@@ -2275,7 +2465,9 @@ MY_LOCALE my_locale_es_PY
&my_locale_typelib_month_names_es_ES,
&my_locale_typelib_ab_month_names_es_ES,
&my_locale_typelib_day_names_es_ES,
- &my_locale_typelib_ab_day_names_es_ES
+ &my_locale_typelib_ab_day_names_es_ES,
+ 10,
+ 9
);
/***** LOCALE END es_PY *****/
@@ -2289,7 +2481,9 @@ MY_LOCALE my_locale_es_SV
&my_locale_typelib_month_names_es_ES,
&my_locale_typelib_ab_month_names_es_ES,
&my_locale_typelib_day_names_es_ES,
- &my_locale_typelib_ab_day_names_es_ES
+ &my_locale_typelib_ab_day_names_es_ES,
+ 10,
+ 9
);
/***** LOCALE END es_SV *****/
@@ -2303,7 +2497,9 @@ MY_LOCALE my_locale_es_US
&my_locale_typelib_month_names_es_ES,
&my_locale_typelib_ab_month_names_es_ES,
&my_locale_typelib_day_names_es_ES,
- &my_locale_typelib_ab_day_names_es_ES
+ &my_locale_typelib_ab_day_names_es_ES,
+ 10,
+ 9
);
/***** LOCALE END es_US *****/
@@ -2317,7 +2513,9 @@ MY_LOCALE my_locale_es_UY
&my_locale_typelib_month_names_es_ES,
&my_locale_typelib_ab_month_names_es_ES,
&my_locale_typelib_day_names_es_ES,
- &my_locale_typelib_ab_day_names_es_ES
+ &my_locale_typelib_ab_day_names_es_ES,
+ 10,
+ 9
);
/***** LOCALE END es_UY *****/
@@ -2331,7 +2529,9 @@ MY_LOCALE my_locale_es_VE
&my_locale_typelib_month_names_es_ES,
&my_locale_typelib_ab_month_names_es_ES,
&my_locale_typelib_day_names_es_ES,
- &my_locale_typelib_ab_day_names_es_ES
+ &my_locale_typelib_ab_day_names_es_ES,
+ 10,
+ 9
);
/***** LOCALE END es_VE *****/
@@ -2345,7 +2545,9 @@ MY_LOCALE my_locale_fr_BE
&my_locale_typelib_month_names_fr_FR,
&my_locale_typelib_ab_month_names_fr_FR,
&my_locale_typelib_day_names_fr_FR,
- &my_locale_typelib_ab_day_names_fr_FR
+ &my_locale_typelib_ab_day_names_fr_FR,
+ 9,
+ 8
);
/***** LOCALE END fr_BE *****/
@@ -2359,7 +2561,9 @@ MY_LOCALE my_locale_fr_CA
&my_locale_typelib_month_names_fr_FR,
&my_locale_typelib_ab_month_names_fr_FR,
&my_locale_typelib_day_names_fr_FR,
- &my_locale_typelib_ab_day_names_fr_FR
+ &my_locale_typelib_ab_day_names_fr_FR,
+ 9,
+ 8
);
/***** LOCALE END fr_CA *****/
@@ -2373,7 +2577,9 @@ MY_LOCALE my_locale_fr_CH
&my_locale_typelib_month_names_fr_FR,
&my_locale_typelib_ab_month_names_fr_FR,
&my_locale_typelib_day_names_fr_FR,
- &my_locale_typelib_ab_day_names_fr_FR
+ &my_locale_typelib_ab_day_names_fr_FR,
+ 9,
+ 8
);
/***** LOCALE END fr_CH *****/
@@ -2387,7 +2593,9 @@ MY_LOCALE my_locale_fr_LU
&my_locale_typelib_month_names_fr_FR,
&my_locale_typelib_ab_month_names_fr_FR,
&my_locale_typelib_day_names_fr_FR,
- &my_locale_typelib_ab_day_names_fr_FR
+ &my_locale_typelib_ab_day_names_fr_FR,
+ 9,
+ 8
);
/***** LOCALE END fr_LU *****/
@@ -2401,7 +2609,9 @@ MY_LOCALE my_locale_it_IT
&my_locale_typelib_month_names_it_CH,
&my_locale_typelib_ab_month_names_it_CH,
&my_locale_typelib_day_names_it_CH,
- &my_locale_typelib_ab_day_names_it_CH
+ &my_locale_typelib_ab_day_names_it_CH,
+ 9,
+ 9
);
/***** LOCALE END it_IT *****/
@@ -2415,7 +2625,9 @@ MY_LOCALE my_locale_nl_BE
&my_locale_typelib_month_names_nl_NL,
&my_locale_typelib_ab_month_names_nl_NL,
&my_locale_typelib_day_names_nl_NL,
- &my_locale_typelib_ab_day_names_nl_NL
+ &my_locale_typelib_ab_day_names_nl_NL,
+ 9,
+ 9
);
/***** LOCALE END nl_BE *****/
@@ -2429,7 +2641,9 @@ MY_LOCALE my_locale_no_NO
&my_locale_typelib_month_names_nb_NO,
&my_locale_typelib_ab_month_names_nb_NO,
&my_locale_typelib_day_names_nb_NO,
- &my_locale_typelib_ab_day_names_nb_NO
+ &my_locale_typelib_ab_day_names_nb_NO,
+ 9,
+ 7
);
/***** LOCALE END no_NO *****/
@@ -2443,7 +2657,9 @@ MY_LOCALE my_locale_sv_FI
&my_locale_typelib_month_names_sv_SE,
&my_locale_typelib_ab_month_names_sv_SE,
&my_locale_typelib_day_names_sv_SE,
- &my_locale_typelib_ab_day_names_sv_SE
+ &my_locale_typelib_ab_day_names_sv_SE,
+ 9,
+ 7
);
/***** LOCALE END sv_FI *****/
@@ -2457,7 +2673,9 @@ MY_LOCALE my_locale_zh_HK
&my_locale_typelib_month_names_zh_CN,
&my_locale_typelib_ab_month_names_zh_CN,
&my_locale_typelib_day_names_zh_CN,
- &my_locale_typelib_ab_day_names_zh_CN
+ &my_locale_typelib_ab_day_names_zh_CN,
+ 3,
+ 3
);
/***** LOCALE END zh_HK *****/
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 91c5cacc4d0..dafe4baa9e5 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -2333,8 +2333,9 @@ void log_slow_statement(THD *thd)
{
thd->proc_info="logging slow query";
- if ((ulong) (thd->start_time - thd->time_after_lock) >
- thd->variables.long_query_time ||
+ if ((thd->start_time > thd->time_after_lock &&
+ (ulong) (thd->start_time - thd->time_after_lock) >
+ thd->variables.long_query_time) ||
(thd->server_status &
(SERVER_QUERY_NO_INDEX_USED | SERVER_QUERY_NO_GOOD_INDEX_USED)) &&
opt_log_queries_not_using_indexes &&
@@ -2583,6 +2584,10 @@ mysql_execute_command(THD *thd)
TABLE_LIST *all_tables;
/* most outer SELECT_LEX_UNIT of query */
SELECT_LEX_UNIT *unit= &lex->unit;
+#ifdef HAVE_REPLICATION
+ /* have table map for update for multi-update statement (BUG#37051) */
+ bool have_table_map_for_update= FALSE;
+#endif
/* Saved variable value */
DBUG_ENTER("mysql_execute_command");
thd->net.no_send_error= 0;
@@ -2662,6 +2667,48 @@ mysql_execute_command(THD *thd)
// force searching in slave.cc:tables_ok()
all_tables->updating= 1;
}
+
+ /*
+ For fix of BUG#37051, the master stores the table map for update
+ in the Query_log_event, and the value is assigned to
+ thd->variables.table_map_for_update before executing the update
+ query.
+
+ If thd->variables.table_map_for_update is set, then we are
+ replicating from a new master, we can use this value to apply
+ filter rules without opening all the tables. However If
+ thd->variables.table_map_for_update is not set, then we are
+ replicating from an old master, so we just skip this and
+ continue with the old method. And of course, the bug would still
+ exist for old masters.
+ */
+ if (lex->sql_command == SQLCOM_UPDATE_MULTI &&
+ thd->table_map_for_update)
+ {
+ have_table_map_for_update= TRUE;
+ table_map table_map_for_update= thd->table_map_for_update;
+ uint nr= 0;
+ TABLE_LIST *table;
+ for (table=all_tables; table; table=table->next_global, nr++)
+ {
+ if (table_map_for_update & ((table_map)1 << nr))
+ table->updating= TRUE;
+ else
+ table->updating= FALSE;
+ }
+
+ if (all_tables_not_ok(thd, all_tables))
+ {
+ /* we warn the slave SQL thread */
+ my_message(ER_SLAVE_IGNORED_TABLE, ER(ER_SLAVE_IGNORED_TABLE), MYF(0));
+ if (thd->one_shot_set)
+ reset_one_shot_variables(thd);
+ DBUG_RETURN(0);
+ }
+
+ for (table=all_tables; table; table=table->next_global)
+ table->updating= TRUE;
+ }
/*
Check if statment should be skipped because of slave filtering
@@ -3607,7 +3654,7 @@ end_with_restore_list:
#ifdef HAVE_REPLICATION
/* Check slave filtering rules */
- if (unlikely(thd->slave_thread))
+ if (unlikely(thd->slave_thread && !have_table_map_for_update))
{
if (all_tables_not_ok(thd, all_tables))
{
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 428d1709f94..a820e9966dc 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -78,7 +78,6 @@ static store_key *get_store_key(THD *thd,
KEYUSE *keyuse, table_map used_tables,
KEY_PART_INFO *key_part, char *key_buff,
uint maybe_null);
-static bool make_simple_join(JOIN *join,TABLE *tmp_table);
static void make_outerjoin_info(JOIN *join);
static bool make_join_select(JOIN *join,SQL_SELECT *select,COND *item);
static void make_join_readinfo(JOIN *join, ulonglong options);
@@ -100,7 +99,7 @@ static COND* substitute_for_best_equal_field(COND *cond,
void *table_join_idx);
static COND *simplify_joins(JOIN *join, List<TABLE_LIST> *join_list,
COND *conds, bool top);
-static bool check_interleaving_with_nj(JOIN_TAB *last, JOIN_TAB *next);
+static bool check_interleaving_with_nj(JOIN_TAB *next);
static void restore_prev_nj_state(JOIN_TAB *last);
static void reset_nj_counters(List<TABLE_LIST> *join_list);
static uint build_bitmap_for_nested_joins(List<TABLE_LIST> *join_list,
@@ -390,11 +389,21 @@ inline int setup_without_group(THD *thd, Item **ref_pointer_array,
{
int res;
nesting_map save_allow_sum_func=thd->lex->allow_sum_func ;
+ /*
+ Need to save the value, so we can turn off only the new NON_AGG_FIELD
+ additions coming from the WHERE
+ */
+ uint8 saved_flag= thd->lex->current_select->full_group_by_flag;
DBUG_ENTER("setup_without_group");
thd->lex->allow_sum_func&= ~(1 << thd->lex->current_select->nest_level);
res= setup_conds(thd, tables, leaves, conds);
+ /* it's not wrong to have non-aggregated columns in a WHERE */
+ if (thd->variables.sql_mode & MODE_ONLY_FULL_GROUP_BY)
+ thd->lex->current_select->full_group_by_flag= saved_flag |
+ (thd->lex->current_select->full_group_by_flag & ~NON_AGG_FIELD_USED);
+
thd->lex->allow_sum_func|= 1 << thd->lex->current_select->nest_level;
res= res || setup_order(thd, ref_pointer_array, tables, fields, all_fields,
order);
@@ -1589,14 +1598,22 @@ JOIN::exec()
(zero_result_cause?zero_result_cause:"No tables used"));
else
{
- result->send_fields(*columns_list,
- Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF);
+ if (result->send_fields(*columns_list,
+ Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
+ {
+ DBUG_VOID_RETURN;
+ }
/*
We have to test for 'conds' here as the WHERE may not be constant
even if we don't have any tables for prepared statements or if
conds uses something like 'rand()'.
+ If the HAVING clause is either impossible or always true, then
+ JOIN::having is set to NULL by optimize_cond.
+ In this case JOIN::exec must check for JOIN::having_value, in the
+ same way it checks for JOIN::cond_value.
*/
if (cond_value != Item::COND_FALSE &&
+ having_value != Item::COND_FALSE &&
(!conds || conds->val_int()) &&
(!having || having->val_int()))
{
@@ -1791,7 +1808,7 @@ JOIN::exec()
/* Free first data from old join */
curr_join->join_free();
- if (make_simple_join(curr_join, curr_tmp_table))
+ if (curr_join->make_simple_join(this, curr_tmp_table))
DBUG_VOID_RETURN;
calc_group_buffer(curr_join, group_list);
count_field_types(select_lex, &curr_join->tmp_table_param,
@@ -1911,7 +1928,7 @@ JOIN::exec()
curr_join->select_distinct=0;
}
curr_tmp_table->reginfo.lock_type= TL_UNLOCK;
- if (make_simple_join(curr_join, curr_tmp_table))
+ if (curr_join->make_simple_join(this, curr_tmp_table))
DBUG_VOID_RETURN;
calc_group_buffer(curr_join, curr_join->group_list);
count_field_types(select_lex, &curr_join->tmp_table_param,
@@ -2356,11 +2373,12 @@ typedef struct st_sargable_param
*/
static bool
-make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds,
+make_join_statistics(JOIN *join, TABLE_LIST *tables_arg, COND *conds,
DYNAMIC_ARRAY *keyuse_array)
{
int error;
TABLE *table;
+ TABLE_LIST *tables= tables_arg;
uint i,table_count,const_count,key;
table_map found_const_table_map, all_table_map, found_ref, refs;
key_map const_ref, eq_part;
@@ -2398,10 +2416,10 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds,
table_vector[i]=s->table=table=tables->table;
table->pos_in_table_list= tables;
error= table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
- if(error)
+ if (error)
{
- table->file->print_error(error, MYF(0));
- DBUG_RETURN(1);
+ table->file->print_error(error, MYF(0));
+ goto error;
}
table->quick_keys.clear_all();
table->reginfo.join_tab=s;
@@ -2476,7 +2494,7 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds,
if (s->dependent & table->map)
s->dependent |= table->reginfo.join_tab->dependent;
}
- if (s->dependent)
+ if (outer_join & s->table->map)
s->table->maybe_null= 1;
}
/* Catch illegal cross references for outer joins */
@@ -2486,7 +2504,7 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds,
{
join->tables=0; // Don't use join->table
my_message(ER_WRONG_OUTER_JOIN, ER(ER_WRONG_OUTER_JOIN), MYF(0));
- DBUG_RETURN(1);
+ goto error;
}
s->key_dependent= s->dependent;
}
@@ -2496,7 +2514,7 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds,
if (update_ref_and_keys(join->thd, keyuse_array, stat, join->tables,
conds, join->cond_equal,
~outer_join, join->select_lex, &sargables))
- DBUG_RETURN(1);
+ goto error;
/* Read tables with 0 or 1 rows (system tables) */
join->const_table_map= 0;
@@ -2512,7 +2530,7 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds,
if ((tmp=join_read_const_table(s, p_pos)))
{
if (tmp > 0)
- DBUG_RETURN(1); // Fatal error
+ goto error; // Fatal error
}
else
found_const_table_map|= s->table->map;
@@ -2584,7 +2602,7 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds,
if ((tmp= join_read_const_table(s, join->positions+const_count-1)))
{
if (tmp > 0)
- DBUG_RETURN(1); // Fatal error
+ goto error; // Fatal error
}
else
found_const_table_map|= table->map;
@@ -2633,12 +2651,12 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds,
set_position(join,const_count++,s,start_keyuse);
if (create_ref_for_key(join, s, start_keyuse,
found_const_table_map))
- DBUG_RETURN(1);
+ goto error;
if ((tmp=join_read_const_table(s,
join->positions+const_count-1)))
{
if (tmp > 0)
- DBUG_RETURN(1); // Fatal error
+ goto error; // Fatal error
}
else
found_const_table_map|= table->map;
@@ -2715,7 +2733,7 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds,
*s->on_expr_ref ? *s->on_expr_ref : conds,
1, &error);
if (!select)
- DBUG_RETURN(1);
+ goto error;
records= get_quick_record_count(join->thd, select, s->table,
&s->const_keys, join->row_limit);
s->quick=select->quick;
@@ -2761,7 +2779,7 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds,
{
optimize_keyuse(join, keyuse_array);
if (choose_plan(join, all_table_map & ~join->const_table_map))
- DBUG_RETURN(TRUE);
+ goto error;
}
else
{
@@ -2771,6 +2789,17 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds,
}
/* Generate an execution plan from the found optimal join order. */
DBUG_RETURN(join->thd->killed || get_best_combination(join));
+
+error:
+ /*
+ Need to clean up join_tab from TABLEs in case of error.
+ They won't get cleaned up by JOIN::cleanup() because JOIN::join_tab
+ may not be assigned yet by this function (which is building join_tab).
+ Dangling TABLE::reginfo.join_tab may cause part_of_refkey to choke.
+ */
+ for (tables= tables_arg; tables; tables= tables->next_leaf)
+ tables->table->reginfo.join_tab= NULL;
+ DBUG_RETURN (1);
}
@@ -4705,6 +4734,18 @@ greedy_search(JOIN *join,
*/
join->positions[idx]= best_pos;
+ /*
+ Update the interleaving state after extending the current partial plan
+ with a new table.
+ We are doing this here because best_extension_by_limited_search reverts
+ the interleaving state to the one of the non-extended partial plan
+ on exit.
+ */
+ IF_DBUG(bool is_interleave_error= )
+ check_interleaving_with_nj (best_table);
+ /* This has been already checked by best_extension_by_limited_search */
+ DBUG_ASSERT(!is_interleave_error);
+
/* find the position of 'best_table' in 'join->best_ref' */
best_idx= idx;
JOIN_TAB *pos= join->best_ref[best_idx];
@@ -4722,7 +4763,7 @@ greedy_search(JOIN *join,
--size_remain;
++idx;
- DBUG_EXECUTE("opt", print_plan(join, join->tables,
+ DBUG_EXECUTE("opt", print_plan(join, idx,
record_count, read_time, read_time,
"extended"););
} while (TRUE);
@@ -4873,7 +4914,7 @@ best_extension_by_limited_search(JOIN *join,
table_map real_table_bit= s->table->map;
if ((remaining_tables & real_table_bit) &&
!(remaining_tables & s->dependent) &&
- (!idx || !check_interleaving_with_nj(join->positions[idx-1].table, s)))
+ (!idx || !check_interleaving_with_nj(s)))
{
double current_record_count, current_read_time;
@@ -5018,7 +5059,7 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count,
{
table_map real_table_bit=s->table->map;
if ((rest_tables & real_table_bit) && !(rest_tables & s->dependent) &&
- (!idx|| !check_interleaving_with_nj(join->positions[idx-1].table, s)))
+ (!idx|| !check_interleaving_with_nj(s)))
{
double records, best;
best_access_path(join, s, thd, rest_tables, idx, record_count,
@@ -5401,48 +5442,42 @@ store_val_in_field(Field *field, Item *item, enum_check_fields check_flag)
}
-static bool
-make_simple_join(JOIN *join,TABLE *tmp_table)
+/**
+ @details Initialize a JOIN as a query execution plan
+ that accesses a single table via a table scan.
+
+ @param parent contains JOIN_TAB and TABLE object buffers for this join
+ @param tmp_table temporary table
+
+ @retval FALSE success
+ @retval TRUE error occurred
+*/
+bool
+JOIN::make_simple_join(JOIN *parent, TABLE *tmp_table)
{
- TABLE **tableptr;
- JOIN_TAB *join_tab;
- DBUG_ENTER("make_simple_join");
+ DBUG_ENTER("JOIN::make_simple_join");
/*
Reuse TABLE * and JOIN_TAB if already allocated by a previous call
to this function through JOIN::exec (may happen for sub-queries).
*/
- if (!join->table_reexec)
- {
- if (!(join->table_reexec= (TABLE**) join->thd->alloc(sizeof(TABLE*))))
- DBUG_RETURN(TRUE); /* purecov: inspected */
- if (join->tmp_join)
- join->tmp_join->table_reexec= join->table_reexec;
- }
- if (!join->join_tab_reexec)
- {
- if (!(join->join_tab_reexec=
- (JOIN_TAB*) join->thd->alloc(sizeof(JOIN_TAB))))
- DBUG_RETURN(TRUE); /* purecov: inspected */
- if (join->tmp_join)
- join->tmp_join->join_tab_reexec= join->join_tab_reexec;
- }
- tableptr= join->table_reexec;
- join_tab= join->join_tab_reexec;
-
- join->join_tab=join_tab;
- join->table=tableptr; tableptr[0]=tmp_table;
- join->tables=1;
- join->const_tables=0;
- join->const_table_map=0;
- join->tmp_table_param.field_count= join->tmp_table_param.sum_func_count=
- join->tmp_table_param.func_count=0;
- join->tmp_table_param.copy_field=join->tmp_table_param.copy_field_end=0;
- join->first_record=join->sort_and_group=0;
- join->send_records=(ha_rows) 0;
- join->group=0;
- join->row_limit=join->unit->select_limit_cnt;
- join->do_send_rows = (join->row_limit) ? 1 : 0;
+ if (!parent->join_tab_reexec &&
+ !(parent->join_tab_reexec= (JOIN_TAB*) thd->alloc(sizeof(JOIN_TAB))))
+ DBUG_RETURN(TRUE); /* purecov: inspected */
+
+ join_tab= parent->join_tab_reexec;
+ table= &parent->table_reexec[0]; parent->table_reexec[0]= tmp_table;
+ tables= 1;
+ const_tables= 0;
+ const_table_map= 0;
+ tmp_table_param.field_count= tmp_table_param.sum_func_count=
+ tmp_table_param.func_count= 0;
+ tmp_table_param.copy_field= tmp_table_param.copy_field_end=0;
+ first_record= sort_and_group=0;
+ send_records= (ha_rows) 0;
+ group= 0;
+ row_limit= unit->select_limit_cnt;
+ do_send_rows= row_limit ? 1 : 0;
join_tab->cache.buff=0; /* No caching */
join_tab->table=tmp_table;
@@ -5459,7 +5494,7 @@ make_simple_join(JOIN *join,TABLE *tmp_table)
join_tab->ref.key = -1;
join_tab->not_used_in_distinct=0;
join_tab->read_first_record= join_init_read_record;
- join_tab->join=join;
+ join_tab->join= this;
join_tab->ref.key_parts= 0;
bzero((char*) &join_tab->read_record,sizeof(join_tab->read_record));
tmp_table->status=0;
@@ -8390,9 +8425,6 @@ static void reset_nj_counters(List<TABLE_LIST> *join_list)
SYNOPSIS
check_interleaving_with_nj()
- join Join being processed
- last_tab Last table in current partial join order (this function is
- not called for empty partial join orders)
next_tab Table we're going to extend the current partial join with
DESCRIPTION
@@ -8477,10 +8509,10 @@ static void reset_nj_counters(List<TABLE_LIST> *join_list)
TRUE Requested join order extension not allowed.
*/
-static bool check_interleaving_with_nj(JOIN_TAB *last_tab, JOIN_TAB *next_tab)
+static bool check_interleaving_with_nj(JOIN_TAB *next_tab)
{
TABLE_LIST *next_emb= next_tab->table->pos_in_table_list->embedding;
- JOIN *join= last_tab->join;
+ JOIN *join= next_tab->join;
if (join->cur_embedding_map & ~next_tab->embedding_map)
{
@@ -9434,11 +9466,11 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
}
if (type == Item::SUM_FUNC_ITEM && !group && !save_sum_fields)
{ /* Can't calc group yet */
- ((Item_sum*) item)->result_field=0;
- for (i=0 ; i < ((Item_sum*) item)->arg_count ; i++)
+ Item_sum *sum_item= (Item_sum *) item;
+ sum_item->result_field=0;
+ for (i=0 ; i < sum_item->get_arg_count() ; i++)
{
- Item **argp= ((Item_sum*) item)->args + i;
- Item *arg= *argp;
+ Item *arg= sum_item->get_arg(i);
if (!arg->const_item())
{
uint field_index= (uint) (reg_field - table->field);
@@ -9468,7 +9500,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
string_total_length+= new_field->pack_length();
}
thd->mem_root= mem_root_save;
- thd->change_item_tree(argp, new Item_field(new_field));
+ arg= sum_item->set_arg(i, thd, new Item_field(new_field));
thd->mem_root= &table->mem_root;
if (!(new_field->flags & NOT_NULL_FLAG))
{
@@ -9477,7 +9509,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
new_field->maybe_null() is still false, it will be
changed below. But we have to setup Item_field correctly
*/
- (*argp)->maybe_null=1;
+ arg->maybe_null=1;
}
new_field->query_id= thd->query_id;
}
@@ -13223,6 +13255,7 @@ join_init_cache(THD *thd,JOIN_TAB *tables,uint table_count)
length=0;
for (i=0 ; i < table_count ; i++)
{
+ bool have_bit_fields= FALSE;
uint null_fields=0,used_fields;
Field **f_ptr,*field;
@@ -13237,13 +13270,16 @@ join_init_cache(THD *thd,JOIN_TAB *tables,uint table_count)
length+=field->fill_cache_field(copy);
if (copy->blob_field)
(*blob_ptr++)=copy;
- if (field->maybe_null())
+ if (field->real_maybe_null())
null_fields++;
+ if (field->type() == MYSQL_TYPE_BIT &&
+ ((Field_bit*)field)->bit_len)
+ have_bit_fields= TRUE;
copy++;
}
}
/* Copy null bits from table */
- if (null_fields && tables[i].table->s->null_fields)
+ if (null_fields || have_bit_fields)
{ /* must copy null bits */
copy->str=(char*) tables[i].table->null_flags;
copy->length= tables[i].table->s->null_bytes;
@@ -13908,9 +13944,9 @@ count_field_types(SELECT_LEX *select_lex, TMP_TABLE_PARAM *param,
param->quick_group=0; // UDF SUM function
param->sum_func_count++;
- for (uint i=0 ; i < sum_item->arg_count ; i++)
+ for (uint i=0 ; i < sum_item->get_arg_count() ; i++)
{
- if (sum_item->args[0]->real_item()->type() == Item::FIELD_ITEM)
+ if (sum_item->get_arg(i)->real_item()->type() == Item::FIELD_ITEM)
param->field_count++;
else
param->func_count++;
diff --git a/sql/sql_select.h b/sql/sql_select.h
index c2f0780f5be..75a905043d2 100644
--- a/sql/sql_select.h
+++ b/sql/sql_select.h
@@ -235,7 +235,11 @@ public:
fetching data from a cursor
*/
bool resume_nested_loop;
- table_map const_table_map,found_const_table_map,outer_join;
+ table_map const_table_map,found_const_table_map;
+ /*
+ Bitmap of all inner tables from outer joins
+ */
+ table_map outer_join;
ha_rows send_records,found_records,examined_rows,row_limit, select_limit;
/*
Used to fetch no more than given amount of rows per one
@@ -348,9 +352,12 @@ public:
cleared only at the end of the execution of the whole query and not caching
allocations that occur in repetition at execution time will result in
excessive memory usage.
+ Note: make_simple_join always creates an execution plan that accesses
+ a single table, thus it is sufficient to have a one-element array for
+ table_reexec.
*/
SORT_FIELD *sortorder; // make_unireg_sortorder()
- TABLE **table_reexec; // make_simple_join()
+ TABLE *table_reexec[1]; // make_simple_join()
JOIN_TAB *join_tab_reexec; // make_simple_join()
/* end of allocation caching storage */
@@ -380,7 +387,7 @@ public:
exec_tmp_table1= 0;
exec_tmp_table2= 0;
sortorder= 0;
- table_reexec= 0;
+ table_reexec[0]= 0;
join_tab_reexec= 0;
thd= thd_arg;
sum_funcs= sum_funcs2= 0;
@@ -472,6 +479,8 @@ public:
return (unit == &thd->lex->unit && (unit->fake_select_lex == 0 ||
select_lex == unit->fake_select_lex));
}
+private:
+ bool make_simple_join(JOIN *join, TABLE *tmp_table);
};
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index 5a4772e9847..a3ccf770a3c 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -44,7 +44,7 @@ static void
append_algorithm(TABLE_LIST *table, String *buff);
static int
view_store_create_info(THD *thd, TABLE_LIST *table, String *buff);
-static bool schema_table_store_record(THD *thd, TABLE *table);
+bool schema_table_store_record(THD *thd, TABLE *table);
/***************************************************************************
@@ -106,7 +106,7 @@ static struct show_privileges_st sys_privileges[]=
{"Alter", "Tables", "To alter the table"},
{"Alter routine", "Functions,Procedures", "To alter or drop stored functions/procedures"},
{"Create", "Databases,Tables,Indexes", "To create new databases and tables"},
- {"Create routine","Functions,Procedures","To use CREATE FUNCTION/PROCEDURE"},
+ {"Create routine","Databases","To use CREATE FUNCTION/PROCEDURE"},
{"Create temporary tables","Databases","To use CREATE TEMPORARY TABLE"},
{"Create view", "Tables", "To create new views"},
{"Create user", "Server Admin", "To create new users"},
@@ -287,11 +287,18 @@ find_files(THD *thd, List<char> *files, const char *db,
#ifndef NO_EMBEDDED_ACCESS_CHECKS
uint col_access=thd->col_access;
#endif
+ uint wild_length= 0;
TABLE_LIST table_list;
DBUG_ENTER("find_files");
- if (wild && !wild[0])
- wild=0;
+ if (wild)
+ {
+ if (!wild[0])
+ wild= 0;
+ else
+ wild_length= strlen(wild);
+ }
+
bzero((char*) &table_list,sizeof(table_list));
@@ -340,8 +347,11 @@ find_files(THD *thd, List<char> *files, const char *db,
{
if (lower_case_table_names)
{
- if (wild_case_compare(files_charset_info, file->name, wild))
- continue;
+ if (my_wildcmp(files_charset_info,
+ file->name, file->name + strlen(file->name),
+ wild, wild + wild_length,
+ wild_prefix, wild_one,wild_many))
+ continue;
}
else if (wild_compare(file->name,wild,0))
continue;
@@ -798,7 +808,7 @@ static bool get_field_default_value(THD *thd, TABLE *table,
{
bool has_default;
bool has_now_default;
-
+ enum enum_field_types field_type= field->type();
/*
We are using CURRENT_TIMESTAMP instead of NOW because it is
more standard
@@ -806,7 +816,7 @@ static bool get_field_default_value(THD *thd, TABLE *table,
has_now_default= table->timestamp_field == field &&
field->unireg_check != Field::TIMESTAMP_UN_FIELD;
- has_default= (field->type() != FIELD_TYPE_BLOB &&
+ has_default= (field_type != FIELD_TYPE_BLOB &&
!(field->flags & NO_DEFAULT_VALUE_FLAG) &&
field->unireg_check != Field::NEXT_NUMBER &&
!((thd->variables.sql_mode & (MODE_MYSQL323 | MODE_MYSQL40))
@@ -821,7 +831,19 @@ static bool get_field_default_value(THD *thd, TABLE *table,
{ // Not null by default
char tmp[MAX_FIELD_WIDTH];
String type(tmp, sizeof(tmp), field->charset());
- field->val_str(&type);
+ if (field_type == MYSQL_TYPE_BIT)
+ {
+ longlong dec= field->val_int();
+ char *ptr= longlong2str(dec, tmp + 2, 2);
+ uint32 length= (uint32) (ptr - tmp);
+ tmp[0]= 'b';
+ tmp[1]= '\'';
+ tmp[length]= '\'';
+ type.length(length + 1);
+ quoted= 0;
+ }
+ else
+ field->val_str(&type);
if (type.length())
{
String def_val;
@@ -1210,21 +1232,25 @@ void append_definer(THD *thd, String *buffer, const LEX_STRING *definer_user,
static int
view_store_create_info(THD *thd, TABLE_LIST *table, String *buff)
{
+ my_bool compact_view_name= TRUE;
my_bool foreign_db_mode= (thd->variables.sql_mode & (MODE_POSTGRESQL |
MODE_ORACLE |
MODE_MSSQL |
MODE_DB2 |
MODE_MAXDB |
MODE_ANSI)) != 0;
- /*
- Compact output format for view can be used
- - if user has db of this view as current db
- - if this view only references table inside it's own db
- */
+
if (!thd->db || strcmp(thd->db, table->view_db.str))
- table->compact_view_format= FALSE;
+ /*
+ print compact view name if the view belongs to the current database
+ */
+ compact_view_name= table->compact_view_format= FALSE;
else
{
+ /*
+ Compact output format for view body can be used
+ if this view only references table inside it's own db
+ */
TABLE_LIST *tbl;
table->compact_view_format= TRUE;
for (tbl= thd->lex->query_tables;
@@ -1245,7 +1271,7 @@ view_store_create_info(THD *thd, TABLE_LIST *table, String *buff)
view_store_options(thd, table, buff);
}
buff->append(STRING_WITH_LEN("VIEW "));
- if (!table->compact_view_format)
+ if (!compact_view_name)
{
append_identifier(thd, buff, table->view_db.str, table->view_db.length);
buff->append('.');
@@ -1441,6 +1467,7 @@ static bool show_status_array(THD *thd, const char *wild,
char name_buffer[80];
int len;
LEX_STRING null_lex_str;
+ CHARSET_INFO *charset= system_charset_info;
DBUG_ENTER("show_status_array");
null_lex_str.str= 0; // For sys_var->value_ptr()
@@ -1469,9 +1496,10 @@ static bool show_status_array(THD *thd, const char *wild,
long nr;
if (show_type == SHOW_SYS)
{
- show_type= ((sys_var*) value)->show_type();
- value= (char*) ((sys_var*) value)->value_ptr(thd, value_type,
- &null_lex_str);
+ sys_var *var= ((sys_var *) value);
+ show_type= var->show_type();
+ value= (char*) var->value_ptr(thd, value_type, &null_lex_str);
+ charset= var->charset(thd);
}
pos= end= buff;
@@ -1520,6 +1548,9 @@ static bool show_status_array(THD *thd, const char *wild,
nr= (long) (thd->query_start() - server_start_time);
end= int10_to_str(nr, buff, 10);
break;
+ case SHOW_QUERIES:
+ end= int10_to_str((long) thd->query_id, buff, 10);
+ break;
#ifdef HAVE_REPLICATION
case SHOW_RPL_STATUS:
end= strmov(buff, rpl_status_type[(int)rpl_status]);
@@ -1794,7 +1825,7 @@ static bool show_status_array(THD *thd, const char *wild,
restore_record(table, s->default_values);
table->field[0]->store(name_buffer, strlen(name_buffer),
system_charset_info);
- table->field[1]->store(pos, (uint32) (end - pos), system_charset_info);
+ table->field[1]->store(pos, (uint32) (end - pos), charset);
if (schema_table_store_record(thd, table))
DBUG_RETURN(TRUE);
}
@@ -1870,7 +1901,7 @@ typedef struct st_index_field_values
1 error
*/
-static bool schema_table_store_record(THD *thd, TABLE *table)
+bool schema_table_store_record(THD *thd, TABLE *table)
{
int error;
if ((error= table->file->write_row(table->record[0])))
diff --git a/sql/sql_string.cc b/sql/sql_string.cc
index 75e47dd0c8e..6bf624a73a2 100644
--- a/sql/sql_string.cc
+++ b/sql/sql_string.cc
@@ -71,25 +71,22 @@ bool String::realloc(uint32 alloc_length)
char *new_ptr;
if (alloced)
{
- if ((new_ptr= (char*) my_realloc(Ptr,len,MYF(MY_WME))))
- {
- Ptr=new_ptr;
- Alloced_length=len;
- }
- else
- return TRUE; // Signal error
+ if (!(new_ptr= (char*) my_realloc(Ptr,len,MYF(MY_WME))))
+ return TRUE; // Signal error
}
else if ((new_ptr= (char*) my_malloc(len,MYF(MY_WME))))
{
+ if (str_length > len - 1)
+ str_length= 0;
if (str_length) // Avoid bugs in memcpy on AIX
memcpy(new_ptr,Ptr,str_length);
new_ptr[str_length]=0;
- Ptr=new_ptr;
- Alloced_length=len;
alloced=1;
}
else
return TRUE; // Signal error
+ Ptr= new_ptr;
+ Alloced_length= len;
}
Ptr[alloc_length]=0; // This make other funcs shorter
return FALSE;
@@ -125,7 +122,7 @@ bool String::set(double num,uint decimals, CHARSET_INFO *cs)
str_charset=cs;
if (decimals >= NOT_FIXED_DEC)
{
- uint32 len= my_sprintf(buff,(buff, "%.14g",num));// Enough for a DATETIME
+ uint32 len= my_sprintf(buff,(buff, "%.15g",num));// Enough for a DATETIME
return copy(buff, len, &my_charset_latin1, cs, &dummy_errors);
}
#ifdef HAVE_FCONVERT
@@ -677,7 +674,7 @@ void String::qs_append(const char *str, uint32 len)
void String::qs_append(double d)
{
char *buff = Ptr + str_length;
- str_length+= my_sprintf(buff, (buff, "%.14g", d));
+ str_length+= my_sprintf(buff, (buff, "%.15g", d));
}
void String::qs_append(double *d)
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 1724513eb8f..ff7f874ffcb 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -1535,7 +1535,9 @@ static bool prepare_blob_field(THD *thd, create_field *sql_field)
if ((sql_field->flags & BLOB_FLAG) && sql_field->length)
{
- if (sql_field->sql_type == FIELD_TYPE_BLOB)
+ if (sql_field->sql_type == FIELD_TYPE_BLOB ||
+ sql_field->sql_type == FIELD_TYPE_TINY_BLOB ||
+ sql_field->sql_type == FIELD_TYPE_MEDIUM_BLOB)
{
/* The user has given a length to the blob column */
sql_field->sql_type= get_blob_type_from_length(sql_field->length);
@@ -2312,7 +2314,12 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
view_checksum(thd, table) == HA_ADMIN_WRONG_CHECKSUM)
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
ER_VIEW_CHECKSUM, ER(ER_VIEW_CHECKSUM));
- result_code= HA_ADMIN_CORRUPT;
+ if (thd->net.last_errno == ER_NO_SUCH_TABLE)
+ /* A missing table is just issued as a failed command */
+ result_code= HA_ADMIN_FAILED;
+ else
+ /* Default failure code is corrupt table */
+ result_code= HA_ADMIN_CORRUPT;
goto send_result;
}
@@ -2322,6 +2329,12 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
goto send_result;
}
+ if (table->schema_table)
+ {
+ result_code= HA_ADMIN_NOT_IMPLEMENTED;
+ goto send_result;
+ }
+
if ((table->table->db_stat & HA_READ_ONLY) && open_for_modify)
{
char buff[FN_REFLEN + MYSQL_ERRMSG_SIZE];
diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc
index bead50e1da8..d3b5289cd68 100644
--- a/sql/sql_trigger.cc
+++ b/sql/sql_trigger.cc
@@ -479,7 +479,7 @@ bool Table_triggers_list::create_trigger(THD *thd, TABLE_LIST *tables,
trigname.trigger_table.length= tables->table_name_length;
if (sql_create_definition_file(&dir, &trigname_file, &trigname_file_type,
- (gptr)&trigname, trigname_file_parameters, 0))
+ (gptr)&trigname, trigname_file_parameters))
return 1;
/*
@@ -569,7 +569,7 @@ bool Table_triggers_list::create_trigger(THD *thd, TABLE_LIST *tables,
/* Create trigger definition file. */
if (!sql_create_definition_file(&dir, &file, &triggers_file_type,
- (gptr)this, triggers_file_parameters, 0))
+ (gptr)this, triggers_file_parameters))
return 0;
err_with_cleanup:
@@ -656,7 +656,7 @@ static bool save_trigger_file(Table_triggers_list *triggers, const char *db,
file.str= file_buff;
return sql_create_definition_file(&dir, &file, &triggers_file_type,
- (gptr)triggers, triggers_file_parameters, 0);
+ (gptr)triggers, triggers_file_parameters);
}
@@ -1427,7 +1427,7 @@ Table_triggers_list::change_table_name_in_trignames(const char *db_name,
trigname.trigger_table= *new_table_name;
if (sql_create_definition_file(&dir, &trigname_file, &trigname_file_type,
- (gptr)&trigname, trigname_file_parameters, 0))
+ (gptr)&trigname, trigname_file_parameters))
return trigger;
}
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index eb4e9b7ed73..8a3f5bcdc26 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -775,7 +775,7 @@ reopen_tables:
DBUG_RETURN(TRUE);
}
- tables_for_update= get_table_map(fields);
+ thd->table_map_for_update= tables_for_update= get_table_map(fields);
/*
Setup timestamp handling and locking mode
@@ -1249,6 +1249,32 @@ multi_update::initialize_tables(JOIN *join)
}
}
+ /*
+ enable uncacheable flag if we update a view with check option
+ and check option has a subselect, otherwise, the check option
+ can be evaluated after the subselect was freed as independent
+ (See full_local in JOIN::join_free()).
+ */
+ if (table_ref->check_option && !join->select_lex->uncacheable)
+ {
+ SELECT_LEX_UNIT *tmp_unit;
+ SELECT_LEX *sl;
+ for (tmp_unit= join->select_lex->first_inner_unit();
+ tmp_unit;
+ tmp_unit= tmp_unit->next_unit())
+ {
+ for (sl= tmp_unit->first_select(); sl; sl= sl->next_select())
+ {
+ if (sl->master_unit()->item)
+ {
+ join->select_lex->uncacheable|= UNCACHEABLE_CHECKOPTION;
+ goto loop_end;
+ }
+ }
+ }
+ }
+loop_end:
+
if (table == first_table_for_update && table_ref->check_option)
{
table_map unupdated_tables= table_ref->check_option->used_tables() &
diff --git a/sql/sql_view.cc b/sql/sql_view.cc
index 8e6d3ed583a..41a638b2618 100644
--- a/sql/sql_view.cc
+++ b/sql/sql_view.cc
@@ -660,7 +660,7 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views,
}
VOID(pthread_mutex_unlock(&LOCK_open));
- if (view->revision != 1)
+ if (mode != VIEW_CREATE_NEW)
query_cache_invalidate3(thd, view, 0);
start_waiting_global_read_lock(thd);
if (res)
@@ -678,12 +678,8 @@ err:
}
-/* index of revision number in following table */
-static const int revision_number_position= 8;
-/* index of last required parameter for making view */
-static const int required_view_parameters= 10;
-/* number of backups */
-static const int num_view_backups= 3;
+/* number of required parameters for making view */
+static const int required_view_parameters= 9;
/*
table of VIEW .frm field descriptors
@@ -716,9 +712,6 @@ static File_option view_parameters[]=
{{(char*) STRING_WITH_LEN("with_check_option")},
my_offsetof(TABLE_LIST, with_check),
FILE_OPTIONS_ULONGLONG},
- {{(char*) STRING_WITH_LEN("revision")},
- my_offsetof(TABLE_LIST, revision),
- FILE_OPTIONS_REV},
{{(char*) STRING_WITH_LEN("timestamp")},
my_offsetof(TABLE_LIST, timestamp),
FILE_OPTIONS_TIMESTAMP},
@@ -880,18 +873,9 @@ loop_out:
}
/*
- read revision number
-
TODO: read dependence list, too, to process cascade/restrict
TODO: special cascade/restrict procedure for alter?
*/
- if (parser->parse((gptr)view, thd->mem_root,
- view_parameters + revision_number_position, 1,
- &file_parser_dummy_hook))
- {
- error= thd->net.report_error? -1 : 0;
- goto err;
- }
}
else
{
@@ -933,7 +917,7 @@ loop_out:
}
if (sql_create_definition_file(&dir, &file, view_file_type,
- (gptr)view, view_parameters, num_view_backups))
+ (gptr)view, view_parameters))
{
error= thd->net.report_error? -1 : 1;
goto err;
@@ -996,13 +980,14 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table,
DBUG_RETURN(0);
}
- if (table->use_index || table->ignore_index)
+ List<String> *index_list= table->use_index ? table->use_index
+ : table->ignore_index;
+ if (index_list)
{
- my_error(ER_WRONG_USAGE, MYF(0),
- table->ignore_index ? "IGNORE INDEX" :
- (table->force_index ? "FORCE INDEX" : "USE INDEX"),
- "VIEW");
- DBUG_RETURN(TRUE);
+ DBUG_ASSERT(index_list->head()); // should never fail
+ my_error(ER_KEY_DOES_NOT_EXITS, MYF(0), index_list->head()->c_ptr(),
+ table->table_name);
+ DBUG_RETURN(TRUE);
}
/* check loop via view definition */
@@ -1868,8 +1853,7 @@ mysql_rename_view(THD *thd,
goto err;
/* rename view and it's backups */
- if (rename_in_schema_file(thd, view->db, view->table_name, new_name,
- view_def.revision - 1, num_view_backups))
+ if (rename_in_schema_file(thd, view->db, view->table_name, new_name))
goto err;
strxnmov(dir_buff, FN_REFLEN, mysql_data_home, "/", view->db, "/", NullS);
@@ -1883,12 +1867,10 @@ mysql_rename_view(THD *thd,
- file_buff);
if (sql_create_definition_file(&pathstr, &file, view_file_type,
- (gptr)&view_def, view_parameters,
- num_view_backups))
+ (gptr)&view_def, view_parameters))
{
/* restore renamed view in case of error */
- rename_in_schema_file(thd, view->db, new_name, view->table_name,
- view_def.revision - 1, num_view_backups);
+ rename_in_schema_file(thd, view->db, new_name, view->table_name);
goto err;
}
} else
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 0eefe782354..51fb5dbdfe4 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -7512,6 +7512,11 @@ drop:
THD *thd= YYTHD;
LEX *lex= thd->lex;
sp_name *spname;
+ if ($4.str && check_db_name($4.str))
+ {
+ my_error(ER_WRONG_DB_NAME, MYF(0), $4.str);
+ MYSQL_YYABORT;
+ }
if (lex->sphead)
{
my_error(ER_SP_NO_DROP_SP, MYF(0), "FUNCTION");
diff --git a/sql/structs.h b/sql/structs.h
index ab8537612fa..9882119b7c5 100644
--- a/sql/structs.h
+++ b/sql/structs.h
@@ -170,7 +170,7 @@ enum SHOW_TYPE
SHOW_UNDEF,
SHOW_LONG, SHOW_LONGLONG, SHOW_INT, SHOW_CHAR, SHOW_CHAR_PTR,
SHOW_DOUBLE_STATUS,
- SHOW_BOOL, SHOW_MY_BOOL, SHOW_OPENTABLES, SHOW_STARTTIME,
+ SHOW_BOOL, SHOW_MY_BOOL, SHOW_OPENTABLES, SHOW_STARTTIME, SHOW_QUERIES,
SHOW_LONG_CONST, SHOW_INT_CONST, SHOW_HAVE, SHOW_SYS, SHOW_HA_ROWS,
SHOW_VARS,
#ifdef HAVE_OPENSSL
diff --git a/sql/table.h b/sql/table.h
index 08326e2fbe0..0884f5ba3d2 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -657,7 +657,6 @@ struct TABLE_LIST
st_lex_user definer; /* definer of view */
ulonglong file_version; /* version of file's field set */
ulonglong updatable_view; /* VIEW can be updated */
- ulonglong revision; /* revision control number */
ulonglong algorithm; /* 0 any, 1 tmp tables , 2 merging */
ulonglong view_suid; /* view is suid (TRUE dy default) */
ulonglong with_check; /* WITH CHECK OPTION */
diff --git a/sql/tztime.cc b/sql/tztime.cc
index 709e3b64752..d3d952e3c1e 100644
--- a/sql/tztime.cc
+++ b/sql/tztime.cc
@@ -1073,6 +1073,7 @@ Time_zone_system::gmt_sec_to_TIME(MYSQL_TIME *tmp, my_time_t t) const
localtime_r(&tmp_t, &tmp_tm);
localtime_to_TIME(tmp, &tmp_tm);
tmp->time_type= MYSQL_TIMESTAMP_DATETIME;
+ adjust_leap_second(tmp);
}
@@ -1157,6 +1158,7 @@ Time_zone_utc::gmt_sec_to_TIME(MYSQL_TIME *tmp, my_time_t t) const
gmtime_r(&tmp_t, &tmp_tm);
localtime_to_TIME(tmp, &tmp_tm);
tmp->time_type= MYSQL_TIMESTAMP_DATETIME;
+ adjust_leap_second(tmp);
}
@@ -1260,6 +1262,7 @@ void
Time_zone_db::gmt_sec_to_TIME(MYSQL_TIME *tmp, my_time_t t) const
{
::gmt_sec_to_TIME(tmp, t, tz_info);
+ adjust_leap_second(tmp);
}
@@ -2373,6 +2376,25 @@ Time_zone *my_tz_find_with_opening_tz_tables(THD *thd, const String *name)
DBUG_RETURN(tz);
}
+
+/**
+ Convert leap seconds into non-leap
+
+ This function will convert the leap seconds added by the OS to
+ non-leap seconds, e.g. 23:59:59, 23:59:60 -> 23:59:59, 00:00:01 ...
+ This check is not checking for years on purpose : although it's not a
+ complete check this way it doesn't require looking (and having installed)
+ the leap seconds table.
+
+ @param[in,out] broken down time structure as filled in by the OS
+*/
+
+void Time_zone::adjust_leap_second(MYSQL_TIME *t)
+{
+ if (t->second == 60 || t->second == 61)
+ t->second= 59;
+}
+
#endif /* !defined(TESTTIME) && !defined(TZINFO2SQL) */
diff --git a/sql/tztime.h b/sql/tztime.h
index 32a942a26e1..750b8dacbe1 100644
--- a/sql/tztime.h
+++ b/sql/tztime.h
@@ -55,6 +55,9 @@ public:
allocated on MEM_ROOT and should not require destruction.
*/
virtual ~Time_zone() {};
+
+protected:
+ static inline void adjust_leap_second(MYSQL_TIME *t);
};
extern Time_zone * my_tz_UTC;
diff --git a/sql/unireg.cc b/sql/unireg.cc
index b581ad4655a..d37bb09d0e8 100644
--- a/sql/unireg.cc
+++ b/sql/unireg.cc
@@ -63,8 +63,8 @@ static bool make_empty_rec(THD *thd, int file, enum db_type table_type,
db_file Handler to use. May be zero, in which case we use
create_info->db_type
RETURN
- 0 ok
- 1 error
+ false ok
+ true error
*/
bool mysql_create_frm(THD *thd, my_string file_name,
@@ -143,6 +143,24 @@ bool mysql_create_frm(THD *thd, my_string file_name,
(create_info->min_rows == 1) && (keys == 0));
int2store(fileinfo+28,key_info_length);
+ /*
+ This gives us the byte-position of the character at
+ (character-position, not byte-position) TABLE_COMMENT_MAXLEN.
+ The trick here is that character-positions start at 0, so the last
+ character in a maximum-allowed length string would be at char-pos
+ MAXLEN-1; charpos MAXLEN will be the position of the terminator.
+ Consequently, bytepos(charpos(MAXLEN)) should be equal to
+ comment[length] (which should also be the terminator, or at least
+ the first byte after the payload in the strict sense). If this is
+ not so (bytepos(charpos(MAXLEN)) comes /before/ the end of the
+ string), the string is too long.
+
+ For additional credit, realise that UTF-8 has 1-3 bytes before 6.0,
+ and 1-4 bytes in 6.0 (6.0 also has UTF-32). This means that the
+ inlined COMMENT supposedly does not exceed 60 character plus
+ terminator, vulgo, 181 bytes.
+ */
+
tmp_len= system_charset_info->cset->charpos(system_charset_info,
create_info->comment.str,
create_info->comment.str +
@@ -165,14 +183,6 @@ bool mysql_create_frm(THD *thd, my_string file_name,
strmake((char*) forminfo+47, create_info->comment.str ?
create_info->comment.str : "", create_info->comment.length);
forminfo[46]=(uchar) create_info->comment.length;
-#ifdef EXTRA_DEBUG
- /*
- EXTRA_DEBUG causes strmake() to initialize its buffer behind the
- payload with a magic value to detect wrong buffer-sizes. We
- explicitly zero that segment again.
- */
- memset((char*) forminfo+47 + forminfo[46], 0, 61 - forminfo[46]);
-#endif
if (my_pwrite(file,(byte*) fileinfo,64,0L,MYF_RW) ||
my_pwrite(file,(byte*) keybuff,key_info_length,
(ulong) uint2korr(fileinfo+6),MYF_RW))