diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt
index 89675138750aad888661c2bcd6b5faa9076e7cb3..a419da5eabf8b1a8a1059955fa00f56072c3b2c8 100755
--- a/client/CMakeLists.txt
+++ b/client/CMakeLists.txt
@@ -32,7 +32,8 @@ INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include
 ADD_EXECUTABLE(mysql completion_hash.cc mysql.cc readline.cc sql_string.cc ../mysys/my_conio.c)
 TARGET_LINK_LIBRARIES(mysql mysqlclient_notls wsock32)
 
-ADD_EXECUTABLE(mysqltest mysqltest.c ../mysys/my_getsystime.c ../mysys/my_copy.c)
+ADD_EXECUTABLE(mysqltest mysqltest.c ../mysys/my_getsystime.c
+               ../mysys/my_copy.c ../mysys/my_mkdir.c)
 TARGET_LINK_LIBRARIES(mysqltest mysqlclient_notls regex wsock32)
 
 ADD_EXECUTABLE(mysqlcheck mysqlcheck.c)
diff --git a/client/Makefile.am b/client/Makefile.am
index c7663c7da822bb9f3e17f671450b11e01a906f40..672bb2e0c477954cb61f4a0426095aa086d48009 100644
--- a/client/Makefile.am
+++ b/client/Makefile.am
@@ -34,7 +34,8 @@ mysqladmin_SOURCES =		mysqladmin.cc
 mysql_LDADD =			@readline_link@ @TERMCAP_LIB@ $(LDADD) $(CXXLDFLAGS)
 mysqltest_SOURCES=              mysqltest.c \
 				$(top_srcdir)/mysys/my_getsystime.c \
-				$(top_srcdir)/mysys/my_copy.c
+				$(top_srcdir)/mysys/my_copy.c \
+				$(top_srcdir)/mysys/my_mkdir.c
 
 mysqltest_LDADD =		$(top_builddir)/regex/libregex.a $(LDADD)
 mysqlbinlog_SOURCES =   	mysqlbinlog.cc \
diff --git a/client/mysqltest.c b/client/mysqltest.c
index 88575c26bc6a9f229490fc92d5af86d7d8519a08..05c9ced38485ce3dd1e87f6fbbc1359ebc06d1bf 100644
--- a/client/mysqltest.c
+++ b/client/mysqltest.c
@@ -51,6 +51,10 @@
 #ifdef HAVE_SYS_WAIT_H
 #include <sys/wait.h>
 #endif
+#ifdef __WIN__
+#include <direct.h>
+#endif
+
 
 #ifndef WEXITSTATUS
 # ifdef __WIN__
@@ -277,7 +281,7 @@ enum enum_commands {
   Q_REPLACE_REGEX, Q_REMOVE_FILE, Q_FILE_EXIST,
   Q_WRITE_FILE, Q_COPY_FILE, Q_PERL, Q_DIE, Q_EXIT, Q_SKIP,
   Q_CHMOD_FILE, Q_APPEND_FILE, Q_CAT_FILE, Q_DIFF_FILES,
-  Q_SEND_QUIT,
+  Q_SEND_QUIT, Q_CHANGE_USER, Q_MKDIR, Q_RMDIR,
 
   Q_UNKNOWN,			       /* Unknown command.   */
   Q_COMMENT,			       /* Comments, ignored. */
@@ -366,6 +370,10 @@ const char *command_names[]=
   "cat_file",
   "diff_files",
   "send_quit",
+  "change_user",
+  "mkdir",
+  "rmdir",
+
   0
 };
 
@@ -2741,6 +2749,67 @@ void do_file_exist(struct st_command *command)
 }
 
 
+/*
+  SYNOPSIS
+  do_mkdir
+  command	called command
+
+  DESCRIPTION
+  mkdir <dir_name>
+  Create the directory <dir_name>
+*/
+
+void do_mkdir(struct st_command *command)
+{
+  int error;
+  static DYNAMIC_STRING ds_dirname;
+  const struct command_arg mkdir_args[] = {
+    "dirname", ARG_STRING, TRUE, &ds_dirname, "Directory to create"
+  };
+  DBUG_ENTER("do_mkdir");
+
+  check_command_args(command, command->first_argument,
+                     mkdir_args, sizeof(mkdir_args)/sizeof(struct command_arg),
+                     ' ');
+
+  DBUG_PRINT("info", ("creating directory: %s", ds_dirname.str));
+  error= my_mkdir(ds_dirname.str, 0777, MYF(0)) != 0;
+  handle_command_error(command, error);
+  dynstr_free(&ds_dirname);
+  DBUG_VOID_RETURN;
+}
+
+/*
+  SYNOPSIS
+  do_rmdir
+  command	called command
+
+  DESCRIPTION
+  rmdir <dir_name>
+  Remove the empty directory <dir_name>
+*/
+
+void do_rmdir(struct st_command *command)
+{
+  int error;
+  static DYNAMIC_STRING ds_dirname;
+  const struct command_arg rmdir_args[] = {
+    "dirname", ARG_STRING, TRUE, &ds_dirname, "Directory to remove"
+  };
+  DBUG_ENTER("do_rmdir");
+
+  check_command_args(command, command->first_argument,
+                     rmdir_args, sizeof(rmdir_args)/sizeof(struct command_arg),
+                     ' ');
+
+  DBUG_PRINT("info", ("removing directory: %s", ds_dirname.str));
+  error= rmdir(ds_dirname.str) != 0;
+  handle_command_error(command, error);
+  dynstr_free(&ds_dirname);
+  DBUG_VOID_RETURN;
+}
+
+
 /*
   Read characters from line buffer or file. This is needed to allow
   my_ungetc() to buffer MAX_DELIMITER_LENGTH characters for a file
@@ -3046,6 +3115,69 @@ void do_send_quit(struct st_command *command)
 }
 
 
+/*
+  SYNOPSIS
+  do_change_user
+  command       called command
+
+  DESCRIPTION
+  change_user [<user>], [<passwd>], [<db>]
+  <user> - user to change to
+  <passwd> - user password
+  <db> - default database
+
+  Changes the user and causes the database specified by db to become
+  the default (current) database for the the current connection.
+
+*/
+
+void do_change_user(struct st_command *command)
+{
+  MYSQL *mysql = &cur_con->mysql;
+  /* static keyword to make the NetWare compiler happy. */
+  static DYNAMIC_STRING ds_user, ds_passwd, ds_db;
+  const struct command_arg change_user_args[] = {
+    { "user", ARG_STRING, FALSE, &ds_user, "User to connect as" },
+    { "password", ARG_STRING, FALSE, &ds_passwd, "Password used when connecting" },
+    { "database", ARG_STRING, FALSE, &ds_db, "Database to select after connect" },
+  };
+
+  DBUG_ENTER("do_change_user");
+
+  check_command_args(command, command->first_argument,
+                     change_user_args,
+                     sizeof(change_user_args)/sizeof(struct command_arg),
+                     ',');
+
+  if (cur_con->stmt)
+  {
+    mysql_stmt_close(cur_con->stmt);
+    cur_con->stmt= NULL;
+  }
+
+  if (!ds_user.length)
+    dynstr_set(&ds_user, mysql->user);
+
+  if (!ds_passwd.length)
+    dynstr_set(&ds_passwd, mysql->passwd);
+
+  if (!ds_db.length)
+    dynstr_set(&ds_db, mysql->db);
+
+  DBUG_PRINT("info",("connection: '%s' user: '%s' password: '%s' database: '%s'",
+                      cur_con->name, ds_user.str, ds_passwd.str, ds_db.str));
+
+  if (mysql_change_user(mysql, ds_user.str, ds_passwd.str, ds_db.str))
+    die("change user failed: %s", mysql_error(mysql));
+
+  dynstr_free(&ds_user);
+  dynstr_free(&ds_passwd);
+  dynstr_free(&ds_db);
+
+  DBUG_VOID_RETURN;
+}
+
+
 /*
   SYNOPSIS
   do_perl
@@ -6847,11 +6979,14 @@ int main(int argc, char **argv)
       case Q_ECHO: do_echo(command); command_executed++; break;
       case Q_SYSTEM: do_system(command); break;
       case Q_REMOVE_FILE: do_remove_file(command); break;
+      case Q_MKDIR: do_mkdir(command); break;
+      case Q_RMDIR: do_rmdir(command); break;
       case Q_FILE_EXIST: do_file_exist(command); break;
       case Q_WRITE_FILE: do_write_file(command); break;
       case Q_APPEND_FILE: do_append_file(command); break;
       case Q_DIFF_FILES: do_diff_files(command); break;
       case Q_SEND_QUIT: do_send_quit(command); break;
+      case Q_CHANGE_USER: do_change_user(command); break;
       case Q_CAT_FILE: do_cat_file(command); break;
       case Q_COPY_FILE: do_copy_file(command); break;
       case Q_CHMOD_FILE: do_chmod_file(command); break;
diff --git a/mysql-test/r/binlog.result b/mysql-test/r/binlog.result
index 0a199c87545622d647c7854c54c635ad10e81053..e6c5e3222deaaee3a21744a5711fbf5e48e90bcd 100644
--- a/mysql-test/r/binlog.result
+++ b/mysql-test/r/binlog.result
@@ -567,4 +567,19 @@ master-bin.000001	36585	Rotate	1	36629	master-bin.000002;pos=4
 drop table t1;
 set global binlog_cache_size=@bcs;
 set session autocommit = @ac;
+drop table if exists t1;
+reset master;
+create table t1 (a bigint unsigned, b bigint(20) unsigned);
+prepare stmt from "insert into t1 values (?,?)";
+set @a= 9999999999999999;
+set @b= 14632475938453979136;
+execute stmt using @a, @b;
+deallocate prepare stmt;
+drop table t1;
+show binlog events from 0;
+Log_name	Pos	Event_type	Server_id	End_log_pos	Info
+master-bin.000001	4	Format_desc	1	98	Server version, Binlog ver: 4
+master-bin.000001	98	Query	1	219	use `test`; create table t1 (a bigint unsigned, b bigint(20) unsigned)
+master-bin.000001	219	Query	1	343	use `test`; insert into t1 values (9999999999999999,14632475938453979136)
+master-bin.000001	343	Query	1	419	use `test`; drop table t1
 End of 5.0 tests
diff --git a/mysql-test/r/mysqltest.result b/mysql-test/r/mysqltest.result
index d03e21b1bb0447f9d8ad251d0fb89eda75512283..a7df1a523cff240c51e023d587a75527e8e00ba8 100644
--- a/mysql-test/r/mysqltest.result
+++ b/mysql-test/r/mysqltest.result
@@ -722,4 +722,7 @@ a	int(11)	YES		NULL
 b	varchar(255)	YES		NULL	
 c	datetime	YES		NULL	
 drop table t1;
+mysqltest: At line 1: change user failed: Unknown database 'inexistent'
+mysqltest: At line 1: change user failed: Access denied for user 'inexistent'@'localhost' (using password: NO)
+mysqltest: At line 1: change user failed: Access denied for user 'root'@'localhost' (using password: YES)
 End of tests
diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result
index f547654bed196b4081f774957f0c7c3fca485cbc..8845f011971b948912f600c2fcf683a6230363dc 100644
--- a/mysql-test/r/ps.result
+++ b/mysql-test/r/ps.result
@@ -1693,4 +1693,20 @@ t1	CREATE TABLE `t1` (
   `?` decimal(2,1) default NULL
 ) ENGINE=MyISAM DEFAULT CHARSET=latin1
 drop table t1;
+drop table if exists t1;
+create table t1 (a bigint unsigned, b bigint(20) unsigned);
+prepare stmt from "insert into t1 values (?,?)";
+set @a= 9999999999999999;
+set @b= 14632475938453979136;
+insert into t1 values (@a, @b);
+select * from t1 where a = @a and b = @b;
+a	b
+9999999999999999	14632475938453979136
+execute stmt using @a, @b;
+select * from t1 where a = @a and b = @b;
+a	b
+9999999999999999	14632475938453979136
+9999999999999999	14632475938453979136
+deallocate prepare stmt;
+drop table t1;
 End of 5.0 tests.
diff --git a/mysql-test/t/binlog.test b/mysql-test/t/binlog.test
index 5d1399925c3034da51cc9ae43e00a0166f69cc8d..b35c81b3b182be4ff0d4447550cbc23cd6566616 100644
--- a/mysql-test/t/binlog.test
+++ b/mysql-test/t/binlog.test
@@ -106,4 +106,21 @@ drop table t1;
 set global binlog_cache_size=@bcs;
 set session autocommit = @ac;
 
+#
+# Bug#33798: prepared statements improperly handle large unsigned ints
+#
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+reset master;
+create table t1 (a bigint unsigned, b bigint(20) unsigned);
+prepare stmt from "insert into t1 values (?,?)";
+set @a= 9999999999999999;
+set @b= 14632475938453979136;
+execute stmt using @a, @b;
+deallocate prepare stmt;
+drop table t1;
+--replace_regex /\/\* xid=.* \*\//\/* XID *\// /table_id: [0-9]+/table_id: #/ /Server ver: [^,]*,/Server version,/
+show binlog events from 0;
+
 --echo End of 5.0 tests
diff --git a/mysql-test/t/mysqltest.test b/mysql-test/t/mysqltest.test
index ec188af0244456c475c97fc1c54d05cff0c60be7..5856bfff036c418b37ced95b91400438dce24a95 100644
--- a/mysql-test/t/mysqltest.test
+++ b/mysql-test/t/mysqltest.test
@@ -2083,5 +2083,46 @@ eval $show_statement;
 
 drop table t1;
 
+# ----------------------------------------------------------------------------
+# Test change_user command
+# ----------------------------------------------------------------------------
+
+--error 1
+--exec echo "--change_user root,,inexistent" | $MYSQL_TEST 2>&1
+
+--error 1
+--exec echo "--change_user inexistent,,test" | $MYSQL_TEST 2>&1
+
+--error 1
+--exec echo "--change_user root,inexistent,test" | $MYSQL_TEST 2>&1
+
+--change_user
+--change_user root
+--change_user root,,
+--change_user root,,test
+
+# ----------------------------------------------------------------------------
+# Test mkdir and rmdir command
+# ----------------------------------------------------------------------------
+
+mkdir $MYSQLTEST_VARDIR/tmp/testdir;
+rmdir $MYSQLTEST_VARDIR/tmp/testdir;
+
+# Directory already exist
+mkdir $MYSQLTEST_VARDIR/tmp/testdir;
+--error 1
+mkdir $MYSQLTEST_VARDIR/tmp/testdir;
+
+# Remove dir with file inside
+write_file $MYSQLTEST_VARDIR/tmp/testdir/file1.txt;
+hello
+EOF
+--error 1
+rmdir $MYSQLTEST_VARDIR/tmp/testdir;
+
+remove_file $MYSQLTEST_VARDIR/tmp/testdir/file1.txt;
+rmdir $MYSQLTEST_VARDIR/tmp/testdir;
+
+
 --echo End of tests
 
diff --git a/mysql-test/t/ps.test b/mysql-test/t/ps.test
index c1505ffd6457be880dc5a3f53ca89800ed554c70..3f4b37f13f40b014b381a5668b6663af9738f85d 100644
--- a/mysql-test/t/ps.test
+++ b/mysql-test/t/ps.test
@@ -1807,4 +1807,21 @@ execute stmt using @a;
 show create table t1;
 drop table t1;
 
+#
+# Bug#33798: prepared statements improperly handle large unsigned ints
+#
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+create table t1 (a bigint unsigned, b bigint(20) unsigned);
+prepare stmt from "insert into t1 values (?,?)";
+set @a= 9999999999999999;
+set @b= 14632475938453979136;
+insert into t1 values (@a, @b);
+select * from t1 where a = @a and b = @b;
+execute stmt using @a, @b;
+select * from t1 where a = @a and b = @b;
+deallocate prepare stmt;
+drop table t1;
+
 --echo End of 5.0 tests.
diff --git a/sql/item.cc b/sql/item.cc
index 713e7709bcb485fb0cbfbe249356d8c140f33189..ffb18054750642ff1b82028d608a8bbb5708adb5 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -2580,6 +2580,7 @@ bool Item_param::set_from_user_var(THD *thd, const user_var_entry *entry)
   if (entry && entry->value)
   {
     item_result_type= entry->type;
+    unsigned_flag= entry->unsigned_flag;
     if (strict_type && required_result_type != item_result_type)
       DBUG_RETURN(1);
     switch (item_result_type) {
@@ -2875,7 +2876,10 @@ const String *Item_param::query_val_str(String* str) const
 {
   switch (state) {
   case INT_VALUE:
-    str->set(value.integer, &my_charset_bin);
+    if (unsigned_flag)
+      str->set((ulonglong) value.integer, &my_charset_bin);
+    else
+      str->set(value.integer, &my_charset_bin);
     break;
   case REAL_VALUE:
     str->set(value.real, NOT_FIXED_DEC, &my_charset_bin);