[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