mfp / ocaml-sqlexpr

Minimalistic syntax extension for type-safe, convenient execution of SQL statements.
Other
86 stars 17 forks source link

blocking `select` #31

Open vbmithr opened 5 years ago

vbmithr commented 5 years ago

It seems to me that selecting an empty table blocks, it is possible to have an option type returned in case the table is empty or something?

Haven't looked at it enough maybe but I can't find an easy solution to avoid (lwt-)blocking on an empty table.

mfp commented 5 years ago

On Tue, Jul 24, 2018 at 01:39:28AM -0700, Vincent Bernardoff wrote:

It seems to me that selecting an empty table blocks, it is possible to have an option type returned in case the table is empty or something?

Haven't looked at it enough maybe but I can't find an easy solution to avoid (lwt-)blocking on an empty table.

Do you have a minimal test case for this? I haven't been able to reproduce it with

Sqlexpr_sqlite.Make(Sqlexpr_concurrency.Id), Sqlexpr_sqlite.Make(Sqlexpr_concurrency.Lwt), nor Sqlexpr_sqlite_lwt

with the following code, adapted from the example:

(*   ocamlfind ocamlopt -package sqlexpr,sqlexpr.ppx,lwt.ppx -o example example.ml  -thread -linkpkg *)

module Sqlexpr = Sqlexpr_sqlite.Make(Sqlexpr_concurrency.Lwt)
module S = Sqlexpr

let init_db db =
  S.execute db
    [%sqlinit "CREATE TABLE IF NOT EXISTS users(
              id INTEGER PRIMARY KEY,
              login TEXT UNIQUE,
              password TEXT NON NULL,
              name TEXT,
              email TEXT
            );"]

let fold_users db f acc =
  S.fold db f acc [%sqlc "SELECT @s{login}, @s{password}, @s?{email} FROM users"]

let insert_user db ~login ~password ?name ?email () =
  S.insert db
    [%sqlc"INSERT INTO users(login, password, name, email)
         VALUES(%s, %s, %s?, %s?)"]
    login password name email

let () =
  Lwt_main.run @@
  let db = S.open_db "example.db" in
  let%lwt () = init_db db in
  let%lwt l1 = fold_users db (fun l (login, _, _) -> Lwt.return @@ login :: l) [] in
  let%lwt l2 = S.select db [%sqlc "SELECT @s{login} FROM users"] in
    Printf.printf "%d users\n%!" @@ List.length l1;
    assert (l1 = []);
    assert (l2 = []);
    Lwt.return_unit

let auto_init_db, check_db, auto_check_db = [%sqlcheck "sqlite"]

getting:

$ ./example 
0 users
$

-- Mauricio Fernández