summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
Diffstat (limited to 'sql')
-rw-r--r--sql/field.cc9
-rw-r--r--sql/filesort.cc3
-rw-r--r--sql/filesort_utils.cc2
-rw-r--r--sql/item.cc3
-rw-r--r--sql/item_cmpfunc.cc13
-rw-r--r--sql/item_cmpfunc.h1
-rw-r--r--sql/item_sum.cc2
-rw-r--r--sql/partition_info.cc20
-rw-r--r--sql/partition_info.h1
-rw-r--r--sql/share/errmsg-utf8.txt46
-rw-r--r--sql/sql_acl.cc75
-rw-r--r--sql/sql_partition.cc11
-rw-r--r--sql/sql_yacc.yy8
-rw-r--r--sql/structs.h2
-rw-r--r--sql/table.cc8
15 files changed, 135 insertions, 69 deletions
diff --git a/sql/field.cc b/sql/field.cc
index 36f9fd5ee36..141a7354433 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -4738,7 +4738,14 @@ longlong Field_double::val_int_from_real(bool want_unsigned_result)
float8get(j,ptr);
res= double_to_longlong(j, want_unsigned_result, &error);
- if (error)
+ /*
+ Note, val_uint() is currently used for auto_increment purposes only,
+ and we want to suppress all warnings in such cases.
+ If we ever start using val_uint() for other purposes,
+ val_int_from_real() will need a new separate parameter to
+ suppress warnings.
+ */
+ if (error && !want_unsigned_result)
{
THD *thd= get_thd();
ErrConvDouble err(j);
diff --git a/sql/filesort.cc b/sql/filesort.cc
index 3f174029d48..7f7407fc2dc 100644
--- a/sql/filesort.cc
+++ b/sql/filesort.cc
@@ -998,7 +998,8 @@ static void make_sortkey(register Sort_param *param,
if (maybe_null)
*to++=1;
char *tmp_buffer= param->tmp_buffer ? param->tmp_buffer : (char*)to;
- String tmp(tmp_buffer, param->sort_length, cs);
+ String tmp(tmp_buffer, param->tmp_buffer ? param->sort_length :
+ sort_field->length, cs);
String *res= item->str_result(&tmp);
if (!res)
{
diff --git a/sql/filesort_utils.cc b/sql/filesort_utils.cc
index 370a4e655b6..1e0cf096145 100644
--- a/sql/filesort_utils.cc
+++ b/sql/filesort_utils.cc
@@ -96,7 +96,7 @@ uchar **Filesort_buffer::alloc_sort_buffer(uint num_records, uint record_length)
if (m_idx_array.is_null())
{
- sort_buff_sz= num_records * (record_length + sizeof(uchar*));
+ sort_buff_sz= ((size_t)num_records) * (record_length + sizeof(uchar*));
set_if_bigger(sort_buff_sz, record_length * MERGEBUFF2);
uchar **sort_keys=
(uchar**) my_malloc(sort_buff_sz, MYF(MY_THREAD_SPECIFIC));
diff --git a/sql/item.cc b/sql/item.cc
index 8c64a10c496..97bd15b688e 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -4623,7 +4623,8 @@ resolve_ref_in_select_and_group(THD *thd, Item_ident *ref, SELECT_LEX *select)
if (thd->variables.sql_mode & MODE_ONLY_FULL_GROUP_BY &&
select->having_fix_field &&
- select_ref != not_found_item && !group_by_ref)
+ select_ref != not_found_item && !group_by_ref &&
+ !ref->alias_name_used)
{
/*
Report the error if fields was found only in the SELECT item list and
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index 2ad2b5fe61a..c7e957731f7 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -1849,6 +1849,19 @@ bool Item_func_opt_neg::eq(const Item *item, bool binary_cmp) const
}
+bool Item_func_interval::fix_fields(THD *thd, Item **ref)
+{
+ if (Item_int_func::fix_fields(thd, ref))
+ return true;
+ for (uint i= 0 ; i < row->cols(); i++)
+ {
+ if (row->element_index(i)->check_cols(1))
+ return true;
+ }
+ return false;
+}
+
+
void Item_func_interval::fix_length_and_dec()
{
uint rows= row->cols();
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index cc336289355..361e4b3558f 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -878,6 +878,7 @@ public:
{
allowed_arg_cols= 0; // Fetch this value from first argument
}
+ bool fix_fields(THD *, Item **);
longlong val_int();
void fix_length_and_dec();
const char *func_name() const { return "interval"; }
diff --git a/sql/item_sum.cc b/sql/item_sum.cc
index 1a4fe3b0ccc..0e2e9f0795d 100644
--- a/sql/item_sum.cc
+++ b/sql/item_sum.cc
@@ -3594,7 +3594,7 @@ void Item_func_group_concat::print(String *str, enum_query_type query_type)
}
}
str->append(STRING_WITH_LEN(" separator \'"));
- str->append(*separator);
+ str->append_for_single_quote(separator->ptr(), separator->length());
str->append(STRING_WITH_LEN("\')"));
}
diff --git a/sql/partition_info.cc b/sql/partition_info.cc
index ce9329e8f6a..14f301e2d85 100644
--- a/sql/partition_info.cc
+++ b/sql/partition_info.cc
@@ -2743,6 +2743,24 @@ end:
DBUG_RETURN(result);
}
+
+bool partition_info::error_if_requires_values() const
+{
+ switch (part_type) {
+ case NOT_A_PARTITION:
+ case HASH_PARTITION:
+ break;
+ case RANGE_PARTITION:
+ my_error(ER_PARTITION_REQUIRES_VALUES_ERROR, MYF(0), "RANGE", "LESS THAN");
+ return true;
+ case LIST_PARTITION:
+ my_error(ER_PARTITION_REQUIRES_VALUES_ERROR, MYF(0), "LIST", "IN");
+ return true;
+ }
+ return false;
+}
+
+
/**
Fix partition data from parser.
@@ -2832,6 +2850,8 @@ bool partition_info::fix_parser_data(THD *thd)
part_elem= it++;
List_iterator<part_elem_value> list_val_it(part_elem->list_val_list);
num_elements= part_elem->list_val_list.elements;
+ if (!num_elements && error_if_requires_values())
+ DBUG_RETURN(true);
DBUG_ASSERT(part_type == RANGE_PARTITION ?
num_elements == 1U : TRUE);
for (j= 0; j < num_elements; j++)
diff --git a/sql/partition_info.h b/sql/partition_info.h
index ec7374b3e3e..b271ff08e82 100644
--- a/sql/partition_info.h
+++ b/sql/partition_info.h
@@ -368,6 +368,7 @@ public:
bool *prune_needs_default_values,
MY_BITMAP *used_partitions);
bool has_same_partitioning(partition_info *new_part_info);
+ bool error_if_requires_values() const;
private:
static int list_part_cmp(const void* a, const void* b);
bool set_up_default_partitions(handler *file, HA_CREATE_INFO *info,
diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt
index 0a2d704a94d..52be5e14e14 100644
--- a/sql/share/errmsg-utf8.txt
+++ b/sql/share/errmsg-utf8.txt
@@ -1735,29 +1735,29 @@ ER_WRONG_AUTO_KEY 42000 S1009
ER_BINLOG_CANT_DELETE_GTID_DOMAIN
eng "Could not delete gtid domain. Reason: %s."
ER_NORMAL_SHUTDOWN
- cze "%s: normální ukončení\n"
- dan "%s: Normal nedlukning\n"
- nla "%s: Normaal afgesloten \n"
- eng "%s: Normal shutdown\n"
- est "%s: MariaDB lõpetas\n"
- fre "%s: Arrêt normal du serveur\n"
- ger "%s: Normal heruntergefahren\n"
- greek "%s: Φυσιολογική διαδικασία shutdown\n"
- hun "%s: Normal leallitas\n"
- ita "%s: Shutdown normale\n"
- jpn "%s: 通常シャットダウン\n"
- kor "%s: 정상적인 shutdown\n"
- nor "%s: Normal avslutning\n"
- norwegian-ny "%s: Normal nedkopling\n"
- pol "%s: Standardowe zakończenie działania\n"
- por "%s: 'Shutdown' normal\n"
- rum "%s: Terminare normala\n"
- rus "%s: Корректная остановка\n"
- serbian "%s: Normalno gašenje\n"
- slo "%s: normálne ukončenie\n"
- spa "%s: Apagado normal\n"
- swe "%s: Normal avslutning\n"
- ukr "%s: Нормальне завершення\n"
+ cze "%s: norm-Bální ukončení"
+ dan "%s: Normal nedlukning"
+ nla "%s: Normaal afgesloten"
+ eng "%s: Normal shutdown"
+ est "%s: MariaDB lõpetas"
+ fre "%s: Arrêt normal du serveur"
+ ger "%s: Normal heruntergefahren"
+ greek "%s: Φυσιολογική διαδικασία shutdown"
+ hun "%s: Normal leallitas"
+ ita "%s: Shutdown normale"
+ jpn "%s: 通常シャットダウン"
+ kor "%s: 정상적인 shutdown"
+ nor "%s: Normal avslutning"
+ norwegian-ny "%s: Normal nedkopling"
+ pol "%s: Standardowe zakończenie działania"
+ por "%s: 'Shutdown' normal"
+ rum "%s: Terminare normala"
+ rus "%s: Корректная остановка"
+ serbian "%s: Normalno gašenje"
+ slo "%s: normálne ukončenie"
+ spa "%s: Apagado normal"
+ swe "%s: Normal avslutning"
+ ukr "%s: Нормальне завершення"
ER_GOT_SIGNAL
cze "%s: přijat signal %d, končím\n"
dan "%s: Fangede signal %d. Afslutter!!\n"
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index 6029f4ed71a..503b65f2be0 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -2282,37 +2282,42 @@ static void acl_insert_user(const char *user, const char *host,
}
-static void acl_update_db(const char *user, const char *host, const char *db,
+static bool acl_update_db(const char *user, const char *host, const char *db,
ulong privileges)
{
mysql_mutex_assert_owner(&acl_cache->lock);
+ bool updated= false;
+
for (uint i=0 ; i < acl_dbs.elements ; i++)
{
ACL_DB *acl_db=dynamic_element(&acl_dbs,i,ACL_DB*);
if ((!acl_db->user && !user[0]) ||
- (acl_db->user &&
- !strcmp(user,acl_db->user)))
+ (acl_db->user &&
+ !strcmp(user,acl_db->user)))
{
if ((!acl_db->host.hostname && !host[0]) ||
- (acl_db->host.hostname &&
- !strcmp(host, acl_db->host.hostname)))
+ (acl_db->host.hostname &&
+ !strcmp(host, acl_db->host.hostname)))
{
- if ((!acl_db->db && !db[0]) ||
- (acl_db->db && !strcmp(db,acl_db->db)))
+ if ((!acl_db->db && !db[0]) ||
+ (acl_db->db && !strcmp(db,acl_db->db)))
- {
- if (privileges)
+ {
+ if (privileges)
{
acl_db->access= privileges;
acl_db->initial_access= acl_db->access;
}
- else
- delete_dynamic_element(&acl_dbs,i);
- }
+ else
+ delete_dynamic_element(&acl_dbs,i);
+ updated= true;
+ }
}
}
}
+
+ return updated;
}
@@ -3746,9 +3751,21 @@ static int replace_db_table(TABLE *table, const char *db,
acl_cache->clear(1); // Clear privilege cache
if (old_row_exists)
acl_update_db(combo.user.str,combo.host.str,db,rights);
- else
- if (rights)
- acl_insert_db(combo.user.str,combo.host.str,db,rights);
+ else if (rights)
+ {
+ /*
+ If we did not have an already existing row, for users, we must always
+ insert an ACL_DB entry. For roles however, it is possible that one was
+ already created when DB privileges were propagated from other granted
+ roles onto the current role. For this case, first try to update the
+ existing entry, otherwise insert a new one.
+ */
+ if (!combo.is_role() ||
+ !acl_update_db(combo.user.str, combo.host.str, db, rights))
+ {
+ acl_insert_db(combo.user.str,combo.host.str,db,rights);
+ }
+ }
DBUG_RETURN(0);
/* This could only happen if the grant tables got corrupted */
@@ -5651,6 +5668,7 @@ static int merge_role_privileges(ACL_ROLE *role __attribute__((unused)),
{
PRIVS_TO_MERGE *data= (PRIVS_TO_MERGE *)context;
+ DBUG_ASSERT(grantee->counter > 0);
if (--grantee->counter)
return 1; // don't recurse into grantee just yet
@@ -6743,17 +6761,14 @@ end_index_init:
DBUG_RETURN(return_val);
}
-
-static my_bool role_propagate_grants_action(void *ptr,
- void *unused __attribute__((unused)))
+static my_bool collect_leaf_roles(void *role_ptr,
+ void *roles_array)
{
- ACL_ROLE *role= (ACL_ROLE *)ptr;
- if (role->counter)
- return 0;
-
- mysql_mutex_assert_owner(&acl_cache->lock);
- PRIVS_TO_MERGE data= { PRIVS_TO_MERGE::ALL, 0, 0 };
- traverse_role_graph_up(role, &data, NULL, merge_role_privileges);
+ ACL_ROLE *role= static_cast<ACL_ROLE *>(role_ptr);
+ Dynamic_array<ACL_ROLE *> *array=
+ static_cast<Dynamic_array<ACL_ROLE *> *>(roles_array);
+ if (!role->counter)
+ array->push(role);
return 0;
}
@@ -6820,7 +6835,15 @@ bool grant_reload(THD *thd)
}
mysql_mutex_lock(&acl_cache->lock);
- my_hash_iterate(&acl_roles, role_propagate_grants_action, NULL);
+ Dynamic_array<ACL_ROLE *> leaf_roles;
+ my_hash_iterate(&acl_roles, collect_leaf_roles, &leaf_roles);
+ PRIVS_TO_MERGE data= { PRIVS_TO_MERGE::ALL, 0, 0 };
+ for (size_t i= 0; i < leaf_roles.elements(); i++)
+ {
+ traverse_role_graph_up(leaf_roles.at(i), &data, NULL,
+ merge_role_privileges);
+ }
+
mysql_mutex_unlock(&acl_cache->lock);
mysql_rwlock_unlock(&LOCK_grant);
diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc
index 330892c16e9..941182dda53 100644
--- a/sql/sql_partition.cc
+++ b/sql/sql_partition.cc
@@ -4882,16 +4882,11 @@ uint prep_alter_part_table(THD *thd, TABLE *table, Alter_info *alter_info,
my_error(ER_PARTITION_WRONG_VALUES_ERROR, MYF(0),
"LIST", "IN");
}
- else if (tab_part_info->part_type == RANGE_PARTITION)
- {
- my_error(ER_PARTITION_REQUIRES_VALUES_ERROR, MYF(0),
- "RANGE", "LESS THAN");
- }
else
{
- DBUG_ASSERT(tab_part_info->part_type == LIST_PARTITION);
- my_error(ER_PARTITION_REQUIRES_VALUES_ERROR, MYF(0),
- "LIST", "IN");
+ DBUG_ASSERT(tab_part_info->part_type == RANGE_PARTITION ||
+ tab_part_info->part_type == LIST_PARTITION);
+ (void) tab_part_info->error_if_requires_values();
}
goto err;
}
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index f379364e453..1d380ce0c6b 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -5097,12 +5097,8 @@ opt_part_values:
partition_info *part_info= lex->part_info;
if (! lex->is_partition_management())
{
- if (part_info->part_type == RANGE_PARTITION)
- my_yyabort_error((ER_PARTITION_REQUIRES_VALUES_ERROR, MYF(0),
- "RANGE", "LESS THAN"));
- if (part_info->part_type == LIST_PARTITION)
- my_yyabort_error((ER_PARTITION_REQUIRES_VALUES_ERROR, MYF(0),
- "LIST", "IN"));
+ if (part_info->error_if_requires_values())
+ MYSQL_YYABORT;
}
else
part_info->part_type= HASH_PARTITION;
diff --git a/sql/structs.h b/sql/structs.h
index c1c832d07ec..2ab102d82f9 100644
--- a/sql/structs.h
+++ b/sql/structs.h
@@ -204,7 +204,7 @@ typedef int *(*update_var)(THD *, struct st_mysql_show_var *);
typedef struct st_lex_user {
LEX_STRING user, host, plugin, auth;
LEX_STRING pwtext, pwhash;
- bool is_role() { return user.str[0] && !host.str[0]; }
+ bool is_role() const { return user.str[0] && !host.str[0]; }
void set_lex_string(LEX_STRING *l, char *buf)
{
if (is_role())
diff --git a/sql/table.cc b/sql/table.cc
index 53d88bc02aa..6b1ae3d0245 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -6337,6 +6337,14 @@ void TABLE::create_key_part_by_field(KEY_PART_INFO *key_part_info,
might be reused.
*/
key_part_info->store_length= key_part_info->length;
+ /*
+ For BIT fields null_bit is not set to 0 even if the field is defined
+ as NOT NULL, look at Field_bit::Field_bit
+ */
+ if (!field->real_maybe_null())
+ {
+ key_part_info->null_bit= 0;
+ }
/*
The total store length of the key part is the raw length of the field +