diff --git a/db.go b/db.go
index 2ba9df76507811017ad1553623eca66ec2b76ecd..2b11c2f6aecbd1634fe475393b9aff8be6398841 100644
--- a/db.go
+++ b/db.go
@@ -178,13 +178,13 @@ type Database interface {
 	// collection to exists will fail returning the original error a call to
 	// Collection() would have returned. The output of C() may be a cached
 	// collection value.
-	C(...string) Collection
+	C(string) Collection
 
 	// Collection() returns a `db.Collection{}` struct by name. Some databases
 	// support collections of more than one source or table, refer to the
 	// documentation of the specific database adapter to see if using multiple
 	// sources is supported.
-	Collection(...string) (Collection, error)
+	Collection(string) (Collection, error)
 
 	// Collections() returns the names of all non-system sources or tables within
 	// the active database.
diff --git a/postgresql/collection.go b/postgresql/collection.go
index 5656e6e616f91670ec1216b375f69c03ebfc5d3a..f06f1f0eb5676bf0ee37e27268bd7aae5204b63c 100644
--- a/postgresql/collection.go
+++ b/postgresql/collection.go
@@ -35,8 +35,8 @@ import (
 )
 
 type table struct {
-	sqlutil.T
 	*database
+	name string
 }
 
 var _ = db.Collection(&table{})
@@ -50,7 +50,7 @@ func (t *table) Find(conds ...interface{}) db.Result {
 func (t *table) Truncate() error {
 	_, err := t.database.Exec(&sqlgen.Statement{
 		Type:  sqlgen.Truncate,
-		Table: sqlgen.TableWithName(t.MainTableName()),
+		Table: sqlgen.TableWithName(t.Name()),
 	})
 	if err != nil {
 		return err
@@ -75,7 +75,7 @@ func (t *table) Append(item interface{}) (interface{}, error) {
 
 	var pKey []string
 
-	if pKey, err = t.database.getPrimaryKey(t.MainTableName()); err != nil {
+	if pKey, err = t.database.getPrimaryKey(t.Name()); err != nil {
 		if err != sql.ErrNoRows {
 			// Can't tell primary key.
 			return nil, err
@@ -84,7 +84,7 @@ func (t *table) Append(item interface{}) (interface{}, error) {
 
 	stmt := &sqlgen.Statement{
 		Type:    sqlgen.Insert,
-		Table:   sqlgen.TableWithName(t.MainTableName()),
+		Table:   sqlgen.TableWithName(t.Name()),
 		Columns: sqlgenCols,
 		Values:  sqlgenVals,
 	}
@@ -158,7 +158,7 @@ func (t *table) Append(item interface{}) (interface{}, error) {
 
 // Exists returns true if the collection exists.
 func (t *table) Exists() bool {
-	if err := t.database.tableExists(t.Tables...); err != nil {
+	if err := t.database.tableExists(t.Name()); err != nil {
 		return false
 	}
 	return true
@@ -166,5 +166,5 @@ func (t *table) Exists() bool {
 
 // Name returns the name of the table or tables that form the collection.
 func (t *table) Name() string {
-	return strings.Join(t.Tables, `, `)
+	return t.name
 }
diff --git a/postgresql/database.go b/postgresql/database.go
index 2dc9a99e9eec56e9ccb6ab7afbb863dea168a522..1dd8acd84fdb3c9345dd10f366c7c5b7601245c0 100644
--- a/postgresql/database.go
+++ b/postgresql/database.go
@@ -52,6 +52,7 @@ type database struct {
 	cachedStatements *cache.Cache
 	collections      map[string]*table
 	collectionsMu    sync.Mutex
+	builder          db.QueryBuilder
 }
 
 type cachedStatement struct {
@@ -152,6 +153,8 @@ func (d *database) Open() error {
 		return err
 	}
 
+	d.builder = builder.NewBuilder(d, template.Template)
+
 	d.cachedStatements = cache.NewCache()
 
 	d.collections = make(map[string]*table)
@@ -197,16 +200,12 @@ func (d *database) Close() error {
 }
 
 // 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 {
+func (d *database) C(name string) db.Collection {
+	if c, ok := d.collections[name]; ok {
 		return c
 	}
 
-	c, err := d.Collection(names...)
+	c, err := d.Collection(name)
 	if err != nil {
 		return &adapter.NonExistentCollection{Err: err}
 	}
@@ -214,43 +213,21 @@ func (d *database) C(names ...string) db.Collection {
 }
 
 // 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
-	}
-
+func (d *database) Collection(name string) (db.Collection, error) {
 	if d.tx != nil {
 		if d.tx.Done() {
 			return nil, sql.ErrTxDone
 		}
 	}
 
-	col := &table{database: d}
-	col.T.Tables = names
-
-	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
-		}
+	if err := d.tableExists(name); err != nil {
+		return nil, err
 	}
 
-	// Saving the collection for C().
+	col := &table{database: d, name: name}
+
 	d.collectionsMu.Lock()
-	d.collections[sqlutil.HashTableNames(names)] = col
+	d.collections[name] = col
 	d.collectionsMu.Unlock()
 
 	return col, nil
@@ -638,7 +615,7 @@ func (d *database) getPrimaryKey(tableName string) ([]string, error) {
 
 // Builder returns a custom query builder.
 func (d *database) Builder() db.QueryBuilder {
-	return builder.NewBuilder(d, template)
+	return d.builder
 }
 
 // waitForConnection tries to execute the connectFn function, if connectFn
diff --git a/postgresql/database_test.go b/postgresql/database_test.go
index f98e862e20f0c806330f3635a85afb954ed3e43a..94053effbea249a3089c8ce22ee09aacfa80c1dc 100644
--- a/postgresql/database_test.go
+++ b/postgresql/database_test.go
@@ -35,9 +35,7 @@ import (
 	"time"
 
 	"github.com/jmoiron/sqlx"
-	"github.com/stretchr/testify/assert"
 	"upper.io/db"
-	"upper.io/db/util/sqlutil"
 )
 
 const (
@@ -1131,225 +1129,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 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",
-		db.Raw{"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
@@ -1914,269 +1693,6 @@ func TestOptionTypeJsonbStruct(t *testing.T) {
 	}
 }
 
-func TestQueryBuilder(t *testing.T) {
-	var sess db.Database
-	var err error
-
-	if sess, err = db.Open(Adapter, settings); err != nil {
-		t.Fatal(err)
-	}
-
-	defer sess.Close()
-
-	b := sess.Builder()
-
-	assert := assert.New(t)
-
-	// Testing SELECT.
-
-	assert.Equal(
-		`SELECT * FROM "artist"`,
-		b.SelectAllFrom("artist").String(),
-	)
-
-	assert.Equal(
-		`SELECT * FROM "artist"`,
-		b.Select().From("artist").String(),
-	)
-
-	assert.Equal(
-		`SELECT * FROM "artist" LIMIT -1 OFFSET 5`,
-		b.Select().From("artist").Limit(-1).Offset(5).String(),
-	)
-
-	assert.Equal(
-		`SELECT "id" FROM "artist"`,
-		b.Select("id").From("artist").String(),
-	)
-
-	assert.Equal(
-		`SELECT "id", "name" FROM "artist"`,
-		b.Select("id", "name").From("artist").String(),
-	)
-
-	assert.Equal(
-		`SELECT * FROM "artist" WHERE ("name" = $1)`,
-		b.SelectAllFrom("artist").Where("name", "Haruki").String(),
-	)
-
-	assert.Equal(
-		`SELECT * FROM "artist" WHERE (name LIKE $1)`,
-		b.SelectAllFrom("artist").Where("name LIKE ?", `%F%`).String(),
-	)
-
-	assert.Equal(
-		`SELECT "id" FROM "artist" WHERE (name LIKE $1 OR name LIKE $2)`,
-		b.Select("id").From("artist").Where(`name LIKE ? OR name LIKE ?`, `%Miya%`, `F%`).String(),
-	)
-
-	assert.Equal(
-		`SELECT * FROM "artist" WHERE ("id" > $1)`,
-		b.SelectAllFrom("artist").Where("id >", 2).String(),
-	)
-
-	assert.Equal(
-		`SELECT * FROM "artist" WHERE (id <= 2 AND name != $1)`,
-		b.SelectAllFrom("artist").Where("id <= 2 AND name != ?", "A").String(),
-	)
-
-	assert.Equal(
-		`SELECT * FROM "artist" WHERE ("id" IN ($1, $2, $3, $4))`,
-		b.SelectAllFrom("artist").Where("id IN", []int{1, 9, 8, 7}).String(),
-	)
-
-	assert.Equal(
-		`SELECT * FROM "artist" WHERE (name IS NOT NULL)`,
-		b.SelectAllFrom("artist").Where("name IS NOT NULL").String(),
-	)
-
-	assert.Equal(
-		`SELECT * FROM "artist" AS "a", "publication" AS "p" WHERE (p.author_id = a.id) LIMIT 1`,
-		b.Select().From("artist a", "publication as p").Where("p.author_id = a.id").Limit(1).String(),
-	)
-
-	assert.Equal(
-		`SELECT "id" FROM "artist" NATURAL JOIN "publication"`,
-		b.Select("id").From("artist").Join("publication").String(),
-	)
-
-	assert.Equal(
-		`SELECT * FROM "artist" AS "a" JOIN "publication" AS "p" ON (p.author_id = a.id) LIMIT 1`,
-		b.SelectAllFrom("artist a").Join("publication p").On("p.author_id = a.id").Limit(1).String(),
-	)
-
-	assert.Equal(
-		`SELECT * FROM "artist" AS "a" JOIN "publication" AS "p" ON (p.author_id = a.id) WHERE ("a"."id" = $1) LIMIT 1`,
-		b.SelectAllFrom("artist a").Join("publication p").On("p.author_id = a.id").Where("a.id", 2).Limit(1).String(),
-	)
-
-	assert.Equal(
-		`SELECT * FROM "artist" JOIN "publication" AS "p" ON (p.author_id = a.id) WHERE (a.id = 2) LIMIT 1`,
-		b.SelectAllFrom("artist").Join("publication p").On("p.author_id = a.id").Where("a.id = 2").Limit(1).String(),
-	)
-
-	assert.Equal(
-		`SELECT * FROM "artist" AS "a" JOIN "publication" AS "p" ON (p.title LIKE $1 OR p.title LIKE $2) WHERE (a.id = $3) LIMIT 1`,
-		b.SelectAllFrom("artist a").Join("publication p").On("p.title LIKE ? OR p.title LIKE ?", "%Totoro%", "%Robot%").Where("a.id = ?", 2).Limit(1).String(),
-	)
-
-	assert.Equal(
-		`SELECT * FROM "artist" AS "a" LEFT JOIN "publication" AS "p1" ON (p1.id = a.id) RIGHT JOIN "publication" AS "p2" ON (p2.id = a.id)`,
-		b.SelectAllFrom("artist a").
-			LeftJoin("publication p1").On("p1.id = a.id").
-			RightJoin("publication p2").On("p2.id = a.id").
-			String(),
-	)
-
-	assert.Equal(
-		`SELECT * FROM "artist" CROSS JOIN "publication"`,
-		b.SelectAllFrom("artist").CrossJoin("publication").String(),
-	)
-
-	assert.Equal(
-		`SELECT * FROM "artist" JOIN "publication" USING ("id")`,
-		b.SelectAllFrom("artist").Join("publication").Using("id").String(),
-	)
-
-	assert.Equal(
-		`SELECT DATE()`,
-		b.Select(db.Raw{"DATE()"}).String(),
-	)
-
-	// Testing INSERT.
-
-	assert.Equal(
-		`INSERT INTO "artist" VALUES ($1, $2), ($3, $4), ($5, $6)`,
-		b.InsertInto("artist").
-			Values(10, "Ryuichi Sakamoto").
-			Values(11, "Alondra de la Parra").
-			Values(12, "Haruki Murakami").
-			String(),
-	)
-
-	assert.Equal(
-		`INSERT INTO "artist" ("name", "id") VALUES ($1, $2)`,
-		b.InsertInto("artist").Values(map[string]string{"id": "12", "name": "Chavela Vargas"}).String(),
-	)
-
-	assert.Equal(
-		`INSERT INTO "artist" ("name", "id") VALUES ($1, $2)`,
-		b.InsertInto("artist").Values(struct {
-			ID   int    `db:"id"`
-			Name string `db:"name"`
-		}{12, "Chavela Vargas"}).String(),
-	)
-
-	assert.Equal(
-		`INSERT INTO "artist" ("name", "id") VALUES ($1, $2)`,
-		b.InsertInto("artist").Columns("name", "id").Values("Chavela Vargas", 12).String(),
-	)
-
-	// Testing DELETE.
-
-	assert.Equal(
-		`DELETE FROM "artist" WHERE (name = $1) LIMIT 1`,
-		b.DeleteFrom("artist").Where("name = ?", "Chavela Vargas").Limit(1).String(),
-	)
-
-	assert.Equal(
-		`DELETE FROM "artist" WHERE (id > 5)`,
-		b.DeleteFrom("artist").Where("id > 5").String(),
-	)
-
-	// Testing UPDATE.
-
-	assert.Equal(
-		`UPDATE "artist" SET "name" = $1`,
-		b.Update("artist").Set("name", "Artist").String(),
-	)
-
-	assert.Equal(
-		`UPDATE "artist" SET "name" = $1 WHERE ("id" < $2)`,
-		b.Update("artist").Set("name = ?", "Artist").Where("id <", 5).String(),
-	)
-
-	assert.Equal(
-		`UPDATE "artist" SET "name" = $1 WHERE ("id" < $2)`,
-		b.Update("artist").Set(map[string]string{"name": "Artist"}).Where(db.Cond{"id <": 5}).String(),
-	)
-
-	assert.Equal(
-		`UPDATE "artist" SET "name" = $1 WHERE ("id" < $2)`,
-		b.Update("artist").Set(struct {
-			Nombre string `db:"name"`
-		}{"Artist"}).Where(db.Cond{"id <": 5}).String(),
-	)
-
-	assert.Equal(
-		`UPDATE "artist" SET "name" = $1, "last_name" = $2 WHERE ("id" < $3)`,
-		b.Update("artist").Set(struct {
-			Nombre string `db:"name"`
-		}{"Artist"}).Set(map[string]string{"last_name": "Foo"}).Where(db.Cond{"id <": 5}).String(),
-	)
-
-	assert.Equal(
-		`UPDATE "artist" SET "name" = $1 || ' ' || $2 || id, "id" = id + $3 WHERE (id > $4)`,
-		b.Update("artist").Set(
-			"name = ? || ' ' || ? || id", "Artist", "#",
-			"id = id + ?", 10,
-		).Where("id > ?", 0).String(),
-	)
-
-	/*
-		// INSERT INTO artist (name) VALUES(? || ?)
-		if err = b.InsertInto("artist").Columns("name").Values(db.Expr("? || ' ' || ?", "Tom", "Yorke")).Exec(); err != nil {
-			t.Fatal(err)
-		}
-		// INSERT INTO artist ("name") VALUES('Michael Jackson')
-		if err = b.InsertInto("artist").Columns("name").Record(map[string]string{"no": "Not me!", "name": "Michael Jackson"}).Exec(); err != nil {
-			t.Fatal(err)
-		}
-
-		// INSERT INTO artist ("id", "name") VALUES(20, 'Francisco Toledo')
-		if err = b.InsertInto("artist").Value(map[string]string{"id": 20, "name": "Francisco Toledo"}).Exec(); err != nil {
-			t.Fatal(err)
-		}
-
-		// INSERT INTO artist ("name") VALUES('Mads Mikkelsen')
-		if err = b.InsertInto("artist").Value(artistType{"Mads Mikkelsen"}).Exec(); err != nil {
-			t.Fatal(err)
-		}
-	*/
-
-	// Testing actual queries.
-
-	/*
-		var artist artistType
-		var artists []artistType
-
-		err = b.SelectAllFrom("artist").Iterator().All(&artists)
-		assert.NoError(err)
-		assert.True(len(artists) > 0)
-
-		err = b.SelectAllFrom("artist").Iterator().One(&artist)
-		assert.NoError(err)
-		assert.NotNil(artist)
-
-		var qs db.QuerySelector
-
-		qs = b.SelectAllFrom("artist")
-		iter := qs.Iterator()
-		for iter.Next(&artist) {
-			assert.Nil(iter.Err())
-			assert.NotNil(artist)
-		}
-
-		assert.Nil(iter.Close())
-
-		qs = b.Select().From("artist a").Join("publications p").On("p1.id = a.id").Using("id")
-		assert.Error(qs.Iterator().One(&artist), `Should not work because it attempts to use both "On()" and "Using()" in the same JOIN.`)
-
-		qs = b.Select().From("artist a").On("p1.id = a.id")
-		assert.Error(qs.Iterator().One(&artist), `Should not work because it should put a "Join()" before "On()".`)
-	*/
-}
-
 // TestExhaustConnections simulates a "too many connections" situation
 // triggered by opening more transactions than available connections.
 // upper.io/db deals with this problem by waiting a bit more for the connection
diff --git a/util/sqlgen/default.go b/util/sqlgen/default.go
index 3bd1a5c67068a8447d923ce76fa48ab32a8476c1..db531ccd2d7157126645ac9021eb7151890c11e6 100644
--- a/util/sqlgen/default.go
+++ b/util/sqlgen/default.go
@@ -16,6 +16,7 @@ const (
 	defaultDescKeyword         = `DESC`
 	defaultAscKeyword          = `ASC`
 	defaultDefaultOperator     = `=`
+	defaultAssignmentOperator  = `=`
 	defaultClauseGroup         = `({{.}})`
 	defaultClauseOperator      = ` {{.}} `
 	defaultColumnValue         = `{{.Column}} {{.Operator}} {{.Value}}`
@@ -64,36 +65,44 @@ const (
 	`
 
 	defaultSelectLayout = `
-		SELECT
+    SELECT
 
-			{{if .Columns}}
-				{{.Columns}}
-			{{else}}
-				*
-			{{end}}
+      {{if .Columns}}
+        {{.Columns}}
+      {{else}}
+        *
+      {{end}}
 
-			FROM {{.Table}}
+      {{if .Table}}
+        FROM {{.Table}}
+      {{end}}
 
-			{{.Joins}}
+      {{.Joins}}
 
-			{{.Where}}
+      {{.Where}}
 
-			{{.GroupBy}}
+      {{.GroupBy}}
 
-			{{.OrderBy}}
+      {{.OrderBy}}
 
-			{{if .Limit}}
-				LIMIT {{.Limit}}
-			{{end}}
+      {{if .Limit}}
+        LIMIT {{.Limit}}
+      {{end}}
 
-			{{if .Offset}}
-				OFFSET {{.Offset}}
-			{{end}}
+      {{if .Offset}}
+        OFFSET {{.Offset}}
+      {{end}}
 	`
 	defaultDeleteLayout = `
-		DELETE
-			FROM {{.Table}}
-			{{.Where}}
+    DELETE
+      FROM {{.Table}}
+      {{.Where}}
+    {{if .Limit}}
+      LIMIT {{.Limit}}
+    {{end}}
+    {{if .Offset}}
+      OFFSET {{.Offset}}
+    {{end}}
 	`
 	defaultUpdateLayout = `
 		UPDATE
@@ -118,11 +127,11 @@ const (
 	`
 
 	defaultInsertLayout = `
-		INSERT INTO {{.Table}}
-			({{.Columns}})
-		VALUES
-			{{.Values}}
-		{{.Extra}}
+    INSERT INTO {{.Table}}
+      {{if .Columns }}({{.Columns}}){{end}}
+    VALUES
+      {{.Values}}
+    {{.Extra}}
 	`
 
 	defaultTruncateLayout = `
@@ -158,6 +167,7 @@ var defaultTemplate = &Template{
 	DescKeyword:         defaultDescKeyword,
 	AscKeyword:          defaultAscKeyword,
 	DefaultOperator:     defaultDefaultOperator,
+	AssignmentOperator:  defaultAssignmentOperator,
 	ClauseGroup:         defaultClauseGroup,
 	ClauseOperator:      defaultClauseOperator,
 	ColumnValue:         defaultColumnValue,
diff --git a/util/sqlutil/sqlutil.go b/util/sqlutil/sqlutil.go
deleted file mode 100644
index 3290adfa2e5451eaad77cd63e666a493ece7ada4..0000000000000000000000000000000000000000
--- a/util/sqlutil/sqlutil.go
+++ /dev/null
@@ -1,54 +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 sqlutil
-
-import (
-	"strings"
-)
-
-type T struct {
-	Columns []string
-	Tables  []string // Holds table names.
-}
-
-// MainTableName returns the name of the first table.
-func (t *T) MainTableName() string {
-	return t.NthTableName(0)
-}
-
-// NthTableName returns the table name at index i.
-func (t *T) NthTableName(i int) string {
-	if len(t.Tables) > i {
-		chunks := strings.SplitN(t.Tables[i], " ", 2)
-		if len(chunks) > 0 {
-			return chunks[0]
-		}
-	}
-	return ""
-}
-
-// HashTableNames returns a unique string for the given array of tables.
-func HashTableNames(names []string) string {
-	return strings.Join(names, "|")
-	// I think we don't really need to do this, the strings.Join already provides a unique string per array.
-	// return fmt.Sprintf("%x", md5.Sum([]byte(strings.Join(names, "|"))))
-}