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)