Class: RubyVolt::DataType::VoltTable

Inherits:
Complex show all
Defined in:
lib/ruby_volt/data_type/complex/volt_table.rb

Class Method Summary collapse

Methods inherited from RubyVolt::DataType

classifyDataType, testpacking, voltDataType

Class Method Details

.pack(columns, rows) ⇒ Object



6
7
8
9
10
11
12
13
14
15
16
17
18
# File 'lib/ruby_volt/data_type/complex/volt_table.rb', line 6

def pack(columns, rows)
  # The "Table Metadata Length" stores the length in bytes of the contents of the table from byte 8 (the end of the metadata length field) all the way to the end of the "Column Names" sequence. NOTE: It does not include the row count value. See below for an example.
  status_code = ProcedureCallStatusCode.pack(0) # OK Status code
  columns_sequence = pack_columns(columns) # Columns data
  rows_sequence = pack_rows(columns, rows) # Rows data
   = status_code.bytesize + columns_sequence.bytesize # Table Metadata Length
  total_table_length =  + rows_sequence.bytesize # Total Table Length
  [Integer.pack(total_table_length),
   Integer.pack(),
   status_code,
   columns_sequence,
   rows_sequence].join
end

.pack_columns(columns = []) ⇒ Object

[“column”, DataType]

ex.: [[“city”, :String], [“population”, :Long]]



33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/ruby_volt/data_type/complex/volt_table.rb', line 33

def pack_columns(columns = []) # [["column", DataType]] ex.: [["city", :String], ["population", :Long]]
  # The size of the "Column Types" and "Column Names" sequences is expected to equal the value stored in "Column Count".
  # Column names are limited to the ASCII character set. Strings in row values are still UTF-8 encoded.
  # Values with 4-byte (integer) length fields are signed and are limited to a max of 1 megabyte.
  col_types, col_names = [], []
  columns.each do |col|
    col_name, dataType = *col
    col_name = "modified_tuples" if col_name == ""
    dataType = classifyDataType(dataType) unless dataType < DataType
    col_types << WireTypeInfo.pack(dataType)
    col_names << Varbinary.pack(col_name) # ASCII-8bit
  end
  Short.pack(columns.size) + col_types.join + col_names.join
end

.pack_rows(columns, rows = []) ⇒ Object

[val1, val2, …]


60
61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/ruby_volt/data_type/complex/volt_table.rb', line 60

def pack_rows(columns, rows = []) # [[val1, val2, ...]]
  # Each row is preceded by a 4 byte integer that holds the length of the row not including the length. For example, if a row is a single 4-byte integer column, the value of this length prefix will be 4. Row size is artificially restricted to 2 megabytes.
  # The body of the row is packed array of values. The value at index i is is of type specified by the column type field for index i.
  Integer.pack(rows.size) + # Row count
  rows.map do |row_values|
    rlength = 0
    row_values.map.with_index do |val, index|
      dataType = columns[index][1]
      packed = dataType.pack(val)
      rlength += packed.bytesize
      packed
    end.join.prepend(Integer.pack(rlength))
  end.join
end

.unpack(bytes, &block) ⇒ Object



20
21
22
23
24
25
# File 'lib/ruby_volt/data_type/complex/volt_table.rb', line 20

def unpack(bytes, &block)
  table_info = unpack_table_info(bytes)
  columns = unpack_columns(bytes)
  rows = unpack_rows(columns, bytes, &block)
  [*table_info, columns, rows]
end

.unpack_columns(bytes) ⇒ Object



48
49
50
51
52
53
54
55
56
57
58
# File 'lib/ruby_volt/data_type/complex/volt_table.rb', line 48

def unpack_columns(bytes)
  columns_count = Short.unpack(bytes)
  columns = columns_count.times.map do
    WireTypeInfo.unpack(bytes)
  end
  columns.map do |dataType|
    col_name = Varbinary.unpack(bytes) # ASCII-8bit
    col_name = "modified_tuples" if col_name == ""
    [col_name, dataType]
  end
end

.unpack_rows(columns, bytes, &block) ⇒ Object

Block for parsing on fly



75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/ruby_volt/data_type/complex/volt_table.rb', line 75

def unpack_rows(columns, bytes, &block) # Block for parsing on fly
  rows_count = Integer.unpack(bytes)
  rows = []
  rows_count.times do
    Integer.unpack(bytes) # Bytesize of row length
    row = columns.map do |c|
      dataType = c[1]
      dataType.unpack(bytes)
    end
    if block_given?
      yield(row)
    else
      rows << row
    end
  end
  rows
end

.unpack_table_info(bytes) ⇒ Object



27
28
29
30
31
# File 'lib/ruby_volt/data_type/complex/volt_table.rb', line 27

def unpack_table_info(bytes)
  [Integer.unpack(bytes), # total_table_length
   Integer.unpack(bytes), # table_metadata_length
   ProcedureCallStatusCode.unpack(bytes)] # status_code
end