sql.Scan在应该返回ErrNoRows错误时没有返回

huangapple go评论79阅读模式
英文:

sql.Scan not returning ErrNoRows error when it should

问题

我有一个由sqlc生成的GetAccount函数。

当我调用GetAccount(/*未使用的id*/)时,应该返回一个ErrNoRows错误。但是我没有得到任何错误,而是返回了一个具有默认值(零和空字符串)的Account。

GetAccount的实现如下:

const getAccount = `-- name: GetAccount :one
SELECT id, owner, balance, currency, created_at
FROM accounts
WHERE id = $1
`

func (q *Queries) GetAccount(ctx context.Context, id int64) (Account, error) {
    row := q.db.QueryRowContext(ctx, getAccount, id)
    var i Account
    err := row.Scan(
      &i.ID,
      &i.Owner,
      &i.Balance,
      &i.Currency,
      &i.CreatedAt,
    )
    return i, err
}

为什么在没有返回行时我没有得到任何错误?

编辑:

根据要求,这是我调用GetAccount的方式。它是一个Gin请求处理程序。

type getAccountRequest struct {
    ID int64 `uri:"id" binding:"required,min=1"`
}

func (server *Server) getAccount(ctx *gin.Context) {
    var request getAccountRequest
    err := ctx.ShouldBindUri(&request)
    if err != nil {
        ctx.JSON(http.StatusBadRequest, errorResponse(err))
        return
    }

    account, err := server.store.GetAccount(ctx, request.ID) //<-在这里调用
    if err == sql.ErrNoRows {
        ctx.JSON(http.StatusNotFound, errorResponse(err))
        return
    } else if err != nil {
        ctx.JSON(http.StatusInternalServerError, errorResponse(err))
        return
    }
    ctx.JSON(http.StatusOK, account)
}

编辑2:

为了明确起见,当我说

应该返回一个ErrNoRows错误

我之所以这样说是因为调用row.Scan应该产生错误。

文档:

func (r *Row) Scan(dest ...any) error

Scan将匹配的行的列复制到dest指向的值中。有关详细信息,请参阅Rows.Scan的文档。如果有多行与查询匹配,Scan将使用第一行并丢弃其余行。如果查询没有匹配的行,则Scan返回ErrNoRows。

英文:

I have a function GetAccount which is generated by sqlc.

When I call GetAccount(/*unused id*/), An ErrNoRows error should be returned. Instead I am getting no error and an Account with default values (zeros and empty strings) returned.

GetAccount implementation:

const getAccount = `-- name: GetAccount :one
SELECT id, owner, balance, currency, created_at
FROM accounts
WHERE id = $1
`

func (q *Queries) GetAccount(ctx context.Context, id int64) (Account, error) {
    row := q.db.QueryRowContext(ctx, getAccount, id)
    var i Account
    err := row.Scan(
      &amp;i.ID,
      &amp;i.Owner,
      &amp;i.Balance,
      &amp;i.Currency,
      &amp;i.CreatedAt,
    )
    return i, err
}

Why I am not getting any error when there are no rows to return?

Edit:

As requested, here is how I am calling GetAccount. It is a Gin request handler.

type getAccountRequest struct {
	ID int64 `uri:&quot;id&quot; binding:&quot;required,min=1&quot;`
}

func (server *Server) getAccount(ctx *gin.Context) {
	var request getAccountRequest
	err := ctx.ShouldBindUri(&amp;request)
	if err != nil {
		ctx.JSON(http.StatusBadRequest, errorResponse(err))
		return
	}

	account, err := server.store.GetAccount(ctx, request.ID) //&lt;-called here
	if err == sql.ErrNoRows {
		ctx.JSON(http.StatusNotFound, errorResponse(err))
		return
	} else if err != nil {
		ctx.JSON(http.StatusInternalServerError, errorResponse(err))
		return
	}
	ctx.JSON(http.StatusOK, account)
}

Edit 2:

For clarity, when I say

> An ErrNoRows error should be returned

I state this because of the call to row.Scan which should produce the error.

Documentation:

> func (r *Row) Scan(dest ...any) error
>
>Scan copies the columns from the matched row into the values pointed at by dest. See the documentation on Rows.Scan for details. If more than one row matches the query, Scan uses the first row and discards the rest. If no row matches the query, Scan returns ErrNoRows.

答案1

得分: 1

你正在覆盖 SQL 错误:

    account, err := server.store.GetAccount(ctx, request.ID) // <- 在这里调用
    err = ctx.ShouldBindUri(&request)
    if err == sql.ErrNoRows {

你应该在调用 GetAccount 后立即检查错误:

    account, err := server.store.GetAccount(ctx, request.ID) // <- 在这里调用
    if err == sql.ErrNoRows {
英文:

You are overwriting the sql error:

    account, err := server.store.GetAccount(ctx, request.ID) //&lt;-called here
    err = ctx.ShouldBindUri(&amp;request)
    if err == sql.ErrNoRows {

You should check the error immediately after the GetAccount call:

    account, err := server.store.GetAccount(ctx, request.ID) //&lt;-called here
    if err == sql.ErrNoRows {

huangapple
  • 本文由 发表于 2022年10月3日 09:15:09
  • 转载请务必保留本文链接:https://go.coder-hub.com/73930353.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定