flattendb 0.0.1.96
Sign up to get free protection for your applications and to get access to all the features.
- 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
|