omf_oml 0.9.7 → 0.9.8
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/csv_table.rb +80 -0
- data/lib/omf_oml/endpoint.rb +3 -3
- data/lib/omf_oml/network.rb +4 -4
- data/lib/omf_oml/schema.rb +2 -2
- data/lib/omf_oml/sequel/sequel_server.rb +3 -3
- data/lib/omf_oml/sql_row.rb +53 -41
- data/lib/omf_oml/sql_source.rb +84 -36
- data/lib/omf_oml/table.rb +5 -2
- data/lib/omf_oml/tuple.rb +2 -2
- data/lib/omf_oml/version.rb +1 -1
- data/omf_oml.gemspec +1 -0
- data/test/data/brooklynDemo.sq3 +0 -0
- metadata +23 -5
@@ -0,0 +1,80 @@
|
|
1
|
+
|
2
|
+
require 'csv'
|
3
|
+
require 'omf_oml'
|
4
|
+
require 'omf_oml/table'
|
5
|
+
|
6
|
+
|
7
|
+
|
8
|
+
module OMF::OML
|
9
|
+
|
10
|
+
# This class represents a table whose content is initially stored in a
|
11
|
+
# CSV file.
|
12
|
+
#
|
13
|
+
class OmlCsvTable < OmlTable
|
14
|
+
|
15
|
+
# @param opts
|
16
|
+
#
|
17
|
+
def self.create(tname, file_name, opts = {}, &on_before_row_added)
|
18
|
+
self.new(tname, file_name, opts, &on_before_row_added)
|
19
|
+
end
|
20
|
+
|
21
|
+
#
|
22
|
+
# tname - Name of table
|
23
|
+
# schema - OmlSchema or Array containing [name, type*] for every column in table
|
24
|
+
# Table adds a '__id__' column at the beginning which keeps track of the rows unique id
|
25
|
+
# @params opts
|
26
|
+
# @opts :max_size - keep table to that size by dropping older rows
|
27
|
+
# @opts :index - only keep the latest inserted row for a unique col value - messes with row order
|
28
|
+
# @opts :has_csv_header If true use first row in file as schema descriptor
|
29
|
+
# @opts :schema Schema associated with this table
|
30
|
+
#
|
31
|
+
def initialize(tname, file_name, opts = {}, &on_before_row_added)
|
32
|
+
unless File.readable?(file_name)
|
33
|
+
raise "Can't read CSV file '#{file_name}'"
|
34
|
+
end
|
35
|
+
csv_opts = {}
|
36
|
+
csv_opts[:headers] = (opts.delete(:has_csv_header) == true)
|
37
|
+
unless csv_opts[:headers]
|
38
|
+
raise "Current implementation only works with CSV files which inlcude a schema description in the first line"
|
39
|
+
end
|
40
|
+
|
41
|
+
encoding = opts.delete(:encoding)
|
42
|
+
mode = "rb"
|
43
|
+
mode << ":#{encoding}" if encoding
|
44
|
+
csv = CSV.open(file_name, mode, csv_opts)
|
45
|
+
|
46
|
+
unless schema = opts.delete(:schema)
|
47
|
+
unless csv_opts[:headers]
|
48
|
+
raise "No schema given and ':has_csv_header' not set to capture schema from file header"
|
49
|
+
end
|
50
|
+
first_row = csv.shift.fields # force reading the first row to have the header parsed
|
51
|
+
#csv.shift.each do |h, v| puts "#{h} => #{v.class}" end
|
52
|
+
schema = csv.headers.map do |c|
|
53
|
+
c = c.encode('UTF-8', :invalid => :replace, :undef => :replace, :replace => '?')
|
54
|
+
name, type = c.split(':')
|
55
|
+
[name, type || 'string']
|
56
|
+
end
|
57
|
+
end
|
58
|
+
super tname, schema, opts
|
59
|
+
|
60
|
+
if first_row # from getting the CSV header
|
61
|
+
first_row.insert(0, @row_id += 1) if @add_index
|
62
|
+
@rows = [@schema.cast_row(first_row)]
|
63
|
+
end
|
64
|
+
|
65
|
+
# This assumes that CSV reader is setup with proper schema converters
|
66
|
+
csv.each do |r|
|
67
|
+
# Convert any strange strings into a clean ruby string
|
68
|
+
row = r.fields.map do |e|
|
69
|
+
e ? e.encode('UTF-8', :invalid => :replace, :undef => :replace, :replace => '?') : nil
|
70
|
+
end
|
71
|
+
row.insert(0, @row_id += 1) if @add_index
|
72
|
+
@rows << @schema.cast_row(row)
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
|
77
|
+
|
78
|
+
|
79
|
+
end # class
|
80
|
+
end # module
|
data/lib/omf_oml/endpoint.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
|
2
|
-
require '
|
2
|
+
require 'omf_base/lobject'
|
3
3
|
require 'omf_oml'
|
4
4
|
|
5
5
|
require 'omf_oml/oml_tuple'
|
@@ -10,7 +10,7 @@ module OMF::OML
|
|
10
10
|
# be visualized. After creating the object, the @run@ method needs to be called to
|
11
11
|
# start processing the stream.
|
12
12
|
#
|
13
|
-
class OmlEndpoint < OMF::
|
13
|
+
class OmlEndpoint < OMF::Base::LObject
|
14
14
|
|
15
15
|
# Register a proc to be called when a new stream was
|
16
16
|
# discovered on this endpoint.
|
@@ -77,7 +77,7 @@ module OMF::OML
|
|
77
77
|
# and instance and then immediately calls the +run+ methods.
|
78
78
|
#
|
79
79
|
#
|
80
|
-
class OmlSession < OMF::
|
80
|
+
class OmlSession < OMF::Base::LObject # :nodoc
|
81
81
|
|
82
82
|
# Return the value for the respective @key@ in the protocol header.
|
83
83
|
#
|
data/lib/omf_oml/network.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'monitor'
|
2
2
|
require 'json'
|
3
3
|
require 'set'
|
4
|
-
require '
|
4
|
+
require 'omf_base/lobject'
|
5
5
|
require 'omf_oml'
|
6
6
|
|
7
7
|
|
@@ -19,7 +19,7 @@ module OMF::OML
|
|
19
19
|
# This class represents a network consisting of nodes and links with their respective
|
20
20
|
# attributes.
|
21
21
|
#
|
22
|
-
class OmlNetwork < OMF::
|
22
|
+
class OmlNetwork < OMF::Base::LObject
|
23
23
|
include MonitorMixin
|
24
24
|
|
25
25
|
@@name2network = {}
|
@@ -310,7 +310,7 @@ module OMF::OML
|
|
310
310
|
|
311
311
|
# This class represents an abstract network element and shouldn't be used directly.
|
312
312
|
#
|
313
|
-
class NetworkElement < OMF::
|
313
|
+
class NetworkElement < OMF::Base::LObject
|
314
314
|
|
315
315
|
attr_reader :name
|
316
316
|
attr_reader :el_id
|
@@ -449,7 +449,7 @@ end
|
|
449
449
|
|
450
450
|
if $0 == __FILE__
|
451
451
|
require 'json'
|
452
|
-
include OMF::
|
452
|
+
include OMF::Base::OML
|
453
453
|
|
454
454
|
nw = OmlNetwork.new
|
455
455
|
|
data/lib/omf_oml/schema.rb
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
|
2
|
-
require '
|
2
|
+
require 'omf_base/lobject'
|
3
3
|
require 'omf_oml'
|
4
4
|
|
5
5
|
module OMF::OML
|
6
6
|
|
7
7
|
# This class represents the schema of an OML measurement stream.
|
8
8
|
#
|
9
|
-
class OmlSchema < OMF::
|
9
|
+
class OmlSchema < OMF::Base::LObject
|
10
10
|
|
11
11
|
CLASS2TYPE = {
|
12
12
|
TrueClass => 'boolean',
|
@@ -4,7 +4,7 @@ require 'time'
|
|
4
4
|
require 'logger'
|
5
5
|
require 'sequel'
|
6
6
|
|
7
|
-
require '
|
7
|
+
require 'omf_base/lobject'
|
8
8
|
require 'omf_oml'
|
9
9
|
|
10
10
|
# module OMF::OML
|
@@ -14,7 +14,7 @@ require 'omf_oml'
|
|
14
14
|
module OMF::OML::Sequel
|
15
15
|
module Server
|
16
16
|
|
17
|
-
class Query < OMF::
|
17
|
+
class Query < OMF::Base::LObject
|
18
18
|
|
19
19
|
def self.parse(xmls, repoFactory = RepositoryFactory.new, logger = Logger.new(STDOUT))
|
20
20
|
if xmls.kind_of? String
|
@@ -222,7 +222,7 @@ module OMF::OML::Sequel
|
|
222
222
|
|
223
223
|
end # Query
|
224
224
|
|
225
|
-
class RepositoryFactory < OMF::
|
225
|
+
class RepositoryFactory < OMF::Base::LObject
|
226
226
|
|
227
227
|
def initialize(opts = {})
|
228
228
|
@opts = opts
|
data/lib/omf_oml/sql_row.rb
CHANGED
@@ -1,52 +1,52 @@
|
|
1
1
|
|
2
|
-
require 'omf_oml/
|
2
|
+
require 'omf_oml/oml_tuple'
|
3
3
|
require 'omf_oml/table'
|
4
4
|
|
5
5
|
module OMF::OML
|
6
|
-
|
7
6
|
|
8
|
-
|
7
|
+
|
8
|
+
|
9
9
|
# Read the content of a table and feeds it out as a tuple store.
|
10
10
|
# After creation of the object. The actual tuple feed is started
|
11
11
|
# with a call to +run+.
|
12
12
|
#
|
13
13
|
class OmlSqlRow < OmlTuple
|
14
14
|
attr_reader :row
|
15
|
-
|
16
|
-
#
|
15
|
+
|
16
|
+
#
|
17
17
|
# Create a representation of a row in a database. Can be used to fill a table.
|
18
18
|
#
|
19
19
|
# @param [String] sql_table_name - name of SQL table in respective SQL database
|
20
20
|
# @param [OmlSchema] schema - the schema describing the tuple
|
21
|
-
# @param [Sequel]
|
22
|
-
# @param [Hash] opts:
|
21
|
+
# @param [Sequel::Dataset] query - Databasequery to execute
|
22
|
+
# @param [Hash] opts:
|
23
23
|
# - offset: Ignore first +offset+ rows. If negative or zero serve +offset+ rows initially
|
24
24
|
# - limit: Number of rows to fetch each time [1000]
|
25
|
-
# - check_interval: Interval in seconds when to check for new data. If 0, only run once.
|
25
|
+
# - check_interval: Interval in seconds when to check for new data. If < 0, only run once.
|
26
26
|
# - query_interval: Interval between consecutive queries when processing large result set.
|
27
27
|
#
|
28
|
-
def initialize(sql_table_name, schema,
|
28
|
+
def initialize(sql_table_name, schema, query, opts = {})
|
29
29
|
@sname = sql_table_name
|
30
30
|
@schema = schema
|
31
31
|
raise "Expected OmlSchema but got '#{schema.class}" unless schema.is_a? OmlSchema
|
32
|
-
@
|
33
|
-
|
32
|
+
@query = query
|
33
|
+
|
34
34
|
unless @offset = opts[:offset]
|
35
35
|
@offset = 0
|
36
36
|
end
|
37
37
|
@limit = opts[:limit]
|
38
38
|
@limit = 1000 unless @limit
|
39
|
-
|
39
|
+
|
40
40
|
@check_interval = opts[:check_interval]
|
41
|
-
@check_interval =
|
41
|
+
@check_interval = -1 unless @check_interval
|
42
42
|
@query_interval = opts[:query_interval]
|
43
|
-
|
43
|
+
|
44
44
|
@on_new_vector_proc = {}
|
45
45
|
|
46
|
-
super opts[:name] || sql_table_name, schema
|
46
|
+
super opts[:name] || sql_table_name, schema
|
47
47
|
end
|
48
|
-
|
49
|
-
|
48
|
+
|
49
|
+
|
50
50
|
# Return a specific element of the vector identified either
|
51
51
|
# by it's name, or its col index
|
52
52
|
#
|
@@ -56,18 +56,18 @@ module OMF::OML
|
|
56
56
|
else
|
57
57
|
unless @row.key? name_or_index
|
58
58
|
raise "Unknown column name '#{name_or_index}'"
|
59
|
-
end
|
59
|
+
end
|
60
60
|
@row[name_or_index]
|
61
61
|
end
|
62
62
|
end
|
63
|
-
|
64
|
-
# Return the elements of the row as an array using the
|
63
|
+
|
64
|
+
# Return the elements of the row as an array using the
|
65
65
|
# associated schema or 'schema' if non-nil.
|
66
66
|
#
|
67
67
|
def to_a(schema = nil)
|
68
68
|
a = (schema || @schema).hash_to_row(@row) # don't need type conversion as sequel is doing this for us
|
69
69
|
end
|
70
|
-
|
70
|
+
|
71
71
|
# Return an array including the values for the names elements
|
72
72
|
# given as parameters.
|
73
73
|
#
|
@@ -76,19 +76,19 @@ module OMF::OML
|
|
76
76
|
col_names.collect do |n|
|
77
77
|
unless @row.key? n
|
78
78
|
raise "Unknown column name '#{n}'"
|
79
|
-
end
|
79
|
+
end
|
80
80
|
@row[n]
|
81
81
|
end
|
82
82
|
end
|
83
|
-
|
83
|
+
|
84
84
|
def ts
|
85
85
|
self[:oml_ts_server]
|
86
86
|
end
|
87
|
-
|
87
|
+
|
88
88
|
def seq_no
|
89
89
|
self[:oml_seq]
|
90
|
-
end
|
91
|
-
|
90
|
+
end
|
91
|
+
|
92
92
|
# Register a proc to be called when a new tuple arrived
|
93
93
|
# on this stream.
|
94
94
|
#
|
@@ -149,14 +149,14 @@ module OMF::OML
|
|
149
149
|
self.on_new_tuple(t) do |v|
|
150
150
|
r = v.to_a(schema)
|
151
151
|
#puts r.inspect
|
152
|
-
t.add_row(r)
|
152
|
+
t.add_row(r)
|
153
153
|
end
|
154
154
|
t
|
155
155
|
end
|
156
156
|
|
157
157
|
|
158
158
|
protected
|
159
|
-
|
159
|
+
|
160
160
|
def run(in_thread = true)
|
161
161
|
return if @running
|
162
162
|
if in_thread
|
@@ -172,16 +172,17 @@ module OMF::OML
|
|
172
172
|
_run
|
173
173
|
end
|
174
174
|
end
|
175
|
-
|
175
|
+
|
176
176
|
private
|
177
|
-
|
177
|
+
|
178
178
|
def _run
|
179
179
|
if @check_interval <= 0
|
180
|
-
while _run_once; end
|
180
|
+
#while _run_once; end
|
181
|
+
_run_once
|
181
182
|
else
|
182
183
|
@running = true
|
183
184
|
while (@running)
|
184
|
-
begin
|
185
|
+
begin
|
185
186
|
unless _run_once
|
186
187
|
# All rows read, wait a bit for news to show up
|
187
188
|
sleep @check_interval
|
@@ -190,22 +191,22 @@ module OMF::OML
|
|
190
191
|
warn ex
|
191
192
|
debug "\t", ex.backtrace.join("\n\t")
|
192
193
|
end
|
193
|
-
end
|
194
|
+
end
|
194
195
|
end
|
195
196
|
end
|
196
|
-
|
197
|
+
|
197
198
|
# Run a query on database an serve all rows found one at a time.
|
198
199
|
# Return true if there might be more rows in the database
|
199
200
|
def _run_once
|
200
201
|
row_cnt = 0
|
201
202
|
t = table_name = @sname
|
202
203
|
if (@offset < 0)
|
203
|
-
cnt = @
|
204
|
+
cnt = @query.count()
|
204
205
|
@offset = cnt + @offset # @offset was negative here
|
205
206
|
debug("Initial offset #{@offset} in '#{table_name}' with #{cnt} rows")
|
206
207
|
@offset = 0 if @offset < 0
|
207
208
|
end
|
208
|
-
@
|
209
|
+
@query.limit(@limit, @offset).each do |r|
|
209
210
|
@row = r
|
210
211
|
@on_new_vector_proc.each_value do |proc|
|
211
212
|
proc.call(self)
|
@@ -216,10 +217,10 @@ module OMF::OML
|
|
216
217
|
debug "Read #{row_cnt} (total #{@offset}) rows from '#{@sname}'" if row_cnt > 0
|
217
218
|
if more_to_read = row_cnt >= @limit # there could be more to read
|
218
219
|
sleep @query_interval if @query_interval # don't hammer database
|
219
|
-
end
|
220
|
-
more_to_read
|
220
|
+
end
|
221
|
+
more_to_read
|
221
222
|
end
|
222
|
-
|
223
|
+
|
223
224
|
end # OmlSqlRow
|
224
225
|
|
225
226
|
|
@@ -227,8 +228,19 @@ end
|
|
227
228
|
|
228
229
|
if $0 == __FILE__
|
229
230
|
|
231
|
+
OMF::Base::Loggable.init_log('sql_row_test')
|
232
|
+
|
233
|
+
require 'omf_oml/sql_source'
|
234
|
+
db_file = File.join(File.dirname(__FILE__), '../../test/data/brooklynDemo.sq3')
|
235
|
+
ss = OMF::OML::OmlSqlSource.new('sqlite://' + File.absolute_path(db_file))
|
236
|
+
|
237
|
+
r = ss.create_stream('wimaxmonitor_wimaxstatus')
|
238
|
+
puts r
|
239
|
+
|
240
|
+
exit
|
241
|
+
|
230
242
|
require 'omf_oml/table'
|
231
|
-
ep = OMF::OML::OmlSqlSource.new('brooklynDemo.sq3')
|
243
|
+
ep = OMF::OML::OmlSqlSource.new(File.join(File.dirname(__FILE__), '../../test/data/brooklynDemo.sq3'))
|
232
244
|
ep.on_new_stream() do |s|
|
233
245
|
puts ">>>>>>>>>>>> New stream #{s.stream_name}: #{s.names.join(', ')}"
|
234
246
|
case s.stream_name
|
@@ -239,7 +251,7 @@ if $0 == __FILE__
|
|
239
251
|
end
|
240
252
|
|
241
253
|
s.on_new_vector() do |v|
|
242
|
-
puts "New vector(#{s.stream_name}): #{v.select(*select).join('|')}"
|
254
|
+
puts "New vector(#{s.stream_name}): #{v.select(*select).join('|')}"
|
243
255
|
end
|
244
256
|
end
|
245
257
|
ep.run()
|
data/lib/omf_oml/sql_source.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
|
2
2
|
require 'sequel'
|
3
3
|
|
4
|
-
require '
|
4
|
+
require 'omf_base/lobject'
|
5
5
|
require 'omf_oml/endpoint'
|
6
6
|
require 'omf_oml/tuple'
|
7
7
|
require 'omf_oml/sql_row'
|
@@ -14,12 +14,12 @@ module OMF::OML
|
|
14
14
|
# After creating the object, the @run@ method needs to be called to
|
15
15
|
# start producing the streams.
|
16
16
|
#
|
17
|
-
class OmlSqlSource < OMF::
|
18
|
-
|
17
|
+
class OmlSqlSource < OMF::Base::LObject
|
18
|
+
|
19
19
|
# Sequel adaptors sometimes don't return a :type identifier,
|
20
20
|
# but always return the :db_type. This is a list of maps which may not work
|
21
21
|
# for all adaptors
|
22
|
-
#
|
22
|
+
#
|
23
23
|
FALLBACK_MAPPING = {
|
24
24
|
'UNSIGNED INTEGER' => :integer
|
25
25
|
}
|
@@ -49,42 +49,44 @@ module OMF::OML
|
|
49
49
|
@on_new_stream_procs.delete key
|
50
50
|
end
|
51
51
|
end
|
52
|
-
|
53
|
-
# Return a table (more precisely an OmlTable instance) fed from
|
52
|
+
|
53
|
+
# Return a table (more precisely an OmlTable instance) fed from
|
54
54
|
# the content of a table 'table_name' in this database.
|
55
55
|
#
|
56
56
|
# table_name - Name of table in the SQL database
|
57
|
-
# opts -
|
58
|
-
# :include_oml_internals - Include OML 'header' columns [true]
|
57
|
+
# opts -
|
59
58
|
# :name - name used for returned OML Table [table_name]
|
60
59
|
# All other options defined for OmlSqlRow#new
|
61
60
|
#
|
62
61
|
def create_table(table_name, opts = {})
|
63
62
|
tn = opts.delete(:name) || table_name
|
64
63
|
schema = _schema_for_table(table_name)
|
65
|
-
r = OmlSqlRow.new(table_name, schema,
|
64
|
+
r = OmlSqlRow.new(table_name, schema, _def_query_for_table(table_name), opts)
|
66
65
|
r.to_table(tn, opts)
|
67
66
|
end
|
68
|
-
|
67
|
+
|
69
68
|
# Call 'block' for every row in 'table_name' table.
|
70
69
|
#
|
71
70
|
# table_name - Name of table in the SQL database
|
72
|
-
# opts -
|
73
|
-
# :include_oml_internals[boolean] - Include OML 'header' columns [true]
|
71
|
+
# opts -
|
74
72
|
# :schema[Schema] Schema to use for creating row
|
75
73
|
# All other options defined for OmlSqlRow#new
|
74
|
+
# returns OmlSqlRow
|
76
75
|
#
|
77
76
|
def create_stream(table_name, opts = {}, &block)
|
78
77
|
rschema = opts.delete(:schema)
|
79
78
|
schema = _schema_for_table(table_name)
|
80
|
-
r = OmlSqlRow.new(table_name, schema,
|
81
|
-
|
82
|
-
|
83
|
-
|
79
|
+
r = OmlSqlRow.new(table_name, schema, _def_query_for_table(table_name), opts)
|
80
|
+
if block
|
81
|
+
ropts = {}
|
82
|
+
ropts[:schema] = rschema if rschema
|
83
|
+
r.to_stream(ropts, &block)
|
84
|
+
end
|
85
|
+
r
|
84
86
|
end
|
85
87
|
|
86
88
|
#
|
87
|
-
# Run a query on the database and return the result as an OmlTable. The provided schema
|
89
|
+
# Run a query on the database and return the result as an OmlTable. The provided schema
|
88
90
|
# needs to describe the SQL queries result set. Unfortunately we can only do very little
|
89
91
|
# sanity checks here
|
90
92
|
#
|
@@ -96,6 +98,33 @@ module OMF::OML
|
|
96
98
|
tbl
|
97
99
|
end
|
98
100
|
|
101
|
+
#
|
102
|
+
# Run a query on the database and return the result as an OmlTable. The provided schema
|
103
|
+
# needs to describe the SQL queries result set. Unfortunately we can only do very little
|
104
|
+
# sanity checks here. The query will be defined in the provided block which is passed in
|
105
|
+
# the Sequel Database object and is expected to return a Sequel Dataset instance.
|
106
|
+
#
|
107
|
+
def query2(table_name, schema, &block)
|
108
|
+
tbl = OmlTable.create(table_name, schema)
|
109
|
+
q = block.call(@db)
|
110
|
+
unless q.is_a? Sequel::Dataset
|
111
|
+
raise "Expected a Sequel::Dataset object, but got '#{q.class}'"
|
112
|
+
end
|
113
|
+
q.each do |row|
|
114
|
+
tbl << tbl.schema.hash_to_row(row)
|
115
|
+
end
|
116
|
+
tbl
|
117
|
+
end
|
118
|
+
|
119
|
+
# Return a Sequel Dataset from 'table_name'. See Sequel documentation on
|
120
|
+
# what one can do with that.
|
121
|
+
#
|
122
|
+
# db_table_name Name of table in database
|
123
|
+
#
|
124
|
+
def dataset(db_table_name)
|
125
|
+
@db.from(db_table_name)
|
126
|
+
end
|
127
|
+
|
99
128
|
# Start checking the database for tables and create a new stream
|
100
129
|
# by calling the internal +report_new_table+ method.
|
101
130
|
# If +check_every+ > 0 continue checking every +check_every+ seconds
|
@@ -130,11 +159,6 @@ module OMF::OML
|
|
130
159
|
report_new_table(table_name) unless table_name.start_with?('_')
|
131
160
|
end
|
132
161
|
@tables
|
133
|
-
|
134
|
-
# postgresql
|
135
|
-
# SELECT tablename FROM pg_tables
|
136
|
-
# WHERE tablename NOT LIKE �pg\\_%�
|
137
|
-
# AND tablename NOT LIKE �sql\\_%�;
|
138
162
|
end
|
139
163
|
|
140
164
|
|
@@ -158,7 +182,7 @@ module OMF::OML
|
|
158
182
|
end
|
159
183
|
table
|
160
184
|
end
|
161
|
-
|
185
|
+
|
162
186
|
def _schema_for_table(table_name)
|
163
187
|
begin
|
164
188
|
schema_descr = @db.schema(table_name).map do |col_name, cd|
|
@@ -173,30 +197,54 @@ module OMF::OML
|
|
173
197
|
raise "Problems reading schema of table '#{table_name}'. Does it exist? (#{@db.tables})"
|
174
198
|
end
|
175
199
|
end
|
200
|
+
|
201
|
+
def _def_query_for_table(table_name)
|
202
|
+
t = table_name
|
203
|
+
@db["SELECT _senders.name as oml_sender, a.* FROM #{t} AS a INNER JOIN _senders ON (_senders.id = a.oml_sender_id);"]
|
204
|
+
end
|
176
205
|
end
|
177
|
-
|
206
|
+
|
178
207
|
|
179
208
|
|
180
209
|
end
|
181
210
|
|
182
211
|
if $0 == __FILE__
|
212
|
+
OMF::Base::Loggable.init_log('sql_source_test')
|
183
213
|
|
184
214
|
require 'omf_oml/table'
|
185
|
-
|
186
|
-
ep.
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
215
|
+
db_file = File.join(File.dirname(__FILE__), '../../test/data/brooklynDemo.sq3')
|
216
|
+
ep = OMF::OML::OmlSqlSource.new('sqlite://' + File.absolute_path(db_file), limit: 10)
|
217
|
+
|
218
|
+
def on_new_stream(ep)
|
219
|
+
ep.on_new_stream() do |s|
|
220
|
+
puts ">>>>>>>>>>>> New stream #{s.stream_name}: #{s.schema.names}"
|
221
|
+
case s.stream_name
|
222
|
+
when 'wimaxmonitor_wimaxstatus'
|
223
|
+
select = [:oml_ts_server, :sender_hostname, :frequency, :signal, :rssi, :cinr, :avg_tx_pwr]
|
224
|
+
when 'GPSlogger_gps_data'
|
225
|
+
select = [:oml_ts_server, :oml_sender_id, :lat, :lon]
|
226
|
+
end
|
194
227
|
|
195
|
-
|
196
|
-
|
228
|
+
s.on_new_tuple() do |v|
|
229
|
+
begin
|
230
|
+
puts "New vector(#{s.stream_name}): #{v.select(*select).join('|')}"
|
231
|
+
rescue Exception => ex
|
232
|
+
puts "ERROR: #{ex}"
|
233
|
+
abort
|
234
|
+
end
|
235
|
+
end
|
197
236
|
end
|
237
|
+
ep.run()
|
198
238
|
end
|
199
|
-
|
239
|
+
|
240
|
+
t = ep.query2('gps', [[:lat, :float], [:lon, :float]]) do |db|
|
241
|
+
db.from('GPSlogger_gps_data').select(:lat, :lon).limit(2)
|
242
|
+
end
|
243
|
+
puts t.rows.inspect
|
244
|
+
puts t.schema
|
245
|
+
|
246
|
+
# Raw query on database
|
247
|
+
puts ep.dataset('GPSlogger_gps_data').select(:lat, :lon).limit(2).all
|
200
248
|
|
201
249
|
end
|
202
250
|
|
data/lib/omf_oml/table.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
|
2
2
|
require 'monitor'
|
3
3
|
|
4
|
-
require '
|
4
|
+
require 'omf_base/lobject'
|
5
5
|
require 'omf_oml'
|
6
6
|
require 'omf_oml/schema'
|
7
7
|
|
@@ -12,8 +12,11 @@ module OMF::OML
|
|
12
12
|
# This class represents a database like table holding a sequence of OML measurements (rows) according
|
13
13
|
# a common schema.
|
14
14
|
#
|
15
|
-
class OmlTable < OMF::
|
15
|
+
class OmlTable < OMF::Base::LObject
|
16
16
|
|
17
|
+
# @param opts
|
18
|
+
# @opts :index Creates an index table (all rows have distinct values at column 'index')
|
19
|
+
#
|
17
20
|
def self.create(tname, schema, opts = {}, &on_before_row_added)
|
18
21
|
if (index = opts.delete(:index))
|
19
22
|
require 'omf_oml/indexed_table'
|
data/lib/omf_oml/tuple.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
|
2
|
-
require '
|
2
|
+
require 'omf_base/lobject'
|
3
3
|
require 'omf_oml'
|
4
4
|
require 'omf_oml/schema'
|
5
5
|
|
@@ -14,7 +14,7 @@ module OMF::OML
|
|
14
14
|
# Use +OmlTuple+ if the schema is an OML one. +OmlTuple+ has additional convenience
|
15
15
|
# methods.
|
16
16
|
#
|
17
|
-
class Tuple < OMF::
|
17
|
+
class Tuple < OMF::Base::LObject
|
18
18
|
|
19
19
|
# Return a specific element of the tuple identified either
|
20
20
|
# by it's name, or its col index
|
data/lib/omf_oml/version.rb
CHANGED
data/omf_oml.gemspec
CHANGED
@@ -23,5 +23,6 @@ Gem::Specification.new do |s|
|
|
23
23
|
# specify any dependencies here; for example:
|
24
24
|
# s.add_development_dependency "minitest", "~> 2.11.3"
|
25
25
|
#s.add_runtime_dependency "sqlite3", "~> 1.3.6"
|
26
|
+
s.add_runtime_dependency 'omf_base'
|
26
27
|
s.add_runtime_dependency 'sequel', '~> 3.45'
|
27
28
|
end
|
Binary file
|
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: 0.9.
|
4
|
+
version: 0.9.8
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,8 +9,24 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-08-29 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: omf_base
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
14
30
|
- !ruby/object:Gem::Dependency
|
15
31
|
name: sequel
|
16
32
|
requirement: !ruby/object:Gem::Requirement
|
@@ -39,6 +55,7 @@ files:
|
|
39
55
|
- Gemfile
|
40
56
|
- Rakefile
|
41
57
|
- lib/omf_oml.rb
|
58
|
+
- lib/omf_oml/csv_table.rb
|
42
59
|
- lib/omf_oml/endpoint.rb
|
43
60
|
- lib/omf_oml/indexed_table.rb
|
44
61
|
- lib/omf_oml/network.rb
|
@@ -51,6 +68,7 @@ files:
|
|
51
68
|
- lib/omf_oml/tuple.rb
|
52
69
|
- lib/omf_oml/version.rb
|
53
70
|
- omf_oml.gemspec
|
71
|
+
- test/data/brooklynDemo.sq3
|
54
72
|
homepage: https://www.mytestbed.net
|
55
73
|
licenses: []
|
56
74
|
post_install_message:
|
@@ -71,9 +89,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
71
89
|
version: '0'
|
72
90
|
requirements: []
|
73
91
|
rubyforge_project: omf_oml
|
74
|
-
rubygems_version: 1.8.
|
92
|
+
rubygems_version: 1.8.23
|
75
93
|
signing_key:
|
76
94
|
specification_version: 3
|
77
95
|
summary: Glue between OMF and OML.
|
78
|
-
test_files:
|
79
|
-
|
96
|
+
test_files:
|
97
|
+
- test/data/brooklynDemo.sq3
|