交易后返回由CockroachDB创建的行ID

时间:2019-05-15 01:51:45

标签: go cockroachdb

执行了创建一行的cockroachDB事务后,我想将该ID返回给我的应用程序。

我当前正在使用database/sql golang包定义交易。然后,我使用crdb客户端对CockroachDB执行事务。

除了与crdb事务本身有关的错误之外,我无法从crdb事务返回任何内容。如果界面无法提供返回新行ID的方式,人们如何检索他们最近创建的行?

我有一些执行两次插入的事务。我得到了这些插入的结果ID,并返回了包含这两个ID值的响应。

func myTransaction(ctx context.Context, tx *sql.Tx) (MyTxnResponse, error) {
  var aResult string
  if err := tx.QueryRowContext(ctx, `INSERT INTO foo (a,b,c) VALUES (1,2,3) RETURNING foo_id`).Scan(&aResult); err != nil { ... }

  var bResult string
  if err := tx.QueryRowContext(ctx, `INSERT INTO bar (d,e,f) VALUES (4,5,6) RETURNING bar_id`).Scan(&bResult); err != nil { ... }

  return MyTxnResponse{A: aResult, B: bResult}
}

现在,我想针对CRDB执行事务

var responseStruct MyTxnResponse
err := crdb.ExecuteTx(ctx.Background(), db, nil, func(tx *sql.Tx) error {
    res, err := myTransaction(ctx,tx)

    // This is what I am currently doing... it seems bad
    responseStruct.A = res.A
    responseStruct.B = res.B

    return err
}
... use responseStruct for something

我可以通过使用此外部var解决方案并仅更改其关闭状态来获得事务的结果,但这似乎是一个非常糟糕的模式。如果我保持这种模式,我肯定会丢失一些会炸掉我脸上的东西。

是否存在从交易中退还东西的标准方法?

1 个答案:

答案 0 :(得分:1)

您有个正确的主意:在事务外部声明变量,然后在事务闭包内部分配变量。这是从像这样的闭包中“返回” Go中事物的惯用方式,因为唯一的选择是让函数返回interface{},这需要运行时强制转换才能有用。

此处有几个快捷方式:由于responseStructres是同一类型,因此您无需列出所有字段。您可以简单地说responseStruct = res

您甚至可以将myTransaction的结果直接分配给responseStruct,而完全避免使用临时res。但是,您在这里必须小心变量范围-不能使用:=,因为那样会在闭包内部创建新的responseStruct。相反,您必须声明所有 other 变量(此处为err),以便可以使用普通的=赋值:

var responseStruct MyTxnResponse
err := crdb.ExecuteTx(context.Background(), db, nil, func(tx *sql.Tx) error {
    var err error
    responseStruct, err = myTransaction(ctx, tx)
    return err
})
// use responseStruct (but only if err is nil)