+DBUtils provides wrapper functions for low level database retrieval. It saves
+you the trouble of mucking around with statement handles for small database
+queries and does exception handling in the common cases for you.
+
+Query and retrieval functions share the parameter scheme:
+
+ query_or_retrieval(C<FORM, DBH, QUERY[, BINDVALUES]>)
+
+=over 4
+
+=item *
+
+C<FORM> is used for error handling only. It can be omitted in theory, but should
+not. In most cases you will call it with C<$::form>.
+
+=item *
+
+C<DBH> is a handle to the database, as returned by the C<DBI::connect> routine.
+If you don't have an active connection, you can use
+C<SL::DB->client->dbh> or get a C<Rose::DB::Object> handle from any RDBO class with
+C<<SL::DB::Part->new->db->dbh>>. In both cases the handle will have AutoCommit set.
+
+See C<PITFALLS AND CAVEATS> for common errors.
+
+=item *
+
+C<QUERY> must be exactly one query. You don't need to include the terminal
+C<;>. There must be no tainted data interpolated into the string. Instead use
+the DBI placeholder syntax.
+
+=item *
+
+All additional parameters will be used as C<BINDVALUES> for the query. Note
+that DBI can't bind arrays to a C<id IN (?)>, so you will need to generate a
+statement with exactly one C<?> for each bind value. DBI can however bind
+DateTime objects, and you should always pass these for date selections.
+
+=back
+
+=head1 PITFALLS AND CAVEATS
+
+=head2 Locking
+
+As mentioned above, there are two sources of database handles in the program:
+C<<$::form->get_standard_dbh>> and C<<SL::DB::Object->new->db->dbh>>. It's easy
+to produce deadlocks when using both of them. To reduce the likelyhood of
+locks, try to obey these rules:
+
+=over 4
+
+=item *
+
+In a controller that uses Rose objects, never use C<get_standard_dbh>.
+
+=item *
+
+In backend code, that has no preference, always accept the database handle as a
+parameter from the controller.
+
+=back
+
+=head2 Exports
+
+C<DBUtils> is one of the last modules in the program to use C<@EXPORT> instead
+of C<@EXPORT_OK>. This means it will flood your namespace with its functions,
+causing potential clashes. When writing new code, always either export nothing
+and call directly:
+
+ use SL::DBUtils ();
+ DBUtils::selectall_hashref_query(...)
+
+or export only what you need:
+
+ use SL::DBUtils qw(selectall_hashref_query);
+ selectall_hashref_query(...)
+