преобразовать запрос go-pg в простой sql
Можно ли преобразовать запрос go-pg
err = db.Model(story).
Relation("Author").
Where("story.id = ?", story1.Id).
Select()
в простой SQL?
Это было бы полезно для отладки. Поэтому я мог скопировать этот простой SQL-запрос и запустить его в клиенте psql в виде строки. Наверное, для этого есть какой-то пакет?
4 ответа
Это указано в вики проекта:
Как просмотреть запросы, генерируемые этой библиотекой?
Вы можете настроить регистратор запросов следующим образом:
type dbLogger struct { }
func (d dbLogger) BeforeQuery(c context.Context, q *pg.QueryEvent) (context.Context, error) {
return c, nil
}
func (d dbLogger) AfterQuery(c context.Context, q *pg.QueryEvent) (context.Context, error) {
fmt.Println(q.FormattedQuery())
return c, nil
}
db := pg.Connect(&pg.Options{...})
db.AddQueryHook(dbLogger{})
Проблема: синтаксический анализ RAW sql из ORM по умолчанию отсутствует с v10.
Что ж, думаю, уже слишком поздно. Возможно, кто-то (например, я) столкнется с этой проблемой в 2021 году. Вот несколько шагов, как вы могли бы решить эту проблему:
- [x] Читать DOC.
- [x] Проверить все структуры.
- [x] Реализуйте все методы.
Решение проблемы
Это решение "ответвлено" от этой проблемы, но я объясню его шаг за шагом. Прежде всего нам нужно прочитать исходный код хука go-pg. Как я уже сказал ранее: нам нужно проверить все структуры из этого документа. Но нам повезло. Есть только 1 структура!
// QueryEvent ...
type QueryEvent struct {
StartTime time.Time
DB orm.DB
Model interface{}
Query interface{}
Params []interface{}
fmtedQuery []byte
Result Result
Err error
Stash map[interface{}]interface{}
}
Нам действительно не нужно полностью реализовывать эту структуру. Но когда вы используете db.AddQueryHook() (где db - ссылка на наше соединение с БД, а AddQueryHook() - метод), AddQueryHook() ждет от вас этого интерфейса:
type QueryHook interface {
BeforeQuery(context.Context, *QueryEvent) (context.Context, error)
AfterQuery(context.Context, *QueryEvent) error
}
Итак, мы уже прочитали документы, проверили структуры. А потом что? Ответ довольно прост:
- Реализуйте все методы.
ТБХ, я думал, что это сложнее, чем есть на самом деле. Для его реализации вам просто нужно создать 2 метода текущей (новой пустой) структуры, которые реализуют функциональность методов выше, например:
- Создание пустой структуры
type dbLogger struct{}
- Добавление методов из документа:
func (d dbLogger) BeforeQuery(c context.Context, q *pg.QueryEvent) (context.Context, error) {
return c, nil
}
func (d dbLogger) AfterQuery(c context.Context, q *pg.QueryEvent) error {
fq, _ := q.FormattedQuery()
fmt.Println(string(fq))
return nil
}
Надеюсь, это поможет всем, кто хоть раз сталкивался с этой проблемой.
//db your *pg.DB
// q your *orm.Query = db.Model(&yourModel).
qq := pg.QueryEvent{
DB: db,
Model: q.TableModel(),
Query: q,
}
fmt.Println(qq.FormattedQuery())
Так что в твоем случае
q:= db.Model(story).
Relation("Author").
Where("story.id = ?", story1.Id)
fmt.Println("running SQL:")
qq := pg.QueryEvent{
DB: db,
Model: q.TableModel(),
Query: q,
}
fmt.Println(qq.FormattedQuery())
q.Select()
Я только что обновлялся с go-pg v7 до v10, и у меня возникла проблема, когда
Query.AppendFormat()
то, что я использовал, чтобы получить RAW SQL, был удален.
После использования комментариев в этом посте для вдохновения мне удалось извлечь его, используя приведенный ниже код.
import (
"github.com/go-pg/pg/v10/orm"
)
func QueryToString(q *orm.Query) string {
value, _ := q.AppendQuery(orm.NewFormatter(), nil)
return string(value)
}
Надеюсь, это поможет будущим зрителям