let fullstring_of_type = fun ty ->
    let opt_of_string = fun s ->
      if s = "" then None else Some s
    and intopt_string = fun iopt ->
      Dbf_misc.apply_opt (Printf.sprintf "(%d)") iopt
    and int2opt_string = fun i2opt ->
      Dbf_misc.apply_opt
        (fun (i1, i2) -> Printf.sprintf "(%d, %d)" i1 i2) i2opt
    in
      match ty with
        | SQL_db.TinyInt   (i, opt)
        | SQL_db.MediumInt (i, opt)
        | SQL_db.Int       (i, opt)
        | SQL_db.BigInt    (i, opt)
          -> join_opt
            ([Some (string_of_type ty);
              intopt_string (i);
              opt_of_string (string_of_numeric_option opt)])

        | SQL_db.Double  (i, opt)
        | SQL_db.Float   (i, opt)
        | SQL_db.Decimal (i, opt)
          -> join_opt
            ([Some (string_of_type ty);
              int2opt_string (i);
              opt_of_string (string_of_numeric_option opt)])

        | SQL_db.Char    i
        | SQL_db.VarChar i
          -> join_opt
            ([Some (string_of_type ty);
              Some (Printf.sprintf "(%d)" i)])

        | SQL_db.TinyBlob   -> string_of_type ty
        | SQL_db.Blob       -> string_of_type ty
        | SQL_db.MediumBlob -> string_of_type ty
        | SQL_db.LongBlob   -> string_of_type ty

        | SQL_db.TinyText   -> string_of_type ty
        | SQL_db.Text       -> string_of_type ty
        | SQL_db.MediumText -> string_of_type ty
        | SQL_db.LongText   -> string_of_type ty