diff --git a/.gitattributes b/.gitattributes
index 57071044d5d94962a181424a2fedeebae1e35a30..1d1623387926a5e68bdca69e94eacb0a5c01f8e2 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -192,7 +192,6 @@ testfont binary
 /lib/modules/Protocols.pmod/X.pmod/_Types.pmod foreign_ident
 /lib/modules/Protocols.pmod/X.pmod/_Xlib.pmod foreign_ident
 /lib/modules/SSL.pmod/testsuite.in foreign_ident
-/lib/modules/Sql.pmod/sql_result.pike foreign_ident
 /lib/modules/Sql.pmod/tds.pike foreign_ident
 /lib/modules/Standards.pmod/ASN1.pmod/Decode.pmod foreign_ident
 /lib/modules/Standards.pmod/ASN1.pmod/Types.pmod foreign_ident
diff --git a/lib/modules/Sql.pmod/Sql.pike b/lib/modules/Sql.pmod/Sql.pike
index da85b0d6a615aef726bd592cf1907d73a2916cfa..da1fac270f2d78db0b7bd16084e2d1522eef0682 100644
--- a/lib/modules/Sql.pmod/Sql.pike
+++ b/lib/modules/Sql.pmod/Sql.pike
@@ -8,11 +8,48 @@
 
 #pike __REAL_VERSION__
 
-//! Implements those functions that need not be present in all SQL-modules.
+//! This class encapsulates a connection to an SQL server. It is a
+//! generic interface on top of the DB server specific
+//! implementations. That doesn't mean that there aren't plenty of
+//! server specific characteristics that still shine through, though.
+//!
+//! This class also serves as an interface guideline for the DB server
+//! specific connection classes.
+//!
+//! @section Untyped and typed mode
+//!
+//! The query results are returned in different ways depending on the
+//! query functions used: The @tt{..typed_query@} functions select
+//! typed mode, while the other query functions uses the older untyped
+//! mode.
+//!
+//! In untyped mode, all values except SQL NULL are returned as
+//! strings in their display representation, and SQL NULL is returned
+//! as zero.
+//!
+//! In typed mode, values are returned in pike native form where it
+//! works well. That means at least that SQL integer fields are
+//! returned as pike integers, floats as floats, SQL NULL as
+//! @[Val.null], and of course strings still as strings. The
+//! representation of other SQL types depend on the capabilities of
+//! the server specific backends. It's also possible that floats in
+//! some cases are represented in other ways if too much precision is
+//! lost in the conversion to pike floats.
+//!
+//! @endsection
+//!
+//! @note
+//! For historical reasons, there may be server specific backends that
+//! operate differently from what is described here, e.g. some that
+//! return a bit of typed data in untyped mode.
+//!
+//! @note
+//! Typed operation was not supported at all prior to Pike 7.8.363,
+//! and may not be supported for all databases.
 
 #define ERROR(X ...)	predef::error(X)
 
-//! Object to use for the actual SQL-queries.
+//! Server specific connection object used for the actual SQL queries.
 object master_sql;
 
 //! Convert all field names in mappings to lower_case.
@@ -397,11 +434,15 @@ void select_db(string db)
 }
 
 //! Compiles the query (if possible). Otherwise returns it as is.
-//! The resulting object can be used multiple times in query() and
-//! big_query().
+//! The resulting object can be used multiple times to the query
+//! functions.
 //!
 //! @param q
 //!   SQL-query to compile.
+//!
+//! @seealso
+//! @[query], @[typed_query], @[big_query], @[big_typed_query],
+//! @[streaming_query], @[streaming_typed_query]
 string|object compile_query(string q)
 {
   if (functionp(master_sql->compile_query)) {
@@ -439,7 +480,7 @@ protected ZeroWrapper zero = ZeroWrapper();
 //! Handle @[sprintf]-based quoted arguments
 //!
 //! @param query
-//!   The query as sent to @[query()] or @[big_query()].
+//!   The query as sent to one of the query functions.
 //!
 //! @param extraargs
 //!   The arguments following the query.
@@ -476,7 +517,8 @@ protected array(string|mapping(string|int:mixed))
   return ({sprintf(query,@args), b});
 }
 
-//!   Send an SQL query to the underlying SQL-server.
+//! Sends an SQL query synchronously to the underlying SQL-server and
+//! returns the results in untyped mode.
 //!
 //! @param q
 //!   Query to send to the SQL-server. This can either be a string with the
@@ -512,8 +554,9 @@ protected array(string|mapping(string|int:mixed))
 //!   Returns one of the following on success:
 //!   @mixed
 //!     @type array(mapping(string:string))
-//!       The result as an array of mappings indexed on the name
-//!       of the columns
+//!       The result as an array of mappings indexed on the name of
+//!       the columns. The values are either strings with the display
+//!       representations or zero for the SQL NULL value.
 //!     @type zero
 //!       The value @expr{0@} (zero) if the query didn't return any
 //!       result (eg @tt{INSERT@} or similar).
@@ -523,7 +566,7 @@ protected array(string|mapping(string|int:mixed))
 //!   Throws an exception if the query fails.
 //!
 //! @seealso
-//!   @[big_query]
+//!   @[typed_query], @[big_query], @[streaming_query]
 array(mapping(string:string)) query(object|string q,
 				    mixed ... extraargs)
 {
@@ -558,7 +601,8 @@ array(mapping(string:string)) query(object|string q,
 //!     @type array(mapping(string:mixed))
 //!       The result as an array of mappings indexed on the name of
 //!       the columns. The values have the appropriate native pike
-//!       types where they fit the SQL data types.
+//!       types where they fit the SQL data types - see the class doc
+//!       for details on typed mode.
 //!     @type zero
 //!       The value @expr{0@} (zero) if the query didn't return any
 //!       result (eg @tt{INSERT@} or similar).
@@ -591,17 +635,22 @@ array(mapping(string:mixed)) typed_query(object|string q, mixed ... extraargs)
   return res_obj_to_array(master_sql->big_typed_query(q));
 }
 
-//! Send an SQL query to the underlying SQL-server.
+//! Sends an SQL query synchronously to the underlying SQL-server and
+//! returns the results in untyped mode.
 //!
 //! For the arguments, please see the @[query()] function.
 //!
-//! Send an SQL query to the underlying SQL-server. The result is
-//! returned as an Sql.sql_result object. This allows for having some
-//! more info about the result as well as processing the result in a
-//! streaming fashion, although the result itself wasn't obtained
-//! streamingly from the server. Returns @expr{0@} if the query didn't
-//! return any result (e.g. @tt{INSERT@} or similar). For the other
-//! arguments, they are the same as for the @[query()] function.
+//! The result is returned as an @[Sql.sql_result] object in untyped
+//! mode. This allows for having some more info about the result as
+//! well as processing the result in a streaming fashion, although the
+//! result itself wasn't obtained streamingly from the server. Returns
+//! @expr{0@} if the query didn't return any result (e.g. @tt{INSERT@}
+//! or similar).
+//!
+//! @note
+//! Despite the name, this function is not only useful for "big"
+//! queries. It typically has less overhead than @[query] also for
+//! ones that return only a few rows.
 //!
 //! @seealso
 //!   @[query], @[streaming_query]
@@ -639,28 +688,30 @@ int|object big_query(object|string q, mixed ... extraargs)
   return 0;
 }
 
-//! Send an SQL query to the underlying SQL-server.
+//! Sends an SQL query synchronously to the underlying SQL-server and
+//! returns the results in typed mode.
 //!
 //! For the arguments, please see the @[query()] function.
 //!
-//! The returned @[Sql.sql_result] object (if any) will be in
-//! @tt{TYPED@}-mode.
+//! The result is returned as an @[Sql.sql_result] object in typed
+//! mode. This allows for having some more info about the result as
+//! well as processing the result in a streaming fashion, although the
+//! result itself wasn't obtained streamingly from the server. Returns
+//! @expr{0@} if the query didn't return any result (e.g. @tt{INSERT@}
+//! or similar).
 //!
 //! @note
 //!   This interface is not supported by all sql databases.
 //!   If not supported, the result will currently be the same
 //!   as if @[big_query()] would be called.
 //!
-//! @returns
-//!   Returns @expr{0@} if the query didn't return any result
-//!   (e.g. @tt{INSERT@} or similar).
-//!   The result (if any) is returned as an @[Sql.sql_result] object.
-//!   This allows for having some more info about the result as well
-//!   as processing the result in a streaming fashion, although the
-//!   result itself wasn't obtained streamingly from the server.
+//! @note
+//! Despite the name, this function is not only useful for "big"
+//! queries. It typically has less overhead than @[typed_query] also
+//! for ones that return only a few rows.
 //!
 //! @seealso
-//!   @[query], @[big_query], @[streaming_query]
+//!   @[query], @[typed_query], @[big_query], @[streaming_query]
 int|object big_typed_query(object|string q, mixed ... extraargs)
 {
   if (!master_sql->big_typed_query) return big_query(q, @extraargs);
@@ -686,12 +737,17 @@ int|object big_typed_query(object|string q, mixed ... extraargs)
   return 0;
 }
 
-//! Send an SQL query to the underlying SQL-server. The result is
-//! returned as a streaming Sql.sql_result object. This allows for
-//! having results larger than the available memory, and returning
-//! some more info about the result. Returns @expr{0@} if the query
-//! didn't return any result (e.g. INSERT or similar). For the other
-//! arguments, they are the same as for the @[query()] function.
+//! Sends an SQL query synchronously to the underlying SQL-server and
+//! returns the results streaming in untyped mode.
+//!
+//! For the arguments, please see the @[query()] function.
+//!
+//! The result is returned as a streaming @[Sql.sql_result] object in
+//! untyped mode. This allows for having results larger than the
+//! available memory, and returning some more info about the result.
+//! Returns @expr{0@} if the query didn't return any result (e.g.
+//! INSERT or similar). For the other arguments, they are the same as
+//! for the @[query()] function.
 //!
 //! @note
 //!   Streaming operation is not supported by all sql databases.
@@ -699,7 +755,7 @@ int|object big_typed_query(object|string q, mixed ... extraargs)
 //!   @[big_query()].
 //!
 //! @seealso
-//!   @[big_query]
+//!   @[big_query], @[streaming_typed_query]
 int|object streaming_query(object|string q, mixed ... extraargs)
 {
   if(!master_sql->streaming_query) return big_query(q, @extraargs);
@@ -725,12 +781,16 @@ int|object streaming_query(object|string q, mixed ... extraargs)
   return 0;
 }
 
-//! Send an SQL query to the underlying SQL-server. The result is
-//! returned as a streaming Sql.sql_result object. This allows for
-//! having results larger than the available memory, and returning
-//! some more info about the result. Returns @expr{0@} if the query
-//! didn't return any result (e.g. INSERT or similar). For the other
-//! arguments, they are the same as for the @[query()] function.
+//! Sends an SQL query synchronously to the underlying SQL-server and
+//! returns the results streaming in typed mode.
+//!
+//! For the arguments, please see the @[query()] function.
+//!
+//! The result is returned as a streaming @[Sql.sql_result] object in
+//! typed mode. This allows for having results larger than the
+//! available memory, and returning some more info about the result.
+//! Returns @expr{0@} if the query didn't return any result (e.g.
+//! INSERT or similar).
 //!
 //! @note
 //!   Neither streaming operation nor typed results are supported
@@ -739,7 +799,7 @@ int|object streaming_query(object|string q, mixed ... extraargs)
 //!   may fall back even further).
 //!
 //! @seealso
-//!   @[big_query]
+//!   @[streaming_query], @[big_typed_query]
 int|object streaming_typed_query(object|string q, mixed ... extraargs)
 {
   if(!master_sql->streaming_typed_query) return big_typed_query(q, @extraargs);
diff --git a/lib/modules/Sql.pmod/mysql.pike b/lib/modules/Sql.pmod/mysql.pike
index e1bab684e5dea3ed203af6f18b8e478fcd4daca2..3e945061897fcedcb70135545e34a501bb2dd580 100644
--- a/lib/modules/Sql.pmod/mysql.pike
+++ b/lib/modules/Sql.pmod/mysql.pike
@@ -4,8 +4,54 @@
  * Glue for the Mysql-module
  */
 
-//! Implements the glue needed to access the Mysql-module from the generic
-//! SQL module.
+//! This class encapsulates a connection to a MySQL server, and
+//! implements the glue needed to access the Mysql module from the
+//! generic SQL module.
+//!
+//! @section Typed mode
+//!
+//! When query results are returned in typed mode, the MySQL data
+//! types are represented like this:
+//!
+//! @dl
+//! @item The NULL value
+//!   Returned as @[Val.null].
+//!
+//! @item BIT, TINYINT, BOOL, SMALLINT, MEDIUMINT, INT, BIGINT
+//!   Returned as pike integers.
+//!
+//! @item FLOAT, DOUBLE
+//!   Returned as pike floats.
+//!
+//! @item DECIMAL
+//!   Returned as pike integers for fields that are declared to
+//!   contain zero decimals, otherwise returned as @[Gmp.mpq] objects.
+//!
+//! @item DATE, DATETIME, TIME, YEAR
+//!   Returned as strings in their display representation (see the
+//!   MySQL manual).
+//!
+//!   @[Calendar] objects are not used partly because they always
+//!   represent a specific point or range in time, which these MySQL
+//!   types do not.
+//!
+//! @item TIMESTAMP
+//!   Also returned as strings in the display representation.
+//!
+//!   The reason is that it's both more efficient and more robust (wrt
+//!   time zone interpretations) to convert these to unix timestamps
+//!   on the MySQL side rather than in the client glue. I.e. use the
+//!   @tt{UNIX_TIMESTAMP@} function in the queries to retrieve them as
+//!   unix timestamps on integer form.
+//!
+//! @item String types
+//!   All string types are returned as pike strings. The MySQL glue
+//!   can handle charset conversions for text strings - see
+//!   @[set_charset] and @[set_unicode_decode_mode].
+//!
+//! @enddl
+//!
+//! @section
 
 #pike __REAL_VERSION__
 
diff --git a/lib/modules/Sql.pmod/sql_result.pike b/lib/modules/Sql.pmod/sql_result.pike
index 686b80e4d336e2e7506ca061d2579f3dd4408cd6..3748355e9a75aebf31b6412dbd353ba767e82ee4 100644
--- a/lib/modules/Sql.pmod/sql_result.pike
+++ b/lib/modules/Sql.pmod/sql_result.pike
@@ -1,5 +1,5 @@
 /*
- * $Id: sql_result.pike,v 1.25 2009/11/06 16:54:14 grubba Exp $
+ * $Id$
  *
  * Implements the generic result module of the SQL-interface
  *
@@ -67,27 +67,10 @@ void seek(int skip) {
 //! Fetch the next row from the result.
 //!
 //! @returns
-//!   Returns an array with one element per field in
-//!   the same order as reported by @[fetch_fields()].
-//!   The elements may be one of:
-//!   @mixed
-//!     @type zero|object(Sql.NULL)
-//!       @[UNDEFINED] or @[Sql.NULL] if the field is @tt{NULL@}.
-//!     @type string
-//!       A string containing the data for the field.
-//!     @type int
-//!       An int (possibly large) if generated by @[Sql.big_typed_query()]
-//!       or @[Sql.streaming_typed_query()] (aka @tt{TYPED@}-operation)
-//!       and the SQL field type was of an integer type.
-//!     @type float
-//!       A float if generated by @[Sql.big_typed_query()] or
-//!       @[Sql.streaming_typed_query()] (aka @tt{TYPED@}-operation)
-//!       and the SQL field type was of a floating-point type.
-//!   @endmixed
-//!
-//! @note
-//!    @tt{TYPED@}-operation was not supported at all prior to Pike 7.8.363,
-//!    and may not be supported for all databases.
+//!   Returns an array with one element per field in the same order as
+//!   reported by @[fetch_fields()]. See the @[Sql.Sql] class
+//!   documentation for more details on how different data types are
+//!   represented.
 int|array(string|int|float) fetch_row();
 
 // --- Iterator API