@@ -82,22 +82,45 @@ public final class DatabaseFunction: Identifiable, Sendable {
8282 /// such as `Int`, `String`, `Date`, etc. The array is guaranteed to
8383 /// have exactly `argumentCount` elements, provided `argumentCount` is
8484 /// not nil.
85- public init (
85+ public convenience init (
8686 _ name: String ,
8787 argumentCount: Int ? = nil ,
8888 pure: Bool = false ,
8989 function: @escaping @Sendable ( [ DatabaseValue] ) throws -> ( any DatabaseValueConvertible ) ? )
9090 {
91- self . id = ID ( name: name, nArg: argumentCount. map ( CInt . init) ?? - 1 )
92- self . isPure = pure
93- self . kind = . function { ( argc, argv) in
91+ self . init ( name, argumentCount: argumentCount, pure: pure) { ( argc, argv, context) in
9492 let arguments = ( 0 ..< Int ( argc) ) . map { index in
95- DatabaseValue ( sqliteValue: argv. unsafelyUnwrapped [ index] !)
93+ DatabaseValue ( sqliteValue: argv [ index] !)
94+ }
95+ let result = try function ( arguments)
96+ switch result? . databaseValue. storage ?? . null {
97+ case . null:
98+ sqlite3_result_null ( context)
99+ case . int64( let int64) :
100+ sqlite3_result_int64 ( context, int64)
101+ case . double( let double) :
102+ sqlite3_result_double ( context, double)
103+ case . string( let string) :
104+ sqlite3_result_text ( context, string, - 1 , SQLITE_TRANSIENT)
105+ case . blob( let data) :
106+ data. withUnsafeBytes {
107+ sqlite3_result_blob ( context, $0. baseAddress, CInt ( $0. count) , SQLITE_TRANSIENT)
108+ }
96109 }
97- return try function ( arguments)
98110 }
99111 }
100112
113+ init (
114+ _ name: String ,
115+ argumentCount: Int ? = nil ,
116+ pure: Bool = false ,
117+ xFunc: @escaping XFunc )
118+ {
119+ self . id = ID ( name: name, nArg: argumentCount. map ( CInt . init) ?? - 1 )
120+ self . isPure = pure
121+ self . kind = . function( xFunc)
122+ }
123+
101124 /// Creates an SQL aggregate function.
102125 ///
103126 /// For example:
@@ -256,11 +279,10 @@ public final class DatabaseFunction: Identifiable, Sendable {
256279 /// Feeds the `pApp` parameter of sqlite3_create_function_v2
257280 /// <http://sqlite.org/capi3ref.html#sqlite3_create_function>
258281 private class FunctionDefinition {
259- let compute : ( CInt , UnsafeMutablePointer < OpaquePointer ? > ? ) throws -> ( any DatabaseValueConvertible ) ?
260- init ( compute: @escaping ( CInt , UnsafeMutablePointer < OpaquePointer ? > ? )
261- throws -> ( any DatabaseValueConvertible ) ? )
282+ let xFunc : XFunc
283+ init ( xFunc: @escaping XFunc )
262284 {
263- self . compute = compute
285+ self . xFunc = xFunc
264286 }
265287 }
266288
@@ -283,11 +305,19 @@ public final class DatabaseFunction: Identifiable, Sendable {
283305 }
284306 }
285307
308+ /// Feeds the `xFunc` parameter of sqlite3_create_function_v2
309+ /// <http://sqlite.org/capi3ref.html#sqlite3_create_function>
310+ typealias XFunc = @Sendable (
311+ _ argc: CInt ,
312+ _ argv: UnsafeMutablePointer < OpaquePointer ? > ,
313+ _ context: OpaquePointer ?
314+ ) throws -> Void
315+
286316 /// A function kind: an "SQL function" or an "aggregate".
287317 /// See <http://sqlite.org/capi3ref.html#sqlite3_create_function>
288318 private enum Kind : Sendable {
289319 /// A regular function: SELECT f(1)
290- case function( @ Sendable ( CInt , UnsafeMutablePointer < OpaquePointer ? > ? ) throws -> ( any DatabaseValueConvertible ) ? )
320+ case function( XFunc )
291321
292322 /// An aggregate: SELECT f(foo) FROM bar GROUP BY baz
293323 case aggregate( @Sendable ( ) -> any DatabaseAggregate )
@@ -296,8 +326,8 @@ public final class DatabaseFunction: Identifiable, Sendable {
296326 /// <http://sqlite.org/capi3ref.html#sqlite3_create_function>
297327 var definition : AnyObject {
298328 switch self {
299- case . function( let compute ) :
300- return FunctionDefinition ( compute : compute )
329+ case . function( let xFunc ) :
330+ return FunctionDefinition ( xFunc : xFunc )
301331 case . aggregate( let makeAggregate) :
302332 return AggregateDefinition ( makeAggregate: makeAggregate)
303333 }
@@ -312,9 +342,7 @@ public final class DatabaseFunction: Identifiable, Sendable {
312342 . fromOpaque ( sqlite3_user_data ( sqliteContext) )
313343 . takeUnretainedValue ( )
314344 do {
315- try DatabaseFunction . report (
316- result: definition. compute ( argc, argv) ,
317- in: sqliteContext)
345+ try definition. xFunc ( argc, argv. unsafelyUnwrapped, sqliteContext)
318346 } catch {
319347 DatabaseFunction . report ( error: error, in: sqliteContext)
320348 }
0 commit comments