@@ -14,6 +14,17 @@ you can use the static description of its properties to build type-safe queries.
1414schema of your app is defined first and foremost in your database, and then you define Swift types
1515that represent those database definitions.
1616
17+ * [ Defining a table] ( #Defining-a-table )
18+ * [ Customizing a table] ( #Customizing-a-table )
19+ * [ Table names] ( #Table-names )
20+ * [ Column names] ( #Column-names )
21+ * [ Custom data types] ( #Custom-data-types )
22+ * [ RawRepresentable] ( #RawRepresentable )
23+ * [ JSON] ( #JSON )
24+ * [ Default representations for dates and UUIDs] ( #Default-representations-for-dates-and-UUIDs )
25+ * [ Primary keyed tables] ( #Primary-keyed-tables )
26+ * [ Ephemeral columns] ( #Ephemeral-columns )
27+
1728### Defining a table
1829
1930Suppose your database has a table defined with the following create statement:
@@ -152,113 +163,6 @@ with your table's columns, instead. For these data types you must either define
152163The library comes with several `QueryRepresentable` conformances to aid in representing dates,
153164UUIDs, and JSON, and you can define your own conformances for your own custom data types.
154165
155- #### Dates
156-
157- While some relational databases, like MySQL and Postgres, have native support for dates, SQLite
158- does _not_. Instead, it has 3 different ways to represent dates:
159-
160- * Text column interpreted as ISO-8601-formatted string.
161- * Int column interpreted as number of seconds since Unix epoch.
162- * Double column interpreted as a Julian day (number of days since November 24, 4713 BC).
163-
164- Because of this ambiguity, the `@Table` macro does not know what you intend when you define a data
165- type like this:
166-
167- ```swift
168- @Table struct Reminder {
169- let id: Int
170- var date: Date // 🛑 'Date' column requires a query representation
171- }
172- ```
173-
174- In order to make it explicit how you expect to turn a `Date` into a type that SQLite understands
175- (_i.e._ text, integer, or double) you can use the `@Column` macro with the `as:` argument. The
176- library comes with 3 strategies out the box to help, ``Foundation/Date/ISO8601Representation`` for
177- storing the date as a string, ``Foundation/Date/UnixTimeRepresentation`` for storing the date as an
178- integer, and ``Foundation/Date/JulianDayRepresentation`` for storing the date as a floating point
179- number.
180-
181- Any of these representations can be used like so:
182-
183- ```swift
184- @Table struct Reminder {
185- let id: Int
186- @Column(as: Date.ISO8601Representation.self)
187- var date: Date
188- }
189- ```
190-
191- And StructuredQueries will take care of formatting the value for the database:
192-
193- @Row {
194- @Column {
195- ```swift
196- Reminder.insert(
197- Reminder.Draft(date: Date())
198- )
199- ```
200- }
201- @Column {
202- ```sql
203- INSERT INTO " reminders"
204- (" date " )
205- VALUES
206- ('2018-01-29 00:08:00.000')
207- ```
208- }
209- }
210-
211- When querying against a date column with a Swift date, you will need to explicitly bundle up the
212- Swift date into the appropriate representation to use various query helpers. This can be done using
213- the `#bind` macro:
214-
215- ```swift
216- Reminder.where { $0.created > #bind(startDate) }
217- ```
218-
219- #### UUID
220-
221- SQLite also does not have native support for UUIDs. If you try to use a UUID in your tables you
222- will get an error:
223-
224- ```swift
225- @Table struct Reminder {
226- let id: UUID // 🛑 'UUID' column requires a query representation
227- var title = " "
228- }
229- ```
230-
231- To use such identifiers in your table you can store the column as a data blob, and then you can
232- use the ``Foundation/UUID/BytesRepresentation`` column representation:
233-
234- ```swift
235- @Table struct Reminder {
236- @Column(as: UUID.BytesRepresentation.self)
237- let id: UUID
238- var title = " "
239- }
240- ```
241-
242- Alternatively you can store the column as text and use either
243- ``Foundation/UUID/LowercasedRepresentation`` or ``Foundation/UUID/UppercasedRepresentation`` to
244- translate the UUID to text:
245-
246- ```swift
247- @Table struct Reminder {
248- @Column(as: UUID.LowercasedRepresentation.self)
249- let id: UUID
250- var title = " "
251- }
252- ```
253-
254- When querying against a UUID column with a Swift UUID, you will need to explicitly bundle up the
255- Swift UUID into the appropriate representation to use various query helpers. This can be done using
256- the `#bind` macro:
257-
258- ```swift
259- Reminder.where { $0.id != #bind(reminder.id) }
260- ```
261-
262166#### RawRepresentable
263167
264168Simple data types, in particular ones conforming to `RawRepresentable` whose `RawValue` is a string
@@ -353,6 +257,106 @@ With that you can insert reminders with notes like so:
353257 }
354258}
355259
260+ #### Default representations for dates and UUIDs
261+
262+ While some relational databases, like MySQL and Postgres, have native types for dates and UUIDs,
263+ SQLite does _not_, and instead can represent them in a variety of ways. In order to lessen the
264+ friction of building queries with dates and UUIDs, the library has decided to provide a default
265+ representation for dates and UUIDs, and if that choice does not fit your schema you can explicitly
266+ specify the representation you want.
267+
268+ ##### Dates
269+
270+ Dates in SQLite have 3 different representations:
271+
272+ * Text column interpreted as ISO-8601-formatted string.
273+ * Int column interpreted as number of seconds since Unix epoch.
274+ * Double column interpreted as a Julian day (number of days since November 24, 4713 BC).
275+
276+ By default, StructuredQueries will bind and decode dates as ISO-8601 text. If you want the library
277+ to use a different representation (_i.e._ integer or double), you can provide an explicit query
278+ representation to the `@Column` macro's `as:` argument. ``Foundation/Date/UnixTimeRepresentation``
279+ will store the date as an integer, and ``Foundation/Date/JulianDayRepresentation`` will store the
280+ date as a floating point number.
281+
282+ For example:
283+
284+ ```swift
285+ @Table struct Reminder {
286+ let id: Int
287+ @Column(as: Date.UnixTimeRepresentation.self)
288+ var date: Date
289+ }
290+ ```
291+
292+ And StructuredQueries will take care of formatting the value for the database:
293+
294+ @Row {
295+ @Column {
296+ ```swift
297+ Reminder.insert(
298+ Reminder.Draft(date: Date())
299+ )
300+ ```
301+ }
302+ @Column {
303+ ```sql
304+ INSERT INTO " reminders"
305+ (" date " )
306+ VALUES
307+ (1517184480)
308+ ```
309+ }
310+ }
311+
312+ If you use the non-default date representation in your schema, then while querying against a
313+ date column with a Swift Date, you will need to explicitly bundle up the Swift date into the
314+ appropriate representation to use various query helpers. This can be done using the `#bind` macro:
315+
316+ ```swift
317+ Reminder.where { $0.created > #bind(startDate) }
318+ ```
319+
320+ > Note: When using the default representation for dates (ISO-8601 text) you do not need to use
321+ > the `#bind` macro:
322+ >
323+ > ```swift
324+ > Reminder.where { $0.created > startDate }
325+ > ```
326+
327+ ##### UUIDs
328+
329+ SQLite also does not have type-level support for UUIDs. By default, the library will bind and decode
330+ UUIDs as lowercased, hexadecimal text, but it also provides custom representations. This includes
331+ ``Foundation/UUID/UppercasedRepresentation`` for uppercased text, as well as
332+ ``Foundation/UUID/BytesRepresentation`` for raw bytes.
333+
334+ To use such custom representations, you can provide it to the `@Column` macro's `as:` parameter:
335+
336+ ```swift
337+ @Table struct Reminder {
338+ @Column(as: UUID.BytesRepresentation.self)
339+ let id: UUID
340+ var title = " "
341+ }
342+ ```
343+
344+ If you use the non-default UUID representation in your schema, then while querying against a UUID
345+ column with a Swift UUID, you will need to explicitly bundle up the Swift UUID into the appropriate
346+ representation to use various query helpers. This can be done using
347+ the `#bind` macro:
348+
349+ ```swift
350+ Reminder.where { $0.id != #bind(reminder.id) }
351+ ```
352+
353+ > Note: When using the default representation for UUID (lower-cased text) you do not need to use
354+ > the `#bind` macro:
355+ >
356+ > ```swift
357+ > Reminder.where { $0.id != reminder.id }
358+ > ```
359+
356360### Primary keyed tables
357361
358362It is possible to tell let the `@Table` macro know which property of your data type is the primary
0 commit comments