pgmoon

用纯 Lua (MoonScript) 编写的 PostgreSQL 客户端库

$ opm get kazz3m/pgmoon

pgmoon

!测试

> 注意! 您是否正在使用最新版本的 OpenResty? 您必须更新到 > pgmoon 1.12 或更高版本,由于 Lua 模式兼容性的更改,任何 > 返回受影响行数的查询将返回预期值。

pgmoon 是用纯 Lua (MoonScript) 编写的 PostgreSQL 客户端库。

pgmoon 最初是为在 [OpenResty][5] 中使用而设计的,以利用 [cosocket api][4] 提供异步查询,但它也可以在使用 [LuaSocket][1] 的常规 Lua 环境中工作(可选地使用 luaossl 或 [LuaCrypto][2] 进行 MD5 身份验证,以及 [LuaSec][6] 进行 SSL 连接)。 pgmoon 还可以使用 [cqueues][] 的套接字,当实例化时将 "cqueues" 作为套接字类型传递。

它是运行您的查询的完美选择,无论是在 OpenResty 的环境中还是在命令行(例如测试)中,以及在像 [Lapis][3] 这样的 Web 框架中。

安装

    $ luarocks install pgmoon

依赖项

pgmoon 支持各种环境和库,因此可能需要安装额外的依赖项,具体取决于您打算如何与数据库通信。

> 提示:如果您使用的是 OpenResty,则不需要额外的依赖项。

需要某些套接字库,具体取决于您的环境,您可以选择一个。

  • OpenResty — 使用内置套接字,因此不需要额外的依赖项。

  • LuaSocket — 适合命令行数据库访问,具有最高的平台兼容性 luarocks install luasocket

  • cqueuesluarocks install cqueues

如果您使用的是 PUC Lua 5.1 或 5.2,那么您需要一个位库(LuaJIT 不需要)。

    $ luarocks install luabitop

如果您想使用 JSON 类型,则需要 lua-cjson。

    $ luarocks install lua-cjson

如果您想使用 LuaSocket 的 SSL 连接,则需要 LuaSec:(OpenResty 和 cqueues 自带 SSL 实现)。

    $ luarocks install luasec

如果您想使用密码身份验证,则需要一个加密库。

  • OpenResty — 将使用内置函数,不需要额外的依赖项。

  • luaossl — 推荐 luarocks install luaossl

  • luacrypto — 已弃用的库,不推荐。

示例

    local pgmoon = require("pgmoon")
    local pg = pgmoon.new({
      host = "127.0.0.1",
      port = "5432",
      database = "mydb",
      user = "postgres"
    })
    
    assert(pg:connect())
    
    local res = assert(pg:query("select * from users where username = " ..
      pg:escape_literal("leafo")))

如果您使用的是 OpenResty,您应该在完成套接字后释放它,以便它可以在将来的请求中重用。

    pg:keepalive()

参考

require("pgmoon") 返回的表中的函数

new(options={})

创建一个新的 Postgres 对象。 不会自动连接。 获取选项表。 该表可以具有以下键

  • "host":要连接到的主机(默认:"127.0.0.1"

  • "port":要连接到的端口(默认:"5432"

  • "user":用于身份验证的数据库用户名(默认:"postgres"

  • "database":要连接到的数据库名称 必需

  • "password":身份验证密码,可选,具体取决于服务器配置。

  • "ssl":启用 ssl(默认:false

  • "ssl_verify":验证服务器证书(默认:nil

  • "ssl_required":如果服务器不支持 SSL 连接,则中止连接(默认:nil

  • "pool":可选,使用 OpenResty cosocket 时使用的池名称(默认为 "#{host}:#{port}:#{database}"

  • "socket_type":可选,要使用的套接字类型,可以是:"nginx""luasocket"cqueues(默认:如果在 nginx 中为 "nginx",否则为 "luasocket"

new 返回的 Postgres 对象上的方法

success, err = postgres:connect()

使用 new 调用中指定的凭据连接到 Postgres 服务器。 成功时返回 true,失败时返回 nil 和错误消息。

postgres:settimeout(time)

设置所有套接字操作(连接、写入、接收)的超时值(以毫秒为单位)。 此函数没有任何返回值。

success, err = postgres:disconnect()

关闭到服务器的套接字(如果已打开)。 在此之后,除了另一个连接调用外,不应该在对象上调用其他方法。

success, err = postgres:keepalive(...)

通过 setkeepalive 方法将套接字释放给 OpenResty 套接字池。 此处传递的任何参数也会传递给 setkeepalive

result, num_queries = postgres:query(query_string)

result, err, partial, num_queries = postgres:query(query_string)

向服务器发送查询。 失败时返回 nil 和错误消息。

成功时返回一个结果,具体取决于发送的查询类型。

SELECT 查询、带 returningINSERT 或任何其他返回结果集的查询将返回结果的数组表。 每个结果都是一个哈希表,其中键是列的名称,值是结果集中该行的结果。

    local res = pg:query("select id, name from users")

可能会返回

    {
      {
        id = 123,
        name = "Leafo"
      },
      {
        id = 234,
        name = "Lee"
      }
    }

任何影响行数的查询,如 UPDATEDELETEINSERT,都将返回一个结果表,其中 affected_rows 字段设置为受影响的行数。

    local res = pg:query("delete from users")

可能会返回

    {
      affected_rows = 2
    }

任何没有结果集或更新行的查询都将返回 true

此方法还支持通过 ; 分隔发送多个查询。 执行的查询数作为结果对象之后的第二个返回值返回。 当执行多个查询时,结果对象会略微改变。 它成为一个数组表,包含所有单个结果。

    local res, num_queries = pg:query([[
      select id, name from users;
      select id, title from posts
    ]])

可能会返回

    num_queries = 2
    
    res = {
      {
        {
          id = 123,
          name = "Leafo"
        },
        {
          id = 234,
          name = "Lee"
        }
      },
      {
        {
          id = 546,
          title = "My first post"
        }
      }
    }

类似地,对于返回受影响行数或仅返回 true 的查询,当有多个这样的查询时,它们将被包装在额外的数组表中。 您也可以根据需要混合使用不同的查询类型。

因为 Postgres 每次执行一个查询,所以前面的查询可能成功,而后面的查询可能失败。 如果多个查询失败,则部分结果和执行的部分查询数将在错误消息之后返回。

escaped = postgres:escape_literal(val)

转义 Lua 值,以便将其用作 Postgres 值,并将其插入查询字符串中。 当将用户提供的數據发送到查询中时,您应该使用此方法来防止 SQL 注入攻击。

escaped = postgres:escape_identifier(val)

转义 Lua 值,以便将其用作 Postgres 标识符。 这包括表格或列名。 这不包括普通值,您应该为此使用 escape_literal。 当名称与内置语言关键字冲突时,需要标识符转义。

str = tostring(postgres)

返回 Postgres 对象当前状态的字符串表示形式。

SSL 连接

pgmoon 可以建立到 Postgres 服务器的 SSL 连接。 如果服务器不支持 SSL,它也可以拒绝连接到它。 正如 pgmoon 依赖 LuaSocket 在 OpenResty 之外使用一样,它也依赖 LuaSec 在此类上下文中进行 SSL 连接。

    local pgmoon = require("pgmoon")
    local pg = pgmoon.new({
      host = "127.0.0.1",
      ssl = true, -- enable SSL
      ssl_verify = true, -- verify server certificate
      ssl_required = true, -- abort if the server does not support SSL connections
      ssl_version = "tlsv1_2", -- e.g., defaults to highest available, no less than TLS v1.1 (LuaSec only)
      cafile = "...", -- certificate authority (LuaSec only)
      cert = "...", -- client certificate (LuaSec only)
      key = "...", -- client key (LuaSec only)
    })
    
    assert(pg:connect())

> 注意:在 Postgres 12 及更高版本中,客户端 > 连接接受的最小 SSL 版本为 1.2。 当使用 LuaSec 连接到 SSL 服务器时,如果您 > 没有指定 ssl_version,则使用 tlsv1_2

在 OpenResty 中,确保配置 [lua_ssl_trusted_certificate][7] 指令,如果您希望验证服务器证书,因为 LuaSec 仅有的选项在这种情况下变得无关紧要。

身份验证类型

Postgres 有一些身份验证类型。 pgmoon 目前支持信任和 MD5 身份验证。

类型转换

Postgres 具有非常丰富的内置类型。 pgmoon 将尽力将任何 Postgres 类型转换为适当的 Lua 类型。

所有整数、浮点数和数字类型都转换为 Lua 的数字类型。 布尔类型转换为 Lua 布尔值。 JSON 类型使用 Lua CJSON 解码为 Lua 表。 Lua 表可以像下面描述的那样编码为 JSON。

任何数组类型都自动转换为 Lua 数组表。 如果您需要将 Lua 数组编码为 Postgres 的数组语法,则可以使用 pgmoon.arrays 模块。 请参见下文。

任何其他类型都将作为 Lua 字符串返回。

处理数组

从查询返回时,数组会自动解码。 数字、字符串和布尔类型会自动加载。 还支持嵌套数组。

使用 encode_array 将 Lua 表编码为查询的数组语法。

    local pgmoon = require("pgmoon")
    local pg = pgmoon.new(auth)
    pg:connect()
    
    local encode_array = require("pgmoon.arrays").encode_array
    local my_array = {1,2,3,4,5}
    pg:query("insert into some_table (some_arr_col) values(" .. encode_array(my_array) .. ")")

处理 JSON

从查询返回时,jsonjsonb 类型会自动解码。

使用 encode_json 将 Lua 表编码为查询的 JSON 语法。

    local pgmoon = require("pgmoon")
    local pg = pgmoon.new(auth)
    pg:connect()
    
    local encode_json = require("pgmoon.json").encode_json
    local my_tbl = {hello = "world"}
    pg:query("insert into some_table (some_json_col) values(" .. encode_json(my_tbl) .. ")")

处理 hstore

因为 hstore 是一个扩展类型,所以需要一个查询来找出类型 ID,然后 pgmoon 才能自动对其进行解码。 连接后,在您的连接对象上调用 setup_hstore 方法来进行设置。

    local pgmoon = require("pgmoon")
    local pg = pgmoon.new(auth)
    pg:connect()
    pg:setup_hstore()

使用 encode_hstore 将 Lua 表编码为 hstore 语法,以便在更新和插入时使用。

    local encode_hstore = require("pgmoon.hstore").encode_hstore
    local tbl = {foo = "bar"}
    pg:query("insert into some_table (hstore_col) values(" .. encode_hstore(tbl) .. ")")

您可以使用 decode_hstore 函数手动从字符串解码 hstore 值。 只有在您没有调用 setup_hstore 时才需要这样做。

    local decode_hstore = require("pgmoon.hstore").decode_hstore
    local res = pg:query("select * from some_table")
    local hstore_tbl = decode_hstore(res[1].hstore_col)

转换 NULL

默认情况下,Postgres 中的 NULL 会转换为 nil,这意味着它们在结果表中不可见。 如果您想将 NULL 转换为某个可见值,请将 Postgres 对象上的 convert_null 设置为 true

    local pgmoon = require("pgmoon")
    local pg = pgmoon.new(auth)
    pg:connect()
    
    pg.convert_null = true
    local res = pg:query("select NULL the_null")
    
    assert(pg.NULL == res[1].the_null)

如上所示,NULL 值设置为 pg.NULL。 您可以更改此值,使 pgmoon 使用其他内容作为 NULL。 例如,如果您使用的是 OpenResty,您可能希望重用 ngx.null

联系

作者:Leaf Corcoran (leafo) (@moonscript) 电子邮件:leafot@gmail.com 主页:<http://leafo.net>

变更日志

  • 1.12.0 — 2021-01-06 - Lua 模式兼容性修复,支持 Lua 5.1 到 5.4 (@jprjr)。 修复了 SSL 版本未传递的错误。 使用 LuaSec 时默认使用 TLS v1.2。 Luabitop 不再作为依赖项自动安装。 新的测试套件。

  • 1.11.0 — 2020-03-26 - 允许在使用 LuaSec 时使用 TLS v1.2(Miles Elam)

  • 1.10.0 — 2019-04-15 - 支持 luaossl 用于加密函数,添加了缺少加密库时更好的错误。

  • 1.9.0 — 2018-04-02 - nginx 池名称包含用户,连接报告名称为 pgmoon

  • 1.8.0 — 2016-11-07 — 添加 cqueues 支持,修复了 Nginx cosocket 的 SSL 调用 (@thibaultCha)

  • 1.7.0 — 2016-09-21 — 添加到 opm,添加对 openresty 池的支持,更好的默认池,支持 hstore (@edan)

  • 1.6.0 — 2016-07-21 — 添加对 json 和 jsonb 数组解码的支持

  • 1.5.0 — 2016-07-12 — 添加 SSL 支持 (@thibaultCha),添加 UUID 数组类型 (@edan),添加对通知的支持 (@starius)

  • 1.4.0 — 2016-02-18 — 添加对解码 jsonb 的支持,添加一个 json 序列化器 (@thibaultCha)

  • 1.3.0 — 2016-02-11 — 修复了解析看起来像数字的字符串失败的错误,添加了在 init 上下文中在 ngx 中使用时的支持 (@thibaultCha),添加了明文密码身份验证,修复了 md5 身份验证的警告。

  • 1.2.0 — 2015-07-10 — 添加对 PostgreSQL 数组的支持

  • 1.1.1 — 2014-08-12 — 修复了 md5 身份验证的错误

  • 1.1.0 — 2014-05-21 — 添加对在一个调用中进行多个查询的支持

  • 1.0.0 — 2014-05-19 — 初始发布

许可证 (MIT)

版权所有 (C) 2021 by Leaf Corcoran

特此授予任何取得本软件及相关文档文件(“软件”)副本的人,不受限制地处理软件的权利,包括但不限于使用、复制、修改、合并、发布、分发、再许可和/或销售软件副本的权利,以及允许获得软件的人员这样做,但须符合以下条件:

以上版权声明和此许可声明应包含在软件的所有副本或实质部分中。

该软件按“原样”提供,不附带任何形式的明示或暗示的担保,包括但不限于适销性、特定用途适用性和非侵权担保。在任何情况下,作者或版权持有者均不对因使用或与软件有关的任何索赔、损害或其他责任(无论是在合同、侵权行为或其他方面)负责。

[1]: http://w3.impa.br/~diego/software/luasocket/ [2]: http://mkottman.github.io/luacrypto/ [3]: http://leafo.net/lapis [4]: http://wiki.nginx.org/HttpLuaModule#ngx.socket.tcp [5]: https://openresty.org.cn/ [6]: https://github.com/brunoos/luasec [7]: https://github.com/openresty/lua-nginx-module#lua_ssl_trusted_certificate [cqueues]: http://25thandclement.com/~william/projects/cqueues.html

作者

Leaf Corcoran (leafo)

许可证

mit

版本

  • kazz3m/pgmoon 1.12.0 作者: kazz3m
    用纯 Lua (MoonScript) 编写的 PostgreSQL 客户端库 2021-06-11 02:38:14