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
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
|
---
title: Sqlite.jsm
slug: Mozilla/JavaScript_code_modules/Sqlite.jsm
translation_of: Mozilla/JavaScript_code_modules/Sqlite.jsm
---
<p>{{ gecko_minversion_header("20.0") }}</p>
<p>Le module de code JavaScript <code>Sqlite.jsm </code> offre une interface de stockage/SQLite. <code> Sqlite.jsm </code> fonctionne avec des interfaces XPCOM de stockage de bas niveau:</p>
<ul>
<li>la gestion de la déclaration est automatique. Sqlite.jsm va créer, gérer et détruire les instances d'instructions pour vous. Vous ne devez pas vous soucier de la mise en cache des instances des états créés, les détruire lorsque vous avez terminé, etc. Cela se traduit par moins de lignes de code pour communiquer avec SQLite.</li>
<li>Toutes les opérations sont asynchrones. Utilisation des API de stockage synchrones est déconseillée, car ils bloquent le thread principal. Toutes les fonctionnalités de <code>Sqlite.jsm</code> sont asynchrone.</li>
<li>La gestion de la mémoire est plus facile. <code>Sqlite.jsm</code> gère les déclarations pour vous, il peut effectuer des actions intelligentes comme purger toutes les déclarations mises en cache qui ne sont pas utilisés, ce qui libère la mémoire dans le processus. Il y a même une API <code>shrinkMemory </code> qui permettra de minimiser automatiquement l'utilisation de la mémoire de la connexion.</li>
<li>Des opérations sont simples. Sqlite.jsm utilise une API de transaction construit avec <a href="/fr/docs/Mozilla/JavaScript_code_modules/Task.jsm" title="/fr/docs/Mozilla/JavaScript_code_modules/Task.jsm">task.jsm</a> qui permet aux transactions d'être écrites en tant que fonctions de procédure JavaScript (par opposition à une série d'opérations motrices de rappel). Si la fonction est lancée, la transaction est automatiquement annulée. Cela rend le code facile à lire et à écrire.</li>
<li><code>Sqlite.jsm </code> est un module JavaScript pur. Les complexités de XPCOM sont la plupart du temps cachés. Les programmeurs JavaScript doivent se sentir à l'aise en l'utilisant.</li>
</ul>
<p>{{ note("Le module de code de Javascript Sqlite.jsm peut seulement être utilisé du chrome.") }}</p>
<p>Avant de pouvoir utiliser ce module, vous devez l'importer dans votre champ d'application:</p>
<pre>let { Cu } = require('chrome')
<span class="brush: js">Cu.import("resource://gre/modules/Sqlite.jsm")</span></pre>
<h2 id="Obtention_d'une_connexion">Obtention d'une connexion</h2>
<p><code>Sqlite.jsm </code> exporte le symbole <code>Sqlite</code>. Ce symbole est un objet avec une seule fonction: <code>openConnection</code>. Cette fonction prend un objet dictionnaire définissant les options de connexion:</p>
<dl>
<dt>path</dt>
<dd>(Obligatoire) Le fichier de base de données à ouvrir. Cela peut être un chemin absolu ou relatif. Si un chemin relatif est donné, il est interprété comme relatif au répertoire du profil actuel. Si le chemin n'existe pas, une nouvelle base de données SQLite sera créé. La nom se termine généralement par <code>.sqlite</code>.</dd>
<dt>sharedMemoryCache</dt>
<dd>(En option) booléenne indiquant si plusieurs connexions à la base de données partagent la même mémoire cache. Toutefois, le partage nécessite également des connexions pour obtenir un verrou, rendant éventuellement l'accès de base de données plus lente. Par défaut, <code>true</code>.</dd>
<dt>shrinkMemoryOnConnectionIdleMS</dt>
<dd>(En option) Si défini, le de connexion va tenter de minimiser son utilisation de la mémoire après un grand nombre millisecondes de connexion inactive. La connexion est inactive lorsque aucun états n'est exécuter. Noter que ceci n'est pas une minuterie qui pourrait se déclencher pendant que l'Application est active.</dd>
</dl>
<p><code>openConnection(options)</code> retourne une <a href="https://fr.wikipedia.org/wiki/Futures_(informatique)">promise</a> d'une instance de connexion ouverte ou est rejetée si une erreur survient lors de l'ouverture de la base de données.</p>
<p>Voici un exemple:</p>
<pre class="brush: js">let { Cu } = require('chrome')
Cu.import("resource://gre/modules/Sqlite.jsm");
Sqlite.openConnection({ path: "myDatabase.sqlite", sharedMemoryCache: false }).then(
function onConnection(connection) {
// connection is the opened SQLite connection (see below for API).
},
function onError(error) {
// The connection could not be opened. error is an Error describing what went wrong.
}
);
</pre>
<h2 id="Utilisation_des_connexions_ouvertes">Utilisation des connexions ouvertes</h2>
<p>Les connexions ouvertes sont ce que vous interfacer avec <code>Sqlite.jsm</code>. Les sections suivantes détaillent l'API d'une instance de connexion ouverte.</p>
<h3 id="Gestion_des_connexions">Gestion des connexions</h3>
<p>Ces API sont utilisées pour gérer et vérifier l'état de la connexion.</p>
<h4 id="close()">close()</h4>
<p>Ferme la connexion de base de données. <strong> Doit </strong> être appelé pour chaque connexion ouverte.</p>
<p>Cette fonction retourne une promise qui sera résolu lorsque la base de données sera fermée.</p>
<p>Si une transaction est en cours d'execution au moment où cette fonction est appelée, la transaction sera annulée.</p>
<p>Si des déclarations sont en cours au moment où cette fonction est appelée, elles seront annulées.</p>
<p>Les utilisateurs ne doivent pas tenter d'utiliser la connexion après avoir appelé cette méthode que la connexion sera inutilisable.</p>
<h4 id="clone_(readOnly)">clone (readOnly)</h4>
<p>Cette fonction retourne un clone de la connexion-promise actuelle.</p>
<p>Ces fonctions reçoivent l' argument:</p>
<dl>
<dt>readOnly</dt>
<dd>(En option) Si <code>true</code> le clone sera en lecture seule,<code> false</code> par défaut. Si la connexion d'origine est déjà en lecture seule, le clone le sera, indépendamment de cette option. Si la connexion d'origine utilise le cache partagé, ce paramètre sera ignoré et le clone sera aussi privilégié que la connexion d'origine.</dd>
</dl>
<h4 id="transactionInProgress">transactionInProgress</h4>
<p>Cette propriété booléenne indique si une opération est en cours. Cela est rarement nécessaire par les appelants externes.</p>
<h4 id="shrinkMemory()">shrinkMemory()</h4>
<p>Cette fonction peut être appelée pour diminuer l'utilisation de la mémoire de la connexion. Ceci est un <a href="https://fr.wikipedia.org/wiki/Adaptateur_(patron_de_conception)">wrapper</a> utilisé dans le <code><a href="https://www.sqlite.org/pragma.html">PRAGMA</a> shrink_memory</code>, qui impose à SQLite la réduiction d'utilisation de la mémoire (par les caches de compensation, etc.).</p>
<p>Elle peut rendre votre base de données plus lent. Par conséquent, il faut être prudent avant d'appeler cette fonction.</p>
<p>Cela renvoie une promise qui est résolu lorsque l'opération est terminée.</p>
<h4 id="discardCachedStatements()">discardCachedStatements()</h4>
<p>Cette fonction est utilisée pour éliminer les instances d'instructions mises en cache, ce qui libère la mémoire dans le processus. Les déclarations de cache actifs ne seront pas effacées. Peut être appeler à tout moment.</p>
<p>Cela renvoie le nombre de déclarations mises en cache qui ont été rejetés.</p>
<h3 id="Table_et_gestion_du_schéma">Table et gestion du schéma</h3>
<p>Ces API traitent de la gestion des tables et le schéma de base de données.</p>
<h4 id="getSchemaVersion()">getSchemaVersion()</h4>
<p>La version définie par l'utilisateur associé au schéma de la base de données actuelle. Retourne 0 si aucune version de schéma a été défini.</p>
<h4 id="setSchemaVersion(value)">setSchemaVersion(value)</h4>
<p>Definie la valeur <code>value</code> de la nouvelle version associée au schéma de la base de données actuelle. Ceci est un wrapper autour de <code>PRAGMA user_version</code>.</p>
<h4 id="tableExists(name)">tableExists(name)</h4>
<p>Cette fonction détermine si une table existe dans la base de données actuelle. Elle renvoie une promise qui est résolu avec une valeur booléenne indiquant si la table existe.</p>
<h4 id="indexExists(name)">indexExists(name)</h4>
<p>Cette fonction détermine si un index nommé existe dans la base de données actuelle. Elle renvoie une promesse qui est résolu avec une valeur booléenne indiquant si l'index existe.</p>
<h3 id="Déclaration_d'exécution">Déclaration d'exécution</h3>
<p>Ces API facilitent l'exécution des instructions de connexion.</p>
<h4 id="executeCached(sql_params_onRow)">executeCached(sql, params, onRow)</h4>
<h4 id="execute(sql_params_onRow)">execute(sql, params, onRow)</h4>
<p>Ces fonctions similaires sont utilisés pour exécuter une instruction SQL unique sur la connexion. Comme vous l'avez deviné par le nom, il y a 2 options: mises en cache et non mis en cache. En dehors de cela, ils se comportent de manière identique.</p>
<p>Ces fonctions reçoivent les arguments suivants:</p>
<dl>
<dt>sql</dt>
<dd>(Obligatoire) chaîne SQL à exécuter. Le point-virgule final n'est pas nécessaire.</dd>
<dt>params</dt>
<dd>(En option) Paramètres liés à cette déclaration. Cela peut être un tableau ou un objet. Voir les notes ci-dessous.</dd>
<dt>onRow</dt>
<dd>(En option) Fonction qui est appelée lorsqu'une ligne a été reçue.</dd>
</dl>
<p>La valeur de retour est une promise qui est résolu lorsque l'instruction a terminé l'exécution.</p>
<p>Quand une instruction est exécutée via <code>executeCached()</code>, l'objet instruction préparée est mis en cache à l'intérieur de la connexion ouverte. La prochaine fois que cette même instruction SQL est exécutée (<code>sql </code> argument est identique à celui passé avant), l'ancien objet de la déclaration est réutilisée. Cela permet d'économiser du temps associé à l'analyse de l'instruction SQL et la création d'un nouvel objet de déclaration. Inconvénient: l'objet de la déclaration en cache persiste dans la connexion ouverte, en prenant de la mémoire.</p>
<p>Quand une instruction est exécutée via <code>execute()</code>, l'objet de la déclaration sous-jacente est jeté au terme de l'exécution.</p>
<p><code>executeCached()</code> est recommandé pour les déclarations qui seront exécutées plusieurs fois. <code>execute()</code> est recommandé pour les déclarations qui seront exécutées rarement ou une fois.</p>
<p>Noter que les utilisateurs ne doivent pas préparer les états manuellement avant l'exécution. Il suffit d'appeler <code>executeCached()</code> et la déclaration sera préparée pour vous automatiquement.</p>
<p>Les paramètres peuvent être liés à la déclaration faite par la définition de l'argument <code>params </code>. Cet argument peut être un tableau de paramètres ordonnées ou un objet de type dicionnaire. Si la déclaration ne contient pas de paramètres liés, cet argument peut être omis ou spécifié comme nulle.</p>
<p>{{ note("Les utilisateurs sont fortement encouragés à utiliser des paramètres liés au lieu de créer dynamiquement des instructions SQL pour des raisons de sécurité.") }}</p>
<div class="line">{{ note("Les utilisateurs sont encouragés à passer des objets type dictionnaire plutôt que des tableaux pour les paramètres liés car ils empêchent de s'emeler les pinceaux.") }}</div>
<div class="line"> </div>
<div class="line">Lorsque <code>onRow </code> n'est pas défini, les résultats complets de l'opération sont tamponnés avant que l'appelant soit informé de la déclaration d'achèvement. Pour <code>INSERT</code>, <code>UPDATE</code> et <code>DELETE</code>, ce n'est pas pertinentes. Cependant, il peut y avoir des conséquences importante pour <code>SELECT </code>. Si votre déclaration <code>SELECT </code> retourne beaucoup de données, cette mise en mémoire tampon peut entraîner une utilisation excessive de la mémoire. Par conséquent, il est recommandé d'utiliser <code>onRow </code> avec <code>SELECT</code>.</div>
<div class="line">
<div class="line"> </div>
<div class="line" id="LC396">Si <code>StopIteration </code> est emis lors de l'exécution d'un gestionnaire <code>onRow</code>, l'exécution de l'instruction est immédiatement annulée. Les lignes suivantes ne seront pas traitées. La promise est résolu immédiatement.</div>
<div class="line" id="LC397"> </div>
<div class="line" id="LC400">Si une exception <code>StopIteration </code> est levée par le gestionnaire <code>onRow </code>, l'exception est enregistré et le traitement des lignes suivantes se poursuit normalement. La promise est toujours résolue (pas rejetée).</div>
<p>La promise sera rejeté avec une <code>Error </code>, si la déclaration n'a pas terminé l'exécution complète. L'<code>Error </code> peut avoir une propriété <code>errors</code>. Si elle est définie, ce sera un tableau d'objets décrivant les erreurs. Chaque objet possède les propriétés <code>result</code> et <code>message</code>. <code>result </code> est un code d'erreur numérique et <code>message</code> est une chaîne décrivant le problème.</p>
<p>Si <code>onRow </code> est spécifié, la promise sera résolu avec un booléen indiquant si le gestionnaire onRow a été appelé. Sinon, la valeur réglée sera un tableau de <a href="/fr/docs/MozIStorageRow" title="/fr/docs/MozIStorageRow"> <code>mozIStorageRow</code> </a>.</p>
<h4 id="executeTransaction(func_type)">executeTransaction(func, type)</h4>
<p>Cette fonction est utilisée pour exécuter une transaction de base de données. Une transaction est une série de déclarations connexes traités comme une seule unité fonctionnelle. Si la transaction réussit, toutes les déclarations contenues dedans sont engagés comme une seule unité. Si la transaction échoue, la base de données revient à son état avant le début de la transaction.</p>
<p>Cette fonction reçoit les arguments suivants:</p>
<dl>
<dt>func</dt>
<dd>La fonction définissant le corps de la transaction.</dd>
<dt>type</dt>
<dd>Le type de transaction à effectuer. Ce doit être l'une des constantes de <a href="https://www.sqlite.org/lang_transaction.html">TRANSACTION_*</a> sur l'instance de connexion ouverte. Les valeurs valides sont <code>TRANSACTION_DEFERRED</code> , <code>TRANSACTION_IMMEDIATE</code> , <code>TRANSACTION_EXCLUSIVE</code> . Consultez la documentation SQLite pour leur signification. La valeur par défaut est <code>TRANSACTION_DEFERRED</code>.</dd>
</dl>
<p>La fonction passée est une fonction de générateur compatible Task.jsm. Lorsqu'elle est appelée, la fonction reçoit comme argument l'instance de connexion actuelle. Cette fonction de générateur devrait produire des promises, probablement ceux qui sont renvoyés en appelant <code>executeCached()</code> et <code>execute()</code>.</p>
<p>Si nous arrivons à la fin de la fonction de générateur sans erreur, la transaction est validée. Si une erreur se produit, la transaction est abandonnée.</p>
<p>La valeur retournée par cette fonction est une promise qui est résolu lorsque la transaction a été exécutée ou rejetée si la transaction a été annulée.</p>
<h2 id="Exemples">Exemples</h2>
<h3 id="Open_Execute_Close">Open, Execute, Close</h3>
<p>Dans cet exemple, nous ouvrons une connexion, exécutons une instruction simple, puis fermons la connexion.</p>
<pre class="brush: js">Sqlite.openConnection({path: "MyDB.sqlite"}).then(
function onOpen(conn) {
conn.execute("SELECT 1").then(
function onStatementComplete(result) {
conn.close().then(
function onClose() {
alert("We are done!");
}
)
}
)
}
)
</pre>
<p>Ce n'est pas un excellent exemple parce qu'il ne comprend pas la gestion des erreurs et est un peu difficile à lire.</p>
<p>Voici la même chose mais avec <a href="/fr/docs/Mozilla/JavaScript_code_modules/Task.jsm">Task.jsm</a>:</p>
<pre class="brush: js">Task.spawn(function* demoDatabase() {
let conn = yield Sqlite.openConnection({path: "MyDB.sqlite"});
try {
let result = yield conn.execute("SELECT 1");
} finally {
yield conn.close();
}
});</pre>
<h3 id="Bound_Parameters">Bound Parameters</h3>
<p>Voici quelques exemples montrant des paramètres liés. Supposons que nous ouvrons une connexion avec la variable <code>conn</code>.</p>
<pre class="brush: js">let dataToInsert = [
["foo", "bar"],
["biz", "baz"],
["yo", "ho"],
];
Task.spawn(function* doInsert() {
for (let data of dataToInsert) {
yield conn.executeCached("INSERT INTO myTable VALUES (?, ?)", data);
}
});</pre>
</div>
<p>Et la même chose avec des paramètres nommés.</p>
<pre class="brush: js">let dataToInsert = [
{paramA: "foo", paramB: "bar"},
{paramA: "biz", paramB: "baz"},
{paramA: "yo", paramB: "ho"},
];
Task.spawn(function* doInsert() {
for (let data of dataToInsert) {
yield conn.executeCached("INSERT INTO myTable VALUES (:paramA, :paramB)", data);
}
});</pre>
<h3 id="Transactions">Transactions</h3>
<p>Ces exemples montrent comment fonctionnent les transactions.</p>
<pre class="brush: js">conn.executeTransaction(function* simpleTransaction() {
yield conn.execute("INSERT INTO myTable VALUES (?, ?)", ["foo", "bar"]);
yield conn.execute("INSERT INTO myTable VALUES (?, ?)", ["biz", "baz"]);
});</pre>
<p>L'exemple ci-dessus se traduira par 2 instructions INSERT dans une transaction différée (en supposant que les inserts procèdent sans erreur, bien sûr).</p>
<p>Voici un exemple où nous voulons forcer une annulation de la transaction.</p>
<pre class="brush: js">conn.executeTransaction(function* complexTransaction() {
yield conn.execute("INSERT INTO myTable VALUES (?, ?)", ["foo", "bar"]);
let data = yield conn.execute("SELECT * FROM myTable");
if (data.length < 5) {
throw new Error("We don't have the expected 5 rows to perform the next operation!");
}
// ...
});</pre>
<h3 id="Sélection_et_retour_des_données">Sélection et retour des données</h3>
<p>Ces exemples montrent comment accéder aux données qui sont retournées.</p>
<p>Cet exemple montre plusieurs lignes d'une table retournées en utilisant le paramètre <code>onRow</code>.</p>
<pre class="brush: js">let accounts = [];
let accountId, userName;
let statement = "SELECT account_id, username FROM accounts ORDER BY username ASC";
conn.executeCached(statement, null, function(row) {
accountId = row.getResultByName("account_id");
userName = row.getResultByName("username");
accounts.push({ accountId: accountId, userName: userName });
}).then(function onStatementComplete(result) {
// All accounts returned successfully, so do something with them.
<span class="pln"> console</span><span class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="pln">result</span><span class="pun">);</span><span class="pln"> </span><span class="com">// It worked!</span>
if (callback) {
callback(null, accounts);
}
},
function onError(err) {
// An error occurred.
<span class="pln"> console</span><span class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span class="pln">err</span><span class="pun">);</span><span class="pln"> </span><span class="com">// Error, Oh noes!</span>
if (callback) {
callback(err);
}
});</pre>
<div class="note">
<p><strong>Remarque: </strong>les> paramètres <strong> <code>then</code> </strong> peuvent être des fonctions anonymes (i.e. <strong> <code>function()</code> </strong>) , les seulements nomées sont <strong> <code>onStatementComplete</code> </strong> et <strong> <code>onError</code> </strong> pour la lisibilité.</p>
</div>
<p>Cet exemple démontre la récupération d'une ligne sans utiliser le paramètre <code>onRow</code>, en utilisant le résultat de <code>conn.execute</code>. Cet exemple montre également la récupération de la clé primaire de la dernière ligne insérée.</p>
<pre class="brush: js">Task.spawn(function* () {
try {
conn = yield Sqlite.openConnection({ path: dbFile.path });
let statement = "INSERT INTO accounts (username, details) VALUES (:username, :details)"
let params = { username:"LordBusiness", details: "All I'm asking for is total perfection." };
yield conn.execute(statement,params);
// Get accountId of the INSERT.
statement = "SELECT last_insert_rowid() AS lastInsertRowID";
result = yield conn.execute(statement);
// Only one row is returned.
let row = result[0];
let accountId = row.getResultByName("lastInsertRowID");
if (callback) {
callback(null, accountId);
}
} catch (err) {
if (callback) {
callback(err);
}
} finally {
conn.close();
}
});</pre>
<div class="note">
<p><strong>Remarque: </strong> La valeur retournée par<strong> last_insert_rowid()</strong> l'est par connexion, de sorte que vous devrez peut-être ouvrir des connexions séparées lorsque vous faites plusieurs <code>INSERT</code> à différents endroits, pour être sûr que l'identifiant de ligne qui est retourné corresponde.</p>
</div>
<h2 id="Voir_aussi">Voir aussi</h2>
<ul>
<li><a href="https://dxr.mozilla.org/mozilla-central/source/toolkit/modules/Sqlite.jsm">Sqlite.jsm source on DXR</a></li>
<li><a href="/fr/docs/Storage">Storage</a></li>
</ul>
|