diff --git a/lib/modules/Sql.pmod/mysql.pike b/lib/modules/Sql.pmod/mysql.pike
index eef7c16c8b2a705581b74dbc8dbe74f1161d0469..e47ae1748728025eac34af7d6a94f9b72502a509 100644
--- a/lib/modules/Sql.pmod/mysql.pike
+++ b/lib/modules/Sql.pmod/mysql.pike
@@ -1,5 +1,5 @@
 /*
- * $Id: mysql.pike,v 1.33 2006/11/04 19:06:49 nilsson Exp $
+ * $Id: mysql.pike,v 1.34 2006/11/17 18:43:17 mast Exp $
  *
  * Glue for the Mysql-module
  */
@@ -136,12 +136,13 @@ int get_unicode_encode_mode()
   return !!send_charset;
 }
 
+#if constant (Mysql.mysql.HAVE_MYSQL_FIELD_CHARSETNR)
 void set_unicode_decode_mode (int enable)
 //! Enable or disable unicode decode mode.
 //!
 //! In this mode, if the server supports UTF-8 then non-binary text
-//! strings in results are are automatically decoded to (possibly
-//! wide) unicode strings. Not enabled by default.
+//! strings in results are automatically decoded to (possibly wide)
+//! unicode strings. Not enabled by default.
 //!
 //! The statement "@expr{SET character_set_results = utf8@}" is sent
 //! to the server to enable the mode. When the mode is disabled,
@@ -157,9 +158,8 @@ void set_unicode_decode_mode (int enable)
 //!   @expr{character_set_results@} was added in MySQL 4.1.1.
 //!
 //! @note
-//!   This mode is not compatible with earlier pike versions. You need
-//!   to run in compatibility mode <= 7.6 to have it disabled by
-//!   default.
+//!   This function is only available if Pike has been compiled with
+//!   MySQL client library 4.1.0 or later.
 //!
 //! @seealso
 //!   @[set_unicode_encode_mode]
@@ -175,6 +175,7 @@ void set_unicode_decode_mode (int enable)
     utf8_mode &= ~UNICODE_DECODE_MODE;
   }
 }
+#endif
 
 int get_unicode_decode_mode()
 //! Returns nonzero if unicode decode mode is enabled, zero otherwise.
@@ -261,12 +262,20 @@ void set_charset (string charset)
       utf8_mode & (LATIN1_UNICODE_ENCODE_MODE|UTF8_UNICODE_ENCODE_MODE))
     update_unicode_encode_mode_from_charset (charset);
 
-  if (charset == "unicode")
+  if (charset == "unicode") {
+#if constant (Mysql.mysql.HAVE_MYSQL_FIELD_CHARSETNR)
     utf8_mode |= UNICODE_DECODE_MODE;
+#else
+    predef::error ("Unicode decode mode not supported - "
+		   "compiled with MySQL client library < 4.1.0.\n");
+#endif
+  }
+#if constant (Mysql.mysql.HAVE_MYSQL_FIELD_CHARSETNR)
   else if (utf8_mode & UNICODE_DECODE_MODE && charset != "utf8")
     // This setting has been overridden by ::set_charset, so we need
     // to reinstate it.
     ::big_query ("SET character_set_results = utf8");
+#endif
 }
 
 string get_charset()
@@ -554,6 +563,12 @@ int decode_datetime (string timestr)
   }
 }
 
+#if constant (Mysql.mysql.HAVE_MYSQL_FIELD_CHARSETNR)
+#define HAVE_MYSQL_FIELD_CHARSETNR_DO(X...) X
+#else
+#define HAVE_MYSQL_FIELD_CHARSETNR_DO(X...)
+#endif
+
 #define QUERY_BODY(do_query)						\
   if (bindings)								\
     query = .sql_util.emulate_bindings(query,bindings,this);		\
@@ -632,10 +647,12 @@ int decode_datetime (string timestr)
 									\
   if (!objectp(res)) return res;					\
 									\
-  if (utf8_mode & UNICODE_DECODE_MODE) {				\
-    CH_DEBUG ("Using UnicodeWrapper for result.\n");			\
-    return .sql_util.UnicodeWrapper(res);				\
-  }									\
+  HAVE_MYSQL_FIELD_CHARSETNR_DO (					\
+    if (utf8_mode & UNICODE_DECODE_MODE) {				\
+      CH_DEBUG ("Using UnicodeWrapper for result.\n");			\
+      return .sql_util.UnicodeWrapper(res);				\
+    }									\
+  );									\
   return res;
 
 Mysql.mysql_result big_query (string query,
@@ -747,10 +764,16 @@ static void create(string|void host, string|void database,
 
     update_unicode_encode_mode_from_charset (lower_case (charset));
 
+#if constant (Mysql.mysql.HAVE_MYSQL_FIELD_CHARSETNR)
     if (charset == "unicode")
       utf8_mode |= UNICODE_DECODE_MODE;
     else if (options->unicode_decode_mode)
       set_unicode_decode_mode (1);
+#else
+    if (charset == "unicode" || options->unicode_decode_mode)
+      predef::error ("Unicode decode mode not supported - "
+		     "compiled with MySQL client library < 4.1.0.\n");
+#endif
 
   } else {
     ::create(host||"", database||"", user||"", password||"");
diff --git a/lib/modules/Sql.pmod/sql_util.pmod b/lib/modules/Sql.pmod/sql_util.pmod
index 982594e466201c04c280d34d062b91a5c9af3cc1..6eb80ab9d808f7350aef1d707ce34d46da7e237f 100644
--- a/lib/modules/Sql.pmod/sql_util.pmod
+++ b/lib/modules/Sql.pmod/sql_util.pmod
@@ -1,5 +1,5 @@
 /*
- * $Id: sql_util.pmod,v 1.15 2006/08/11 11:08:44 grubba Exp $
+ * $Id: sql_util.pmod,v 1.16 2006/11/17 18:43:17 mast Exp $
  *
  * Some SQL utility functions.
  * They are kept here to avoid circular references.
@@ -61,9 +61,6 @@ string emulate_bindings(string query, mapping(string|int:mixed)|void bindings,
 }
 
 //! Result object wrapper performing utf8 decoding of all fields.
-//!
-//! Useful for eg Mysql connections which have been set to utf8-mode
-//! using eg @expr{"SET NAMES 'utf8'"@}.
 class UnicodeWrapper (
 		      //! The wrapped result object.
 		      static object master_result
@@ -135,11 +132,37 @@ class UnicodeWrapper (
     if (!arrayp(row)) return row;
     array(int|mapping(string:mixed)) field_info = fetch_fields();
     foreach(row; int i; string|int val) {
-      if (stringp(val) && field_info[i]->flags &&
-	  !field_info[i]->flags->binary) {
+      if (stringp(val)) {
+	row[i] = utf8_to_string(val);
+      }
+    }
+    return row;
+  }
+}
+
+#if constant (Mysql.mysql.HAVE_MYSQL_FIELD_CHARSETNR)
+class MySQLUnicodeWrapper
+//! Result wrapper for MySQL that performs UTF-8 decoding of all
+//! nonbinary fields. Useful if the result charset of the connection
+//! has been set to UTF-8.
+//!
+//! @note
+//! There's normally no need to use this class directly. It's used
+//! automatically when @[Mysql.set_unicode_decode_mode] is activated.
+{
+  inherit UnicodeWrapper;
+
+  int|array(string) fetch_row()
+  {
+    int|array(string) row = master_result->fetch_row();
+    if (!arrayp(row)) return row;
+    array(int|mapping(string:mixed)) field_info = fetch_fields();
+    foreach(row; int i; string|int val) {
+      if (stringp(val) && field_info[i]->charsetnr != 63) {
 	row[i] = utf8_to_string(val);
       }
     }
     return row;
   }
 }
+#endif
diff --git a/src/modules/Mysql/acconfig.h b/src/modules/Mysql/acconfig.h
index 4dc03dbea78e3cb2f39ba7f6c617a1b6b1d56119..6e601a9ead3efec7434d891e80125ae8b864770f 100644
--- a/src/modules/Mysql/acconfig.h
+++ b/src/modules/Mysql/acconfig.h
@@ -2,7 +2,7 @@
 || This file is part of Pike. For copyright information see COPYRIGHT.
 || Pike is distributed under GPL, LGPL and MPL. See the file COPYING
 || for more information.
-|| $Id: acconfig.h,v 1.17 2006/08/31 10:10:18 mast Exp $
+|| $Id: acconfig.h,v 1.18 2006/11/17 18:43:17 mast Exp $
 */
 
 /*
@@ -83,4 +83,7 @@
 /* Define if your mysql.h defines CLIENT_INTERACTIVE */
 #undef HAVE_CLIENT_INTERACTIVE
 
+/* Define if MYSQL_FIELD has a charsetnr member */
+#undef HAVE_MYSQL_FIELD_CHARSETNR
+
 #endif /* PIKE_MYSQL_CONFIG_H */
diff --git a/src/modules/Mysql/configure.in b/src/modules/Mysql/configure.in
index 47e061dfc07ae23264138929931a0cdd366ff40a..c4ac535b12e67dea18b123307fa535ffb6bb7ec8 100644
--- a/src/modules/Mysql/configure.in
+++ b/src/modules/Mysql/configure.in
@@ -1,5 +1,5 @@
 #
-# $Id: configure.in,v 1.53 2006/08/31 10:10:18 mast Exp $
+# $Id: configure.in,v 1.54 2006/11/17 18:43:17 mast Exp $
 #
 # Configure script for the mysql-module
 #
@@ -443,6 +443,34 @@ $ret_type * STDCALL mysql_fetch_lengths(MYSQL_RES *mysql)
 
     AC_CHECK_FUNCS(ldiv open sopen close read fileno puts fgets)
 
+    AC_MSG_CHECKING(for the charsetnr member in MYSQL_FIELD)
+    AC_CACHE_VAL(pike_cv_have_mysql_field_charsetnr, [
+      AC_TRY_LINK([
+#ifdef HAVE_WINSOCK2_H
+#include <winsock2.h>
+#elif defined(HAVE_WINSOCK_H)
+#include <winsock.h>
+#endif
+
+#ifdef HAVE_MYSQL_H
+#include <mysql.h>
+#else
+#ifdef HAVE_MYSQL_MYSQL_H
+#include <mysql/mysql.h>
+#else
+#error Need mysql.h headerfile!
+#endif
+#endif
+      ], [
+	void *foo__ = &(((MYSQL_FIELD *) 0)->charsetnr);
+      ], [pike_cv_have_mysql_field_charsetnr="yes"],
+	 [pike_cv_have_mysql_field_charsetnr="no"])
+    ])
+    if test "$pike_cv_have_mysql_field_charsetnr" = yes; then
+      AC_DEFINE(HAVE_MYSQL_FIELD_CHARSETNR)
+    fi
+    AC_MSG_RESULT($pike_cv_have_mysql_field_charsetnr)
+
   fi
 fi
 
diff --git a/src/modules/Mysql/mysql.c b/src/modules/Mysql/mysql.c
index 60fb401560df8cd3018ee9319ad6e28fe0b716fe..224b1939310e37024173a7ad1af440a2b4af97e6 100644
--- a/src/modules/Mysql/mysql.c
+++ b/src/modules/Mysql/mysql.c
@@ -2,7 +2,7 @@
 || This file is part of Pike. For copyright information see COPYRIGHT.
 || Pike is distributed under GPL, LGPL and MPL. See the file COPYING
 || for more information.
-|| $Id: mysql.c,v 1.106 2006/09/16 18:19:21 mast Exp $
+|| $Id: mysql.c,v 1.107 2006/11/17 18:43:18 mast Exp $
 */
 
 /*
@@ -1946,6 +1946,10 @@ PIKE_MODULE_INIT
   add_integer_constant( "CLIENT_SSL", CLIENT_SSL, 0);
 #endif
 
+#ifdef HAVE_MYSQL_FIELD_CHARSETNR
+  add_integer_constant ("HAVE_MYSQL_FIELD_CHARSETNR", 1, 0);
+#endif
+
   set_init_callback(init_mysql_struct);
   set_exit_callback(exit_mysql_struct);
 
diff --git a/src/modules/Mysql/result.c b/src/modules/Mysql/result.c
index 20096f2e0770d5f9c30b1e8880e13112e01640aa..f3ddfe711e71559f4bbcf91889802cdc4a2f2b02 100644
--- a/src/modules/Mysql/result.c
+++ b/src/modules/Mysql/result.c
@@ -2,7 +2,7 @@
 || This file is part of Pike. For copyright information see COPYRIGHT.
 || Pike is distributed under GPL, LGPL and MPL. See the file COPYING
 || for more information.
-|| $Id: result.c,v 1.36 2006/08/10 16:28:25 grubba Exp $
+|| $Id: result.c,v 1.37 2006/11/17 18:43:18 mast Exp $
 */
 
 /*
@@ -134,6 +134,8 @@ void mysqlmod_parse_field(MYSQL_FIELD *field, int support_default)
 {
   if (field) {
     int nbits = 0;
+    struct svalue *save_sp = Pike_sp;
+
     push_text("name"); push_text(field->name);
     push_text("table"); push_text(field->table);
     if (support_default) {
@@ -251,12 +253,12 @@ void mysqlmod_parse_field(MYSQL_FIELD *field, int support_default)
     f_aggregate_multiset(nbits);
 
     push_text("decimals"); push_int(field->decimals);
-      
-    if (support_default) {
-      f_aggregate_mapping(8*2);
-    } else {
-      f_aggregate_mapping(7*2);
-    }
+
+#ifdef HAVE_MYSQL_FIELD_CHARSETNR
+    push_text ("charsetnr"); push_int (field->charsetnr);
+#endif
+
+    f_aggregate_mapping (Pike_sp - save_sp);
   } else {
     /*
      * Should this be an error?