Изменения

Перейти к: навигация, поиск

Funq

2606 байтов добавлено, 12:42, 20 июня 2016
Funq — '''Funq''' — концепция околофункционального, гибкого язык языка запросов к реляционным базам данных, чемчуть-то чуть похожего на LINQ и призванного заменить SQL для разработчиковсложных запросов, оптимизируя их ещё на стадии построения, и давая возможность наложить любое преобразование на запрос в любой момент, к тому же, скрывая диалекты, свойственные отдельным СУБД.
== Идея ==
Вообще-то, внезапно можно осознать, что <code>relation.something().something().something()</code> — функциональный стиль программирования, а точнее, что это очень похоже на [http://www.martinfowler.com/bliki/FluentInterface.html Fluent Interfaces]. Собственно, они и сами являются пародией на ФП, хотя и довольно жалкой.
 
Ещё можно осознать, что по сути '''Funq''' по сути нужен только для тех СУБД, которые не могут хорошо оптимизировать бесконечно длинные цепочки подзапросов. Есть, правда, подозрение, что во многих случаях это ровно ВСЕ СУБД, но в любом случае к таким относится как минимум MySQL.
Кроме того, можно вспомнить язык [http://msdn.microsoft.com/en-us/netframework/aa904594.aspx LINQ] (Language INtegrated Query) от Microsoft. Если в LINQ пользоваться только объектным стилем задания запроса, то LINQ тоже станет похож на Funq. Другое дело, что на практике делать именно так в LINQ практически невозможно и в любом случае неудобно. Важно также, что и цель у создателей LINQ изначально была другая — встроить язык запросов в .NET с помощью обычных его средств и научить языки .NET работать через одни и те же классы и интерфейсы с базами данных, XML-файлами, да и вообще любыми источниками данных, вплоть до обычных массивов.
* Возможность программного последовательного выполнения подзапросов — сначала внутреннего, а потом внешнего, с программной передачей результата первого во второй. В MySQL бывают ситуации, когда это ускоряет выполнение запроса ''в разы''.
Чего пока нетдаже в списке TODO:
* Автоматической генерации алиасов , например , для подзапросов, если они не задаются явно.* Поддержки подстановки хешей в текст запроса (например , в виде field=value AND field=value).
* Нет ORM’а, и даже не обдуман. А возможно, стоит. А возможно, и не стоит.
* Поддержки операции вставки в отношения, выраженные посредством Funq-запросов.
 
Список TODO:
 
* Поддержка автоматического удаления join’ов на «ненужные» таблицы, если ни одно из их полей не указано в запросе. Полезно, например, для какой-нибудь Багзиллы, где есть таблица bugs с огромной кучей полей, которые по-разному хранятся. Соответственно, можно будет просто определить «супертаблицу» со всеми-всеми полями и только указывать, какие мы хотим, а какие не хотим, и Funq бы само удалило лишние join’ы.
* Тесты (!)
* Source-фильтр чтобы писать $dbh->do(funq(table->where(«config=?»)->order()), { arg => value, arg => value, … }), хотя полную функциональность так не реализуешь, так как неизвестен тип подставляемых значений.
* Найти места с неочевидным синтаксисом типа передачи параметров-ссылок на скаляр в качестве выражений и т. п., устранить все такие неочевидности введением методов.
* Возможно, не делать трансляцию SELECT * в список полей, а только логически передавать во внешний запрос.
* Простые методы вставки (наподобие [{{SVN|vitaphoto/solstice/lib-sway/VMX/Common.pm|markup}} VMX::Common::insertall_hashref]) / мульти-обновления (для MySQL, INSERT … ON DUPLICATE KEY SET …).
* Все TODO и FIXME из кода.
== Синтаксис Funq ==
Рассмотрим [[Funq]] на примере его Perl-реализации: модулей [{{SVN|vitaphoto/branch/solstice/lib-sway/Funq/DBI.pm}} Funq::DBI] (объект соединения) и [{{SVN|vitaphoto/branch/solstice/lib-sway/Funq/Query.pm}} Funq::Query] (объект запроса). Под <code>$dbh</code> везде понимается объект соединения, а под $query — объект запроса.
=== Формирование запроса ===
; <code>$query->replace_into($table)</code>: ([http://www.mysql.com/ MySQL]). Превращает запрос в запрос замены выбранных строк в таблицу <code>$table</code>: Аналогично insert_to, но при этом все имеющиеся в таблице записи со значениями полей, входящих в первичный или уникальный ключ, равными значениям одной из вставляемых строк, предварительно удаляются (см. [http://dev.mysql.com/doc/refman/5.0/en/replace.html|Синтаксис REPLACE MySQL]).
<span style="color:red">Внимание!</span> Методы update и delete могут быть применены к запросу только один раз, не могут сочетаться, не могут быть применены после insert_into или replace_into, и аннулируют действие на запрос методов select, group, order, distinct, count, value, включая их предыдущие применения к запросу <span style="color:#f00">(!)</#span>. Кроме того, невозможно применение методов update и delete к запросам, имеющим подзапросы в качестве derived table. При попытке любого из таких запрещённых действий генерируются предупреждения, а вызов игнорируется.
==== Бинарные преобразования ====
А такого понятия, как оптимизация подзапросов, здесь просто не существует, она здесь не нужна! Потому что программист всегда видит перед собой цепочку преобразований такую, что логически каждое следующее преобразование — это подзапрос из предыдущего. Следовательно, использование явных подзапросов не нужно вообще — если где-то нужен подзапрос, транслятор его вставит сам, а если не нужен, то зачем париться и писать лишний вызов, раз это не меняет результат?! Хотя само преобразование '''Wrap''' остаётся для внутреннего использования транслятором. А «условно совместимые» пары преобразований, то есть пары, поведение которых зависит от того, есть между ними подзапрос или нет, отслеживается с помощью переменной «предпочтения подзапроса».
Далее, существует отдельный класс «группа преобразований» ([{{SVN|vitaphoto/branch/solstice/lib-sway/Funq/mysql/Group.pm}} Funq::mysql::Group] для [http://www.mysql.org/ MySQL]), логически описывающий ОДИН SQL-запрос/подзапросу, и НЕ описывающий его подзапросы. У каждого объекта [[Funq]]-преобразования есть метод compile, который в передаваемую ему группу преобразований записывает информацию о себе. В группу преобразований попадают, во-первых, только совместимые преобразования, а во-вторых, только выражения с реальными именами таблиц и полей. То есть, трансляцией имён таблиц и полей «группа преобразований» не занимается.
На выходе транслятора получается специальное представление «полуфабриката SQL-запроса» — связный список, элементы которого могут быть:
[[Категория:Perl]]
[[Категория:РазработкаАрхив]]

Навигация