Skip to content

Commit

Permalink
add parent table pointer to colmap, add SetSqlCreate (fixes #21)
Browse files Browse the repository at this point in the history
  • Loading branch information
jmoiron committed Oct 1, 2014
1 parent 7230d99 commit 5d9b4fb
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 10 deletions.
31 changes: 21 additions & 10 deletions dbmap.go
Expand Up @@ -19,6 +19,7 @@ import (
"strings"

"github.com/jmoiron/sqlx"
"github.com/jmoiron/sqlx/reflectx"
)

// TableNameMapper is the function used by AddTable to map struct names to database table names, in analogy
Expand All @@ -45,11 +46,17 @@ type DbMap struct {
tables []*TableMap
logger *log.Logger
logPrefix string
mapper *reflectx.Mapper
}

// NewDbMap returns a new DbMap using the db connection and dialect
// NewDbMap returns a new DbMap using the db connection and dialect.
func NewDbMap(db *sql.DB, dialect Dialect) *DbMap {
return &DbMap{Db: db, Dialect: dialect, Dbx: sqlx.NewDb(db, dialect.DriverName())}
return &DbMap{
Db: db,
Dialect: dialect,
Dbx: sqlx.NewDb(db, dialect.DriverName()),
mapper: reflectx.NewMapperFunc("db", sqlx.NameMapper),
}
}

// TraceOn turns on SQL statement logging for this DbMap. After this is
Expand Down Expand Up @@ -101,7 +108,7 @@ func (m *DbMap) AddTable(i interface{}, name ...string) *TableMap {
}
}

tmap := &TableMap{gotype: t, TableName: Name, dbmap: m}
tmap := &TableMap{gotype: t, TableName: Name, dbmap: m, mapper: m.mapper}
tmap.setupHooks(i)

n := t.NumField()
Expand All @@ -118,6 +125,7 @@ func (m *DbMap) AddTable(i interface{}, name ...string) *TableMap {
Transient: columnName == "-",
fieldName: f.Name,
gotype: f.Type,
table: tmap,
}
tmap.Columns = append(tmap.Columns, cm)
if cm.fieldName == "Version" {
Expand Down Expand Up @@ -159,24 +167,27 @@ func (m *DbMap) CreateTablesIfNotExists() error {
return err
}

func writeColumnSql(sql *bytes.Buffer, table *TableMap, col *ColumnMap) {
// FIXME: Why can't the column have a reference to its own table as well
func writeColumnSql(sql *bytes.Buffer, col *ColumnMap) {
if len(col.createSql) > 0 {
sql.WriteString(col.createSql)
return
}
sqltype := col.sqltype
if len(sqltype) == 0 {
sqltype = table.dbmap.Dialect.ToSqlType(col)
sqltype = col.table.dbmap.Dialect.ToSqlType(col)
}
sql.WriteString(fmt.Sprintf("%s %s", table.dbmap.Dialect.QuoteField(col.ColumnName), sqltype))
sql.WriteString(fmt.Sprintf("%s %s", col.table.dbmap.Dialect.QuoteField(col.ColumnName), sqltype))
if col.isPK {
sql.WriteString(" not null")
if len(table.Keys) == 1 {
if len(col.table.Keys) == 1 {
sql.WriteString(" primary key")
}
}
if col.Unique {
sql.WriteString(" unique")
}
if col.isAutoIncr {
sql.WriteString(" " + table.dbmap.Dialect.AutoIncrStr())
sql.WriteString(" " + col.table.dbmap.Dialect.AutoIncrStr())
}
}

Expand Down Expand Up @@ -211,7 +222,7 @@ func (m *DbMap) createTables(ifNotExists, exec bool) (map[string]string, error)
s.WriteString(sep)
}
s.WriteString(prefix)
writeColumnSql(&s, table, col)
writeColumnSql(&s, col)
x++
}
}
Expand Down
20 changes: 20 additions & 0 deletions modl_test.go
Expand Up @@ -265,6 +265,26 @@ func TestDoubleAddTable(t *testing.T) {
}
}

// test overriding the create sql
func TestColMapCreateSql(t *testing.T) {
dbmap := newDbMap()
t1 := dbmap.AddTable(TableWithNull{})
b := t1.ColMap("Bytes")
custom := "bytes text NOT NULL"
b.SetSqlCreate(custom)
var buf bytes.Buffer
writeColumnSql(&buf, b)
s := buf.String()
if s != custom {
t.Errorf("Expected custom sql `%s`, got %s", custom, s)
}
err := dbmap.CreateTables()
defer dbmap.Cleanup()
if err != nil {
t.Error(err)
}
}

// what happens if a legacy table has a null value?
func TestNullValues(t *testing.T) {
dbmap := initDbMapNulls()
Expand Down
12 changes: 12 additions & 0 deletions tablemap.go
Expand Up @@ -306,9 +306,13 @@ type ColumnMap struct {
// correct column type to map to in CreateTables()
MaxSize int

// the table this column belongs to
table *TableMap

fieldName string
gotype reflect.Type
sqltype string
createSql string
isPK bool
isAutoIncr bool
}
Expand All @@ -327,6 +331,14 @@ func (c *ColumnMap) SetUnique(b bool) *ColumnMap {
return c
}

// SetSqlCreate overrides the default create statement used when this column
// is created by CreateTable. This will override all other options (like
// SetMaxSize, SetSqlType, etc). To unset, call with the empty string.
func (c *ColumnMap) SetSqlCreate(s string) *ColumnMap {
c.createSql = s
return c
}

// SetSqlType sets an override for the column's sql type. This is a string,
// such as 'varchar(32)' or 'text', which will be used by CreateTable and
// nothing else. It is the caller's responsibility to ensure this will map
Expand Down

0 comments on commit 5d9b4fb

Please sign in to comment.