diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 52d18de..50441b3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,9 +16,20 @@ jobs: runs-on: macos-26 steps: - uses: actions/checkout@v4 - - name: Select Xcode 26.2 - run: sudo xcode-select -s /Applications/Xcode_26.2.app + - name: Select Xcode 26.4 + run: sudo xcode-select -s /Applications/Xcode_26.4.app - name: Run Tests run: swift test - - name: Build Release - run: swift build --configuration release + + linux: + name: Linux + runs-on: ubuntu-latest + container: swift:6.3 + steps: + - uses: actions/checkout@v4 + - name: "Install SQLite" + run: | + apt-get update + apt-get install -y libsqlite3-dev + - name: "Test Swift Package on Linux" + run: swift test diff --git a/Package.resolved b/Package.resolved index 07bdfd1..ce09242 100644 --- a/Package.resolved +++ b/Package.resolved @@ -1,5 +1,5 @@ { - "originHash" : "c6de1475225d93b5b272c602b69005d8951d97e0f955a969df9e5ecfad8de568", + "originHash" : "98cfbae412a5b4e4acf4749db0d30da83e98f22d37e0cea291a2fd1c0cfbca8a", "pins" : [ { "identity" : "combine-schedulers", @@ -15,8 +15,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/groue/GRDB.swift", "state" : { - "revision" : "18497b68fdbb3a09528d260a0a0e1e7e61c8c53d", - "version" : "7.8.0" + "revision" : "36e30a6f1ef10e4194f6af0cff90888526f0c115", + "version" : "7.10.0" } }, { @@ -24,8 +24,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/pointfreeco/sqlite-data", "state" : { - "revision" : "b66b894b9a5710f1072c8eb6448a7edfc2d743d9", - "version" : "1.3.0" + "revision" : "da3a94ed49c7a30d82853de551c07a93196e8cab", + "version" : "1.6.1" } }, { @@ -132,8 +132,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/pointfreeco/swift-structured-queries", "state" : { - "revision" : "b78cf04628173839fb04993c1d650ce9056bcb30", - "version" : "0.25.1" + "revision" : "8da8818fccd9959bd683934ddc62cf45bb65b3c8", + "version" : "0.31.1" } }, { diff --git a/Package.swift b/Package.swift index 54c4f69..0b877d1 100644 --- a/Package.swift +++ b/Package.swift @@ -14,12 +14,12 @@ let package = Package( .package(url: "https://github.com/pointfreeco/swift-tagged", from: "0.10.0"), .package( url: "https://github.com/pointfreeco/sqlite-data", - from: "1.3.0", + from: "1.6.1", traits: ["SQLiteDataTagged"] ), .package( url: "https://github.com/pointfreeco/swift-structured-queries", - from: "0.25.1", + from: "0.31.1", traits: ["StructuredQueriesTagged"] ), .package(url: "https://github.com/pointfreeco/xctest-dynamic-overlay", from: "1.4.3") diff --git a/Sources/SQLiteVecData/Database+LoadSQLiteVec.swift b/Sources/SQLiteVecData/Database+LoadSQLiteVec.swift index 3463aa2..fffb33b 100644 --- a/Sources/SQLiteVecData/Database+LoadSQLiteVec.swift +++ b/Sources/SQLiteVecData/Database+LoadSQLiteVec.swift @@ -1,6 +1,5 @@ import CSQLiteVec import GRDB -import SQLite3 extension Database { /// Loads the sqlite-vec extension into the current database connection. diff --git a/Sources/StructuredQueriesSQLiteVecCore/EmbeddingVector.swift b/Sources/StructuredQueriesSQLiteVecCore/EmbeddingVector.swift index 67a3251..b6b9b97 100644 --- a/Sources/StructuredQueriesSQLiteVecCore/EmbeddingVector.swift +++ b/Sources/StructuredQueriesSQLiteVecCore/EmbeddingVector.swift @@ -90,7 +90,7 @@ import StructuredQueriesCore rhs.array.span.withUnsafeBytes { rhsPtr in let size = Self.count * MemoryLayout.stride return lhsPtr.baseAddress == rhsPtr.baseAddress - || memcmp(lhsPtr.baseAddress, rhsPtr.baseAddress, size) == 0 + || memcmp(lhsPtr.baseAddress!, rhsPtr.baseAddress!, size) == 0 } } } diff --git a/Tests/SQLiteVecDataTests/Vec0QueryTests.swift b/Tests/SQLiteVecDataTests/Vec0QueryTests.swift index c8280f0..b283bb2 100644 --- a/Tests/SQLiteVecDataTests/Vec0QueryTests.swift +++ b/Tests/SQLiteVecDataTests/Vec0QueryTests.swift @@ -51,103 +51,103 @@ struct Vec0QueryTests { """ SELECT "Embeddings"."embedding", "Embeddings"."label" FROM "Embeddings" - WHERE ("Embeddings"."embedding" MATCH '���=��L>���>') + WHERE (("Embeddings"."embedding" MATCH '���=��L>���>')) ORDER BY "Embeddings"."distance" LIMIT 10 """ } results: { """ - ┌───────────────────┐ - │ Embedding( │ - │ embedding: [ │ - │ [0]: 0.0, │ - │ [1]: 1.0, │ - │ [2]: 2.0 │ - │ ], │ - │ label: "item-0" │ - │ ) │ - ├───────────────────┤ - │ Embedding( │ - │ embedding: [ │ - │ [0]: 1.0, │ - │ [1]: 2.0, │ - │ [2]: 3.0 │ - │ ], │ - │ label: "item-1" │ - │ ) │ - ├───────────────────┤ - │ Embedding( │ - │ embedding: [ │ - │ [0]: 2.0, │ - │ [1]: 3.0, │ - │ [2]: 4.0 │ - │ ], │ - │ label: "item-2" │ - │ ) │ - ├───────────────────┤ - │ Embedding( │ - │ embedding: [ │ - │ [0]: 3.0, │ - │ [1]: 4.0, │ - │ [2]: 5.0 │ - │ ], │ - │ label: "item-3" │ - │ ) │ - ├───────────────────┤ - │ Embedding( │ - │ embedding: [ │ - │ [0]: 4.0, │ - │ [1]: 5.0, │ - │ [2]: 6.0 │ - │ ], │ - │ label: "item-4" │ - │ ) │ - ├───────────────────┤ - │ Embedding( │ - │ embedding: [ │ - │ [0]: 5.0, │ - │ [1]: 6.0, │ - │ [2]: 7.0 │ - │ ], │ - │ label: "item-5" │ - │ ) │ - ├───────────────────┤ - │ Embedding( │ - │ embedding: [ │ - │ [0]: 6.0, │ - │ [1]: 7.0, │ - │ [2]: 8.0 │ - │ ], │ - │ label: "item-6" │ - │ ) │ - ├───────────────────┤ - │ Embedding( │ - │ embedding: [ │ - │ [0]: 7.0, │ - │ [1]: 8.0, │ - │ [2]: 9.0 │ - │ ], │ - │ label: "item-7" │ - │ ) │ - ├───────────────────┤ - │ Embedding( │ - │ embedding: [ │ - │ [0]: 8.0, │ - │ [1]: 9.0, │ - │ [2]: 10.0 │ - │ ], │ - │ label: "item-8" │ - │ ) │ - ├───────────────────┤ - │ Embedding( │ - │ embedding: [ │ - │ [0]: 9.0, │ - │ [1]: 10.0, │ - │ [2]: 11.0 │ - │ ], │ - │ label: "item-9" │ - │ ) │ - └───────────────────┘ + ┌─────────────────────┐ + │ Embedding( │ + │ embedding: [ │ + │ [0]: 0.0, │ + │ [1]: 1.0, │ + │ [2]: 2.0 │ + │ ], │ + │ label: "item-0.0" │ + │ ) │ + ├─────────────────────┤ + │ Embedding( │ + │ embedding: [ │ + │ [0]: 1.0, │ + │ [1]: 2.0, │ + │ [2]: 3.0 │ + │ ], │ + │ label: "item-1.0" │ + │ ) │ + ├─────────────────────┤ + │ Embedding( │ + │ embedding: [ │ + │ [0]: 2.0, │ + │ [1]: 3.0, │ + │ [2]: 4.0 │ + │ ], │ + │ label: "item-2.0" │ + │ ) │ + ├─────────────────────┤ + │ Embedding( │ + │ embedding: [ │ + │ [0]: 3.0, │ + │ [1]: 4.0, │ + │ [2]: 5.0 │ + │ ], │ + │ label: "item-3.0" │ + │ ) │ + ├─────────────────────┤ + │ Embedding( │ + │ embedding: [ │ + │ [0]: 4.0, │ + │ [1]: 5.0, │ + │ [2]: 6.0 │ + │ ], │ + │ label: "item-4.0" │ + │ ) │ + ├─────────────────────┤ + │ Embedding( │ + │ embedding: [ │ + │ [0]: 5.0, │ + │ [1]: 6.0, │ + │ [2]: 7.0 │ + │ ], │ + │ label: "item-5.0" │ + │ ) │ + ├─────────────────────┤ + │ Embedding( │ + │ embedding: [ │ + │ [0]: 6.0, │ + │ [1]: 7.0, │ + │ [2]: 8.0 │ + │ ], │ + │ label: "item-6.0" │ + │ ) │ + ├─────────────────────┤ + │ Embedding( │ + │ embedding: [ │ + │ [0]: 7.0, │ + │ [1]: 8.0, │ + │ [2]: 9.0 │ + │ ], │ + │ label: "item-7.0" │ + │ ) │ + ├─────────────────────┤ + │ Embedding( │ + │ embedding: [ │ + │ [0]: 8.0, │ + │ [1]: 9.0, │ + │ [2]: 10.0 │ + │ ], │ + │ label: "item-8.0" │ + │ ) │ + ├─────────────────────┤ + │ Embedding( │ + │ embedding: [ │ + │ [0]: 9.0, │ + │ [1]: 10.0, │ + │ [2]: 11.0 │ + │ ], │ + │ label: "item-9.0" │ + │ ) │ + └─────────────────────┘ """ } } @@ -169,237 +169,237 @@ struct Vec0QueryTests { """ SELECT "Embeddings"."embedding", "Embeddings"."label" FROM "Embeddings" - WHERE ("Embeddings"."embedding" MATCH '���=��L>���>') AND ("Embeddings"."k") = (25) + WHERE (("Embeddings"."embedding" MATCH '���=��L>���>')) AND (("Embeddings"."k") = (25)) ORDER BY "Embeddings"."distance" """ } results: { """ - ┌────────────────────┐ - │ Embedding( │ - │ embedding: [ │ - │ [0]: 0.0, │ - │ [1]: 1.0, │ - │ [2]: 2.0 │ - │ ], │ - │ label: "item-0" │ - │ ) │ - ├────────────────────┤ - │ Embedding( │ - │ embedding: [ │ - │ [0]: 1.0, │ - │ [1]: 2.0, │ - │ [2]: 3.0 │ - │ ], │ - │ label: "item-1" │ - │ ) │ - ├────────────────────┤ - │ Embedding( │ - │ embedding: [ │ - │ [0]: 2.0, │ - │ [1]: 3.0, │ - │ [2]: 4.0 │ - │ ], │ - │ label: "item-2" │ - │ ) │ - ├────────────────────┤ - │ Embedding( │ - │ embedding: [ │ - │ [0]: 3.0, │ - │ [1]: 4.0, │ - │ [2]: 5.0 │ - │ ], │ - │ label: "item-3" │ - │ ) │ - ├────────────────────┤ - │ Embedding( │ - │ embedding: [ │ - │ [0]: 4.0, │ - │ [1]: 5.0, │ - │ [2]: 6.0 │ - │ ], │ - │ label: "item-4" │ - │ ) │ - ├────────────────────┤ - │ Embedding( │ - │ embedding: [ │ - │ [0]: 5.0, │ - │ [1]: 6.0, │ - │ [2]: 7.0 │ - │ ], │ - │ label: "item-5" │ - │ ) │ - ├────────────────────┤ - │ Embedding( │ - │ embedding: [ │ - │ [0]: 6.0, │ - │ [1]: 7.0, │ - │ [2]: 8.0 │ - │ ], │ - │ label: "item-6" │ - │ ) │ - ├────────────────────┤ - │ Embedding( │ - │ embedding: [ │ - │ [0]: 7.0, │ - │ [1]: 8.0, │ - │ [2]: 9.0 │ - │ ], │ - │ label: "item-7" │ - │ ) │ - ├────────────────────┤ - │ Embedding( │ - │ embedding: [ │ - │ [0]: 8.0, │ - │ [1]: 9.0, │ - │ [2]: 10.0 │ - │ ], │ - │ label: "item-8" │ - │ ) │ - ├────────────────────┤ - │ Embedding( │ - │ embedding: [ │ - │ [0]: 9.0, │ - │ [1]: 10.0, │ - │ [2]: 11.0 │ - │ ], │ - │ label: "item-9" │ - │ ) │ - ├────────────────────┤ - │ Embedding( │ - │ embedding: [ │ - │ [0]: 10.0, │ - │ [1]: 11.0, │ - │ [2]: 12.0 │ - │ ], │ - │ label: "item-10" │ - │ ) │ - ├────────────────────┤ - │ Embedding( │ - │ embedding: [ │ - │ [0]: 11.0, │ - │ [1]: 12.0, │ - │ [2]: 13.0 │ - │ ], │ - │ label: "item-11" │ - │ ) │ - ├────────────────────┤ - │ Embedding( │ - │ embedding: [ │ - │ [0]: 12.0, │ - │ [1]: 13.0, │ - │ [2]: 14.0 │ - │ ], │ - │ label: "item-12" │ - │ ) │ - ├────────────────────┤ - │ Embedding( │ - │ embedding: [ │ - │ [0]: 13.0, │ - │ [1]: 14.0, │ - │ [2]: 15.0 │ - │ ], │ - │ label: "item-13" │ - │ ) │ - ├────────────────────┤ - │ Embedding( │ - │ embedding: [ │ - │ [0]: 14.0, │ - │ [1]: 15.0, │ - │ [2]: 16.0 │ - │ ], │ - │ label: "item-14" │ - │ ) │ - ├────────────────────┤ - │ Embedding( │ - │ embedding: [ │ - │ [0]: 15.0, │ - │ [1]: 16.0, │ - │ [2]: 17.0 │ - │ ], │ - │ label: "item-15" │ - │ ) │ - ├────────────────────┤ - │ Embedding( │ - │ embedding: [ │ - │ [0]: 16.0, │ - │ [1]: 17.0, │ - │ [2]: 18.0 │ - │ ], │ - │ label: "item-16" │ - │ ) │ - ├────────────────────┤ - │ Embedding( │ - │ embedding: [ │ - │ [0]: 17.0, │ - │ [1]: 18.0, │ - │ [2]: 19.0 │ - │ ], │ - │ label: "item-17" │ - │ ) │ - ├────────────────────┤ - │ Embedding( │ - │ embedding: [ │ - │ [0]: 18.0, │ - │ [1]: 19.0, │ - │ [2]: 20.0 │ - │ ], │ - │ label: "item-18" │ - │ ) │ - ├────────────────────┤ - │ Embedding( │ - │ embedding: [ │ - │ [0]: 19.0, │ - │ [1]: 20.0, │ - │ [2]: 21.0 │ - │ ], │ - │ label: "item-19" │ - │ ) │ - ├────────────────────┤ - │ Embedding( │ - │ embedding: [ │ - │ [0]: 20.0, │ - │ [1]: 21.0, │ - │ [2]: 22.0 │ - │ ], │ - │ label: "item-20" │ - │ ) │ - ├────────────────────┤ - │ Embedding( │ - │ embedding: [ │ - │ [0]: 21.0, │ - │ [1]: 22.0, │ - │ [2]: 23.0 │ - │ ], │ - │ label: "item-21" │ - │ ) │ - ├────────────────────┤ - │ Embedding( │ - │ embedding: [ │ - │ [0]: 22.0, │ - │ [1]: 23.0, │ - │ [2]: 24.0 │ - │ ], │ - │ label: "item-22" │ - │ ) │ - ├────────────────────┤ - │ Embedding( │ - │ embedding: [ │ - │ [0]: 23.0, │ - │ [1]: 24.0, │ - │ [2]: 25.0 │ - │ ], │ - │ label: "item-23" │ - │ ) │ - ├────────────────────┤ - │ Embedding( │ - │ embedding: [ │ - │ [0]: 24.0, │ - │ [1]: 25.0, │ - │ [2]: 26.0 │ - │ ], │ - │ label: "item-24" │ - │ ) │ - └────────────────────┘ + ┌──────────────────────┐ + │ Embedding( │ + │ embedding: [ │ + │ [0]: 0.0, │ + │ [1]: 1.0, │ + │ [2]: 2.0 │ + │ ], │ + │ label: "item-0.0" │ + │ ) │ + ├──────────────────────┤ + │ Embedding( │ + │ embedding: [ │ + │ [0]: 1.0, │ + │ [1]: 2.0, │ + │ [2]: 3.0 │ + │ ], │ + │ label: "item-1.0" │ + │ ) │ + ├──────────────────────┤ + │ Embedding( │ + │ embedding: [ │ + │ [0]: 2.0, │ + │ [1]: 3.0, │ + │ [2]: 4.0 │ + │ ], │ + │ label: "item-2.0" │ + │ ) │ + ├──────────────────────┤ + │ Embedding( │ + │ embedding: [ │ + │ [0]: 3.0, │ + │ [1]: 4.0, │ + │ [2]: 5.0 │ + │ ], │ + │ label: "item-3.0" │ + │ ) │ + ├──────────────────────┤ + │ Embedding( │ + │ embedding: [ │ + │ [0]: 4.0, │ + │ [1]: 5.0, │ + │ [2]: 6.0 │ + │ ], │ + │ label: "item-4.0" │ + │ ) │ + ├──────────────────────┤ + │ Embedding( │ + │ embedding: [ │ + │ [0]: 5.0, │ + │ [1]: 6.0, │ + │ [2]: 7.0 │ + │ ], │ + │ label: "item-5.0" │ + │ ) │ + ├──────────────────────┤ + │ Embedding( │ + │ embedding: [ │ + │ [0]: 6.0, │ + │ [1]: 7.0, │ + │ [2]: 8.0 │ + │ ], │ + │ label: "item-6.0" │ + │ ) │ + ├──────────────────────┤ + │ Embedding( │ + │ embedding: [ │ + │ [0]: 7.0, │ + │ [1]: 8.0, │ + │ [2]: 9.0 │ + │ ], │ + │ label: "item-7.0" │ + │ ) │ + ├──────────────────────┤ + │ Embedding( │ + │ embedding: [ │ + │ [0]: 8.0, │ + │ [1]: 9.0, │ + │ [2]: 10.0 │ + │ ], │ + │ label: "item-8.0" │ + │ ) │ + ├──────────────────────┤ + │ Embedding( │ + │ embedding: [ │ + │ [0]: 9.0, │ + │ [1]: 10.0, │ + │ [2]: 11.0 │ + │ ], │ + │ label: "item-9.0" │ + │ ) │ + ├──────────────────────┤ + │ Embedding( │ + │ embedding: [ │ + │ [0]: 10.0, │ + │ [1]: 11.0, │ + │ [2]: 12.0 │ + │ ], │ + │ label: "item-10.0" │ + │ ) │ + ├──────────────────────┤ + │ Embedding( │ + │ embedding: [ │ + │ [0]: 11.0, │ + │ [1]: 12.0, │ + │ [2]: 13.0 │ + │ ], │ + │ label: "item-11.0" │ + │ ) │ + ├──────────────────────┤ + │ Embedding( │ + │ embedding: [ │ + │ [0]: 12.0, │ + │ [1]: 13.0, │ + │ [2]: 14.0 │ + │ ], │ + │ label: "item-12.0" │ + │ ) │ + ├──────────────────────┤ + │ Embedding( │ + │ embedding: [ │ + │ [0]: 13.0, │ + │ [1]: 14.0, │ + │ [2]: 15.0 │ + │ ], │ + │ label: "item-13.0" │ + │ ) │ + ├──────────────────────┤ + │ Embedding( │ + │ embedding: [ │ + │ [0]: 14.0, │ + │ [1]: 15.0, │ + │ [2]: 16.0 │ + │ ], │ + │ label: "item-14.0" │ + │ ) │ + ├──────────────────────┤ + │ Embedding( │ + │ embedding: [ │ + │ [0]: 15.0, │ + │ [1]: 16.0, │ + │ [2]: 17.0 │ + │ ], │ + │ label: "item-15.0" │ + │ ) │ + ├──────────────────────┤ + │ Embedding( │ + │ embedding: [ │ + │ [0]: 16.0, │ + │ [1]: 17.0, │ + │ [2]: 18.0 │ + │ ], │ + │ label: "item-16.0" │ + │ ) │ + ├──────────────────────┤ + │ Embedding( │ + │ embedding: [ │ + │ [0]: 17.0, │ + │ [1]: 18.0, │ + │ [2]: 19.0 │ + │ ], │ + │ label: "item-17.0" │ + │ ) │ + ├──────────────────────┤ + │ Embedding( │ + │ embedding: [ │ + │ [0]: 18.0, │ + │ [1]: 19.0, │ + │ [2]: 20.0 │ + │ ], │ + │ label: "item-18.0" │ + │ ) │ + ├──────────────────────┤ + │ Embedding( │ + │ embedding: [ │ + │ [0]: 19.0, │ + │ [1]: 20.0, │ + │ [2]: 21.0 │ + │ ], │ + │ label: "item-19.0" │ + │ ) │ + ├──────────────────────┤ + │ Embedding( │ + │ embedding: [ │ + │ [0]: 20.0, │ + │ [1]: 21.0, │ + │ [2]: 22.0 │ + │ ], │ + │ label: "item-20.0" │ + │ ) │ + ├──────────────────────┤ + │ Embedding( │ + │ embedding: [ │ + │ [0]: 21.0, │ + │ [1]: 22.0, │ + │ [2]: 23.0 │ + │ ], │ + │ label: "item-21.0" │ + │ ) │ + ├──────────────────────┤ + │ Embedding( │ + │ embedding: [ │ + │ [0]: 22.0, │ + │ [1]: 23.0, │ + │ [2]: 24.0 │ + │ ], │ + │ label: "item-22.0" │ + │ ) │ + ├──────────────────────┤ + │ Embedding( │ + │ embedding: [ │ + │ [0]: 23.0, │ + │ [1]: 24.0, │ + │ [2]: 25.0 │ + │ ], │ + │ label: "item-23.0" │ + │ ) │ + ├──────────────────────┤ + │ Embedding( │ + │ embedding: [ │ + │ [0]: 24.0, │ + │ [1]: 25.0, │ + │ [2]: 26.0 │ + │ ], │ + │ label: "item-24.0" │ + │ ) │ + └──────────────────────┘ """ } } @@ -2970,8 +2970,9 @@ struct Vec0QueryTests { let records = (0..<50) .map { index in - Embedding( - embedding: [Float(index), Float(index + 1), Float(index + 2)], + let index = Float(index) + return Embedding( + embedding: [index, index + 1, index + 2], label: "item-\(index)" ) }