当前位置: 首页 > 知识库问答 >
问题:

pgx库中命名的prepared语句,它是如何工作的?

计阳泽
2023-03-14

在Go标准sql库中,*Stmt类型的方法定义如下:

func (s *Stmt) Exec(args ...interface{}) (Result, error)
func (s *Stmt) Query(args ...interface{}) (*Rows, error)

新的(未命名的)语句由以下人员编写:

func (db *DB) Prepare(query string) (*Stmt, error)
  1. 连接池是抽象的,不能直接访问
  2. 在单个连接上准备事务
  3. 如果在Station执行时连接不可用,将在新连接上重新准备连接

PreparedStatement类型未定义任何方法。新命名的prepared语句由以下人员编写:

func (p *ConnPool) Prepare(name, sql string) (*PreparedStatement, error)
  1. 操作直接在连接池上
  2. 在池的所有连接上准备事务
  3. 没有明确的方法如何执行准备好的语句

在Github的评论中,作者更好地解释了pgx和数据库/sql之间的架构差异。留档上的准备也指出(强调我的):

Prepare是幂等的;i、 使用相同的名称和sql参数多次调用Prepare是安全的。这允许代码路径准备和查询/Exec/PrepareEx,而无需考虑语句是否已经准备好。

package main

import (
    "github.com/jackc/pgx"
)

func main() {
    conf := pgx.ConnPoolConfig{
        ConnConfig: pgx.ConnConfig{
            Host:     "/run/postgresql",
            User:     "postgres",
            Database: "test",
        },
        MaxConnections: 5,
    }
    db, err := pgx.NewConnPool(conf)
    if err != nil {
        panic(err)
    }
    _, err = db.Prepare("my-query", "select $1")
    if err != nil {
        panic(err)
    }
    // What to do with the prepared statement?
}
  1. name参数给我的印象是,它可以通过name调用来执行,但是如何执行呢?

这是我自己走得多远:

  1. 没有按名称引用查询的方法(假设)
ps, ok := c.preparedStatements[sql]
            if !ok {
                var err error
                ps, err = c.prepareEx("", sql, nil)
                if err != nil {
                    return "", err
                }
            }

共有1个答案

田宇
2023-03-14

@mkopriva指出,sql文本误导了我。它在这里有双重功能。如果sql变量与c.preparedStatements[sql]映射中的键不匹配,则准备sql中包含的查询,并为ps指定一个新的*PreparedStatement结构。如果它确实匹配一个键,ps变量将指向映射的一个条目。

所以你可以有效地做一些事情,比如:

package main

import (
    "fmt"

    "github.com/jackc/pgx"
)

func main() {
    conf := pgx.ConnPoolConfig{
        ConnConfig: pgx.ConnConfig{
            Host:     "/run/postgresql",
            User:     "postgres",
            Database: "test",
        },
        MaxConnections: 5,
    }
    db, err := pgx.NewConnPool(conf)
    if err != nil {
        panic(err)
    }
    if _, err := db.Prepare("my-query", "select $1::int"); err != nil {
        panic(err)
    }
    row := db.QueryRow("my-query", 10)
    var i int
    if err := row.Scan(&i); err != nil {
        panic(err)
    }
    fmt.Println(i)
}
 类似资料:
  • 正在研究这一点PHP(刚刚开始,正在查看文档)。我在另一个页面上有一个表单,所有内容都正确传递,查询返回结果(这意味着搜索并返回用户搜索的结果)。行数显示正确,因此结果正确,但我尝试的几个选项在显示结果时失败。我只想显示返回行的结果。另外,如果对如何简化prepare语句和bind有什么建议的话,我还没有找到大量使用LIKE和%搜索多个列的示例,如下所示。谢谢

  • 问题内容: 我要做的就是在excel工作表上使用标准范围(例如,命名范围,甚至A1:F100),并在其中运行一些sql查询,然后返回一个记录集,我可以在VBA代码中逐步执行该记录集,甚至只是粘贴到同一工作簿中的其他工作表中。 使用ADODB是一个想法,但是如何设置连接字符串以指向当前工作簿中的某个范围? 我知道在使用Microsoft查询向导之前,这并不理想,但是可以使用。我似乎无法使它仅引用其他

  • 我正在尝试学习使用准备好的语句以避免SQL注入等的正确方法。 当我执行这个脚本时,我从我的脚本中得到一条消息,说插入了0行,我希望这条消息说插入了1行,当然更新了表。我不是完全确定我准备好的陈述,因为我做了一些研究,我的意思是,每一个例子都不一样。 当我更新我的表时,我需要声明所有的字段还是只更新一个字段就可以了?? 任何信息都会很有帮助。 index.php 类/class.scripts.in

  • 假设我们有一个名为托管在tomcat上的服务提供商应用程序,用户单击指向SP a的链接。SP a没有看到提供的令牌,因此它会将用户重定向到IdP进行身份验证(通过某种方式提供SAML Authn请求)。然后,IdP将用户重定向到提供凭据的某个公共登录页面,假设这些凭据正确,IdP将创建一个SAML响应,其中包含一个令牌和一些关于主题的断言,并将其发送回SP a。SP a看到了这一点,并允许用户访问

  • 我有一个恼人的问题,我不明白为什么会发生。为了简单介绍一下,我在Spring Boot项目中使用MySql和JDBC模板实现了批处理(batch insert)。 因此,基本上批插入工作正常,性能非常惊人,但有一个小问题非常烦人,当我插入一个表时,它会导致约束异常,该表在两列(id,value)上有唯一的键。 所以我有以下代码: 当我在Spring Boot中使用数据源代理查看日志时,我可以看到执

  • 为了减少内核或跨进程内存泄漏(Spectre攻击),Linux内核1将使用一个新选项编译,引入到,以便通过所谓的retpoline执行间接调用。 这似乎是一个新发明的术语,因为谷歌搜索只是最近才使用(通常都是在2018年)。 1但是,它不是Linux特有的--类似或相同的构造似乎被用作其他操作系统缓解策略的一部分。