[Moscow.pm] SQL + \%hash -> SQL

Konstantin S. Uvarin khedin на gmail.com
Вт Апр 18 05:28:02 PDT 2017


Приветствую!

  Очередная безумная идея, рождённая вследствие просмотра SQL::Abstract и
всяких прочих LINQ. Периодически возникает ситуация, когда мы что-то
выбираем из базы, но конкретные критерии неизвестны заранее (date < ? или
date > ? или оба). Тут мне известны варианты:

* сделать нужный запрос руками ($sql .= (defined $x ? " foo = ?" : " foo IS
NULL");
* прогенерить из DSL;
* написать один раз функцию, которая генерит селект_заданного_типа для
данной конкретной модели;
* использовать ORM.

(Что я пропустил?..)

Ну и вот, собственно, идея: в большинстве случаев "каждый раз другие"
критерии - это на самом деле просто группа отношений, которые надо
применить к заранее известной таблице. Поэтому пишем шаблон запроса (как с
плейсхолдерами (foo =?)) + добавляем хеши условий вместо одиночных
значений. Т.е. используем SQL как DSL для описания SQL.

Что-то вроде

    my $template_query = "SELECT * FROM foobar f WHERE f.??? ORDER BY
created LIMIT ?";
    my %criteria = ( foo => 42, bar => undef );
    my ($normal_query, @param_list) = decorate_query( $template_query,
\%criteria, 12 );

    на выходе вместо трёх вопросов - "f.foo = ? AND f.bar IS NULL" и потом
два параметра (42, 12).

??? выбрано потому, что вряд ли кто-то в здравом уме напишет три
плейсхолдера подряд без пробелов. А префикс f. мы требуем, ибо может быть
более 1 таблицы (да и скорее всего будет много таблиц - типа пришёл DBA с
листочком - "я вам тут запросы соптимизировал, ннннадо?..").

И вторая часть - а как нам покороче записать foo < 5? SQL::Abstract
предлагает foo => { "<" => 5 }, но мне кажется, что можно сделать через
прототипы + overload (точнее, я уже сделал, но там такой код, что его
показывать стыдно):

    {
        foo => (value < 5) & (value != 3),
        bar => value->in("дыр", "бул", "щыл")),
    }

1. Чего не хватает в списке вариантов?
2. Есть ли уже что-то подобное?
3. Достаточно ли выразителен синтаксис t.???, или надо что-то поинтереснее?
А если мы хотим заранее определить поля? У меня была идея "t.???[city cost
created]", но, может, что-то получше можно?

Всем хорошего (остатка) дня!

-- 
Konstantin S. Uvarin
jabber: see <from>
skype: kuvarin
http://github.com/dallaylaen
----------- следущая часть -----------
Вложение в формате HTML было извлечено…
URL: <http://mail.pm.org/pipermail/moscow-pm/attachments/20170418/26261b6a/attachment.html>


Подробная информация о списке рассылки Moscow-pm