1/* -*- Mode: idl; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2/* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5
6#include "nsISupports.idl"
7
8interface mozIStorageCompletionCallback;
9interface mozIStorageFunction;
10interface mozIStorageProgressHandler;
11interface mozIStorageBaseStatement;
12interface mozIStorageStatement;
13interface mozIStorageAsyncStatement;
14interface mozIStorageStatementCallback;
15interface mozIStoragePendingStatement;
16interface nsIFile;
17
18/**
19 * mozIStorageAsyncConnection represents an asynchronous database
20 * connection attached to a specific file or to an in-memory data
21 * storage.  It is the primary interface for interacting with a
22 * database from the main thread, including creating prepared
23 * statements, executing SQL, and examining database errors.
24 */
25[scriptable, uuid(8bfd34d5-4ddf-4e4b-89dd-9b14f33534c6)]
26interface mozIStorageAsyncConnection : nsISupports {
27  /**
28   * Transaction behavior constants.
29   */
30  const int32_t TRANSACTION_DEFAULT = -1;
31  const int32_t TRANSACTION_DEFERRED = 0;
32  const int32_t TRANSACTION_IMMEDIATE = 1;
33  const int32_t TRANSACTION_EXCLUSIVE = 2;
34
35  /**
36   * The default behavior for all transactions run on this connection. Defaults
37   * to `TRANSACTION_DEFERRED`, and can be overridden for individual
38   * transactions.
39   */
40  attribute int32_t defaultTransactionType;
41
42  /**
43   * The maximum number of bound parameters for statements executed on this
44   * connection. If your statement has more params than this limit, you'll
45   * need to chunk them into multiple statements. See `PlacesUtils.chunkArray`
46   * and its callers in Places for examples of how to do this, or read on for
47   * an overview.
48   *
49   * Keep in mind that the variable limit is for the _total_ number of
50   * parameters, including ones bound by name (using the `:VVV`, `@VVV`, or
51   * `?VVV` syntax) and index (`?` and `?NNN`).
52   *
53   * This means, when chunking:
54   *
55   * - If you're binding 1 param per 1 value per chunk (for example, if you
56   *   have a list of GUIDs and a clause like `WHERE guid IN (?, ?, ?, ...)`,
57   *   your chunk length is just `variableLimit`.
58   * - If you're binding 1 param per 1 value per chunk, but using that
59   *   param in multiple positions in the query (for example, `WHERE url_hash
60   *   IN (hash(?1), hash(?2), ...) AND url IN (?1, ?2, ...)`), you can use the
61   *   `?NNN` syntax with a chunk length of `variableLimit`.
62   * - If you're binding N params per 1 value per chunk (for example, if you
63   *   have a list of items with GUIDs and parent GUIDs, and you want to bind
64   *   both), your chunk length is `variableLimit / N`, since you're binding
65   *   two params for each element.
66   * - If you're binding K params per L values per chunk, plus M fixed ones
67   *   (for example, `WHERE parentGuid = :parentGuid AND guid IN (?, ?, ...)`),
68   *   your chunk length is `variableLimit - M`, to ensure there's space for the
69   *   fixed variables.
70   *
71   * If you bind more params than this limit, `create{Async}Statement` will
72   * fail with a "too many SQL variables" error.
73   */
74  readonly attribute int32_t variableLimit;
75
76  /**
77   * Returns true if a transaction is active on this connection.
78   *
79   * Note that this is true if a transaction is active on the connection,
80   * regardless of how it was opened. There are several ways to open one:
81   *
82   * 1. Explicitly calling `beginTransaction` on a `mozIStorageConnection`.
83   * 2. Calling `executeSimpleSQL("BEGIN")` or
84   *    `createStatement("BEGIN").execute()` on a `mozIStorageConnection`.
85   * 3. Executing an async statement, like
86   *    `createAsyncStatement("BEGIN").executeAsync(...)`. This is what
87   *    `Sqlite.jsm` does under the hood.
88   *
89   * Because of this, it's important *not* to use this attribute to decide
90   * whether to *commit* the active transaction, because the caller that opened
91   * it may not expect that. This is why both `mozStorageTransaction` and
92   * `Sqlite.jsm` use an internal variable (`mHasTransaction` for the former;
93   * `_hasInProgressTransaction` for the latter) to check if their transaction
94   * is already in progress, instead of just checking this attribute before
95   * committing. Otherwise, mozStorage might accidentally commit (or roll back!)
96   * a transaction started by `Sqlite.jsm`, and vice versa.
97   */
98  readonly attribute boolean transactionInProgress;
99
100  /**
101   * Close this database connection, allowing all pending statements
102   * to complete first.
103   *
104   * @param aCallback [optional]
105   *        A callback that will be notified when the close is completed,
106   *        with the following arguments:
107   *        - status: the status of the call
108   *        - value: |null|
109   *
110   * @throws NS_ERROR_NOT_SAME_THREAD
111   *         If called on a thread other than the one that opened it.  The
112   *         callback will not be dispatched.
113   * @throws NS_ERROR_NOT_INITIALIZED
114   *         If called on a connection that has already been closed or was
115   *         never properly opened.  The callback will still be dispatched
116   *         to the main thread despite the returned error.
117   * @note If this call should fail, the callback won't be invoked.
118   */
119  void asyncClose([optional] in mozIStorageCompletionCallback aCallback);
120
121  /**
122   * Forcibly closes a database connection synchronously.
123   * This should only be used when it's required to close and replace the
124   * database synchronously to return control to the consumer, for example in
125   * case of a detected corruption on database opening.
126   * Since this spins the events loop, it should be used only in very particular
127   * and rare situations, or it may cause unexpected consequences (crashes).
128   *
129   * @throws NS_ERROR_NOT_SAME_THREAD
130   *         If called on a thread other than the one that opened it.
131   */
132  [noscript] void spinningSynchronousClose();
133
134  /**
135   * Clone a database and make the clone read only if needed.
136   * SQL Functions and attached on-disk databases are applied to the new clone.
137   *
138   * @param aReadOnly
139   *        If true, the returned database should be put into read-only mode.
140   *
141   * @param aCallback
142   *        A callback that will be notified when the operation is complete,
143   *        with the following arguments:
144   *        - status: the status of the operation
145   *        - value: in case of success, an intance of
146   *             mozIStorageAsyncConnection cloned from this one.
147   *
148   * @throws NS_ERROR_NOT_SAME_THREAD
149   *         If is called on a thread other than the one that opened it.
150   * @throws NS_ERROR_UNEXPECTED
151   *         If this connection is a memory database.
152   *
153   * @note If your connection is already read-only, you will get a read-only
154   *       clone.
155   * @note The resulting connection will implement `mozIStorageConnection`, but
156   *       all synchronous methods will throw if called from the main thread.
157   * @note Due to a bug in SQLite, if you use the shared cache
158   *       (see mozIStorageService), you end up with the same privileges as the
159   *       first connection opened regardless of what is specified in aReadOnly.
160   * @note The following pragmas are copied over to a read-only clone:
161   *        - cache_size
162   *        - temp_store
163   *       The following pragmas are copied over to a writeable clone:
164   *        - cache_size
165   *        - temp_store
166   *        - foreign_keys
167   *        - journal_size_limit
168   *        - synchronous
169   *        - wal_autocheckpoint
170   *       All SQL functions are copied over to read-only and writeable clones.
171   *       Additionally, all temporary tables, triggers, and views, as well as
172   *       any indexes on temporary tables, are copied over to writeable clones.
173   *       For temporary tables, only the schemas are copied, not their
174   *       contents.
175   */
176  void asyncClone(in boolean aReadOnly,
177                  in mozIStorageCompletionCallback aCallback);
178
179  /**
180   * The current database nsIFile.  Null if the database
181   * connection refers to an in-memory database.
182   */
183  readonly attribute nsIFile databaseFile;
184
185  /**
186   * Causes any pending database operation to abort and return at the first
187   * opportunity.
188   * This can only be used on read-only connections that don't implement
189   * the mozIStorageConnection interface.
190   * @note operations that are nearly complete may still be able to complete.
191   * @throws if used on an unsupported connection type, or a closed connection.
192   */
193  void interrupt();
194
195  //////////////////////////////////////////////////////////////////////////////
196  //// Statement creation
197
198  /**
199   * Create an asynchronous statement for the given SQL. An
200   * asynchronous statement can only be used to dispatch asynchronous
201   * requests to the asynchronous execution thread and cannot be used
202   * to take any synchronous actions on the database.
203   *
204   * The expression may use ? to indicate sequential numbered arguments,
205   * ?1, ?2 etc. to indicate specific numbered arguments or :name and
206   * $var to indicate named arguments.
207   *
208   * @param aSQLStatement
209   *        The SQL statement to execute.
210   * @return a new mozIStorageAsyncStatement
211   * @note The statement is created lazily on first execution.
212   */
213  mozIStorageAsyncStatement createAsyncStatement(in AUTF8String aSQLStatement);
214
215  /**
216   * Execute an array of statements created with this connection using
217   * any currently bound parameters. When the array contains multiple
218   * statements, the execution is wrapped in a single
219   * transaction. These statements can be reused immediately, and
220   * reset does not need to be called.
221   *
222   * @param aStatements
223   *        The array of statements to execute asynchronously, in the order they
224   *        are given in the array.
225   * @param aCallback [optional]
226   *        The callback object that will be notified of progress, errors, and
227   *        completion.
228   * @return an object that can be used to cancel the statements execution.
229   *
230   * @note If you have any custom defined functions, they must be
231   *        re-entrant since they can be called on multiple threads.
232   */
233  mozIStoragePendingStatement executeAsync(
234    in Array<mozIStorageBaseStatement> aStatements,
235    [optional] in mozIStorageStatementCallback aCallback
236  );
237
238  /**
239   * Execute asynchronously an SQL expression, expecting no arguments.
240   *
241   * @param aSQLStatement
242   *        The SQL statement to execute
243   * @param aCallback [optional]
244   *        The callback object that will be notified of progress, errors, and
245   *        completion.
246   * @return an object that can be used to cancel the statement execution.
247   */
248  mozIStoragePendingStatement executeSimpleSQLAsync(
249    in AUTF8String aSQLStatement,
250    [optional] in mozIStorageStatementCallback aCallback);
251
252  //////////////////////////////////////////////////////////////////////////////
253  //// Functions
254
255  /**
256   * Create a new SQL function.  If you use your connection on multiple threads,
257   * your function needs to be threadsafe, or it should only be called on one
258   * thread.
259   *
260   * @param aFunctionName
261   *        The name of function to create, as seen in SQL.
262   * @param aNumArguments
263   *        The number of arguments the function takes. Pass -1 for
264   *        variable-argument functions.
265   * @param aFunction
266   *        The instance of mozIStorageFunction, which implements the function
267   *        in question.
268   */
269  void createFunction(in AUTF8String aFunctionName,
270                      in long aNumArguments,
271                      in mozIStorageFunction aFunction);
272
273  /**
274   * Delete custom SQL function.
275   *
276   * @param aFunctionName
277   *        The name of function to remove.
278   */
279  void removeFunction(in AUTF8String aFunctionName);
280
281  /**
282   * Sets a progress handler. Only one handler can be registered at a time.
283   * If you need more than one, you need to chain them yourself.  This progress
284   * handler should be threadsafe if you use this connection object on more than
285   * one thread.
286   *
287   * @param aGranularity
288   *        The number of SQL virtual machine steps between progress handler
289   *        callbacks.
290   * @param aHandler
291   *        The instance of mozIStorageProgressHandler.
292   * @return previous registered handler.
293   */
294  mozIStorageProgressHandler setProgressHandler(in int32_t aGranularity,
295                                                in mozIStorageProgressHandler aHandler);
296
297  /**
298   * Remove a progress handler.
299   *
300   * @return previous registered handler.
301   */
302  mozIStorageProgressHandler removeProgressHandler();
303};
304