如何使用pgx控制准备好的SQL语句中的参数类型?

时间:2018-04-19 11:32:10

标签: postgresql go

我在网络应用程序中使用jackc/pgx进行postgresql-10连接。准备语句语法与database/sql标准库略有不同,但问题仍然相同。

准备好的陈述和执行:

_, err := conn.Prepare("listContacts", `
    select id, name, phonenumber, email from contacts
        order by name
        limit $1
        offset $2
`)
....
//ParseUint caches invalid negative input, returns uint64
page, err := strconv.ParseUint(r.FormValue("page"), 10, 8)
if err != nil {
    http.Error(w, "Invalid argument", http.StatusBadRequest)
    return
}
limit := 27
offset := (page - 1) * l //Forgot parentheses here, caused Error
rows, err := pool.Query("listContacts", limit, offset)
if err != nil {
    http.Error(w, "Internal server error", http.StatusInternalServerError)
    return
}
....

此参数应该显示为整数类型。但是,由于错误,我的代码将 offset 计算为一个巨大的值。这导致查询错误:18446744073709551591 is greater than maximum value for Int8。我纠正了原来的错误。

然而,它确实让我想知道......为什么选择Int8?以及如何控制这个决定?根据{{​​3}}准备好的语句,可以在参数中设置:

  

...可以选择指定相应的参数数据类型列表。如果未指定参数的数据类型或将其声明为未知,则从使用该参数的上下文推断该类型(如果可能)....

由于表格没有太多条目,我猜测 postgresql选择Int8

  

DATA_TYPE

     

预准备语句的参数的数据类型。如果未指定特定参数的数据类型或将其指定为未知,则将从使用该参数的上下文中推断出该数据类型。要引用预准备语句本身中的参数,请使用$ 1,$ 2等

我无法在data_typejackc/pgx文档中找到database/sql选项。

我发现问题如下:

  • 我使用strconv.ParseUint将用户输入转换并清理为仅限正值。
  • 我可以修改代码以使用strconv.ParseInt,进行乘法运算并测试结果值是否适合int8。如果不是<{li},请回复Http.StatusBadRequest
  • 如果数据库将在生产中增长,我将不得不更新我的代码!?
  • 或者在int32int64允许更大的值,并在查询失败时向客户端抛出讨厌的Http.StatusInternalServerError

但是,我真正想要的解决方案:告诉postgresql期待Uint64并以时尚的方式处理客户端的空结果集。

1 个答案:

答案 0 :(得分:1)

  

为什么选择Int8?

     

错误:18446744073709551591大于Int8的最大值

PostgreSQL尝试查找足够大的整数类型来表示常量值18446744073709551591.PostgreSQL的最大整数类型是int8(8字节或64位)或bigint,它有一个最大值9223372036854775807.错误消息18446744073709551591大于9223372036854775807,这是正确的。

参考:Chapter 8. Data Types, PostgreSQL 10

Name    Aliases     Description
bigint  int8        signed eight-byte integer
  

我使用strconv.ParseUint将用户输入转换并清理为a   只有正值。

这是一个坏主意。使用strconv.ParseInt,检查输入值是否在有效范围内,并编写正确的代码。