Skip to content

Commit 52e4e1f

Browse files
authored
Update README.md
1 parent 0f206dd commit 52e4e1f

1 file changed

Lines changed: 53 additions & 8 deletions

File tree

README.md

Lines changed: 53 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
Otter is a pure Swift SQL compiler that allow developers to write plain compile time safe SQL.
1717

1818
- [Installation](#installation)
19+
- [Macros](#or-use-the-swift-macro)
1920
- [Queries](#queries)
2021
- [Types](#types)
2122
- [Operators](#operators)
@@ -103,6 +104,14 @@ that won't scale well beyond a fairly simple schema and a handfull of queries.
103104
# Installation
104105
Otter supports Swift Package Manager. To install add the following to your `Package.swift` file.
105106

107+
> [!TIP]
108+
> If don't want to read any of the README, here are some quick tips:
109+
> * Use singular table names, it is the SQL standard.
110+
> * Orgranize queries in files by usage, not by table.
111+
> * Use `SELECT table.*` to embed the table structs within the results
112+
> * Inject queries and avoid the repository pattern
113+
> * Let SQL answer the questions about your data. Many queries are perfectly fine
114+
106115
```swift
107116
let package = Package(
108117
[...]
@@ -140,7 +149,7 @@ feather gen
140149

141150
This will compile and check all migrations and queries, then generate all Swift required to talk to the database.
142151

143-
#### Adding a New Migration
152+
### Adding a New Migration
144153
When a new migration is needed, you can simply add a new file with a number 1 higher than the previous. To automatically do this the cli tool can do it for you by running
145154
```
146155
feather migrate add
@@ -173,22 +182,51 @@ All queries will be stored in the `/Queries` directory. More than one query can
173182
feather queries add --name <some-name>
174183
```
175184

176-
> [!TIP]
177-
> Organize queries by usage, not by table. This will become more useful later on when we talk about dependency injection.
178-
179-
Open the file that was created in `/Queries`, it should be blank. Individual queries can be defined using the `DEFINE` keyword. At the moment queries can only have one statement.
185+
Open the file that was created in `/Queries`, it should be blank. Individual queries can be defined using the the following format. At the moment a single query can only have one statement.
180186
```sql
181187
fetchUsers:
182188
SELECT * FROM user;
189+
190+
-- Or optionally supply either an input or output name
191+
fetchUsers(input: InputName, output: OutputName):
192+
SELECT * FROM user;
183193
```
184194

185-
If the queries file was named `User.sql` this would be accessible via
195+
> [!TIP]
196+
> Organize queries by usage, not by table.
197+
> This will allow queries to be injected together
198+
199+
Each queries file will get it's own `Queries` types generated. To allow the queries defined in a file to be
200+
passed around and injected together. For example, if we have a `Library.sql` the following types will be generated:
186201
```swift
187-
let query: any FetchUsersQuery = database.userQueries.fetchUsers
188-
let users: [User] = try await query.execute()
202+
// Protocol that defines all queries in the file
203+
let queries: any LibraryQueriesType = database.libraryQueries
204+
205+
// Concrete implementaion
206+
let concreteType: LibraryQueriesImpl
207+
208+
// NO-OP version, can be injected into unit tests/previews
209+
let noopType: LibraryQueriesNoop
210+
```
211+
212+
For the `Noop` queries, we can override any query optionally. Each query be default will return `nil` or an empty `[]`. To override a query you can set it in the initializer.
213+
```swift
214+
LibraryQueriesNoop(getLibrary: Queries.Just([...]))
189215
```
190216

191217
### Input and Output Types
218+
Otter will, if needed, generate types for the inputs and outputs. If a type is a single primitive it will be mapped to the Swift equivalent.
219+
```sql
220+
-- Will return the User struct
221+
fetchUsers:
222+
SELECT * FROM user;
223+
224+
-- Will generate a type for the id and name
225+
fetchUserIdAndNames:
226+
SELECT id, name FROM user;
227+
```
228+
229+
#### Embedding Table Structs
192230
In the example above, since we selected all columns from a single table the query will return the `User` struct that was generated for the table. If additional columns are selected a new structure will be generated to match the selected columns. In the following example we will join in the `post` table to get a users post count.
193231
```sql
194232
fetchUsers:
@@ -319,3 +357,10 @@ class ViewModel {
319357
let query: any LatestExpensesQuery
320358
}
321359
```
360+
361+
## Upcoming Features
362+
* Support for multiple statements in a single query
363+
* Kotlin library/generation
364+
365+
## Contributions
366+
Contributions are welcome and encouraged! Feel free to make a PR or open an issue. If the change is large please open an issue first to make sure the change is desired.

0 commit comments

Comments
 (0)