db_meta 0.1.1 → 0.1.3
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 +4 -4
- data/.gitignore +2 -0
- data/CHANGELOG.md +16 -0
- data/Gemfile.lock +4 -4
- data/README.md +52 -2
- data/db_meta.gemspec +1 -1
- data/lib/db_meta/abstract.rb +13 -5
- data/lib/db_meta/constant.rb +45 -0
- data/lib/db_meta/logger.rb +15 -0
- data/lib/db_meta/oracle/base.rb +54 -0
- data/lib/db_meta/oracle/connection.rb +39 -0
- data/lib/db_meta/oracle/helper.rb +37 -0
- data/lib/db_meta/oracle/objects.rb +204 -0
- data/lib/db_meta/oracle/oracle.rb +172 -3
- data/lib/db_meta/oracle/types/column.rb +70 -0
- data/lib/db_meta/oracle/types/comment.rb +20 -0
- data/lib/db_meta/oracle/types/constraint.rb +91 -0
- data/lib/db_meta/oracle/types/constraint_collection.rb +46 -0
- data/lib/db_meta/oracle/types/database_link.rb +33 -0
- data/lib/db_meta/oracle/types/function.rb +30 -0
- data/lib/db_meta/oracle/types/grant.rb +46 -0
- data/lib/db_meta/oracle/types/grant_collection.rb +42 -0
- data/lib/db_meta/oracle/types/index.rb +43 -0
- data/lib/db_meta/oracle/types/lob.rb +13 -0
- data/lib/db_meta/oracle/types/materialized_view.rb +65 -0
- data/lib/db_meta/oracle/types/package.rb +42 -0
- data/lib/db_meta/oracle/types/package_body.rb +13 -0
- data/lib/db_meta/oracle/types/procedure.rb +30 -0
- data/lib/db_meta/oracle/types/sequence.rb +41 -0
- data/lib/db_meta/oracle/types/synonym.rb +42 -0
- data/lib/db_meta/oracle/types/synonym_collection.rb +42 -0
- data/lib/db_meta/oracle/types/table.rb +164 -0
- data/lib/db_meta/oracle/types/table_data_collection.rb +85 -0
- data/lib/db_meta/oracle/types/trigger.rb +64 -0
- data/lib/db_meta/oracle/types/type.rb +41 -0
- data/lib/db_meta/oracle/types/type_body.rb +13 -0
- data/lib/db_meta/oracle/types/view.rb +60 -0
- data/lib/db_meta/version.rb +1 -1
- data/lib/db_meta.rb +18 -6
- data/todo.txt +43 -0
- metadata +36 -5
@@ -1,7 +1,176 @@
|
|
1
|
+
require 'oci8'
|
2
|
+
require 'fileutils'
|
3
|
+
|
4
|
+
require_relative 'connection'
|
5
|
+
require_relative 'helper'
|
6
|
+
require_relative 'base'
|
7
|
+
require_relative 'objects'
|
8
|
+
|
9
|
+
Dir[File.dirname(__FILE__) + '/types/*.rb'].each {|file| require file }
|
10
|
+
|
1
11
|
module DbMeta
|
12
|
+
module Oracle
|
13
|
+
class Oracle < DbMeta::Abstract
|
14
|
+
include Helper
|
2
15
|
|
3
|
-
|
4
|
-
|
5
|
-
|
16
|
+
register_type(:oracle)
|
17
|
+
|
18
|
+
def initialize(args={})
|
19
|
+
super(args)
|
20
|
+
|
21
|
+
Connection.instance.set(@username, @password, @instance, @worker)
|
22
|
+
|
23
|
+
@objects = Objects.new
|
24
|
+
end
|
25
|
+
|
26
|
+
def fetch(args={})
|
27
|
+
@include_pattern = args[:include]
|
28
|
+
@exclude_pattern = args[:exclude]
|
29
|
+
|
30
|
+
Objects.all.each do |object|
|
31
|
+
next if @exclude_pattern =~ object.name if @exclude_pattern
|
32
|
+
next unless @include_pattern =~ object.name if @include_pattern
|
33
|
+
@objects << object
|
34
|
+
end
|
35
|
+
|
36
|
+
# parallel fetching of object details
|
37
|
+
@objects.fetch
|
38
|
+
ensure
|
39
|
+
Connection.instance.disconnect
|
40
|
+
end
|
41
|
+
|
42
|
+
def extract(args={})
|
43
|
+
format = args[:format] || :sql
|
44
|
+
|
45
|
+
# validate args
|
46
|
+
raise "Format [#{format}] is not supported" unless EXTRACT_FORMATS.include?(format)
|
47
|
+
|
48
|
+
remove_folder(@base_folder)
|
49
|
+
create_folder(@base_folder)
|
50
|
+
|
51
|
+
@objects.merge_synonyms
|
52
|
+
@objects.merge_grants
|
53
|
+
@objects.embed_indexes
|
54
|
+
@objects.embed_constraints
|
55
|
+
@objects.merge_constraints
|
56
|
+
@objects.embed_triggers
|
57
|
+
@objects.handle_table_data(args)
|
58
|
+
|
59
|
+
extract_summary
|
60
|
+
extract_create_all(args)
|
61
|
+
extract_drop_all(args)
|
62
|
+
|
63
|
+
# extract all default objects
|
64
|
+
@objects.default_each do |object|
|
65
|
+
folder = File.join(@base_folder, "#{"%02d" % type_sequence(object.type)}_#{object.type}")
|
66
|
+
create_folder(folder)
|
67
|
+
|
68
|
+
filename = File.join(folder, "#{object.name}.#{format.to_s}")
|
69
|
+
write_buffer_to_file(object.extract(args), filename)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
private
|
74
|
+
|
75
|
+
def extract_summary
|
76
|
+
Log.info("Summarizing...")
|
6
77
|
|
78
|
+
buffer = [block("Summary of #{@username}"), nil]
|
79
|
+
|
80
|
+
total = 0
|
81
|
+
@objects.summary_each do |type, count|
|
82
|
+
total += count
|
83
|
+
buffer << "#{SUMMARY_COLUMN_FORMAT_NAME % type.upcase.to_s}#{"%5d" % count} #{"(#{@objects.summary_system_object[type]} system #{pluralize(@objects.summary_system_object[type], 'object')})" if @objects.summary_system_object[type] > 0}"
|
84
|
+
end
|
85
|
+
buffer << nil
|
86
|
+
|
87
|
+
buffer << "#{SUMMARY_COLUMN_FORMAT_NAME % 'Total Objects'}#{"%5d" % total}"
|
88
|
+
buffer << nil
|
89
|
+
buffer << nil
|
90
|
+
|
91
|
+
# invalid objects
|
92
|
+
if @objects.invalids?
|
93
|
+
buffer << 'Invalid/Disabled Objects'
|
94
|
+
@objects.invalid_each do |type, objects|
|
95
|
+
buffer << "#{SUMMARY_COLUMN_FORMAT_NAME % type.upcase.to_s}#{"%5d" % objects.size}"
|
96
|
+
objects.each do |object|
|
97
|
+
buffer << "#{SUMMARY_COLUMN_FORMAT_NAME_RIGHT % object.name}"
|
98
|
+
end
|
99
|
+
buffer << nil
|
100
|
+
end
|
101
|
+
else
|
102
|
+
buffer << 'No invalid/disabled objects'
|
103
|
+
end
|
104
|
+
buffer << nil
|
105
|
+
|
106
|
+
filename = File.join(@base_folder, "#{"%02d" % type_sequence('SUMMARY')}_summary.txt")
|
107
|
+
write_buffer_to_file(buffer, filename)
|
108
|
+
end
|
109
|
+
|
110
|
+
def extract_create_all(args={})
|
111
|
+
Log.info("Extracting create all script...")
|
112
|
+
|
113
|
+
buffer = [block("#{@username} - CREATE ALL")]
|
114
|
+
|
115
|
+
current_type = nil
|
116
|
+
@objects.default_each do |object|
|
117
|
+
if current_type != object.type
|
118
|
+
buffer << nil;
|
119
|
+
buffer << block(object.type, 40)
|
120
|
+
end
|
121
|
+
|
122
|
+
folder = "#{'%02d' % type_sequence(object.type)}_#{object.type}"
|
123
|
+
file = "#{object.name}.sql"
|
124
|
+
buffer << "@#{File.join(folder,file).downcase.gsub(' ', '_')}"
|
125
|
+
current_type = object.type
|
126
|
+
end
|
127
|
+
buffer << nil
|
128
|
+
buffer << compile_invalid_script
|
129
|
+
buffer << nil
|
130
|
+
|
131
|
+
filename = File.join(@base_folder,"#{'%02d' % type_sequence('CREATE')}_create_all.sql")
|
132
|
+
write_buffer_to_file(buffer, filename)
|
133
|
+
end
|
134
|
+
|
135
|
+
def extract_drop_all(args={})
|
136
|
+
Log.info("Extracting drop all script...")
|
137
|
+
|
138
|
+
buffer = [block("#{@username} - DROP ALL")]
|
139
|
+
|
140
|
+
current_type = nil
|
141
|
+
@objects.reverse_default_each do |object|
|
142
|
+
|
143
|
+
if current_type != object.type
|
144
|
+
buffer << nil;
|
145
|
+
buffer << block(object.type, 40)
|
146
|
+
end
|
147
|
+
|
148
|
+
buffer << object.ddl_drop
|
149
|
+
current_type = object.type
|
150
|
+
end
|
151
|
+
buffer << nil
|
152
|
+
|
153
|
+
filename = File.join(@base_folder,"#{'%02d' % type_sequence('DROP')}_drop_all.sql")
|
154
|
+
write_buffer_to_file(buffer, filename)
|
155
|
+
end
|
156
|
+
|
157
|
+
def compile_invalid_script
|
158
|
+
buffer = [block('Compile invalid objects if needed', 40)]
|
159
|
+
buffer << "declare"
|
160
|
+
buffer << "begin"
|
161
|
+
buffer << " for rec in (select object_name, object_type from user_objects where status = 'INVALID') loop"
|
162
|
+
buffer << " if rec.object_type = 'PACKAGE' or rec.object_type = 'PACKAGE BODY' then"
|
163
|
+
buffer << " execute immediate 'alter PACKAGE ' || rec.object_name || ' compile';"
|
164
|
+
buffer << " execute immediate 'alter PACKAGE ' || rec.object_name || ' compile body';"
|
165
|
+
buffer << " else"
|
166
|
+
buffer << " execute immediate 'alter ' || rec.object_type || ' ' || rec.object_name || ' compile';"
|
167
|
+
buffer << " end if;"
|
168
|
+
buffer << " end loop;"
|
169
|
+
buffer << "end;"
|
170
|
+
buffer << "/"
|
171
|
+
buffer.join("\n")
|
172
|
+
end
|
173
|
+
|
174
|
+
end
|
175
|
+
end
|
7
176
|
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
module DbMeta
|
2
|
+
module Oracle
|
3
|
+
class Column
|
4
|
+
|
5
|
+
attr_accessor :name, :type, :data_length, :data_precision, :data_scale, :nullable, :data_default, :comment
|
6
|
+
|
7
|
+
def initialize(args={})
|
8
|
+
end
|
9
|
+
|
10
|
+
def extract
|
11
|
+
buffer = "#{'%-30s' % @name}"
|
12
|
+
buffer << " #{convert_type}"
|
13
|
+
buffer << " DEFAULT #{@data_default}".strip if @data_default.size > 0
|
14
|
+
return buffer
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.all(args={})
|
18
|
+
columns = []
|
19
|
+
connection = Connection.instance.get
|
20
|
+
cursor = connection.exec("select column_name, data_type, data_length, data_precision, data_scale, nullable, data_default from user_tab_columns where table_name = '#{args[:object_name]}' order by column_id")
|
21
|
+
while row = cursor.fetch()
|
22
|
+
column = Column.new(row)
|
23
|
+
column.name = row[0].to_s
|
24
|
+
column.type = row[1].to_s
|
25
|
+
column.data_length = row[2].to_i
|
26
|
+
column.data_precision = row[3].to_i
|
27
|
+
column.data_scale = row[4].to_i
|
28
|
+
column.nullable = row[5].to_s
|
29
|
+
column.data_default = row[6].to_s
|
30
|
+
|
31
|
+
# column comments
|
32
|
+
cursor2 = connection.exec("select comments from user_col_comments where table_name = '#{args[:object_name]}' and column_name = '#{column.name}'")
|
33
|
+
while row2 = cursor2.fetch()
|
34
|
+
column.comment = row2[0].to_s
|
35
|
+
end
|
36
|
+
cursor2.close
|
37
|
+
columns << column
|
38
|
+
|
39
|
+
end
|
40
|
+
cursor.close
|
41
|
+
|
42
|
+
columns
|
43
|
+
rescue
|
44
|
+
connection.loggoff
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def convert_type
|
50
|
+
case @type
|
51
|
+
when 'FLOAT'
|
52
|
+
buffer = "#{@type}"
|
53
|
+
buffer << "(#{@data_precision})" unless @data_precision == 0
|
54
|
+
return buffer
|
55
|
+
when 'NUMBER'
|
56
|
+
buffer = "#{@type}"
|
57
|
+
buffer << "(#{@data_precision}" unless @data_precision == 0
|
58
|
+
buffer << ",#{@data_scale}" unless @data_scale == 0
|
59
|
+
buffer << ")" if buffer.include?("(")
|
60
|
+
return buffer
|
61
|
+
when /CHAR|RAW/
|
62
|
+
return "#{@type}(#{@data_length} BYTE)"
|
63
|
+
else
|
64
|
+
return @type
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module DbMeta
|
2
|
+
module Oracle
|
3
|
+
class Comment
|
4
|
+
attr_reader :text
|
5
|
+
|
6
|
+
def self.find(args={})
|
7
|
+
|
8
|
+
connection = Connection.instance.get
|
9
|
+
cursor = connection.exec("select comments from user_tab_comments where table_type = '#{args[:type]}' and table_name = '#{args[:name]}'")
|
10
|
+
while row = cursor.fetch()
|
11
|
+
@text = row[0]
|
12
|
+
end
|
13
|
+
|
14
|
+
ensure
|
15
|
+
connection.logoff
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
module DbMeta
|
2
|
+
module Oracle
|
3
|
+
class Constraint < Base
|
4
|
+
register_type('CONSTRAINT')
|
5
|
+
|
6
|
+
attr_reader :constraint_type, :table_name, :search_condition, :referential_constraint, :delete_rule, :columns
|
7
|
+
|
8
|
+
def initialize(args={})
|
9
|
+
super(args)
|
10
|
+
|
11
|
+
@extract_type = :embedded
|
12
|
+
@columns = []
|
13
|
+
end
|
14
|
+
|
15
|
+
def fetch(args={})
|
16
|
+
connection = Connection.instance.get
|
17
|
+
cursor = connection.exec("select * from user_constraints where constraint_name = '#{@name}'")
|
18
|
+
cursor.fetch_hash do |item|
|
19
|
+
@constraint_type = translate_constraint_type(item['CONSTRAINT_TYPE'])
|
20
|
+
@extract_type = :merged if @constraint_type == 'FOREIGN KEY'
|
21
|
+
@table_name = item['TABLE_NAME']
|
22
|
+
@search_condition = item['SEARCH_CONDITION']
|
23
|
+
@delete_rule = item['DELETE_RULE']
|
24
|
+
|
25
|
+
if @constraint_type == 'FOREIGN KEY'
|
26
|
+
constraint = Constraint.new('OBJECT_TYPE' => 'CONSTRAINT', 'OBJECT_NAME' => item['R_CONSTRAINT_NAME'])
|
27
|
+
constraint.fetch
|
28
|
+
@referential_constraint = constraint
|
29
|
+
end
|
30
|
+
end
|
31
|
+
cursor.close
|
32
|
+
|
33
|
+
# get affected columns
|
34
|
+
cursor = connection.exec("select * from user_cons_columns where constraint_name = '#{@name}' order by position")
|
35
|
+
cursor.fetch_hash do |item|
|
36
|
+
@columns << item['COLUMN_NAME']
|
37
|
+
end
|
38
|
+
cursor.close
|
39
|
+
|
40
|
+
ensure
|
41
|
+
connection.logoff
|
42
|
+
end
|
43
|
+
|
44
|
+
|
45
|
+
def extract(args={})
|
46
|
+
buffer = []
|
47
|
+
buffer << "ALTER TABLE #{@table_name} ADD ("
|
48
|
+
buffer << " CONSTRAINT #{@name}"
|
49
|
+
|
50
|
+
case @constraint_type
|
51
|
+
when 'CHECK'
|
52
|
+
buffer << " #{@constraint_type} (#{@search_condition})"
|
53
|
+
when 'FOREIGN KEY'
|
54
|
+
buffer << " #{@constraint_type} (#{@columns.join(', ')})"
|
55
|
+
buffer << " REFERENCES #{@referential_constraint.table_name} (#{@referential_constraint.columns.join(', ')})"
|
56
|
+
else
|
57
|
+
buffer << " #{@constraint_type} (#{@columns.join(', ')})"
|
58
|
+
end
|
59
|
+
|
60
|
+
buffer << " ON DELETE CASCADE" if @delete_rule == 'CASCADE'
|
61
|
+
buffer << " ENABLE VALIDATE"
|
62
|
+
buffer << ");"
|
63
|
+
|
64
|
+
(0..buffer.size-1).each { |n| buffer[n] = ('-- ' + buffer[n])} if args[:comment] == true
|
65
|
+
|
66
|
+
buffer << nil
|
67
|
+
buffer.join("\n")
|
68
|
+
end
|
69
|
+
|
70
|
+
def self.sort_value(type)
|
71
|
+
['PRIMARY KEY', 'FOREIGN KEY', 'UNIQUE', 'CHECK'].index(type)
|
72
|
+
end
|
73
|
+
|
74
|
+
private
|
75
|
+
|
76
|
+
def translate_constraint_type(type)
|
77
|
+
case type
|
78
|
+
when 'P'
|
79
|
+
return 'PRIMARY KEY'
|
80
|
+
when 'U'
|
81
|
+
return 'UNIQUE'
|
82
|
+
when 'C'
|
83
|
+
return 'CHECK'
|
84
|
+
when 'R'
|
85
|
+
return 'FOREIGN KEY'
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module DbMeta
|
2
|
+
module Oracle
|
3
|
+
class ConstraintCollection
|
4
|
+
include DbMeta::Oracle::Helper
|
5
|
+
|
6
|
+
attr_reader :name, :type, :status, :extract_type, :collection
|
7
|
+
|
8
|
+
def initialize(args={})
|
9
|
+
@name = args[:name]
|
10
|
+
@type = args[:type]
|
11
|
+
@status = :valid
|
12
|
+
@extract_type = :default
|
13
|
+
@collection = []
|
14
|
+
end
|
15
|
+
|
16
|
+
def empty?
|
17
|
+
@collection.size == 0
|
18
|
+
end
|
19
|
+
|
20
|
+
def <<(object)
|
21
|
+
@collection << object
|
22
|
+
end
|
23
|
+
|
24
|
+
def extract(args={})
|
25
|
+
buffer = [block(@name)]
|
26
|
+
title = nil
|
27
|
+
@collection.sort_by{ |o| [o.table_name, o.name]}.each do |object|
|
28
|
+
buffer << block(object.table_name, 40) if title != object.table_name
|
29
|
+
buffer << object.extract(args)
|
30
|
+
title = object.table_name
|
31
|
+
end
|
32
|
+
buffer.join("\n")
|
33
|
+
end
|
34
|
+
|
35
|
+
def ddl_drop
|
36
|
+
'-- will automatically be dropped with table object'
|
37
|
+
end
|
38
|
+
|
39
|
+
def system_object?
|
40
|
+
false
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module DbMeta
|
2
|
+
module Oracle
|
3
|
+
class DatabaseLink < Base
|
4
|
+
register_type('DATABASE LINK')
|
5
|
+
|
6
|
+
attr_reader :username, :password, :host
|
7
|
+
|
8
|
+
def fetch(args={})
|
9
|
+
connection = Connection.instance.get
|
10
|
+
cursor = connection.exec("select username, password, host from user_db_links where db_link = '#{@name}'")
|
11
|
+
while row = cursor.fetch()
|
12
|
+
@username = row[0].to_s
|
13
|
+
@password = row[1].to_s
|
14
|
+
@host = row[2].to_s
|
15
|
+
end
|
16
|
+
cursor.close
|
17
|
+
ensure
|
18
|
+
connection.logoff
|
19
|
+
end
|
20
|
+
|
21
|
+
def extract(args={})
|
22
|
+
buffer = []
|
23
|
+
buffer << "CREATE DATABASE LINK #{@name}"
|
24
|
+
buffer << " CONNECT TO #{@username}"
|
25
|
+
buffer << " IDENTIFIED BY :1"
|
26
|
+
buffer << " USING '#{@host}';"
|
27
|
+
buffer << nil
|
28
|
+
buffer.join("\n")
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module DbMeta
|
2
|
+
module Oracle
|
3
|
+
class Function < Base
|
4
|
+
register_type('FUNCTION')
|
5
|
+
|
6
|
+
attr_reader :source
|
7
|
+
|
8
|
+
def fetch
|
9
|
+
@source = ""
|
10
|
+
connection = Connection.instance.get
|
11
|
+
cursor = connection.exec("select text from user_source where type = 'FUNCTION' and name = '#{@name}' order by line")
|
12
|
+
while row = cursor.fetch()
|
13
|
+
@source << row[0].to_s
|
14
|
+
end
|
15
|
+
cursor.close
|
16
|
+
ensure
|
17
|
+
connection.logoff
|
18
|
+
end
|
19
|
+
|
20
|
+
def extract(args={})
|
21
|
+
buffer = [block(@name)]
|
22
|
+
buffer << @source.strip
|
23
|
+
buffer << '/'
|
24
|
+
buffer << nil
|
25
|
+
buffer.join("\n")
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module DbMeta
|
2
|
+
module Oracle
|
3
|
+
class Grant < Base
|
4
|
+
register_type('GRANT')
|
5
|
+
|
6
|
+
attr_reader :grantee, :owner, :table_name, :grantor, :privilege, :grantable
|
7
|
+
|
8
|
+
def initialize(args={})
|
9
|
+
super(args)
|
10
|
+
@extract_type = :merged
|
11
|
+
end
|
12
|
+
|
13
|
+
def fetch(args={})
|
14
|
+
# definition is comma seperated in the name to prevent re-fetching table for every grant
|
15
|
+
@grantee, @owner, @table_name, @grantor, @privilege, @grantable = @name.split(',')
|
16
|
+
end
|
17
|
+
|
18
|
+
def extract(args={})
|
19
|
+
buffer = ""
|
20
|
+
buffer << ( '%-30s' % "-- granted via #{@grantor}: ") if external_grant?
|
21
|
+
buffer << "GRANT #{"%-18s" % @privilege} ON #{"%-32s" % @table_name} TO #{@grantee}"
|
22
|
+
buffer << " WITH GRANT OPTION" if @grantable == 'YES'
|
23
|
+
buffer << ";"
|
24
|
+
buffer
|
25
|
+
end
|
26
|
+
|
27
|
+
def ddl_drop
|
28
|
+
buffer = ""
|
29
|
+
|
30
|
+
buffer << ( '%-30s' % "-- granted via #{@grantor}: ") if external_grant?
|
31
|
+
buffer << "REVOKE #{"%-18s" % @privilege} ON #{"%-32s" % @table_name} FROM #{@grantee};"
|
32
|
+
buffer
|
33
|
+
end
|
34
|
+
|
35
|
+
def external_grant?
|
36
|
+
@grantee == Connection.instance.username.upcase
|
37
|
+
end
|
38
|
+
|
39
|
+
def sort_value
|
40
|
+
return ["2", @grantor, @privilege, @table_name] if external_grant?
|
41
|
+
return ["1", @grantee, @privilege, @table_name]
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module DbMeta
|
2
|
+
module Oracle
|
3
|
+
class GrantCollection
|
4
|
+
include DbMeta::Oracle::Helper
|
5
|
+
|
6
|
+
attr_reader :name, :type, :status, :extract_type, :collection
|
7
|
+
|
8
|
+
def initialize(args={})
|
9
|
+
@name = args[:name]
|
10
|
+
@type = args[:type]
|
11
|
+
@status = :valid
|
12
|
+
@extract_type = :default
|
13
|
+
@collection = []
|
14
|
+
end
|
15
|
+
|
16
|
+
def empty?
|
17
|
+
@collection.size == 0
|
18
|
+
end
|
19
|
+
|
20
|
+
def <<(object)
|
21
|
+
@collection << object
|
22
|
+
end
|
23
|
+
|
24
|
+
def extract(args={})
|
25
|
+
buffer = [block(@name)]
|
26
|
+
buffer << @collection.map{ |o| o.extract(args) }
|
27
|
+
buffer << nil
|
28
|
+
buffer.join("\n")
|
29
|
+
end
|
30
|
+
|
31
|
+
def ddl_drop
|
32
|
+
@collection.reverse_each.map{ |o| o.ddl_drop }.join("\n")
|
33
|
+
end
|
34
|
+
|
35
|
+
def system_object?
|
36
|
+
false
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module DbMeta
|
2
|
+
module Oracle
|
3
|
+
class Index < Base
|
4
|
+
register_type('INDEX')
|
5
|
+
|
6
|
+
attr_reader :index_type, :table_name, :uniqueness, :tablespace
|
7
|
+
|
8
|
+
def initialize(args={})
|
9
|
+
super(args)
|
10
|
+
|
11
|
+
@extract_type = :embedded
|
12
|
+
@columns = []
|
13
|
+
end
|
14
|
+
|
15
|
+
def fetch(args={})
|
16
|
+
connection = Connection.instance.get
|
17
|
+
cursor = connection.exec("select index_type, table_name, uniqueness, tablespace_name from user_indexes where index_name = '#{@name}'")
|
18
|
+
while row = cursor.fetch()
|
19
|
+
@index_type = row[0].to_s
|
20
|
+
@table_name = row[1].to_s
|
21
|
+
@uniqueness = row[2].to_s
|
22
|
+
@tablespace = row[3].to_s
|
23
|
+
end
|
24
|
+
cursor.close
|
25
|
+
|
26
|
+
# involved columns
|
27
|
+
cursor = connection.exec("select column_name from user_ind_columns where index_name = '#{@name}' order by column_position")
|
28
|
+
while row = cursor.fetch()
|
29
|
+
@columns << row[0].to_s
|
30
|
+
end
|
31
|
+
cursor.close
|
32
|
+
|
33
|
+
ensure
|
34
|
+
connection.logoff
|
35
|
+
end
|
36
|
+
|
37
|
+
def extract(args={})
|
38
|
+
"CREATE#{ @uniqueness == 'UNIQUE' ? ' UNIQUE' : nil } INDEX #{@name} ON #{@table_name}(#{@columns.join(', ')});"
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
module DbMeta
|
2
|
+
module Oracle
|
3
|
+
class MaterializedView < Base
|
4
|
+
register_type('MATERIALIZED VIEW')
|
5
|
+
|
6
|
+
attr_reader :query, :build_mode, :refresh_mode, :refresh_method, :interval, :next_date, :rewrite_enabled, :columns
|
7
|
+
|
8
|
+
def fetch(args={})
|
9
|
+
connection = Connection.instance.get
|
10
|
+
|
11
|
+
cursor = connection.exec("select * from user_mviews where mview_name = '#{@name}'")
|
12
|
+
cursor.fetch_hash do |item|
|
13
|
+
@query = item['QUERY']
|
14
|
+
@build_mode = item['BUILD_MODE']
|
15
|
+
@refresh_mode = item['REFRESH_MODE']
|
16
|
+
@refresh_method = item['REFRESH_METHOD']
|
17
|
+
@rewrite_enabled = item['REWRITE_ENABLED'] == 'Y' ? 'ENABLE' : 'DISABLE'
|
18
|
+
end
|
19
|
+
cursor.close
|
20
|
+
|
21
|
+
cursor = connection.exec("select * from user_refresh where rname = '#{@name}'")
|
22
|
+
cursor.fetch_hash do |item|
|
23
|
+
@interval = item['INTERVAL']
|
24
|
+
@next_date = item['NEXT_DATE']
|
25
|
+
end
|
26
|
+
cursor.close
|
27
|
+
|
28
|
+
@columns = Column.all(object_name: @name)
|
29
|
+
|
30
|
+
# comments on materialized views
|
31
|
+
cursor = connection.exec("select * from user_mview_comments where mview_name = '#{@name}'")
|
32
|
+
cursor.fetch_hash do |item|
|
33
|
+
@comment = item['COMMENTS']
|
34
|
+
end
|
35
|
+
cursor.close
|
36
|
+
|
37
|
+
ensure
|
38
|
+
connection.logoff
|
39
|
+
end
|
40
|
+
|
41
|
+
|
42
|
+
def extract(args={})
|
43
|
+
buffer = [block(@name)]
|
44
|
+
buffer << "CREATE MATERIALIZED VIEW #{@name}(#{@columns.map{ |c| c.name}.join(', ')})"
|
45
|
+
buffer << "BUILD #{@build_mode}"
|
46
|
+
buffer << "REFRESH #{@refresh_method} ON #{@refresh_mode}"
|
47
|
+
buffer << "START WITH TO_DATE('#{@next_date}') NEXT #{@interval}" if @interval
|
48
|
+
buffer << "#{@rewrite_enabled} QUERY REWRITE"
|
49
|
+
buffer << 'AS'
|
50
|
+
buffer << @query
|
51
|
+
buffer << '/'
|
52
|
+
buffer << nil
|
53
|
+
|
54
|
+
# materialized view comments
|
55
|
+
if @comment
|
56
|
+
buffer << "COMMENT ON MATERIALIZED VIEW #{@name} IS '#{@comment.gsub("'","''")}';"
|
57
|
+
buffer << nil
|
58
|
+
end
|
59
|
+
|
60
|
+
buffer.join("\n")
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|