diff --git a/README.md b/README.md index 584a440..bef6e30 100644 --- a/README.md +++ b/README.md @@ -205,6 +205,8 @@ function. ```ocaml type value = [ `Int of int + | `Int64 of Int64.t + | `UInt64 of Unsigned.UInt64.t | `Float of float | `String of string | `Bytes of bytes @@ -221,6 +223,8 @@ provided to extract the OCaml types directly from a field: ```ocaml val int : Field.t -> int +val int64 : Field.t -> Int64.t +val uint64 : Field.t -> Unsigned.Int64.t val float : Field.t -> float val string : Field.t -> string val bytes : Field.t -> bytes @@ -234,6 +238,8 @@ For nullable fields, the following analogous functions are also provided: ```ocaml val int_opt : Field.t -> int option +val int64_opt : Field.t -> Int64.t option +val uint64_opt : Field.t -> Unsigned.UInt64.t option val float_opt : Field.t -> float option val string_opt : Field.t -> string option val bytes_opt : Field.t -> bytes option diff --git a/examples/async/nonblocking_async_example.ml b/examples/async/nonblocking_async_example.ml index 71196ad..7037915 100644 --- a/examples/async/nonblocking_async_example.ml +++ b/examples/async/nonblocking_async_example.ml @@ -66,6 +66,8 @@ let print_row row = printf "%20s " name; match M.Field.value field with | `Int i -> printf "%d\n%!" i + | `Int64 i -> printf "%Ld\n%!" i + | `UInt64 i -> printf "%s\n%!" (Unsigned.UInt64.to_string i) | `Float x -> printf "%f\n%!" x | `String s -> printf "%s\n%!" s | `Bytes b -> printf "%s\n%!" (Caml_bytes.to_string b) diff --git a/examples/blocking/blocking_example.ml b/examples/blocking/blocking_example.ml index 81de5dd..c4400e3 100644 --- a/examples/blocking/blocking_example.ml +++ b/examples/blocking/blocking_example.ml @@ -17,6 +17,8 @@ let print_row row = printf "%20s " name; match M.Field.value field with | `Int i -> printf "%d\n%!" i + | `Int64 i -> printf "%Ld\n%!" i + | `UInt64 i -> printf "%s\n%!" (Unsigned.UInt64.to_string i) | `Float x -> printf "%f\n%!" x | `String s -> printf "%s\n%!" s | `Bytes b -> printf "%s\n%!" (Bytes.to_string b) diff --git a/examples/lwt/nonblocking_lwt_example.ml b/examples/lwt/nonblocking_lwt_example.ml index 4602598..49b7fbf 100644 --- a/examples/lwt/nonblocking_lwt_example.ml +++ b/examples/lwt/nonblocking_lwt_example.ml @@ -52,6 +52,8 @@ let print_row row = Lwt_io.printf "%20s " name >>= fun () -> match M.Field.value field with | `Int i -> Lwt_io.printf "%d\n%!" i + | `Int64 i -> Lwt_io.printf "%Ld\n%!" i + | `UInt64 i -> Lwt_io.printf "%s\n%!" (Unsigned.UInt64.to_string i) | `Float x -> Lwt_io.printf "%f\n%!" x | `String s -> Lwt_io.printf "%s\n%!" s | `Bytes b -> Lwt_io.printf "%s\n%!" (Bytes.to_string b) diff --git a/examples/select/nonblocking_select_example.ml b/examples/select/nonblocking_select_example.ml index f8ad038..4ad01b8 100644 --- a/examples/select/nonblocking_select_example.ml +++ b/examples/select/nonblocking_select_example.ml @@ -55,6 +55,8 @@ let print_row row = printf "%20s " name; match M.Field.value field with | `Int i -> printf "%d\n%!" i + | `Int64 i -> printf "%Ld\n%!" i + | `UInt64 i -> printf "%s\n%!" (Unsigned.UInt64.to_string i) | `Float x -> printf "%f\n%!" x | `String s -> printf "%s\n%!" s | `Bytes b -> printf "%s\n%!" (Bytes.to_string b) diff --git a/lib/bind.ml b/lib/bind.ml index 4927f86..b7c9ef7 100644 --- a/lib/bind.ml +++ b/lib/bind.ml @@ -124,6 +124,15 @@ let int ?(unsigned = false) b param ~at = ~unsigned:(if unsigned then yes else no) ~at +let int64 ?(unsigned = false) b param ~at = + let p = allocate int64_t param in + bind b + ~buffer:(coerce (ptr int64_t) (ptr void) p) + ~size:(sizeof int64_t) + ~mysql_type:T.Type.long_long + ~unsigned:(if unsigned then yes else no) + ~at + let float b param ~at = let p = allocate float param in bind b diff --git a/lib/common.ml b/lib/common.ml index 397df26..39ae627 100644 --- a/lib/common.ml +++ b/lib/common.ml @@ -323,6 +323,8 @@ module Stmt = struct match arg with | `Null -> Bind.null b ~at | `Int i -> Bind.int b i ~at + | `Int64 i -> Bind.int64 b i ~at + | `UInt64 i -> Bind.int64 ~unsigned:true b (Unsigned.UInt64.to_int64 i) ~at | `Float x -> Bind.float b x ~at | `String s -> Bind.string b s ~at | `Bytes s -> Bind.blob b s ~at diff --git a/lib/field.ml b/lib/field.ml index 7bd383e..b3ee12a 100644 --- a/lib/field.ml +++ b/lib/field.ml @@ -5,6 +5,8 @@ module T = Ffi_generated.Types type value = [ `Null | `Int of int + | `Int64 of Int64.t + | `UInt64 of Unsigned.UInt64.t | `Float of float | `String of string | `Bytes of bytes @@ -81,8 +83,8 @@ let convert field typ unsigned = | `Short, false -> `Int (UInt.to_int (cast_to uint field)) | (`Int24 | `Long), true -> `Int (UInt32.to_int (cast_to uint32_t field)) | (`Int24 | `Long), false -> `Int (Int32.to_int (cast_to int32_t field)) - | `Long_long, true -> `Int (UInt64.to_int (cast_to uint64_t field)) - | `Long_long, false -> `Int (Int64.to_int (cast_to int64_t field)) + | `Long_long, true -> `UInt64 (cast_to uint64_t field) + | `Long_long, false -> `Int64 (cast_to int64_t field) | `Float, _ -> `Float (cast_to float field) | `Double, _ -> `Float (cast_to double field) | #to_string, _ -> `String (Bytes.to_string (to_bytes field)) @@ -102,8 +104,21 @@ let err field ~info = let int field = match value field with | `Int i -> i + | `Int64 i -> Int64.to_int i + | `UInt64 i -> Unsigned.UInt64.to_int i | _ -> err field ~info:"an integer" +let int64 field = + match value field with + | `Int i -> Int64.of_int i + | `Int64 i -> i + | _ -> err field ~info:"a 64-bit integer" + +let uint64 field = + match value field with + | `UInt64 i -> i + | _ -> err field ~info:"a 64-bit unsigned integer" + let float field = match value field with | `Float x -> x @@ -127,9 +142,24 @@ let time field = let int_opt field = match value field with | `Int i -> Some i + | `Int64 i -> Some (Int64.to_int i) + | `UInt64 i -> Some (Unsigned.UInt64.to_int i) | `Null -> None | _ -> err field ~info:"a nullable integer" +let int64_opt field = + match value field with + | `Int i -> Some (Int64.of_int i) + | `Int64 i -> Some i + | `Null -> None + | _ -> err field ~info:"a nullable 64-bit integer" + +let uint64_opt field = + match value field with + | `UInt64 i -> Some i + | `Null -> None + | _ -> err field ~info:"a nullable 64-bit unsigned integer" + let float_opt field = match value field with | `Float x -> Some x diff --git a/lib/mariadb.ml b/lib/mariadb.ml index 85b7be9..5ca6e36 100644 --- a/lib/mariadb.ml +++ b/lib/mariadb.ml @@ -29,6 +29,8 @@ module type S = sig type value = [ `Null | `Int of int + | `Int64 of Int64.t + | `UInt64 of Unsigned.UInt64.t | `Float of float | `String of string | `Bytes of bytes @@ -41,12 +43,16 @@ module type S = sig val can_be_null : t -> bool val int : t -> int + val int64 : t -> Int64.t + val uint64 : t -> Unsigned.UInt64.t val float : t -> float val string : t -> string val bytes : t -> bytes val time : t -> Time.t val int_opt : t -> int option + val int64_opt : t -> Int64.t option + val uint64_opt : t -> Unsigned.UInt64.t option val float_opt : t -> float option val string_opt : t -> string option val bytes_opt : t -> bytes option diff --git a/lib/mariadb.mli b/lib/mariadb.mli index 0e39c8d..4cc78c8 100644 --- a/lib/mariadb.mli +++ b/lib/mariadb.mli @@ -51,6 +51,8 @@ module type S = sig type value = [ `Null | `Int of int + | `Int64 of Int64.t + | `UInt64 of Unsigned.UInt64.t | `Float of float | `String of string | `Bytes of bytes @@ -81,12 +83,16 @@ module type S = sig *) val int : t -> int + val int64 : t -> Int64.t + val uint64 : t -> Unsigned.UInt64.t val float : t -> float val string : t -> string val bytes : t -> bytes val time : t -> Time.t val int_opt : t -> int option + val int64_opt : t -> Int64.t option + val uint64_opt : t -> Unsigned.UInt64.t option val float_opt : t -> float option val string_opt : t -> string option val bytes_opt : t -> bytes option @@ -385,6 +391,8 @@ module Nonblocking : sig type value = [ `Null | `Int of int + | `Int64 of Int64.t + | `UInt64 of Unsigned.UInt64.t | `Float of float | `String of string | `Bytes of bytes @@ -397,12 +405,16 @@ module Nonblocking : sig val can_be_null : t -> bool val int : t -> int + val int64 : t -> Int64.t + val uint64 : t -> Unsigned.UInt64.t val float : t -> float val string : t -> string val bytes : t -> bytes val time : t -> Time.t val int_opt : t -> int option + val int64_opt : t -> Int64.t option + val uint64_opt : t -> Unsigned.UInt64.t option val float_opt : t -> float option val string_opt : t -> string option val bytes_opt : t -> bytes option diff --git a/lib/nonblocking.ml b/lib/nonblocking.ml index 0184ff2..32b2321 100644 --- a/lib/nonblocking.ml +++ b/lib/nonblocking.ml @@ -398,6 +398,8 @@ module type S = sig type value = [ `Null | `Int of int + | `Int64 of Int64.t + | `UInt64 of Unsigned.UInt64.t | `Float of float | `String of string | `Bytes of bytes @@ -410,12 +412,16 @@ module type S = sig val can_be_null : t -> bool val int : t -> int + val int64 : t -> Int64.t + val uint64 : t -> Unsigned.UInt64.t val float : t -> float val string : t -> string val bytes : t -> bytes val time : t -> Time.t val int_opt : t -> int option + val int64_opt : t -> Int64.t option + val uint64_opt : t -> Unsigned.UInt64.t option val float_opt : t -> float option val string_opt : t -> string option val bytes_opt : t -> bytes option diff --git a/tests/nonblocking/nonblocking_testsuite.ml b/tests/nonblocking/nonblocking_testsuite.ml index c186f9a..3192324 100644 --- a/tests/nonblocking/nonblocking_testsuite.ml +++ b/tests/nonblocking/nonblocking_testsuite.ml @@ -86,6 +86,8 @@ struct let string_of_value = function | `Null -> "NULL" | `Int i -> sprintf "(%d : int)" i + | `Int64 i -> sprintf "(%Ld : int64)" i + | `UInt64 i -> sprintf "(%s : uint64)" (Unsigned.UInt64.to_string i) | `Float x -> sprintf "(%.8g : float)" x | `String s -> sprintf "(%S : string)" s | `Bytes s -> sprintf "(%S : bytes)" (Bytes.to_string s) @@ -106,7 +108,14 @@ struct | `Null, _ | _, `Null -> false | `Int i, `Int i' -> i = i' | `Int i, `Float x | `Float x, `Int i -> float_of_int i = x + | `Int64 i, `Int x | `Int x, `Int64 i -> Int64.(equal i (of_int x)) + | `Int64 i, `Float x | `Float x, `Int64 i -> Int64.to_float i = x + | `UInt64 i, `Int x | `Int x, `UInt64 i -> Unsigned.UInt64.(equal i (of_int x)) + | `UInt64 i, `Float x | `Float x, `UInt64 i -> Int64.to_float (Unsigned.UInt64.to_int64 i) = x + | `UInt64 i, `Int64 x | `Int64 x, `UInt64 i -> Int64.equal (Unsigned.UInt64.to_int64 i) x | `Int _, _ | _, `Int _ -> false + | `Int64 _, _ | _, `Int64 _ -> false + | `UInt64 _, _ | _, `UInt64 _ -> false | `Float x, `Float x' -> equal_float x x' | `Float _, _ | _, `Float _ -> false | `String s, `String s' -> s = s'