omf_oml 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/lib/omf_oml/endpoint.rb +50 -12
- data/lib/omf_oml/oml_tuple.rb +28 -28
- data/lib/omf_oml/schema.rb +64 -38
- data/lib/omf_oml/sql_row.rb +1 -1
- data/lib/omf_oml/sql_source.rb +19 -4
- data/lib/omf_oml/table.rb +2 -2
- data/lib/omf_oml/tuple.rb +23 -34
- data/lib/omf_oml/version.rb +1 -1
- metadata +4 -3
data/lib/omf_oml/endpoint.rb
CHANGED
@@ -30,6 +30,7 @@ module OMF::OML
|
|
30
30
|
|
31
31
|
def initialize(port = 5000, host = "0.0.0.0")
|
32
32
|
require 'socket'
|
33
|
+
debug "OML client listening on #{port}"
|
33
34
|
@serv = TCPServer.new(host, port)
|
34
35
|
@running = false
|
35
36
|
@on_new_stream_procs = {}
|
@@ -108,7 +109,7 @@ module OMF::OML
|
|
108
109
|
private
|
109
110
|
def parse_header(socket, &reportStreamProc)
|
110
111
|
while (l = socket.gets.strip)
|
111
|
-
#puts "H>> '#{l}'"
|
112
|
+
#puts "H>> '#{l}'"
|
112
113
|
return if l.length == 0
|
113
114
|
|
114
115
|
key, *value = l.split(':')
|
@@ -126,29 +127,64 @@ module OMF::OML
|
|
126
127
|
els = desc.split(' ')
|
127
128
|
#puts "ELS: #{els.inspect}"
|
128
129
|
index = els.shift.to_i - 1
|
130
|
+
if (index < 0)
|
131
|
+
# meta data - ignore
|
132
|
+
return
|
133
|
+
end
|
134
|
+
if @streams[index]
|
135
|
+
warn "Schema '#{index}' already defined"
|
136
|
+
return
|
137
|
+
end
|
129
138
|
sname = els.shift
|
130
139
|
schema_desc = els.collect do |el|
|
131
140
|
name, type = el.split(':')
|
141
|
+
if (type == 'blob'); type = 'blob64' end # base64 encode blob
|
132
142
|
{:name => name.to_sym, :type => type.to_sym}
|
133
143
|
end
|
134
144
|
schema_desc.insert(0, {:name => :oml_ts, :type => :double})
|
135
145
|
schema_desc.insert(1, {:name => :sender_id, :type => :string})
|
136
|
-
schema_desc.insert(2, {:name => :oml_seq_no, :type => :integer})
|
146
|
+
schema_desc.insert(2, {:name => :oml_seq_no, :type => :integer})
|
137
147
|
schema = OMF::OML::OmlSchema.create(schema_desc)
|
148
|
+
debug "New schema '#{sname}(#{index})' with schema '#{schema}'"
|
138
149
|
@streams[index] = tuple = OmlTuple.new(sname, schema)
|
139
150
|
@endpoint.report_new_stream(sname, tuple)
|
140
151
|
end
|
141
152
|
|
153
|
+
def parse_meta_row(row)
|
154
|
+
#puts "META>> #{row.inspect}"
|
155
|
+
unless row.length == 5
|
156
|
+
warn "Received mis-formatted META tuple - #{row}"
|
157
|
+
return
|
158
|
+
end
|
159
|
+
key = "#{row[2]}/#{row[3]}".downcase
|
160
|
+
value = row[4]
|
161
|
+
debug "META: '#{key}' - '#{value}'"
|
162
|
+
case key
|
163
|
+
when './schema'
|
164
|
+
parse_schema(value)
|
165
|
+
else
|
166
|
+
warn "Unknwon META type '#{key}'"
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
142
170
|
def parse_rows(socket)
|
143
171
|
sender_id = @header['sender-id'] || 'unknown'
|
144
172
|
while (l = socket.gets)
|
145
173
|
return if l.length == 0
|
146
174
|
|
147
175
|
els = l.strip.split("\t")
|
148
|
-
#puts "R>> '#{els.inspect}'"
|
149
|
-
index = els.delete_at(1).to_i
|
176
|
+
#puts "R(#{sender_id})>> '#{els.inspect}'"
|
177
|
+
index = els.delete_at(1).to_i
|
178
|
+
if (index == 0)
|
179
|
+
parse_meta_row(els)
|
180
|
+
next
|
181
|
+
end
|
182
|
+
unless stream = @streams[index - 1]
|
183
|
+
warn "Receiving tuples for unknown schema index '#{index}'"
|
184
|
+
next
|
185
|
+
end
|
150
186
|
els.insert(1, sender_id)
|
151
|
-
row = @streams[index].parse_tuple(els)
|
187
|
+
row = @streams[index - 1].parse_tuple(els)
|
152
188
|
end
|
153
189
|
end
|
154
190
|
|
@@ -160,13 +196,15 @@ end
|
|
160
196
|
if $0 == __FILE__
|
161
197
|
|
162
198
|
require 'omf_oml/table'
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
199
|
+
require 'omf_base/lobject'
|
200
|
+
OMF::Base::Loggable.init_log 'endpoint'
|
201
|
+
|
202
|
+
ep = OMF::OML::OmlEndpoint.new(3003)
|
203
|
+
ep.on_new_stream() do |name, stream|
|
204
|
+
puts "New stream: #{name}-#{stream}"
|
205
|
+
table = stream.create_table(name + '_tbl', :max_size => 5)
|
206
|
+
table.on_content_changed do |action, change|
|
207
|
+
puts "TTTT > #{action} - #{change}"
|
170
208
|
end
|
171
209
|
end
|
172
210
|
ep.run(false)
|
data/lib/omf_oml/oml_tuple.rb
CHANGED
@@ -9,15 +9,15 @@ require 'omf_oml/schema'
|
|
9
9
|
require 'omf_oml/tuple'
|
10
10
|
|
11
11
|
module OMF::OML
|
12
|
-
|
12
|
+
|
13
13
|
# This class represents a single vector from an OML measurement stream.
|
14
14
|
# It provides various methods to access the vectors elements.
|
15
15
|
#
|
16
|
-
# NOTE: Do not store the vector itself, but make a copy as the instance may be
|
16
|
+
# NOTE: Do not store the vector itself, but make a copy as the instance may be
|
17
17
|
# reused over various rows by the sender.
|
18
18
|
#
|
19
19
|
class OmlTuple < Tuple
|
20
|
-
|
20
|
+
|
21
21
|
# Return the elements of the vector as an array
|
22
22
|
# def to_a(include_index_ts = false)
|
23
23
|
# res = []
|
@@ -31,39 +31,39 @@ module OMF::OML
|
|
31
31
|
# end
|
32
32
|
# res
|
33
33
|
# end
|
34
|
-
|
34
|
+
|
35
35
|
def ts
|
36
36
|
@raw[0].to_f
|
37
37
|
end
|
38
|
-
|
38
|
+
|
39
39
|
def seq_no
|
40
40
|
@raw[1].to_i
|
41
41
|
end
|
42
|
-
|
42
|
+
|
43
43
|
# Note: This method assumes that the first two elements in each OML tuple,
|
44
44
|
# 'oml_ts' and 'oml_seq_no' are not defined in the associated schema.
|
45
45
|
#
|
46
|
-
def process_schema(schema)
|
47
|
-
i = 0
|
48
|
-
@vprocs = {}
|
49
|
-
schema.each_column do |col| #
|
50
|
-
name = col[:name] || raise("Ill-formed schema '#{schema}'")
|
51
|
-
type = col[:type] || raise("Ill-formed schema '#{schema}'")
|
52
|
-
j = i + 2; # need to create a locally scoped variable for the following lambdas
|
53
|
-
@vprocs[name] = @vprocs[i] = case type
|
54
|
-
when :string
|
55
|
-
lambda do |r| r[j] end
|
56
|
-
when :float
|
57
|
-
lambda do |r| r[j].to_f end
|
58
|
-
when :integer
|
59
|
-
lambda do |r| r[j].to_i end
|
60
|
-
else raise "Unrecognized OML type '#{type}' (#{col.inspect})"
|
61
|
-
end
|
62
|
-
i += 1
|
63
|
-
end
|
64
|
-
@vprocs[:oml_ts] = lambda do |r| r[0].to_f end
|
65
|
-
@vprocs[:oml_seq_no] = lambda do |r| r[1].to_i end
|
66
|
-
end
|
67
|
-
|
46
|
+
# def process_schema(schema)
|
47
|
+
# i = 0
|
48
|
+
# @vprocs = {}
|
49
|
+
# schema.each_column do |col| #
|
50
|
+
# name = col[:name] || raise("Ill-formed schema '#{schema}'")
|
51
|
+
# type = col[:type] || raise("Ill-formed schema '#{schema}'")
|
52
|
+
# j = i + 2; # need to create a locally scoped variable for the following lambdas
|
53
|
+
# @vprocs[name] = @vprocs[i] = case type
|
54
|
+
# when :string
|
55
|
+
# lambda do |r| r[j] end
|
56
|
+
# when :float
|
57
|
+
# lambda do |r| r[j].to_f end
|
58
|
+
# when :integer
|
59
|
+
# lambda do |r| r[j].to_i end
|
60
|
+
# else raise "Unrecognized OML type '#{type}' (#{col.inspect})"
|
61
|
+
# end
|
62
|
+
# i += 1
|
63
|
+
# end
|
64
|
+
# @vprocs[:oml_ts] = lambda do |r| r[0].to_f end
|
65
|
+
# @vprocs[:oml_seq_no] = lambda do |r| r[1].to_i end
|
66
|
+
# end
|
67
|
+
|
68
68
|
end # OmlTuple
|
69
69
|
end # OMF::OML
|
data/lib/omf_oml/schema.rb
CHANGED
@@ -8,21 +8,21 @@ require 'omf_base/lobject'
|
|
8
8
|
require 'omf_oml'
|
9
9
|
|
10
10
|
module OMF::OML
|
11
|
-
|
11
|
+
|
12
12
|
# This class represents the schema of an OML measurement stream.
|
13
13
|
#
|
14
14
|
class OmlSchema < OMF::Base::LObject
|
15
|
-
|
15
|
+
|
16
16
|
CLASS2TYPE = {
|
17
17
|
TrueClass => 'boolean',
|
18
18
|
FalseClass => 'boolean',
|
19
19
|
String => 'string',
|
20
|
-
Symbol => 'string',
|
20
|
+
Symbol => 'string',
|
21
21
|
Fixnum => 'decimal',
|
22
22
|
Float => 'double',
|
23
23
|
Time => 'dateTime'
|
24
24
|
}
|
25
|
-
|
25
|
+
|
26
26
|
# Map various type definitions (all lower case) into a single one
|
27
27
|
ANY2TYPE = {
|
28
28
|
'integer' => :integer,
|
@@ -43,9 +43,12 @@ module OMF::OML
|
|
43
43
|
'date' => :date,
|
44
44
|
'dateTime'.downcase => :dateTime, # should be 'datetime' but we downcase the string for comparison
|
45
45
|
'timestamp' => :dateTime, # Postgreql specific, not sure if this works as it.
|
46
|
-
'key' => :key,
|
46
|
+
'key' => :key,
|
47
|
+
'bool' => :bool,
|
48
|
+
'blob' => :blob,
|
49
|
+
'blob64' => :blob64 # base64 encoded blob
|
47
50
|
}
|
48
|
-
|
51
|
+
|
49
52
|
OML_INTERNALS = [
|
50
53
|
:oml_sender,
|
51
54
|
:oml_sender_id,
|
@@ -60,7 +63,7 @@ module OMF::OML
|
|
60
63
|
end
|
61
64
|
return self.new(schema_description)
|
62
65
|
end
|
63
|
-
|
66
|
+
|
64
67
|
# Return the col name at a specific index
|
65
68
|
#
|
66
69
|
def name_at(index)
|
@@ -69,17 +72,25 @@ module OMF::OML
|
|
69
72
|
end
|
70
73
|
d[:name]
|
71
74
|
end
|
72
|
-
|
75
|
+
|
73
76
|
# Return the col index for column named +name+
|
74
77
|
#
|
75
78
|
def index_for_col(name)
|
79
|
+
if name.is_a? Integer
|
80
|
+
# seems they already know hte index
|
81
|
+
index = name
|
82
|
+
if (index >= @schema.length)
|
83
|
+
raise "Index '#{index}' points past schema - #{schema.length}"
|
84
|
+
end
|
85
|
+
return index
|
86
|
+
end
|
76
87
|
name = name.to_sym
|
77
88
|
@schema.each_with_index do |col, i|
|
78
|
-
return i if col[:name] == name
|
89
|
+
return i if col[:name] == name
|
79
90
|
end
|
80
|
-
raise "
|
91
|
+
raise "Unknown column '#{name}'"
|
81
92
|
end
|
82
|
-
|
93
|
+
|
83
94
|
# Return the column names as an array
|
84
95
|
#
|
85
96
|
def names
|
@@ -91,25 +102,25 @@ module OMF::OML
|
|
91
102
|
def type_at(index)
|
92
103
|
@schema[index][:type]
|
93
104
|
end
|
94
|
-
|
105
|
+
|
95
106
|
def columns
|
96
107
|
@schema
|
97
108
|
end
|
98
|
-
|
109
|
+
|
99
110
|
def insert_column_at(index, col)
|
100
|
-
@schema.insert(index, _create_col_descr(col))
|
111
|
+
@schema.insert(index, _create_col_descr(col))
|
101
112
|
end
|
102
|
-
|
113
|
+
|
103
114
|
def replace_column_at(index, col)
|
104
115
|
@schema[index] = _create_col_descr(col)
|
105
116
|
end
|
106
117
|
|
107
118
|
def each_column(&block)
|
108
|
-
@schema.each do |c|
|
109
|
-
block.call(c)
|
119
|
+
@schema.each do |c|
|
120
|
+
block.call(c)
|
110
121
|
end
|
111
122
|
end
|
112
|
-
|
123
|
+
|
113
124
|
# Translate a record described in a hash of 'col_name => value'
|
114
125
|
# to a row array. Note: Will suppress column '__id__'
|
115
126
|
#
|
@@ -127,7 +138,7 @@ module OMF::OML
|
|
127
138
|
end
|
128
139
|
unless (v = hrow[cname]) || (v = hrow[cname.to_sym])
|
129
140
|
next nil if set_nil_when_missing
|
130
|
-
raise "Missing record element '#{cname}' in record '#{hrow}'"
|
141
|
+
raise "Missing record element '#{cname}' in record '#{hrow}' - schema: #{@schema}"
|
131
142
|
end
|
132
143
|
call_type_conversion ? cdescr[:type_conversion].call(v) : v
|
133
144
|
end
|
@@ -135,7 +146,7 @@ module OMF::OML
|
|
135
146
|
#puts "#{r.inspect} -- #{@schema.map {|c| c[:name]}.inspect}"
|
136
147
|
r
|
137
148
|
end
|
138
|
-
|
149
|
+
|
139
150
|
# Cast each element in 'row' into its proper type according to this schema
|
140
151
|
#
|
141
152
|
def cast_row(raw_row, ignore_first_column = false)
|
@@ -150,15 +161,25 @@ module OMF::OML
|
|
150
161
|
end
|
151
162
|
row
|
152
163
|
end
|
153
|
-
|
164
|
+
|
165
|
+
# Cast a named column from a 'raw' row into its proper type according to this schema
|
166
|
+
#
|
167
|
+
def cast_col(col_name, raw_row)
|
168
|
+
index = index_for_col(col_name)
|
169
|
+
unless raw_value = raw_row[index]
|
170
|
+
raise "Row doesn't include a value at '#{index}' (#{raw_row.inspect}-#{describe}) "
|
171
|
+
end
|
172
|
+
value = @schema[index][:type_conversion].call(raw_value)
|
173
|
+
end
|
174
|
+
|
154
175
|
def describe
|
155
176
|
@schema.map {|c| {:name => c[:name], :type => c[:type], :title => c[:title] }}
|
156
177
|
end
|
157
|
-
|
178
|
+
|
158
179
|
def to_json(*opt)
|
159
180
|
describe.to_json(*opt)
|
160
181
|
end
|
161
|
-
|
182
|
+
|
162
183
|
def clone(exclude_oml_internals = false)
|
163
184
|
c = self.dup
|
164
185
|
schema = @schema.clone
|
@@ -170,13 +191,13 @@ module OMF::OML
|
|
170
191
|
c.instance_variable_set('@schema', schema)
|
171
192
|
c
|
172
193
|
end
|
173
|
-
|
194
|
+
|
174
195
|
def to_s
|
175
196
|
"OmlSchema: #{@schema.map {|c| "#{c[:name]}:#{c[:type]}"}.join(', ')}"
|
176
197
|
end
|
177
|
-
|
198
|
+
|
178
199
|
protected
|
179
|
-
|
200
|
+
|
180
201
|
# schema_description - Array containing [name, type*] for every column in table
|
181
202
|
# TODO: define format of TYPE
|
182
203
|
#
|
@@ -187,9 +208,9 @@ module OMF::OML
|
|
187
208
|
insert_column_at(i, cdesc)
|
188
209
|
end
|
189
210
|
debug "schema: '#{describe.inspect}'"
|
190
|
-
|
211
|
+
|
191
212
|
end
|
192
|
-
|
213
|
+
|
193
214
|
# Create a column descriptor from whatever is given by user
|
194
215
|
#
|
195
216
|
def _create_col_descr(col)
|
@@ -199,12 +220,12 @@ module OMF::OML
|
|
199
220
|
if col.kind_of? Array
|
200
221
|
# should be [name, type]
|
201
222
|
if col.length == 1
|
202
|
-
col = {:name => col[0].to_sym,
|
203
|
-
:type => :string,
|
223
|
+
col = {:name => col[0].to_sym,
|
224
|
+
:type => :string,
|
204
225
|
:title => col[0].to_s.split('_').collect {|s| s.capitalize}.join(' ')}
|
205
226
|
elsif col.length == 2
|
206
227
|
col = {:name => col[0].to_sym,
|
207
|
-
:type => col[1].to_sym,
|
228
|
+
:type => col[1].to_sym,
|
208
229
|
:title => col[0].to_s.split('_').collect {|s| s.capitalize}.join(' ')}
|
209
230
|
elsif col.length == 3
|
210
231
|
col = {:name => col[0].to_sym, :type => col[1].to_sym, :title => col[2]}
|
@@ -217,7 +238,7 @@ module OMF::OML
|
|
217
238
|
col[:title] = col[:name].to_s.split('_').collect {|s| s.capitalize}.join(' ')
|
218
239
|
end
|
219
240
|
end
|
220
|
-
|
241
|
+
|
221
242
|
# should normalize type
|
222
243
|
if type = col[:type]
|
223
244
|
tn = type.to_s.split('(')[0] # take care of types like varargs(..)
|
@@ -226,28 +247,33 @@ module OMF::OML
|
|
226
247
|
type = :string
|
227
248
|
end
|
228
249
|
else
|
229
|
-
warn "Missing type definition in '#{col[:name]}', default to 'string' (#{col.inspect})"
|
250
|
+
warn "Missing type definition in '#{col[:name]}', default to 'string' (#{col.inspect})"
|
230
251
|
type = :string
|
231
252
|
end
|
232
253
|
col[:type] = type
|
233
|
-
|
254
|
+
|
234
255
|
col[:type_conversion] = case type
|
235
256
|
when :string
|
236
257
|
lambda do |r| r end
|
237
258
|
when :key
|
238
259
|
lambda do |r| r end
|
239
|
-
when :integer
|
260
|
+
when :integer
|
240
261
|
lambda do |r| r.to_i end
|
241
|
-
when :float
|
262
|
+
when :float
|
242
263
|
lambda do |r| r.to_f end
|
243
|
-
when :
|
264
|
+
when :bool
|
265
|
+
lambda do |r| (r.downcase.start_with? 't') ? true : false end
|
266
|
+
when :date
|
244
267
|
lambda do |r| Date.parse(r) end
|
245
268
|
when :dateTime
|
246
269
|
lambda do |r| Time.parse(r) end
|
270
|
+
when :blob64
|
271
|
+
require "base64"
|
272
|
+
lambda do |r| Base64.decode64(r) end
|
247
273
|
else raise "Unrecognized Schema type '#{type}'"
|
248
274
|
end
|
249
275
|
col
|
250
276
|
end
|
251
277
|
end # OmlSchema
|
252
|
-
|
278
|
+
|
253
279
|
end
|
data/lib/omf_oml/sql_row.rb
CHANGED
@@ -33,7 +33,7 @@ module OMF::OML
|
|
33
33
|
def initialize(sql_table_name, schema, query, opts = {})
|
34
34
|
@sname = sql_table_name
|
35
35
|
@schema = schema
|
36
|
-
raise "Expected OmlSchema but got '#{schema.class}" unless schema.is_a? OmlSchema
|
36
|
+
raise "Expected OmlSchema but got '#{schema.class}'" unless schema.is_a? OmlSchema
|
37
37
|
@query = query
|
38
38
|
|
39
39
|
unless @offset = opts[:offset]
|
data/lib/omf_oml/sql_source.rb
CHANGED
@@ -26,7 +26,8 @@ module OMF::OML
|
|
26
26
|
# for all adaptors
|
27
27
|
#
|
28
28
|
FALLBACK_MAPPING = {
|
29
|
-
'UNSIGNED INTEGER' => :integer
|
29
|
+
'UNSIGNED INTEGER' => :integer,
|
30
|
+
'UNSIGNED BIGINT' => :integer
|
30
31
|
}
|
31
32
|
|
32
33
|
# db_opts - Options used to create a Sequel adapter
|
@@ -62,12 +63,20 @@ module OMF::OML
|
|
62
63
|
# table_name - Name of table in the SQL database
|
63
64
|
# opts -
|
64
65
|
# :name - name used for returned OML Table [table_name]
|
66
|
+
# :schema - Schema to use instead of default table schema
|
67
|
+
# :query - Query to use instead of default one
|
65
68
|
# All other options defined for OmlSqlRow#new
|
66
69
|
#
|
67
70
|
def create_table(table_name, opts = {})
|
68
71
|
tn = opts.delete(:name) || table_name
|
69
|
-
schema = _schema_for_table(table_name)
|
70
|
-
|
72
|
+
schema = opts.delete(:schema) || _schema_for_table(table_name)
|
73
|
+
if q = opts.delete(:query)
|
74
|
+
query = (q.is_a? String) ? @db[q] : q
|
75
|
+
else
|
76
|
+
query = _def_query_for_table(table_name)
|
77
|
+
end
|
78
|
+
r = OmlSqlRow.new(table_name, schema, query, opts)
|
79
|
+
opts[:schema] = schema
|
71
80
|
r.to_table(tn, opts)
|
72
81
|
end
|
73
82
|
|
@@ -180,7 +189,8 @@ module OMF::OML
|
|
180
189
|
unless table = @tables[table_name] # check if already reported before
|
181
190
|
debug "Found table: #{table_name}"
|
182
191
|
schema = _schema_for_table(table_name)
|
183
|
-
|
192
|
+
query = _def_query_for_table(table_name)
|
193
|
+
table = @tables[table_name] = OmlSqlRow.new(table_name, schema, query, @row_opts)
|
184
194
|
#table = @tables[table_name] = OmlSqlRow.new(table_name, @db.schema(table_name), @db_opts, self, @row_opts)
|
185
195
|
@on_new_stream_procs.each_value do |proc|
|
186
196
|
proc.call(table)
|
@@ -195,6 +205,11 @@ module OMF::OML
|
|
195
205
|
unless type = cd[:type] || FALLBACK_MAPPING[cd[:db_type]]
|
196
206
|
warn "Can't find ruby type for database type '#{cd[:db_type]}'"
|
197
207
|
end
|
208
|
+
if col_name == :oml_sender_id
|
209
|
+
# see _def_query_for_table(table_name) which replaces sender_id by sender name
|
210
|
+
col_name = :oml_sender
|
211
|
+
type = 'string'
|
212
|
+
end
|
198
213
|
{:name => col_name, :type => type}
|
199
214
|
end
|
200
215
|
#puts "SCHEMA_DESCR>>>> #{schema_descr}"
|
data/lib/omf_oml/table.rb
CHANGED
@@ -93,10 +93,10 @@ module OMF::OML
|
|
93
93
|
# parameters, an 'action' and the content changed. The 'action' is either
|
94
94
|
# ':added', or ':removed' and the content is an array of rows.
|
95
95
|
#
|
96
|
-
def on_content_changed(key, offset = -1, &proc)
|
96
|
+
def on_content_changed(key = nil, offset = -1, &proc)
|
97
97
|
#puts ">>>>>>> #{offset}"
|
98
98
|
if proc
|
99
|
-
@on_content_changed[key] = proc
|
99
|
+
@on_content_changed[key || proc] = proc
|
100
100
|
if offset >= 0
|
101
101
|
#with_offset = proc.arity == 2
|
102
102
|
proc.call(:added, @rows[offset .. -1])
|
data/lib/omf_oml/tuple.rb
CHANGED
@@ -7,6 +7,7 @@
|
|
7
7
|
require 'omf_base/lobject'
|
8
8
|
require 'omf_oml'
|
9
9
|
require 'omf_oml/schema'
|
10
|
+
require 'omf_oml/table'
|
10
11
|
|
11
12
|
module OMF::OML
|
12
13
|
|
@@ -25,17 +26,11 @@ module OMF::OML
|
|
25
26
|
# by it's name, or its col index
|
26
27
|
#
|
27
28
|
def [](name_or_index)
|
28
|
-
@
|
29
|
+
@schema.cast_col(name_or_index, @raw)
|
29
30
|
end
|
30
31
|
|
31
32
|
# Return the elements of the tuple as an array
|
32
33
|
def to_a()
|
33
|
-
# res = []
|
34
|
-
# r = @raw
|
35
|
-
# @schema.each do |col|
|
36
|
-
# res << @vprocs[col[:name]].call(r)
|
37
|
-
# end
|
38
|
-
# res
|
39
34
|
@schema.cast_row(@raw)
|
40
35
|
end
|
41
36
|
|
@@ -44,28 +39,38 @@ module OMF::OML
|
|
44
39
|
#
|
45
40
|
def select(*col_names)
|
46
41
|
r = @raw
|
47
|
-
col_names.
|
48
|
-
|
49
|
-
p ? p.call(r) : nil
|
42
|
+
col_names.map do |n|
|
43
|
+
self[n]
|
50
44
|
end
|
51
45
|
end
|
52
46
|
|
47
|
+
# Return a table (more precisely an OmlTable instance) fed from
|
48
|
+
# the content of this tuple stream.
|
49
|
+
#
|
50
|
+
# table_name - Name of table
|
51
|
+
# opts -
|
52
|
+
# All options defined for OmlTable#create
|
53
|
+
#
|
54
|
+
def create_table(table_name, opts = {})
|
55
|
+
table = OmlTable.create(table_name, @schema, opts)
|
56
|
+
id = -1
|
57
|
+
on_new_tuple(table) do |t|
|
58
|
+
row = @schema.cast_row(@raw, true)
|
59
|
+
#puts "ROW>> #{row.inspect}"
|
60
|
+
table.add_row(row)
|
61
|
+
end
|
62
|
+
table
|
63
|
+
end
|
64
|
+
|
53
65
|
attr_reader :schema
|
54
66
|
attr_reader :stream_name
|
55
67
|
|
56
68
|
def initialize(name, schema)
|
57
|
-
# if schema.kind_of? Array
|
58
|
-
# schema = OmlSchema.new(schema)
|
59
|
-
# end
|
60
69
|
@stream_name = name
|
61
70
|
@schema = OmlSchema.create(schema)
|
62
|
-
|
63
71
|
@raw = []
|
64
|
-
# puts "SCHEMA: #{schema.inspect}"
|
65
72
|
@on_new_tuple_procs = {}
|
66
|
-
|
67
73
|
super name
|
68
|
-
process_schema(@schema)
|
69
74
|
end
|
70
75
|
|
71
76
|
|
@@ -82,7 +87,7 @@ module OMF::OML
|
|
82
87
|
end
|
83
88
|
end
|
84
89
|
|
85
|
-
# Register a proc to be called when a new tuple arrived
|
90
|
+
# Register a proc to be called when a new tuple arrived
|
86
91
|
#
|
87
92
|
def on_new_tuple(key = :_, &proc)
|
88
93
|
if proc
|
@@ -94,22 +99,6 @@ module OMF::OML
|
|
94
99
|
|
95
100
|
|
96
101
|
protected
|
97
|
-
def process_schema(schema)
|
98
|
-
i = 0
|
99
|
-
@vprocs = {}
|
100
|
-
schema.each_column do |col| #
|
101
|
-
name = col[:name] || raise("Ill-formed schema '#{schema}'")
|
102
|
-
type = col[:type] || raise("Ill-formed schema '#{schema}'")
|
103
|
-
@vprocs[name] = @vprocs[i] = case type
|
104
|
-
when :string
|
105
|
-
lambda do |r| r[i] end
|
106
|
-
when :float
|
107
|
-
lambda do |r| r[i].to_f end
|
108
|
-
else raise "Unrecognized Schema type '#{type}'"
|
109
|
-
end
|
110
|
-
i += 1
|
111
|
-
end
|
112
|
-
end
|
113
102
|
|
114
103
|
end # Tuple
|
115
104
|
end # OMF::OML
|
data/lib/omf_oml/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: omf_oml
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-12-12 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: omf_base
|
@@ -90,9 +90,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
90
90
|
version: '0'
|
91
91
|
requirements: []
|
92
92
|
rubyforge_project: omf_oml
|
93
|
-
rubygems_version: 1.8.
|
93
|
+
rubygems_version: 1.8.23
|
94
94
|
signing_key:
|
95
95
|
specification_version: 3
|
96
96
|
summary: Glue between OMF and OML.
|
97
97
|
test_files:
|
98
98
|
- test/data/brooklynDemo.sq3
|
99
|
+
has_rdoc:
|