[Moscow.pm] аналог SQL View в DBIx

Alex Ivin alex на ivin.info
Сб Июл 19 13:11:02 PDT 2008


Привет всем,

как корректно сделать аналог SQL-вского View в DBIx ?

Т.е. оператор SQL

SELECT cms_menus.id,cms_menus.name,
    CASE cms_page_menus.id WHEN cms_page_menus.id THEN 1 ELSE 0 END is_enable 
FROM cms_menus 
LEFT JOIN cms_page_menus ON cms_page_menus.cms_menu_id=cms_menus.id 
    AND cms_page_menus.cms_page_id=XXXX


должен выдавать:

+----+----------+-----------+
| id | name     | is_enable |
+----+----------+-----------+
|  2 | Sub Menu |         0 |
|  1 | Top Menu |         1 |
+----+----------+-----------+



и этот оператор хочеться оформить в виде объекта DBIx и вызывать 
примерно так:

my $menu_items =  [$c->model('DB::CmsSomeView')->search(
                                                         undef , 
                                                        )];


Пока нашел такое решение:
package DB::CmsView1;

use strict;
use warnings;

use base 'DBIx::Class::Core';

__PACKAGE__->table("DUMMY");
__PACKAGE__->add_columns(qw/id name is_enable /);
__PACKAGE__->result_source_instance->name(\'(SELECT 
cms_menus.id,cms_menus.name,CASE cms_page_menus.id WHEN 
cms_page_menus.id THEN 1 ELSE 0 END is_enable FROM cms_menus  LEFT JOIN 
cms_page_menus ON cms_page_menus.cms_menu_id=cms_menus.id     AND 
cms_page_menus.cms_page_id=?)');

1;
------------------
непосредcтвенно в контроллере (Catalyst) вызываю:

 my $menu_items = [$c->model('CmsView1')->search( {} , {bind => 
[$page_id]})];


Все работает, нужные поля возвращаются.

Но, как в том анекдтоте - "есть нюанс"...
в MySql выстреливается запрос:
SELECT me.id, me.name, me.is_enable FROM (SELECT 
cms_menus.id,cms_menus.name,CASE cms_page_menus.id WHEN 
cms_page_menus.id THEN 1 ELSE 0 END is_enable FROM cms_menus  LEFT JOIN 
cms_page_menus ON cms_page_menus.cms_menu_id=cms_menus.id     AND 
cms_page_menus.cms_page_id=?) me: '2'

Что ни разу не кошерно. Цель использования "вьюхи" - оптимизация 
скорости работы приложения, а какая тут нафиг оптимизация если идет 
вложенный SELECT.


Есть еще вариант "опустится" до использования DBi без всякой там ORM  
фигни для критичных по скорости запросов, но во первых тут появится 
дополнительное соединение с базой данных, а во вторых хочеться остаться 
в рамках DBIx.


Гдето в обзоре я читал что DBIx  позволяет выполнять нативные SQL 
запросы. Интересно как это можно сделать почеловечески?


Уйти от возможности выдать нативный SQL запрос в сторону  "истинного 
ORM" не предлагать, ибо оптимизировать тяжело нагруженную БД через
 DBIx::Class::Relationship 
<http://search.cpan.org/%7Eash/DBIx-Class-0.08007/lib/DBIx/Class/Relationship.pm> 
это все равно что наклеивать обои через щель почтового ящика. А я все 
таки не на конкурсе гинекологов.


С уважением
Alex Ivin



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