1 /++
2 D2SQLite3 provides a thin and convenient wrapper around the SQLite C API.
3 
4 Features:
5 $(UL
6     $(LI Use reference-counted structs (`Database`, `Statement`) instead of SQLite objects
7     pointers.)
8     $(LI Run multistatement SQL code with `Database.run()`.)
9     $(LI Use built-in integral types, floating point types, `string`, `immutable(ubyte)[]` and
10     `Nullable` types directly: conversions to and from SQLite types is automatic and GC-safe.)
11     $(LI Bind multiple values to a prepare statement with `Statement.bindAll()` or
12     `Statement.inject()`. It's also possible to bind the fields of a struct automatically with
13     `Statement.inject()`.)
14     $(LI Handle the results of a query as a range of `Row`s, and the columns of a row
15     as a range of `ColumnData` (equivalent of a `Variant` fit for SQLite types).)
16     $(LI Access the data in a result row directly, by index or by name,
17     with the `Row.peek!T()` methods.)
18     $(LI Make a struct out of the data of a row with `Row.as!T()`.)
19     $(LI Register D functions as SQLite callbacks, with `Database.setUpdateHook()` $(I et al).)
20     $(LI Create new SQLite functions, aggregates or collations out of D functions or delegate,
21     with automatic type converions, with `Database.createFunction()` $(I et al).)
22     $(LI Store all the rows and columns resulting from a query at once with the `cached` function
23     (sometimes useful even if not memory-friendly...).)
24     $(LI Use an unlock notification when two or more connections access the same database in
25     shared-cache mode, either using SQLite's dedicated API (sqlite_unlock_notify) or using an
26     emulated equivalent.)
27 )
28 
29 Authors:
30     Nicolas Sicard (biozic) and other contributors at $(LINK https://github.com/biozic/d2sqlite3)
31 
32 Copyright:
33     Copyright 2011-18 Nicolas Sicard.
34 
35 License:
36     $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
37 +/
38 module d2sqlite3;
39 
40 public import d2sqlite3.library;
41 public import d2sqlite3.database;
42 public import d2sqlite3.statement;
43 public import d2sqlite3.results;
44 public import d2sqlite3.sqlite3;
45 
46 ///
47 unittest // Documentation example
48 {
49     // Note: exception handling is left aside for clarity.
50     import d2sqlite3;
51     import std.typecons : Nullable;
52 
53     // Open a database in memory.
54     auto db = Database(":memory:");
55 
56     // Create a table
57     db.run("DROP TABLE IF EXISTS person;
58             CREATE TABLE person (
59               id    INTEGER PRIMARY KEY,
60               name  TEXT NOT NULL,
61               score FLOAT
62             )");
63 
64     // Prepare an INSERT statement
65     Statement statement = db.prepare(
66         "INSERT INTO person (name, score)
67          VALUES (:name, :score)"
68     );
69 
70     // Bind values one by one (by parameter name or index)
71     statement.bind(":name", "John");
72     statement.bind(2, 77.5);
73     statement.execute();
74     statement.reset(); // Need to reset the statement after execution.
75 
76     // Bind muliple values at the same time
77     statement.bindAll("John", null);
78     statement.execute();
79     statement.reset();
80 
81     // Bind, execute and reset in one call
82     statement.inject("Clara", 88.1);
83 
84     // Count the changes
85     assert(db.totalChanges == 3);
86 
87     // Count the Johns in the table.
88     auto count = db.execute("SELECT count(*) FROM person WHERE name == 'John'")
89                    .oneValue!long;
90     assert(count == 2);
91 
92     // Read the data from the table lazily
93     ResultRange results = db.execute("SELECT * FROM person");
94     foreach (Row row; results)
95     {
96         // Retrieve "id", which is the column at index 0, and contains an int,
97         // e.g. using the peek function (best performance).
98         auto id = row.peek!long(0);
99 
100         // Retrieve "name", e.g. using opIndex(string), which returns a ColumnData.
101         auto name = row["name"].as!string;
102 
103         // Retrieve "score", which is at index 2, e.g. using the peek function,
104         // using a Nullable type
105         auto score = row.peek!(Nullable!double)(2);
106         if (!score.isNull)
107         {
108             // ...
109         }
110     }
111 }