Skip to content

Commit 37a7b72

Browse files
committed
2 parents 709d137 + 0997f34 commit 37a7b72

26 files changed

+1463
-87
lines changed

.travis.yml

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
language: objective-c
2-
env:
3-
- BUILD_SCHEME="SQLite iOS"
4-
- BUILD_SCHEME="SQLite Mac"
2+
matrix:
3+
include:
4+
- env: BUILD_SCHEME="SQLite iOS"
5+
- env: BUILD_SCHEME="SQLite Mac"
6+
- env: VALIDATOR_SUBSPEC="none"
7+
- env: VALIDATOR_SUBSPEC="standard"
8+
- env: VALIDATOR_SUBSPEC="standalone"
59
before_install:
610
- gem install xcpretty --no-document
711
script:
8-
- make test
12+
- ./run-tests.sh
913
osx_image: xcode7.3

CocoaPodsTests/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
gems/

CocoaPodsTests/Gemfile

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
source 'https://rubygems.org'
2+
3+
gem 'cocoapods'
4+
gem 'minitest'

CocoaPodsTests/Gemfile.lock

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
GEM
2+
remote: https://rubygems.org/
3+
specs:
4+
activesupport (4.2.6)
5+
i18n (~> 0.7)
6+
json (~> 1.7, >= 1.7.7)
7+
minitest (~> 5.1)
8+
thread_safe (~> 0.3, >= 0.3.4)
9+
tzinfo (~> 1.1)
10+
claide (1.0.0)
11+
cocoapods (1.0.0)
12+
activesupport (>= 4.0.2)
13+
claide (>= 1.0.0, < 2.0)
14+
cocoapods-core (= 1.0.0)
15+
cocoapods-deintegrate (>= 1.0.0, < 2.0)
16+
cocoapods-downloader (>= 1.0.0, < 2.0)
17+
cocoapods-plugins (>= 1.0.0, < 2.0)
18+
cocoapods-search (>= 1.0.0, < 2.0)
19+
cocoapods-stats (>= 1.0.0, < 2.0)
20+
cocoapods-trunk (>= 1.0.0, < 2.0)
21+
cocoapods-try (>= 1.0.0, < 2.0)
22+
colored (~> 1.2)
23+
escape (~> 0.0.4)
24+
fourflusher (~> 0.3.0)
25+
molinillo (~> 0.4.5)
26+
nap (~> 1.0)
27+
xcodeproj (>= 1.0.0, < 2.0)
28+
cocoapods-core (1.0.0)
29+
activesupport (>= 4.0.2)
30+
fuzzy_match (~> 2.0.4)
31+
nap (~> 1.0)
32+
cocoapods-deintegrate (1.0.0)
33+
cocoapods-downloader (1.0.0)
34+
cocoapods-plugins (1.0.0)
35+
nap
36+
cocoapods-search (1.0.0)
37+
cocoapods-stats (1.0.0)
38+
cocoapods-trunk (1.0.0)
39+
nap (>= 0.8, < 2.0)
40+
netrc (= 0.7.8)
41+
cocoapods-try (1.0.0)
42+
colored (1.2)
43+
escape (0.0.4)
44+
fourflusher (0.3.0)
45+
fuzzy_match (2.0.4)
46+
i18n (0.7.0)
47+
json (1.8.3)
48+
minitest (5.8.4)
49+
molinillo (0.4.5)
50+
nap (1.1.0)
51+
netrc (0.7.8)
52+
thread_safe (0.3.5)
53+
tzinfo (1.2.2)
54+
thread_safe (~> 0.1)
55+
xcodeproj (1.0.0)
56+
activesupport (>= 3)
57+
claide (>= 1.0.0, < 2.0)
58+
colored (~> 1.2)
59+
60+
PLATFORMS
61+
ruby
62+
63+
DEPENDENCIES
64+
cocoapods
65+
minitest

CocoaPodsTests/Makefile

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
test: install
2+
@set -e; \
3+
for test in *_test.rb; do \
4+
bundle exec ./$$test; \
5+
done
6+
7+
install:
8+
@bundle install --path gems
9+
10+
.PHONY: test install

CocoaPodsTests/integration_test.rb

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
#!/usr/bin/env ruby
2+
3+
require 'minitest/autorun'
4+
require_relative 'test_running_validator'
5+
6+
class IntegrationTest < Minitest::Test
7+
8+
def test_validate_project
9+
assert validator.validate, "validation failed: #{validator.failure_reason}"
10+
end
11+
12+
private
13+
14+
def validator
15+
@validator ||= TestRunningValidator.new(podspec, []).tap do |validator|
16+
subspec = ENV["VALIDATOR_SUBSPEC"]
17+
validator.test_files = Dir["#{project_test_dir}/*.swift"]
18+
validator.config.verbose = true
19+
validator.no_clean = true
20+
validator.use_frameworks = true
21+
validator.fail_fast = true
22+
validator.local = true
23+
validator.allow_warnings = true
24+
if subspec == "none"
25+
validator.no_subspecs = true
26+
else
27+
validator.only_subspec = subspec
28+
end
29+
end
30+
end
31+
32+
def podspec
33+
File.expand_path(File.dirname(__FILE__) + '/../SQLite.swift.podspec')
34+
end
35+
36+
def project_test_dir
37+
File.expand_path(File.dirname(__FILE__) + '/../SQLiteTests')
38+
end
39+
end
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
require 'cocoapods'
2+
require 'cocoapods/validator'
3+
require 'fileutils'
4+
5+
class TestRunningValidator < Pod::Validator
6+
APP_TARGET = 'App'
7+
TEST_TARGET = 'Tests'
8+
9+
attr_accessor :test_files
10+
11+
def create_app_project
12+
super.tap do
13+
project = Xcodeproj::Project.open(validation_dir + "#{APP_TARGET}.xcodeproj")
14+
create_test_target(project)
15+
end
16+
end
17+
18+
def install_pod
19+
super.tap do
20+
if local?
21+
FileUtils.ln_s file.dirname, validation_dir + "Pods/#{spec.name}"
22+
end
23+
end
24+
end
25+
26+
def podfile_from_spec(*args)
27+
super(*args).tap do |pod_file|
28+
add_test_target(pod_file)
29+
end
30+
end
31+
32+
def build_pod
33+
super
34+
Pod::UI.message "\Testing with xcodebuild.\n".yellow do
35+
run_tests
36+
end
37+
end
38+
39+
private
40+
def create_test_target(project)
41+
test_target = project.new_target(:unit_test_bundle, TEST_TARGET, consumer.platform_name, deployment_target)
42+
group = project.new_group(TEST_TARGET)
43+
test_target.add_file_references(test_files.map { |file| group.new_file(file) })
44+
project.save
45+
create_test_scheme(project, test_target)
46+
project
47+
end
48+
49+
def create_test_scheme(project, test_target)
50+
project.recreate_user_schemes
51+
test_scheme = Xcodeproj::XCScheme.new(test_scheme_path(project))
52+
test_scheme.add_test_target(test_target)
53+
test_scheme.save!
54+
end
55+
56+
def test_scheme_path(project)
57+
Xcodeproj::XCScheme.user_data_dir(project.path) + "#{TEST_TARGET}.xcscheme"
58+
end
59+
60+
def add_test_target(pod_file)
61+
app_target = pod_file.target_definitions[APP_TARGET]
62+
Pod::Podfile::TargetDefinition.new(TEST_TARGET, app_target)
63+
end
64+
65+
def run_tests
66+
command = %W(clean test -workspace #{APP_TARGET}.xcworkspace -scheme #{TEST_TARGET} -configuration Debug)
67+
case consumer.platform_name
68+
when :ios
69+
command += %w(CODE_SIGN_IDENTITY=- -sdk iphonesimulator)
70+
command += Fourflusher::SimControl.new.destination('iPhone 4s', deployment_target)
71+
when :osx
72+
command += %w(LD_RUNPATH_SEARCH_PATHS=@loader_path/../Frameworks)
73+
when :tvos
74+
command += %w(CODE_SIGN_IDENTITY=- -sdk appletvsimulator)
75+
command += Fourflusher::SimControl.new.destination('Apple TV 1080p', deployment_target)
76+
else
77+
return # skip watchos
78+
end
79+
80+
output, status = Dir.chdir(validation_dir) { _xcodebuild(command) }
81+
unless status.success?
82+
message = 'Returned an unsuccessful exit code.'
83+
if config.verbose?
84+
message += "\nXcode output: \n#{output}\n"
85+
else
86+
message += ' You can use `--verbose` for more information.'
87+
end
88+
error('xcodebuild', message)
89+
end
90+
end
91+
end

Documentation/Index.md

Lines changed: 79 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
- [Read-Only Databases](#read-only-databases)
1212
- [In-Memory Databases](#in-memory-databases)
1313
- [Thread-Safety](#thread-safety)
14+
- [Connection Pools](#connection-pools)
1415
- [Building Type-Safe SQL](#building-type-safe-sql)
1516
- [Expressions](#expressions)
1617
- [Compound Expressions](#compound-expressions)
@@ -111,8 +112,26 @@ install SQLite.swift with Carthage:
111112
112113
3. Run `pod install`.
113114
115+
#### Requiring a specific version of SQLite
116+
117+
If you want to use a more recent version of SQLite than what is provided with the OS you can require the `standalone` subspec:
118+
119+
``` ruby
120+
pod 'SQLite.swift/standalone', '~> 0.10.1'
121+
```
122+
123+
By default this will use the most recent version of SQLite without any extras. If you want you can further customize this by adding another dependency to sqlite3 or one of its subspecs:
124+
125+
``` ruby
126+
pod 'SQLite.swift/standalone', '~> 0.10.1'
127+
pod 'sqlite3/fts5', '= 3.11.1' # SQLite 3.11.1 with FTS5 enabled
128+
```
129+
130+
See the [sqlite3 podspec][sqlite3pod] for more details.
131+
114132
[CocoaPods]: https://cocoapods.org
115133
[CocoaPods Installation]: https://guides.cocoapods.org/using/getting-started.html#getting-started
134+
[sqlite3pod]: https://github.com/clemensg/sqlite3pod
116135

117136

118137
### Manual
@@ -233,7 +252,7 @@ Every Connection comes equipped with its own serial queue for statement executio
233252

234253
If you maintain multiple connections for a single database, consider setting a timeout (in seconds) and/or a busy handler:
235254

236-
```swift
255+
``` swift
237256
db.busyTimeout = 5
238257

239258
db.busyHandler({ tries in
@@ -247,6 +266,33 @@ db.busyHandler({ tries in
247266
> _Note:_ The default timeout is 0, so if you see `database is locked` errors, you may be trying to access the same database simultaneously from multiple connections.
248267

249268

269+
### Connection Pools
270+
271+
Connection pools use SQLite WAL mode to allow concurrent reads and writes, which can increase performance. Connection pools are created similar to connections:
272+
273+
``` swift
274+
let pool = try ConnectionPool("path/to/db.sqlite3")
275+
```
276+
277+
Writes are done inside of a readWrite block:
278+
279+
``` swift
280+
pool.readWrite { connection in
281+
try connection.run(users.insert(email <- "alice@mac.com", name <- "Alice"))
282+
}
283+
```
284+
285+
Reads are done inside of a read block:
286+
287+
``` swift
288+
pool.read { connection in
289+
for user in try connection.prepare(users) {
290+
print("id: \(user[id]), email: \(user[email]), name: \(user[name])")
291+
}
292+
}
293+
```
294+
295+
250296
## Building Type-Safe SQL
251297

252298
SQLite.swift comes with a typed expression layer that directly maps [Swift types](https://developer.apple.com/library/prerelease/ios/documentation/General/Reference/SwiftStandardLibraryReference/) to their [SQLite counterparts](https://www.sqlite.org/datatype3.html).
@@ -1381,6 +1427,22 @@ try db.run(emails.create(.FTS4([subject, body], tokenize: .Porter)))
13811427
// CREATE VIRTUAL TABLE "emails" USING fts4("subject", "body", tokenize=porter)
13821428
```
13831429

1430+
We can set the full range of parameters by creating a `FTS4Config` object.
1431+
1432+
``` swift
1433+
let emails = VirtualTable("emails")
1434+
let subject = Expression<String>("subject")
1435+
let body = Expression<String>("body")
1436+
let config = FTS4Config()
1437+
.column(subject)
1438+
.column(body, [.unindexed])
1439+
.languageId("lid")
1440+
.order(.Desc)
1441+
1442+
try db.run(emails.create(.FTS4(config))
1443+
// CREATE VIRTUAL TABLE "emails" USING fts4("subject", "body", notindexed="body", languageid="lid", order="desc")
1444+
```
1445+
13841446
Once we insert a few rows, we can search using the `match` function, which takes a table or column as its first argument and a query string as its second.
13851447

13861448
``` swift
@@ -1396,6 +1458,22 @@ let replies = emails.filter(subject.match("Re:*"))
13961458
// SELECT * FROM "emails" WHERE "subject" MATCH 'Re:*'
13971459
```
13981460

1461+
### FTS5
1462+
1463+
When linking against a version of SQLite with [FTS5](http://www.sqlite.org/fts5.html) enabled we can create the virtual table
1464+
in a similar fashion.
1465+
1466+
```swift
1467+
let emails = VirtualTable("emails")
1468+
let subject = Expression<String>("subject")
1469+
let body = Expression<String>("body")
1470+
let config = FTS5Config()
1471+
.column(subject)
1472+
.column(body, [.unindexed])
1473+
1474+
try db.run(emails.create(.FTS5(config))
1475+
// CREATE VIRTUAL TABLE "emails" USING fts5("subject", "body" UNINDEXED)
1476+
```
13991477

14001478
## Executing Arbitrary SQL
14011479

Makefile

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
BUILD_TOOL = xcodebuild
22
BUILD_SCHEME = SQLite Mac
3-
BUILD_ARGUMENTS = -scheme "$(BUILD_SCHEME)"
3+
ifeq ($(BUILD_SCHEME),SQLite iOS)
4+
BUILD_ARGUMENTS = -scheme "$(BUILD_SCHEME)" -sdk iphonesimulator
5+
else
6+
BUILD_ARGUMENTS = -scheme "$(BUILD_SCHEME)"
7+
endif
48

59
XCPRETTY := $(shell command -v xcpretty)
610
SWIFTCOV := $(shell command -v swiftcov)

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,7 @@ These projects enhance or use SQLite.swift:
230230
Looking for something else? Try another Swift wrapper (or [FMDB][]):
231231
232232
- [Camembert](https://github.com/remirobert/Camembert)
233-
- [EonilSQLite3](https://github.com/Eonil/SQLite3)
233+
- [GRDB](https://github.com/groue/GRDB.swift)
234234
- [SQLiteDB](https://github.com/FahimF/SQLiteDB)
235235
- [Squeal](https://github.com/nerdyc/Squeal)
236236
- [SwiftData](https://github.com/ryanfowler/SwiftData)

0 commit comments

Comments
 (0)