Commit efe5d60e authored by unknown's avatar unknown
Browse files

Manual merge.


client/mysqltest.c:
  Auto merged
mysql-test/r/grant.result:
  Auto merged
mysql-test/r/information_schema.result:
  Auto merged
sql/lex.h:
  Auto merged
sql/mysql_priv.h:
  Auto merged
sql/set_var.cc:
  Auto merged
sql/sql_acl.cc:
  Auto merged
sql/sql_parse.cc:
  Auto merged
sql/sql_yacc.yy:
  Auto merged
parents 15f84399 23517e16
Loading
Loading
Loading
Loading
+307 −107
Original line number Diff line number Diff line
@@ -437,6 +437,10 @@ my_bool mysql_rpl_probe(MYSQL *mysql __attribute__((unused))) { return 1; }
#endif
static void replace_dynstr_append_mem(DYNAMIC_STRING *ds, const char *val,
				      int len);
static void replace_dynstr_append(DYNAMIC_STRING *ds, const char *val);
static int normal_handle_error(const char *query, struct st_query *q,
                               MYSQL *mysql, DYNAMIC_STRING *ds);
static int normal_handle_no_error(struct st_query *q);

static void do_eval(DYNAMIC_STRING* query_eval, const char* query)
{
@@ -951,7 +955,7 @@ static void do_exec(struct st_query* q)
      ds= &ds_res;

    while (fgets(buf, sizeof(buf), res_file))
      replace_dynstr_append_mem(ds, buf, strlen(buf));
      replace_dynstr_append(ds, buf);
  }
  error= pclose(res_file);

@@ -1613,6 +1617,29 @@ void init_manager()
}
#endif


/*
  Connect to a server doing several retries if needed.

  SYNOPSIS
    safe_connect()
      con               - connection structure to be used
      host, user, pass, - connection parameters
      db, port, sock

  NOTE
    This function will try to connect to the given server MAX_CON_TRIES
    times and sleep CON_RETRY_SLEEP seconds between attempts before
    finally giving up. This helps in situation when the client starts
    before the server (which happens sometimes).
    It will ignore any errors during these retries. One should use
    connect_n_handle_errors() if he expects a connection error and wants
    handle as if it was an error from a usual statement.

  RETURN VALUE
    0 - success, non-0 - failure
*/

int safe_connect(MYSQL* con, const char* host, const char* user,
		 const char* pass,
		 const char* db, int port, const char* sock)
@@ -1634,6 +1661,114 @@ int safe_connect(MYSQL* con, const char* host, const char* user,
}


/*
  Connect to a server and handle connection errors in case when they occur.

  SYNOPSIS
    connect_n_handle_errors()
      q                 - context of connect "query" (command)
      con               - connection structure to be used
      host, user, pass, - connection parameters
      db, port, sock
      create_conn       - out parameter, set to zero if connection was
                          not established and is not touched otherwise

  DESCRIPTION
    This function will try to establish a connection to server and handle
    possible errors in the same manner as if "connect" was usual SQL-statement
    (If error is expected it will ignore it once it occurs and log the
    "statement" to the query log).
    Unlike safe_connect() it won't do several attempts.

  RETURN VALUE
    0 - success, non-0 - failure
*/

int connect_n_handle_errors(struct st_query *q, MYSQL* con, const char* host,
                            const char* user, const char* pass,
                            const char* db, int port, const char* sock,
                            int* create_conn)
{
  DYNAMIC_STRING ds_tmp, *ds;
  int error= 0;

  /*
    Altough we ignore --require or --result before connect() command we still
    need to handle record_file because of "@result_file sql-command" syntax.
  */
  if (q->record_file[0])
  {
    init_dynamic_string(&ds_tmp, "", 16384, 65536);
    ds= &ds_tmp;
  }
  else
    ds= &ds_res;

  if (!disable_query_log)
  {
    /*
      It is nice to have connect() statement logged in result file
      in this case.
      QQ: Should we do this only if we are expecting an error ?
    */
    char port_buff[22]; /* This should be enough for any int */
    char *port_end;
    dynstr_append_mem(ds, "connect(", 8);
    replace_dynstr_append(ds, host);
    dynstr_append_mem(ds, ",", 1);
    replace_dynstr_append(ds, user);
    dynstr_append_mem(ds, ",", 1);
    replace_dynstr_append(ds, pass);
    dynstr_append_mem(ds, ",", 1);
    if (db)
      replace_dynstr_append(ds, db);
    dynstr_append_mem(ds, ",", 1);
    port_end= int10_to_str(port, port_buff, 10);
    replace_dynstr_append_mem(ds, port_buff, port_end - port_buff);
    dynstr_append_mem(ds, ",", 1);
    if (sock)
      replace_dynstr_append(ds, sock);
    dynstr_append_mem(ds, ")", 1);
    dynstr_append_mem(ds, delimiter, delimiter_length);
    dynstr_append_mem(ds, "\n", 1);
  }
  if (!mysql_real_connect(con, host, user, pass, db, port, sock ? sock: 0,
                          CLIENT_MULTI_STATEMENTS))
  {
    error= normal_handle_error("connect", q, con, ds);
    *create_conn= 0;
    goto err;
  }
  else if (normal_handle_no_error(q))
  {
    /*
      Fail if there was no error but we expected it.
      We also don't want to have connection in this case.
    */
    mysql_close(con);
    *create_conn= 0;
    error= 1;
    goto err;
  }

  if (record)
  {
    if (!q->record_file[0] && !result_file)
      die("At line %u: Missing result file", start_lineno);
    if (!result_file)
      str_to_file(q->record_file, ds->str, ds->length);
  }
  else if (q->record_file[0])
    error|= check_result(ds, q->record_file, q->require_file);

err:
  free_replace();
  if (ds == &ds_tmp)
    dynstr_free(&ds_tmp);
  return error;
}


int do_connect(struct st_query* q)
{
  char* con_name, *con_user,*con_pass, *con_host, *con_port_str,
@@ -1642,6 +1777,8 @@ int do_connect(struct st_query* q)
  char buff[FN_REFLEN];
  int con_port;
  int free_con_sock = 0;
  int error= 0;
  int create_conn= 1;

  DBUG_ENTER("do_connect");
  DBUG_PRINT("enter",("connect: %s",p));
@@ -1706,18 +1843,28 @@ int do_connect(struct st_query* q)
  /* Special database to allow one to connect without a database name */
  if (con_db && !strcmp(con_db,"*NO-ONE*"))
    con_db=0;
  if ((safe_connect(&next_con->mysql, con_host,
		    con_user, con_pass,

  if (q->abort_on_error)
  {
    if ((safe_connect(&next_con->mysql, con_host, con_user, con_pass,
		      con_db, con_port, con_sock ? con_sock: 0)))
      die("Could not open connection '%s': %s", con_name,
          mysql_error(&next_con->mysql));
  }
  else
    error= connect_n_handle_errors(q, &next_con->mysql, con_host, con_user,
                                   con_pass, con_db, con_port, con_sock,
                                   &create_conn);

  if (create_conn)
  {
    if (!(next_con->name= my_strdup(con_name, MYF(MY_WME))))
      die(NullS);
    cur_con= next_con++;
  }
  if (free_con_sock)
    my_free(con_sock, MYF(MY_WME));
  DBUG_RETURN(0);
  DBUG_RETURN(error);
}


@@ -2356,6 +2503,13 @@ static void replace_dynstr_append_mem(DYNAMIC_STRING *ds, const char *val,
  dynstr_append_mem(ds, val, len);
}

/* Append zero-terminated string to ds, with optional replace */

static void replace_dynstr_append(DYNAMIC_STRING *ds, const char *val)
{
  replace_dynstr_append_mem(ds, val, strlen(val));
}


/*
  Append all results to the dynamic string separated with '\t'
@@ -2502,92 +2656,13 @@ static int run_query_normal(MYSQL* mysql, struct st_query* q, int flags)
	 (!(last_result= res= mysql_store_result(mysql)) &&
	  mysql_field_count(mysql)))
    {
      if (q->require_file)
      {
	abort_not_supported_test();
      }
      if (q->abort_on_error)
	die("At line %u: query '%s' failed: %d: %s", start_lineno, query,
	    mysql_errno(mysql), mysql_error(mysql));
      else
      {
	for (i=0 ; (uint) i < q->expected_errors ; i++)
	{
          if (((q->expected_errno[i].type == ERR_ERRNO) &&
               (q->expected_errno[i].code.errnum == mysql_errno(mysql))) ||
              ((q->expected_errno[i].type == ERR_SQLSTATE) &&
               (strcmp(q->expected_errno[i].code.sqlstate,mysql_sqlstate(mysql)) == 0)))
	  {
	    if (i == 0 && q->expected_errors == 1)
	    {
	      /* Only log error if there is one possible error */
	      dynstr_append_mem(ds,"ERROR ",6);
	      replace_dynstr_append_mem(ds, mysql_sqlstate(mysql),
					strlen(mysql_sqlstate(mysql)));
	      dynstr_append_mem(ds, ": ", 2);
	      replace_dynstr_append_mem(ds,mysql_error(mysql),
					strlen(mysql_error(mysql)));
	      dynstr_append_mem(ds,"\n",1);
	    }
	    /* Don't log error if we may not get an error */
            else if (q->expected_errno[0].type == ERR_SQLSTATE ||
                     (q->expected_errno[0].type == ERR_ERRNO &&
                      q->expected_errno[0].code.errnum != 0))
	      dynstr_append(ds,"Got one of the listed errors\n");
	    goto end;				/* Ok */
	  }
	}
	DBUG_PRINT("info",("i: %d  expected_errors: %d", i,
			   q->expected_errors));
	dynstr_append_mem(ds, "ERROR ",6);
	replace_dynstr_append_mem(ds, mysql_sqlstate(mysql),
				  strlen(mysql_sqlstate(mysql)));
	dynstr_append_mem(ds,": ",2);
	replace_dynstr_append_mem(ds, mysql_error(mysql),
				  strlen(mysql_error(mysql)));
	dynstr_append_mem(ds,"\n",1);
	if (i)
	{
          if (q->expected_errno[0].type == ERR_ERRNO)
            verbose_msg("query '%s' failed with wrong errno %d instead of %d...",
                        q->query, mysql_errno(mysql), q->expected_errno[0].code.errnum);
          else
            verbose_msg("query '%s' failed with wrong sqlstate %s instead of %s...",
                        q->query, mysql_sqlstate(mysql), q->expected_errno[0].code.sqlstate);
      if (normal_handle_error(query, q, mysql, ds))
        error= 1;
      goto end;
    }
	verbose_msg("query '%s' failed: %d: %s", q->query, mysql_errno(mysql),
		    mysql_error(mysql));
	/*
	  if we do not abort on error, failure to run the query does
	  not fail the whole test case
	*/
	goto end;
      }
      /*{
	verbose_msg("failed in mysql_store_result for query '%s' (%d)", query,
	mysql_errno(mysql));
	error = 1;
	goto end;
	}*/
    }

    if (q->expected_errno[0].type == ERR_ERRNO &&
        q->expected_errno[0].code.errnum != 0)
    if (normal_handle_no_error(q))
    {
      /* Error code we wanted was != 0, i.e. not an expected success */
      verbose_msg("query '%s' succeeded - should have failed with errno %d...",
                  q->query, q->expected_errno[0].code.errnum);
      error = 1;
      goto end;
    }
    else if (q->expected_errno[0].type == ERR_SQLSTATE &&
             strcmp(q->expected_errno[0].code.sqlstate,"00000") != 0)
    {
      /* SQLSTATE we wanted was != "00000", i.e. not an expected success */
      verbose_msg("query '%s' succeeded - should have failed with sqlstate %s...",
                  q->query, q->expected_errno[0].code.sqlstate);
      error= 1;
      goto end;
    }
@@ -2608,8 +2683,7 @@ static int run_query_normal(MYSQL* mysql, struct st_query* q, int flags)
	  {
	    if (i)
	      dynstr_append_mem(ds, "\t", 1);
	    replace_dynstr_append_mem(ds, field[i].name,
				      strlen(field[i].name));
	    replace_dynstr_append(ds, field[i].name);
	  }
	  dynstr_append_mem(ds, "\n", 1);
	}
@@ -2686,6 +2760,135 @@ static int run_query_normal(MYSQL* mysql, struct st_query* q, int flags)
}


/*
  Handle errors which occurred after execution of conventional (non-prepared)
  statement.

  SYNOPSIS
    normal_handle_error()
      query - query string
      q     - query context
      mysql - connection through which query was sent to server
      ds    - dynamic string which is used for output buffer

  NOTE
    If there is an unexpected error this function will abort mysqltest
    immediately.

  RETURN VALUE
    0 - OK
    1 - Some other error was expected.
*/

static int normal_handle_error(const char *query, struct st_query *q,
                               MYSQL *mysql, DYNAMIC_STRING *ds)
{
  uint i;

  DBUG_ENTER("normal_handle_error");

  if (q->require_file)
    abort_not_supported_test();

  if (q->abort_on_error)
    die("At line %u: query '%s' failed: %d: %s", start_lineno, query,
        mysql_errno(mysql), mysql_error(mysql));
  else
  {
    for (i= 0 ; (uint) i < q->expected_errors ; i++)
    {
      if (((q->expected_errno[i].type == ERR_ERRNO) &&
            (q->expected_errno[i].code.errnum == mysql_errno(mysql))) ||
          ((q->expected_errno[i].type == ERR_SQLSTATE) &&
           (strcmp(q->expected_errno[i].code.sqlstate, mysql_sqlstate(mysql)) == 0)))
      {
        if (q->expected_errors == 1)
        {
          /* Only log error if there is one possible error */
          dynstr_append_mem(ds, "ERROR ", 6);
          replace_dynstr_append(ds, mysql_sqlstate(mysql));
          dynstr_append_mem(ds, ": ", 2);
          replace_dynstr_append(ds, mysql_error(mysql));
          dynstr_append_mem(ds,"\n",1);
        }
	/* Don't log error if we may not get an error */
        else if (q->expected_errno[0].type == ERR_SQLSTATE ||
                 (q->expected_errno[0].type == ERR_ERRNO &&
                  q->expected_errno[0].code.errnum != 0))
          dynstr_append(ds,"Got one of the listed errors\n");
        /* OK */
        DBUG_RETURN(0);
      }
    }

    DBUG_PRINT("info",("i: %d  expected_errors: %d", i, q->expected_errors));

    dynstr_append_mem(ds, "ERROR ",6);
    replace_dynstr_append(ds, mysql_sqlstate(mysql));
    dynstr_append_mem(ds, ": ", 2);
    replace_dynstr_append(ds, mysql_error(mysql));
    dynstr_append_mem(ds, "\n", 1);

    if (i)
    {
      if (q->expected_errno[0].type == ERR_ERRNO)
        verbose_msg("query '%s' failed with wrong errno %d instead of %d...",
                    q->query, mysql_errno(mysql),
                    q->expected_errno[0].code.errnum);
      else
        verbose_msg("query '%s' failed with wrong sqlstate %s instead of %s...",
                    q->query, mysql_sqlstate(mysql),
                    q->expected_errno[0].code.sqlstate);
      DBUG_RETURN(1);
    }

    /*
      If we do not abort on error, failure to run the query does not fail the
      whole test case.
    */
    verbose_msg("query '%s' failed: %d: %s", q->query, mysql_errno(mysql),
                mysql_error(mysql));
    DBUG_RETURN(0);
  }
}


/*
  Handle absence of errors after execution of convetional statement.

  SYNOPSIS
    normal_handle_error()
      q - context of query

  RETURN VALUE
    0 - OK
    1 - Some error was expected from this query.
*/

static int normal_handle_no_error(struct st_query *q)
{
  DBUG_ENTER("normal_handle_no_error");

  if (q->expected_errno[0].type == ERR_ERRNO &&
      q->expected_errno[0].code.errnum != 0)
  {
    /* Error code we wanted was != 0, i.e. not an expected success */
    verbose_msg("query '%s' succeeded - should have failed with errno %d...",
                q->query, q->expected_errno[0].code.errnum);
    DBUG_RETURN(1);
  }
  else if (q->expected_errno[0].type == ERR_SQLSTATE &&
           strcmp(q->expected_errno[0].code.sqlstate,"00000") != 0)
  {
    /* SQLSTATE we wanted was != "00000", i.e. not an expected success */
    verbose_msg("query '%s' succeeded - should have failed with sqlstate %s...",
                q->query, q->expected_errno[0].code.sqlstate);
    DBUG_RETURN(1);
  }

  DBUG_RETURN(0);
}

/****************************************************************************\
 *  If --ps-protocol run ordinary statements using prepared statemnt C API
\****************************************************************************/
@@ -2879,8 +3082,7 @@ static int run_query_stmt(MYSQL *mysql, struct st_query *q, int flags)
      {
        if (col_idx)
          dynstr_append_mem(ds, "\t", 1);
        replace_dynstr_append_mem(ds, field[col_idx].name,
                                  strlen(field[col_idx].name));
        replace_dynstr_append(ds, field[col_idx].name);
      }
      dynstr_append_mem(ds, "\n", 1);
    }
@@ -3148,11 +3350,9 @@ static int run_query_stmt_handle_error(char *query, struct st_query *q,
        {
          /* Only log error if there is one possible error */
          dynstr_append_mem(ds,"ERROR ",6);
          replace_dynstr_append_mem(ds, mysql_stmt_sqlstate(stmt),
                                    strlen(mysql_stmt_sqlstate(stmt)));
          replace_dynstr_append(ds, mysql_stmt_sqlstate(stmt));
          dynstr_append_mem(ds, ": ", 2);
          replace_dynstr_append_mem(ds,mysql_stmt_error(stmt),
                                    strlen(mysql_stmt_error(stmt)));
          replace_dynstr_append(ds,mysql_stmt_error(stmt));
          dynstr_append_mem(ds,"\n",1);
        }
        /* Don't log error if we may not get an error */
@@ -3166,11 +3366,9 @@ static int run_query_stmt_handle_error(char *query, struct st_query *q,
    DBUG_PRINT("info",("i: %d  expected_errors: %d", i,
                       q->expected_errors));
    dynstr_append_mem(ds, "ERROR ",6);
    replace_dynstr_append_mem(ds, mysql_stmt_sqlstate(stmt),
                              strlen(mysql_stmt_sqlstate(stmt)));
    replace_dynstr_append(ds, mysql_stmt_sqlstate(stmt));
    dynstr_append_mem(ds,": ",2);
    replace_dynstr_append_mem(ds, mysql_stmt_error(stmt),
                              strlen(mysql_stmt_error(stmt)));
    replace_dynstr_append(ds, mysql_stmt_error(stmt));
    dynstr_append_mem(ds,"\n",1);
    if (i)
    {
@@ -3452,7 +3650,9 @@ int main(int argc, char **argv)
    {
      processed = 1;
      switch (q->type) {
      case Q_CONNECT: do_connect(q); break;
      case Q_CONNECT:
        error|= do_connect(q);
        break;
      case Q_CONNECTION: select_connection(q->first_argument); break;
      case Q_DISCONNECT:
      case Q_DIRTY_CLOSE:
+2 −2
Original line number Diff line number Diff line
@@ -10,8 +10,8 @@ GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost' REQUIRE CIPHER 'EDH-RSA-DES-CBC3
GRANT SELECT ON `mysqltest`.* TO 'mysqltest_1'@'localhost'
grant delete on mysqltest.* to mysqltest_1@localhost;
select * from mysql.user where user="mysqltest_1";
Host	User	Password	Select_priv	Insert_priv	Update_priv	Delete_priv	Create_priv	Drop_priv	Reload_priv	Shutdown_priv	Process_priv	File_priv	Grant_priv	References_priv	Index_priv	Alter_priv	Show_db_priv	Super_priv	Create_tmp_table_priv	Lock_tables_priv	Execute_priv	Repl_slave_priv	Repl_client_priv	Create_view_priv	Show_view_priv	Create_routine_priv	Alter_routine_priv	ssl_type	ssl_cipher	x509_issuer	x509_subject	max_questions	max_updates	max_connections
localhost	mysqltest_1		N	N	N	N	N	N	N	N	N	N	N	N	N	N	N	N	N	N	N	N	N									0	0	0
Host	User	Password	Select_priv	Insert_priv	Update_priv	Delete_priv	Create_priv	Drop_priv	Reload_priv	Shutdown_priv	Process_priv	File_priv	Grant_priv	References_priv	Index_priv	Alter_priv	Show_db_priv	Super_priv	Create_tmp_table_priv	Lock_tables_priv	Execute_priv	Repl_slave_priv	Repl_client_priv	Create_view_priv	Show_view_priv	Create_routine_priv	Alter_routine_priv	ssl_type	ssl_cipher	x509_issuer	x509_subject	max_questions	max_updates	max_connections	max_user_connections
localhost	mysqltest_1		N	N	N	N	N	N	N	N	N	N	N	N	N	N	N	N	N	N	N	N	N									0	0	0	0
show grants for mysqltest_1@localhost;
Grants for mysqltest_1@localhost
GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost' REQUIRE CIPHER 'EDH-RSA-DES-CBC3-SHA'
+1 −0
Original line number Diff line number Diff line
@@ -611,6 +611,7 @@ Create_routine_priv select,insert,update,references
Alter_routine_priv	select,insert,update,references
max_questions	select,insert,update,references
max_connections	select,insert,update,references
max_user_connections	select,insert,update,references
use test;
create function sub1(i int) returns int
return i+1;
+1 −0
Original line number Diff line number Diff line
@@ -102,6 +102,7 @@ user CREATE TABLE `user` (
  `max_questions` int(11) unsigned NOT NULL default '0',
  `max_updates` int(11) unsigned NOT NULL default '0',
  `max_connections` int(11) unsigned NOT NULL default '0',
  `max_user_connections` int(11) unsigned NOT NULL default '0',
  PRIMARY KEY  (`Host`,`User`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='Users and global privileges'
show create table func;
+89 −0
Original line number Diff line number Diff line
drop table if exists t1;
create table t1 (i int);
delete from mysql.user where user like 'mysqltest\_%';
delete from mysql.db where user like 'mysqltest\_%';
delete from mysql.tables_priv where user like 'mysqltest\_%';
delete from mysql.columns_priv where user like 'mysqltest\_%';
flush privileges;
grant usage on *.* to mysqltest_1@localhost with max_queries_per_hour 2;
select * from t1;
i
select * from t1;
i
select * from t1;
ERROR 42000: User 'mysqltest_1' has exceeded the 'max_questions' resource (current value: 2)
select * from t1;
ERROR 42000: User 'mysqltest_1' has exceeded the 'max_questions' resource (current value: 2)
drop user mysqltest_1@localhost;
grant usage on *.* to mysqltest_1@localhost with max_updates_per_hour 2;
select * from t1;
i
select * from t1;
i
select * from t1;
i
delete from t1;
delete from t1;
delete from t1;
ERROR 42000: User 'mysqltest_1' has exceeded the 'max_updates' resource (current value: 2)
select * from t1;
i
delete from t1;
ERROR 42000: User 'mysqltest_1' has exceeded the 'max_updates' resource (current value: 2)
select * from t1;
i
drop user mysqltest_1@localhost;
grant usage on *.* to mysqltest_1@localhost with max_connections_per_hour 2;
select * from t1;
i
select * from t1;
i
connect(localhost,mysqltest_1,,test,MYSQL_PORT,MYSQL_SOCK);
ERROR 42000: User 'mysqltest_1' has exceeded the 'max_connections' resource (current value: 2)
select * from t1;
i
connect(localhost,mysqltest_1,,test,9306,/home/dlenev/src/mysql-5.0-1339/mysql-test/var/tmp/master.sock);
ERROR 42000: User 'mysqltest_1' has exceeded the 'max_connections' resource (current value: 2)
drop user mysqltest_1@localhost;
flush privileges;
grant usage on *.* to mysqltest_1@localhost with max_user_connections 2;
select * from t1;
i
select * from t1;
i
connect(localhost,mysqltest_1,,test,MYSQL_PORT,MYSQL_SOCK);
ERROR 42000: User 'mysqltest_1' has exceeded the 'max_user_connections' resource (current value: 2)
select * from t1;
i
grant usage on *.* to mysqltest_1@localhost with max_user_connections 3;
select * from t1;
i
connect(localhost,mysqltest_1,,test,MYSQL_PORT,MYSQL_SOCK);
ERROR 42000: User 'mysqltest_1' has exceeded the 'max_user_connections' resource (current value: 3)
drop user mysqltest_1@localhost;
select @@session.max_user_connections, @@global.max_user_connections;
@@session.max_user_connections	@@global.max_user_connections
0	0
set session max_user_connections= 2;
ERROR HY000: Variable 'max_user_connections' is a GLOBAL variable and should be set with SET GLOBAL
set global max_user_connections= 2;
select @@session.max_user_connections, @@global.max_user_connections;
@@session.max_user_connections	@@global.max_user_connections
2	2
grant usage on *.* to mysqltest_1@localhost;
select @@session.max_user_connections, @@global.max_user_connections;
@@session.max_user_connections	@@global.max_user_connections
2	2
select * from t1;
i
connect(localhost,mysqltest_1,,test,MYSQL_PORT,MYSQL_SOCK);
ERROR 42000: User mysqltest_1 has already more than 'max_user_connections' active connections
grant usage on *.* to mysqltest_1@localhost with max_user_connections 3;
select @@session.max_user_connections, @@global.max_user_connections;
@@session.max_user_connections	@@global.max_user_connections
3	2
connect(localhost,mysqltest_1,,test,MYSQL_PORT,MYSQL_SOCK);
ERROR 42000: User 'mysqltest_1' has exceeded the 'max_user_connections' resource (current value: 3)
set global max_user_connections= 0;
drop user mysqltest_1@localhost;
drop table t1;
Loading