GetInfo.Ru – Компьютерная библиотека
Последние поступления
Как выбрать систему управления базы данных
Базы данных03/09/14
Этапы загрузки UNIX (в схеме)
Unix27/03/12
Gatewall Antispam: тотальный контроль электронной почты
Спам21/04/11
Мастер-класс: создаем Интернет-магазин (Часть 1)
Обзоры ПО20/04/11
CorelDRAW Graphics Suite X5: Что нового?
Обзоры ПО20/07/10
Добавить статью
Самые читаемые материалы
Дерево каталогов NESTED SETS (вложенные множества) и управление им(169706)
Дерево каталогов NESTED SETS (вложенные множества) и управление им. Часть 2(29012)
SQL сервер PostgreSQL(25113)
Теоретические основы реляционных баз данных(24222)
Как выбрать систему управления базы данных(22042)
Всего статей: 793Всего авторов: 364Подразделов: 47Добавлено за сутки: 0
Статьи  СТАТЬИ Форум  ФОРУМ Рейтинг  РЕЙТИНГ Поиск  ПОИСК Контакты  КОНТАКТЫ
» Главная » Базы данных » Дерево каталогов NESTED SETS (вложенные множества) и управление им. Часть 2

Дерево каталогов NESTED SETS (вложенные множества) и управление им. Часть 2


Сергей Томулевич
phoinix@asit.ru

Страницы: [ 1 ] [ 2 ] [ 3 ] [ 4 ] [ 5 ] [ 6 ] [ 7 ]

6.2.2. Возврат подчиненных узлов в виде массива:

Код:

sub get_child_in_array {
# Получаем данные: объект, перемещаемый узел, место перемещения, порядок перемещения
    my ($self, %common)= @_;
# перемещаемый узел
    my $unit = $common{'unit'} || undef;
# что выбираем
    my $branch = $common{'branch'} || undef;
# дополнительные поля запроса
    my $field = $common{'field'} || undef;
# если выбираем все поля
    $field = $self->{'table'}.'.*' if $field =~ /\*/;
# объявляем переменную, массив идентификаторов
    my @data;
# определяем данные узла
    if ($unit) {$self = &select_unit($self, $unit)}
    elsif (!$self->{'unit'}->{'id'}) {$unit = 'root'; $self->{'unit'}->{'level'} = '0'}
# определяем, есть ли подчиненные узлы
    unless ($unit eq 'root' || $self->{'unit'}->{'right'} - $self->{'unit'}->{'left'} > 1) {return [{id=>'none'}]}
# Производим выборку ветви
    my $sql = 'SELECT '.$self->{'id'}.', '.$self->{'left'}.', '.$self->{'right'}.', '.$self->{'level'}.
                ($field ? ', '.$field : '').
              ' FROM '.$self->{'table'}.
              ' WHERE '.
                $self->{'left'}.' > '.$self->{'unit'}->{'left'}.' AND '.
                $self->{'right'}.' < '.$self->{'unit'}->{'right'}.
# Если мультидерево, ограничение
                ($self->{'type'} eq 'M' ?
                 ' AND '.$self->{'multi'}.' = \''.$self->{'unit'}->{'multi'}.'\'' : '').
# Вся ветвь или непосредственный родитель
              ($branch && $branch eq 'all' ?
               ' ORDER BY '.$self->{'left'} :
               ' AND '.$self->{'level'}.' = \''.$self->{'unit'}->{'level'}.' + 1 ORDER BY '.$self->{'left'});
    my $sth = $self->{'DBI'}->prepare($sql); $sth->execute();
    while (my $row = $sth->fetchrow_hashref()) {push @data, $row}
    $sth->finish();
# возвращаем массив
    return \@data
}

Вызов:

...
my $unit = ... # Определяем идентификатор узла
...
use MyModule::NestedSets;
my $nested = new MyModule::NestedSets {table=>'catalog_category', type=>'M', DBI=>$dbh};
my $child = $nested->get_parent_in_array(unit=>$unit, branch=>'all', field=>'name AS name_field, note');
...

7. Проверка целостности дерева

Так как структура дерева использует неявное подчинение, существует вариант того что дерево может "разлететься", потерять организацию. Для этого используем проверки описанные в первой статье:

  • Левый ключ ВСЕГДА меньше правого;
  • Наименьший левый ключ ВСЕГДА равен 1;
  • Наибольший правый ключ ВСЕГДА равен двойному числу узлов;
  • Разница между правым и левым ключом ВСЕГДА нечетное число;
  • Если уровень узла нечетное число то тогда левый ключ ВСЕГДА нечетное число, то же самое и для четных чисел;
  • Ключи ВСЕГДА уникальны, вне зависимости от того правый он или левый;

Код:

sub check_tree {
# Получаем данные: объект
    my ($self, $repair) = @_;
# Результат проверки
    my %data;
# Левый ключ ВСЕГДА меньше правого
    my $sql = 'SELECT '.($self->{'type'} eq 'M' ?
                         $self->{'multi'}.' AS multi' : 'COUNT('.$self->{'id'}.') AS num').
              ' FROM '.$self->{'table'}.
              ' WHERE '.$self->{'left'}.' >= '.$self->{'right'}.
              ($self->{'type'} eq 'M' ? ' GROUP BY '.$self->{'multi'} : '');
    my $sth = $self->{'DBI'}->prepare($sql); $sth->execute();
    while (my $row = $sth->fetchrow_hashref()) {
        if ($self->{'type'} eq 'M') {$data{$$row{'multi'}} = 1}
        elsif ($$row{'num'} && $$row{'num'} > 0) {$data{'check'} = 'no'}
    }
    $sth->finish();
# Наименьший левый ключ ВСЕГДА равен 1
# Наибольший правый ключ ВСЕГДА равен двойному числу узлов

    $sql = 'SELECT '.($self->{'type'} eq 'M' ? $self->{'multi'}.' AS multi, ' : '').
               ' COUNT('.$self->{'id'}.') AS num, '.
               ' MIN('.$self->{'left'}.') AS lk, '.
               ' MAX('.$self->{'right'}.') AS rk'.
           ' FROM '.$self->{'table'}.
           ($self->{'type'} eq 'M' ? ' GROUP BY '.$self->{'multi'} : '');
    $sth = $self->{'DBI'}->prepare($sql); $sth->execute();
    while (my $row = $sth->fetchrow_hashref()) {
        unless ($$row{'lk'} == 1 && $$row{'rk'} / $$row{'num'} == 2) {
            if ($self->{'type'} eq 'M') {$data{$$row{'multi'}} = 1} else {$data{'check'} = 'no'}
        }
    }
    $sth->finish();
# Разница между правым и левым ключом ВСЕГДА нечетное число
    $sql = 'SELECT '.($self->{'type'} eq 'M' ?
                      $self->{'multi'}.' AS multi, ''COUNT('.$self->{'id'}.') AS num, ').
               ' MOD(('.$self->{'right'}.' - '.$self->{'left'}.'), 2) AS os'.
           ' FROM '.$self->{'table'}.
           ' GROUP BY '.$self->{'id'}.
           ' HAVING os = 0';
    $sth = $self->{'DBI'}->prepare($sql); $sth->execute();
    while (my $row = $sth->fetchrow_hashref()) {
        if ($self->{'type'} eq 'M') {$data{$$row{'multi'}} = 1}
        elsif ($$row{'num'} && $$row{'num'} > 0) {$data{'check'} = 'no'}
    }
    $sth->finish();

 
28.01.2005
Версия для печати Версия для печати Запомнить ссылку Запомнить ссылку
Ваша оценка:  1   2   3   4   5     

 О проектеПерепечаткаАвторамПартнерыО нас пишут
Наверх
©2003—2007. GETINFO.RU. ВСЕ ПРАВА ЗАЩИЩЕНЫ.