IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Bases de données Delphi Discussion :

caractère & dans un char n'est pas restauré correctement avec le composant firedac


Sujet :

Bases de données Delphi

  1. #1
    Membre habitué
    Profil pro
    Inscrit en
    Février 2007
    Messages
    341
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 341
    Points : 150
    Points
    150
    Par défaut caractère & dans un char n'est pas restauré correctement avec le composant firedac
    Bonjour,

    J'explicite le sujet.
    Je travaille avec delphi 10.4 sur une base mariadb/mysql.
    J'ai constaté avec un peu d'étonnement que si je fais une requête du genre :

    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    DROP TABLE IF EXISTS util;
    CREATE TABLE `util` (
      `U_nom` CHAR(30) NOT NULL DEFAULT '' COLLATE 'latin1_general_ci',
      `U_mp` CHAR(250) NOT NULL COLLATE 'latin1_general_ci',
      PRIMARY KEY (`U_nom`) USING BTREE
    )
    COLLATE='latin1_general_ci'
    ENGINE=InnoDB;
     
    /*!40000 ALTER TABLE util DISABLE KEYS */; 
    INSERT INTO util (U_nom, U_mp) VALUES
    ('toto', 'e.*+°*MëÎ*&bXvS}v+°@vX<WgbXi*°Oe|@v:Ö&>W1a');
    /*!40000 ALTER TABLE util ENABLE KEYS */;

    à l'aide d'un TFDQuery, le caractère & et les caractères bXvS qui le suivent ne sont pas restitués dans le champ ?

    Si j'exécute cette requête avec heidisql, aucun problème ...

    Dans le moniteur firedac (compliqué de comprendre comment ça fonctionne avec 0 information dans l'aide), j'ai une ligne :

    >> dm2.q1.Prepare [Command="/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; ...
    avec la valeur à insérer correcte avec &bXvS présent

    puis une ligne :

    . Preprocessed [CMD="/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; ...
    et à ce stade là, les caractères &bXvS ne sont plus présents dans la valeur à insérer ....

    J'ai d'autres lignes à insérer avec un & présent dans le champ, et tous les & disparaissent avec 0 ou plusieurs caractères à leur suite qui disparaissent aussi, par exemple :

    s+vtYÎC:éÈQÜCÎb/êEä93|b9.rêT&ACbIÈèäc qui devient s+vtYÎC:éÈQÜCÎb/êEä93|b9.rêT

    ou

    t&*i1yéjqI+)W+5g#4 CZ1_8x]ûtDdBp qui devient t*i1yéjqI+)W+5g#4 CZ1_8x]ûtDdBp

    Quelqu'un aurait-il une explication à ce comportement très étrange ?

    Merci d'avance.

  2. #2
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 036
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 67
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 036
    Points : 40 941
    Points
    40 941
    Billets dans le blog
    62
    Par défaut
    Bonjour,

    je ne travaille que très peu avec MySQL.
    La première idée qui me vient est de demander si le character_set du FDConnection est renseigné ?

    Cela écrit je ne suis pas sûr que ce soit Firedac le problème

    voici un test rapide VCL
    Nom : Capture.PNG
Affichages : 223
Taille : 13,4 Ko

    le premier label, j'ai fait un simple copier/coller à partir de ton message : pas de perluette
    NOTE : dans la table j'ai ajouté un \ devant chaque perluette pour bien voir où celle-ci aurait dû être
    le second est une liaison (livebindings) pas de perluette
    pourtant le DBEdit parle de lui même la perluette y est !

    Si tu modifies la propriété ShowAccelChar des Tlabels à false alors, la perluette apparait
    MVP Embarcadero
    Delphi installés : D3,D7,D2010,XE4,XE7,D10 (Rio, Sidney), D11 (Alexandria), D12 (Athènes)
    SGBD : Firebird 2.5, 3, SQLite
    générateurs États : FastReport, Rave, QuickReport
    OS : Window Vista, Windows 10, Windows 11, Ubuntu, Androïd

  3. #3
    Membre habitué
    Profil pro
    Inscrit en
    Février 2007
    Messages
    341
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 341
    Points : 150
    Points
    150
    Par défaut
    Merci pour ta réponse, mais je n'affiche rien, c'est juste un insert values dans une requête
    Je sais que la perluette est influencée par ShowAccelChar, mais en l'occurence ça n'a rien à voir il me semble
    J'ai trouvé une solution entraitant chaque string lors de la sauvegarde et en ajoutant un antislash devant le perluette.
    Dans ces conditions le antislash n'apparaît pas mais la perluette oui.

    Je pense que ça devrait plutôt venir du moteur sql ou firedac ...
    Je vais faire des essais en renseignant le caracter_set du fdconnection

  4. #4
    Membre habitué
    Profil pro
    Inscrit en
    Février 2007
    Messages
    341
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 341
    Points : 150
    Points
    150
    Par défaut
    Citation Envoyé par navyg Voir le message
    Je vais faire des essais en renseignant le caracter_set du fdconnection
    Bon, ça ne change rien ...

  5. #5
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 688
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 688
    Points : 13 117
    Points
    13 117
    Par défaut
    & à l'instar de ! est considéré comme une macro par Firedac. Il va donc remplacer bXvS par la valeur assignée, et puisqu'elle est nulle la chaîne semble tronquée.

    Dans ton cas, il faut désactiver l'interprétation des macros en jouant sur ResourceOptions/MacroExpand du TFDQuery.

  6. #6
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 036
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 67
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 036
    Points : 40 941
    Points
    40 941
    Billets dans le blog
    62
    Par défaut
    Bon, cela dit, je n'aurais jamais écrit la requête ainsi, d'ailleurs il s'agirait plus d'un FDScript (je ne suis pas chaud sur plusieurs lignes SQL dans une query)

    J'aurais utilisé une requête paramétrée
    par exemple comme ceci
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    FDConnexion.ExecSQL('INSERT INTO util (U_nom, U_mp) VALUES (:n,:m)',['toto', 'e.*+°*MëÎ*&bXvS}v+°@vX<WgbXi*°Oe|@v:Ö&>W1a')]);
    MVP Embarcadero
    Delphi installés : D3,D7,D2010,XE4,XE7,D10 (Rio, Sidney), D11 (Alexandria), D12 (Athènes)
    SGBD : Firebird 2.5, 3, SQLite
    générateurs États : FastReport, Rave, QuickReport
    OS : Window Vista, Windows 10, Windows 11, Ubuntu, Androïd

  7. #7
    Membre habitué
    Profil pro
    Inscrit en
    Février 2007
    Messages
    341
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 341
    Points : 150
    Points
    150
    Par défaut
    Citation Envoyé par Andnotor Voir le message
    & à l'instar de ! est considéré comme une macro par Firedac. Il va donc remplacer bXvS par la valeur assignée, et puisqu'elle est nulle la chaîne semble tronquée.

    Dans ton cas, il faut désactiver l'interprétation des macros en jouant sur ResourceOptions/MacroExpand du TFDQuery.
    Ok merci, bien compris
    Effectivement si je mets ce paramètre à false, je n'ai plus besoin d'insérer le caractère d'échappement \ avant &.
    Ainsi même à la restauration, le & est pris comme caractère et non pas comme indicateur de paramètres ou autre macro.
    Mais même si je laisse le caractère \ devant le &, le \ n'apparaît pas tant que je ne le double pas.

    Bon je ne sais pas ce que je vais choisir comme méthode ... maintenant que j'en ai deux qui fonctionnent, il va falloir faire un choix

  8. #8
    Membre habitué
    Profil pro
    Inscrit en
    Février 2007
    Messages
    341
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 341
    Points : 150
    Points
    150
    Par défaut
    Citation Envoyé par SergioMaster Voir le message
    Bon, cela dit, je n'aurais jamais écrit la requête ainsi, d'ailleurs il s'agirait plus d'un FDScript (je ne suis pas chaud sur plusieurs lignes SQL dans une query)

    J'aurais utilisé une requête paramétrée
    par exemple comme ceci
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    FDConnexion.ExecSQL('INSERT INTO util (U_nom, U_mp) VALUES (:n,:m)',['toto', 'e.*+°*MëÎ*&bXvS}v+°@vX<WgbXi*°Oe|@v:Ö&>W1a')]);
    Ce que j'exécute est la réplique de ce que j'ai vu lorsqu'on demande une sauvegarde d'une base dans un fichier sql.
    En fait, il y a toutes les lignes de chaque table dans ce insert et bien plus de champs que les deux que j'ai indiqués. En tout ça doit faire près de cent mille lignes.

    Ca marche très bien comme ça et c'est très rapide. Les fichiers sont faciles à interpréter, stocker, transférer, voir zipper.
    Je pense que je ne vais pas changer ma façon de faire car elle me semble efficace et simple.

  9. #9
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 036
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 67
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 036
    Points : 40 941
    Points
    40 941
    Billets dans le blog
    62
    Par défaut
    J'utilise souvent cette technique : récupérer le script de remplissage d'une table dans un fichier. Mais j'utilise FDScript (et son SQLScriptFileName) plutôt qu'un FDQuery. (avec la même option concernant macroexpand cela fonctionne)
    FDScript à une option CommitEachNCommand ce qui peut être utile pour de gros volumes
    MVP Embarcadero
    Delphi installés : D3,D7,D2010,XE4,XE7,D10 (Rio, Sidney), D11 (Alexandria), D12 (Athènes)
    SGBD : Firebird 2.5, 3, SQLite
    générateurs États : FastReport, Rave, QuickReport
    OS : Window Vista, Windows 10, Windows 11, Ubuntu, Androïd

  10. #10
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 452
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 452
    Points : 24 860
    Points
    24 860
    Par défaut
    Je faisais une chose similaire avec MySQL 4.1, MySQL AB Administrator et un TMyScript qui plafonnait à 2Go de SQL si mes souvenirs sont bons (faut dire que certaine machines n'avaient que 512Mo de RAM) alors que le TMyDump pouvait largement dépassé cela.

    Je connais pas FDScript mais si tu produits toi même les scripts, que tu mélanges des CREATE TABLE avec des CREATE TRIGGER et blocs de procédure anonyme, quasiment tous les composants Scripts découpent mal cela, assures-toi de bien vérifier les limites de ton script.
    Pour TOraScript, j'ai refait un TScriptCutter qui sépare les parties DDL et DML.

    je te recommande de désactiver les Macros, pour un gros script, cela consomme du temps de les chercher en plus de l'effet de bord que tu constates de l'esperluette.

    As-tu pensé à utiliser "MySQL Command Line Client" ?
    la commande mysqldump pour extraire
    la commande mysql pour lancer le SQL de Dump

    Avec MySQL, pense que les INSERT peuvent être faire en BULK si j'ai bon souvenir, c'est à dire plusieurs séries de VALUES, et un maximum de 1000 (avec COMMIT comme cela a été mentionné a faire régulièrement)
    Pense aussi à désactiver les INDEX lors des INSERT et les réactiver après, c'est plus rapide pour insérer les données et générer les index en deux temps.

    En même temps, le code fourni au début ressemble à un Dump et il devrait suivre les recommandations ci-dessus.
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  11. #11
    Membre habitué
    Profil pro
    Inscrit en
    Février 2007
    Messages
    341
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 341
    Points : 150
    Points
    150
    Par défaut
    Citation Envoyé par SergioMaster Voir le message
    J'utilise souvent cette technique : récupérer le script de remplissage d'une table dans un fichier. Mais j'utilise FDScript (et son SQLScriptFileName) plutôt qu'un FDQuery. (avec la même option concernant macroexpand cela fonctionne)
    FDScript à une option CommitEachNCommand ce qui peut être utile pour de gros volumes
    Je n'avais jamais exploré ce composant, mais il semble effectivement plus intéressant et plus adapté pour les gros volumes.
    merci

  12. #12
    Membre habitué
    Profil pro
    Inscrit en
    Février 2007
    Messages
    341
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 341
    Points : 150
    Points
    150
    Par défaut
    Citation Envoyé par ShaiLeTroll Voir le message
    Je faisais une chose similaire avec MySQL 4.1, MySQL AB Administrator et un TMyScript qui plafonnait à 2Go de SQL si mes souvenirs sont bons (faut dire que certaine machines n'avaient que 512Mo de RAM) alors que le TMyDump pouvait largement dépassé cela.

    Je connais pas FDScript mais si tu produits toi même les scripts, que tu mélanges des CREATE TABLE avec des CREATE TRIGGER et blocs de procédure anonyme, quasiment tous les composants Scripts découpent mal cela, assures-toi de bien vérifier les limites de ton script.
    Pour TOraScript, j'ai refait un TScriptCutter qui sépare les parties DDL et DML.

    je te recommande de désactiver les Macros, pour un gros script, cela consomme du temps de les chercher en plus de l'effet de bord que tu constates de l'esperluette.

    As-tu pensé à utiliser "MySQL Command Line Client" ?
    la commande mysqldump pour extraire
    la commande mysql pour lancer le SQL de Dump

    Avec MySQL, pense que les INSERT peuvent être faire en BULK si j'ai bon souvenir, c'est à dire plusieurs séries de VALUES, et un maximum de 1000 (avec COMMIT comme cela a été mentionné a faire régulièrement)
    Pense aussi à désactiver les INDEX lors des INSERT et les réactiver après, c'est plus rapide pour insérer les données et générer les index en deux temps.

    En même temps, le code fourni au début ressemble à un Dump et il devrait suivre les recommandations ci-dessus.
    Je construis ma sauvegarde à la mimine en suivant l'exemple d'une sauvegarde de heidisql par exemple et ça fonctionne très bien.
    Effectivement, après le INSERT, j'ai tous les enregistrements de la table (la plus grosse a 40000 enregistrement et ça se passe très bien)
    J'ai désactivé les macros et paramètres pour la restauration et je n'ai pas vu grand changement dans le temps de traitement.
    Je désactive aussi bien sûr les foreign keys, sinon ça ne marche pas.
    Pour les index, je vais voir ça aussi.

    Merci.

  13. #13
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 036
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 67
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 036
    Points : 40 941
    Points
    40 941
    Billets dans le blog
    62
    Par défaut
    Un bémol quand même à cette technique : les Blobs (en particulier les binary blobs), chose qu'un FDBatchmove traite correctement
    MVP Embarcadero
    Delphi installés : D3,D7,D2010,XE4,XE7,D10 (Rio, Sidney), D11 (Alexandria), D12 (Athènes)
    SGBD : Firebird 2.5, 3, SQLite
    générateurs États : FastReport, Rave, QuickReport
    OS : Window Vista, Windows 10, Windows 11, Ubuntu, Androïd

  14. #14
    Membre habitué
    Profil pro
    Inscrit en
    Février 2007
    Messages
    341
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 341
    Points : 150
    Points
    150
    Par défaut
    Citation Envoyé par SergioMaster Voir le message
    Un bémol quand même à cette technique : les Blobs (en particulier les binary blobs), chose qu'un FDBatchmove traite correctement
    pas de blob !
    merci de l'avertissement ;o)

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Un caractère Unicode dans un char* ?
    Par Ekinoks dans le forum C
    Réponses: 4
    Dernier message: 13/08/2008, 01h10
  2. accents dans console windows: c'est pas normal..
    Par zais_ethael dans le forum C++
    Réponses: 2
    Dernier message: 06/04/2008, 11h21
  3. [AJAX] Le javascript dans ma réponse n'est pas interprété !
    Par stitch dans le forum Général JavaScript
    Réponses: 2
    Dernier message: 14/05/2007, 13h13
  4. les caractères spéciaux dans l'url, c'est mal !
    Par _gargamel_ dans le forum Servlets/JSP
    Réponses: 2
    Dernier message: 10/05/2007, 16h03

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo