Введение
база данных / sql
В стандартной библиотеке sql Go тип *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)
- Пул соединений абстрагирован и не доступен напрямую
- Транзакция подготовлена для одного соединения
- Если соединение недоступно во время выполнения устава, оно будет повторно подготовлено для нового соединения.
pgx
PreparedStatement
Тип не имеет методов, определенных.Новый именованный подготовленный оператор подготовлен следующим образом:
func (p *ConnPool) Prepare(name, sql string) (*PreparedStatement, error)
- Операции находятся непосредственно в пуле соединений
- Транзакция подготовлена для всех соединений пула
- Не существует четкого способа выполнения подготовленного оператора
В комментарии Github автор лучше объясняет различия в архитектуре между pgx и database / sql.В документации по Prepare
также говорится (выделено мое):
Подготовка идемпотентна;то есть безопасно вызывать Prepare несколько раз с одним и тем же именем и аргументами sql.Это позволяет использовать кодовый путь для 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?
}
Вопрос (ы)
- Аргумент
name
создает впечатление, что его можно выполнить, вызвав егоname
, но как? - Документация создает впечатление, что методы
Query
/ Exec
каким-то образом используют подготовленные операторы.Однако эти методы не принимают аргумент name
.Как это соответствует им? - Предположительно, сопоставление выполняется с помощью содержимого запроса.Тогда в чем же смысл именования утверждений?
Возможные ответы
Вот как далеко я себя получил:
- Нет методов, которые ссылаются назапросы по имени (допущение)
- Сопоставление выполняется в теле запроса в
conn.ExecEx()
.Если это еще не подготовлено, это будет сделано:
ps, ok := c.preparedStatements[sql]
if !ok {
var err error
ps, err = c.prepareEx("", sql, nil)
if err != nil {
return "", err
}
}
Самому PosgreSQL это нужно для чего-то (предположение).