Vous n'êtes pas identifié(e).
Pages : 1
Bonjour à tous,
Je recontre un problème avec les triggers de PostgreSQL. En effet, il m'est impossible de modifier une colonne de type boolean par l'intermédiaire d'un trigger.
Voici mon code procédural PL/pgSQL
1. DECLARE
2. cur INTEGER;
3. im INTEGER;
4. pfID INTEGER;
5. dis BOOLEAN;
6. BEGIN
7.
8. IF (TG_OP = 'UPDATE') THEN
9. cur = NEW.current_size;
10. lim = OLD.files_limit;
11. pfID = NEW.photo_folder_id;
12. END IF;
13.
14. IF (cur >= lim) THEN
15. UPDATE t_photo_folder
16. SET disabled = TRUE
17. WHERE photo_folder_id = pfID;
18. RETURN NULL;
18. END IF;
19.
20. RETURN NULL;
21. END;
J'obtient l'erreur suivante :
2009-08-18 10:22:49 ERROR : ERREUR: dépassement de limite (en profondeur) de la pile
HINT: Augmenter le paramètre « max_stack_depth » après vous être assuré que la
limite de profondeur de la pile de la plateforme est adéquate.
CONTEXT: instruction SQL « UPDATE t_photo_folder SET disabled = TRUE WHERE photo_folder_id = $1 »
PL/pgSQL function "change_folder_status" line 15 at SQL statement
instruction SQL « UPDATE t_photo_folder SET disabled = TRUE WHERE photo_folder_id = $1 »
PL/pgSQL function "change_folder_status" line 15 at SQL statement
instruction SQL « UPDATE t_photo_folder SET disabled = TRUE WHERE photo_folder_id = $1 »
PL/pgSQL function "change_folder_status" line 15 at SQL statement
instruction SQL « UPDATE t_photo_folder SET disabled = TRUE WHERE photo_folder_id = $1 »
PL/pgSQL function "change_folder_status" line 15 at SQL statement
instruction SQL « UPDATE t_photo_folder SET disabled = TRUE WHERE photo_folder_id = $1 »
La table t_photo_folder
{
photo_folder_id INTEGER
name VARCHAR2
current_size INTEGER
files_limit INTEGER
disabled BOOLEAN
}
J'ai essayé de modifier la colonne files_limit avec mon UPDATE et de la changer par une autre valeur et cela fonctionne sans problème. J'ai pas de soucis aussi avec les intructions INSERT et DELETE.
Donc je ne comprends pas du tout d'où vient le problème. Merci d'avance de votre aide.
Dernière modification par GoLDoRaK (19/08/2009 10:34:05)
Hors ligne
Hé bien, c'est assez simple une fois qu'on a pigé
Vous faites un UPDATE de t_photo_folder qui déclenche le trigger, qui exécute une fonction qui fait un UPDATE sur t_photo_folder qui déclenche le trigger qui exécute une fonction qui fait un UPDATE sur t_photo_folder qui déclenche le trigger qui... vous comprenez je pense
Bref, il ne faut pas faire un UPDATE sur la table qui est celle du trigger. Il vous faut modifier la fonction trigger par :
1. DECLARE
2. cur INTEGER;
3. im INTEGER;
4. pfID INTEGER;
5. dis BOOLEAN;
6. BEGIN
7.
8. IF (TG_OP = 'UPDATE') THEN
9. cur = NEW.current_size;
10. lim = OLD.files_limit;
11. pfID = NEW.photo_folder_id;
12. END IF;
13.
14. IF (cur >= lim) THEN
15. disabled = TRUE;
18. END IF;
19.
20. RETURN NULL;
21. END;
Par contre, je ne suis pas sûr pour le RETURN NULL, tout dépend s'il s'agit d'un trigger BEFORE ou AFTER.
Guillaume.
Hors ligne
Par contre, je trouve bizarre de comparer une limite de fichiers avec une taille... mais bon, rien à voir avec le soucis de récursion.
Guillaume.
Hors ligne
Merci pour votre réponse guillaume,
En effet, ca tombe dans une boucle infinie, je comprends mieux mon erreur.
Par contre, je ne peux pas mettre directement la colone disabled = true. Il m'envoie l'erreur suivante :
CONTEXT: SQL statement in PL/PgSQL function "change_folder_status" near line 14
2009-08-18 11:12:16 ERROR : ERREUR: erreur de syntaxe sur ou près de « disabled »
LINE 1: disabled = TRUE
^
C'est un trigger after, donc il est appellé après un update sur la table t_photo_folder.
Pour répondre à votre curiosité, je compare le nombre total de fichiers dans un dossier à le nombre courant de fichier dans le dossier : en effet, il faut que je renomme ma colonne en current_files_number.
Hors ligne
Oups, boulette de ma part. Il faut utiliser := et on doit utiliser la table NEW:
1. DECLARE
2. cur INTEGER;
3. im INTEGER;
4. pfID INTEGER;
5. dis BOOLEAN;
6. BEGIN
7.
8. IF (TG_OP = 'UPDATE') THEN
9. cur = NEW.current_size;
10. lim = OLD.files_limit;
11. pfID = NEW.photo_folder_id;
12. END IF;
13.
14. IF (cur >= lim) THEN
15. NEW.disabled := TRUE;
18. END IF;
19.
20. RETURN NULL;
21. END;
De plus, à mon souvenir, si vous devez modifier un élément de la table, il faut que ce soit un trigger before. Et la valeur du RETURN doit être NEW.
Guillaume.
Hors ligne
En effet, je viens de changer mon trigger en BEFORE avec le code procédural suivante :
DECLARE
cur INTEGER;
lim INTEGER;
BEGIN
IF (TG_OP = 'UPDATE') THEN
cur = NEW.current_files_number;
lim = OLD.files_limit;
END IF;
IF (cur >= lim) THEN
NEW.disabled := TRUE;
RETURN NEW;
END IF;
RETURN NEW;
END;
cela marche parfaitement.
Merci beaucoup de votre aide.
Dernière modification par GoLDoRaK (19/08/2009 11:39:30)
Hors ligne
Si votre trigger ne se déclenche que pour un UPDATE, vous pouvez encore simplifier le code:
BEGIN
IF NEW.current_files_number >= OLD.files_limit THEN
NEW.disabled := TRUE;
END IF;
RETURN NEW;
END;
Guillaume.
Hors ligne
Je viens d'appliquer votre conseil, merci encore pour votre aide précieuse.
Hors ligne
Pages : 1