diff --git a/util/sqlgen/benchmark_test.go b/util/sqlgen/benchmark_test.go
index 3cc2e25f2052bf6705902427aaf5cc419cbd3bf6..923950352ff8da46fdd6d2026175fcfb36250149 100644
--- a/util/sqlgen/benchmark_test.go
+++ b/util/sqlgen/benchmark_test.go
@@ -12,15 +12,21 @@ func BenchmarkColumn(b *testing.B) {
 	}
 }
 
-func BenchmarkColumnNestedValue(b *testing.B) {
+func BenchmarkCompileColumn(b *testing.B) {
 	for i := 0; i < b.N; i++ {
-		_ = Column{Value: "a"}
+		_ = Column{Value: "a"}.Compile(defaultTemplate)
 	}
 }
 
-func BenchmarkCompileColumn(b *testing.B) {
+func BenchmarkColumns(b *testing.B) {
 	for i := 0; i < b.N; i++ {
-		_ = Column{Value: "a"}.Compile(defaultTemplate)
+		_ = Columns{{"a"}, {"b"}, {"c"}}
+	}
+}
+
+func BenchmarkCompileColumns(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		_ = Columns{{"a"}, {"b"}, {"c"}}.Compile(defaultTemplate)
 	}
 }
 
@@ -30,6 +36,36 @@ func BenchmarkValue(b *testing.B) {
 	}
 }
 
+func BenchmarkCompileValue(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		_ = Value{"a"}.Compile(defaultTemplate)
+	}
+}
+
+func BenchmarkValues(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		_ = Values{{"a"}, {"b"}, {"c"}, {1}, {2}, {3}}
+	}
+}
+
+func BenchmarkCompileValues(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		_ = Values{{"a"}, {"b"}, {"c"}, {1}, {2}, {3}}.Compile(defaultTemplate)
+	}
+}
+
+func BenchmarkDatabase(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		_ = Database{"TestDatabase"}
+	}
+}
+
+func BenchmarkCompileDatabase(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		_ = Database{"TestDatabase"}.Compile(defaultTemplate)
+	}
+}
+
 func BenchmarkValueRaw(b *testing.B) {
 	for i := 0; i < b.N; i++ {
 		_ = Value{Raw{"a"}}
@@ -42,6 +78,76 @@ func BenchmarkColumnValue(b *testing.B) {
 	}
 }
 
+func BenchmarkCompileColumnValue(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		_ = ColumnValue{Column{"a"}, "=", Value{Raw{"7"}}}.Compile(defaultTemplate)
+	}
+}
+
+func BenchmarkColumnValues(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		_ = ColumnValues{{Column{"a"}, "=", Value{Raw{"7"}}}}
+	}
+}
+
+func BenchmarkCompileColumnValues(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		_ = ColumnValues{{Column{"a"}, "=", Value{Raw{"7"}}}}.Compile(defaultTemplate)
+	}
+}
+
+func BenchmarkOrderBy(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		_ = OrderBy{
+			SortColumns: SortColumns{
+				SortColumn{Column: Column{"foo"}},
+			},
+		}
+	}
+}
+
+func BenchmarkCompileOrderBy(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		_ = OrderBy{
+			SortColumns: SortColumns{
+				SortColumn{Column: Column{"foo"}},
+			},
+		}.Compile(defaultTemplate)
+	}
+}
+
+func BenchmarkGroupBy(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		_ = GroupBy{
+			Column{"foo"},
+		}
+	}
+}
+
+func BenchmarkCompileGroupBy(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		_ = GroupBy{
+			Column{"foo"},
+		}.Compile(defaultTemplate)
+	}
+}
+
+func BenchmarkWhere(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		_ = Where{
+			ColumnValue{Column{"baz"}, "=", Value{99}},
+		}
+	}
+}
+
+func BenchmarkCompileWhere(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		_ = Where{
+			ColumnValue{Column{"baz"}, "=", Value{99}},
+		}.Compile(defaultTemplate)
+	}
+}
+
 func BenchmarkTable(b *testing.B) {
 	for i := 0; i < b.N; i++ {
 		_ = Table{"foo"}
@@ -75,14 +181,6 @@ func BenchmarkCompileRandomTable(b *testing.B) {
 	}
 }
 
-func BenchmarkWhere(b *testing.B) {
-	for i := 0; i < b.N; i++ {
-		_ = Where{
-			ColumnValue{Column{"a"}, "=", Value{Raw{"7"}}},
-		}
-	}
-}
-
 func BenchmarkCompileSelect(b *testing.B) {
 	var stmt Statement
 
diff --git a/util/sqlgen/column.go b/util/sqlgen/column.go
index a43ec871888369423acfeefac2530d7974fd67bd..6a69c98de0ec65b3126cbba9d49754f78c5f573d 100644
--- a/util/sqlgen/column.go
+++ b/util/sqlgen/column.go
@@ -14,20 +14,33 @@ type Column struct {
 	Value interface{}
 }
 
+func (self Column) Hash() string {
+	switch t := self.Value.(type) {
+	case cc:
+		return `Column(` + t.Hash() + `)`
+	case string:
+		return `Column(` + t + `)`
+	}
+	return fmt.Sprintf(`Column(%v)`, self.Value)
+}
+
 func (self Column) Compile(layout *Template) (compiled string) {
 
-	if s, ok := layout.Cache(self); ok {
-		return s
+	if c, ok := layout.Read(self); ok {
+		return c
 	}
 
 	switch value := self.Value.(type) {
 	case string:
-		input := strings.TrimSpace(value)
+		// input := strings.TrimSpace(value)
+		input := trimString(value)
 
-		chunks := reAliasSeparator.Split(input, 2)
+		//chunks := reAliasSeparator.Split(input, 2)
+		chunks := separateByAS(input)
 
 		if len(chunks) == 1 {
-			chunks = reSpaceSeparator.Split(input, 2)
+			//chunks = reSpaceSeparator.Split(input, 2)
+			chunks = separateBySpace(input)
 		}
 
 		name := chunks[0]
@@ -35,7 +48,8 @@ func (self Column) Compile(layout *Template) (compiled string) {
 		nameChunks := strings.SplitN(name, layout.ColumnSeparator, 2)
 
 		for i := range nameChunks {
-			nameChunks[i] = strings.TrimSpace(nameChunks[i])
+			// nameChunks[i] = strings.TrimSpace(nameChunks[i])
+			nameChunks[i] = trimString(nameChunks[i])
 			nameChunks[i] = mustParse(layout.IdentifierQuote, Raw{nameChunks[i]})
 		}
 
@@ -44,7 +58,8 @@ func (self Column) Compile(layout *Template) (compiled string) {
 		var alias string
 
 		if len(chunks) > 1 {
-			alias = strings.TrimSpace(chunks[1])
+			// alias = strings.TrimSpace(chunks[1])
+			alias = trimString(chunks[1])
 			alias = mustParse(layout.IdentifierQuote, Raw{alias})
 		}
 
@@ -55,7 +70,7 @@ func (self Column) Compile(layout *Template) (compiled string) {
 		compiled = fmt.Sprintf("%v", self.Value)
 	}
 
-	layout.SetCache(self, compiled)
+	layout.Write(self, compiled)
 
-	return compiled
+	return
 }
diff --git a/util/sqlgen/column_value.go b/util/sqlgen/column_value.go
index 2d8dfd1577b94e3ceb84ff30e978bf52c24adea5..fbe57987c43aec83b0ed24b42cb15156dd82c3f9 100644
--- a/util/sqlgen/column_value.go
+++ b/util/sqlgen/column_value.go
@@ -16,10 +16,14 @@ type columnValue_s struct {
 	Value    string
 }
 
+func (self ColumnValue) Hash() string {
+	return `ColumnValue(` + self.Column.Hash() + `;` + self.Operator + `;` + self.Value.Hash() + `)`
+}
+
 func (self ColumnValue) Compile(layout *Template) (compiled string) {
 
-	if s, ok := layout.Cache(self); ok {
-		return s
+	if c, ok := layout.Read(self); ok {
+		return c
 	}
 
 	data := columnValue_s{
@@ -30,18 +34,26 @@ func (self ColumnValue) Compile(layout *Template) (compiled string) {
 
 	compiled = mustParse(layout.ColumnValue, data)
 
+	layout.Write(self, compiled)
+
 	return
 }
 
 type ColumnValues []ColumnValue
 
+func (self ColumnValues) Hash() string {
+	hash := make([]string, 0, len(self))
+	for i := range self {
+		hash = append(hash, self[i].Hash())
+	}
+	return `ColumnValues(` + strings.Join(hash, `,`) + `)`
+}
+
 func (self ColumnValues) Compile(layout *Template) (compiled string) {
 
-	/*
-		if s, ok := layout.Cache(self); ok {
-			return s
-		}
-	*/
+	if c, ok := layout.Read(self); ok {
+		return c
+	}
 
 	l := len(self)
 
@@ -53,5 +65,7 @@ func (self ColumnValues) Compile(layout *Template) (compiled string) {
 
 	compiled = strings.Join(out, layout.IdentifierSeparator)
 
+	layout.Write(self, compiled)
+
 	return
 }
diff --git a/util/sqlgen/columns.go b/util/sqlgen/columns.go
index 0cf1039306d5f61bd036cd4a94698c24dc5fff22..dfe41f2e38c5133550751bd4d1a3501081e1537c 100644
--- a/util/sqlgen/columns.go
+++ b/util/sqlgen/columns.go
@@ -6,7 +6,20 @@ import (
 
 type Columns []Column
 
-func (self Columns) Compile(layout *Template) string {
+func (self Columns) Hash() string {
+	hash := make([]string, 0, len(self))
+	for i := range self {
+		hash = append(hash, self[i].Hash())
+	}
+	return `Columns(` + strings.Join(hash, `,`) + `)`
+}
+
+func (self Columns) Compile(layout *Template) (compiled string) {
+
+	if c, ok := layout.Read(self); ok {
+		return c
+	}
+
 	l := len(self)
 
 	if l > 0 {
@@ -16,7 +29,10 @@ func (self Columns) Compile(layout *Template) string {
 			out[i] = self[i].Compile(layout)
 		}
 
-		return strings.Join(out, layout.IdentifierSeparator)
+		compiled = strings.Join(out, layout.IdentifierSeparator)
 	}
-	return ""
+
+	layout.Write(self, compiled)
+
+	return
 }
diff --git a/util/sqlgen/database.go b/util/sqlgen/database.go
index 4e89db551a3f3ee6c04ddfc26238858c75db8053..6c5f731477d0053b264ff9640f03a2288c1e8dbd 100644
--- a/util/sqlgen/database.go
+++ b/util/sqlgen/database.go
@@ -8,6 +8,18 @@ type Database struct {
 	Value string
 }
 
-func (self Database) Compile(layout *Template) string {
-	return mustParse(layout.IdentifierQuote, Raw{fmt.Sprintf(`%v`, self.Value)})
+func (self Database) Hash() string {
+	return `Database(` + self.Value + `)`
+}
+
+func (self Database) Compile(layout *Template) (compiled string) {
+	if c, ok := layout.Read(self); ok {
+		return c
+	}
+
+	compiled = mustParse(layout.IdentifierQuote, Raw{fmt.Sprintf(`%v`, self.Value)})
+
+	layout.Write(self, compiled)
+
+	return
 }
diff --git a/util/sqlgen/default.go b/util/sqlgen/default.go
index 9038db0fa9cd0eb9097c815ebc7f26edee4391f8..4b2a3f20922f845b401e3af2416e891b2da8a57b 100644
--- a/util/sqlgen/default.go
+++ b/util/sqlgen/default.go
@@ -1,5 +1,9 @@
 package sqlgen
 
+import (
+	"upper.io/cache"
+)
+
 const (
 	defaultColumnSeparator     = `.`
 	defaultIdentifierSeparator = `, `
@@ -113,34 +117,33 @@ const (
 )
 
 var defaultTemplate = &Template{
-	defaultColumnSeparator,
-	defaultIdentifierSeparator,
-	defaultIdentifierQuote,
-	defaultValueSeparator,
-	defaultValueQuote,
-	defaultAndKeyword,
-	defaultOrKeyword,
-	defaultNotKeyword,
-	defaultDescKeyword,
-	defaultAscKeyword,
-	defaultDefaultOperator,
-	defaultClauseGroup,
-	defaultClauseOperator,
-	defaultColumnValue,
-	defaultTableAliasLayout,
-	defaultColumnAliasLayout,
-	defaultSortByColumnLayout,
-	defaultWhereLayout,
-	defaultOrderByLayout,
-	defaultInsertLayout,
-	defaultSelectLayout,
-	defaultUpdateLayout,
-	defaultDeleteLayout,
-	defaultTruncateLayout,
-	defaultDropDatabaseLayout,
-	defaultDropTableLayout,
-	defaultSelectCountLayout,
-	defaultGroupByLayout,
-	nil,
-	nil,
+	ColumnSeparator:     defaultColumnSeparator,
+	IdentifierSeparator: defaultIdentifierSeparator,
+	IdentifierQuote:     defaultIdentifierQuote,
+	ValueSeparator:      defaultValueSeparator,
+	ValueQuote:          defaultValueQuote,
+	AndKeyword:          defaultAndKeyword,
+	OrKeyword:           defaultOrKeyword,
+	NotKeyword:          defaultNotKeyword,
+	DescKeyword:         defaultDescKeyword,
+	AscKeyword:          defaultAscKeyword,
+	DefaultOperator:     defaultDefaultOperator,
+	ClauseGroup:         defaultClauseGroup,
+	ClauseOperator:      defaultClauseOperator,
+	ColumnValue:         defaultColumnValue,
+	TableAliasLayout:    defaultTableAliasLayout,
+	ColumnAliasLayout:   defaultColumnAliasLayout,
+	SortByColumnLayout:  defaultSortByColumnLayout,
+	WhereLayout:         defaultWhereLayout,
+	OrderByLayout:       defaultOrderByLayout,
+	InsertLayout:        defaultInsertLayout,
+	SelectLayout:        defaultSelectLayout,
+	UpdateLayout:        defaultUpdateLayout,
+	DeleteLayout:        defaultDeleteLayout,
+	TruncateLayout:      defaultTruncateLayout,
+	DropDatabaseLayout:  defaultDropDatabaseLayout,
+	DropTableLayout:     defaultDropTableLayout,
+	SelectCountLayout:   defaultSelectCountLayout,
+	GroupByLayout:       defaultGroupByLayout,
+	Cache:               cache.NewCache(),
 }
diff --git a/util/sqlgen/group_by.go b/util/sqlgen/group_by.go
index 54e7f03ffd9ec0b3baf47ff82425663b618e5673..28aa812fce9d25ace9f726c627530568aa83a9a2 100644
--- a/util/sqlgen/group_by.go
+++ b/util/sqlgen/group_by.go
@@ -6,14 +6,26 @@ type groupBy_s struct {
 	GroupColumns string
 }
 
-func (self GroupBy) Compile(layout *Template) string {
+func (self GroupBy) Hash() string {
+	return `GroupBy(` + Columns(self).Hash() + `)`
+}
+
+func (self GroupBy) Compile(layout *Template) (compiled string) {
+
+	if c, ok := layout.Read(self); ok {
+		return c
+	}
+
 	if len(self) > 0 {
 
 		data := groupBy_s{
 			GroupColumns: Columns(self).Compile(layout),
 		}
 
-		return mustParse(layout.GroupByLayout, data)
+		compiled = mustParse(layout.GroupByLayout, data)
 	}
-	return ""
+
+	layout.Write(self, compiled)
+
+	return
 }
diff --git a/util/sqlgen/interfaces.go b/util/sqlgen/interfaces.go
new file mode 100644
index 0000000000000000000000000000000000000000..234742c40098cf1696bbe100b25faafa6070482a
--- /dev/null
+++ b/util/sqlgen/interfaces.go
@@ -0,0 +1,14 @@
+package sqlgen
+
+import (
+	"upper.io/cache"
+)
+
+type cc interface {
+	cache.Cacheable
+	compilable
+}
+
+type compilable interface {
+	Compile(*Template) string
+}
diff --git a/util/sqlgen/order_by.go b/util/sqlgen/order_by.go
index 758a13eb3bf25ee00a071f8102d651527348d6e7..a88fe69a3cb5e7077ece8af0e4f49d94d1b5c86a 100644
--- a/util/sqlgen/order_by.go
+++ b/util/sqlgen/order_by.go
@@ -1,6 +1,8 @@
 package sqlgen
 
-import "strings"
+import (
+	"strings"
+)
 
 type SortColumn struct {
 	Column
@@ -14,6 +16,18 @@ type sortColumn_s struct {
 
 type SortColumns []SortColumn
 
+func (self SortColumn) Hash() string {
+	return `SortColumn(` + self.Column.Hash() + `;` + self.Sort.Hash() + `)`
+}
+
+func (self SortColumns) Hash() string {
+	hash := make([]string, 0, len(self))
+	for i := range self {
+		hash = append(hash, self[i].Hash())
+	}
+	return `SortColumns(` + strings.Join(hash, `,`) + `)`
+}
+
 func (self SortColumns) Compile(layout *Template) string {
 	l := len(self)
 	s := make([]string, 0, l)
@@ -23,12 +37,21 @@ func (self SortColumns) Compile(layout *Template) string {
 	return strings.Join(s, layout.IdentifierSeparator)
 }
 
-func (self SortColumn) Compile(layout *Template) string {
+func (self SortColumn) Compile(layout *Template) (compiled string) {
+
+	if c, ok := layout.Read(self); ok {
+		return c
+	}
+
 	data := sortColumn_s{
 		Column: self.Column.Compile(layout),
 		Sort:   self.Sort.Compile(layout),
 	}
-	return mustParse(layout.SortByColumnLayout, data)
+
+	compiled = mustParse(layout.SortByColumnLayout, data)
+
+	layout.Write(self, compiled)
+	return
 }
 
 type OrderBy struct {
@@ -39,14 +62,26 @@ type orderBy_s struct {
 	SortColumns string
 }
 
-func (self OrderBy) Compile(layout *Template) string {
+func (self OrderBy) Hash() string {
+	return `OrderBy(` + self.SortColumns.Hash() + `)`
+}
+
+func (self OrderBy) Compile(layout *Template) (compiled string) {
+
+	if c, ok := layout.Read(self); ok {
+		return c
+	}
+
 	if len(self.SortColumns) > 0 {
 		data := orderBy_s{
 			SortColumns: self.SortColumns.Compile(layout),
 		}
-		return mustParse(layout.OrderByLayout, data)
+		compiled = mustParse(layout.OrderByLayout, data)
 	}
-	return ""
+
+	layout.Write(self, compiled)
+
+	return
 }
 
 type Sort uint8
@@ -57,6 +92,16 @@ const (
 	SqlSortDesc
 )
 
+func (self Sort) Hash() string {
+	switch self {
+	case SqlSortAsc:
+		return `Sort(1)`
+	case SqlSortDesc:
+		return `Sort(2)`
+	}
+	return `Sort(0)`
+}
+
 func (self Sort) Compile(layout *Template) string {
 	switch self {
 	case SqlSortAsc:
diff --git a/util/sqlgen/raw.go b/util/sqlgen/raw.go
index d62a3aca8fbdbe1eebfdf9613c18eb0afbb5d177..cda0e66bd25c0805badfdf648b7f5b7ab6481fcf 100644
--- a/util/sqlgen/raw.go
+++ b/util/sqlgen/raw.go
@@ -4,6 +4,14 @@ type Raw struct {
 	Raw string
 }
 
+func (self Raw) Hash() string {
+	return `Raw(` + self.Raw + `)`
+}
+
+func (self Raw) Compile(*Template) string {
+	return self.Raw
+}
+
 func (self Raw) String() string {
 	return self.Raw
 }
diff --git a/util/sqlgen/table.go b/util/sqlgen/table.go
index 141c4dc2052c2b34d0b369b9077c41f419edba02..ed28c8b596327a0b6712d9e2fe6d0c0bc28205cd 100644
--- a/util/sqlgen/table.go
+++ b/util/sqlgen/table.go
@@ -1,16 +1,9 @@
 package sqlgen
 
 import (
-	"regexp"
 	"strings"
 )
 
-var (
-	reTableSeparator = regexp.MustCompile(`\s*?,\s*?`)
-	reAliasSeparator = regexp.MustCompile(`(?i:\s+AS\s+)`)
-	reSpaceSeparator = regexp.MustCompile(`\s+`)
-)
-
 type table_t struct {
 	Name  string
 	Alias string
@@ -55,7 +48,7 @@ func quotedTableName(layout *Template, input string) string {
 }
 
 func (self Table) Hash() string {
-	return self.Name
+	return `Table(` + self.Name + `)`
 }
 
 func (self Table) Compile(layout *Template) (compiled string) {
@@ -64,25 +57,22 @@ func (self Table) Compile(layout *Template) (compiled string) {
 		return
 	}
 
-	if layout.isCached(self) {
-
-		compiled = layout.getCache(self)
-
-	} else {
+	if c, ok := layout.Read(self); ok {
+		return c
+	}
 
-		// Splitting tables by a comma
-		parts := separateByComma(self.Name)
+	// Splitting tables by a comma
+	parts := separateByComma(self.Name)
 
-		l := len(parts)
+	l := len(parts)
 
-		for i := 0; i < l; i++ {
-			parts[i] = quotedTableName(layout, parts[i])
-		}
+	for i := 0; i < l; i++ {
+		parts[i] = quotedTableName(layout, parts[i])
+	}
 
-		compiled = strings.Join(parts, layout.IdentifierSeparator)
+	compiled = strings.Join(parts, layout.IdentifierSeparator)
 
-		layout.setCache(self, compiled)
-	}
+	layout.Write(self, compiled)
 
 	return
 }
diff --git a/util/sqlgen/template.go b/util/sqlgen/template.go
index 7502e27f73b0b80bf92916d98d4241ceac3d31c4..e3ff175cb0619793fe32f907581eb7de2e687104 100644
--- a/util/sqlgen/template.go
+++ b/util/sqlgen/template.go
@@ -1,5 +1,9 @@
 package sqlgen
 
+import (
+	"upper.io/cache"
+)
+
 type Template struct {
 	ColumnSeparator     string
 	IdentifierSeparator string
@@ -29,50 +33,5 @@ type Template struct {
 	DropTableLayout     string
 	SelectCountLayout   string
 	GroupByLayout       string
-	cache               map[interface{}]string
-	cachedTemplates     map[string]string
-}
-
-type cacheable interface {
-	Hash() string
-}
-
-func (self *Template) SetCache(key interface{}, value string) {
-	if self.cache == nil {
-		self.cache = make(map[interface{}]string)
-	}
-	self.cache[key] = value
-}
-
-func (self *Template) Cache(key interface{}) (string, bool) {
-	if self.cache != nil {
-		if s, ok := self.cache[key]; ok {
-			return s, true
-		}
-	}
-	return "", false
-}
-
-func (self *Template) getCache(i cacheable) string {
-	if self.cachedTemplates == nil {
-		return ""
-	}
-	return self.cachedTemplates[i.Hash()]
-}
-
-func (self *Template) setCache(i cacheable, s string) {
-	if self.cachedTemplates == nil {
-		self.cachedTemplates = map[string]string{}
-	}
-	self.cachedTemplates[i.Hash()] = s
-}
-
-func (self *Template) isCached(i cacheable) bool {
-	if self.cachedTemplates == nil {
-		return false
-	}
-	if _, ok := self.cachedTemplates[i.Hash()]; ok {
-		return true
-	}
-	return false
+	*cache.Cache
 }
diff --git a/util/sqlgen/value.go b/util/sqlgen/value.go
index 651c809364673e689b289c13c56e71b0b8998c5a..aae5f25efa97785090a2870cadd486a1d4bb5f86 100644
--- a/util/sqlgen/value.go
+++ b/util/sqlgen/value.go
@@ -11,14 +11,47 @@ type Value struct {
 	Value interface{}
 }
 
-func (self Value) Compile(layout *Template) string {
+func (self Value) Hash() string {
+	switch t := self.Value.(type) {
+	case cc:
+		return `Value(` + t.Hash() + `)`
+	case string:
+		return `Value(` + t + `)`
+	}
+	return fmt.Sprintf(`Value(%v)`, self.Value)
+}
+
+func (self Value) Compile(layout *Template) (compiled string) {
+
+	if c, ok := layout.Read(self); ok {
+		return c
+	}
+
 	if raw, ok := self.Value.(Raw); ok {
-		return raw.Raw
+		compiled = raw.Raw
+	} else {
+		compiled = mustParse(layout.ValueQuote, Raw{fmt.Sprintf(`%v`, self.Value)})
 	}
-	return mustParse(layout.ValueQuote, Raw{fmt.Sprintf(`%v`, self.Value)})
+
+	layout.Write(self, compiled)
+
+	return
 }
 
-func (self Values) Compile(layout *Template) string {
+func (self Values) Hash() string {
+	hash := make([]string, 0, len(self))
+	for i := range self {
+		hash = append(hash, self[i].Hash())
+	}
+	return `Values(` + strings.Join(hash, `,`) + `)`
+}
+
+func (self Values) Compile(layout *Template) (compiled string) {
+
+	if c, ok := layout.Read(self); ok {
+		return c
+	}
+
 	l := len(self)
 
 	if l > 0 {
@@ -28,8 +61,10 @@ func (self Values) Compile(layout *Template) string {
 			chunks = append(chunks, self[i].Compile(layout))
 		}
 
-		return strings.Join(chunks, layout.ValueSeparator)
+		compiled = strings.Join(chunks, layout.ValueSeparator)
 	}
 
-	return ""
+	layout.Write(self, compiled)
+
+	return
 }
diff --git a/util/sqlgen/where.go b/util/sqlgen/where.go
index df61fcf33919db5550f76e5c79d1955be93ed59b..bcc9b677649258ac887fea097f5cab3b8f3eb3d3 100644
--- a/util/sqlgen/where.go
+++ b/util/sqlgen/where.go
@@ -5,49 +5,87 @@ import (
 )
 
 type (
-	Or    []interface{}
-	And   []interface{}
-	Where []interface{}
+	Or    []cc
+	And   []cc
+	Where []cc
 )
 
 type conds struct {
 	Conds string
 }
 
-func (self Or) Compile(layout *Template) string {
-	return groupCondition(layout, self, mustParse(layout.ClauseOperator, layout.OrKeyword))
+func (self Or) Hash() string {
+	hash := make([]string, 0, len(self))
+	for i := range self {
+		hash = append(hash, self[i].Hash())
+	}
+	return `Or(` + strings.Join(hash, `,`) + `)`
+}
+
+func (self Or) Compile(layout *Template) (compiled string) {
+	if c, ok := layout.Read(self); ok {
+		return c
+	}
+
+	compiled = groupCondition(layout, self, mustParse(layout.ClauseOperator, layout.OrKeyword))
+
+	layout.Write(self, compiled)
+
+	return
 }
 
-func (self And) Compile(layout *Template) string {
-	return groupCondition(layout, self, mustParse(layout.ClauseOperator, layout.AndKeyword))
+func (self And) Hash() string {
+	hash := make([]string, 0, len(self))
+	for i := range self {
+		hash = append(hash, self[i].Hash())
+	}
+	return `And(` + strings.Join(hash, `,`) + `)`
 }
 
-func (self Where) Compile(layout *Template) string {
+func (self And) Compile(layout *Template) (compiled string) {
+	if c, ok := layout.Read(self); ok {
+		return c
+	}
+
+	compiled = groupCondition(layout, self, mustParse(layout.ClauseOperator, layout.AndKeyword))
+
+	layout.Write(self, compiled)
+
+	return
+}
+
+func (self Where) Hash() string {
+	hash := make([]string, 0, len(self))
+	for i := range self {
+		hash = append(hash, self[i].Hash())
+	}
+	return `Where(` + strings.Join(hash, `,`) + `)`
+}
+
+func (self Where) Compile(layout *Template) (compiled string) {
+	if c, ok := layout.Read(self); ok {
+		return c
+	}
+
 	grouped := groupCondition(layout, self, mustParse(layout.ClauseOperator, layout.AndKeyword))
+
 	if grouped != "" {
-		return mustParse(layout.WhereLayout, conds{grouped})
+		compiled = mustParse(layout.WhereLayout, conds{grouped})
 	}
-	return ""
+
+	layout.Write(self, compiled)
+
+	return
 }
 
-func groupCondition(layout *Template, terms []interface{}, joinKeyword string) string {
+func groupCondition(layout *Template, terms []cc, joinKeyword string) string {
 	l := len(terms)
 
 	chunks := make([]string, 0, l)
 
 	if l > 0 {
-		var i int
-		for i = 0; i < l; i++ {
-			switch v := terms[i].(type) {
-			case ColumnValue:
-				chunks = append(chunks, v.Compile(layout))
-			case Or:
-				chunks = append(chunks, v.Compile(layout))
-			case And:
-				chunks = append(chunks, v.Compile(layout))
-			case Raw:
-				chunks = append(chunks, v.String())
-			}
+		for i := 0; i < l; i++ {
+			chunks = append(chunks, terms[i].Compile(layout))
 		}
 	}