oracle_to_mysql 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,80 @@
1
+ module OracleToMysql
2
+ module PrivateInstanceMethods
3
+ def otm_set_strategy(strategy,options={})
4
+ raise "Invalid strategy #{strategy}" unless OTM_VALID_STRATEGIES.include?(strategy)
5
+ @otm_strategy = strategy
6
+ # TODO: verify options
7
+ @otm_strategy_options = options
8
+ end
9
+
10
+ # LOGGING FUNCTIONS BEGIN
11
+ def otm_output(msg)
12
+ puts "[#{self.to_s}]#{msg}"
13
+ end
14
+ def otm_started(msg)
15
+ self.otm_output("[started t=#{self.otm_time_elapsed_since_otm_timestamp}]#{msg}")
16
+ end
17
+ def otm_finished(msg)
18
+ self.otm_output("[finished t=#{self.otm_time_elapsed_since_otm_timestamp}]#{msg}")
19
+ end
20
+ # LOGGING FUNCTIONS END
21
+
22
+ def otm_time_elapsed_since_otm_timestamp
23
+ if @otm_timestamp.nil?
24
+ self.otm_timestamp # calling this first, causes the lazily loaded timestamp to load...
25
+ 0
26
+ else
27
+ Time.now - self.otm_timestamp
28
+ end
29
+ end
30
+
31
+ # This reflects on the various strategy, retain, and other options that the client class has specified
32
+ # and generates a linear sequence of command names that will be executed
33
+ # on .otm_execute
34
+ #
35
+ def otm_execute_command_names
36
+ if @otm_execute_command_names.nil?
37
+ case self.otm_strategy
38
+ when :atomic_rename
39
+ @otm_execute_command_names = [
40
+ :write_sqlplus_commands_to_file,
41
+ :fork_and_execute_sqlplus_commands_file,
42
+ :write_and_execute_mysql_commands_to_bash_file
43
+ ]
44
+ when :accumulative
45
+ @otm_execute_command_names = [
46
+ :write_sqlplus_commands_to_file,
47
+ :fork_and_execute_sqlplus_commands_file,
48
+ :write_and_execute_mysql_commands_to_bash_file_in_replace_mode
49
+ ]
50
+ else
51
+ raise "Invalid otm_strategy=#{@otm_strategy}"
52
+ end
53
+
54
+ ## All strategies should cleanup after themselves lastly
55
+ @otm_execute_command_names << :delete_temp_files
56
+ end
57
+ @otm_execute_command_names
58
+ end
59
+
60
+ # This generates a temp file suffixed with the specified x
61
+ # it is used
62
+ def generate_tmp_file_name(x)
63
+ File.join(self.tmp_directory,"#{self.otm_target_table}_#{self.otm_timestamp.to_i}_#{x}")
64
+ end
65
+
66
+ # Must pass an argument, retain_n is "the number tables old relative to the current table"
67
+ # if n is 1, the retained table is simple <TBL>_old
68
+ # if its greater, there a dynamic "show retained tables for this table", sort lexically,
69
+ # and return the -nth retain_n (i think) (negative nth) from the list
70
+ #
71
+ def otm_retained_target_table(retain_n)
72
+ if retain_n == 1
73
+ "#{self.otm_target_table}#{OTM_RETAIN_KEY}"
74
+ else
75
+ raise "TODO: HAVE NOT DEALT WITH n != 1 retain option"
76
+ end
77
+ end
78
+
79
+ end
80
+ end
@@ -0,0 +1,18 @@
1
+ module OracleToMysql
2
+ module ProtectedClassMethods
3
+ def otm_default_strategy
4
+ :atomic_rename # can also be :accumulative
5
+ end
6
+
7
+ # These options set what happens to an existing target if it exists
8
+ # a retain value of n=1, means "keep the last table arround"
9
+ #
10
+ def otm_default_retain_options
11
+ return {
12
+ :n => 1,
13
+ :table_name_pattern => Proc.new {|dest_table| Regexp.new(/(#{dest_table})(#{self.class::OTM_RETAIN_KEY})(\d+)/)},
14
+ :new_table_name => Proc.new {|dest_table| "#{dest_table}#{self.class::OTM_RETAIN_KEY}#{Time.now.to_i.to_s}"}
15
+ }
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,74 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{oracle_to_mysql}
8
+ s.version = "1.1.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Joe Goggins", "Chris Dinger"]
12
+ s.date = %q{2010-11-15}
13
+ s.description = %q{Wraps the sqlplus binary and mysql binary does not currently require OCI8 or MySQL gems (might someday tho)}
14
+ s.email = %q{joe.goggins@umn.edu}
15
+ s.extra_rdoc_files = [
16
+ "README.rdoc"
17
+ ]
18
+ s.files = [
19
+ ".document",
20
+ ".specification",
21
+ "README.rdoc",
22
+ "Rakefile",
23
+ "VERSION",
24
+ "lib/oracle_to_mysql.rb",
25
+ "lib/oracle_to_mysql/api_instance_methods.rb",
26
+ "lib/oracle_to_mysql/command.rb",
27
+ "lib/oracle_to_mysql/command/delete_temp_files.rb",
28
+ "lib/oracle_to_mysql/command/fork_and_execute_sqlplus_command.rb",
29
+ "lib/oracle_to_mysql/command/write_and_execute_mysql_commands_to_bash_file.rb",
30
+ "lib/oracle_to_mysql/command/write_and_execute_mysql_commands_to_bash_file_in_replace_mode.rb",
31
+ "lib/oracle_to_mysql/command/write_sqlplus_commands_to_file.rb",
32
+ "lib/oracle_to_mysql/must_override_instance_methods.rb",
33
+ "lib/oracle_to_mysql/optional_override_instance_methods.rb",
34
+ "lib/oracle_to_mysql/private_instance_methods.rb",
35
+ "lib/oracle_to_mysql/protected_class_methods.rb",
36
+ "oracle_to_mysql.gemspec",
37
+ "test/demo/ps_term_tbl.rb",
38
+ "test/demo/ps_term_tbl_accumulative.rb",
39
+ "test/demo/test_oracle_to_mysql_against_ps_term_tbl.rb",
40
+ "test/helper.rb",
41
+ "test/oracle_to_mysql.example.yml",
42
+ "test/test_against_ps_term_tbl_accumulative.rb",
43
+ "test/test_oracle_to_mysql.rb"
44
+ ]
45
+ s.homepage = %q{http://github.com/joegoggins/oracle_to_mysql}
46
+ s.require_paths = ["lib"]
47
+ s.rubygems_version = %q{1.3.7}
48
+ s.summary = %q{A gem for mirroring data from an oracle db to a mysql db}
49
+ s.test_files = [
50
+ "test/demo/ps_term_tbl.rb",
51
+ "test/demo/ps_term_tbl_accumulative.rb",
52
+ "test/demo/test_oracle_to_mysql_against_ps_term_tbl.rb",
53
+ "test/helper.rb",
54
+ "test/test_against_ps_term_tbl_accumulative.rb",
55
+ "test/test_oracle_to_mysql.rb"
56
+ ]
57
+
58
+ if s.respond_to? :specification_version then
59
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
60
+ s.specification_version = 3
61
+
62
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
63
+ s.add_runtime_dependency(%q<POpen4>, [">= 0"])
64
+ s.add_development_dependency(%q<thoughtbot-shoulda>, [">= 0"])
65
+ else
66
+ s.add_dependency(%q<POpen4>, [">= 0"])
67
+ s.add_dependency(%q<thoughtbot-shoulda>, [">= 0"])
68
+ end
69
+ else
70
+ s.add_dependency(%q<POpen4>, [">= 0"])
71
+ s.add_dependency(%q<thoughtbot-shoulda>, [">= 0"])
72
+ end
73
+ end
74
+
@@ -0,0 +1,63 @@
1
+ class PsTermTbl
2
+ include OracleToMysql
3
+
4
+ def otm_target_table
5
+ "otm_ps_term_tbl"
6
+ end
7
+
8
+ def otm_source_sql
9
+ "select
10
+ trim(INSTITUTION) || CHR(9) ||
11
+ trim(ACAD_CAREER) || CHR(9) ||
12
+ trim(STRM) || CHR(9) ||
13
+ trim(DESCR) || CHR(9) ||
14
+ trim(DESCRSHORT) || CHR(9) ||
15
+ case when TERM_BEGIN_DT is null then '\\N' else to_char(TERM_BEGIN_DT, 'YYYY-MM-DD') end || CHR(9) ||
16
+ case when TERM_END_DT is null then '\\N' else to_char(TERM_END_DT, 'YYYY-MM-DD') end || CHR(9) ||
17
+ trim(SESSION_CODE) || CHR(9) ||
18
+ WEEKS_OF_INSTRUCT || CHR(9) ||
19
+ trim(TERM_CATEGORY) || CHR(9) ||
20
+ trim(ACAD_YEAR) || CHR(9) ||
21
+ trim(TRANSCIPT_DT_PRT) || CHR(9) ||
22
+ trim(HOLIDAY_SCHEDULE) || CHR(9) ||
23
+ case when SIXTY_PCT_DT is null then '\\N' else to_char(SIXTY_PCT_DT, 'YYYY-MM-DD') end || CHR(9) ||
24
+ trim(USE_DYN_CLASS_DATE) || CHR(9) ||
25
+ trim(INCLUDE_IN_SS) || CHR(9) ||
26
+ case when SSR_TRMAC_LAST_DT is null then '\\N' else to_char(SSR_TRMAC_LAST_DT, 'YYYY-MM-DD') end || CHR(9) ||
27
+ case when SSR_PLNDISPONLY_DT is null then '\\N' else to_char(SSR_PLNDISPONLY_DT, 'YYYY-MM-DD') end || CHR(9) ||
28
+ case when SSR_SSENRLAVAIL_DT is null then '\\N' else to_char(SSR_SSENRLAVAIL_DT, 'YYYY-MM-DD') end || CHR(9)
29
+ from ps_term_tbl
30
+ where institution='UMNTC'"
31
+ end
32
+ def otm_target_sql
33
+ "
34
+ create table if not exists #{self.otm_target_table} (
35
+ institution varchar(5),
36
+ acad_career varchar(4),
37
+ strm varchar(4),
38
+ descr varchar(30),
39
+ descrshort varchar(10),
40
+ term_begin_dt date,
41
+ term_end_dt date,
42
+ session_code varchar(3),
43
+ weeks_of_instruct integer,
44
+ term_category varchar(1),
45
+ acad_year varchar(4),
46
+ transcipt_dt_prt varchar(2),
47
+ holiday_schedule varchar(6),
48
+ sixty_pct_dt date,
49
+ use_dyn_class_date varchar(1),
50
+ include_in_ss varchar(1),
51
+ ssr_trmac_last_dt date,
52
+ ssr_plndisponly_dt date,
53
+ ssr_ssenrlavail_dt date,
54
+ primary key (institution, acad_career, strm),
55
+ key (institution),
56
+ key (acad_career),
57
+ key (strm),
58
+ key (term_begin_dt),
59
+ key (term_end_dt)
60
+ )
61
+ "
62
+ end
63
+ end
@@ -0,0 +1,11 @@
1
+ # This class extends from demo/ps_term_tbl to
2
+ # demo/test the accumulative mirror option
3
+ # It also tests that child classes effectively can override OracleToMysql options
4
+ # set in the parent
5
+ require 'ps_term_tbl'
6
+ class PsTermTblAccumulative < PsTermTbl
7
+ # OVERRIDDEN from default to test :accumulative option
8
+ def otm_strategy
9
+ :accumulative
10
+ end
11
+ end
@@ -0,0 +1,59 @@
1
+ require 'helper'
2
+
3
+ # test.demo is already in the load path, hence the omission of "demo/" here
4
+ # require 'ps_um_dept_tree'
5
+ # require 'job_queue_run'
6
+ require 'ps_term_tbl'
7
+ class TestOracleToMysql < Test::Unit::TestCase
8
+ context "Test API against ps_term_tbl" do
9
+ setup do
10
+ @ps_term_tbl_inst = PsTermTbl.new
11
+ # @ps_um_dept_tree = PsUmDeptTree.new
12
+ end
13
+ should "Assert the otm_strategy's default is an atomic_rename" do
14
+ assert_equal(@ps_term_tbl_inst.otm_strategy, :atomic_rename)
15
+ end
16
+
17
+ should "Assert an instance override the default" do
18
+ @ps_term_tbl_inst.otm_set_strategy(:accumulative)
19
+ assert_equal(@ps_term_tbl_inst.otm_strategy, :accumulative)
20
+ @ps_term_tbl_inst.otm_set_strategy(:atomic_rename)
21
+ assert_equal(@ps_term_tbl_inst.otm_strategy, :atomic_rename)
22
+ end
23
+
24
+ should "Have default otm_retain_options" do
25
+ retain_options = @ps_term_tbl_inst.otm_retain_options
26
+ assert(retain_options.has_key?(:n))
27
+ assert(retain_options.has_key?(:table_name_pattern))
28
+ assert(retain_options.has_key?(:new_table_name))
29
+ end
30
+
31
+ should "be able to invoke otm_execute" do
32
+ @ps_term_tbl_inst.otm_execute
33
+ end
34
+ #
35
+ # should "Should be able to do a dry-run that outputs what the otm_execute will do" do
36
+ # assert_nothing_raised do
37
+ # x = PsTermTbl.otm_execute_command_names.each do |command_name|
38
+ # puts command_name
39
+ # end
40
+ # end
41
+ # end
42
+ #
43
+ # should "implement the required ClientInterfaceClassMethods" do
44
+ # [PsTermTbl,PsUmDeptTree].each do |klass|
45
+ # [:otm_source_sql, :otm_target_table, :otm_target_sql].each do |meth|
46
+ # puts klass.send(meth)
47
+ # end
48
+ # end
49
+ # end
50
+ #
51
+ # should "have hashes for their target and source" do
52
+ # [PsTermTbl,PsUmDeptTree].each do |klass|
53
+ # [:otm_source_config_hash, :otm_target_config_hash].each do |meth|
54
+ # puts klass.send(meth).inspect
55
+ # end
56
+ # end
57
+ # end
58
+ end
59
+ end
@@ -0,0 +1,13 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ require 'shoulda'
4
+
5
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
6
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
7
+ require 'oracle_to_mysql'
8
+
9
+ # Add the demo dir and load for test cases
10
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__),'demo'))
11
+
12
+ class Test::Unit::TestCase
13
+ end
@@ -0,0 +1,13 @@
1
+ oracle_source:
2
+ username: TODO
3
+ password: TODO
4
+ host: TODO
5
+ database: TODO
6
+ port: 1521
7
+
8
+ mysql_target:
9
+ username: TODO
10
+ password: TODO
11
+ host: TODO
12
+ port: 3306
13
+ database: TODO
@@ -0,0 +1,12 @@
1
+ require 'helper'
2
+ require 'ps_term_tbl_accumulative'
3
+ class TestAgainstPsTermTblAccumulative < Test::Unit::TestCase
4
+ context "Test API against ps_term_tbl" do
5
+ setup do
6
+ @ps_term_tbl_inst = PsTermTblAccumulative.new
7
+ end
8
+ should "be able to invoke otm_execute" do
9
+ @ps_term_tbl_inst.otm_execute
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,7 @@
1
+ require 'helper'
2
+
3
+ class TestOracleToMysql < Test::Unit::TestCase
4
+ should "probably rename this file and start testing for real" do
5
+ flunk "hey buddy, you should probably rename this file and start testing for real"
6
+ end
7
+ end
metadata ADDED
@@ -0,0 +1,124 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: oracle_to_mysql
3
+ version: !ruby/object:Gem::Version
4
+ hash: 19
5
+ prerelease: false
6
+ segments:
7
+ - 1
8
+ - 1
9
+ - 0
10
+ version: 1.1.0
11
+ platform: ruby
12
+ authors:
13
+ - Joe Goggins
14
+ - Chris Dinger
15
+ autorequire:
16
+ bindir: bin
17
+ cert_chain: []
18
+
19
+ date: 2010-11-15 00:00:00 -06:00
20
+ default_executable:
21
+ dependencies:
22
+ - !ruby/object:Gem::Dependency
23
+ name: POpen4
24
+ prerelease: false
25
+ requirement: &id001 !ruby/object:Gem::Requirement
26
+ none: false
27
+ requirements:
28
+ - - ">="
29
+ - !ruby/object:Gem::Version
30
+ hash: 3
31
+ segments:
32
+ - 0
33
+ version: "0"
34
+ type: :runtime
35
+ version_requirements: *id001
36
+ - !ruby/object:Gem::Dependency
37
+ name: thoughtbot-shoulda
38
+ prerelease: false
39
+ requirement: &id002 !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - ">="
43
+ - !ruby/object:Gem::Version
44
+ hash: 3
45
+ segments:
46
+ - 0
47
+ version: "0"
48
+ type: :development
49
+ version_requirements: *id002
50
+ description: Wraps the sqlplus binary and mysql binary does not currently require OCI8 or MySQL gems (might someday tho)
51
+ email: joe.goggins@umn.edu
52
+ executables: []
53
+
54
+ extensions: []
55
+
56
+ extra_rdoc_files:
57
+ - README.rdoc
58
+ files:
59
+ - .document
60
+ - .specification
61
+ - README.rdoc
62
+ - Rakefile
63
+ - VERSION
64
+ - lib/oracle_to_mysql.rb
65
+ - lib/oracle_to_mysql/api_instance_methods.rb
66
+ - lib/oracle_to_mysql/command.rb
67
+ - lib/oracle_to_mysql/command/delete_temp_files.rb
68
+ - lib/oracle_to_mysql/command/fork_and_execute_sqlplus_command.rb
69
+ - lib/oracle_to_mysql/command/write_and_execute_mysql_commands_to_bash_file.rb
70
+ - lib/oracle_to_mysql/command/write_and_execute_mysql_commands_to_bash_file_in_replace_mode.rb
71
+ - lib/oracle_to_mysql/command/write_sqlplus_commands_to_file.rb
72
+ - lib/oracle_to_mysql/must_override_instance_methods.rb
73
+ - lib/oracle_to_mysql/optional_override_instance_methods.rb
74
+ - lib/oracle_to_mysql/private_instance_methods.rb
75
+ - lib/oracle_to_mysql/protected_class_methods.rb
76
+ - oracle_to_mysql.gemspec
77
+ - test/demo/ps_term_tbl.rb
78
+ - test/demo/ps_term_tbl_accumulative.rb
79
+ - test/demo/test_oracle_to_mysql_against_ps_term_tbl.rb
80
+ - test/helper.rb
81
+ - test/oracle_to_mysql.example.yml
82
+ - test/test_against_ps_term_tbl_accumulative.rb
83
+ - test/test_oracle_to_mysql.rb
84
+ has_rdoc: true
85
+ homepage: http://github.com/joegoggins/oracle_to_mysql
86
+ licenses: []
87
+
88
+ post_install_message:
89
+ rdoc_options: []
90
+
91
+ require_paths:
92
+ - lib
93
+ required_ruby_version: !ruby/object:Gem::Requirement
94
+ none: false
95
+ requirements:
96
+ - - ">="
97
+ - !ruby/object:Gem::Version
98
+ hash: 3
99
+ segments:
100
+ - 0
101
+ version: "0"
102
+ required_rubygems_version: !ruby/object:Gem::Requirement
103
+ none: false
104
+ requirements:
105
+ - - ">="
106
+ - !ruby/object:Gem::Version
107
+ hash: 3
108
+ segments:
109
+ - 0
110
+ version: "0"
111
+ requirements: []
112
+
113
+ rubyforge_project:
114
+ rubygems_version: 1.3.7
115
+ signing_key:
116
+ specification_version: 3
117
+ summary: A gem for mirroring data from an oracle db to a mysql db
118
+ test_files:
119
+ - test/demo/ps_term_tbl.rb
120
+ - test/demo/ps_term_tbl_accumulative.rb
121
+ - test/demo/test_oracle_to_mysql_against_ps_term_tbl.rb
122
+ - test/helper.rb
123
+ - test/test_against_ps_term_tbl_accumulative.rb
124
+ - test/test_oracle_to_mysql.rb