1
- # swift-sqlcipher
1
+ # Swift SQLCipher
2
2
3
3
swift-sqlcipher is a C source packaging of [ SQLite3]
4
- with the [ SQLCipher] and [ Full-text search] extensions,
4
+ with built-in [ SQLCipher] and [ Full-text search] extensions,
5
5
along with a [ SQLiteDB] Swift package that provides
6
- API parity with the [ SQLite.swift] project.
6
+ API parity with the venerable [ SQLite.swift] project.
7
7
8
- It is meant to be a platform-agnostic project and does not presume the presence
9
- of any specific SQLite binary.
10
- It works out-of-the-box on macOS, iOS, Linux, Android, and Windows.
8
+ This is a stand-along and platform-agnostic project, and
9
+ does not presume the presence of any SQLite binary.
10
+ It is therefore suitable for embedded projects or
11
+ environments without any accessible ` sqlite3.so ` library (e.g., Android).
11
12
12
13
## Features
13
14
14
15
- A pure-Swift interface
15
16
- Embeds a modern and consistent sqlite (3.46.1) and sqlcipher (4.6.1) build in the library
17
+ - Works on iOS, macOS, Android, Windows, and Linux
16
18
- A type-safe, optional-aware SQL expression builder
17
19
- A flexible, chainable, lazy-executing query layer
18
20
- Automatically-typed data access
@@ -23,7 +25,6 @@ It works out-of-the-box on macOS, iOS, Linux, Android, and Windows.
23
25
- Extensively tested
24
26
- [ SQLCipher] [ ] support using the embedded [ LibTomCrypt] [ ] library
25
27
- [ Schema query/migration] [ ]
26
- - Works on iOS, macOS, Android, Windows, and Linux
27
28
28
29
[ SQLCipher ] : https://www.zetetic.net/sqlcipher/
29
30
[ LibTomCrypt ] : http://www.libtom.net/LibTomCrypt/
@@ -36,78 +37,73 @@ It works out-of-the-box on macOS, iOS, Linux, Android, and Windows.
36
37
``` swift
37
38
import SQLiteDB
38
39
39
- // Wrap everything in a do...catch to handle errors
40
- do {
41
- let db = try Connection (" path/to/db.sqlite3" )
42
-
43
- let users = Table (" users" )
44
- let id = SQLExpression< Int64 > (" id" )
45
- let name = SQLExpression< String ?> (" name" )
46
- let email = SQLExpression< String > (" email" )
47
-
48
- try db.run (users.create { t in
49
- t.column (id, primaryKey : true )
50
- t.column (name)
51
- t.column (email, unique : true )
52
- })
53
- // CREATE TABLE "users" (
54
- // "id" INTEGER PRIMARY KEY NOT NULL,
55
- // "name" TEXT,
56
- // "email" TEXT NOT NULL UNIQUE
57
- // )
58
-
59
- let insert = users.insert (name <- " Alice" , email <- " alice@mac.com" )
60
- let rowid = try db.run (insert)
61
- // INSERT INTO "users" ("name", "email") VALUES ('Alice', 'alice@mac.com')
62
-
63
- for user in try db.prepare (users) {
64
- print (" id: \( user[id] ) , name: \( user[name] ) , email: \( user[email] ) " )
65
- // id: 1, name: Optional("Alice"), email: alice@mac.com
66
- }
67
- // SELECT * FROM "users"
68
-
69
- let alice = users.filter (id == rowid)
70
-
71
- try db.run (alice.update (email <- email.replace (" mac.com" , with : " me.com" )))
72
- // UPDATE "users" SET "email" = replace("email", 'mac.com', 'me.com')
73
- // WHERE ("id" = 1)
74
-
75
- try db.run (alice.delete ())
76
- // DELETE FROM "users" WHERE ("id" = 1)
77
-
78
- try db.scalar (users.count ) // 0
79
- // SELECT count(*) FROM "users"
80
- } catch {
81
- print (error)
40
+ let db = try Connection (" path/to/db.sqlite3" )
41
+
42
+ // set the (optional) encryption key for the database
43
+ // this must be the first action performed on the Connection
44
+ try db.key (" x'2DD29CA851E7B56E4697B0E1F08507293D761A05CE4D1B628663F411A8086D99'" )
45
+
46
+ let users = Table (" users" )
47
+ let id = SQLExpression< Int64 > (" id" )
48
+ let name = SQLExpression< String ?> (" name" )
49
+ let email = SQLExpression< String > (" email" )
50
+
51
+ try db.run (users.create { t in
52
+ t.column (id, primaryKey : true )
53
+ t.column (name)
54
+ t.column (email, unique : true )
55
+ })
56
+ // CREATE TABLE "users" (
57
+ // "id" INTEGER PRIMARY KEY NOT NULL,
58
+ // "name" TEXT,
59
+ // "email" TEXT NOT NULL UNIQUE
60
+ // )
61
+
62
+ let insert = users.insert (name <- " Alice" , email <- " alice@mac.com" )
63
+ let rowid = try db.run (insert)
64
+ // INSERT INTO "users" ("name", "email") VALUES ('Alice', 'alice@mac.com')
65
+
66
+ for user in try db.prepare (users) {
67
+ print (" id: \( user[id] ) , name: \( user[name] ) , email: \( user[email] ) " )
68
+ // id: 1, name: Optional("Alice"), email: alice@mac.com
82
69
}
70
+ // SELECT * FROM "users"
71
+
72
+ let alice = users.filter (id == rowid)
73
+
74
+ try db.run (alice.update (email <- email.replace (" mac.com" , with : " me.com" )))
75
+ // UPDATE "users" SET "email" = replace("email", 'mac.com', 'me.com')
76
+ // WHERE ("id" = 1)
77
+
78
+ try db.run (alice.delete ())
79
+ // DELETE FROM "users" WHERE ("id" = 1)
80
+
81
+ try db.scalar (users.count ) // 0
82
+ // SELECT count(*) FROM "users"
83
83
```
84
84
85
85
SQLiteDB also works as a lightweight, Swift-friendly wrapper over the C
86
86
API.
87
87
88
88
``` swift
89
- do {
90
- // ...
91
-
92
- let stmt = try db.prepare (" INSERT INTO users (email) VALUES (?)" )
93
- for email in [" betty@icloud.com" , " cathy@icloud.com" ] {
94
- try stmt.run (email)
95
- }
96
-
97
- db.totalChanges // 3
98
- db.changes // 1
99
- db.lastInsertRowid // 3
100
-
101
- for row in try db.prepare (" SELECT id, email FROM users" ) {
102
- print (" id: \( row[0 ] ) , email: \( row[1 ] ) " )
103
- // id: Optional(2), email: Optional("betty@icloud.com")
104
- // id: Optional(3), email: Optional("cathy@icloud.com")
105
- }
106
-
107
- try db.scalar (" SELECT count(*) FROM users" ) // 2
108
- } catch {
109
- print (error)
89
+ // ...
90
+
91
+ let stmt = try db.prepare (" INSERT INTO users (email) VALUES (?)" )
92
+ for email in [" betty@icloud.com" , " cathy@icloud.com" ] {
93
+ try stmt.run (email)
110
94
}
95
+
96
+ db.totalChanges // 3
97
+ db.changes // 1
98
+ db.lastInsertRowid // 3
99
+
100
+ for row in try db.prepare (" SELECT id, email FROM users" ) {
101
+ print (" id: \( row[0 ] ) , email: \( row[1 ] ) " )
102
+ // id: Optional(2), email: Optional("betty@icloud.com")
103
+ // id: Optional(3), email: Optional("cathy@icloud.com")
104
+ }
105
+
106
+ try db.scalar (" SELECT count(*) FROM users" ) // 2
111
107
```
112
108
113
109
[ Read the documentation] [ See Documentation ]
@@ -149,16 +145,15 @@ Swift code.
149
145
150
146
## License
151
147
152
- SQLite.swift is available under the MIT license. See [ the LICENSE
153
- file] ( ./LICENSE.txt ) for more information.
148
+ MIT license. See [ the LICENSE file] ( ./LICENSE.txt ) for more information.
154
149
155
150
## Alternatives
156
151
157
152
Here are a number of other popular SQLite alternative packages:
158
153
159
- - [ swift-toolchain-sqlite] ( https://github.com/swiftlang/swift-toolchain-sqlite )
160
154
- [ SQLite.swift] ( https://github.com/stephencelis/SQLite.swift )
161
155
- [ GRDB] ( https://github.com/groue/GRDB.swift )
156
+ - [ swift-toolchain-sqlite] ( https://github.com/swiftlang/swift-toolchain-sqlite )
162
157
- [ FMDB]
163
158
164
159
[ SQLite3 ] : https://www.sqlite.org
0 commit comments