Something I’ve wanted to add to PGX and Mssql for a while is a way to execute a query and deal with each row as they come in, instead of building up a list and then working with that.
For example, it’s common to run a query and then immediately rewrite the result:
Mssql.execute "SELECT a, b, c FROM example"
>>| List.map ~f:t_of_row
This holds the entire DB result set in memory + the list we’re generating, so it uses ~twice as much peak memory as this would (if it existed):
Mssql.execute_map "SELECT a, b, c FROM example" ~f:t_of_row
The list interface also forces you to wait for all of the results to come in, and something like this would be much lower-latency:
Mssql.execute_iter "SELECT a, b, c FROM example ~f:print_row
Unfortunately in databases, some queries return multiple result sets:
Mssql.execute_multi_result db "SELECT a; SELECT b"
>>| fun (results: Row.t list list) -> ...
Which is all background to my question: Is there some map/fold-like interface that makes sense for a function like this, which returns a nested list? Are there examples of libraries that do this?
I can come up with some messy ways to do this if I only care about an iter
version, like:
val execute_multi_result_iter : result_set_over_f:(unit -> unit) -> row_f:(Row.t -> unit) -> db -> unit Deferred.t
But that seems… not ergonomic, and I can’t really figure out how to design a fold
-like function at all.
Am I missing something obvious?