Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Problem z funkcja rekurencyjna (dosyc dlugie)
Forum PHP.pl > Forum > Bazy danych > PostgreSQL
delta9
Postgres 8.2

mam nastepujaca tabele:

T = (page_id. parent_page_id, title)

title sobie odpuscimy bo nie jest istotne dla problemu (ale pobieram pozniej w zapytaniu)

page_id | parent_page_id
2 | 0
4 | 3
3 | 2
6 | 4
7 | 2
9 | 0
10 | 9

czyli kazde page_id albo nie ma (0) albo posiada rodzica i tworzy sie nam pewna hierachia

chcialbym wyswietlic finalnie takie drzewko:

-2
--3
--7
---4
----6
-9
--10

napisalem funckje rekurencyjna i funkcje opakowujaca ktora zalatwia tabele tymczasowe itd:

funkcja opakowujaca:

  1. CREATE OR REPLACE FUNCTION get_list_pages_final()
  2. RETURNS SETOF t_get_list_pages_out AS $BODY$
  3. DECLARE
  4. result t_get_list_pages_out;
  5. test1 integer;
  6. test2 integer;
  7. q TEXT;
  8. BEGIN -- tabele tymczasowe ...
  9. q := 'SELECT count(relname) FROM pg_class WHERE relname = 'tt_get_list_pages_temp'';
  10. execute q INTO test1; IF test1 = 0 then
  11. raise notice 'tworze tt_get_list_pages_temp';
  12. EXECUTE 'CREATE TEMP TABLE tt_get_list_pages_temp (page_id INT, depth INT)';
  13. else raise notice 'NIE TWORZE tt_get_list_pages_temp';
  14. end IF;
  15.  
  16. execute 'INSERT INTO tt_get_list_pages_temp VALUES (0,0)';
  17.  
  18. q := 'SELECT count(relname) FROM pg_class WHERE relname = 'tt_get_list_pages_result'';
  19. execute q INTO test2; IF test2 = 0 then
  20. raise notice 'tworze tt_get_list_pages_result';
  21. EXECUTE 'CREATE TEMP TABLE tt_get_list_pages_result (page_id INT, title TEXT, depth INT)';
  22. else raise notice 'NIE TWORZE tt_get_list_pages_result';
  23. end IF;
  24.  
  25. -- uruchimineie funckji rekurencyjnej
  26. perform * FROM get_list_pages_rek(0); FOR result IN SELECT * FROM tt_get_list_pages_result LOOP
  27. RETURN next result;
  28. end loop;
  29.  
  30. -- sprzatanie
  31. TRUNCATE TABLE tt_get_list_pages_temp;
  32. TRUNCATE TABLE tt_get_list_pages_result;
  33. END;
  34. $BODY$
  35. LANGUAGE 'plpgsql' VOLATILE;


i glowna funkcja rekurencyjna:
  1. CREATE OR REPLACE FUNCTION get_list_pages_rek(_page_id integer)
  2. RETURNS void AS $BODY$
  3. DECLARE
  4. root RECORD;
  5. _depth INT := 0;
  6. q TEXT;
  7. BEGIN FOR root IN SELECT page_id, title FROM pages WHERE parent_page_id = _page_id LOOP
  8. raise notice 'root=%',root;
  9. -- pobranie aktualnego poziomu
  10. q := 'SELECT depth FROM tt_get_list_pages_temp WHERE page_id = 0'; -- 1 na stale
  11. execute q INTO _depth; _depth := _depth + 1;
  12. raise notice 'depth=%',_depth;
  13. -- update tabeli tymczasowej
  14. execute 'UPDATE tt_get_list_pages_temp SET depth = ' || quote_literal(_depth) || ' WHERE page_id = 0';
  15. -- update tabeli wynikow
  16. execute 'INSERT INTO tt_get_list_pages_result VALUES ( ' || quote_literal(root.page_id) || ', ' || quote_literal(root.title) || ', ' || quote_literal(_depth) ||')';
  17. -- rekurencyjne wywolanie funkcji
  18. execute get_list_pages_rek(root.page_id);
  19. END LOOP;
  20. raise notice 'ITERACJA ZAKONCZONA';
  21. execute 'UPDATE tt_get_list_pages_temp SET depth = 1 WHERE page_id = 0';
  22. END;
  23.  
  24. $BODY$
  25. LANGUAGE 'plpgsql' VOLATILE;



reszta postu (za dlugi sie okazal)


po uruchomieniu

  1. SELECT * FROM get_list_pages_final()


dostaje takie messages: (bez bledow, bardziej debugowo)

Kod
NOTICE:  NIE TWORZE tt_get_list_pages_temp
NOTICE:  NIE TWORZE tt_get_list_pages_result
NOTICE:  root=(2,"tytul strony")
CONTEXT:  SQL statement "select * from get_list_pages_rek(0)"
PL/pgSQL function "get_list_pages_final" line 28 at execute statement
NOTICE:  depth=1
CONTEXT:  SQL statement "select * from get_list_pages_rek(0)"
PL/pgSQL function "get_list_pages_final" line 28 at execute statement
NOTICE:  root=(3,"inny tytul")
CONTEXT:  PL/pgSQL function "get_list_pages_rek" line 18 at execute statement
SQL statement "select * from get_list_pages_rek(0)"
PL/pgSQL function "get_list_pages_final" line 28 at execute statement
NOTICE:  depth=2
CONTEXT:  PL/pgSQL function "get_list_pages_rek" line 18 at execute statement
SQL statement "select * from get_list_pages_rek(0)"
PL/pgSQL function "get_list_pages_final" line 28 at execute statement
NOTICE:  root=(4,kolejna)
CONTEXT:  PL/pgSQL function "get_list_pages_rek" line 18 at execute statement
PL/pgSQL function "get_list_pages_rek" line 18 at execute statement
SQL statement "select * from get_list_pages_rek(0)"
PL/pgSQL function "get_list_pages_final" line 28 at execute statement
NOTICE:  depth=3
CONTEXT:  PL/pgSQL function "get_list_pages_rek" line 18 at execute statement
PL/pgSQL function "get_list_pages_rek" line 18 at execute statement
SQL statement "select * from get_list_pages_rek(0)"
PL/pgSQL function "get_list_pages_final" line 28 at execute statement
NOTICE:  root=(6,"inny tytul")
CONTEXT:  PL/pgSQL function "get_list_pages_rek" line 18 at execute statement
PL/pgSQL function "get_list_pages_rek" line 18 at execute statement
PL/pgSQL function "get_list_pages_rek" line 18 at execute statement
SQL statement "select * from get_list_pages_rek(0)"
PL/pgSQL function "get_list_pages_final" line 28 at execute statement
NOTICE:  depth=4
CONTEXT:  PL/pgSQL function "get_list_pages_rek" line 18 at execute statement
PL/pgSQL function "get_list_pages_rek" line 18 at execute statement
PL/pgSQL function "get_list_pages_rek" line 18 at execute statement
SQL statement "select * from get_list_pages_rek(0)"
PL/pgSQL function "get_list_pages_final" line 28 at execute statement
NOTICE:  ITERACJA ZAKONCZONA
CONTEXT:  PL/pgSQL function "get_list_pages_rek" line 18 at execute statement
PL/pgSQL function "get_list_pages_rek" line 18 at execute statement
PL/pgSQL function "get_list_pages_rek" line 18 at execute statement
PL/pgSQL function "get_list_pages_rek" line 18 at execute statement
SQL statement "select * from get_list_pages_rek(0)"
PL/pgSQL function "get_list_pages_final" line 28 at execute statement
NOTICE:  ITERACJA ZAKONCZONA
CONTEXT:  PL/pgSQL function "get_list_pages_rek" line 18 at execute statement
PL/pgSQL function "get_list_pages_rek" line 18 at execute statement
PL/pgSQL function "get_list_pages_rek" line 18 at execute statement
SQL statement "select * from get_list_pages_rek(0)"
PL/pgSQL function "get_list_pages_final" line 28 at execute statement
NOTICE:  ITERACJA ZAKONCZONA
CONTEXT:  PL/pgSQL function "get_list_pages_rek" line 18 at execute statement
PL/pgSQL function "get_list_pages_rek" line 18 at execute statement
SQL statement "select * from get_list_pages_rek(0)"
PL/pgSQL function "get_list_pages_final" line 28 at execute statement
NOTICE:  root=(7,"tytul jakistam")
CONTEXT:  PL/pgSQL function "get_list_pages_rek" line 18 at execute statement
SQL statement "select * from get_list_pages_rek(0)"
PL/pgSQL function "get_list_pages_final" line 28 at execute statement
NOTICE:  depth=2
CONTEXT:  PL/pgSQL function "get_list_pages_rek" line 18 at execute statement
SQL statement "select * from get_list_pages_rek(0)"
PL/pgSQL function "get_list_pages_final" line 28 at execute statement
NOTICE:  ITERACJA ZAKONCZONA
CONTEXT:  PL/pgSQL function "get_list_pages_rek" line 18 at execute statement
PL/pgSQL function "get_list_pages_rek" line 18 at execute statement
SQL statement "select * from get_list_pages_rek(0)"
PL/pgSQL function "get_list_pages_final" line 28 at execute statement
NOTICE:  ITERACJA ZAKONCZONA
CONTEXT:  PL/pgSQL function "get_list_pages_rek" line 18 at execute statement
SQL statement "select * from get_list_pages_rek(0)"
PL/pgSQL function "get_list_pages_final" line 28 at execute statement
NOTICE:  root=(9,lalalal)
CONTEXT:  SQL statement "select * from get_list_pages_rek(0)"
PL/pgSQL function "get_list_pages_final" line 28 at execute statement
NOTICE:  depth=2
CONTEXT:  SQL statement "select * from get_list_pages_rek(0)"
PL/pgSQL function "get_list_pages_final" line 28 at execute statement
NOTICE:  root=(10,xcczxczxc)
CONTEXT:  PL/pgSQL function "get_list_pages_rek" line 18 at execute statement
SQL statement "select * from get_list_pages_rek(0)"
PL/pgSQL function "get_list_pages_final" line 28 at execute statement
NOTICE:  depth=3
CONTEXT:  PL/pgSQL function "get_list_pages_rek" line 18 at execute statement
SQL statement "select * from get_list_pages_rek(0)"
PL/pgSQL function "get_list_pages_final" line 28 at execute statement
NOTICE:  ITERACJA ZAKONCZONA
CONTEXT:  PL/pgSQL function "get_list_pages_rek" line 18 at execute statement
PL/pgSQL function "get_list_pages_rek" line 18 at execute statement
SQL statement "select * from get_list_pages_rek(0)"
PL/pgSQL function "get_list_pages_final" line 28 at execute statement
NOTICE:  ITERACJA ZAKONCZONA
CONTEXT:  PL/pgSQL function "get_list_pages_rek" line 18 at execute statement
SQL statement "select * from get_list_pages_rek(0)"
PL/pgSQL function "get_list_pages_final" line 28 at execute statement
NOTICE:  ITERACJA ZAKONCZONA
CONTEXT:  SQL statement "select * from get_list_pages_rek(0)"
PL/pgSQL function "get_list_pages_final" line 28 at execute statement

Total query runtime: 20 ms.
7 rows retrieved.


ogolnie mam nastepujace problemy:

1.

Kod
NOTICE:  root=(2,"tytul strony")
CONTEXT:  SQL statement "select * from get_list_pages_rek(0)"
PL/pgSQL function "get_list_pages_final" line 28 at execute statement
NOTICE:  depth=1


z tego co rozumiem, komunikat o wywolaniu 'get_list_pages_final' pojawia sie przed NOTICE: depth=1 a w kodzie NAJPIERW sie notice o depth a dopiero potem wywolanie - czy moze ty byc problem synchronizacji komunikatow?

2.

zwraca ogolnie dobre wyniki, ale dla page_id = 7 liczy zle, pokazuje 1 a powinno byc dwa - widac w messages ze cos nie tak (rekurencyjne wywoalnia bez wyswietlania NOTICE: root = xxxx ) tam zapewne jest blad ale siedze nad tym juz dlugo i nie potrafie dojsc w ktorym momencie zaczyna sie kaszana (jest to powiazane tez z pkt. 1 mojego pytania)

3.

wiem ze rozwiazanie nie jest optymalne, moze ma ktos lepszy pomysl na rozwiaznie? finalnie funckja ma pmagac rysowac drzewko zaleznosci dla stron w CMS'ie
Zbłąkany
ltree
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.