[Moscow.pm] конструкторе sql запросов

vividsnow vividsnow на gmail.com
Вс Апр 6 17:31:18 PDT 2014


чтобы не изобретать велик, попробуйте для "where" использовать:

https://metacpan.org/pod/SQL::Abstract#where-where-order
https://metacpan.org/pod/SQL::Abstract#WHERE-CLAUSES

On 04/03/2014 10:06 PM, Nick Knutov wrote:
> Мне уже стало интересно и таки добил.
>
> Полный пример - https://gist.github.com/knutov/9959392
>
> Вопросы:
> 1) как и можно ли обойтись без временной переменной $t? Читал
> документацию, не придумал.
>
> 2) как бы вы это улучшили?
>
> 3) Этот конструктор не очень хорошо позволяет работать с уловиями IN ()
> в where и совсем не позволяет сделать опциональный вложенный селект со
> своими параметрами в where. Может кто-нибудь придумает как это сделать?
>
> ps: Нашел SQL::OOP -
> https://metacpan.org/pod/distribution/SQL-OOP/README.pod - который почти
> идеально мне подходит, кроме того, что много букв. Но интереснее сделать
> своё )
>
> pps: Главный кусок кода из гиста:
>
> sub query2 (@) {
> 	my ($in, $p, $o, $l) = @_;
>
> 	my @aa = map {my $t = $_; map { $_ .' '. $t->{$_}[0] . ' ? '} keys %$t}
> @$p;
> 	my @bb = map {my $t = $_; map {  $t->{$_}[1] } keys %$t} @$p;
>
> 	(join' ', $in, map @$_, grep $_->[1],
> 		 $p ? [where => join ' AND ', @aa] : (),
> 		 $o ? ['ORDER BY' => join ',', @$o] : (),
> 		 $l ? [limit => join ',', ('?') x @$l] : ()),
> 	$p ? @bb : (), $l ? @$l : ()
> }
>
> say Dumper query2 'SELECT i FROM t', [{'x' => ['=',99]}, {'a' =>
> ['=',1]},{'b' => ['>',3]}], ['id DESC','a ASC'], [0,1];
> }
>
> 03.04.2014 8:11, Nick Knutov пишет:
>>
>> Спасибо, я наконец проникся.
>>
>> Но при таком конструкторе не учитывается порядок следования полей в
>> условии AND, который иногда очень даже следует учитывать в случае с
>> MySQL. Пример:
>>
>> query 'select i from t', {qw(x 99 a 1 b 3)}, ['id desc','a asc'], [0,1];
>> даст
>> where a = ? and b = ? and x = ?
>>
>> И, может быть у вас есть готовый код, позволяющий сделать
>>
>> query 'select i from t', {'a' => ['=',1],'b' => ['>',3]}, ['id desc','a
>> asc'], [0,1];
>>
>> или чего-то такого по условиям, можно с другим входным форматом (надо
>> задавать не только =, но и <,>,IS, IS NOT, IN и т.д.)?
>>
>> У меня получилось:
>>
>> (join' ', $in, map @$_, grep $_->[1],
>> 	 $p ? [where => join ' and ', map $_.' '.$p->{$_}[0].' ?', keys%$p] : (),
>> 	 $o ? ['order by' => join ',', @$o] : (),
>> 	 $l ? [limit => join ',', ('?') x @$l] : ()),
>> $p ? map($_->[1], values $p) : (), $l ? @$l : ()
>>
>> Но оно стало еще менее читабельным. И если добавить поддержку {'a' =>
>> [1], ...}, считая, что если элемент один, то значение - единственный
>> элемент, а действие по умолчанию - "=", то код получается еще мене красивым.
>>
>>
>> upd: А если делать массив для соблюдения порядка, то для конструкции
>> [
>> 	{'x' => ['=',99]},
>> 	{'a' => ['=',1]},
>> 	{'b' => ['>',3]}
>> ]
>> слишком многоэтажные конструкции получаются.
>>
>>
>> 18.12.2013 14:07, vividsnow пишет:
>>> как вариант что-то вроде:
>>> https://gist.github.com/vividsnow/8d294801959975730fc3
>>> (возможно более специфичное к вашей задаче)
>>>
>>> On 12/18/2013 03:44 AM, Nick Knutov wrote:
>>>> Не вижу, чем мне это может помочь.
>>>>
>>>> В данном примере posts_sql_view() возвращает нечто очень большое и
>>>> сложное, например селект с джойнами по куче таблиц из селекта с джойнами.
>>>>
>>>> Как минимум, конструировать запрос мне надо начиная с того места, где
>>>> может быть WHERE. И, например, как тут - наличие LIMIT и его количество
>>>> зависит от других параметров.
>>>>
>>>>
>>>> 18.12.2013 5:34, vividsnow пишет:
>>>>> https://metacpan.org/pod/SQL::Abstract
>>>>>
>>>>>
>>>>> 2013/12/18 Nick Knutov <mail на knutov.com <mailto:mail на knutov.com>>
>>>>>
>>>>>      У меня в коде в некоторых функциях, в зависимости от входных параметров,
>>>>>      конструируются разные sql запросы. Пример:
>>>>>
>>>>>      my $sql = posts_sql_view();
>>>>>      $sql .= ' WHERE ' if $type or $id or $main;
>>>>>      do { $sql .= ' ty.id =? '; push @params, $type;} if $type;
>>>>>      do { $sql .= ' AND p.id =? LIMIT 1'; push @params, $id
>>>>>      } if $id;
>>>>>      $sql .= ' ORDER BY id DESC ' unless $id;
>>>>>      do { $sql .= ' LIMIT ? ' ; push @params, $limit } if $limit and not $id;
>>>>>
>>>>>      Мне не нравится как это визуально выглядит. Как бы вы это переписали,
>>>>>      чтобы было понятнее и читабельнее?
>>>>>
>>>>>      ps: в некоторых других случаях можно было бы использовать && вместо
>>>>>      do{}, но не тут.
>>>>>
>>>>>      pps: ORM предлагать и обсуждать не надо. Как минимум потому, что запросы
>>>>>      сложные и сложность/стоимость проверки того, что генерирует ORM
>>>>>      многократно выше любого профита от ORM в данной ситуации.
>>>>>
>>>>>      --
>>>>>      Best Regards,
>>>>>      Nick Knutov
>>>>>      http://knutov.com
>>>>>      ICQ: 272873706
>>>>>      Voice: +7-904-84-23-130 <tel:%2B7-904-84-23-130>
>>>>>      --
>>>>>      Moscow.pm mailing list
>>>>>      moscow-pm на pm.org <mailto:moscow-pm на pm.org> | http://moscow.pm.org
>>>>>
>>>>>
>>>>>
>>>>>
>>>>
>>
>


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