db_meta 0.4.0 → 0.5.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.
- checksums.yaml +5 -5
- data/.ruby-version +1 -0
- data/.travis.yml +33 -10
- data/.travis/oracle/download.sh +14 -0
- data/.travis/oracle/install.sh +32 -0
- data/.travis/setup_accounts.sh +8 -0
- data/CHANGELOG.md +7 -0
- data/Gemfile +1 -1
- data/Gemfile.lock +45 -16
- data/README.md +1 -0
- data/Rakefile +2 -1
- data/db_meta.gemspec +15 -15
- data/docker/README.md +42 -0
- data/lib/db_meta.rb +10 -14
- data/lib/db_meta/abstract.rb +11 -21
- data/lib/db_meta/constant.rb +23 -25
- data/lib/db_meta/logger.rb +4 -7
- data/lib/db_meta/oracle/base.rb +9 -11
- data/lib/db_meta/oracle/connection.rb +3 -4
- data/lib/db_meta/oracle/helper.rb +7 -9
- data/lib/db_meta/oracle/objects.rb +45 -45
- data/lib/db_meta/oracle/oracle.rb +34 -30
- data/lib/db_meta/oracle/types/column.rb +15 -17
- data/lib/db_meta/oracle/types/comment.rb +2 -5
- data/lib/db_meta/oracle/types/constraint.rb +29 -32
- data/lib/db_meta/oracle/types/constraint_collection.rb +4 -6
- data/lib/db_meta/oracle/types/database_link.rb +4 -5
- data/lib/db_meta/oracle/types/function.rb +4 -5
- data/lib/db_meta/oracle/types/grant.rb +9 -10
- data/lib/db_meta/oracle/types/grant_collection.rb +4 -6
- data/lib/db_meta/oracle/types/index.rb +9 -11
- data/lib/db_meta/oracle/types/job.rb +2 -3
- data/lib/db_meta/oracle/types/lob.rb +2 -3
- data/lib/db_meta/oracle/types/materialized_view.rb +15 -18
- data/lib/db_meta/oracle/types/package.rb +7 -8
- data/lib/db_meta/oracle/types/package_body.rb +2 -3
- data/lib/db_meta/oracle/types/procedure.rb +4 -5
- data/lib/db_meta/oracle/types/queue.rb +24 -26
- data/lib/db_meta/oracle/types/sequence.rb +7 -8
- data/lib/db_meta/oracle/types/synonym.rb +6 -7
- data/lib/db_meta/oracle/types/synonym_collection.rb +4 -6
- data/lib/db_meta/oracle/types/table.rb +31 -34
- data/lib/db_meta/oracle/types/table_data_collection.rb +22 -18
- data/lib/db_meta/oracle/types/trigger.rb +12 -14
- data/lib/db_meta/oracle/types/type.rb +6 -7
- data/lib/db_meta/oracle/types/type_body.rb +2 -3
- data/lib/db_meta/oracle/types/view.rb +12 -14
- data/lib/db_meta/version.rb +1 -1
- metadata +27 -9
@@ -1,11 +1,11 @@
|
|
1
1
|
module DbMeta
|
2
2
|
module Oracle
|
3
3
|
class Table < Base
|
4
|
-
register_type(
|
4
|
+
register_type("TABLE")
|
5
5
|
|
6
6
|
attr_reader :columns, :temporary, :cache, :iot_type, :duration
|
7
7
|
|
8
|
-
def initialize(args={})
|
8
|
+
def initialize(args = {})
|
9
9
|
super(args)
|
10
10
|
|
11
11
|
@comment = nil # table level comment
|
@@ -18,65 +18,63 @@ module DbMeta
|
|
18
18
|
end
|
19
19
|
|
20
20
|
def add_object(object)
|
21
|
-
@indexes << object if object.type ==
|
22
|
-
@constraints << object if object.type ==
|
23
|
-
@triggers << object if object.type ==
|
21
|
+
@indexes << object if object.type == "INDEX"
|
22
|
+
@constraints << object if object.type == "CONSTRAINT"
|
23
|
+
@triggers << object if object.type == "TRIGGER"
|
24
24
|
end
|
25
25
|
|
26
26
|
def fetch
|
27
|
-
@comment = Comment.find(type:
|
27
|
+
@comment = Comment.find(type: "TABLE", name: @name)
|
28
28
|
@columns = Column.all(object_name: @name)
|
29
29
|
|
30
30
|
connection = Connection.instance.get
|
31
31
|
cursor = connection.exec("select temporary, cache, iot_type, duration from user_tables where table_name = '#{@name}'")
|
32
|
-
while row = cursor.fetch
|
33
|
-
@temporary = row[0].to_s.strip ==
|
34
|
-
@cache = row[1].to_s.strip ==
|
32
|
+
while (row = cursor.fetch)
|
33
|
+
@temporary = row[0].to_s.strip == "Y" ? "GLOBAL TEMPORARY" : nil
|
34
|
+
@cache = row[1].to_s.strip == "Y" ? "CACHE" : "NOCACHE"
|
35
35
|
@iot_type = row[2].to_s
|
36
36
|
@duration = row[3].to_s
|
37
37
|
end
|
38
38
|
cursor.close
|
39
|
-
|
40
39
|
rescue
|
41
40
|
connection.logoff
|
42
41
|
end
|
43
42
|
|
44
|
-
|
45
|
-
def extract(args={})
|
43
|
+
def extract(args = {})
|
46
44
|
buffer = [block(@name)]
|
47
45
|
buffer << "CREATE#{" #{@temporary}" if @temporary} TABLE #{@name}"
|
48
|
-
buffer <<
|
46
|
+
buffer << "("
|
49
47
|
|
50
48
|
# add columns
|
51
49
|
@columns.each_with_index do |c, index|
|
52
|
-
buffer << " #{c.extract}#{
|
50
|
+
buffer << " #{c.extract}#{"," if index + 1 < @columns.size}"
|
53
51
|
end
|
54
52
|
|
55
53
|
# Primary key definition must be here for IOT tables
|
56
|
-
if @iot_type ==
|
57
|
-
constraint = @constraints.
|
58
|
-
buffer[-1] +=
|
54
|
+
if @iot_type == "IOT"
|
55
|
+
constraint = @constraints.find { |c| c.constraint_type == "PRIMARY KEY" }
|
56
|
+
buffer[-1] += ","
|
59
57
|
buffer << " CONSTRAINT #{constraint.name}"
|
60
|
-
buffer << " PRIMARY KEY (#{constraint.columns.join(
|
58
|
+
buffer << " PRIMARY KEY (#{constraint.columns.join(", ")})"
|
61
59
|
buffer << " ENABLE VALIDATE"
|
62
60
|
end
|
63
61
|
|
64
|
-
buffer <<
|
62
|
+
buffer << ")"
|
65
63
|
buffer << translate_duration if @duration.size > 0
|
66
64
|
buffer << @cache if @temporary
|
67
65
|
buffer << "ORGANIZATION INDEX" if @iot_type == "IOT"
|
68
|
-
buffer[-1] +=
|
66
|
+
buffer[-1] += ";"
|
69
67
|
buffer << nil
|
70
68
|
|
71
69
|
# table comments
|
72
70
|
if @comment
|
73
|
-
buffer << "COMMENT ON TABLE #{@name} IS '#{@comment.text("'","''")}';"
|
71
|
+
buffer << "COMMENT ON TABLE #{@name} IS '#{@comment.text("'", "''")}';"
|
74
72
|
end
|
75
73
|
|
76
74
|
# table column comments
|
77
75
|
@columns.each do |column|
|
78
76
|
next if column.comment.size == 0
|
79
|
-
buffer << "COMMENT ON COLUMN #{@name}.#{column.name} IS '#{column.comment.gsub("'","''")}';"
|
77
|
+
buffer << "COMMENT ON COLUMN #{@name}.#{column.name} IS '#{column.comment.gsub("'", "''")}';"
|
80
78
|
end
|
81
79
|
|
82
80
|
# indexes
|
@@ -94,15 +92,15 @@ module DbMeta
|
|
94
92
|
# constaints
|
95
93
|
if @constraints.size > 0
|
96
94
|
buffer << block("Constraints", 40)
|
97
|
-
@constraints.sort_by{ |c| [
|
98
|
-
buffer << constraint.extract(args.merge({comment: (constraint.constraint_type ==
|
95
|
+
@constraints.sort_by { |c| [Constraint.sort_value(c.constraint_type), c.name] }.each do |constraint|
|
96
|
+
buffer << constraint.extract(args.merge({comment: (constraint.constraint_type == "FOREIGN KEY")}))
|
99
97
|
end
|
100
98
|
end
|
101
99
|
|
102
100
|
# triggers
|
103
101
|
if @triggers.size > 0
|
104
102
|
buffer << block("Triggers", 40)
|
105
|
-
buffer << @triggers.map{ |o| o.extract(args) }.join("\n")
|
103
|
+
buffer << @triggers.map { |o| o.extract(args) }.join("\n")
|
106
104
|
buffer << nil
|
107
105
|
end
|
108
106
|
|
@@ -113,19 +111,19 @@ module DbMeta
|
|
113
111
|
"DROP #{@type} #{@name} CASCADE CONSTRAINTS PURGE;"
|
114
112
|
end
|
115
113
|
|
116
|
-
def get_core_data_where_clause(id=1000000)
|
114
|
+
def get_core_data_where_clause(id = 1000000)
|
117
115
|
buffer = []
|
118
116
|
@constraints.each do |constraint|
|
119
|
-
if constraint.constraint_type ==
|
117
|
+
if constraint.constraint_type == "PRIMARY KEY"
|
120
118
|
constraint.columns.each do |column|
|
121
119
|
buffer << "#{column} < #{id}"
|
122
120
|
end
|
123
121
|
end
|
124
122
|
end
|
125
123
|
|
126
|
-
return
|
124
|
+
return "" if buffer.size == 0
|
127
125
|
|
128
|
-
|
126
|
+
"where " + buffer.join(" and ")
|
129
127
|
end
|
130
128
|
|
131
129
|
private
|
@@ -133,14 +131,13 @@ module DbMeta
|
|
133
131
|
def translate_duration
|
134
132
|
case @duration
|
135
133
|
when "SYS$TRANSACTION"
|
136
|
-
|
134
|
+
"ON COMMIT DELETE ROWS"
|
137
135
|
when "SYS$SESSION"
|
138
|
-
|
139
|
-
|
140
|
-
|
136
|
+
"ON COMMIT PRESERVE ROWS"
|
137
|
+
else
|
138
|
+
"-- table duration definition [#{@duration}] is unknown and may need code adaptations"
|
141
139
|
end
|
142
140
|
end
|
143
|
-
|
144
141
|
end
|
145
142
|
end
|
146
143
|
end
|
@@ -5,7 +5,7 @@ module DbMeta
|
|
5
5
|
|
6
6
|
attr_reader :name, :type, :status, :extract_type, :collection
|
7
7
|
|
8
|
-
def initialize(args={})
|
8
|
+
def initialize(args = {})
|
9
9
|
@name = args[:name]
|
10
10
|
@type = args[:type]
|
11
11
|
@status = :valid
|
@@ -13,9 +13,10 @@ module DbMeta
|
|
13
13
|
@tables = args[:tables]
|
14
14
|
end
|
15
15
|
|
16
|
-
def extract(args={})
|
16
|
+
def extract(args = {})
|
17
17
|
buffer = [block(@name)]
|
18
18
|
buffer << "set define off;"
|
19
|
+
buffer << "set sqlblanklines on;"
|
19
20
|
buffer << nil
|
20
21
|
|
21
22
|
connection = Connection.instance.get
|
@@ -33,13 +34,13 @@ module DbMeta
|
|
33
34
|
statement = "select * from #{table.name} #{table.get_core_data_where_clause}"
|
34
35
|
cursor = connection.exec(statement)
|
35
36
|
cursor.fetch_hash do |item|
|
36
|
-
buffer << "insert into #{table.name}(#{item.keys.join(
|
37
|
+
buffer << "insert into #{table.name}(#{item.keys.join(", ")}) values(#{format_values(name_type_map, item)});"
|
37
38
|
end
|
38
39
|
cursor.close
|
39
40
|
buffer << nil
|
40
41
|
end
|
41
42
|
|
42
|
-
buffer <<
|
43
|
+
buffer << "commit;"
|
43
44
|
buffer << nil
|
44
45
|
|
45
46
|
buffer.join("\n")
|
@@ -48,7 +49,7 @@ module DbMeta
|
|
48
49
|
end
|
49
50
|
|
50
51
|
def ddl_drop
|
51
|
-
|
52
|
+
"-- will automatically be dropped with table object"
|
52
53
|
end
|
53
54
|
|
54
55
|
def system_object?
|
@@ -61,31 +62,34 @@ module DbMeta
|
|
61
62
|
buffer = []
|
62
63
|
|
63
64
|
item.each_pair do |key, value|
|
64
|
-
if value
|
65
|
-
buffer <<
|
65
|
+
if value.nil?
|
66
|
+
buffer << "NULL"
|
66
67
|
next
|
67
68
|
end
|
68
69
|
|
69
|
-
case name_type_map[key]
|
70
|
+
buffer << case name_type_map[key]
|
70
71
|
when /varchar|char/i
|
71
|
-
|
72
|
+
"'#{value.gsub("'", "''")}'"
|
72
73
|
when /clob/i
|
73
|
-
|
74
|
+
m = []
|
75
|
+
d = value.read
|
76
|
+
d.chars.each_slice(2000).map(&:join).each do |item|
|
77
|
+
m << "to_clob('#{item}')"
|
78
|
+
end
|
79
|
+
m.join(" || ")
|
74
80
|
when /date/i
|
75
|
-
|
81
|
+
"to_date('#{value.strftime("%Y-%m-%d %H:%M:%S")}','YYYY-MM-DD HH24:MI:SS')"
|
76
82
|
when /timestamp/i
|
77
|
-
|
83
|
+
"to_timezone('#{value.strftime("%Y-%m-%d %H:%M:%S %Z")}','YYYY-MM-DD HH24:MI:SS.FF TZD')"
|
78
84
|
when /raw/i
|
79
|
-
|
80
|
-
|
81
|
-
|
85
|
+
"'#{value}'"
|
86
|
+
else
|
87
|
+
value.to_s
|
82
88
|
end
|
83
89
|
end
|
84
90
|
|
85
|
-
buffer.join(
|
91
|
+
buffer.join(", ")
|
86
92
|
end
|
87
|
-
|
88
93
|
end
|
89
|
-
|
90
94
|
end
|
91
95
|
end
|
@@ -1,11 +1,11 @@
|
|
1
1
|
module DbMeta
|
2
2
|
module Oracle
|
3
3
|
class Trigger < Base
|
4
|
-
register_type(
|
4
|
+
register_type("TRIGGER")
|
5
5
|
|
6
6
|
attr_accessor :trigger_type, :trigger_event, :for_each, :table_name, :referencing_names, :description, :tigger_body
|
7
7
|
|
8
|
-
def initialize(args={})
|
8
|
+
def initialize(args = {})
|
9
9
|
super(args)
|
10
10
|
|
11
11
|
@extract_type = :embedded
|
@@ -14,7 +14,7 @@ module DbMeta
|
|
14
14
|
def fetch
|
15
15
|
connection = Connection.instance.get
|
16
16
|
cursor = connection.exec("select trigger_type, triggering_event, table_name, referencing_names, description, trigger_body from user_triggers where trigger_name = '#{@name}'")
|
17
|
-
while row = cursor.fetch
|
17
|
+
while (row = cursor.fetch)
|
18
18
|
@trigger_type = row[0].to_s
|
19
19
|
@triggering_event = row[1].to_s
|
20
20
|
@table_name = row[2].to_s
|
@@ -30,15 +30,15 @@ module DbMeta
|
|
30
30
|
connection.logoff
|
31
31
|
end
|
32
32
|
|
33
|
-
def extract(args={})
|
33
|
+
def extract(args = {})
|
34
34
|
buffer = []
|
35
35
|
buffer << "CREATE OR REPLACE TRIGGER #{@name}"
|
36
36
|
buffer << "#{@trigger_type} #{@triggering_event}"
|
37
37
|
buffer << "ON #{@table_name}"
|
38
|
-
buffer <<
|
39
|
-
buffer <<
|
40
|
-
buffer <<
|
41
|
-
buffer <<
|
38
|
+
buffer << @referencing_names.to_s
|
39
|
+
buffer << @for_each.to_s if @for_each
|
40
|
+
buffer << @trigger_body.strip.to_s if @trigger_body
|
41
|
+
buffer << "/"
|
42
42
|
buffer << nil
|
43
43
|
buffer.join("\n")
|
44
44
|
end
|
@@ -46,19 +46,17 @@ module DbMeta
|
|
46
46
|
private
|
47
47
|
|
48
48
|
def parse_trigger_type
|
49
|
-
@for_each =
|
49
|
+
@for_each = "FOR EACH ROW" if /each row/i.match?(@trigger_type)
|
50
50
|
|
51
51
|
case @trigger_type
|
52
52
|
when /before/i
|
53
|
-
@trigger_type =
|
53
|
+
@trigger_type = "BEFORE"
|
54
54
|
when /after/i
|
55
|
-
@trigger_type =
|
55
|
+
@trigger_type = "AFTER"
|
56
56
|
when /instead of/i
|
57
|
-
@for_each =
|
57
|
+
@for_each = "FOR EACH ROW"
|
58
58
|
end
|
59
|
-
|
60
59
|
end
|
61
|
-
|
62
60
|
end
|
63
61
|
end
|
64
62
|
end
|
@@ -1,21 +1,21 @@
|
|
1
1
|
module DbMeta
|
2
2
|
module Oracle
|
3
3
|
class Type < Base
|
4
|
-
register_type(
|
4
|
+
register_type("TYPE")
|
5
5
|
|
6
6
|
def fetch
|
7
7
|
@source = ""
|
8
8
|
@body = ""
|
9
9
|
connection = Connection.instance.get
|
10
10
|
cursor = connection.exec("select text from user_source where type = 'TYPE' and name = '#{@name}' order by line")
|
11
|
-
while row = cursor.fetch
|
11
|
+
while (row = cursor.fetch)
|
12
12
|
@source << row[0].to_s
|
13
13
|
end
|
14
14
|
cursor.close
|
15
15
|
|
16
16
|
# check for type body
|
17
17
|
cursor = connection.exec("select text from user_source where type = 'TYPE BODY' and name = '#{@name}' order by line")
|
18
|
-
while row = cursor.fetch
|
18
|
+
while (row = cursor.fetch)
|
19
19
|
@body << row[0].to_s
|
20
20
|
end
|
21
21
|
cursor.close
|
@@ -23,19 +23,18 @@ module DbMeta
|
|
23
23
|
connection.logoff
|
24
24
|
end
|
25
25
|
|
26
|
-
def extract(args={})
|
26
|
+
def extract(args = {})
|
27
27
|
buffer = [block(@name)]
|
28
28
|
buffer << "CREATE OR REPLACE #{@source.strip}"
|
29
|
-
buffer <<
|
29
|
+
buffer << "/"
|
30
30
|
buffer << nil
|
31
31
|
if @body.size > 0
|
32
32
|
buffer << "CREATE OR REPLACE #{@body.strip}"
|
33
|
-
buffer <<
|
33
|
+
buffer << "/"
|
34
34
|
buffer << nil
|
35
35
|
end
|
36
36
|
buffer.join("\n")
|
37
37
|
end
|
38
|
-
|
39
38
|
end
|
40
39
|
end
|
41
40
|
end
|
@@ -1,22 +1,22 @@
|
|
1
1
|
module DbMeta
|
2
2
|
module Oracle
|
3
3
|
class View < Base
|
4
|
-
register_type(
|
4
|
+
register_type("VIEW")
|
5
5
|
|
6
|
-
def initialize(args={})
|
6
|
+
def initialize(args = {})
|
7
7
|
super(args)
|
8
8
|
|
9
9
|
@comment = nil # view level comment
|
10
10
|
end
|
11
11
|
|
12
|
-
def fetch(args={})
|
13
|
-
@comment = Comment.find(type:
|
12
|
+
def fetch(args = {})
|
13
|
+
@comment = Comment.find(type: "TABLE", name: @name)
|
14
14
|
@columns = Column.all(object_name: @name)
|
15
15
|
|
16
16
|
@source = ""
|
17
17
|
connection = Connection.instance.get
|
18
18
|
cursor = Connection.instance.get.exec("select text from user_views where view_name = '#{@name}'")
|
19
|
-
while row = cursor.fetch
|
19
|
+
while (row = cursor.fetch)
|
20
20
|
@source << row[0].to_s
|
21
21
|
end
|
22
22
|
cursor.close
|
@@ -24,37 +24,35 @@ module DbMeta
|
|
24
24
|
connection.logoff
|
25
25
|
end
|
26
26
|
|
27
|
-
|
28
|
-
def extract(args={})
|
27
|
+
def extract(args = {})
|
29
28
|
buffer = [block(@name)]
|
30
29
|
buffer << "CREATE OR REPLACE VIEW #{@name}"
|
31
|
-
buffer <<
|
30
|
+
buffer << "("
|
32
31
|
|
33
32
|
# add columns
|
34
33
|
@columns.each_with_index do |c, index|
|
35
|
-
buffer << " #{c.name}#{
|
34
|
+
buffer << " #{c.name}#{"," if index + 1 < @columns.size}"
|
36
35
|
end
|
37
36
|
|
38
|
-
buffer <<
|
37
|
+
buffer << ")"
|
39
38
|
buffer << "AS"
|
40
39
|
buffer << @source.strip
|
41
|
-
buffer[-1] +=
|
40
|
+
buffer[-1] += ";"
|
42
41
|
buffer << nil
|
43
42
|
|
44
43
|
# view comments
|
45
44
|
if @comment
|
46
|
-
buffer << "COMMENT ON VIEW #{@name} IS '#{@comment.text("'","''")}';"
|
45
|
+
buffer << "COMMENT ON VIEW #{@name} IS '#{@comment.text("'", "''")}';"
|
47
46
|
end
|
48
47
|
|
49
48
|
# view column comments
|
50
49
|
@columns.each do |column|
|
51
50
|
next if column.comment.size == 0
|
52
|
-
buffer << "COMMENT ON COLUMN #{@name}.#{column.name} IS '#{column.comment.gsub("'","''")}';"
|
51
|
+
buffer << "COMMENT ON COLUMN #{@name}.#{column.name} IS '#{column.comment.gsub("'", "''")}';"
|
53
52
|
end
|
54
53
|
|
55
54
|
buffer.join("\n")
|
56
55
|
end
|
57
|
-
|
58
56
|
end
|
59
57
|
end
|
60
58
|
end
|