Skip to content

Commit 16813a2

Browse files
authored
Merge pull request #274 from jongleb/fix-comment-by-review
Move queries inside dynamic select module
2 parents 4f45c0a + 2a3116a commit 16813a2

File tree

4 files changed

+1258
-1076
lines changed

4 files changed

+1258
-1076
lines changed

doc/sql/dynamic-select.md

Lines changed: 36 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ Dynamic Select is currently supported **only in OCaml** code generation (`-gen c
1414

1515
Dynamic Select allows you to choose which columns to SELECT at runtime while maintaining full type safety. Just write a regular `SELECT` query and add the `dynamic_select=true` metadata flag — every column in the select list becomes a composable field that can be picked or combined at runtime using applicative combinators.
1616

17+
Unlike simply ignoring unwanted columns in the callback, Dynamic Select builds the SQL query with only the selected columns. This means the database server processes and transfers less data — unused column expressions (subqueries, function calls, etc.) are never evaluated.
18+
1719
## Basic Syntax
1820

1921
Add a metadata comment before a regular SELECT query:
@@ -40,43 +42,39 @@ module Select_product_col : sig
4042
end
4143
```
4244

43-
The generated query function takes a `~col` parameter:
44-
45-
```ocaml
46-
val select_product : db -> col:'a Select_product_col.t -> id:int64 -> 'a option IO.m
47-
```
48-
4945
## Usage with Combinators
5046

47+
The query function `select` is generated inside the `*_col` module — no need to open an extra module:
48+
5149
### Single Field
5250

5351
```ocaml
54-
let* result = Db.select_product conn ~col:Select_product_col.name ~id:1L
52+
let* result = Db.Select_product_col.(select conn name ~id:1L)
5553
(* result : string option *)
5654
```
5755

5856
### Combined Fields with `let+` / `and+`
5957

60-
```ocaml
61-
open Select_product_col
58+
Compose fields inline:
6259

63-
let combined =
64-
let+ n = name
65-
and+ p = price in
66-
(n, p)
67-
68-
let* result = Db.select_product conn ~col:combined ~id:1L
60+
```ocaml
61+
let* result = Db.Select_product_col.(select conn (let+ n = name and+ p = price in (n, p)) ~id:1L)
6962
(* result : (string * float) option *)
7063
```
7164

72-
### Three or More Fields
65+
Or bind the selector separately when it gets longer:
7366

7467
```ocaml
75-
let all_fields =
68+
open Db.Select_product_col
69+
70+
let combined =
7671
let+ n = name
7772
and+ p = price
7873
and+ c = category in
7974
(n, p, c)
75+
76+
let* result = select conn combined ~id:1L
77+
(* result : (string * float * string) option *)
8078
```
8179

8280
### With Transformation
@@ -98,25 +96,35 @@ let with_constant =
9896

9997
## Multiple Rows (Callback)
10098

101-
Dynamic select works the same for queries returning multiple rows. The callback receives `~col`:
99+
For queries returning multiple rows, pass a callback after the fields:
102100

103101
```sql
104102
-- [sqlgg] dynamic_select=true
105103
-- @list_products
106104
SELECT id, name, price FROM products WHERE stock > @min_stock;
107105
```
108106

107+
Inline style:
108+
109+
```ocaml
110+
Db.List_products_col.(select conn
111+
(let+ i = id and+ n = name and+ p = price in (i, n, p))
112+
~min_stock:5L
113+
(fun (i, n, p) -> printf "id=%Ld, name=%s, price=%.2f\n" i n p))
114+
```
115+
116+
Or with a separate binding:
117+
109118
```ocaml
110-
open List_products_col
119+
open Db.List_products_col
111120
112121
let combined =
113122
let+ i = id
114123
and+ n = name
115124
and+ p = price in
116125
(i, n, p)
117126
118-
let () = Db.list_products conn ~col:combined ~min_stock:5L (fun ~col ->
119-
let (i, n, p) = col in
127+
let () = select conn combined ~min_stock:5L (fun (i, n, p) ->
120128
printf "id=%Ld, name=%s, price=%.2f\n" i n p
121129
)
122130
```
@@ -173,14 +181,12 @@ module With_param_col : sig
173181
end
174182
175183
(* Usage *)
176-
let* r = Db.with_param conn ~col:(With_param_col.custom "Hello") ~id:1L
184+
let* r = Db.With_param_col.(select conn (custom "Hello") ~id:1L)
177185
178186
(* Combine with other fields *)
179-
let combined =
180-
let+ i = id
181-
and+ n = name
182-
and+ c = custom "Hello" in
183-
(i, n, c)
187+
let* r = Db.With_param_col.(select conn
188+
(let+ i = id and+ n = name and+ c = custom "Hello" in (i, n, c))
189+
~id:1L)
184190
```
185191

186192
### Arithmetic Parameters
@@ -364,13 +370,9 @@ You don't have to return tuples — use records:
364370
```ocaml
365371
type product_info = { name: string; price: float }
366372
367-
let info_col =
368-
let open Select_product_col in
369-
let+ n = name
370-
and+ p = price in
371-
{ name = n; price = p }
372-
373-
let* result = Db.select_product conn ~col:info_col ~id:1L
373+
let* result = Db.Select_product_col.(select conn
374+
(let+ n = name and+ p = price in { name = n; price = p })
375+
~id:1L)
374376
(* result : product_info option *)
375377
```
376378

0 commit comments

Comments
 (0)