blackwinter-flattendb 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
data/ChangeLog ADDED
@@ -0,0 +1,5 @@
1
+ = Revision history for flattendb
2
+
3
+ == x.y.z [yyyy-mm-dd]
4
+
5
+ * ...
data/README ADDED
@@ -0,0 +1,42 @@
1
+ = flattendb - Flatten relational databases
2
+
3
+ == VERSION
4
+
5
+ This documentation refers to flattendb version 0.0.4
6
+
7
+
8
+ == DESCRIPTION
9
+
10
+ TODO: well, the description... ;-)
11
+
12
+
13
+ == LINKS
14
+
15
+ <b></b>
16
+ Documentation:: <http://prometheus.rubyforge.org/flattendb>
17
+ Source code (old):: <http://prometheus.rubyforge.org/svn/scratch/flattendb>
18
+ Source code:: <http://github.com/blackwinter/flattendb>
19
+ Rubyforge project:: <http://rubyforge.org/projects/prometheus>
20
+
21
+
22
+ == AUTHORS
23
+
24
+ * Jens Wille <mailto:jens.wille@uni-koeln.de>
25
+
26
+
27
+ == LICENSE AND COPYRIGHT
28
+
29
+ Copyright (C) 2007 University of Cologne,
30
+ Albertus-Magnus-Platz, 50932 Cologne, Germany
31
+
32
+ flattendb is free software: you can redistribute it and/or modify it under the
33
+ terms of the GNU General Public License as published by the Free Software
34
+ Foundation, either version 3 of the License, or (at your option) any later
35
+ version.
36
+
37
+ flattendb is distributed in the hope that it will be useful, but WITHOUT ANY
38
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
39
+ A PARTICULAR PURPOSE. See the GNU General Public License for more details.
40
+
41
+ You should have received a copy of the GNU General Public License along with
42
+ flattendb. If not, see <http://www.gnu.org/licenses/>.
data/Rakefile ADDED
@@ -0,0 +1,21 @@
1
+ begin
2
+ require 'hen'
3
+ rescue LoadError
4
+ abort "Please install the 'hen' gem first."
5
+ end
6
+
7
+ require 'lib/flattendb/version'
8
+
9
+ Hen.lay! {{
10
+ :rubyforge => {
11
+ :package => 'flattendb'
12
+ },
13
+
14
+ :gem => {
15
+ :version => FlattenDB::VERSION,
16
+ :summary => 'Flatten relational databases.',
17
+ :files => FileList['lib/**/*.rb', 'bin/*'].to_a,
18
+ :extra_files => FileList['[A-Z]*', 'example/*'].to_a,
19
+ :dependencies => %w[highline libxml-ruby builder ruby-nuggets]
20
+ }
21
+ }}
data/bin/flattendb ADDED
@@ -0,0 +1,195 @@
1
+ #! /usr/bin/ruby
2
+
3
+ #--
4
+ ###############################################################################
5
+ # #
6
+ # flattendb -- Flatten relational databases #
7
+ # #
8
+ # Copyright (C) 2007 University of Cologne, #
9
+ # Albertus-Magnus-Platz, #
10
+ # 50932 Cologne, Germany #
11
+ # #
12
+ # Authors: #
13
+ # Jens Wille <jens.wille@uni-koeln.de> #
14
+ # #
15
+ # flattendb is free software; you can redistribute it and/or modify it under #
16
+ # the terms of the GNU General Public License as published by the Free #
17
+ # Software Foundation; either version 3 of the License, or (at your option) #
18
+ # any later version. #
19
+ # #
20
+ # flattendb is distributed in the hope that it will be useful, but WITHOUT #
21
+ # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
22
+ # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
23
+ # more details. #
24
+ # #
25
+ # You should have received a copy of the GNU General Public License along #
26
+ # with flattendb. If not, see <http://www.gnu.org/licenses/>. #
27
+ # #
28
+ ###############################################################################
29
+ #++
30
+
31
+ require 'optparse'
32
+
33
+ require 'rubygems'
34
+ require 'highline/import'
35
+ require 'nuggets/array/flatten_once'
36
+
37
+ $: << File.join(File.dirname(__FILE__), '..', 'lib')
38
+
39
+ require 'flattendb'
40
+ require 'flattendb/cli'
41
+
42
+ include FlattenDB::CLI
43
+
44
+ USAGE = "Usage: #{$0} [-h|--help] [options]"
45
+ abort USAGE if ARGV.empty?
46
+
47
+ $global_options = {
48
+ :type => :mysql,
49
+ :infiles => [],
50
+ :outfile => nil,
51
+ :confile => nil,
52
+ :keep => false,
53
+ :mysql => {
54
+ :intype => :xml
55
+ },
56
+ :mdb => {
57
+ :intype => :mdb
58
+ }
59
+ }
60
+
61
+ $opts_by_type = {
62
+ :mysql => {
63
+ :title => 'MySQL',
64
+ :opts => lambda { |opts|
65
+ opts.on('-x', '--mysql-xml', "Input file is of type XML [This is the default]") {
66
+ $global_options[:mysql][:intype] = :xml
67
+ }
68
+ opts.on('-s', '--sql', "Input file is of type SQL") {
69
+ $global_options[:mysql][:intype] = :sql
70
+ }
71
+ }
72
+ },
73
+ :mdb => {
74
+ :title => 'MS Access',
75
+ :opts => lambda { |opts|
76
+ opts.on('-m', '--mdb', "Input file is of type MDB [This is the default]") {
77
+ $global_options[:mdb][:intype] = :mdb
78
+ }
79
+ opts.on('-y', '--mdb-xml', "Input file is of type XML") {
80
+ $global_options[:mdb][:intype] = :xml
81
+ }
82
+ }
83
+ }
84
+ }
85
+
86
+ def type_options(type, opts, with_heading = true)
87
+ if type == :all
88
+ $opts_by_type.keys.sort_by { |t| t.to_s }.each { |t|
89
+ type_options(t, opts, with_heading)
90
+ }
91
+ else
92
+ opt = $opts_by_type[type.to_sym]
93
+
94
+ if with_heading
95
+ opts.separator ''
96
+ opts.separator " - [#{type}] #{opt[:title]}"
97
+ end
98
+
99
+ opt[:opts][opts]
100
+ end
101
+ end
102
+
103
+ OptionParser.new { |opts|
104
+ opts.banner = USAGE
105
+
106
+ opts.separator ''
107
+ opts.separator 'Options:'
108
+
109
+ if $type
110
+ opts.separator " [-t, --type] TYPE OVERRIDE IN EFFECT (#{$type})"
111
+ else
112
+ opts.on('-t', '--type TYPE', "Type of database at hand [Default: #{$global_options[:type]}]") { |t|
113
+ $global_options[:type] = t.downcase.to_sym
114
+ }
115
+ end
116
+
117
+ opts.separator ''
118
+
119
+ opts.on('-i', '--input-file FILE', "Input file; depending on the database type, this option", "may be given multiple times [REQUIRED]") { |f|
120
+ $global_options[:infiles] << f
121
+ }
122
+
123
+ opts.on('-o', '--output-file FILE', "Output file (flat XML) [REQUIRED]") { |f|
124
+ $global_options[:outfile] = f
125
+ }
126
+
127
+ opts.on('-c', '--config-file FILE', "Configuration file (YAML) [REQUIRED]") { |f|
128
+ $global_options[:confile] = f
129
+ }
130
+
131
+ opts.separator ''
132
+
133
+ opts.on('-k', '--keep', "Keep any intermediate files (generated XML dumps, etc.)") {
134
+ $global_options[:keep] = true
135
+ }
136
+
137
+ opts.separator ''
138
+ opts.separator 'Database-specific Options:'
139
+
140
+ if $type
141
+ type_options($type, opts, false)
142
+ else
143
+ type_options(:all, opts)
144
+ end
145
+
146
+ opts.separator ''
147
+ opts.separator 'Generic options:'
148
+
149
+ opts.on('-h', '--help', 'Print this help message and exit') {
150
+ abort opts.to_s
151
+ }
152
+
153
+ opts.on('--version', 'Print program version and exit') {
154
+ abort "#{File.basename($0)} v#{FlattenDB::VERSION}"
155
+ }
156
+ }.parse!
157
+
158
+ $type ||= $global_options[:type]
159
+ $options = $global_options[$type] || {}
160
+
161
+ # Load corresponding module
162
+ begin
163
+ require "flattendb/types/#{$type}"
164
+ rescue LoadError
165
+ abort "Database type '#{$type}' is not supported at the moment."
166
+ end
167
+
168
+ abort "No output file specified" unless $global_options[:outfile]
169
+
170
+ if confile = $global_options[:confile]
171
+ abort "Configuration file not found: #{confile}" unless File.readable?(confile)
172
+ else
173
+ abort "No configuration file specified"
174
+ end
175
+
176
+ $global_options[:infiles].each { |infile|
177
+ abort "Input file not found: #{infile}" unless File.readable?(infile)
178
+ }
179
+
180
+ $infiles = $global_options[:infiles]
181
+ $outfile = $global_options[:outfile]
182
+ $confile = $global_options[:confile]
183
+
184
+ # Load type-specific script
185
+ begin
186
+ load File.join(File.dirname(__FILE__), "flattendb.#{$type}")
187
+ rescue LoadError
188
+ # silently ignore
189
+ end
190
+
191
+ FlattenDB[$type].new($infile || $infiles, $outfile, $confile).flatten!.to_xml
192
+
193
+ unless $global_options[:keep]
194
+ File.delete($dump_file) if $dump_file
195
+ end
data/bin/flattendb.mdb ADDED
@@ -0,0 +1,55 @@
1
+ #! /usr/bin/ruby
2
+
3
+ # vi:ft=ruby
4
+
5
+ #--
6
+ ###############################################################################
7
+ # #
8
+ # flattendb -- Flatten relational databases #
9
+ # #
10
+ # Copyright (C) 2007 University of Cologne, #
11
+ # Albertus-Magnus-Platz, #
12
+ # 50932 Cologne, Germany #
13
+ # #
14
+ # Authors: #
15
+ # Jens Wille <jens.wille@uni-koeln.de> #
16
+ # #
17
+ # flattendb is free software; you can redistribute it and/or modify it under #
18
+ # the terms of the GNU General Public License as published by the Free #
19
+ # Software Foundation; either version 3 of the License, or (at your option) #
20
+ # any later version. #
21
+ # #
22
+ # flattendb is distributed in the hope that it will be useful, but WITHOUT #
23
+ # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
24
+ # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
25
+ # more details. #
26
+ # #
27
+ # You should have received a copy of the GNU General Public License along #
28
+ # with flattendb. If not, see <http://www.gnu.org/licenses/>. #
29
+ # #
30
+ ###############################################################################
31
+ #++
32
+
33
+ unless $type
34
+ $type = :mdb
35
+ load File.join(File.dirname(__FILE__), 'flattendb')
36
+ else
37
+ case $options[:intype]
38
+ when :xml
39
+ $infiles.each { |infile|
40
+ unless IO.read(infile, 6) == '<?xml '
41
+ abort "Input file doesn't seem to be a valid XML file, XML declaration missing: #{infile}"
42
+ end
43
+ }
44
+ when :mdb
45
+ tables_cmd = 'mdb-tables'
46
+ export_cmd = 'mdb-export'
47
+
48
+ require_commands(tables_cmd, export_cmd, :pkg => 'mdbtools')
49
+ require_libraries('fastercsv')
50
+
51
+ $infiles.map! { |infile|
52
+ $dump_file
53
+ }
54
+ end
55
+ end
@@ -0,0 +1,91 @@
1
+ #! /usr/bin/ruby
2
+
3
+ # vi:ft=ruby
4
+
5
+ #--
6
+ ###############################################################################
7
+ # #
8
+ # flattendb -- Flatten relational databases #
9
+ # #
10
+ # Copyright (C) 2007 University of Cologne, #
11
+ # Albertus-Magnus-Platz, #
12
+ # 50932 Cologne, Germany #
13
+ # #
14
+ # Authors: #
15
+ # Jens Wille <jens.wille@uni-koeln.de> #
16
+ # #
17
+ # flattendb is free software; you can redistribute it and/or modify it under #
18
+ # the terms of the GNU General Public License as published by the Free #
19
+ # Software Foundation; either version 3 of the License, or (at your option) #
20
+ # any later version. #
21
+ # #
22
+ # flattendb is distributed in the hope that it will be useful, but WITHOUT #
23
+ # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
24
+ # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
25
+ # more details. #
26
+ # #
27
+ # You should have received a copy of the GNU General Public License along #
28
+ # with flattendb. If not, see <http://www.gnu.org/licenses/>. #
29
+ # #
30
+ ###############################################################################
31
+ #++
32
+
33
+ unless $type
34
+ $type = :mysql
35
+ load File.join(File.dirname(__FILE__), 'flattendb')
36
+ else
37
+ $infile = $infiles.first
38
+
39
+ case $options[:intype]
40
+ when :xml
41
+ unless IO.read($infile, 6) == '<?xml '
42
+ abort "Input file doesn't seem to be a valid XML file, XML declaration missing"
43
+ end
44
+ when :sql
45
+ $dump_file = $infile.sub(/\.(?:sql|dump)$/i, '') << '.xml'
46
+ abort "Dump file and output file are the same: #{$dump_file} = #{$outfile}" \
47
+ if File.expand_path($dump_file) == File.expand_path($outfile)
48
+
49
+ mysql_cmd = 'mysql'
50
+ dump_cmd = 'mysqldump'
51
+
52
+ require_commands(mysql_cmd, dump_cmd, :pkg => 'a suitable MySQL client')
53
+ require_libraries('mysql')
54
+
55
+ mysql_user = ask('Please enter the MySQL user name: ') \
56
+ { |q| q.default = ENV['USER'] }
57
+ mysql_pass = ask("Please enter the MySQL password for that user: ") \
58
+ { |q| q.echo = false }
59
+
60
+ # according to <http://www.adamspiers.org/computing/mysqldiff/#how> MySQL
61
+ # default permissions allow anyone to create databases beginning with the
62
+ # prefix 'test_'
63
+ temp_db = 'flattendb_temp_%d_%d' % [Time.now, $$]
64
+ temp_user = 'flattendb_user'
65
+ temp_pass = 'flattendb_pass'
66
+
67
+ mysql_args = "--one-database -u#{temp_user} -p#{temp_pass} #{temp_db} < #{$infile}"
68
+ dump_args = "--xml -u#{temp_user} -p#{temp_pass} #{temp_db} > #{$dump_file}"
69
+
70
+ begin
71
+ mysql = Mysql.real_connect('localhost', mysql_user, mysql_pass)
72
+
73
+ mysql.query("CREATE DATABASE #{temp_db}")
74
+ mysql.query("GRANT ALL ON #{temp_db}.* TO '#{temp_user}'@'localhost' IDENTIFIED BY '#{temp_pass}'")
75
+
76
+ system("#{mysql_cmd} #{mysql_args} && #{dump_cmd} #{dump_args}")
77
+ rescue Mysql::Error => err
78
+ abort "ERROR #{err.errno} (#{err.sqlstate}): #{err.error}"
79
+ ensure
80
+ if mysql
81
+ mysql.query("REVOKE ALL ON #{temp_db}.* FROM '#{temp_user}'@'localhost'") \
82
+ if mysql_user == 'root'
83
+
84
+ mysql.query("DROP DATABASE IF EXISTS #{temp_db}")
85
+ mysql.close
86
+ end
87
+ end
88
+
89
+ $infile = $dump_file
90
+ end
91
+ end
@@ -0,0 +1,120 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <ndr>
3
+ <row>
4
+ <Bla>12</Bla>
5
+ <Blub></Blub>
6
+ <ObjID>1</ObjID>
7
+ <attr1>
8
+ <ObjID>1</ObjID>
9
+ <Val>3</Val>
10
+ <attr1ID>1</attr1ID>
11
+ </attr1>
12
+ <attr2>
13
+ <ObjID>1</ObjID>
14
+ <Val>4</Val>
15
+ <attr2ID>3</attr2ID>
16
+ </attr2>
17
+ <barobject>
18
+ <Bar>1002</Bar>
19
+ <ObjID>1</ObjID>
20
+ <attr4>
21
+ <Val>0</Val>
22
+ <attr4ID>2</attr4ID>
23
+ </attr4>
24
+ <attr4ID>2</attr4ID>
25
+ </barobject>
26
+ <fooobject>
27
+ <Foo>112</Foo>
28
+ <ObjID>1</ObjID>
29
+ <attr1>
30
+ <ObjID>1</ObjID>
31
+ <Val>3</Val>
32
+ <attr1ID>1</attr1ID>
33
+ </attr1>
34
+ <attr1ID>1</attr1ID>
35
+ <attr3>
36
+ <Val>8</Val>
37
+ <attr3ID>2</attr3ID>
38
+ </attr3>
39
+ <attr3ID>2</attr3ID>
40
+ </fooobject>
41
+ </row>
42
+ <row>
43
+ <Bla>12</Bla>
44
+ <Blub>hi</Blub>
45
+ <ObjID>2</ObjID>
46
+ <attr1>
47
+ <ObjID>2</ObjID>
48
+ <Val>2</Val>
49
+ <attr1ID>2</attr1ID>
50
+ </attr1>
51
+ <attr2>
52
+ <ObjID>2</ObjID>
53
+ <Val>5</Val>
54
+ <attr2ID>2</attr2ID>
55
+ </attr2>
56
+ <barobject>
57
+ <Bar>1200</Bar>
58
+ <ObjID>2</ObjID>
59
+ <attr4>
60
+ <Val>0</Val>
61
+ <attr4ID>1</attr4ID>
62
+ </attr4>
63
+ <attr4ID>1</attr4ID>
64
+ </barobject>
65
+ <fooobject>
66
+ <Foo>122</Foo>
67
+ <ObjID>2</ObjID>
68
+ <attr1>
69
+ <ObjID>2</ObjID>
70
+ <Val>2</Val>
71
+ <attr1ID>2</attr1ID>
72
+ </attr1>
73
+ <attr1ID>2</attr1ID>
74
+ <attr3>
75
+ <Val>0</Val>
76
+ <attr3ID>1</attr3ID>
77
+ </attr3>
78
+ <attr3ID>1</attr3ID>
79
+ </fooobject>
80
+ </row>
81
+ <row>
82
+ <Bla>1</Bla>
83
+ <Blub>ho</Blub>
84
+ <ObjID>3</ObjID>
85
+ <attr1>
86
+ <ObjID>3</ObjID>
87
+ <Val>1</Val>
88
+ <attr1ID>3</attr1ID>
89
+ </attr1>
90
+ <attr2>
91
+ <ObjID>3</ObjID>
92
+ <Val>6</Val>
93
+ <attr2ID>1</attr2ID>
94
+ </attr2>
95
+ <barobject>
96
+ <Bar>1000</Bar>
97
+ <ObjID>3</ObjID>
98
+ <attr4>
99
+ <Val>9</Val>
100
+ <attr4ID>3</attr4ID>
101
+ </attr4>
102
+ <attr4ID>3</attr4ID>
103
+ </barobject>
104
+ <fooobject>
105
+ <Foo>111</Foo>
106
+ <ObjID>3</ObjID>
107
+ <attr1>
108
+ <ObjID>3</ObjID>
109
+ <Val>1</Val>
110
+ <attr1ID>3</attr1ID>
111
+ </attr1>
112
+ <attr1ID>3</attr1ID>
113
+ <attr3>
114
+ <Val>7</Val>
115
+ <attr3ID>3</attr3ID>
116
+ </attr3>
117
+ <attr3ID>3</attr3ID>
118
+ </fooobject>
119
+ </row>
120
+ </ndr>