diff --git a/mysql/_example/main.go b/mysql/_example/main.go
index 8b073845520baa9c21248fb502760871d4a9d254..f84ee44873407e37e7b88aed88fd946b46579ef0 100644
--- a/mysql/_example/main.go
+++ b/mysql/_example/main.go
@@ -6,13 +6,13 @@ import (
 	"os"
 	"time"
 
-	"upper.io/db"         // Imports the main db package.
-	_ "upper.io/db/mysql" // Improts the mysql adapter.
+	"upper.io/db"       // Imports the main db package.
+	"upper.io/db/mysql" // Improts the mysql adapter.
 )
 
-var settings = db.Settings{
+var settings = mysql.ConnectionURL{
 	Database: `upperio_tests`, // Database name.
-	Host:     `127.0.0.1`,
+	Address:  db.ParseAddress(`127.0.0.1`),
 	User:     `upperio_tests`,  // Database username.
 	Password: `upperio_secret`, // Database password.
 }
@@ -27,8 +27,8 @@ type Birthday struct {
 
 func main() {
 
-	if os.Getenv("TEST_HOST") != "" {
-		settings.Host = os.Getenv("TEST_HOST")
+	if addr := os.Getenv("TEST_HOST"); addr != "" {
+		settings.Address = db.ParseAddress(addr)
 	}
 
 	// Attemping to establish a connection to the database.
diff --git a/mysql/collection.go b/mysql/collection.go
index 429099daaa7d7ac57f7474a07352feb61542cc61..5a70b2bd14113ff684b8e8f94dee0534d11a615d 100644
--- a/mysql/collection.go
+++ b/mysql/collection.go
@@ -23,35 +23,27 @@ package mysql
 
 import (
 	"database/sql"
-	"strings"
 
-	"upper.io/db"
+	"upper.io/builder"
 	"upper.io/builder/sqlgen"
-	"upper.io/db/internal/sqlutil"
-	"upper.io/db/internal/sqlutil/result"
+	"upper.io/db"
+	"upper.io/db/internal/sqladapter"
 )
 
 type table struct {
-	sqlutil.T
-	*database
+	sqladapter.Collection
 }
 
 var _ = db.Collection(&table{})
 
-// Find creates a result set with the given conditions.
-func (t *table) Find(terms ...interface{}) db.Result {
-	where, arguments := template.ToWhereWithArguments(terms)
-	return result.NewResult(template, t, where, arguments)
-}
-
 // Truncate deletes all rows from the table.
 func (t *table) Truncate() error {
-	_, err := t.database.Exec(&sqlgen.Statement{
+	stmt := sqlgen.Statement{
 		Type:  sqlgen.Truncate,
-		Table: sqlgen.TableWithName(t.MainTableName()),
-	})
+		Table: sqlgen.TableWithName(t.Name()),
+	}
 
-	if err != nil {
+	if _, err := t.Database().Builder().Exec(&stmt); err != nil {
 		return err
 	}
 	return nil
@@ -59,36 +51,24 @@ func (t *table) Truncate() error {
 
 // Append inserts an item (map or struct) into the collection.
 func (t *table) Append(item interface{}) (interface{}, error) {
-	var pKey []string
-
-	columnNames, columnValues, err := t.FieldValues(item)
-
+	columnNames, columnValues, err := builder.Map(item)
 	if err != nil {
 		return nil, err
 	}
 
-	sqlgenCols, sqlgenVals, sqlgenArgs, err := template.ToColumnsValuesAndArguments(columnNames, columnValues)
-
-	if err != nil {
-		return nil, err
-	}
-
-	if pKey, err = t.database.getPrimaryKey(t.MainTableName()); err != nil {
+	var pKey []string
+	if pKey, err = t.Database().TablePrimaryKey(t.Name()); err != nil {
 		if err != sql.ErrNoRows {
-			// Can't tell primary key.
 			return nil, err
 		}
 	}
 
-	stmt := &sqlgen.Statement{
-		Type:    sqlgen.Insert,
-		Table:   sqlgen.TableWithName(t.MainTableName()),
-		Columns: sqlgenCols,
-		Values:  sqlgenVals,
-	}
+	q := t.Database().Builder().InsertInto(t.Name()).
+		Columns(columnNames...).
+		Values(columnValues...)
 
 	var res sql.Result
-	if res, err = t.database.Exec(stmt, sqlgenArgs...); err != nil {
+	if res, err = q.Exec(); err != nil {
 		return nil, err
 	}
 
@@ -141,15 +121,6 @@ func (t *table) Append(item interface{}) (interface{}, error) {
 	return keyMap, nil
 }
 
-// Exists returns true if the collection exists.
-func (t *table) Exists() bool {
-	if err := t.database.tableExists(t.Tables...); err != nil {
-		return false
-	}
-	return true
-}
-
-// Name returns the name of the table or tables that form the collection.
-func (t *table) Name() string {
-	return strings.Join(t.Tables, `, `)
+func newTable(d *database, name string) *table {
+	return &table{sqladapter.NewCollection(d, name)}
 }
diff --git a/mysql/connection.go b/mysql/connection.go
index e9264c905946dd2f83780f93034d36ddeed657b8..2e83a40db7407d86efb96a10980bc5e96008b8fe 100644
--- a/mysql/connection.go
+++ b/mysql/connection.go
@@ -99,6 +99,10 @@ func (c ConnectionURL) String() (s string) {
 		c.Options["charset"] = "utf8"
 	}
 
+	if _, ok := c.Options["parseTime"]; !ok {
+		c.Options["parseTime"] = "true"
+	}
+
 	// Converting options into URL values.
 	vv := url.Values{}
 
diff --git a/mysql/connection_test.go b/mysql/connection_test.go
index e306aa9a519e3efab197d21fc2a110865fcf7d39..d0b7cc44e511c32bbcf72ca6dc9df8fd93e11d4a 100644
--- a/mysql/connection_test.go
+++ b/mysql/connection_test.go
@@ -39,7 +39,7 @@ func TestConnectionURL(t *testing.T) {
 	// Adding a database name.
 	c.Database = "mydbname"
 
-	if c.String() != "/mydbname?charset=utf8" {
+	if c.String() != "/mydbname?charset=utf8&parseTime=true" {
 		t.Fatal(`Test failed, got:`, c.String())
 	}
 
@@ -49,7 +49,7 @@ func TestConnectionURL(t *testing.T) {
 		"sys_var": "esc@ped",
 	}
 
-	if c.String() != "/mydbname?charset=utf8mb4%2Cutf8&sys_var=esc%40ped" {
+	if c.String() != "/mydbname?charset=utf8mb4%2Cutf8&parseTime=true&sys_var=esc%40ped" {
 		t.Fatal(`Test failed, got:`, c.String())
 	}
 
@@ -60,21 +60,21 @@ func TestConnectionURL(t *testing.T) {
 	c.User = "user"
 	c.Password = "pass"
 
-	if c.String() != `user:pass@/mydbname?charset=utf8` {
+	if c.String() != `user:pass@/mydbname?charset=utf8&parseTime=true` {
 		t.Fatal(`Test failed, got:`, c.String())
 	}
 
 	// Setting host.
 	c.Address = db.HostPort("1.2.3.4", 3306)
 
-	if c.String() != `user:pass@tcp(1.2.3.4:3306)/mydbname?charset=utf8` {
+	if c.String() != `user:pass@tcp(1.2.3.4:3306)/mydbname?charset=utf8&parseTime=true` {
 		t.Fatal(`Test failed, got:`, c.String())
 	}
 
 	// Setting socket.
 	c.Address = db.Socket("/path/to/socket")
 
-	if c.String() != `user:pass@unix(/path/to/socket)/mydbname?charset=utf8` {
+	if c.String() != `user:pass@unix(/path/to/socket)/mydbname?charset=utf8&parseTime=true` {
 		t.Fatal(`Test failed, got:`, c.String())
 	}
 
diff --git a/mysql/database.go b/mysql/database.go
index aa1c567b86ac5f64e8162e4f36476dbafcebfdce..1091ce5d32a96c6ae47380907988b8c23389052e 100644
--- a/mysql/database.go
+++ b/mysql/database.go
@@ -22,345 +22,120 @@
 package mysql
 
 import (
-	"database/sql"
 	"strings"
-	"sync"
-	"time"
 
 	_ "github.com/go-sql-driver/mysql" // MySQL driver.
 	"github.com/jmoiron/sqlx"
-	"upper.io/cache"
-	"upper.io/db"
-	"upper.io/db/internal/adapter"
-	"upper.io/db/internal/schema"
 	"upper.io/builder/sqlgen"
-	"upper.io/db/internal/sqlutil"
+	template "upper.io/builder/template/mysql"
+	"upper.io/db"
+	"upper.io/db/internal/sqladapter"
 	"upper.io/db/internal/sqlutil/tx"
 )
 
-var (
-	sqlPlaceholder = sqlgen.RawValue(`?`)
-)
-
 type database struct {
-	connURL          db.ConnectionURL
-	session          *sqlx.DB
-	tx               *sqltx.Tx
-	schema           *schema.DatabaseSchema
-	cachedStatements *cache.Cache
-	collections      map[string]*table
-	collectionsMu    sync.Mutex
+	*sqladapter.BaseDatabase
 }
 
-type cachedStatement struct {
-	*sqlx.Stmt
-	query string
-}
-
-var waitForConnMu sync.Mutex
-
-var (
-	_ = db.Database(&database{})
-	_ = db.Tx(&tx{})
-)
+var _ = db.Database(&database{})
 
-type columnSchemaT struct {
-	Name string `db:"column_name"`
+// CompileAndReplacePlaceholders compiles the given statement into an string
+// and replaces each generic placeholder with the placeholder the driver
+// expects (if any).
+func (d *database) CompileAndReplacePlaceholders(stmt *sqlgen.Statement) (query string) {
+	return stmt.Compile(d.Template())
 }
 
-func (d *database) prepareStatement(stmt *sqlgen.Statement) (p *sqlx.Stmt, query string, err error) {
-	if d.session == nil {
-		return nil, "", db.ErrNotConnected
-	}
-
-	pc, ok := d.cachedStatements.ReadRaw(stmt)
-
-	if ok {
-		ps := pc.(*cachedStatement)
-		p = ps.Stmt
-		query = ps.query
-	} else {
-		query = compileAndReplacePlaceholders(stmt)
-
-		if d.tx != nil {
-			p, err = d.tx.Preparex(query)
-		} else {
-			p, err = d.session.Preparex(query)
-		}
-
-		if err != nil {
-			return nil, query, err
+// Err translates some known errors into generic errors.
+func (d *database) Err(err error) error {
+	if err != nil {
+		s := err.Error()
+		if strings.Contains(s, `many connections`) {
+			return db.ErrTooManyClients
 		}
-
-		d.cachedStatements.Write(stmt, &cachedStatement{p, query})
 	}
-
-	return p, query, nil
-}
-
-func compileAndReplacePlaceholders(stmt *sqlgen.Statement) string {
-	return stmt.Compile(template.Template)
-}
-
-// Driver returns the underlying *sqlx.DB instance.
-func (d *database) Driver() interface{} {
-	return d.session
+	return err
 }
 
-// Open attempts to connect to the database server using already stored settings.
+// Open attempts to open a connection to the database server.
 func (d *database) Open() error {
-	var err error
+	var sess *sqlx.DB
 
-	// Before db.ConnectionURL we used a unified db.Settings struct. This
-	// condition checks for that type and provides backwards compatibility.
-	if settings, ok := d.connURL.(db.Settings); ok {
-
-		// User is providing a db.Settings struct, let's translate it into a
-		// ConnectionURL{}.
-		conn := ConnectionURL{
-			User:     settings.User,
-			Password: settings.Password,
-			Database: settings.Database,
-			Options: map[string]string{
-				"charset": settings.Charset,
-			},
-		}
-
-		// Connection charset, UTF-8 by default.
-		if conn.Options["charset"] == "" {
-			conn.Options["charset"] = "utf8"
-		}
-
-		// parseTime=true changes the output type of DATE and DATETIME values to time.Time instead of []byte / string
-		if conn.Options["parseTime"] == "" {
-			conn.Options["parseTime"] = "true"
-		}
-
-		if settings.Socket != "" {
-			conn.Address = db.Socket(settings.Socket)
-		} else {
-			if settings.Host == "" {
-				settings.Host = "127.0.0.1"
-			}
-			if settings.Port == 0 {
-				settings.Port = defaultPort
-			}
-			conn.Address = db.HostPort(settings.Host, uint(settings.Port))
-		}
-
-		// Replace original d.connURL
-		d.connURL = conn
-	}
-
-	connFn := func(d **database) (err error) {
-		(*d).session, err = sqlx.Open(`mysql`, (*d).connURL.String())
+	connFn := func(sess **sqlx.DB) (err error) {
+		*sess, err = sqlx.Open("mysql", d.ConnectionURL().String())
 		return
 	}
 
-	if err := waitForConnection(func() error { return connFn(&d) }); err != nil {
+	if err := d.WaitForConnection(func() error { return connFn(&sess) }); err != nil {
 		return err
 	}
 
-	d.session.Mapper = sqlutil.NewMapper()
-
-	d.cachedStatements = cache.NewCache()
-
-	d.collections = make(map[string]*table)
-
-	if d.schema == nil {
-		if err = d.populateSchema(); err != nil {
-			return err
-		}
-	}
-
-	return nil
+	return d.Bind(sess)
 }
 
-// Clone returns a cloned db.Database session, this is typically used for
-// transactions.
-func (d *database) Clone() (db.Database, error) {
-	return d.clone()
+// Setup configures the adapter.
+func (d *database) Setup(connURL db.ConnectionURL) error {
+	d.BaseDatabase = sqladapter.NewDatabase(d, connURL, template.Template())
+	return d.Open()
 }
 
-func (d *database) clone() (*database, error) {
-	clone := &database{
-		schema: d.schema,
-	}
-	if err := clone.Setup(d.connURL); err != nil {
-		return nil, err
+// Use changes the active database.
+func (d *database) Use(name string) (err error) {
+	var conn ConnectionURL
+	if conn, err = ParseURL(d.ConnectionURL().String()); err != nil {
+		return err
 	}
-	return clone, nil
-}
-
-// Ping checks whether a connection to the database is still alive by pinging
-// it, establishing a connection if necessary.
-func (d *database) Ping() error {
-	return d.session.Ping()
-}
-
-// Close terminates the current database session.
-func (d *database) Close() error {
-	if d.session != nil {
-		if d.tx != nil && !d.tx.Done() {
-			d.tx.Rollback()
-		}
-		d.cachedStatements.Clear()
-		return d.session.Close()
+	conn.Database = name
+	if d.BaseDatabase != nil {
+		d.Close()
 	}
-	return nil
+	return d.Setup(conn)
 }
 
-// C returns a collection interface.
-func (d *database) C(names ...string) db.Collection {
-	if len(names) == 0 {
-		return &adapter.NonExistentCollection{Err: db.ErrMissingCollectionName}
-	}
-
-	if c, ok := d.collections[sqlutil.HashTableNames(names)]; ok {
-		return c
-	}
-
-	c, err := d.Collection(names...)
-	if err != nil {
-		return &adapter.NonExistentCollection{Err: err}
-	}
-	return c
+// Clone creates a new database connection with the same settings as the
+// original.
+func (d *database) Clone() (db.Database, error) {
+	return d.clone()
 }
 
-// Collection returns a table by name.
-func (d *database) Collection(names ...string) (db.Collection, error) {
-	var err error
-
-	if len(names) == 0 {
-		return nil, db.ErrMissingCollectionName
-	}
-
-	if d.tx != nil {
-		if d.tx.Done() {
-			return nil, sql.ErrTxDone
-		}
-	}
-
-	col := &table{database: d}
-	col.T.Tables = names
-	col.T.Mapper = d.session.Mapper
-
-	for _, name := range names {
-		chunks := strings.SplitN(name, ` `, 2)
-
-		if len(chunks) == 0 {
-			return nil, db.ErrMissingCollectionName
-		}
-
-		tableName := chunks[0]
-
-		if err := d.tableExists(tableName); err != nil {
-			return nil, err
-		}
-
-		if col.Columns, err = d.tableColumns(tableName); err != nil {
-			return nil, err
-		}
-	}
-
-	// Saving the collection for C().
-	d.collectionsMu.Lock()
-	d.collections[sqlutil.HashTableNames(names)] = col
-	d.collectionsMu.Unlock()
-
-	return col, nil
+// NewTable returns a db.Collection.
+func (d *database) NewTable(name string) db.Collection {
+	return newTable(d, name)
 }
 
 // Collections returns a list of non-system tables from the database.
 func (d *database) Collections() (collections []string, err error) {
 
-	tablesInSchema := len(d.schema.Tables)
-
-	// Is schema already populated?
-	if tablesInSchema > 0 {
-		// Pulling table names from schema.
-		return d.schema.Tables, nil
-	}
-
-	stmt := &sqlgen.Statement{
-		Type: sqlgen.Select,
-		Columns: sqlgen.JoinColumns(
-			sqlgen.ColumnWithName(`table_name`),
-		),
-		Table: sqlgen.TableWithName(`information_schema.tables`),
-		Where: sqlgen.WhereConditions(
-			&sqlgen.ColumnValue{
-				Column:   sqlgen.ColumnWithName(`table_schema`),
-				Operator: `=`,
-				Value:    sqlPlaceholder,
-			},
-		),
-	}
-
-	// Executing statement.
-	var rows *sqlx.Rows
-	if rows, err = d.Query(stmt, d.schema.Name); err != nil {
-		return nil, err
-	}
+	if len(d.Schema().Tables) == 0 {
+		q := d.Builder().Select("table_name").
+			From("information_schema.tables").
+			Where("table_schema = ?", d.Schema().Name)
 
-	collections = []string{}
+		iter := q.Iterator()
+		defer iter.Close()
 
-	var name string
-
-	for rows.Next() {
-		// Getting table name.
-		if err = rows.Scan(&name); err != nil {
-			rows.Close()
-			return nil, err
+		for iter.Next() {
+			var tableName string
+			if err := iter.Scan(&tableName); err != nil {
+				return nil, err
+			}
+			d.Schema().AddTable(tableName)
 		}
-
-		// Adding table entry to schema.
-		d.schema.AddTable(name)
-
-		// Adding table to collections array.
-		collections = append(collections, name)
 	}
 
-	return collections, nil
-}
-
-// Use changes the active database.
-func (d *database) Use(name string) (err error) {
-	var conn ConnectionURL
-
-	if conn, err = ParseURL(d.connURL.String()); err != nil {
-		return err
-	}
-
-	conn.Database = name
-
-	d.connURL = conn
-
-	d.schema = nil
-
-	return d.Open()
+	return d.Schema().Tables, nil
 }
 
 // Drop removes all tables from the current database.
 func (d *database) Drop() error {
-
-	_, err := d.Query(&sqlgen.Statement{
+	stmt := &sqlgen.Statement{
 		Type:     sqlgen.DropDatabase,
-		Database: sqlgen.DatabaseWithName(d.schema.Name),
-	})
-
-	return err
-}
-
-// Setup stores database settings.
-func (d *database) Setup(connURL db.ConnectionURL) error {
-	d.connURL = connURL
-	return d.Open()
-}
-
-// Name returns the name of the database.
-func (d *database) Name() string {
-	return d.schema.Name
+		Database: sqlgen.DatabaseWithName(d.Schema().Name),
+	}
+	if _, err := d.Builder().Exec(stmt); err != nil {
+		return err
+	}
+	return nil
 }
 
 // Transaction starts a transaction block and returns a db.Tx struct that can
@@ -375,119 +150,48 @@ func (d *database) Transaction() (db.Tx, error) {
 	}
 
 	connFn := func(sqlTx **sqlx.Tx) (err error) {
-		*sqlTx, err = clone.session.Beginx()
+		*sqlTx, err = clone.Session().Beginx()
 		return
 	}
 
-	if err := waitForConnection(func() error { return connFn(&sqlTx) }); err != nil {
-		return nil, err
-	}
-
-	clone.tx = sqltx.New(sqlTx)
-	return &tx{Tx: clone.tx, database: clone}, nil
-}
-
-// Exec compiles and executes a statement that does not return any rows.
-func (d *database) Exec(stmt *sqlgen.Statement, args ...interface{}) (sql.Result, error) {
-	var query string
-	var p *sqlx.Stmt
-	var err error
-
-	if db.Debug {
-		var start, end int64
-		start = time.Now().UnixNano()
-
-		defer func() {
-			end = time.Now().UnixNano()
-			sqlutil.Log(query, args, err, start, end)
-		}()
-	}
-
-	if p, query, err = d.prepareStatement(stmt); err != nil {
-		return nil, err
-	}
-
-	return p.Exec(args...)
-}
-
-// Query compiles and executes a statement that returns rows.
-func (d *database) Query(stmt *sqlgen.Statement, args ...interface{}) (*sqlx.Rows, error) {
-	var query string
-	var p *sqlx.Stmt
-	var err error
-
-	if db.Debug {
-		var start, end int64
-		start = time.Now().UnixNano()
-
-		defer func() {
-			end = time.Now().UnixNano()
-			sqlutil.Log(query, args, err, start, end)
-		}()
-	}
-
-	if p, query, err = d.prepareStatement(stmt); err != nil {
+	if err := d.WaitForConnection(func() error { return connFn(&sqlTx) }); err != nil {
 		return nil, err
 	}
 
-	return p.Queryx(args...)
-}
-
-// QueryRow compiles and executes a statement that returns at most one row.
-func (d *database) QueryRow(stmt *sqlgen.Statement, args ...interface{}) (*sqlx.Row, error) {
-	var query string
-	var p *sqlx.Stmt
-	var err error
-
-	if db.Debug {
-		var start, end int64
-		start = time.Now().UnixNano()
-
-		defer func() {
-			end = time.Now().UnixNano()
-			sqlutil.Log(query, args, err, start, end)
-		}()
-	}
-
-	if p, query, err = d.prepareStatement(stmt); err != nil {
-		return nil, err
-	}
+	clone.BindTx(sqlTx)
 
-	return p.QueryRowx(args...), nil
+	return &sqltx.Database{Database: clone, Tx: clone.Tx()}, nil
 }
 
-// populateSchema looks up for the table info in the database and populates its
+// PopulateSchema looks up for the table info in the database and populates its
 // schema for internal use.
-func (d *database) populateSchema() (err error) {
+func (d *database) PopulateSchema() (err error) {
 	var collections []string
 
-	d.schema = schema.NewDatabaseSchema()
+	d.NewSchema()
 
-	// Get database name.
-	stmt := &sqlgen.Statement{
-		Type: sqlgen.Select,
-		Columns: sqlgen.JoinColumns(
-			sqlgen.RawValue(`DATABASE()`),
-		),
-	}
+	q := d.Builder().Select(db.Raw{"DATABASE() AS name"})
 
-	var row *sqlx.Row
+	var dbName string
 
-	if row, err = d.QueryRow(stmt); err != nil {
-		return err
-	}
+	iter := q.Iterator()
+	defer iter.Close()
 
-	if err = row.Scan(&d.schema.Name); err != nil {
-		return err
+	if iter.Next() {
+		if err := iter.Scan(&dbName); err != nil {
+			return err
+		}
+	} else {
+		return iter.Err()
 	}
 
-	// The Collections() call will populate schema if its nil.
+	d.Schema().Name = dbName
+
 	if collections, err = d.Collections(); err != nil {
 		return err
 	}
 
 	for i := range collections {
-		// Populate each collection.
 		if _, err = d.Collection(collections[i]); err != nil {
 			return err
 		}
@@ -496,198 +200,101 @@ func (d *database) populateSchema() (err error) {
 	return err
 }
 
-func (d *database) tableExists(names ...string) error {
-	var stmt *sqlgen.Statement
-	var err error
-	var rows *sqlx.Rows
+// TableExists checks whether a table exists and returns an error in case it doesn't.
+func (d *database) TableExists(name string) error {
+	if d.Schema().HasTable(name) {
+		return nil
+	}
 
-	for i := range names {
+	q := d.Builder().Select("table_name").
+		From("information_schema.tables").
+		Where("table_schema = ? AND table_name = ?", d.Schema().Name, name)
 
-		if d.schema.HasTable(names[i]) {
-			// We already know this table exists.
-			continue
-		}
+	iter := q.Iterator()
+	defer iter.Close()
 
-		stmt = &sqlgen.Statement{
-			Type:  sqlgen.Select,
-			Table: sqlgen.TableWithName(`information_schema.tables`),
-			Columns: sqlgen.JoinColumns(
-				sqlgen.ColumnWithName(`table_name`),
-			),
-			Where: sqlgen.WhereConditions(
-				&sqlgen.ColumnValue{
-					Column:   sqlgen.ColumnWithName(`table_schema`),
-					Operator: `=`,
-					Value:    sqlPlaceholder,
-				},
-				&sqlgen.ColumnValue{
-					Column:   sqlgen.ColumnWithName(`table_name`),
-					Operator: `=`,
-					Value:    sqlPlaceholder,
-				},
-			),
-		}
-
-		if rows, err = d.Query(stmt, d.schema.Name, names[i]); err != nil {
-			return db.ErrCollectionDoesNotExist
-		}
-
-		if !rows.Next() {
-			rows.Close()
-			return db.ErrCollectionDoesNotExist
+	if iter.Next() {
+		var tableName string
+		if err := iter.Scan(&tableName); err != nil {
+			return err
 		}
+	} else {
+		return db.ErrCollectionDoesNotExist
 	}
 
 	return nil
 }
 
-func (d *database) tableColumns(tableName string) ([]string, error) {
-
-	// Making sure this table is allocated.
-	tableSchema := d.schema.Table(tableName)
-
-	if len(tableSchema.Columns) > 0 {
-		return tableSchema.Columns, nil
-	}
-
-	stmt := &sqlgen.Statement{
-		Type:  sqlgen.Select,
-		Table: sqlgen.TableWithName(`information_schema.columns`),
-		Columns: sqlgen.JoinColumns(
-			sqlgen.ColumnWithName(`column_name`),
-			sqlgen.ColumnWithName(`data_type`),
-		),
-		Where: sqlgen.WhereConditions(
-			&sqlgen.ColumnValue{
-				Column:   sqlgen.ColumnWithName(`table_schema`),
-				Operator: `=`,
-				Value:    sqlPlaceholder,
-			},
-			&sqlgen.ColumnValue{
-				Column:   sqlgen.ColumnWithName(`table_name`),
-				Operator: `=`,
-				Value:    sqlPlaceholder,
-			},
-		),
-	}
+// TableColumns returns all columns from the given table.
+func (d *database) TableColumns(tableName string) ([]string, error) {
+	s := d.Schema()
 
-	var rows *sqlx.Rows
-	var err error
+	if len(s.Table(tableName).Columns) == 0 {
 
-	if rows, err = d.Query(stmt, d.schema.Name, tableName); err != nil {
-		return nil, err
-	}
+		q := d.Builder().Select("column_name").
+			From("information_schema.columns").
+			Where("table_schema = ? AND table_name = ?", d.Schema().Name, tableName)
 
-	tableFields := []columnSchemaT{}
+		var rows []struct {
+			Name string `db:"column_name"`
+		}
 
-	if err = sqlutil.FetchRows(rows, &tableFields); err != nil {
-		return nil, err
-	}
+		if err := q.Iterator().All(&rows); err != nil {
+			return nil, err
+		}
 
-	d.schema.TableInfo[tableName].Columns = make([]string, 0, len(tableFields))
+		s.TableInfo[tableName].Columns = make([]string, 0, len(rows))
 
-	for i := range tableFields {
-		d.schema.TableInfo[tableName].Columns = append(d.schema.TableInfo[tableName].Columns, tableFields[i].Name)
+		for i := range rows {
+			s.TableInfo[tableName].Columns = append(s.TableInfo[tableName].Columns, rows[i].Name)
+		}
 	}
 
-	return d.schema.TableInfo[tableName].Columns, nil
+	return s.Table(tableName).Columns, nil
 }
 
-func (d *database) getPrimaryKey(tableName string) ([]string, error) {
-
-	tableSchema := d.schema.Table(tableName)
+// TablePrimaryKey returns all primary keys from the given table.
+func (d *database) TablePrimaryKey(tableName string) ([]string, error) {
+	s := d.Schema()
 
-	if len(tableSchema.PrimaryKey) != 0 {
-		return tableSchema.PrimaryKey, nil
-	}
+	ts := s.Table(tableName)
 
-	stmt := &sqlgen.Statement{
-		Type: sqlgen.Select,
-		Table: sqlgen.RawValue(`
-				information_schema.table_constraints AS t
-				JOIN information_schema.key_column_usage k
-				USING(constraint_name, table_schema, table_name)
-		`),
-		Columns: sqlgen.JoinColumns(
-			sqlgen.ColumnWithName(`k.column_name`),
-		),
-		Where: sqlgen.WhereConditions(
-			&sqlgen.ColumnValue{
-				Column:   sqlgen.ColumnWithName(`t.constraint_type`),
-				Operator: `=`,
-				Value:    sqlgen.NewValue(`primary key`),
-			},
-			&sqlgen.ColumnValue{
-				Column:   sqlgen.ColumnWithName(`t.table_schema`),
-				Operator: `=`,
-				Value:    sqlPlaceholder,
-			},
-			&sqlgen.ColumnValue{
-				Column:   sqlgen.ColumnWithName(`t.table_name`),
-				Operator: `=`,
-				Value:    sqlPlaceholder,
-			},
-		),
-		OrderBy: &sqlgen.OrderBy{
-			SortColumns: sqlgen.JoinSortColumns(
-				&sqlgen.SortColumn{
-					Column: sqlgen.ColumnWithName(`k.ordinal_position`),
-					Order:  sqlgen.Ascendent,
-				},
-			),
-		},
+	if len(ts.PrimaryKey) != 0 {
+		return ts.PrimaryKey, nil
 	}
 
-	var rows *sqlx.Rows
-	var err error
+	ts.PrimaryKey = make([]string, 0, 1)
 
-	if rows, err = d.Query(stmt, d.schema.Name, tableName); err != nil {
-		return nil, err
-	}
+	q := d.Builder().Select("k.column_name").
+		From("information_schema.table_constraints AS t").
+		Join("information_schema.key_column_usage AS k").
+		Using("constraint_name", "table_schema", "table_name").
+		Where(`
+			t.constraint_type = 'primary key'
+			AND t.table_schema = ?
+			AND t.table_name = ?
+		`, d.Schema().Name, tableName).
+		OrderBy("k.ordinal_position")
 
-	tableSchema.PrimaryKey = make([]string, 0, 1)
+	iter := q.Iterator()
+	defer iter.Close()
 
-	for rows.Next() {
-		var key string
-		if err = rows.Scan(&key); err != nil {
+	for iter.Next() {
+		var pKey string
+		if err := iter.Scan(&pKey); err != nil {
 			return nil, err
 		}
-		tableSchema.PrimaryKey = append(tableSchema.PrimaryKey, key)
+		ts.PrimaryKey = append(ts.PrimaryKey, pKey)
 	}
 
-	return tableSchema.PrimaryKey, nil
+	return ts.PrimaryKey, nil
 }
 
-// waitForConnection tries to execute the connectFn function, if connectFn
-// returns an error, then waitForConnection will keep trying until connectFn
-// returns nil. Maximum waiting time is 5s after having acquired the lock.
-func waitForConnection(connectFn func() error) error {
-	// This lock ensures first-come, first-served and prevents opening too many
-	// file descriptors.
-	waitForConnMu.Lock()
-	defer waitForConnMu.Unlock()
-
-	// Minimum waiting time.
-	waitTime := time.Millisecond * 10
-
-	// Waitig 5 seconds for a successful connection.
-	for timeStart := time.Now(); time.Now().Sub(timeStart) < time.Second*5; {
-		if err := connectFn(); err != nil {
-			if strings.Contains(err.Error(), `many connections`) {
-				// Sleep and try again if, and only if, the server replied with a "too
-				// many clients" error.
-				time.Sleep(waitTime)
-				if waitTime < time.Millisecond*500 {
-					// Wait a bit more next time.
-					waitTime = waitTime * 2
-				}
-				continue
-			}
-			// Return any other error immediately.
-			return err
-		}
-		return nil
+func (d *database) clone() (*database, error) {
+	clone := &database{}
+	clone.BaseDatabase = d.BaseDatabase.Clone(clone)
+	if err := clone.Open(); err != nil {
+		return nil, err
 	}
-
-	return db.ErrGivingUpTryingToConnect
+	return clone, nil
 }
diff --git a/mysql/database_test.go b/mysql/database_test.go
index 87f1325e95f23390e18fd03271946721a530d760..7877b3b7ae46322452d42081673dfda49c09ac2c 100644
--- a/mysql/database_test.go
+++ b/mysql/database_test.go
@@ -36,7 +36,6 @@ import (
 
 	"github.com/jmoiron/sqlx"
 	"upper.io/db"
-	"upper.io/db/internal/sqlutil"
 )
 
 const (
@@ -156,7 +155,7 @@ func init() {
 }
 
 // Attempts to open an empty datasource.
-func TestOpenFailed(t *testing.T) {
+func SkipTestOpenFailed(t *testing.T) {
 	var err error
 
 	// Attempt to open an empty database.
@@ -167,7 +166,7 @@ func TestOpenFailed(t *testing.T) {
 }
 
 // Attempts to open an empty datasource.
-func TestOpenWithWrongData(t *testing.T) {
+func SkipTestOpenWithWrongData(t *testing.T) {
 	var err error
 	var rightSettings, wrongSettings db.Settings
 
@@ -222,27 +221,6 @@ func TestOpenWithWrongData(t *testing.T) {
 	}
 }
 
-// Old settings must be compatible.
-func TestOldSettings(t *testing.T) {
-	var err error
-	var sess db.Database
-
-	oldSettings := db.Settings{
-		Database: databaseName,
-		User:     username,
-		Password: password,
-		Host:     host,
-	}
-
-	// Opening database.
-	if sess, err = db.Open(Adapter, oldSettings); err != nil {
-		t.Fatal(err)
-	}
-
-	// Closing database.
-	sess.Close()
-}
-
 // Test USE
 func TestUse(t *testing.T) {
 	var err error
@@ -924,231 +902,6 @@ func TestRemove(t *testing.T) {
 	}
 }
 
-// Attempts to use SQL raw statements.
-func TestRawRelations(t *testing.T) {
-	var sess db.Database
-	var err error
-
-	var artist db.Collection
-	var publication db.Collection
-	var review db.Collection
-
-	type artistType struct {
-		ID   int64  `db:"id,omitempty"`
-		Name string `db:"name"`
-	}
-
-	type publicationType struct {
-		ID       int64  `db:"id,omitempty"`
-		Title    string `db:"title"`
-		AuthorID int64  `db:"author_id"`
-	}
-
-	type reviewType struct {
-		ID            int64     `db:"id,omitempty"`
-		PublicationID int64     `db:"publication_id"`
-		Name          string    `db:"name"`
-		Comments      string    `db:"comments"`
-		Created       time.Time `db:"created"`
-	}
-
-	if sess, err = db.Open(Adapter, settings); err != nil {
-		t.Fatal(err)
-	}
-
-	defer sess.Close()
-
-	// Artist collection.
-	if artist, err = sess.Collection("artist"); err != nil {
-		t.Fatal(err)
-	}
-
-	if err = artist.Truncate(); err != nil {
-		t.Fatal(err)
-	}
-
-	// Publication collection.
-	if publication, err = sess.Collection("publication"); err != nil {
-		t.Fatal(err)
-	}
-
-	if err = publication.Truncate(); err != nil {
-		t.Fatal(err)
-	}
-
-	// Review collection.
-	if review, err = sess.Collection("review"); err != nil {
-		t.Fatal(err)
-	}
-
-	if err = review.Truncate(); err != nil {
-		t.Fatal(err)
-	}
-
-	// Adding some artists.
-	var miyazakiID interface{}
-	miyazaki := artistType{Name: `Hayao Miyazaki`}
-	if miyazakiID, err = artist.Append(miyazaki); err != nil {
-		t.Fatal(err)
-	}
-	miyazaki.ID = miyazakiID.(int64)
-
-	var asimovID interface{}
-	asimov := artistType{Name: `Isaac Asimov`}
-	if asimovID, err = artist.Append(asimov); err != nil {
-		t.Fatal(err)
-	}
-
-	var marquezID interface{}
-	marquez := artistType{Name: `Gabriel García Márquez`}
-	if marquezID, err = artist.Append(marquez); err != nil {
-		t.Fatal(err)
-	}
-
-	// Adding some publications.
-	publication.Append(publicationType{
-		Title:    `Tonari no Totoro`,
-		AuthorID: miyazakiID.(int64),
-	})
-
-	publication.Append(publicationType{
-		Title:    `Howl's Moving Castle`,
-		AuthorID: miyazakiID.(int64),
-	})
-
-	publication.Append(publicationType{
-		Title:    `Ponyo`,
-		AuthorID: miyazakiID.(int64),
-	})
-
-	publication.Append(publicationType{
-		Title:    `Memoria de mis Putas Tristes`,
-		AuthorID: marquezID.(int64),
-	})
-
-	publication.Append(publicationType{
-		Title:    `El Coronel no tiene quien le escriba`,
-		AuthorID: marquezID.(int64),
-	})
-
-	publication.Append(publicationType{
-		Title:    `El Amor en los tiempos del Cólera`,
-		AuthorID: marquezID.(int64),
-	})
-
-	publication.Append(publicationType{
-		Title:    `I, Robot`,
-		AuthorID: asimovID.(int64),
-	})
-
-	var foundationID interface{}
-	foundationID, err = publication.Append(publicationType{
-		Title:    `Foundation`,
-		AuthorID: asimovID.(int64),
-	})
-	if err != nil {
-		t.Fatal(err)
-	}
-
-	publication.Append(publicationType{
-		Title:    `The Robots of Dawn`,
-		AuthorID: asimovID.(int64),
-	})
-
-	// Adding reviews for foundation.
-	review.Append(reviewType{
-		PublicationID: foundationID.(int64),
-		Name:          "John Doe",
-		Comments:      "I love The Foundation series.",
-		Created:       time.Now(),
-	})
-
-	review.Append(reviewType{
-		PublicationID: foundationID.(int64),
-		Name:          "Edr Pls",
-		Comments:      "The Foundation series made me fall in love with Isaac Asimov.",
-		Created:       time.Now(),
-	})
-
-	// Exec'ing a raw query.
-	var artistPublication db.Collection
-	if artistPublication, err = sess.Collection(`artist AS a`, `publication AS p`); err != nil {
-		t.Fatal(err)
-	}
-
-	res := artistPublication.Find(
-		db.Raw{`a.id = p.author_id`},
-	).Select(
-		"p.id",
-		"p.title as publication_title",
-		"a.name AS artist_name",
-	)
-
-	type artistPublicationType struct {
-		ID               int64  `db:"id"`
-		PublicationTitle string `db:"publication_title"`
-		ArtistName       string `db:"artist_name"`
-	}
-
-	all := []artistPublicationType{}
-
-	if err = res.All(&all); err != nil {
-		t.Fatal(err)
-	}
-
-	if len(all) != 9 {
-		t.Fatalf("Expecting some rows.")
-	}
-
-}
-
-func TestRawQuery(t *testing.T) {
-	var sess db.Database
-	var rows *sqlx.Rows
-	var err error
-	var drv *sqlx.DB
-
-	type publicationType struct {
-		ID       int64  `db:"id,omitempty"`
-		Title    string `db:"title"`
-		AuthorID int64  `db:"author_id"`
-	}
-
-	if sess, err = db.Open(Adapter, settings); err != nil {
-		t.Fatal(err)
-	}
-
-	defer sess.Close()
-
-	drv = sess.Driver().(*sqlx.DB)
-
-	rows, err = drv.Queryx(`
-		SELECT
-			p.id,
-			p.title AS publication_title,
-			a.name AS artist_name
-		FROM
-			artist AS a,
-			publication AS p
-		WHERE
-			a.id = p.author_id
-	`)
-
-	if err != nil {
-		t.Fatal(err)
-	}
-
-	var all []publicationType
-
-	if err = sqlutil.FetchRows(rows, &all); err != nil {
-		t.Fatal(err)
-	}
-
-	if len(all) != 9 {
-		t.Fatalf("Expecting some rows.")
-	}
-}
-
 // Attempts to test database transactions.
 func TestTransactionsAndRollback(t *testing.T) {
 	var sess db.Database
diff --git a/mysql/mysql.go b/mysql/mysql.go
index d46c200c77995b1b5fafaaea42200943e47e46af..2a247fd407119ac1f8b7b9c9d124aa6310278c0c 100644
--- a/mysql/mysql.go
+++ b/mysql/mysql.go
@@ -22,50 +22,12 @@
 package mysql // import "upper.io/db/mysql"
 
 import (
-	"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 = `mysql`
 
-var template *sqlutil.TemplateWithUtils
-
 func init() {
-	template = sqlutil.NewTemplateWithUtils(&sqlgen.Template{
-		ColumnSeparator:     adapterColumnSeparator,
-		IdentifierSeparator: adapterIdentifierSeparator,
-		IdentifierQuote:     adapterIdentifierQuote,
-		ValueSeparator:      adapterValueSeparator,
-		ValueQuote:          adapterValueQuote,
-		AndKeyword:          adapterAndKeyword,
-		OrKeyword:           adapterOrKeyword,
-		NotKeyword:          adapterNotKeyword,
-		DescKeyword:         adapterDescKeyword,
-		AscKeyword:          adapterAscKeyword,
-		DefaultOperator:     adapterDefaultOperator,
-		AssignmentOperator:  adapterAssignmentOperator,
-		ClauseGroup:         adapterClauseGroup,
-		ClauseOperator:      adapterClauseOperator,
-		ColumnValue:         adapterColumnValue,
-		TableAliasLayout:    adapterTableAliasLayout,
-		ColumnAliasLayout:   adapterColumnAliasLayout,
-		SortByColumnLayout:  adapterSortByColumnLayout,
-		WhereLayout:         adapterWhereLayout,
-		OrderByLayout:       adapterOrderByLayout,
-		InsertLayout:        adapterInsertLayout,
-		SelectLayout:        adapterSelectLayout,
-		UpdateLayout:        adapterUpdateLayout,
-		DeleteLayout:        adapterDeleteLayout,
-		TruncateLayout:      adapterTruncateLayout,
-		DropDatabaseLayout:  adapterDropDatabaseLayout,
-		DropTableLayout:     adapterDropTableLayout,
-		CountLayout:         adapterSelectCountLayout,
-		GroupByLayout:       adapterGroupByLayout,
-		Cache:               cache.NewCache(),
-	})
-
 	db.Register(Adapter, &database{})
 }
diff --git a/mysql/template.go b/mysql/template.go
deleted file mode 100644
index 20db212c8672c723b968ee549b8c65c9cf5daeba..0000000000000000000000000000000000000000
--- a/mysql/template.go
+++ /dev/null
@@ -1,135 +0,0 @@
-// 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 mysql
-
-const (
-	adapterColumnSeparator     = `.`
-	adapterIdentifierSeparator = `, `
-	adapterIdentifierQuote     = "`{{.Value}}`"
-	adapterValueSeparator      = `, `
-	adapterValueQuote          = `'{{.}}'`
-	adapterAndKeyword          = `AND`
-	adapterOrKeyword           = `OR`
-	adapterNotKeyword          = `NOT`
-	adapterDescKeyword         = `DESC`
-	adapterAscKeyword          = `ASC`
-	adapterDefaultOperator     = `=`
-	adapterAssignmentOperator  = `=`
-	adapterClauseGroup         = `({{.}})`
-	adapterClauseOperator      = ` {{.}} `
-	adapterColumnValue         = `{{.Column}} {{.Operator}} {{.Value}}`
-	adapterTableAliasLayout    = `{{.Name}}{{if .Alias}} AS {{.Alias}}{{end}}`
-	adapterColumnAliasLayout   = `{{.Name}}{{if .Alias}} AS {{.Alias}}{{end}}`
-	adapterSortByColumnLayout  = `{{.Column}} {{.Order}}`
-
-	adapterOrderByLayout = `
-		{{if .SortColumns}}
-			ORDER BY {{.SortColumns}}
-		{{end}}
-	`
-
-	adapterWhereLayout = `
-		{{if .Conds}}
-			WHERE {{.Conds}}
-		{{end}}
-	`
-
-	adapterSelectLayout = `
-		SELECT
-
-			{{if .Columns}}
-				{{.Columns}}
-			{{else}}
-				*
-			{{end}}
-
-			{{if .Table}}
-				FROM {{.Table}}
-			{{end}}
-
-			{{.Where}}
-
-			{{.GroupBy}}
-
-			{{.OrderBy}}
-
-			{{if .Limit}}
-				LIMIT {{.Limit}}
-			{{end}}
-
-			{{if .Offset}}
-				OFFSET {{.Offset}}
-			{{end}}
-	`
-	adapterDeleteLayout = `
-		DELETE
-			FROM {{.Table}}
-			{{.Where}}
-	`
-	adapterUpdateLayout = `
-		UPDATE
-			{{.Table}}
-		SET {{.ColumnValues}}
-			{{ .Where }}
-	`
-
-	adapterSelectCountLayout = `
-		SELECT
-			COUNT(1) AS _t
-		FROM {{.Table}}
-			{{.Where}}
-
-			{{if .Limit}}
-				LIMIT {{.Limit}}
-			{{end}}
-
-			{{if .Offset}}
-				OFFSET {{.Offset}}
-			{{end}}
-	`
-
-	adapterInsertLayout = `
-		INSERT INTO {{.Table}}
-			({{.Columns}})
-		VALUES
-			({{.Values}})
-		{{.Extra}}
-	`
-
-	adapterTruncateLayout = `
-		TRUNCATE TABLE {{.Table}}
-	`
-
-	adapterDropDatabaseLayout = `
-		DROP DATABASE {{.Database}}
-	`
-
-	adapterDropTableLayout = `
-		DROP TABLE {{.Table}}
-	`
-
-	adapterGroupByLayout = `
-		{{if .GroupColumns}}
-			GROUP BY {{.GroupColumns}}
-		{{end}}
-	`
-)
diff --git a/mysql/tx.go b/mysql/tx.go
deleted file mode 100644
index 21b6ecf866557ec95b251262ca0694904a7156fa..0000000000000000000000000000000000000000
--- a/mysql/tx.go
+++ /dev/null
@@ -1,55 +0,0 @@
-// 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 mysql
-
-import (
-	"upper.io/db/internal/sqlutil/tx"
-)
-
-type tx struct {
-	*sqltx.Tx
-	*database
-}
-
-// Driver returns the current transaction session.
-func (t *tx) Driver() interface{} {
-	if t != nil && t.Tx != nil {
-		return t.Tx.Tx
-	}
-	return nil
-}
-
-// Commit commits the current transaction.
-func (t *tx) Commit() error {
-	if err := t.Tx.Commit(); err != nil {
-		return err
-	}
-	return nil
-}
-
-// Rollback discards the current transaction.
-func (t *tx) Rollback() error {
-	if err := t.Tx.Rollback(); err != nil {
-		return err
-	}
-	return nil
-}