Skip to content

Commit 19fd8a5

Browse files
committed
WIP
Simplify
1 parent 2ae7b9b commit 19fd8a5

File tree

4 files changed

+141
-150
lines changed

4 files changed

+141
-150
lines changed

.swiftlint.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,5 +38,5 @@ line_length:
3838
ignores_comments: true
3939

4040
file_length:
41-
warning: 900
42-
error: 900
41+
warning: 800
42+
error: 800

SQLite.xcodeproj/project.pbxproj

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
03A65E971C6BB3210062603F /* libsqlite3.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 03A65E961C6BB3210062603F /* libsqlite3.tbd */; };
5151
19A17073552293CA063BEA66 /* Result.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17E723300E5ED3771DCB5 /* Result.swift */; };
5252
19A1709C3E7A406E62293B2A /* Fixtures.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17B93B48B5560E6E51791 /* Fixtures.swift */; };
53+
19A170ACC97B19730FB7BA4D /* Connection+Aggregation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A175A9CB446640AE6F2200 /* Connection+Aggregation.swift */; };
5354
19A17152E32A9585831E3FE0 /* DateAndTimeFunctions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17BA55DABB480F9020C8A /* DateAndTimeFunctions.swift */; };
5455
19A1717B10CC941ACB5533D6 /* FTS5.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1730E4390C775C25677D1 /* FTS5.swift */; };
5556
19A171967CC511C4F6F773C9 /* RowTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A175C1F9CB3BBAB8FCEC7B /* RowTests.swift */; };
@@ -67,6 +68,7 @@
6768
19A174D78559CD30679BCCCB /* FTS5Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1721B8984686B9963B45D /* FTS5Tests.swift */; };
6869
19A1750CEE9B05267995CF3D /* FTS5.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1730E4390C775C25677D1 /* FTS5.swift */; };
6970
19A175DFF47B84757E547C62 /* fixtures in Resources */ = {isa = PBXBuildFile; fileRef = 19A17E2695737FAB5D6086E3 /* fixtures */; };
71+
19A176376CB6A94759F7980A /* Connection+Aggregation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A175A9CB446640AE6F2200 /* Connection+Aggregation.swift */; };
7072
19A176406BDE9D9C80CC9FA3 /* QueryIntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17BA6B4E282C1315A115C /* QueryIntegrationTests.swift */; };
7173
19A1769C1F3A7542BECF50FF /* DateAndTimeFunctionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1729B75C33F9A0B9A89C1 /* DateAndTimeFunctionTests.swift */; };
7274
19A177CC33F2E6A24AF90B02 /* CipherTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17399EA9E61235D5D77BF /* CipherTests.swift */; };
@@ -75,6 +77,7 @@
7577
19A1785195182AF8731A8BDA /* RowTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A175C1F9CB3BBAB8FCEC7B /* RowTests.swift */; };
7678
19A1792C0520D4E83C2EB075 /* Errors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A1710E73A46D5AC721CDA9 /* Errors.swift */; };
7779
19A179A0C45377CB09BB358C /* CipherTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17399EA9E61235D5D77BF /* CipherTests.swift */; };
80+
19A179B59450FE7C4811AB8A /* Connection+Aggregation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A175A9CB446640AE6F2200 /* Connection+Aggregation.swift */; };
7881
19A179CCF9671E345E5A9811 /* Cipher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A178A39ACA9667A62663CC /* Cipher.swift */; };
7982
19A179E76EA6207669B60C1B /* Cipher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A178A39ACA9667A62663CC /* Cipher.swift */; };
8083
19A17C4B951CB054EE48AB1C /* CipherTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A17399EA9E61235D5D77BF /* CipherTests.swift */; };
@@ -237,6 +240,7 @@
237240
19A1729B75C33F9A0B9A89C1 /* DateAndTimeFunctionTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DateAndTimeFunctionTests.swift; sourceTree = "<group>"; };
238241
19A1730E4390C775C25677D1 /* FTS5.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FTS5.swift; sourceTree = "<group>"; };
239242
19A17399EA9E61235D5D77BF /* CipherTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CipherTests.swift; sourceTree = "<group>"; };
243+
19A175A9CB446640AE6F2200 /* Connection+Aggregation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Connection+Aggregation.swift"; sourceTree = "<group>"; };
240244
19A175C1F9CB3BBAB8FCEC7B /* RowTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RowTests.swift; sourceTree = "<group>"; };
241245
19A178A39ACA9667A62663CC /* Cipher.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Cipher.swift; sourceTree = "<group>"; };
242246
19A1794B7972D14330A65BBD /* Linux.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = Linux.md; sourceTree = "<group>"; };
@@ -462,6 +466,7 @@
462466
19A1710E73A46D5AC721CDA9 /* Errors.swift */,
463467
02A43A9722738CF100FEC494 /* Backup.swift */,
464468
19A17E723300E5ED3771DCB5 /* Result.swift */,
469+
19A175A9CB446640AE6F2200 /* Connection+Aggregation.swift */,
465470
);
466471
path = Core;
467472
sourceTree = "<group>";
@@ -850,6 +855,7 @@
850855
19A17FF4A10B44D3937C8CAC /* Errors.swift in Sources */,
851856
19A1737286A74F3CF7412906 /* DateAndTimeFunctions.swift in Sources */,
852857
19A17073552293CA063BEA66 /* Result.swift in Sources */,
858+
19A179B59450FE7C4811AB8A /* Connection+Aggregation.swift in Sources */,
853859
);
854860
runOnlyForDeploymentPostprocessing = 0;
855861
};
@@ -945,6 +951,7 @@
945951
19A1792C0520D4E83C2EB075 /* Errors.swift in Sources */,
946952
19A17E29278A12BC4F542506 /* DateAndTimeFunctions.swift in Sources */,
947953
19A173EFEF0B3BD0B3ED406C /* Result.swift in Sources */,
954+
19A176376CB6A94759F7980A /* Connection+Aggregation.swift in Sources */,
948955
);
949956
runOnlyForDeploymentPostprocessing = 0;
950957
};
@@ -1008,6 +1015,7 @@
10081015
19A17490543609FCED53CACC /* Errors.swift in Sources */,
10091016
19A17152E32A9585831E3FE0 /* DateAndTimeFunctions.swift in Sources */,
10101017
19A17F1B3F0A3C96B5ED6D64 /* Result.swift in Sources */,
1018+
19A170ACC97B19730FB7BA4D /* Connection+Aggregation.swift in Sources */,
10111019
);
10121020
runOnlyForDeploymentPostprocessing = 0;
10131021
};
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
import Foundation
2+
#if SQLITE_SWIFT_STANDALONE
3+
import sqlite3
4+
#elseif SQLITE_SWIFT_SQLCIPHER
5+
import SQLCipher
6+
#elseif os(Linux)
7+
import CSQLite
8+
#else
9+
import SQLite3
10+
#endif
11+
12+
extension Connection {
13+
typealias Aggregate = @convention(block) (Int, OpaquePointer?, Int32, UnsafeMutablePointer<OpaquePointer?>?) -> Void
14+
15+
/// Creates or redefines a custom SQL aggregate.
16+
///
17+
/// - Parameters:
18+
///
19+
/// - aggregate: The name of the aggregate to create or redefine.
20+
///
21+
/// - argumentCount: The number of arguments that the aggregate takes. If
22+
/// `nil`, the aggregate may take any number of arguments.
23+
///
24+
/// Default: `nil`
25+
///
26+
/// - deterministic: Whether or not the aggregate is deterministic (_i.e._
27+
/// the aggregate always returns the same result for a given input).
28+
///
29+
/// Default: `false`
30+
///
31+
/// - step: A block of code to run for each row of an aggregation group.
32+
/// The block is called with an array of raw SQL values mapped to the
33+
/// aggregate’s parameters, and an UnsafeMutablePointer to a state
34+
/// variable.
35+
///
36+
/// - final: A block of code to run after each row of an aggregation group
37+
/// is processed. The block is called with an UnsafeMutablePointer to a
38+
/// state variable, and should return a raw SQL value (or nil).
39+
///
40+
/// - state: A block of code to run to produce a fresh state variable for
41+
/// each aggregation group. The block should return an
42+
/// UnsafeMutablePointer to the fresh state variable.
43+
public func createAggregation<T>(
44+
_ aggregate: String,
45+
argumentCount: UInt? = nil,
46+
deterministic: Bool = false,
47+
step: @escaping ([Binding?], UnsafeMutablePointer<T>) -> Void,
48+
final: @escaping (UnsafeMutablePointer<T>) -> Binding?,
49+
state: @escaping () -> UnsafeMutablePointer<T>) {
50+
51+
let argc = argumentCount.map { Int($0) } ?? -1
52+
let box: Aggregate = { (stepFlag: Int, context: OpaquePointer?, argc: Int32, argv: UnsafeMutablePointer<OpaquePointer?>?) in
53+
let ptr = sqlite3_aggregate_context(context, 64)! // needs to be at least as large as uintptr_t; better way to do this?
54+
let mutablePointer = ptr.assumingMemoryBound(to: UnsafeMutableRawPointer.self)
55+
if stepFlag > 0 {
56+
let arguments = getArguments(argc: argc, argv: argv)
57+
if ptr.assumingMemoryBound(to: Int64.self).pointee == 0 {
58+
let value = state()
59+
mutablePointer.pointee = UnsafeMutableRawPointer(mutating: value)
60+
}
61+
step(arguments, mutablePointer.pointee.assumingMemoryBound(to: T.self))
62+
} else {
63+
let result = final(mutablePointer.pointee.assumingMemoryBound(to: T.self))
64+
set(result: result, on: context)
65+
}
66+
}
67+
68+
var flags = SQLITE_UTF8
69+
if deterministic {
70+
flags |= SQLITE_DETERMINISTIC
71+
}
72+
73+
sqlite3_create_function_v2(
74+
handle,
75+
aggregate,
76+
Int32(argc),
77+
flags,
78+
unsafeBitCast(box, to: UnsafeMutableRawPointer.self),
79+
nil, { context, argc, value in
80+
let function = unsafeBitCast(sqlite3_user_data(context), to: Aggregate.self)
81+
function(1, context, argc, value)
82+
}, { context in
83+
let function = unsafeBitCast(sqlite3_user_data(context), to: Aggregate.self)
84+
function(0, context, 0, nil)
85+
},
86+
nil
87+
)
88+
if aggregations[aggregate] == nil {
89+
aggregations[aggregate] = [:]
90+
}
91+
aggregations[aggregate]?[argc] = box
92+
}
93+
}

0 commit comments

Comments
 (0)