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