You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: doc/sql/dynamic-select.md
+36-34Lines changed: 36 additions & 34 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -14,6 +14,8 @@ Dynamic Select is currently supported **only in OCaml** code generation (`-gen c
14
14
15
15
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.
16
16
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
+
17
19
## Basic Syntax
18
20
19
21
Add a metadata comment before a regular SELECT query:
@@ -40,43 +42,39 @@ module Select_product_col : sig
40
42
end
41
43
```
42
44
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
-
49
45
## Usage with Combinators
50
46
47
+
The query function `select` is generated inside the `*_col` module — no need to open an extra module:
48
+
51
49
### Single Field
52
50
53
51
```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)
55
53
(* result : string option *)
56
54
```
57
55
58
56
### Combined Fields with `let+` / `and+`
59
57
60
-
```ocaml
61
-
open Select_product_col
58
+
Compose fields inline:
62
59
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)
69
62
(* result : (string * float) option *)
70
63
```
71
64
72
-
### Three or More Fields
65
+
Or bind the selector separately when it gets longer:
73
66
74
67
```ocaml
75
-
let all_fields =
68
+
open Db.Select_product_col
69
+
70
+
let combined =
76
71
let+ n = name
77
72
and+ p = price
78
73
and+ c = category in
79
74
(n, p, c)
75
+
76
+
let* result = select conn combined ~id:1L
77
+
(* result : (string * float * string) option *)
80
78
```
81
79
82
80
### With Transformation
@@ -98,25 +96,35 @@ let with_constant =
98
96
99
97
## Multiple Rows (Callback)
100
98
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:
102
100
103
101
```sql
104
102
-- [sqlgg] dynamic_select=true
105
103
-- @list_products
106
104
SELECT id, name, price FROM products WHERE stock > @min_stock;
107
105
```
108
106
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
+
109
118
```ocaml
110
-
open List_products_col
119
+
open Db.List_products_col
111
120
112
121
let combined =
113
122
let+ i = id
114
123
and+ n = name
115
124
and+ p = price in
116
125
(i, n, p)
117
126
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) ->
120
128
printf "id=%Ld, name=%s, price=%.2f\n" i n p
121
129
)
122
130
```
@@ -173,14 +181,12 @@ module With_param_col : sig
173
181
end
174
182
175
183
(* 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)
177
185
178
186
(* 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)
184
190
```
185
191
186
192
### Arithmetic Parameters
@@ -364,13 +370,9 @@ You don't have to return tuples — use records:
364
370
```ocaml
365
371
type product_info = { name: string; price: float }
366
372
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 })
0 commit comments