diff --git a/db.go b/db.go
index ec5659ac66cb77b628b1244c2d599d8bfc01c3eb..d28d94e2028e24099b40b275c18f23a618bc7815 100644
--- a/db.go
+++ b/db.go
@@ -100,6 +100,10 @@ type Func struct {
 // 	}
 type And []interface{}
 
+func (a And) And(exp ...interface{}) And {
+	return append(a, exp...)
+}
+
 // Or is an array of interfaced that is used to join two or more expressions
 // under logical disjunction, it accepts `db.Cond{}`, `db.And{}`, `db.Raw{}`
 // and other `db.Or{}` values.
@@ -113,6 +117,10 @@ type And []interface{}
 // 	}
 type Or []interface{}
 
+func (o Or) Or(exp ...interface{}) Or {
+	return append(o, exp...)
+}
+
 // Raw holds chunks of data to be passed to the database without any filtering.
 // Use with care.
 //
diff --git a/postgresql/_dumps/structs.sql b/postgresql/_dumps/structs.sql
index 0b4069022cefa2a685b64745a97d2bdb97cdab06..25a210f573e6ba623a789e25db6cda8da9b7fd50 100644
--- a/postgresql/_dumps/structs.sql
+++ b/postgresql/_dumps/structs.sql
@@ -64,3 +64,12 @@ CREATE TABLE composite_keys (
   some_val varchar(255) default '',
   primary key (code, user_id)
 );
+
+DROP TABLE IF EXISTS option_types;
+
+CREATE TABLE option_types (
+  id serial primary key,
+  name varchar(255) default '',
+  tags varchar(64)[],
+  settings jsonb
+);
diff --git a/postgresql/database_test.go b/postgresql/database_test.go
index c474f78c491e1859db7cb2ecf93a70b50767eb19..c0d522a9c57d21d8b2eee4ddd9c7d99422351346 100644
--- a/postgresql/database_test.go
+++ b/postgresql/database_test.go
@@ -1651,6 +1651,281 @@ func TestDataTypes(t *testing.T) {
 	}
 }
 
+func TestOptionTypes(t *testing.T) {
+	var err error
+	var sess db.Database
+	var optionTypes db.Collection
+
+	if sess, err = db.Open(Adapter, settings); err != nil {
+		t.Fatal(err)
+	}
+
+	defer sess.Close()
+
+	if optionTypes, err = sess.Collection("option_types"); err != nil {
+		t.Fatal(err)
+	}
+
+	if err = optionTypes.Truncate(); err != nil {
+		t.Fatal(err)
+	}
+
+	// TODO: lets do some benchmarking on these auto-wrapped option types..
+
+	// TODO: add nullable jsonb field mapped to a []string
+
+	// A struct with wrapped option types defined in the struct tags
+	// for postgres string array and jsonb types
+	type optionType struct {
+		ID       int64                  `db:"id,omitempty"`
+		Name     string                 `db:"name"`
+		Tags     []string               `db:"tags,stringarray"`
+		Settings map[string]interface{} `db:"settings,jsonb"`
+	}
+
+	// Item 1
+	item1 := optionType{
+		Name:     "Food",
+		Tags:     []string{"toronto", "pizza"},
+		Settings: map[string]interface{}{"a": 1, "b": 2},
+	}
+
+	id, err := optionTypes.Append(item1)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	if pk, ok := id.(int64); !ok || pk == 0 {
+		t.Fatalf("Expecting an ID.")
+	}
+
+	var item1Chk optionType
+	if err := optionTypes.Find(db.Cond{"id": id}).One(&item1Chk); err != nil {
+		t.Fatal(err)
+	}
+
+	if item1Chk.Settings["a"].(float64) != 1 { // float64 because of json..
+		t.Fatalf("Expecting Settings['a'] of jsonb value to be 1")
+	}
+
+	if item1Chk.Tags[0] != "toronto" {
+		t.Fatalf("Expecting first element of Tags stringarray to be 'toronto'")
+	}
+
+	// Item 1 B
+	item1b := &optionType{
+		Name:     "Golang",
+		Tags:     []string{"love", "it"},
+		Settings: map[string]interface{}{"go": 1, "lang": 2},
+	}
+
+	id, err = optionTypes.Append(item1b)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	if pk, ok := id.(int64); !ok || pk == 0 {
+		t.Fatalf("Expecting an ID.")
+	}
+
+	var item1bChk optionType
+	if err := optionTypes.Find(db.Cond{"id": id}).One(&item1bChk); err != nil {
+		t.Fatal(err)
+	}
+
+	if item1bChk.Settings["go"].(float64) != 1 { // float64 because of json..
+		t.Fatalf("Expecting Settings['go'] of jsonb value to be 1")
+	}
+
+	if item1bChk.Tags[0] != "love" {
+		t.Fatalf("Expecting first element of Tags stringarray to be 'love'")
+	}
+
+	// Item 1 C
+	item1c := &optionType{
+		Name: "Sup", Tags: []string{}, Settings: map[string]interface{}{},
+	}
+
+	id, err = optionTypes.Append(item1c)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	if pk, ok := id.(int64); !ok || pk == 0 {
+		t.Fatalf("Expecting an ID.")
+	}
+
+	var item1cChk optionType
+	if err := optionTypes.Find(db.Cond{"id": id}).One(&item1cChk); err != nil {
+		t.Fatal(err)
+	}
+
+	if len(item1cChk.Tags) != 0 {
+		t.Fatalf("Expecting tags array to be empty but is %v", item1cChk.Tags)
+	}
+
+	if len(item1cChk.Settings) != 0 {
+		t.Fatalf("Expecting Settings map to be empty")
+	}
+
+	// An option type to pointer jsonb field
+	type optionType2 struct {
+		ID       int64                   `db:"id,omitempty"`
+		Name     string                  `db:"name"`
+		Tags     []string                `db:"tags,stringarray"`
+		Settings *map[string]interface{} `db:"settings,jsonb"`
+	}
+
+	item2 := optionType2{
+		Name: "JS", Tags: []string{"hi", "bye"}, Settings: nil,
+	}
+
+	id, err = optionTypes.Append(item2)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	if pk, ok := id.(int64); !ok || pk == 0 {
+		t.Fatalf("Expecting an ID.")
+	}
+
+	var item2Chk optionType2
+	res := optionTypes.Find(db.Cond{"id": id})
+	if err := res.One(&item2Chk); err != nil {
+		t.Fatal(err)
+	}
+
+	if item2Chk.ID != id.(int64) {
+		t.Fatalf("Expecting id to match")
+	}
+
+	if item2Chk.Name != item2.Name {
+		t.Fatalf("Expecting Name to match")
+	}
+
+	if item2Chk.Tags[0] != item2.Tags[0] || len(item2Chk.Tags) != len(item2.Tags) {
+		t.Fatalf("Expecting tags to match")
+	}
+
+	// Update the value
+	m := map[string]interface{}{}
+	m["lang"] = "javascript"
+	m["num"] = 31337
+	item2.Settings = &m
+	err = res.Update(item2)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	if err := res.One(&item2Chk); err != nil {
+		t.Fatal(err)
+	}
+
+	if (*item2Chk.Settings)["num"].(float64) != 31337 { // float64 because of json..
+		t.Fatalf("Expecting Settings['num'] of jsonb value to be 31337")
+	}
+
+	if (*item2Chk.Settings)["lang"] != "javascript" {
+		t.Fatalf("Expecting Settings['lang'] of jsonb value to be 'javascript'")
+	}
+
+	// An option type to pointer string array field
+	type optionType3 struct {
+		ID       int64                  `db:"id,omitempty"`
+		Name     string                 `db:"name"`
+		Tags     *[]string              `db:"tags,stringarray"`
+		Settings map[string]interface{} `db:"settings,jsonb"`
+	}
+
+	item3 := optionType3{
+		Name: "Julia", Tags: nil, Settings: map[string]interface{}{"girl": true, "lang": true},
+	}
+
+	id, err = optionTypes.Append(item3)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	if pk, ok := id.(int64); !ok || pk == 0 {
+		t.Fatalf("Expecting an ID.")
+	}
+
+	var item3Chk optionType2
+	if err := optionTypes.Find(db.Cond{"id": id}).One(&item3Chk); err != nil {
+		t.Fatal(err)
+	}
+}
+
+func TestOptionTypeJsonbStruct(t *testing.T) {
+	var err error
+	var sess db.Database
+	var optionTypes db.Collection
+
+	if sess, err = db.Open(Adapter, settings); err != nil {
+		t.Fatal(err)
+	}
+
+	defer sess.Close()
+
+	if optionTypes, err = sess.Collection("option_types"); err != nil {
+		t.Fatal(err)
+	}
+
+	if err = optionTypes.Truncate(); err != nil {
+		t.Fatal(err)
+	}
+
+	// A struct with wrapped option types defined in the struct tags
+	// for postgres string array and jsonb types
+	type Settings struct {
+		Name string `json:"name"`
+		Num  int64  `json:"num"`
+	}
+
+	type OptionType struct {
+		ID       int64    `db:"id,omitempty"`
+		Name     string   `db:"name"`
+		Tags     []string `db:"tags,stringarray"`
+		Settings Settings `db:"settings,jsonb"`
+	}
+
+	item1 := &OptionType{
+		Name:     "Hi",
+		Tags:     []string{"aah", "ok"},
+		Settings: Settings{Name: "a", Num: 123},
+	}
+
+	id, err := optionTypes.Append(item1)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	if pk, ok := id.(int64); !ok || pk == 0 {
+		t.Fatalf("Expecting an ID.")
+	}
+
+	var item1Chk OptionType
+	if err := optionTypes.Find(db.Cond{"id": id}).One(&item1Chk); err != nil {
+		t.Fatal(err)
+	}
+
+	if len(item1Chk.Tags) != 2 {
+		t.Fatalf("Expecting 2 tags")
+	}
+
+	if item1Chk.Tags[0] != "aah" {
+		t.Fatalf("Expecting first tag to be 0")
+	}
+
+	if item1Chk.Settings.Name != "a" {
+		t.Fatalf("Expecting Name to be 'a'")
+	}
+
+	if item1Chk.Settings.Num != 123 {
+		t.Fatalf("Expecting Num to be 123")
+	}
+}
+
 // We are going to benchmark the engine, so this is no longed needed.
 func TestDisableDebug(t *testing.T) {
 	os.Setenv(db.EnvEnableDebug, "")
diff --git a/util/sqlutil/fetch.go b/util/sqlutil/fetch.go
index cd75d147eed1066e2d4e86690bddb048b8b30e76..73dd137678940bdbc893a93a68d66f041bb77527 100644
--- a/util/sqlutil/fetch.go
+++ b/util/sqlutil/fetch.go
@@ -22,7 +22,7 @@
 package sqlutil
 
 import (
-	"errors"
+	"encoding/json"
 	"reflect"
 
 	"github.com/jmoiron/sqlx"
@@ -150,16 +150,101 @@ func fetchResult(itemT reflect.Type, rows *sqlx.Rows, columns []string) (reflect
 	case reflect.Struct:
 
 		values := make([]interface{}, len(columns))
-		fields := rows.Mapper.TraversalsByName(itemT, columns)
+		typeMap := rows.Mapper.TypeMap(itemT)
+		fieldMap := typeMap.Names
+		wrappedValues := map[reflect.Value][]interface{}{}
 
-		if err = fieldsByTraversal(item, fields, values, true); err != nil {
-			return item, err
+		for i, k := range columns {
+			fi, ok := fieldMap[k]
+			if !ok {
+				values[i] = new(interface{})
+				continue
+			}
+
+			f := reflectx.FieldByIndexesReadOnly(item, fi.Index)
+
+			// TODO: refactor into a nice pattern
+			if _, ok := fi.Options["stringarray"]; ok {
+				values[i] = &[]byte{}
+				wrappedValues[f] = []interface{}{"stringarray", values[i]}
+			} else if _, ok := fi.Options["int64array"]; ok {
+				values[i] = &[]byte{}
+				wrappedValues[f] = []interface{}{"int64array", values[i]}
+			} else if _, ok := fi.Options["jsonb"]; ok {
+				values[i] = &[]byte{}
+				wrappedValues[f] = []interface{}{"jsonb", values[i]}
+			} else {
+				values[i] = f.Addr().Interface()
+			}
+
+			if u, ok := values[i].(db.Unmarshaler); ok {
+				values[i] = scanner{u}
+			}
 		}
 
+		// Scanner - for reads
+		// Valuer  - for writes
+
+		// OptionTypes
+		// - before/after scan
+		// - before/after valuer..
+
 		if err = rows.Scan(values...); err != nil {
 			return item, err
 		}
 
+		// TODO: move this stuff out of here.. find a nice pattern
+		for f, v := range wrappedValues {
+			opt := v[0].(string)
+			b := v[1].(*[]byte)
+
+			switch opt {
+			case "stringarray":
+				v := StringArray{}
+				err := v.Scan(*b)
+				if err != nil {
+					return item, err
+				}
+				f.Set(reflect.ValueOf(v))
+			case "int64array":
+				v := Int64Array{}
+				err := v.Scan(*b)
+				if err != nil {
+					return item, err
+				}
+				f.Set(reflect.ValueOf(v))
+			case "jsonb":
+				if len(*b) == 0 {
+					continue
+				}
+
+				var vv reflect.Value
+				t := reflect.PtrTo(f.Type())
+
+				switch t.Kind() {
+				case reflect.Map:
+					vv = reflect.MakeMap(t)
+				case reflect.Slice:
+					vv = reflect.MakeSlice(t, 0, 0)
+				default:
+					vv = reflect.New(t)
+				}
+
+				err := json.Unmarshal(*b, vv.Interface())
+				if err != nil {
+					return item, err
+				}
+
+				vv = vv.Elem().Elem()
+
+				if !vv.IsValid() || (vv.Kind() == reflect.Ptr && vv.IsNil()) {
+					continue
+				}
+
+				f.Set(vv)
+			}
+		}
+
 	case reflect.Map:
 
 		columns, err := rows.Columns()
@@ -188,34 +273,3 @@ func fetchResult(itemT reflect.Type, rows *sqlx.Rows, columns []string) (reflect
 
 	return item, nil
 }
-
-func fieldsByTraversal(v reflect.Value, traversals [][]int, values []interface{}, ptrs bool) error {
-	v = reflect.Indirect(v)
-
-	if v.Kind() != reflect.Struct {
-		return errors.New("argument not a struct")
-	}
-
-	for i, traversal := range traversals {
-
-		if len(traversal) == 0 {
-			values[i] = new(interface{})
-			continue
-		}
-
-		f := reflectx.FieldByIndexes(v, traversal)
-
-		if ptrs {
-			values[i] = f.Addr().Interface()
-		} else {
-			values[i] = f.Interface()
-		}
-
-		// Provides compatibility with db.Unmarshaler
-		if u, ok := values[i].(db.Unmarshaler); ok {
-			values[i] = scanner{u}
-		}
-
-	}
-	return nil
-}
diff --git a/util/sqlutil/scanner.go b/util/sqlutil/scanner.go
index 5baa5ca8d3b695171fd9ee10160b0c6e16f0c4ff..34bde7a0fe4fc2b2b8db6d9c6f32c9bda48cd132 100644
--- a/util/sqlutil/scanner.go
+++ b/util/sqlutil/scanner.go
@@ -23,6 +23,12 @@ package sqlutil
 
 import (
 	"database/sql"
+	"database/sql/driver"
+	"encoding/json"
+	"errors"
+	"strconv"
+	"strings"
+
 	"upper.io/db"
 )
 
@@ -35,3 +41,148 @@ func (u scanner) Scan(v interface{}) error {
 }
 
 var _ sql.Scanner = scanner{}
+
+//------
+
+type JsonbType struct {
+	V interface{}
+}
+
+func (j *JsonbType) Scan(src interface{}) error {
+	b, ok := src.([]byte)
+	if !ok {
+		return errors.New("Scan source was not []bytes")
+	}
+
+	v := JsonbType{}
+	if err := json.Unmarshal(b, &v.V); err != nil {
+		return err
+	}
+	*j = v
+	return nil
+}
+
+func (j JsonbType) Value() (driver.Value, error) {
+	b, err := json.Marshal(j.V)
+	if err != nil {
+		return nil, err
+	}
+	return b, nil
+}
+
+//------
+
+type StringArray []string
+
+func (a *StringArray) Scan(src interface{}) error {
+	if src == nil {
+		*a = StringArray{}
+		return nil
+	}
+	b, ok := src.([]byte)
+	if !ok {
+		return errors.New("Scan source was not []bytes")
+	}
+	if len(b) == 0 {
+		return nil
+	}
+	s := string(b)[1 : len(b)-1]
+	if s == "" {
+		return nil
+	}
+	results := strings.Split(s, ",")
+	*a = StringArray(results)
+	return nil
+}
+
+// Value implements the driver.Valuer interface.
+func (a StringArray) Value() (driver.Value, error) {
+	if a == nil {
+		return nil, nil
+	}
+
+	if n := len(a); n > 0 {
+		// There will be at least two curly brackets, 2*N bytes of quotes,
+		// and N-1 bytes of delimiters.
+		b := make([]byte, 1, 1+3*n)
+		b[0] = '{'
+
+		b = appendArrayQuotedString(b, a[0])
+		for i := 1; i < n; i++ {
+			b = append(b, ',')
+			b = appendArrayQuotedString(b, a[i])
+		}
+
+		return append(b, '}'), nil
+	}
+
+	return []byte{'{', '}'}, nil
+}
+
+func appendArrayQuotedString(b []byte, v string) []byte {
+	b = append(b, '"')
+	for {
+		i := strings.IndexAny(v, `"\`)
+		if i < 0 {
+			b = append(b, v...)
+			break
+		}
+		if i > 0 {
+			b = append(b, v[:i]...)
+		}
+		b = append(b, '\\', v[i])
+		v = v[i+1:]
+	}
+	return append(b, '"')
+}
+
+//------
+
+type Int64Array []int64
+
+func (a *Int64Array) Scan(src interface{}) error {
+	if src == nil {
+		return nil
+	}
+	b, ok := src.([]byte)
+	if !ok {
+		return errors.New("Scan source was not []bytes")
+	}
+
+	s := string(b)[1 : len(b)-1]
+	parts := strings.Split(s, ",")
+	results := make([]int64, 0)
+	for _, n := range parts {
+		i, err := strconv.ParseInt(n, 10, 64)
+		if err != nil {
+			return err
+		}
+		results = append(results, i)
+	}
+	*a = Int64Array(results)
+	return nil
+}
+
+// Value implements the driver.Valuer interface.
+func (a Int64Array) Value() (driver.Value, error) {
+	if a == nil {
+		return nil, nil
+	}
+
+	if n := len(a); n > 0 {
+		// There will be at least two curly brackets, N bytes of values,
+		// and N-1 bytes of delimiters.
+		b := make([]byte, 1, 1+2*n)
+		b[0] = '{'
+
+		b = strconv.AppendInt(b, a[0], 10)
+		for i := 1; i < n; i++ {
+			b = append(b, ',')
+			b = strconv.AppendInt(b, a[i], 10)
+		}
+
+		return append(b, '}'), nil
+	}
+
+	return []byte{'{', '}'}, nil
+}
diff --git a/util/sqlutil/sqlutil.go b/util/sqlutil/sqlutil.go
index be01beddc5ad0bd9efcf8e51f66ce72e89cfcb8e..93427815168f626d965b3990c9b71fee3b0d21fc 100644
--- a/util/sqlutil/sqlutil.go
+++ b/util/sqlutil/sqlutil.go
@@ -23,14 +23,12 @@ package sqlutil
 
 import (
 	"database/sql"
+	"fmt"
 	"reflect"
 	"regexp"
 	"strings"
 
 	"github.com/jmoiron/sqlx/reflectx"
-
-	"menteslibres.net/gosexy/to"
-
 	"upper.io/db"
 )
 
@@ -46,11 +44,6 @@ var (
 	nullStringType  = reflect.TypeOf(sql.NullString{})
 )
 
-// NormalizeColumn prepares a column for comparison against another column.
-func NormalizeColumn(s string) string {
-	return strings.ToLower(reColumnCompareExclude.ReplaceAllString(s, ""))
-}
-
 // T type is commonly used by adapters to map database/sql values to Go values
 // using FieldValues()
 type T struct {
@@ -60,23 +53,13 @@ type T struct {
 
 func (t *T) columnLike(s string) string {
 	for _, name := range t.Columns {
-		if NormalizeColumn(s) == NormalizeColumn(name) {
+		if normalizeColumn(s) == normalizeColumn(name) {
 			return name
 		}
 	}
 	return s
 }
 
-func marshal(v interface{}) (interface{}, error) {
-	if m, isMarshaler := v.(db.Marshaler); isMarshaler {
-		var err error
-		if v, err = m.MarshalDB(); err != nil {
-			return nil, err
-		}
-	}
-	return v, nil
-}
-
 func (t *T) FieldValues(item interface{}) ([]string, []interface{}, error) {
 	fields := []string{}
 	values := []interface{}{}
@@ -95,14 +78,30 @@ func (t *T) FieldValues(item interface{}) ([]string, []interface{}, error) {
 
 	case reflect.Struct:
 
-		fieldMap := t.Mapper.TypeMap(itemT).FieldMap()
+		fieldMap := t.Mapper.TypeMap(itemT).Names
 		nfields := len(fieldMap)
 
 		values = make([]interface{}, 0, nfields)
 		fields = make([]string, 0, nfields)
 
 		for _, fi := range fieldMap {
-			value := reflectx.FieldByIndexesReadOnly(itemV, fi.Index).Interface()
+			// log.Println("=>", fi.Name, fi.Options)
+
+			fld := reflectx.FieldByIndexesReadOnly(itemV, fi.Index)
+			if fld.Kind() == reflect.Ptr && fld.IsNil() {
+				continue
+			}
+
+			var value interface{}
+			if _, ok := fi.Options["stringarray"]; ok {
+				value = StringArray(fld.Interface().([]string))
+			} else if _, ok := fi.Options["int64array"]; ok {
+				value = Int64Array(fld.Interface().([]int64))
+			} else if _, ok := fi.Options["jsonb"]; ok {
+				value = JsonbType{fld.Interface()}
+			} else {
+				value = fld.Interface()
+			}
 
 			if _, ok := fi.Options["omitempty"]; ok {
 				if value == fi.Zero.Interface() {
@@ -128,7 +127,7 @@ func (t *T) FieldValues(item interface{}) ([]string, []interface{}, error) {
 
 		for i, keyV := range mkeys {
 			valv := itemV.MapIndex(keyV)
-			fields[i] = t.columnLike(to.String(keyV.Interface()))
+			fields[i] = t.columnLike(fmt.Sprintf("%v", keyV.Interface()))
 
 			v, err := marshal(valv.Interface())
 			if err != nil {
@@ -137,6 +136,7 @@ func (t *T) FieldValues(item interface{}) ([]string, []interface{}, error) {
 
 			values[i] = v
 		}
+
 	default:
 		return nil, nil, db.ErrExpectingMapOrStruct
 	}
@@ -144,6 +144,16 @@ func (t *T) FieldValues(item interface{}) ([]string, []interface{}, error) {
 	return fields, values, nil
 }
 
+func marshal(v interface{}) (interface{}, error) {
+	if m, isMarshaler := v.(db.Marshaler); isMarshaler {
+		var err error
+		if v, err = m.MarshalDB(); err != nil {
+			return nil, err
+		}
+	}
+	return v, nil
+}
+
 func reset(data interface{}) error {
 	// Resetting element.
 	v := reflect.ValueOf(data).Elem()
@@ -153,6 +163,11 @@ func reset(data interface{}) error {
 	return nil
 }
 
+// normalizeColumn prepares a column for comparison against another column.
+func normalizeColumn(s string) string {
+	return strings.ToLower(reColumnCompareExclude.ReplaceAllString(s, ""))
+}
+
 // NewMapper creates a reflectx.Mapper
 func NewMapper() *reflectx.Mapper {
 	return reflectx.NewMapper("db")