Merge "Remove github.com/rubenv/sql-migrate and gopkg.in/yaml.v1"
diff --git a/go/src/github.com/jmoiron/sqlx/README.google b/go/src/github.com/jmoiron/sqlx/README.google
index 85f76b9..00e9c8d 100644
--- a/go/src/github.com/jmoiron/sqlx/README.google
+++ b/go/src/github.com/jmoiron/sqlx/README.google
@@ -1,5 +1,5 @@
-URL: https://github.com/jmoiron/sqlx/archive/69738bd209812c5a381786011aff17944a384554.zip
-Version: 69738bd209812c5a381786011aff17944a384554
+URL: https://github.com/jmoiron/sqlx/archive/398dd5876282499cdfd4cb8ea0f31a672abe9495.zip
+Version: 398dd5876282499cdfd4cb8ea0f31a672abe9495
 License: MIT
 License File: LICENSE
 
@@ -7,11 +7,8 @@
 sqlx provides a set of extensions on go's standard database/sql library.
 
 Local Modifications:
-
-Added newlines to sqlx_test.go debug output on lines 74 and 82 to prevent it
-from crashing our test runner.
-
-Remove the following imports from sqlx_test.go:
+- Added newlines to sqlx_test.go debug output on lines 77 and 87 to keep
+  our test runner happy
+- Removed the following import from sqlx_test.go:
   * github.com/lib/pq
-  * github.com/mattn/go-sqlite3
 
diff --git a/go/src/github.com/jmoiron/sqlx/README.md b/go/src/github.com/jmoiron/sqlx/README.md
index 4e3eb6d..55155d0 100644
--- a/go/src/github.com/jmoiron/sqlx/README.md
+++ b/go/src/github.com/jmoiron/sqlx/README.md
@@ -13,35 +13,32 @@
 * Marshal rows into structs (with embedded struct support), maps, and slices
 * Named parameter support including prepared statements
 * `Get` and `Select` to go quickly from query to struct/slice
-* `LoadFile` for executing statements from a file
 
-There is now some [fairly comprehensive documentation](http://jmoiron.github.io/sqlx/) for sqlx.
-You can also read the usage below for a quick sample on how sqlx works, or check out the [API
-documentation on godoc](http://godoc.org/github.com/jmoiron/sqlx).
+In addition to the [godoc API documentation](http://godoc.org/github.com/jmoiron/sqlx),
+there is also some [standard documentation](http://jmoiron.github.io/sqlx/) that
+explains how to use `database/sql` along with sqlx.
 
 ## Recent Changes
 
-The ability to use basic types as Select and Get destinations was added.  This
-is only valid when there is one column in the result set, and both functions
-return an error if this isn't the case.  This allows for much simpler patterns
-of access for single column results:
+* sqlx/types.JsonText has been renamed to JSONText to follow Go naming conventions.
 
-```go
-var count int
-err := db.Get(&count, "SELECT count(*) FROM person;")
+This breaks backwards compatibility, but it's in a way that is trivially fixable
+(`s/JsonText/JSONText/g`).  The `types` package is both experimental and not in
+active development currently.
 
-var names []string
-err := db.Select(&names, "SELECT name FROM person;")
-```
-
-See the note on Scannability at the bottom of this README for some more info.
+More importantly, [golang bug #13905](https://github.com/golang/go/issues/13905)
+makes `types.JSONText` and `types.GzippedText` _potentially unsafe_, **especially**
+when used with common auto-scan sqlx idioms like `Select` and `Get`.
 
 ### Backwards Compatibility
 
-There is no Go1-like promise of absolute stability, but I take the issue
-seriously and will maintain the library in a compatible state unless vital
-bugs prevent me from doing so.  Since [#59](https://github.com/jmoiron/sqlx/issues/59) and [#60](https://github.com/jmoiron/sqlx/issues/60) necessitated
-breaking behavior, a wider API cleanup was done at the time of fixing.
+There is no Go1-like promise of absolute stability, but I take the issue seriously
+and will maintain the library in a compatible state unless vital bugs prevent me 
+from doing so.  Since [#59](https://github.com/jmoiron/sqlx/issues/59) and 
+[#60](https://github.com/jmoiron/sqlx/issues/60) necessitated breaking behavior, 
+a wider API cleanup was done at the time of fixing.  It's possible this will happen
+in future;  if it does, a git tag will be provided for users requiring the old
+behavior to continue to use it until such a time as they can migrate.
 
 ## install
 
@@ -50,21 +47,21 @@
 ## issues
 
 Row headers can be ambiguous (`SELECT 1 AS a, 2 AS a`), and the result of
-`Columns()` can have duplicate names on queries like:
+`Columns()` does not fully qualify column names in queries like:
 
 ```sql
 SELECT a.id, a.name, b.id, b.name FROM foos AS a JOIN foos AS b ON a.parent = b.id;
 ```
 
 making a struct or map destination ambiguous.  Use `AS` in your queries
-to give rows distinct names, `rows.Scan` to scan them manually, or 
+to give columns distinct names, `rows.Scan` to scan them manually, or 
 `SliceScan` to get a slice of results.
 
 ## usage
 
 Below is an example which shows some common use cases for sqlx.  Check 
 [sqlx_test.go](https://github.com/jmoiron/sqlx/blob/master/sqlx_test.go) for more
-usage.  
+usage.
 
 
 ```go
@@ -103,7 +100,7 @@
 }
 
 func main() {
-    // this connects & tries a simple 'SELECT 1', panics on error
+    // this Pings the database trying to connect, panics on error
     // use sqlx.Open() for sql.Open() semantics
     db, err := sqlx.Connect("postgres", "user=foo dbname=bar sslmode=disable")
     if err != nil {
@@ -186,73 +183,3 @@
 }
 ```
 
-## Scannability
-
-Get and Select are able to take base types, so the following is now possible:
-
-```go
-var name string
-db.Get(&name, "SELECT first_name FROM person WHERE id=$1", 10)
-
-var ids []int64
-db.Select(&ids, "SELECT id FROM person LIMIT 20;")
-```
-
-This can get complicated with destination types which are structs, like `sql.NullString`.  Because of this, straightforward rules for *scannability* had to be developed.  Iff something is "Scannable", then it is used directly in `rows.Scan`;  if it's not, then the standard sqlx struct rules apply.
-
-Something is scannable if any of the following are true:
-
-* It is not a struct, ie. `reflect.ValueOf(v).Kind() != reflect.Struct`
-* It implements the `sql.Scanner` interface
-* It has no exported fields (eg. `time.Time`)
-
-## embedded structs
-
-Scan targets obey Go attribute rules directly, including nested embedded structs.  Older versions of sqlx would attempt to also descend into non-embedded structs, but this is no longer supported.
-
-Go makes *accessing* '[ambiguous selectors](http://play.golang.org/p/MGRxdjLaUc)' a compile time error, defining structs with ambiguous selectors is legal.  Sqlx will decide which field to use on a struct based on a breadth first search of the struct and any structs it embeds, as specified by the order of the fields as accessible by `reflect`, which generally means in source-order.  This means that sqlx chooses the outer-most, top-most matching name for targets, even when the selector might technically be ambiguous.
-
-## scan safety
-
-By default, scanning into structs requires the structs to have fields for all of the
-columns in the query.  This was done for a few reasons:
-
-* A mistake in naming during development could lead you to believe that data is
-  being written to a field when actually it can't be found and it is being dropped
-* This behavior mirrors the behavior of the Go compiler with respect to unused
-  variables
-* Selecting more data than you need is wasteful (more data on the wire, more time
-  marshalling, etc)
-
-Unlike Marshallers in the stdlib, the programmer scanning an sql result into a struct
-will generally have a full understanding of what the underlying data model is *and*
-full control over the SQL statement.
-
-Despite this, there are use cases where it's convenient to be able to ignore unknown
-columns.  In most of these cases, you might be better off with `ScanSlice`, but where
-you want to still use structs, there is now the `Unsafe` method.  Its usage is most
-simply shown in an example:
-
-```go
-    db, err := sqlx.Connect("postgres", "user=foo dbname=bar sslmode=disable")
-    if err != nil {
-        log.Fatal(err)
-    }
-
-    type Person {
-        Name string
-    }
-    var p Person
-
-    // This fails, because there is no destination for location in Person
-    err = db.Get(&p, "SELECT name, location FROM person LIMIT 1")
-    
-    udb := db.Unsafe()
-    
-    // This succeeds and just sets `Name` in the p struct
-    err = udb.Get(&p, "SELECT name, location FROM person LIMIT 1")
-```
-
-The `Unsafe` method is implemented on `Tx`, `DB`, and `Stmt`.  When you use an unsafe
-`Tx` or `DB` to create a new `Tx` or `Stmt`, those inherit its lack of safety.
-
diff --git a/go/src/github.com/jmoiron/sqlx/bind.go b/go/src/github.com/jmoiron/sqlx/bind.go
index 2f1ec2b..564635c 100644
--- a/go/src/github.com/jmoiron/sqlx/bind.go
+++ b/go/src/github.com/jmoiron/sqlx/bind.go
@@ -2,7 +2,12 @@
 
 import (
 	"bytes"
+	"errors"
+	"reflect"
 	"strconv"
+	"strings"
+
+	"github.com/jmoiron/sqlx/reflectx"
 )
 
 // Bindvar types supported by Rebind, BindMap and BindStruct.
@@ -31,11 +36,10 @@
 // FIXME: this should be able to be tolerant of escaped ?'s in queries without
 // losing much speed, and should be to avoid confusion.
 
-// FIXME: this is now produces the wrong results for oracle's NAMED bindtype
-
 // Rebind a query from the default bindtype (QUESTION) to the target bindtype.
 func Rebind(bindType int, query string) string {
-	if bindType != DOLLAR {
+	switch bindType {
+	case QUESTION, UNKNOWN:
 		return query
 	}
 
@@ -45,7 +49,12 @@
 	j := 1
 	for _, b := range qb {
 		if b == '?' {
-			rqb = append(rqb, '$')
+			switch bindType {
+			case DOLLAR:
+				rqb = append(rqb, '$')
+			case NAMED:
+				rqb = append(rqb, ':', 'a', 'r', 'g')
+			}
 			for _, b := range strconv.Itoa(j) {
 				rqb = append(rqb, byte(b))
 			}
@@ -61,7 +70,6 @@
 // much simpler and should be more resistant to odd unicode, but it is twice as
 // slow.  Kept here for benchmarking purposes and to possibly replace Rebind if
 // problems arise with its somewhat naive handling of unicode.
-
 func rebindBuff(bindType int, query string) string {
 	if bindType != DOLLAR {
 		return query
@@ -82,3 +90,97 @@
 
 	return rqb.String()
 }
+
+// In expands slice values in args, returning the modified query string
+// and a new arg list that can be executed by a database. The `query` should
+// use the `?` bindVar.  The return value uses the `?` bindVar.
+func In(query string, args ...interface{}) (string, []interface{}, error) {
+	// argMeta stores reflect.Value and length for slices and
+	// the value itself for non-slice arguments
+	type argMeta struct {
+		v      reflect.Value
+		i      interface{}
+		length int
+	}
+
+	var flatArgsCount int
+	var anySlices bool
+
+	meta := make([]argMeta, len(args))
+
+	for i, arg := range args {
+		v := reflect.ValueOf(arg)
+		t := reflectx.Deref(v.Type())
+
+		if t.Kind() == reflect.Slice {
+			meta[i].length = v.Len()
+			meta[i].v = v
+
+			anySlices = true
+			flatArgsCount += meta[i].length
+
+			if meta[i].length == 0 {
+				return "", nil, errors.New("empty slice passed to 'in' query")
+			}
+		} else {
+			meta[i].i = arg
+			flatArgsCount++
+		}
+	}
+
+	// don't do any parsing if there aren't any slices;  note that this means
+	// some errors that we might have caught below will not be returned.
+	if !anySlices {
+		return query, args, nil
+	}
+
+	newArgs := make([]interface{}, 0, flatArgsCount)
+
+	var arg, offset int
+	var buf bytes.Buffer
+
+	for i := strings.IndexByte(query[offset:], '?'); i != -1; i = strings.IndexByte(query[offset:], '?') {
+		if arg >= len(meta) {
+			// if an argument wasn't passed, lets return an error;  this is
+			// not actually how database/sql Exec/Query works, but since we are
+			// creating an argument list programmatically, we want to be able
+			// to catch these programmer errors earlier.
+			return "", nil, errors.New("number of bindVars exceeds arguments")
+		}
+
+		argMeta := meta[arg]
+		arg++
+
+		// not a slice, continue.
+		// our questionmark will either be written before the next expansion
+		// of a slice or after the loop when writing the rest of the query
+		if argMeta.length == 0 {
+			offset = offset + i + 1
+			newArgs = append(newArgs, argMeta.i)
+			continue
+		}
+
+		// write everything up to and including our ? character
+		buf.WriteString(query[:offset+i+1])
+
+		newArgs = append(newArgs, argMeta.v.Index(0).Interface())
+
+		for si := 1; si < argMeta.length; si++ {
+			buf.WriteString(", ?")
+			newArgs = append(newArgs, argMeta.v.Index(si).Interface())
+		}
+
+		// slice the query and reset the offset. this avoids some bookkeeping for
+		// the write after the loop
+		query = query[offset+i+1:]
+		offset = 0
+	}
+
+	buf.WriteString(query)
+
+	if arg < len(meta) {
+		return "", nil, errors.New("number of bindVars less than number arguments")
+	}
+
+	return buf.String(), newArgs, nil
+}
diff --git a/go/src/github.com/jmoiron/sqlx/named.go b/go/src/github.com/jmoiron/sqlx/named.go
index d753518..4df8095 100644
--- a/go/src/github.com/jmoiron/sqlx/named.go
+++ b/go/src/github.com/jmoiron/sqlx/named.go
@@ -79,7 +79,7 @@
 	if err != nil {
 		return nil, err
 	}
-	return &Rows{Rows: r, Mapper: n.Stmt.Mapper}, err
+	return &Rows{Rows: r, Mapper: n.Stmt.Mapper, unsafe: isUnsafe(n)}, err
 }
 
 // QueryRowx this NamedStmt.  Because of limitations with QueryRow, this is
@@ -90,7 +90,7 @@
 
 // Select using this NamedStmt
 func (n *NamedStmt) Select(dest interface{}, arg interface{}) error {
-	rows, err := n.Query(arg)
+	rows, err := n.Queryx(arg)
 	if err != nil {
 		return err
 	}
@@ -105,6 +105,13 @@
 	return r.scanAny(dest, false)
 }
 
+// Unsafe creates an unsafe version of the NamedStmt
+func (n *NamedStmt) Unsafe() *NamedStmt {
+	r := &NamedStmt{Params: n.Params, Stmt: n.Stmt, QueryString: n.QueryString}
+	r.Stmt.unsafe = true
+	return r
+}
+
 // A union interface of preparer and binder, required to be able to prepare
 // named statements (as the bindtype must be determined).
 type namedPreparer interface {
@@ -286,11 +293,19 @@
 	return string(rebound), names, err
 }
 
-// Bind binds a struct or a map to a query with named parameters.
+// BindNamed binds a struct or a map to a query with named parameters.
+// DEPRECATED: use sqlx.Named` instead of this, it may be removed in future.
 func BindNamed(bindType int, query string, arg interface{}) (string, []interface{}, error) {
 	return bindNamedMapper(bindType, query, arg, mapper())
 }
 
+// Named takes a query using named parameters and an argument and
+// returns a new query with a list of args that can be executed by
+// a database.  The return value uses the `?` bindvar.
+func Named(query string, arg interface{}) (string, []interface{}, error) {
+	return bindNamedMapper(QUESTION, query, arg, mapper())
+}
+
 func bindNamedMapper(bindType int, query string, arg interface{}, m *reflectx.Mapper) (string, []interface{}, error) {
 	if maparg, ok := arg.(map[string]interface{}); ok {
 		return bindMap(bindType, query, maparg)
diff --git a/go/src/github.com/jmoiron/sqlx/reflectx/reflect.go b/go/src/github.com/jmoiron/sqlx/reflectx/reflect.go
index d49b7bc..04d2080 100644
--- a/go/src/github.com/jmoiron/sqlx/reflectx/reflect.go
+++ b/go/src/github.com/jmoiron/sqlx/reflectx/reflect.go
@@ -1,25 +1,67 @@
-// Package reflect implements extensions to the standard reflect lib suitable
+// Package reflectx implements extensions to the standard reflect lib suitable
 // for implementing marshaling and unmarshaling packages.  The main Mapper type
-// allows for Go-compatible named atribute access, including accessing embedded
+// allows for Go-compatible named attribute access, including accessing embedded
 // struct attributes and the ability to use  functions and struct tags to
 // customize field names.
 //
 package reflectx
 
-import "sync"
-
 import (
+	"fmt"
 	"reflect"
 	"runtime"
+	"strings"
+	"sync"
 )
 
-type fieldMap map[string][]int
+// A FieldInfo is a collection of metadata about a struct field.
+type FieldInfo struct {
+	Index    []int
+	Path     string
+	Field    reflect.StructField
+	Zero     reflect.Value
+	Name     string
+	Options  map[string]string
+	Embedded bool
+	Children []*FieldInfo
+	Parent   *FieldInfo
+}
+
+// A StructMap is an index of field metadata for a struct.
+type StructMap struct {
+	Tree  *FieldInfo
+	Index []*FieldInfo
+	Paths map[string]*FieldInfo
+	Names map[string]*FieldInfo
+}
+
+// GetByPath returns a *FieldInfo for a given string path.
+func (f StructMap) GetByPath(path string) *FieldInfo {
+	return f.Paths[path]
+}
+
+// GetByTraversal returns a *FieldInfo for a given integer path.  It is
+// analogous to reflect.FieldByIndex.
+func (f StructMap) GetByTraversal(index []int) *FieldInfo {
+	if len(index) == 0 {
+		return nil
+	}
+
+	tree := f.Tree
+	for _, i := range index {
+		if i >= len(tree.Children) || tree.Children[i] == nil {
+			return nil
+		}
+		tree = tree.Children[i]
+	}
+	return tree
+}
 
 // Mapper is a general purpose mapper of names to struct fields.  A Mapper
 // behaves like most marshallers, optionally obeying a field tag for name
 // mapping and a function to provide a basic mapping of fields to names.
 type Mapper struct {
-	cache      map[reflect.Type]fieldMap
+	cache      map[reflect.Type]*StructMap
 	tagName    string
 	tagMapFunc func(string) string
 	mapFunc    func(string) string
@@ -30,7 +72,7 @@
 // by tagName.  If tagName is the empty string, it is ignored.
 func NewMapper(tagName string) *Mapper {
 	return &Mapper{
-		cache:   make(map[reflect.Type]fieldMap),
+		cache:   make(map[reflect.Type]*StructMap),
 		tagName: tagName,
 	}
 }
@@ -40,7 +82,7 @@
 // have values like "name,omitempty".
 func NewMapperTagFunc(tagName string, mapFunc, tagMapFunc func(string) string) *Mapper {
 	return &Mapper{
-		cache:      make(map[reflect.Type]fieldMap),
+		cache:      make(map[reflect.Type]*StructMap),
 		tagName:    tagName,
 		mapFunc:    mapFunc,
 		tagMapFunc: tagMapFunc,
@@ -52,7 +94,7 @@
 // for any other field, the mapped name will be f(field.Name)
 func NewMapperFunc(tagName string, f func(string) string) *Mapper {
 	return &Mapper{
-		cache:   make(map[reflect.Type]fieldMap),
+		cache:   make(map[reflect.Type]*StructMap),
 		tagName: tagName,
 		mapFunc: f,
 	}
@@ -60,7 +102,7 @@
 
 // TypeMap returns a mapping of field strings to int slices representing
 // the traversal down the struct to reach the field.
-func (m *Mapper) TypeMap(t reflect.Type) fieldMap {
+func (m *Mapper) TypeMap(t reflect.Type) *StructMap {
 	m.mutex.Lock()
 	mapping, ok := m.cache[t]
 	if !ok {
@@ -78,9 +120,9 @@
 	mustBe(v, reflect.Struct)
 
 	r := map[string]reflect.Value{}
-	nm := m.TypeMap(v.Type())
-	for tagName, indexes := range nm {
-		r[tagName] = FieldByIndexes(v, indexes)
+	tm := m.TypeMap(v.Type())
+	for tagName, fi := range tm.Names {
+		r[tagName] = FieldByIndexes(v, fi.Index)
 	}
 	return r
 }
@@ -92,12 +134,12 @@
 	v = reflect.Indirect(v)
 	mustBe(v, reflect.Struct)
 
-	nm := m.TypeMap(v.Type())
-	traversal, ok := nm[name]
+	tm := m.TypeMap(v.Type())
+	fi, ok := tm.Names[name]
 	if !ok {
-		return *new(reflect.Value)
+		return v
 	}
-	return FieldByIndexes(v, traversal)
+	return FieldByIndexes(v, fi.Index)
 }
 
 // FieldsByName returns a slice of values corresponding to the slice of names
@@ -107,35 +149,34 @@
 	v = reflect.Indirect(v)
 	mustBe(v, reflect.Struct)
 
-	nm := m.TypeMap(v.Type())
-
+	tm := m.TypeMap(v.Type())
 	vals := make([]reflect.Value, 0, len(names))
 	for _, name := range names {
-		traversal, ok := nm[name]
+		fi, ok := tm.Names[name]
 		if !ok {
 			vals = append(vals, *new(reflect.Value))
 		} else {
-			vals = append(vals, FieldByIndexes(v, traversal))
+			vals = append(vals, FieldByIndexes(v, fi.Index))
 		}
 	}
 	return vals
 }
 
-// Traversals by name returns a slice of int slices which represent the struct
+// TraversalsByName returns a slice of int slices which represent the struct
 // traversals for each mapped name.  Panics if t is not a struct or Indirectable
 // to a struct.  Returns empty int slice for each name not found.
 func (m *Mapper) TraversalsByName(t reflect.Type, names []string) [][]int {
 	t = Deref(t)
 	mustBe(t, reflect.Struct)
-	nm := m.TypeMap(t)
+	tm := m.TypeMap(t)
 
 	r := make([][]int, 0, len(names))
 	for _, name := range names {
-		traversal, ok := nm[name]
+		fi, ok := tm.Names[name]
 		if !ok {
 			r = append(r, []int{})
 		} else {
-			r = append(r, traversal)
+			r = append(r, fi.Index)
 		}
 	}
 	return r
@@ -177,13 +218,13 @@
 
 // -- helpers & utilities --
 
-type Kinder interface {
+type kinder interface {
 	Kind() reflect.Kind
 }
 
 // mustBe checks a value against a kind, panicing with a reflect.ValueError
 // if the kind isn't that which is required.
-func mustBe(v Kinder, expected reflect.Kind) {
+func mustBe(v kinder, expected reflect.Kind) {
 	k := v.Kind()
 	if k != expected {
 		panic(&reflect.ValueError{Method: methodName(), Kind: k})
@@ -201,8 +242,9 @@
 }
 
 type typeQueue struct {
-	t reflect.Type
-	p []int
+	t  reflect.Type
+	fi *FieldInfo
+	pp string // Parent path
 }
 
 // A copying append that creates a new slice each time.
@@ -217,27 +259,65 @@
 
 // getMapping returns a mapping for the t type, using the tagName, mapFunc and
 // tagMapFunc to determine the canonical names of fields.
-func getMapping(t reflect.Type, tagName string, mapFunc, tagMapFunc func(string) string) fieldMap {
+func getMapping(t reflect.Type, tagName string, mapFunc, tagMapFunc func(string) string) *StructMap {
+	m := []*FieldInfo{}
+
+	root := &FieldInfo{}
 	queue := []typeQueue{}
-	queue = append(queue, typeQueue{Deref(t), []int{}})
-	m := fieldMap{}
+	queue = append(queue, typeQueue{Deref(t), root, ""})
+
 	for len(queue) != 0 {
 		// pop the first item off of the queue
 		tq := queue[0]
 		queue = queue[1:]
+		nChildren := 0
+		if tq.t.Kind() == reflect.Struct {
+			nChildren = tq.t.NumField()
+		}
+		tq.fi.Children = make([]*FieldInfo, nChildren)
+
 		// iterate through all of its fields
-		for fieldPos := 0; fieldPos < tq.t.NumField(); fieldPos++ {
+		for fieldPos := 0; fieldPos < nChildren; fieldPos++ {
 			f := tq.t.Field(fieldPos)
 
-			name := f.Tag.Get(tagName)
-			if len(name) == 0 {
+			fi := FieldInfo{}
+			fi.Field = f
+			fi.Zero = reflect.New(f.Type).Elem()
+			fi.Options = map[string]string{}
+
+			var tag, name string
+			if tagName != "" && strings.Contains(string(f.Tag), tagName+":") {
+				tag = f.Tag.Get(tagName)
+				name = tag
+			} else {
 				if mapFunc != nil {
 					name = mapFunc(f.Name)
-				} else {
-					name = f.Name
 				}
-			} else if tagMapFunc != nil {
-				name = tagMapFunc(name)
+			}
+
+			parts := strings.Split(name, ",")
+			if len(parts) > 1 {
+				name = parts[0]
+				for _, opt := range parts[1:] {
+					kv := strings.Split(opt, "=")
+					if len(kv) > 1 {
+						fi.Options[kv[0]] = kv[1]
+					} else {
+						fi.Options[kv[0]] = ""
+					}
+				}
+			}
+
+			if tagMapFunc != nil {
+				tag = tagMapFunc(tag)
+			}
+
+			fi.Name = name
+
+			if tq.pp == "" || (tq.pp == "" && tag == "") {
+				fi.Path = fi.Name
+			} else {
+				fi.Path = fmt.Sprintf("%s.%s", tq.pp, fi.Name)
 			}
 
 			// if the name is "-", disabled via a tag, skip it
@@ -246,23 +326,46 @@
 			}
 
 			// skip unexported fields
-			if len(f.PkgPath) != 0 {
+			if len(f.PkgPath) != 0 && !f.Anonymous {
 				continue
 			}
 
 			// bfs search of anonymous embedded structs
 			if f.Anonymous {
-				queue = append(queue, typeQueue{Deref(f.Type), apnd(tq.p, fieldPos)})
-				continue
+				pp := tq.pp
+				if tag != "" {
+					pp = fi.Path
+				}
+
+				fi.Embedded = true
+				fi.Index = apnd(tq.fi.Index, fieldPos)
+				nChildren := 0
+				ft := Deref(f.Type)
+				if ft.Kind() == reflect.Struct {
+					nChildren = ft.NumField()
+				}
+				fi.Children = make([]*FieldInfo, nChildren)
+				queue = append(queue, typeQueue{Deref(f.Type), &fi, pp})
+			} else if fi.Zero.Kind() == reflect.Struct || (fi.Zero.Kind() == reflect.Ptr && fi.Zero.Type().Elem().Kind() == reflect.Struct) {
+				fi.Index = apnd(tq.fi.Index, fieldPos)
+				fi.Children = make([]*FieldInfo, Deref(f.Type).NumField())
+				queue = append(queue, typeQueue{Deref(f.Type), &fi, fi.Path})
 			}
 
-			// if the name is shadowed by an earlier identical name in the search, skip it
-			if _, ok := m[name]; ok {
-				continue
-			}
-			// add it to the map at the current position
-			m[name] = apnd(tq.p, fieldPos)
+			fi.Index = apnd(tq.fi.Index, fieldPos)
+			fi.Parent = tq.fi
+			tq.fi.Children[fieldPos] = &fi
+			m = append(m, &fi)
 		}
 	}
-	return m
+
+	flds := &StructMap{Index: m, Tree: root, Paths: map[string]*FieldInfo{}, Names: map[string]*FieldInfo{}}
+	for _, fi := range flds.Index {
+		flds.Paths[fi.Path] = fi
+		if fi.Name != "" && !fi.Embedded {
+			flds.Names[fi.Path] = fi
+		}
+	}
+
+	return flds
 }
diff --git a/go/src/github.com/jmoiron/sqlx/reflectx/reflect_test.go b/go/src/github.com/jmoiron/sqlx/reflectx/reflect_test.go
index 1fcba66..8072244 100644
--- a/go/src/github.com/jmoiron/sqlx/reflectx/reflect_test.go
+++ b/go/src/github.com/jmoiron/sqlx/reflectx/reflect_test.go
@@ -19,7 +19,7 @@
 
 	f := Foo{1, 2, 3}
 	fv := reflect.ValueOf(f)
-	m := NewMapper("")
+	m := NewMapperFunc("", func(s string) string { return s })
 
 	v := m.FieldByName(fv, "A")
 	if ival(v) != f.A {
@@ -35,57 +35,425 @@
 	}
 }
 
-func TestEmbedded(t *testing.T) {
+func TestBasicEmbedded(t *testing.T) {
 	type Foo struct {
 		A int
 	}
 
 	type Bar struct {
-		Foo
-		B int
+		Foo // `db:""` is implied for an embedded struct
+		B   int
+		C   int `db:"-"`
 	}
 
 	type Baz struct {
-		A int
-		Bar
+		A   int
+		Bar `db:"Bar"`
 	}
 
-	m := NewMapper("")
+	m := NewMapperFunc("db", func(s string) string { return s })
+
+	z := Baz{}
+	z.A = 1
+	z.B = 2
+	z.C = 4
+	z.Bar.Foo.A = 3
+
+	zv := reflect.ValueOf(z)
+	fields := m.TypeMap(reflect.TypeOf(z))
+
+	if len(fields.Index) != 5 {
+		t.Errorf("Expecting 5 fields")
+	}
+
+	// for _, fi := range fields.Index {
+	// 	log.Println(fi)
+	// }
+
+	v := m.FieldByName(zv, "A")
+	if ival(v) != z.A {
+		t.Errorf("Expecting %d, got %d", z.A, ival(v))
+	}
+	v = m.FieldByName(zv, "Bar.B")
+	if ival(v) != z.Bar.B {
+		t.Errorf("Expecting %d, got %d", z.Bar.B, ival(v))
+	}
+	v = m.FieldByName(zv, "Bar.A")
+	if ival(v) != z.Bar.Foo.A {
+		t.Errorf("Expecting %d, got %d", z.Bar.Foo.A, ival(v))
+	}
+	v = m.FieldByName(zv, "Bar.C")
+	if _, ok := v.Interface().(int); ok {
+		t.Errorf("Expecting Bar.C to not exist")
+	}
+
+	fi := fields.GetByPath("Bar.C")
+	if fi != nil {
+		t.Errorf("Bar.C should not exist")
+	}
+}
+
+func TestEmbeddedSimple(t *testing.T) {
+	type UUID [16]byte
+	type MyID struct {
+		UUID
+	}
+	type Item struct {
+		ID MyID
+	}
+	z := Item{}
+
+	m := NewMapper("db")
+	m.TypeMap(reflect.TypeOf(z))
+}
+
+func TestBasicEmbeddedWithTags(t *testing.T) {
+	type Foo struct {
+		A int `db:"a"`
+	}
+
+	type Bar struct {
+		Foo     // `db:""` is implied for an embedded struct
+		B   int `db:"b"`
+	}
+
+	type Baz struct {
+		A   int `db:"a"`
+		Bar     // `db:""` is implied for an embedded struct
+	}
+
+	m := NewMapper("db")
 
 	z := Baz{}
 	z.A = 1
 	z.B = 2
 	z.Bar.Foo.A = 3
-	zv := reflect.ValueOf(z)
 
-	v := m.FieldByName(zv, "A")
-	if ival(v) != z.A {
-		t.Errorf("Expecting %d, got %d", ival(v), z.A)
+	zv := reflect.ValueOf(z)
+	fields := m.TypeMap(reflect.TypeOf(z))
+
+	if len(fields.Index) != 5 {
+		t.Errorf("Expecting 5 fields")
 	}
-	v = m.FieldByName(zv, "B")
+
+	// for _, fi := range fields.index {
+	// 	log.Println(fi)
+	// }
+
+	v := m.FieldByName(zv, "a")
+	if ival(v) != z.Bar.Foo.A { // the dominant field
+		t.Errorf("Expecting %d, got %d", z.Bar.Foo.A, ival(v))
+	}
+	v = m.FieldByName(zv, "b")
 	if ival(v) != z.B {
-		t.Errorf("Expecting %d, got %d", ival(v), z.B)
+		t.Errorf("Expecting %d, got %d", z.B, ival(v))
+	}
+}
+
+func TestFlatTags(t *testing.T) {
+	m := NewMapper("db")
+
+	type Asset struct {
+		Title string `db:"title"`
+	}
+	type Post struct {
+		Author string `db:"author,required"`
+		Asset  Asset  `db:""`
+	}
+	// Post columns: (author title)
+
+	post := Post{Author: "Joe", Asset: Asset{Title: "Hello"}}
+	pv := reflect.ValueOf(post)
+
+	v := m.FieldByName(pv, "author")
+	if v.Interface().(string) != post.Author {
+		t.Errorf("Expecting %s, got %s", post.Author, v.Interface().(string))
+	}
+	v = m.FieldByName(pv, "title")
+	if v.Interface().(string) != post.Asset.Title {
+		t.Errorf("Expecting %s, got %s", post.Asset.Title, v.Interface().(string))
+	}
+}
+
+func TestNestedStruct(t *testing.T) {
+	m := NewMapper("db")
+
+	type Details struct {
+		Active bool `db:"active"`
+	}
+	type Asset struct {
+		Title   string  `db:"title"`
+		Details Details `db:"details"`
+	}
+	type Post struct {
+		Author string `db:"author,required"`
+		Asset  `db:"asset"`
+	}
+	// Post columns: (author asset.title asset.details.active)
+
+	post := Post{
+		Author: "Joe",
+		Asset:  Asset{Title: "Hello", Details: Details{Active: true}},
+	}
+	pv := reflect.ValueOf(post)
+
+	v := m.FieldByName(pv, "author")
+	if v.Interface().(string) != post.Author {
+		t.Errorf("Expecting %s, got %s", post.Author, v.Interface().(string))
+	}
+	v = m.FieldByName(pv, "title")
+	if _, ok := v.Interface().(string); ok {
+		t.Errorf("Expecting field to not exist")
+	}
+	v = m.FieldByName(pv, "asset.title")
+	if v.Interface().(string) != post.Asset.Title {
+		t.Errorf("Expecting %s, got %s", post.Asset.Title, v.Interface().(string))
+	}
+	v = m.FieldByName(pv, "asset.details.active")
+	if v.Interface().(bool) != post.Asset.Details.Active {
+		t.Errorf("Expecting %v, got %v", post.Asset.Details.Active, v.Interface().(bool))
+	}
+}
+
+func TestInlineStruct(t *testing.T) {
+	m := NewMapperTagFunc("db", strings.ToLower, nil)
+
+	type Employee struct {
+		Name string
+		ID   int
+	}
+	type Boss Employee
+	type person struct {
+		Employee `db:"employee"`
+		Boss     `db:"boss"`
+	}
+	// employees columns: (employee.name employee.id boss.name boss.id)
+
+	em := person{Employee: Employee{Name: "Joe", ID: 2}, Boss: Boss{Name: "Dick", ID: 1}}
+	ev := reflect.ValueOf(em)
+
+	fields := m.TypeMap(reflect.TypeOf(em))
+	if len(fields.Index) != 6 {
+		t.Errorf("Expecting 6 fields")
+	}
+
+	v := m.FieldByName(ev, "employee.name")
+	if v.Interface().(string) != em.Employee.Name {
+		t.Errorf("Expecting %s, got %s", em.Employee.Name, v.Interface().(string))
+	}
+	v = m.FieldByName(ev, "boss.id")
+	if ival(v) != em.Boss.ID {
+		t.Errorf("Expecting %v, got %v", em.Boss.ID, ival(v))
+	}
+}
+
+func TestFieldsEmbedded(t *testing.T) {
+	m := NewMapper("db")
+
+	type Person struct {
+		Name string `db:"name"`
+	}
+	type Place struct {
+		Name string `db:"name"`
+	}
+	type Article struct {
+		Title string `db:"title"`
+	}
+	type PP struct {
+		Person  `db:"person,required"`
+		Place   `db:",someflag"`
+		Article `db:",required"`
+	}
+	// PP columns: (person.name name title)
+
+	pp := PP{}
+	pp.Person.Name = "Peter"
+	pp.Place.Name = "Toronto"
+	pp.Article.Title = "Best city ever"
+
+	fields := m.TypeMap(reflect.TypeOf(pp))
+	// for i, f := range fields {
+	// 	log.Println(i, f)
+	// }
+
+	ppv := reflect.ValueOf(pp)
+
+	v := m.FieldByName(ppv, "person.name")
+	if v.Interface().(string) != pp.Person.Name {
+		t.Errorf("Expecting %s, got %s", pp.Person.Name, v.Interface().(string))
+	}
+
+	v = m.FieldByName(ppv, "name")
+	if v.Interface().(string) != pp.Place.Name {
+		t.Errorf("Expecting %s, got %s", pp.Place.Name, v.Interface().(string))
+	}
+
+	v = m.FieldByName(ppv, "title")
+	if v.Interface().(string) != pp.Article.Title {
+		t.Errorf("Expecting %s, got %s", pp.Article.Title, v.Interface().(string))
+	}
+
+	fi := fields.GetByPath("person")
+	if _, ok := fi.Options["required"]; !ok {
+		t.Errorf("Expecting required option to be set")
+	}
+	if !fi.Embedded {
+		t.Errorf("Expecting field to be embedded")
+	}
+	if len(fi.Index) != 1 || fi.Index[0] != 0 {
+		t.Errorf("Expecting index to be [0]")
+	}
+
+	fi = fields.GetByPath("person.name")
+	if fi == nil {
+		t.Errorf("Expecting person.name to exist")
+	}
+	if fi.Path != "person.name" {
+		t.Errorf("Expecting %s, got %s", "person.name", fi.Path)
+	}
+
+	fi = fields.GetByTraversal([]int{1, 0})
+	if fi == nil {
+		t.Errorf("Expecting traveral to exist")
+	}
+	if fi.Path != "name" {
+		t.Errorf("Expecting %s, got %s", "name", fi.Path)
+	}
+
+	fi = fields.GetByTraversal([]int{2})
+	if fi == nil {
+		t.Errorf("Expecting traversal to exist")
+	}
+	if _, ok := fi.Options["required"]; !ok {
+		t.Errorf("Expecting required option to be set")
+	}
+
+	trs := m.TraversalsByName(reflect.TypeOf(pp), []string{"person.name", "name", "title"})
+	if !reflect.DeepEqual(trs, [][]int{{0, 0}, {1, 0}, {2, 0}}) {
+		t.Errorf("Expecting traversal: %v", trs)
+	}
+}
+
+func TestPtrFields(t *testing.T) {
+	m := NewMapperTagFunc("db", strings.ToLower, nil)
+	type Asset struct {
+		Title string
+	}
+	type Post struct {
+		*Asset `db:"asset"`
+		Author string
+	}
+
+	post := &Post{Author: "Joe", Asset: &Asset{Title: "Hiyo"}}
+	pv := reflect.ValueOf(post)
+
+	fields := m.TypeMap(reflect.TypeOf(post))
+	if len(fields.Index) != 3 {
+		t.Errorf("Expecting 3 fields")
+	}
+
+	v := m.FieldByName(pv, "asset.title")
+	if v.Interface().(string) != post.Asset.Title {
+		t.Errorf("Expecting %s, got %s", post.Asset.Title, v.Interface().(string))
+	}
+	v = m.FieldByName(pv, "author")
+	if v.Interface().(string) != post.Author {
+		t.Errorf("Expecting %s, got %s", post.Author, v.Interface().(string))
+	}
+}
+
+func TestNamedPtrFields(t *testing.T) {
+	m := NewMapperTagFunc("db", strings.ToLower, nil)
+
+	type User struct {
+		Name string
+	}
+
+	type Asset struct {
+		Title string
+
+		Owner *User `db:"owner"`
+	}
+	type Post struct {
+		Author string
+
+		Asset1 *Asset `db:"asset1"`
+		Asset2 *Asset `db:"asset2"`
+	}
+
+	post := &Post{Author: "Joe", Asset1: &Asset{Title: "Hiyo", Owner: &User{"Username"}}} // Let Asset2 be nil
+	pv := reflect.ValueOf(post)
+
+	fields := m.TypeMap(reflect.TypeOf(post))
+	if len(fields.Index) != 9 {
+		t.Errorf("Expecting 9 fields")
+	}
+
+	v := m.FieldByName(pv, "asset1.title")
+	if v.Interface().(string) != post.Asset1.Title {
+		t.Errorf("Expecting %s, got %s", post.Asset1.Title, v.Interface().(string))
+	}
+	v = m.FieldByName(pv, "asset1.owner.name")
+	if v.Interface().(string) != post.Asset1.Owner.Name {
+		t.Errorf("Expecting %s, got %s", post.Asset1.Owner.Name, v.Interface().(string))
+	}
+	v = m.FieldByName(pv, "asset2.title")
+	if v.Interface().(string) != post.Asset2.Title {
+		t.Errorf("Expecting %s, got %s", post.Asset2.Title, v.Interface().(string))
+	}
+	v = m.FieldByName(pv, "asset2.owner.name")
+	if v.Interface().(string) != post.Asset2.Owner.Name {
+		t.Errorf("Expecting %s, got %s", post.Asset2.Owner.Name, v.Interface().(string))
+	}
+	v = m.FieldByName(pv, "author")
+	if v.Interface().(string) != post.Author {
+		t.Errorf("Expecting %s, got %s", post.Author, v.Interface().(string))
+	}
+}
+
+func TestFieldMap(t *testing.T) {
+	type Foo struct {
+		A int
+		B int
+		C int
+	}
+
+	f := Foo{1, 2, 3}
+	m := NewMapperFunc("db", strings.ToLower)
+
+	fm := m.FieldMap(reflect.ValueOf(f))
+
+	if len(fm) != 3 {
+		t.Errorf("Expecting %d keys, got %d", 3, len(fm))
+	}
+	if fm["a"].Interface().(int) != 1 {
+		t.Errorf("Expecting %d, got %d", 1, ival(fm["a"]))
+	}
+	if fm["b"].Interface().(int) != 2 {
+		t.Errorf("Expecting %d, got %d", 2, ival(fm["b"]))
+	}
+	if fm["c"].Interface().(int) != 3 {
+		t.Errorf("Expecting %d, got %d", 3, ival(fm["c"]))
 	}
 }
 
 func TestTagNameMapping(t *testing.T) {
 	type Strategy struct {
-		StrategyId   string `protobuf:"bytes,1,opt,name=strategy_id" json:"strategy_id,omitempty"`
+		StrategyID   string `protobuf:"bytes,1,opt,name=strategy_id" json:"strategy_id,omitempty"`
 		StrategyName string
 	}
 
 	m := NewMapperTagFunc("json", strings.ToUpper, func(value string) string {
 		if strings.Contains(value, ",") {
 			return strings.Split(value, ",")[0]
-		} else {
-			return value
 		}
+		return value
 	})
 	strategy := Strategy{"1", "Alpah"}
 	mapping := m.TypeMap(reflect.TypeOf(strategy))
 
 	for _, key := range []string{"strategy_id", "STRATEGYNAME"} {
-		if _, ok := mapping[key]; !ok {
+		if fi := mapping.GetByPath(key); fi == nil {
 			t.Errorf("Expecting to find key %s in mapping but did not.", key)
 		}
 	}
@@ -103,7 +471,7 @@
 	mapping := m.TypeMap(reflect.TypeOf(p))
 
 	for _, key := range []string{"id", "name", "wears_glasses"} {
-		if _, ok := mapping[key]; !ok {
+		if fi := mapping.GetByPath(key); fi == nil {
 			t.Errorf("Expecting to find key %s in mapping but did not.", key)
 		}
 	}
@@ -116,10 +484,9 @@
 	s := SportsPerson{Weight: 100, Age: 30, Person: p}
 	mapping = m.TypeMap(reflect.TypeOf(s))
 	for _, key := range []string{"id", "name", "wears_glasses", "weight", "age"} {
-		if _, ok := mapping[key]; !ok {
+		if fi := mapping.GetByPath(key); fi == nil {
 			t.Errorf("Expecting to find key %s in mapping but did not.", key)
 		}
-
 	}
 
 	type RugbyPlayer struct {
@@ -131,33 +498,14 @@
 	r := RugbyPlayer{12, true, false, s}
 	mapping = m.TypeMap(reflect.TypeOf(r))
 	for _, key := range []string{"id", "name", "wears_glasses", "weight", "age", "position", "is_intense"} {
-		if _, ok := mapping[key]; !ok {
+		if fi := mapping.GetByPath(key); fi == nil {
 			t.Errorf("Expecting to find key %s in mapping but did not.", key)
 		}
 	}
 
-	if _, ok := mapping["isallblack"]; ok {
+	if fi := mapping.GetByPath("isallblack"); fi != nil {
 		t.Errorf("Expecting to ignore `IsAllBlack` field")
 	}
-
-	type EmbeddedLiteral struct {
-		Embedded struct {
-			Person   string
-			Position int
-		}
-		IsIntense bool
-	}
-
-	e := EmbeddedLiteral{}
-	mapping = m.TypeMap(reflect.TypeOf(e))
-	//fmt.Printf("Mapping: %#v\n", mapping)
-
-	//f := FieldByIndexes(reflect.ValueOf(e), mapping["isintense"])
-	//fmt.Println(f, f.Interface())
-
-	//tbn := m.TraversalsByName(reflect.TypeOf(e), []string{"isintense"})
-	//fmt.Printf("%#v\n", tbn)
-
 }
 
 type E1 struct {
diff --git a/go/src/github.com/jmoiron/sqlx/sqlx.go b/go/src/github.com/jmoiron/sqlx/sqlx.go
index d195705..74e0a31 100644
--- a/go/src/github.com/jmoiron/sqlx/sqlx.go
+++ b/go/src/github.com/jmoiron/sqlx/sqlx.go
@@ -58,7 +58,7 @@
 	// it's not important that we use the right mapper for this particular object,
 	// we're only concerned on how many exported fields this struct has
 	m := mapper()
-	if len(m.TypeMap(t)) == 0 {
+	if len(m.TypeMap(t).Index) == 0 {
 		return true
 	}
 	return false
@@ -105,29 +105,35 @@
 
 // determine if any of our extensions are unsafe
 func isUnsafe(i interface{}) bool {
-	switch i.(type) {
+	switch v := i.(type) {
 	case Row:
-		return i.(Row).unsafe
+		return v.unsafe
 	case *Row:
-		return i.(*Row).unsafe
+		return v.unsafe
 	case Rows:
-		return i.(Rows).unsafe
+		return v.unsafe
 	case *Rows:
-		return i.(*Rows).unsafe
+		return v.unsafe
+	case NamedStmt:
+		return v.Stmt.unsafe
+	case *NamedStmt:
+		return v.Stmt.unsafe
 	case Stmt:
-		return i.(Stmt).unsafe
+		return v.unsafe
+	case *Stmt:
+		return v.unsafe
 	case qStmt:
-		return i.(qStmt).Stmt.unsafe
+		return v.unsafe
 	case *qStmt:
-		return i.(*qStmt).Stmt.unsafe
+		return v.unsafe
 	case DB:
-		return i.(DB).unsafe
+		return v.unsafe
 	case *DB:
-		return i.(*DB).unsafe
+		return v.unsafe
 	case Tx:
-		return i.(Tx).unsafe
+		return v.unsafe
 	case *Tx:
-		return i.(*Tx).unsafe
+		return v.unsafe
 	case sql.Rows, *sql.Rows:
 		return false
 	default:
@@ -279,7 +285,7 @@
 
 // BindNamed binds a query using the DB driver's bindvar type.
 func (db *DB) BindNamed(query string, arg interface{}) (string, []interface{}, error) {
-	return BindNamed(BindType(db.driverName), query, arg)
+	return bindNamedMapper(BindType(db.driverName), query, arg, db.Mapper)
 }
 
 // NamedQuery using this DB.
@@ -377,7 +383,7 @@
 
 // BindNamed binds a query within a transaction's bindvar type.
 func (tx *Tx) BindNamed(query string, arg interface{}) (string, []interface{}, error) {
-	return BindNamed(BindType(tx.driverName), query, arg)
+	return bindNamedMapper(BindType(tx.driverName), query, arg, tx.Mapper)
 }
 
 // NamedQuery within a transaction.
@@ -428,18 +434,18 @@
 // Stmtx returns a version of the prepared statement which runs within a transaction.  Provided
 // stmt can be either *sql.Stmt or *sqlx.Stmt.
 func (tx *Tx) Stmtx(stmt interface{}) *Stmt {
-	var st sql.Stmt
 	var s *sql.Stmt
-	switch stmt.(type) {
-	case sql.Stmt:
-		st = stmt.(sql.Stmt)
-		s = &st
+	switch v := stmt.(type) {
 	case Stmt:
-		s = stmt.(Stmt).Stmt
+		s = v.Stmt
 	case *Stmt:
-		s = stmt.(*Stmt).Stmt
+		s = v.Stmt
+	case sql.Stmt:
+		s = &v
 	case *sql.Stmt:
-		s = stmt.(*sql.Stmt)
+		s = v
+	default:
+		panic(fmt.Sprintf("non-statement type %v passed to Stmtx", reflect.ValueOf(stmt).Type()))
 	}
 	return &Stmt{Stmt: tx.Stmt(s), Mapper: tx.Mapper}
 }
@@ -473,35 +479,35 @@
 
 // Select using the prepared statement.
 func (s *Stmt) Select(dest interface{}, args ...interface{}) error {
-	return Select(&qStmt{*s}, dest, "", args...)
+	return Select(&qStmt{s}, dest, "", args...)
 }
 
 // Get using the prepared statement.
 func (s *Stmt) Get(dest interface{}, args ...interface{}) error {
-	return Get(&qStmt{*s}, dest, "", args...)
+	return Get(&qStmt{s}, dest, "", args...)
 }
 
 // MustExec (panic) using this statement.  Note that the query portion of the error
 // output will be blank, as Stmt does not expose its query.
 func (s *Stmt) MustExec(args ...interface{}) sql.Result {
-	return MustExec(&qStmt{*s}, "", args...)
+	return MustExec(&qStmt{s}, "", args...)
 }
 
 // QueryRowx using this statement.
 func (s *Stmt) QueryRowx(args ...interface{}) *Row {
-	qs := &qStmt{*s}
+	qs := &qStmt{s}
 	return qs.QueryRowx("", args...)
 }
 
 // Queryx using this statement.
 func (s *Stmt) Queryx(args ...interface{}) (*Rows, error) {
-	qs := &qStmt{*s}
+	qs := &qStmt{s}
 	return qs.Queryx("", args...)
 }
 
 // qStmt is an unexposed wrapper which lets you use a Stmt as a Queryer & Execer by
 // implementing those interfaces and ignoring the `query` argument.
-type qStmt struct{ Stmt }
+type qStmt struct{ *Stmt }
 
 func (q *qStmt) Query(query string, args ...interface{}) (*sql.Rows, error) {
 	return q.Stmt.Query(args...)
@@ -738,7 +744,7 @@
 }
 
 // SliceScan a row, returning a []interface{} with values similar to MapScan.
-// This function is primarly intended for use where the number of columns
+// This function is primarily intended for use where the number of columns
 // is not known.  Because you can pass an []interface{} directly to Scan,
 // it's recommended that you do that as it will not have to allocate new
 // slices per row.
diff --git a/go/src/github.com/jmoiron/sqlx/sqlx_test.go b/go/src/github.com/jmoiron/sqlx/sqlx_test.go
index 2096004..3716c75 100644
--- a/go/src/github.com/jmoiron/sqlx/sqlx_test.go
+++ b/go/src/github.com/jmoiron/sqlx/sqlx_test.go
@@ -24,6 +24,7 @@
 
 	_ "github.com/go-sql-driver/mysql"
 	"github.com/jmoiron/sqlx/reflectx"
+	_ "github.com/mattn/go-sqlite3"
 )
 
 /* compile time checks that Db, Tx, Stmt (qStmt) implement expected interfaces */
@@ -56,6 +57,10 @@
 	TestMysql = mydsn != "skip"
 	TestSqlite = sqdsn != "skip"
 
+	if !strings.Contains(mydsn, "parseTime=true") {
+		mydsn += "?parseTime=true"
+	}
+
 	if TestPostgres {
 		pgdb, err = Connect("postgres", pgdsn)
 		if err != nil {
@@ -130,12 +135,20 @@
     last_name text NULL,
     email text NULL
 );
+
+CREATE TABLE employees (
+	name text,
+	id integer,
+	boss_id integer
+);
+
 `,
 	drop: `
 drop table person;
 drop table place;
 drop table capplace;
 drop table nullperson;
+drop table employees;
 `,
 }
 
@@ -179,18 +192,6 @@
 	Person
 }
 
-type Loop1 struct {
-	Person
-}
-
-type Loop2 struct {
-	Loop1
-}
-
-type Loop3 struct {
-	Loop2
-}
-
 type SliceMember struct {
 	Country   string
 	City      sql.NullString
@@ -200,7 +201,7 @@
 }
 
 // Note that because of field map caching, we need a new type here
-// if we've used Place already soemwhere in sqlx
+// if we've used Place already somewhere in sqlx
 type CPlace Place
 
 func MultiExec(e Execer, query string) {
@@ -252,6 +253,9 @@
 	} else {
 		tx.MustExec(tx.Rebind("INSERT INTO capplace (\"COUNTRY\", \"TELCODE\") VALUES (?, ?)"), "Sarf Efrica", "27")
 	}
+	tx.MustExec(tx.Rebind("INSERT INTO employees (name, id) VALUES (?, ?)"), "Peter", "4444")
+	tx.MustExec(tx.Rebind("INSERT INTO employees (name, id, boss_id) VALUES (?, ?, ?)"), "Joe", "1", "4444")
+	tx.MustExec(tx.Rebind("INSERT INTO employees (name, id, boss_id) VALUES (?, ?, ?)"), "Martin", "2", "4444")
 	tx.Commit()
 }
 
@@ -323,10 +327,61 @@
 		}
 		rowsx.Close()
 
+		// test Named stmt
+		if !isUnsafe(db) {
+			t.Error("Expected db to be unsafe, but it isn't")
+		}
+		nstmt, err := db.PrepareNamed(`SELECT * FROM person WHERE first_name != :name`)
+		if err != nil {
+			t.Fatal(err)
+		}
+		// its internal stmt should be marked unsafe
+		if !nstmt.Stmt.unsafe {
+			t.Error("expected NamedStmt to be unsafe but its underlying stmt did not inherit safety")
+		}
+		pps = []PersonPlus{}
+		err = nstmt.Select(&pps, map[string]interface{}{"name": "Jason"})
+		if err != nil {
+			t.Fatal(err)
+		}
+		if len(pps) != 1 {
+			t.Errorf("Expected 1 person back, got %d", len(pps))
+		}
+
+		// test it with a safe db
+		db.unsafe = false
+		if isUnsafe(db) {
+			t.Error("expected db to be safe but it isn't")
+		}
+		nstmt, err = db.PrepareNamed(`SELECT * FROM person WHERE first_name != :name`)
+		if err != nil {
+			t.Fatal(err)
+		}
+		// it should be safe
+		if isUnsafe(nstmt) {
+			t.Error("NamedStmt did not inherit safety")
+		}
+		nstmt.Unsafe()
+		if !isUnsafe(nstmt) {
+			t.Error("expected newly unsafed NamedStmt to be unsafe")
+		}
+		pps = []PersonPlus{}
+		err = nstmt.Select(&pps, map[string]interface{}{"name": "Jason"})
+		if err != nil {
+			t.Fatal(err)
+		}
+		if len(pps) != 1 {
+			t.Errorf("Expected 1 person back, got %d", len(pps))
+		}
+
 	})
 }
 
 func TestEmbeddedStructs(t *testing.T) {
+	type Loop1 struct{ Person }
+	type Loop2 struct{ Loop1 }
+	type Loop3 struct{ Loop2 }
+
 	RunWithSchema(defaultSchema, t, func(db *DB, t *testing.T) {
 		loadDefaultFixture(db, t)
 		peopleAndPlaces := []PersonPlace{}
@@ -411,6 +466,82 @@
 	})
 }
 
+func TestJoinQuery(t *testing.T) {
+	type Employee struct {
+		Name string
+		ID   int64
+		// BossID is an id into the employee table
+		BossID sql.NullInt64 `db:"boss_id"`
+	}
+	type Boss Employee
+
+	RunWithSchema(defaultSchema, t, func(db *DB, t *testing.T) {
+		loadDefaultFixture(db, t)
+
+		var employees []struct {
+			Employee
+			Boss `db:"boss"`
+		}
+
+		err := db.Select(
+			&employees,
+			`SELECT employees.*, boss.id "boss.id", boss.name "boss.name" FROM employees
+			  JOIN employees AS boss ON employees.boss_id = boss.id`)
+		if err != nil {
+			t.Fatal(err)
+		}
+
+		for _, em := range employees {
+			if len(em.Employee.Name) == 0 {
+				t.Errorf("Expected non zero lengthed name.")
+			}
+			if em.Employee.BossID.Int64 != em.Boss.ID {
+				t.Errorf("Expected boss ids to match")
+			}
+		}
+	})
+}
+
+func TestJoinQueryNamedPointerStructs(t *testing.T) {
+	type Employee struct {
+		Name string
+		ID   int64
+		// BossID is an id into the employee table
+		BossID sql.NullInt64 `db:"boss_id"`
+	}
+	type Boss Employee
+
+	RunWithSchema(defaultSchema, t, func(db *DB, t *testing.T) {
+		loadDefaultFixture(db, t)
+
+		var employees []struct {
+			Emp1  *Employee `db:"emp1"`
+			Emp2  *Employee `db:"emp2"`
+			*Boss `db:"boss"`
+		}
+
+		err := db.Select(
+			&employees,
+			`SELECT emp.name "emp1.name", emp.id "emp1.id", emp.boss_id "emp1.boss_id",
+			 emp.name "emp2.name", emp.id "emp2.id", emp.boss_id "emp2.boss_id",
+			 boss.id "boss.id", boss.name "boss.name" FROM employees AS emp
+			  JOIN employees AS boss ON emp.boss_id = boss.id
+			  `)
+		if err != nil {
+			t.Fatal(err)
+		}
+
+		for _, em := range employees {
+			if len(em.Emp1.Name) == 0 || len(em.Emp2.Name) == 0 {
+				t.Errorf("Expected non zero lengthed name.")
+			}
+			if em.Emp1.BossID.Int64 != em.Boss.ID || em.Emp2.BossID.Int64 != em.Boss.ID {
+				t.Errorf("Expected boss ids to match")
+			}
+		}
+	})
+}
+
 func TestSelectSliceMapTime(t *testing.T) {
 	RunWithSchema(defaultSchema, t, func(db *DB, t *testing.T) {
 		loadDefaultFixture(db, t)
@@ -483,9 +614,9 @@
 		}
 
 		p := Person{
-			FirstName: sql.NullString{"ben", true},
-			LastName:  sql.NullString{"doe", true},
-			Email:     sql.NullString{"ben@doe.com", true},
+			FirstName: sql.NullString{String: "ben", Valid: true},
+			LastName:  sql.NullString{String: "doe", Valid: true},
+			Email:     sql.NullString{String: "ben@doe.com", Valid: true},
 		}
 
 		q1 := `INSERT INTO person (first_name, last_name, email) VALUES (:first_name, :last_name, :email)`
@@ -517,16 +648,16 @@
 		// queries and NamedStmt queries, which use different code paths internally.
 		old := *db.Mapper
 
-		type JsonPerson struct {
+		type JSONPerson struct {
 			FirstName sql.NullString `json:"FIRST"`
 			LastName  sql.NullString `json:"last_name"`
 			Email     sql.NullString
 		}
 
-		jp := JsonPerson{
-			FirstName: sql.NullString{"ben", true},
-			LastName:  sql.NullString{"smith", true},
-			Email:     sql.NullString{"ben@smith.com", true},
+		jp := JSONPerson{
+			FirstName: sql.NullString{String: "ben", Valid: true},
+			LastName:  sql.NullString{String: "smith", Valid: true},
+			Email:     sql.NullString{String: "ben@smith.com", Valid: true},
 		}
 
 		db.Mapper = reflectx.NewMapperFunc("json", strings.ToUpper)
@@ -549,7 +680,7 @@
 
 		// Checks that a person pulled out of the db matches the one we put in
 		check := func(t *testing.T, rows *Rows) {
-			jp = JsonPerson{}
+			jp = JSONPerson{}
 			for rows.Next() {
 				err = rows.StructScan(&jp)
 				if err != nil {
@@ -617,7 +748,7 @@
 
 	RunWithSchema(schema, t, func(db *DB, t *testing.T) {
 		type TT struct {
-			Id    int
+			ID    int
 			Value *string
 		}
 		var v, v2 TT
@@ -625,14 +756,14 @@
 
 		db.MustExec(r(`INSERT INTO tt (id) VALUES (1)`))
 		db.Get(&v, r(`SELECT * FROM tt`))
-		if v.Id != 1 {
-			t.Errorf("Expecting id of 1, got %v", v.Id)
+		if v.ID != 1 {
+			t.Errorf("Expecting id of 1, got %v", v.ID)
 		}
 		if v.Value != nil {
-			t.Errorf("Expecting NULL to map to nil, got %s", v.Value)
+			t.Errorf("Expecting NULL to map to nil, got %s", *v.Value)
 		}
 
-		v.Id = 2
+		v.ID = 2
 		// NOTE: this incidentally uncovered a bug which was that named queries with
 		// pointer destinations would not work if the passed value here was not addressable,
 		// as reflectx.FieldByIndexes attempts to allocate nil pointer receivers for
@@ -641,11 +772,11 @@
 		db.NamedExec(`INSERT INTO tt (id, value) VALUES (:id, :value)`, v)
 
 		db.Get(&v2, r(`SELECT * FROM tt WHERE id=2`))
-		if v.Id != v2.Id {
-			t.Errorf("%v != %v", v.Id, v2.Id)
+		if v.ID != v2.ID {
+			t.Errorf("%v != %v", v.ID, v2.ID)
 		}
 		if v2.Value != nil {
-			t.Errorf("Expecting NULL to map to nil, got %s", v.Value)
+			t.Errorf("Expecting NULL to map to nil, got %s", *v.Value)
 		}
 	})
 }
@@ -1035,7 +1166,7 @@
 			t.Error(err)
 		}
 		if *pcount != count {
-			t.Error("expected %d = %d", *pcount, count)
+			t.Errorf("expected %d = %d", *pcount, count)
 		}
 
 		// test Select...
@@ -1076,6 +1207,7 @@
 		t.Errorf("Should return error when using bogus driverName")
 	}
 }
+
 func TestRebind(t *testing.T) {
 	q1 := `INSERT INTO foo (a, b, c, d, e, f, g, h, i) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`
 	q2 := `INSERT INTO foo (a, b, c) VALUES (?, ?, "foo"), ("Hi", ?, ?)`
@@ -1090,6 +1222,20 @@
 	if s2 != `INSERT INTO foo (a, b, c) VALUES ($1, $2, "foo"), ("Hi", $3, $4)` {
 		t.Errorf("q2 failed")
 	}
+
+	s1 = Rebind(NAMED, q1)
+	s2 = Rebind(NAMED, q2)
+
+	ex1 := `INSERT INTO foo (a, b, c, d, e, f, g, h, i) VALUES ` +
+		`(:arg1, :arg2, :arg3, :arg4, :arg5, :arg6, :arg7, :arg8, :arg9, :arg10)`
+	if s1 != ex1 {
+		t.Error("q1 failed on Named params")
+	}
+
+	ex2 := `INSERT INTO foo (a, b, c) VALUES (:arg1, :arg2, "foo"), ("Hi", :arg3, :arg4)`
+	if s2 != ex2 {
+		t.Error("q2 failed on Named params")
+	}
 }
 
 func TestBindMap(t *testing.T) {
@@ -1171,7 +1317,7 @@
 		for _, m := range messages {
 			_, err := db.NamedExec(q1, m)
 			if err != nil {
-				t.Error(err)
+				t.Fatal(err)
 			}
 		}
 		var count int
@@ -1194,6 +1340,147 @@
 	})
 }
 
+func TestIssue197(t *testing.T) {
+	// this test actually tests for a bug in database/sql:
+	//   https://github.com/golang/go/issues/13905
+	// this potentially makes _any_ named type that is an alias for []byte
+	// unsafe to use in a lot of different ways (basically, unsafe to hold
+	// onto after loading from the database).
+	t.Skip()
+
+	type mybyte []byte
+	type Var struct{ Raw json.RawMessage }
+	type Var2 struct{ Raw []byte }
+	type Var3 struct{ Raw mybyte }
+	RunWithSchema(defaultSchema, t, func(db *DB, t *testing.T) {
+		var err error
+		var v, q Var
+		if err = db.Get(&v, `SELECT '{"a": "b"}' AS raw`); err != nil {
+			t.Fatal(err)
+		}
+		fmt.Printf("%s: v %s\n", db.DriverName(), v.Raw)
+		if err = db.Get(&q, `SELECT 'null' AS raw`); err != nil {
+			t.Fatal(err)
+		}
+		fmt.Printf("%s: v %s\n", db.DriverName(), v.Raw)
+
+		var v2, q2 Var2
+		if err = db.Get(&v2, `SELECT '{"a": "b"}' AS raw`); err != nil {
+			t.Fatal(err)
+		}
+		fmt.Printf("%s: v2 %s\n", db.DriverName(), v2.Raw)
+		if err = db.Get(&q2, `SELECT 'null' AS raw`); err != nil {
+			t.Fatal(err)
+		}
+		fmt.Printf("%s: v2 %s\n", db.DriverName(), v2.Raw)
+
+		var v3, q3 Var3
+		if err = db.QueryRow(`SELECT '{"a": "b"}' AS raw`).Scan(&v3.Raw); err != nil {
+			t.Fatal(err)
+		}
+		fmt.Printf("v3 %s\n", v3.Raw)
+		if err = db.QueryRow(`SELECT '{"c": "d"}' AS raw`).Scan(&q3.Raw); err != nil {
+			t.Fatal(err)
+		}
+		fmt.Printf("v3 %s\n", v3.Raw)
+		t.Fail()
+	})
+}
+
+func TestIn(t *testing.T) {
+	// some quite normal situations
+	type tr struct {
+		q    string
+		args []interface{}
+		c    int
+	}
+	tests := []tr{
+		{"SELECT * FROM foo WHERE x = ? AND v in (?) AND y = ?",
+			[]interface{}{"foo", []int{0, 5, 7, 2, 9}, "bar"},
+			7},
+		{"SELECT * FROM foo WHERE x in (?)",
+			[]interface{}{[]int{1, 2, 3, 4, 5, 6, 7, 8}},
+			8},
+	}
+	for _, test := range tests {
+		q, a, err := In(test.q, test.args...)
+		if err != nil {
+			t.Error(err)
+		}
+		if len(a) != test.c {
+			t.Errorf("Expected %d args, but got %d (%+v)", test.c, len(a), a)
+		}
+		if strings.Count(q, "?") != test.c {
+			t.Errorf("Expected %d bindVars, got %d", test.c, strings.Count(q, "?"))
+		}
+	}
+
+	// too many bindVars, but no slices, so short circuits parsing
+	// i'm not sure if this is the right behavior;  this query/arg combo
+	// might not work, but we shouldn't parse if we don't need to
+	{
+		orig := "SELECT * FROM foo WHERE x = ? AND y = ?"
+		q, a, err := In(orig, "foo", "bar", "baz")
+		if err != nil {
+			t.Error(err)
+		}
+		if len(a) != 3 {
+			t.Errorf("Expected 3 args, but got %d (%+v)", len(a), a)
+		}
+		if q != orig {
+			t.Error("Expected unchanged query.")
+		}
+	}
+
+	tests = []tr{
+		// too many bindvars;  slice present so should return error during parse
+		{"SELECT * FROM foo WHERE x = ? and y = ?",
+			[]interface{}{"foo", []int{1, 2, 3}, "bar"},
+			0},
+		// empty slice, should return error before parse
+		{"SELECT * FROM foo WHERE x = ?",
+			[]interface{}{[]int{}},
+			0},
+		// too *few* bindvars, should return an error
+		{"SELECT * FROM foo WHERE x = ? AND y in (?)",
+			[]interface{}{[]int{1, 2, 3}},
+			0},
+	}
+	for _, test := range tests {
+		_, _, err := In(test.q, test.args...)
+		if err == nil {
+			t.Error("Expected an error, but got nil.")
+		}
+	}
+	RunWithSchema(defaultSchema, t, func(db *DB, t *testing.T) {
+		loadDefaultFixture(db, t)
+		//tx.MustExec(tx.Rebind("INSERT INTO place (country, city, telcode) VALUES (?, ?, ?)"), "United States", "New York", "1")
+		//tx.MustExec(tx.Rebind("INSERT INTO place (country, telcode) VALUES (?, ?)"), "Hong Kong", "852")
+		//tx.MustExec(tx.Rebind("INSERT INTO place (country, telcode) VALUES (?, ?)"), "Singapore", "65")
+		telcodes := []int{852, 65}
+		q := "SELECT * FROM place WHERE telcode IN(?) ORDER BY telcode"
+		query, args, err := In(q, telcodes)
+		if err != nil {
+			t.Error(err)
+		}
+		query = db.Rebind(query)
+		places := []Place{}
+		err = db.Select(&places, query, args...)
+		if err != nil {
+			t.Error(err)
+		}
+		if len(places) != 2 {
+			t.Fatalf("Expecting 2 results, got %d", len(places))
+		}
+		if places[0].TelCode != 65 {
+			t.Errorf("Expecting singapore first, but got %#v", places[0])
+		}
+		if places[1].TelCode != 852 {
+			t.Errorf("Expecting hong kong second, but got %#v", places[1])
+		}
+	})
+}
+
 func TestBindStruct(t *testing.T) {
 	var err error
 
@@ -1319,7 +1606,6 @@
 		if *target2.K != "one" {
 			t.Errorf("Expected target2.K to be `one`, got `%v`", target2.K)
 		}
-
 	})
 }
 
@@ -1336,7 +1622,6 @@
 	b.StartTimer()
 	for i := 0; i < b.N; i++ {
 		bindStruct(DOLLAR, q1, am, mapper())
-		//bindMap(QUESTION, q1, am)
 	}
 }
 
@@ -1352,7 +1637,14 @@
 	b.StartTimer()
 	for i := 0; i < b.N; i++ {
 		bindMap(DOLLAR, q1, am)
-		//bindMap(QUESTION, q1, am)
+	}
+}
+
+func BenchmarkIn(b *testing.B) {
+	q := `SELECT * FROM foo WHERE x = ? AND v in (?) AND y = ?`
+
+	for i := 0; i < b.N; i++ {
+		_, _, _ = In(q, []interface{}{"foo", []int{0, 5, 7, 2, 9}, "bar"}...)
 	}
 }
 
diff --git a/go/src/github.com/jmoiron/sqlx/types/types.go b/go/src/github.com/jmoiron/sqlx/types/types.go
index f1700b6..53848bc 100644
--- a/go/src/github.com/jmoiron/sqlx/types/types.go
+++ b/go/src/github.com/jmoiron/sqlx/types/types.go
@@ -10,8 +10,12 @@
 	"io/ioutil"
 )
 
+// GzippedText is a []byte which transparently gzips data being submitted to
+// a database and ungzips data being Scanned from a database.
 type GzippedText []byte
 
+// Value implements the driver.Valuer interface, gzipping the raw value of
+// this GzippedText.
 func (g GzippedText) Value() (driver.Value, error) {
 	b := make([]byte, 0, len(g))
 	buf := bytes.NewBuffer(b)
@@ -22,6 +26,8 @@
 
 }
 
+// Scan implements the sql.Scanner interface, ungzipping the value coming off
+// the wire and storing the raw result in the GzippedText.
 func (g *GzippedText) Scan(src interface{}) error {
 	var source []byte
 	switch src.(type) {
@@ -42,21 +48,21 @@
 	return nil
 }
 
-// JsonText is a json.RawMessage, which is a []byte underneath.
+// JSONText is a json.RawMessage, which is a []byte underneath.
 // Value() validates the json format in the source, and returns an error if
-// the json is not valid.  Scan does no validation.  JsonText additionally
+// the json is not valid.  Scan does no validation.  JSONText additionally
 // implements `Unmarshal`, which unmarshals the json within to an interface{}
-type JsonText json.RawMessage
+type JSONText json.RawMessage
 
-// Returns the *j as the JSON encoding of j.
-func (j *JsonText) MarshalJSON() ([]byte, error) {
+// MarshalJSON returns the *j as the JSON encoding of j.
+func (j *JSONText) MarshalJSON() ([]byte, error) {
 	return *j, nil
 }
 
 // UnmarshalJSON sets *j to a copy of data
-func (j *JsonText) UnmarshalJSON(data []byte) error {
+func (j *JSONText) UnmarshalJSON(data []byte) error {
 	if j == nil {
-		return errors.New("JsonText: UnmarshalJSON on nil pointer")
+		return errors.New("JSONText: UnmarshalJSON on nil pointer")
 	}
 	*j = append((*j)[0:0], data...)
 	return nil
@@ -65,7 +71,7 @@
 
 // Value returns j as a value.  This does a validating unmarshal into another
 // RawMessage.  If j is invalid json, it returns an error.
-func (j JsonText) Value() (driver.Value, error) {
+func (j JSONText) Value() (driver.Value, error) {
 	var m json.RawMessage
 	var err = j.Unmarshal(&m)
 	if err != nil {
@@ -75,7 +81,7 @@
 }
 
 // Scan stores the src in *j.  No validation is done.
-func (j *JsonText) Scan(src interface{}) error {
+func (j *JSONText) Scan(src interface{}) error {
 	var source []byte
 	switch src.(type) {
 	case string:
@@ -83,13 +89,18 @@
 	case []byte:
 		source = src.([]byte)
 	default:
-		return errors.New("Incompatible type for JsonText")
+		return errors.New("Incompatible type for JSONText")
 	}
-	*j = JsonText(append((*j)[0:0], source...))
+	*j = JSONText(append((*j)[0:0], source...))
 	return nil
 }
 
 // Unmarshal unmarshal's the json in j to v, as in json.Unmarshal.
-func (j *JsonText) Unmarshal(v interface{}) error {
+func (j *JSONText) Unmarshal(v interface{}) error {
 	return json.Unmarshal([]byte(*j), v)
 }
+
+// Pretty printing for JSONText types
+func (j JSONText) String() string {
+	return string(j)
+}
diff --git a/go/src/github.com/jmoiron/sqlx/types/types_test.go b/go/src/github.com/jmoiron/sqlx/types/types_test.go
index e5c9e1a..78a1ef8 100644
--- a/go/src/github.com/jmoiron/sqlx/types/types_test.go
+++ b/go/src/github.com/jmoiron/sqlx/types/types_test.go
@@ -17,8 +17,8 @@
 	}
 }
 
-func TestJsonText(t *testing.T) {
-	j := JsonText(`{"foo": 1, "bar": 2}`)
+func TestJSONText(t *testing.T) {
+	j := JSONText(`{"foo": 1, "bar": 2}`)
 	v, err := j.Value()
 	if err != nil {
 		t.Errorf("Was not expecting an error")
@@ -34,7 +34,7 @@
 		t.Errorf("Expected valid json but got some garbage instead? %#v", m)
 	}
 
-	j = JsonText(`{"foo": 1, invalid, false}`)
+	j = JSONText(`{"foo": 1, invalid, false}`)
 	v, err = j.Value()
 	if err == nil {
 		t.Errorf("Was expecting invalid json to fail!")