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.
@@ -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.key? cname
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(hrow[cname])
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
- unless raw_row.length == @schema.length
166
- raise "Row needs to have same size as schema (#{raw_row.inspect})"
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
@@ -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
- # *opts:
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, db_file, source, opts = {})
27
+ def initialize(table_name, schema_raw, db_opts, source, opts = {})
20
28
  @sname = table_name
21
- @db_file = db_file
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 = find_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
- include_oml_internals ? @row.dup : @row[4 .. -1]
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 find_schema()
167
- stmt = _statement
168
- cnames = stmt.columns
169
- ctypes = stmt.types
170
- schema = []
171
- #schema << {:name => :oml_sender, :type => 'STRING'}
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
- # Rename first col
177
- first = schema[0]
178
- raise "BUG: Should be 'name'" if first[:name] != :name
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
- _statement.execute(@limit, @offset).each do |r|
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
 
@@ -1,5 +1,5 @@
1
1
 
2
- require 'sqlite3'
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
- # +opts+ - passed on as +opts+ to the OmlSqlRow constructor
19
+ # db_opts - Options used to create a Sequel adapter
20
20
  #
21
- def initialize(db_file, opts = {})
22
- raise "Can't find database '#{db_file}'" unless File.readable?(db_file)
23
- @db_file = db_file
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
- @table_opts = opts
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
- unless @db
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.execute( "SELECT * FROM sqlite_master WHERE type='table';") do |r|
81
- table_name = r[1]
82
- report_new_table(table_name, @table_opts) unless table_name.start_with?('_')
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, opts = {})
97
- return if @tables.key?(table_name) # check if already reported before
98
- debug "Found table: #{table_name}"
99
- t = @tables[table_name] = OmlSqlRow.new(table_name, @db_file, self, opts)
100
- @on_new_stream_procs.each_value do |proc|
101
- proc.call(t)
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
@@ -178,7 +178,7 @@ module OMF::OML
178
178
  #
179
179
  def _add_row(row, needs_casting = false)
180
180
  if needs_casting
181
- row = @schema.cast_row(row)
181
+ row = @schema.cast_row(row, true)
182
182
  end
183
183
  #puts row.inspect
184
184
  if @on_before_row_added
@@ -1,6 +1,6 @@
1
1
 
2
2
  module OMF
3
3
  module OML
4
- VERSION = '0.9.3'
4
+ VERSION = '0.9.4'
5
5
  end
6
6
  end
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.3
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-10-15 00:00:00.000000000 Z
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: &13713900 !ruby/object:Gem::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: *13713900
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.10
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: