Index: trunk/db_sqlite.go
===================================================================
--- trunk/db_sqlite.go	(revision 620)
+++ trunk/db_sqlite.go	(revision 645)
@@ -2,4 +2,5 @@
 
 import (
+	"context"
 	"database/sql"
 	"fmt"
@@ -11,4 +12,6 @@
 	_ "github.com/mattn/go-sqlite3"
 )
+
+const sqliteQueryTimeout = 5 * time.Second
 
 const sqliteSchema = `
@@ -210,6 +213,9 @@
 	defer db.lock.RUnlock()
 
+	ctx, cancel := context.WithTimeout(context.TODO(), sqliteQueryTimeout)
+	defer cancel()
+
 	var stats DatabaseStats
-	row := db.db.QueryRow(`SELECT
+	row := db.db.QueryRowContext(ctx, `SELECT
 		(SELECT COUNT(*) FROM User) AS users,
 		(SELECT COUNT(*) FROM Network) AS networks,
@@ -233,5 +239,9 @@
 	defer db.lock.RUnlock()
 
-	rows, err := db.db.Query("SELECT id, username, password, admin, realname FROM User")
+	ctx, cancel := context.WithTimeout(context.TODO(), sqliteQueryTimeout)
+	defer cancel()
+
+	rows, err := db.db.QueryContext(ctx,
+		"SELECT id, username, password, admin, realname FROM User")
 	if err != nil {
 		return nil, err
@@ -261,8 +271,13 @@
 	defer db.lock.RUnlock()
 
+	ctx, cancel := context.WithTimeout(context.TODO(), sqliteQueryTimeout)
+	defer cancel()
+
 	user := &User{Username: username}
 
 	var password, realname sql.NullString
-	row := db.db.QueryRow("SELECT id, password, admin, realname FROM User WHERE username = ?", username)
+	row := db.db.QueryRowContext(ctx,
+		"SELECT id, password, admin, realname FROM User WHERE username = ?",
+		username)
 	if err := row.Scan(&user.ID, &password, &user.Admin, &realname); err != nil {
 		return nil, err
@@ -276,4 +291,7 @@
 	db.lock.Lock()
 	defer db.lock.Unlock()
+
+	ctx, cancel := context.WithTimeout(context.TODO(), sqliteQueryTimeout)
+	defer cancel()
 
 	args := []interface{}{
@@ -286,8 +304,15 @@
 	var err error
 	if user.ID != 0 {
-		_, err = db.db.Exec("UPDATE User SET password = :password, admin = :admin, realname = :realname WHERE username = :username", args...)
+		_, err = db.db.ExecContext(ctx, `
+			UPDATE User SET password = :password, admin = :admin,
+				realname = :realname WHERE username = :username`,
+			args...)
 	} else {
 		var res sql.Result
-		res, err = db.db.Exec("INSERT INTO User(username, password, admin, realname) VALUES (:username, :password, :admin, :realname)", args...)
+		res, err = db.db.ExecContext(ctx, `
+			INSERT INTO
+			User(username, password, admin, realname)
+			VALUES (:username, :password, :admin, :realname)`,
+			args...)
 		if err != nil {
 			return err
@@ -303,4 +328,7 @@
 	defer db.lock.Unlock()
 
+	ctx, cancel := context.WithTimeout(context.TODO(), sqliteQueryTimeout)
+	defer cancel()
+
 	tx, err := db.db.Begin()
 	if err != nil {
@@ -309,5 +337,5 @@
 	defer tx.Rollback()
 
-	_, err = tx.Exec(`DELETE FROM DeliveryReceipt
+	_, err = tx.ExecContext(ctx, `DELETE FROM DeliveryReceipt
 		WHERE id IN (
 			SELECT DeliveryReceipt.id
@@ -320,5 +348,5 @@
 	}
 
-	_, err = tx.Exec(`DELETE FROM Channel
+	_, err = tx.ExecContext(ctx, `DELETE FROM Channel
 		WHERE id IN (
 			SELECT Channel.id
@@ -331,10 +359,10 @@
 	}
 
-	_, err = tx.Exec("DELETE FROM Network WHERE user = ?", id)
-	if err != nil {
-		return err
-	}
-
-	_, err = tx.Exec("DELETE FROM User WHERE id = ?", id)
+	_, err = tx.ExecContext(ctx, "DELETE FROM Network WHERE user = ?", id)
+	if err != nil {
+		return err
+	}
+
+	_, err = tx.ExecContext(ctx, "DELETE FROM User WHERE id = ?", id)
 	if err != nil {
 		return err
@@ -348,5 +376,9 @@
 	defer db.lock.RUnlock()
 
-	rows, err := db.db.Query(`SELECT id, name, addr, nick, username, realname, pass,
+	ctx, cancel := context.WithTimeout(context.TODO(), sqliteQueryTimeout)
+	defer cancel()
+
+	rows, err := db.db.QueryContext(ctx, `
+		SELECT id, name, addr, nick, username, realname, pass,
 			connect_commands, sasl_mechanism, sasl_plain_username, sasl_plain_password,
 			sasl_external_cert, sasl_external_key, enabled
@@ -392,4 +424,7 @@
 	db.lock.Lock()
 	defer db.lock.Unlock()
+
+	ctx, cancel := context.WithTimeout(context.TODO(), sqliteQueryTimeout)
+	defer cancel()
 
 	var saslMechanism, saslPlainUsername, saslPlainPassword sql.NullString
@@ -430,5 +465,5 @@
 	var err error
 	if network.ID != 0 {
-		_, err = db.db.Exec(`
+		_, err = db.db.ExecContext(ctx, `
 			UPDATE Network
 			SET name = :name, addr = :addr, nick = :nick, username = :username,
@@ -440,5 +475,5 @@
 	} else {
 		var res sql.Result
-		res, err = db.db.Exec(`
+		res, err = db.db.ExecContext(ctx, `
 			INSERT INTO Network(user, name, addr, nick, username, realname, pass,
 				connect_commands, sasl_mechanism, sasl_plain_username,
@@ -460,4 +495,7 @@
 	defer db.lock.Unlock()
 
+	ctx, cancel := context.WithTimeout(context.TODO(), sqliteQueryTimeout)
+	defer cancel()
+
 	tx, err := db.db.Begin()
 	if err != nil {
@@ -466,15 +504,15 @@
 	defer tx.Rollback()
 
-	_, err = tx.Exec("DELETE FROM DeliveryReceipt WHERE network = ?", id)
-	if err != nil {
-		return err
-	}
-
-	_, err = tx.Exec("DELETE FROM Channel WHERE network = ?", id)
-	if err != nil {
-		return err
-	}
-
-	_, err = tx.Exec("DELETE FROM Network WHERE id = ?", id)
+	_, err = tx.ExecContext(ctx, "DELETE FROM DeliveryReceipt WHERE network = ?", id)
+	if err != nil {
+		return err
+	}
+
+	_, err = tx.ExecContext(ctx, "DELETE FROM Channel WHERE network = ?", id)
+	if err != nil {
+		return err
+	}
+
+	_, err = tx.ExecContext(ctx, "DELETE FROM Network WHERE id = ?", id)
 	if err != nil {
 		return err
@@ -488,5 +526,8 @@
 	defer db.lock.RUnlock()
 
-	rows, err := db.db.Query(`SELECT
+	ctx, cancel := context.WithTimeout(context.TODO(), sqliteQueryTimeout)
+	defer cancel()
+
+	rows, err := db.db.QueryContext(ctx, `SELECT
 			id, name, key, detached, detached_internal_msgid,
 			relay_detached, reattach_on, detach_after, detach_on
@@ -521,4 +562,7 @@
 	db.lock.Lock()
 	defer db.lock.Unlock()
+
+	ctx, cancel := context.WithTimeout(context.TODO(), sqliteQueryTimeout)
+	defer cancel()
 
 	args := []interface{}{
@@ -538,5 +582,5 @@
 	var err error
 	if ch.ID != 0 {
-		_, err = db.db.Exec(`UPDATE Channel
+		_, err = db.db.ExecContext(ctx, `UPDATE Channel
 			SET network = :network, name = :name, key = :key, detached = :detached,
 				detached_internal_msgid = :detached_internal_msgid, relay_detached = :relay_detached,
@@ -545,5 +589,5 @@
 	} else {
 		var res sql.Result
-		res, err = db.db.Exec(`INSERT INTO Channel(network, name, key, detached, detached_internal_msgid, relay_detached, reattach_on, detach_after, detach_on)
+		res, err = db.db.ExecContext(ctx, `INSERT INTO Channel(network, name, key, detached, detached_internal_msgid, relay_detached, reattach_on, detach_after, detach_on)
 			VALUES (:network, :name, :key, :detached, :detached_internal_msgid, :relay_detached, :reattach_on, :detach_after, :detach_on)`, args...)
 		if err != nil {
@@ -559,5 +603,8 @@
 	defer db.lock.Unlock()
 
-	_, err := db.db.Exec("DELETE FROM Channel WHERE id = ?", id)
+	ctx, cancel := context.WithTimeout(context.TODO(), sqliteQueryTimeout)
+	defer cancel()
+
+	_, err := db.db.ExecContext(ctx, "DELETE FROM Channel WHERE id = ?", id)
 	return err
 }
@@ -567,5 +614,9 @@
 	defer db.lock.RUnlock()
 
-	rows, err := db.db.Query(`SELECT id, target, client, internal_msgid
+	ctx, cancel := context.WithTimeout(context.TODO(), sqliteQueryTimeout)
+	defer cancel()
+
+	rows, err := db.db.QueryContext(ctx, `
+		SELECT id, target, client, internal_msgid
 		FROM DeliveryReceipt
 		WHERE network = ?`, networkID)
@@ -596,4 +647,7 @@
 	defer db.lock.Unlock()
 
+	ctx, cancel := context.WithTimeout(context.TODO(), sqliteQueryTimeout)
+	defer cancel()
+
 	tx, err := db.db.Begin()
 	if err != nil {
@@ -602,5 +656,5 @@
 	defer tx.Rollback()
 
-	_, err = tx.Exec("DELETE FROM DeliveryReceipt WHERE network = ? AND client IS ?",
+	_, err = tx.ExecContext(ctx, "DELETE FROM DeliveryReceipt WHERE network = ? AND client IS ?",
 		networkID, toNullString(client))
 	if err != nil {
@@ -611,5 +665,6 @@
 		rcpt := &receipts[i]
 
-		res, err := tx.Exec(`INSERT INTO DeliveryReceipt(network, target, client, internal_msgid)
+		res, err := tx.ExecContext(ctx, `
+			INSERT INTO DeliveryReceipt(network, target, client, internal_msgid)
 			VALUES (:network, :target, :client, :internal_msgid)`,
 			sql.Named("network", networkID),
