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.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -0
  3. data/CHANGELOG.md +16 -0
  4. data/Gemfile.lock +4 -4
  5. data/README.md +52 -2
  6. data/db_meta.gemspec +1 -1
  7. data/lib/db_meta/abstract.rb +13 -5
  8. data/lib/db_meta/constant.rb +45 -0
  9. data/lib/db_meta/logger.rb +15 -0
  10. data/lib/db_meta/oracle/base.rb +54 -0
  11. data/lib/db_meta/oracle/connection.rb +39 -0
  12. data/lib/db_meta/oracle/helper.rb +37 -0
  13. data/lib/db_meta/oracle/objects.rb +204 -0
  14. data/lib/db_meta/oracle/oracle.rb +172 -3
  15. data/lib/db_meta/oracle/types/column.rb +70 -0
  16. data/lib/db_meta/oracle/types/comment.rb +20 -0
  17. data/lib/db_meta/oracle/types/constraint.rb +91 -0
  18. data/lib/db_meta/oracle/types/constraint_collection.rb +46 -0
  19. data/lib/db_meta/oracle/types/database_link.rb +33 -0
  20. data/lib/db_meta/oracle/types/function.rb +30 -0
  21. data/lib/db_meta/oracle/types/grant.rb +46 -0
  22. data/lib/db_meta/oracle/types/grant_collection.rb +42 -0
  23. data/lib/db_meta/oracle/types/index.rb +43 -0
  24. data/lib/db_meta/oracle/types/lob.rb +13 -0
  25. data/lib/db_meta/oracle/types/materialized_view.rb +65 -0
  26. data/lib/db_meta/oracle/types/package.rb +42 -0
  27. data/lib/db_meta/oracle/types/package_body.rb +13 -0
  28. data/lib/db_meta/oracle/types/procedure.rb +30 -0
  29. data/lib/db_meta/oracle/types/sequence.rb +41 -0
  30. data/lib/db_meta/oracle/types/synonym.rb +42 -0
  31. data/lib/db_meta/oracle/types/synonym_collection.rb +42 -0
  32. data/lib/db_meta/oracle/types/table.rb +164 -0
  33. data/lib/db_meta/oracle/types/table_data_collection.rb +85 -0
  34. data/lib/db_meta/oracle/types/trigger.rb +64 -0
  35. data/lib/db_meta/oracle/types/type.rb +41 -0
  36. data/lib/db_meta/oracle/types/type_body.rb +13 -0
  37. data/lib/db_meta/oracle/types/view.rb +60 -0
  38. data/lib/db_meta/version.rb +1 -1
  39. data/lib/db_meta.rb +18 -6
  40. data/todo.txt +43 -0
  41. 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,13 @@
1
+ module DbMeta
2
+ module Oracle
3
+ class PackageBody < Base
4
+ register_type('PACKAGE BODY')
5
+
6
+ def initialize(args={})
7
+ super(args)
8
+ @extract_type = :embedded
9
+ end
10
+
11
+ end
12
+ end
13
+ 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,13 @@
1
+ module DbMeta
2
+ module Oracle
3
+ class TypeBody < Base
4
+ register_type('TYPE BODY')
5
+
6
+ def initialize(args={})
7
+ super(args)
8
+ @extract_type = :embedded
9
+ end
10
+
11
+ end
12
+ end
13
+ 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
@@ -1,3 +1,3 @@
1
1
  module DbMeta
2
- VERSION = "0.1.1"
2
+ VERSION = "0.1.3"
3
3
  end
data/lib/db_meta.rb CHANGED
@@ -1,26 +1,38 @@
1
1
  require_relative 'db_meta/version'
2
- require_relative 'db_meta/abstract'
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(**args)
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(**args)
19
- abstract.fetch(args)
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(**args)
23
- abstract.extract(args)
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