Bandeau
Gestinux

Support and Development forum

UPDATE FOR dans postgres

talexone
le 20 février 2014
à 11:08
Rappel du sujet :

Erreur dans TGQuery.Select acec WITH_LOCK

Requête :

SELECT J.Code, J.Name, J.ManualEntry, J.JournalClass, AC.Id, AC.Account, J.CloseDate
FROM Journals J
LEFT JOIN Accounts AC ON AC.Id=J.LinkedAccountId
WHERE J.Id = 1
FOR UPDATE

Valeur J.LinkedAccountId est 0

Message d’erreur :
"ERREUR : FOR UPDATE ne peut être appliqué sur le côté possiblement NULL d’une jointure externe"

Solution :
Ajouter OF [Tablename]

Exemple :

SELECT J.Code, J.Name, J.ManualEntry, J.JournalClass, AC.Id, AC.Account, J.CloseDate
FROM Journals J
LEFT JOIN Accounts AC ON AC.Id=J.LinkedAccountId
WHERE J.Id = 1
FOR UPDATE OF J
Re : UPDATE FOR dans postgres

C’est un oubli fâcheux, non détecté faute de tests suffisants sur postgreSQL.
Je vais corriger dès que possible pour une prochaine version.
Merci pour votre indulgence et votre aide dans les tests !

Tintinux

Re : UPDATE FOR dans postgres

Pour ne pas trop modifier votre code j’ai créé une fonctionne en attendant votre mise à jour.

function TableNameFromQuery(Query: string): string;
var
  TempStr: string;
  offset, i: integer;
  KeyWords: array[0..6] of string = ('FROM','LEFT','RIGHT','INNER','WHERE',',',' ');
  Direction: array [0..6] of integer = (0,1,1,1,1,1,0); // 0 - Right Part , 1 - Left Part
begin
  TempStr := UpperCase(Query);
  for i := 0 to 6 do begin
    offset := Pos(KeyWords[i], TempStr);
    if offset > 0 then
      case Direction[i] of
        0: TempStr := Trim(RightStr(TempStr, Length(TempStr) - offset - (Length(KeyWords[i])-1)));
        1: TempStr := Trim(LeftStr(TempStr, offset - 1));
      end;
  end;
  result := TempStr;
end;

et modifié le TGQuery.Create :
Select(aDbConnection, aSql + ' FOR UPDATE OF ' + TableNameFromQuery(aSql));

Le parser est très simple mais suffisant dans ce cas.

talexone

Re : UPDATE FOR dans postgres

Bonjour

C’est une bonne idée que j’aurais suivie si j’avais plus de temps. Si vous l’avez testé avec succès, vous pouvez mettre à jour ce code vous-même, je vous ai donné les droits "Développeur" sur le SVN de SourceForge (je suppose que c’est le même pseudo !).

Il faut modifier uniquement le trunk, car on va laisser la V 1.0 comme cela, je préciserai qu’elle a certains problèmes sous Postgresql.

Et, attention, cet ajout de "OF table" ne doit se faire que sous PostgreSql, car MySql n’admet pas cette syntaxe. Il y a une fonction et des types énumérés pour faire la distinction, et idéalement on regroupe ce qui est spécifique à certains SGBD dans des méthodes suffixées par leur nom.

Cordialement,

Tintinux

Re : UPDATE FOR dans postgres

Bonsoir,

J’ai ajouté la vérification de dbmstype dans mon code. Avez vous parametré mon compte pour commit ? J’ai vu que sur sourceforge le ticket a été créé pour ce bug.

Cdt,

talexone

Re : UPDATE FOR dans postgres

Oui, le compte SourceForge a été paramétré et apparemment vous avez pu publier...
J’avais ajouté le bug pour ne pas oublier et je vais vous l’assigner asap.
Je ferai des tests complémentaires ce soir.
Cordialement,
Tintinux

Re : UPDATE FOR dans postgres

Hello,

J’ai vérifié que le commit 949 fonctionne bien avec MySQL.

Par contre, je vois un problème

potentiel

avec PostgreSql si quelqu’un écrit dans le futur une requête avec JOIN non précédé de INNER
Ce mot clé étant facultatif sous SQL, sauf spécificité que j’ignorerais. La jointure INNER est faite par défaut.
D’autre part, je ne crois pas que la 1ère table sera trouvée, si elle est immédiatement suivie d’un retour à la ligne.

Normalement ça n’arrivera pas dans Gestinux actuellement, et la correction peut attendre, mais je suggère quand même une vérification, avec une base avec PostgreSql, de toutes les options de menu affichant un DbGrid.

Cordialement,

Re : UPDATE FOR dans postgres

Bonjour,

tintinuxPar contre, je vois un problème potentiel avec PostgreSql si quelqu’un écrit dans le futur une requête avec JOIN non précédé de INNER
Ce mot clé étant facultatif sous SQL, sauf spécificité que j’ignorerais. La jointure INNER est faite par défaut.

Ce n’est pas vraiment un problème car on peux facilement ajouter les mots clés à vérifier dans la liste. Je suis parti sur la base des requêtes existant dans gestinux qui pour la plus part n’utilise que LEFT JOIN (sauf erreur je n’ai pas vraiment scruté chaque requête existante).

tintinuxD’autre part, je ne crois pas que la 1ère table sera trouvée, si elle est immédiatement suivie d’un retour à la ligne.

Pour le moment j’ai créé la fonction pour palier les erreur des fonctionnement de base, plus tard je pourrai faire des testes plus poussé et l’améliorer s’il faut.

tintinuxje suggère quand même une vérification, avec une base avec PostgreSql, de toutes les options de menu affichant un DbGrid

J’ai essayé de tester dans chaque menu affichant une liste. Pour le moment sans problèmes.

A+

talexone

Réagir au sujet
Forum sur abonnement

Pour participer à ce forum, vous devez vous enregistrer au préalable. Merci d’indiquer ci-dessous l’identifiant personnel qui vous a été fourni. Si vous n’êtes pas enregistré, vous devez vous inscrire.