Vous n'êtes pas identifié(e).
par contre ma règle usernew_insert2 refuse de fonctionner. pourtant la règle a bien été crée sans erreur.
ex : INSERT INTO LGPUSERNEW (password) VALUES ('pass');
>> ERREUR: une valeur NULL viole la contrainte NOT NULL de la colonne « nom »
Le premier problème est qu'il y a 2 règles AS ON INSERT TO LGPUSERNEW DO INSTEAD
et il n'en faudrait qu'une seule.
En l'état vraisemblablement PG exécute la 1ere règle d'abord et s'arrête net sur nom à NULL sans même exécuter la 2eme règle.
Le deuxième problème est que l'INSERT de la seconde règle est de toute façon invalide. Il faudrait plutôt qu'il ressemble à
INSERT INTO LGPUTILS VALUES
(default,
current_user,
NEW.PASSWORD);
La syntaxe colonne=valeur, c'est pour les UPDATEs.
Sinon sur le principe, utiliser des règles pour faire ça est excessivement compliqué à mettre au point et sans intérêt réel par rapport à une simple fonction procédurale.
:'( bouh bouh, va falloir modifier du code pour se connecter à postgresql malgré une compatibilité avec h2/sybase/oracle/sqlserver
Le code cité en exemple ne passe pas sous oracle non plus:
SQL> create table Tutu (isNull_ INTEGER);
Table created.
SQL> insert into Tutu Values(false);
insert into Tutu Values(false)
*
ERROR at line 1:
ORA-00984: column not allowed here
Autant pour la compatibilité inter-SGBD, le principe d'utiliser des entiers au lieu des booléens se tient tout à fait, autant une fois qu'on a fait ce choix, que vient faire le mot clef false dans une requête? C'est lui qui n'est pas supporté par tous les SGBDs, et plus généralement le concept de valeur booléenne en SQL (select 1=1 from dual ne fonctionne pas non plus)
Il me semble que ce trigger ne retourne pas NEW quand colonneA n'a pas changé et n'est pas NULL, dans ce cas il ne retourne rien.
C'est une erreur, il faut obligatoirement retourner NEW.
Accessoirement, pour ce genre de test le plus simple est d'utiliser IF new.colonneA IS DISTINCT FROM old.colonneA THEN... END IF, qui fonctionne comme attendu y compris quand il y a des valeurs nulles.
Je suis tout à vous pour des renseignements supplémentaires.
Le message d'erreur serait bien utile.
Sinon le même problème est évoqué sur stackoverflow:
http://stackoverflow.com/questions/3895 … postgresql
avec plusieurs pistes différentes proposées.
Aucune n'utilise pg_locks, ce qui à mon avis confirme ce qui est dit ici, mais certaines utilisent SELECT FOR UPDATE NOWAIT avec récupération de l'erreur "lock_not_available", intéressant pour se passer du flag+update supplémentaire évoqués plus haut.
La stratégie par introspection des locks est très délicate. De mémoire les lignes verrouillées ne sont pas dans pg_locks mais sur les pages disque de la table elle-même, l'intérêt étant qu'on peut verrouiller énormément de lignes sans consommer de mémoire ou d'espace disque ailleurs.
Une stratégie plus sûre serait plutôt d'implémenter la condition "ligne pas bloquée" avec une colonne dédiée à ça dans la table, le traitement s'appropriant la ligne avec un UPDATE conditionnel. Eventuellement cette colonne peut être un ID unique de traitement qui fait référence à une table des traitements pour un contrôle fin.
Existe-t-il un moyen de faire du PL/pgSQL sans créer de fonction ?
Oui, à partir de la 9.0 avec la commande DO:
L'update en question pourrait s'écrire à peu près comme ça avec postgres:
UPDATE Table1
SET colonneCount=s.monCount, colonneMax=s.monMax, colonneMin =s.monCount
FROM (SELECT COUNT(*) AS monCount, MAX(val) AS monMax, MIN(val) AS monMin FROM Table2) s
WHERE id = 1;
Et la version standard passe-partout serait plutôt:
UPDATE Table1
SET colonneCount = (SELECT COUNT(*) from Table2),
colonneMax= (SELECT MAX(val) from Table2),
colonneMin= (SELECT MIN(val) from Table2)
WHERE id=1;
La doc détaille le rôle de ces bases:
http://docs.postgresqlfr.org/9.0/manage … tedbs.html
Chez moi avec mysql 5.1.41 (ubuntu) ça donne ça:
mysql> select password('test');
+-------------------------------------------+
| password('test') |
+-------------------------------------------+
| *94BDCEBE19083CE2A1F959FD02F964C7AF4CFC29 |
+-------------------------------------------+
1 row in set (0.00 sec)
En fait la fonction password() a été changée à partir de mysql 4.1, donc apparemment tu utilises une version plus ancienne.
L'ancien comportement est disponible via old_password.
Voilà ce que donne old_password('test') sur mysql5:
mysql> select old_password('test');
+----------------------+
| old_password('test') |
+----------------------+
| 378b243e220ca493 |
+----------------------+
1 row in set (0.00 sec)
C'est bien ton résultat. Donc en fait c'est old_password() que tu veux.
L'algorithme de la fonction old_password() est spécifique à mysql, mais il est assez simple à réimplémenter, il y a un code php équivalent ici:
http://stackoverflow.com/questions/2602 … ementation
Ca parait tout à fait jouable en plpgsql.
L'équivalent de la fonction password() de mysql est:
'*' || upper(encode(digest(digest('LE MOT DE PASSE EN CLAIR','sha1'), 'sha1'), 'hex'))
La fonction digest() fait partie du module crypto (dans contrib)
PostgreSQL 8.4 est également (pour l'instant) installé sur le 192.168.0.36. Les exe sont dans G:\Wamp\PostgreSQL\bin (Windows 7)
La base, installée sur le serveur (192.168.0.15) , s'intitule basetest, le username est usertest et son password est userpasschcp 1252 set PSQL="G:\Wamp\PostgreSQL\bin" %PSQL%\pg_dump --host=192.168.0.15 --username=usertest basetest > c:\test.sql
Cela passe... Mais dans la console, je dois remplir "Mot de passe".
Il suffit d'ajouter
set PGPASSWORD=userpass
dans le script avant l'appel à pg_dump pour éviter la saisie manuelle.
Tu auras plus vite fait de supprimer le PREPARE qui n'est pas utile, dans le sens où tu peux faire:
CREATE TEMP TABLE tmpCas AS SELECT....
Le PREPARE est surtout utile quand une requête est réutilisée de multiples fois ce qui n'est pas le cas ici.
Il reste qu'à la fin de la fonction je ne pense pas que
SELECT * FROM t_cas;
fasse quelque chose en plpgsql.
Il faudrait plutot faire
RETURN QUERY SELECT * FROM t_cas;
Et il faudra aussi avant ça ajouter un DEALLOCATE pour libérer ce qu'a alloué le PREPARE.
Ah! C'est pas LANGUAGE sql qu'il faut pour la fonction , c'est plpgsql.
La fonction n'est même pas encore créée, je ne réussi pas à la faire compiler.
Je pensais que c'était une erreur d'exécution parce que le message d'erreur initial, celui-ci:
ERROR: relation "t_cas" does not exist
LINE 156: INSERT INTO t_cas(intCasId, strNoDossier, strConseillerNom,...
est visiblement une erreur d'exécution, pas une erreur de création de fonction.
Est-ce que tu pourrais copier-coller dans la discussion l'intégralité du create function dans sa version actuelle, message d'erreur inclus?
J'ai enlevé le point virgule et c'est la même chose.
Est-ce que ça pourrait avoir un lien avec mon schéma?
J'ai toutefois tenté de spécifier stirq. avant t_cas et j'ai le même problème..
C'est-à-dire que tu as une table stirq.t_cas qui existe et que INSERT INTO stirq.t_cas sort un message d'erreur disant qu'elle n'existe pas?
A ce niveau là on peut se demander si tu exécutes bien la version de la fonction que tu modifies.
Par exemple il pourrait y avoir une version dans le schéma public, une autre avec le même nom dans le schéma stirq.
Si à l'exécution il va chercher la fonction dans l'autre schéma, ça expliquerait que quoi que tu essaies ça ne change rien à l'erreur (qui n'a pas lieu d'être).
Il serait intéressant de vérifier que ton CREATE FUNCTION spécifie ou non un schéma, quel est le search_path au moment du CREATE FUNCTION, et est-ce que c'est le même search_path qu'au moment de l'exécution de la fonction, et enfin est-ce qu'il y a plusieurs instances de la fonction créées dans des schémas différents.
le problème c'est que l'"afficheur est réglé" sur latin1 et pas latin9
Un afficheur réglé sur latin1 ne pourrait pas afficher [œ] puisque ce caractère n'existe pas dans le jeu de caractères latin1.
Voir http://fr.wikipedia.org/wiki/ISO_8859-1
œ a pour code 189 en iso-8859-15
Il se trouve que ce code existe aussi en iso-8859-1 et il est attribué au caractère ½
Donc si tu rentres un caractère ½ dans une base latin1 et que tu le relis avec une interprétation latin9, tu vois œ
Il n'y a rien d'anormal là dedans si ce n'est le fait de lire des contenus latin1 avec un afficheur réglé sur latin9, ou inversement.
Une méthode sûre pour savoir où sont les fichiers de données:
show data_directory
en SQL.
On essaie de commenter la 1° ligne de type host, pour forcer les connexions à passer par les sockets Unix plutôt que par TCP/IP. Arrêt relance de postgres.
Au début semble permettre le bon fonctionnement de test_bug.php, mais au bout d'un moment les erreurs reviennent.
Il n'est pas possible de forcer les sockets unix de cette manière (en changeant uniquement le pg_hba.conf), c'est le client qui doit choisir s'il se connecte en socket unix ou TCP/IP.
Par ailleurs le message d'erreur indiqué côté client ne peut pas se produire avec une connexion par socket unix.
Pour se connecter en socket unix, mettre dans le champ host le chemin complet de la socket, commençant par un slash, par exemple host=/var/run/postgresql/.s.PGSQL.5432
Si nécessaire, regarder dans postgresql.conf pour avoir l'emplacement du fichier, ou netstat -l qui doit aussi l'indiquer
Dernière remarque, le post parle beaucoup de comparaison entre deux scripts, mais ces deux scripts n'utilisent pas la même méthode de connexion, il y en a qui fait:
$conn = @pg_connect("host=localhost dbname=toto user=dico password=toto");
et l'autre
$dbh = pg_connect("dbname=mabase user=postgres password=postgres");
Ce deuxième cas est dit "plantant régulièrement" mais le message d'erreur n'est pas indiqué, il serait utile de l'indiquer.
Apparement l'idée est de porter sous PG le last_insert_id() de MySQL. Pour ce faire le bout de code en PHP va chercher dans l'insert la table destination et en déduit le nom de la séquence.
A mon sens, l'ensemble doit être remplacé par un simple SELECT lastval()