summaryrefslogtreecommitdiff
path: root/sql/sql_acl.cc
diff options
context:
space:
mode:
authorSergei Golubchik <sergii@pisem.net>2013-09-18 13:07:31 +0200
committerSergei Golubchik <sergii@pisem.net>2013-09-18 13:07:31 +0200
commit4ec2e9d7eda78d409d1b017ef4d8928fe9055438 (patch)
tree6c3a74a740d3c1c5f3a7d1f8154d8a791b435b3f /sql/sql_acl.cc
parent1a2a9d74fe1256554eceb09bbc6752a6376df87d (diff)
parent197bdbae4db78ba65f3668803bebd3c4a4509ae5 (diff)
downloadmariadb-git-4ec2e9d7eda78d409d1b017ef4d8928fe9055438.tar.gz
5.5 merge and fixes for compiler/test errors
Diffstat (limited to 'sql/sql_acl.cc')
-rw-r--r--sql/sql_acl.cc49
1 files changed, 22 insertions, 27 deletions
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index d98c2d88781..2c6364ed61f 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -6085,8 +6085,8 @@ static int handle_grant_struct(enum enum_acl_lists struct_no, bool drop,
LEX_USER *user_from, LEX_USER *user_to)
{
int result= 0;
- uint idx;
- uint elements;
+ int idx;
+ int elements;
const char *user;
const char *host;
ACL_USER *acl_user= NULL;
@@ -6135,8 +6135,8 @@ static int handle_grant_struct(enum enum_acl_lists struct_no, bool drop,
DBUG_PRINT("loop",("scan struct: %u search user: '%s' host: '%s'",
struct_no, user_from->user.str, user_from->host.str));
#endif
- /* Loop over all elements. */
- for (idx= 0; idx < elements; idx++)
+ /* Loop over all elements *backwards* (see the comment below). */
+ for (idx= elements - 1; idx >= 0; idx--)
{
/*
Get a pointer to the element.
@@ -6187,6 +6187,7 @@ static int handle_grant_struct(enum enum_acl_lists struct_no, bool drop,
result= 1; /* At least one element found. */
if ( drop )
{
+ elements--;
switch ( struct_no ) {
case USER_ACL:
delete_dynamic_element(&acl_users, idx);
@@ -6200,6 +6201,15 @@ static int handle_grant_struct(enum enum_acl_lists struct_no, bool drop,
case PROC_PRIVILEGES_HASH:
case FUNC_PRIVILEGES_HASH:
my_hash_delete(grant_name_hash, (uchar*) grant_name);
+ /*
+ In our HASH implementation on deletion one elements
+ is moved into a place where a deleted element was,
+ and the last element is moved into the empty space.
+ Thus we need to re-examine the current element, but
+ we don't have to restart the search from the beginning.
+ */
+ if (idx != elements)
+ idx++;
break;
case PROXY_USERS_ACL:
@@ -6207,21 +6217,6 @@ static int handle_grant_struct(enum enum_acl_lists struct_no, bool drop,
break;
}
- elements--;
- /*
- - If we are iterating through an array then we just have moved all
- elements after the current element one position closer to its head.
- This means that we have to take another look at the element at
- current position as it is a new element from the array's tail.
- - If we are iterating through a hash the current element was replaced
- with one of elements from the tail. So we also have to take a look
- at the new element in current position.
- Note that in our HASH implementation hash_delete() won't move any
- elements with position after current one to position before the
- current (i.e. from the tail to the head), so it is safe to continue
- iteration without re-starting.
- */
- idx--;
}
else if ( user_to )
{
@@ -6262,15 +6257,15 @@ static int handle_grant_struct(enum enum_acl_lists struct_no, bool drop,
my_hash_update(grant_name_hash, (uchar*) grant_name, (uchar*) old_key,
old_key_length);
/*
- hash_update() operation could have moved element from the tail
- of the hash to the current position. So we need to take a look
- at the element in current position once again.
- Thanks to the fact that hash_update() for our HASH implementation
- won't move any elements from the tail of the hash to the positions
- before the current one (a.k.a. head) it is safe to continue
- iteration without restarting.
+ hash_update() operation could have moved element from the tail or
+ the head of the hash to the current position. But it can never
+ move an element from the head to the tail or from the tail to the
+ head over the current element.
+ So we need to examine the current element once again, but
+ we don't need to restart the search from the beginning.
*/
- idx--;
+ if (idx != elements)
+ idx++;
break;
}