Skip to content
This repository was archived by the owner on Oct 10, 2025. It is now read-only.

Conversation

@hiimtmac
Copy link

Hello! Thank you for this project, Kuzu is great.

I'm not sure if I was "holding it wrong" but it seems the existing execute

public func execute<T>(
    _ preparedStatement: PreparedStatement,
    _ parameters: [String: T?]
) throws -> QueryResult { ... }

Is limiting in that T can only be one type, so I havent found a way to nicely bind arguments of heterogeneous types. For example:

let result = try conn.execute(stmt, ["a": Int64(1), "b": "1"]) // Conflicting arguments to generic parameter 'T' ('Int64' vs. 'String')

I added some functionality (guarded for now under @_spi(Typed)) for encoding and decoding types, which allows for encoding/decoding on linux to follow the same paths as the Darwin platforms (no need for the wrapper types). You can see usage in the TypedTests.swift test file.

If this is something of interest to the maintainers Im happy to adjust as needed to your liking!

@mewim
Copy link
Contributor

mewim commented Sep 26, 2025

Hi @hiimtmac,

Thanks for your interest in kuzu-swift.

There is actually a way to use mixed parameter types even in the current version:

    func testMixedTypeParam() throws {
        let params: [String: Any] = [
            "1": "One",
            "2": KuzuInt64Wrapper(value: 2),
        ]
        let preparedStatement = try conn.prepare("RETURN $1, $2")
        let result = try conn.execute(preparedStatement, params)
        XCTAssert(result.hasNext())
        let row = try result.getNext()!
        XCTAssertEqual(try! row.getValue(0) as! String, "One")
        XCTAssertEqual(try! row.getValue(1) as! Int64, 2)
    }

However, I do agree that your approach of allowing primitive types is more erganomic and intuitive. I am a bit concerned about the compatibility though due to the use of upcoming feature and bumping min version to 6.0

@hiimtmac
Copy link
Author

Happy to bump it back down to 5.9 (not using any specific features from 6.0 and anything I did builds fine with 5.9 - just figured with 6.2 released may as well). I can also remove the .enableUpcomingFeature("ExistentialAny") if you'd prefer, AFAICT all it does is force you to write any when using a protocol as existential (ie let t: any KuzuDecodable vs let t: KuzuDecodable)

@mewim mewim requested a review from Copilot September 26, 2025 20:02
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR introduces a typed encoding/decoding system to reduce usage of "Any" types in the kuzu-swift library, enabling heterogeneous parameter binding in prepared statements. The changes allow users to pass parameters of different types in the same dictionary without generic type constraints.

Key changes:

  • Adds @_spi(Typed) protocols KuzuEncodable and KuzuDecodable for type-safe value conversion
  • Introduces a new execute_ method that accepts [String: any KuzuEncodable] parameters
  • Includes comprehensive type system support for primitives, collections, and complex Kuzu types

Reviewed Changes

Copilot reviewed 15 out of 15 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
Tests/kuzu-swiftTests/TypedTests.swift Test suite demonstrating typed parameter binding and value extraction
Sources/Kuzu/KuzuEncodable.swift Encoding protocols and implementations for Swift types to Kuzu values
Sources/Kuzu/KuzuDecodable.swift Decoding protocols and implementations for Kuzu values to Swift types
Sources/Kuzu/Types+Extensions.swift Core type definitions and data type mappings
Sources/Kuzu/Connection+Extensions.swift New execute_ method using typed parameters
Sources/Kuzu/FlatTuple+Extensions.swift Typed subscript accessors for result tuples
Package.swift Swift 6.0 upgrade and ExistentialAny feature enablement
Multiple source files Import visibility changes from @_implementationOnly to public

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

Comment on lines +512 to +513
let blobSize = strlen(cBlobValue)
let blobData = Data(bytes: cBlobValue, count: blobSize)
Copy link

Copilot AI Sep 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using strlen on binary data is incorrect as it will stop at the first null byte. Use the actual blob size from the Kuzu API instead.

Suggested change
let blobSize = strlen(cBlobValue)
let blobData = Data(bytes: cBlobValue, count: blobSize)
let blobSize = kuzu_value_get_blob_size(container.ptr)
let blobData = Data(bytes: cBlobValue, count: Int(blobSize))

Copilot uses AI. Check for mistakes.
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That function doesn't exist

@hiimtmac
Copy link
Author

@mewim I reverted the Package.swift changes and address the copilot review 👍

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants