Class: OMF::OML::OmlSchema

Inherits:
Base::LObject
  • Object
show all
Defined in:
lib/omf_oml/schema.rb

Overview

This class represents the schema of an OML measurement stream.

Constant Summary collapse

CLASS2TYPE =
{
  TrueClass => 'boolean',
  FalseClass => 'boolean',
  String => 'string',
  Symbol => 'string',
  Fixnum => 'decimal',
  Float => 'double',
  Time => 'dateTime'
}
ANY2TYPE =

Map various type definitions (all lower case) into a single one

{
  'integer' => :integer,
  'int' => :integer,
  'int32' => :integer,
  'int64' => :integer,
  'bigint' => :integer,
  'smallint' => :integer,
  'unsigned integer' => :integer,
  'unsigned bigint' => :integer,
  'float' => :float,
  'real' => :float,
  'double' => :float,
  'double precision' => :float,
  'text' => :string,
  'string' => :string,
  'varargs' => :string,
  'date' => :date,
  'dateTime'.downcase => :dateTime, # should be 'datetime' but we downcase the string for comparison
  'timestamp' => :dateTime, # Postgreql specific, not sure if this works as it.
  'key' => :key,
  'bool' => :bool,
  'blob' => :blob,
  'blob64' => :blob64 # base64 encoded blob
}
OML_INTERNALS =
[
  :oml_sender,
  :oml_sender_id,
  :oml_seq,
  :oml_ts_client,
  :oml_ts_server
]

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.create(schema_description) ⇒ Object



60
61
62
63
64
65
# File 'lib/omf_oml/schema.rb', line 60

def self.create(schema_description)
  if schema_description.kind_of? self
    return schema_description.clone
  end
  return self.new(schema_description)
end

Instance Method Details

#cast_col(col_name, raw_row) ⇒ Object

Cast a named column from a ‘raw’ row into its proper type according to this schema



167
168
169
170
171
172
173
# File 'lib/omf_oml/schema.rb', line 167

def cast_col(col_name, raw_row)
  index = index_for_col(col_name)
  unless raw_value = raw_row[index]
    raise "Row doesn't include a value at '#{index}' (#{raw_row.inspect}-#{describe}) "
  end
  value = @schema[index][:type_conversion].call(raw_value)
end

#cast_row(raw_row, ignore_first_column = false) ⇒ Object

Cast each element in ‘row’ into its proper type according to this schema



152
153
154
155
156
157
158
159
160
161
162
163
# File 'lib/omf_oml/schema.rb', line 152

def cast_row(raw_row, ignore_first_column = false)
  start_index = ignore_first_column ? 1 : 0
  unless raw_row.length == @schema.length - start_index
    raise "Row needs to have same size as schema (#{raw_row.inspect}-#{describe}) "
  end
  # This can be done more elegantly in 1.9
  row = []
  raw_row.each_with_index do |el, i|
    row << @schema[i + start_index][:type_conversion].call(el)
  end
  row
end

#clone(exclude_oml_internals = false) ⇒ Object



183
184
185
186
187
188
189
190
191
192
193
# File 'lib/omf_oml/schema.rb', line 183

def clone(exclude_oml_internals = false)
  c = self.dup
  schema = @schema.clone
  if exclude_oml_internals
    schema = schema.select do |cd|
      not OML_INTERNALS.include?(cd[:name])
    end
  end
  c.instance_variable_set('@schema', schema)
  c
end

#columnsObject



106
107
108
# File 'lib/omf_oml/schema.rb', line 106

def columns
  @schema
end

#describeObject



175
176
177
# File 'lib/omf_oml/schema.rb', line 175

def describe
  @schema.map {|c| {:name => c[:name], :type => c[:type], :title => c[:title] }}
end

#each_column(&block) ⇒ Object



118
119
120
121
122
# File 'lib/omf_oml/schema.rb', line 118

def each_column(&block)
  @schema.each do |c|
    block.call(c)
  end
end

#hash_to_row(hrow, set_nil_when_missing = false, call_type_conversion = false) ⇒ Object

Translate a record described in a hash of ‘col_name => value’ to a row array. Note: Will suppress column ‘__id__’

hrow - Hash describing a row set_nil_when_missing - If true, set any columns not described in hrow to nil



130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
# File 'lib/omf_oml/schema.rb', line 130

def hash_to_row(hrow, set_nil_when_missing = false, call_type_conversion = false)
  #puts "HASH2A => #{hrow.inspect}"
  remove_first_col = false
  r = @schema.collect do |cdescr|
    cname = cdescr[:name]
    if cname == :__id__
      remove_first_col = true
      next nil
    end
    unless (v = hrow[cname]) ||  (v = hrow[cname.to_sym])
      next nil if set_nil_when_missing
      raise "Missing record element '#{cname}' in record '#{hrow}' - schema: #{@schema}"
    end
    call_type_conversion ? cdescr[:type_conversion].call(v) : v
  end
  r.shift if remove_first_col # remove __id__ columns
  #puts "#{r.inspect} -- #{@schema.map {|c| c[:name]}.inspect}"
  r
end

#index_for_col(name) ⇒ Object

Return the col index for column named name



78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/omf_oml/schema.rb', line 78

def index_for_col(name)
  if name.is_a? Integer
    # seems they already know hte index
    index = name
    if (index >= @schema.length)
      raise "Index '#{index}' points past schema - #{schema.length}"
    end
    return index
  end
  name = name.to_sym
  @schema.each_with_index do |col, i|
    return i if col[:name] == name
  end
  raise "Unknown column '#{name}'"
end

#insert_column_at(index, col) ⇒ Object



110
111
112
# File 'lib/omf_oml/schema.rb', line 110

def insert_column_at(index, col)
  @schema.insert(index, _create_col_descr(col))
end

#name_at(index) ⇒ Object

Return the col name at a specific index



69
70
71
72
73
74
# File 'lib/omf_oml/schema.rb', line 69

def name_at(index)
  unless d = @schema[index]
    raise "Index '#{index}' out of bounds"
  end
  d[:name]
end

#namesObject

Return the column names as an array



96
97
98
# File 'lib/omf_oml/schema.rb', line 96

def names
  @schema.collect do |col| col[:name] end
end

#replace_column_at(index, col) ⇒ Object



114
115
116
# File 'lib/omf_oml/schema.rb', line 114

def replace_column_at(index, col)
  @schema[index] = _create_col_descr(col)
end

#to_json(*opt) ⇒ Object



179
180
181
# File 'lib/omf_oml/schema.rb', line 179

def to_json(*opt)
  describe.to_json(*opt)
end

#to_sObject



195
196
197
# File 'lib/omf_oml/schema.rb', line 195

def to_s
  "OmlSchema: #{@schema.map {|c| "#{c[:name]}:#{c[:type]}"}.join(', ')}"
end

#type_at(index) ⇒ Object

Return the col type at a specific index



102
103
104
# File 'lib/omf_oml/schema.rb', line 102

def type_at(index)
  @schema[index][:type]
end