1 /++
2 Managing SQLite3 database connections.
3 
4 Authors:
5     Nicolas Sicard (biozic) and other contributors at $(LINK https://github.com/biozic/d2sqlite3)
6 
7 Copyright:
8     Copyright 2011-18 Nicolas Sicard.
9 
10 License:
11     $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
12 +/
13 module d2sqlite3.database;
14 
15 import d2sqlite3.statement;
16 import d2sqlite3.results;
17 import d2sqlite3.sqlite3;
18 import d2sqlite3.internal.memory;
19 import d2sqlite3.internal.util;
20 
21 import std.conv : text, to;
22 import std.exception : enforce;
23 import std.string : format, fromStringz, toStringz;
24 import std.typecons : Nullable;
25 
26 import core.stdc.stdlib : free;
27 
28 /// Set _UnlockNotify version if compiled with SqliteEnableUnlockNotify or SqliteFakeUnlockNotify
29 version (SqliteEnableUnlockNotify) version = _UnlockNotify;
30 else version (SqliteFakeUnlockNotify) version = _UnlockNotify;
31 
32 /// Type for the internal representation of blobs
33 alias Blob = immutable(ubyte)[];
34 
35 /// SQLite type codes
36 enum SqliteType
37 {
38     INTEGER = SQLITE_INTEGER, ///
39     FLOAT = SQLITE_FLOAT, ///
40     TEXT = SQLITE3_TEXT, ///
41     BLOB = SQLITE_BLOB, ///
42     NULL = SQLITE_NULL ///
43 }
44 
45 /++
46 A caracteristic of user-defined functions or aggregates.
47 +/
48 enum Deterministic
49 {
50     /++
51     The returned value is the same if the function is called with the same parameters.
52     +/
53     yes = 0x800,
54 
55     /++
56     The returned value can vary even if the function is called with the same parameters.
57     +/
58     no = 0
59 }
60 
61 /++
62 An database connection.
63 
64 This struct is a reference-counted wrapper around a `sqlite3*` pointer.
65 +/
66 struct Database
67 {
68     import std.traits : isFunctionPointer, isDelegate;
69     import std.typecons : RefCounted, RefCountedAutoInitialize;
70 
71 private:
72     struct Payload
73     {
74         sqlite3* handle;
75         void* updateHook;
76         void* commitHook;
77         void* rollbackHook;
78         void* progressHandler;
79         void* traceCallback;
80         void* profileCallback;
81         version (_UnlockNotify) IUnlockNotifyHandler unlockNotifyHandler;
82         debug string filename;
83 
84         this(sqlite3* handle) nothrow
85         {
86             this.handle = handle;
87         }
88 
89         ~this() nothrow
90         {
91             debug ensureNotInGC!Database(filename);
92             free(updateHook);
93             free(commitHook);
94             free(rollbackHook);
95             free(progressHandler);
96             free(traceCallback);
97             free(profileCallback);
98 
99             if (!handle)
100                 return;
101             sqlite3_progress_handler(handle, 0, null, null);
102             sqlite3_close(handle);
103         }
104     }
105 
106     RefCounted!(Payload, RefCountedAutoInitialize.no) p;
107 
108     void check(int result)
109     {
110         enforce(result == SQLITE_OK, new SqliteException(errmsg(p.handle), result));
111     }
112 
113 public:
114     /++
115     Opens a database connection.
116 
117     Params:
118         path = The path to the database file. In recent versions of SQLite, the path can be
119         an URI with options.
120 
121         flags = Options flags.
122 
123     See_Also: $(LINK http://www.sqlite.org/c3ref/open.html) to know how to use the flags
124     parameter or to use path as a file URI if the current configuration allows it.
125     +/
126     this(string path, int flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE)
127     {
128         sqlite3* hdl;
129         auto result = sqlite3_open_v2(path.toStringz, &hdl, flags, null);
130         enforce(result == SQLITE_OK, new SqliteException(hdl ? errmsg(hdl) : "Error opening the database", result));
131         p = Payload(hdl);
132         debug p.filename = path;
133     }
134 
135     /++
136     Explicitly closes the database connection.
137 
138     After a successful call to `close()`, using the database connection or one of its prepared
139     statement is an error. The `Database` object is destroyed and cannot be used any more.
140     +/
141     void close()
142     {
143         auto result = sqlite3_close(p.handle);
144         enforce(result == SQLITE_OK, new SqliteException(errmsg(p.handle), result));
145         p.handle = null;
146         destroy(p);
147     }
148 
149     /++
150     Gets the SQLite internal _handle of the database connection.
151     +/
152     sqlite3* handle() @property nothrow
153     {
154         return p.handle;
155     }
156 
157     /++
158     Gets the path associated with an attached database.
159 
160     Params:
161         database = The name of an attached database.
162 
163     Returns: The absolute path of the attached database.
164         If there is no attached database, or if database is a temporary or
165         in-memory database, then null is returned.
166     +/
167     string attachedFilePath(string database = "main")
168     {
169         assert(p.handle);
170         return sqlite3_db_filename(p.handle, database.toStringz).to!string;
171     }
172 
173     /++
174     Gets the read-only status of an attached database.
175 
176     Params:
177         database = The name of an attached database.
178     +/
179     bool isReadOnly(string database = "main")
180     {
181         assert(p.handle);
182         immutable ret = sqlite3_db_readonly(p.handle, database.toStringz);
183         enforce(ret >= 0, new SqliteException("Database not found: %s".format(database), ret));
184         return ret == 1;
185     }
186 
187     /++
188     Gets metadata for a specific table column of an attached database.
189 
190     Params:
191         table = The name of the table.
192 
193         column = The name of the column.
194 
195         database = The name of a database attached. If null, then all attached databases
196         are searched for the table using the same algorithm used by the database engine
197         to resolve unqualified table references.
198     +/
199     TableColumnMetadata tableColumnMetadata(string table, string column, string database = "main")
200     {
201         TableColumnMetadata data;
202         char* pzDataType, pzCollSeq;
203         int notNull, primaryKey, autoIncrement;
204         assert(p.handle);
205         check(sqlite3_table_column_metadata(p.handle, database.toStringz, table.toStringz,
206             column.toStringz, &pzDataType, &pzCollSeq, &notNull, &primaryKey, &autoIncrement));
207         data.declaredTypeName = pzDataType.to!string;
208         data.collationSequenceName = pzCollSeq.to!string;
209         data.isNotNull = cast(bool) notNull;
210         data.isPrimaryKey = cast(bool) primaryKey;
211         data.isAutoIncrement = cast(bool) autoIncrement;
212         return data;
213     }
214 
215     /++
216     Executes a single SQL statement and returns the results directly.
217 
218     It's the equivalent of `prepare(sql).execute()`.
219     Or when used with args the equivalent of:
220     ---
221     auto stm = prepare(sql);
222     stm.bindAll(args);
223     stm.execute();
224     ---
225 
226     The results become undefined when the Database goes out of scope and is destroyed.
227 
228     Params:
229         sql = The code of the SQL statement.
230         args = Optional arguments to bind to the SQL statement.
231     +/
232     ResultRange execute(Args...)(string sql, Args args)
233     {
234         auto stm = prepare(sql);
235         static if (Args.length) stm.bindAll(args);
236         return stm.execute();
237     }
238     ///
239     unittest
240     {
241         auto db = Database(":memory:");
242         db.execute("CREATE TABLE test (val INTEGER)");
243         db.execute("INSERT INTO test (val) VALUES (:v)", 1);
244         assert(db.execute("SELECT val FROM test WHERE val=:v", 1).oneValue!int == 1);
245     }
246 
247     /++
248     Runs an SQL script that can contain multiple statements.
249 
250     Params:
251         script = The code of the SQL script.
252 
253         dg = A delegate to call for each statement to handle the results. The passed
254         ResultRange will be empty if a statement doesn't return rows. If the delegate
255         return false, the execution is aborted.
256     +/
257     void run(string script, bool delegate(ResultRange) dg = null)
258     {
259         foreach (sql; script.byStatement)
260         {
261             auto stmt = prepare(sql);
262             auto results = stmt.execute();
263             if (dg && !dg(results))
264                 return;
265         }
266     }
267     ///
268     unittest
269     {
270         auto db = Database(":memory:");
271         db.run(`CREATE TABLE test1 (val INTEGER);
272                 CREATE TABLE test2 (val FLOAT);
273                 DROP TABLE test1;
274                 DROP TABLE test2;`);
275     }
276 
277     /++
278     Prepares (compiles) a single SQL statement and returns it, so that it can be bound to
279     values before execution.
280 
281     The statement becomes invalid if the Database goes out of scope and is destroyed.
282     +/
283     Statement prepare(string sql)
284     {
285         return Statement(this, sql);
286     }
287 
288     /// Convenience functions equivalent to an SQL statement.
289     void begin() { execute("BEGIN"); }
290     /// Ditto
291     void commit() { execute("COMMIT"); }
292     /// Ditto
293     void rollback() { execute("ROLLBACK"); }
294 
295     /++
296     Returns the rowid of the last INSERT statement.
297     +/
298     long lastInsertRowid()
299     {
300         assert(p.handle);
301         return sqlite3_last_insert_rowid(p.handle);
302     }
303 
304     /++
305     Gets the number of database rows that were changed, inserted or deleted by the most
306     recently executed SQL statement.
307     +/
308     int changes() @property nothrow
309     {
310         assert(p.handle);
311         return sqlite3_changes(p.handle);
312     }
313 
314     /++
315     Gets the number of database rows that were changed, inserted or deleted since the
316     database was opened.
317     +/
318     int totalChanges() @property nothrow
319     {
320         assert(p.handle);
321         return sqlite3_total_changes(p.handle);
322     }
323 
324     /++
325     Gets the SQLite error code of the last operation.
326     +/
327     int errorCode() @property nothrow
328     {
329         return p.handle ? sqlite3_errcode(p.handle) : 0;
330     }
331 
332     /++
333     Interrupts any pending database operations.
334 
335     It's safe to call this function from anouther thread.
336 
337     See_also: $(LINK http://www.sqlite.org/c3ref/interrupt.html).
338     +/
339     void interrupt()
340     {
341         assert(p.handle);
342         sqlite3_interrupt(p.handle);
343     }
344 
345     /++
346     Sets a connection configuration option.
347 
348     See_Also: $(LINK http://www.sqlite.org/c3ref/db_config.html).
349     +/
350     void config(Args...)(int code, Args args)
351     {
352         assert(p.handle);
353         auto result = sqlite3_db_config(p.handle, code, args);
354         enforce(result == SQLITE_OK, new SqliteException("Database configuration: error %s".format(result), result));
355     }
356 
357     /++
358     Enables or disables loading extensions.
359     +/
360     void enableLoadExtensions(bool enable = true)
361     {
362         assert(p.handle);
363         immutable ret = sqlite3_enable_load_extension(p.handle, enable);
364         enforce(ret == SQLITE_OK,
365             new SqliteException("Could not enable loading extensions.", ret));
366     }
367 
368     /++
369     Loads an extension.
370 
371     Params:
372         path = The path of the extension file.
373 
374         entryPoint = The name of the entry point function. If null is passed, SQLite
375         uses the name of the extension file as the entry point.
376     +/
377     void loadExtension(string path, string entryPoint = null)
378     {
379         assert(p.handle);
380         char* p_err;
381         scope (failure)
382             sqlite3_free(p_err);
383 
384         immutable ret = sqlite3_load_extension(p.handle, path.toStringz, entryPoint.toStringz, &p_err);
385         enforce(ret == SQLITE_OK, new SqliteException(
386                 "Could not load extension: %s:%s (%s)".format(entryPoint, path,
387                 p_err !is null ? fromStringz(p_err) : "No additional info"), ret));
388     }
389 
390     /++
391     Creates and registers a new function in the database.
392 
393     If a function with the same name and the same arguments already exists, it is replaced
394     by the new one.
395 
396     The memory associated with the function will be released when the database connection
397     is closed.
398 
399     Params:
400         name = The name that the function will have in the database.
401 
402         fun = a delegate or function that implements the function. $(D_PARAM fun)
403         must satisfy the following criteria:
404             $(UL
405                 $(LI It must not be variadic.)
406                 $(LI Its arguments must all have a type that is compatible with SQLite types:
407                 it must be a boolean or numeric type, a string, an array, `null`,
408                 or a `Nullable!T` where T is any of the previous types.)
409                 $(LI Its return value must also be of a compatible type.)
410             )
411             or
412             $(UL
413                 $(LI It must be a normal or type-safe variadic function where the arguments
414                 are of type `ColumnData`. In other terms, the signature of the function must be:
415                 `function(ColumnData[] args)` or `function(ColumnData[] args...)`)
416                 $(LI Its return value must be a boolean or numeric type, a string, an array, `null`,
417                 or a `Nullable!T` where T is any of the previous types.)
418             )
419         Pass a `null` function pointer to delete the function from the database connection.
420 
421         det = Tells SQLite whether the result of the function is deterministic, i.e. if the
422         result is the same when called with the same parameters. Recent versions of SQLite
423         perform optimizations based on this. Set to `Deterministic.no` otherwise.
424 
425     See_Also: $(LINK http://www.sqlite.org/c3ref/create_function.html).
426     +/
427     void createFunction(T)(string name, T fun, Deterministic det = Deterministic.yes)
428         if (isFunctionPointer!T || isDelegate!T)
429     {
430         import std.meta : AliasSeq, staticMap, EraseAll;
431         import std.traits : variadicFunctionStyle, Variadic, ParameterTypeTuple,
432             ParameterDefaultValueTuple, ReturnType, Unqual;
433 
434         static assert(variadicFunctionStyle!(fun) == Variadic.no
435             || is(ParameterTypeTuple!fun == AliasSeq!(ColumnData[])),
436             "only type-safe variadic functions with ColumnData arguments are supported");
437 
438         static if (is(ParameterTypeTuple!fun == AliasSeq!(ColumnData[])))
439         {
440             extern(C) static nothrow
441             void x_func(sqlite3_context* context, int argc, sqlite3_value** argv)
442             {
443                 string name;
444                 try
445                 {
446                     import std.array : appender;
447                     auto args = appender!(ColumnData[]);
448 
449                     foreach (i; 0 .. argc)
450                     {
451                         auto value = argv[i];
452                         immutable type = sqlite3_value_type(value);
453 
454                         final switch (type)
455                         {
456                             case SqliteType.INTEGER:
457                                 args.put(ColumnData(getValue!long(value)));
458                                 break;
459 
460                             case SqliteType.FLOAT:
461                                 args.put(ColumnData(getValue!double(value)));
462                                 break;
463 
464                             case SqliteType.TEXT:
465                                 args.put(ColumnData(getValue!string(value)));
466                                 break;
467 
468                             case SqliteType.BLOB:
469                                 args.put(ColumnData(getValue!Blob(value)));
470                                 break;
471 
472                             case SqliteType.NULL:
473                                 args.put(ColumnData(null));
474                                 break;
475                         }
476                     }
477 
478                     auto ptr = sqlite3_user_data(context);
479 
480                     auto wrappedDelegate = delegateUnwrap!T(ptr);
481                     auto dlg = wrappedDelegate.dlg;
482                     name = wrappedDelegate.name;
483                     setResult(context, dlg(args.data));
484                 }
485                 catch (Exception e)
486                 {
487                     sqlite3_result_error(context, "error in function %s(): %s"
488                         .nothrowFormat(name, e.msg).toStringz, -1);
489                 }
490             }
491         }
492         else
493         {
494             static assert(!is(ReturnType!fun == void), "function must not return void");
495 
496             alias PT = staticMap!(Unqual, ParameterTypeTuple!fun);
497             alias PD = ParameterDefaultValueTuple!fun;
498 
499             extern (C) static nothrow
500             void x_func(sqlite3_context* context, int argc, sqlite3_value** argv)
501             {
502                 string name;
503                 try
504                 {
505                     // Get the deledate and its name
506                     auto ptr = sqlite3_user_data(context);
507                     auto wrappedDelegate = delegateUnwrap!T(ptr);
508                     auto dlg = wrappedDelegate.dlg;
509                     name = wrappedDelegate.name;
510 
511                     enum maxArgc = PT.length;
512                     enum minArgc = PT.length - EraseAll!(void, PD).length;
513 
514                     if (argc > maxArgc)
515                     {
516                         auto txt = ("too many arguments in function %s(), expecting at most %s"
517                             ).format(name, maxArgc);
518                         sqlite3_result_error(context, txt.toStringz, -1);
519                     }
520                     else if (argc < minArgc)
521                     {
522                         auto txt = ("too few arguments in function %s(), expecting at least %s"
523                             ).format(name, minArgc);
524                         sqlite3_result_error(context, txt.toStringz, -1);
525                     }
526                     else
527                     {
528                         PT args;
529                         foreach (i, type; PT)
530                         {
531                             if (i < argc)
532                                 args[i] = getValue!type(argv[i]);
533                             else
534                                 static if (is(typeof(PD[i])))
535                                     args[i] = PD[i];
536                         }
537                         setResult(context, dlg(args));
538                     }
539                 }
540                 catch (Exception e)
541                 {
542                     sqlite3_result_error(context, "error in function %s(): %s"
543                         .nothrowFormat(name, e.msg).toStringz, -1);
544                 }
545             }
546         }
547 
548         assert(name.length, "function has an empty name");
549 
550         if (!fun)
551             createFunction(name, null);
552 
553         assert(p.handle);
554         check(sqlite3_create_function_v2(p.handle, name.toStringz, -1,
555               SQLITE_UTF8 | det, delegateWrap(fun, name), &x_func, null, null, &free));
556     }
557     ///
558     unittest
559     {
560         string star(int count, string starSymbol = "*")
561         {
562             import std.range : repeat;
563             import std.array : join;
564 
565             return starSymbol.repeat(count).join;
566         }
567 
568         auto db = Database(":memory:");
569         db.createFunction("star", &star);
570         assert(db.execute("SELECT star(5)").oneValue!string == "*****");
571         assert(db.execute("SELECT star(3, '♥')").oneValue!string == "♥♥♥");
572     }
573     ///
574     unittest
575     {
576         // The implementation of the new function
577         string myList(ColumnData[] args)
578         {
579             import std.array : appender;
580             import std.string : format, join;
581 
582             auto app = appender!(string[]);
583             foreach (arg; args)
584             {
585                 if (arg.type == SqliteType.TEXT)
586                     app.put(`"%s"`.format(arg));
587                 else
588                     app.put("%s".format(arg));
589             }
590             return app.data.join(", ");
591         }
592 
593         auto db = Database(":memory:");
594         db.createFunction("my_list", &myList);
595         auto list = db.execute("SELECT my_list(42, 3.14, 'text', NULL)").oneValue!string;
596         assert(list == `42, 3.14, "text", null`);
597     }
598 
599     /// Ditto
600     void createFunction(T)(string name, T fun = null)
601         if (is(T == typeof(null)))
602     {
603         assert(name.length, "function has an empty name");
604         assert(p.handle);
605         check(sqlite3_create_function_v2(p.handle, name.toStringz, -1, SQLITE_UTF8,
606                 null, fun, null, null, null));
607     }
608 
609     /++
610     Creates and registers a new aggregate function in the database.
611 
612     Params:
613         name = The name that the aggregate function will have in the database.
614 
615         agg = The struct of type T implementing the aggregate. T must implement
616         at least these two methods: `accumulate()` and `result()`.
617         Each parameter and the returned type of `accumulate()` and `result()` must be
618         a boolean or numeric type, a string, an array, `null`, or a `Nullable!T`
619         where T is any of the previous types. These methods cannot be variadic.
620 
621         det = Tells SQLite whether the result of the function is deterministic, i.e. if the
622         result is the same when called with the same parameters. Recent versions of SQLite
623         perform optimizations based on this. Set to `Deterministic.no` otherwise.
624 
625     See_Also: $(LINK http://www.sqlite.org/c3ref/create_function.html).
626     +/
627     void createAggregate(T)(string name, T agg, Deterministic det = Deterministic.yes)
628     {
629         import std.meta : staticMap;
630         import std.traits : isAggregateType, ReturnType, variadicFunctionStyle, Variadic,
631             Unqual, ParameterTypeTuple;
632         import core.stdc.stdlib : malloc;
633 
634         static assert(isAggregateType!T,
635             T.stringof ~ " should be an aggregate type");
636         static assert(is(typeof(T.accumulate) == function),
637             T.stringof ~ " should have a method named accumulate");
638         static assert(is(typeof(T.result) == function),
639             T.stringof ~ " should have a method named result");
640         static assert(is(typeof({
641                 alias RT = ReturnType!(T.result);
642                 setResult!RT(null, RT.init);
643             })), T.stringof ~ ".result should return an SQLite-compatible type");
644         static assert(variadicFunctionStyle!(T.accumulate) == Variadic.no,
645             "variadic functions are not supported");
646         static assert(variadicFunctionStyle!(T.result) == Variadic.no,
647             "variadic functions are not supported");
648 
649         alias PT = staticMap!(Unqual, ParameterTypeTuple!(T.accumulate));
650         alias RT = ReturnType!(T.result);
651 
652         static struct Context
653         {
654             T aggregate;
655             string functionName;
656         }
657 
658         extern(C) static nothrow
659         void x_step(sqlite3_context* context, int /* argc */, sqlite3_value** argv)
660         {
661             auto ctx = cast(Context*) sqlite3_user_data(context);
662             if (!ctx)
663             {
664                 sqlite3_result_error_nomem(context);
665                 return;
666             }
667 
668             PT args;
669             try
670             {
671                 foreach (i, type; PT)
672                     args[i] = getValue!type(argv[i]);
673 
674                 ctx.aggregate.accumulate(args);
675             }
676             catch (Exception e)
677             {
678                 sqlite3_result_error(context, "error in aggregate function %s(): %s"
679                     .nothrowFormat(ctx.functionName, e.msg).toStringz, -1);
680             }
681         }
682 
683         extern(C) static nothrow
684         void x_final(sqlite3_context* context)
685         {
686             auto ctx = cast(Context*) sqlite3_user_data(context);
687             if (!ctx)
688             {
689                 sqlite3_result_error_nomem(context);
690                 return;
691             }
692 
693             try
694             {
695                 setResult(context, ctx.aggregate.result());
696             }
697             catch (Exception e)
698             {
699                 sqlite3_result_error(context, "error in aggregate function %s(): %s"
700                     .nothrowFormat(ctx.functionName, e.msg).toStringz, -1);
701             }
702         }
703 
704         static if (is(T == class) || is(T == Interface))
705             assert(agg, "Attempt to create an aggregate function from a null reference");
706 
707         auto ctx = cast(Context*) malloc(Context.sizeof);
708         ctx.aggregate = agg;
709         ctx.functionName = name;
710 
711         assert(p.handle);
712         check(sqlite3_create_function_v2(p.handle, name.toStringz, PT.length, SQLITE_UTF8 | det,
713             cast(void*) ctx, null, &x_step, &x_final, &free));
714     }
715     ///
716     unittest // Aggregate creation
717     {
718         import std.array : Appender, join;
719 
720         // The implementation of the aggregate function
721         struct Joiner
722         {
723             private
724             {
725                 Appender!(string[]) stringList;
726                 string separator;
727             }
728 
729             this(string separator)
730             {
731                 this.separator = separator;
732             }
733 
734             void accumulate(string word)
735             {
736                 stringList.put(word);
737             }
738 
739             string result()
740             {
741                 return stringList.data.join(separator);
742             }
743         }
744 
745         auto db = Database(":memory:");
746         db.run("CREATE TABLE test (word TEXT);
747                 INSERT INTO test VALUES ('My');
748                 INSERT INTO test VALUES ('cat');
749                 INSERT INTO test VALUES ('is');
750                 INSERT INTO test VALUES ('black');");
751 
752         db.createAggregate("dash_join", Joiner("-"));
753         auto text = db.execute("SELECT dash_join(word) FROM test").oneValue!string;
754         assert(text == "My-cat-is-black");
755     }
756 
757     /++
758     Creates and registers a collation function in the database.
759 
760     Params:
761         name = The name that the function will have in the database.
762 
763         fun = a delegate or function that implements the collation. The function $(D_PARAM fun)
764         must be `nothrow`` and satisfy these criteria:
765             $(UL
766                 $(LI Takes two string arguments (s1 and s2). These two strings are slices of C-style strings
767                   that SQLite manages internally, so there is no guarantee that they are still valid
768                   when the function returns.)
769                 $(LI Returns an integer (ret).)
770                 $(LI If s1 is less than s2, ret < 0.)
771                 $(LI If s1 is equal to s2, ret == 0.)
772                 $(LI If s1 is greater than s2, ret > 0.)
773                 $(LI If s1 is equal to s2, then s2 is equal to s1.)
774                 $(LI If s1 is equal to s2 and s2 is equal to s3, then s1 is equal to s3.)
775                 $(LI If s1 is less than s2, then s2 is greater than s1.)
776                 $(LI If s1 is less than s2 and s2 is less than s3, then s1 is less than s3.)
777             )
778 
779     See_Also: $(LINK http://www.sqlite.org/lang_aggfunc.html)
780     +/
781     void createCollation(T)(string name, T fun)
782         if (isFunctionPointer!T || isDelegate!T)
783     {
784         import std.traits : isImplicitlyConvertible, functionAttributes, FunctionAttribute,
785             ParameterTypeTuple, isSomeString, ReturnType;
786 
787         static assert(isImplicitlyConvertible!(typeof(fun("a", "b")), int),
788             "the collation function has a wrong signature");
789 
790         static assert(functionAttributes!(T) & FunctionAttribute.nothrow_,
791             "only nothrow functions are allowed as collations");
792 
793         alias PT = ParameterTypeTuple!fun;
794         static assert(isSomeString!(PT[0]),
795             "the first argument of function " ~ name ~ " should be a string");
796         static assert(isSomeString!(PT[1]),
797             "the second argument of function " ~ name ~ " should be a string");
798         static assert(isImplicitlyConvertible!(ReturnType!fun, int),
799             "function " ~ name ~ " should return a value convertible to an int");
800 
801         extern (C) static nothrow
802         int x_compare(void* ptr, int n1, const(void)* str1, int n2, const(void)* str2)
803         {
804             static string slice(const(void)* str, int n) nothrow
805             {
806                 // The string data is owned by SQLite, so it should be safe
807                 // to take a slice of it.
808                 return str ? (cast(immutable) (cast(const(char)*) str)[0 .. n]) : null;
809             }
810 
811             return delegateUnwrap!T(ptr).dlg(slice(str1, n1), slice(str2, n2));
812         }
813 
814         assert(p.handle);
815         auto dgw = delegateWrap(fun, name);
816         auto result = sqlite3_create_collation_v2(p.handle, name.toStringz, SQLITE_UTF8,
817             delegateWrap(fun, name), &x_compare, &free);
818         if (result != SQLITE_OK)
819         {
820             free(dgw);
821             throw new SqliteException(errmsg(p.handle), result);
822         }
823     }
824     ///
825     unittest // Collation creation
826     {
827         // The implementation of the collation
828         int my_collation(string s1, string s2) nothrow
829         {
830             import std.uni : icmp;
831             import std.exception : assumeWontThrow;
832 
833             return assumeWontThrow(icmp(s1, s2));
834         }
835 
836         auto db = Database(":memory:");
837         db.createCollation("my_coll", &my_collation);
838         db.run("CREATE TABLE test (word TEXT);
839                 INSERT INTO test (word) VALUES ('straße');
840                 INSERT INTO test (word) VALUES ('strasses');");
841 
842         auto word = db.execute("SELECT word FROM test ORDER BY word COLLATE my_coll")
843                       .oneValue!string;
844         assert(word == "straße");
845     }
846 
847     /++
848     Registers a delegate of type `UpdateHookDelegate` as the database's update hook.
849 
850     Any previously set hook is released. Pass `null` to disable the callback.
851 
852     See_Also: $(LINK http://www.sqlite.org/c3ref/commit_hook.html).
853     +/
854     void setUpdateHook(UpdateHookDelegate updateHook)
855     {
856         extern(C) static nothrow
857         void callback(void* ptr, int type, const(char)* dbName, const(char)* tableName, long rowid)
858         {
859             WrappedDelegate!UpdateHookDelegate* dg;
860             dg = delegateUnwrap!UpdateHookDelegate(ptr);
861             dg.dlg(type, dbName.to!string, tableName.to!string, rowid);
862         }
863 
864         free(p.updateHook);
865         p.updateHook = delegateWrap(updateHook);
866         assert(p.handle);
867         sqlite3_update_hook(p.handle, &callback, p.updateHook);
868     }
869 
870     /++
871     Registers a delegate of type `CommitHookDelegate` as the database's commit hook.
872     Any previously set hook is released.
873 
874     Params:
875         commitHook = A delegate that should return a non-zero value
876         if the operation must be rolled back, or 0 if it can commit.
877         Pass `null` to disable the callback.
878 
879     See_Also: $(LINK http://www.sqlite.org/c3ref/commit_hook.html).
880     +/
881     void setCommitHook(CommitHookDelegate commitHook)
882     {
883         extern(C) static nothrow
884         int callback(void* ptr)
885         {
886             auto dlg = delegateUnwrap!CommitHookDelegate(ptr).dlg;
887             return dlg();
888         }
889 
890         free(p.commitHook);
891         p.commitHook = delegateWrap(commitHook);
892         assert(p.handle);
893         sqlite3_commit_hook(p.handle, &callback, p.commitHook);
894     }
895 
896     /++
897     Registers a delegate of type `RoolbackHookDelegate` as the database's rollback hook.
898 
899     Any previously set hook is released.
900     Pass `null` to disable the callback.
901 
902     See_Also: $(LINK http://www.sqlite.org/c3ref/commit_hook.html).
903     +/
904     void setRollbackHook(RoolbackHookDelegate rollbackHook)
905     {
906         extern(C) static nothrow
907         void callback(void* ptr)
908         {
909             auto dlg = delegateUnwrap!RoolbackHookDelegate(ptr).dlg;
910             dlg();
911         }
912 
913         free(p.rollbackHook);
914         p.rollbackHook = delegateWrap(rollbackHook);
915         assert(p.handle);
916         sqlite3_rollback_hook(p.handle, &callback, p.rollbackHook);
917     }
918 
919     /++
920     Registers a delegate of type `ProgressHandlerDelegate` as the progress handler.
921 
922     Any previously set handler is released.
923     Pass `null` to disable the callback.
924 
925     Params:
926         pace = The approximate number of virtual machine instructions that are
927         evaluated between successive invocations of the handler.
928 
929         progressHandler = A delegate that should return 0 if the operation can continue
930         or another value if it must be aborted.
931 
932     See_Also: $(LINK http://www.sqlite.org/c3ref/progress_handler.html).
933     +/
934     void setProgressHandler(int pace, ProgressHandlerDelegate progressHandler)
935     {
936         extern(C) static nothrow
937         int callback(void* ptr)
938         {
939             auto dlg = delegateUnwrap!ProgressHandlerDelegate(ptr).dlg;
940             return dlg();
941         }
942 
943         free(p.progressHandler);
944         p.progressHandler = delegateWrap(progressHandler);
945         assert(p.handle);
946         sqlite3_progress_handler(p.handle, pace, &callback, p.progressHandler);
947     }
948 
949     /++
950     Registers a delegate of type `TraceCallbackDelegate` as the trace callback.
951 
952     Any previously set profile or trace callback is released.
953     Pass `null` to disable the callback.
954 
955     The string parameter that is passed to the callback is the SQL text of the statement being
956     executed.
957 
958     See_Also: $(LINK http://www.sqlite.org/c3ref/profile.html).
959     +/
960     void setTraceCallback(TraceCallbackDelegate traceCallback)
961     {
962         extern(C) static nothrow
963         void callback(void* ptr, const(char)* str)
964         {
965             auto dlg = delegateUnwrap!TraceCallbackDelegate(ptr).dlg;
966             dlg(str.to!string);
967         }
968 
969         free(p.traceCallback);
970         p.traceCallback = delegateWrap(traceCallback);
971         assert(p.handle);
972         sqlite3_trace(p.handle, &callback, p.traceCallback);
973     }
974 
975     /++
976     Registers a delegate of type `ProfileCallbackDelegate` as the profile callback.
977 
978     Any previously set profile or trace callback is released.
979     Pass `null` to disable the callback.
980 
981     The string parameter that is passed to the callback is the SQL text of the statement being
982     executed. The time unit is defined in SQLite's documentation as nanoseconds (subject to change,
983     as the functionality is experimental).
984 
985     See_Also: $(LINK http://www.sqlite.org/c3ref/profile.html).
986     +/
987     void setProfileCallback(ProfileCallbackDelegate profileCallback)
988     {
989         extern(C) static nothrow
990         void callback(void* ptr, const(char)* str, sqlite3_uint64 time)
991         {
992             auto dlg = delegateUnwrap!ProfileCallbackDelegate(ptr).dlg;
993             dlg(str.to!string, time);
994         }
995 
996         free(p.profileCallback);
997         p.profileCallback = delegateWrap(profileCallback);
998         assert(p.handle);
999         sqlite3_profile(p.handle, &callback, p.profileCallback);
1000     }
1001 
1002     version (_UnlockNotify)
1003     {
1004         /++
1005         Registers a `IUnlockNotifyHandler` used to handle database locks.
1006 
1007         When running in shared-cache mode, a database operation may fail with an SQLITE_LOCKED error if
1008         the required locks on the shared-cache or individual tables within the shared-cache cannot be obtained.
1009         See SQLite Shared-Cache Mode for a description of shared-cache locking.
1010         This API may be used to register a callback that SQLite will invoke when the connection currently
1011         holding the required lock relinquishes it.
1012         This API can be used only if the SQLite library was compiled with the `SQLITE_ENABLE_UNLOCK_NOTIFY`
1013         C-preprocessor symbol defined.
1014 
1015         See_Also: $(LINK http://sqlite.org/c3ref/unlock_notify.html).
1016 
1017         Parameters:
1018             unlockNotifyHandler - custom handler used to control the unlocking mechanism
1019         +/
1020         void setUnlockNotifyHandler(IUnlockNotifyHandler unlockNotifyHandler)
1021         {
1022             p.unlockNotifyHandler = unlockNotifyHandler;
1023         }
1024 
1025         /// Setup and waits for unlock notify using the provided `IUnlockNotifyHandler`
1026         package (d2sqlite3) auto waitForUnlockNotify()
1027         {
1028             if (p.unlockNotifyHandler is null) return SQLITE_LOCKED;
1029 
1030             version (SqliteEnableUnlockNotify)
1031             {
1032                 extern(C) static nothrow
1033                 void callback(void** ntfPtr, int nPtr)
1034                 {
1035                     for (int i=0; i<nPtr; i++)
1036                     {
1037                         auto handler = cast(IUnlockNotifyHandler*)ntfPtr[i];
1038                         handler.emit(SQLITE_OK);
1039                     }
1040                 }
1041 
1042                 int rc = sqlite3_unlock_notify(p.handle, &callback, &p.unlockNotifyHandler);
1043                 assert(rc==SQLITE_LOCKED || rc==SQLITE_OK);
1044 
1045                 /+ The call to sqlite3_unlock_notify() always returns either SQLITE_LOCKED or SQLITE_OK.
1046 
1047                 If SQLITE_LOCKED was returned, then the system is deadlocked. In this case this function
1048                 needs to return SQLITE_LOCKED to the caller so that the current transaction can be rolled
1049                 back. Otherwise, block until the unlock-notify callback is invoked, then return SQLITE_OK.
1050                 +/
1051                 if(rc == SQLITE_OK)
1052                 {
1053                     p.unlockNotifyHandler.wait();
1054                     scope (exit) p.unlockNotifyHandler.reset();
1055                     return p.unlockNotifyHandler.result;
1056                 }
1057                 return rc;
1058             }
1059             else
1060             {
1061                 p.unlockNotifyHandler.waitOne();
1062                 auto res = p.unlockNotifyHandler.result;
1063                 if (res != SQLITE_OK) p.unlockNotifyHandler.reset();
1064                 return res;
1065             }
1066         }
1067     }
1068 }
1069 
1070 /// Delegate types
1071 alias UpdateHookDelegate = void delegate(int type, string dbName, string tableName, long rowid) nothrow;
1072 /// ditto
1073 alias CommitHookDelegate = int delegate() nothrow;
1074 /// ditto
1075 alias RoolbackHookDelegate = void delegate() nothrow;
1076 /// ditto
1077 alias ProgressHandlerDelegate = int delegate() nothrow;
1078 /// ditto
1079 alias TraceCallbackDelegate = void delegate(string sql) nothrow;
1080 /// ditto
1081 alias ProfileCallbackDelegate = void delegate(string sql, ulong time) nothrow;
1082 
1083 /// Information about a table column.
1084 struct TableColumnMetadata
1085 {
1086     string declaredTypeName; ///
1087     string collationSequenceName; ///
1088     bool isNotNull; ///
1089     bool isPrimaryKey; ///
1090     bool isAutoIncrement; ///
1091 }
1092 
1093 version (_UnlockNotify)
1094 {
1095     /++
1096     UnlockNotifyHandler interface to be used for custom implementations of UnlockNotify pattern with SQLite.
1097 
1098     Note:
1099     For the C API sqlite3_unlock_notify to be used, this library must be compiled with
1100     `-version=SqliteEnableUnlockNotify`.
1101     Otherwise only emulated solution is provided, that is based on retries for the defined amount of time.
1102 
1103     Implementation must be able to handle situation when emit is called sooner than the wait itself.
1104 
1105     See_Also: $(LINK http://sqlite.org/c3ref/unlock_notify.html).
1106     See_Also: $(LINK http://www.sqlite.org/unlock_notify.html).
1107     +/
1108     interface IUnlockNotifyHandler
1109     {
1110         version (SqliteEnableUnlockNotify)
1111         {
1112             /// Blocks until emit is called
1113             void wait();
1114 
1115             /++
1116             Unlocks the handler.
1117             This is called from registered callback from SQLite.
1118 
1119             Params:
1120                 state = Value to set as a handler result. It can be SQLITE_LOCKED or SQLITE_OK.
1121             +/
1122             void emit(int state) nothrow;
1123         }
1124         else
1125         {
1126             /++
1127             This is used as an alternative when SQLite is not compiled with SQLITE_ENABLE_UNLOCK_NOTIFY, and
1128             when the library is built with `-version=SqliteFakeUnlockNotify`.
1129             Using this, the handler tries to wait out the SQLITE_LOCKED state for some time.
1130             Implementation have to block for some amount of time and check if total amount is not greater than some constant afterwards.
1131             If there is still some time to try again, the handler must set the result to SQLITE_OK or to SQLITE_LOCKED otherwise.
1132             +/
1133             void waitOne();
1134         }
1135 
1136         /// Resets the handler for the next use
1137         void reset();
1138 
1139         /// Result after wait is finished
1140         @property int result() const;
1141     }
1142 
1143     version (SqliteEnableUnlockNotify)
1144     {
1145         /++
1146         UnlockNotifyHandler used when SQLite is compiled with SQLITE_ENABLE_UNLOCK_NOTIFY, and
1147         when the library is built with `-version=SqliteEnableUnlockNotify`.
1148         It is implemented using the standard `core.sync` package.
1149 
1150         Use setUnlockNotifyHandler method to handle the database lock.
1151 
1152         See_Also: $(LINK http://sqlite.org/c3ref/unlock_notify.html).
1153         See_Also: $(LINK http://www.sqlite.org/unlock_notify.html).
1154         +/
1155         final class UnlockNotifyHandler : IUnlockNotifyHandler
1156         {
1157             import core.sync.condition : Condition;
1158             import core.sync.mutex : Mutex;
1159 
1160             private
1161             {
1162                 __gshared Mutex mtx;
1163                 __gshared Condition cond;
1164                 __gshared int res;
1165                 __gshared bool fired;
1166             }
1167 
1168             /// Constructor
1169             this()
1170             {
1171                 mtx = new Mutex();
1172                 cond = new Condition(mtx);
1173             }
1174 
1175             /// Blocks until emit is called
1176             void wait()
1177             {
1178                 synchronized (mtx)
1179                 {
1180                     if (!fired) cond.wait();
1181                 }
1182             }
1183 
1184             /// Unlocks the handler, state is one of SQLITE_LOCKED or SQLITE_OK
1185             void emit(int res) nothrow
1186             in { assert(res == SQLITE_LOCKED || res == SQLITE_OK); }
1187             do
1188             {
1189                 try
1190                 {
1191                     synchronized (mtx)
1192                     {
1193                         this.res = res;
1194                         fired = true;
1195                         cond.notify();
1196                     }
1197                 }
1198                 catch (Exception) {}
1199             }
1200 
1201             /// Resets the handler for the next use
1202             void reset()
1203             {
1204                 res = SQLITE_LOCKED;
1205                 fired = false;
1206             }
1207 
1208             /// Result after wait is finished
1209             @property int result() const
1210             out (result) { assert(result == SQLITE_OK || result == SQLITE_LOCKED); }
1211             do { return res; }
1212         }
1213     }
1214     else
1215     {
1216         /++
1217         UnlockNotifyHandler that can be used when SQLite is not compiled with SQLITE_ENABLE_UNLOCK_NOTIFY,
1218         and when the library is built with `-version=SqliteFakeUnlockNotify`..
1219         It retries the statement execution for the provided amount of time before the SQLITE_LOCKED is returned.
1220 
1221         Use setUnlockNotifyHandler method to handle the database lock.
1222 
1223         See_Also: $(LINK http://sqlite.org/c3ref/unlock_notify.html).
1224         See_Also: $(LINK http://www.sqlite.org/unlock_notify.html).
1225         +/
1226         final class UnlockNotifyHandler : IUnlockNotifyHandler
1227         {
1228             import core.time : Duration, msecs;
1229             import std.datetime.stopwatch : StopWatch;
1230 
1231             private
1232             {
1233                 int res;
1234                 Duration maxDuration;
1235                 StopWatch sw;
1236             }
1237 
1238             /// Constructor
1239             this(Duration max = 1000.msecs)
1240             in { assert(max > Duration.zero); }
1241             do
1242             {
1243                 maxDuration = max;
1244             }
1245 
1246             /// Blocks for some time to retry the statement
1247             void waitOne()
1248             {
1249                 import core.thread : Thread;
1250                 import std.random : uniform;
1251 
1252                 if (!sw.running) sw.start;
1253 
1254                 Thread.sleep(uniform(50, 100).msecs);
1255 
1256                 if (sw.peek > maxDuration)
1257                 {
1258                     sw.stop;
1259                     res = SQLITE_LOCKED;
1260                 }
1261                 else res = SQLITE_OK;
1262             }
1263 
1264             /// Resets the handler for the next use
1265             void reset()
1266             {
1267                 res = SQLITE_LOCKED;
1268                 sw.reset();
1269             }
1270 
1271             /// Result after wait is finished
1272             @property int result() const
1273             out (result) { assert(result == SQLITE_OK || result == SQLITE_LOCKED); }
1274             do
1275             {
1276                 return res;
1277             }
1278         }
1279     }
1280 
1281     unittest
1282     {
1283         import core.time : Duration, msecs;
1284 
1285         /++
1286         Tests the unlock notify facility.
1287         Params:
1288             delay - time to wait in the transaction to block the other one
1289             expected - expected result (can be used to test timeout when fake unlock notify is used)
1290         +/
1291         void testUnlockNotify(Duration delay = 500.msecs, int expected = 3)
1292         {
1293             import core.thread : Thread;
1294             import core.time : msecs, seconds;
1295             import std.concurrency : spawn;
1296 
1297             static void test(int n, Duration delay)
1298             {
1299                 auto db = Database("file::memory:?cache=shared", SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_URI | SQLITE_OPEN_MEMORY);
1300                 db.setUnlockNotifyHandler = new UnlockNotifyHandler();
1301                 db.execute("BEGIN IMMEDIATE");
1302                 Thread.sleep(delay);
1303                 db.execute("INSERT INTO foo (bar) VALUES (?)", n);
1304                 db.commit();
1305             }
1306 
1307             auto db = Database("file::memory:?cache=shared", SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_URI | SQLITE_OPEN_MEMORY);
1308             db.execute(`CREATE TABLE foo (bar INTEGER);`);
1309 
1310             spawn(&test, 1, delay);
1311             Thread.sleep(100.msecs);
1312             spawn(&test, 2, delay);
1313             Thread.sleep(2*delay + 100.msecs);
1314             assert(db.execute("SELECT sum(bar) FROM foo").oneValue!int == expected, format!"%s != %s"(db.execute("SELECT sum(bar) FROM foo").oneValue!int, expected));
1315         }
1316 
1317         testUnlockNotify();
1318         version (SqliteFakeUnlockNotify) testUnlockNotify(1500.msecs, 1); //timeout test
1319     }
1320 }
1321 
1322 /++
1323 Exception thrown when SQLite functions return an error.
1324 +/
1325 class SqliteException : Exception
1326 {
1327     /++
1328     The _code of the error that raised the exception
1329     +/
1330     int code;
1331 
1332     /++
1333     The SQL code that raised the exception, if applicable.
1334     +/
1335     string sql;
1336 
1337     private this(string msg, string sql, int code,
1338                  string file = __FILE__, size_t line = __LINE__, Throwable next = null)
1339         @safe pure nothrow @nogc
1340     {
1341         this.sql = sql;
1342         this.code = code;
1343         super(msg, file, line, next);
1344     }
1345 
1346 package(d2sqlite3):
1347     this(string msg, int code, string sql = null,
1348          string file = __FILE__, size_t line = __LINE__, Throwable next = null)
1349          @safe pure nothrow
1350     {
1351         this(text("error ", code, ": ", msg), sql, code, file, line, next);
1352     }
1353 }