lol_dba 2.1.5 → 2.1.6
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 +4 -4
- data/.codeclimate.yml +179 -0
- data/.gitignore +1 -1
- data/.rspec +2 -0
- data/.rubocop.yml +7 -0
- data/.travis.yml +16 -9
- data/Appraisals +19 -12
- data/Gemfile +1 -8
- data/Gemfile.lock +60 -59
- data/README.md +5 -2
- data/Rakefile +4 -4
- data/bin/lol_dba +2 -2
- data/gemfiles/rails_3_2.gemfile +0 -3
- data/gemfiles/rails_3_2.gemfile.lock +33 -31
- data/gemfiles/rails_4_0.gemfile +0 -3
- data/gemfiles/rails_4_0.gemfile.lock +31 -27
- data/gemfiles/rails_4_1.gemfile +0 -3
- data/gemfiles/rails_4_1.gemfile.lock +29 -26
- data/gemfiles/rails_4_2.gemfile +0 -3
- data/gemfiles/rails_4_2.gemfile.lock +52 -48
- data/gemfiles/rails_5_0.gemfile +0 -3
- data/gemfiles/rails_5_0.gemfile.lock +55 -51
- data/gemfiles/rails_5_1.gemfile +0 -3
- data/gemfiles/rails_5_1.gemfile.lock +57 -53
- data/gemfiles/rails_5_2.gemfile +9 -0
- data/gemfiles/rails_5_2.gemfile.lock +115 -0
- data/lib/lol_dba/cli.rb +26 -15
- data/lib/lol_dba/index_finding/belongs_to.rb +32 -0
- data/lib/lol_dba/index_finding/error_logging.rb +15 -0
- data/lib/lol_dba/index_finding/has_and_belongs_to_many.rb +20 -0
- data/lib/lol_dba/index_finding/has_many.rb +47 -0
- data/lib/lol_dba/index_finding/index_finder.rb +81 -0
- data/lib/lol_dba/index_finding/migration_formatter.rb +50 -0
- data/lib/lol_dba/index_finding/relation_inspector.rb +30 -0
- data/lib/lol_dba/index_finding/relation_inspector_factory.rb +13 -0
- data/lib/lol_dba/rails_compatibility.rb +47 -0
- data/lib/lol_dba/railtie.rb +2 -2
- data/lib/lol_dba/sql_migrations/migration.rb +51 -0
- data/lib/lol_dba/sql_migrations/migration_mocker.rb +70 -0
- data/lib/lol_dba/sql_migrations/sql_generator.rb +49 -0
- data/lib/lol_dba/sql_migrations/writer.rb +29 -0
- data/lib/lol_dba/version.rb +1 -1
- data/lib/lol_dba.rb +14 -188
- data/lib/tasks/lol_dba.rake +7 -8
- data/lol_dba.gemspec +19 -16
- data/spec/associations_index_spec.rb +43 -56
- data/spec/fixtures/app/models/address.rb +0 -1
- data/spec/fixtures/app/models/billable_week.rb +1 -3
- data/spec/fixtures/app/models/company.rb +0 -1
- data/spec/fixtures/app/models/complex_billable_week.rb +0 -1
- data/spec/fixtures/app/models/complex_timesheet.rb +0 -1
- data/spec/fixtures/app/models/country.rb +1 -1
- data/spec/fixtures/app/models/favourite.rb +0 -2
- data/spec/fixtures/app/models/freelancer.rb +1 -3
- data/spec/fixtures/app/models/gift.rb +0 -2
- data/spec/fixtures/app/models/god.rb +1 -1
- data/spec/fixtures/app/models/project.rb +0 -2
- data/spec/fixtures/app/models/timesheet.rb +1 -3
- data/spec/fixtures/app/models/user.rb +0 -2
- data/spec/fixtures/app/models/worker.rb +0 -1
- data/spec/fixtures/app/models/worker_user.rb +2 -3
- data/spec/fixtures/schema.rb +53 -53
- data/spec/migration_formatter_spec.rb +66 -0
- data/spec/spec_helper.rb +17 -9
- data/spec/sql_generator_spec.rb +9 -0
- metadata +88 -19
- data/lib/lol_dba/migration.rb +0 -40
- data/lib/lol_dba/sql_generator.rb +0 -96
- data/lib/lol_dba/writer.rb +0 -25
- data/spec/common_function_spec.rb +0 -96
@@ -1,89 +1,76 @@
|
|
1
|
-
|
1
|
+
RSpec.describe 'Collect indexes based on associations:' do
|
2
|
+
let (:indexes) { LolDba::IndexFinder.check_for_indexes }
|
2
3
|
|
3
|
-
|
4
|
+
it 'find relationship indexes' do
|
5
|
+
expect(indexes).not_to be_empty
|
4
6
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
7
|
+
expect(indexes).to have_key('companies')
|
8
|
+
expect(indexes).to have_key('companies_freelancers')
|
9
|
+
expect(indexes).to have_key('addresses')
|
10
|
+
expect(indexes).to have_key('purchases')
|
9
11
|
end
|
10
12
|
|
11
|
-
it
|
12
|
-
expect(
|
13
|
-
|
14
|
-
expect(@relationship_indexes).to have_key("companies")
|
15
|
-
expect(@relationship_indexes).to have_key("companies_freelancers")
|
16
|
-
expect(@relationship_indexes).to have_key("addresses")
|
17
|
-
expect(@relationship_indexes).to have_key("purchases")
|
18
|
-
end
|
19
|
-
|
20
|
-
it "find indexes for belongs_to" do
|
21
|
-
expect(@relationship_indexes["addresses"]).to include("country_id")
|
22
|
-
expect(@relationship_indexes["favourites"]).to include("user_id")
|
13
|
+
it 'find indexes for belongs_to' do
|
14
|
+
expect(indexes['addresses']).to include('country_id')
|
15
|
+
expect(indexes['favourites']).to include('user_id')
|
23
16
|
end
|
24
17
|
|
25
|
-
it
|
26
|
-
expect(
|
18
|
+
it 'find indexes for polymorphic belongs_to' do
|
19
|
+
expect(indexes['addresses']).to include(%w[addressable_id addressable_type])
|
27
20
|
end
|
28
21
|
|
29
|
-
it
|
30
|
-
expect(
|
22
|
+
it 'find indexes for belongs_to with custom foreign key' do
|
23
|
+
expect(indexes['companies']).to include('owner_id')
|
31
24
|
end
|
32
25
|
|
33
|
-
it
|
34
|
-
expect(
|
35
|
-
expect(
|
26
|
+
it 'find indexes for has_and_belongs_to_many' do
|
27
|
+
expect(indexes['companies_freelancers']).to include(%w[company_id freelancer_id])
|
28
|
+
expect(indexes['companies_freelancers']).not_to include(%w[freelancer_id company_id])
|
36
29
|
end
|
37
30
|
|
38
|
-
it
|
39
|
-
expect(
|
31
|
+
it 'find indexes for has_and_belongs_to_many with custom join_table, primary and foreign keys' do
|
32
|
+
expect(indexes['purchases']).to include(%w[buyer_id present_id])
|
40
33
|
end
|
41
34
|
|
42
35
|
it "find indexes for has_and_belongs_to_many but don't create the left_side index" do
|
43
|
-
expect(
|
44
|
-
end
|
45
|
-
|
46
|
-
it "do not add an already existing index" do
|
47
|
-
expect(@relationship_indexes["companies"]).not_to include("country_id")
|
36
|
+
expect(indexes['purchases']).not_to include('left_side_id')
|
48
37
|
end
|
49
38
|
|
50
|
-
it
|
51
|
-
expect(
|
52
|
-
expect(@relationship_indexes["billable_weeks"]).not_to include(["billable_week_id", "remote_worker_id"])
|
39
|
+
it 'do not add an already existing index' do
|
40
|
+
expect(indexes['companies']).not_to include('country_id')
|
53
41
|
end
|
54
42
|
|
55
|
-
it
|
56
|
-
expect(
|
43
|
+
it 'find indexes for has_many :through' do
|
44
|
+
expect(indexes['billable_weeks']).to include('remote_worker_id', 'timesheet_id')
|
45
|
+
expect(indexes['billable_weeks']).not_to include(%w[billable_week_id remote_worker_id])
|
57
46
|
end
|
58
47
|
|
59
|
-
it
|
60
|
-
expect(
|
61
|
-
expect(@relationship_indexes["addresses_wrongs"]).to be_nil
|
48
|
+
it 'find indexes for has_many :through with source and foreign key' do
|
49
|
+
expect(indexes['complex_billable_week']).to include(%w[freelancer_id id_complex_timesheet])
|
62
50
|
end
|
63
51
|
|
64
|
-
it
|
65
|
-
expect(
|
66
|
-
expect(
|
67
|
-
expect(@warning_messages).to match(/\'addresses_wrongs\'/)
|
52
|
+
it 'do not include wrong class' do
|
53
|
+
expect(indexes['wrongs']).to be_nil
|
54
|
+
expect(indexes['addresses_wrongs']).to be_nil
|
68
55
|
end
|
69
56
|
|
70
|
-
it
|
71
|
-
expect(
|
57
|
+
it 'find indexes for STI' do
|
58
|
+
expect(indexes['users']).to include(%w[id type])
|
72
59
|
end
|
73
60
|
|
74
|
-
it
|
75
|
-
expect(
|
61
|
+
it 'find indexes for STI with custom inheritance column' do
|
62
|
+
expect(indexes['freelancers']).to include(%w[id worker_type])
|
76
63
|
end
|
77
64
|
|
78
|
-
it
|
79
|
-
expect(
|
80
|
-
expect(
|
81
|
-
expect(
|
65
|
+
it 'find indexes, than use custom class name option in association' do
|
66
|
+
expect(indexes['employers_freelancers']).to be_nil
|
67
|
+
expect(indexes['companies_freelancers']).to include(%w[company_id freelancer_id])
|
68
|
+
expect(indexes['companies_freelancers']).not_to include(%w[freelancer_id company_id])
|
82
69
|
end
|
83
70
|
|
84
|
-
it
|
85
|
-
expect(
|
86
|
-
expect(
|
87
|
-
expect(
|
71
|
+
it 'create index for HABTM with polymorphic relationship' do
|
72
|
+
expect(indexes['favourites']).to include(%w[favourable_id favourable_type])
|
73
|
+
expect(indexes['favourites']).not_to include(%w[project_id user_id])
|
74
|
+
expect(indexes['favourites']).not_to include(%w[project_id worker_user_id])
|
88
75
|
end
|
89
76
|
end
|
@@ -1,8 +1,7 @@
|
|
1
1
|
class Freelancer < ActiveRecord::Base
|
2
|
-
|
3
2
|
self.inheritance_column = 'worker_type'
|
4
3
|
# use for testing custom class_name FK
|
5
|
-
has_and_belongs_to_many :employers, class_name:
|
4
|
+
has_and_belongs_to_many :employers, class_name: 'Company'
|
6
5
|
|
7
6
|
has_many :billable_weeks, foreign_key: :remote_worker_id
|
8
7
|
has_many :timesheets, through: :billable_weeks
|
@@ -10,5 +9,4 @@ class Freelancer < ActiveRecord::Base
|
|
10
9
|
# Use for testing custom has_many :through
|
11
10
|
has_many :complex_billable_weeks
|
12
11
|
has_many :complex_timesheets, through: :complex_billable_weeks
|
13
|
-
|
14
12
|
end
|
@@ -1,5 +1,4 @@
|
|
1
1
|
class User < ActiveRecord::Base
|
2
|
-
|
3
2
|
has_one :company, foreign_key: :owner_id
|
4
3
|
has_one :address, as: :addressable
|
5
4
|
|
@@ -10,5 +9,4 @@ class User < ActiveRecord::Base
|
|
10
9
|
has_many :favourite_projects, through: :favourites, source: :favourable, source_type: 'Project'
|
11
10
|
|
12
11
|
validates_uniqueness_of :name
|
13
|
-
|
14
12
|
end
|
data/spec/fixtures/schema.rb
CHANGED
@@ -1,91 +1,91 @@
|
|
1
1
|
ActiveRecord::Schema.define do
|
2
|
-
create_table
|
3
|
-
t.column
|
4
|
-
t.column
|
5
|
-
t.column
|
2
|
+
create_table 'users', force: true do |t|
|
3
|
+
t.column 'name', :string
|
4
|
+
t.column 'email', :string
|
5
|
+
t.column 'type', :string
|
6
6
|
end
|
7
7
|
|
8
|
-
create_table
|
9
|
-
t.column
|
10
|
-
t.column
|
11
|
-
t.column
|
8
|
+
create_table 'companies', force: true do |t|
|
9
|
+
t.column 'name', :text
|
10
|
+
t.column 'owned_id', :integer
|
11
|
+
t.column 'country_id', :integer
|
12
12
|
end
|
13
13
|
|
14
14
|
add_index :companies, :country_id
|
15
15
|
|
16
|
-
create_table
|
17
|
-
t.column
|
18
|
-
t.column
|
19
|
-
t.column
|
20
|
-
t.column
|
16
|
+
create_table 'addresses', force: true do |t|
|
17
|
+
t.column 'addressable_type', :string
|
18
|
+
t.column 'addressable_id', :integer
|
19
|
+
t.column 'address', :text
|
20
|
+
t.column 'country_id', :integer
|
21
21
|
end
|
22
22
|
|
23
|
-
create_table
|
24
|
-
t.column
|
25
|
-
t.column
|
23
|
+
create_table 'freelancers', force: true do |t|
|
24
|
+
t.column 'name', :string
|
25
|
+
t.column 'price_per_hour', :integer
|
26
26
|
t.column 'worker_type', :string
|
27
27
|
end
|
28
28
|
|
29
|
-
create_table
|
30
|
-
t.column
|
31
|
-
t.column
|
29
|
+
create_table 'timesheets', force: true do |t|
|
30
|
+
t.column 'price_per_hour', :integer
|
31
|
+
t.column 'hours', :integer
|
32
32
|
end
|
33
33
|
|
34
|
-
create_table
|
35
|
-
t.column
|
36
|
-
t.column
|
34
|
+
create_table 'complex_timesheets', force: true do |t|
|
35
|
+
t.column 'price_per_hour', :integer
|
36
|
+
t.column 'hours', :integer
|
37
37
|
end
|
38
38
|
|
39
|
-
create_table
|
40
|
-
t.column
|
41
|
-
t.column
|
42
|
-
t.column
|
39
|
+
create_table 'billable_weeks', force: true do |t|
|
40
|
+
t.column 'date', :date
|
41
|
+
t.column 'timesheet_id', :integer
|
42
|
+
t.column 'remote_worker_id', :integer
|
43
43
|
end
|
44
44
|
|
45
|
-
create_table
|
46
|
-
t.column
|
47
|
-
t.column
|
48
|
-
t.column
|
45
|
+
create_table 'complex_billable_week', force: true do |t|
|
46
|
+
t.column 'date', :date
|
47
|
+
t.column 'id_complex_timesheet', :integer
|
48
|
+
t.column 'freelancer_id', :integer
|
49
49
|
end
|
50
50
|
|
51
|
-
create_table
|
52
|
-
t.column
|
53
|
-
t.column
|
51
|
+
create_table 'companies_freelancers', id: false, force: true do |t|
|
52
|
+
t.column 'freelancer_id', :integer
|
53
|
+
t.column 'company_id', :integer
|
54
54
|
end
|
55
55
|
|
56
|
-
create_table
|
57
|
-
t.column
|
58
|
-
t.column
|
56
|
+
create_table 'gifts', primary_key: 'custom_primary_key', force: true do |t|
|
57
|
+
t.column 'name', :string
|
58
|
+
t.column 'price', :integer
|
59
59
|
end
|
60
60
|
|
61
|
-
create_table
|
62
|
-
t.column
|
63
|
-
t.column
|
61
|
+
create_table 'purchases', id: false, force: true do |t|
|
62
|
+
t.column 'present_id', :integer
|
63
|
+
t.column 'buyer_id', :integer
|
64
64
|
end
|
65
65
|
|
66
|
-
create_table
|
67
|
-
t.column
|
66
|
+
create_table 'countries', force: true do |t|
|
67
|
+
t.column 'name', :string
|
68
68
|
end
|
69
69
|
|
70
|
-
create_table
|
70
|
+
create_table 'components', force: :cascade do |t|
|
71
71
|
end
|
72
72
|
|
73
|
-
create_table
|
74
|
-
t.column
|
75
|
-
t.column
|
73
|
+
create_table 'group_components', force: :cascade do |t|
|
74
|
+
t.column 'group_id', :integer
|
75
|
+
t.column 'component_id', :integer
|
76
76
|
end
|
77
77
|
|
78
|
-
create_table
|
78
|
+
create_table 'groups', force: :cascade do |t|
|
79
79
|
end
|
80
80
|
|
81
|
-
create_table
|
82
|
-
t.column
|
83
|
-
t.column
|
81
|
+
create_table 'projects', force: true do |t|
|
82
|
+
t.column 'name', :string
|
83
|
+
t.column 'user_id', :integer
|
84
84
|
end
|
85
85
|
|
86
|
-
create_table
|
87
|
-
t.column
|
88
|
-
t.column
|
89
|
-
t.column
|
86
|
+
create_table 'favourites', force: true do |t|
|
87
|
+
t.column 'user_id', :integer
|
88
|
+
t.column 'favourable_id', :integer
|
89
|
+
t.column 'favourable_type', :string
|
90
90
|
end
|
91
91
|
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
RSpec.describe LolDba::MigrationFormatter do
|
2
|
+
describe '#migration_instructions' do
|
3
|
+
subject(:formatter) { LolDba::MigrationFormatter.new('') }
|
4
|
+
let(:index_to_add) { ['add_index :report, :_id_test_plan'] }
|
5
|
+
|
6
|
+
it 'print migration skeleton with set name' do
|
7
|
+
migration = formatter.migration_instructions(index_to_add)
|
8
|
+
expect(migration).to match(/class AddMissingIndexes/i)
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'print migration with add_keys params' do
|
12
|
+
migration = formatter.migration_instructions(index_to_add)
|
13
|
+
expect(migration).to match(/add_index :report, :_id_test_plan/i)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe '#format_for_migration' do
|
18
|
+
subject(:formatter) { LolDba::MigrationFormatter.new('') }
|
19
|
+
|
20
|
+
it 'return data for migrations for non-indexed single key in table' do
|
21
|
+
relationship_indexes = { users: [:user_id] }
|
22
|
+
|
23
|
+
add_indexes = formatter.format_for_migration(relationship_indexes)
|
24
|
+
|
25
|
+
expect(add_indexes.first).to eq('add_index :users, :user_id')
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'return data for migrations for non-indexed composite key in table' do
|
29
|
+
relationship_indexes = { friends: [%i[user_id friend_id]] }
|
30
|
+
|
31
|
+
add_indexes = formatter.format_for_migration(relationship_indexes)
|
32
|
+
|
33
|
+
expect(add_indexes.first).to eq('add_index :friends, [:user_id, :friend_id]')
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'ignore empty or nil keys for table' do
|
37
|
+
relationship_indexes = { table: [''], table2: [nil] }
|
38
|
+
add_indexes = formatter.format_for_migration(relationship_indexes)
|
39
|
+
|
40
|
+
expect(add_indexes).to be_empty
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
describe '#puts_migration_content' do
|
45
|
+
before do
|
46
|
+
@indexes = LolDba::IndexFinder.check_for_indexes
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'print migration code' do
|
50
|
+
expect($stdout).to receive(:puts).with(/AddMissingIndexes/i)
|
51
|
+
LolDba::MigrationFormatter.new(@indexes).puts_migration_content
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'print warning messages if they exist' do
|
55
|
+
warning = 'warning text here'
|
56
|
+
expect($stdout).to receive(:puts)
|
57
|
+
|
58
|
+
LolDba::MigrationFormatter.new({}).puts_migration_content
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'print nothing if no indexes and warning messages exist' do
|
62
|
+
expect($stdout).to receive(:puts).with('Yey, no missing indexes found!')
|
63
|
+
LolDba::MigrationFormatter.new({}).puts_migration_content
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,16 +1,20 @@
|
|
1
|
+
require 'bundler/setup'
|
1
2
|
require 'rails/all'
|
2
3
|
require 'lol_dba'
|
4
|
+
require 'simplecov'
|
3
5
|
|
4
|
-
ENV[
|
6
|
+
ENV['RAILS_ENV'] ||= 'test'
|
7
|
+
|
8
|
+
SimpleCov.start
|
5
9
|
|
6
10
|
ActiveRecord::Base.establish_connection(
|
7
|
-
:
|
8
|
-
:
|
11
|
+
adapter: 'sqlite3',
|
12
|
+
database: ':memory:'
|
9
13
|
)
|
10
14
|
|
11
15
|
module Rails
|
12
16
|
def self.root
|
13
|
-
|
17
|
+
'spec/fixtures/'
|
14
18
|
end
|
15
19
|
end
|
16
20
|
Dir.glob("#{Rails.root}/app/models/*.rb").sort.each { |file| require_dependency file }
|
@@ -20,15 +24,19 @@ load 'fixtures/schema.rb'
|
|
20
24
|
|
21
25
|
root_dir = File.dirname(__FILE__)
|
22
26
|
|
23
|
-
#add current dir to the load path
|
24
|
-
|
27
|
+
# add current dir to the load path
|
28
|
+
$LOAD_PATH.unshift('.')
|
29
|
+
|
25
30
|
RSpec.configure do |config|
|
26
|
-
config.
|
27
|
-
|
31
|
+
config.disable_monkey_patching!
|
32
|
+
|
33
|
+
config.expect_with :rspec do |c|
|
34
|
+
c.syntax = :expect
|
35
|
+
c.include_chain_clauses_in_custom_matcher_descriptions = true
|
28
36
|
end
|
37
|
+
|
29
38
|
config.mock_with :rspec do |mocks|
|
30
39
|
mocks.allow_message_expectations_on_nil = true
|
31
40
|
mocks.verify_partial_doubles = true
|
32
41
|
end
|
33
|
-
config.disable_monkey_patching!
|
34
42
|
end
|