diff options
-rw-r--r-- | mysql-test/r/create_drop_role.result | 9 | ||||
-rw-r--r-- | mysql-test/t/create_drop_role.test | 11 | ||||
-rw-r--r-- | sql/handler.cc | 38 | ||||
-rw-r--r-- | sql/sql_acl.cc | 12 | ||||
-rw-r--r-- | storage/innobase/include/ut0wqueue.h | 13 | ||||
-rw-r--r-- | storage/innobase/ut/ut0wqueue.cc | 19 | ||||
-rw-r--r-- | support-files/wsrep.cnf.sh | 4 |
7 files changed, 73 insertions, 33 deletions
diff --git a/mysql-test/r/create_drop_role.result b/mysql-test/r/create_drop_role.result index 498dd4c1c02..886dcfd0e72 100644 --- a/mysql-test/r/create_drop_role.result +++ b/mysql-test/r/create_drop_role.result @@ -77,3 +77,12 @@ Note 1976 Can't drop role 'role_1'; it doesn't exist DROP ROLE role_1; ERROR HY000: Operation DROP ROLE failed for 'role_1' DROP USER u1@localhost; +CREATE ROLE r; +GRANT SHOW DATABASES ON *.* TO r; +CREATE USER foo; +CREATE USER bar; +GRANT r TO foo; +CREATE OR REPLACE USER foo IDENTIFIED WITH non_existing_plugin; +ERROR HY000: Plugin 'non_existing_plugin' is not loaded +DROP ROLE r; +DROP USER bar; diff --git a/mysql-test/t/create_drop_role.test b/mysql-test/t/create_drop_role.test index be33083e6c4..11bc832c6e9 100644 --- a/mysql-test/t/create_drop_role.test +++ b/mysql-test/t/create_drop_role.test @@ -54,3 +54,14 @@ DROP ROLE IF EXISTS role_1; DROP ROLE role_1; DROP USER u1@localhost; + +# MDEV-17942 +CREATE ROLE r; +GRANT SHOW DATABASES ON *.* TO r; +CREATE USER foo; +CREATE USER bar; +GRANT r TO foo; +--error ER_PLUGIN_IS_NOT_LOADED +CREATE OR REPLACE USER foo IDENTIFIED WITH non_existing_plugin; +DROP ROLE r; +DROP USER bar; diff --git a/sql/handler.cc b/sql/handler.cc index 9faa3b61a81..ae63640ae5c 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -3064,7 +3064,7 @@ int handler::update_auto_increment() bool append= FALSE; THD *thd= table->in_use; struct system_variables *variables= &thd->variables; - int tmp; + int result=0, tmp; enum enum_check_fields save_count_cuted_fields; DBUG_ENTER("handler::update_auto_increment"); @@ -3201,18 +3201,27 @@ int handler::update_auto_increment() */ if (thd->killed == KILL_BAD_DATA || nr > table->next_number_field->get_max_int_value()) - DBUG_RETURN(HA_ERR_AUTOINC_ERANGE); - /* - Field refused this value (overflow) and truncated it, use the result - of the truncation (which is going to be inserted); however we try to - decrease it to honour auto_increment_* variables. - That will shift the left bound of the reserved interval, we don't - bother shifting the right bound (anyway any other value from this - interval will cause a duplicate key). - */ - nr= prev_insert_id(table->next_number_field->val_int(), variables); - if (unlikely(table->next_number_field->store((longlong)nr, TRUE))) - nr= table->next_number_field->val_int(); + { + /* + It's better to return an error here than getting a confusing + 'duplicate key error' later. + */ + result= HA_ERR_AUTOINC_ERANGE; + } + else + { + /* + Field refused this value (overflow) and truncated it, use the result + of the truncation (which is going to be inserted); however we try to + decrease it to honour auto_increment_* variables. + That will shift the left bound of the reserved interval, we don't + bother shifting the right bound (anyway any other value from this + interval will cause a duplicate key). + */ + nr= prev_insert_id(table->next_number_field->val_int(), variables); + if (unlikely(table->next_number_field->store((longlong)nr, TRUE))) + nr= table->next_number_field->val_int(); + } } if (append) { @@ -3237,6 +3246,9 @@ int handler::update_auto_increment() */ insert_id_for_cur_row= nr; + if (result) // overflow + DBUG_RETURN(result); + /* Set next insert id to point to next auto-increment value to be able to handle multi-row statements. diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 6958098d4a6..537dcc77c8c 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -10116,6 +10116,7 @@ bool mysql_create_user(THD *thd, List <LEX_USER> &list, bool handle_as_role) LEX_USER *user_name; List_iterator <LEX_USER> user_list(list); bool binlog= false; + bool some_users_dropped= false; DBUG_ENTER("mysql_create_user"); DBUG_PRINT("entry", ("Handle as %s", handle_as_role ? "role" : "user")); @@ -10182,6 +10183,8 @@ bool mysql_create_user(THD *thd, List <LEX_USER> &list, bool handle_as_role) result= true; continue; } + else + some_users_dropped= true; // Proceed with the creation } else if (thd->lex->create_info.if_not_exists()) @@ -10250,12 +10253,21 @@ bool mysql_create_user(THD *thd, List <LEX_USER> &list, bool handle_as_role) } } + if (result && some_users_dropped && !handle_as_role) + { + /* Rebuild in-memory structs, since 'acl_users' has been modified */ + rebuild_check_host(); + rebuild_role_grants(); + } + mysql_mutex_unlock(&acl_cache->lock); if (result) + { my_error(ER_CANNOT_USER, MYF(0), (handle_as_role) ? "CREATE ROLE" : "CREATE USER", wrong_users.c_ptr_safe()); + } if (binlog) result |= write_bin_log(thd, FALSE, thd->query(), thd->query_length()); diff --git a/storage/innobase/include/ut0wqueue.h b/storage/innobase/include/ut0wqueue.h index 771d8d6ae5c..3a96d7d4059 100644 --- a/storage/innobase/include/ut0wqueue.h +++ b/storage/innobase/include/ut0wqueue.h @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 2006, 2014, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2017, 2019, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -63,14 +64,10 @@ ib_wqueue_add( mem_heap_t* heap); /*!< in: memory heap to use for allocating the list node */ -/******************************************************************** -Check if queue is empty. */ -ibool -ib_wqueue_is_empty( -/*===============*/ - /* out: TRUE if queue empty - else FALSE */ - const ib_wqueue_t* wq); /* in: work queue */ +/** Check if queue is empty. +@param wq wait queue +@return whether the queue is empty */ +bool ib_wqueue_is_empty(ib_wqueue_t* wq); /****************************************************************//** Wait for a work item to appear in the queue. diff --git a/storage/innobase/ut/ut0wqueue.cc b/storage/innobase/ut/ut0wqueue.cc index ccd5c10555c..35f14fd20fe 100644 --- a/storage/innobase/ut/ut0wqueue.cc +++ b/storage/innobase/ut/ut0wqueue.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2006, 2015, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, MariaDB Corporation. All Rights Reserved. +Copyright (c) 2019, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -201,16 +201,15 @@ ib_wqueue_nowait( return (node ? node->data : NULL); } -/******************************************************************** -Check if queue is empty. */ -ibool -ib_wqueue_is_empty( -/*===============*/ - /* out: TRUE if queue empty - else FALSE */ - const ib_wqueue_t* wq) /* in: work queue */ +/** Check if queue is empty. +@param wq wait queue +@return whether the queue is empty */ +bool ib_wqueue_is_empty(ib_wqueue_t* wq) { - return(ib_list_is_empty(wq->items)); + mutex_enter(&wq->mutex); + bool is_empty = ib_list_is_empty(wq->items); + mutex_exit(&wq->mutex); + return is_empty; } /******************************************************************** diff --git a/support-files/wsrep.cnf.sh b/support-files/wsrep.cnf.sh index 51ce3dca2dd..7242fff9f7a 100644 --- a/support-files/wsrep.cnf.sh +++ b/support-files/wsrep.cnf.sh @@ -67,10 +67,10 @@ wsrep_slave_threads=1 wsrep_certify_nonPK=1 # Maximum number of rows in write set -wsrep_max_ws_rows=131072 +wsrep_max_ws_rows=0 # Maximum size of write set -wsrep_max_ws_size=1073741824 +wsrep_max_ws_size=2147483647 # to enable debug level logging, set this to 1 wsrep_debug=0 |