преобразовать запрос 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 метода текущей (новой пустой) структуры, которые реализуют функциональность методов выше, например:

  1. Создание пустой структуры type dbLogger struct{}
  2. Добавление методов из документа:
      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)
}

Надеюсь, это поможет будущим зрителям

Другие вопросы по тегам