英文:
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(
&i.ID,
&i.Owner,
&i.Balance,
&i.Currency,
&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:"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) //<-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) //<-called here
err = ctx.ShouldBindUri(&request)
if err == sql.ErrNoRows {
You should check the error immediately after the GetAccount call:
account, err := server.store.GetAccount(ctx, request.ID) //<-called here
if err == sql.ErrNoRows {
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论