bc3 0.1.2 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,473 @@
1
+ #!/usr/bin/env ruby
2
+ =begin rdoc
3
+ ==What's for
4
+
5
+ BC3 offers no genuine method to compare database content.
6
+
7
+ This script is part of a solution to compare two tables in two databases
8
+ (or different selections in one database...)
9
+
10
+ ==How to use
11
+ Call
12
+ bc3_db-compare <configfile> <targetfile> [<logfile>]
13
+
14
+ The configfile will be used to prepare a database connection and
15
+ a DB-selection. The result is written to targetfile.
16
+
17
+ The optional logfile will get some logging data
18
+ (can be used to analyse errors).
19
+
20
+ ==How to use in BC3
21
+ Import the file formats from file examples/BCSettings_db4bc3.
22
+ to Beyond Compare 3 (BC3)
23
+
24
+ Save your two configuration files with extension bcpkg
25
+
26
+ Compare your two configuration files.
27
+
28
+
29
+ ==How it works
30
+ You can define file formats with conversion process.
31
+ This script implement such a conversion for
32
+ database access.
33
+
34
+ The file to compare contains a
35
+ configuration to make a data base selection and
36
+ build a result file.
37
+
38
+ Two of this configuration files will be compared with BC3.
39
+ BC3 calls this script as conversion tool,
40
+ the data base selection is executed and a text file is the result.
41
+
42
+ The configuration file defines the configuration in yaml-syntax.
43
+ Details see DBconverter#check_configuration_file.
44
+
45
+ The file formats can be imported from file examples/BCSettings_db4bc3.bcpkg
46
+
47
+ This script based on a question in
48
+ http://www.scootersoftware.com/vbulletin/showthread.php?t=7360
49
+ =end
50
+
51
+ =begin
52
+ ==Beyond Compare
53
+ Beyond Compare is limited to comparison of plain text files. To compare binary files, or to format files before comparison, Beyond Compare can call an external program to generate a temporary text file for comparison. The following details the conversion process.
54
+
55
+ To access settings for external conversion in the File Viewer, select Tools | Edit Current Rules. Go to the Conversion tab.
56
+
57
+ Variables for external conversion
58
+ %s - source file and path
59
+ %t - target file and path
60
+ %n - source filename
61
+ %x - extension of the source file
62
+ =end
63
+ require 'yaml'
64
+ require 'sequel'
65
+ require 'log4r'
66
+ $log = Log4r::Logger.new('log')
67
+
68
+ module BC3
69
+ =begin rdoc
70
+ Class to support comparison of database content.
71
+
72
+ Define a converter for Beyond Compare 3.
73
+ =end
74
+ class DBconverter
75
+ VERSION = '0.2.0'
76
+ #Exitcodes
77
+ EXITCODES = {
78
+ # => 1 normal ruby errors (syntax error)
79
+ :sourcefile_missing => 2,
80
+ :configuration_error => 3,
81
+ :configuration_incomplete => 4,
82
+
83
+ :db_connection_error => 10,
84
+ :adapter_unknown => 11,
85
+ :sequel_error => 12,
86
+ :db_table_missing => 20,
87
+
88
+ :dataset_error => 30,
89
+
90
+ :argv_wrong => 90,
91
+ } # File.open(__FILE__){|f| puts f.read.scan(/EXITCODES\[(.*)\]/) }; exit
92
+
93
+
94
+ OBLIGATORY_KEYS = %w{adapter db tab}
95
+ VALID_KEYS = OBLIGATORY_KEYS + %w{
96
+ server password username
97
+ header schema
98
+ data headline
99
+ select filter order
100
+ sql
101
+ show_sql
102
+ }
103
+
104
+ =begin rdoc
105
+ Expect a configuration file and a filename to save the result.
106
+
107
+ Without target file name, an empty object is created.
108
+ =end
109
+ def initialize( source_filename = nil, target_filename = nil, log_filename = nil )
110
+ if target_filename
111
+
112
+ if log_filename
113
+ $log.outputters << Log4r::FileOutputter.new('log', :filename => log_filename )
114
+ end
115
+
116
+ @header = true #Default
117
+
118
+ $log.info("Start conversion (%s)%s => %s" % [DBconverter::VERSION, source_filename, target_filename]) if $log.info?
119
+ #set attributes
120
+ $log.debug("Open %s" % source_filename) if $log.debug?
121
+ check_configuration_file(source_filename)
122
+ analyse_configuration_file(File.read(source_filename), File.dirname(source_filename))
123
+
124
+ prepare_dataset()
125
+ save_target(target_filename)
126
+ end
127
+ end # initialize
128
+
129
+ =begin rdoc
130
+ Leave the script after an error.
131
+
132
+ For unit test, this may be redefined to throw an exception or similar.
133
+ =end
134
+ def bc3_exit( exitcode, description)
135
+ $log.error(description) if $log.error?
136
+ exit EXITCODES[exitcode]
137
+ end
138
+ =begin rdoc
139
+ Check existence of configuration file.
140
+ =end
141
+ def check_configuration_file(filename)
142
+ if ! filename or ! File.exist?(filename)
143
+ bc3_exit(:sourcefile_missing, "Open %s" % filename.inspect)
144
+ end
145
+ end
146
+ =begin rdoc
147
+ Open and analyse configuration file
148
+
149
+ ==Examples for configuration files
150
+ Compare data of table 'languages' in sqlite data base file 'test.db' in a
151
+ csv-file.
152
+
153
+ adapter: sqlite
154
+ db: test.db
155
+ tab: languages
156
+ data: csv_tab
157
+
158
+
159
+
160
+ ==Obligatory configuration settings
161
+ ===adapter
162
+ Defines the type of DB-connection.
163
+
164
+ Supported:
165
+ * ado (server required, username and password optional)
166
+ * sqlite
167
+
168
+ ===db
169
+ Name of the @db.
170
+
171
+ * ado: name of the database.
172
+ * sqlite: filename
173
+
174
+ Warning! BC3 calls the script from bc3-folder.
175
+ The filename should be an absolute path.
176
+
177
+ ===tab
178
+ Table name for comparison.
179
+
180
+ ==Optional configuration settings
181
+ ===schema
182
+ if true, the table schema (meta data of table) is added on top.
183
+
184
+ ==Adapt the selection
185
+
186
+ ===select
187
+ Restrict columns.
188
+ See Sequel::@dataset#select
189
+ http://sequel.rubyforge.org/rdoc/classes/Sequel/@dataset.html#M000439
190
+
191
+ ===filter
192
+ Where-clause. Restrict rows.
193
+ See Sequel::@dataset#filter
194
+ * http://sequel.rubyforge.org/rdoc/classes/Sequel/@dataset.html#M000412
195
+
196
+ ===order
197
+ See Sequel::@dataset#order
198
+ http://sequel.rubyforge.org/rdoc/classes/Sequel/@dataset.html#M000429
199
+
200
+ List of column names.
201
+
202
+ ===sql
203
+ You can define a sql-command.
204
+
205
+ This sql-command will ignore all other selection commands (select, filter, order)
206
+
207
+ =end
208
+ def analyse_configuration_file(configuration, dirname = nil)
209
+
210
+ $log.debug("Analyse Configuration") if $log.debug?
211
+ options = {}
212
+ begin
213
+ options = YAML.load(configuration)
214
+ rescue ArgumentError => err
215
+ bc3_exit(:configuration_error, "Configuration file has error #{err}")
216
+ end
217
+ # check obligatory parameters
218
+ OBLIGATORY_KEYS.each{|opt|
219
+ if ! options[opt]
220
+ bc3_exit(:configuration_incomplete,"Option %s missing" % opt)
221
+ end
222
+ }
223
+ options.each{|key, value|
224
+ if ! VALID_KEYS.include?(key)
225
+ $log.warn("Undefined option %s" % key) if $log.warn?
226
+ end
227
+ }
228
+
229
+ @dbname = options['db']
230
+ case @adapter = options['adapter']
231
+ when 'ado'
232
+ if ! @server = options['server']
233
+ bc3_exit(:db_connection_error, "No Server given" % @dbname)
234
+ end
235
+ if ! @dbname
236
+ bc3_exit(:db_connection_error, "No @db given" % @dbname)
237
+ end
238
+ @username = options['username'] #optional, not needed for all logins (single sign on...)
239
+ @password = options['password'] #optional, not needed for all logins (single sign on...)
240
+ when 'sqlite'
241
+ #set the path relative to configuration file
242
+ @dbname = File.join(dirname, @dbname) if dirname and ! File.exist?(@dbname)
243
+ if ! File.exist?(@dbname)
244
+ bc3_exit(:db_connection_error, "DB-File %s not found in %s" % [@dbname, Dir.pwd])
245
+ end
246
+ else
247
+ bc3_exit(:adapter_unknown, "Adapter %s not defined " % @adapter.inspect)
248
+ end
249
+ @tabsym = options['tab'].downcase.to_sym
250
+
251
+ @select = [options['select']].flatten if options['select']
252
+ @filter = options['filter']
253
+ @order = options['order']
254
+ @sql = options['sql']
255
+
256
+ @header = options['header'] if options.has_key?('header') #add header (information about DB, table,,,)
257
+ @show_schema = options['schema']
258
+ @show_sql = options['show_sql']
259
+ @headline = options['headline'] #add headline for csv
260
+
261
+ case @show_data = options['data']
262
+ when nil #no data required
263
+ when 'inspect', 'csv_tab'
264
+ $log.info("Define data conversion routine #{@show_data}") if $log.info?
265
+ else
266
+ $log.error("Data conversion routine #{@show_data} not found") if $log.error?
267
+ end
268
+ end #analyse_configuration_file
269
+
270
+ #add header information
271
+ attr_accessor :header
272
+ #add heading data to csv
273
+ attr_accessor :headline
274
+ #(re)-define select-clause (what fields are needed)
275
+ attr_accessor :select
276
+ #(re)-define where-clause
277
+ attr_accessor :filter
278
+ #(re)-define order-clause
279
+ attr_accessor :order
280
+ #(re)-define raw sql -clause.
281
+ #This inactivates #select, #filter and #order
282
+ attr_writer :sql
283
+
284
+ =begin rdoc
285
+ Connect DB
286
+ =end
287
+ def connect()
288
+ $log.debug("Connect DB %s" % @dbname) if $log.debug?
289
+ begin
290
+ case @adapter
291
+ when 'ado'
292
+ @db = Sequel.connect(
293
+ :adapter=>'ado',
294
+ :host =>@server,
295
+ :database=>@dbname,
296
+ :user => @username,
297
+ :password=>@password
298
+ )
299
+ when 'sqlite'
300
+ @db = Sequel.sqlite(@dbname)
301
+ else
302
+ bc3_exit(:adapter_unknown, "Adapter %s not defined " % @adapter.inspect)
303
+ end #@adapter
304
+ #Test connection
305
+ if @db.test_connection
306
+ $log.info("Connected to DB %s" % @dbname) if $log.info?
307
+ else
308
+ bc3_exit(:db_connection_error, "DB-Connection error")
309
+ end
310
+ rescue Sequel::DatabaseError, Sequel::DatabaseConnectionError => err
311
+ bc3_exit(:sequel_error, "DB-Connection error: %s" % err.inspect)
312
+ end
313
+ @db
314
+ end #connect
315
+ =begin rdoc
316
+ Prepare @dataset.
317
+
318
+ Defines only the accessor.
319
+ There is no check, if the data are correct.
320
+ =end
321
+ def prepare_dataset(tabsym = @tabsym, select = @select, filter = @filter, order = @order )
322
+ @db = connect
323
+
324
+ if ! tabsym
325
+ $log.error("No table name available") if $log.error?
326
+ return {}
327
+ elsif ! @db.table_exists?(tabsym)
328
+ bc3_exit(:db_table_missing, "DB error: Table #{tabsym} not defined")
329
+ end
330
+
331
+ if @sql
332
+ $log.info("Use raw sql for dataset (#{@sql.inspect})") if $log.info?
333
+ return @dataset = @db.execute(@sql)
334
+ end
335
+
336
+ @dataset = @db[tabsym]
337
+ if select
338
+ $log.debug("Restrict rows to #{select.inspect}") if $log.debug?
339
+ @select.each{|row|
340
+ $log.warn("Rows definition for filter is no symbol: #{row.inspect}") unless row.is_a?(Symbol)
341
+ }
342
+ @dataset = @dataset.select(*select)
343
+ end
344
+ if filter
345
+ $log.debug("Restrict columns to #{filter.inspect}") if $log.debug?
346
+ @dataset = @dataset.filter(filter)
347
+ end
348
+ if order
349
+ $log.debug("Order columns by #{order.inspect}") if $log.debug?
350
+ @dataset = @dataset.order(order)
351
+ end
352
+ @dataset
353
+ end #prepare_dataset()
354
+ =begin rdoc
355
+ Build target file
356
+ =end
357
+ def save_target(filename = @target_filename)
358
+ $log.info("Save %s" % [filename]) if $log.info?
359
+ File.open(filename, 'w'){|f|
360
+ f << build_target.join("\n")
361
+ }
362
+ end #save_target
363
+ =begin rdoc
364
+ Build content for target file
365
+ =end
366
+ def build_target()
367
+
368
+ bc3_exit(:db_connection_error, "Database missing (forgot #prepare_dataset ?)") unless @db
369
+
370
+ txt = []
371
+ if @header
372
+ txt << "Check table %s.%s" % [@dbname, @tabsym]
373
+ end
374
+
375
+
376
+ if ! @db.table_exists?(@tabsym)
377
+ txt << "Table #{@tabsym} not found"
378
+ bc3_exit(:db_table_missing, "Table #{@tabsym} not found")
379
+ end
380
+
381
+ =begin
382
+ Add schema of table.
383
+ =end
384
+ if @show_schema
385
+ $log.debug("Get table schema #{@tabsym}") if $log.debug?
386
+ txt << "Table schema #{@tabsym}" if @header
387
+ txt << @db.schema(@tabsym).to_yaml
388
+ end
389
+
390
+ =begin
391
+ Add SQL
392
+ =end
393
+ if @show_sql
394
+ $log.debug("Write SQL-command (%s)" % (@sql ? 'raw sql' : 'dataset')) if $log.debug?
395
+
396
+ txt << "SQL for selection:" if @header
397
+ txt << ( @sql ? @sql : @dataset.sql )
398
+ end
399
+
400
+ =begin
401
+ Check table content/get content.
402
+
403
+ Only, when options['data'] is set.
404
+ =end
405
+ if @show_data
406
+ $log.debug("Get data from #{@tabsym}") if $log.debug?
407
+ txt << "Data content of table #{@tabsym}:" if @header
408
+
409
+ first_line = true
410
+ @dataset.each{|line|
411
+ case @show_data
412
+ when 'inspect'
413
+ txt << line.inspect
414
+ when 'csv_tab'
415
+ case line
416
+ when Array #@sql defined
417
+ txt << line.join("\t")
418
+ when Hash #Sequel::Dataset
419
+ if first_line and @headline
420
+ txt << @dataset.columns.map{|x|x.to_s}.join("\t")
421
+ end
422
+ txt << build_csv_line(line, "\t")
423
+ else
424
+ bc3_exit(:dataset_error , "Type of dataset is undefined #{line.inspect}")
425
+ end #case line
426
+ else
427
+ $log.error("Data conversion routine #{@show_data} not found") if $log.error?
428
+ txt << "Data conversion routine #{@show_data} not found"
429
+ end
430
+ first_line = false
431
+ }
432
+ else#ok, maybe you only want to compare the scheme.
433
+ $log.info("No data output") if $log.debug?
434
+ end
435
+ txt
436
+ end #build_target
437
+ =begin rdoc
438
+ Build one character separated value-line.
439
+ =end
440
+ def build_csv_line(line, sep, dataset = @dataset)
441
+ vals = []
442
+ dataset.columns.each{|col|
443
+ if line[col].respond_to?(:include?) and line[col].include?(sep)
444
+ $log.warn("Data contain separator #{sep} (#{line[col]})") if $log.warn?
445
+ vals << "\"#{line[col]}\""
446
+ else
447
+ vals << line[col].to_s
448
+ end
449
+
450
+ }
451
+ vals.join(sep)
452
+ end
453
+ end #class DBconverter
454
+ end #module BC3
455
+
456
+
457
+ $log.outputters = Log4r::StdoutOutputter.new('log', :level => Log4r::WARN)
458
+
459
+ $log.info("Start %s V%s" % [__FILE__, BC3::DBconverter::VERSION]) if $log.info?
460
+ if $log.debug?
461
+ $log.debug(" Parameters: %s" % ARGV.inspect)
462
+ $log.debug(" We are in: %s" % Dir.pwd)
463
+ end
464
+
465
+
466
+ if ARGV.empty?
467
+ $log.error("Testcase ARGV empty")
468
+ #~ $log.outputters = Log4r::StdoutOutputter.new('log', :level => Log4r::DEBUG)
469
+ #~ conv = DBconverter.new('../unittest/test_sql.db4bc3', 'xx')
470
+ exit BC3::DBconverter::EXITCODES[:argv_wrong]
471
+ else
472
+ conv = BC3::DBconverter.new(*ARGV)
473
+ end unless defined? SKIP_AUTOSTART
data/changes.rd CHANGED
@@ -8,12 +8,15 @@
8
8
  * Changed BC3::Snapshot.newd -> BC3::Snapshot.new_filesystem (newd as alias)
9
9
  * BC3::Snapshot.save saves yaml or bcss file
10
10
  * bin/bc_merge.rb can handle yaml-files
11
+
11
12
  ==0.1.2 2011-02-20
12
13
  * BC3::SnapshotParse: Support UTF for linux files
13
14
  * BC3::Snapshot#utf: Added flag. Allows creation of Linux-UTF-snapshots.
14
15
  * BC3::Snapshot: Support UTF for linux files (Snapshot uses UTF-8).
15
16
  * BC3::Snapshot.uncompress: Added
16
17
 
18
+ ==0.2.0 2011-04-08
19
+ * Add bc3_db_compare.rb
17
20
 
18
21
 
19
22
  =Known problems/Todos
@@ -0,0 +1,6 @@
1
+ adapter: sqlite
2
+ db: ./test.db
3
+ tab: languages
4
+ show_sql: true
5
+ headline: true
6
+ data: csv_tab
@@ -0,0 +1,8 @@
1
+ adapter: sqlite
2
+ db: ./test.db
3
+ tab: languages
4
+ show_sql: true
5
+ data: csv_tab
6
+ headline: true
7
+ filter:
8
+ - :key: [ 1, 2, 3, 4, 5, 6, 7, 8 ]
@@ -0,0 +1,11 @@
1
+ adapter: sqlite
2
+ db: ./test.db
3
+ tab: languages
4
+ data: csv_tab
5
+ show_sql: true
6
+ sql: |
7
+ SELECT * FROM `languages`
8
+ WHERE ((`key` IN (1, 2, 3, 4, 6, 7, 8)))
9
+ headline: true
10
+ filter:
11
+ - :key: [ 1, 2, 3, 4, 5, 6, 7, 8 ]
data/lib/bc3.rb CHANGED
@@ -85,7 +85,7 @@ require 'bc3/time'
85
85
  require 'bc3/parse'
86
86
 
87
87
  module BC3
88
- VERSION = '0.1.2'
88
+ VERSION = '0.2.0'
89
89
  end
90
90
 
91
91
  __END__
@@ -1 +1 @@
1
- =begin rdoc
2
1
  bignum too big to convert into `unsigned long' (RangeError)
3
2
  AD_EPOCH = 116_444_736_000_000_000
4
3
  AD_MULTIPLIER = 10_000_000
5
4
  # convert a Time object to AD's epoch
6
5
  def time2ad()
7
6
  (self.to_f * AD_MULTIPLIER) + AD_EPOCH
8
7
  end
9
8
  # convert from AD's time string to a Time object
10
9
  def self.ad2time(time)
11
10
  Time.at((time.to_f - AD_EPOCH) / AD_MULTIPLIER)
12
11
  end
12
+ =begin rdoc
13
13
  bignum too big to convert into `unsigned long' (RangeError)
14
14
  AD_EPOCH = 116_444_736_000_000_000
15
15
  AD_MULTIPLIER = 10_000_000
16
16
  # convert a Time object to AD's epoch
17
17
  def time2ad()
18
18
  (self.to_f * AD_MULTIPLIER) + AD_EPOCH
19
19
  end
20
20
  # convert from AD's time string to a Time object
21
21
  def self.ad2time(time)
22
22
  Time.at((time.to_f - AD_EPOCH) / AD_MULTIPLIER)
23
23
  end
@@ -0,0 +1,310 @@
1
+ =begin
2
+ This tests need sqlite3.
3
+
4
+ Details see
5
+ * http://www.sqlite.org/
6
+ * http://rubygems.org/gems/sqlite3
7
+
8
+ =end
9
+ gem 'test-unit'
10
+ require 'test/unit'
11
+
12
+ $:.unshift('../bin')
13
+ SKIP_AUTOSTART = true #avoid ARGV-interpretation
14
+ require 'bc3_db_compare.rb'
15
+
16
+ #~ $log.level = Log4r::FATAL
17
+ TESTDB = 'test.db'
18
+ TESTDATA = [
19
+ {:lc2=>"af", :lc3=>"afr", :name_en=>"Afrikaans", :iso8859=>"ISO8859_1"},
20
+ {:lc2=>"ar", :lc3=>"ara", :name_en=>"Arabic", :iso8859=>nil},
21
+ {:lc2=>"bg", :lc3=>"bul", :name_en=>"Bulgarian", :iso8859=>"ISO8859_5"},
22
+ {:lc2=>"br", :lc3=>"por", :name_en=>"Portuguese braz.", :iso8859=>"ISO8859_1"},
23
+ {:lc2=>"de", :lc3=>"deu", :name_en=>"German", :iso8859=>"ISO8859_1"},
24
+ {:lc2=>"en", :lc3=>"eng", :name_en=>"English", :iso8859=>"ISO8859_1"},
25
+ {:lc2=>"es", :lc3=>"spa", :name_en=>"Spanish", :iso8859=>"ISO8859_1"},
26
+ {:lc2=>"et", :lc3=>"est", :name_en=>"Estonian", :iso8859=>"ISO8859_4"},
27
+ {:lc2=>"fi", :lc3=>"fin", :name_en=>"Finnish", :iso8859=>"ISO8859_1"},
28
+ {:lc2=>"pt", :lc3=>"por", :name_en=>"Portuguese", :iso8859=>"ISO8859_1"},
29
+ ]
30
+ def build_testdata()
31
+ if ! File.exist?(TESTDB)
32
+ db = Sequel.sqlite(TESTDB)
33
+ db.create_table :languages do
34
+ primary_key :key
35
+ column :lc2, :string, :max_chars => 2
36
+ column :lc3, :string
37
+ column :name_en, :string
38
+ column :iso8859, :string
39
+ end
40
+ TESTDATA.each{|ds| db[:languages].insert(ds)}
41
+ end
42
+ end
43
+
44
+
45
+ class BC3::DBconverter
46
+ #Build excetions as replacement for exit
47
+ EXCEPTIONS = {}
48
+ EXITCODES.each{|key, value|
49
+ eval <<-xx
50
+ EXCEPTIONS[#{key.inspect}] = Error_#{key} = Class.new(SystemExit)
51
+ xx
52
+ }
53
+ =begin rdoc
54
+ For unit test, this must be redefined,
55
+ else the test is finished.
56
+ =end
57
+ def bc3_exit( exitcode, description)
58
+ #~ $log.error(description) if $log.error?
59
+ #~ exit EXITCODES[exitcode]
60
+ raise EXCEPTIONS[exitcode], description
61
+ end
62
+ end #class BC3::DBconverter
63
+
64
+ class Test_configuration < Test::Unit::TestCase
65
+ =begin
66
+ Build some test data with sqlite
67
+ =end
68
+ def self.startup
69
+ build_testdata
70
+ end #self.startup
71
+ def setup()
72
+ @bc3 = BC3::DBconverter.new()
73
+ end
74
+ def test_configuration()
75
+ #Invalid yaml-data
76
+ assert_raise(BC3::DBconverter::Error_configuration_error){
77
+ @bc3.analyse_configuration_file("- 1\na")
78
+ }
79
+
80
+ assert_raise(BC3::DBconverter::Error_configuration_incomplete){
81
+ @bc3.analyse_configuration_file('xx')
82
+ }
83
+ #adapter, tab and db must be defined.
84
+ assert_raise(BC3::DBconverter::Error_configuration_incomplete){
85
+ @bc3.analyse_configuration_file(<<-config
86
+ adapter: undefined_adapter
87
+ db: undefined_db
88
+ config
89
+ )
90
+ }
91
+ assert_raise(BC3::DBconverter::Error_adapter_unknown){
92
+ @bc3.analyse_configuration_file(<<-config
93
+ adapter: undefined_adapter
94
+ db: undefined_db
95
+ tab: xx
96
+ config
97
+ )
98
+ }
99
+ end #test_configuration()
100
+ def test_configuration_ado()
101
+ assert_nothing_raised(){
102
+ @bc3.analyse_configuration_file(<<-config
103
+ adapter: ado
104
+ db: undefined_db
105
+ tab: xx
106
+ server: xx
107
+ config
108
+ )
109
+ }
110
+ assert_raise(BC3::DBconverter::Error_db_connection_error, 'Server missing'){
111
+ @bc3.analyse_configuration_file(<<-config
112
+ adapter: ado
113
+ db: undefined_db
114
+ tab: xx
115
+ config
116
+ )
117
+ }
118
+ end
119
+
120
+ def test_configuration_sqlite()
121
+ assert_nothing_raised(){
122
+ @bc3.analyse_configuration_file(<<-config
123
+ adapter: sqlite
124
+ db: #{TESTDB}
125
+ tab: languages
126
+ config
127
+ )
128
+ }
129
+ assert_raise(BC3::DBconverter::Error_configuration_incomplete, 'filename missing'){
130
+ @bc3.analyse_configuration_file(<<-config
131
+ adapter: sqlite
132
+ tab: xx
133
+ config
134
+ )
135
+ }
136
+ assert_raise(BC3::DBconverter::Error_db_connection_error, 'filename wrong'){
137
+ @bc3.analyse_configuration_file(<<-config
138
+ adapter: sqlite
139
+ db: undefined_db
140
+ tab: xx
141
+ config
142
+ )
143
+ }
144
+ assert_nothing_raised(){
145
+ @bc3.analyse_configuration_file(<<-config
146
+ adapter: sqlite
147
+ db: #{TESTDB}
148
+ tab: xx_languages
149
+ config
150
+ )
151
+ }
152
+ #Test table xx_languages
153
+ assert_raise(BC3::DBconverter::Error_db_table_missing, 'table not defined'){
154
+ @bc3.prepare_dataset()
155
+ }
156
+ end
157
+ end
158
+
159
+ class Test_testdata_sqlite < Test::Unit::TestCase
160
+ def self.startup
161
+ build_testdata
162
+ end #self.startup
163
+ def setup()
164
+ @bc3 = BC3::DBconverter.new()
165
+ @bc3.analyse_configuration_file(<<-config
166
+ adapter: sqlite
167
+ db: #{TESTDB}
168
+ tab: languages
169
+ config
170
+ )
171
+ end
172
+ def test_dataset()
173
+ assert_instance_of(Sequel::SQLite::Dataset, @bc3.prepare_dataset())
174
+ assert_equal("SELECT * FROM `languages`", @bc3.prepare_dataset.sql)
175
+ assert_equal([], @bc3.build_target())
176
+ @bc3.header = true
177
+ assert_equal(["Check table test.db.languages"], @bc3.build_target())
178
+ end
179
+ end
180
+
181
+ class Test_testdata_sqlite_inspect < Test::Unit::TestCase
182
+ def self.startup
183
+ build_testdata
184
+ end #self.startup
185
+ def setup()
186
+ @bc3 = BC3::DBconverter.new()
187
+ @bc3.analyse_configuration_file(<<-config
188
+ adapter: sqlite
189
+ db: #{TESTDB}
190
+ tab: languages
191
+ data: inspect
192
+ config
193
+ )
194
+ end
195
+ def test_dataset()
196
+ assert_instance_of(Sequel::SQLite::Dataset, @bc3.prepare_dataset())
197
+ assert_equal("SELECT * FROM `languages`", @bc3.prepare_dataset.sql)
198
+ assert_equal("{:key=>1, :lc2=>\"af\", :lc3=>\"afr\", :name_en=>\"Afrikaans\", :iso8859=>\"ISO8859_1\"}\n{:key=>2, :lc2=>\"ar\", :lc3=>\"ara\", :name_en=>\"Arabic\", :iso8859=>nil}\n{:key=>3, :lc2=>\"bg\", :lc3=>\"bul\", :name_en=>\"Bulgarian\", :iso8859=>\"ISO8859_5\"}\n{:key=>4, :lc2=>\"br\", :lc3=>\"por\", :name_en=>\"Portuguese braz.\", :iso8859=>\"ISO8859_1\"}\n{:key=>5, :lc2=>\"de\", :lc3=>\"deu\", :name_en=>\"German\", :iso8859=>\"ISO8859_1\"}\n{:key=>6, :lc2=>\"en\", :lc3=>\"eng\", :name_en=>\"English\", :iso8859=>\"ISO8859_1\"}\n{:key=>7, :lc2=>\"es\", :lc3=>\"spa\", :name_en=>\"Spanish\", :iso8859=>\"ISO8859_1\"}\n{:key=>8, :lc2=>\"et\", :lc3=>\"est\", :name_en=>\"Estonian\", :iso8859=>\"ISO8859_4\"}\n{:key=>9, :lc2=>\"fi\", :lc3=>\"fin\", :name_en=>\"Finnish\", :iso8859=>\"ISO8859_1\"}\n{:key=>10, :lc2=>\"pt\", :lc3=>\"por\", :name_en=>\"Portuguese\", :iso8859=>\"ISO8859_1\"}",
199
+ @bc3.build_target.join("\n")
200
+ )
201
+ end
202
+ end
203
+
204
+ class Test_testdata_sqlite_csv_tab < Test::Unit::TestCase
205
+ def self.startup
206
+ build_testdata
207
+ end #self.startup
208
+ def setup()
209
+ @bc3 = BC3::DBconverter.new()
210
+ @bc3.analyse_configuration_file(<<-config
211
+ adapter: sqlite
212
+ db: #{TESTDB}
213
+ tab: languages
214
+ data: csv_tab
215
+ config
216
+ )
217
+ end
218
+ def test_dataset()
219
+ assert_instance_of(Sequel::SQLite::Dataset, @bc3.prepare_dataset())
220
+ assert_equal("SELECT * FROM `languages`", @bc3.prepare_dataset.sql)
221
+ assert_equal(%{1 af afr Afrikaans ISO8859_1
222
+ 2 ar ara Arabic
223
+ 3 bg bul Bulgarian ISO8859_5
224
+ 4 br por Portuguese braz. ISO8859_1
225
+ 5 de deu German ISO8859_1
226
+ 6 en eng English ISO8859_1
227
+ 7 es spa Spanish ISO8859_1
228
+ 8 et est Estonian ISO8859_4
229
+ 9 fi fin Finnish ISO8859_1
230
+ 10 pt por Portuguese ISO8859_1},
231
+ @bc3.build_target.join("\n")
232
+ )
233
+ end
234
+ def test_dataset_headline()
235
+ @bc3.headline = true
236
+ assert_equal("SELECT * FROM `languages`", @bc3.prepare_dataset.sql)
237
+ assert_equal(%{key lc2 lc3 name_en iso8859
238
+ 1 af afr Afrikaans ISO8859_1
239
+ 2 ar ara Arabic
240
+ 3 bg bul Bulgarian ISO8859_5
241
+ 4 br por Portuguese braz. ISO8859_1
242
+ 5 de deu German ISO8859_1
243
+ 6 en eng English ISO8859_1
244
+ 7 es spa Spanish ISO8859_1
245
+ 8 et est Estonian ISO8859_4
246
+ 9 fi fin Finnish ISO8859_1
247
+ 10 pt por Portuguese ISO8859_1},
248
+ @bc3.build_target.join("\n")
249
+ )
250
+ end
251
+ def test_dataset_filter()
252
+ @bc3.filter = {:key => [1,2] }
253
+ assert_equal("SELECT * FROM `languages` WHERE (`key` IN (1, 2))", @bc3.prepare_dataset.sql)
254
+ assert_equal(%{1 af afr Afrikaans ISO8859_1
255
+ 2 ar ara Arabic\t},
256
+ @bc3.build_target.join("\n")
257
+ )
258
+ @bc3.filter = nil #reset filter
259
+ end
260
+ def test_dataset_select()
261
+ @bc3.select = [:lc2, :lc3]
262
+ assert_equal("SELECT `lc2`, `lc3` FROM `languages`", @bc3.prepare_dataset.sql)
263
+ assert_equal(%{af afr
264
+ ar ara
265
+ bg bul
266
+ br por
267
+ de deu
268
+ en eng
269
+ es spa
270
+ et est
271
+ fi fin
272
+ pt por},
273
+ @bc3.build_target.join("\n")
274
+ )
275
+ @bc3.select = nil #reset filter
276
+ end
277
+ def test_dataset_order()
278
+ @bc3.order = [:name_en]
279
+ assert_equal("SELECT * FROM `languages` ORDER BY (`name_en`)", @bc3.prepare_dataset.sql)
280
+ #~ puts @bc3.build_target.join("\n")
281
+ assert_equal(%{1 af afr Afrikaans ISO8859_1
282
+ 2 ar ara Arabic
283
+ 3 bg bul Bulgarian ISO8859_5
284
+ 6 en eng English ISO8859_1
285
+ 8 et est Estonian ISO8859_4
286
+ 9 fi fin Finnish ISO8859_1
287
+ 5 de deu German ISO8859_1
288
+ 10 pt por Portuguese ISO8859_1
289
+ 4 br por Portuguese braz. ISO8859_1
290
+ 7 es spa Spanish ISO8859_1},
291
+ @bc3.build_target.join("\n")
292
+ )
293
+ @bc3.order = nil #reset filter
294
+ end
295
+ def test_dataset_sql()
296
+ @bc3.sql = "SELECT * FROM `languages` WHERE (`key` IN (1, 2))"
297
+ #exception before @bc3.prepare_dataset
298
+ assert_raise(BC3::DBconverter::Error_db_connection_error){@bc3.build_target}
299
+ assert_instance_of(SQLite3::ResultSet, @bc3.prepare_dataset)
300
+ assert_equal(%w{key lc2 lc3 name_en iso8859}, @bc3.prepare_dataset.columns)
301
+
302
+ assert_equal(%{1 af afr Afrikaans ISO8859_1
303
+ 2 ar ara Arabic\t},
304
+ @bc3.build_target.join("\n")
305
+ )
306
+ @bc3.sql = nil #reset sql
307
+ end
308
+ end
309
+
310
+ __END__
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bc3
3
3
  version: !ruby/object:Gem::Version
4
- hash: 31
4
+ hash: 23
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
- - 1
9
8
  - 2
10
- version: 0.1.2
9
+ - 0
10
+ version: 0.2.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Knut Lickert
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-02-20 00:00:00 +01:00
18
+ date: 2011-04-08 00:00:00 +02:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -32,6 +32,34 @@ dependencies:
32
32
  version: "0"
33
33
  type: :runtime
34
34
  version_requirements: *id001
35
+ - !ruby/object:Gem::Dependency
36
+ name: sequel
37
+ prerelease: false
38
+ requirement: &id002 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ hash: 3
44
+ segments:
45
+ - 0
46
+ version: "0"
47
+ type: :development
48
+ version_requirements: *id002
49
+ - !ruby/object:Gem::Dependency
50
+ name: sqlite3
51
+ prerelease: false
52
+ requirement: &id003 !ruby/object:Gem::Requirement
53
+ none: false
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ hash: 3
58
+ segments:
59
+ - 0
60
+ version: "0"
61
+ type: :development
62
+ version_requirements: *id003
35
63
  description: |
36
64
  Build and analyse Beyond Compare (BC3) Snapshot-Files.
37
65
  This gem allows flexible definition of BC3-snapshots and
@@ -43,6 +71,7 @@ email: knut@lickert.net
43
71
  executables:
44
72
  - bc3_merge.rb
45
73
  - bc3_search.rb
74
+ - bc3_db_compare.rb
46
75
  extensions: []
47
76
 
48
77
  extra_rdoc_files:
@@ -50,11 +79,13 @@ extra_rdoc_files:
50
79
  - changes.rd
51
80
  - bin/bc3_merge.rb
52
81
  - bin/bc3_search.rb
82
+ - bin/bc3_db_compare.rb
53
83
  files:
54
84
  - changes.rd
55
85
  - BCSS_Binary_Format.txt
56
86
  - bin/bc3_merge.rb
57
87
  - bin/bc3_search.rb
88
+ - bin/bc3_db_compare.rb
58
89
  - lib/bc3.rb
59
90
  - lib/bc3/file.rb
60
91
  - lib/bc3/folder.rb
@@ -77,6 +108,11 @@ files:
77
108
  - examples/scootersoftware/UnicodePath(Linux).bcss
78
109
  - examples/scootersoftware/UnicodeFilenames(Win32).bcss
79
110
  - examples/scootersoftware/UnicodePath(Win32).bcss
111
+ - examples_db_connect/BCSettings_db4bc3.bcpkg
112
+ - examples_db_connect/sqlite_test_1.db4bc3
113
+ - examples_db_connect/sqlite_test_2.db4bc3
114
+ - examples_db_connect/sqlite_test_sql.db4bc3
115
+ - examples_db_connect/test.db
80
116
  - unittest/unittest_bc3_helper.rb
81
117
  - unittest/unittest_bc3_time.rb
82
118
  - unittest/unittest_bc3_file.rb
@@ -84,6 +120,7 @@ files:
84
120
  - unittest/unittest_bc3_snapshot.rb
85
121
  - unittest/unittest_bc3_merge.rb
86
122
  - unittest/unittest_bc3_search.rb
123
+ - unittest/unittest_bc3_db_compare.rb
87
124
  has_rdoc: true
88
125
  homepage: http://gems.rubypla.net/bc3
89
126
  licenses: []
@@ -114,6 +151,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
114
151
  version: "0"
115
152
  requirements:
116
153
  - Beyond Compare, see http://www.scootersoftware.com
154
+ - sequel for bc3_db_compare.rb
117
155
  rubyforge_project:
118
156
  rubygems_version: 1.3.7
119
157
  signing_key:
@@ -127,3 +165,4 @@ test_files:
127
165
  - unittest/unittest_bc3_snapshot.rb
128
166
  - unittest/unittest_bc3_merge.rb
129
167
  - unittest/unittest_bc3_search.rb
168
+ - unittest/unittest_bc3_db_compare.rb