update todo examples to 0.4 and use migrations

* update tests/x.py

 * add examples/x.py
This commit is contained in:
Ryan Leckey 2020-07-18 05:43:16 -07:00
parent 820618f396
commit 96b76dc737
26 changed files with 480 additions and 236 deletions

1
.gitignore vendored
View file

@ -9,4 +9,3 @@ target/
# Environment
.env
!tests/.env

1
examples/.gitignore vendored Normal file
View file

@ -0,0 +1 @@
sqlite/todos/todos.db

View file

@ -1,29 +1,41 @@
# TODOs Example
## Setup
1. Declare the database URL
```
export DATABASE_URL="mysql://root:password@localhost/todos"
```
2. Create the database.
```
$ sqlx db create
```
3. Run sql migrations
```
$ sqlx migrate run
```
## Usage
Declare the database URL:
Add a todo
```
export DATABASE_URL="mysql://localhost/todos"
cargo run -- add "todo description"
```
Connect to `mysql` and create the database:
Complete a todo.
```
$ mysql
mysql> CREATE DATABASE todos;
cargo run -- done <todo id>
```
Load the database schema (using the MySQL CLI interface thats already open):
List all todos
```
mysql> USE todos;
mysql> source schema.sql
cargo run
```
Use `exit` to exit the MySQL CLI. Then, to run this example:
- Add a todo: `cargo run -- add "todo description"`
- Complete a todo: `cargo run -- done <todo id>`
- List all todos: `cargo run`

View file

@ -1,5 +1,6 @@
CREATE TABLE IF NOT EXISTS todos (
CREATE TABLE IF NOT EXISTS todos
(
id BIGINT UNSIGNED PRIMARY KEY NOT NULL AUTO_INCREMENT,
description TEXT NOT NULL,
description TEXT NOT NULL,
done BOOLEAN NOT NULL DEFAULT FALSE
);

View file

@ -1,5 +1,5 @@
use anyhow::Context;
use sqlx::MySqlPool;
use sqlx::mysql::MySqlPool;
use sqlx::Done;
use std::env;
use structopt::StructOpt;
@ -18,10 +18,7 @@ enum Command {
#[async_std::main]
#[paw::main]
async fn main(args: Args) -> anyhow::Result<()> {
let pool = MySqlPool::new(
&env::var("DATABASE_URL").context("`DATABASE_URL` must be set to run this example")?,
)
.await?;
let pool = MySqlPool::connect(&env::var("DATABASE_URL")?).await?;
match args.cmd {
Some(Command::Add { description }) => {
@ -47,8 +44,8 @@ async fn main(args: Args) -> anyhow::Result<()> {
}
async fn add_todo(pool: &MySqlPool, description: String) -> anyhow::Result<u64> {
// Insert the TODO, then obtain the ID of this row
sqlx::query!(
// Insert the task, then obtain the ID of this row
let todo_id = sqlx::query!(
r#"
INSERT INTO todos ( description )
VALUES ( ? )
@ -56,13 +53,10 @@ VALUES ( ? )
description
)
.execute(pool)
.await?;
.await?
.last_insert_id();
let rec: (u64,) = sqlx::query_as("SELECT LAST_INSERT_ID()")
.fetch_one(pool)
.await?;
Ok(rec.0)
Ok(todo_id)
}
async fn complete_todo(pool: &MySqlPool, id: u64) -> anyhow::Result<bool> {
@ -75,7 +69,8 @@ WHERE id = ?
id
)
.execute(pool)
.await?;
.await?
.rows_affected();
Ok(rows_affected > 0)
}

View file

@ -1,29 +1,41 @@
# TODOs Example
## Setup
1. Declare the database URL
```
export DATABASE_URL="postgres://postgres:password@localhost/todos"
```
2. Create the database.
```
$ sqlx db create
```
3. Run sql migrations
```
$ sqlx migrate run
```
## Usage
Declare the database URL:
Add a todo
```
export DATABASE_URL="postgres://postgres@localhost/todos"
cargo run -- add "todo description"
```
Create the database:
Complete a todo.
```
createdb -U postgres todos
cargo run -- done <todo id>
```
Load the database schema:
List all todos
```
psql -d "$DATABASE_URL" -f ./schema.sql
cargo run
```
Run:
- Add a todo: `cargo run -- add "todo description"`
- Complete a todo: `cargo run -- done <todo id>`
- List all todos: `cargo run`

View file

@ -1,5 +1,6 @@
CREATE TABLE IF NOT EXISTS todos (
CREATE TABLE IF NOT EXISTS todos
(
id BIGSERIAL PRIMARY KEY,
description TEXT NOT NULL,
description TEXT NOT NULL,
done BOOLEAN NOT NULL DEFAULT FALSE
);

View file

@ -1,5 +1,5 @@
use anyhow::Context;
use sqlx::PgPool;
use sqlx::postgres::PgPool;
use sqlx::Done;
use std::env;
use structopt::StructOpt;
@ -18,10 +18,7 @@ enum Command {
#[async_std::main]
#[paw::main]
async fn main(args: Args) -> anyhow::Result<()> {
let mut pool = PgPool::new(
&env::var("DATABASE_URL").context("`DATABASE_URL` must be set to run this example")?,
)
.await?;
let pool = PgPool::connect(&env::var("DATABASE_URL")?).await?;
match args.cmd {
Some(Command::Add { description }) => {
@ -39,14 +36,14 @@ async fn main(args: Args) -> anyhow::Result<()> {
}
None => {
println!("Printing list of all todos");
list_todos(&mut pool).await?;
list_todos(&pool).await?;
}
}
Ok(())
}
async fn add_todo(mut pool: &PgPool, description: String) -> anyhow::Result<i64> {
async fn add_todo(pool: &PgPool, description: String) -> anyhow::Result<i64> {
let rec = sqlx::query!(
r#"
INSERT INTO todos ( description )
@ -55,13 +52,13 @@ RETURNING id
"#,
description
)
.fetch_one(&mut pool)
.fetch_one(pool)
.await?;
Ok(rec.id)
}
async fn complete_todo(mut pool: &PgPool, id: i64) -> anyhow::Result<bool> {
async fn complete_todo(pool: &PgPool, id: i64) -> anyhow::Result<bool> {
let rows_affected = sqlx::query!(
r#"
UPDATE todos
@ -70,8 +67,9 @@ WHERE id = $1
"#,
id
)
.execute(&mut pool)
.await?;
.execute(pool)
.await?
.rows_affected();
Ok(rows_affected > 0)
}

View file

@ -1,27 +1,41 @@
# TODOs Example
## Setup
1. Declare the database URL
```
export DATABASE_URL="sqlite:todos.db"
```
2. Create the database.
```
$ sqlx db create
```
3. Run sql migrations
```
$ sqlx migrate run
```
## Usage
Declare the database URL:
Add a todo
```
export DATABASE_URL="sqlite:///path/to/this/directory/todos.db"
cargo run -- add "todo description"
```
Create the database:
Complete a todo.
```
sqlite3 todos.db
cargo run -- done <todo id>
```
Load the database schema (using the SQLite CLI interface opened from the previous command):
List all todos
```
sqlite> .read schema.sql
cargo run
```
Use `.exit` to leave the SQLite CLI. Then, to run this example:
- Add a todo: `cargo run -- add "todo description"`
- Complete a todo: `cargo run -- done <todo id>`
- List all todos: `cargo run`

View file

@ -0,0 +1,6 @@
CREATE TABLE IF NOT EXISTS todos
(
id INTEGER PRIMARY KEY NOT NULL,
description TEXT NOT NULL,
done BOOLEAN NOT NULL DEFAULT 0
);

View file

@ -1,5 +0,0 @@
CREATE TABLE IF NOT EXISTS todos (
id INTEGER PRIMARY KEY NOT NULL,
description TEXT NOT NULL,
done BOOLEAN NOT NULL DEFAULT 0
);

View file

@ -1,5 +1,5 @@
use anyhow::Context;
use sqlx::SqlitePool;
use sqlx::sqlite::SqlitePool;
use sqlx::Done;
use std::env;
use structopt::StructOpt;
@ -18,10 +18,7 @@ enum Command {
#[async_std::main]
#[paw::main]
async fn main(args: Args) -> anyhow::Result<()> {
let pool = SqlitePool::new(
&env::var("DATABASE_URL").context("`DATABASE_URL` must be set to run this example")?,
)
.await?;
let pool = SqlitePool::connect(&env::var("DATABASE_URL")?).await?;
match args.cmd {
Some(Command::Add { description }) => {
@ -49,22 +46,19 @@ async fn main(args: Args) -> anyhow::Result<()> {
async fn add_todo(pool: &SqlitePool, description: String) -> anyhow::Result<i64> {
let mut conn = pool.acquire().await?;
// Insert the TODO, then obtain the ID of this row
sqlx::query!(
// Insert the task, then obtain the ID of this row
let id = sqlx::query!(
r#"
INSERT INTO todos ( description )
VALUES ( $1 )
VALUES ( ?1 )
"#,
description
)
.execute(&mut conn)
.await?;
.await?
.last_insert_rowid();
let rec: (i64,) = sqlx::query_as("SELECT last_insert_rowid()")
.fetch_one(&mut conn)
.await?;
Ok(rec.0)
Ok(id)
}
async fn complete_todo(pool: &SqlitePool, id: i64) -> anyhow::Result<bool> {
@ -72,12 +66,13 @@ async fn complete_todo(pool: &SqlitePool, id: i64) -> anyhow::Result<bool> {
r#"
UPDATE todos
SET done = TRUE
WHERE id = $1
WHERE id = ?1
"#,
id
)
.execute(pool)
.await?;
.await?
.rows_affected();
Ok(rows_affected > 0)
}

87
examples/x.py Executable file
View file

@ -0,0 +1,87 @@
#!/usr/bin/env python3
import sys
import os
from os import path
# base dir of sqlx workspace
dir_workspace = path.dirname(path.dirname(path.realpath(__file__)))
# dir of tests
dir_tests = path.join(dir_workspace, "tests")
# extend import path to tests/
sys.path.append(dir_tests)
import subprocess
import time
import argparse
from docker import start_database
parser = argparse.ArgumentParser()
parser.add_argument("-p", "--project")
parser.add_argument("-l", "--list-projects", action="store_true")
argv, unknown = parser.parse_known_args()
def run(command, env=None, cwd=None, display=None):
if display:
print(f"\x1b[93m $ {display}\x1b[0m")
else:
print(f"\x1b[93m $ {command}\x1b[0m")
res = subprocess.run(
command.split(" "),
env=dict(**os.environ, **env),
cwd=cwd,
)
if res.returncode != 0:
sys.exit(res.returncode)
def sqlx(command, url, cwd=None):
run(f"cargo --quiet run -p sqlx-cli --bin sqlx -- {command}", cwd=cwd, env={"DATABASE_URL": url},
display=f"sqlx {command}")
def project(name, database=None, driver=None):
if argv.list_projects:
print(f"{name}")
return
if argv.project and name != argv.project:
return
print(f"\x1b[2m # {name}\x1b[0m")
env = {}
cwd = path.join(dir_workspace, "examples", name)
if database is not None:
database_url = start_database(driver, database, cwd=cwd)
env["DATABASE_URL"] = database_url
# show the database url
print(f"\x1b[94m @ {database_url}\x1b[0m")
# database drop (if exists)
sqlx("db drop -y", database_url, cwd=cwd)
# database create
sqlx("db create", database_url, cwd=cwd)
# migrate
sqlx("migrate run", database_url, cwd=cwd)
# check
run("cargo check", cwd=cwd, env=env)
# todos
project("mysql/todos", driver="mysql_8", database="todos")
project("postgres/todos", driver="postgres_12", database="todos")
project("sqlite/todos", driver="sqlite", database="todos.db")

2
tests/.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
!.env
__pycache__

View file

@ -1,21 +1,28 @@
-----BEGIN CERTIFICATE-----
MIIDdTCCAl2gAwIBAgIUDlkBz/x3GgypHOBLD9grAx2DQT0wDQYJKoZIhvcNAQEL
BQAwSjELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFDASBgNVBAoM
C0xhdW5jaEJhZGdlMRAwDgYDVQQDDAdzcWx4LWNhMB4XDTIwMDUyMjA2NDEzNFoX
DTQ3MTAwNzA2NDEzNFowSjELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3Ju
aWExFDASBgNVBAoMC0xhdW5jaEJhZGdlMRAwDgYDVQQDDAdzcWx4LWNhMIIBIjAN
BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwiG50Cfhp/3jRRF2Zk+bWsFe52S4
s+xfGX6NoQwWZRUWqUuiYNXDXPX82lMXcdoTV8U/QgKAG7P19zwPN2q+pNPdd6S1
t1SSJP5ozaQRHFxwVGwj99Nu7La/00Qo0P4VI5kldISHz0fFA6BBT7XGSKwRQj0N
gk7Gc2Si5EG3WTaAkz5A+jsbBBzJ4CrqK/O2jHRJDExeptxKu4tY5RkX1lI9HAvm
AUMPtlguEdldWJo5qOOpytEEyhnDRbiat4hNV68UzsYB5AUucRXgatgENCoADQf/
qEqFU0RjFml72H4RHxY2iPGEF+GPxVm/u2wnJHOSQ/fUO1x+kcGEXJ5Z+wIDAQAB
o1MwUTAdBgNVHQ4EFgQUeHc1DDZ2/SJwIjFk4QkuiyXJiyQwHwYDVR0jBBgwFoAU
eHc1DDZ2/SJwIjFk4QkuiyXJiyQwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0B
AQsFAAOCAQEAO5lYFNaFwYjSkSzO19xery699gdzAFKrDxVrKg1Pybatiz6WXMRp
O/5wo61wXg3qMFhj5WdKj0A/nbkGnLoFgW99nw1V7vDqEba5FDfautZNnImIpNkg
WPXN7NRlVBDBKKg+Vx0DFBo9ucAa11gwT+eSdLf4GCwQW8NahmloOorDbg0/CAPw
65duNS260+LsHXqb9jlxB2KXCi6GhenwyIglGtT9g3vh5ntIH53fr1P1aP+zup6b
Atry/KLvi+qLWtgWQwPGDlsft7ieBU0mpX+avs9lKmtwkxaFOfG5aHylxjbC1mKa
v497AO7TATCTsHhCaWgkIg4GAT61fUK9iA==
MIIEzTCCAzWgAwIBAgIQFN6Kw8UmgcAAAGlENSADBzANBgkqhkiG9w0BAQsFADB/
MR4wHAYDVQQKExVta2NlcnQgZGV2ZWxvcG1lbnQgQ0ExKjAoBgNVBAsMIW1laGNv
ZGVAR29sZW0ubG9jYWwgKFJ5YW4gTGVja2V5KTExMC8GA1UEAwwobWtjZXJ0IG1l
aGNvZGVAR29sZW0ubG9jYWwgKFJ5YW4gTGVja2V5KTAeFw0yMDA3MTgxMjE1NDla
Fw0zMDA3MTgxMjE1NDlaMH8xHjAcBgNVBAoTFW1rY2VydCBkZXZlbG9wbWVudCBD
QTEqMCgGA1UECwwhbWVoY29kZUBHb2xlbS5sb2NhbCAoUnlhbiBMZWNrZXkpMTEw
LwYDVQQDDChta2NlcnQgbWVoY29kZUBHb2xlbS5sb2NhbCAoUnlhbiBMZWNrZXkp
MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAnElV+r9IY3H3jBM72Og3
MINManqh2VpBvbn6ZlQiYKsyeRiK0hyx+7PugJiw8NW60rHI9z4P4ie5pyCsXQ/F
3dkAmEuliFGOR3NclzUtBu/K3eYrwafO57cLc/k/1skcqV4p8Q4XILsRP25TiSJp
O3Q3Oq70t/unZRONKHUsQfag1z79xW36w09mnFMYTBUKQB1QcaZnGZ0xFyp6jk+w
Z0molgMSDiJS3gWP0zdSGRHVL+eR/072EqYBZ6ycSlfh1XlaP4SM9DMR5K/X9Iwi
AQCSWFPAksUoSLrG/+pyHYWtcelj7u6NNRxIcW6DiyF+HgeSx9YJTnYq0eP9zqbb
gBEhaPz6bnTTzJo6+peyHLHaClxx3K9l6oDK2Z2ZMVLXw4oDcwep6JHdBh2w4MCz
r7DiopNHrnZ3flSz0msy2bf/aZ5k1TzjtmQDzJ8Ln+UlKdqyyA6UOZGA1yyYPS4j
B5EwY/G1bh/1onxHD5h2yBEDtF9mEhXEigioRB/C1W9JAgMBAAGjRTBDMA4GA1Ud
DwEB/wQEAwICBDASBgNVHRMBAf8ECDAGAQH/AgEAMB0GA1UdDgQWBBT0YKcYJw+Y
op0QUrxexXHJ+ond9DANBgkqhkiG9w0BAQsFAAOCAYEAIoDIJo9eQ4Ifs0oxvwVR
CRlZ/VZLm23dMSpMr5BLP/MvUP8W4wQY5Q2U3UO2RSABiJqLiZhS8XSPMzy7o9Ha
wqbnXRbrX6TkYLrQT5pvZwImOis6+zYl2uMo3BS1wMTllNhQBAC+SqCrM+t3E5xD
oasKmaqVo0flWSrHpU/hTVJLrU1rE00ghxVGjiAXoi+JvN718zI7hiIeHh+ikJlW
qEVqtcaPdBKUoaf0c/xDGo/+aEr8BhPcEx5XLjvDiLdc0lHfmt3rRKCrJh8aDoMm
8PpYZwx7zc+CG4BDY+Bz6kZ5VCSd9RQ3XNjJEd25tgd3IDuiXQGp5CQoVOCQQyKv
QKKhy87ZsThgcHZUR36KHXXLdRy2uAT36G2+HKdzjVTgS5nlYIdBJFi5Fvc+3Syb
vM3rhXbJtg0HPZCHmzIRwLqdhyKEKxEKUy9DfkoO1RtXWLS0+1uDDdmZYLQ2qTC2
/CtEMstXpen5DIy5P1lX8ycUF/UDHOAd6ba6KNul0tCo
-----END CERTIFICATE-----

View file

@ -1 +0,0 @@
1FCE7310D7E3C29BA5ED14EEF264E66C25727029

View file

@ -1,19 +1,25 @@
-----BEGIN CERTIFICATE-----
MIIDGDCCAgACFB/OcxDX48Kbpe0U7vJk5mwlcnApMA0GCSqGSIb3DQEBCwUAMEox
CzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRQwEgYDVQQKDAtMYXVu
Y2hCYWRnZTEQMA4GA1UEAwwHc3FseC1jYTAeFw0yMDA1MjIwNjQyNDJaFw00NzEw
MDcwNjQyNDJaMEcxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRQw
EgYDVQQKDAtMYXVuY2hCYWRnZTENMAsGA1UEAwwEc3FseDCCASIwDQYJKoZIhvcN
AQEBBQADggEPADCCAQoCggEBAM6rGt+k8fcURVGOIVpYcSpHYVJqvWaYEp+SGmvQ
KdMGjE1AHHwd6iT692G3hrZ4hHzvEmrWX4Cp7o9GEF1v912qVWxjUAuufJUFt8Jb
Xa6h0n/PDbgIqU5RQPoOnvlkLrE3fC+BYpBCy+TuEezrTINIOnKVUplYJWYJ78/u
nrensQOj/IeOF1kSeeF049nG7dnqEA+5qTMLAFTVacMIcGyDZX7AqDTsNpwy5QMq
fld1RRPOoNLTYcHq9q3a8XeVXONmxMGh9oatnsIIxGuw22exfvhJzNKgx/+5x6UI
2R+MRBdqz7UWksN37X/lhG8fm5a1zdvmaGC/JSfkaQAMM78CAwEAATANBgkqhkiG
9w0BAQsFAAOCAQEAsz7ty4bK9ml1YwRrWNcSAk0kmGufThhAYhMOu+7rfsV6V5x5
Eh+TvmBoLNFQ/i7LZdmVGTdp90co+FgLHtJ0j/HQguNou02VZ5/5GCSDsJWGxR+6
nZj9M8yP+thYapd7ndkWmjDBioTRKUVeQN8c3L8u6G+ElUJYImebaK2GxivPUCC0
ReHYTACYTf9GdgYYplYdNK+KiKpMLCKvB9f5sXI0Rk8pDXrQxoK34FacBttGdHek
Dbiq26LCszdwbUJhamvne8XFpNqAAh5WMA+b6bKH1OQpr+VNdkAsDZwuAj/MQqJE
vP7IzDLrnjy0fjeI0nW0J8/ch0+1BayJsz8aoQ==
MIIESDCCArCgAwIBAgIQODSVfo7ZFlBmT/IUqU7BmzANBgkqhkiG9w0BAQsFADB/
MR4wHAYDVQQKExVta2NlcnQgZGV2ZWxvcG1lbnQgQ0ExKjAoBgNVBAsMIW1laGNv
ZGVAR29sZW0ubG9jYWwgKFJ5YW4gTGVja2V5KTExMC8GA1UEAwwobWtjZXJ0IG1l
aGNvZGVAR29sZW0ubG9jYWwgKFJ5YW4gTGVja2V5KTAeFw0xOTA2MDEwMDAwMDBa
Fw0zMDA3MTgxMjE5MTNaMFUxJzAlBgNVBAoTHm1rY2VydCBkZXZlbG9wbWVudCBj
ZXJ0aWZpY2F0ZTEqMCgGA1UECwwhbWVoY29kZUBHb2xlbS5sb2NhbCAoUnlhbiBM
ZWNrZXkpMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAt2IFkflE4SVs
/WOwWjs4MHY+xIQt6LPqVpBLOeem7cm9ZdyHblojesZijV/4vbc4bwlksOBvJEkV
OSanMUimT9AMwjOzJBv0Yyj8ElCI+v/2y2QJ7JHVfn5pBTbk84+lugtgP8hW5ULj
tPDyE14E+8sNCXSa62C1a+lgssNLc+/EAGYQF4moQxIsZFuiI3EViLx4I6ayD/TY
r4U1HBFS8sY/rWDVSh82Bx85OZCK+06xbiMpzbi5b69WwsaOh16e/yJmEa2mQKbl
WZo3qT9LfMn5u1AX7KL7WKBeuohZkeI6sBMFcrO3yXGSmoSL07I2Ya2pSmJyMp8x
idGp06DwnQIDAQABo2owaDAOBgNVHQ8BAf8EBAMCBaAwEwYDVR0lBAwwCgYIKwYB
BQUHAwEwDAYDVR0TAQH/BAIwADAfBgNVHSMEGDAWgBT0YKcYJw+Yop0QUrxexXHJ
+ond9DASBgNVHREECzAJggdzcWx4LnJzMA0GCSqGSIb3DQEBCwUAA4IBgQAoGsn1
m5xYYo2I06NFhvoRqXfNhBH3W44hHjp6PjHqONW1U8KSM7lXbElNQ+tmCN8uThU6
RM+xY1bHB7rQxwGb0RxKqQphWJcBz9Or9vmqdam2rnBqza8B560MQSBv8kXCSKKY
SSpa/pRaWCbGLDgXs2RL6seBaT2S2qvRPRwxiyDPTPU3fkjyeQDw4nPCpQ/7+dtu
Cc7qg/NeUllW1wKYotTSxfo3FUR08Z73j1BFOoPvUgG1m8YWiDe90pQJDIAU059z
3IT4e2Jxm8yxudrlDdXmxBBLy4tA3drXYV654PoIszs1D+U6b84w3wE8/30Y8DyX
+InJUQ3kCFeZfS7a7eAtBcqCJVJBpzfieu7ekZpiG3dFo0cn5QFojtwy20VmfKJU
A7D0Ibb6J/UoRVBPoY8KTlYnd+7L2dEaVaE7hSE0emrC9NXa5t+it6xeAFDX0G/1
N31vTfkZABuWrPU3XGCkb87TQxk1hRE6Yw/Hu0TM3DSreLd7dkRHnwt6KEs=
-----END CERTIFICATE-----

View file

@ -10,7 +10,10 @@ services:
image: mysql:8.0
volumes:
- "./mysql/setup.sql:/docker-entrypoint-initdb.d/setup.sql"
ports:
- 3306
environment:
MYSQL_ROOT_HOST: '%'
MYSQL_ROOT_PASSWORD: password
MYSQL_DATABASE: sqlx
@ -18,7 +21,10 @@ services:
image: mysql:5.7
volumes:
- "./mysql/setup.sql:/docker-entrypoint-initdb.d/setup.sql"
ports:
- 3306
environment:
MYSQL_ROOT_HOST: '%'
MYSQL_ROOT_PASSWORD: password
MYSQL_DATABASE: sqlx
@ -26,7 +32,10 @@ services:
image: mysql:5.6
volumes:
- "./mysql/setup.sql:/docker-entrypoint-initdb.d/setup.sql"
ports:
- 3306
environment:
MYSQL_ROOT_HOST: '%'
MYSQL_ROOT_PASSWORD: password
MYSQL_DATABASE: sqlx
@ -39,6 +48,8 @@ services:
image: mariadb:10.5
volumes:
- "./mysql/setup.sql:/docker-entrypoint-initdb.d/setup.sql"
ports:
- 3306
environment:
MYSQL_ROOT_PASSWORD: password
MYSQL_DATABASE: sqlx
@ -47,6 +58,8 @@ services:
image: mariadb:10.4
volumes:
- "./mysql/setup.sql:/docker-entrypoint-initdb.d/setup.sql"
ports:
- 3306
environment:
MYSQL_ROOT_PASSWORD: password
MYSQL_DATABASE: sqlx
@ -55,6 +68,8 @@ services:
image: mariadb:10.3
volumes:
- "./mysql/setup.sql:/docker-entrypoint-initdb.d/setup.sql"
ports:
- 3306
environment:
MYSQL_ROOT_PASSWORD: password
MYSQL_DATABASE: sqlx
@ -63,6 +78,8 @@ services:
image: mariadb:10.2
volumes:
- "./mysql/setup.sql:/docker-entrypoint-initdb.d/setup.sql"
ports:
- 3306
environment:
MYSQL_ROOT_PASSWORD: password
MYSQL_DATABASE: sqlx
@ -71,6 +88,8 @@ services:
image: mariadb:10.1
volumes:
- "./mysql/setup.sql:/docker-entrypoint-initdb.d/setup.sql"
ports:
- 3306
environment:
MYSQL_ROOT_PASSWORD: password
MYSQL_DATABASE: sqlx
@ -86,6 +105,8 @@ services:
dockerfile: postgres/Dockerfile
args:
VERSION: 13-beta1
ports:
- 5432
environment:
POSTGRES_DB: sqlx
POSTGRES_USER: postgres
@ -103,6 +124,8 @@ services:
dockerfile: postgres/Dockerfile
args:
VERSION: 12.3
ports:
- 5432
environment:
POSTGRES_DB: sqlx
POSTGRES_USER: postgres
@ -120,6 +143,8 @@ services:
dockerfile: postgres/Dockerfile
args:
VERSION: 10.13
ports:
- 5432
environment:
POSTGRES_DB: sqlx
POSTGRES_USER: postgres
@ -136,6 +161,8 @@ services:
dockerfile: postgres/Dockerfile
args:
VERSION: 9.6
ports:
- 5432
environment:
POSTGRES_DB: sqlx
POSTGRES_USER: postgres
@ -152,6 +179,8 @@ services:
dockerfile: postgres/Dockerfile
args:
VERSION: 9.5
ports:
- 5432
environment:
POSTGRES_DB: sqlx
POSTGRES_USER: postgres
@ -173,6 +202,8 @@ services:
dockerfile: mssql/Dockerfile
args:
VERSION: 2019-latest
ports:
- 1433
environment:
ACCEPT_EULA: Y
SA_PASSWORD: Password123!

69
tests/docker.py Normal file
View file

@ -0,0 +1,69 @@
import subprocess
import time
from os import path
# base dir of sqlx workspace
dir_workspace = path.dirname(path.dirname(path.realpath(__file__)))
# dir of tests
dir_tests = path.join(dir_workspace, "tests")
# start database server and return a URL to use to connect
def start_database(driver, database, cwd):
if driver == "sqlite":
# short-circuit for sqlite
return f"sqlite://{path.join(cwd, database)}"
res = subprocess.run(
["docker-compose", "up", "-d", driver],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
cwd=dir_tests,
)
if res.returncode != 0:
print(res.stderr, file=sys.stderr)
if b"done" in res.stderr:
time.sleep(30)
# determine appropriate port for driver
if driver.startswith("mysql"):
port = 3306
elif driver.startswith("postgres"):
port = 5432
elif driver.startswith("mssql"):
port = 1433
else:
raise NotImplementedError
# find port
res = subprocess.run(
["docker", "inspect", f"-f='{{{{(index (index .NetworkSettings.Ports \"{port}/tcp\") 0).HostPort}}}}'",
f"sqlx_{driver}_1"],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
cwd=dir_tests,
)
if res.returncode != 0:
print(res.stderr, file=sys.stderr)
port = int(res.stdout[1:-2].decode())
# construct appropriate database URL
if driver.startswith("mysql"):
return f"mysql://root:password@127.0.0.1:{port}/{database}"
elif driver.startswith("postgres"):
return f"postgres://postgres:password@localhost:{port}/{database}"
elif driver.startswith("mssql"):
return f"mssql://sa:Password123!@127.0.0.1:{port}/{database}"
else:
raise NotImplementedError

View file

@ -1,28 +1,40 @@
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDCIbnQJ+Gn/eNF
EXZmT5tawV7nZLiz7F8Zfo2hDBZlFRapS6Jg1cNc9fzaUxdx2hNXxT9CAoAbs/X3
PA83ar6k0913pLW3VJIk/mjNpBEcXHBUbCP3027str/TRCjQ/hUjmSV0hIfPR8UD
oEFPtcZIrBFCPQ2CTsZzZKLkQbdZNoCTPkD6OxsEHMngKuor87aMdEkMTF6m3Eq7
i1jlGRfWUj0cC+YBQw+2WC4R2V1Ymjmo46nK0QTKGcNFuJq3iE1XrxTOxgHkBS5x
FeBq2AQ0KgANB/+oSoVTRGMWaXvYfhEfFjaI8YQX4Y/FWb+7bCckc5JD99Q7XH6R
wYRcnln7AgMBAAECggEALAMNZ13DURzES8Jbv3JI3Fh+taMmJNRv8w23+k0NPrl7
O8KD+8Q62HaEbtLru8ofHIUBhGugs6cnGngpUv0GX8QQr7FN6VRpFa4AAK8zmeRz
KxChTuxGd7Au6SzIvCj+jeWIklQBnkK9LcdFR1cErzEjcIr65xII99xW+bzUXosR
k+aPOSUQXpvkzVgh03uxYBFS3MdF3o+YsLUIQMce4FGwCZJp2vuJfIo8Lfa0s4wd
fae6J6lq2dSoNG9q6rHYFJ3C+IjHxO+Ak/kEvxpSam8oz8+9YsuJ8idjweoHRo+P
mCIZVeAHHdtBM2T4xhvV51HOa89fB8SHVhtww/3OYQKBgQDma5IEbGOtOAi+muam
4by5npDA/3mwXwHADaO5GA7g0BA6XSMjNBQ58fMd/MoJZiUMUFyxzVpXGpLbNNTr
V+w9ol7YoVh6RHpdkpo96MlAwkpxJr06csHX0NDrw4WHvQuBGch4Mm9UnBZaRZhb
VE+s8Piw3cQocd3Kvy5vEflhkwKBgQDXrtrxv1rdsWbt7JYMtm0TIBWVzDV/5qcJ
n4FmkSAjHdGHUwsGCuBCWQ7d+YLtoeCR1XThds2TnNu+zJAHRyFWaUxh+XeWNFnk
R2KAW0WzRS/CMXBYV5k0oXnginFjtigO8MVlbsdunY7IfgeMh4/HXt6cYiOiA/Io
SO4Bw0cG+QKBgQCcWP9iOv3DipL8anT5ZZC+TqagHnm+wCia3WZrcLSfvO5V+96c
w3i5/L9faKjaidG3skvDZbjYA7MERKv46Nbm12cODSTRCegR2CkKuwrcAzmp34Rk
xXtcaldosmnHufG1bv5E+MvsGGFebXy888+AZJ4KvN+eJe095k2mlgamOwKBgC6f
rtapbeQUkFKIXRtcaBHFUsUyArKmUp+C6n8YiiDtNjkRm4Vv3nCZPdyALmxeHOSJ
hx2iB+iL9Pi20b+xAaTjWE6plc9Te8ccI0/p6xRItX0+ILIIJac57NW8N6y9WMV6
CMHXg6cGyjHPBKS9PTh06pxVnqxMPBG3SjP5WaZJAoGBAOA1zE2z6xJCO8cEvo3d
C3FB9NWVqortQtYCn6Y/dt35noLEhe5gfr94BFwhZ2paJZ4dKQXsreaVzMMG6dEP
BjsOPQUHItIOrph2tuWvjWdC51jqgKOGTCCuuX7VJHlhxtaAnrS4RW84yVHugsj0
c3xRxbj6IWgUQfXU6NhEocXv
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
DA9cfDb28UfOAMuxPKzOqg==
-----END PRIVATE KEY-----

View file

@ -1,28 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDOqxrfpPH3FEVR
jiFaWHEqR2FSar1mmBKfkhpr0CnTBoxNQBx8Heok+vdht4a2eIR87xJq1l+Aqe6P
RhBdb/ddqlVsY1ALrnyVBbfCW12uodJ/zw24CKlOUUD6Dp75ZC6xN3wvgWKQQsvk
7hHs60yDSDpylVKZWCVmCe/P7p63p7EDo/yHjhdZEnnhdOPZxu3Z6hAPuakzCwBU
1WnDCHBsg2V+wKg07DacMuUDKn5XdUUTzqDS02HB6vat2vF3lVzjZsTBofaGrZ7C
CMRrsNtnsX74SczSoMf/ucelCNkfjEQXas+1FpLDd+1/5YRvH5uWtc3b5mhgvyUn
5GkADDO/AgMBAAECggEBAKEqxlZKJ3frkvM6x7/Q4M97wuWm3/U1+q/+HCSfvT4Y
CSnlKVGRcptMK8dEfAWojolvVwmCDBAmdSe+F90GB/4/a0aPXEj/1Z/RSbCD19br
02Bgc+5kssOkketvo4IRImiJQIs7d0XREXiCP/BmvtBSb2IUGMoE94VPknixOY02
Dbcxy7s/r7lqqWwaJNT1vDR/7l5kwsZnWfMRleaQPSGSh3ShVANEDCFb2bK0/s6w
DwshCn/Hh8ThVXK9JcchszIyvIIWWIdaaaHf4iN6G/4a0rqTaGAAo6Si9mZO1WK1
emqnM/KQuhCI/Upwfcu/P5lfhscpc4vIpILUsEV6WKECgYEA8F/mwCIpz3NLe++z
dXCjByhwgpPyaZHJ2P+Av2q9jiIOVhFxheQ+7zuBYc7dOmLDmLoQGaOSQABWkzdm
hjn6NhJoJVY01Np5dSwIFZuC/PQaevidRVCWI1yLxU20ezN6xT2JeDJCuINjyYGG
oropg9KENUFbmNwRUqvVlzCCYLUCgYEA3BpLb9LASpOtiDLvVD+IWxdbcbjVFmuG
/1RPq+1PQNoJdjdEocf9r7K4jMTJuLULmy8MDyox94SqJ+91jvGDDoNisGLRCbic
gUg3HuC1J5oVwlqRC5F21tx9W0ZK85VWkvJQ6MiCZy1eqlaABSEcQ8Mn/4PhX2P/
0/1sofQw7yMCgYEA0/t/QAng3XZMJ2xo0zUWUQW00zMuITPU0m3hWO4FZQdbpUOU
3gNADTJpE5yfNRJMdLAB6tp5679gmkvNOqp+opjxB5xS0zQo0NCYAJY4mmObxr7h
03MSNPU0vjec5tmrd66hQULx3E7i/Z4g4flTC1HoDh8pbFEHZeTsZHz/PdECgYA/
p/MtUhx+9Rr5CxIgoYdEIQs3ZqdqJosSiUXJiYakUOrvn6hfycFa8Stiuv9ERkgn
B4JLWH6/AUVc62pqfvrSVblTHiEq2JOa6FHYwlBiNbQZU6wjVlyyY2512WyP6h7x
vNcdm+/q+zontYCs+xh7mJOW2INz3S3+F4s1g7QrVQKBgE0rBT29byusUQCV/AZM
hFIyJIEYO+R3n8b8ocfsMTvAUVJzXe+KAHQIvgjiAX1e4jo0xjgR4FNJyd8olhYR
BSIZyWZTk5KuFjWztt0SCIAdXLiFBbTKsLR044jvjBSIx8XDfXv3kYx6YcbxbnsK
noIkTIopteVr069/pyL6PiUx
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC3YgWR+UThJWz9
Y7BaOzgwdj7EhC3os+pWkEs556btyb1l3IduWiN6xmKNX/i9tzhvCWSw4G8kSRU5
JqcxSKZP0AzCM7MkG/RjKPwSUIj6//bLZAnskdV+fmkFNuTzj6W6C2A/yFblQuO0
8PITXgT7yw0JdJrrYLVr6WCyw0tz78QAZhAXiahDEixkW6IjcRWIvHgjprIP9Niv
hTUcEVLyxj+tYNVKHzYHHzk5kIr7TrFuIynNuLlvr1bCxo6HXp7/ImYRraZApuVZ
mjepP0t8yfm7UBfsovtYoF66iFmR4jqwEwVys7fJcZKahIvTsjZhralKYnIynzGJ
0anToPCdAgMBAAECggEABVjnXq1NE9+agP0CLG9joQ4hoGtWR13PrHyCpQqbNH3Y
dvrqPA6G0FKulv7Aaw/Hpn04oWu58e3rn4IACBDdQKCJbrRBOgFSq/2K9CHDDMaf
9KhTHcHW3txixZMnM+7xXy5rvRBjcEX2C9WmyWfJb2opVChBSDHGuIHSnwPQ1G2R
t8PrSTD3uN7VbpdDj0pznZN7UzTxXGNyy98ruZIY6haK6urd9BRGQD8RKe6hQL6k
5m+AWW7vhIEgBmNeYg5RHoxaeECI89L7cq1Z+0kMMqyvaXdBUTpsjXGW56kYRt+A
qTwxlBbCQRTZuHz+vnuWEiJ2/YbY5b5xpraHqnc8ZQKBgQDoa2ilYqA+Fb/elgyX
kaXuf/d8EGLLQ2KHk+nkJeXLnbMGq7v1ISSVLsWDkMGJyENQOHh5hJVub7ew/AK2
SGQ0FA1F6AcLJ+0aiWY+pvhesKLtW+cXVooiL4M6w8YgDZyH7V988sM0l7FejauK
ZyDHDsaWOR2IT0eKg0bVh+N6XwKBgQDJ/P4Ua7wlvphTPc4mfjvTkppDpv0YDW8x
t89Y5mLscsDV8okHav3MlKhKOPqEbmcw1sS0txT3NxLFUpFfONsuYsfT24z96XI4
cHKUDP1zEFq+7D+A20F3ydks5+OW5FofcDNbc2+Yg/0upXe38wVfBJj1VEWGz70C
GSN+j6vugwKBgDEdKXLxgX09KVuHB8grvg3FOu4bpFThu3t89UsB+ypo+8DoH4Lw
awOfa5uexlcwW5EjLco4Cz/YGdAroQMWDx62MgvYuUxRNpiJ+nI45HlWCEfySMY0
wmHw+mE7p610UuSic7A6uKdvesrJUzufCV0nMS3jiesZHbwWe6x518cvAoGBAI9P
7GpKwlS5dVRiXrkbCZGky8VCXwLIzWMmOnymAfwns0BZc/YKaIbV1s3KvZxmxNp3
F1vtJnf84FmWqsQ4D/NKbOOZO+EP2FXJGtKGoPEZ4njiIHBpoHrAgVGGOglefb8e
maHCNqSsyV9mUZn3WJFBLtGp+CadkEpD0dZDU8bHAoGADRorYjov1pEEWbHhQaQP
X1pQsc8Oc/tQAvh9GOJPpvJ0r2hdMMMJC/lC6+63MyKKrXScagVcajgRk1ES0V2/
9YizDOY8S4fEtHTSbPJHSS2orXhJ8KSAxl1JbjNDlDPj9EcOvocaehssZ9Tf2bPg
7ywoQK2oCbW2Hq9WcgYIubY=
-----END PRIVATE KEY-----

View file

@ -41,7 +41,10 @@ async fn it_can_select_expression_by_name() -> anyhow::Result<()> {
#[sqlx_macros::test]
async fn it_can_fail_to_connect() -> anyhow::Result<()> {
let res = MssqlConnection::connect("mssql://sa@localhost").await;
let mut url = dotenv::var("DATABASE_URL")?;
url = url.replace("Password", "NotPassword");
let res = MssqlConnection::connect(&url).await;
let err = res.unwrap_err();
let err = err.into_database_error().unwrap();

View file

@ -241,7 +241,7 @@ mod json_tests {
// NOTE: This is testing recursive (and transparent) usage of the `Json` wrapper. You don't
// need to wrap the Vec in Json<_> to make the example work.
#[derive(Debug, PartialEq, serde::Serialize, serde::Deserialize, sqlx::FromRow)]
#[derive(Debug, PartialEq, serde::Serialize, serde::Deserialize)]
struct Customer {
json_column: Json<Vec<i64>>,
}

View file

@ -28,7 +28,7 @@ async fn it_can_select_void() -> anyhow::Result<()> {
let mut conn = new::<Postgres>().await?;
// pg_notify just happens to be a function that returns void
let value: () = sqlx::query_scalar("select pg_notify('chan', 'message');")
let _value: () = sqlx::query_scalar("select pg_notify('chan', 'message');")
.fetch_one(&mut conn)
.await?;

Binary file not shown.

View file

@ -5,8 +5,8 @@ import os
import sys
import time
import argparse
import getpass
from glob import glob
from docker import start_database
parser = argparse.ArgumentParser()
parser.add_argument("-t", "--target")
@ -16,23 +16,14 @@ parser.add_argument("--test")
argv, unknown = parser.parse_known_args()
# base dir of sqlx workspace
dir_workspace = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
def start(service):
res = subprocess.run(
["docker-compose", "up", "-d", service],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
cwd=os.path.dirname(__file__),
)
if res.returncode != 0:
print(res.stderr, file=sys.stderr)
if b"done" in res.stderr:
time.sleep(30)
# dir of tests
dir_tests = os.path.join(dir_workspace, "tests")
def run(command, comment=None, env=None, service=None, tag=None, args=None):
def run(command, comment=None, env=None, service=None, tag=None, args=None, database_url_args=None):
if argv.list_targets:
if tag:
print(f"{tag}")
@ -48,8 +39,18 @@ def run(command, comment=None, env=None, service=None, tag=None, args=None):
if comment is not None:
print(f"\x1b[2m # {comment}\x1b[0m")
environ = env or {}
if service is not None:
start(service)
database_url = start_database(service, database="sqlite/sqlite.db" if service == "sqlite" else "sqlx", cwd=dir_tests)
if database_url_args:
database_url += "?" + database_url_args
environ["DATABASE_URL"] = database_url
# show the database url
print(f"\x1b[94m @ {database_url}\x1b[0m")
command_args = []
@ -70,7 +71,7 @@ def run(command, comment=None, env=None, service=None, tag=None, args=None):
*command.split(" "),
*command_args
],
env=env,
env=dict(**os.environ, **environ),
cwd=cwd,
)
@ -134,56 +135,44 @@ for runtime in ["async-std", "tokio", "actix"]:
#
run(
f"cargo test --no-default-features --features all-types,sqlite,runtime-{runtime}",
f"cargo test --no-default-features --features macros,offline,all-types,sqlite,runtime-{runtime}",
comment=f"test sqlite",
env={"DATABASE_URL": f"sqlite://tests/sqlite/sqlite.db"},
service="sqlite",
tag=f"sqlite" if runtime == "async-std" else f"sqlite_{runtime}",
# FIXME: The SQLite driver does not currently support concurrent access to the same database
args=["--test-threads=1"],
)
#
# postgres
#
for version in ["12", "10", "9.6", "9.5"]:
v = version.replace(".", "_")
for version in ["12", "10", "9_6", "9_5"]:
run(
f"cargo test --no-default-features --features all-types,postgres,runtime-{runtime}",
f"cargo test --no-default-features --features macros,offline,all-types,postgres,runtime-{runtime}",
comment=f"test postgres {version}",
env={"DATABASE_URL": f"postgres://postgres:password@postgres_{v}/sqlx"},
service=f"postgres_{v}",
tag=f"postgres_{v}" if runtime == "async-std" else f"postgres_{v}_{runtime}",
service=f"postgres_{version}",
tag=f"postgres_{version}" if runtime == "async-std" else f"postgres_{version}_{runtime}",
)
#
# postgres ssl
#
for version in ["12", "10", "9.6", "9.5"]:
v = version.replace(".", "_")
# +ssl
for version in ["12", "10", "9_6", "9_5"]:
run(
f"cargo test --no-default-features --features all-types,postgres,runtime-{runtime}",
f"cargo test --no-default-features --features macros,offline,all-types,postgres,runtime-{runtime}",
comment=f"test postgres {version} ssl",
env={
"DATABASE_URL": f"postgres://postgres:password@postgres_{v}/sqlx?sslmode=verify-ca&sslrootcert=.%2Ftests%2Fcerts%2Fca.crt"
},
service=f"postgres_{v}",
tag=f"postgres_{v}_ssl" if runtime == "async-std" else f"postgres_{v}_ssl_{runtime}",
database_url_args="sslmode=verify-ca&sslrootcert=.%2Ftests%2Fcerts%2Fca.crt",
service=f"postgres_{version}",
tag=f"postgres_{version}_ssl" if runtime == "async-std" else f"postgres_{version}_ssl_{runtime}",
)
#
# mysql
#
for version in ["8", "5.7", "5.6"]:
v = version.replace(".", "_")
for version in ["8", "5_7", "5_6"]:
run(
f"cargo test --no-default-features --features all-types,mysql,runtime-{runtime}",
f"cargo test --no-default-features --features macros,offline,all-types,mysql,runtime-{runtime}",
comment=f"test mysql {version}",
env={"DATABASE_URL": f"mysql://root:password@mysql_{v}/sqlx"},
service=f"mysql_{v}",
tag=f"mysql_{v}" if runtime == "async-std" else f"mysql_{v}_{runtime}",
service=f"mysql_{version}",
tag=f"mysql_{version}" if runtime == "async-std" else f"mysql_{version}_{runtime}",
)
#
@ -191,13 +180,23 @@ for runtime in ["async-std", "tokio", "actix"]:
#
for version in ["10_5", "10_4", "10_3", "10_2", "10_1"]:
v = version.replace(".", "_")
run(
f"cargo test --no-default-features --features all-types,mysql,runtime-{runtime}",
f"cargo test --no-default-features --features macros,offline,all-types,mysql,runtime-{runtime}",
comment=f"test mariadb {version}",
env={"DATABASE_URL": f"mysql://root:password@mariadb_{v}/sqlx"},
service=f"mariadb_{v}",
tag=f"mariadb_{v}" if runtime == "async-std" else f"mariadb_{v}_{runtime}",
service=f"mariadb_{version}",
tag=f"mariadb_{version}" if runtime == "async-std" else f"mariadb_{version}_{runtime}",
)
#
# mssql
#
for version in ["2019"]:
run(
f"cargo test --no-default-features --features macros,offline,all-types,mssql,runtime-{runtime}",
comment=f"test mssql {version}",
service=f"mssql_{version}",
tag=f"mssql_{version}" if runtime == "async-std" else f"mssql_{version}_{runtime}",
)
# TODO: Use [grcov] if available