diff --git a/ql/_dumps/Makefile b/ql/_dumps/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..cba56b0150415fb40b311ce885b8d59a497ff8b8
--- /dev/null
+++ b/ql/_dumps/Makefile
@@ -0,0 +1,3 @@
+all:
+	rm -f test.db
+	cat structs.sql | ql -db test.db
diff --git a/ql/_dumps/structs.sql b/ql/_dumps/structs.sql
new file mode 100644
index 0000000000000000000000000000000000000000..1d4da9ef191d5f3802f63251ec356b1524db0d1e
--- /dev/null
+++ b/ql/_dumps/structs.sql
@@ -0,0 +1,32 @@
+BEGIN TRANSACTION;
+
+DROP TABLE IF EXISTS artist;
+
+CREATE TABLE artist (
+  id int,
+  name string
+);
+
+DROP TABLE IF EXISTS data_types;
+
+CREATE TABLE data_types (
+  id int,
+  _uint int,
+  _uint8 int,
+  _uint16 int,
+  _uint32 int,
+  _uint64 int,
+  _int int,
+  _int8 int,
+  _int16 int,
+  _int32 int,
+  _int64 int,
+  _float32 float32,
+  _float64 float64,
+  _bool bool,
+  _string string,
+  _date time,
+  _time time
+);
+
+COMMIT;
diff --git a/ql/collection.go b/ql/collection.go
new file mode 100644
index 0000000000000000000000000000000000000000..c22157c4f2a66ccb0a492b727a0ed6e944f32632
--- /dev/null
+++ b/ql/collection.go
@@ -0,0 +1,246 @@
+/*
+  Copyright (c) 2014 José Carlos Nieto, https://menteslibres.net/xiam
+
+  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 ql
+
+import (
+	"fmt"
+	"menteslibres.net/gosexy/to"
+	"strings"
+	"time"
+	"upper.io/db"
+	"upper.io/db/util/sqlutil"
+)
+
+// Represents a QL table.
+type Table struct {
+	source *Source
+	sqlutil.T
+}
+
+func (self *Table) Find(terms ...interface{}) db.Result {
+
+	queryChunks := sqlutil.NewQueryChunks()
+
+	// No specific fields given.
+	if len(queryChunks.Fields) == 0 {
+		queryChunks.Fields = []string{`*`}
+	}
+
+	// Compiling conditions
+	queryChunks.Conditions, queryChunks.Arguments = self.compileConditions(terms)
+
+	if queryChunks.Conditions == "" {
+		queryChunks.Conditions = `1 = 1`
+	}
+
+	// Creating a result handler.
+	result := &Result{
+		self,
+		queryChunks,
+		nil,
+	}
+
+	return result
+}
+
+// Transforms conditions into arguments for sql.Exec/sql.Query
+func (self *Table) compileConditions(term interface{}) (string, []string) {
+	sql := []string{}
+	args := []string{}
+
+	switch t := term.(type) {
+	case []interface{}:
+		for i := range t {
+			rsql, rargs := self.compileConditions(t[i])
+			if rsql != "" {
+				sql = append(sql, rsql)
+				args = append(args, rargs...)
+			}
+		}
+		if len(sql) > 0 {
+			return `(` + strings.Join(sql, ` AND `) + `)`, args
+		}
+	case db.Or:
+		for i := range t {
+			rsql, rargs := self.compileConditions(t[i])
+			if rsql != "" {
+				sql = append(sql, rsql)
+				args = append(args, rargs...)
+			}
+		}
+		if len(sql) > 0 {
+			return `(` + strings.Join(sql, ` OR `) + `)`, args
+		}
+	case db.And:
+		for i := range t {
+			rsql, rargs := self.compileConditions(t[i])
+			if rsql != "" {
+				sql = append(sql, rsql)
+				args = append(args, rargs...)
+			}
+		}
+		if len(sql) > 0 {
+			return `(` + strings.Join(sql, ` AND `) + `)`, args
+		}
+	case db.Cond:
+		return self.compileStatement(t)
+	}
+
+	return "", args
+}
+
+func (self *Table) compileStatement(where db.Cond) (string, []string) {
+
+	str := make([]string, len(where))
+	arg := make([]string, len(where))
+
+	i := 0
+
+	for key, _ := range where {
+		key = strings.Trim(key, ` `)
+		chunks := strings.SplitN(key, ` `, 2)
+
+		op := `=`
+
+		if len(chunks) > 1 {
+			op = chunks[1]
+		}
+
+		str[i] = fmt.Sprintf(`%s %s ?`, chunks[0], op)
+		arg[i] = toInternal(where[key])
+
+		i++
+	}
+
+	switch len(str) {
+	case 1:
+		return str[0], arg
+	case 0:
+		return "", []string{}
+	}
+
+	return `(` + strings.Join(str, ` AND `) + `)`, arg
+}
+
+// Deletes all the rows within the collection.
+func (self *Table) Truncate() error {
+
+	_, err := self.source.doExec(
+		fmt.Sprintf(`TRUNCATE TABLE %s`, self.Name()),
+	)
+
+	return err
+}
+
+// Appends an item (map or struct) into the collection.
+func (self *Table) Append(item interface{}) (interface{}, error) {
+
+	fields, values, err := self.FieldValues(item, toInternal)
+
+	// Error ocurred, stop appending.
+	if err != nil {
+		return nil, err
+	}
+
+	tx, err := self.source.session.Begin()
+
+	if err != nil {
+		return nil, err
+	}
+
+	res, err := self.source.doExec(
+		fmt.Sprintf(`INSERT INTO %s`, self.Name()),
+		sqlFields(fields),
+		`VALUES`,
+		sqlValues(values),
+	)
+
+	if err != nil {
+		return nil, err
+	}
+
+	err = tx.Commit()
+
+	if err != nil {
+		return nil, err
+	}
+
+	var id int64
+
+	id, err = res.LastInsertId()
+
+	if err != nil {
+		return nil, err
+	}
+
+	return id, nil
+}
+
+// Returns true if the collection exists.
+func (self *Table) Exists() bool {
+	rows, err := self.source.session.Query(`
+		SELECT Name
+			FROM __Table
+		WHERE Name == ?`,
+		self.Name(),
+	)
+
+	if err != nil {
+		return false
+	}
+
+	defer rows.Close()
+
+	return rows.Next()
+}
+
+func toInternalInterface(val interface{}) interface{} {
+	return toInternal(val)
+}
+
+// Converts a Go value into internal database representation.
+func toInternal(val interface{}) string {
+
+	switch t := val.(type) {
+	case []byte:
+		return string(t)
+	case time.Time:
+		return t.Format(DateFormat)
+	case time.Duration:
+		return fmt.Sprintf(TimeFormat, int(t/time.Hour), int(t/time.Minute%60), int(t/time.Second%60), t%time.Second/time.Millisecond)
+	case bool:
+		if t == true {
+			return `1`
+		} else {
+			return `0`
+		}
+	}
+
+	return to.String(val)
+}
+
+// Convers a database representation (after auto-conversion) into a Go value.
+func toNative(val interface{}) interface{} {
+	return val
+}
diff --git a/ql/database.go b/ql/database.go
new file mode 100644
index 0000000000000000000000000000000000000000..e5fa42c87a63b8561e954cce2345d9e88fe96f39
--- /dev/null
+++ b/ql/database.go
@@ -0,0 +1,346 @@
+/*
+  Copyright (c) 2014 José Carlos Nieto, https://menteslibres.net/xiam
+
+  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 ql
+
+import (
+	"database/sql"
+	"fmt"
+	_ "github.com/cznic/ql/driver"
+	"reflect"
+	"regexp"
+	"strings"
+	"upper.io/db"
+)
+
+var Debug = true
+
+// Format for saving dates.
+var DateFormat = "2006-01-02 15:04:05"
+
+// Format for saving times.
+var TimeFormat = "%d:%02d:%02d.%d"
+
+var columnPattern = regexp.MustCompile(`^([a-z]+)\(?([0-9,]+)?\)?\s?([a-z]*)?`)
+
+const driverName = `ql`
+
+func init() {
+	db.Register(driverName, &Source{})
+}
+
+type sqlValues_t []string
+
+type Source struct {
+	config      db.Settings
+	session     *sql.DB
+	name        string
+	collections map[string]db.Collection
+}
+
+type sqlQuery struct {
+	Query []string
+	Args  []interface{}
+}
+
+func sqlCompile(terms []interface{}) *sqlQuery {
+	q := &sqlQuery{}
+
+	q.Query = []string{}
+
+	for _, term := range terms {
+		switch t := term.(type) {
+		case string:
+			q.Query = append(q.Query, t)
+		case []string:
+			for _, arg := range t {
+				q.Args = append(q.Args, arg)
+			}
+		case sqlValues_t:
+			args := make([]string, len(t))
+			for i, arg := range t {
+				args[i] = `?`
+				q.Args = append(q.Args, arg)
+			}
+			q.Query = append(q.Query, `(`+strings.Join(args, `, `)+`)`)
+		}
+	}
+
+	return q
+}
+
+func sqlFields(names []string) string {
+	return `(` + strings.Join(names, `, `) + `)`
+}
+
+func sqlValues(values []string) sqlValues_t {
+	ret := make(sqlValues_t, len(values))
+	for i, _ := range values {
+		ret[i] = values[i]
+	}
+	return ret
+}
+
+func (self *Source) doExec(terms ...interface{}) (sql.Result, error) {
+	if self.session == nil {
+		return nil, db.ErrNotConnected
+	}
+
+	chunks := sqlCompile(terms)
+
+	query := strings.Join(chunks.Query, ` `)
+
+	for i := 0; i < len(chunks.Args); i++ {
+		query = strings.Replace(query, `?`, fmt.Sprintf(`$%d`, i+1), 1)
+	}
+
+	if Debug == true {
+		fmt.Printf("Q: %s\n", query)
+		fmt.Printf("A: %v\n", chunks.Args)
+	}
+
+	return self.session.Exec(query, chunks.Args...)
+}
+
+func (self *Source) doQuery(terms ...interface{}) (*sql.Rows, error) {
+	if self.session == nil {
+		return nil, db.ErrNotConnected
+	}
+
+	chunks := sqlCompile(terms)
+
+	query := strings.Join(chunks.Query, ` `)
+
+	for i := 0; i < len(chunks.Args); i++ {
+		query = strings.Replace(query, `?`, fmt.Sprintf(`$%d`, i+1), 1)
+	}
+
+	if Debug == true {
+		fmt.Printf("Q: %s\n", query)
+		fmt.Printf("A: %v\n", chunks.Args)
+	}
+
+	return self.session.Query(query, chunks.Args...)
+}
+
+func (self *Source) doQueryRow(terms ...interface{}) (*sql.Row, error) {
+	if self.session == nil {
+		return nil, db.ErrNotConnected
+	}
+
+	chunks := sqlCompile(terms)
+
+	query := strings.Join(chunks.Query, ` `)
+
+	for i := 0; i < len(chunks.Args); i++ {
+		query = strings.Replace(query, `?`, fmt.Sprintf(`$%d`, i+1), 1)
+	}
+
+	if Debug == true {
+		fmt.Printf("Q: %s\n", query)
+		fmt.Printf("A: %v\n", chunks.Args)
+	}
+
+	return self.session.QueryRow(query, chunks.Args...), nil
+}
+
+// Returns the string name of the database.
+func (self *Source) Name() string {
+	return self.config.Database
+}
+
+// Stores database settings.
+func (self *Source) Setup(config db.Settings) error {
+	self.config = config
+	self.collections = make(map[string]db.Collection)
+	return self.Open()
+}
+
+// Returns the underlying *sql.DB instance.
+func (self *Source) Driver() interface{} {
+	return self.session
+}
+
+// Attempts to connect to a database using the stored settings.
+func (self *Source) Open() error {
+	var err error
+
+	if self.config.Database == "" {
+		return db.ErrMissingDatabaseName
+	}
+
+	self.session, err = sql.Open(`ql`, self.config.Database)
+
+	if err != nil {
+		return err
+	}
+
+	return nil
+}
+
+// Closes the current database session.
+func (self *Source) Close() error {
+	if self.session != nil {
+		return self.session.Close()
+	}
+	return nil
+}
+
+// Changes the active database.
+func (self *Source) Use(database string) error {
+	self.config.Database = database
+	return self.Open()
+}
+
+// Starts a transaction block.
+func (self *Source) Begin() error {
+	_, err := self.session.Exec(`BEGIN`)
+	return err
+}
+
+// Ends a transaction block.
+func (self *Source) End() error {
+	_, err := self.session.Exec(`END`)
+	return err
+}
+
+// Drops the currently active database.
+func (self *Source) Drop() error {
+	self.session.Query(fmt.Sprintf(`DROP DATABASE "%s"`, self.config.Database))
+	return nil
+}
+
+// Returns a list of all tables within the currently active database.
+func (self *Source) Collections() ([]string, error) {
+	var collections []string
+	var collection string
+
+	rows, err := self.session.Query(`SELECT Name FROM __Table`)
+
+	if err != nil {
+		return nil, err
+	}
+
+	defer rows.Close()
+
+	for rows.Next() {
+		if err = rows.Scan(&collection); err != nil {
+			return nil, err
+		}
+		collections = append(collections, collection)
+	}
+
+	err = rows.Err()
+
+	if err != nil {
+		return nil, err
+	}
+
+	return collections, nil
+}
+
+// Returns a collection instance by name.
+func (self *Source) Collection(name string) (db.Collection, error) {
+
+	if collection, ok := self.collections[name]; ok == true {
+		return collection, nil
+	}
+
+	table := &Table{}
+
+	table.source = self
+	table.DB = self
+	table.PrimaryKey = `id`
+
+	table.SetName = name
+
+	// Table exists?
+	if table.Exists() == false {
+		return table, db.ErrCollectionDoesNotExists
+	}
+
+	// Fetching table datatypes and mapping to internal gotypes.
+	rows, err := table.source.doQuery(
+		`SELECT
+			Name, Type
+		FROM __Column
+		WHERE
+			TableName = ?`,
+		[]string{table.Name()},
+	)
+
+	if err != nil {
+		return table, err
+	}
+
+	columns := []struct {
+		ColumnName string
+		DataType   string
+	}{}
+
+	err = table.FetchRows(&columns, rows)
+
+	if err != nil {
+		return nil, err
+	}
+
+	table.ColumnTypes = make(map[string]reflect.Kind, len(columns))
+
+	for _, column := range columns {
+
+		column.ColumnName = strings.ToLower(column.ColumnName)
+		column.DataType = strings.ToLower(column.DataType)
+
+		results := columnPattern.FindStringSubmatch(column.DataType)
+
+		// Default properties.
+		dextra := ""
+		dtype := `varchar`
+
+		dtype = results[1]
+
+		if len(results) > 3 {
+			dextra = results[3]
+		}
+
+		ctype := reflect.String
+
+		// Guessing datatypes.
+		switch dtype {
+		case `smallint`, `integer`, `bigint`, `serial`, `bigserial`:
+			if dextra == `unsigned` {
+				ctype = reflect.Uint64
+			} else {
+				ctype = reflect.Int64
+			}
+		case `real`, `double`:
+			ctype = reflect.Float64
+		}
+
+		table.ColumnTypes[column.ColumnName] = ctype
+	}
+
+	self.collections[name] = table
+
+	return table, nil
+}
diff --git a/ql/database_test.go b/ql/database_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..74d90d5ec6612d2bd54285a35a6207cf2ffa3db1
--- /dev/null
+++ b/ql/database_test.go
@@ -0,0 +1,702 @@
+/*
+  Copyright (c) 2014 José Carlos Nieto, https://menteslibres.net/xiam
+
+  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.
+*/
+
+/*
+	Tests for the ql wrapper.
+
+	Execute the Makefile in ./_dumps/ to create the expected database structure.
+
+	cd _dumps
+	make
+	cd ..
+	go test
+*/
+package ql
+
+import (
+	"database/sql"
+	"fmt"
+	"menteslibres.net/gosexy/to"
+	"reflect"
+	"strings"
+	"testing"
+	"time"
+	"upper.io/db"
+)
+
+// Wrapper.
+const wrapperName = "ql"
+
+// Wrapper settings.
+const dbname = "file://_dumps/test.db"
+
+// Global settings for tests.
+var settings = db.Settings{
+	Database: dbname,
+}
+
+// Structure for testing conversions and datatypes.
+type testValuesStruct struct {
+	Uint   uint   `field:"_uint"`
+	Uint8  uint8  `field:"_uint8"`
+	Uint16 uint16 `field:"_uint16"`
+	Uint32 uint32 `field:"_uint32"`
+	Uint64 uint64 `field:"_uint64"`
+
+	Int   int   `field:"_int"`
+	Int8  int8  `field:"_int8"`
+	Int16 int16 `field:"_int16"`
+	Int32 int32 `field:"_int32"`
+	Int64 int64 `field:"_int64"`
+
+	Float32 float32 `field:"_float32"`
+	Float64 float64 `field:"_float64"`
+
+	Bool   bool   `field:"_bool"`
+	String string `field:"_string"`
+
+	Date time.Time     `field:"_date"`
+	Time time.Duration `field:"_time"`
+}
+
+// Declaring some values to insert, we expect the same values to be returned.
+var testValues = testValuesStruct{
+	1, 1, 1, 1, 1,
+	-1, -1, -1, -1, -1,
+	1.337, 1.337,
+	true,
+	"Hello world!",
+	time.Date(2012, 7, 28, 1, 2, 3, 0, time.UTC),
+	time.Second * time.Duration(7331),
+}
+
+// Enabling outputting some information to stdout (like the SQL query and its
+// arguments), useful for development.
+func TestEnableDebug(t *testing.T) {
+	Debug = true
+}
+
+// Trying to open an empty datasource, it must fail.
+func TestOpenFailed(t *testing.T) {
+	_, err := db.Open(wrapperName, db.Settings{})
+
+	if err == nil {
+		t.Errorf("Expecting an error.")
+	}
+}
+
+// Truncates all collections.
+func TestTruncate(t *testing.T) {
+
+	var err error
+
+	// Opening database.
+	sess, err := db.Open(wrapperName, settings)
+
+	if err != nil {
+		t.Fatalf(err.Error())
+	}
+
+	// We should close the database when it's no longer in use.
+	defer sess.Close()
+
+	// Getting a list of all collections in this database.
+	collections, err := sess.Collections()
+	fmt.Printf("%v\n", collections)
+
+	if err != nil {
+		t.Fatalf(err.Error())
+	}
+
+	for _, name := range collections {
+
+		// Pointing the collection.
+		col, err := sess.Collection(name)
+		if err != nil {
+			t.Fatalf(err.Error())
+		}
+
+		// Since this is a SQL collection (table), the structure must exists before
+		// we can use it.
+		exists := col.Exists()
+
+		if exists == true {
+			// Truncating the structure, if exists.
+			err = col.Truncate()
+
+			if err != nil {
+				t.Fatalf(err.Error())
+			}
+		}
+
+	}
+}
+
+// This test appends some data into the "artist" table.
+func TestAppend(t *testing.T) {
+
+	var err error
+	var id interface{}
+
+	// Opening database.
+	sess, err := db.Open(wrapperName, settings)
+
+	if err != nil {
+		t.Fatalf(err.Error())
+	}
+
+	// We should close the database when it's no longer in use.
+	defer sess.Close()
+
+	// Getting a pointer to the "artist" collection.
+	artist, err := sess.Collection("artist")
+
+	if err != nil {
+		t.Fatalf(err.Error())
+	}
+
+	// Appending a map.
+	id, err = artist.Append(map[string]string{
+		"name": "Ozzie",
+	})
+
+	if to.Int64(id) == 0 {
+		t.Fatalf("Expecting an ID.")
+	}
+
+	// Appending a struct.
+	id, err = artist.Append(struct {
+		Name string `field:name`
+	}{
+		"Flea",
+	})
+
+	if to.Int64(id) == 0 {
+		t.Fatalf("Expecting an ID.")
+	}
+
+	// Appending a struct (using tags to specify the field name).
+	id, err = artist.Append(struct {
+		ArtistName string `field:"name"`
+	}{
+		"Slash",
+	})
+
+	if to.Int64(id) == 0 {
+		t.Fatalf("Expecting an ID.")
+	}
+
+}
+
+// This test tries to use an empty filter and count how many elements were
+// added into the artist collection.
+func TestResultCount(t *testing.T) {
+
+	var err error
+	var res db.Result
+
+	// Opening database.
+	sess, err := db.Open(wrapperName, settings)
+
+	if err != nil {
+		t.Fatalf(err.Error())
+	}
+
+	defer sess.Close()
+
+	// We should close the database when it's no longer in use.
+	artist, _ := sess.Collection("artist")
+
+	res = artist.Find()
+
+	// Counting all the matching rows.
+	total, err := res.Count()
+
+	if err != nil {
+		t.Fatalf(err.Error())
+	}
+
+	if total == 0 {
+		t.Fatalf("Should not be empty, we've just added some rows!")
+	}
+
+}
+
+// This test uses and result and tries to fetch items one by one.
+func TestResultFetch(t *testing.T) {
+
+	var err error
+	var res db.Result
+
+	// Opening database.
+	sess, err := db.Open(wrapperName, settings)
+
+	if err != nil {
+		t.Fatalf(err.Error())
+	}
+
+	// We should close the database when it's no longer in use.
+	defer sess.Close()
+
+	artist, err := sess.Collection("artist")
+
+	if err != nil {
+		t.Fatalf(err.Error())
+	}
+
+	// Testing map
+	res = artist.Find()
+
+	row_m := map[string]interface{}{}
+
+	for {
+		err = res.Next(&row_m)
+
+		if err == db.ErrNoMoreRows {
+			// No more row_ms left.
+			break
+		}
+
+		if err == nil {
+			if to.Int64(row_m["id"]) == 0 {
+				t.Fatalf("Expecting a not null ID.")
+			}
+			if to.String(row_m["name"]) == "" {
+				t.Fatalf("Expecting a name.")
+			}
+		} else {
+			t.Fatalf(err.Error())
+		}
+	}
+
+	res.Close()
+
+	// Testing struct
+	row_s := struct {
+		Id   uint64
+		Name string
+	}{}
+
+	res = artist.Find()
+
+	for {
+		err = res.Next(&row_s)
+
+		if err == db.ErrNoMoreRows {
+			// No more row_s' left.
+			break
+		}
+
+		if err == nil {
+			if row_s.Id == 0 {
+				t.Fatalf("Expecting a not null ID.")
+			}
+			if row_s.Name == "" {
+				t.Fatalf("Expecting a name.")
+			}
+		} else {
+			t.Fatalf(err.Error())
+		}
+	}
+
+	res.Close()
+
+	// Testing tagged struct
+	row_t := struct {
+		Value1 uint64 `field:"id"`
+		Value2 string `field:"name"`
+	}{}
+
+	res = artist.Find()
+
+	for {
+		err = res.Next(&row_t)
+
+		if err == db.ErrNoMoreRows {
+			// No more row_t's left.
+			break
+		}
+
+		if err == nil {
+			if row_t.Value1 == 0 {
+				t.Fatalf("Expecting a not null ID.")
+			}
+			if row_t.Value2 == "" {
+				t.Fatalf("Expecting a name.")
+			}
+		} else {
+			t.Fatalf(err.Error())
+		}
+	}
+
+	res.Close()
+
+	// Testing Result.All() with a slice of maps.
+	res = artist.Find()
+
+	all_rows_m := []map[string]interface{}{}
+	err = res.All(&all_rows_m)
+
+	if err != nil {
+		t.Fatalf(err.Error())
+	}
+
+	for _, single_row_m := range all_rows_m {
+		if to.Int64(single_row_m["id"]) == 0 {
+			t.Fatalf("Expecting a not null ID.")
+		}
+	}
+
+	// Testing Result.All() with a slice of structs.
+	res = artist.Find()
+
+	all_rows_s := []struct {
+		Id   uint64
+		Name string
+	}{}
+	err = res.All(&all_rows_s)
+
+	if err != nil {
+		t.Fatalf(err.Error())
+	}
+
+	for _, single_row_s := range all_rows_s {
+		if single_row_s.Id == 0 {
+			t.Fatalf("Expecting a not null ID.")
+		}
+	}
+
+	// Testing Result.All() with a slice of tagged structs.
+	res = artist.Find()
+
+	all_rows_t := []struct {
+		Value1 uint64 `field:"id"`
+		Value2 string `field:"name"`
+	}{}
+	err = res.All(&all_rows_t)
+
+	if err != nil {
+		t.Fatalf(err.Error())
+	}
+
+	for _, single_row_t := range all_rows_t {
+		if single_row_t.Value1 == 0 {
+			t.Fatalf("Expecting a not null ID.")
+		}
+	}
+}
+
+// This test tries to update some previously added rows.
+func TestUpdate(t *testing.T) {
+	var err error
+
+	// Opening database.
+	sess, err := db.Open(wrapperName, settings)
+
+	if err != nil {
+		t.Fatalf(err.Error())
+	}
+
+	// We should close the database when it's no longer in use.
+	defer sess.Close()
+
+	// Getting a pointer to the "artist" collection.
+	artist, err := sess.Collection("artist")
+
+	if err != nil {
+		t.Fatalf(err.Error())
+	}
+
+	// Value
+	value := struct {
+		Id   uint64
+		Name string
+	}{}
+
+	// Getting the first artist.
+	res := artist.Find(db.Cond{"id !=": 0}).Limit(1)
+
+	err = res.One(&value)
+
+	if err != nil {
+		t.Fatalf(err.Error())
+	}
+
+	// Updating with a map
+	row_m := map[string]interface{}{
+		"name": strings.ToUpper(value.Name),
+	}
+
+	err = res.Update(row_m)
+
+	if err != nil {
+		t.Fatalf(err.Error())
+	}
+
+	err = res.One(&value)
+
+	if err != nil {
+		t.Fatalf(err.Error())
+	}
+
+	if value.Name != row_m["name"] {
+		t.Fatalf("Expecting a modification.")
+	}
+
+	// Updating with a struct
+	row_s := struct {
+		Name string
+	}{strings.ToLower(value.Name)}
+
+	err = res.Update(row_s)
+
+	if err != nil {
+		t.Fatalf(err.Error())
+	}
+
+	err = res.One(&value)
+
+	if err != nil {
+		t.Fatalf(err.Error())
+	}
+
+	if value.Name != row_s.Name {
+		t.Fatalf("Expecting a modification.")
+	}
+
+	// Updating with a tagged struct
+	row_t := struct {
+		Value1 string `field:"name"`
+	}{strings.Replace(value.Name, "z", "Z", -1)}
+
+	err = res.Update(row_t)
+
+	if err != nil {
+		t.Fatalf(err.Error())
+	}
+
+	err = res.One(&value)
+
+	if err != nil {
+		t.Fatalf(err.Error())
+	}
+
+	if value.Name != row_t.Value1 {
+		t.Fatalf("Expecting a modification.")
+	}
+
+}
+
+// This test tries to remove some previously added rows.
+func TestRemove(t *testing.T) {
+
+	var err error
+
+	// Opening database.
+	sess, err := db.Open(wrapperName, settings)
+
+	if err != nil {
+		t.Fatalf(err.Error())
+	}
+
+	// We should close the database when it's no longer in use.
+	defer sess.Close()
+
+	// Getting a pointer to the "artist" collection.
+	artist, err := sess.Collection("artist")
+
+	if err != nil {
+		t.Fatalf(err.Error())
+	}
+
+	// Getting the artist with id = 1
+	res := artist.Find(db.Cond{"id": 1})
+
+	// Trying to remove the row.
+	err = res.Remove()
+
+	if err != nil {
+		t.Fatalf(err.Error())
+	}
+}
+
+// This test tries to add many different datatypes to a single row in a
+// collection, then it tries to get the stored datatypes and check if the
+// stored and the original values match.
+func TestDataTypes(t *testing.T) {
+	var res db.Result
+
+	// Opening database.
+	sess, err := db.Open(wrapperName, settings)
+
+	if err != nil {
+		t.Fatalf(err.Error())
+	}
+
+	// We should close the database when it's no longer in use.
+	defer sess.Close()
+
+	// Getting a pointer to the "data_types" collection.
+	dataTypes, err := sess.Collection("data_types")
+	dataTypes.Truncate()
+
+	// Appending our test subject.
+	id, err := dataTypes.Append(testValues)
+
+	if err != nil {
+		t.Fatalf(err.Error())
+	}
+
+	// Trying to get the same subject we added.
+	res = dataTypes.Find(db.Cond{"id": id})
+
+	exists, err := res.Count()
+
+	if err != nil {
+		t.Fatalf(err.Error())
+	}
+
+	if exists == 0 {
+		t.Errorf("Expecting an item.")
+	}
+
+	// Trying to dump the subject into an empty structure of the same type.
+	var item testValuesStruct
+	res.One(&item)
+
+	// The original value and the test subject must match.
+	if reflect.DeepEqual(item, testValues) == false {
+		t.Errorf("Struct is different.")
+	}
+}
+
+// We are going to benchmark the engine, so this is no longed needed.
+func TestDisableDebug(t *testing.T) {
+	Debug = false
+}
+
+// Benchmarking raw database/sql.
+func BenchmarkAppendRaw(b *testing.B) {
+	sess, err := db.Open(wrapperName, settings)
+
+	if err != nil {
+		b.Fatalf(err.Error())
+	}
+
+	defer sess.Close()
+
+	artist, err := sess.Collection("artist")
+	artist.Truncate()
+
+	driver := sess.Driver().(*sql.DB)
+
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		_, err := driver.Exec(`INSERT INTO artist (name) VALUES('Hayao Miyazaki')`)
+		if err != nil {
+			b.Fatalf(err.Error())
+		}
+	}
+}
+
+// Benchmarking Append().
+//
+// Contributed by wei2912
+// See: https://github.com/gosexy/db/issues/20#issuecomment-20097801
+func BenchmarkAppendDbItem(b *testing.B) {
+	sess, err := db.Open(wrapperName, settings)
+
+	if err != nil {
+		b.Fatalf(err.Error())
+	}
+
+	defer sess.Close()
+
+	artist, err := sess.Collection("artist")
+	artist.Truncate()
+
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		_, err = artist.Append(map[string]string{"name": "Leonardo DaVinci"})
+		if err != nil {
+			b.Fatalf(err.Error())
+		}
+	}
+}
+
+// Benchmarking Append() with transactions.
+//
+// Contributed by wei2912
+// See: https://github.com/gosexy/db/issues/20#issuecomment-20167939
+// Applying the BEGIN and END transaction optimizations.
+func BenchmarkAppendDbItem_Transaction(b *testing.B) {
+	sess, err := db.Open(wrapperName, settings)
+
+	if err != nil {
+		b.Fatalf(err.Error())
+	}
+
+	defer sess.Close()
+
+	artist, err := sess.Collection("artist")
+	artist.Truncate()
+
+	err = sess.Begin()
+	if err != nil {
+		b.Fatalf(err.Error())
+	}
+
+	for i := 0; i < b.N; i++ {
+		_, err = artist.Append(map[string]string{"name": "Isaac Asimov"})
+		if err != nil {
+			b.Fatalf(err.Error())
+		}
+	}
+
+	err = sess.End()
+	if err != nil {
+		b.Fatalf(err.Error())
+	}
+}
+
+// Benchmarking Append with a struct.
+func BenchmarkAppendStruct(b *testing.B) {
+	sess, err := db.Open(wrapperName, settings)
+
+	if err != nil {
+		b.Fatalf(err.Error())
+	}
+
+	defer sess.Close()
+
+	artist, err := sess.Collection("artist")
+	artist.Truncate()
+
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		_, err = artist.Append(struct{ Name string }{"John Lennon"})
+		if err != nil {
+			b.Fatalf(err.Error())
+		}
+	}
+}
diff --git a/ql/result.go b/ql/result.go
new file mode 100644
index 0000000000000000000000000000000000000000..cb8c3dfb41769c4981ebefd02182b450173a3b8f
--- /dev/null
+++ b/ql/result.go
@@ -0,0 +1,251 @@
+/*
+  Copyright (c) 2014 José Carlos Nieto, https://menteslibres.net/xiam
+
+  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 ql
+
+import (
+	"database/sql"
+	"fmt"
+	"strings"
+	"upper.io/db"
+	"upper.io/db/util/sqlutil"
+)
+
+type counter struct {
+	Total uint64 `field:"total"`
+}
+
+type Result struct {
+	table       *Table
+	queryChunks *sqlutil.QueryChunks
+	// This is the main query cursor. It starts as a nil value.
+	cursor *sql.Rows
+}
+
+// Executes a SELECT statement that can feed Next(), All() or One().
+func (self *Result) setCursor() error {
+	var err error
+	// We need a cursor, if the cursor does not exists yet then we create one.
+	if self.cursor == nil {
+		self.cursor, err = self.table.source.doQuery(
+			// Mandatory SQL.
+			fmt.Sprintf(
+				`SELECT %s FROM "%s" WHERE %s`,
+				// Fields.
+				strings.Join(self.queryChunks.Fields, `, `),
+				// Table name
+				self.table.Name(),
+				// Conditions
+				self.queryChunks.Conditions,
+			),
+			// Arguments
+			self.queryChunks.Arguments,
+			// Optional SQL
+			self.queryChunks.Sort,
+			self.queryChunks.Limit,
+			self.queryChunks.Offset,
+		)
+	}
+	return err
+}
+
+// Determines the maximum limit of results to be returned.
+func (self *Result) Limit(n uint) db.Result {
+	self.queryChunks.Limit = fmt.Sprintf(`LIMIT %d`, n)
+	return self
+}
+
+// Determines how many documents will be skipped before starting to grab
+// results.
+func (self *Result) Skip(n uint) db.Result {
+	self.queryChunks.Offset = fmt.Sprintf(`OFFSET %d`, n)
+	return self
+}
+
+// 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 (self *Result) Sort(fields ...string) db.Result {
+	sort := make([]string, 0, len(fields))
+
+	for _, field := range fields {
+		if strings.HasPrefix(field, `-`) == true {
+			sort = append(sort, field[1:]+` DESC`)
+		} else {
+			sort = append(sort, field+` ASC`)
+		}
+	}
+
+	self.queryChunks.Sort = `ORDER BY ` + strings.Join(sort, `, `)
+
+	return self
+}
+
+// Retrieves only the given fields.
+func (self *Result) Select(fields ...string) db.Result {
+	self.queryChunks.Fields = fields
+	return self
+}
+
+// Dumps all results into a pointer to an slice of structs or maps.
+func (self *Result) All(dst interface{}) error {
+	var err error
+
+	if self.cursor != nil {
+		return db.ErrQueryIsPending
+	}
+
+	// Current cursor.
+	err = self.setCursor()
+
+	if err != nil {
+		return err
+	}
+
+	defer self.Close()
+
+	// Fetching all results within the cursor.
+	err = self.table.T.FetchRows(dst, self.cursor)
+
+	return err
+}
+
+// Fetches only one result from the resultset.
+func (self *Result) One(dst interface{}) error {
+	var err error
+
+	if self.cursor != nil {
+		return db.ErrQueryIsPending
+	}
+
+	defer self.Close()
+
+	err = self.Next(dst)
+
+	return err
+}
+
+// Fetches the next result from the resultset.
+func (self *Result) Next(dst interface{}) error {
+
+	var err error
+
+	// Current cursor.
+	err = self.setCursor()
+
+	if err != nil {
+		self.Close()
+	}
+
+	// Fetching the next result from the cursor.
+	err = self.table.T.FetchRow(dst, self.cursor)
+
+	if err != nil {
+		self.Close()
+	}
+
+	return err
+}
+
+// Removes the matching items from the collection.
+func (self *Result) Remove() error {
+	var err error
+	_, err = self.table.source.doExec(
+		fmt.Sprintf(
+			`DELETE FROM "%s" WHERE %s`,
+			self.table.Name(),
+			self.queryChunks.Conditions,
+		),
+		self.queryChunks.Arguments,
+	)
+	return err
+
+}
+
+// Updates matching items from the collection with values of the given map or
+// struct.
+func (self *Result) Update(values interface{}) error {
+
+	ff, vv, err := self.table.FieldValues(values, toInternal)
+
+	if err != nil {
+		return err
+	}
+
+	total := len(ff)
+
+	updateFields := make([]string, total)
+	updateArgs := make([]string, total)
+
+	for i := 0; i < total; i++ {
+		updateFields[i] = fmt.Sprintf(`%s = ?`, ff[i])
+		updateArgs[i] = vv[i]
+	}
+
+	_, err = self.table.source.doExec(
+		fmt.Sprintf(
+			`UPDATE "%s" SET %s WHERE %s`,
+			self.table.Name(),
+			strings.Join(updateFields, `, `),
+			self.queryChunks.Conditions,
+		),
+		updateArgs,
+		self.queryChunks.Arguments,
+	)
+
+	return err
+}
+
+// Closes the result set.
+func (self *Result) Close() error {
+	var err error
+	if self.cursor != nil {
+		err = self.cursor.Close()
+		self.cursor = nil
+	}
+	return err
+}
+
+// Counts matching elements.
+func (self *Result) Count() (uint64, error) {
+
+	rows, err := self.table.source.doQuery(
+		fmt.Sprintf(
+			`SELECT COUNT(1) AS total FROM "%s" WHERE %s`,
+			self.table.Name(),
+			self.queryChunks.Conditions,
+		),
+		self.queryChunks.Arguments,
+	)
+
+	if err != nil {
+		return 0, err
+	}
+
+	dst := counter{}
+	self.table.T.FetchRow(&dst, rows)
+
+	rows.Close()
+
+	return dst.Total, nil
+}