Comments 16
Это можно сделать и без кодогенерации, если помнить что embed
позволяет использовать embed.FS
Тогда враппер может делать Query("user_select.sql", 1, 2, "abc")
. У этого есть свои минусы, но минусы есть и в кодогенерации.
Про embed.FS помним, однако мне не нравится оверхед на чтение всего этого дела в момент выполнения уже непосредственно кода. Кодогенерация позволяет сделать это всё один раз на машине девелопера или в CI и дальше спокойно пользоваться константными значениями.
А этот оверхед он здесь с нами, в одной комнате?
Нравится/не нравится - это аргумент, который имеет место быть, но если бенчмарки показывают что разница исчезающе мала, то смысла в кодогенерации никакой.
Если приложение пишется один раз и никогда не изменяется, то действительно один раз сгенерировал и забыл.
Но если код меняется, не должно быть такого, что SQL поменялся у вас на машине, а результат кодогенерации меняется где-то там в CI, потому что это кошмар для отладки.
Значит, всем разработчикам нужен будет хук. Или проверки на MR. И решение внезапно перестает быть простым.
Тут кроме временного оверхеда есть еще тот, который момент выявления ошибки. При кодогенерации и аналогичных подходах (причем не важно, говорим мы про интеграцию SQL или о чем-то еще) проблемы чтения, парсинга и тд выявляются на этапе сборки, а не потом где-нибудь на проде, задеплоеном в далекую галактику. Особенно актуально, если прод — это не веб-сервис, а системная приложуха, развернутая на какой-нибудь железке на заводе города N.
А если наши гипотетические разработчики меняют SQL и потом не проверяют ожидаемый результат тестами или хотя бы руками — то тут уже ни хуки, ни embed не поможет.
Ну а в целом, я не вижу причин, почему какой-либо из этих методов интеграции SQL не мог бы существовать. И так норм и этак неплохо, просто предлагаю тот, что симпатизирует мне во вполне ограниченном числе кейсов.
Спасибо за идею и её реализацию.
Я тоже пришёл к тому, чтобы хранить SQL-код отдельно в файлах с embed. Этот подход позволяет подключать различные инструменты для анализа и проверки SQL, а также использовать современные технологии, такие как LLM. Лично мне нравится работать с LLM, так как она действительно помогает выявлять потенциальные проблемы и уведомляет о них в MR (PR).
Конечно, есть сложности с переменными, но, на мой взгляд, их можно размещать в зависимости от контекста в более подходящих местах.
Идея кодогенерации пока кажется мне избыточной и сложной для понимания — это как магия. Но надо будет попробовать и поглядеть, как это будет выглядеть в процессах.
В целом тоже примерно так делаю. И с вами почти согласен.
Однако у автора есть здравое зерно: избавится от ручного прописывания и дальнейшей поддержки всех этих эмбедов.
Возможно попробую сделать что-то похожее или возьму то, что автор предложил. Надо попробовать.
Тем более что в кодогенерацию уже пробовал и никакой магии в ней не вижу.
При таком подходе запрос не засоряет Go код и удобно читается.
Но зачем? Запрос - это полноценная часть логики, в чем выигрыш вынесения в отдельный файл? Тут упомянали анализ инструментами, но ведь тот же GoLand умеет проверять SQL в литералах.
Опять решаем софт проблемы хард методами. Если приходит новый тимлид и резко требует "убрать SQL запросы из кода" должен стоять вопрос о профпригодности этого тимлида и целесообразности его требований, а не срочное исполнение всех хотелок странного извращенца.
Мы подрались и остановились на использовании билдера (goqu), ибо на том проекте было много мест, где запросы собираются с большим количеством разных фильтров, параметров и тд.
Спасибо за наводку на doug-martin/goqu, но с этими всеми «билдерами» на любом ЯП надо изучать особенности их DSL и особенно, если там есть неочевидные вещи. Если надо миграцию с версии 1 на 2 сделать, тоже дает проблемы. Пока пробуем github.com/VauntDev/tqla, и шаблон используется стандартный text/template.
У sqlc, очевидно, есть фатальный недостаток
Отличие в более ограниченной зоне ответственности у sqlamble: никакого парсинга самих файлов, ни врапперов для отправки запросов, только внедрение содержимого файлов запросов. Чисто некий эмбеддер, так-то можно подключать им любые текстовые файлы.
Поддерживаю. Хорошее решение. Вопрос "А зачем?" на эту тему давно себе не задаю, после трех месяцев, потраченных на перевод кода проекта с MS SQL на PostgreSQL. Там SQL и код приложения были в одной куче и это был реально трэш ))
В одном, из приложений я решил хранить sql код в самой БД в отдельной таблице. Для сетевой и локальной версий и это работает. Храню как запросы так и хранимые процедуры для двух баз sqlite и sql server.
Скрэмбл для тех, кто ненавидит SQL в Go коде