Source file column_lowcardinality.ml

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
open Column_types
open Binary

let reader_lowcardinality_of_spec ~(resolver : string -> in_channel -> int -> value array)
    (s : string) : (in_channel -> int -> value array) option =
  let s = String.lowercase_ascii (String.trim s) in
  if has_prefix s "lowcardinality(" then
    let inner = String.sub s 15 (String.length s - 16) |> String.trim in
    let inner_nullable, inner_base =
      if has_prefix inner "nullable(" then
        (true, String.sub inner 9 (String.length inner - 10) |> String.trim)
      else (false, inner)
    in
    let dict_reader = resolver inner_base in
    Some
      (fun ic n ->
        let index_ser = read_uint64_le ic in
        let key_type = Int64.to_int (Int64.logand index_ser 0xFFL) in
        let index_rows = read_uint64_le ic |> Int64.to_int in
        let dict = if index_rows > 0 then dict_reader ic index_rows else [||] in
        let keys_rows = read_uint64_le ic |> Int64.to_int in
        let read_key () =
          match key_type with
          | 0 -> input_byte ic
          | 1 -> Binary.read_int16_le ic |> Int32.to_int
          | 2 -> Binary.read_int32_le ic |> Int32.to_int
          | _ -> read_uint64_le ic |> Int64.to_int
        in
        let res = Array.make n Null in
        for i = 0 to n - 1 do
          let idx = if i < keys_rows then read_key () else 0 in
          if inner_nullable && idx = 0 then res.(i) <- Null
          else
            let di = if inner_nullable then idx - 1 else idx in
            res.(i) <- (if di >= 0 && di < Array.length dict then dict.(di) else Null)
        done;
        res)
  else None

let reader_lowcardinality_of_spec_br ~(resolver : string -> Buffered_reader.t -> int -> value array)
    (s : string) : (Buffered_reader.t -> int -> value array) option =
  let s = String.lowercase_ascii (String.trim s) in
  if has_prefix s "lowcardinality(" then
    let inner = String.sub s 15 (String.length s - 16) |> String.trim in
    let inner_nullable, inner_base =
      if has_prefix inner "nullable(" then
        (true, String.sub inner 9 (String.length inner - 10) |> String.trim)
      else (false, inner)
    in
    let dict_reader = resolver inner_base in
    Some
      (fun br n ->
        let index_ser = read_uint64_le_br br in
        let key_type = Int64.to_int (Int64.logand index_ser 0xFFL) in
        let index_rows = read_uint64_le_br br |> Int64.to_int in
        let dict = if index_rows > 0 then dict_reader br index_rows else [||] in
        let keys_rows = read_uint64_le_br br |> Int64.to_int in
        let read_key () =
          match key_type with
          | 0 -> read_uint8_br br
          | 1 -> Binary.read_int16_le_br br |> Int32.to_int
          | 2 -> Binary.read_int32_le_br br |> Int32.to_int
          | _ -> read_uint64_le_br br |> Int64.to_int
        in
        let res = Array.make n Null in
        for i = 0 to n - 1 do
          let idx = if i < keys_rows then read_key () else 0 in
          if inner_nullable && idx = 0 then res.(i) <- Null
          else
            let di = if inner_nullable then idx - 1 else idx in
            res.(i) <- (if di >= 0 && di < Array.length dict then dict.(di) else Null)
        done;
        res)
  else None