myreplicator 1.0.6 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. data/app/assets/javascripts/myreplicator/select2.js +2685 -0
  2. data/app/assets/stylesheets/myreplicator/select2-spinner.gif +0 -0
  3. data/app/assets/stylesheets/myreplicator/select2.css +612 -0
  4. data/app/assets/stylesheets/myreplicator/select2.png +0 -0
  5. data/app/models/myreplicator/export.rb +25 -7
  6. data/app/models/myreplicator/vertica_export.rb +5 -0
  7. data/app/views/myreplicator/exports/_form.html.erb +48 -27
  8. data/app/views/myreplicator/exports/index.html.erb +4 -4
  9. data/db/migrate/20130213211927_create_myreplicator_vertica_exports.rb +22 -0
  10. data/db/migrate/20130213211927_create_myreplicator_vertica_exports.rb~ +8 -0
  11. data/lib/exporter/export_metadata.rb +7 -1
  12. data/lib/exporter/mysql_exporter.rb +103 -29
  13. data/lib/exporter/sql_commands.rb +8 -9
  14. data/lib/exporter.rb +1 -0
  15. data/lib/loader/loader.rb +32 -12
  16. data/lib/loader/vertica/source_db.rb +30 -0
  17. data/lib/loader/vertica/source_db.rb~ +30 -0
  18. data/lib/loader/vertica/types.rb +44 -0
  19. data/lib/loader/vertica/vertica_loader.rb +235 -0
  20. data/lib/loader/vertica/vertica_loader.rb~ +175 -0
  21. data/lib/loader/vertica/vertica_sql.rb +59 -0
  22. data/lib/loader/vertica/vertica_sql.rb~ +60 -0
  23. data/lib/loader/vertica.rb +1 -0
  24. data/lib/myreplicator/version.rb +1 -1
  25. data/lib/transporter/transporter.rb +11 -1
  26. data/test/dummy/app/models/vertica_db.rb +7 -0
  27. data/test/dummy/config/database.yml +7 -0
  28. data/test/dummy/config/database.yml~ +2 -2
  29. data/test/dummy/config/myreplicator.yml +5 -0
  30. data/test/dummy/config/myreplicator.yml~ +0 -2
  31. data/test/dummy/log/development.log +1664 -9510
  32. data/test/dummy/tmp/cache/assets/CD5/B90/sprockets%2Fc999d13a6a21113981c0d820e8043bdf +0 -0
  33. data/test/dummy/tmp/cache/assets/CD7/030/sprockets%2F9ba4859590582b8b72a650b2b00b6cd2 +0 -0
  34. data/test/dummy/tmp/cache/assets/CE5/670/sprockets%2Fe9e4122f1706626a21da6f8457f088ce +0 -0
  35. data/test/dummy/tmp/cache/assets/D06/5D0/sprockets%2F91850a20c0ddfa3d8814ca91870fb715 +0 -0
  36. data/test/dummy/tmp/cache/assets/D14/3A0/sprockets%2Fe59a60053fada52e8185281b4ee887a5 +0 -0
  37. data/test/dummy/tmp/cache/assets/D7C/E30/sprockets%2F0ba91e21bddfc7e1de102b22183e1e11 +0 -0
  38. data/test/dummy/tmp/cache/assets/D8B/B60/sprockets%2Faa32227c440a378ccd21218eefeb80bf +0 -0
  39. data/test/dummy/tmp/cache/assets/DA7/E50/sprockets%2F47bf4f2b4afeac775e6d572a83343fb8 +0 -0
  40. data/test/dummy/tmp/cache/assets/DA8/910/sprockets%2Fab5775c4a837bd4d97ac394d473cda9b +0 -0
  41. data/test/dummy/tmp/cache/assets/DAA/060/sprockets%2Facc0d22b9d28123cc1c84d0db630d0ba +0 -0
  42. data/test/dummy/tmp/cache/assets/DF8/5D0/sprockets%2Fb815ed34d61cfed96222daa3bfd1d84d +0 -0
  43. data/test/dummy/tmp/cache/assets/E1C/AC0/sprockets%2Faff544a3a34eb7dab7d46b0cb2cd7b70 +0 -0
  44. data/test/dummy/tmp/cache/assets/E2E/1F0/sprockets%2Fa24e3d7bc5ae4d40adf6f1b8fe94e7c3 +0 -0
  45. data/test/fixtures/myreplicator/vertica_exports.yml +11 -0
  46. data/test/unit/myreplicator/vertica_export_test.rb +9 -0
  47. metadata +43 -13
  48. data/test/dummy/tmp/myreplicator/okl_test_batchy_batches_1358547945.tsv.gz +0 -0
  49. data/test/dummy/tmp/myreplicator/okl_test_batchy_batches_1358547945.tsv.json +0 -1
@@ -1,6 +1,6 @@
1
1
  <%
2
2
  #rather than yaml arrays of the drop downs
3
- export_to = ["destination_db","s3","both"]
3
+ export_to = ["destination_db","backup","vertica"]
4
4
  export_type = ["incremental","fulldump"]
5
5
  %>
6
6
  <%= form_for(@export) do |f| %>
@@ -16,6 +16,18 @@ export_type = ["incremental","fulldump"]
16
16
  </div>
17
17
  <% end %>
18
18
  <div class="form-section">
19
+ <label>Export to</label>
20
+ <select name="export[export_to]" id="export_to" class="chosen" data-placeholder="Select export destination">
21
+ <% export_to.each do |val| %>
22
+ <option value="<%= val %>" <% if @export.export_to == val %>SELECTED<% end %>><%= val %></option>
23
+ <% end %>
24
+ </select>
25
+ <label>Export type</label>
26
+ <select name="export[export_type]" id="export_type" class="chosen" data-placeholder="Select your export type">
27
+ <% export_type.each do |val| %>
28
+ <option value="<%= val %>" <% if @export.export_type == val %>SELECTED<% end %>><%= val %></option>
29
+ <% end %>
30
+ </select>
19
31
  <label>Source Schema</label>
20
32
  <%= f.select :source_schema, @dbs %>
21
33
  <label>Destination Schema</label>
@@ -28,20 +40,8 @@ export_type = ["incremental","fulldump"]
28
40
  <%= f.text_field :incremental_column_type %>
29
41
  <label>Maximum Incremental Value</label>
30
42
  <%= f.text_field :max_incremental_value %>
31
- <label>S3 Path</label>
43
+ <label>Store a copy in</label>
32
44
  <%= f.text_field :s3_path %>
33
- <label>Export to</label>
34
- <select name="export[export_to]" id="export_to" class="chosen" data-placeholder="Select export destination">
35
- <% export_to.each do |val| %>
36
- <option value="<%= val %>" <% if @export.export_to == val %>SELECTED<% end %>><%= val %></option>
37
- <% end %>
38
- </select>
39
- <label>Export type</label>
40
- <select name="export[export_type]" id="export_type" class="chosen" data-placeholder="Select your export type">
41
- <% export_type.each do |val| %>
42
- <option value="<%= val %>" <% if @export.export_type == val %>SELECTED<% end %>><%= val %></option>
43
- <% end %>
44
- </select>
45
45
  <label>Active</label>
46
46
  <select name="export[active]" id="active" class="chosen">
47
47
  <option value="true" <% if @export.active == true %>SELECTED<% end %>>true</option>
@@ -124,8 +124,7 @@ export_type = ["incremental","fulldump"]
124
124
  <%= link_to content_tag(:span, 'cancel'), exports_path, :class => "btn left action cancel" %>
125
125
  </div>
126
126
  <% end %>
127
- <%= javascript_include_tag "myreplicator/chosen.jquery.min" %>
128
- <%= javascript_include_tag "myreplicator/cronwtf.min" %>
127
+
129
128
  <script>
130
129
  var dbs = {
131
130
  <% @tables.each do |key,values| %>
@@ -138,13 +137,28 @@ var dbs = {
138
137
  }
139
138
  $(function(){
140
139
  CronUI.translate();
141
- $(".chosen").chosen();
142
- $("#export_destination_schema,#export_table_name").chosen();
140
+ $(".chosen").select2();
141
+ var $destination = $("#export_destination_schema").clone();
142
+ var $table_name = $("#export_table_name").clone()
143
+ $("#export_destination_schema").select2();
144
+ $("#export_table_name").select2();
143
145
  $(".cron").chosen().change(function(){CronUI.translate()});
144
- $("#export_source_schema").chosen().change(function(){
146
+ $("#export_source_schema").select2().change(function(){
145
147
  exportSchemaSelect($(this).val())
146
148
  });
147
149
  exportSchemaSelect($("#export_source_schema").val());
150
+
151
+ $("#export_to").change(function(){
152
+ var exp = $(this).val();
153
+ if(exp == 'vertica'){
154
+ $("#export_destination_schema").select2("destroy").before('<input type="text" id="export_destination_schema" name="export[destination_schema]"/>').remove();
155
+ }else{
156
+ if($("#s2id_export_destination_schema").length < 1){
157
+ $("#export_destination_schema").before($destination).remove();
158
+ $("#export_destination_schema").select2();
159
+ }
160
+ }
161
+ })
148
162
  $("#cron-min").slider({
149
163
  min: 1,
150
164
  max: 59,
@@ -218,18 +232,25 @@ function editInit(){
218
232
  }
219
233
  }
220
234
  CronUI.translate();
221
- $("#export_table_name").val("<%= @export.table_name %>").trigger("liszt:updated");
235
+ <% if @export.export_to != 'vertica' %>
236
+ $("#export_table_name").select2("val","<%= @export.table_name %>")
237
+ <% else %>
238
+ $("#export_destination_schema").select2("destroy").before('<input type="text" id="export_destination_schema" name="export[destination_schema]" value="<%= @export.destination_schema %>"/>').remove();
239
+ <% end %>
222
240
  }
223
241
 
224
242
  function exportSchemaSelect(val){
225
243
  var target = $("#export_table_name");
226
- var tables = dbs[val];
227
- var l = tables.length;
228
- var options = "";
229
- for(i=0;i<l;i++){
230
- options += "<option value='"+tables[i]+"'>"+tables[i]+"</option>";
244
+ if(target.hasClass("select2-offscreen")){
245
+ target.select2("destroy")
246
+ var tables = dbs[val];
247
+ var l = tables.length;
248
+ var options = "";
249
+ for(i=0;i<l;i++){
250
+ options += "<option value='"+tables[i]+"'>"+tables[i]+"</option>";
251
+ }
252
+ target.val('').find("option").remove()
253
+ target.append(options).select2();
231
254
  }
232
- target.val('').find("option").remove().trigger("liszt:updated");
233
- target.append(options).trigger("liszt:updated");
234
255
  }
235
256
  </script>
@@ -8,14 +8,14 @@
8
8
  <table class="data-grid">
9
9
  <thead>
10
10
  <tr>
11
+ <th><%= sortable "export_type" %></th>
12
+ <th><%= sortable "export_to", "Export Desitination" %></th>
11
13
  <th colspan="2"><%= sortable "source_schema" %></th>
12
14
  <th><%= sortable "destination_schema" %></th>
13
15
  <th><%= sortable "table_name" %></th>
14
16
  <th><%= sortable "incremental_column" %></th>
15
17
  <th><%= sortable "incremental_column_type" %></th>
16
18
  <th><%= sortable "max_incremental_value" %></th>
17
- <th><%= sortable "export_to", "Export Desitination" %></th>
18
- <th><%= sortable "export_type" %></th>
19
19
  <th><%= sortable "s3_path" %></th>
20
20
  <th><%= sortable "cron" %></th>
21
21
  <th class="center">Actions</th>
@@ -24,6 +24,8 @@
24
24
  <tbody>
25
25
  <% @exports.each do |export| %>
26
26
  <tr>
27
+ <td><%= export.export_type %></td>
28
+ <td><%= export.export_to %></td>
27
29
  <td class="state"><span class="status <% if export.active %>active<% else %>inactive<% end %>" title="<% if export.active %>Active<% else %>Inactive<% end %>"></span></td>
28
30
  <td class="source"><%= export.source_schema %></td>
29
31
  <td><%= export.destination_schema %></td>
@@ -31,8 +33,6 @@
31
33
  <td><%= export.incremental_column %></td>
32
34
  <td><%= export.incremental_column_type %></td>
33
35
  <td><%= export.max_incremental_value %></td>
34
- <td><%= export.export_to %></td>
35
- <td><%= export.export_type %></td>
36
36
  <td><%= export.s3_path %></td>
37
37
  <td><span class="cron" data-cron="<%= export.cron %>" title=""><%= export.cron %></span></td>
38
38
  <td>
@@ -0,0 +1,22 @@
1
+ class CreateMyreplicatorVerticaExports < ActiveRecord::Migration
2
+ def change
3
+ create_table :myreplicator_vertica_exports do |t|
4
+ t.string :database
5
+ t.string :schema
6
+ t.string :table_name
7
+ t.string :file_path
8
+ t.string :file_format
9
+ t.string :delimiter
10
+ t.string :field_enclosed_by
11
+ t.string :line_terminated_by
12
+ t.string :cron
13
+ t.string :state, :default => "new"
14
+ t.text :error
15
+ t.boolean :active, :default => true
16
+ t.integer :exporter_pid
17
+ t.datetime :export_started_at, :default => nil
18
+ t.datetime :export_finished_at, :default => nil
19
+ t.timestamps
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,8 @@
1
+ class CreateMyreplicatorVerticaExports < ActiveRecord::Migration
2
+ def change
3
+ create_table :myreplicator_vertica_exports do |t|
4
+
5
+ t.timestamps
6
+ end
7
+ end
8
+ end
@@ -5,6 +5,7 @@ module Myreplicator
5
5
 
6
6
  attr_accessor(:export_time,
7
7
  :export_finished_at,
8
+ :export_to,
8
9
  :table,
9
10
  :database,
10
11
  :state,
@@ -13,6 +14,7 @@ module Myreplicator
13
14
  :incremental_val,
14
15
  :ssh,
15
16
  :export_type,
17
+ :store_in,
16
18
  :on_duplicate,
17
19
  :filepath,
18
20
  :zipped,
@@ -158,7 +160,9 @@ module Myreplicator
158
160
  :export_id => @export_id,
159
161
  :filepath => @filepath,
160
162
  :zipped => @zipped,
161
- :export_type => @export_type
163
+ :export_type => @export_type,
164
+ :export_to => @export_to,
165
+ :store_in => @store_in
162
166
  }
163
167
  return obj.to_json
164
168
  end
@@ -203,6 +207,8 @@ module Myreplicator
203
207
  @on_duplicate = options[:on_duplicate] if options[:on_duplicate]
204
208
  @export_type = options[:export_type] if options[:export_type]
205
209
  @zipped = options[:zipped].nil? ? false : options[:zipped]
210
+ @store_in = options[:store_in] if options[:store_in]
211
+ @export_to = options[:export_to] if options[:export_to]
206
212
  @ssh = nil
207
213
 
208
214
  @success_callbacks = []
@@ -15,19 +15,19 @@ module Myreplicator
15
15
 
16
16
  ExportMetadata.record(:table => @export_obj.table_name,
17
17
  :database => @export_obj.source_schema,
18
+ :export_to => load_to,
18
19
  :export_id => @export_obj.id,
19
20
  :filepath => filepath,
21
+ :store_in => @export_obj.s3_path,
20
22
  :incremental_col => @export_obj.incremental_column) do |metadata|
21
23
 
22
24
  prepare metadata
23
25
 
24
- case @export_obj.export_type?
25
- when :new
26
+ if @export_obj.export_type? == :new && load_to == "mysql"
26
27
  on_failure_state_trans(metadata, "new") # If failed, go back to new
27
28
  on_export_success(metadata)
28
29
  initial_export metadata
29
-
30
- when :incremental
30
+ elsif @export_obj.export_type? == :incremental or load_to == "vertica"
31
31
  on_failure_state_trans(metadata, "failed") # Set state trans on failure
32
32
  on_export_success(metadata)
33
33
  incremental_export metadata
@@ -35,7 +35,15 @@ module Myreplicator
35
35
 
36
36
  end # metadata
37
37
  end
38
-
38
+
39
+ def load_to
40
+ if @export_obj.export_to == "vertica"
41
+ return "vertica"
42
+ else
43
+ return "mysql"
44
+ end
45
+ end
46
+
39
47
  ##
40
48
  # Setups SSH connection to remote host
41
49
  ##
@@ -65,12 +73,10 @@ module Myreplicator
65
73
  metadata.export_type = "initial"
66
74
  max_value = @export_obj.max_value if @export_obj.incremental_export?
67
75
  cmd = initial_mysqldump_cmd
68
-
69
76
  exporting_state_trans # mark exporting
70
77
 
71
78
  puts "Exporting..."
72
79
  result = execute_export(cmd, metadata)
73
-
74
80
  check_result(result, 0)
75
81
 
76
82
  @export_obj.update_max_val(max_value) if @export_obj.incremental_export?
@@ -78,10 +84,19 @@ module Myreplicator
78
84
 
79
85
  def initial_mysqldump_cmd
80
86
  flags = ["create-options", "single-transaction"]
81
- cmd = SqlCommands.mysqldump(:db => @export_obj.source_schema,
82
- :flags => flags,
83
- :filepath => filepath,
84
- :table_name => @export_obj.table_name)
87
+ cmd = ""
88
+ # Mysql - Mysql Export
89
+ if @export_obj.export_to == "destination_db"
90
+ cmd = SqlCommands.mysqldump(:db => @export_obj.source_schema,
91
+ :flags => flags,
92
+ :filepath => filepath,
93
+ :table_name => @export_obj.table_name)
94
+ else # Other destinations
95
+ cmd = SqlCommands.mysql_export_outfile(:db => @export_obj.source_schema,
96
+ :filepath => filepath,
97
+ :table => @export_obj.table_name)
98
+ end
99
+
85
100
  return cmd
86
101
  end
87
102
 
@@ -118,6 +133,7 @@ module Myreplicator
118
133
  cmd = SqlCommands.mysql_export(:db => @export_obj.source_schema,
119
134
  :filepath => filepath,
120
135
  :sql => sql)
136
+
121
137
  return cmd
122
138
  end
123
139
 
@@ -125,27 +141,85 @@ module Myreplicator
125
141
  # Exports table incrementally, similar to incremental_export method
126
142
  # Dumps file in tmp directory specified in myreplicator.yml
127
143
  # Note that directory needs 777 permissions for mysql to be able to export the file
128
- # Uses ;~; as the delimiter and new line for lines
144
+ # Uses \\0 as the delimiter and new line for lines
129
145
  ##
130
146
 
131
147
  def incremental_export_into_outfile metadata
132
- max_value = @export_obj.max_value
133
- metadata.export_type = "incremental_outfile"
134
-
135
- @export_obj.update_max_val if @export_obj.max_incremental_value.blank?
136
-
137
- cmd = SqlCommands.mysql_export_outfile(:db => @export_obj.source_schema,
138
- :table => @export_obj.table_name,
139
- :filepath => filepath,
140
- :incremental_col => @export_obj.incremental_column,
141
- :incremental_col_type => @export_obj.incremental_column_type,
142
- :incremental_val => @export_obj.max_incremental_value)
143
- exporting_state_trans
144
- puts "Exporting..."
145
- result = execute_export(cmd, metadata)
146
- check_result(result, 0)
147
- max_value = incremental_export_into_outfile(metadata)
148
- return max_value
148
+ unless @export_obj.is_running?
149
+ max_value = @export_obj.max_value
150
+ metadata.export_type = "incremental_outfile"
151
+ @export_obj.update_max_val if @export_obj.max_incremental_value.blank?
152
+
153
+ options = {
154
+ :db => @export_obj.source_schema,
155
+ :table => @export_obj.table_name,
156
+ :filepath => filepath,
157
+ :destination_schema => @export_obj.destination_schema}
158
+
159
+ unless schema_changed?(options)[:changed]
160
+ options[:incremental_col] = @export_obj.incremental_column
161
+ options[:incremental_col_type] = @export_obj.incremental_column_type
162
+ options[:incremental_val] = @export_obj.max_incremental_value
163
+ end
164
+
165
+ cmd = SqlCommands.mysql_export_outfile(options)
166
+ exporting_state_trans
167
+ puts "Exporting..."
168
+ result = execute_export(cmd, metadata)
169
+ check_result(result, 0)
170
+ metadata.incremental_val = max_value # store max val in metadata
171
+ @export_obj.update_max_val(max_value) # update max value if export was successful
172
+ end
173
+ return false
174
+ end
175
+
176
+ def self.compare_schemas vertica_schema, mysql_schema
177
+ if vertica_schema.size != mysql_schema.size
178
+ return {:changed => true, :mysql_schema => mysql_schema, :vertica_schema => vertica_schema,:new => false}
179
+ else
180
+ index = 0
181
+ while index < vertica_schema.size
182
+ # puts vertica_schema.rows[index][:column_name] + " " + mysql_schema[index]["column_name"]
183
+ # check for column name
184
+ if vertica_schema.rows[index][:column_name] != mysql_schema[index]["column_name"]
185
+ return true
186
+ end
187
+
188
+ # puts vertica_schema.rows[index][:data_type] + " " + VerticaTypes.convert(mysql_schema[index]["data_type"],mysql_schema[index]["column_type"])
189
+ # check for column's data type
190
+ if (vertica_schema.rows[index][:data_type] != VerticaTypes.convert(mysql_schema[index]["data_type"],mysql_schema[index]["column_type"]) and vertica_schema.rows[index][:data_type] != "timestamp")
191
+ return true
192
+ end
193
+ # and others ?? (PRIMARY, DEFAULT NULL, etc.)
194
+ index += 1
195
+ end
196
+ end
197
+ return false
198
+ end
199
+
200
+ def self.schema_changed? options
201
+ puts options
202
+ mysql_schema = Loader.mysql_table_definition(options)
203
+ vertica_schema = VerticaLoader.destination_table_vertica(options)
204
+
205
+ # empty result set from vertica means table does not exist
206
+ unless vertica_schema.size > 0
207
+ return {:changed => true, :mysql_schema => mysql_schema, :new => true}
208
+ end
209
+
210
+ # compare two schemas
211
+ mysql_schema_simple_form = []
212
+ mysql_schema.each(:as => :hash) do |row|
213
+ mysql_schema_simple_form << row
214
+ end
215
+
216
+ mysql_schema_2 = mysql_schema_simple_form
217
+ if compare_schemas(vertica_schema, mysql_schema_2)
218
+ result = {:changed => true, :mysql_schema => mysql_schema, :vertica_schema => vertica_schema,:new => false}
219
+ else
220
+ result = {:changed => false}
221
+ end
222
+ return result
149
223
  end
150
224
 
151
225
  ##
@@ -36,7 +36,7 @@ module Myreplicator
36
36
  # cmd += "--tab=#{options[:filepath]} "
37
37
  # cmd += "--fields-enclosed-by=\'\"\' "
38
38
  # cmd += "--fields-escaped-by=\'\\\\\' "
39
-
39
+
40
40
  return cmd
41
41
  end
42
42
 
@@ -80,16 +80,17 @@ module Myreplicator
80
80
  options = args.extract_options!
81
81
  options.reverse_merge! :flags => []
82
82
  db = options[:db]
83
+
83
84
  # Database host when ssh'ed into the db server
84
85
 
85
86
  db_host = "127.0.0.1"
86
-
87
+
87
88
  if !ssh_configs(db)["ssh_db_host"].blank?
88
89
  db_host = ssh_configs(db)["ssh_db_host"]
89
90
  elsif !db_configs(db)["host"].blank?
90
- db_host += db_configs(db)["host"]
91
+ db_host = db_configs(db)["host"]
91
92
  end
92
-
93
+
93
94
  flags = ""
94
95
 
95
96
  self.mysql_flags.each_pair do |flag, value|
@@ -120,11 +121,11 @@ module Myreplicator
120
121
  def self.get_outfile_sql options
121
122
  sql = "SELECT * INTO OUTFILE '#{options[:filepath]}' "
122
123
 
123
- sql += " FIELDS TERMINATED BY ';~;' OPTIONALLY ENCLOSED BY '\\\"' LINES TERMINATED BY '\\n'"
124
+ sql += " FIELDS TERMINATED BY '\\0' OPTIONALLY ENCLOSED BY '\\\"' LINES TERMINATED BY '\\n'"
124
125
 
125
126
  sql += "FROM #{options[:db]}.#{options[:table]} "
126
127
 
127
- if options[:incremental_col] && options[:incremental_val]
128
+ if options[:incremental_col] && !options[:incremental_val].blank?
128
129
  if options[:incremental_col_type] == "datetime"
129
130
  sql += "WHERE #{options[:incremental_col]} >= '#{options[:incremental_val]}'"
130
131
  else
@@ -159,8 +160,6 @@ module Myreplicator
159
160
  end
160
161
  end
161
162
 
162
- # BOB : You always build the host,password,username part of the command
163
- # Seems like this should be in a function somewhere
164
163
  cmd = Myreplicator.mysql
165
164
  cmd += "#{flags} -u#{db_configs(db)["username"]} -p#{db_configs(db)["password"]} "
166
165
  cmd += "-h#{db_host} " if db_configs(db)["host"].blank?
@@ -189,7 +188,7 @@ module Myreplicator
189
188
  options = args.extract_options!
190
189
  sql = "SELECT * FROM #{options[:db]}.#{options[:table]} "
191
190
 
192
- if options[:incremental_col] && options[:incremental_val]
191
+ if options[:incremental_col] && !options[:incremental_val].blank?
193
192
  if options[:incremental_col_type] == "datetime"
194
193
  sql += "WHERE #{options[:incremental_col]} >= '#{options[:incremental_val]}'"
195
194
  else
data/lib/exporter.rb CHANGED
@@ -1,3 +1,4 @@
1
1
  Dir["#{File.expand_path(File.dirname(__FILE__))}/exporter/*.rb"].each { | f | require File.expand_path(f) }
2
2
  Dir["#{File.expand_path(File.dirname(__FILE__))}/transporter/*.rb"].each { | f | require File.expand_path(f) }
3
3
  Dir["#{File.expand_path(File.dirname(__FILE__))}/loader/*.rb"].each { | f | require File.expand_path(f) }
4
+ Dir["#{File.expand_path(File.dirname(__FILE__))}/loader/vertica/*.rb"].each { | f | require File.expand_path(f) }
data/lib/loader/loader.rb CHANGED
@@ -177,24 +177,31 @@ module Myreplicator
177
177
  metadata.zipped = false
178
178
 
179
179
  options = {:table_name => exp.table_name, :db => exp.destination_schema,
180
- :filepath => metadata.destination_filepath(tmp_dir)}
180
+ :filepath => metadata.destination_filepath(tmp_dir), :source_schema => exp.source_schema}
181
181
 
182
182
  if metadata.export_type == "incremental_outfile"
183
- options[:fields_terminated_by] = ";~;"
183
+ options[:fields_terminated_by] = "\\0"
184
184
  options[:lines_terminated_by] = "\\n"
185
185
  end
186
186
 
187
- cmd = ImportSql.load_data_infile(options)
188
-
189
- puts cmd
190
-
191
- result = `#{cmd}` # execute
192
-
193
- unless result.nil?
194
- if result.size > 0
195
- raise Exceptions::LoaderError.new("Incremental Load #{metadata.filename} Failed!\n#{result}")
187
+ case metadata.export_to
188
+ when "vertica"
189
+ options = {:table_name => exp.table_name, :db => ActiveRecord::Base.configurations["vertica"]["database"],
190
+ :filepath => metadata.destination_filepath(tmp_dir), :source_schema => exp.source_schema, :export_id => metadata.export_id}
191
+ options[:destination_schema] = exp.destination_schema
192
+ Kernel.p "===== LOAD TO VERTICA ====="
193
+ Kernel.p options
194
+ Myreplicator::VerticaLoader.load options
195
+ when "mysql"
196
+ cmd = ImportSql.load_data_infile(options)
197
+ puts cmd
198
+ result = `#{cmd}` # execute
199
+ unless result.nil?
200
+ if result.size > 0
201
+ raise Exceptions::LoaderError.new("Incremental Load #{metadata.filename} Failed!\n#{result}")
202
+ end
196
203
  end
197
- end
204
+ end #case
198
205
  end
199
206
 
200
207
  ##
@@ -252,5 +259,18 @@ module Myreplicator
252
259
  return files
253
260
  end
254
261
 
262
+ def self.mysql_table_definition options
263
+ Kernel.p options
264
+ sql = "SELECT table_schema, table_name, column_name, is_nullable, data_type, column_type, column_key "
265
+ sql += "FROM INFORMATION_SCHEMA.COLUMNS where table_name = '#{options[:table]}' "
266
+ sql += "and table_schema = '#{options[:source_schema]}';"
267
+
268
+ puts sql
269
+
270
+ desc = DB.exec_sql(options[:source_schema], sql)
271
+ puts desc
272
+ return desc
273
+ end
274
+
255
275
  end
256
276
  end
@@ -0,0 +1,30 @@
1
+ module Myreplicator
2
+ class DB < ActiveRecord::Base
3
+
4
+ def self.connect db
5
+ establish_connection(ActiveRecord::Base.configurations[db])
6
+ end
7
+
8
+ ##
9
+ # Returns tables as an Array
10
+ # releases the connection
11
+ ##
12
+ def self.get_tables(db)
13
+ tables = []
14
+ begin
15
+ self.connect(db)
16
+ tables = self.connection.tables
17
+ self.connection_pool.release_connection
18
+ rescue Mysql2::Error => e
19
+ puts "Connection to #{db} Failed!"
20
+ puts e.message
21
+ end
22
+ return tables
23
+ end
24
+
25
+ def self.exec_sql source_db,sql
26
+ DB.connect(source_db)
27
+ return DB.connection.execute(sql)
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,30 @@
1
+ module VerticaUtils
2
+ class SourceDb < ActiveRecord::Base
3
+
4
+ def self.connect db
5
+ establish_connection(ActiveRecord::Base.configurations[db])
6
+ end
7
+
8
+ ##
9
+ # Returns tables as an Array
10
+ # releases the connection
11
+ ##
12
+ def self.get_tables(db)
13
+ tables = []
14
+ begin
15
+ self.connect(db)
16
+ tables = self.connection.tables
17
+ self.connection_pool.release_connection
18
+ rescue Mysql2::Error => e
19
+ puts "Connection to #{db} Failed!"
20
+ puts e.message
21
+ end
22
+ return tables
23
+ end
24
+
25
+ def self.exec_sql source_db,sql
26
+ SourceDb.connect(source_db)
27
+ return SourceDb.connection.execute(sql)
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,44 @@
1
+ module Myreplicator
2
+ class VerticaTypes
3
+
4
+ def self.convert type, col_type
5
+ if mysql_vertica_conversion[type].blank?
6
+ return col_type
7
+ else
8
+ return mysql_vertica_conversion[type]
9
+ end
10
+ end
11
+
12
+ def self.mysql_vertica_conversion
13
+ map = {
14
+ "int" => "int",
15
+ "integer" => "int",
16
+ "int8" => "int",
17
+ "smallint" => "int",
18
+ "bigint" => "int",
19
+ "tinyint" => "int",
20
+ "numeric" => "int",
21
+ "text" => "VARCHAR(65000)",
22
+ "mediumtext" => "VARCHAR(65000)",
23
+ "bit" => "binary",
24
+ "longtext" => "VARCHAR(65000)",
25
+ "float" => "decimal"
26
+ }
27
+ end
28
+
29
+ def self.convert_key key
30
+ map = {
31
+ "UNI" => "UNIQUE",
32
+ " MUL" => "",
33
+ "PRI" => "PRIMARY KEY"
34
+ }
35
+
36
+ if map[key].blank?
37
+ return ""
38
+ else
39
+ return map[key]
40
+ end
41
+ end
42
+
43
+ end
44
+ end