activerecord-import 0.3.1 → 0.4.0
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 +7 -0
- data/.gitignore +31 -0
- data/Brewfile +3 -0
- data/Gemfile +39 -0
- data/Rakefile +1 -24
- data/activerecord-import.gemspec +22 -0
- data/benchmarks/README +32 -0
- data/benchmarks/benchmark.rb +64 -0
- data/benchmarks/boot.rb +18 -0
- data/benchmarks/lib/base.rb +137 -0
- data/benchmarks/lib/cli_parser.rb +103 -0
- data/benchmarks/lib/float.rb +15 -0
- data/benchmarks/lib/mysql_benchmark.rb +22 -0
- data/benchmarks/lib/output_to_csv.rb +18 -0
- data/benchmarks/lib/output_to_html.rb +69 -0
- data/benchmarks/models/test_innodb.rb +3 -0
- data/benchmarks/models/test_memory.rb +3 -0
- data/benchmarks/models/test_myisam.rb +3 -0
- data/benchmarks/schema/mysql_schema.rb +16 -0
- data/gemfiles/3.1.gemfile +4 -0
- data/gemfiles/3.2.gemfile +4 -0
- data/gemfiles/4.0.gemfile +4 -0
- data/lib/activerecord-import/active_record/adapters/abstract_adapter.rb +0 -1
- data/lib/activerecord-import/active_record/adapters/em_mysql2_adapter.rb +8 -0
- data/lib/activerecord-import/adapters/abstract_adapter.rb +5 -58
- data/lib/activerecord-import/adapters/em_mysql2_adapter.rb +5 -0
- data/lib/activerecord-import/adapters/mysql_adapter.rb +50 -3
- data/lib/activerecord-import/adapters/sqlite3_adapter.rb +28 -3
- data/lib/activerecord-import/base.rb +3 -2
- data/lib/activerecord-import/em_mysql2.rb +7 -0
- data/lib/activerecord-import/import.rb +29 -29
- data/lib/activerecord-import/synchronize.rb +11 -10
- data/lib/activerecord-import/value_sets_parser.rb +54 -0
- data/lib/activerecord-import/version.rb +5 -0
- data/test/adapters/em_mysql2.rb +1 -0
- data/test/adapters/jdbcmysql.rb +1 -0
- data/test/adapters/mysql.rb +1 -0
- data/test/adapters/mysql2.rb +1 -0
- data/test/adapters/mysql2spatial.rb +1 -0
- data/test/adapters/mysqlspatial.rb +1 -0
- data/test/adapters/postgis.rb +1 -0
- data/test/adapters/postgresql.rb +1 -0
- data/test/adapters/seamless_database_pool.rb +1 -0
- data/test/adapters/spatialite.rb +1 -0
- data/test/adapters/sqlite3.rb +1 -0
- data/test/database.yml.sample +57 -0
- data/test/em_mysql2/import_test.rb +6 -0
- data/test/import_test.rb +350 -0
- data/test/jdbcmysql/import_test.rb +6 -0
- data/test/models/book.rb +3 -0
- data/test/models/group.rb +3 -0
- data/test/models/topic.rb +7 -0
- data/test/models/widget.rb +7 -0
- data/test/mysql/import_test.rb +6 -0
- data/test/mysql2/import_test.rb +6 -0
- data/test/mysqlspatial/import_test.rb +6 -0
- data/test/mysqlspatial2/import_test.rb +6 -0
- data/test/postgis/import_test.rb +4 -0
- data/test/postgresql/import_test.rb +4 -0
- data/test/schema/generic_schema.rb +104 -0
- data/test/schema/mysql_schema.rb +17 -0
- data/test/schema/version.rb +10 -0
- data/test/sqlite3/import_test.rb +52 -0
- data/test/support/active_support/test_case_extensions.rb +67 -0
- data/test/support/factories.rb +19 -0
- data/test/support/generate.rb +29 -0
- data/test/support/mysql/assertions.rb +55 -0
- data/test/support/mysql/import_examples.rb +147 -0
- data/test/support/postgresql/import_examples.rb +21 -0
- data/test/synchronize_test.rb +22 -0
- data/test/test_helper.rb +48 -0
- data/test/value_sets_bytes_parser_test.rb +96 -0
- data/test/value_sets_records_parser_test.rb +32 -0
- metadata +120 -58
- data/VERSION +0 -1
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: b643c184e9c5ecb05a667d0845794f7a5282417d
|
4
|
+
data.tar.gz: f02c166d88df6237b5ca09350d85a6fbd41927d5
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 22c96aa8eed0dc9594b7e7bc0592266506c7a4c93bbe2d5cbb0b08550728a00a91e95deb9adf087c5a74008f1fecc93588a603402d91ce70b44fd6f2495b5fa6
|
7
|
+
data.tar.gz: caf4b4f41c6e34f55d340f43d1fa82e5b33dd1dfb52d27970ad61d29a478b2988d310521a0aac580d76a26ef269f967f06c7baf828b89da4948dd028d9c5e950
|
data/.gitignore
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
## MAC OS
|
2
|
+
.DS_Store
|
3
|
+
|
4
|
+
## TEXTMATE
|
5
|
+
*.tmproj
|
6
|
+
tmtags
|
7
|
+
|
8
|
+
## EMACS
|
9
|
+
*~
|
10
|
+
\#*
|
11
|
+
.\#*
|
12
|
+
|
13
|
+
## VIM
|
14
|
+
*.swp
|
15
|
+
|
16
|
+
## PROJECT::GENERAL
|
17
|
+
coverage
|
18
|
+
rdoc
|
19
|
+
pkg
|
20
|
+
*.gem
|
21
|
+
*.lock
|
22
|
+
|
23
|
+
## PROJECT::SPECIFIC
|
24
|
+
log/*.log
|
25
|
+
test.db
|
26
|
+
test/database.yml
|
27
|
+
|
28
|
+
.bundle/
|
29
|
+
.redcar/
|
30
|
+
.rvmrc
|
31
|
+
docsite/
|
data/Brewfile
ADDED
data/Gemfile
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
|
3
|
+
gemspec
|
4
|
+
|
5
|
+
# Database Adapters
|
6
|
+
platforms :ruby do
|
7
|
+
gem "em-synchrony", "~> 1.0.3"
|
8
|
+
gem "mysql2", "~> 0.3.0"
|
9
|
+
gem "pg", "~> 0.9"
|
10
|
+
gem "sqlite3-ruby", "~> 1.3.1"
|
11
|
+
gem "seamless_database_pool", "~> 1.0.13"
|
12
|
+
end
|
13
|
+
|
14
|
+
platforms :jruby do
|
15
|
+
gem "jdbc-mysql"
|
16
|
+
gem "activerecord-jdbcmysql-adapter"
|
17
|
+
end
|
18
|
+
|
19
|
+
# Support libs
|
20
|
+
gem "factory_girl", "~> 4.2.0"
|
21
|
+
gem "delorean", "~> 0.2.0"
|
22
|
+
|
23
|
+
# Debugging
|
24
|
+
platforms :mri_18 do
|
25
|
+
gem "ruby-debug", "= 0.10.4"
|
26
|
+
end
|
27
|
+
|
28
|
+
platforms :jruby do
|
29
|
+
gem "ruby-debug-base", "= 0.10.4"
|
30
|
+
gem "ruby-debug", "= 0.10.4"
|
31
|
+
end
|
32
|
+
|
33
|
+
platforms :mri_19 do
|
34
|
+
gem "debugger"
|
35
|
+
end
|
36
|
+
|
37
|
+
version = ENV['RAILS_VERSION'] || "3.2"
|
38
|
+
|
39
|
+
eval_gemfile File.expand_path("../gemfiles/#{version}.gemfile", __FILE__)
|
data/Rakefile
CHANGED
@@ -4,29 +4,6 @@ Bundler.setup
|
|
4
4
|
require 'rake'
|
5
5
|
require 'rake/testtask'
|
6
6
|
|
7
|
-
begin
|
8
|
-
require 'jeweler'
|
9
|
-
Jeweler::Tasks.new do |gem|
|
10
|
-
gem.name = "activerecord-import"
|
11
|
-
gem.summary = %Q{Bulk-loading extension for ActiveRecord}
|
12
|
-
gem.description = %Q{Extraction of the ActiveRecord::Base#import functionality from ar-extensions for Rails 3 and beyond}
|
13
|
-
gem.email = "zach.dennis@gmail.com"
|
14
|
-
gem.homepage = "http://github.com/zdennis/activerecord-import"
|
15
|
-
gem.authors = ["Zach Dennis"]
|
16
|
-
gem.files = FileList["VERSION", "Rakefile", "README*", "lib/**/*"]
|
17
|
-
|
18
|
-
bundler = Bundler.load
|
19
|
-
bundler.dependencies_for(:default).each do |dependency|
|
20
|
-
gem.add_dependency dependency.name, *dependency.requirements_list
|
21
|
-
end
|
22
|
-
|
23
|
-
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
24
|
-
end
|
25
|
-
Jeweler::GemcutterTasks.new
|
26
|
-
rescue LoadError
|
27
|
-
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
28
|
-
end
|
29
|
-
|
30
7
|
namespace :display do
|
31
8
|
task :notice do
|
32
9
|
puts
|
@@ -36,7 +13,7 @@ namespace :display do
|
|
36
13
|
end
|
37
14
|
task :default => ["display:notice"]
|
38
15
|
|
39
|
-
ADAPTERS = %w(mysql mysql2 jdbcmysql postgresql sqlite3 seamless_database_pool mysqlspatial mysql2spatial spatialite postgis)
|
16
|
+
ADAPTERS = %w(mysql mysql2 em_mysql2 jdbcmysql postgresql sqlite3 seamless_database_pool mysqlspatial mysql2spatial spatialite postgis)
|
40
17
|
ADAPTERS.each do |adapter|
|
41
18
|
namespace :test do
|
42
19
|
desc "Runs #{adapter} database tests."
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/activerecord-import/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.authors = ["Zach Dennis"]
|
6
|
+
gem.email = ["zach.dennis@gmail.com"]
|
7
|
+
gem.summary = "Bulk-loading extension for ActiveRecord"
|
8
|
+
gem.description = "Extraction of the ActiveRecord::Base#import functionality from ar-extensions for Rails 3 and beyond"
|
9
|
+
gem.homepage = "http://github.com/zdennis/activerecord-import"
|
10
|
+
|
11
|
+
gem.files = `git ls-files`.split($\)
|
12
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
13
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
14
|
+
gem.name = "activerecord-import"
|
15
|
+
gem.require_paths = ["lib"]
|
16
|
+
gem.version = ActiveRecord::Import::VERSION
|
17
|
+
|
18
|
+
gem.required_ruby_version = ">= 1.9.2"
|
19
|
+
|
20
|
+
gem.add_runtime_dependency "activerecord", ">= 3.0"
|
21
|
+
gem.add_development_dependency "rake"
|
22
|
+
end
|
data/benchmarks/README
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
To run the benchmarks, from within the benchmarks run:
|
2
|
+
ruby benchmark.rb [options]
|
3
|
+
|
4
|
+
The following options are supported:
|
5
|
+
--adapter [String] The database adapter to use. IE: mysql, postgresql, oracle
|
6
|
+
|
7
|
+
--do-not-delete By default all records in the benchmark tables will be deleted at the end of the benchmark. This flag indicates not to delete the benchmark data.
|
8
|
+
--num [Integer] The number of objects to benchmark. (Required!)
|
9
|
+
--table-type [String] The table type to test. This can be used multiple times. By default it is all table types.
|
10
|
+
--to-csv [String] Print results in a CSV file format
|
11
|
+
--to-html [String] Print results in HTML format (String filename must be supplied)
|
12
|
+
|
13
|
+
See "ruby benchmark.rb -h" for the complete listing of options.
|
14
|
+
|
15
|
+
EXAMPLES
|
16
|
+
--------
|
17
|
+
To output to html format:
|
18
|
+
ruby benchmark.rb --adapter=mysql --to-html=results.html
|
19
|
+
|
20
|
+
To output to csv format:
|
21
|
+
ruby benchmark.rb --adapter=mysql --to-csv=results.csv
|
22
|
+
|
23
|
+
LIMITATIONS
|
24
|
+
-----------
|
25
|
+
Currently MySQL is the only supported adapter to benchmark.
|
26
|
+
|
27
|
+
AUTHOR
|
28
|
+
------
|
29
|
+
Zach Dennis
|
30
|
+
zach.dennis@gmail.com
|
31
|
+
http://www.continuousthinking.com
|
32
|
+
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require "pathname"
|
2
|
+
this_dir = Pathname.new File.dirname(__FILE__)
|
3
|
+
require this_dir.join('boot')
|
4
|
+
|
5
|
+
# Parse the options passed in via the command line
|
6
|
+
options = BenchmarkOptionParser.parse( ARGV )
|
7
|
+
|
8
|
+
# The support directory where we use to load our connections and models for the
|
9
|
+
# benchmarks.
|
10
|
+
SUPPORT_DIR = this_dir.join('../test')
|
11
|
+
|
12
|
+
# Load the database adapter
|
13
|
+
adapter = options.adapter
|
14
|
+
|
15
|
+
# load the library
|
16
|
+
LIB_DIR = this_dir.join("../lib")
|
17
|
+
require LIB_DIR.join("activerecord-import/#{adapter}")
|
18
|
+
|
19
|
+
ActiveRecord::Base.logger = Logger.new("log/test.log")
|
20
|
+
ActiveRecord::Base.logger.level = Logger::DEBUG
|
21
|
+
ActiveRecord::Base.configurations["test"] = YAML.load(SUPPORT_DIR.join("database.yml").open)[adapter]
|
22
|
+
ActiveRecord::Base.establish_connection "test"
|
23
|
+
|
24
|
+
ActiveSupport::Notifications.subscribe(/active_record.sql/) do |event, _, _, _, hsh|
|
25
|
+
ActiveRecord::Base.logger.info hsh[:sql]
|
26
|
+
end
|
27
|
+
|
28
|
+
adapter_schema = SUPPORT_DIR.join("schema/#{adapter}_schema.rb")
|
29
|
+
require adapter_schema if File.exists?(adapter_schema)
|
30
|
+
Dir[this_dir.join("models/*.rb")].each{ |file| require file }
|
31
|
+
|
32
|
+
# Load databse specific benchmarks
|
33
|
+
require File.join( File.dirname( __FILE__ ), 'lib', "#{adapter}_benchmark" )
|
34
|
+
|
35
|
+
# TODO implement method/table-type selection
|
36
|
+
table_types = nil
|
37
|
+
if options.benchmark_all_types
|
38
|
+
table_types = [ "all" ]
|
39
|
+
else
|
40
|
+
table_types = options.table_types.keys
|
41
|
+
end
|
42
|
+
puts
|
43
|
+
|
44
|
+
letter = options.adapter[0].chr
|
45
|
+
clazz_str = letter.upcase + options.adapter[1..-1].downcase
|
46
|
+
clazz = Object.const_get( clazz_str + "Benchmark" )
|
47
|
+
|
48
|
+
benchmarks = []
|
49
|
+
options.number_of_objects.each do |num|
|
50
|
+
benchmarks << (benchmark = clazz.new)
|
51
|
+
benchmark.send( "benchmark", table_types, num )
|
52
|
+
end
|
53
|
+
|
54
|
+
options.outputs.each do |output|
|
55
|
+
format = output.format.downcase
|
56
|
+
output_module = Object.const_get( "OutputTo#{format.upcase}" )
|
57
|
+
benchmarks.each do |benchmark|
|
58
|
+
output_module.output_results( output.filename, benchmark.results )
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
puts
|
63
|
+
puts "Done with benchmark!"
|
64
|
+
|
data/benchmarks/boot.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
begin ; require 'rubygems' ; rescue LoadError ; end
|
2
|
+
require 'active_record' # ActiveRecord loads the Benchmark library automatically
|
3
|
+
require 'active_record/version'
|
4
|
+
require 'fastercsv'
|
5
|
+
require 'fileutils'
|
6
|
+
require 'logger'
|
7
|
+
|
8
|
+
# Files are loaded alphabetically. If this is a problem then manually specify the files
|
9
|
+
# that need to be loaded here.
|
10
|
+
Dir[ File.join( File.dirname( __FILE__ ), 'lib', '*.rb' ) ].sort.each{ |f| require f }
|
11
|
+
|
12
|
+
ActiveRecord::Base.logger = Logger.new STDOUT
|
13
|
+
|
14
|
+
|
15
|
+
|
16
|
+
|
17
|
+
|
18
|
+
|
@@ -0,0 +1,137 @@
|
|
1
|
+
class BenchmarkBase
|
2
|
+
|
3
|
+
attr_reader :results
|
4
|
+
|
5
|
+
# The main benchmark method dispatcher. This dispatches the benchmarks
|
6
|
+
# to actual benchmark_xxxx methods.
|
7
|
+
#
|
8
|
+
# == PARAMETERS
|
9
|
+
# * table_types - an array of table types to benchmark
|
10
|
+
# * num - the number of record insertions to test
|
11
|
+
def benchmark( table_types, num )
|
12
|
+
array_of_cols_and_vals = build_array_of_cols_and_vals( num )
|
13
|
+
table_types.each do |table_type|
|
14
|
+
self.send( "benchmark_#{table_type}", array_of_cols_and_vals )
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
# Returns an OpenStruct which contains two attritues, +description+ and +tms+ after performing an
|
19
|
+
# actual benchmark.
|
20
|
+
#
|
21
|
+
# == PARAMETERS
|
22
|
+
# * description - the description of the block that is getting benchmarked
|
23
|
+
# * blk - the block of code to benchmark
|
24
|
+
#
|
25
|
+
# == RETURNS
|
26
|
+
# An OpenStruct object with the following attributes:
|
27
|
+
# * description - the description of the benchmark ran
|
28
|
+
# * tms - a Benchmark::Tms containing the results of the benchmark
|
29
|
+
def bm( description, &blk )
|
30
|
+
tms = nil
|
31
|
+
puts "Benchmarking #{description}"
|
32
|
+
|
33
|
+
Benchmark.bm { |x| tms = x.report { blk.call } }
|
34
|
+
delete_all
|
35
|
+
failed = false
|
36
|
+
|
37
|
+
OpenStruct.new :description=>description, :tms=>tms, :failed=>failed
|
38
|
+
end
|
39
|
+
|
40
|
+
# Given a model class (ie: Topic), and an array of columns and value sets
|
41
|
+
# this will perform all of the benchmarks necessary for this library.
|
42
|
+
#
|
43
|
+
# == PARAMETERS
|
44
|
+
# * model_clazz - the model class to benchmark (ie: Topic)
|
45
|
+
# * array_of_cols_and_vals - an array of column identifiers and value sets
|
46
|
+
#
|
47
|
+
# == RETURNS
|
48
|
+
# returns true
|
49
|
+
def bm_model( model_clazz, array_of_cols_and_vals )
|
50
|
+
puts
|
51
|
+
puts "------ Benchmarking #{model_clazz.name} -------"
|
52
|
+
|
53
|
+
cols,vals = array_of_cols_and_vals
|
54
|
+
num_inserts = vals.size
|
55
|
+
|
56
|
+
# add a new result group for this particular benchmark
|
57
|
+
group = []
|
58
|
+
@results << group
|
59
|
+
|
60
|
+
description = "#{model_clazz.name}.create (#{num_inserts} records)"
|
61
|
+
group << bm( description ) {
|
62
|
+
vals.each do |values|
|
63
|
+
model_clazz.create create_hash_for_cols_and_vals( cols, values )
|
64
|
+
end }
|
65
|
+
|
66
|
+
description = "#{model_clazz.name}.import(column, values) for #{num_inserts} records with validations"
|
67
|
+
group << bm( description ) { model_clazz.import cols, vals, :validate=>true }
|
68
|
+
|
69
|
+
description = "#{model_clazz.name}.import(columns, values) for #{num_inserts} records without validations"
|
70
|
+
group << bm( description ) { model_clazz.import cols, vals, :validate=>false }
|
71
|
+
|
72
|
+
models = []
|
73
|
+
array_of_attrs = []
|
74
|
+
|
75
|
+
vals.each do |arr|
|
76
|
+
array_of_attrs << (attrs={})
|
77
|
+
arr.each_with_index { |value, i| attrs[cols[i]] = value }
|
78
|
+
end
|
79
|
+
array_of_attrs.each{ |attrs| models << model_clazz.new(attrs) }
|
80
|
+
|
81
|
+
description = "#{model_clazz.name}.import(models) for #{num_inserts} records with validations"
|
82
|
+
group << bm( description ) { model_clazz.import models, :validate=>true }
|
83
|
+
|
84
|
+
description = "#{model_clazz.name}.import(models) for #{num_inserts} records without validations"
|
85
|
+
group << bm( description ) { model_clazz.import models, :validate=>false }
|
86
|
+
|
87
|
+
true
|
88
|
+
end
|
89
|
+
|
90
|
+
# Returns a two element array composing of an array of columns and an array of
|
91
|
+
# value sets given the passed +num+.
|
92
|
+
#
|
93
|
+
# === What is a value set?
|
94
|
+
# A value set is an array of arrays. Each child array represents an array of value sets
|
95
|
+
# for a given row of data.
|
96
|
+
#
|
97
|
+
# For example, say we wanted to represent an insertion of two records:
|
98
|
+
# column_names = [ 'id', 'name', 'description' ]
|
99
|
+
# record1 = [ 1, 'John Doe', 'A plumber' ]
|
100
|
+
# record2 = [ 2, 'John Smith', 'A painter' ]
|
101
|
+
# value_set [ record1, record2 ]
|
102
|
+
#
|
103
|
+
# == PARAMETER
|
104
|
+
# * num - the number of records to create
|
105
|
+
def build_array_of_cols_and_vals( num )
|
106
|
+
cols = [ :my_name, :description ]
|
107
|
+
value_sets = []
|
108
|
+
num.times { |i| value_sets << [ "My Name #{i}", "My Description #{i}" ] }
|
109
|
+
[ cols, value_sets ]
|
110
|
+
end
|
111
|
+
|
112
|
+
# Returns a hash of column identifier to value mappings giving the passed in
|
113
|
+
# value array.
|
114
|
+
#
|
115
|
+
# Example:
|
116
|
+
# cols = [ 'id', 'name', 'description' ]
|
117
|
+
# values = [ 1, 'John Doe', 'A plumber' ]
|
118
|
+
# hsh = create_hash_for_cols_and_vals( cols, values )
|
119
|
+
# # hsh => { 'id'=>1, 'name'=>'John Doe', 'description'=>'A plumber' }
|
120
|
+
def create_hash_for_cols_and_vals( cols, vals )
|
121
|
+
h = {}
|
122
|
+
cols.zip( vals ){ |col,val| h[col] = val }
|
123
|
+
h
|
124
|
+
end
|
125
|
+
|
126
|
+
# Deletes all records from all ActiveRecord subclasses
|
127
|
+
def delete_all
|
128
|
+
ActiveRecord::Base.send( :subclasses ).each do |subclass|
|
129
|
+
subclass.delete_all if subclass.respond_to? :delete_all
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
def initialize # :nodoc:
|
134
|
+
@results = []
|
135
|
+
end
|
136
|
+
|
137
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
require 'ostruct'
|
3
|
+
|
4
|
+
#
|
5
|
+
# == PARAMETERS
|
6
|
+
# * a - database adapter. ie: mysql, postgresql, oracle, etc.
|
7
|
+
# * n - number of objects to test with. ie: 1, 100, 1000, etc.
|
8
|
+
# * t - the table types to test. ie: myisam, innodb, memory, temporary, etc.
|
9
|
+
#
|
10
|
+
module BenchmarkOptionParser
|
11
|
+
BANNER = "Usage: ruby #{$0} [options]\nSee ruby #{$0} -h for more options."
|
12
|
+
|
13
|
+
def self.print_banner
|
14
|
+
puts BANNER
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.print_banner!
|
18
|
+
print_banner
|
19
|
+
exit
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.print_options( options )
|
23
|
+
puts "Benchmarking the following options:"
|
24
|
+
puts " Database adapter: #{options.adapter}"
|
25
|
+
puts " Number of objects: #{options.number_of_objects}"
|
26
|
+
puts " Table types:"
|
27
|
+
print_valid_table_types( options, :prefix=>" " )
|
28
|
+
end
|
29
|
+
|
30
|
+
# TODO IMPLEMENT THIS
|
31
|
+
def self.print_valid_table_types( options, hsh={:prefix=>''} )
|
32
|
+
if options.table_types.keys.size > 0
|
33
|
+
options.table_types.keys.sort.each{ |type| puts hsh[:prefix].to_s + type.to_s }
|
34
|
+
else
|
35
|
+
puts 'No table types defined.'
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.parse( args )
|
40
|
+
options = OpenStruct.new(
|
41
|
+
:table_types => {},
|
42
|
+
:delete_on_finish => true,
|
43
|
+
:number_of_objects => [],
|
44
|
+
:outputs => [] )
|
45
|
+
|
46
|
+
opts = OptionParser.new do |opts|
|
47
|
+
opts.banner = BANNER
|
48
|
+
|
49
|
+
# parse the database adapter
|
50
|
+
opts.on( "a", "--adapter [String]",
|
51
|
+
"The database adapter to use. IE: mysql, postgresql, oracle" ) do |arg|
|
52
|
+
options.adapter = arg
|
53
|
+
end
|
54
|
+
|
55
|
+
# parse do_not_delete flag
|
56
|
+
opts.on( "d", "--do-not-delete",
|
57
|
+
"By default all records in the benchmark tables will be deleted at the end of the benchmark. " +
|
58
|
+
"This flag indicates not to delete the benchmark data." ) do |arg|
|
59
|
+
options.delete_on_finish = false
|
60
|
+
end
|
61
|
+
|
62
|
+
# parse the number of row objects to test
|
63
|
+
opts.on( "n", "--num [Integer]",
|
64
|
+
"The number of objects to benchmark." ) do |arg|
|
65
|
+
options.number_of_objects << arg.to_i
|
66
|
+
end
|
67
|
+
|
68
|
+
# parse the table types to test
|
69
|
+
opts.on( "t", "--table-type [String]",
|
70
|
+
"The table type to test. This can be used multiple times." ) do |arg|
|
71
|
+
if arg =~ /^all$/
|
72
|
+
options.table_types['all'] = options.benchmark_all_types = true
|
73
|
+
else
|
74
|
+
options.table_types[arg] = true
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
# print results in CSV format
|
79
|
+
opts.on( "--to-csv [String]", "Print results in a CSV file format" ) do |filename|
|
80
|
+
options.outputs << OpenStruct.new( :format=>'csv', :filename=>filename)
|
81
|
+
end
|
82
|
+
|
83
|
+
# print results in HTML format
|
84
|
+
opts.on( "--to-html [String]", "Print results in HTML format" ) do |filename|
|
85
|
+
options.outputs << OpenStruct.new( :format=>'html', :filename=>filename )
|
86
|
+
end
|
87
|
+
end #end opt.parse!
|
88
|
+
|
89
|
+
begin
|
90
|
+
opts.parse!( args )
|
91
|
+
if options.table_types.size == 0
|
92
|
+
options.table_types['all'] = options.benchmark_all_types = true
|
93
|
+
end
|
94
|
+
rescue Exception => ex
|
95
|
+
print_banner!
|
96
|
+
end
|
97
|
+
|
98
|
+
print_options( options )
|
99
|
+
|
100
|
+
options
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|