Skip to content

Commit

Permalink
Merge branch 'development'
Browse files Browse the repository at this point in the history
  • Loading branch information
groue committed Sep 3, 2021
2 parents ba41c22 + 042fbe9 commit 1acf8e4
Show file tree
Hide file tree
Showing 37 changed files with 1,245 additions and 122 deletions.
3 changes: 3 additions & 0 deletions .swiftlint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,6 @@ opt_in_rules:

vertical_whitespace:
max_empty_lines: 2

line_length:
ignores_urls: true
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ GRDB adheres to [Semantic Versioning](https://semver.org/), with one exception:

#### 5.x Releases

- `5.11.x` Releases - [5.11.0](#5110)
- `5.10.x` Releases - [5.10.0](#5100)
- `5.9.x` Releases - [5.9.0](#590)
- `5.8.x` Releases - [5.8.0](#580)
Expand Down Expand Up @@ -77,6 +78,15 @@ GRDB adheres to [Semantic Versioning](https://semver.org/), with one exception:

---

## 5.11.0

Released September 3, 2021 • [diff](https://github.com/groue/GRDB.swift/compare/v5.10.0...v5.11.0)

- **Fixed**: Version 5.10.0, when embedded as an Xcode project, would enable the FTS5 full-text engine on system versions that do not provide it.
- **New**: [#1046](https://github.com/groue/GRDB.swift/pull/1046) by [@groue](https://github.com/groue): Improve performance of by-index row decoding
- **New**: [#1029](https://github.com/groue/GRDB.swift/pull/1029) by [@sberrevoets](https://github.com/sberrevoets), [@groue](https://github.com/groue): Column coding strategies for Codable records


## 5.10.0

Released August 22, 2021 • [diff](https://github.com/groue/GRDB.swift/compare/v5.9.0...v5.10.0)
Expand Down
4 changes: 2 additions & 2 deletions Documentation/FullTextSearch.md
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,7 @@ let pattern = FTS3Pattern(matchingAnyTokenIn: "") // nil
let pattern = FTS3Pattern(matchingAnyTokenIn: "*") // nil
```

FTS3Pattern are regular [values](../README.md#values). You can use them as query [arguments](http://groue.github.io/GRDB.swift/docs/5.10/Structs/StatementArguments.html):
FTS3Pattern are regular [values](../README.md#values). You can use them as query [arguments](http://groue.github.io/GRDB.swift/docs/5.11/Structs/StatementArguments.html):

```swift
let documents = try Document.fetchAll(db,
Expand Down Expand Up @@ -529,7 +529,7 @@ let pattern = FTS5Pattern(matchingAnyTokenIn: "") // nil
let pattern = FTS5Pattern(matchingAnyTokenIn: "*") // nil
```

FTS5Pattern are regular [values](../README.md#values). You can use them as query [arguments](http://groue.github.io/GRDB.swift/docs/5.10/Structs/StatementArguments.html):
FTS5Pattern are regular [values](../README.md#values). You can use them as query [arguments](http://groue.github.io/GRDB.swift/docs/5.11/Structs/StatementArguments.html):

```swift
let documents = try Document.fetchAll(db,
Expand Down
2 changes: 1 addition & 1 deletion Documentation/Migrations.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ try dbQueue.read { db in
}
```

See the [DatabaseMigrator reference](http://groue.github.io/GRDB.swift/docs/5.10/Structs/DatabaseMigrator.html) for more migrator methods.
See the [DatabaseMigrator reference](http://groue.github.io/GRDB.swift/docs/5.11/Structs/DatabaseMigrator.html) for more migrator methods.


## The `eraseDatabaseOnSchemaChange` Option
Expand Down
2 changes: 1 addition & 1 deletion GRDB.swift.podspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'GRDB.swift'
s.version = '5.10.0'
s.version = '5.11.0'

s.license = { :type => 'MIT', :file => 'LICENSE' }
s.summary = 'A toolkit for SQLite databases, with a focus on application development.'
Expand Down
8 changes: 8 additions & 0 deletions GRDB.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -1217,6 +1217,9 @@
C96C0F2B2084A442006B2981 /* SQLiteDateParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = C96C0F242084A442006B2981 /* SQLiteDateParser.swift */; };
C96C0F2C2084A459006B2981 /* SQLiteDateParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = C96C0F242084A442006B2981 /* SQLiteDateParser.swift */; };
C96C0F2D2084A45A006B2981 /* SQLiteDateParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = C96C0F242084A442006B2981 /* SQLiteDateParser.swift */; };
D263F40A26C613090038B07F /* DatabaseColumnEncodingStrategyTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D263F40926C613090038B07F /* DatabaseColumnEncodingStrategyTests.swift */; };
D263F40B26C613090038B07F /* DatabaseColumnEncodingStrategyTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D263F40926C613090038B07F /* DatabaseColumnEncodingStrategyTests.swift */; };
D263F40C26C613090038B07F /* DatabaseColumnEncodingStrategyTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D263F40926C613090038B07F /* DatabaseColumnEncodingStrategyTests.swift */; };
DC2393C81ABE35F8003FF113 /* GRDB-Bridging.h in Headers */ = {isa = PBXBuildFile; fileRef = DC2393C61ABE35F8003FF113 /* GRDB-Bridging.h */; settings = {ATTRIBUTES = (Public, ); }; };
DC3773F919C8CBB3004FCF85 /* GRDB.h in Headers */ = {isa = PBXBuildFile; fileRef = DC3773F819C8CBB3004FCF85 /* GRDB.h */; settings = {ATTRIBUTES = (Public, ); }; };
/* End PBXBuildFile section */
Expand Down Expand Up @@ -1625,6 +1628,7 @@
AAA4DCFE230F1E0600C74B15 /* GRDB.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = GRDB.framework; sourceTree = BUILT_PRODUCTS_DIR; };
AAA4DDD4230F262000C74B15 /* GRDBtvOSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = GRDBtvOSTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
C96C0F242084A442006B2981 /* SQLiteDateParser.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SQLiteDateParser.swift; sourceTree = "<group>"; };
D263F40926C613090038B07F /* DatabaseColumnEncodingStrategyTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DatabaseColumnEncodingStrategyTests.swift; sourceTree = "<group>"; };
DC2393C61ABE35F8003FF113 /* GRDB-Bridging.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "GRDB-Bridging.h"; sourceTree = "<group>"; };
DC3773F319C8CBB3004FCF85 /* GRDB.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = GRDB.framework; sourceTree = BUILT_PRODUCTS_DIR; };
DC3773F719C8CBB3004FCF85 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1771,6 +1775,7 @@
560B3FA41C19DFF800C58EC7 /* PersistableRecord */ = {
isa = PBXGroup;
children = (
D263F40926C613090038B07F /* DatabaseColumnEncodingStrategyTests.swift */,
5665FA322129EEA0004D8612 /* DatabaseDateEncodingStrategyTests.swift */,
56703290212B544F007D270F /* DatabaseUUIDEncodingStrategyTests.swift */,
566A843F2041914000E50BFD /* MutablePersistableRecordChangesTests.swift */,
Expand Down Expand Up @@ -3343,6 +3348,7 @@
564CE5BF21B8FFA300652B19 /* DatabaseRegionObservationTests.swift in Sources */,
5653EAEF20944B4F00F46237 /* AssociationParallelDecodableRecordTests.swift in Sources */,
56A2383C1B9C74A90082EB20 /* DatabaseErrorTests.swift in Sources */,
D263F40B26C613090038B07F /* DatabaseColumnEncodingStrategyTests.swift in Sources */,
5690C32A1D23E6D800E59934 /* FoundationDateComponentsTests.swift in Sources */,
5657AB3A1D108BA9006283EF /* FoundationDataTests.swift in Sources */,
563363D61C94484E000BE133 /* DatabaseQueueReleaseMemoryTests.swift in Sources */,
Expand Down Expand Up @@ -3574,6 +3580,7 @@
56D4966C1D81309E008276D7 /* RecordMinimalPrimaryKeyRowIDTests.swift in Sources */,
564CE5BE21B8FFA300652B19 /* DatabaseRegionObservationTests.swift in Sources */,
564F9C1E1F069B4E00877A00 /* DatabaseAggregateTests.swift in Sources */,
D263F40A26C613090038B07F /* DatabaseColumnEncodingStrategyTests.swift in Sources */,
5653EAEE20944B4F00F46237 /* AssociationParallelDecodableRecordTests.swift in Sources */,
56D496861D813147008276D7 /* UpdateStatementTests.swift in Sources */,
56D4965D1D81304E008276D7 /* FoundationNSNumberTests.swift in Sources */,
Expand Down Expand Up @@ -3938,6 +3945,7 @@
AAA4DD99230F262000C74B15 /* DatabaseRegionObservationTests.swift in Sources */,
AAA4DD9A230F262000C74B15 /* AssociationParallelDecodableRecordTests.swift in Sources */,
AAA4DD9C230F262000C74B15 /* DatabaseErrorTests.swift in Sources */,
D263F40C26C613090038B07F /* DatabaseColumnEncodingStrategyTests.swift in Sources */,
AAA4DD9D230F262000C74B15 /* FoundationDateComponentsTests.swift in Sources */,
AAA4DD9E230F262000C74B15 /* FoundationDataTests.swift in Sources */,
AAA4DD9F230F262000C74B15 /* DatabaseQueueReleaseMemoryTests.swift in Sources */,
Expand Down
2 changes: 0 additions & 2 deletions GRDB/Core/Database.swift
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,6 @@ public final class Database: CustomStringConvertible, CustomDebugStringConvertib
//
// - DatabaseCursorTests.testIssue583()
// - http://sqlite.1065341.n5.nabble.com/Issue-report-sqlite3-set-authorizer-triggers-error-4-516-SQLITE-ABORT-ROLLBACK-during-statement-itern-td107972.html
// swiftlint:disable:previous line_length
let dbPointer = Unmanaged.passUnretained(self).toOpaque()
sqlite3_set_authorizer(
sqliteConnection,
Expand Down Expand Up @@ -1293,7 +1292,6 @@ extension Database {
// > options and using sqlcipher_export() to migrate the contents and
// > schema of the original db into the new one:
// > https://discuss.zetetic.net/t/how-to-encrypt-a-plaintext-sqlite-database-to-use-sqlcipher-and-avoid-file-is-encrypted-or-is-not-a-database-errors/
// swiftlint:disable:previous line_length
let code = passphrase.withUnsafeBytes {
sqlite3_rekey(sqliteConnection, $0.baseAddress, Int32($0.count))
}
Expand Down
36 changes: 25 additions & 11 deletions GRDB/Core/Row.swift
Original file line number Diff line number Diff line change
Expand Up @@ -166,10 +166,10 @@ extension Row {
// MARK: - Extracting Values

/// Fatal errors if index is out of bounds
@inline(__always)
@usableFromInline
/* private */ func _checkedIndex(_ index: Int, file: StaticString = #file, line: UInt = #line) -> Int {
/* private */ func _checkIndex(_ index: Int, file: StaticString = #file, line: UInt = #line) {
GRDBPrecondition(index >= 0 && index < count, "row index out of range", file: file, line: line)
return index
}

/// Returns true if and only if one column contains a non-null value, or if
Expand Down Expand Up @@ -204,7 +204,8 @@ extension Row {
/// in performance-critical code because it can avoid decoding database
/// values.
public func hasNull(atIndex index: Int) -> Bool {
impl.hasNull(atUncheckedIndex: _checkedIndex(index))
_checkIndex(index)
return impl.hasNull(atUncheckedIndex: index)
}

/// Returns Int64, Double, String, Data or nil, depending on the value
Expand All @@ -213,7 +214,8 @@ extension Row {
/// Indexes span from 0 for the leftmost column to (row.count - 1) for the
/// righmost column.
public subscript(_ index: Int) -> DatabaseValueConvertible? {
impl.databaseValue(atUncheckedIndex: _checkedIndex(index)).storage.value
_checkIndex(index)
return impl.databaseValue(atUncheckedIndex: index).storage.value
}

/// Returns the value at given index, converted to the requested type.
Expand Down Expand Up @@ -241,6 +243,7 @@ extension Row {
/// This method exists as an optimization opportunity for types that adopt
/// StatementColumnConvertible. It *may* trigger SQLite built-in conversions
/// (see <https://www.sqlite.org/datatype3.html>).
@inline(__always)
@inlinable
public subscript<Value: DatabaseValueConvertible & StatementColumnConvertible>(_ index: Int) -> Value? {
try! decodeIfPresent(Value.self, atIndex: index)
Expand Down Expand Up @@ -269,6 +272,7 @@ extension Row {
/// This method exists as an optimization opportunity for types that adopt
/// StatementColumnConvertible. It *may* trigger SQLite built-in conversions
/// (see <https://www.sqlite.org/datatype3.html>).
@inline(__always)
@inlinable
public subscript<Value: DatabaseValueConvertible & StatementColumnConvertible>(_ index: Int) -> Value {
try! decode(Value.self, atIndex: index)
Expand Down Expand Up @@ -712,7 +716,8 @@ extension Row {
atIndex index: Int)
throws -> Value?
{
try Value.decodeIfPresent(fromRow: self, atUncheckedIndex: _checkedIndex(index))
_checkIndex(index)
return try Value.decodeIfPresent(fromRow: self, atUncheckedIndex: index)
}

/// Returns the value at given index, converted to the requested type.
Expand All @@ -728,7 +733,8 @@ extension Row {
atIndex index: Int)
throws -> Value
{
try Value.decode(fromRow: self, atUncheckedIndex: _checkedIndex(index))
_checkIndex(index)
return try Value.decode(fromRow: self, atUncheckedIndex: index)
}

/// Returns the value at given column, converted to the requested type.
Expand Down Expand Up @@ -787,13 +793,15 @@ extension Row {
/// This method exists as an optimization opportunity for types that adopt
/// StatementColumnConvertible. It *may* trigger SQLite built-in conversions
/// (see <https://www.sqlite.org/datatype3.html>).
@inline(__always)
@inlinable
func decodeIfPresent<Value: DatabaseValueConvertible & StatementColumnConvertible>(
_ type: Value.Type = Value.self,
atIndex index: Int)
throws -> Value?
{
try Value.fastDecodeIfPresent(fromRow: self, atUncheckedIndex: _checkedIndex(index))
_checkIndex(index)
return try Value.fastDecodeIfPresent(fromRow: self, atUncheckedIndex: index)
}

/// Returns the value at given index, converted to the requested type.
Expand All @@ -807,13 +815,15 @@ extension Row {
/// This method exists as an optimization opportunity for types that adopt
/// StatementColumnConvertible. It *may* trigger SQLite built-in conversions
/// (see <https://www.sqlite.org/datatype3.html>).
@inline(__always)
@inlinable
func decode<Value: DatabaseValueConvertible & StatementColumnConvertible>(
_ type: Value.Type = Value.self,
atIndex index: Int)
throws -> Value
{
try Value.fastDecode(fromRow: self, atUncheckedIndex: _checkedIndex(index))
_checkIndex(index)
return try Value.fastDecode(fromRow: self, atUncheckedIndex: index)
}

/// Returns the value at given column, converted to the requested type.
Expand All @@ -828,6 +838,7 @@ extension Row {
/// This method exists as an optimization opportunity for types that adopt
/// StatementColumnConvertible. It *may* trigger SQLite built-in conversions
/// (see <https://www.sqlite.org/datatype3.html>).
@inline(__always)
@inlinable
func decodeIfPresent<Value: DatabaseValueConvertible & StatementColumnConvertible>(
_ type: Value.Type = Value.self,
Expand Down Expand Up @@ -899,7 +910,8 @@ extension Row {
/// The returned data does not owns its bytes: it must not be used longer
/// than the row's lifetime.
func decodeDataNoCopyIfPresent(atIndex index: Int) throws -> Data? {
try impl.fastDecodeDataNoCopyIfPresent(atUncheckedIndex: _checkedIndex(index))
_checkIndex(index)
return try impl.fastDecodeDataNoCopyIfPresent(atUncheckedIndex: index)
}

/// Returns the Data at given index.
Expand All @@ -913,7 +925,8 @@ extension Row {
/// The returned data does not owns its bytes: it must not be used longer
/// than the row's lifetime.
func decodeDataNoCopy(atIndex index: Int) throws -> Data {
try impl.fastDecodeDataNoCopy(atUncheckedIndex: _checkedIndex(index))
_checkIndex(index)
return try impl.fastDecodeDataNoCopy(atUncheckedIndex: index)
}

/// Returns the optional Data at given column.
Expand Down Expand Up @@ -1657,7 +1670,8 @@ extension Row {

/// Accesses the (ColumnName, DatabaseValue) pair at given index.
public subscript(position: RowIndex) -> (String, DatabaseValue) {
let index = _checkedIndex(position.index)
let index = position.index
_checkIndex(index)
return (
impl.columnName(atUncheckedIndex: index),
impl.databaseValue(atUncheckedIndex: index))
Expand Down
30 changes: 20 additions & 10 deletions GRDB/Core/StatementColumnConvertible.swift
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,21 @@ public protocol StatementColumnConvertible {
// MARK: - Conversions

extension DatabaseValueConvertible where Self: StatementColumnConvertible {
@usableFromInline
/* private */ static func _valueMismatch(
fromStatement sqliteStatement: SQLiteStatement,
atUncheckedIndex index: Int32,
context: @autoclosure () -> RowDecodingContext)
throws -> Never
{
throw RowDecodingError.valueMismatch(
Self.self,
sqliteStatement: sqliteStatement,
index: index,
context: context())
}

@inline(__always)
@inlinable
static func fastDecode(
fromStatement sqliteStatement: SQLiteStatement,
Expand All @@ -55,15 +70,12 @@ extension DatabaseValueConvertible where Self: StatementColumnConvertible {
guard sqlite3_column_type(sqliteStatement, index) != SQLITE_NULL,
let value = self.init(sqliteStatement: sqliteStatement, index: index)
else {
throw RowDecodingError.valueMismatch(
Self.self,
sqliteStatement: sqliteStatement,
index: index,
context: context())
try _valueMismatch(fromStatement: sqliteStatement, atUncheckedIndex: index, context: context())
}
return value
}

@inline(__always)
@inlinable
static func fastDecode(
fromRow row: Row,
Expand All @@ -80,6 +92,7 @@ extension DatabaseValueConvertible where Self: StatementColumnConvertible {
return try row.fastDecode(Self.self, atUncheckedIndex: index)
}

@inline(__always)
@inlinable
static func fastDecodeIfPresent(
fromStatement sqliteStatement: SQLiteStatement,
Expand All @@ -91,15 +104,12 @@ extension DatabaseValueConvertible where Self: StatementColumnConvertible {
return nil
}
guard let value = self.init(sqliteStatement: sqliteStatement, index: index) else {
throw RowDecodingError.valueMismatch(
Self.self,
sqliteStatement: sqliteStatement,
index: index,
context: context())
try _valueMismatch(fromStatement: sqliteStatement, atUncheckedIndex: index, context: context())
}
return value
}

@inline(__always)
@inlinable
static func fastDecodeIfPresent(
fromRow row: Row,
Expand Down
2 changes: 2 additions & 0 deletions GRDB/Core/Support/Foundation/DatabaseDateComponents.swift
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ public struct DatabaseDateComponents: DatabaseValueConvertible, StatementColumnC
/// - parameters:
/// - sqliteStatement: A pointer to an SQLite statement.
/// - index: The column index.
@inline(__always)
@inlinable
public init?(sqliteStatement: SQLiteStatement, index: Int32) {
guard let cString = sqlite3_column_text(sqliteStatement, index) else {
return nil
Expand Down
3 changes: 3 additions & 0 deletions GRDB/Core/Support/Foundation/Date.swift
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ extension Date: DatabaseValueConvertible {
return nil
}

@usableFromInline
init?(databaseDateComponents: DatabaseDateComponents) {
guard databaseDateComponents.format.hasYMDComponents else {
// Refuse to turn hours without any date information into Date:
Expand Down Expand Up @@ -117,6 +118,8 @@ extension Date: StatementColumnConvertible {
/// - parameters:
/// - sqliteStatement: A pointer to an SQLite statement.
/// - index: The column index.
@inline(__always)
@inlinable
public init?(sqliteStatement: SQLiteStatement, index: Int32) {
switch sqlite3_column_type(sqliteStatement, index) {
case SQLITE_INTEGER, SQLITE_FLOAT:
Expand Down
9 changes: 6 additions & 3 deletions GRDB/Core/Support/Foundation/Decimal.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ extension Decimal: DatabaseValueConvertible {
return self.init(double)
case let .string(string):
// Must match NSNumber.fromDatabaseValue(_:)
return self.init(string: string, locale: posixLocale)
return self.init(string: string, locale: _posixLocale)
default:
return nil
}
Expand All @@ -26,6 +26,8 @@ extension Decimal: DatabaseValueConvertible {

/// Decimal adopts StatementColumnConvertible
extension Decimal: StatementColumnConvertible {
@inline(__always)
@inlinable
public init?(sqliteStatement: SQLiteStatement, index: Int32) {
switch sqlite3_column_type(sqliteStatement, index) {
case SQLITE_INTEGER:
Expand All @@ -35,12 +37,13 @@ extension Decimal: StatementColumnConvertible {
case SQLITE_TEXT:
self.init(
string: String(cString: sqlite3_column_text(sqliteStatement, index)!),
locale: posixLocale)
locale: _posixLocale)
default:
return nil
}
}
}

private let posixLocale = Locale(identifier: "en_US_POSIX")
@usableFromInline
let _posixLocale = Locale(identifier: "en_US_POSIX")
#endif
Loading

0 comments on commit 1acf8e4

Please sign in to comment.