• 15 апреля стартует «Курс «SQL-injection Master» ©» от команды The Codeby

    За 3 месяца вы пройдете путь от начальных навыков работы с SQL-запросами к базам данных до продвинутых техник. Научитесь находить уязвимости связанные с базами данных, и внедрять произвольный SQL-код в уязвимые приложения.

    На последнюю неделю приходится экзамен, где нужно будет показать свои навыки, взломав ряд уязвимых учебных сайтов, и добыть флаги. Успешно сдавшие экзамен получат сертификат.

    Запись на курс до 25 апреля. Получить промодоступ ...

Перемещение узлов Nested Sets. Формирование Sql запроса

  • Автор темы artkl
  • Дата начала
A

artkl

Здравствуйте уважаемые программисты.
Обращаюсь к вам, так как сам дурак и не могу понять суть формирования sql запроса в БД (MySql), для перемещения узлов дерева, упакованных по методу nested sets.
Вообщем есть класс управления деревьями, часть которого я и выкладываю:

PHP:
<?php
/**
* Класс обработки иерархии в БД (nested sets)
*/
Class Tree
{
var $CI; //Глобальный объект ядра CI
//Основные поля используемые в таблице
var $t_id			= 't_id'; //уникальный индетификатор каждого узла
var $right_key		= 'right_key'; //правый ключ
var $left_key		 = 'left_key'; //левый ключ
var $level			 = 'level';
var $name			 = 'name'; //имя узла
var	$description	= 'description'; //описание узла

var $table_name	= 'taxonomy';

var $return			= array(); // Сообщения возвращаемые после выполнения

function __construct()
{
$this->CI =& get_instance();

$this->CI->load->database();
}
/*********************************************************************
* Возвращает информацию о узле.
* Уровень, правый и левый ключ
*/
private function get_info_node($t_id)
{
$t_id = (int)$t_id;

$get = 'SELECT '.$this->left_key.','.$this->right_key.','.$this->level.' FROM `'.$this->table_name.'` WHERE `'.$this->t_id.'`='.$t_id;
$get = $this->CI->db->query($get);
$get = $get->result_array();

//Если делаем перемещение в корень, то возвращаем уровень = 0, максимальный правый и минимальный левый ключи
if($t_id==0)
{
$get = 'SELECT max('.$this->right_key.'), min('.$this->left_key.') FROM `'.$this->table_name.'`';
$get = $this->CI->db->query($get);
$get = $get->result_array();

return array(0,$get['0']['right_key'],$get['0']['left_key']);
}

if(count($get)>0) return array($get['0']['level'],$get['0']['right_key'],$get['0']['left_key']);
//else return false;
else echo 'count <= 0';
die;
}
/*********************************************************************
* Перемещение узла.
* $t_id : id перемещаемого узла
* $parrent_t_id : id нового родителя
*/
function move($t_id,$parrent_t_id)
{
list($level,$right_key,$left_key) = $this->get_info_node($t_id);
list($level_near,$right_key_near,$left_key_near) = $this->get_info_node($parrent_t_id);

$skew_level = $level_near - $level + 1;
$skew_tree = $right_key - $left_key;

if($right_key_near > $right_key)
{
$skew_edit = $right_key_near - $left_key + 1;
$get = 'UPDATE '.$this->table_name.'
SET
'.$this->right_key.' = CASE WHEN '.$this->left_key.' >= '.$left_key.'
THEN '.$this->right_key.' + '.$skew_edit.'
ELSE CASE WHEN '.$this->right_key.' < '.$left_key.'
THEN '.$this->right_key.' + '.$skew_tree.'
ELSE '.$this->right_key.'
END
END,
'.$this->level.' = CASE WHEN '.$this->left_key.' >= '.$left_key.'
THEN '.$this->left_key.' + '.$skew_level.'
ELSE '.$this->left_key.'
END,
'.$this->left_key.' = CASE WHEN '.$this->left_key.' >= '.$left_key.'
THEN '.$this->left_key.' + '.$skew_edit.'
ELSE CASE WHEN '.$this->left_key.' > '.$right_key_near.'
THEN '.$this->left_key.' + '.$skew_tree.'
ELSE '.$this->left_key.'
END
END
WHERE
'.$this->right_key.' > '.$right_key_near.' AND
'.$this->left_key.' < '.$right_key;
echo $this->CI->db->query($get);
} else
{
echo "else. debug! :) #156 in libraries/Tree.php";
}
}

Метод move() полностью не дописан, пока что только реализован вариант перемещения в "область вышестоящих узлов"
При написании, пользовался статьей.

Так вот, при выполнении запроса в БД меняется только значение level у корневого узла (+1,+3)(!!! :KillMe: ), а остальные значения остаются неизменными.
По всякому пробовал извращаться над кодом, не помогло. Пробовал выполнять запрос ко всем типам таблиц (MyISAM,InnoDB и т.д.)

Извините за наглость, но наведите на верный путь в плане формирования sql-запроса на перемещение, пожалуйста. Самому в голову уже ничего не приходит.

PS В данный момент работаю с фрейворком Codeiginter.
PSS Если возможно, без закидывания тухлыми помидорами, я только учусь..
 
A

artkl

Проблема решена путем заимствования sql-запроса из готовой для работы с nested sets :KillMe:

Хотя суть составления запроса все равно не понятна. Думаю следует прикупить литературу по sql.

Тему можно закрывать.
 
Мы в соцсетях:

Обучение наступательной кибербезопасности в игровой форме. Начать игру!