powered by simpleCommunicator - 2.0.60     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / рекурсивный вызов функции в plperl
5 сообщений из 5, страница 1 из 1
рекурсивный вызов функции в plperl
    #35751107
wmw85
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Вот нехитрая функция

CREATE OR REPLACE FUNCTION "public"."correct_keys_catalog" (integer, integer, integer)
RETURNS integer AS $$

my $key = $_[2] + 1;
my $lvl = $_[3] + 1;

my $ddd = 'SELECT id FROM portal_catalog WHERE parent_id = '.$_[1].' ORDER BY sort ASC;';
my $my_rv = spi_exec_query($ddd);

my $nrows = $my_rv->{processed};
foreach my $rn (0 .. $nrows - 1)
{
my $catalog_row = $my_rv->{rows}[$rn];
my $l_key = $key;

$recurs_q = 'SELECT * FROM correct_keys_catalog('.$catalog_row->{id}.', '.$l_key.', '.$lvl.');';
my $recurs = spi_exec_query($recurs_q);
$key = $recurs->{rows}[0]->{correct_keys_portal_catalog};

my $upd_query = 'UPDATE catalog SET left_key='.$l_key.', right_key='.$key.' WHERE id = '.$catalog_row->{id}.';';
spi_exec_query($upd_query);

$key++;
}

$lvl--;
return $key;

$$ LANGUAGE "plperl"
VOLATILE
CALLED ON NULL INPUT
SECURITY DEFINER;

для таблицы
CREATE TABLE "catalog"
(
"id" INTEGER NOT NULL,
"name" VARCHAR(255),
"left_key" INTEGER,
"right_key" INTEGER,
"inlev" INT2,
"parent_id" INTEGER default 0,
"num_goods" INTEGER,
"sort" INTEGER default 0,
"type" INTEGER default 1,
"ident" INTEGER,
"latin_name" VARCHAR(255),
PRIMARY KEY ("id")
);

Задача - корректировать левые/правые ключи дерева.
На php есть рекурсивная функция для решения этой задачи, но сейчас потребовалось переписать в субд.

В таком виде функция работает не корректно - при рекурсивном вызове всегда возвращает значение, полученное при первом вызове. Может рекурсия запрещена в plperl?
Или результаты выполнения как то кэшируются? Подскажите, пожалуста, уже много времени убил, не знаю где искать причину.
...
Рейтинг: 0 / 0
рекурсивный вызов функции в plperl
    #35751184
Фотография Ёш
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: plaintext
1.
2.
my $nrows = $my_rv->{processed};
foreach my $rn ( 0  .. $nrows -  1 )
может быть у Вас первый селект ничего не выбирает и как результат, $nrows = 0 и цикл не выполняется ? добавьте отладочный вывод и посмотрите, типа:

Код: plaintext
1.
2.
3.
4.
5.
6.
my $ddd = 'SELECT id FROM portal_catalog WHERE parent_id = '.$_[ 1 ].' ORDER BY sort ASC;';
elog(NOTICE, "ddd query: [$ddd]");
my $my_rv = spi_exec_query($ddd);

my $nrows = $my_rv->{processed};
elog(NOTICE, "nrows: '$nrows'");

Код: plaintext
1.
2.
3.
 $recurs_q = 'SELECT * FROM correct_keys_catalog('.$catalog_row->{id}.', '.$l_key.', '.$lvl.');';
 my $recurs = spi_exec_query($recurs_q);
 $key = $recurs->{rows}[ 0 ]->{correct_keys_portal_catalog};
по умолчанию колонка в результате вызова функции называется по имени этой функции - исправьте выделенное с
Код: plaintext
correct_keys_portal_catalog
на
Код: plaintext
correct_keys_catalog
или используйте алиасы


--
„Истина — это вовсе не то, что можно убедительно доказать, это то, что
делает всё проще и понятнее“ — Антуан де Сент-Экзюпери
...
Рейтинг: 0 / 0
рекурсивный вызов функции в plperl
    #35751270
wmw85
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Проверку поставил. Лишней не будет. Название столбца поменял, это просто опечатка. Работает как прежде.
При замене my на local

Код: plaintext
1.
2.
3.
4.
my $key = $_[ 2 ] +  1 ;
my $lvl = $_[ 3 ] +  1 ;

my $ddd = 'SELECT id FROM portal_catalog WHERE parent_id = '.$_[ 1 ].' ORDER BY sort ASC;';
my $my_rv = spi_exec_query($ddd);

либо выдает ошибку в строке
Код: plaintext
$recurs_q = 'SELECT * FROM correct_keys_catalog('.$catalog_row->{id}.', '.$l_key.', '.$lvl.');';

либо проставляет другие ключи, правда тоже не верные. Может здесь искать?
...
Рейтинг: 0 / 0
рекурсивный вызов функции в plperl
    #35751776
wmw85
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Вот вид в котором функция работает:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
CREATE OR REPLACE FUNCTION "public"."correct_keys_catalog" (integer, integer, integer) 
RETURNS integer AS $$

my $key = $_[ 1 ] +  1 ;
my $lvl = $_[ 2 ] +  1 ;
  
my $ddd = 'SELECT id FROM catalog WHERE parent_id = '.$_[ 0 ].' ORDER BY sort ASC;';
my $my_rv = spi_exec_query($ddd);
	 elog(NOTICE, "key,lvl,pid = [$key,$lvl,$_[0]]");
$nrows = $my_rv->{processed};
if($nrows >  0 )
{
	foreach my $rn ( 0  .. $nrows -  1 )
	{
	  	elog(NOTICE, "rn = [$rn]");
my $catalog_row = $my_rv->{rows}[$rn];
	  	$l_key = $key;
				$upd_query = 'UPDATE catalog SET left_key='.$l_key.', inlev='.$lvl.' WHERE id = '.$catalog_row->{id}.';';
elog(NOTICE, "$upd_query");
		spi_exec_query($upd_query);

	  	$recurs_q = 'SELECT * FROM correct_keys_catalog('.$catalog_row->{id}.', '.$l_key.', '.$lvl.');';

	  	$recurs = spi_exec_query($recurs_q);
		$key = $recurs->{rows}[ 0 ]->{correct_keys_catalog};
	
		$upd_query = 'UPDATE catalog SET right_key='.$key.' WHERE id = '.$catalog_row->{id}.';';
elog(NOTICE, "$upd_query");
		spi_exec_query($upd_query);
		
		$key++;
	}
}
$lvl--;
return $key;

        
       
$$ LANGUAGE "plperl"
VOLATILE
CALLED ON NULL INPUT
SECURITY DEFINER;

Можно применять для деревьев вида
CREATE my_tree (
id INT(10) NOT NULL AUTO_INCREMENT,
name VARCHAR(150) NOT NULL,
left_key INT(10) NOT NULL DEFAULT 0,
right_key INT(10) NOT NULL DEFAULT 0,
level INT(10) NOT NULL DEFAULT 0,
PRIMARY KEY id,
INDEX left_key (left_key, right_key, level)
)

Наверняка изобрел велосипед. Если есть более оптимизированные примеры или предложения по оптимизации, пишите, наверняка кому-нибуь пригодится
...
Рейтинг: 0 / 0
рекурсивный вызов функции в plperl
    #35751780
wmw85
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Код: plaintext
elog(NOTICE, "$upd_query");
конечно лучше убрать :)
...
Рейтинг: 0 / 0
5 сообщений из 5, страница 1 из 1
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / рекурсивный вызов функции в plperl
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]