diff --git a/internal/debug/debug.go b/internal/debug/debug.go
new file mode 100644
index 0000000000000000000000000000000000000000..826bbcb5650e78fa7d7df2f2d74a8f9edcb18b6a
--- /dev/null
+++ b/internal/debug/debug.go
@@ -0,0 +1,83 @@
+// Copyright (c) 2012-2015 The upper.io/db authors. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+package debug
+
+import (
+	"fmt"
+	"log"
+	"os"
+	"regexp"
+	"strings"
+
+	"upper.io/db"
+)
+
+var (
+	reInvisibleChars       = regexp.MustCompile(`[\s\r\n\t]+`)
+	reColumnCompareExclude = regexp.MustCompile(`[^a-zA-Z0-9]`)
+)
+
+func init() {
+	if os.Getenv(db.EnvEnableDebug) != "" {
+		db.Debug = true
+	}
+}
+
+// Debug is used for printing SQL queries and arguments.
+type Debug struct {
+	SQL   string
+	Args  []interface{}
+	Err   error
+	Start int64
+	End   int64
+}
+
+// Print prints a debug message to stdlog.
+func (d *Debug) Print() {
+	d.SQL = reInvisibleChars.ReplaceAllString(d.SQL, ` `)
+	d.SQL = strings.TrimSpace(d.SQL)
+
+	s := make([]string, 0, 3)
+
+	if d.SQL != "" {
+		s = append(s, fmt.Sprintf(`Q: %s`, d.SQL))
+	}
+
+	if len(d.Args) > 0 {
+		s = append(s, fmt.Sprintf(`A: %v`, d.Args))
+	}
+
+	if d.Err != nil {
+		s = append(s, fmt.Sprintf(`E: %q`, d.Err))
+	}
+
+	s = append(s, fmt.Sprintf(`T: %0.5fs`, float64(d.End-d.Start)/float64(1e9)))
+
+	log.Printf("\n\t%s\n\n", strings.Join(s, "\n\t"))
+}
+
+func Log(query string, args []interface{}, err error, start int64, end int64) {
+	if db.Debug {
+		d := Debug{query, args, err, start, end}
+		d.Print()
+	}
+}
diff --git a/internal/sqladapter/database.go b/internal/sqladapter/database.go
index 294d80fad552fb68444f897c3d2b348c8c18b7b6..830c5a75a08b7ec7cd0c991bb055987b039e84a3 100644
--- a/internal/sqladapter/database.go
+++ b/internal/sqladapter/database.go
@@ -6,13 +6,13 @@ import (
 	"time"
 
 	"github.com/jmoiron/sqlx"
+	"upper.io/builder"
+	"upper.io/builder/sqlgen"
 	"upper.io/cache"
 	"upper.io/db"
-	"upper.io/builder"
 	"upper.io/db/internal/adapter"
+	"upper.io/db/internal/debug"
 	"upper.io/db/internal/schema"
-	"upper.io/builder/sqlgen"
-	"upper.io/db/internal/sqlutil"
 	"upper.io/db/internal/sqlutil/tx"
 )
 
@@ -186,7 +186,7 @@ func (d *BaseDatabase) Exec(stmt *sqlgen.Statement, args ...interface{}) (sql.Re
 
 		defer func() {
 			end = time.Now().UnixNano()
-			sqlutil.Log(query, args, err, start, end)
+			debug.Log(query, args, err, start, end)
 		}()
 	}
 
@@ -209,7 +209,7 @@ func (d *BaseDatabase) Query(stmt *sqlgen.Statement, args ...interface{}) (*sqlx
 
 		defer func() {
 			end = time.Now().UnixNano()
-			sqlutil.Log(query, args, err, start, end)
+			debug.Log(query, args, err, start, end)
 		}()
 	}
 
@@ -232,7 +232,7 @@ func (d *BaseDatabase) QueryRow(stmt *sqlgen.Statement, args ...interface{}) (*s
 
 		defer func() {
 			end = time.Now().UnixNano()
-			sqlutil.Log(query, args, err, start, end)
+			debug.Log(query, args, err, start, end)
 		}()
 	}
 
diff --git a/internal/sqlutil/result/result.go b/internal/sqlutil/result/result.go
new file mode 100644
index 0000000000000000000000000000000000000000..2e50932e1e4e16bdc991fbe3fed76d2c375a812c
--- /dev/null
+++ b/internal/sqlutil/result/result.go
@@ -0,0 +1,170 @@
+// Copyright (c) 2012-2015 The upper.io/db authors. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+package result
+
+import (
+	"upper.io/db"
+)
+
+type Result struct {
+	b       db.QueryBuilder
+	table   string
+	iter    db.Iterator
+	limit   int
+	offset  int
+	fields  []interface{}
+	columns []interface{}
+	orderBy []interface{}
+	groupBy []interface{}
+	conds   []interface{}
+}
+
+// NewResult creates and results a new result set on the given table, this set
+// is limited by the given sqlgen.Where conditions.
+func NewResult(b db.QueryBuilder, table string, conds []interface{}) *Result {
+	return &Result{
+		b:     b,
+		table: table,
+		conds: conds,
+	}
+}
+
+// Sets conditions for reducing the working set.
+func (r *Result) Where(conds ...interface{}) db.Result {
+	r.conds = conds
+	return r
+}
+
+// Determines the maximum limit of results to be returned.
+func (r *Result) Limit(n uint) db.Result {
+	r.limit = int(n)
+	return r
+}
+
+// Determines how many documents will be skipped before starting to grab
+// results.
+func (r *Result) Skip(n uint) db.Result {
+	r.offset = int(n)
+	return r
+}
+
+// Used to group results that have the same value in the same column or
+// columns.
+func (r *Result) Group(fields ...interface{}) db.Result {
+	r.groupBy = fields
+	return r
+}
+
+// Determines sorting of results according to the provided names. Fields may be
+// prefixed by - (minus) which means descending order, ascending order would be
+// used otherwise.
+func (r *Result) Sort(fields ...interface{}) db.Result {
+	r.orderBy = fields
+	return r
+}
+
+// Retrieves only the given fields.
+func (r *Result) Select(fields ...interface{}) db.Result {
+	r.fields = fields
+	return r
+}
+
+// Dumps all results into a pointer to an slice of structs or maps.
+func (r *Result) All(dst interface{}) error {
+	return r.buildSelect().Iterator().All(dst)
+}
+
+// Fetches only one result from the resultset.
+func (r *Result) One(dst interface{}) error {
+	return r.buildSelect().Iterator().One(dst)
+}
+
+// Fetches the next result from the resultset.
+func (r *Result) Next(dst interface{}) (err error) {
+	if r.iter == nil {
+		r.iter = r.buildSelect().Iterator()
+	}
+	if !r.iter.Next(dst) {
+		return r.iter.Err()
+	}
+	return nil
+}
+
+// Removes the matching items from the collection.
+func (r *Result) Remove() error {
+	q := r.b.DeleteFrom(r.table).
+		Where(r.conds...).
+		Limit(r.limit)
+
+	_, err := q.Exec()
+	return err
+}
+
+// Closes the result set.
+func (r *Result) Close() error {
+	if r.iter != nil {
+		return r.iter.Close()
+	}
+	return nil
+}
+
+// Updates matching items from the collection with values of the given map or
+// struct.
+func (r *Result) Update(values interface{}) error {
+	q := r.b.Update(r.table).
+		Set(values).
+		Where(r.conds...).
+		Limit(r.limit)
+
+	_, err := q.Exec()
+	return err
+}
+
+// Counts the elements within the main conditions of the set.
+func (r *Result) Count() (uint64, error) {
+	counter := struct {
+		Count uint64 `db:"_t"`
+	}{}
+
+	q := r.buildSelect()
+	q.Columns(db.Raw{"COUNT(1) AS _t"}).Limit(1)
+
+	if err := q.Iterator().One(&counter); err != nil {
+		return 0, err
+	}
+
+	return counter.Count, nil
+}
+
+func (r *Result) buildSelect() db.QuerySelector {
+	q := r.b.Select(r.fields...)
+
+	q.From(r.table)
+	q.Where(r.conds...)
+	q.Limit(r.limit)
+	q.Offset(r.offset)
+
+	q.GroupBy(r.groupBy...)
+	q.OrderBy(r.orderBy...)
+
+	return q
+}
diff --git a/internal/sqlutil/tx/tx.go b/internal/sqlutil/tx/tx.go
new file mode 100644
index 0000000000000000000000000000000000000000..18ebbf3c937be3a329cc778c26aa99d471539c7d
--- /dev/null
+++ b/internal/sqlutil/tx/tx.go
@@ -0,0 +1,46 @@
+// Copyright (c) 2012-2015 The upper.io/db authors. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+package sqltx
+
+import (
+	"github.com/jmoiron/sqlx"
+)
+
+type Tx struct {
+	*sqlx.Tx
+	done bool
+}
+
+func New(tx *sqlx.Tx) *Tx {
+	return &Tx{Tx: tx}
+}
+
+func (t *Tx) Done() bool {
+	return t.done
+}
+
+func (t *Tx) Commit() (err error) {
+	if err = t.Tx.Commit(); err == nil {
+		t.done = true
+	}
+	return err
+}
diff --git a/postgresql/database.go b/postgresql/database.go
index dfd110521ffb632f52f2c5372dd7aa2cf12a6c82..6c112a03d5ff41b0e42b3780faacd7e97d6bbfcf 100644
--- a/postgresql/database.go
+++ b/postgresql/database.go
@@ -27,9 +27,9 @@ import (
 
 	"github.com/jmoiron/sqlx"
 	_ "github.com/lib/pq" // PostgreSQL driver.
+	"upper.io/builder/sqlgen"
 	"upper.io/db"
 	"upper.io/db/internal/sqladapter"
-	"upper.io/builder/sqlgen"
 )
 
 type database struct {
@@ -89,7 +89,7 @@ func (d *database) Open() error {
 
 // Setup configures the adapter.
 func (d *database) Setup(connURL db.ConnectionURL) error {
-	d.BaseDatabase = sqladapter.NewDatabase(d, connURL, template.Template)
+	d.BaseDatabase = sqladapter.NewDatabase(d, connURL, template)
 	return d.Open()
 }
 
diff --git a/postgresql/postgresql.go b/postgresql/postgresql.go
index f0d51db49b9f62f222e029fa2fd4785b21fe5e2e..bb1fa95b58f1079c5d10438a649c09c8862fcb33 100644
--- a/postgresql/postgresql.go
+++ b/postgresql/postgresql.go
@@ -22,19 +22,19 @@
 package postgresql // import "upper.io/db/postgresql"
 
 import (
+	"upper.io/builder/sqlgen"
 	"upper.io/cache"
 	"upper.io/db"
-	"upper.io/builder/sqlgen"
-	"upper.io/db/internal/sqlutil"
 )
 
 // Adapter is the public name of the adapter.
 const Adapter = `postgresql`
 
-var template *sqlutil.TemplateWithUtils
+var template *sqlgen.Template
 
 func init() {
-	template = sqlutil.NewTemplateWithUtils(&sqlgen.Template{
+
+	template = &sqlgen.Template{
 		ColumnSeparator:     adapterColumnSeparator,
 		IdentifierSeparator: adapterIdentifierSeparator,
 		IdentifierQuote:     adapterIdentifierQuote,
@@ -68,7 +68,7 @@ func init() {
 		CountLayout:         adapterSelectCountLayout,
 		GroupByLayout:       adapterGroupByLayout,
 		Cache:               cache.NewCache(),
-	})
+	}
 
 	db.Register(Adapter, &database{})
 }