Merge pull request #224 from vapor/sqlite

sqlite 3
This commit is contained in:
Tanner 2017-10-04 13:35:58 -04:00 committed by GitHub
commit 99f440d44f
7 changed files with 346 additions and 1 deletions

View File

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg
width="50px"
height="50px"
viewBox="0 0 50 50"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
>
<title>Vapor</title>
<desc>The Vapor droplet logo in pink and blue.</desc>
<defs>
<linearGradient
x1="1.11022302e-14%"
y1="5.88522518%"
x2="1.11022302e-14%"
y2="59.5616958%"
id="pink-and-blue"
>
<stop stop-color="#F7CAC9" offset="0%"></stop>
<stop stop-color="#92A8D1" offset="100%"></stop>
</linearGradient>
</defs>
<g id="droplet" fill="url(#pink-and-blue)">
<path
d="M17.6186417,50 C17.6186417,50 35.2941176,27.6875238 35.2941176,17.8366268 C35.2941176,7.98572985 27.3932603,0 17.6470588,0 C7.90085736,0 0,7.98572985 0,17.8366268 C0,27.6875238 17.6186417,50 17.6186417,50 Z"
transform="translate(17.647059, 25.000000) scale(1, -1) translate(-17.647059, -25.000000)"
></path>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg
width="50px"
height="50px"
viewBox="0 0 50 50"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
>
<title>Vapor</title>
<desc>The Vapor droplet logo in white.</desc>
<g id="droplet" fill="#FFFFFF">
<path
d="M17.6186417,50 C17.6186417,50 35.2941176,27.6875238 35.2941176,17.8366268 C35.2941176,7.98572985 27.3932603,0 17.6470588,0 C7.90085736,0 0,7.98572985 0,17.8366268 C0,27.6875238 17.6186417,50 17.6186417,50 Z"
transform="translate(17.647059, 25.000000) scale(1, -1) translate(-17.647059, -25.000000)"
></path>
</g>
</svg>

After

Width:  |  Height:  |  Size: 699 B

203
3.0/docs/sqlite/overview.md Normal file
View File

@ -0,0 +1,203 @@
# SQLite Overview
Let's dive into the [vapor/sqlite](https://github.com/vapor/sqlite) package and
see how to connect to and query a database.
!!! warning
This documentation provides an overview for the SQLite API.
If you are using SQLite with Fluent, you will likely never need to use
this API. Use [Fluent's APIs](../fluent/overview.md) instead.
Follow the instructions in the [package](package.md) section to add the SQLite package to your project. Once its added, you should be able to use `import SQLite.`
## Database
The first step to making a query is to create a `Database`.
### In Memory
In-memory SQLite databases are great for testing as they aren't persisted between application boots.
```swift
import SQLite
let db = Database(storage: .memory)
```
### File path
SQLite requires a single file to persist the database contents.
```swift
import SQLite
let db = Database(storage: .file(path: "/tmp/db.sqlite"))
```
!!! tip
If the database file does not already exist, it will be created.
## Connection
Once you have initialized your database, you can create a connection.
```swift
let conn = try db.makeConnection(on: .global())
```
!!! note
Pay special attention to which `DispatchQueue` you pass to `makeConnection(on:)`.
This will be the queue SQLite calls you back on.
!!! tip
If you are using SQLite with Vapor, make sure to pass the [worker](async/worker.md)'s queue here.
## Query
Once you have a `Connection`, you can use it to create a `Query`.
```swift
let query = conn.query("SELECT * FROM users")
```
### Binding Values
If you are executing a query that has input values, you should bind these using parameters.
```swift
let query = conn.query("INSERT INTO users (name, age) VALUES (?, ?)")
query.bind("Albert")
query.bind(138)
```
You can also bind values using method chaining.
```swift
let query = conn.query("INSERT INTO users (name, age) VALUES (?, ?)")
.bind("Albert")
.bind(138)
```
### Output Stream
If you expect output from your query, you must attach a stream. The easiest way
to do this is by using the `drain` convenience.
```swift
query.drain { row in
print(row)
}
```
You can also use `drain(into:)` and pass in a custom `InputStream` to capture the query's results.
#### Row
The `Query` will output `Row`s. These are simple structs.
```swift
struct Row {
var fields: [String: Field]
subscript(field: String) -> Data? { get }
}
```
You can subscript a `Row` object to get the optional `Data`.
```swift
let nameData = row["name"] // Data?
```
`Data` is an enum that contains all possible types of SQLite data.
```swift
public enum Data {
case integer(Int)
case float(Double)
case text(String)
case blob(Foundation.Data)
case null
}
```
For each option, there are convenience properties for casting the `Data` enum.
```swift
let name = row["name"]?.text // String
```
### Run
Once your query is ready to execute, you simply call `.execute()`. This returns a `Future<Void>`
that will be completed when the query is done executing.
```swift
query.execute().then {
print("done!")
}
```
#### All
If you simply want to fetch all of the results, you can use the `.all()` convenience.
This will automatically create a stream and return a future containing your results.
```swift
query.all().then { rows in
print(rows)
}
```
#### Sync
For situations where blocking is appropriate (perhaps in tests) you can use `.sync()` to block
until the query's results are ready and return them directly.
```swift
// don't do this unless blocking is OK
let rows = try conn.query("SELECT * FROM users").sync()
```
### Example
Now for the complete example:
```swift
import SQLite
let db = Database(storage: .memory)
let conn = try db.makeConnection(on: .global()) // take care to use correct queue
conn.query("SELECT * FROM users")
.all()
.then { rows in
print(rows)
}
.catch { err in
print(err)
}
// wait for results
```
An example with values being bound:
```swift
import SQLite
let db = Database(storage: .memory)
let conn = try db.makeConnection(on: .global()) // take care to use correct queue
conn.query("INSERT INTO users (name, age) VALUES (?, ?)")
.bind("Albert")
.bind(138)
.execute()
.then {
print("done")
}
.catch { err in
print(err)
}
// wait for results
```

View File

@ -0,0 +1,43 @@
# Using SQLite
The [vapor/sqlite](https://github.com/vapor/sqlite) package is a lightweight, nonblocking/async wrapper around SQLite 3's C API. It provides an intuitive Swift interface for working with SQLite that can be used with any Swift project.
On top of `[vapor/sqlite](https://github.com/vapor/sqlite)`, we have built `[vapor/fluent-sqlite](https://github.com/vapor/fluent-sqlite)`. This package conforms our SQLite wrapper to Fluent's [driver](fluent/driver.md) protocol, allowing SQLite databases to be used with Fluent.
## With Fluent
This package is included with Fluent by default, and serves as Fluent's default database type. To use SQLite with Fluent, just [include Fluent])(fluent/package.md) in your project.
Then use the following to import `SQLite`.
```swift
import SQLite
```
If you need access to the Fluent driver specifically, use:
```swift
import FluentSQLite
```
## Without Fluent
This package was built to be a powerful interface for SQLite whether or not you use Fluent. To include this SQLite package in your project, simply add it to your Package manifest.
```swift
// swift-tools-version:4.0
import PackageDescription
let package = Package(
name: "Project",
dependencies: [
...
.package(url: "https://github.com/vapor/sqlite.git", .upToNextMajor(from: "3.0.0")),
],
targets: [
.target(name: "Project", dependencies: ["Async", ... ])
]
)
```
Use `import SQLite` to access the Swift SQLite APIs.

View File

@ -0,0 +1,48 @@
.md-header {
box-shadow: 0px 0px 8px #657590!important;
}
.md-main__inner {
padding-top: 0;
}
.md-nav__button img {
width: 90%;
}
.md-logo {
padding: 6px;
}
.md-sidebar__inner .md-logo {
width: 60px!important;
}
.md-header-nav__title {
line-height: 4.6rem;
}
@media only screen and (min-width:75em) {
.md-header-nav__button img {
width: 28px!important;
height: 28px!important;
}
.md-main__inner {
padding-top: 1rem;
}
}
@media only screen and (min-width:100em) {
.md-header-nav__button img {
width: 32px!important;
height: 32px!important;
}
}
@media only screen and (min-width:125em) {
.md-header-nav__button img {
width: 38px!important;
height: 38px!important;
}
}

View File

@ -10,7 +10,7 @@ pages:
- 'Route Collection': 'vapor/route-collection.md'
- 'Route Group': 'vapor/route-group.md'
- Async:
- 'Index': 'async/index.md'
- 'Package': 'async/package.md'
- 'Promise & Future': 'async/promise-future.md'
- 'Stream': 'async/stream.md'
- HTTP:
@ -45,6 +45,9 @@ pages:
- 'Message authentication': 'crypto/mac.md'
- 'Password hashing': 'crypto/passwords.md'
- 'Random': 'crypto/random.md'
- SQLite:
- 'Package': 'sqlite/package.md'
- 'Overview': 'sqlite/overview.md'
# - 'Advanced':
# - 'RequestParser': 'http/request-parser.md'
# - 'RequestSerializer': 'http/request-serializer.md'