首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >SQL跳过select的第一个值

SQL跳过select的第一个值
EN

Stack Overflow用户
提问于 2021-01-01 20:43:11
回答 1查看 161关注 0票数 0

我不确定为什么我的代码省略了select语句接收到的第一行。代码是:

代码语言:javascript
复制
func (s *sqlserver) FindAllProducts() (products []*Product, err error) {
    ctx, cancel := getContext()
    defer cancel()

    rows, err := s.QueryContext(ctx,
        "select productid, productname, pricecents, brandname from products")
    if err != nil {
        return
    }   
    defer rows.Close()
    
    for rows.Next() {
        product := new(Product)
        err = rows.Scan(
            &product.ProductID,
            &product.ProductName,
            &product.PriceCents,
            &product.BrandName,
            )
        if err != nil {
            return
        }
        products = append(products, product)
    }
    return
}

还有一个单元测试,它使用go-sqlmock来提供测试代码库:

代码语言:javascript
复制
func TestProduct(t *testing.T) {
    db, mock, err := sqlmock.New()
    if err != nil {
        require.NoError(t, err)
    }
    s := sqlserver{db}
    defer s.Close()

    product1 := &Product{
        1,
        "soda",
        100,
        "prites",
    }
    product2 := &Product{
        60,
        "slurpee",
        400,
        "koce",
    }
    product3 := &Product{
        21,
        "borg",
        210,
        "ham",
    }

    query := "^insert into *"
    mock.ExpectExec(query).
        WithArgs(product1.ProductID, product1.ProductName, product1.PriceCents, product1.BrandName).
        WillReturnResult(sqlmock.NewResult(0, 1))

    query = "^insert into *"
    mock.ExpectExec(query).
        WithArgs(product2.ProductID, product2.ProductName, product2.PriceCents, product2.BrandName).
        WillReturnResult(sqlmock.NewResult(1, 1))

    query = "^insert into *"
    mock.ExpectExec(query).
        WithArgs(product3.ProductID, product3.ProductName, product3.PriceCents, product3.BrandName).
        WillReturnResult(sqlmock.NewResult(2, 1))

    query = "^select .+ from *"
    rows := sqlmock.NewRows([]string{"productid", "productname", "pricecents", "brandname"}).
        AddRow(product1.ProductID, product1.ProductName, product1.PriceCents, product1.BrandName)
    mock.ExpectQuery(query).
        WithArgs(product1.ProductID).
        WillReturnRows(rows)

    query = "^select .+ from *"
    rows.AddRow(product2.ProductID, product2.ProductName, product2.PriceCents, product2.BrandName)
    rows.AddRow(product3.ProductID, product3.ProductName, product3.PriceCents, product3.BrandName)
    mock.ExpectQuery(query).
        WillReturnRows(rows)

    err = s.InsertProduct(product1)
    assert.NoError(t, err)

    err = s.InsertProduct(product2)
    assert.NoError(t, err)

    err = s.InsertProduct(product3)
    assert.NoError(t, err)

    product, err := s.FindProductFromID(product1.ProductID)
    assert.NoError(t, err)
    assert.Equal(t, product1, product)

    products, err := s.FindAllProducts()
    assert.NoError(t, err)
    assert.Len(t, products, 3)
    assert.Equal(t, *product1, *products[0])
    assert.Equal(t, *product2, *products[1])
    assert.Equal(t, *product3, *products[2])

    err = mock.ExpectationsWereMet()
    assert.NoError(t, err)
}

将产品插入到表中可以很好地工作,但是当我尝试使用s.FindAllProducts检索产品时,返回的产品中总是缺少第一个产品(导致assert.Len(t, products, 3)失败)。任何帮助都非常感谢!

编辑:关于在将值扫描到产品中之前调用rows.Next(),这是文档所说的操作,因为指针应该在第一行之前开始一个索引。但是,我已经调试了代码,问题似乎是指针从前面的一个位置开始(指向第一行),然后调用rows.Next()将它移到下一行。我曾尝试在初始化产品后移动此语句,但代码随后抛出错误:Received unexpected error: sql: Scan called without calling Next

编辑2:这似乎是go-sqlmock的一个直接问题,因为在一个真实的SQL数据库上测试之后,数据库正确地返回了所有3行。

EN

回答 1

Stack Overflow用户

发布于 2021-01-02 08:08:21

发现了错误,因为由于某些原因,行是一个指针,go-sqlmock会修改行集,导致其中的原始行被删除,并且每次调用WillReturnRows时都需要重置。代码的以下部分:

代码语言:javascript
复制
    query = "^select .+ from *"
    rows.AddRow(product2.ProductID, product2.ProductName, product2.PriceCents, product2.BrandName)
    rows.AddRow(product3.ProductID, product3.ProductName, product3.PriceCents, product3.BrandName)
    mock.ExpectQuery(query).
        WillReturnRows(rows)

应该修改为添加回原始行,如下所示:

代码语言:javascript
复制
    query = "^select .+ from *"
    rows = sqlmock.NewRows([]string{"productid", "productname", "pricecents", "brandname"})
    rows.AddRow(product1.ProductID, product1.ProductName, product1.PriceCents, product2.BrandName)
    rows.AddRow(product2.ProductID, product2.ProductName, product2.PriceCents, product2.BrandName)
    rows.AddRow(product3.ProductID, product3.ProductName, product3.PriceCents, product3.BrandName)
    mock.ExpectQuery(query).
        WillReturnRows(rows)

现在测试通过了!

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65529768

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档