Skip to content

Commit 26aab9c

Browse files
authored
Add map_value_result + rename error (#346)
1 parent b762fe7 commit 26aab9c

File tree

5 files changed

+51
-13
lines changed

5 files changed

+51
-13
lines changed

examples/sqlite.roc

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ main! = |_args|
1515
1616
List.for_each_try!(
1717
todo,
18-
|{ id, task }|
19-
Stdout.line!("\tid: ${id}, task: ${task}"),
18+
|{ id, task, status }|
19+
Stdout.line!("\tid: ${id}, task: ${task}, status: ${Inspect.to_str(status)}"),
2020
)?
2121

2222
completed = query_todos_by_status!(db_path, "completed")?
@@ -25,8 +25,8 @@ main! = |_args|
2525
2626
List.for_each_try!(
2727
completed,
28-
|{ id, task }|
29-
Stdout.line!("\tid: ${id}, task: ${task}"),
28+
|{ id, task, status }|
29+
Stdout.line!("\tid: ${id}, task: ${task}, status: ${Inspect.to_str(status)}"),
3030
)?
3131

3232
Ok({})
@@ -35,12 +35,23 @@ query_todos_by_status! = |db_path, status|
3535
Sqlite.query_many!(
3636
{
3737
path: db_path,
38-
query: "SELECT id, task FROM todos WHERE status = :status;",
38+
query: "SELECT id, task, status FROM todos WHERE status = :status;",
3939
bindings: [{ name: ":status", value: String(status) }],
4040
# This uses the record builder syntax: https://www.roc-lang.org/examples/RecordBuilder/README.html
4141
rows: { Sqlite.decode_record <-
4242
id: Sqlite.i64("id") |> Sqlite.map_value(Num.to_str),
4343
task: Sqlite.str("task"),
44+
status: Sqlite.str("status") |> Sqlite.map_value_result(decode_db_status),
4445
},
4546
},
4647
)
48+
49+
TodoStatus : [Todo, Completed, InProgress]
50+
51+
decode_db_status : Str -> Result TodoStatus _
52+
decode_db_status = |status_str|
53+
when status_str is
54+
"todo" -> Ok(Todo)
55+
"completed" -> Ok(Completed)
56+
"in-progress" -> Ok(InProgress)
57+
_ -> Err(ParseError("Unknown status str: ${status_str}"))

examples/todos.db

0 Bytes
Binary file not shown.

flake.lock

Lines changed: 6 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

flake.nix

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
]);
4444

4545
sharedInputs = (with pkgs; [
46+
sqlite
4647
jq
4748
rust
4849
llvmPkgs.clang

platform/Sqlite.roc

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ module [
1313
errcode_to_str,
1414
decode_record,
1515
map_value,
16+
map_value_result,
1617
tagged_value,
1718
str,
1819
bytes,
@@ -336,7 +337,7 @@ query_many_prepared! = |{ stmt, bindings, rows: decode }|
336337
try(reset!, stmt)
337338
res
338339

339-
SqlDecodeErr err : [FieldNotFound Str, SqliteErr ErrCode Str]err
340+
SqlDecodeErr err : [NoSuchField Str, SqliteErr ErrCode Str]err
340341
SqlDecode a err := List Str -> (Stmt => Result a (SqlDecodeErr err))
341342

342343
## Decode a Sqlite row into a record by combining decoders.
@@ -378,6 +379,31 @@ map_value = |@SqlDecode(gen_decode), mapper|
378379
Ok(mapper(val)),
379380
)
380381

382+
## Transform the output of a decoder by applying a function (that returns a Result) to the decoded value.
383+
## The Result is converted to SqlDecode.
384+
##
385+
## Example:
386+
## ```
387+
## decode_status : Str -> Result OnlineStatus UnknownStatusErr
388+
## decode_status = |status_str|
389+
## when status_str is
390+
## "online" -> Ok(Online)
391+
## "offline" -> Ok(Offline)
392+
## _ -> Err(UnknownStatus("${status_str}"))
393+
##
394+
## Sqlite.str("status") |> Sqlite.map_value_result(decode_status)
395+
## ```
396+
map_value_result : SqlDecode a err, (a -> Result c (SqlDecodeErr err)) -> SqlDecode c err
397+
map_value_result = |@SqlDecode(gen_decode), mapper|
398+
@SqlDecode(
399+
|cols|
400+
decode! = gen_decode(cols)
401+
402+
|stmt|
403+
val = try(decode!, stmt)
404+
mapper(val),
405+
)
406+
381407
RowCountErr err : [NoRowsReturned, TooManyRowsReturned]err
382408

383409
# internal use only
@@ -434,7 +460,7 @@ decoder = |fn|
434460

435461
Err(NotFound) ->
436462
|_|
437-
Err(FieldNotFound(name)),
463+
Err(NoSuchField(name)),
438464
)
439465

440466
## Decode a [Value] keeping it tagged. This is useful when data could be many possible types.

0 commit comments

Comments
 (0)