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
@@ -0,0 +1,42 @@
|
|
1
|
+
module DbMeta
|
2
|
+
module Oracle
|
3
|
+
class Package < Base
|
4
|
+
register_type('PACKAGE')
|
5
|
+
|
6
|
+
attr_reader :header, :body
|
7
|
+
|
8
|
+
def fetch
|
9
|
+
@header = ""
|
10
|
+
cursor = Connection.instance.get.exec("select text from user_source where type = 'PACKAGE' and name = '#{@name}' order by line")
|
11
|
+
while row = cursor.fetch()
|
12
|
+
@header << row[0].to_s
|
13
|
+
end
|
14
|
+
cursor.close
|
15
|
+
|
16
|
+
@body = ""
|
17
|
+
connection = Connection.instance.get
|
18
|
+
cursor = connection.exec("select text from user_source where type = 'PACKAGE BODY' and name = '#{@name}' order by line")
|
19
|
+
while row = cursor.fetch()
|
20
|
+
@body << row[0].to_s
|
21
|
+
end
|
22
|
+
cursor.close
|
23
|
+
ensure
|
24
|
+
connection.logoff
|
25
|
+
end
|
26
|
+
|
27
|
+
def extract(args={})
|
28
|
+
buffer = [block(@name)]
|
29
|
+
buffer << "CREATE OR REPLACE #{@header.strip}"
|
30
|
+
buffer << '/'
|
31
|
+
buffer << nil
|
32
|
+
|
33
|
+
buffer << "CREATE OR REPLACE #{@body.strip}"
|
34
|
+
buffer << '/'
|
35
|
+
buffer << nil
|
36
|
+
|
37
|
+
buffer.join("\n")
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module DbMeta
|
2
|
+
module Oracle
|
3
|
+
class Procedure < Base
|
4
|
+
register_type('PROCEDURE')
|
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 = 'PROCEDURE' 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,41 @@
|
|
1
|
+
module DbMeta
|
2
|
+
module Oracle
|
3
|
+
class Sequence < Base
|
4
|
+
register_type('SEQUENCE')
|
5
|
+
|
6
|
+
attr_reader :min_value, :max_value, :increment_by, :cycle_flag, :order_flag, :cache_size, :last_number
|
7
|
+
|
8
|
+
def fetch
|
9
|
+
connection = Connection.instance.get
|
10
|
+
cursor = connection.exec("select to_char(min_value), to_char(max_value), to_char(increment_by), cycle_flag, order_flag, to_char(cache_size), to_char(last_number) from user_sequences where sequence_name = '#{@name}'")
|
11
|
+
while row = cursor.fetch()
|
12
|
+
@min_value = row[0].to_i
|
13
|
+
@max_value = row[1].to_i
|
14
|
+
@increment_by = row[2].to_i
|
15
|
+
@cycle_flag = row[3].to_s
|
16
|
+
@order_flag = row[4].to_s
|
17
|
+
@cache_size = row[5].to_i
|
18
|
+
@last_number = row[6].to_i
|
19
|
+
end
|
20
|
+
cursor.close
|
21
|
+
ensure
|
22
|
+
connection.logoff
|
23
|
+
end
|
24
|
+
|
25
|
+
def extract(args={})
|
26
|
+
buffer = [block(@name)]
|
27
|
+
buffer << "CREATE SEQUENCE #{@name}"
|
28
|
+
buffer << " START WITH #{@last_number}"
|
29
|
+
buffer << " MAXVALUE #{@max_value}"
|
30
|
+
buffer << " MINVALUE #{@min_value}"
|
31
|
+
buffer << (@cycle_flag == 'N' ? ' NOCYCLE' : ' CYCLE')
|
32
|
+
buffer << (@cache_size == 0 ? ' NOCACHE' : " CACHE #{@cache_size}")
|
33
|
+
buffer << (@order_flag == 'N' ? ' NOORDER' : ' ORDER')
|
34
|
+
buffer << ';'
|
35
|
+
buffer << nil
|
36
|
+
buffer.join("\n")
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module DbMeta
|
2
|
+
module Oracle
|
3
|
+
class Synonym < Base
|
4
|
+
register_type('SYNONYM')
|
5
|
+
|
6
|
+
attr_reader :table_owner, :table_name, :db_link
|
7
|
+
|
8
|
+
def initialize(args={})
|
9
|
+
super(args)
|
10
|
+
|
11
|
+
@extract_type = :merged
|
12
|
+
end
|
13
|
+
|
14
|
+
def fetch(args={})
|
15
|
+
connection = Connection.instance.get
|
16
|
+
cursor = connection.exec("select table_owner, table_name, db_link from user_synonyms where synonym_name = '#{@name}'")
|
17
|
+
while row = cursor.fetch()
|
18
|
+
@table_owner = row[0].to_s
|
19
|
+
@table_name = row[1].to_s
|
20
|
+
@db_link = row[2].to_s
|
21
|
+
end
|
22
|
+
cursor.close
|
23
|
+
ensure
|
24
|
+
connection.logoff
|
25
|
+
end
|
26
|
+
|
27
|
+
def extract(args={})
|
28
|
+
line = ""
|
29
|
+
line << "CREATE OR REPALCE SYNONYM #{@name} FOR "
|
30
|
+
line << "#{@table_owner}." if @table_owner.size > 0
|
31
|
+
line << "#{@table_name}"
|
32
|
+
line << "@#{@db_link}" if @db_link.size > 0
|
33
|
+
line << ";"
|
34
|
+
|
35
|
+
buffer = []
|
36
|
+
buffer << line
|
37
|
+
buffer.join("\n")
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module DbMeta
|
2
|
+
module Oracle
|
3
|
+
class SynonymCollection
|
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,164 @@
|
|
1
|
+
module DbMeta
|
2
|
+
module Oracle
|
3
|
+
class Table < Base
|
4
|
+
register_type('TABLE')
|
5
|
+
|
6
|
+
attr_reader :columns, :temporary, :cache, :iot_type, :duration
|
7
|
+
|
8
|
+
def initialize(args={})
|
9
|
+
super(args)
|
10
|
+
|
11
|
+
@comment = nil # table level comment
|
12
|
+
|
13
|
+
@comment = nil
|
14
|
+
@columns = []
|
15
|
+
@indexes = []
|
16
|
+
@constraints = []
|
17
|
+
@triggers = []
|
18
|
+
end
|
19
|
+
|
20
|
+
def add_object(object)
|
21
|
+
@indexes << object if object.type == 'INDEX'
|
22
|
+
@constraints << object if object.type == 'CONSTRAINT'
|
23
|
+
@triggers << object if object.type == 'TRIGGER'
|
24
|
+
end
|
25
|
+
|
26
|
+
def fetch
|
27
|
+
@comment = Comment.find(type: 'TABLE', name: @name)
|
28
|
+
@columns = Column.all(object_name: @name)
|
29
|
+
|
30
|
+
connection = Connection.instance.get
|
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 == 'Y' ? 'GLOBAL TEMPORARY' : nil
|
34
|
+
@cache = row[1].to_s.strip == 'Y' ? 'CACHE' : 'NOCACHE'
|
35
|
+
@iot_type = row[2].to_s
|
36
|
+
@duration = row[3].to_s
|
37
|
+
end
|
38
|
+
cursor.close
|
39
|
+
|
40
|
+
rescue
|
41
|
+
connection.logoff
|
42
|
+
end
|
43
|
+
|
44
|
+
|
45
|
+
def extract(args={})
|
46
|
+
buffer = [block(@name)]
|
47
|
+
buffer << "CREATE#{" #{@temporary}" if @temporary} TABLE #{@name}"
|
48
|
+
buffer << '('
|
49
|
+
|
50
|
+
# add columns
|
51
|
+
@columns.each_with_index do |c, index|
|
52
|
+
buffer << " #{c.extract}#{',' if index+1 < @columns.size}"
|
53
|
+
end
|
54
|
+
|
55
|
+
# Primary key definition must be here for IOT tables
|
56
|
+
if @iot_type == 'IOT'
|
57
|
+
constraint = @constraints.select{ |c| c.constraint_type == 'PRIMARY KEY'}[0]
|
58
|
+
buffer[-1] += ','
|
59
|
+
buffer << " CONSTRAINT #{constraint.name}"
|
60
|
+
buffer << " PRIMARY KEY (#{constraint.columns.join(', ')})"
|
61
|
+
buffer << " ENABLE VALIDATE"
|
62
|
+
end
|
63
|
+
|
64
|
+
buffer << ')'
|
65
|
+
buffer << translate_duration if @duration.size > 0
|
66
|
+
buffer << @cache if @temporary
|
67
|
+
buffer << "ORGANIZATION INDEX" if @iot_type == "IOT"
|
68
|
+
buffer[-1] += ';'
|
69
|
+
buffer << nil
|
70
|
+
|
71
|
+
# table comments
|
72
|
+
if @comment
|
73
|
+
buffer << "COMMENT ON TABLE #{@name} IS '#{@comment.text("'","''")}';"
|
74
|
+
end
|
75
|
+
|
76
|
+
# table column comments
|
77
|
+
@columns.each do |column|
|
78
|
+
next if column.comment.size == 0
|
79
|
+
buffer << "COMMENT ON COLUMN #{@name}.#{column.name} IS '#{column.comment.gsub("'","''")}';"
|
80
|
+
end
|
81
|
+
|
82
|
+
# indexes
|
83
|
+
if @indexes.size > 0
|
84
|
+
buffer << block("Indexes", 40)
|
85
|
+
@indexes.each do |index|
|
86
|
+
line = ""
|
87
|
+
line << "-- System Index: " if index.system_object? || @iot_type == "IOT"
|
88
|
+
line << index.extract(args)
|
89
|
+
buffer << line
|
90
|
+
end
|
91
|
+
buffer << nil
|
92
|
+
end
|
93
|
+
|
94
|
+
# constaints
|
95
|
+
if @constraints.size > 0
|
96
|
+
buffer << block("Constraints", 40)
|
97
|
+
@constraints.sort_by{ |c| [ Constraint.sort_value(c.constraint_type), c.name] }.each do |constraint|
|
98
|
+
buffer << constraint.extract(args.merge({comment: (constraint.constraint_type == 'FOREIGN KEY')}))
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
# triggers
|
103
|
+
if @triggers.size > 0
|
104
|
+
buffer << block("Triggers", 40)
|
105
|
+
buffer << @triggers.map{ |o| o.extract(args) }.join("\n")
|
106
|
+
buffer << nil
|
107
|
+
end
|
108
|
+
|
109
|
+
buffer.join("\n")
|
110
|
+
end
|
111
|
+
|
112
|
+
def ddl_drop
|
113
|
+
"DROP #{@type} #{@name} CASCADE CONSTRAINTS PURGE;"
|
114
|
+
end
|
115
|
+
|
116
|
+
def system_object?
|
117
|
+
is_system_object = super
|
118
|
+
return is_system_object if is_system_object
|
119
|
+
|
120
|
+
# check for tables created based on materialized views
|
121
|
+
n = 0
|
122
|
+
connection = Connection.instance.get
|
123
|
+
cursor = connection.exec("select count(*) as n from user_mviews where mview_name = '#{@name}'")
|
124
|
+
cursor.fetch_hash do |item|
|
125
|
+
n = item['N']
|
126
|
+
end
|
127
|
+
cursor.close
|
128
|
+
|
129
|
+
return n == 1
|
130
|
+
ensure
|
131
|
+
connection.logoff if connection
|
132
|
+
end
|
133
|
+
|
134
|
+
def get_core_data_where_clause(id=1000000)
|
135
|
+
buffer = []
|
136
|
+
@constraints.each do |constraint|
|
137
|
+
if constraint.constraint_type == 'PRIMARY KEY'
|
138
|
+
constraint.columns.each do |column|
|
139
|
+
buffer << "#{column} < #{id}"
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
return '' if buffer.size == 0
|
145
|
+
buffer.insert(0, 'where')
|
146
|
+
buffer.join(' ')
|
147
|
+
end
|
148
|
+
|
149
|
+
private
|
150
|
+
|
151
|
+
def translate_duration
|
152
|
+
case @duration
|
153
|
+
when "SYS$TRANSACTION"
|
154
|
+
return "ON COMMIT DELETE ROWS"
|
155
|
+
when "SYS$SESSION"
|
156
|
+
return "ON COMMIT PRESERVE ROWS"
|
157
|
+
else
|
158
|
+
return "-- table duration definition [#{@duration}] is unknown and may need code adaptations"
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
module DbMeta
|
2
|
+
module Oracle
|
3
|
+
class TableDataCollection
|
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
|
+
@tables = args[:tables]
|
14
|
+
end
|
15
|
+
|
16
|
+
def extract(args={})
|
17
|
+
buffer = [block(@name)]
|
18
|
+
buffer << nil
|
19
|
+
|
20
|
+
connection = Connection.instance.get
|
21
|
+
|
22
|
+
@tables.each do |table|
|
23
|
+
buffer << block(table.name, 40)
|
24
|
+
|
25
|
+
name_type_map = {}
|
26
|
+
table.columns.each do |column|
|
27
|
+
name_type_map[column.name] = column.type
|
28
|
+
end
|
29
|
+
|
30
|
+
cursor = connection.exec("select * from #{table.name} #{table.get_core_data_where_clause}")
|
31
|
+
cursor.fetch_hash do |item|
|
32
|
+
buffer << "insert into #{table.name}(#{item.keys.join(', ')}) values(#{format_values(name_type_map, item)});"
|
33
|
+
end
|
34
|
+
cursor.close
|
35
|
+
buffer << nil
|
36
|
+
end
|
37
|
+
|
38
|
+
buffer << 'commit;'
|
39
|
+
buffer << nil
|
40
|
+
|
41
|
+
buffer.join("\n")
|
42
|
+
ensure
|
43
|
+
connection.logoff
|
44
|
+
end
|
45
|
+
|
46
|
+
def ddl_drop
|
47
|
+
'-- will automatically be dropped with table object'
|
48
|
+
end
|
49
|
+
|
50
|
+
def system_object?
|
51
|
+
false
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
def format_values(name_type_map, item)
|
57
|
+
buffer = []
|
58
|
+
|
59
|
+
item.each_pair do |key, value|
|
60
|
+
if value == nil
|
61
|
+
buffer << 'NULL'
|
62
|
+
next
|
63
|
+
end
|
64
|
+
|
65
|
+
case name_type_map[key]
|
66
|
+
when /varchar|char/i
|
67
|
+
buffer << "'#{value.gsub("'","''")}'"
|
68
|
+
when /clob/i
|
69
|
+
buffer << "'#{item.read}'"
|
70
|
+
when /date/i
|
71
|
+
buffer << "to_date('#{value.strftime("%Y-%m-%d %H:%M:%S")}','YYYY-MM-DD HH24:MI:SS')"
|
72
|
+
when /timestamp/i
|
73
|
+
buffer << "to_timezone('#{value.strftime("%Y-%m-%d %H:%M:%S %Z")}','YYYY-MM-DD HH24:MI:SS.FF TZD')"
|
74
|
+
else
|
75
|
+
buffer << value.to_s
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
buffer.join(', ')
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
module DbMeta
|
2
|
+
module Oracle
|
3
|
+
class Trigger < Base
|
4
|
+
register_type('TRIGGER')
|
5
|
+
|
6
|
+
attr_accessor :trigger_type, :trigger_event, :for_each, :table_name, :referencing_names, :description, :tigger_body
|
7
|
+
|
8
|
+
def initialize(args={})
|
9
|
+
super(args)
|
10
|
+
|
11
|
+
@extract_type = :embedded
|
12
|
+
end
|
13
|
+
|
14
|
+
def fetch
|
15
|
+
connection = Connection.instance.get
|
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()
|
18
|
+
@trigger_type = row[0].to_s
|
19
|
+
@triggering_event = row[1].to_s
|
20
|
+
@table_name = row[2].to_s
|
21
|
+
@referencing_names = row[3].to_s
|
22
|
+
@description = row[4].to_s
|
23
|
+
@trigger_body = row[5].to_s
|
24
|
+
end
|
25
|
+
|
26
|
+
parse_trigger_type
|
27
|
+
|
28
|
+
cursor.close
|
29
|
+
ensure
|
30
|
+
connection.logoff
|
31
|
+
end
|
32
|
+
|
33
|
+
def extract(args={})
|
34
|
+
buffer = []
|
35
|
+
buffer << "CREATE OR REPLACE TRIGGER #{@name}"
|
36
|
+
buffer << "#{@trigger_type} #{@triggering_event}"
|
37
|
+
buffer << "ON #{@table_name}"
|
38
|
+
buffer << "#{@referencing_names}"
|
39
|
+
buffer << "#{@for_each}" if @for_each
|
40
|
+
buffer << "#{@trigger_body.strip}"
|
41
|
+
buffer << '/'
|
42
|
+
buffer << nil
|
43
|
+
buffer.join("\n")
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def parse_trigger_type
|
49
|
+
@for_each = 'FOR EACH ROW' if @trigger_type =~ /each row/i
|
50
|
+
|
51
|
+
case @trigger_type
|
52
|
+
when /before/i
|
53
|
+
@trigger_type = 'BEFORE'
|
54
|
+
when /after/i
|
55
|
+
@trigger_type = 'AFTER'
|
56
|
+
when /instead of/i
|
57
|
+
@for_each = 'FOR EACH ROW'
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module DbMeta
|
2
|
+
module Oracle
|
3
|
+
class Type < Base
|
4
|
+
register_type('TYPE')
|
5
|
+
|
6
|
+
def fetch
|
7
|
+
@source = ""
|
8
|
+
@body = ""
|
9
|
+
connection = Connection.instance.get
|
10
|
+
cursor = connection.exec("select text from user_source where type = 'TYPE' and name = '#{@name}' order by line")
|
11
|
+
while row = cursor.fetch()
|
12
|
+
@source << row[0].to_s
|
13
|
+
end
|
14
|
+
cursor.close
|
15
|
+
|
16
|
+
# check for type body
|
17
|
+
cursor = connection.exec("select text from user_source where type = 'TYPE BODY' and name = '#{@name}' order by line")
|
18
|
+
while row = cursor.fetch()
|
19
|
+
@body << row[0].to_s
|
20
|
+
end
|
21
|
+
cursor.close
|
22
|
+
ensure
|
23
|
+
connection.logoff
|
24
|
+
end
|
25
|
+
|
26
|
+
def extract(args={})
|
27
|
+
buffer = [block(@name)]
|
28
|
+
buffer << "CREATE OR REPLACE #{@source.strip}"
|
29
|
+
buffer << '/'
|
30
|
+
buffer << nil
|
31
|
+
if @body.size > 0
|
32
|
+
buffer << "CREATE OR REPLACE #{@body.strip}"
|
33
|
+
buffer << '/'
|
34
|
+
buffer << nil
|
35
|
+
end
|
36
|
+
buffer.join("\n")
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module DbMeta
|
2
|
+
module Oracle
|
3
|
+
class View < Base
|
4
|
+
register_type('VIEW')
|
5
|
+
|
6
|
+
def initialize(args={})
|
7
|
+
super(args)
|
8
|
+
|
9
|
+
@comment = nil # view level comment
|
10
|
+
end
|
11
|
+
|
12
|
+
def fetch(args={})
|
13
|
+
@comment = Comment.find(type: 'TABLE', name: @name)
|
14
|
+
@columns = Column.all(object_name: @name)
|
15
|
+
|
16
|
+
@source = ""
|
17
|
+
connection = Connection.instance.get
|
18
|
+
cursor = Connection.instance.get.exec("select text from user_views where view_name = '#{@name}'")
|
19
|
+
while row = cursor.fetch()
|
20
|
+
@source << row[0].to_s
|
21
|
+
end
|
22
|
+
cursor.close
|
23
|
+
ensure
|
24
|
+
connection.logoff
|
25
|
+
end
|
26
|
+
|
27
|
+
|
28
|
+
def extract(args={})
|
29
|
+
buffer = [block(@name)]
|
30
|
+
buffer << "CREATE OR REPLACE VIEW #{@name}"
|
31
|
+
buffer << '('
|
32
|
+
|
33
|
+
# add columns
|
34
|
+
@columns.each_with_index do |c, index|
|
35
|
+
buffer << " #{c.name}#{',' if index+1 < @columns.size}"
|
36
|
+
end
|
37
|
+
|
38
|
+
buffer << ')'
|
39
|
+
buffer << "AS"
|
40
|
+
buffer << @source.strip
|
41
|
+
buffer[-1] += ';'
|
42
|
+
buffer << nil
|
43
|
+
|
44
|
+
# view comments
|
45
|
+
if @comment
|
46
|
+
buffer << "COMMENT ON VIEW #{@name} IS '#{@comment.text("'","''")}';"
|
47
|
+
end
|
48
|
+
|
49
|
+
# view column comments
|
50
|
+
@columns.each do |column|
|
51
|
+
next if column.comment.size == 0
|
52
|
+
buffer << "COMMENT ON COLUMN #{@name}.#{column.name} IS '#{column.comment.gsub("'","''")}';"
|
53
|
+
end
|
54
|
+
|
55
|
+
buffer.join("\n")
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
data/lib/db_meta/version.rb
CHANGED
data/lib/db_meta.rb
CHANGED
@@ -1,26 +1,38 @@
|
|
1
1
|
require_relative 'db_meta/version'
|
2
|
-
require_relative 'db_meta/
|
2
|
+
require_relative 'db_meta/constant'
|
3
|
+
require_relative 'db_meta/logger'
|
3
4
|
|
5
|
+
require_relative 'db_meta/abstract'
|
4
6
|
require_relative 'db_meta/oracle/oracle'
|
5
7
|
|
8
|
+
Log = Logger.new(STDOUT)
|
9
|
+
|
6
10
|
module DbMeta
|
7
11
|
|
8
12
|
DATABASE_TYPES = [:oracle]
|
9
13
|
|
10
14
|
class DbMeta
|
11
15
|
|
12
|
-
def initialize(
|
16
|
+
def initialize(args={})
|
13
17
|
@database_type = args[:database_type] || DATABASE_TYPES[0]
|
14
18
|
raise "allowed database types are [#{DATABASE_TYPES.join(', ')}], but provided was [#{@database_type}]" unless DATABASE_TYPES.include?(@database_type)
|
15
19
|
@abstract = Abstract.from_type(@database_type, args)
|
16
20
|
end
|
17
21
|
|
18
|
-
def fetch(
|
19
|
-
|
22
|
+
def fetch(args={})
|
23
|
+
Log.info("Fetching...")
|
24
|
+
@abstract.fetch(args)
|
25
|
+
Log.info("Fetch completed")
|
26
|
+
# rescue => e
|
27
|
+
# Log.error(e.to_s)
|
20
28
|
end
|
21
29
|
|
22
|
-
def extract(
|
23
|
-
|
30
|
+
def extract(args={})
|
31
|
+
Log.info("Extracting...")
|
32
|
+
@abstract.extract(args)
|
33
|
+
Log.info("Extraction completed")
|
34
|
+
# rescue => e
|
35
|
+
# Log.error(e.to_s)
|
24
36
|
end
|
25
37
|
|
26
38
|
end
|