disposable_db 0.0.1
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.
- data/.gitignore +6 -0
- data/Gemfile +4 -0
- data/LICENSE +0 -0
- data/README +0 -0
- data/Rakefile +1 -0
- data/bench/bench.rb +96 -0
- data/bench/bench_helper.rb +28 -0
- data/disposable_db.gemspec +29 -0
- data/lib/disposable_db.rb +39 -0
- data/lib/disposable_db/database.rb +30 -0
- data/lib/disposable_db/databases/sqlite.rb +17 -0
- data/lib/disposable_db/disposable_model.rb +36 -0
- data/lib/disposable_db/table_template.rb +34 -0
- data/lib/disposable_db/version.rb +3 -0
- data/spec/database_spec.rb +24 -0
- data/spec/databases/sqlite_spec.rb +5 -0
- data/spec/disposable_db_spec.rb +11 -0
- data/spec/disposable_model_spec.rb +41 -0
- data/spec/spec_helper.rb +9 -0
- data/spec/table_template_spec.rb +23 -0
- metadata +120 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
File without changes
|
data/README
ADDED
File without changes
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/bench/bench.rb
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
require File.expand_path("../bench_helper", __FILE__)
|
2
|
+
|
3
|
+
def create_columns(n = 100)
|
4
|
+
columns = []
|
5
|
+
n.times do |i|
|
6
|
+
columns << TableTemplate::Column.new("field_#{i}", String)
|
7
|
+
end
|
8
|
+
columns
|
9
|
+
end
|
10
|
+
|
11
|
+
def create_database(table_template)
|
12
|
+
database = Databases::SQLite.new(:connection_string => 'sqlite://tmp/benchmark.db')
|
13
|
+
#database = Databases::SQLite.new
|
14
|
+
database.create_table! table_template
|
15
|
+
database
|
16
|
+
end
|
17
|
+
|
18
|
+
def create_model
|
19
|
+
columns = create_columns
|
20
|
+
|
21
|
+
tt = TableTemplate.new('benchmark', columns)
|
22
|
+
|
23
|
+
database = create_database tt
|
24
|
+
|
25
|
+
DisposableModel.factory(:database => database, :table_name => tt.name)
|
26
|
+
end
|
27
|
+
|
28
|
+
n = 10000
|
29
|
+
batch = []
|
30
|
+
Benchmark.bm(30) do |x|
|
31
|
+
m = create_model
|
32
|
+
x.report("generating random data:") { n.times { generate_random_data(m.columns) } }
|
33
|
+
|
34
|
+
m = create_model
|
35
|
+
cols = m.columns
|
36
|
+
batch = []
|
37
|
+
v = generate_random_data(cols)
|
38
|
+
result = RubyProf.profile do
|
39
|
+
#x.report("imports with transaction:") do
|
40
|
+
n.times do |i|
|
41
|
+
batch << v.values
|
42
|
+
if batch.length >= 1000
|
43
|
+
m.import(cols, batch)
|
44
|
+
batch = []
|
45
|
+
end
|
46
|
+
end
|
47
|
+
m.import(cols, batch) unless batch.length < 1
|
48
|
+
#end
|
49
|
+
end
|
50
|
+
|
51
|
+
printer = RubyProf::GraphPrinter.new(result)
|
52
|
+
printer.print(STDOUT, {})
|
53
|
+
|
54
|
+
exit
|
55
|
+
|
56
|
+
|
57
|
+
# Print a graph profile to text
|
58
|
+
printer = RubyProf::GraphPrinter.new(result)
|
59
|
+
printer.print(STDOUT, {})
|
60
|
+
|
61
|
+
m = create_model
|
62
|
+
x.report("single inserts with transaction:") { m.transaction { n.times { m.insert(generate_random_data(m.columns)) } } }
|
63
|
+
|
64
|
+
m = create_model
|
65
|
+
v = generate_random_data(m.columns)
|
66
|
+
x.report("single inserts:") { n.times { m.insert(v) } }
|
67
|
+
|
68
|
+
m = create_model
|
69
|
+
h = {}
|
70
|
+
m.columns.each { |c| h[c] = :"$new_#{c.to_s}" }
|
71
|
+
p = m.dataset.prepare(:insert, :insert_all_columns, h)
|
72
|
+
v = generate_random_data(m.columns, "new_")
|
73
|
+
x.report("prepared single inserts:") do
|
74
|
+
n.times do
|
75
|
+
p.call(v)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
m = create_model
|
80
|
+
x.report("single inserts with transaction:") { m.transaction { n.times { m.insert(generate_random_data(m.columns)) } } }
|
81
|
+
|
82
|
+
m = create_model
|
83
|
+
v = generate_random_data(m.columns)
|
84
|
+
x.report("multi inserts with transaction:") do
|
85
|
+
m.transaction do
|
86
|
+
n.times do
|
87
|
+
batch build_batch(batch, m.columns, v)
|
88
|
+
if batch.length >= 100
|
89
|
+
m.import(m.columns, batch)
|
90
|
+
batch = []
|
91
|
+
end
|
92
|
+
end
|
93
|
+
m.multi_insert(batch) unless batch.empty?
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler/setup'
|
3
|
+
require 'ffaker'
|
4
|
+
require 'benchmark'
|
5
|
+
require 'ruby-prof'
|
6
|
+
require 'disposable_db'
|
7
|
+
require 'fileutils'
|
8
|
+
|
9
|
+
include DisposableDB
|
10
|
+
|
11
|
+
class TableTemplate::Column
|
12
|
+
|
13
|
+
def mock
|
14
|
+
if self.type.kind_of?(Numeric)
|
15
|
+
rand(999999999999999)
|
16
|
+
else
|
17
|
+
Faker::Name.name
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def generate_random_data(column_names, prefix = nil)
|
23
|
+
data = {}
|
24
|
+
column_names.each do |cn|
|
25
|
+
data[:"#{prefix}#{cn.to_s}"] = Faker::Name.name
|
26
|
+
end
|
27
|
+
data
|
28
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "disposable_db/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "disposable_db"
|
7
|
+
s.version = DisposableDB::VERSION
|
8
|
+
s.authors = ["Keith Larrimore"]
|
9
|
+
s.email = ["keithlarrimore@icehook.com"]
|
10
|
+
s.authors = ['Keith Larrimore']
|
11
|
+
s.homepage = 'https://github.com/klarrimore/disposable_db'
|
12
|
+
s.date = Date.today.to_s
|
13
|
+
s.summary = 'A utility that makes it easy to create "on-the-fly databases"'
|
14
|
+
s.description = 'A utility that makes it easy to create "on-the-fly databases"'
|
15
|
+
|
16
|
+
#s.rubyforge_project = "disposable_db"
|
17
|
+
|
18
|
+
s.files = `git ls-files`.split("\n")
|
19
|
+
s.test_files = `git ls-files -- {test,spec,bench,features}/*`.split("\n")
|
20
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
21
|
+
s.require_paths = ["lib"]
|
22
|
+
|
23
|
+
# specify any dependencies here; for example:
|
24
|
+
s.add_development_dependency 'rspec', ['>= 2.9.0']
|
25
|
+
s.add_development_dependency 'bundler'
|
26
|
+
s.add_development_dependency 'ffaker', ['>= 1.13.0']
|
27
|
+
s.add_development_dependency 'ruby-prof'
|
28
|
+
s.add_runtime_dependency 'sequel', ['= 3.33.0']
|
29
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'logger'
|
2
|
+
require 'tempfile'
|
3
|
+
require 'sequel'
|
4
|
+
require 'disposable_db/version'
|
5
|
+
require 'disposable_db/table_template'
|
6
|
+
require 'disposable_db/database'
|
7
|
+
require 'disposable_db/databases/sqlite'
|
8
|
+
require 'disposable_db/disposable_model'
|
9
|
+
|
10
|
+
module DisposableDB
|
11
|
+
class << self
|
12
|
+
|
13
|
+
def options
|
14
|
+
@options ||= {
|
15
|
+
:log => true
|
16
|
+
}
|
17
|
+
end
|
18
|
+
|
19
|
+
def log(message)
|
20
|
+
logger.info("[disposable_db] #{message}") if logging?
|
21
|
+
end
|
22
|
+
|
23
|
+
def logger
|
24
|
+
@logger ||= options[:logger] || Logger.new(STDOUT)
|
25
|
+
end
|
26
|
+
|
27
|
+
def logger=(logger)
|
28
|
+
@logger = logger
|
29
|
+
end
|
30
|
+
|
31
|
+
def logging?
|
32
|
+
options[:log]
|
33
|
+
end
|
34
|
+
|
35
|
+
class DisposableDBError < StandardError #:nodoc:
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module DisposableDB
|
2
|
+
class Database
|
3
|
+
attr_accessor :connection
|
4
|
+
|
5
|
+
def initialize(args = {})
|
6
|
+
@connection = args[:connection] || Sequel.sqlite
|
7
|
+
end
|
8
|
+
|
9
|
+
def create_table!(table_template)
|
10
|
+
@connection.create_table! table_template.name.to_sym do
|
11
|
+
table_template.columns.each do |column|
|
12
|
+
column column.name.to_sym, column.type
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def create_table(table_template)
|
18
|
+
@connection.create_table? table_template.name.to_sym do
|
19
|
+
table_template.columns.each do |column|
|
20
|
+
column column.name.to_sym, column.type
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def table_exists?(name)
|
26
|
+
@connection.table_exists? name
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module DisposableDB
|
2
|
+
module Databases
|
3
|
+
class SQLite < Database
|
4
|
+
|
5
|
+
def intialize(args = {})
|
6
|
+
unless args.has_key? :connection
|
7
|
+
if args[:connection_string]
|
8
|
+
args[:connection] = Sequel.sqlite(args[:connection_string])
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
super(args)
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module DisposableDB
|
2
|
+
class DisposableModel
|
3
|
+
|
4
|
+
class << self
|
5
|
+
def build(database, table_name)
|
6
|
+
|
7
|
+
m = Class.new(Sequel::Model(database.connection)) do
|
8
|
+
set_dataset table_name.to_sym
|
9
|
+
|
10
|
+
def self.database
|
11
|
+
@database
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.database=(d)
|
15
|
+
@database = d
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.transaction(opts = {}, &block)
|
19
|
+
self.database.connection.transaction opts, &block
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
m.database = database
|
24
|
+
|
25
|
+
m
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
def DisposableModel.factory(args = {})
|
31
|
+
database = args[:database] || Database.new
|
32
|
+
table_name = args[:table_name] || 'disposable_table'
|
33
|
+
build(database, table_name)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module DisposableDB
|
2
|
+
class TableTemplate
|
3
|
+
attr_accessor :name, :columns
|
4
|
+
|
5
|
+
def initialize(name, columns = [])
|
6
|
+
@name = name
|
7
|
+
@columns = columns
|
8
|
+
end
|
9
|
+
|
10
|
+
def add_column(column)
|
11
|
+
@columns << column
|
12
|
+
end
|
13
|
+
|
14
|
+
class Column
|
15
|
+
attr_accessor :name, :type, :indexed
|
16
|
+
|
17
|
+
def self.types
|
18
|
+
# [String, Integer, Fixnum, Bignum, Float, Numeric, BigDecimal, Date, DateTime, Time, File, TrueClass, FalseClass]
|
19
|
+
#types = Sequel::Schema::Generator::GENERIC_TYPES
|
20
|
+
|
21
|
+
#name ? types.select { |t| t.name == name }.first : types
|
22
|
+
Sequel::Schema::Generator::GENERIC_TYPES
|
23
|
+
end
|
24
|
+
|
25
|
+
def initialize(name, type, options = {})
|
26
|
+
@name = name
|
27
|
+
@type = type
|
28
|
+
@indexed = options[:indexed] || false
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
include DisposableDB::Databases
|
4
|
+
|
5
|
+
describe Database do
|
6
|
+
|
7
|
+
it "can be instantiated" do
|
8
|
+
Database.new.should be_an_instance_of(Database)
|
9
|
+
end
|
10
|
+
|
11
|
+
it "can create table" do
|
12
|
+
columns = []
|
13
|
+
columns << TableTemplate::Column.new('t1', Integer)
|
14
|
+
columns << TableTemplate::Column.new('t2', String)
|
15
|
+
|
16
|
+
tt = TableTemplate.new('foo', columns)
|
17
|
+
|
18
|
+
d = Database.new
|
19
|
+
d.table_exists?(tt.name).should be_false
|
20
|
+
d.create_table tt
|
21
|
+
d.table_exists?(tt.name).should be_true
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe DisposableModel do
|
4
|
+
|
5
|
+
it "can be instantiated" do
|
6
|
+
m = DisposableModel.factory(:database => Database.new)
|
7
|
+
m.new.should be_a_kind_of(Sequel::Model)
|
8
|
+
end
|
9
|
+
|
10
|
+
it "has a database" do
|
11
|
+
m = DisposableModel.factory(:database => Database.new)
|
12
|
+
m.database.should be_a_kind_of(Database)
|
13
|
+
end
|
14
|
+
|
15
|
+
it "has a database with connection" do
|
16
|
+
m = DisposableModel.factory(:database => Database.new(:connection => Sequel.sqlite))
|
17
|
+
m.database.connection.should be_a_kind_of(Sequel::SQLite::Database)
|
18
|
+
end
|
19
|
+
|
20
|
+
it "has a database with adjustable connection" do
|
21
|
+
m1 = DisposableModel.factory(:database => Database.new(:connection => Sequel.sqlite))
|
22
|
+
m2 = DisposableModel.factory(:database => Database.new(:connection => Sequel.sqlite('/tmp/test.db')))
|
23
|
+
m1.database.connection.uri.should == 'sqlite:/'
|
24
|
+
m2.database.connection.uri.should == 'sqlite://tmp/test.db'
|
25
|
+
end
|
26
|
+
|
27
|
+
it "has an underlying table with columns" do
|
28
|
+
columns = []
|
29
|
+
columns << TableTemplate::Column.new('t1', Integer)
|
30
|
+
columns << TableTemplate::Column.new('t2', String)
|
31
|
+
|
32
|
+
tt = TableTemplate.new('foo', columns)
|
33
|
+
|
34
|
+
database = Databases::SQLite.new
|
35
|
+
database.create_table! tt
|
36
|
+
|
37
|
+
m = DisposableModel.factory(:database => database, :table_name => tt.name)
|
38
|
+
m.columns.length.should == columns.length
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe TableTemplate do
|
4
|
+
|
5
|
+
it "can be instantiated" do
|
6
|
+
tt = TableTemplate.new('foo')
|
7
|
+
tt.should be_an_instance_of(TableTemplate)
|
8
|
+
end
|
9
|
+
|
10
|
+
it "can add columns" do
|
11
|
+
tt = TableTemplate.new('foo')
|
12
|
+
columns = []
|
13
|
+
columns << TableTemplate::Column.new('t1', Integer)
|
14
|
+
columns << TableTemplate::Column.new('t2', String)
|
15
|
+
|
16
|
+
columns.each do |column|
|
17
|
+
tt.add_column column
|
18
|
+
end
|
19
|
+
|
20
|
+
tt.columns.length.should == columns.length
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
metadata
ADDED
@@ -0,0 +1,120 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: disposable_db
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Keith Larrimore
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-03-26 00:00:00.000000000Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rspec
|
16
|
+
requirement: &11827800 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 2.9.0
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *11827800
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: bundler
|
27
|
+
requirement: &11826540 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
33
|
+
type: :development
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *11826540
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: ffaker
|
38
|
+
requirement: &11824160 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ! '>='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: 1.13.0
|
44
|
+
type: :development
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *11824160
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: ruby-prof
|
49
|
+
requirement: &11823320 !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
type: :development
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: *11823320
|
58
|
+
- !ruby/object:Gem::Dependency
|
59
|
+
name: sequel
|
60
|
+
requirement: &11822320 !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - =
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: 3.33.0
|
66
|
+
type: :runtime
|
67
|
+
prerelease: false
|
68
|
+
version_requirements: *11822320
|
69
|
+
description: A utility that makes it easy to create "on-the-fly databases"
|
70
|
+
email:
|
71
|
+
- keithlarrimore@icehook.com
|
72
|
+
executables: []
|
73
|
+
extensions: []
|
74
|
+
extra_rdoc_files: []
|
75
|
+
files:
|
76
|
+
- .gitignore
|
77
|
+
- Gemfile
|
78
|
+
- LICENSE
|
79
|
+
- README
|
80
|
+
- Rakefile
|
81
|
+
- bench/bench.rb
|
82
|
+
- bench/bench_helper.rb
|
83
|
+
- disposable_db.gemspec
|
84
|
+
- lib/disposable_db.rb
|
85
|
+
- lib/disposable_db/database.rb
|
86
|
+
- lib/disposable_db/databases/sqlite.rb
|
87
|
+
- lib/disposable_db/disposable_model.rb
|
88
|
+
- lib/disposable_db/table_template.rb
|
89
|
+
- lib/disposable_db/version.rb
|
90
|
+
- spec/database_spec.rb
|
91
|
+
- spec/databases/sqlite_spec.rb
|
92
|
+
- spec/disposable_db_spec.rb
|
93
|
+
- spec/disposable_model_spec.rb
|
94
|
+
- spec/spec_helper.rb
|
95
|
+
- spec/table_template_spec.rb
|
96
|
+
homepage: https://github.com/klarrimore/disposable_db
|
97
|
+
licenses: []
|
98
|
+
post_install_message:
|
99
|
+
rdoc_options: []
|
100
|
+
require_paths:
|
101
|
+
- lib
|
102
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
103
|
+
none: false
|
104
|
+
requirements:
|
105
|
+
- - ! '>='
|
106
|
+
- !ruby/object:Gem::Version
|
107
|
+
version: '0'
|
108
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
109
|
+
none: false
|
110
|
+
requirements:
|
111
|
+
- - ! '>='
|
112
|
+
- !ruby/object:Gem::Version
|
113
|
+
version: '0'
|
114
|
+
requirements: []
|
115
|
+
rubyforge_project:
|
116
|
+
rubygems_version: 1.8.17
|
117
|
+
signing_key:
|
118
|
+
specification_version: 3
|
119
|
+
summary: A utility that makes it easy to create "on-the-fly databases"
|
120
|
+
test_files: []
|