1 /++
2 This module is part of d2sqlite3.
3 
4 Authors:
5     Nicolas Sicard (biozic) and other contributors at $(LINK https://github.com/biozic/d2sqlite3)
6 
7 Copyright:
8     Copyright 2011-17 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 : to;
22 import std.exception : enforce;
23 import std..string : format, toStringz;
24 import std.typecons : Nullable;
25 
26 /// Set _UnlockNotify version if compiled with SqliteEnableUnlockNotify or SqliteFakeUnlockNotify
27 version (SqliteEnableUnlockNotify) version = _UnlockNotify;
28 else version (SqliteFakeUnlockNotify) version = _UnlockNotify;
29 
30 /// Type for the internal representation of blobs
31 alias Blob = immutable(ubyte)[];
32 
33 /// SQLite type codes
34 enum SqliteType
35 {
36     INTEGER = SQLITE_INTEGER, ///
37     FLOAT = SQLITE_FLOAT, ///
38     TEXT = SQLITE3_TEXT, ///
39     BLOB = SQLITE_BLOB, ///
40     NULL = SQLITE_NULL ///
41 }
42 
43 /++
44 A caracteristic of user-defined functions or aggregates.
45 +/
46 enum Deterministic
47 {
48     /++
49     The returned value is the same if the function is called with the same parameters.
50     +/
51     yes = 0x800,
52 
53     /++
54     The returned value can vary even if the function is called with the same parameters.
55     +/
56     no = 0
57 }
58 
59 /++
60 An database connection.
61 
62 This struct is a reference-counted wrapper around a `sqlite3*` pointer.
63 +/
64 struct Database
65 {
66     import std.traits : isFunctionPointer, isDelegate;
67     import std.typecons : RefCounted, RefCountedAutoInitialize;
68 
69 private:
70     struct Payload
71     {
72         sqlite3* handle;
73         void* updateHook;
74         void* commitHook;
75         void* rollbackHook;
76         void* progressHandler;
77         void* traceCallback;
78         void* profileCallback;
79         version (_UnlockNotify) IUnlockNotifyHandler unlockNotifyHandler;
80 
81         this(sqlite3* handle) nothrow
82         {
83             this.handle = handle;
84         }
85 
86         ~this()
87         {
88             close();
89         }
90 
91         void close()
92         {
93             if (!handle)
94                 return;
95 
96             sqlite3_progress_handler(handle, 0, null, null);
97             auto result = sqlite3_close(handle);
98             // Check that destructor was not call by the GC
99             // See https://p0nce.github.io/d-idioms/#GC-proof-resource-class
100             import core.exception : InvalidMemoryOperationError;
101             try
102             {
103                 enforce(result == SQLITE_OK, new SqliteException(errmsg(handle), result));
104             }
105             catch (InvalidMemoryOperationError e)
106             {
107                 import core.stdc.stdio : fprintf, stderr;
108                 fprintf(stderr, "Error: release of Database resource incorrectly"
109                                 ~ " depends on destructors called by the GC.\n");
110                 assert(false); // crash
111             }
112             handle = null;
113             ptrFree(updateHook);
114             ptrFree(commitHook);
115             ptrFree(rollbackHook);
116             ptrFree(progressHandler);
117             ptrFree(traceCallback);
118             ptrFree(profileCallback);
119         }
120     }
121 
122     RefCounted!(Payload, RefCountedAutoInitialize.no) p;
123 
124     void check(int result)
125     {
126         enforce(result == SQLITE_OK, new SqliteException(errmsg(p.handle), result));
127     }
128 
129 public:
130     /++
131     Opens a database connection.
132 
133     Params:
134         path = The path to the database file. In recent versions of SQLite, the path can be
135         an URI with options.
136 
137         flags = Options flags.
138 
139     See_Also: $(LINK http://www.sqlite.org/c3ref/open.html) to know how to use the flags
140     parameter or to use path as a file URI if the current configuration allows it.
141     +/
142     this(string path, int flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE)
143     {
144         sqlite3* hdl;
145         auto result = sqlite3_open_v2(path.toStringz, &hdl, flags, null);
146         enforce(result == SQLITE_OK, new SqliteException(hdl ? errmsg(hdl) : "Error opening the database", result));
147         p = Payload(hdl);
148     }
149 
150     /++
151     Explicitly closes the database connection.
152 
153     After a call to `close()`, using the database connection or one of its prepared statement
154     is an error. The `Database` object is destroyed and cannot be used any more.
155     +/
156     void close()
157     {
158         p.close();
159         destroy(p);
160     }
161 
162     /++
163     Gets the SQLite internal _handle of the database connection.
164     +/
165     sqlite3* handle() @property nothrow
166     {
167         return p.handle;
168     }
169 
170     /++
171     Gets the path associated with an attached database.
172 
173     Params:
174         database = The name of an attached database.
175 
176     Returns: The absolute path of the attached database.
177         If there is no attached database, or if database is a temporary or
178         in-memory database, then null is returned.
179     +/
180     string attachedFilePath(string database = "main")
181     {
182         assert(p.handle);
183         return sqlite3_db_filename(p.handle, database.toStringz).to!string;
184     }
185 
186     /++
187     Gets the read-only status of an attached database.
188 
189     Params:
190         database = The name of an attached database.
191     +/
192     bool isReadOnly(string database = "main")
193     {
194         immutable ret = sqlite3_db_readonly(p.handle, database.toStringz);
195         enforce(ret >= 0, new SqliteException("Database not found: %s".format(database)));
196         return ret == 1;
197     }
198 
199     /++
200     Gets metadata for a specific table column of an attached database.
201 
202     Params:
203         table = The name of the table.
204 
205         column = The name of the column.
206 
207         database = The name of a database attached. If null, then all attached databases
208         are searched for the table using the same algorithm used by the database engine
209         to resolve unqualified table references.
210     +/
211     TableColumnMetadata tableColumnMetadata(string table, string column, string database = "main")
212     {
213         TableColumnMetadata data;
214         char* pzDataType, pzCollSeq;
215         int notNull, primaryKey, autoIncrement;
216         check(sqlite3_table_column_metadata(p.handle, database.toStringz, table.toStringz,
217             column.toStringz, &pzDataType, &pzCollSeq, &notNull, &primaryKey, &autoIncrement));
218         data.declaredTypeName = pzDataType.to!string;
219         data.collationSequenceName = pzCollSeq.to!string;
220         data.isNotNull = cast(bool) notNull;
221         data.isPrimaryKey = cast(bool) primaryKey;
222         data.isAutoIncrement = cast(bool) autoIncrement;
223         return data;
224     }
225 
226     /++
227     Executes a single SQL statement and returns the results directly.
228 
229     It's the equivalent of `prepare(sql).execute()`.
230     Or when used with args the equivalent of:
231     ---
232     auto stm = prepare(sql);
233     stm.bindAll(args);
234     stm.execute();
235     ---
236 
237     The results become undefined when the Database goes out of scope and is destroyed.
238 
239     Params:
240         sql = The code of the SQL statement.
241         args = Optional arguments to bind to the SQL statement.
242     +/
243     ResultRange execute(Args...)(string sql, Args args)
244     {
245         auto stm = prepare(sql);
246         static if (Args.length) stm.bindAll(args);
247         return stm.execute();
248     }
249     ///
250     unittest
251     {
252         auto db = Database(":memory:");
253         db.execute("CREATE TABLE test (val INTEGER)");
254         db.execute("INSERT INTO test (val) VALUES (:v)", 1);
255         assert(db.execute("SELECT val FROM test WHERE val=:v", 1).oneValue!int == 1);
256     }
257 
258     /++
259     Runs an SQL script that can contain multiple statements.
260 
261     Params:
262         script = The code of the SQL script.
263 
264         dg = A delegate to call for each statement to handle the results. The passed
265         ResultRange will be empty if a statement doesn't return rows. If the delegate
266         return false, the execution is aborted.
267     +/
268     void run(string script, bool delegate(ResultRange) dg = null)
269     {
270         foreach (sql; script.byStatement)
271         {
272             auto stmt = prepare(sql);
273             auto results = stmt.execute();
274             if (dg && !dg(results))
275                 return;
276         }
277     }
278     ///
279     unittest
280     {
281         auto db = Database(":memory:");
282         db.run(`CREATE TABLE test1 (val INTEGER);
283                 CREATE TABLE test2 (val FLOAT);
284                 DROP TABLE test1;
285                 DROP TABLE test2;`);
286     }
287 
288     /++
289     Prepares (compiles) a single SQL statement and returngs it, so that it can be bound to
290     values before execution.
291 
292     The statement becomes invalid if the Database goes out of scope and is destroyed.
293     +/
294     Statement prepare(string sql)
295     {
296         return Statement(this, sql);
297     }
298 
299     /// Convenience functions equivalent to an SQL statement.
300     void begin() { execute("BEGIN"); }
301     /// Ditto
302     void commit() { execute("COMMIT"); }
303     /// Ditto
304     void rollback() { execute("ROLLBACK"); }
305 
306     /++
307     Returns the rowid of the last INSERT statement.
308     +/
309     long lastInsertRowid()
310     {
311         assert(p.handle);
312         return sqlite3_last_insert_rowid(p.handle);
313     }
314 
315     /++
316     Gets the number of database rows that were changed, inserted or deleted by the most
317     recently executed SQL statement.
318     +/
319     int changes() @property nothrow
320     {
321         assert(p.handle);
322         return sqlite3_changes(p.handle);
323     }
324 
325     /++
326     Gets the number of database rows that were changed, inserted or deleted since the
327     database was opened.
328     +/
329     int totalChanges() @property nothrow
330     {
331         assert(p.handle);
332         return sqlite3_total_changes(p.handle);
333     }
334 
335     /++
336     Gets the SQLite error code of the last operation.
337     +/
338     int errorCode() @property nothrow
339     {
340         return p.handle ? sqlite3_errcode(p.handle) : 0;
341     }
342 
343     /++
344     Interrupts any pending database operations.
345 
346     It's safe to call this function from anouther thread.
347 
348     See_also: $(LINK http://www.sqlite.org/c3ref/interrupt.html).
349     +/
350     void interrupt()
351     {
352         assert(p.handle);
353         sqlite3_interrupt(p.handle);
354     }
355 
356     /++
357     Sets a connection configuration option.
358 
359     See_Also: $(LINK http://www.sqlite.org/c3ref/db_config.html).
360     +/
361     void config(Args...)(int code, Args args)
362     {
363         auto result = sqlite3_db_config(p.handle, code, args);
364         enforce(result == SQLITE_OK, new SqliteException("Database configuration: error %s".format(result)));
365     }
366 
367     version (SQLITE_OMIT_LOAD_EXTENSION) {}
368     else
369     {
370         /++
371         Enables or disables loading extensions.
372         +/
373         void enableLoadExtensions(bool enable = true)
374         {
375             enforce(sqlite3_enable_load_extension(p.handle, enable) == SQLITE_OK,
376                 new SqliteException("Could not enable loading extensions."));
377         }
378 
379         /++
380         Loads an extension.
381 
382         Params:
383             path = The path of the extension file.
384 
385             entryPoint = The name of the entry point function. If null is passed, SQLite
386             uses the name of the extension file as the entry point.
387         +/
388         void loadExtension(string path, string entryPoint = null)
389         {
390             immutable ret = sqlite3_load_extension(p.handle, path.toStringz, entryPoint.toStringz, null);
391             enforce(ret == SQLITE_OK, new SqliteException(
392                     "Could not load extension: %s:%s".format(entryPoint, path)));
393         }
394     }
395 
396     /++
397     Creates and registers a new function in the database.
398 
399     If a function with the same name and the same arguments already exists, it is replaced
400     by the new one.
401 
402     The memory associated with the function will be released when the database connection
403     is closed.
404 
405     Params:
406         name = The name that the function will have in the database.
407 
408         fun = a delegate or function that implements the function. $(D_PARAM fun)
409         must satisfy the following criteria:
410             $(UL
411                 $(LI It must not be variadic.)
412                 $(LI Its arguments must all have a type that is compatible with SQLite types:
413                 it must be a boolean or numeric type, a string, an array, `null`,
414                 or a `Nullable!T` where T is any of the previous types.)
415                 $(LI Its return value must also be of a compatible type.)
416             )
417             or
418             $(UL
419                 $(LI It must be a normal or type-safe variadic function where the arguments
420                 are of type `ColumnData`. In other terms, the signature of the function must be:
421                 `function(ColumnData[] args)` or `function(ColumnData[] args...)`)
422                 $(LI Its return value must be a boolean or numeric type, a string, an array, `null`,
423                 or a `Nullable!T` where T is any of the previous types.)
424             )
425         Pass a `null` function pointer to delete the function from the database connection.
426 
427         det = Tells SQLite whether the result of the function is deterministic, i.e. if the
428         result is the same when called with the same parameters. Recent versions of SQLite
429         perform optimizations based on this. Set to `Deterministic.no` otherwise.
430 
431     See_Also: $(LINK http://www.sqlite.org/c3ref/create_function.html).
432     +/
433     void createFunction(T)(string name, T fun, Deterministic det = Deterministic.yes)
434         if (isFunctionPointer!T || isDelegate!T)
435     {
436         import std.meta : AliasSeq, staticMap, EraseAll;
437         import std.traits : variadicFunctionStyle, Variadic, ParameterTypeTuple,
438             ParameterDefaultValueTuple, ReturnType, Unqual;
439 
440         static assert(variadicFunctionStyle!(fun) == Variadic.no
441             || is(ParameterTypeTuple!fun == AliasSeq!(ColumnData[])),
442             "only type-safe variadic functions with ColumnData arguments are supported");
443 
444         static if (is(ParameterTypeTuple!fun == AliasSeq!(ColumnData[])))
445         {
446             extern(C) static nothrow
447             void x_func(sqlite3_context* context, int argc, sqlite3_value** argv)
448             {
449                 string name;
450                 try
451                 {
452                     import std.array : appender;
453                     auto args = appender!(ColumnData[]);
454 
455                     foreach (i; 0 .. argc)
456                     {
457                         auto value = argv[i];
458                         immutable type = sqlite3_value_type(value);
459 
460                         final switch (type)
461                         {
462                             case SqliteType.INTEGER:
463                                 args.put(ColumnData(getValue!long(value)));
464                                 break;
465 
466                             case SqliteType.FLOAT:
467                                 args.put(ColumnData(getValue!double(value)));
468                                 break;
469 
470                             case SqliteType.TEXT:
471                                 args.put(ColumnData(getValue!string(value)));
472                                 break;
473 
474                             case SqliteType.BLOB:
475                                 args.put(ColumnData(getValue!Blob(value)));
476                                 break;
477 
478                             case SqliteType.NULL:
479                                 args.put(ColumnData(null));
480                                 break;
481                         }
482                     }
483 
484                     auto ptr = sqlite3_user_data(context);
485 
486                     auto wrappedDelegate = delegateUnwrap!T(ptr);
487                     auto dlg = wrappedDelegate.dlg;
488                     name = wrappedDelegate.name;
489                     setResult(context, dlg(args.data));
490                 }
491                 catch (Exception e)
492                 {
493                     sqlite3_result_error(context, "error in function %s(): %s"
494                         .nothrowFormat(name, e.msg).toStringz, -1);
495                 }
496             }
497         }
498         else
499         {
500             static assert(!is(ReturnType!fun == void), "function must not return void");
501 
502             alias PT = staticMap!(Unqual, ParameterTypeTuple!fun);
503             alias PD = ParameterDefaultValueTuple!fun;
504 
505             extern (C) static nothrow
506             void x_func(sqlite3_context* context, int argc, sqlite3_value** argv)
507             {
508                 string name;
509                 try
510                 {
511                     // Get the deledate and its name
512                     auto ptr = sqlite3_user_data(context);
513                     auto wrappedDelegate = delegateUnwrap!T(ptr);
514                     auto dlg = wrappedDelegate.dlg;
515                     name = wrappedDelegate.name;
516 
517                     enum maxArgc = PT.length;
518                     enum minArgc = PT.length - EraseAll!(void, PD).length;
519 
520                     if (argc > maxArgc)
521                     {
522                         auto txt = ("too many arguments in function %s(), expecting at most %s"
523                             ).format(name, maxArgc);
524                         sqlite3_result_error(context, txt.toStringz, -1);
525                     }
526                     else if (argc < minArgc)
527                     {
528                         auto txt = ("too few arguments in function %s(), expecting at least %s"
529                             ).format(name, minArgc);
530                         sqlite3_result_error(context, txt.toStringz, -1);
531                     }
532                     else
533                     {
534                         PT args;
535                         foreach (i, type; PT)
536                         {
537                             if (i < argc)
538                                 args[i] = getValue!type(argv[i]);
539                             else
540                                 static if (is(typeof(PD[i])))
541                                     args[i] = PD[i];
542                         }
543                         setResult(context, dlg(args));
544                     }
545                 }
546                 catch (Exception e)
547                 {
548                     sqlite3_result_error(context, "error in function %s(): %s"
549                         .nothrowFormat(name, e.msg).toStringz, -1);
550                 }
551             }
552         }
553 
554         assert(name.length, "function has an empty name");
555 
556         if (!fun)
557             createFunction(name, null);
558 
559         assert(p.handle);
560         check(sqlite3_create_function_v2(p.handle, name.toStringz, -1,
561               SQLITE_UTF8 | det, delegateWrap(fun, name), &x_func, null, null, &ptrFree));
562     }
563     ///
564     unittest
565     {
566         string star(int count, string starSymbol = "*")
567         {
568             import std.range : repeat;
569             import std.array : join;
570 
571             return starSymbol.repeat(count).join;
572         }
573 
574         auto db = Database(":memory:");
575         db.createFunction("star", &star);
576         assert(db.execute("SELECT star(5)").oneValue!string == "*****");
577         assert(db.execute("SELECT star(3, '♥')").oneValue!string == "♥♥♥");
578     }
579     ///
580     unittest
581     {
582         // The implementation of the new function
583         string myList(ColumnData[] args)
584         {
585             import std.array : appender;
586             import std..string : format, join;
587 
588             auto app = appender!(string[]);
589             foreach (arg; args)
590             {
591                 if (arg.type == SqliteType.TEXT)
592                     app.put(`"%s"`.format(arg));
593                 else
594                     app.put("%s".format(arg));
595             }
596             return app.data.join(", ");
597         }
598 
599         auto db = Database(":memory:");
600         db.createFunction("my_list", &myList);
601         auto list = db.execute("SELECT my_list(42, 3.14, 'text', NULL)").oneValue!string;
602         assert(list == `42, 3.14, "text", null`);
603     }
604 
605     /// Ditto
606     void createFunction(T)(string name, T fun = null)
607         if (is(T == typeof(null)))
608     {
609         assert(name.length, "function has an empty name");
610         assert(p.handle);
611         check(sqlite3_create_function_v2(p.handle, name.toStringz, -1, SQLITE_UTF8,
612                 null, fun, null, null, null));
613     }
614 
615     /++
616     Creates and registers a new aggregate function in the database.
617 
618     Params:
619         name = The name that the aggregate function will have in the database.
620 
621         agg = The struct of type T implementing the aggregate. T must implement
622         at least these two methods: `accumulate()` and `result()`.
623         Each parameter and the returned type of `accumulate()` and `result()` must be
624         a boolean or numeric type, a string, an array, `null`, or a `Nullable!T`
625         where T is any of the previous types. These methods cannot be variadic.
626 
627         det = Tells SQLite whether the result of the function is deterministic, i.e. if the
628         result is the same when called with the same parameters. Recent versions of SQLite
629         perform optimizations based on this. Set to `Deterministic.no` otherwise.
630 
631     See_Also: $(LINK http://www.sqlite.org/c3ref/create_function.html).
632     +/
633     void createAggregate(T)(string name, T agg, Deterministic det = Deterministic.yes)
634     {
635         import std.meta : staticMap;
636         import std.traits : isAggregateType, ReturnType, variadicFunctionStyle, Variadic,
637             Unqual, ParameterTypeTuple;
638         import core.stdc.stdlib : malloc;
639 
640         static assert(isAggregateType!T,
641             T.stringof ~ " should be an aggregate type");
642         static assert(is(typeof(T.accumulate) == function),
643             T.stringof ~ " should have a method named accumulate");
644         static assert(is(typeof(T.result) == function),
645             T.stringof ~ " should have a method named result");
646         static assert(is(typeof({
647                 alias RT = ReturnType!(T.result);
648                 setResult!RT(null, RT.init);
649             })), T.stringof ~ ".result should return an SQLite-compatible type");
650         static assert(variadicFunctionStyle!(T.accumulate) == Variadic.no,
651             "variadic functions are not supported");
652         static assert(variadicFunctionStyle!(T.result) == Variadic.no,
653             "variadic functions are not supported");
654 
655         alias PT = staticMap!(Unqual, ParameterTypeTuple!(T.accumulate));
656         alias RT = ReturnType!(T.result);
657 
658         static struct Context
659         {
660             T aggregate;
661             string functionName;
662         }
663 
664         extern(C) static nothrow
665         void x_step(sqlite3_context* context, int /* argc */, sqlite3_value** argv)
666         {
667             auto ctx = cast(Context*) sqlite3_user_data(context);
668             if (!ctx)
669             {
670                 sqlite3_result_error_nomem(context);
671                 return;
672             }
673 
674             PT args;
675             try
676             {
677                 foreach (i, type; PT)
678                     args[i] = getValue!type(argv[i]);
679 
680                 ctx.aggregate.accumulate(args);
681             }
682             catch (Exception e)
683             {
684                 sqlite3_result_error(context, "error in aggregate function %s(): %s"
685                     .nothrowFormat(ctx.functionName, e.msg).toStringz, -1);
686             }
687         }
688 
689         extern(C) static nothrow
690         void x_final(sqlite3_context* context)
691         {
692             auto ctx = cast(Context*) sqlite3_user_data(context);
693             if (!ctx)
694             {
695                 sqlite3_result_error_nomem(context);
696                 return;
697             }
698 
699             try
700             {
701                 setResult(context, ctx.aggregate.result());
702             }
703             catch (Exception e)
704             {
705                 sqlite3_result_error(context, "error in aggregate function %s(): %s"
706                     .nothrowFormat(ctx.functionName, e.msg).toStringz, -1);
707             }
708         }
709 
710         static if (is(T == class) || is(T == Interface))
711             assert(agg, "Attempt to create an aggregate function from a null reference");
712 
713         auto ctx = cast(Context*) malloc(Context.sizeof);
714         ctx.aggregate = agg;
715         ctx.functionName = name;
716 
717         assert(p.handle);
718         check(sqlite3_create_function_v2(p.handle, name.toStringz, PT.length, SQLITE_UTF8 | det,
719             cast(void*) ctx, null, &x_step, &x_final, &ptrFree));
720     }
721     ///
722     unittest // Aggregate creation
723     {
724         import std.array : Appender, join;
725 
726         // The implementation of the aggregate function
727         struct Joiner
728         {
729             private
730             {
731                 Appender!(string[]) stringList;
732                 string separator;
733             }
734 
735             this(string separator)
736             {
737                 this.separator = separator;
738             }
739 
740             void accumulate(string word)
741             {
742                 stringList.put(word);
743             }
744 
745             string result()
746             {
747                 return stringList.data.join(separator);
748             }
749         }
750 
751         auto db = Database(":memory:");
752         db.run("CREATE TABLE test (word TEXT);
753                 INSERT INTO test VALUES ('My');
754                 INSERT INTO test VALUES ('cat');
755                 INSERT INTO test VALUES ('is');
756                 INSERT INTO test VALUES ('black');");
757 
758         db.createAggregate("dash_join", Joiner("-"));
759         auto text = db.execute("SELECT dash_join(word) FROM test").oneValue!string;
760         assert(text == "My-cat-is-black");
761     }
762 
763     /++
764     Creates and registers a collation function in the database.
765 
766     Params:
767         name = The name that the function will have in the database.
768 
769         fun = a delegate or function that implements the collation. The function $(D_PARAM fun)
770         must be `nothrow`` and satisfy these criteria:
771             $(UL
772                 $(LI Takes two string arguments (s1 and s2). These two strings are slices of C-style strings
773                   that SQLite manages internally, so there is no guarantee that they are still valid
774                   when the function returns.)
775                 $(LI Returns an integer (ret).)
776                 $(LI If s1 is less than s2, ret < 0.)
777                 $(LI If s1 is equal to s2, ret == 0.)
778                 $(LI If s1 is greater than s2, ret > 0.)
779                 $(LI If s1 is equal to s2, then s2 is equal to s1.)
780                 $(LI If s1 is equal to s2 and s2 is equal to s3, then s1 is equal to s3.)
781                 $(LI If s1 is less than s2, then s2 is greater than s1.)
782                 $(LI If s1 is less than s2 and s2 is less than s3, then s1 is less than s3.)
783             )
784 
785     See_Also: $(LINK http://www.sqlite.org/lang_aggfunc.html)
786     +/
787     void createCollation(T)(string name, T fun)
788         if (isFunctionPointer!T || isDelegate!T)
789     {
790         import std.traits : isImplicitlyConvertible, functionAttributes, FunctionAttribute,
791             ParameterTypeTuple, isSomeString, ReturnType;
792 
793         static assert(isImplicitlyConvertible!(typeof(fun("a", "b")), int),
794             "the collation function has a wrong signature");
795 
796         static assert(functionAttributes!(T) & FunctionAttribute.nothrow_,
797             "only nothrow functions are allowed as collations");
798 
799         alias PT = ParameterTypeTuple!fun;
800         static assert(isSomeString!(PT[0]),
801             "the first argument of function " ~ name ~ " should be a string");
802         static assert(isSomeString!(PT[1]),
803             "the second argument of function " ~ name ~ " should be a string");
804         static assert(isImplicitlyConvertible!(ReturnType!fun, int),
805             "function " ~ name ~ " should return a value convertible to an int");
806 
807         extern (C) static nothrow
808         int x_compare(void* ptr, int n1, const(void)* str1, int n2, const(void)* str2)
809         {
810             static string slice(const(void)* str, int n) nothrow
811             {
812                 // The string data is owned by SQLite, so it should be safe
813                 // to take a slice of it.
814                 return str ? (cast(immutable) (cast(const(char)*) str)[0 .. n]) : null;
815             }
816 
817             return delegateUnwrap!T(ptr).dlg(slice(str1, n1), slice(str2, n2));
818         }
819 
820         assert(p.handle);
821         auto dgw = delegateWrap(fun, name);
822         auto result = sqlite3_create_collation_v2(p.handle, name.toStringz, SQLITE_UTF8,
823             delegateWrap(fun, name), &x_compare, &ptrFree);
824         if (result != SQLITE_OK)
825         {
826             ptrFree(dgw);
827             throw new SqliteException(errmsg(p.handle), result);
828         }
829     }
830     ///
831     unittest // Collation creation
832     {
833         // The implementation of the collation
834         int my_collation(string s1, string s2) nothrow
835         {
836             import std.uni : icmp;
837             import std.exception : assumeWontThrow;
838 
839             return assumeWontThrow(icmp(s1, s2));
840         }
841 
842         auto db = Database(":memory:");
843         db.createCollation("my_coll", &my_collation);
844         db.run("CREATE TABLE test (word TEXT);
845                 INSERT INTO test (word) VALUES ('straße');
846                 INSERT INTO test (word) VALUES ('strasses');");
847 
848         auto word = db.execute("SELECT word FROM test ORDER BY word COLLATE my_coll")
849                       .oneValue!string;
850         assert(word == "straße");
851     }
852 
853     /++
854     Registers a delegate of type `UpdateHookDelegate` as the database's update hook.
855 
856     Any previously set hook is released. Pass `null` to disable the callback.
857 
858     See_Also: $(LINK http://www.sqlite.org/c3ref/commit_hook.html).
859     +/
860     void setUpdateHook(UpdateHookDelegate updateHook)
861     {
862         extern(C) static nothrow
863         void callback(void* ptr, int type, const(char)* dbName, const(char)* tableName, long rowid)
864         {
865             WrappedDelegate!UpdateHookDelegate* dg;
866             dg = delegateUnwrap!UpdateHookDelegate(ptr);
867             dg.dlg(type, dbName.to!string, tableName.to!string, rowid);
868         }
869 
870         ptrFree(p.updateHook);
871         p.updateHook = delegateWrap(updateHook);
872         sqlite3_update_hook(p.handle, &callback, p.updateHook);
873     }
874 
875     /++
876     Registers a delegate of type `CommitHookDelegate` as the database's commit hook.
877     Any previously set hook is released.
878 
879     Params:
880         commitHook = A delegate that should return a non-zero value
881         if the operation must be rolled back, or 0 if it can commit.
882         Pass `null` to disable the callback.
883 
884     See_Also: $(LINK http://www.sqlite.org/c3ref/commit_hook.html).
885     +/
886     void setCommitHook(CommitHookDelegate commitHook)
887     {
888         extern(C) static nothrow
889         int callback(void* ptr)
890         {
891             auto dlg = delegateUnwrap!CommitHookDelegate(ptr).dlg;
892             return dlg();
893         }
894 
895         ptrFree(p.commitHook);
896         p.commitHook = delegateWrap(commitHook);
897         sqlite3_commit_hook(p.handle, &callback, p.commitHook);
898     }
899 
900     /++
901     Registers a delegate of type `RoolbackHookDelegate` as the database's rollback hook.
902 
903     Any previously set hook is released.
904     Pass `null` to disable the callback.
905 
906     See_Also: $(LINK http://www.sqlite.org/c3ref/commit_hook.html).
907     +/
908     void setRollbackHook(RoolbackHookDelegate rollbackHook)
909     {
910         extern(C) static nothrow
911         void callback(void* ptr)
912         {
913             auto dlg = delegateUnwrap!RoolbackHookDelegate(ptr).dlg;
914             dlg();
915         }
916 
917         ptrFree(p.rollbackHook);
918         p.rollbackHook = delegateWrap(rollbackHook);
919         sqlite3_rollback_hook(p.handle, &callback, p.rollbackHook);
920     }
921 
922     /++
923     Registers a delegate of type `ProgressHandlerDelegate` as the progress handler.
924 
925     Any previously set handler is released.
926     Pass `null` to disable the callback.
927 
928     Params:
929         pace = The approximate number of virtual machine instructions that are
930         evaluated between successive invocations of the handler.
931 
932         progressHandler = A delegate that should return 0 if the operation can continue
933         or another value if it must be aborted.
934 
935     See_Also: $(LINK http://www.sqlite.org/c3ref/progress_handler.html).
936     +/
937     void setProgressHandler(int pace, ProgressHandlerDelegate progressHandler)
938     {
939         extern(C) static nothrow
940         int callback(void* ptr)
941         {
942             auto dlg = delegateUnwrap!ProgressHandlerDelegate(ptr).dlg;
943             return dlg();
944         }
945 
946         ptrFree(p.progressHandler);
947         p.progressHandler = delegateWrap(progressHandler);
948         sqlite3_progress_handler(p.handle, pace, &callback, p.progressHandler);
949     }
950 
951     /++
952     Registers a delegate of type `TraceCallbackDelegate` as the trace callback.
953 
954     Any previously set trace callback is released.
955     Pass `null` to disable the callback.
956 
957     The string parameter that is passed to the callback is the SQL text of the statement being
958     executed.
959 
960     See_Also: $(LINK http://www.sqlite.org/c3ref/profile.html).
961     +/
962     void setTraceCallback(TraceCallbackDelegate traceCallback)
963     {
964         extern(C) static nothrow
965         void callback(void* ptr, const(char)* str)
966         {
967             auto dlg = delegateUnwrap!TraceCallbackDelegate(ptr).dlg;
968             dlg(str.to!string);
969         }
970 
971         ptrFree(p.traceCallback);
972         p.traceCallback = delegateWrap(traceCallback);
973         sqlite3_trace(p.handle, &callback, p.traceCallback);
974     }
975 
976     /++
977     Registers a delegate of type `ProfileCallbackDelegate` as the profile callback.
978 
979     Any previously set profile callback is released.
980     Pass `null` to disable the callback.
981 
982     The string parameter that is passed to the callback is the SQL text of the statement being
983     executed. The time unit is defined in SQLite's documentation as nanoseconds (subject to change,
984     as the functionality is experimental).
985 
986     See_Also: $(LINK http://www.sqlite.org/c3ref/profile.html).
987     +/
988     void setProfileCallback(ProfileCallbackDelegate profileCallback)
989     {
990         extern(C) static nothrow
991         void callback(void* ptr, const(char)* str, sqlite3_uint64 time)
992         {
993             auto dlg = delegateUnwrap!ProfileCallbackDelegate(ptr).dlg;
994             dlg(str.to!string, time);
995         }
996 
997         ptrFree(p.profileCallback);
998         p.profileCallback = delegateWrap(profileCallback);
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             body
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             body { 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             body
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             body
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, or 0 if this _code is not known.
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     {
1340         this.sql = sql;
1341         this.code = code;
1342         super(msg, file, line, next);
1343     }
1344 
1345     this(string msg, int code, string sql = null,
1346          string file = __FILE__, size_t line = __LINE__, Throwable next = null)
1347     {
1348         this("error %d: %s".format(code, msg), sql, code, file, line, next);
1349     }
1350 
1351     this(string msg, string sql = null,
1352          string file = __FILE__, size_t line = __LINE__, Throwable next = null)
1353     {
1354         this(msg, sql, 0, file, line, next);
1355     }
1356 }