pgx lib中的命名准备语句,它是如何工作的?

介绍

数据库/sql

在 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. 如果连接在语句执行时不可用,它将在新连接上重新准备。

pgx

PreparedStatement类型没有定义任何方法。一个新的命名准备语句由以下人员准备:

func (p *ConnPool) Prepare(name, sql string) (*PreparedStatement, error)
  1. 操作直接在连接池上

  2. 事务在池的所有连接上准备好

  3. 没有明确的方法如何执行准备好的语句

Prepare 是幂等的;也就是说,使用相同的名称和 sql 参数多次调用 Prepare 是安全的。这允许Prepare 和 Query/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,但是如何呢?

  2. 该文档给人的印象是Query/Exec方法以某种方式利用了准备好的语句。但是,这些方法不接受参数name。它如何匹配它们?

  3. 据推测,匹配是由查询内容完成的。那么命名语句的意义何在?

可能的答案

这是我得到的结果:

  1. 没有按名称引用查询的方法(假设)

  2. 匹配是在查询主体上完成的conn.ExecEx()。如果还没有准备好,将完成:

ps, ok := c.preparedStatements[sql]

            if !ok {

                var err error

                ps, err = c.prepareEx("", sql, nil)

                if err != nil {

                    return "", err

                }

            }

PosgreSQL 本身需要它来做某事(假设)。


holdtom
浏览 250回答 1
1回答

繁星coding

它在这里有双重功能。如果sql变量与映射中的键不匹配c.preparedStatements[sql],则准备好包含在 中的查询sql并将新*PreparedStatement结构指定给ps. 如果它确实匹配了一个键,ps变量将指向地图的一个条目。如此有效,您可以执行以下操作:package mainimport (    "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)}
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go