diff --git a/.travis.yml b/.travis.yml index d9e0e34b..3fa139d6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,7 +3,7 @@ go: - 1.1 - tip -servies: +services: - mysql - postgres - sqlite3 diff --git a/README.md b/README.md index 4e63eca8..e7bb424b 100644 --- a/README.md +++ b/README.md @@ -627,6 +627,18 @@ locally to test the library. gorp uses reflection to construct SQL queries and bind parameters. See the BenchmarkNativeCrud vs BenchmarkGorpCrud in gorp_test.go for a simple perf test. On my MacBook Pro gorp is about 2-3% slower than hand written SQL. +## Pull requests / Contributions + +Contributions are very welcome. Please follow these guidelines: + +* Fork the `develop` branch and issue pull requests targeting the `develop` branch + * If you don't do this, I'll likely cherry pick your commit into develop +* If you are adding an enhancement, please open an issue first with your proposed change. +* Changes that break backwards compatibility in the public API are only accepted after we + discuss on a GitHub issue for a while. + +Thanks! + ## Contributors * matthias-margush - column aliasing via tags diff --git a/dialect.go b/dialect.go index 74c914ca..6b6ef0e8 100644 --- a/dialect.go +++ b/dialect.go @@ -75,7 +75,7 @@ func (d SqliteDialect) ToSqlType(val reflect.Type, maxsize int, isAutoIncr bool) return d.ToSqlType(val.Elem(), maxsize, isAutoIncr) case reflect.Bool: return "integer" - case reflect.Int, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint16, reflect.Uint32, reflect.Uint64: + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: return "integer" case reflect.Float64, reflect.Float32: return "real" @@ -86,14 +86,12 @@ func (d SqliteDialect) ToSqlType(val reflect.Type, maxsize int, isAutoIncr bool) } switch val.Name() { - case "NullableInt64": + case "NullInt64": return "integer" - case "NullableFloat64": + case "NullFloat64": return "real" - case "NullableBool": + case "NullBool": return "integer" - case "NullableBytes": - return "blob" case "Time": return "datetime" } @@ -161,7 +159,7 @@ func (d PostgresDialect) ToSqlType(val reflect.Type, maxsize int, isAutoIncr boo return d.ToSqlType(val.Elem(), maxsize, isAutoIncr) case reflect.Bool: return "boolean" - case reflect.Int, reflect.Int16, reflect.Int32, reflect.Uint16, reflect.Uint32: + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Uint8, reflect.Uint16, reflect.Uint32: if isAutoIncr { return "serial" } @@ -171,7 +169,9 @@ func (d PostgresDialect) ToSqlType(val reflect.Type, maxsize int, isAutoIncr boo return "bigserial" } return "bigint" - case reflect.Float64, reflect.Float32: + case reflect.Float64: + return "double precision" + case reflect.Float32: return "real" case reflect.Slice: if val.Elem().Kind() == reflect.Uint8 { @@ -180,15 +180,13 @@ func (d PostgresDialect) ToSqlType(val reflect.Type, maxsize int, isAutoIncr boo } switch val.Name() { - case "NullableInt64": + case "NullInt64": return "bigint" - case "NullableFloat64": - return "double" - case "NullableBool": - return "smallint" - case "NullableBytes": - return "bytea" - case "Time", "NullTime": + case "NullFloat64": + return "double precision" + case "NullBool": + return "boolean" + case "Time": return "timestamp with time zone" } @@ -248,7 +246,7 @@ func (d PostgresDialect) QuoteField(f string) string { } func (d PostgresDialect) QuotedTableForQuery(schema string, table string) string { - if (strings.TrimSpace(schema) == "") { + if strings.TrimSpace(schema) == "" { return d.QuoteField(table) } @@ -275,10 +273,22 @@ func (m MySQLDialect) ToSqlType(val reflect.Type, maxsize int, isAutoIncr bool) return m.ToSqlType(val.Elem(), maxsize, isAutoIncr) case reflect.Bool: return "boolean" - case reflect.Int, reflect.Int16, reflect.Int32, reflect.Uint16, reflect.Uint32: + case reflect.Int8: + return "tinyint" + case reflect.Uint8: + return "tinyint unsigned" + case reflect.Int16: + return "smallint" + case reflect.Uint16: + return "smallint unsigned" + case reflect.Int, reflect.Int32: return "int" - case reflect.Int64, reflect.Uint64: + case reflect.Uint, reflect.Uint32: + return "int unsigned" + case reflect.Int64: return "bigint" + case reflect.Uint64: + return "bigint unsigned" case reflect.Float64, reflect.Float32: return "double" case reflect.Slice: @@ -288,14 +298,12 @@ func (m MySQLDialect) ToSqlType(val reflect.Type, maxsize int, isAutoIncr bool) } switch val.Name() { - case "NullableInt64": + case "NullInt64": return "bigint" - case "NullableFloat64": + case "NullFloat64": return "double" - case "NullableBool": + case "NullBool": return "tinyint" - case "NullableBytes": - return "mediumblob" case "Time": return "datetime" } diff --git a/gorp.go b/gorp.go index 02c33444..5ba0ba37 100644 --- a/gorp.go +++ b/gorp.go @@ -978,14 +978,9 @@ func (m *DbMap) Select(i interface{}, query string, args ...interface{}) ([]inte } // Exec runs an arbitrary SQL statement. args represent the bind parameters. -// This is equivalent to running: Prepare(), Exec() using database/sql +// This is equivalent to running: Exec() using database/sql func (m *DbMap) Exec(query string, args ...interface{}) (sql.Result, error) { - m.trace(query, args) - //stmt, err := m.Db.Prepare(query) - //if err != nil { - // return nil, err - //} - //fmt.Println("Exec", query, args) + m.trace(query, args...) return m.Db.Exec(query, args...) } @@ -1037,7 +1032,7 @@ func (m *DbMap) Begin() (*Transaction, error) { func (m *DbMap) tableFor(t reflect.Type, checkPK bool) (*TableMap, error) { table := tableOrNil(m, t) if table == nil { - panic(fmt.Sprintf("No table found for type: %v", t.Name())) + return nil, errors.New(fmt.Sprintf("No table found for type: %v", t.Name())) } if checkPK && len(table.keys) < 1 { @@ -1077,12 +1072,12 @@ func (m *DbMap) tableForPointer(ptr interface{}, checkPK bool) (*TableMap, refle } func (m *DbMap) queryRow(query string, args ...interface{}) *sql.Row { - m.trace(query, args) + m.trace(query, args...) return m.Db.QueryRow(query, args...) } func (m *DbMap) query(query string, args ...interface{}) (*sql.Rows, error) { - m.trace(query, args) + m.trace(query, args...) return m.Db.Query(query, args...) } @@ -1121,13 +1116,8 @@ func (t *Transaction) Select(i interface{}, query string, args ...interface{}) ( // Exec has the same behavior as DbMap.Exec(), but runs in a transaction. func (t *Transaction) Exec(query string, args ...interface{}) (sql.Result, error) { - t.dbmap.trace(query, args) - stmt, err := t.tx.Prepare(query) - if err != nil { - return nil, err - } - defer stmt.Close() - return stmt.Exec(args...) + t.dbmap.trace(query, args...) + return t.tx.Exec(query, args...) } // SelectInt is a convenience wrapper around the gorp.SelectInt function. @@ -1218,12 +1208,12 @@ func (t *Transaction) ReleaseSavepoint(savepoint string) error { } func (t *Transaction) queryRow(query string, args ...interface{}) *sql.Row { - t.dbmap.trace(query, args) + t.dbmap.trace(query, args...) return t.tx.QueryRow(query, args...) } func (t *Transaction) query(query string, args ...interface{}) (*sql.Rows, error) { - t.dbmap.trace(query, args) + t.dbmap.trace(query, args...) return t.tx.Query(query, args...) }