stephencelis / SQLite.swift

A type-safe, Swift-language layer over SQLite3.
MIT License
9.64k stars 1.56k forks source link

createFunction not working with functions with 3 or 4 arguments #1010

Open alanhaw opened 4 years ago

alanhaw commented 4 years ago

sqlite.swift version: 0.11.6 - from ChangeLog.md, 0.12.2 from info.plist bundle version (downloaded Feb 20/2020) XCode version: 11.3.1 (11C504) macOS 10.14.6 sqlite.swift was integrated with the project manually

With the following code:

    func distance(num1: Int) -> Int {
        return 1
    }
    func distance(num1: Int, den1: Int) -> Int {
        return 2
    }
    func distance(num1: Int, den1: Int, num3: Int) -> Int {
        return 3
    }
            let test1: (Expression<Int>) -> Expression<Int> = (
                try db3!.createFunction("test1", deterministic: true) { anumer in
                    return self.distance(num1: anumer )
                }
            )
            let test2: (Expression<Int>, Expression<Int>) -> Expression<Int> = (
                try db3!.createFunction("test2", deterministic: true) { anumer, adenom in
                    return self.distance(num1: anumer, den1: adenom )
                }
            )
            let test3: (Expression<Int>, Expression<Int>, Expression<Int>) -> Expression<Int> = (
                try db3!.createFunction("test3", deterministic: true) { anumer, adenom, anum3 in
                    return self.distance(num1: anumer, den1: adenom, num3: anum3 )
                }
            )

The code compiles except that the definition of test3 reports an error at the beginning of "{ anumer". It seems to be that createFunction works with 1 or 2 parameters, but not with 3 (nor 4, I've tried). The error is: "Contextual type for closure argument list expects 1 argument, which cannot be implicitly ignored".

When I observe the expression lookup as I type in "db3.createFunction" it looks like there are an awful lot of typed definitions of createFunction. I am wondering if the multiple definitions are confusing the compiler, giving the error. This may be specific to certain XCode versions [speculation].

This has been questioned on stackoverflow awhile back: https://stackoverflow.com/questions/57383494/how-to-properly-define-closure-for-custom-function-in-sqlite

And to add an example with 4 parameters:

let dbdistance: (Expression<Int>, Expression<Int>, Expression<Int>, Expression<Int>) -> Expression<Int> = (
                try db3!.createFunction("dbdistance", argumentCount: UInt(4), deterministic: true) {num1, den1, num2, den2 in
                    return distance(num1: num1, den1: den1, num2: num2, den2: den2)
                }
            )

This returns a compile error of: "Contextual closure type '([Binding?]) -> Binding?' expects 1 argument, but 4 were used in closure body"

stuart312 commented 3 years ago

Hi @alanhaw, did you figure out a workaround or solution to this problem? I'm stuck with the same need for a 4-argument function and I don't really want to use the un-type-safe way

alanhaw commented 3 years ago

In the circumstances I was in, I needed 4 arguments but they were related. So I re-wrote my code to group the arguments as pairs, and thus passed only 2 arguments into createFunction. But this is not a general solution.

On Oct 27, 2020, at 12:13 PM, stuart312 notifications@github.com wrote:

Hi @alanhaw https://github.com/alanhaw, did you figure out a workaround or solution to this problem? I'm stuck with the same need for a 4-argument function and I don't really want to use the un-type-safe way

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/stephencelis/SQLite.swift/issues/1010#issuecomment-717429104, or unsubscribe https://github.com/notifications/unsubscribe-auth/AENSVQZOPDVEHMSATPZIJYTSM4ETNANCNFSM4OKUQXAA.

jberkel commented 3 years ago

looks like a needless limitation, could easily add more arguments