func (f *Field) Address() string {
	name := f.fieldVarAddress()
	var casted bool
	if mapped, ok := mappings[f.Type]; ok {
		name = fmt.Sprintf("(*%s)(%s)", mapped, name)
		casted = true
	}
	return f.wrapAddress(name, casted)
}
Address returns the string representation of the code used to get the
pointer to the field.
package generator
import (
	"bytes"
	"fmt"
	"go/types"
	"reflect"
	"strconv"
	"strings"
	"unicode"
)
var reservedKeywords = map[string]struct{}{
	"all":               {},
	"analyse":           {},
	"analyze":           {},
	"and":               {},
	"any":               {},
	"array":             {},
	"as":                {},
	"asc":               {},
	"asymmetric":        {},
	"authorization":     {},
	"binary":            {},
	"both":              {},
	"case":              {},
	"cast":              {},
	"check":             {},
	"collate":           {},
	"collation":         {},
	"columns":           {},
	"concurrently":      {},
	"constraint":        {},
	"create":            {},
	"cross":             {},
	"current_catalog":   {},
	"current_date":      {},
	"current_role":      {},
	"current_schema":    {},
	"current_time":      {},
	"current_timestamp": {},
	"current_user":      {},
	"default":           {},
	"deferrable":        {},
	"desc":              {},
	"distinct":          {},
	"do":                {},
	"end":               {},
	"except":            {},
	"false":             {},
	"fetch":             {},
	"for":               {},
	"foreign":           {},
	"from":              {},
	"grant":             {},
	"group":             {},
	"having":            {},
	"in":                {},
	"index":             {},
	"initially":         {},
	"inner":             {},
	"intersect":         {},
	"into":              {},
	"join":              {},
	"key":               {},
	"lateral":           {},
	"leading":           {},
	"left":              {},
	"like":              {},
	"limit":             {},
	"localtime":         {},
	"localtimestamp":    {},
	"natural":           {},
	"not":               {},
	"null":              {},
	"offset":            {},
	"on":                {},
	"only":              {},
	"or":                {},
	"order":             {},
	"overlaps":          {},
	"placing":           {},
	"primary":           {},
	"references":        {},
	"returning":         {},
	"select":            {},
	"some":              {},
	"symmetric":         {},
	"table":             {},
	"then":              {},
	"to":                {},
	"trailing":          {},
	"true":              {},
	"union":             {},
	"unique":            {},
	"user":              {},
	"using":             {},
	"variadic":          {},
	"verbose":           {},
	"when":              {},
	"where":             {},
	"window":            {},
	"with":              {},
}
var specialTypes = map[string]string{
	"gopkg.in/src-d/go-kallax.v1.UUID":      "kallax.UUID",
	"gopkg.in/src-d/go-kallax.v1.ULID":      "kallax.ULID",
	"gopkg.in/src-d/go-kallax.v1.NumericID": "kallax.NumericID",
	"github.com/satori/go.uuid.UUID":        "kallax.UUID",
	"github.com/gofrs/uuid.UUID":            "kallax.UUID",
	"net/url.URL":                           "url.URL",
	"time.Time":                             "time.Time",
}
var mappings = map[string]string{
	"url.URL": "types.URL",
}
type Package struct {
	pkg *types.Package
	Name string
	Models        []*Model
	indexedModels map[string]*Model
}
func NewPackage(pkg *types.Package) *Package {
	return &Package{
		Name:          pkg.Name(),
		pkg:           pkg,
		indexedModels: make(map[string]*Model),
	}
}
func (p *Package) SetModels(models []*Model) {
	for _, m := range models {
		p.indexedModels[m.Name] = m
	}
	p.Models = models
}
func (p *Package) FindModel(name string) *Model {
	return p.indexedModels[name]
}
func (p *Package) addMissingRelationships() error {
	for _, m := range p.Models {
		for _, f := range m.Fields {
			if f.Kind == Relationship && !f.IsInverse() {
				if err := p.trySetFK(f.TypeSchemaName(), f); err != nil {
					return err
				}
			}
		}
	}
	return nil
}
func (p *Package) trySetFK(model string, fk *Field) error {
	m := p.FindModel(model)
	if m == nil {
		return fmt.Errorf("kallax: cannot assign implicit foreign key to non-existent model %s", model)
	}
	var found bool
	for _, f := range m.Fields {
		if f.Kind == Relationship {
			if f.ForeignKey() == fk.ForeignKey() {
				found = true
				break
			}
		} else {
			if f.ColumnName() == fk.ForeignKey() {
				found = true
				break
			}
		}
	}
	if !found {
		for _, ifk := range m.ImplicitFKs {
			if ifk.Name == fk.ForeignKey() {
				found = true
				break
			}
		}
	}
	if !found {
		m.ImplicitFKs = append(m.ImplicitFKs, ImplicitFK{
			Name: fk.ForeignKey(),
			Type: identifierType(fk.Model.ID),
		})
	}
	return nil
}
const (
	StoreNamePattern = "%sStore"
	QueryNamePattern = "%sQuery"
	ResultSetNamePattern = "%sResultSet"
)
type Model struct {
	Name string
	StoreName string
	QueryName string
	ResultSetName string
	Table string
	Type string
	Fields []*Field
	ImplicitFKs []ImplicitFK
	ID *Field
	Events Events
	Node *types.Named
	CtorFunc *types.Func
	Package *types.Package
}
func NewModel(n string) *Model {
	return &Model{
		Name:          n,
		StoreName:     fmt.Sprintf(StoreNamePattern, n),
		QueryName:     fmt.Sprintf(QueryNamePattern, n),
		ResultSetName: fmt.Sprintf(ResultSetNamePattern, n),
		Type:          "struct",
	}
}
func (m *Model) Alias() string {
	return "__" + strings.ToLower(m.Name)
}
func (m *Model) String() string {
	var events []string
	for _, e := range m.Events {
		events = append(events, string(e))
	}
	return fmt.Sprintf("%q [%d Field(s)] [Events: %s]", m.Name, len(m.Fields)-1, events)
}
type occurrences map[string]uint
func (o occurrences) inc(name string) {
	o[name]++
}
func (o occurrences) repeated() []string {
	var result []string
	for v, times := range o {
		if times > 1 {
			result = append(result, v)
		}
	}
	return result
}
func (m *Model) repeatedFields() []string {
	var occ = make(occurrences)
	m.checkFieldOccurrences(m.Fields, occ)
	return occ.repeated()
}
func (m *Model) checkFieldOccurrences(fields []*Field, occurrences occurrences) {
	for _, f := range fields {
		if f.Inline() {
			m.checkFieldOccurrences(f.Fields, occurrences)
		} else {
			occurrences.inc(f.Name)
		}
	}
}
func (m *Model) repeatedCols() []string {
	columns := make(occurrences)
	m.checkFieldColumns(m.Fields, columns)
	return columns.repeated()
}
func (m *Model) checkFieldColumns(fields []*Field, cols occurrences) {
	for _, f := range fields {
		if f.Inline() {
			m.checkFieldColumns(f.Fields, cols)
		} else if f.Kind != Relationship {
			cols.inc(f.ColumnName())
		}
	}
}
func (m *Model) Validate() error {
	if m.ID == nil {
		return fmt.Errorf("kallax: model %s has no primary key defined", m.Name)
	}
	if !isValidIdentifier(m.ID) {
		return fmt.Errorf("kallax: primary key %q of model %q does not have a valid identifier type (%s)", m.ID.Name, m.Name, m.ID.Type)
	}
	if fields := m.repeatedFields(); len(fields) > 0 {
		return fmt.Errorf("kallax: the following fields are repeated: %v", fields)
	}
	if cols := m.repeatedCols(); len(cols) > 0 {
		return fmt.Errorf("kallax: the following column names are repeated: %v", cols)
	}
	if m.Table == "" {
		return fmt.Errorf("kallax: model %s has no table", m.Name)
	}
	return nil
}
func (m *Model) CtorArgs() string {
	if m.CtorFunc == nil {
		return ""
	}
	var ret []string
	sig := m.CtorFunc.Type().(*types.Signature)
	paramsLen := sig.Params().Len()
	for i := 0; i < paramsLen; i++ {
		param := sig.Params().At(i)
		typeName, ok := findableTypeName(param.Type(), m.Package)
		if !ok {
			typeName = typeString(param.Type(), m.Package)
		}
		if paramsLen == i+1 && sig.Variadic() {
			typeName = "..." + typeName
		} else  
		if collectionElemType(param.Type()) != nil && !strings.HasPrefix(typeName, "[]") {
			typeName = "[]" + typeName
		}
		paramName := param.Name()
		if paramName == "s" {
			paramName = fmt.Sprintf("arg%v", i)
		}
		ret = append(ret, fmt.Sprintf("%v %v", paramName, typeName))
	}
	return strings.Join(ret, ", ")
}
func (m *Model) CtorArgVars() string {
	if m.CtorFunc == nil {
		return ""
	}
	var ret []string
	sig := m.CtorFunc.Type().(*types.Signature)
	paramsLen := sig.Params().Len()
	for i := 0; i < sig.Params().Len(); i++ {
		arg := sig.Params().At(i).Name()
		if paramsLen == i+1 && sig.Variadic() {
			arg += "..."
		}
		ret = append(ret, arg)
	}
	return strings.Join(ret, ", ")
}
func (m *Model) CtorReturns() string {
	if m.CtorFunc == nil {
		return "(record *" + m.Name + ")"
	}
	var ret []string
	hasError := false
	sig := m.CtorFunc.Type().(*types.Signature)
	for i := 0; i < sig.Results().Len(); i++ {
		res := sig.Results().At(i)
		typeName, ok := findableTypeName(res.Type(), m.Package)
		if !ok {
			typeName = typeString(res.Type(), m.Package)
		}
		if isTypeOrPtrTo(res.Type(), m.Node) {
			ret = append(ret, "record "+typeName)
		} else if isBuiltinError(res.Type()) && !hasError {
			ret = append(ret, "err "+typeName)
			hasError = true
		} else if res.Name() != "" {
			ret = append(ret, fmt.Sprintf("r%d %v", i, res.Name()))
		} else {
			ret = append(ret, fmt.Sprintf("r%d %v", i, typeName))
		}
	}
	return "(" + strings.Join(ret, ", ") + ")"
}
func (m *Model) CtorRetVars() string {
	if m.CtorFunc == nil {
		return "record"
	}
	var ret []string
	hasError := false
	sig := m.CtorFunc.Type().(*types.Signature)
	for i := 0; i < sig.Results().Len(); i++ {
		res := sig.Results().At(i)
		if isTypeOrPtrTo(res.Type(), m.Node) {
			ret = append(ret, "record")
		} else if isBuiltinError(res.Type()) && !hasError {
			ret = append(ret, "err")
			hasError = true
		} else {
			ret = append(ret, fmt.Sprintf("r%d", i))
		}
	}
	return strings.Join(ret, ", ")
}
func (m *Model) SetFields(fields []*Field) error {
	var fs []*Field
	var id *Field
	for _, f := range flattenFields(fields) {
		f.Model = m
		if f.IsPrimaryKey() && f.Type != BaseModel {
			if id != nil {
				return fmt.Errorf(
					"kallax: found more than one primary key in model %s: %s and %s",
					m.Name,
					id.Name,
					f.Name,
				)
			}
			id = f
		} else if f.IsPrimaryKey() {
			if f.primaryKey == "" {
				return fmt.Errorf(
					"kallax: primary key defined in %s has no field name, but it must be specified",
					f.Name,
				)
			}
			id = f
			fs = append(fs, f)
		} else {
			fs = append(fs, f)
		}
	}
	if id != nil && id.Type == BaseModel {
		for i, f := range fs {
			if f.columnName == id.primaryKey {
				f.isPrimaryKey = true
				f.isAutoincrement = id.isAutoincrement
				id = f
				if len(fs)-1 == i {
					fs = append(fs[:i])
				} else {
					fs = append(fs[:i], fs[i+1:]...)
				}
				break
			}
		}
		if id.Type == BaseModel {
			return fmt.Errorf(
				"kallax: the primary key was supposed to be %s according to the pk definition in %s, but the field could not be found",
				id.primaryKey,
				id.Name,
			)
		}
	}
	if id != nil {
		m.Fields = []*Field{id}
		m.ID = id
	}
	m.Fields = append(m.Fields, fs...)
	return nil
}
func (m *Model) Relationships() []*Field {
	return relationshipsOnFields(m.Fields)
}
func (m *Model) Inverses() []*Field {
	var inverses []*Field
	for _, f := range relationshipsOnFields(m.Fields) {
		if f.IsInverse() {
			inverses = append(inverses, f)
		}
	}
	return inverses
}
func (m *Model) NonInverses() []*Field {
	var rels []*Field
	for _, f := range relationshipsOnFields(m.Fields) {
		if !f.IsInverse() {
			rels = append(rels, f)
		}
	}
	return rels
}
func (m *Model) HasRelationships() bool {
	return len(m.Relationships()) > 0
}
func (m *Model) HasInverses() bool {
	return len(m.Inverses()) > 0
}
func (m *Model) HasNonInverses() bool {
	return len(m.NonInverses()) > 0
}
func relationshipsOnFields(fields []*Field) []*Field {
	var result []*Field
	for _, f := range fields {
		if f.Kind == Relationship {
			result = append(result, f)
		} else if f.Inline() {
			result = append(result, relationshipsOnFields(f.Fields)...)
		}
	}
	return result
}
type ImplicitFK struct {
	Name string
	Type string
}
type Field struct {
	Name string
	Type string
	Kind FieldKind
	Node *types.Var
	Tag reflect.StructTag
	Fields []*Field
	Parent *Field
	Model *Model
	IsPtr bool
	IsJSON bool
	IsAlias bool
	IsEmbedded bool
	primaryKey      string
	isPrimaryKey    bool
	isUnique        bool
	isAutoincrement bool
	columnName      string
}
type FieldKind int
const (
	Basic FieldKind = iota
	Array
	Slice
	Map
	Interface
	Struct
	Relationship
	Invalid
)
func (t FieldKind) String() string {
	switch t {
	case Basic:
		return "Basic"
	case Array:
		return "Array"
	case Slice:
		return "Slice"
	case Map:
		return "Map"
	case Interface:
		return "Interface"
	case Struct:
		return "Struct"
	case Relationship:
		return "Relationship"
	case Invalid:
		return "Invalid"
	default:
		return "UNKNOWN"
	}
}
func NewField(n, t string, tag reflect.StructTag) *Field {
	pkName, autoincr, isPrimaryKey := pkProperties(tag)
	return &Field{
		Name: n,
		Type: t,
		Tag:  tag,
		primaryKey:      pkName,
		columnName:      columnName(n, tag),
		isPrimaryKey:    isPrimaryKey,
		isUnique:        isUnique(tag),
		isAutoincrement: autoincr,
	}
}
func isUnique(tag reflect.StructTag) bool {
	return tag.Get("unique") == "true"
}
func pkProperties(tag reflect.StructTag) (name string, autoincr, isPrimaryKey bool) {
	val, ok := tag.Lookup("pk")
	if !ok {
		return
	}
	isPrimaryKey = true
	if val == "autoincr" || val == "" {
		if val == "autoincr" {
			autoincr = true
		}
		return
	}
	parts := strings.Split(val, ",")
	name = parts[0]
	if len(parts) > 1 && parts[1] == "autoincr" {
		autoincr = true
	}
	return
}
func (f *Field) SetFields(sf []*Field) {
	for _, field := range sf {
		field.Parent = f
		field.Model = f.Model
		f.Fields = append(f.Fields, field)
	}
}
func (f *Field) ColumnName() string {
	return f.columnName
}
func columnName(name string, tag reflect.StructTag) string {
	n := strings.TrimSpace(strings.Split(tag.Get("kallax"), ",")[0])
	if n == "" {
		n = toLowerSnakeCase(name)
	}
	if _, ok := reservedKeywords[strings.ToLower(n)]; ok {
		n = "_" + n
	}
	return n
}
func (f *Field) ForeignKey() string {
	if f.Kind != Relationship {
		return ""
	}
	fk := strings.Split(f.Tag.Get("fk"), ",")[0]
	if fk == "" && !f.IsInverse() {
		fk = foreignKeyForModel(f.Model.Name)
	} else if fk == "" {
		fk = foreignKeyForModel(f.TypeSchemaName())
	}
	return fk
}
func (f *Field) IsPrimaryKey() bool {
	return f.isPrimaryKey
}
func (f *Field) IsUnique() bool {
	return f.isUnique
}
func (f *Field) IsAutoIncrement() bool {
	return f.isAutoincrement
}
func (f *Field) IsInverse() bool {
	if f.Kind != Relationship {
		return false
	}
	for _, part := range strings.Split(f.Tag.Get("fk"), ",") {
		if part == "inverse" {
			return true
		}
	}
	return false
}
func (f *Field) IsOneToManyRelationship() bool {
	return f.Kind == Relationship && strings.HasPrefix(f.Type, "[]")
}
func foreignKeyForModel(model string) string {
	return toLowerSnakeCase(model) + "_id"
}
func (f *Field) Inline() bool {
	if f.Type == BaseModel || f.IsEmbedded {
		return true
	}
	tag := f.Tag.Get("kallax")
	for _, p := range strings.Split(tag, ",") {
		if p == "inline" {
			return true
		}
	}
	return false
}
func (f *Field) JSONName() string {
	tag := strings.Split(f.Tag.Get("json"), ",")[0]
	if tag == "" {
		tag = f.Name
	}
	return tag
}
func (f *Field) String() string {
	return f.Name
}
func (f *Field) fieldName() string {
	if f.Parent != nil {
		return fmt.Sprintf("%s.%s", f.Parent.fieldName(), f.Name)
	}
	return f.Name
}
func (f *Field) fieldVarName() string {
	return fmt.Sprintf("r.%s", f.fieldName())
}
func (f *Field) fieldVarAddress() string {
	name := f.fieldVarName()
	if !f.IsPtr {
		name = "&" + name
	}
	return name
}