Skip to content

Commit cbff16e

Browse files
committed
Align with agu-z/roc-pg#13
1 parent b7e3422 commit cbff16e

19 files changed

Lines changed: 968 additions & 793 deletions

README.md

Lines changed: 63 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -27,24 +27,26 @@ The plan is to support all the other SQL commands, but that's coming later. In t
2727
Connecting and performing a query
2828

2929
```haskell
30-
task : Task (List { name: Str, price: Dec }) _
31-
task =
32-
client <- Pg.Client.withConnect {
33-
host: "localhost",
34-
port: 5432,
35-
user: "postgres",
36-
database: "postgres",
37-
auth: Password "password"
38-
}
39-
40-
Pg.Cmd.new "select name, price from products"
41-
|> Pg.Cmd.expectN (
42-
Pg.Result.succeed {
43-
name: <- Pg.Result.str "name" |> Pg.Result.apply,
44-
price: <- Pg.Result.dec "price" |> Pg.Result.apply
45-
}
46-
)
47-
|> Pg.Client.command client
30+
products! : {} => Result (List { name : Str, price : Dec }) _
31+
products! = |_|
32+
client = Pg.Client.connect!(
33+
{
34+
host: "localhost",
35+
port: 5432,
36+
user: "postgres",
37+
auth: None,
38+
database: "postgres",
39+
},
40+
)?
41+
42+
Pg.Cmd.new("select name, price from products")
43+
|> Pg.Cmd.expect_n(
44+
{ Pg.Result.record_builder <-
45+
name: Pg.Result.str("name"),
46+
price: Pg.Result.dec("price"),
47+
},
48+
)
49+
|> Pg.Client.command!(client)
4850
```
4951

5052
<details>
@@ -53,15 +55,15 @@ Parameterized queries
5355
</summary>
5456

5557
```elm
56-
Pg.Cmd.new "select name, price from products where id = $1"
57-
|> Pg.Cmd.bind [ Pg.Cmd.u32 productId ]
58-
|> Pg.Cmd.expect1 (
59-
Pg.Result.succeed {
60-
name: <- Pg.Result.str "name" |> Pg.Result.apply,
61-
price: <- Pg.Result.dec "price" |> Pg.Result.apply
62-
}
63-
)
64-
|> Pg.Client.command client
58+
Pg.Cmd.new("select name, price from products where id = $1")
59+
|> Pg.Cmd.bind([ Pg.Cmd.u32(product_id) ])
60+
|> Pg.Cmd.expect1(
61+
{ Pg.Result.record_builder <-
62+
name: Pg.Result.str("name"),
63+
price: Pg.Result.dec("price"),
64+
},
65+
)
66+
|> Pg.Client.command!(client)?
6567
```
6668

6769
</details>
@@ -72,16 +74,14 @@ Prepared statements
7274
</summary>
7375

7476
```elm
75-
selectUser <-
77+
select_user =
7678
"select email from users where id = $1"
77-
|> Pg.Client.prepare { client, name: "selectUser" }
78-
|> await
79-
80-
selectUser
81-
|> Pg.Cmd.bind [ Pg.Cmd.u32 userId ]
82-
|> Pg.Cmd.expect1 (Pg.Result.str "email")
83-
|> Pg.Client.command client
79+
|> Pg.Client.prepare!({ client, name: "select_user" })?
8480

81+
select_user
82+
|> Pg.Cmd.bind([Pg.Cmd.u32(user_id)])
83+
|> Pg.Cmd.expect1(Pg.Result.str("email"))
84+
|> Pg.Client.command!(client)?
8585
```
8686

8787
</details>
@@ -92,33 +92,36 @@ Batch commands in a single roundtrip (applicative)
9292
</summary>
9393

9494
```elm
95-
Pg.Batch.succeed \email -> \products -> { email, products }
96-
|> Pg.Batch.with
95+
Pg.Batch.succeed(|email| |products| { email, products })
96+
|> Pg.Batch.with(
9797
(
98-
selectUser
99-
|> Pg.Cmd.bind [ Pg.Cmd.u32 userId ]
100-
|> Pg.Cmd.expect1 (Pg.Result.str "email")
101-
)
102-
|> Pg.Batch.with
98+
select_user
99+
|> Pg.Cmd.bind([Pg.Cmd.u32(user_id)])
100+
|> Pg.Cmd.expect1(Pg.Result.str("email"))
101+
),
102+
)
103+
|> Pg.Batch.with(
103104
(
104-
Pg.Cmd.new
105+
Pg.Cmd.new(
105106
"""
106107
select name, price from products
107108
inner join orders on orders.product_id = products.id
108109
where orders.id = $1
109-
"""
110-
|> Pg.Cmd.bind [ Pg.Cmd.u32 orderId ]
111-
|> Pg.Cmd.expectN (
112-
Pg.Result.succeed {
113-
name: <- Pg.Result.str "name" |> Pg.Result.apply,
114-
price: <- Pg.Result.dec "price" |> Pg.Result.apply
115-
}
116-
)
117-
)
118-
|> Pg.Client.batch client
110+
""",
111+
)
112+
|> Pg.Cmd.bind([Pg.Cmd.u32(order_id)])
113+
|> Pg.Cmd.expect_n(
114+
{ Pg.Result.record_builder <-
115+
name: Pg.Result.str("name"),
116+
price: Pg.Result.dec("price"),
117+
},
118+
)
119+
),
120+
)
121+
|> Pg.Client.batch!(client)?
119122
```
120123

121-
Note: `selectUser` referes to prepared statement in the previous example
124+
Note: `select_user` referes to prepared statement in the previous example
122125

123126
</details>
124127

@@ -128,14 +131,14 @@ Batch commands in a single roundtrip (list)
128131
</summary>
129132

130133
```elm
131-
updateCmd = \product ->
132-
Pg.Cmd.new "update products set desc = $1 where id = $2"
133-
|> Pg.Cmd.bind [ Pg.Cmd.str product.desc, Pg.Cmd.u32 product.id ]
134+
update_cmd = |product|
135+
Pg.Cmd.new("update products set desc = $1 where id = $2")
136+
|> Pg.Cmd.bind([Pg.Cmd.str(product.desc), Pg.Cmd.u32(product.id)])
134137

135-
productsToUpdate
136-
|> List.map updateCmd
138+
products_to_update
139+
|> List.map(update_cmd)
137140
|> Pg.Batch.sequence
138-
|> Pg.Client.batch client
141+
|> Pg.Client.batch!(client)?
139142
```
140143

141144
Note: `roc-pg` automatically reuses statements in a batch by only parsing (and describing) once per unique SQL string. This also works with applicative batches.

examples/basic-webserver.roc

Lines changed: 15 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -9,23 +9,12 @@ import pg.Pg.Cmd
99
import pg.Pg.Result
1010

1111
Model : {
12-
pg_client : Client,
12+
client : Client,
1313
}
1414

1515
init! = |_|
1616
_ = Stdout.line!("Start!")
1717

18-
# NOTE: The Tcp.Stream is closed as soon as the last reference to it is dropped.
19-
# We therefore connect in `init!` and store the connection in our `Model` so that
20-
# we can keep it going until the end of the program.
21-
#
22-
# For some reason `basic-webserver` dies if the Tcp.Stream is closed. I don't know
23-
# why. This prevents us from connecting to pg during a request for example, as the
24-
# connection's `Tcp.Stream` would be dropped at the end of the request and
25-
# `basic-webserver` would die.
26-
#
27-
# There is no error message or anything when this issue occurs.
28-
# NOTE: `connect!` can make the process exit without an error.
2918
client = Pg.Client.connect!(
3019
{
3120
host: "localhost",
@@ -34,19 +23,11 @@ init! = |_|
3423
auth: None,
3524
database: "postgres",
3625
},
37-
)
38-
39-
_ =
40-
when client is
41-
Ok(_) ->
42-
Stdout.line!("Success!")
43-
44-
Err(_) ->
45-
Stdout.line!("Failure!")
26+
)?
4627

4728
_ = Stdout.line!("Connected!")
4829

49-
Ok({ pg_client: client? })
30+
Ok({ client })
5031

5132
respond! = |_request, model|
5233
rows =
@@ -59,27 +40,24 @@ respond! = |_request, model|
5940
)
6041
|> Pg.Cmd.bind([Pg.Cmd.str("John"), Pg.Cmd.u8(32)])
6142
|> Pg.Cmd.expect_n(
62-
(
63-
Pg.Result.succeed(
64-
|name|
65-
|age|
66-
age_str = Num.to_str(age)
67-
68-
"${name}: ${age_str}",
69-
)
70-
|> Pg.Result.with(Pg.Result.str("name"))
71-
|> Pg.Result.with(Pg.Result.u8("age"))
72-
),
43+
{ Pg.Result.record_builder <-
44+
name: Pg.Result.str("name"),
45+
age: Pg.Result.u8("age"),
46+
},
7347
)
74-
|> Pg.Client.command!(model.pg_client)?
48+
|> Pg.Client.command!(model.client)?
49+
50+
response_body =
51+
rows
52+
|> List.map(Inspect.to_str)
53+
|> Str.join_with("\n")
7554

76-
s = Str.join_with(rows, "\n")
77-
_ = Stdout.line!(s)
55+
Stdout.line!("Responding with: ${response_body}")?
7856
7957
Ok(
8058
{
8159
status: 200,
8260
headers: [],
83-
body: Str.to_utf8(s),
61+
body: Str.to_utf8(response_body),
8462
},
8563
)

examples/batch.roc

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
app [main!] {
2-
pg: "../src/main.roc",
32
pf: platform "https://github.com/roc-lang/basic-cli/releases/download/0.19.0/Hj-J_zxz7V9YurCSTFcFdu6cQJie4guzsPMUi5kBYUk.tar.br",
3+
pg: "../src/main.roc",
44
}
55

66
import pf.Stdout
77
import pg.Pg.Cmd
8-
import pg.Pg.BasicCliClient
8+
import pg.Pg.Client
99
import pg.Pg.Batch
1010
import pg.Pg.Result
1111

1212
main! = |_|
13-
client = Pg.BasicCliClient.connect!(
13+
client = Pg.Client.connect!(
1414
{
1515
host: "localhost",
1616
port: 5432,
@@ -44,7 +44,7 @@ main! = |_|
4444
|> Pg.Cmd.expect1(Pg.Result.u8("value"))
4545
),
4646
)
47-
|> Pg.BasicCliClient.batch!(client)?
47+
|> Pg.Client.batch!(client)?
4848
4949
str42 = Num.to_str(result_with.forty_two)
5050
_ = Stdout.line!("${result_with.hi} ${str42}")
@@ -58,7 +58,7 @@ main! = |_|
5858
|> Pg.Cmd.expect1(Pg.Result.u8("value")),
5959
)
6060
|> Pg.Batch.sequence
61-
|> Pg.BasicCliClient.batch!(client)?
61+
|> Pg.Client.batch!(client)?
6262
6363
result_seq_str = result_seq |> List.map(Num.to_str) |> Str.join_with(", ")
6464

examples/prepared.roc

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
app [main!] {
2-
pg: "../src/main.roc",
32
pf: platform "https://github.com/roc-lang/basic-cli/releases/download/0.19.0/Hj-J_zxz7V9YurCSTFcFdu6cQJie4guzsPMUi5kBYUk.tar.br",
3+
pg: "../src/main.roc",
44
}
55

66
import pf.Stdout
77
import pg.Pg.Cmd
8-
import pg.Pg.BasicCliClient
8+
import pg.Pg.Client
99
import pg.Pg.Result
1010

1111
main! = |_|
12-
client = Pg.BasicCliClient.connect!(
12+
client = Pg.Client.connect!(
1313
{
1414
host: "localhost",
1515
port: 5432,
@@ -23,14 +23,14 @@ main! = |_|
2323

2424
add_cmd =
2525
"select $1::int + $2::int as result"
26-
|> Pg.BasicCliClient.prepare!({ client, name: "add" })?
26+
|> Pg.Client.prepare!({ client, name: "add" })?
2727

2828
add_and_print! = |a, b|
2929
result =
3030
add_cmd
3131
|> Pg.Cmd.bind([Pg.Cmd.u8(a), Pg.Cmd.u8(b)])
3232
|> Pg.Cmd.expect1(Pg.Result.u8("result"))
33-
|> Pg.BasicCliClient.command!(client)?
33+
|> Pg.Client.command!(client)?
3434

3535
a_str = Num.to_str(a)
3636
b_str = Num.to_str(b)
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
app [main!] {
2+
pf: platform "https://github.com/roc-lang/basic-cli/releases/download/0.19.0/Hj-J_zxz7V9YurCSTFcFdu6cQJie4guzsPMUi5kBYUk.tar.br",
3+
pg: "../src/main.roc",
4+
}
5+
6+
import pf.Stdout
7+
import pg.Pg.Cmd
8+
import pg.Pg.Client
9+
import pg.Pg.Result
10+
11+
main! = |_|
12+
client = Pg.Client.connect!(
13+
{
14+
host: "localhost",
15+
port: 5432,
16+
user: "postgres",
17+
auth: None,
18+
database: "postgres",
19+
},
20+
)?
21+
22+
_ = Stdout.line!("Connected!")
23+
24+
rows =
25+
Pg.Cmd.new(
26+
"""
27+
select $1 as name, $2 as age
28+
union all
29+
select 'Julio' as name, 23 as age
30+
""",
31+
)
32+
|> Pg.Cmd.bind([Pg.Cmd.str("John"), Pg.Cmd.u8(32)])
33+
|> Pg.Cmd.expect_n(
34+
{ Pg.Result.record_builder <-
35+
name: Pg.Result.str("name"),
36+
age: Pg.Result.u8("age"),
37+
},
38+
)
39+
|> Pg.Client.command!(client)?
40+
41+
str =
42+
rows
43+
|> List.map(Inspect.to_str)
44+
|> Str.join_with("\n")
45+
46+
Stdout.line!("Got records:\n${str}")

0 commit comments

Comments
 (0)