dat.v1 - Postgres data access toolkit (BREAKING CHANGES)

polaris · 2015-06-14 15:18:05 · 733 次点击    
这是一个分享于 2015-06-14 15:18:05 的资源,其中的信息可能已经有所发展或是发生改变。

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 to DB to be consistent with database/sql

  • Connection is now the interface for DB and Tx. Use Connection to receive either a DB or Tx.

  • 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 and SelectDoc.HasOne renamed to Many and One for retrieving hierarchical JSON documents. BTW, SelectDoc itself can be used in Many and One 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 use DB directly.

  • Fixes to dat.NullTime to properly work with JSON timestamps from HTTP handlers and timestamptz.


评论:

enobeer:

Thanks for creating this. Any plans to support Join() in builder?

mgutz:

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);
enobeer:

The first option looks perfect, thanks! I didn't realize From() accepts join statements.

elithrar_:

Great stuff—I like the change to *runner.DB.

Out of curiosity: have you ever tested the interpolation against an SQLi fuzzer/testing tool?

mgutz:

There is now. https://github.com/mgutz/dat/blob/v1/sqlx-runner/sqli_test.go

elithrar_:

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).


入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

733 次点击  
加入收藏 微博
0 回复
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传