omf_oml 0.9.3 → 0.9.4
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/schema.rb +14 -8
- data/lib/omf_oml/sql_row.rb +53 -49
- data/lib/omf_oml/sql_source.rb +28 -27
- data/lib/omf_oml/table.rb +1 -1
- data/lib/omf_oml/version.rb +1 -1
- metadata +11 -5
data/lib/omf_oml/schema.rb
CHANGED
@@ -25,14 +25,18 @@ module OMF::OML
|
|
25
25
|
'int32' => :integer,
|
26
26
|
'int64' => :integer,
|
27
27
|
'bigint' => :integer,
|
28
|
+
'smallint' => :integer,
|
28
29
|
'unsigned integer' => :integer,
|
30
|
+
'unsigned bigint' => :integer,
|
29
31
|
'float' => :float,
|
30
32
|
'real' => :float,
|
31
33
|
'double' => :float,
|
34
|
+
'double precision' => :float,
|
32
35
|
'text' => :string,
|
33
36
|
'string' => :string,
|
34
37
|
'date' => :date,
|
35
38
|
'dateTime'.downcase => :dateTime, # should be 'datetime' but we downcase the string for comparison
|
39
|
+
'timestamp' => :dateTime, # Postgreql specific, not sure if this works as it.
|
36
40
|
'key' => :key,
|
37
41
|
}
|
38
42
|
|
@@ -108,7 +112,7 @@ module OMF::OML
|
|
108
112
|
type = :string
|
109
113
|
end
|
110
114
|
else
|
111
|
-
warn "Missing type definition in '#{col[:name]}', default to 'string'"
|
115
|
+
warn "Missing type definition in '#{col[:name]}', default to 'string' (#{col.inspect})"
|
112
116
|
type = :string
|
113
117
|
end
|
114
118
|
col[:type] = type
|
@@ -144,15 +148,16 @@ module OMF::OML
|
|
144
148
|
# hrow - Hash describing a row
|
145
149
|
# set_nil_when_missing - If true, set any columns not described in hrow to nil
|
146
150
|
#
|
147
|
-
def hash_to_row(hrow, set_nil_when_missing = false)
|
151
|
+
def hash_to_row(hrow, set_nil_when_missing = false, call_type_conversion = true)
|
152
|
+
#puts "HASH2A => #{hrow.inspect}"
|
148
153
|
r = @schema.collect do |cdescr|
|
149
154
|
cname = cdescr[:name]
|
150
155
|
next nil if cname == :__id__
|
151
|
-
unless hrow
|
156
|
+
unless (v = hrow[cname]) || (v = hrow[cname.to_sym])
|
152
157
|
next nil if set_nil_when_missing
|
153
158
|
raise "Missing record element '#{cname}' in record '#{hrow}'"
|
154
159
|
end
|
155
|
-
cdescr[:type_conversion].call(
|
160
|
+
call_type_conversion ? cdescr[:type_conversion].call(v) : v
|
156
161
|
end
|
157
162
|
r.shift # remove __id__ columns
|
158
163
|
#puts "#{r.inspect} -- #{@schema.map {|c| c[:name]}.inspect}"
|
@@ -161,14 +166,15 @@ module OMF::OML
|
|
161
166
|
|
162
167
|
# Cast each element in 'row' into its proper type according to this schema
|
163
168
|
#
|
164
|
-
def cast_row(raw_row)
|
165
|
-
|
166
|
-
|
169
|
+
def cast_row(raw_row, ignore_first_column = false)
|
170
|
+
start_index = ignore_first_column ? 1 : 0
|
171
|
+
unless raw_row.length == @schema.length - start_index
|
172
|
+
raise "Row needs to have same size as schema (#{raw_row.inspect}-#{describe}) "
|
167
173
|
end
|
168
174
|
# This can be done more elegantly in 1.9
|
169
175
|
row = []
|
170
176
|
raw_row.each_with_index do |el, i|
|
171
|
-
row << @schema[i][:type_conversion].call(el)
|
177
|
+
row << @schema[i + start_index][:type_conversion].call(el)
|
172
178
|
end
|
173
179
|
row
|
174
180
|
end
|
data/lib/omf_oml/sql_row.rb
CHANGED
@@ -10,15 +10,23 @@ module OMF::OML
|
|
10
10
|
# with a call to +run+.
|
11
11
|
#
|
12
12
|
class OmlSqlRow < OmlTuple
|
13
|
+
attr_reader :row
|
13
14
|
|
14
|
-
#
|
15
|
+
#
|
16
|
+
# Create a representation of a row in a database. Can be used to fill a table.
|
17
|
+
#
|
18
|
+
# table_name - name table in respective SQL database
|
19
|
+
# schema_raw - a hash returned by the sequel library's #schema method
|
20
|
+
# db_opts - Enough information to open a Sequel database adapter
|
21
|
+
# source - Reference to the SqlSource which created this instance
|
22
|
+
# opts:
|
15
23
|
# - offset: Ignore first +offset+ rows. If negative or zero serve +offset+ rows initially
|
16
24
|
# - limit: Number of rows to fetch each time [1000]
|
17
25
|
# - check_interval: Interval in seconds when to check for new data. If 0, only run once.
|
18
26
|
#
|
19
|
-
def initialize(table_name,
|
27
|
+
def initialize(table_name, schema_raw, db_opts, source, opts = {})
|
20
28
|
@sname = table_name
|
21
|
-
@
|
29
|
+
@db_opts = db_opts
|
22
30
|
@source = source
|
23
31
|
|
24
32
|
unless @offset = opts[:offset]
|
@@ -33,7 +41,7 @@ module OMF::OML
|
|
33
41
|
|
34
42
|
@on_new_vector_proc = {}
|
35
43
|
|
36
|
-
schema =
|
44
|
+
schema = parse_schema(schema_raw)
|
37
45
|
super table_name, schema
|
38
46
|
end
|
39
47
|
|
@@ -47,7 +55,8 @@ module OMF::OML
|
|
47
55
|
|
48
56
|
# Return the elements of the vector as an array
|
49
57
|
def to_a(include_oml_internals = false)
|
50
|
-
|
58
|
+
a = @schema.hash_to_row(@row, false, false) # don't need type conversion as sequel is doing this for us
|
59
|
+
include_oml_internals ? a : a[4 .. -1]
|
51
60
|
end
|
52
61
|
|
53
62
|
# Return an array including the values for the names elements
|
@@ -163,22 +172,16 @@ module OMF::OML
|
|
163
172
|
|
164
173
|
protected
|
165
174
|
|
166
|
-
def
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
cnames.size.times do |i|
|
173
|
-
name = cnames[i].to_sym
|
174
|
-
schema << {:name => name, :type => ctypes[i]}
|
175
|
+
def parse_schema(raw)
|
176
|
+
#puts ">> PARSE SCHEMA"
|
177
|
+
sd = raw.collect do |col|
|
178
|
+
name, opts = col
|
179
|
+
#puts col.inspect
|
180
|
+
{:name => name, :type => opts[:db_type]}
|
175
181
|
end
|
176
|
-
#
|
177
|
-
|
178
|
-
|
179
|
-
first[:name] = :oml_sender
|
180
|
-
|
181
|
-
OmlSchema.new(schema)
|
182
|
+
# Query we are using is adding the 'oml_sender_name' to the front of the table
|
183
|
+
sd.insert(0, :name => 'oml_sender', :type => :string)
|
184
|
+
OmlSchema.new(sd)
|
182
185
|
end
|
183
186
|
|
184
187
|
# override
|
@@ -197,16 +200,6 @@ module OMF::OML
|
|
197
200
|
def run(in_thread = true)
|
198
201
|
return if @running
|
199
202
|
if in_thread
|
200
|
-
if @db
|
201
|
-
# force opening of database in new thread
|
202
|
-
begin
|
203
|
-
@db.close
|
204
|
-
rescue Exception
|
205
|
-
# ALERT: issues with finalising statments, don't know how to deal with it
|
206
|
-
end
|
207
|
-
@db = nil
|
208
|
-
@stmt = nil
|
209
|
-
end
|
210
203
|
Thread.new do
|
211
204
|
begin
|
212
205
|
_run
|
@@ -223,6 +216,8 @@ module OMF::OML
|
|
223
216
|
private
|
224
217
|
|
225
218
|
def _run
|
219
|
+
@db = Sequel.connect(@db_opts)
|
220
|
+
|
226
221
|
if @check_interval <= 0
|
227
222
|
_run_once
|
228
223
|
else
|
@@ -245,7 +240,16 @@ module OMF::OML
|
|
245
240
|
# Return true if there might be more rows in the database
|
246
241
|
def _run_once
|
247
242
|
row_cnt = 0
|
248
|
-
|
243
|
+
t = table_name = @sname
|
244
|
+
if (@offset < 0)
|
245
|
+
cnt = @db[table_name.to_sym].count()
|
246
|
+
@offset = cnt + @offset # @offset was negative here
|
247
|
+
debug("Initial offset #{@offset} in '#{table_name}' with #{cnt} rows")
|
248
|
+
@offset = 0 if @offset < 0
|
249
|
+
end
|
250
|
+
@db["SELECT _senders.name as oml_sender, #{t}.* FROM #{t} INNER JOIN _senders ON (_senders.id = #{t}.oml_sender_id) LIMIT #{@limit} OFFSET #{@offset};"].each do |r|
|
251
|
+
#@db["SELECT _senders.name as oml_sender, #{t}.* FROM #{t} JOIN _senders WHERE #{t}.oml_sender_id = _senders.id LIMIT #{@limit} OFFSET #{@offset};"].each do |r|
|
252
|
+
#puts "ROW>>> #{r.inspect}"
|
249
253
|
@row = r
|
250
254
|
@on_new_vector_proc.each_value do |proc|
|
251
255
|
proc.call(self)
|
@@ -253,27 +257,27 @@ module OMF::OML
|
|
253
257
|
row_cnt += 1
|
254
258
|
end
|
255
259
|
@offset += row_cnt
|
256
|
-
debug "Read #{row_cnt}/#{@offset} rows from '#{@sname}'"
|
260
|
+
debug "Read #{row_cnt}/#{@offset} rows from '#{@sname}'" if row_cnt > 0
|
257
261
|
row_cnt >= @limit # there could be more to read
|
258
262
|
end
|
259
263
|
|
260
|
-
def _statement
|
261
|
-
unless @stmt
|
262
|
-
db = @db = SQLite3::Database.new(@db_file)
|
263
|
-
@db.type_translation = true
|
264
|
-
table_name = t = @sname
|
265
|
-
if @offset < 0
|
266
|
-
cnt = db.execute("select count(*) from #{table_name};")[0][0].to_i
|
267
|
-
#debug "CNT: #{cnt}.#{cnt.class} offset: #{@offset}"
|
268
|
-
@offset = cnt + @offset # @offset was negative here
|
269
|
-
debug("Initial offset #{@offset} in '#{table_name}' with #{cnt} rows")
|
270
|
-
@offset = 0 if @offset < 0
|
271
|
-
end
|
272
|
-
#@stmt = db.prepare("SELECT * FROM #{table_name} LIMIT ? OFFSET ?;")
|
273
|
-
@stmt = db.prepare("SELECT _senders.name, #{t}.* FROM #{t} JOIN _senders WHERE #{t}.oml_sender_id = _senders.id LIMIT ? OFFSET ?;")
|
274
|
-
end
|
275
|
-
@stmt
|
276
|
-
end
|
264
|
+
# def _statement
|
265
|
+
# unless @stmt
|
266
|
+
# db = @db = SQLite3::Database.new(@db_file)
|
267
|
+
# @db.type_translation = true
|
268
|
+
# table_name = t = @sname
|
269
|
+
# if @offset < 0
|
270
|
+
# cnt = db.execute("select count(*) from #{table_name};")[0][0].to_i
|
271
|
+
# #debug "CNT: #{cnt}.#{cnt.class} offset: #{@offset}"
|
272
|
+
# @offset = cnt + @offset # @offset was negative here
|
273
|
+
# debug("Initial offset #{@offset} in '#{table_name}' with #{cnt} rows")
|
274
|
+
# @offset = 0 if @offset < 0
|
275
|
+
# end
|
276
|
+
# #@stmt = db.prepare("SELECT * FROM #{table_name} LIMIT ? OFFSET ?;")
|
277
|
+
# @stmt = db.prepare("SELECT _senders.name, #{t}.* FROM #{t} JOIN _senders WHERE #{t}.oml_sender_id = _senders.id LIMIT ? OFFSET ?;")
|
278
|
+
# end
|
279
|
+
# @stmt
|
280
|
+
# end
|
277
281
|
end # OmlSqlRow
|
278
282
|
|
279
283
|
|
data/lib/omf_oml/sql_source.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
|
2
|
-
require '
|
2
|
+
require 'sequel'
|
3
3
|
|
4
4
|
require 'omf_common/lobject'
|
5
5
|
require 'omf_oml/endpoint'
|
@@ -16,15 +16,19 @@ module OMF::OML
|
|
16
16
|
#
|
17
17
|
class OmlSqlSource < OMF::Common::LObject
|
18
18
|
|
19
|
-
#
|
19
|
+
# db_opts - Options used to create a Sequel adapter
|
20
20
|
#
|
21
|
-
|
22
|
-
|
23
|
-
|
21
|
+
# Sequel.connect(:adapter=>'postgres', :host=>'norbit.npc.nicta.com.au', :user=>'oml2', :password=>'omlisgoodforyou', :database=>'openflow-demo')
|
22
|
+
#
|
23
|
+
def initialize(db_opts, row_opts = {})
|
24
24
|
@running = false
|
25
25
|
@on_new_stream_procs = {}
|
26
26
|
@tables = {}
|
27
|
-
@
|
27
|
+
@db_opts = db_opts
|
28
|
+
debug "Opening DB (#{db_opts})"
|
29
|
+
@db = Sequel.connect(db_opts)
|
30
|
+
debug "DB: #{@db.inspect}"
|
31
|
+
@row_opts = row_opts
|
28
32
|
end
|
29
33
|
|
30
34
|
# Register a proc to be called when a new stream was
|
@@ -38,13 +42,6 @@ module OMF::OML
|
|
38
42
|
end
|
39
43
|
end
|
40
44
|
|
41
|
-
|
42
|
-
# def report_new_stream(stream)
|
43
|
-
# @on_new_stream_procs.each_value do |proc|
|
44
|
-
# proc.call(stream)
|
45
|
-
# end
|
46
|
-
# end
|
47
|
-
|
48
45
|
# Start checking the database for tables and create a new stream
|
49
46
|
# by calling the internal +report_new_table+ method.
|
50
47
|
# If +check_every+ > 0 continue checking every +check_every+ seconds
|
@@ -71,16 +68,18 @@ module OMF::OML
|
|
71
68
|
end
|
72
69
|
|
73
70
|
def run_once()
|
74
|
-
|
75
|
-
@db = SQLite3::Database.new(@db_file)
|
76
|
-
@db.type_translation = true
|
77
|
-
end
|
78
|
-
|
71
|
+
debug "Finding tables #{@db.tables}"
|
79
72
|
# first find tables
|
80
|
-
@db.
|
81
|
-
table_name =
|
82
|
-
report_new_table(table_name
|
73
|
+
@db.tables.each do |tn|
|
74
|
+
table_name = tn.to_s
|
75
|
+
report_new_table(table_name) unless table_name.start_with?('_')
|
83
76
|
end
|
77
|
+
@tables
|
78
|
+
|
79
|
+
# postgresql
|
80
|
+
# SELECT tablename FROM pg_tables
|
81
|
+
# WHERE tablename NOT LIKE �pg\\_%�
|
82
|
+
# AND tablename NOT LIKE �sql\\_%�;
|
84
83
|
end
|
85
84
|
|
86
85
|
|
@@ -93,13 +92,15 @@ module OMF::OML
|
|
93
92
|
# +on_new_stream+ is then called with the new stream as its single
|
94
93
|
# argument.
|
95
94
|
#
|
96
|
-
def report_new_table(table_name
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
95
|
+
def report_new_table(table_name)
|
96
|
+
unless table = @tables[table_name] # check if already reported before
|
97
|
+
debug "Found table: #{table_name}"
|
98
|
+
table = @tables[table_name] = OmlSqlRow.new(table_name, @db.schema(table_name), @db_opts, self, @row_opts)
|
99
|
+
@on_new_stream_procs.each_value do |proc|
|
100
|
+
proc.call(table)
|
101
|
+
end
|
102
102
|
end
|
103
|
+
table
|
103
104
|
end
|
104
105
|
|
105
106
|
end
|
data/lib/omf_oml/table.rb
CHANGED
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: 0.9.
|
4
|
+
version: 0.9.4
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-11-18 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: sqlite3
|
16
|
-
requirement:
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ~>
|
@@ -21,7 +21,12 @@ dependencies:
|
|
21
21
|
version: 1.3.6
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements:
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 1.3.6
|
25
30
|
description: ! "Glue functionality between OMF and OMF related libraries, such as
|
26
31
|
OMF Web and Labwiki, and\n OML."
|
27
32
|
email:
|
@@ -66,8 +71,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
66
71
|
version: '0'
|
67
72
|
requirements: []
|
68
73
|
rubyforge_project: omf_oml
|
69
|
-
rubygems_version: 1.8.
|
74
|
+
rubygems_version: 1.8.24
|
70
75
|
signing_key:
|
71
76
|
specification_version: 3
|
72
77
|
summary: Glue between OMF and OML.
|
73
78
|
test_files: []
|
79
|
+
has_rdoc:
|