Skip to content

Commit 66a7886

Browse files
authored
Move some SQLite functionality into SQLite module (#157)
* Move some SQLite functionality into SQLite module This includes: - The custom Date/UUID representations - The JSON functions - The `rowid` column - The temporary trigger helpers - FTS5 Not included (yet): - Our insert statement still supports some SQLite-only functionality (the `OR` clause). - Need to audit the scalar/aggregate function helpers for any SQLite-specific functions. * wip * wip * wip * wip * wip * wip * wip
1 parent 1115d2b commit 66a7886

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+1347
-738
lines changed

Sources/StructuredQueries/Documentation.docc/StructuredQueries.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,15 @@ This module also contains all of the macros that support the core functionality
1111

1212
See [`StructuredQueriesCore`](<doc:/StructuredQueriesCore>) for general library usage.
1313

14+
StructuredQueries also ships SQLite-specific helpers:
15+
16+
- [`StructuredQueriesSQLiteCore`](<doc:/StructuredQueriesSQLiteCore>): Core, SQLite-specific
17+
functionality, including full-text search, type-safe temporary triggers, full-text search, and
18+
more.
19+
20+
- [`StructuredQueriesSQLite`](<doc:/StructuredQueriesSQLite>): Everything from
21+
`StructuredQueriesSQLiteCore` and macros that support it, like `@DatabaseFunction.`
22+
1423
## Topics
1524

1625
### Macros

Sources/StructuredQueriesCore/AggregateFunctions.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ public struct AggregateFunction<QueryValue>: QueryExpression, Sendable {
216216
var order: QueryFragment?
217217
var filter: QueryFragment?
218218

219-
init(
219+
package init(
220220
_ name: QueryFragment,
221221
isDistinct: Bool = false,
222222
_ arguments: [QueryFragment] = [],

Sources/StructuredQueriesCore/Documentation.docc/Articles/DefiningYourSchema.md

Lines changed: 2 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Defining your schema
22

3-
Learn how to replicate your database's schema in first class Swift types
4-
using the `@Table` and `@Column` macros.
3+
Learn how to replicate your database's schema in first class Swift types using the `@Table` and
4+
`@Column` macros.
55

66
## Overview
77

@@ -22,7 +22,6 @@ that represent those database definitions.
2222
* [RawRepresentable](#RawRepresentable)
2323
* [JSON](#JSON)
2424
* [Tagged identifiers](#Tagged-identifiers)
25-
* [Default representations for dates and UUIDs](#Default-representations-for-dates-and-UUIDs)
2625
* [Primary keyed tables](#Primary-keyed-tables)
2726
* [Ephemeral columns](#Ephemeral-columns)
2827
* [Generated columns](#Generated-columns)
@@ -306,106 +305,6 @@ RemindersList.leftJoin(Reminder.all) {
306305
}
307306
```
308307

309-
#### Default representations for dates and UUIDs
310-
311-
While some relational databases, like MySQL and Postgres, have native types for dates and UUIDs,
312-
SQLite does _not_, and instead can represent them in a variety of ways. In order to lessen the
313-
friction of building queries with dates and UUIDs, the library has decided to provide a default
314-
representation for dates and UUIDs, and if that choice does not fit your schema you can explicitly
315-
specify the representation you want.
316-
317-
##### Dates
318-
319-
Dates in SQLite have 3 different representations:
320-
321-
* Text column interpreted as ISO-8601-formatted string.
322-
* Int column interpreted as number of seconds since Unix epoch.
323-
* Double column interpreted as a Julian day (number of days since November 24, 4713 BC).
324-
325-
By default, StructuredQueries will bind and decode dates as ISO-8601 text. If you want the library
326-
to use a different representation (_i.e._ integer or double), you can provide an explicit query
327-
representation to the `@Column` macro's `as:` argument. ``Foundation/Date/UnixTimeRepresentation``
328-
will store the date as an integer, and ``Foundation/Date/JulianDayRepresentation`` will store the
329-
date as a floating point number.
330-
331-
For example:
332-
333-
```swift
334-
@Table struct Reminder {
335-
let id: Int
336-
@Column(as: Date.UnixTimeRepresentation.self)
337-
var date: Date
338-
}
339-
```
340-
341-
And StructuredQueries will take care of formatting the value for the database:
342-
343-
@Row {
344-
@Column {
345-
```swift
346-
Reminder.insert {
347-
Reminder.Draft(date: Date())
348-
}
349-
```
350-
}
351-
@Column {
352-
```sql
353-
INSERT INTO "reminders"
354-
("date")
355-
VALUES
356-
(1517184480)
357-
```
358-
}
359-
}
360-
361-
If you use the non-default date representation in your schema, then while querying against a
362-
date column with a Swift Date, you will need to explicitly bundle up the Swift date into the
363-
appropriate representation to use various query helpers. This can be done using the `#bind` macro:
364-
365-
```swift
366-
Reminder.where { $0.created > #bind(startDate) }
367-
```
368-
369-
> Note: When using the default representation for dates (ISO-8601 text) you do not need to use
370-
> the `#bind` macro:
371-
>
372-
> ```swift
373-
> Reminder.where { $0.created > startDate }
374-
> ```
375-
376-
##### UUIDs
377-
378-
SQLite also does not have type-level support for UUIDs. By default, the library will bind and decode
379-
UUIDs as lowercased, hexadecimal text, but it also provides custom representations. This includes
380-
``Foundation/UUID/UppercasedRepresentation`` for uppercased text, as well as
381-
``Foundation/UUID/BytesRepresentation`` for raw bytes.
382-
383-
To use such custom representations, you can provide it to the `@Column` macro's `as:` parameter:
384-
385-
```swift
386-
@Table struct Reminder {
387-
@Column(as: UUID.BytesRepresentation.self)
388-
let id: UUID
389-
var title = ""
390-
}
391-
```
392-
393-
If you use the non-default UUID representation in your schema, then while querying against a UUID
394-
column with a Swift UUID, you will need to explicitly bundle up the Swift UUID into the appropriate
395-
representation to use various query helpers. This can be done using
396-
the `#bind` macro:
397-
398-
```swift
399-
Reminder.where { $0.id != #bind(reminder.id) }
400-
```
401-
402-
> Note: When using the default representation for UUID (lower-cased text) you do not need to use
403-
> the `#bind` macro:
404-
>
405-
> ```swift
406-
> Reminder.where { $0.id != reminder.id }
407-
> ```
408-
409308
### Primary keyed tables
410309

411310
It is possible to let the `@Table` macro know which property of your data type is the primary

Sources/StructuredQueriesCore/Documentation.docc/Articles/FullTextSearch.md

Lines changed: 0 additions & 26 deletions
This file was deleted.

Sources/StructuredQueriesCore/Documentation.docc/Articles/GettingStarted.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -305,7 +305,7 @@ capable of. See <doc:SelectStatements> for more examples of select statements, a
305305
The library provides the tools necessary to construct type-safe insert statements in SQL, including
306306
inserting an entire value into a table, inserting only a subset of rows, as well as what to do on
307307
conflicts. Using the `Reminder` data type from above, we can insert data for all of its rows using
308-
the ``Table/insert(or:_:values:onConflict:where:doUpdate:where:)`` method:
308+
the ``Table/insert(_:values:onConflict:where:doUpdate:where:)`` method:
309309

310310
@Row {
311311
@Column {
@@ -339,7 +339,7 @@ and the number of columns and data type of each column must match what is specif
339339
trailing closure.
340340

341341
You can provide a 3rd trailing closure to
342-
``Table/insert(or:_:values:onConflict:where:doUpdate:where:)`` to describe what to do in case there
342+
``Table/insert(_:values:onConflict:where:doUpdate:where:)`` to describe what to do in case there
343343
is a conflict while inserting data. For example, suppose we had a unique index on the "title" column
344344
of the reminders table. Then when inserting a value with a repeated title we could resolve the
345345
conflict by appending the string `" (Copy)"` to the title:
@@ -451,7 +451,7 @@ queries.
451451

452452
The library provides tools for constructing type-safe update statements in SQL, including updating
453453
all rows in a table, a filtered set of rows, or rows with specific primary keys.
454-
``Table/update(or:set:)`` returns an update statement given a closure that describes the changes you
454+
``Table/update(set:)`` returns an update statement given a closure that describes the changes you
455455
want to make to the table by mutating an `inout` representation of the table's columns. You can
456456
assign new values or even call a selection of mutating methods and in-place operators.
457457

Sources/StructuredQueriesCore/Documentation.docc/Articles/InsertStatements.md

Lines changed: 11 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ Learn how to build queries that insert data into a database.
77
### Inserting records
88

99
The simplest way to insert table records into the database is the
10-
[`Table.insert`](<doc:Table/insert(or:_:values:onConflict:where:doUpdate:where:)>), which takes a
10+
[`Table.insert`](<doc:Table/insert(_:values:onConflict:where:doUpdate:where:)>), which takes a
1111
trailing closure and the record(s) to be inserted:
1212

1313
@Row {
@@ -191,7 +191,7 @@ As well as introduce conditional or looping logic:
191191
### Inserting from a select statement
192192

193193
To insert a row into a table with the results of a ``Select`` statement, use
194-
``Table/insert(or:_:select:onConflict:)``:
194+
``Table/insert(_:select:onConflict:)``:
195195

196196
@Row {
197197
@Column {
@@ -219,7 +219,7 @@ statement's columns.
219219
### Inserting default values
220220

221221
To insert a row into a table where all values have database-provided defaults, use
222-
``Table/insert(or:)``:
222+
``Table/insert()``:
223223

224224
@Row {
225225
@Column {
@@ -309,7 +309,7 @@ ReminderForm(
309309
```
310310

311311
When the draft is ready to be committed back to the database, you can use
312-
``PrimaryKeyedTable/upsert(or:values:)``, which generates an ``Insert`` with an "upsert" clause:
312+
``PrimaryKeyedTable/upsert(values:)``, which generates an ``Insert`` with an "upsert" clause:
313313

314314
@Row {
315315
@Column {
@@ -333,30 +333,7 @@ When the draft is ready to be committed back to the database, you can use
333333

334334
### Conflict resolution and upserts
335335

336-
Every insert function includes an optional `or` parameter, which can be used to specify the `OR`
337-
clause for conflict resolution:
338-
339-
@Row {
340-
@Column {
341-
```swift
342-
Tag.insert(or: .ignore) {
343-
$0.title
344-
} values: {
345-
"home"
346-
}
347-
```
348-
}
349-
@Column {
350-
```sql
351-
INSERT OR IGNORE INTO "tags"
352-
("title")
353-
VALUES
354-
('home')
355-
```
356-
}
357-
}
358-
359-
And many include an optional upsert clause. You can unconditionally upsert using the
336+
Most insert functions include an optional upsert clause. You can unconditionally upsert using the
360337
`onConflictDoUpdate` trailing closure:
361338

362339
@Row {
@@ -446,24 +423,24 @@ Upsert clauses have an additional, special argument for referring to a row that
446423
`WHERE` conditions are also supported, on both the conflict and update clauses.
447424

448425
> Tip: The `onConflictDoUpdate` and `doUpdate` closures work similarly to the closure parameter of
449-
> ``Table/update(or:set:)``. See <doc:UpdateStatements> for more information on building these
426+
> ``Table/update(set:)``. See <doc:UpdateStatements> for more information on building these
450427
> clauses.
451428
452429
## Topics
453430

454431
### Inserting values
455432

456-
- ``Table/insert(or:_:values:onConflict:where:doUpdate:where:)``
457-
- ``Table/insert(or:_:values:onConflictDoUpdate:where:)``
458-
- ``Table/insert(or:)``
433+
- ``Table/insert(_:values:onConflict:where:doUpdate:where:)``
434+
- ``Table/insert(_:values:onConflictDoUpdate:where:)``
435+
- ``Table/insert()``
459436

460437
### Inserting drafts
461438

462-
- ``PrimaryKeyedTable/upsert(or:values:)``
439+
- ``PrimaryKeyedTable/upsert(values:)``
463440

464441
### Inserting from a select
465442

466-
- ``Table/insert(or:_:select:onConflict:where:doUpdate:where:)``
443+
- ``Table/insert(_:select:onConflict:where:doUpdate:where:)``
467444

468445
### Upserts
469446

Sources/StructuredQueriesCore/Documentation.docc/Articles/Operators.md

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -130,9 +130,3 @@ Explore the full list of operators below.
130130
- ``PartialSelectStatement/exists()``
131131
- ``Swift/Array``
132132
- ``Swift/ClosedRange``
133-
134-
### Casting
135-
136-
- ``QueryExpression/cast(as:)``
137-
- ``SQLiteType``
138-
- ``SQLiteTypeAffinity``

Sources/StructuredQueriesCore/Documentation.docc/Articles/PrimaryKeyedTables.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,8 @@ let draft = Reminder.Draft(title: "Get groceries")
5555

5656
The `id` is not necessary to provide because it is optional. This allows you to insert rows into
5757
your database without specifying the id. The library comes with a special
58-
``PrimaryKeyedTable/insert(or:_:onConflict:)`` method that allows you to insert a row
59-
into the database by providing only a draft:
58+
``PrimaryKeyedTable/insert(_:onConflict:)`` method that allows you to insert a row into the database
59+
by providing only a draft:
6060

6161
@Row {
6262
@Column {
@@ -188,8 +188,8 @@ The ``PrimaryKeyedTable/find(_:)`` method can be used for updates and deletions
188188
}
189189

190190

191-
A special ``PrimaryKeyedTable/update(or:_:)`` method is also provided to update all the fields of a
192-
row with the corresponding primary key:
191+
A special ``PrimaryKeyedTable/update(_:)`` method is also provided to update all the fields of a row
192+
with the corresponding primary key:
193193

194194
@Row {
195195
@Column {

0 commit comments

Comments
 (0)