bc3 0.1.2 → 0.2.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.
@@ -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