dat is moving towards API stability. Unfortunately there are breaking changes (for the good) to be more consistent with database/sql and sqlx.
Changes from legacy to v1
Original dat moved to legacy branch.
Move to gopkg.in for API stability.
Legacy
Connection
renamed toDB
to be consistent withdatabase/sql
Connection
is now the interface forDB
andTx
. UseConnection
to receive either aDB
orTx
.Support for nested transactions. Needs user testing and feedback.
In a nested transaction only the top-most commit commits to the database if it has not been rollbacked. Any rollback in nested function results in entire transaction being rollbacked and leaves the transaction in
tx.IsRollbacked()
state.
``` go
func nested(conn runner.Connection) error {
tx, err := conn.Begin()
if err != nil {
return err
}
defer tx.AutoRollback()
_, err := tx.SQL('...').Exec()
if err != nil {
return err
}
return tx.Commit()
}
func fromDB() error {
return nested(DB)
}
func fromTx() error {
tx, err := DB.Begin()
if err != nil {
return err
}
defer tx.AutoRollback()
err := nested(tx)
if err ! = nil {
return logger.Error("Failed in nested", err)
}
// if Rollback was called, Commit returns an error
return tx.Commit()
}
```
-
SelectDoc.HasMany
andSelectDoc.HasOne
renamed toMany
andOne
for retrieving hierarchical JSON documents. BTW,SelectDoc
itself can be used inMany
andOne
to build N-deep hierarchies.
```go
DB.SelectDoc("id", "user_name", "avatar").
Many("recent_comments", `SELECT id, title FROM comments WHERE id = users.id LIMIT 10`).
Many("recent_posts", `SELECT id, title FROM posts WHERE author_id = users.id LIMIT 10`).
One("account", `SELECT balance FROM accounts WHERE user_id = users.id`).
From("users").
Where("id = $1", 4).
QueryStruct(&obj) // obj must be agreeable with json.Unmarshal()
```
Session obsoleted. Go's db library does not support transaction-less sessions. Use
Tx
if you need a session, otherwise useDB
directly.Fixes to dat.NullTime to properly work with JSON timestamps from HTTP handlers and
timestamptz
.
评论:
enobeer:
mgutz:Thanks for creating this. Any plans to support Join() in builder?
enobeer:I don't plan to add a Join method. The first option is
DB.Select('*'). From(` users u INNER JOIN account acc on (acc.user_id = u.id) `). Where("acc.balance > $1", amount). QueryStruct(&users)
There are also scopes
brokeUsers := ` INNER JOIN account acc on (acc.user_id = u.user_id) WHERE acc.balance < 1 ` richUsers := ` INNER JOIN account acc on (acc.user_id = u.user_id) WHERE acc.balance > 1000000 ` err := DB.Select("*").From("users u").Scope(brokeUsers).QueryStruct(&users);
elithrar_:The first option looks perfect, thanks! I didn't realize From() accepts join statements.
mgutz:Great stuff—I like the change to
*runner.DB
.Out of curiosity: have you ever tested the interpolation against an SQLi fuzzer/testing tool?
elithrar_:There is now. https://github.com/mgutz/dat/blob/v1/sqlx-runner/sqli_test.go
Appreciated—just saw the commit come in via an IFTTT email (dat is on my "tell me when it's updated" list).
I've been a big fan of sqlx but dat's RTT performance + API (syntax) have been drawing me over. Current project is using Amazon RDS so avoiding 2+ 20ms round trips per query is a Big Deal (tm).
