flattendb 0.0.1.96
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/COPYING +676 -0
- data/ChangeLog +5 -0
- data/README +33 -0
- data/Rakefile +23 -0
- data/bin/flattendb +129 -0
- data/bin/flattendb.mysql +97 -0
- data/example/mysql-sample.flat.xml +120 -0
- data/example/mysql-sample.sql +0 -0
- data/example/mysql-sample.xml +162 -0
- data/example/mysql-sample2flat.yaml +10 -0
- data/lib/flattendb/base.rb +99 -0
- data/lib/flattendb/mysql.rb +199 -0
- data/lib/flattendb/version.rb +55 -0
- data/lib/flattendb.rb +40 -0
- metadata +97 -0
data/README
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
= flattendb - Flatten relational databases
|
2
|
+
|
3
|
+
== VERSION
|
4
|
+
|
5
|
+
This documentation refers to flattendb version 0.0.1
|
6
|
+
|
7
|
+
|
8
|
+
== DESCRIPTION
|
9
|
+
|
10
|
+
TODO: well, the description... ;-)
|
11
|
+
|
12
|
+
|
13
|
+
== AUTHORS
|
14
|
+
|
15
|
+
* Jens Wille <mailto:jens.wille@uni-koeln.de>
|
16
|
+
|
17
|
+
|
18
|
+
== LICENSE AND COPYRIGHT
|
19
|
+
|
20
|
+
Copyright (C) 2007 University of Cologne,
|
21
|
+
Albertus-Magnus-Platz, 50932 Cologne, Germany
|
22
|
+
|
23
|
+
flattendb is free software: you can redistribute it and/or modify it under the
|
24
|
+
terms of the GNU General Public License as published by the Free Software
|
25
|
+
Foundation, either version 3 of the License, or (at your option) any later
|
26
|
+
version.
|
27
|
+
|
28
|
+
flattendb is distributed in the hope that it will be useful, but WITHOUT ANY
|
29
|
+
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
30
|
+
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
31
|
+
|
32
|
+
You should have received a copy of the GNU General Public License along with
|
33
|
+
flattendb. If not, see <http://www.gnu.org/licenses/>.
|
data/Rakefile
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'lib/flattendb/version'
|
2
|
+
|
3
|
+
FILES = FileList['lib/**/*.rb'].to_a
|
4
|
+
EXECS = FileList['bin/*'].to_a
|
5
|
+
RDOCS = %w[README COPYING ChangeLog]
|
6
|
+
OTHER = FileList['[A-Z]*', 'example/*'].to_a
|
7
|
+
|
8
|
+
task(:doc_spec) {{
|
9
|
+
:title => 'flattendb Application documentation',
|
10
|
+
:rdoc_files => RDOCS + FILES
|
11
|
+
}}
|
12
|
+
|
13
|
+
task(:gem_spec) {{
|
14
|
+
:name => 'flattendb',
|
15
|
+
:version => FlattenDB::VERSION,
|
16
|
+
:summary => 'Flatten relational databases',
|
17
|
+
:files => FILES + EXECS + OTHER,
|
18
|
+
:require_path => 'lib',
|
19
|
+
:bindir => 'bin',
|
20
|
+
:executables => EXECS,
|
21
|
+
:extra_rdoc_files => RDOCS,
|
22
|
+
:dependencies => %w[highline mysql libxml-ruby builder]
|
23
|
+
}}
|
data/bin/flattendb
ADDED
@@ -0,0 +1,129 @@
|
|
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
|
+
|
36
|
+
$: << File.join(File.dirname(__FILE__), '..', 'lib')
|
37
|
+
|
38
|
+
require 'flattendb'
|
39
|
+
|
40
|
+
USAGE = "Usage: #{$0} [-h|--help] [options] <infile> <outfile> <configfile>"
|
41
|
+
|
42
|
+
$options = {
|
43
|
+
:type => :mysql,
|
44
|
+
:mysql => {
|
45
|
+
:intype => :xml,
|
46
|
+
:keep => false
|
47
|
+
}
|
48
|
+
}
|
49
|
+
|
50
|
+
def type_options(type, opts, with_heading = true)
|
51
|
+
heading = lambda { |name|
|
52
|
+
if with_heading
|
53
|
+
opts.separator ''
|
54
|
+
opts.separator "- #{name}"
|
55
|
+
end
|
56
|
+
}
|
57
|
+
|
58
|
+
case type.to_sym
|
59
|
+
when :mysql
|
60
|
+
heading['MySQL']
|
61
|
+
|
62
|
+
opts.on('-x', '--xml', "Input file is of type XML [This is the default]") {
|
63
|
+
$options[:mysql][:intype] = :xml
|
64
|
+
}
|
65
|
+
opts.on('-s', '--sql', "Input file is of type SQL") {
|
66
|
+
$options[:mysql][:intype] = :sql
|
67
|
+
}
|
68
|
+
opts.on('-k', '--keep', "Keep intermediate XML dump; only applies if input type is 'sql'") {
|
69
|
+
$options[:mysql][:keep] = true
|
70
|
+
}
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
OptionParser.new { |opts|
|
75
|
+
opts.banner = USAGE
|
76
|
+
opts.separator ''
|
77
|
+
|
78
|
+
opts.separator 'Options:'
|
79
|
+
if $type
|
80
|
+
opts.separator " [-t, --type] TYPE OVERRIDE IN EFFECT (#{$type})"
|
81
|
+
else
|
82
|
+
opts.on('-t', '--type TYPE', "Type of database at hand [Default: #{$options[:type]}]") { |t|
|
83
|
+
$options[:type] = t.downcase.to_sym
|
84
|
+
}
|
85
|
+
end
|
86
|
+
|
87
|
+
opts.separator ''
|
88
|
+
opts.separator 'Database-specific Options:'
|
89
|
+
|
90
|
+
if $type
|
91
|
+
type_options($type, opts, false)
|
92
|
+
else
|
93
|
+
%w[mysql].each { |t|
|
94
|
+
type_options(t, opts)
|
95
|
+
}
|
96
|
+
end
|
97
|
+
|
98
|
+
opts.separator ''
|
99
|
+
opts.separator 'Generic options:'
|
100
|
+
opts.on('-h', '--help', 'Print this help message and exit') {
|
101
|
+
abort opts.to_s
|
102
|
+
}
|
103
|
+
opts.on('--version', 'Print program version and exit') {
|
104
|
+
abort "#{File.basename($0)} v#{FlattenDB::VERSION}"
|
105
|
+
}
|
106
|
+
}.parse!
|
107
|
+
|
108
|
+
$type ||= $options[:type]
|
109
|
+
$options = $options[$type] || {}
|
110
|
+
|
111
|
+
# Load corresponding module
|
112
|
+
begin
|
113
|
+
require "flattendb/#{$type}"
|
114
|
+
rescue LoadError
|
115
|
+
abort "Database type '#{$type}' is not supported at the moment."
|
116
|
+
end
|
117
|
+
|
118
|
+
abort USAGE unless ARGV.size == 3
|
119
|
+
|
120
|
+
$infile, $outfile, configfile = ARGV
|
121
|
+
|
122
|
+
abort "Input file not found: #{$infile}" unless File.readable?($infile)
|
123
|
+
|
124
|
+
# Load type-specific script
|
125
|
+
load File.join(File.dirname(__FILE__), "flattendb.#{$type}")
|
126
|
+
|
127
|
+
FlattenDB[$type].new($infile, $outfile, configfile).flatten!.to_xml
|
128
|
+
|
129
|
+
File.delete($dump_file) if $dump_file && !$options[:keep]
|
data/bin/flattendb.mysql
ADDED
@@ -0,0 +1,97 @@
|
|
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
|
+
if $0 == __FILE__
|
34
|
+
$type = :mysql
|
35
|
+
load File.join(File.dirname(__FILE__), 'flattendb')
|
36
|
+
else
|
37
|
+
case $options[:intype]
|
38
|
+
when :xml
|
39
|
+
abort "Input file doesn't seem to be a valid XML file, XML declaration missing" \
|
40
|
+
unless IO.read($infile, 6) == '<?xml '
|
41
|
+
when :sql
|
42
|
+
require 'mysql'
|
43
|
+
|
44
|
+
mysql_cmd = 'mysql'
|
45
|
+
dump_cmd = 'mysqldump'
|
46
|
+
|
47
|
+
[mysql_cmd, dump_cmd].each { |cmd|
|
48
|
+
catch :cmd_found do
|
49
|
+
ENV['PATH'].split(':').each { |path|
|
50
|
+
throw :cmd_found if File.executable?(File.join(path, cmd))
|
51
|
+
}
|
52
|
+
|
53
|
+
abort "Command not found: #{cmd}"
|
54
|
+
end
|
55
|
+
}
|
56
|
+
|
57
|
+
mysql_user = ask('Please enter the MySQL user name: ') \
|
58
|
+
{ |q| q.default = ENV['USER'] }
|
59
|
+
mysql_pass = ask("Please enter the MySQL password for that user: ") \
|
60
|
+
{ |q| q.echo = false }
|
61
|
+
|
62
|
+
# according to <http://www.adamspiers.org/computing/mysqldiff/#how> MySQL
|
63
|
+
# default permissions allow anyone to create databases beginning with the
|
64
|
+
# prefix 'test_'
|
65
|
+
temp_db = 'flattendb_temp_%d_%d' % [Time.now, $$]
|
66
|
+
temp_user = 'flattendb_user'
|
67
|
+
temp_pass = 'flattendb_pass'
|
68
|
+
|
69
|
+
$dump_file = $infile.sub(/\.(?:sql|dump)$/i, '') << '.xml'
|
70
|
+
abort "Dump file and output file are the same: #{$dump_file} = #{$outfile}" \
|
71
|
+
if File.expand_path($dump_file) == File.expand_path($outfile)
|
72
|
+
|
73
|
+
mysql_args = "--one-database -u#{temp_user} -p#{temp_pass} #{temp_db} < #{$infile}"
|
74
|
+
dump_args = "--xml -u#{temp_user} -p#{temp_pass} #{temp_db} > #{$dump_file}"
|
75
|
+
|
76
|
+
begin
|
77
|
+
mysql = Mysql.real_connect('localhost', mysql_user, mysql_pass)
|
78
|
+
|
79
|
+
mysql.query("CREATE DATABASE #{temp_db}")
|
80
|
+
mysql.query("GRANT ALL ON #{temp_db}.* TO '#{temp_user}'@'localhost' IDENTIFIED BY '#{temp_pass}'")
|
81
|
+
|
82
|
+
system("#{mysql_cmd} #{mysql_args} && #{dump_cmd} #{dump_args}")
|
83
|
+
rescue Mysql::Error => err
|
84
|
+
abort "ERROR #{err.errno} (#{err.sqlstate}): #{err.error}"
|
85
|
+
ensure
|
86
|
+
if mysql
|
87
|
+
mysql.query("REVOKE ALL ON #{temp_db}.* FROM '#{temp_user}'@'localhost'") \
|
88
|
+
if mysql_user == 'root'
|
89
|
+
|
90
|
+
mysql.query("DROP DATABASE IF EXISTS #{temp_db}")
|
91
|
+
mysql.close
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
$infile = $dump_file
|
96
|
+
end
|
97
|
+
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>
|
File without changes
|
@@ -0,0 +1,162 @@
|
|
1
|
+
<?xml version="1.0"?>
|
2
|
+
<mysqldump xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
3
|
+
<database name="ndr">
|
4
|
+
<table_structure name="object">
|
5
|
+
<field Field="ObjID" Type="int(11)" Null="NO" Key="" Default="" Extra="" />
|
6
|
+
<field Field="Bla" Type="int(11)" Null="NO" Key="" Default="" Extra="" />
|
7
|
+
<field Field="Blub" Type="varchar(50)" Null="YES" Key="" Extra="" />
|
8
|
+
<options Name="object" Engine="MyISAM" Version="10" Row_format="Fixed" Collation="utf8_general_ci" Create_options="" Comment="" />
|
9
|
+
</table_structure>
|
10
|
+
<table_data name="object">
|
11
|
+
<row>
|
12
|
+
<field name="ObjID">1</field>
|
13
|
+
<field name="Bla">12</field>
|
14
|
+
<field name="Blub"></field>
|
15
|
+
</row>
|
16
|
+
<row>
|
17
|
+
<field name="ObjID">2</field>
|
18
|
+
<field name="Bla">12</field>
|
19
|
+
<field name="Blub">hi</field>
|
20
|
+
</row>
|
21
|
+
<row>
|
22
|
+
<field name="ObjID">3</field>
|
23
|
+
<field name="Bla">1</field>
|
24
|
+
<field name="Blub">ho</field>
|
25
|
+
</row>
|
26
|
+
</table_data>
|
27
|
+
<table_structure name="fooobject">
|
28
|
+
<field Field="ObjID" Type="int(11)" Null="NO" Key="" Default="" Extra="" />
|
29
|
+
<field Field="attr1ID" Type="int(11)" Null="NO" Key="" Default="" Extra="" />
|
30
|
+
<field Field="attr3ID" Type="int(11)" Null="NO" Key="" Default="" Extra="" />
|
31
|
+
<field Field="Foo" Type="int(11)" Null="NO" Key="" Default="" Extra="" />
|
32
|
+
<options Name="fooobject" Engine="MyISAM" Version="10" Row_format="Fixed" Collation="utf8_general_ci" Create_options="" Comment="" />
|
33
|
+
</table_structure>
|
34
|
+
<table_data name="fooobject">
|
35
|
+
<row>
|
36
|
+
<field name="ObjID">1</field>
|
37
|
+
<field name="attr1ID">1</field>
|
38
|
+
<field name="attr3ID">2</field>
|
39
|
+
<field name="Foo">112</field>
|
40
|
+
</row>
|
41
|
+
<row>
|
42
|
+
<field name="ObjID">2</field>
|
43
|
+
<field name="attr1ID">2</field>
|
44
|
+
<field name="attr3ID">1</field>
|
45
|
+
<field name="Foo">122</field>
|
46
|
+
</row>
|
47
|
+
<row>
|
48
|
+
<field name="ObjID">3</field>
|
49
|
+
<field name="attr1ID">3</field>
|
50
|
+
<field name="attr3ID">3</field>
|
51
|
+
<field name="Foo">111</field>
|
52
|
+
</row>
|
53
|
+
</table_data>
|
54
|
+
<table_structure name="barobject">
|
55
|
+
<field Field="ObjID" Type="int(11)" Null="NO" Key="" Default="" Extra="" />
|
56
|
+
<field Field="attr4ID" Type="int(11)" Null="NO" Key="" Default="" Extra="" />
|
57
|
+
<field Field="Bar" Type="int(11)" Null="NO" Key="" Default="" Extra="" />
|
58
|
+
<options Name="barobject" Engine="MyISAM" Version="10" Row_format="Fixed" Collation="utf8_general_ci" Create_options="" Comment="" />
|
59
|
+
</table_structure>
|
60
|
+
<table_data name="barobject">
|
61
|
+
<row>
|
62
|
+
<field name="ObjID">1</field>
|
63
|
+
<field name="attr4ID">2</field>
|
64
|
+
<field name="Bar">1002</field>
|
65
|
+
</row>
|
66
|
+
<row>
|
67
|
+
<field name="ObjID">2</field>
|
68
|
+
<field name="attr4ID">1</field>
|
69
|
+
<field name="Bar">1200</field>
|
70
|
+
</row>
|
71
|
+
<row>
|
72
|
+
<field name="ObjID">3</field>
|
73
|
+
<field name="attr4ID">3</field>
|
74
|
+
<field name="Bar">1000</field>
|
75
|
+
</row>
|
76
|
+
</table_data>
|
77
|
+
<table_structure name="attr1">
|
78
|
+
<field Field="ObjID" Type="int(11)" Null="NO" Key="" Default="" Extra="" />
|
79
|
+
<field Field="attr1ID" Type="int(11)" Null="NO" Key="" Default="" Extra="" />
|
80
|
+
<field Field="Val" Type="int(11)" Null="NO" Key="" Default="" Extra="" />
|
81
|
+
<options Name="attr1" Engine="MyISAM" Version="10" Row_format="Fixed" Collation="utf8_general_ci" Create_options="" Comment="" />
|
82
|
+
</table_structure>
|
83
|
+
<table_data name="attr1">
|
84
|
+
<row>
|
85
|
+
<field name="ObjID">1</field>
|
86
|
+
<field name="attr1ID">1</field>
|
87
|
+
<field name="Val">3</field>
|
88
|
+
</row>
|
89
|
+
<row>
|
90
|
+
<field name="ObjID">2</field>
|
91
|
+
<field name="attr1ID">2</field>
|
92
|
+
<field name="Val">2</field>
|
93
|
+
</row>
|
94
|
+
<row>
|
95
|
+
<field name="ObjID">3</field>
|
96
|
+
<field name="attr1ID">3</field>
|
97
|
+
<field name="Val">1</field>
|
98
|
+
</row>
|
99
|
+
</table_data>
|
100
|
+
<table_structure name="attr2">
|
101
|
+
<field Field="ObjID" Type="int(11)" Null="NO" Key="" Default="" Extra="" />
|
102
|
+
<field Field="attr2ID" Type="int(11)" Null="NO" Key="" Default="" Extra="" />
|
103
|
+
<field Field="Val" Type="int(11)" Null="NO" Key="" Default="" Extra="" />
|
104
|
+
<options Name="attr2" Engine="MyISAM" Version="10" Row_format="Fixed" Collation="utf8_general_ci" Create_options="" Comment="" />
|
105
|
+
</table_structure>
|
106
|
+
<table_data name="attr2">
|
107
|
+
<row>
|
108
|
+
<field name="ObjID">1</field>
|
109
|
+
<field name="attr2ID">3</field>
|
110
|
+
<field name="Val">4</field>
|
111
|
+
</row>
|
112
|
+
<row>
|
113
|
+
<field name="ObjID">2</field>
|
114
|
+
<field name="attr2ID">2</field>
|
115
|
+
<field name="Val">5</field>
|
116
|
+
</row>
|
117
|
+
<row>
|
118
|
+
<field name="ObjID">3</field>
|
119
|
+
<field name="attr2ID">1</field>
|
120
|
+
<field name="Val">6</field>
|
121
|
+
</row>
|
122
|
+
</table_data>
|
123
|
+
<table_structure name="attr3">
|
124
|
+
<field Field="attr3ID" Type="int(11)" Null="NO" Key="" Default="" Extra="" />
|
125
|
+
<field Field="Val" Type="int(11)" Null="NO" Key="" Default="" Extra="" />
|
126
|
+
<options Name="attr3" Engine="MyISAM" Version="10" Row_format="Fixed" Collation="utf8_general_ci" Create_options="" Comment="" />
|
127
|
+
</table_structure>
|
128
|
+
<table_data name="attr3">
|
129
|
+
<row>
|
130
|
+
<field name="attr3ID">1</field>
|
131
|
+
<field name="Val">0</field>
|
132
|
+
</row>
|
133
|
+
<row>
|
134
|
+
<field name="attr3ID">2</field>
|
135
|
+
<field name="Val">8</field>
|
136
|
+
</row>
|
137
|
+
<row>
|
138
|
+
<field name="attr3ID">3</field>
|
139
|
+
<field name="Val">7</field>
|
140
|
+
</row>
|
141
|
+
</table_data>
|
142
|
+
<table_structure name="attr4">
|
143
|
+
<field Field="attr4ID" Type="int(11)" Null="NO" Key="" Default="" Extra="" />
|
144
|
+
<field Field="Val" Type="int(11)" Null="NO" Key="" Default="" Extra="" />
|
145
|
+
<options Name="attr4" Engine="MyISAM" Version="10" Row_format="Fixed" Collation="utf8_general_ci" Create_options="" Comment="" />
|
146
|
+
</table_structure>
|
147
|
+
<table_data name="attr4">
|
148
|
+
<row>
|
149
|
+
<field name="attr4ID">1</field>
|
150
|
+
<field name="Val">0</field>
|
151
|
+
</row>
|
152
|
+
<row>
|
153
|
+
<field name="attr4ID">2</field>
|
154
|
+
<field name="Val">0</field>
|
155
|
+
</row>
|
156
|
+
<row>
|
157
|
+
<field name="attr4ID">3</field>
|
158
|
+
<field name="Val">9</field>
|
159
|
+
</row>
|
160
|
+
</table_data>
|
161
|
+
</database>
|
162
|
+
</mysqldump>
|
@@ -0,0 +1,99 @@
|
|
1
|
+
#--
|
2
|
+
###############################################################################
|
3
|
+
# #
|
4
|
+
# A component of flattendb, the relational database flattener. #
|
5
|
+
# #
|
6
|
+
# Copyright (C) 2007 University of Cologne, #
|
7
|
+
# Albertus-Magnus-Platz, #
|
8
|
+
# 50932 Cologne, Germany #
|
9
|
+
# #
|
10
|
+
# Authors: #
|
11
|
+
# Jens Wille <jens.wille@uni-koeln.de> #
|
12
|
+
# #
|
13
|
+
# flattendb is free software; you can redistribute it and/or modify it under #
|
14
|
+
# the terms of the GNU General Public License as published by the Free #
|
15
|
+
# Software Foundation; either version 3 of the License, or (at your option) #
|
16
|
+
# any later version. #
|
17
|
+
# #
|
18
|
+
# flattendb is distributed in the hope that it will be useful, but WITHOUT #
|
19
|
+
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
|
20
|
+
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
|
21
|
+
# more details. #
|
22
|
+
# #
|
23
|
+
# You should have received a copy of the GNU General Public License along #
|
24
|
+
# with flattendb. If not, see <http://www.gnu.org/licenses/>. #
|
25
|
+
# #
|
26
|
+
###############################################################################
|
27
|
+
#++
|
28
|
+
|
29
|
+
require 'rubygems'
|
30
|
+
require 'builder'
|
31
|
+
|
32
|
+
module FlattenDB
|
33
|
+
|
34
|
+
class Base
|
35
|
+
|
36
|
+
@types = {}
|
37
|
+
|
38
|
+
BUILDER_OPTIONS = {
|
39
|
+
:xml => {
|
40
|
+
:indent => 2
|
41
|
+
}
|
42
|
+
}
|
43
|
+
|
44
|
+
# cf. <http://www.w3.org/TR/2006/REC-xml-20060816/#NT-Name>
|
45
|
+
ELEMENT_START = %r{^[a-zA-Z_:]}
|
46
|
+
ELEMENT_CHARS = %q{\w:.-}
|
47
|
+
|
48
|
+
class << self
|
49
|
+
|
50
|
+
def types
|
51
|
+
Base.instance_variable_get :@types
|
52
|
+
end
|
53
|
+
|
54
|
+
def [](type)
|
55
|
+
types[type]
|
56
|
+
end
|
57
|
+
|
58
|
+
protected
|
59
|
+
|
60
|
+
def inherited(klass)
|
61
|
+
types[klass.name.split('::')[1..-1].downcase.to_sym] = klass
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
def flatten!(*args)
|
67
|
+
raise NotImplementedError, 'must be defined by sub-class'
|
68
|
+
end
|
69
|
+
|
70
|
+
def to_xml(*args)
|
71
|
+
raise NotImplementedError, 'must be defined by sub-class'
|
72
|
+
end
|
73
|
+
|
74
|
+
private
|
75
|
+
|
76
|
+
def initialize_builder(type, output, builder_options = {})
|
77
|
+
builder_options = (BUILDER_OPTIONS[type] || {}).merge(builder_options)
|
78
|
+
|
79
|
+
@builder = case type
|
80
|
+
when :xml
|
81
|
+
Builder::XmlMarkup.new(builder_options.merge(:target => output))
|
82
|
+
else
|
83
|
+
raise ArgumentError, "builder of type '#{type}' not supported"
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
# mysql:: <http://dev.mysql.com/doc/refman/5.0/en/identifiers.html>
|
88
|
+
def column_to_element(column)
|
89
|
+
element = column.dup
|
90
|
+
|
91
|
+
element.insert(0, '_') unless element =~ ELEMENT_START
|
92
|
+
element.gsub!(/[^#{ELEMENT_CHARS}]/, '')
|
93
|
+
|
94
|
+
element
|
95
|
+
end
|
96
|
+
|
97
|
+
end
|
98
|
+
|
99
|
+
end
|