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 :

Firedac + SQLite et détection de modification


Sujet :

Bases de données Delphi

  1. #1
    Membre chevronné Avatar de der§en
    Homme Profil pro
    Bretagne
    Inscrit en
    Septembre 2005
    Messages
    1 111
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Bretagne
    Secteur : Industrie

    Informations forums :
    Inscription : Septembre 2005
    Messages : 1 111
    Par défaut Firedac + SQLite et détection de modification
    Bonjour,

    pour tester les possibilités de Firedac avec SQLite, j’ai chargé en mémoire ma base SQLite (base de 10 Mo) au chargement de mon appli, les pers sont excellente.

    En sortie, je voudrais pouvoir décidé de sauver sur disque ma base en mémoire mais seulement si elle a reçu des modifications.

    J’ai pas trouvé comment déterminer avec exactitude si la base a été modifiée, auriez-vous une idée ou une solution ?

    Merci d’avance de vos propositions.

  2. #2
    Expert confirmé
    Avatar de popo
    Homme Profil pro
    Analyste programmeur Delphi / C#
    Inscrit en
    Mars 2005
    Messages
    3 003
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Analyste programmeur Delphi / C#
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2005
    Messages : 3 003
    Par défaut
    Puisque tu as décidé de tout mettre en mémoire, pourquoi ne pas tout simplement mettre l'information qu'il te manque en mémoire également ?
    Il suffit de mettre à jour cette information de la même manière que tu mets à jour le reste.

    Edit :
    Au passage, cette approche est dangereuse.
    S'il y a le moindre plantage non géré dans ton application, tu risques de perdre toutes tes modifications en mémoire.
    Une base SQLite est faite pour travailler en local, de sorte que tu n'a normalement pas de problème d'accès.
    Je te suggère de lire et écrire dans la base uniquement lorsque c'est nécessaire et uniquement sur les données qui sont nécessaires.

  3. #3
    Membre émérite
    Homme Profil pro
    Chef de projets retraité
    Inscrit en
    Juillet 2011
    Messages
    458
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Cher (Centre)

    Informations professionnelles :
    Activité : Chef de projets retraité
    Secteur : Transports

    Informations forums :
    Inscription : Juillet 2011
    Messages : 458
    Par défaut
    Bonjour,
    Citation Envoyé par der§en Voir le message
    En sortie, je voudrais pouvoir décidé de sauver sur disque ma base en mémoire mais seulement si elle a reçu des modifications.
    Je ne connais pas FIREDAC mais l'interface
    sqlite3_changes()
    ou
    sqlite3_total_changes()
    sont là exprès

    Cordialement

  4. #4
    Rédacteur/Modérateur

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

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

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 663
    Billets dans le blog
    65
    Par défaut
    Citation Envoyé par der§en Voir le message
    En sortie, je voudrais pouvoir décidé de sauver sur disque ma base en mémoire mais seulement si elle a reçu des modifications.
    Hum, A moins que tu veuilles faire une copie de la base, je ne comprends pas bien le terme "sauver" sauf si tu utilises des tables en mode CacheUpdates.
    Ensuite tu peux toujours utiliser une variable booléenne globale, false par défaut et que tu mettrais à true dès le premier "POST".
    Sache également que tu peux obtenir le nombre de lignes modifiées si tu utilises des querys (exemple ndeleted:=FDQuery.ExecSQL('DELETE FROM MATABLE WHERE N=1'))

    Pour moi c'est trop flou comme demande
    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

  5. #5
    Membre chevronné Avatar de der§en
    Homme Profil pro
    Bretagne
    Inscrit en
    Septembre 2005
    Messages
    1 111
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Bretagne
    Secteur : Industrie

    Informations forums :
    Inscription : Septembre 2005
    Messages : 1 111
    Par défaut
    Ma base est principalement pour des accès en lecture seule, mais il peux arriver qu’il faille faire des MAJ.

    Je me demandais si Firedac, était capable de me dire si il a eu des modifications dans la base sans avoir à mettre ma propre gestion, histoire de ne pas réinventer la roue.

    Quand je parle de sauver, il s’agit pour moi de créer une copie de la base en mémoire après avoir appliquer TFDSQLiteValidate.Sweep !

  6. #6
    Rédacteur/Modérateur

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

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

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 663
    Billets dans le blog
    65
    Par défaut
    C'est le "en mémoire" qui me chiffonne !
    Il me semble que tu pourrais le faire directement en utilisant un FDConnection.EXECSQL('VACUUM INTO Copiebase.sdb'); mais ça demande quelques tests, https://www.sqlite.org/lang_vacuum.html
    j'ai déjà utilisé d'autres "commandes" SQLite en direct mais pas celle-ci
    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 chevronné Avatar de der§en
    Homme Profil pro
    Bretagne
    Inscrit en
    Septembre 2005
    Messages
    1 111
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Bretagne
    Secteur : Industrie

    Informations forums :
    Inscription : Septembre 2005
    Messages : 1 111
    Par défaut
    Si tu veux, une fois remplacé ma base perso par une plus générique, je peux publier mon datamodule avec un exemple utilisant TFDQuery pour que tu puisses voir comment j’ai chargé en mémoire ma base SQLite !

  8. #8
    Rédacteur/Modérateur

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

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

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 663
    Billets dans le blog
    65
    Par défaut
    Maintenant que je me suis un peu remis au codage, oui, pourquoi pas
    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

  9. #9
    Membre Expert
    Avatar de ALWEBER
    Homme Profil pro
    Expert Delphi
    Inscrit en
    Mars 2006
    Messages
    1 543
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 70
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Expert Delphi

    Informations forums :
    Inscription : Mars 2006
    Messages : 1 543
    Billets dans le blog
    10
    Par défaut Pourquoi pas un Trigger
    Je pense que l'utilisation de "trigger" est aussi une solution. +D'infos si tu le souhaites. Si tu nous envoies un exemple j’essaierai de te faire un essai avec le solution que je propose.

  10. #10
    Rédacteur/Modérateur

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

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

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 663
    Billets dans le blog
    65
    Par défaut
    Citation Envoyé par SergioMaster Voir le message
    j'ai déjà utilisé d'autres "commandes" SQLite en direct mais pas celle-ci
    Voilà j'ai retrouvé au moins une utilisation dans mes codes, pour gérer les changements possibles de la structure d'une base de données
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    version:=FDCnxcomptes.ExecSQlScalar('PRAGMA user_version');
    Code à retrouver dans ce dépôt unité Udm.pas

    Comme cette histoire de chargement me chiffonne, j'ai effectivement lu que c'était possible via les API SQLite https://www.sqlite.org/inmemorydb.html
    Toutefois, à moins que cela m'ait échappé, je ne crois pas que cette fonctionnalité soit offerte dans Firedac mais j'avoue ne pas avoir cherché

    Bon, pour commencer ma journée (en attendant l'installation de la dernière version Bêta de D13) je vais faire ces deux tentatives à partir d'un projet vide.
    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

  11. #11
    Membre émérite
    Homme Profil pro
    Chef de projets retraité
    Inscrit en
    Juillet 2011
    Messages
    458
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Cher (Centre)

    Informations professionnelles :
    Activité : Chef de projets retraité
    Secteur : Transports

    Informations forums :
    Inscription : Juillet 2011
    Messages : 458
    Par défaut
    Bonjour,
    Citation Envoyé par SergioMaster Voir le message
    Voilà j'ai retrouvé au moins une utilisation dans mes codes, pour gérer les changements possibles de la structure d'une base de données
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    version:=FDCnxcomptes.ExecSQlScalar('PRAGMA user_version');
    Pour pouvoir vérifier la version utilisateur, encore faut il la mettre à jour car celle ci nest jamais mise à jour par SQLITE.
    The user_version pragma will get or set the value of the user-version integer at offset 60 in the database header. The user-version is an integer that is available to applications to use however they want. SQLite makes no use of the user-version itself.
    Par contre le pragma Data_version peut être intéressant
    PRAGMA schema.data_version;

    The "PRAGMA data_version" command provides an indication that the database file has been modified. Interactive programs that hold database content in memory or that display database content on-screen can use the PRAGMA data_version command to determine if they need to flush and reload their memory or update the screen display.

    The integer values returned by two invocations of "PRAGMA data_version" from the same connection will be different if changes were committed to the database by any other connection in the interim. The "PRAGMA data_version" value is unchanged for commits made on the same database connection. The behavior of "PRAGMA data_version" is the same for all database connections, including database connections in separate processes and shared cache database connections.

    The "PRAGMA data_version" value is a local property of each database connection and so values returned by two concurrent invocations of "PRAGMA data_version" on separate database connections are often different even though the underlying database is identical. It is only meaningful to compare the "PRAGMA data_version" values returned by the same database connection at two different points in time.
    EDIT 29/08/2025 9H56 Ceci ne semble vérifié que pour les autres connections à la base de données
    Cordialement

  12. #12
    Modérateur
    Avatar de tourlourou
    Homme Profil pro
    Biologiste ; Progr(amateur)
    Inscrit en
    Mars 2005
    Messages
    3 940
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Biologiste ; Progr(amateur)

    Informations forums :
    Inscription : Mars 2005
    Messages : 3 940
    Billets dans le blog
    6
    Par défaut
    Bonjour,
    Peut-être la comparaison des valeurs de PRAGMA schema.data_version à condition qu'elle soit récupérée par une connexion à ta base en mémoire différente de celle qui la modifie ?
    Delphi 5 Pro - Delphi 11.3 Alexandria Community Edition - CodeTyphon 6.90 sous Windows 10 ; CT 6.40 sous Ubuntu 18.04 (VM)
    . Ignorer la FAQ Delphi et les Cours et Tutoriels Delphi nuit gravement à notre code !

  13. #13
    Rédacteur/Modérateur

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

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

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 663
    Billets dans le blog
    65
    Par défaut
    Oui, j'avais pensé à après tests, ce matin, cela n'a pas été concluant.
    Pour le user_version effectivement, il ne faut pas oublier de le modifier, c'est à charge de l'utilisateur (ou plutôt du programme) de le faire

    voici un extrait du code en cours, je n'ai pas réussi à passer directement l'instruction VACUUM en SQL, donc avec Firedac j'utilise les composants idoines (FDSQLiteValidate et FDSQLiteBackup)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
     
    procedure TMainForm.btnVacuumClick(Sender: TObject);
    begin
    FDTable1.DisableControls;
    FDConnection1.Connected:=False;
    FDSQLiteValidate1.Sweep;
    FDConnection1.Connected:=True;
    FDTable1.EnableControls;
    end;
     
    function TMainForm.get_databaseversion: integer;
    begin
    try result:=FDConnection1.ExecSQLScalar('PRAGMA user_version');
    except result:=0;
    end;
    end;
     
    procedure TMainForm.VacuumInFileClick(Sender: TObject);
    begin
     FDConnection1.ExecSQL(Format('PRAGMA user_version=%d',[get_databaseversion+1]));
     version.Caption:=format('version = %d',[get_databaseversion]);
     btnVacuumClick(Sender);
     FDSQLiteBackup1.Database:=FDConnection1.Params.Database;
     FDSQLiteBackup1.DestDatabase:=Format('test_bk%d.sdb',[get_databaseversion]);
     FDSQLiteBackup1.Backup;
    end;
    me reste à comprendre la fameuse phrase
    ma base en mémoire
    N.B. Il n'est pas indiqué si l'on a affaire à une seule table ou plusieurs ce qui changerait la chose
    [EDIT 10:43] cependant un SQL genre n:=FDConnection1.ExecSQLScalar('SELECT Changes()'); if n>0 then .... {modifications sur la base de données} pourrait répondre à la question (je viens de faire un essai,toujours avec une seule table toutefois, le SQL fonctionne

    pour l'instant j'en suis resté au simple cachedupdate=true d'une table et donc l'utilisation de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if FDTable1.UpdatesPending then FDTable1.ApplyUpdates();
    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
    Rédacteur/Modérateur

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

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

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 663
    Billets dans le blog
    65
    Par défaut
    Rectification, l'utilisation de VACUUM INTO fonctionne
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    procedure TMainForm.Button2Click(Sender: TObject);
    begin
     FDConnection1.Connected:=False;
     FDConnection1.ExecSQL('VACUUM INTO "C:\Athenes\VCL\SQliteTest\Win32\Debug\test_vac.sdb"');
     FDConnection1.Connected:=true;
    end;
    deux erreurs de ma part m'avais fait indiqué le contraire :
    l'oubli de INTO lors de ma codification
    la syntaxe pour ce qui est de la destination, en ne mettant que VACUUM INTO test_vac.sdb je ne retrouvais pas le fichier

    Cette solution permet de d'éviter tout les composants (FDSQLiteValidate, FDSQLiteBackup, FDSQLitePhysDriver et FDGUIxAsyncExecuteDialog) nécessaires de mon post précédent.
    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

  15. #15
    Rédacteur/Modérateur

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

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

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 663
    Billets dans le blog
    65
    Par défaut
    M'attaquant désormais à la partie base en mémoire, en fouillant dans le docwiki, je suis effectivement "tombé" sur la partie "Utilisation d'une base de données SQLite en mémoire dans une application Delphi" dans cette page @der§en est-ce cette technique que tu testes ?
    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

  16. #16
    Rédacteur/Modérateur

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

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

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 663
    Billets dans le blog
    65
    Par défaut
    Avec la technique citée dans mon précédent post
    voici une solution
    SQLiteInMem.zip
    Choses à signaler
    Il faut bien sûr changer les chemins de la base de données (en dur dans mon code)
    Pour la sauvegarde/sweep j'ai fait au plus simple mais, AMHA, il faudrait toujours garder le même nom de base, donc renommer l'ancienne "version" et faire la commande de VACUUM le nom de la base restant inchangé, mais comme je n'ai pas vraiment compris le besoin ....
    Je n'ai fait qu'un test partiel en utilisant uniquement les insertions par SQL direct (les boutons à côté de la barre de navigation), j'ai été déçu de ne pas avoir les nombres d'enregistrement modifiés totaux mais, vu la technique utilisée c'est logique
    Citation Envoyé par doc sqlite
    The changes() function returns the number of database rows that were changed or inserted or deleted by the most recently completed INSERT, DELETE, or UPDATE statement
    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

  17. #17
    Membre émérite
    Homme Profil pro
    Chef de projets retraité
    Inscrit en
    Juillet 2011
    Messages
    458
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Cher (Centre)

    Informations professionnelles :
    Activité : Chef de projets retraité
    Secteur : Transports

    Informations forums :
    Inscription : Juillet 2011
    Messages : 458
    Par défaut
    Bonjour,

    NB. Il y a une fonction SQL aussi pour cela

    changes()

    The changes() function returns the number of database rows that were changed or inserted or deleted by the most recently completed INSERT, DELETE, or UPDATE statement, exclusive of statements in lower-level triggers. The changes() SQL function is a wrapper around the sqlite3_changes64() C/C++ function and hence follows the same rules for counting changes.
    On doit pouvoir l'utiliser ainsi:

    et obtenir le résultat demandé

    Cordialement

  18. #18
    Rédacteur/Modérateur

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

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

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 663
    Billets dans le blog
    65
    Par défaut
    @acaumes
    c'est ce que j'ai fait, mais le nombre de changements n'est pas vraiment ce que j'ttendais, dans mon premier jus (hors base en mémoire) j'utilisais des tables en mode cachedupdate ce qui, après le applyupdates me donnait un meilleur résultat
    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

  19. #19
    Membre émérite
    Homme Profil pro
    Chef de projets retraité
    Inscrit en
    Juillet 2011
    Messages
    458
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Cher (Centre)

    Informations professionnelles :
    Activité : Chef de projets retraité
    Secteur : Transports

    Informations forums :
    Inscription : Juillet 2011
    Messages : 458
    Par défaut
    Citation Envoyé par SergioMaster Voir le message
    @acaumes
    c'est ce que j'ai fait, mais le nombre de changements n'est pas vraiment ce que j'ttendais, dans mon premier jus (hors base en mémoire) j'utilisais des tables en mode cachedupdate ce qui, après le applyupdates me donnait un meilleur résultat
    Oups, j'ai lu trop vite, je croyais qu'il s'agissait de l'interface C de SQLITE.
    NB. Cette commande ne traite pas des modifications entrainées par autre chose que les INSERT/DELETE/UPDATE et encore juste les plus récents (c'est à dire pas tous) et de plus elle oublie les triggers...

  20. #20
    Membre chevronné Avatar de der§en
    Homme Profil pro
    Bretagne
    Inscrit en
    Septembre 2005
    Messages
    1 111
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Bretagne
    Secteur : Industrie

    Informations forums :
    Inscription : Septembre 2005
    Messages : 1 111
    Par défaut
    Désolé du retard voici le code de mon TDatamodule, si vous voyez des horreurs ou des amélioration possible, je suis preneur:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    unit uDataModule;
     
    interface
     
    uses
      System.SysUtils, System.Classes,
      FireDAC.Comp.Client, FireDAC.Stan.Def, FireDAC.Stan.Async,
      FireDAC.DApt, FireDAC.Phys.SQLite, FireDAC.Phys.SQLiteWrapper,
      FireDAC.Phys, FireDAC.UI.Intf, FireDAC.Comp.UI, FireDAC.Stan.Intf,
      FireDAC.Stan.Option, FireDAC.Stan.Error, FireDAC.Phys.Intf, FireDAC.Stan.Pool,
      FireDAC.VCLUI.Wait, Data.DB, FireDAC.Phys.SQLiteDef, FireDAC.Stan.ExprFuncs,
      FireDAC.Stan.Param, FireDAC.DatS, FireDAC.DApt.Intf, Data.Bind.Components,
      Data.Bind.DBScope, FireDAC.Comp.DataSet;
     
     
    type
      TdmDB = class(TDataModule)
        FDConnectionMem: TFDConnection;
        FDPhysSQLiteDriverLinkPolaris: TFDPhysSQLiteDriverLink;
        FDGUIxWaitCursor1: TFDGUIxWaitCursor;
        dsVilles: TDataSource;
        fdqVilles: TFDQuery;
        bsVilles: TBindSourceDB;
        FDSQLiteValidate1: TFDSQLiteValidate;
        procedure DataModuleCreate(Sender: TObject);
        procedure DataModuleDestroy(Sender: TObject);
      private
        FModified: Boolean;
        FDBFile: string;
        procedure LoadDBInMemory;
        procedure SaveDBToDisk(ASaveWithTimestamp: Boolean = True);
        procedure SetDBFile(const AValue: string);
      public
        property DBFile: string read FDBFile write SetDBFile;
      end;
     
    var
      dmDB: TdmDB;
     
    implementation
     
    {%CLASSGROUP 'Vcl.Controls.TControl'}
     
    {$R *.dfm}
     
    uses
      Vcl.Dialogs;
     
    procedure TdmDB.DataModuleCreate(Sender: TObject);
    begin
      FModified := False;
    end;
     
    procedure TdmDB.DataModuleDestroy(Sender: TObject);
    begin
      // Sauver la DB mémoire en sortie
      //  ShowMessage(Format('Il y a %d enregistrements modifiés', [fdqVilles.ChangeCount]));
      //  ShowMessage(Format('Il y a %s enregistrements en attente', [BoolToStr(fdqVilles.UpdatesPending, true)]));
     
      if FModified then
        SaveDBToDisk;
    end;
     
    procedure TdmDB.LoadDBInMemory;
    var
      DiskConn: TFDConnection;
      Backup: TFDSQLiteBackup;
    begin
      // --- Connexion mémoire partagée ---
      FDConnectionMem.DriverName  := 'SQLite';
      FDConnectionMem.Params.Values['Database'] := 'file::memory:?cache=shared';
      FDConnectionMem.LoginPrompt := False;
      FDConnectionMem.Connected   := True;
     
      // --- Connexion disque ---
      DiskConn := TFDConnection.Create(nil);
      try
        DiskConn.DriverName      := 'SQLite';
        DiskConn.Params.Database := FDBFile;
        DiskConn.Params.Add('OpenMode=ReadWrite'); // lecture/écriture possible
        DiskConn.LoginPrompt     := False;
        DiskConn.Connected       := True;
     
        // --- Backup disque -> mémoire ---
        Backup := TFDSQLiteBackup.Create(nil);
        try
          Backup.Database        := DiskConn.Params.Database;      // base disque
          Backup.DestDatabaseObj := FDConnectionMem.CliObj;        // base mémoire
          Backup.DriverLink      := FDPhysSQLiteDriverLinkPolaris; // Nécessaire pour fonctionner.
          Backup.DestMode        := smCreate;
     
          Backup.Backup;
        finally
          Backup.Free;
        end;
     
      finally
        DiskConn.Free;
      end;
    end;
     
    procedure TdmDB.SaveDBToDisk(ASaveWithTimestamp: Boolean);
    var
      Backup: TFDSQLiteBackup;
      LPath, LName, LExt: string;
      LDBFileOut: string;
    begin
      if not FDConnectionMem.Connected then
        Exit;
     
      // Création de la copie de la base sur disque;
      if ASaveWithTimestamp then
      begin
        LPath := ExtractFilePath(FDBFile);
        LName := ChangeFileExt(ExtractFileName(FDBFile), '');
        LExt := ExtractFileExt(FDBFile);
        LDBFileOut := Format('%s%s-%s%s', [LPath, LName, FormatDateTime('yyyymmdd_hhnnss', Now), LExt]);
      end
      else
        LDBFileOut := FDBFile;
     
      // Equivalent a la commande VACUUM pour réduire la taille de la base...
      FDSQLiteValidate1.Sweep;
     
      Backup := TFDSQLiteBackup.Create(nil);
      try
        Backup.DatabaseObj  := FDConnectionMem.CliObj;        // mémoire partagée
        Backup.DestDatabase := LDBFileOut;                    // fichier disque
        Backup.DriverLink   := FDPhysSQLiteDriverLinkPolaris; // Nécessaire pour fonctionner.
        Backup.DestMode     := smCreate;                      // recrée le fichier
     
        Backup.Backup;
      finally
        Backup.Free;
      end;
    end;
     
    procedure TdmDB.SetDBFile(const AValue: string);
    begin
      if (AValue <> EmptyStr) and FileExists(AValue) then
      begin
        FDBFile := AValue;
     
        // Charger en mémoire partagée
        LoadDBInMemory;
     
        fdqVilles.Active := True;
      end;
    end;
     
    end.

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. Monitor Firedac sqlite et MySQL
    Par Papy214 dans le forum Bases de données
    Réponses: 4
    Dernier message: 26/09/2018, 15h58
  2. Firedac SQLite + pooled
    Par Papy214 dans le forum Langage
    Réponses: 13
    Dernier message: 18/09/2018, 15h08
  3. Problème avec Delphi Firedac SQLite et les commit
    Par duss57 dans le forum Bases de données
    Réponses: 3
    Dernier message: 14/09/2018, 14h30
  4. Firedac + SQlite => erreur incomprise : interrupted
    Par Papy214 dans le forum Langage
    Réponses: 7
    Dernier message: 06/09/2018, 09h38
  5. Epées et FireDac SQLite
    Par Zacheus dans le forum Delphi
    Réponses: 8
    Dernier message: 12/11/2015, 17h11

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