Как я могу заставить esqueleto сгенерировать для меня строку SQL?

86

Как я могу заставить esqueleto сгенерировать строку SQL из fromоператора?

В документации toRawSqlуказано, что «вы можете просто включить постоянное ведение журнала запросов». Я пробовал все возможные формы, MonadLoggerкоторые мог понять, но он никогда не печатал SQL. В той же документации также говорится: «Использование этой функции вручную ... возможно, но утомительно». Однако ни конструкторы типа, ни функции, возвращающие значения типа, QueryTypeне экспортируются. Мне удалось обойти это, заметив, что QueryTypeэто newtypeи используя unsafeCoerce!

Мне также пришлось предоставить Connection(который я получил через SQLite), хотя не должно быть необходимости подключаться к базе данных для генерации SQL.

Вот что у меня есть. Должен быть способ получше.

withSqliteConn ":memory:" $
    \conn -> return $ toRawSql SELECT
                               (unsafeCoerce ((const mempty)
                                  :: a -> Text.Lazy.Builder.Builder))
                               (conn, initialIdentState) myFromStatement)

http://hackage.haskell.org/package/esqueleto-1.3.4.2/docs/Database-Esqueleto-Internal-Sql.html

Том Эллис
источник
2
Я считаю, что причина, по которой вам нужно установить соединение, заключается в том, что он полиморфен в базе данных и использует предполагаемые SqlPersistэкземпляры для генерации строк SQL, специфичных для базы данных.
Томас
2
Однако соединение и тип базовой базы данных - разные вещи. Должна быть возможность генерировать только строку SQL.
Том Эллис

Ответы:

2

За время, esqueletoпрошедшее с момента публикации этого вопроса, он претерпел ряд серьезных изменений. Начиная с версии 2.1.2 и нескольких более ранних версий, QueryType aпараметр, который требовал вашего unsafeCoerce, был удален из toRawSql; эта большая бородавка больше не нужна.

В текущей реализации Connectionтребуется. Я считаю , что, как указано имя синоним типа, IdentInfo, esqueletoиспользует это , чтобы идентификаторы сборки в запросе. Например, он может добавить имя базы данных. Я действительно не изучил источник достаточно глубоко. Достаточно сказать, что передача поддельного соединения (т.е. undefined) не работает; Я не знаю, можно ли реализовать фиктивное соединение. Ваше решение кажется работоспособным.

Остальная часть вашего решения должна работать нормально. Поскольку toRawSqlэто явно внутренняя функция, API здесь кажется разумным. Хотя другие отмечают, что «должно быть» возможно сгенерировать строку, не зависящую от соединения, это выходит за рамки toRawSql.

Вы упомянули, что не можете использовать MonadLoggerкак рекомендовано. Что вы пробовали и что вышло?

оборота Christian Conkle
источник
К MonadLoggerсожалению, не могу вспомнить, что пробовал . Это было довольно давно.
Tom Ellis
У вас есть тестовый проект под рукой, чтобы увидеть, toRawSqlработает ли сейчас для варианта использования этого вопроса? Я настроил esqueletoсреду, чтобы опробовать его, но у меня не было времени разобраться, persistentа все остальное оборудование действительно построило и обработало реальный запрос.
Christian Conkle
У меня вообще нет тестовой среды или каких-либо проектов esqueleto, извините.
Tom Ellis