1. Documentation
  2. >
  3. Module
  4. >
  5. JSQL

Module JSQL

Ce module est dédié à la manipulation de données persistantes côté client. Il est basé sur l'API IndexedDB, en facilite l'usage en exploitant les Promise et le vocabulaire SQL mais ne prévois pas de PolyFill de compatibilité lorsque ces API ne sont pas supportés. Il peut être utilisé indépendamment de Dynamique mais est aussi prévu pour s'y intégrer en tant que module.

Le module JSQL permet:

  • La création, la suppression et la mise à jour simplifiée de bases de données: createDatabase, deleteDatabase;

  • L'ajout et la mise à jour de données à une base de données: insertInto;

  • La selection de données depuis une base de données: selectFrom;

  • La suppression de données d'une base de données: deleteFrom;

  • La récupération de la version d'une base de données et la mise à jour d'une base de données depuis un objet de description de base de données: getDatabaseVersion, processDescription.

Le module utilise les WebWorker afin d'optimiser les performances lors des sélections/mises à jour, insertions et suppressions des données. L'URL vers le script JavaScript utilisé comme Worker est défini par la propriété JSQL.workerUrl. Elle peut être modifiée en utilisant la méthode JSQL.setWorkerUrl ou en l'assignant directement. L'usage de la méthode permet de précharger automatiquement ce script, le rendant accessible immédiatement lors de son usage par la suite du code et permet ainsi d'améliorer les délais de traitement.

Processus de création et de mise à jour

La création et la mise à jour de base de données s'effectue à partir de fichier JSON dont chaque version aura son fichier correspondant. La création de la base de données se fait automatiquement par parsage et application du fichier correspondant à la version 1.

Lorsqu'une mise à jour de la base de données est à effectuer depuis une version X à Y, le fichier JSON de chaque version depuis X à Y est chargé ainsi que les scripts de mise à jour associés. Ces scripts ont pour but d'appliquer la structure d'une nouvelle version à la base de données et est en charge de déplacer les données si nécessaire. Les fichiers sources pour chaque version de la base de données sont spécifiés lors de l'utilisation de la méthode JSQL.createDatabase:

(async function() { const database = await JSQL.createDatabase({ /* ou Dynamique.module.JSQL si Dynamique est utilisé */ name : "DB-TEST", version : 2, source : { "1" : { description : "url_vers_mon_fichier_decrivant_ma_base_v1.json" }, "2" : { description : "url_vers_mon_fichier_decrivant_ma_base_v2.json", script : "url_vers_mon_script_qui_sera_utilise_pour_convertir_ma_base_depuis_v1_a_v2.js" } }, onupgradeneeded : function() { alert("Mise à jour ou création nécessaire"); }, onversionchange : function() { alert("Nouvelle version disponible."); document.location.reload(); } }); if(database) { // Ici on ne test pas si database !== false car une version sera toujours > 0 alert("Base de données prête !"); } else { alert("Erreur !"); } })();

Les scripts de mise à jour sont uniquement nécessaire à partir de la version 2 d'une base de données car la version 1 correspond à sa création et qu'il n'y a donc pas de données à transposer.

Les scripts de mise à jour doivent se comporter comme si leur code se trouve dans le corp d'une fonction JavaScript et dont les arguments sont:

  • [0]: objet IDBDatabase pouvant être utilisé afin de modifier la structure de la base de données;
  • [1]: description de la base de données pour cette version;
  • [2]: objet fournie comme premier argument de JSQL.createDatabase.

Afin de simplifier l'application d'une version de base de données, la méthode JSQL.processDescription peut être utilisée.

L'ouverture d'une base de données étant l'opération nécessitant le plus de ressources, une base de données restera ouverte indéfiniment une fois créée et ceux jusqu'à ce que l'application soit quittée.

Format des fichiers de description de base de données

Cette section définie le fonctionnement interne du module afin de palier aux inconvénients de l'API IndexedDB. Il explique notamment le principe de sur-mise à jour qui est utilisé.

{ "premiereTable" : { "primaryKey" : ["nomDUneColonne"/*, ... */], "autoIncrement" : false, "index" : [{ "name" : "id", "key" : "id", "unique" : true, "multiEntry" : false, "locale" : false }] }, "secondeTable" : { "primaryKey" : ["nomDUneColonne"/*, ... */], "autoIncrement" : false, "index" : [{ "name" : "name", "key" : "name", "unique" : true, "multiEntry" : false, "locale" : false }] } }

Versionnage et délais maximum de transaction (timeout)

Cette section définie le fonctionnement interne du module afin de palier aux inconvénients de l'API IndexedDB. Il explique notamment le principe de sur-mise à jour qui est utilisé.

Lors de la création ou lorsqu'une mise à jour d'une base de données est nécessaire, une nouvelle transaction est ouverte et l'événement onupgradeneeded propagé. Au cours de cet événement, les opérations de modification de la base de données sont réalisables, tel que le défini l'API IndexedDB.

Cette transaction étant implicitement en lecture/écriture et non en lecture seule, elle met un verrou sur la base de données concernée, la rendant temporairement inacessible par une autre transaction. Un délais maximum avant expiration (timeout) est mis en place par les navigateurs afin de fermer automatiquement cette transaction si elle est inactive depuis un certains temps, permettant ainsi aux transactions suivantes de pouvoir accéder de nouveau à la base. Ce délais varie d'un navigateur à l'autre et ne permet donc par d'effectuer des opérations asynchrones, comme des requêtes XHR ou Fetch, afin de charger des ressources particulières permettant de mettre à jour la base de données.

La mise à jour/création d'une base se fait donc de manière séquencielle et chronométré ce qui implique d'inclure la totalité du code correspondant à chaque version dans la fonction attachée à l'événement onupgradeneeded. Ce comportement ne permet ni d'organiser le code comme le développeur le souhaite ni un bon support du code à travers le temps, notamment pour les bases de données à l'architecture complexe et subissant régulièrement des mises à jours.

Afin de palier à ce problème, le module JSQL utilise un méchanisme de sur-mise à jour d'une base de données. Le versionnage d'une base de données se défini alors pas dizaine et non par unité. Ainsi si la version 1 est demandée, c'est la version 10 qui sera créée. Ce méchanisme permet d'ouvrir une première fois la base de données dans la version demandée * 10, d'analyser si une mise à jour/création est nécessaire et depuis quelle version, de fermer la base de données, de charger les ressources nécessaires (fichiers JSON, JavaScript...) de manières asynchrones et indépendamment de toute contrainte, de ré-ouvrir la base de données avec la version demandée * 10 + 1 afin d'enfin y appliquer les mises à jour.
La version "développeur" d'une base données s'obtient alors par le calcul: version = Math.floor(databaseVersion / 10);

Vous pouvez obtenir les versions d'une base de données en utilisant la méthode JSQL.getDatabaseVersion où le second argument peut alors être utilisé afin de récupérer soit la version "développeur" soit la version système.

Accessibilité

Lorsque le module JSQL est utilisé sans Dynamique, il s'initialise directement sur l'objet window. Il est alors accessible tel que:

JSQL.createDatabase(...); // === window.JSQL.createDatabase(...);

Lorsque JSQL est utilisé avec Dynamique, il s'initialise en tant que module de ce dernier. Il est alors accessible tel que:

Dynamique.module.JSQL

Compatibilité

Le module JSQL a été réalisé sous le standard EcmaScript 6.

Dépendances

Le module JSQL utilise l'API IndexedDB, l'API WebWorker et les Promises.

Source

/Module/JSQL/JSQL.js
/Module/JSQL/JSQL-Worker.js