ygrek / sqlgg

SQL Guided (code) Generator
https://ygrek.org/p/sqlgg/
GNU General Public License v2.0
62 stars 20 forks source link

NULLs handling (in OCaml particularly) #5

Closed gdsfh closed 1 month ago

gdsfh commented 10 years ago

Seems that nullable columns are treated as non-nullable.

create table test1 (opt integer null);

-- @get_test1
select opt from test1;
sqlgg -gen caml -name Make this.sql > that.ml
  let get_test1 db  callback =
    let invoke_callback stmt =
      callback
        (T.get_column_Int stmt 0)
    in
    T.select db "select opt from test1" T.no_params invoke_callback

Signature of T tells us that callback will get num, not an num option.

Fix please!1111

Coobaha commented 5 years ago

@ygrek Hi! Huge thanks for this project! Any update on this?

ygrek commented 5 years ago

I expect it to be huge can of worms and not very excited to open it, given that nullif/ifnull allows to workaround in most cases? Maybe describe your usecase?

Coobaha commented 5 years ago

I don't have particular use case, was just fiddling with your lib. Sometimes it could be possible to have nullable columns that are part of API contract, so handling them with default values looses the context that value was not provided. Suggested workaround with nullif/ifnull forces me to handle this nulls in query which is also error-prone. I would prefer to have Value.t option in my code

ygrek commented 5 years ago

I would prefer to have that to :) For now status is "patches welcome"

ygrek commented 5 years ago

Now option type is generated for NULL columns in resulting schema. This can only happen for column projection from tables, because currently any expression will erase nullable property, but this is expected to cover many cases in practice.

Example from original bugreport now produces :

  let get_test1 db  callback =
    let invoke_callback stmt =
      callback
        ~opt:(T.get_column_Int_nullable stmt 0)
    in
    T.select db ("select opt from test1") T.no_params invoke_callback

and opt has type num option

thx @cyberhuman for the idea

jongleb commented 1 month ago

now

let select_1 db  callback acc =
      let invoke_callback stmt =
        callback
          ~opt:(T.get_column_Int_nullable stmt 0)
      in
      let r_acc = ref acc in
      IO.(>>=) (T.select db ("select opt from test1") T.no_params (fun x -> r_acc := invoke_callback x !r_acc))
      (fun () -> IO.return !r_acc)