aboutsummaryrefslogtreecommitdiff
path: root/lib/errors/importErrors.ml
blob: 04f9deb850cf4953cfc8fac6855b5bd55694f5fc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
open StdLabels
module CSV = ImportCSV
module Table = ImportDataTypes.Table

let bom = "\xEF\xBB\xBF"

type xlsError = {
  source : Table.t;
  row : int;
  sheet : int;
  target : Table.t option;
  value : CSV.DataType.t;
  exn : exn;
}

exception
  JsonError of {
    json : string;
    element : string;
  }

exception InvalidEncoding of string
exception NullKey of int
exception SqlError of Sqlite3.Rc.t
exception MisplacedWindow
exception Unknown_source of string
exception Unknown_extension of string

exception Cycle of string list
(** Cycle between the dpendencies *)

exception
  TypeError of {
    expected : ImportDataTypes.Types.t;
    actual : ImportDataTypes.Types.t;
    expression : string;
    subset : string;
  }

let repr_error = function
  | SqlError s -> Printf.sprintf "%s Error" (Sqlite3.Rc.to_string s)
  | JsonError { json; element } -> Printf.sprintf "%s : %s" element json
  | NullKey k ->
      Printf.sprintf "The key %s is null" (ImportCSV.Csv.column_to_string k)
  | Unknown_source source ->
      Printf.sprintf "The source %s is referenced without beiing declared"
        source
  | MisplacedWindow -> "A group function cannot appear here"
  | TypeError { expected; actual; expression; subset } ->
      Printf.sprintf
        "In this expression %s has type %s but %s was expected:\n%s" subset
        (ImportDataTypes.Types.string_of_t actual)
        (ImportDataTypes.Types.string_of_t expected)
        expression
  | Unknown_extension ext -> Printf.sprintf "Unknown file extension %s" ext
  | Cycle deps ->
      Printf.sprintf "Cycle between the dependencies : %s"
        (String.concat ~sep:"," deps)
  | Failure e -> e
  | e ->
      Printexc.print_backtrace Stdlib.stdout;
      Printexc.to_string e

type t = Csv.out_channel Lazy.t

let output_error : t -> xlsError -> unit =
 fun csv error ->
  let target =
    match error.target with
    | None -> ""
    | Some value -> value.name
  in

  Csv.output_record (Lazy.force csv)
    [
      Table.name error.source;
      string_of_int error.sheet;
      string_of_int error.row;
      target;
      CSV.DataType.to_string error.value;
      repr_error error.exn;
    ]

let log : with_bom:bool -> string -> string -> t =
 fun ~with_bom prefix dirname ->
  lazy
    (let file = Filename.concat dirname (String.cat prefix "_errors.csv") in

     prerr_endline @@ String.cat "Errors found. See the file " file;

     (* Open the error file *)
     let channel = Out_channel.open_bin file in
     if with_bom then output_string channel bom;
     let log_error = Csv.to_channel ~separator:';' ~excel_tricks:true channel in
     (* Generate a header for the error file *)
     Csv.output_record log_error
       [ "Source"; "Tab"; "Row"; "Target"; "Value"; "Error" ];
     log_error)