我在网络应用程序中使用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_type
或jackc/pgx
文档中找到database/sql
选项。
我发现问题如下:
strconv.ParseUint
将用户输入转换并清理为仅限正值。strconv.ParseInt
,进行乘法运算并测试结果值是否适合int8
。如果不是<{li},请回复Http.StatusBadRequest
int32
或int64
允许更大的值,并在查询失败时向客户端抛出讨厌的Http.StatusInternalServerError
但是,我真正想要的解决方案:告诉postgresql期待Uint64
并以时尚的方式处理客户端的空结果集。
答案 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
,检查输入值是否在有效范围内,并编写正确的代码。