Как стать автором
Обновить

Комментарии 59

а для чего он нужен, если SQL не знать, то запрос не напишешь, ну серьезно, а если знать, то не нужно?
Он нужен для удобного и безопасного написания сложных SQL-запросов, чтобы не пихать весь запрос в строку, а потом не подставлять туда переменные. Плюс при использовании этой библиотеки часть ошибок в запросе можно отловить еще на этапе, когда Ruby распарсивает файл, а не когда запрос уйдет в базу данных.
Можно примеры эксепшенов, где Ruby ругается на кривой запрос? Является ли ваш билдер гарантом того, что если Ruby распарсит файл — запрос не обвалится в базе данных? Если нет, то какой смысл — дебаг удлинняется в 2 раза.

Ну и примеры реально сложных(с несколькими джоинами и вложенными) запросов?

И для каких диалектов(БД) написана библиотека?
Попробуйте написать по ошибке wehere вместо where — эксепшн на этапе исполнения. Попробуйте, скажем, забыть запятую между таблицами в from — файл не распарсится. Так что от опечаток точно защищает.

Естественно, билдер не может являтся абсолютным гарантом того, что запрос не обвалится, хотябы по той причине, что вы можете указать несуществующую таблицу, а билдер ничего не знает о структуре БД.

Приведите пример сложного, на ваш взгяд, запроса, я его перепишу для своего билдера. Единственное что не поддерживается пока — это UNION'ы. JOIN'ы и вложенные подзапросы — сколько угодно.

С MySQL, PostgreSQL, SQLite работать должна.
>Попробуйте написать по ошибке wehere вместо where — эксепшн на этапе исполнения. Попробуйте, скажем, забыть запятую между таблицами в from — файл не распарсится. Так что от опечаток точно защищает.

имхо от этого спасёт даже банальная подсветка кода, а умный IDE в таких запросах даже автокомплишен умеют (см. www.jetbrains.com/idea/features/sql.html).
Извините, но мне не известны IDE для Ruby поддерживающие подсветку кода прямо внутри строк rb-файла. Более того, большинство Ruby-разработчиков не используют IDE вообще, в том числе и я.

Я не очень понял, чего вы привязались к этой валидации кода, библиотека писалась совсем не для этого. Вам вот часто приходится писать голые SQL-запросы?
>Извините, но мне не известны IDE для Ruby поддерживающие подсветку кода прямо внутри строк rb-файла.
вышеупомянутая IDEA?

>Вам вот часто приходится писать голые SQL-запросы?
сейчас, при наличии grails/gorm — вообще не приходится, ибо ORM там мощнейщий.

впрочем, ваш DSL на него слегка похож:

def c = Account.createCriteria()
def results = c {
	like("holderFirstName", "Fred%")
	and {
		between("balance", 500, 1000)
		eq("branch", "London")
	}
	maxResults(10)
	order("holderLastName", "desc")
}
> вышеупомянутая IDEA?
Любопытно. Т. е. если я напишу str = «SELECT * FROM table» она подсветит? А как она понимает что в строке именно SQL?

Мне кажется, что мой синтаксис посимпатичнее и значительно ближе к оригинальному SQL, нет?

Вполне подсветит. Более того, может заглянуть в БД и проверить, что вы обращаетесь к существующей таблице и к существующим столбцам.

О том, что в строке SQL — Идея понимает по контексту, в котором эта строка использована. Хотя, конечно, если вы продергиваете строку через несколько интерфейсов/иерархий да еще и собираете по частям — такое она не опознает. Да и я наверное бы мне сразу распознал :)
>Мне кажется, что мой синтаксис посимпатичнее и значительно ближе к оригинальному SQL, нет?

возможно.
но лично для меня это скорее минус, а не плюс.
да и ваш систаксис поверх gorm несложно реализовать, думаю.
Один в один как Sequel. Мне сиквел как раз нравиться тем, что его можно использовать и как мощный ORM, и как простой DSL к SQL.
Офигеть, какая мне разница, в какой момент упадет программа, если она все равно упадет в run-time.

P.S. На nemerle можно написать такой же код, но с проверкой в compile-time=)
Вау, круто. Т. е. он во время компиляции даже проверяет наличие необходимых таблиц и колонок в базе? (См. мой коммент выше) Просто магией попахивает )

И эту библиотеку я писал совсем не с целю валидации кода запросов, это лишь бесплатный бонус )

Это не бонус, так как парсинг происходит во время выполнения, следовательно программа упадет в run-time.

Без проблем: nemerle позволяет расширять свой синтаксис через макросы, которые работают на этапе компиляции, поэтому можно сделать запрос в DB во время компилирования, получить структуру базы и ругнуться в случае необходимости.
Я рад, за nemerle, но эта статья про Ruby.
Зато теперь вы хотя бы отдаленно представляете, какого в каждой статье по PHP читать про Ruby и Python =)
>Он нужен для удобного и безопасного написания сложных SQL-запросов,

Сложных? Ну-ка набросайте мне выборку записей с N-й M штук (identity идут в разнобой). Желательно для PostgresSQL или DB2. Далее на очереди рекурсивные выбороки, полнотекстовый поиск. Простой селект я и сам без ошибок накатаю.
> Ну-ка набросайте
Что за тон вообще?
> выборку записей с N-й M штук
Чем не устраивают limit и offset из второго примера?

>Что за тон вообще?

Сорри, если задел, но в моей практике эта штука вообще не применима.

> Чем не устраивают limit и offset из второго примера?

Тем что их нету в Db2. И рекурсию ваш DSL не сделает скорее всего.
Хорошая демонстрация гибкости языка! Но на деле — думаю дороговато (в плане производительности)
Вы видели, скажем, код рельс? По сравнению с ним этот DSL — это просто детская шалость (в плане потерь в скорости исполнения)
А мне понравилось. Как раз размышлял над возможностью создания аналогичной фишки на Питоне с помощью with. Но там скорее всего всё же посложнее получится.

Весь интерес конечно не в том, чтобы переписать SQL на новый лад, а в перспективе развития. Наверняка можно много чего донавернуть. Автовалидацию полей, кэш, возможно генерацию объектов из результата выборки. По моему это было бы потрясающе удобно. Просто пишешь почти на SQL и всё делается на автомате. Впрочем, на Руби никогда не писал (только игрался немного), так что не скажу, чего вам, рубистам, надо. Верняк сейчас рельсовики скажут, что им ActiveRecord хватает.
sqlalchemy?
Шутите? Ему до чистого SQL как пешком до Китая. Хотя штука конечно забавная.
я не думаю, что вы на питоне напишете что-то серьезнее, чем sqlalchemy. и сравнивать ее с «чистым SQL» глупо — это разные вещи.
Ну что значит «серьёзнее»? Я в общем то не собираюсь создавать библиотек вселенского масштаба. А для собственного развлечения подойдут и «несерьёзные» поделки.

Зачем вы мне предложили алхимию я так и не понял. Мне то как раз интересно было бы использовать синтаксис максимально приближённый к SQL (чтобы сложные запросы не выглядели монструозно; в sqlAlchemy они страшны даже с использованием одного подзапроса, не говоря о большем), но с дополнительными плюшками, типа валидации введённых данных а-ля поля в Django, кешированием и пр. Пока подобной реализации на Питоне мне не встречалось.
из перечисленных вами фич в алхимии есть и кэш, и генерация объектов по результатам выборки. валидацию тоже можно добавить на нужном уровне (да она в принципе и так присутствует). синтаксически SQL максимально приспособлен для написания запросов, ожидать от питона того-же — странно. а жанге все, что сложнее простой выборки делается через extra, в котором уже идет обычный SQL.

а насчет развлечений — да, велосипеды писать полезно, т.к. знаний много новых появляется. а заодно уважение к серьезным проектам)
Гм. Где-то тут на хабре проскакивала ссылка на перевод статейки в духе «ORM — Вьетнам компьютерной науки». Там очень чётко были разжёваны плюсы и минусы такого подхода. В общих чертах — приходится вместо SQL учить нечто, написаное на языке. Это нечто более громоздко, часто трудно в изучении и при этом часто не даёт нужной гибкости. Алхимия даёт гибкость, но ценой той самой громоздкой монструозности сложных запросов.

Язык запросов максимально преспособлен для написания запросов, ага. ) От Питона я не совсем того ожидаю. Вернитесь к самому посту и посмотрите. Практически SQL, но на самом деле Ruby. А это даёт, как мне кажется, кучу плюшек. Во-первых можно писать сложные запросы без трёхэтажных ORM-конструкций. Во-вторых от автора запроса может быть скрыта львиная часть работы. Всё те же упомянутые валидация, кеширование, преобразование результата в объект. Я думаю что мне было бы удобно пользоваться такой штукой.

На Питоне решение из Джанго меня в принципе устраивает. Алхимия на мой вкус не слишком интуитивно-понятная и слишком громоздкая. Но описаное выше решение было бы близким к идеальному. Конечно до той поры, пока объектные базы не будут работать со скоростью реляционных.
посмотрите на gorm — для многих вещей страшный hql(sql) не нужен:

Спасибо, конечно. Но до grails я видимо ещё не скоро доберусь. А так на вскидку обёртка обёрткой.
В питоне можно использовать перезагрузку операторов. Саму идею можно посмотреть в рецепте Infix operators.
В итоге чистый питон-SQL пишется примерно так:
query = SELECT| (tbl.col, tbl.col2, tbl.col3 ) \
                 |FROM| tbl \
                 |JOIN| (tbl.col == tbl2.col)
                 |WHERE| (tbl.col == 10 |AND| tbl2.col < 20)
                 |LIMIT| 100

Хотя мне больше нравится смешивать синтаксис питона и sql, как-то так:
query = SelectQuery()
query.select(tbl.col, tbl.col2, tbl.col3)
query.from(tbl |JOIN| (tbl.col == tbl2.col))
query.where(tbl.col == 10 |AND| tbl2.col < 20)
query.limit(100)
пипец… уж извините
За пример реализации спасибо.

Понятно, что нужно использовать магию. Правда в таком варианте тяжеловато будет делать дополнительную обработку полей. Хотелось бы чего-то более тонкого, хотя это я уже привередничаю. На самом деле конечно 90% задач решается простыми запросами. Но концепт нравится.
НЛО прилетело и опубликовало эту надпись здесь
Я так не делаю, конечно. Это просто пример. Хотя при создании прототипов так делать все-таки можно для ускорения процесса разработки, когда производительность не очень важна.

На Sequel действительно сложные запросы выглядят, извините, какашечно )
Ну вообще-то денормализация это пример зла.
Иногда необходимого зла (ради производительности), но всё равно зла.
давайте есчо погреем планету, ну же!

btw, идея хороша (ибо на поверхности), однако сразу видно что у неё есть потолок возможностей, а значит — смысла нет.
Вам известны идеи у которых нет потолка возможностей?
вот в том-то и дело, я считаю что писать что то как верхушку SQL — нет смысла. Лучше простой датамаппер + процедуры pl/python в postgresql.
Вы не поняли. У любой идеи есть потолок возможностей. Потолок возможностей есть и у самих реляционных БД. Поэтому писать фразу, что у идеи «есть потолок возможностей, а значит — смысла нет» — по меньшей мере наивно.
очевидно я имел ввиду «невозможность реализовать все вложенное в сам SQL».
если уж использовать современную реляционную бд — то и со всеми возможностями в неё вложенными. А это и процедуры и дриггеры и вьюшки и иногда очень замысловатые подзапросы. В противном случае толку от базы будет как от простого мемори-холдера (а-ля memcache).

И вот все такие потуги выглядят забавными — зачем? Ну какой нормальный высоконагруженный проект будет использовать тяжелый ORM? Если сравнить время сборки запроса с 0 в случае жесткого написания, разница получается в разы =). И поддержка множества баз на таких проектах тоже не нужна — все заточено под 1.

Наоборот, маппинг данных — весьма полезная штукенция, потому как все равно это неявно будет делаться в коде.

Далее. Если уж писать DSL, то делать это декларативно! Нахрена каждый раз в рантайме собирать один и тот же не меняемый sql но с разными данными? Только время процессора жрать зря. Ко всему прочему и таблицы в рантайме обычно не меняются. А вот декларативно ещё более-менее простительно, т.к. делается 1 раз, а потом просто данные засовываются. Ну например класс + метакласс (в случае питона) и чтоб метакласс распарсил все в процессе импорта. Т.е. и тип базы (для способов квотирования) тоже в рантайме не меняется — то все тип топ.
Не обращайте внимания на снобов и маргиналов, пишите еще больше полезных и не очень утилит на Ruby.

2All: не вижу ничего плохого в том, что человек потренировался в написании DSL и выложил результат на общее обозрение, не побоявшись критики.
Одно замечание… для «чистоты» рубы должно быть where (posts.author_id == users.id) && (users.name == 'Vlad Semenov') вместо where (posts.author_id == users.id) & (users.name == 'Vlad Semenov'), согласитесь =)
Руби не дает перегружать логические операторы.
Так бы и было, если бы это было технически возможно. Но руби не дает перегружать &&, || и даже !=.
Так держать.
Очень правильное начинание.

Красиво и удобно.

P.S.: напоминает Microsoft LINQ ;)
Идея написать этот DSL появилась после того, как я поковырялся с LINQ, так что это не случайность )
тот факт, что не все гладко и «где-то пришлось поизвращаться из-за невозможности перегрузки оператора» говорит, что код уже сейчас далеко не идеален. Так зачем же менять правильный SQL на звращенный код, учить псевдоязык, в котором сначала from tables, а потом select, обязательны скобки и пр. с чем еще не столкнулись?

Вы конечно молодец, но, имхо, у вас нет возможности реализовать идею так как вы хотели её видеть на финише, когда брались за реализацию.
На самом деле получилось даже ближе к оригиналу, чем я ожидал изначально. Надо понимать, что данный DSL существует для удобной подстановки значений переменных в SQL-запрос. Корректне сравнивать его со строкой, содержащей SQL, в которую напиханы подстановки переменных (что не безопасно) или плейсхолдеры. Если плейсхолдеров много, то можно запутаться.
да что вы за эту подстановку зацепились.
неужели а-ля «select * from asd where x = ?, y = ?» аналога нет в руби?
ой =)

ладно, чем не безопасно?
Полезная штука, на самом деле. А критика про ненадобность она неуместна. Ведь точно так же можно утверждать, зачем в рельсы понапихивали эти дурацкие хэлперы, ведь можно всё писать на чистом html'е! Конечно можно, но… но чтоб не устраивать холиворы скажу, что в рельсах хэлперы существуют очень долго, портируются на другие фреймворки, всем хорошо, и чистые хтмли юзают только там где это нужно.
У меня один вопрос — «Зачем?»
Почитайте коменты для начала.
Привет, скаже а на этой технологии можно реализовывать произвольные грамматики, например, такую:

git.shadanakar.org/?p=onPHP.git;a=blob;f=doc/OQL-BNF;h=e3a0a448053c160d85d65b0619377c72cc1a54e3;hb=refs/heads/master

?
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации