-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcsv.ur
49 lines (45 loc) · 2.08 KB
/
csv.ur
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
fun csvFold [fs] [acc] (f : $fs -> acc -> acc)
(injs : $(map sql_injectable fs)) (reads : $(map read fs)) (fl : folder fs) =
let
fun doLine line acc =
let
val (commas, total, line, acc') =
@foldR [read] [fn r => string -> int * int * string * $r]
(fn [nm ::_] [t ::_] [r ::_] [[nm] ~ r] (_ : read t) acc line =>
case String.split line #"," of
None =>
let
val (commas, total, line, r) = acc line
in
(commas, total+1, "", {nm = readError (String.trim line)} ++ r)
end
| Some (token, line) =>
let
val (commas, total, line, r) = acc line
in
(commas+1, total+1, line, {nm = readError (String.trim token)} ++ r)
end)
(fn line => (0, 0, line, {})) fl reads line
in
if commas <> total-1 || line <> "" then
error <xml>Wrong number of commas in CSV input ({[commas]}, {[total]}, {[line]})</xml>
else
f acc' acc
end
fun loop input acc =
case String.split input #"\n" of
None =>
(case input of
"" => acc
| _ => doLine input acc)
| Some (line, input) =>
loop input (doLine line acc)
in
loop
end
fun parse [fs] (injs : $(map sql_injectable fs)) (reads : $(map read fs)) (fl : folder fs)
(input : string) =
@csvFold (fn r acc => r :: acc) injs reads fl input []
fun importTable [fs] [cs] (injs : $(map sql_injectable fs)) (reads : $(map read fs)) (fl : folder fs)
(tab : sql_table fs cs) (input : string) =
List.app (@Sql.easy_insert injs fl tab) (@parse injs reads fl input)