Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
180 commits
Select commit Hold shift + click to select a range
22967fc
wip
stephencelis Feb 18, 2025
8e7058c
Add overloads
stephencelis Feb 18, 2025
e69f66b
wip
stephencelis Feb 18, 2025
370ceec
wip
mbrandonw Feb 19, 2025
97fec01
wip
mbrandonw Feb 19, 2025
0f7cf74
select only color for search query
mbrandonw Feb 19, 2025
2bd94cc
Revert "select only color for search query"
mbrandonw Feb 19, 2025
2976e42
wip
mbrandonw Feb 19, 2025
d819dc7
wip
stephencelis Feb 19, 2025
baa3e47
wip
stephencelis Feb 20, 2025
0e0c250
wip
stephencelis Feb 20, 2025
86b73f4
clean up
mbrandonw Feb 21, 2025
ebcc9e2
more clean up
mbrandonw Feb 21, 2025
a8ce7f9
a little bit more clean up
mbrandonw Feb 21, 2025
ae0066b
more clean up
mbrandonw Feb 21, 2025
46c5cb0
wip
mbrandonw Feb 21, 2025
16e4238
disable indices for now
mbrandonw Feb 21, 2025
dc36985
wip
mbrandonw Feb 21, 2025
1cdd0a5
wip
mbrandonw Feb 21, 2025
ccd619a
wip
mbrandonw Feb 22, 2025
65362f1
wip
mbrandonw Feb 22, 2025
12eb058
remove mutablerecord conformances
mbrandonw Feb 22, 2025
aefb43d
rename column
mbrandonw Feb 22, 2025
4a9fd22
wip
stephencelis Feb 27, 2025
ee68b6b
wip
stephencelis Mar 13, 2025
6965e4e
Convert SyncUps to StructuredQueries.
mbrandonw Mar 14, 2025
884cf42
wip
mbrandonw Mar 14, 2025
a682f4a
wip
mbrandonw Mar 14, 2025
ff272a8
wip
mbrandonw Mar 14, 2025
0828bae
fixes
mbrandonw Mar 16, 2025
7830cc4
SyncUpForm tests'
mbrandonw Mar 16, 2025
49a4289
wip
stephencelis Mar 17, 2025
01da866
Merge remote-tracking branch 'origin/main' into structure
stephencelis Mar 17, 2025
2baffe5
wip
stephencelis Mar 17, 2025
30b87a1
wip
stephencelis Mar 17, 2025
c44bae3
wip
stephencelis Mar 17, 2025
3c1a703
wip
stephencelis Mar 17, 2025
f985140
wip
stephencelis Mar 17, 2025
fc646af
wip
stephencelis Mar 17, 2025
0321e2f
fixes
mbrandonw Mar 18, 2025
fbfe8cb
wip
stephencelis Mar 19, 2025
9fcd36b
fix
stephencelis Mar 19, 2025
1a74430
wip
stephencelis Mar 20, 2025
0447953
wip
stephencelis Mar 20, 2025
eb4970b
wip
mbrandonw Mar 20, 2025
6a6c1ff
wip
mbrandonw Mar 20, 2025
06cea85
wip
stephencelis Mar 20, 2025
39c3015
wip
mbrandonw Mar 21, 2025
c8e47b8
wip;
mbrandonw Mar 22, 2025
8a4277e
wip
mbrandonw Mar 22, 2025
dff45ba
wip
stephencelis Mar 24, 2025
84a274f
wip
stephencelis Mar 24, 2025
98495b1
wip
stephencelis Mar 24, 2025
c18de06
wip
stephencelis Mar 24, 2025
d411fc5
wip
stephencelis Mar 24, 2025
7375c72
wip
stephencelis Mar 24, 2025
706441c
wip
stephencelis Mar 24, 2025
2932597
wip
stephencelis Mar 24, 2025
f49bd73
wip
stephencelis Mar 24, 2025
1f3d719
wip
stephencelis Mar 24, 2025
40140ec
wip
stephencelis Mar 24, 2025
4ac2900
wip
stephencelis Mar 24, 2025
7ac00e9
wip
stephencelis Mar 27, 2025
8bd0389
Merge remote-tracking branch 'origin/main' into structure
stephencelis Mar 27, 2025
eb4ccd7
wip
stephencelis Mar 27, 2025
3b027fa
Merge branch 'main' into structure
stephencelis Mar 27, 2025
95fb9ce
wip
stephencelis Mar 28, 2025
783b687
wip
mbrandonw Mar 31, 2025
3e3707e
wip
stephencelis Mar 31, 2025
dad79da
Use 'unscoped' branch from structured queries.
mbrandonw Apr 1, 2025
4bbc431
Update for unscoped branch.
mbrandonw Apr 2, 2025
5d38f09
clean up
mbrandonw Apr 2, 2025
079bb1f
wip
stephencelis Apr 4, 2025
6156e10
fix
stephencelis Apr 5, 2025
945b996
wip
stephencelis Apr 5, 2025
a124b32
wip
stephencelis Apr 5, 2025
0140ec2
wip
stephencelis Apr 5, 2025
3b35de2
Merge remote-tracking branch 'origin/unscoped' into structure
mbrandonw Apr 6, 2025
ef484c6
update migratinos
mbrandonw Apr 6, 2025
1644433
wip
mbrandonw Apr 7, 2025
dd7a5db
wip
mbrandonw Apr 7, 2025
ec57801
wip
stephencelis Apr 7, 2025
76e4989
wipo
mbrandonw Apr 8, 2025
0607a7c
wip
stephencelis Apr 8, 2025
354b2cd
Merge remote-tracking branch 'origin/main' into structure
stephencelis Apr 8, 2025
22d8648
wip
stephencelis Apr 8, 2025
190d71b
wip
stephencelis Apr 8, 2025
b7c81d1
wip
stephencelis Apr 8, 2025
084e822
clean up
mbrandonw Apr 10, 2025
0722e32
wip
mbrandonw Apr 12, 2025
005dd2e
Clean uop
mbrandonw Apr 12, 2025
39745aa
wip
stephencelis Apr 13, 2025
08535a8
wip
stephencelis Apr 13, 2025
98826de
wip
stephencelis Apr 14, 2025
05f3d0b
clean up
mbrandonw Apr 15, 2025
693a2ea
wip
mbrandonw Apr 16, 2025
411545a
wip
stephencelis Apr 16, 2025
b929c8d
format
stephencelis Apr 16, 2025
f7a5468
wip
mbrandonw Apr 16, 2025
c1f0ba7
Merge remote-tracking branch 'origin/main' into structure
mbrandonw Apr 16, 2025
c768b22
format
mbrandonw Apr 16, 2025
1652657
wip
mbrandonw Apr 16, 2025
f69b946
Merge remote-tracking branch 'origin/main' into structure
stephencelis Apr 16, 2025
659bb81
batch seed
stephencelis Apr 16, 2025
8179a9a
wip
stephencelis Apr 16, 2025
d78ac32
clean up
mbrandonw Apr 17, 2025
f6f41e6
wip
stephencelis Apr 17, 2025
61979b9
wip
mbrandonw Apr 17, 2025
1884ae4
wip
stephencelis Apr 17, 2025
43603fa
wip
stephencelis Apr 17, 2025
8761d1b
wip
stephencelis Apr 17, 2025
e573ee3
S Q -> SQ
stephencelis Apr 17, 2025
d650901
rename name to title
mbrandonw Apr 17, 2025
4b31f41
docs
mbrandonw Apr 17, 2025
6e9336c
wip
stephencelis Apr 18, 2025
7dda98e
wip
stephencelis Apr 18, 2025
d458f12
wip
mbrandonw Apr 18, 2025
ad5f590
wip
mbrandonw Apr 18, 2025
86019d6
wip
stephencelis Apr 18, 2025
963c15b
wip
stephencelis Apr 18, 2025
f8d0444
wip
stephencelis Apr 18, 2025
a65a9bb
wip
stephencelis Apr 18, 2025
0d46048
clean up
mbrandonw Apr 18, 2025
9ed19f8
wip
stephencelis Apr 18, 2025
d9cfaa6
wip
stephencelis Apr 18, 2025
0b7b0fa
wip
stephencelis Apr 18, 2025
e752994
wip
stephencelis Apr 18, 2025
69c78f6
wip
stephencelis Apr 18, 2025
2910fca
wip
stephencelis Apr 18, 2025
07b2a81
wip
stephencelis Apr 18, 2025
95084b6
wip
stephencelis Apr 18, 2025
a7ffa31
wip
stephencelis Apr 18, 2025
695b3d9
wip
stephencelis Apr 18, 2025
352623c
wip
stephencelis Apr 18, 2025
1561d35
wip
stephencelis Apr 18, 2025
6f9cd4c
wip
stephencelis Apr 18, 2025
7b5c52f
wip
stephencelis Apr 18, 2025
6a5e5b9
wip
stephencelis Apr 18, 2025
a9252cc
wip
stephencelis Apr 18, 2025
158ab08
wip
stephencelis Apr 18, 2025
009453c
wip
stephencelis Apr 18, 2025
0c0f7d3
wip
stephencelis Apr 18, 2025
491d630
Add fetchOne overloads for SelectStatement
stephencelis Apr 18, 2025
95744a7
Basic support for lists of reminders by tag
mbrandonw Apr 19, 2025
2d047f7
clean up
mbrandonw Apr 19, 2025
b570e08
clean up
mbrandonw Apr 19, 2025
b08eb33
clean up
mbrandonw Apr 19, 2025
8ff011d
clean up
mbrandonw Apr 19, 2025
05f3c5c
wip
mbrandonw Apr 20, 2025
9df7bfd
wip
stephencelis Apr 20, 2025
dc90f97
wip
stephencelis Apr 20, 2025
70c77a8
clean up
mbrandonw Apr 20, 2025
73c90fb
Bump
stephencelis Apr 21, 2025
1e1ed2d
Merge remote-tracking branch 'origin/main' into structure
stephencelis Apr 21, 2025
6fba787
wip
stephencelis Apr 21, 2025
d77bd2c
wip
mbrandonw Apr 21, 2025
aaa4557
fix
mbrandonw Apr 21, 2025
9e44498
wip
mbrandonw Apr 21, 2025
45f0acd
wip
stephencelis Apr 21, 2025
6555991
wip
mbrandonw Apr 21, 2025
3abceaf
wip
mbrandonw Apr 21, 2025
2a9787c
wip
mbrandonw Apr 21, 2025
4e2f77f
wip
stephencelis Apr 22, 2025
fd8ca4c
wip
mbrandonw Apr 22, 2025
c019dd6
wip
mbrandonw Apr 22, 2025
a5e558a
wip
stephencelis Apr 22, 2025
9482b68
wip
stephencelis Apr 22, 2025
e7d9ef8
wip
stephencelis Apr 22, 2025
0298885
wip
stephencelis Apr 22, 2025
034f7ba
wip
stephencelis Apr 22, 2025
5b8624d
wip
stephencelis Apr 22, 2025
2ca57d5
wip
stephencelis Apr 22, 2025
117c523
wip
stephencelis Apr 22, 2025
d508165
wip
stephencelis Apr 22, 2025
28f114b
wip
mbrandonw Apr 22, 2025
d52fa40
Merge remote-tracking branch 'origin/structure-2' into structure
mbrandonw Apr 22, 2025
e4a0d9c
wip
mbrandonw Apr 22, 2025
0c6c9ef
wip
mbrandonw Apr 22, 2025
c8054a3
wip
stephencelis Apr 22, 2025
a62870a
wip
stephencelis Apr 22, 2025
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: 4 additions & 1 deletion .spi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,7 @@ builder:
configs:
- documentation_targets:
- SharingGRDB
swift_version: 6.0
- SharingGRDBCore
- StructuredQueriesGRDB
- StructuredQueriesGRDBCore
custom_documentation_parameters: [--enable-experimental-overloaded-symbol-presentation]
32 changes: 17 additions & 15 deletions Examples/CaseStudies/Animations.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import Dependencies
import SharingGRDB
import SwiftUI

Expand All @@ -7,14 +6,14 @@ struct AnimationsCaseStudy: SwiftUICaseStudy {
This demonstrates how to animate fetching data from the database, or when data changes in \
the database. Simply provide the `animation` argument to `fetchAll` (or the other querying \
tools, such as `fetch` and `fetchOne`).

This is analogous to how animations work in SwiftData in which one provides an `animation` \
argument to the `@Query` macro.
"""
let caseStudyTitle = "Animations"

@SharedReader(.fetchAll(sql: #"SELECT * FROM "facts" ORDER BY "id" DESC"#, animation: .default))
private var facts: [Fact]
@FetchAll(Fact.order { $0.id.desc() }, animation: .default)
private var facts

@Dependency(\.defaultDatabase) var database

Expand All @@ -36,32 +35,35 @@ struct AnimationsCaseStudy: SwiftUICaseStudy {
as: UTF8.self
)
try await database.write { db in
_ = try Fact(body: fact).inserted(db)
try Fact.insert(Fact.Draft(body: fact))
.execute(db)
}
}
} catch {}
}
}
}

private struct Fact: Codable, FetchableRecord, Identifiable, MutablePersistableRecord {
static let databaseTableName = "facts"
var id: Int64?
@Table
private struct Fact: Identifiable {
let id: Int
var body: String
mutating func didInsert(_ inserted: InsertionSuccess) {
id = inserted.rowID
}
}

extension DatabaseWriter where Self == DatabaseQueue {
static var animationDatabase: Self {
let databaseQueue = try! DatabaseQueue()
var migrator = DatabaseMigrator()
migrator.registerMigration("Create 'facts' table") { db in
try db.create(table: Fact.databaseTableName) { table in
table.autoIncrementedPrimaryKey("id")
table.column("body", .text).notNull()
}
try #sql(
"""
CREATE TABLE "facts" (
"id" INTEGER PRIMARY KEY AUTOINCREMENT,
"body" TEXT NOT NULL
)
"""
)
.execute(db)
}
try! migrator.migrate(databaseQueue)
return databaseQueue
Expand Down
6 changes: 4 additions & 2 deletions Examples/CaseStudies/App.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@ struct CaseStudiesApp: App {
var body: some Scene {
WindowGroup {
Form {
Text("""
Text(
"""
Open the preview in each case study file to run a case study.
""")
"""
)
}
}
}
Expand Down
56 changes: 32 additions & 24 deletions Examples/CaseStudies/DynamicQuery.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import Dependencies
import SharingGRDB
import SwiftUI

Expand All @@ -8,13 +7,13 @@ struct DynamicQueryDemo: SwiftUICaseStudy {
a fact about a number is loaded from the network and saved to a database. You can search the \
facts for text, and the list will stay in sync so that if a new fact is added to the database \
that satisfies the search term, it will immediately appear.
To accomplish this one can invoke the `load` method defined on the `@SharedReader` projected \
value in order to set a new query with dynamic parameters.

To accomplish this one can invoke the `load` method defined on the `@Fetch` projected value in \
order to set a new query with dynamic parameters.
"""
let caseStudyTitle = "Dynamic Query"

@State.SharedReader(.fetch(Facts(), animation: .default)) private var facts = Facts.Value()
@Fetch(Facts(), animation: .default) private var facts = Facts.Value()
@State var query = ""

@Dependency(\.defaultDatabase) var database
Expand All @@ -38,10 +37,14 @@ struct DynamicQueryDemo: SwiftUICaseStudy {
ForEach(facts.facts) { fact in
Text(fact.body)
}
.onDelete { indexSet in
.onDelete { indices in
withErrorReporting {
try database.write { db in
_ = try Fact.deleteAll(db, ids: indexSet.compactMap { facts.facts[$0].id })
let ids = indices.map { facts.facts[$0].id }
try Fact
.where { $0.id.in(ids) }
.delete()
.execute(db)
}
}
}
Expand All @@ -50,7 +53,7 @@ struct DynamicQueryDemo: SwiftUICaseStudy {
.searchable(text: $query)
.task(id: query) {
await withErrorReporting {
try await $facts.load(.fetch(Facts(query: query), animation: .default))
try await $facts.load(Facts(query: query), animation: .default)
}
}
.task {
Expand All @@ -65,7 +68,8 @@ struct DynamicQueryDemo: SwiftUICaseStudy {
as: UTF8.self
)
try await database.write { db in
_ = try Fact(body: fact).inserted(db)
try Fact.insert(Fact.Draft(body: fact))
.execute(db)
}
}
} catch {}
Expand All @@ -80,35 +84,39 @@ struct DynamicQueryDemo: SwiftUICaseStudy {
var totalCount = 0
}
func fetch(_ db: Database) throws -> Value {
let query = Fact.order(Column("id").desc).filter(Column("body").like("%\(query)%"))
let search =
Fact
.where { $0.body.contains(query) }
.order { $0.id.desc() }
return try Value(
facts: query.fetchAll(db),
searchCount: query.fetchCount(db),
totalCount: Fact.fetchCount(db)
facts: search.fetchAll(db),
searchCount: search.fetchCount(db),
totalCount: Fact.all.fetchCount(db)
)
}
}

}

private struct Fact: Codable, FetchableRecord, Identifiable, MutablePersistableRecord {
static let databaseTableName = "facts"
var id: Int64?
@Table
private struct Fact: Identifiable {
let id: Int
var body: String
mutating func didInsert(_ inserted: InsertionSuccess) {
id = inserted.rowID
}
}

extension DatabaseWriter where Self == DatabaseQueue {
static var dynamicQueryDatabase: Self {
let databaseQueue = try! DatabaseQueue()
var migrator = DatabaseMigrator()
migrator.registerMigration("Create 'facts' table") { db in
try db.create(table: Fact.databaseTableName) { table in
table.autoIncrementedPrimaryKey("id")
table.column("body", .text).notNull()
}
try #sql(
"""
CREATE TABLE "facts" (
"id" INTEGER PRIMARY KEY AUTOINCREMENT,
"body" TEXT NOT NULL
)
"""
)
.execute(db)
}
try! migrator.migrate(databaseQueue)
return databaseQueue
Expand Down
42 changes: 24 additions & 18 deletions Examples/CaseStudies/ObservableModelDemo.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import Dependencies
import SharingGRDB
import SwiftUI

Expand All @@ -7,7 +6,7 @@ struct ObservableModelDemo: SwiftUICaseStudy {
This demonstrates how to use the `fetchAll` and `fetchOne` tools in an @Observable model. \
In SwiftUI, the `@Query` macro only works when installed directly in a SwiftUI view, and \
cannot be used outside of views.

The tools provided with this library work basically anywhere, including in `@Observable` \
models and UIKit view controllers.
"""
Expand Down Expand Up @@ -47,10 +46,10 @@ struct ObservableModelDemo: SwiftUICaseStudy {
@MainActor
private class Model {
@ObservationIgnored
@SharedReader(.fetchAll(sql: #"SELECT * FROM "facts" ORDER BY "id" DESC"#, animation: .default))
var facts: [Fact]
@FetchAll(Fact.order { $0.id.desc() }, animation: .default)
var facts
@ObservationIgnored
@SharedReader(.fetchOne(sql: #"SELECT count(*) FROM "facts""#, animation: .default))
@FetchOne(Fact.count(), animation: .default)
var factsCount = 0
var number = 0

Expand All @@ -66,38 +65,45 @@ private class Model {
as: UTF8.self
)
try await database.write { db in
_ = try Fact(body: fact).inserted(db)
try Fact.insert(Fact.Draft(body: fact))
.execute(db)
}
}
}

func deleteFact(indices: IndexSet) {
_ = withErrorReporting {
withErrorReporting {
try database.write { db in
try Fact.deleteAll(db, ids: indices.compactMap { facts[$0].id })
let ids = indices.map { facts[$0].id }
try Fact
.where { $0.id.in(ids) }
.delete()
.execute(db)
}
}
}
}

private struct Fact: Codable, FetchableRecord, Identifiable, MutablePersistableRecord {
static let databaseTableName = "facts"
var id: Int64?
@Table
private struct Fact: Identifiable {
let id: Int
var body: String
mutating func didInsert(_ inserted: InsertionSuccess) {
id = inserted.rowID
}
}

extension DatabaseWriter where Self == DatabaseQueue {
static var observableModelDatabase: Self {
let databaseQueue = try! DatabaseQueue()
var migrator = DatabaseMigrator()
migrator.registerMigration("Create 'facts' table") { db in
try db.create(table: Fact.databaseTableName) { table in
table.autoIncrementedPrimaryKey("id")
table.column("body", .text).notNull()
}
try #sql(
"""
CREATE TABLE "facts" (
"id" INTEGER PRIMARY KEY AUTOINCREMENT,
"body" TEXT NOT NULL
)
"""
)
.execute(db)
}
try! migrator.migrate(databaseQueue)
return databaseQueue
Expand Down
33 changes: 17 additions & 16 deletions Examples/CaseStudies/SwiftDataTemplateDemo.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ struct SwiftDataTemplateView: SwiftUICaseStudy {
let caseStudyTitle = "SwiftData Template"

@Dependency(\.defaultDatabase) private var database
@SharedReader(.fetch(Items(), animation: .default)) private var items
@FetchAll(Item.all, animation: .default) private var items

var body: some View {
NavigationStack {
List {
ForEach(items, id: \.id) { item in
ForEach(items) { item in
NavigationLink {
Text(
"Item at \(item.timestamp, format: Date.FormatStyle(date: .numeric, time: .standard))"
Expand All @@ -41,28 +41,24 @@ struct SwiftDataTemplateView: SwiftUICaseStudy {
private func addItem() {
withErrorReporting {
try database.write { db in
_ = try Item(timestamp: Date()).inserted(db)
try Item.insert().execute(db)
}
}
}

private func deleteItems(offsets: IndexSet) {
withErrorReporting {
try database.write { db in
_ = try Item.deleteAll(db, keys: offsets.map { items[$0].id })
try Item.where { $0.id.in(offsets.map { items[$0].id }) }.delete().execute(db)
}
}
}

private struct Items: FetchKeyRequest {
func fetch(_ db: Database) throws -> [Item] {
try Item.order(Column("timestamp").desc).fetchAll(db)
}
}
}

private struct Item: Codable, Hashable, FetchableRecord, MutablePersistableRecord {
var id: Int64?
@Table
private struct Item: Identifiable {
let id: Int
@Column(as: Date.ISO8601Representation.self)
var timestamp: Date
}

Expand All @@ -71,10 +67,15 @@ extension DatabaseWriter where Self == DatabaseQueue {
let databaseQueue = try! DatabaseQueue()
var migrator = DatabaseMigrator()
migrator.registerMigration("Create items table") { db in
try db.create(table: Item.databaseTableName) { table in
table.autoIncrementedPrimaryKey("id")
table.column("timestamp", .datetime).notNull()
}
try #sql(
"""
CREATE TABLE "items" (
"id" INTEGER PRIMARY KEY AUTOINCREMENT,
"timestamp" TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP
)
"""
)
.execute(db)
}
try! migrator.migrate(databaseQueue)
return databaseQueue
Expand Down
Loading