hasten 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/LICENSE.txt +22 -0
- data/README.md +40 -0
- data/Rakefile +18 -0
- data/bin/hasten +17 -0
- data/lib/hasten.rb +9 -0
- data/lib/hasten/command.rb +50 -0
- data/lib/hasten/commands/classes.rb +10 -0
- data/lib/hasten/commands/insert.rb +11 -0
- data/lib/hasten/commands/other.rb +11 -0
- data/lib/hasten/commands/table.rb +45 -0
- data/lib/hasten/commands/view.rb +16 -0
- data/lib/hasten/dump.rb +82 -0
- data/lib/hasten/modes.rb +70 -0
- data/lib/hasten/version.rb +3 -0
- data/spec/command_spec.rb +80 -0
- data/spec/dump_spec.rb +101 -0
- data/spec/spec_helper.rb +6 -0
- data/spec/table_spec.rb +32 -0
- data/spec/view_spec.rb +26 -0
- metadata +98 -0
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
ZDI0OWQyMjE1ODRhNGJhNWNmY2Y3YmJjMzk3OTU1NzYxMmYxYWNmZQ==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
OGU2NDQ3Yjg1NDE4NTYzZmM2NDI1MjVjMDU0Mjg0ZTAxMzlmZTRhYg==
|
7
|
+
SHA512:
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
YmI2Njc3MDJlYTcyYTE3NDBhYzMzM2JkNjU4ODUxMmRiMmIzYTRjYWEzMDJi
|
10
|
+
Yjg1MDIzNjAyZmY4ZmRkM2I4ZDkyYzgyNzJiYzQ4ZmM2Mjg2MGQ2YTI3YjJj
|
11
|
+
ZjYxNjg3MWZiZTc0NTE1NDA0MmFiNjJlZTM5NDI5NGM4ZDRhNzM=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
NzIyZTg2ZjJhNmM5OTg2MTM1OGI0NjZkYmU4ZTc5ODVmNjM1ZDY4MjZjYmI5
|
14
|
+
ZDRjNTIzNmM4MzBiOWIwNzQyYjY2OTIxMzY2ZjA5Mzk1NmI4OGVmZWYyMWVh
|
15
|
+
ZDJlYmY2NzA0OWYxMWRmYWU0YTI3Mjk3ZGY2YzQ4NzhiODVkNDY=
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2015 Derrick Parkhurst
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
Hasten
|
2
|
+
===============
|
3
|
+
[![Gem Version](https://badge.fury.io/rb/hasten.svg)](http://badge.fury.io/rb/hasten)
|
4
|
+
[![Build Status](https://travis-ci.org/thirtysixthspan/hasten.svg?branch=master)](https://travis-ci.org/thirtysixthspan/hasten)
|
5
|
+
|
6
|
+
Overview
|
7
|
+
--------
|
8
|
+
|
9
|
+
Hasten speeds up the import of mysql dumps containing very large innodb tables with multiple indexes by setting certain mysql modes, removing all indexes from table definitions, and then altering the tables to add the indexes back once all inserts have been completed.
|
10
|
+
|
11
|
+
USAGE
|
12
|
+
-----
|
13
|
+
This gem provides an executable script `hasten` that can be used as follows to import SQL files exported from mysqldump.
|
14
|
+
```
|
15
|
+
cat DUMPFILE | hasten | mysql -uUSER -pPASSWORD DATABASE
|
16
|
+
```
|
17
|
+
|
18
|
+
License
|
19
|
+
-------
|
20
|
+
Copyright (c) 2015
|
21
|
+
Derrick Parkhurst (derrick.parkhurst@gmail.com),
|
22
|
+
|
23
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
24
|
+
of this software and associated documentation files (the "Software"), to deal
|
25
|
+
in the Software without restriction, including without limitation the rights
|
26
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
27
|
+
copies of the Software, and to permit persons to whom the Software is
|
28
|
+
furnished to do so, subject to the following conditions:
|
29
|
+
|
30
|
+
The above copyright notice and this permission notice shall be included in
|
31
|
+
all copies or substantial portions of the Software.
|
32
|
+
|
33
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
34
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
35
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
36
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
37
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
38
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
39
|
+
THE SOFTWARE.
|
40
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'rspec/core/rake_task'
|
2
|
+
require 'bundler/gem_tasks'
|
3
|
+
|
4
|
+
RSpec::Core::RakeTask.new(:spec)
|
5
|
+
|
6
|
+
task :default => :spec
|
7
|
+
|
8
|
+
namespace :gem do
|
9
|
+
|
10
|
+
task :build do
|
11
|
+
`gem build jiragit.gemspec`
|
12
|
+
end
|
13
|
+
|
14
|
+
task :install => [:build] do
|
15
|
+
`gem install pkg/jiragit*.gem`
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
data/bin/hasten
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# Hasten (speed up) the import of mysql dumps containing very large
|
3
|
+
# innodb tables with multiple indexes.
|
4
|
+
#
|
5
|
+
# Sets modes
|
6
|
+
# Indexes are removed from all table definitions.
|
7
|
+
# Indexes are added after all inserts are complete.
|
8
|
+
#
|
9
|
+
# usage:
|
10
|
+
# cat DUMPFILE | hasten | mysql -uroot DATABASE
|
11
|
+
#
|
12
|
+
require 'hasten'
|
13
|
+
|
14
|
+
|
15
|
+
Hasten::DEFAULT_MODES.each { |mode| puts mode }
|
16
|
+
Hasten::Dump.new(STDIN, STDOUT).execute
|
17
|
+
puts Hasten::COMMIT
|
data/lib/hasten.rb
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
require "hasten/version"
|
2
|
+
require "hasten/modes"
|
3
|
+
require "hasten/command"
|
4
|
+
require "hasten/commands/table"
|
5
|
+
require "hasten/commands/view"
|
6
|
+
require "hasten/commands/insert"
|
7
|
+
require "hasten/commands/other"
|
8
|
+
require "hasten/commands/classes"
|
9
|
+
require "hasten/dump"
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module Hasten
|
2
|
+
|
3
|
+
class Command < Array
|
4
|
+
|
5
|
+
def complete?
|
6
|
+
last.match(/;$/) ||
|
7
|
+
last.match(/^--/) ||
|
8
|
+
last.match(/^\s*$/)
|
9
|
+
end
|
10
|
+
|
11
|
+
def <<(items)
|
12
|
+
if items.respond_to? :each
|
13
|
+
items.each { |item| self.push item }
|
14
|
+
else
|
15
|
+
self.push items
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def type
|
20
|
+
COMMAND_CLASSES
|
21
|
+
.detect { |klass| klass.match?(sql) }
|
22
|
+
.to_s
|
23
|
+
.gsub(/^.*::/,'')
|
24
|
+
end
|
25
|
+
|
26
|
+
def sql
|
27
|
+
conditional ? extract : strip
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def squish
|
33
|
+
self.map(&:chomp).join(' ')
|
34
|
+
end
|
35
|
+
|
36
|
+
def strip
|
37
|
+
squish.gsub(/^\s+/,'').gsub(/;\s+$/,'')
|
38
|
+
end
|
39
|
+
|
40
|
+
def conditional
|
41
|
+
squish.match(/^\s*\/\*\![0-9]{5}\s+(.*?)\s*\*\//)
|
42
|
+
end
|
43
|
+
|
44
|
+
def extract
|
45
|
+
conditional[1]
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Hasten
|
2
|
+
|
3
|
+
class Table < Command
|
4
|
+
|
5
|
+
def self.match?(sql)
|
6
|
+
sql.match(/^CREATE\s+(TEMPORARY\s+)*TABLE/i)
|
7
|
+
end
|
8
|
+
|
9
|
+
def name
|
10
|
+
sql[/(?<=`).*?(?=`)/]
|
11
|
+
end
|
12
|
+
|
13
|
+
def without_indexes
|
14
|
+
revised = reject &index_line
|
15
|
+
revised[-2].gsub!(/,$/,'')
|
16
|
+
revised
|
17
|
+
end
|
18
|
+
|
19
|
+
def indexes
|
20
|
+
self
|
21
|
+
.select(&index_line)
|
22
|
+
.map{ |line| line.gsub(/^\s+/,'') }
|
23
|
+
.map{ |line| line.gsub(/,\s*$/,'') }
|
24
|
+
.map{ |line| line.chomp }
|
25
|
+
end
|
26
|
+
|
27
|
+
def index_statements
|
28
|
+
indexes
|
29
|
+
.map { |definition| "ALTER TABLE `#{name}` ADD #{definition};" }
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def index_line
|
35
|
+
->(line){
|
36
|
+
line.match(/^\s*(KEY|INDEX)/i) ||
|
37
|
+
line.match(/^\s*(FULLTEXT|SPATIAL)\s+(KEY|INDEX)/i) ||
|
38
|
+
line.match(/^\s*(UNIQUE|FOREIGN)\s+(KEY|INDEX)/i) ||
|
39
|
+
line.match(/^\s*CONSTRAINT.*?(UNIQUE|FOREIGN)\s+(KEY|INDEX)/i)
|
40
|
+
}
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
data/lib/hasten/dump.rb
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
module Hasten
|
2
|
+
|
3
|
+
class Dump
|
4
|
+
|
5
|
+
attr_accessor :command
|
6
|
+
|
7
|
+
def initialize(io_in, io_out)
|
8
|
+
@io_in = io_in
|
9
|
+
@io_out = io_out
|
10
|
+
end
|
11
|
+
|
12
|
+
def execute
|
13
|
+
while self.command = parse_command
|
14
|
+
dump_command
|
15
|
+
end
|
16
|
+
dump_indexes
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
attr_reader :io_in, :io_out
|
22
|
+
|
23
|
+
def tables
|
24
|
+
@tables ||= []
|
25
|
+
end
|
26
|
+
|
27
|
+
def views
|
28
|
+
@views ||= []
|
29
|
+
end
|
30
|
+
|
31
|
+
def parse_command
|
32
|
+
return unless line = io_in.gets
|
33
|
+
|
34
|
+
self.command = Command.new
|
35
|
+
self.command << line
|
36
|
+
return command if command.complete?
|
37
|
+
|
38
|
+
while line = io_in.gets
|
39
|
+
self.command << line
|
40
|
+
break if command.complete?
|
41
|
+
end
|
42
|
+
|
43
|
+
command
|
44
|
+
end
|
45
|
+
|
46
|
+
def dump_command
|
47
|
+
send("dump_#{command.type.to_s.downcase}")
|
48
|
+
end
|
49
|
+
|
50
|
+
def dump_table
|
51
|
+
tables << table = Table.new
|
52
|
+
table << command
|
53
|
+
io_out.puts table.without_indexes
|
54
|
+
end
|
55
|
+
|
56
|
+
def dump_view
|
57
|
+
views << view = View.new
|
58
|
+
view << command
|
59
|
+
io_out.puts view
|
60
|
+
end
|
61
|
+
|
62
|
+
def dump_insert
|
63
|
+
io_out.puts command
|
64
|
+
end
|
65
|
+
|
66
|
+
def dump_other
|
67
|
+
io_out.puts command
|
68
|
+
end
|
69
|
+
|
70
|
+
def dump_indexes
|
71
|
+
tables_not_overwritten_by_views.each do |table|
|
72
|
+
io_out.puts table.index_statements
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def tables_not_overwritten_by_views
|
77
|
+
tables.reject { |table| views.map(&:name).include?(table.name) }
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
data/lib/hasten/modes.rb
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
module Hasten
|
2
|
+
|
3
|
+
# By default, MySQL runs with autocommit mode enabled. This means that
|
4
|
+
# as soon as you execute a statement that updates (modifies) a table,
|
5
|
+
# MySQL stores the update on disk to make it permanent.
|
6
|
+
#
|
7
|
+
# To disable autocommit mode explicitly, use the following statement:
|
8
|
+
# SET autocommit=0;
|
9
|
+
# After disabling autocommit mode by setting the autocommit variable
|
10
|
+
# to zero, changes to transaction-safe tables (such as those for
|
11
|
+
# InnoDB, BDB, or NDBCLUSTER) are not made permanent immediately.
|
12
|
+
# You must use COMMIT to store your changes to disk or ROLLBACK to
|
13
|
+
# ignore the changes.
|
14
|
+
#
|
15
|
+
# From http://dev.mysql.com/doc/refman/5.0/en/commit.html
|
16
|
+
#
|
17
|
+
DISABLE_AUTOCOMMIT = "SET SESSION autocommit=0;"
|
18
|
+
COMMIT = "COMMIT;"
|
19
|
+
|
20
|
+
# If you have UNIQUE constraints on secondary keys, you can speed
|
21
|
+
# up a table import by turning off the uniqueness checks temporarily
|
22
|
+
# during the import operation:
|
23
|
+
# SET unique_checks=0;
|
24
|
+
# ... import operation ...
|
25
|
+
# SET unique_checks=1;
|
26
|
+
# For big tables, this saves a lot of disk I/O because InnoDB can then
|
27
|
+
# use its insert buffer to write secondary index records as a batch.
|
28
|
+
# Be certain that the data contains no duplicate keys.
|
29
|
+
#
|
30
|
+
# From http://dev.mysql.com/doc/refman/5.0/en/converting-tables-to-innodb.html
|
31
|
+
#
|
32
|
+
DISABLE_UNIQUENESS_CHECKS = "SET SESSION unique_checks=0;"
|
33
|
+
|
34
|
+
# To make it easier to reload dump files for tables that have foreign
|
35
|
+
# key relationships, mysqldump automatically includes a statement in
|
36
|
+
# the dump output to set foreign_key_checks to 0. This avoids problems
|
37
|
+
# with tables having to be reloaded in a particular order when the dump
|
38
|
+
# is reloaded. It is also possible to set this variable manually:
|
39
|
+
# mysql> SET foreign_key_checks = 0;
|
40
|
+
# mysql> SOURCE dump_file_name;
|
41
|
+
# mysql> SET foreign_key_checks = 1;
|
42
|
+
# This enables you to import the tables in any order if the dump file
|
43
|
+
# contains tables that are not correctly ordered for foreign keys. It
|
44
|
+
# also speeds up the import operation.
|
45
|
+
#
|
46
|
+
# From http://dev.mysql.com/doc/refman/5.1/en/create-table-foreign-keys.html
|
47
|
+
#
|
48
|
+
DISABLE_FOREIGN_KEY_CHECKS = "SET SESSION foreign_key_checks=0;"
|
49
|
+
|
50
|
+
# The sql_log_bin variable controls whether logging to the binary log
|
51
|
+
# is done. The default value is 1 (do logging). To change logging for
|
52
|
+
# the current session, change the session value of this variable. The
|
53
|
+
# session user must have the SUPER privilege to set this variable. Set
|
54
|
+
# this variable to 0 for a session to temporarily disable binary
|
55
|
+
# logging while making changes to the master which you do not want to
|
56
|
+
# replicate to the slave.
|
57
|
+
# SET sql_log_bin = {0|1}
|
58
|
+
#
|
59
|
+
# From http://dev.mysql.com/doc/refman/5.7/en/set-sql-log-bin.html
|
60
|
+
#
|
61
|
+
DISABLE_BINARY_LOGS = "SET SESSION sql_log_bin=0;"
|
62
|
+
|
63
|
+
DEFAULT_MODES = [
|
64
|
+
DISABLE_AUTOCOMMIT,
|
65
|
+
DISABLE_UNIQUENESS_CHECKS,
|
66
|
+
DISABLE_FOREIGN_KEY_CHECKS,
|
67
|
+
DISABLE_BINARY_LOGS
|
68
|
+
]
|
69
|
+
|
70
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require './spec/spec_helper'
|
2
|
+
|
3
|
+
describe Hasten::Command do
|
4
|
+
|
5
|
+
it "strips whitespace from sql" do
|
6
|
+
subject << " SET TIME_ZONE='+00:00'; "
|
7
|
+
expect(subject.sql).to eq "SET TIME_ZONE='+00:00'"
|
8
|
+
end
|
9
|
+
|
10
|
+
it "extracts conditional sql" do
|
11
|
+
subject << "/*!40103 SET TIME_ZONE='+00:00' */;"
|
12
|
+
expect(subject.sql).to eq "SET TIME_ZONE='+00:00'"
|
13
|
+
end
|
14
|
+
|
15
|
+
it "considers comments complete" do
|
16
|
+
subject << "-- Server version 5.6.22"
|
17
|
+
expect(subject.complete?).to be_true
|
18
|
+
end
|
19
|
+
|
20
|
+
it "considers semicolon terminated lines complete" do
|
21
|
+
subject << "DROP TABLE IF EXISTS `test`;"
|
22
|
+
expect(subject.complete?).to be_true
|
23
|
+
end
|
24
|
+
|
25
|
+
it "considers lines without semicolons incomplete" do
|
26
|
+
subject << "DROP TABLE IF EXISTS `test`"
|
27
|
+
expect(subject.complete?).to be_false
|
28
|
+
end
|
29
|
+
|
30
|
+
it "parses multiline sql" do
|
31
|
+
subject << <<-EOC
|
32
|
+
SELECT *
|
33
|
+
FROM `test`
|
34
|
+
WHERE c1 = 'name';
|
35
|
+
EOC
|
36
|
+
expect(subject.complete?).to be_true
|
37
|
+
end
|
38
|
+
|
39
|
+
it "identifies Table definitions" do
|
40
|
+
subject << <<-EOC
|
41
|
+
CREATE TABLE `test` (
|
42
|
+
`id` int(11) NOT NULL AUTO_INCREMENT,
|
43
|
+
`q1` int(11) DEFAULT NULL,
|
44
|
+
`q2` int(11) DEFAULT NULL,
|
45
|
+
PRIMARY KEY (`id`),
|
46
|
+
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
|
47
|
+
EOC
|
48
|
+
expect(subject.type).to eq('Table')
|
49
|
+
end
|
50
|
+
|
51
|
+
it "identifies View definitions" do
|
52
|
+
subject << <<-EOC
|
53
|
+
CREATE VIEW `test` AS
|
54
|
+
SELECT * FROM `section1`
|
55
|
+
UNION
|
56
|
+
SELECT * FROM `section2`;
|
57
|
+
EOC
|
58
|
+
expect(subject.type).to eq('View')
|
59
|
+
end
|
60
|
+
|
61
|
+
it "identifies Insert statements" do
|
62
|
+
subject << <<-EOC
|
63
|
+
INSERT INTO `contact_fields` VALUES
|
64
|
+
(1,'Name',0),
|
65
|
+
(2,'Address',0),
|
66
|
+
(3,'Phone',0);
|
67
|
+
EOC
|
68
|
+
expect(subject.type).to eq('Insert')
|
69
|
+
end
|
70
|
+
|
71
|
+
it "accepts other commands" do
|
72
|
+
command1 = Hasten::Command.new
|
73
|
+
command1 << "line 1"
|
74
|
+
command1 << "line 2"
|
75
|
+
command2 = Hasten::Command.new
|
76
|
+
command2 << command1
|
77
|
+
expect(command2.sql).to eq command1.sql
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
data/spec/dump_spec.rb
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
require './spec/spec_helper'
|
2
|
+
|
3
|
+
describe Hasten::Dump do
|
4
|
+
|
5
|
+
context "with indexed tables" do
|
6
|
+
|
7
|
+
let(:in_io) {
|
8
|
+
StringIO.new(<<-EOS)
|
9
|
+
CREATE TABLE `test` (
|
10
|
+
`id` int(11) NOT NULL AUTO_INCREMENT,
|
11
|
+
`q1` int(11) DEFAULT NULL,
|
12
|
+
`q2` int(11) DEFAULT NULL,
|
13
|
+
PRIMARY KEY (`id`),
|
14
|
+
KEY `q1_idx` (`q1`),
|
15
|
+
KEY `q1_q2_idx` (`q1`,`q2`)
|
16
|
+
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
|
17
|
+
EOS
|
18
|
+
}
|
19
|
+
|
20
|
+
let(:out_io) { StringIO.new }
|
21
|
+
|
22
|
+
before do
|
23
|
+
described_class.new(in_io,out_io).execute
|
24
|
+
end
|
25
|
+
|
26
|
+
it "shifts indexes to the end of the dump" do
|
27
|
+
expect(out_io.string).to include "ALTER TABLE `test` ADD KEY `q1_idx` (`q1`);"
|
28
|
+
end
|
29
|
+
|
30
|
+
it "removes indexes from the table definition" do
|
31
|
+
expect(squish out_io.string).to include (squish <<-EOS)
|
32
|
+
CREATE TABLE `test` (
|
33
|
+
`id` int(11) NOT NULL AUTO_INCREMENT,
|
34
|
+
`q1` int(11) DEFAULT NULL,
|
35
|
+
`q2` int(11) DEFAULT NULL,
|
36
|
+
PRIMARY KEY (`id`)
|
37
|
+
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
|
38
|
+
EOS
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
|
43
|
+
context "with insert statements" do
|
44
|
+
|
45
|
+
let(:in_io) {
|
46
|
+
StringIO.new(<<-EOS)
|
47
|
+
CREATE TABLE `test` (
|
48
|
+
`id` int(11) NOT NULL AUTO_INCREMENT,
|
49
|
+
`q1` int(11) DEFAULT NULL,
|
50
|
+
`q2` int(11) DEFAULT NULL,
|
51
|
+
PRIMARY KEY (`id`)
|
52
|
+
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
|
53
|
+
INSERT INTO `test` VALUES
|
54
|
+
(1,1,2),
|
55
|
+
(2,3,4),
|
56
|
+
(3,5,6);
|
57
|
+
EOS
|
58
|
+
}
|
59
|
+
|
60
|
+
let(:out_io) { StringIO.new }
|
61
|
+
|
62
|
+
before do
|
63
|
+
described_class.new(in_io,out_io).execute
|
64
|
+
end
|
65
|
+
|
66
|
+
it "passes insert statement unmodified" do
|
67
|
+
expect(squish out_io.string).to include (squish <<-EOS)
|
68
|
+
INSERT INTO `test` VALUES
|
69
|
+
(1,1,2),
|
70
|
+
(2,3,4),
|
71
|
+
(3,5,6);
|
72
|
+
EOS
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
|
77
|
+
context "with views" do
|
78
|
+
|
79
|
+
let(:in_io) {
|
80
|
+
StringIO.new(<<-EOS)
|
81
|
+
VIEW `test` AS
|
82
|
+
SELECT `section1`.`q1`,`section2`.`q2`
|
83
|
+
FROM `test`
|
84
|
+
JOIN `section1s` ON `test`.`section1_id` = `section1s`.`id`
|
85
|
+
JOIN `section2s` ON `test`.`section2_id` = `section2s`.`id`
|
86
|
+
EOS
|
87
|
+
}
|
88
|
+
|
89
|
+
let(:out_io) { StringIO.new }
|
90
|
+
|
91
|
+
before do
|
92
|
+
described_class.new(in_io,out_io).execute
|
93
|
+
end
|
94
|
+
|
95
|
+
it "passes insert statement unmodified" do
|
96
|
+
expect(squish out_io.string).to include (squish in_io.string)
|
97
|
+
end
|
98
|
+
|
99
|
+
end
|
100
|
+
|
101
|
+
end
|
data/spec/spec_helper.rb
ADDED
data/spec/table_spec.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
require './spec/spec_helper'
|
2
|
+
|
3
|
+
describe Hasten::Table do
|
4
|
+
|
5
|
+
it "identifies delimited table names" do
|
6
|
+
subject << <<-EOC
|
7
|
+
CREATE TABLE `test` (
|
8
|
+
`id` int(11) NOT NULL AUTO_INCREMENT,
|
9
|
+
`q1` int(11) DEFAULT NULL,
|
10
|
+
`q2` int(11) DEFAULT NULL,
|
11
|
+
PRIMARY KEY (`id`),
|
12
|
+
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
|
13
|
+
EOC
|
14
|
+
expect(subject.name).to eq('test')
|
15
|
+
end
|
16
|
+
|
17
|
+
it "identifies indexes" do
|
18
|
+
subject << [
|
19
|
+
"CREATE TABLE `test` (",
|
20
|
+
" `id` int(11) NOT NULL AUTO_INCREMENT,",
|
21
|
+
" `q1` int(11) DEFAULT NULL,",
|
22
|
+
" `q2` int(11) DEFAULT NULL,",
|
23
|
+
" PRIMARY KEY (`id`),",
|
24
|
+
" KEY `q1_idx` (`q1`),",
|
25
|
+
" KEY `q1_q2_idx` (`q1`,`q2`)",
|
26
|
+
") ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;"
|
27
|
+
]
|
28
|
+
expect(subject.indexes.first).to eq "KEY `q1_idx` (`q1`)"
|
29
|
+
expect(subject.indexes.last).to eq "KEY `q1_q2_idx` (`q1`,`q2`)"
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
data/spec/view_spec.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
require './spec/spec_helper'
|
2
|
+
|
3
|
+
describe Hasten::View do
|
4
|
+
|
5
|
+
it "identifies delimited view names" do
|
6
|
+
subject << <<-EOC
|
7
|
+
CREATE VIEW `test` AS
|
8
|
+
SELECT * FROM `section1`
|
9
|
+
UNION
|
10
|
+
SELECT * FROM `section2`;
|
11
|
+
EOC
|
12
|
+
expect(subject.name).to eq('test')
|
13
|
+
end
|
14
|
+
|
15
|
+
it "identifies delimited view names for alternative syntax" do
|
16
|
+
subject << <<-EOC
|
17
|
+
VIEW `test` AS
|
18
|
+
SELECT `section1`.`q1`,`section2`.`q2`
|
19
|
+
FROM `test`
|
20
|
+
JOIN `section1s` ON `test`.`section1_id` = `section1s`.`id`
|
21
|
+
JOIN `section2s` ON `test`.`section2_id` = `section2s`.`id`
|
22
|
+
EOC
|
23
|
+
expect(subject.name).to eq('test')
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
metadata
ADDED
@@ -0,0 +1,98 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: hasten
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Derrick Parkhurst
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-01-11 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.7'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.7'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ~>
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ~>
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
description: Hasten the import of mysql dumps, especially those containing very large
|
42
|
+
innodb tables with multiple indexes.
|
43
|
+
email:
|
44
|
+
- derrick.parkhurst@gmail.com
|
45
|
+
executables:
|
46
|
+
- hasten
|
47
|
+
extensions: []
|
48
|
+
extra_rdoc_files: []
|
49
|
+
files:
|
50
|
+
- LICENSE.txt
|
51
|
+
- README.md
|
52
|
+
- Rakefile
|
53
|
+
- bin/hasten
|
54
|
+
- lib/hasten.rb
|
55
|
+
- lib/hasten/command.rb
|
56
|
+
- lib/hasten/commands/classes.rb
|
57
|
+
- lib/hasten/commands/insert.rb
|
58
|
+
- lib/hasten/commands/other.rb
|
59
|
+
- lib/hasten/commands/table.rb
|
60
|
+
- lib/hasten/commands/view.rb
|
61
|
+
- lib/hasten/dump.rb
|
62
|
+
- lib/hasten/modes.rb
|
63
|
+
- lib/hasten/version.rb
|
64
|
+
- spec/command_spec.rb
|
65
|
+
- spec/dump_spec.rb
|
66
|
+
- spec/spec_helper.rb
|
67
|
+
- spec/table_spec.rb
|
68
|
+
- spec/view_spec.rb
|
69
|
+
homepage: http://github.com/thirtysixthspan/hasten
|
70
|
+
licenses:
|
71
|
+
- MIT
|
72
|
+
metadata: {}
|
73
|
+
post_install_message:
|
74
|
+
rdoc_options: []
|
75
|
+
require_paths:
|
76
|
+
- lib
|
77
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - ! '>='
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: '0'
|
82
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
83
|
+
requirements:
|
84
|
+
- - ! '>='
|
85
|
+
- !ruby/object:Gem::Version
|
86
|
+
version: '0'
|
87
|
+
requirements: []
|
88
|
+
rubyforge_project:
|
89
|
+
rubygems_version: 2.4.5
|
90
|
+
signing_key:
|
91
|
+
specification_version: 4
|
92
|
+
summary: Hasten the import of mysqldumps dumps
|
93
|
+
test_files:
|
94
|
+
- spec/command_spec.rb
|
95
|
+
- spec/dump_spec.rb
|
96
|
+
- spec/spec_helper.rb
|
97
|
+
- spec/table_spec.rb
|
98
|
+
- spec/view_spec.rb
|