Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,12 @@ jobs:
name: Linux
strategy:
matrix:
swift:
- "6.3"
swift: ["6.1", "6.3"]
runs-on: ubuntu-latest
container: swift:${{ matrix.swift }}
steps:
- uses: actions/checkout@v5
- name: Install SQLite
run: apt update && apt -y install libsqlite3-dev
- name: Build
run: swift build
run: swift build --build-tests
6 changes: 1 addition & 5 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -77,11 +77,7 @@ let package = Package(
dependencies: [
.package(url: "https://github.com/pointfreeco/swift-case-paths", from: "1.8.0"),
.package(url: "https://github.com/pointfreeco/swift-custom-dump", from: "1.3.3"),
.package(
url: "https://github.com/pointfreeco/swift-dependencies",
from: "1.14.0",
traits: ["Foundation"]

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

6.1 can't scope traits this way without breaking dependents. If we want we could introduce another Package file for 6.2 or 6.3, wherever it's fixed.

),
.package(url: "https://github.com/pointfreeco/swift-dependencies", from: "1.14.0"),
.package(url: "https://github.com/pointfreeco/swift-macro-testing", from: "0.6.3"),
.package(url: "https://github.com/pointfreeco/swift-snapshot-testing", from: "1.18.4"),
.package(url: "https://github.com/pointfreeco/swift-tagged", from: "0.10.0"),
Expand Down
51 changes: 34 additions & 17 deletions Sources/StructuredQueries/Macros.swift
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,15 @@ public import StructuredQueriesCore
named(allCasePaths),
named(_$Element)
)
@attached(memberAttribute)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

The #if CasePaths trait branching for macro attributes is syntax not supported in 6.1.

public macro Table(
_ name: String = "",
schema schemaName: String = ""
) =
#externalMacro(
module: "StructuredQueriesMacros",
type: "TableMacro"
)
#else
@attached(
extension,
Expand All @@ -67,16 +76,16 @@ public import StructuredQueriesCore
named(tableName),
named(CodingKeys)
)
@attached(memberAttribute)
public macro Table(
_ name: String = "",
schema schemaName: String = ""
) =
#externalMacro(
module: "StructuredQueriesMacros",
type: "TableMacro"
)
#endif
@attached(memberAttribute)
public macro Table(
_ name: String = "",
schema schemaName: String = ""
) =
#externalMacro(
module: "StructuredQueriesMacros",
type: "TableMacro"
)

/// Defines a "selection" of columns that can be decoded from a query.
///
Expand Down Expand Up @@ -144,6 +153,14 @@ public macro Table(
named(allCasePaths),
named(_$Element)
)
@attached(memberAttribute)
public macro Selection(
_ name: String = ""
) =
#externalMacro(
module: "StructuredQueriesMacros",
type: "TableMacro"
)
#else
@attached(
extension,
Expand Down Expand Up @@ -171,15 +188,15 @@ public macro Table(
named(tableName),
named(CodingKeys)
)
@attached(memberAttribute)
public macro Selection(
_ name: String = ""
) =
#externalMacro(
module: "StructuredQueriesMacros",
type: "TableMacro"
)
#endif
@attached(memberAttribute)
public macro Selection(
_ name: String = ""
) =
#externalMacro(
module: "StructuredQueriesMacros",
type: "TableMacro"
)

/// Customizes a column generated by the ``/StructuredQueriesCore/Table`` protocol.
///
Expand Down
11 changes: 0 additions & 11 deletions Sources/StructuredQueriesCore/Operators.swift
Original file line number Diff line number Diff line change
Expand Up @@ -395,17 +395,6 @@ extension QueryExpression where QueryValue == Bool {
}
}

// NB: This overload is required due to an overload resolution bug of 'Updates[dynamicMember:]'.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Noticed this was fixed by the recent JSON changes, so dropping it.

@_documentation(visibility: private)
public prefix func ! (
expression: any QueryExpression<Bool>
) -> some QueryExpression<Bool> {
func open(_ expression: some QueryExpression<Bool>) -> SQLQueryExpression<Bool> {
SQLQueryExpression(expression.not())
}
return open(expression)
}

extension SQLQueryExpression<Bool> {
public mutating func toggle() {
self = Self(not())
Expand Down
4 changes: 2 additions & 2 deletions Sources/StructuredQueriesCore/ScalarFunctions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -75,12 +75,12 @@ extension QueryExpression where QueryValue: _OptionalPromotable {
/// `NULL` when both expressions are equal.
public func nullif<Other: QueryExpression>(
_ other: Other
) -> some QueryExpression<QueryValue._Optionalized>
) -> SQLQueryExpression<QueryValue._Optionalized>

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

6.1 does not like this opaque result type.

where
Other.QueryValue: _OptionalPromotable,
Other.QueryValue._Optionalized == QueryValue._Optionalized
{
QueryFunction("nullif", self, other)
SQLQueryExpression(QueryFunction("nullif", self, other))
}
}

Expand Down
4 changes: 2 additions & 2 deletions Tests/StructuredQueriesMacrosTests/TableMacroTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2840,7 +2840,7 @@ extension SnapshotTests {
}
}

@Test func `@Selection with empty struct`() {
@Test("@Selection with empty struct") func selectionWithEmptyStruct() {

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

6.1 cannot build these identifiers.

assertMacro {
"""
@Selection
Expand Down Expand Up @@ -4063,7 +4063,7 @@ extension SnapshotTests {
}
}

@Test func `selection enum requires CasePaths trait`() {
@Test("selection enum requires CasePaths trait") func selectionEnumRequiresCasePathsTrait() {
assertMacro {
"""
@Selection enum Post {
Expand Down
7 changes: 6 additions & 1 deletion Tests/StructuredQueriesTests/DatabaseFunctionTests.swift
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
import Dependencies
import Foundation
import InlineSnapshotTesting
import SQLite3
import StructuredQueries
import StructuredQueriesSQLite
import StructuredQueriesTestSupport
import Testing
import _StructuredQueriesSQLite

#if canImport(Darwin)
import SQLite3
#else
import _StructuredQueriesSQLite3
#endif

extension SnapshotTests {
@Suite struct DatabaseFunctionTests {
@Dependency(\.defaultDatabase) var database
Expand Down
3 changes: 2 additions & 1 deletion Tests/StructuredQueriesTests/DecodingTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,8 @@ extension SnapshotTests {
)
}

@Test func `NULL value in optional column does not decode as default`() throws {
@Test("NULL value in optional column does not decode as default")
func nullValueInOptionalColumnDoesNotDecodeAsDefault() throws {
try withDependencies {
$0.defaultDatabase = db
} operation: {
Expand Down
3 changes: 2 additions & 1 deletion Tests/StructuredQueriesTests/EnumTableTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -644,7 +644,8 @@
}
}

@Test func `enum case with defaults isn't always decoded successfully`() {
@Test("enum case with defaults isn't always decoded successfully")
func enumCaseWithDefaultsIsntAlwaysDecodedSuccessfully() {
assertQuery(
Attachment.upsert {
Attachment
Expand Down
41 changes: 23 additions & 18 deletions Tests/StructuredQueriesTests/InsertTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -715,27 +715,32 @@ extension SnapshotTests {
}
}

// NB: This currently crashes in Xcode 26.
#if swift(<6.2)
@Test func onConflict_invalidUpdateFilters() {
withKnownIssue {
assertQuery(
Reminder.insert {
Reminder.Draft(remindersListID: 1)
} where: {
$0.isFlagged
}
) {
"""
INSERT INTO "reminders"
("id", "assignedUserID", "dueDate", "isCompleted", "isFlagged", "notes", "priority", "remindersListID", "title", "updatedAt")
VALUES
(NULL, NULL, NULL, 0, 0, '', NULL, 1, '', '2040-02-14 23:31:30.000')
"""
@Test func onConflict_invalidUpdateFilters() {
print(
Reminder.insert {
Reminder.Draft(remindersListID: 1)
} where: {
$0.isFlagged
}
.query.debugDescription
)
withKnownIssue {
assertQuery(
Reminder.insert {
Reminder.Draft(remindersListID: 1)
} where: {
$0.isFlagged
}
) {
"""
INSERT INTO "reminders"
("id", "assignedUserID", "dueDate", "isCompleted", "isFlagged", "notes", "priority", "remindersListID", "title", "updatedAt")
VALUES
(NULL, NULL, NULL, 0, 0, '', NULL, 1, '', '2040-02-14 23:31:30.000')
"""
}
}
#endif
}

@Test func onConflict_conditionalWhere() {
let condition = false
Expand Down
8 changes: 4 additions & 4 deletions Tests/StructuredQueriesTests/JSONBTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -677,7 +677,7 @@ extension SnapshotTests {
}

@available(iOS 26, macOS 26, tvOS 26, watchOS 26, *)
@Test func `jsonSet on a JSONBRepresentation`() {
@Test("jsonSet on a JSONBRepresentation") func jsonSetOnAJSONBRepresentation() {
assertQuery(
Post.select { $0.notes.jsonSet(\.[0], "z") }
) {
Expand Down Expand Up @@ -1271,7 +1271,7 @@ extension SnapshotTests {
}

@available(iOS 26, macOS 26, tvOS 26, watchOS 26, *)
@Test func `Multiple jsonSet's are fused`() throws {
@Test("Multiple jsonSet's are fused") func multipleJsonSetsAreFused() throws {
try db.execute(Profile.delete())
assertQuery(
Profile.update {
Expand All @@ -1291,7 +1291,7 @@ extension SnapshotTests {
}

@available(iOS 26, macOS 26, tvOS 26, watchOS 26, *)
@Test func `Multiple jsonReplace's are fused`() throws {
@Test("Multiple jsonReplace's are fused") func multipleJsonReplacesAreFused() throws {
try db.execute(Profile.delete())
assertQuery(
Profile.update {
Expand All @@ -1311,7 +1311,7 @@ extension SnapshotTests {
}

@available(iOS 26, macOS 26, tvOS 26, watchOS 26, *)
@Test func `Multiple jsonInsert's are fused`() throws {
@Test("Multiple jsonInsert's are fused") func multipleJsonInsertsAreFused() throws {
try db.execute(Profile.delete())
assertQuery(
Profile.update {
Expand Down
6 changes: 4 additions & 2 deletions Tests/StructuredQueriesTests/JSONEachTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -366,7 +366,9 @@ extension SnapshotTests {
}

@available(iOS 26, macOS 26, tvOS 26, watchOS 26, *)
@Test func `aggregate scalar quantities in JSON arrays`() throws {
@Test("aggregate scalar quantities in JSON arrays") func aggregateScalarQuantitiesInJSONArrays()
throws
{
try db.execute(
Profile.insert {
Profile.Draft(favoriteNumbers: [42, 1729])
Expand Down Expand Up @@ -682,7 +684,7 @@ extension SnapshotTests {
}

@available(iOS 26, macOS 26, tvOS 26, watchOS 26, *)
@Test func `jsonEach over a JSONBRepresentation`() {
@Test("jsonEach over a JSONBRepresentation") func jsonEachOverAJSONBRepresentation() {
assertQuery(
BlobTrip
.join(BlobTrip.columns.geofence.jsonEach()) { _, _ in true }
Expand Down
9 changes: 6 additions & 3 deletions Tests/StructuredQueriesTests/JSONFunctionsTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -719,7 +719,9 @@ extension SnapshotTests {
}

@available(iOS 26, macOS 26, tvOS 26, watchOS 26, *)
@Test func `jsonbExtract from a JSONRepresentation`() throws {
@Test("jsonbExtract from a JSONRepresentation") func jsonbExtractFromAJSONRepresentation()
throws
{
try db.execute(Doc.delete())
try db.execute(
Doc.insert {
Expand All @@ -746,7 +748,7 @@ extension SnapshotTests {
}

@available(iOS 26, macOS 26, tvOS 26, watchOS 26, *)
@Test func `jsonbSet on a JSONRepresentation`() throws {
@Test("jsonbSet on a JSONRepresentation") func jsonbSetOnAJSONRepresentation() throws {
try db.execute(Doc.delete())
try db.execute(
Doc.insert {
Expand All @@ -773,7 +775,8 @@ extension SnapshotTests {
}

@available(iOS 26, macOS 26, tvOS 26, watchOS 26, *)
@Test func `jsonbAppend and jsonbRemove on a JSONRepresentation`() throws {
@Test("jsonbAppend and jsonbRemove on a JSONRepresentation")
func jsonbAppendAndJsonbRemoveOnAJSONRepresentation() throws {
try db.execute(Doc.delete())
try db.execute(
Doc.insert {
Expand Down
7 changes: 6 additions & 1 deletion Tests/StructuredQueriesTests/MapTests.swift
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
import Dependencies
import Foundation
import InlineSnapshotTesting
import SQLite3
import StructuredQueries
import StructuredQueriesSQLite
import StructuredQueriesTestSupport
import Testing
import _StructuredQueriesSQLite

#if canImport(Darwin)
import SQLite3
#else
import _StructuredQueriesSQLite3
#endif

extension SnapshotTests {
@Suite struct MapTests {
@Dependency(\.defaultDatabase) var database
Expand Down
Loading
Loading