<div dir="ltr">А чем не понравился  ВИШчЖЖСдфы  или другие ORM, которые используют SQL::Abstract?<div><br></div><div>Как минимум, они берут на себя и такие вещи, как join/prefetch/having etc..</div></div><div class="gmail_extra"><br><div class="gmail_quote">18 апреля 2017 г., 15:28 пользователь Konstantin S. Uvarin via Moscow-pm <span dir="ltr"><<a href="mailto:moscow-pm@pm.org" target="_blank">moscow-pm@pm.org</a>></span> написал:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div class="gmail_default" style="font-family:monospace,monospace">Приветствую!<br><br></div><div class="gmail_default" style="font-family:monospace,monospace">  Очередная безумная идея, рождённая вследствие просмотра SQL::Abstract и всяких прочих LINQ. Периодически возникает ситуация, когда мы что-то выбираем из базы, но конкретные критерии неизвестны заранее (date < ? или date > ? или оба). Тут мне известны варианты:<br><br></div><div class="gmail_default" style="font-family:monospace,monospace">* сделать нужный запрос руками ($sql .= (defined $x ? " foo = ?" : " foo IS NULL");<br></div><div class="gmail_default" style="font-family:monospace,monospace">* прогенерить из DSL;<br></div><div class="gmail_default" style="font-family:monospace,monospace">* написать один раз функцию, которая генерит селект_заданного_типа для данной конкретной модели;<br></div><div class="gmail_default" style="font-family:monospace,monospace">* использовать ORM.<br><br></div><div class="gmail_default" style="font-family:monospace,monospace">(Что я пропустил?..) <br></div><div class="gmail_default" style="font-family:monospace,monospace"><br></div><div class="gmail_default" style="font-family:monospace,monospace">Ну и вот, собственно, идея: в большинстве случаев "каждый раз другие" критерии - это на самом деле просто группа отношений, которые надо применить к заранее известной таблице. Поэтому пишем шаблон запроса (как с плейсхолдерами (foo =?)) + добавляем хеши условий вместо одиночных значений. Т.е. используем SQL как DSL для описания SQL.<br><br></div><div class="gmail_default" style="font-family:monospace,monospace">Что-то вроде<br><br></div><div class="gmail_default" style="font-family:monospace,monospace">    my $template_query = "SELECT * FROM foobar f WHERE f.??? ORDER BY created LIMIT ?";<br></div><div class="gmail_default" style="font-family:monospace,monospace">    my %criteria = ( foo => 42, bar => undef );<br></div><div class="gmail_default" style="font-family:monospace,monospace">    my ($normal_query, @param_list) = decorate_query( $template_query, \%criteria, 12 );<br><br></div><div class="gmail_default" style="font-family:monospace,monospace">    на выходе вместо трёх вопросов - "f.foo = ? AND f.bar IS NULL" и потом два параметра (42, 12). <br><br></div><div class="gmail_default" style="font-family:monospace,monospace">??? выбрано потому, что вряд ли кто-то в здравом уме напишет три плейсхолдера подряд без пробелов. А префикс f. мы требуем, ибо может быть более 1 таблицы (да и скорее всего будет много таблиц - типа пришёл DBA с листочком - "я вам тут запросы соптимизировал, ннннадо?..").<br></div><div class="gmail_default" style="font-family:monospace,monospace"><br></div><div class="gmail_default" style="font-family:monospace,monospace">И вторая часть - а как нам покороче записать foo < 5? SQL::Abstract предлагает foo => { "<" => 5 }, но мне кажется, что можно сделать через прототипы + overload (точнее, я уже сделал, но там такой код, что его показывать стыдно):<br><br></div><div class="gmail_default" style="font-family:monospace,monospace">    {<br></div><div class="gmail_default" style="font-family:monospace,monospace">        foo => (value < 5) & (value != 3),<br></div><div class="gmail_default" style="font-family:monospace,monospace">        bar => value->in("дыр", "бул", "щыл")),<br>    }<br><br></div><div class="gmail_default" style="font-family:monospace,monospace">1. Чего не хватает в списке вариантов?<br></div><div class="gmail_default" style="font-family:monospace,monospace">2. Есть ли уже что-то подобное?<br></div><div class="gmail_default" style="font-family:monospace,monospace">3. Достаточно ли выразителен синтаксис t.???, или надо что-то поинтереснее? А если мы хотим заранее определить поля? У меня была идея "t.???[city cost created]", но, может, что-то получше можно? <br><br></div><div class="gmail_default" style="font-family:monospace,monospace">Всем хорошего (остатка) дня!<span class="HOEnZb"><font color="#888888"><br></font></span></div><span class="HOEnZb"><font color="#888888"><br>-- <br><div class="m_-5652066752214567417gmail_signature"><div dir="ltr"><div><div><div><font face="monospace,monospace">Konstantin S. Uvarin<br></font></div><font face="monospace,monospace">jabber: see <from><br></font></div><font face="monospace,monospace">skype: kuvarin<br></font></div><font face="monospace,monospace"><a href="http://github.com/dallaylaen" target="_blank">http://github.com/dallaylaen</a><br></font></div></div>
</font></span></div>
<br>--<br>
Moscow.pm mailing list<br>
<a href="mailto:moscow-pm@pm.org">moscow-pm@pm.org</a> | <a href="http://moscow.pm.org" rel="noreferrer" target="_blank">http://moscow.pm.org</a><br>
<br></blockquote></div><br></div>