low_card_tables 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +18 -0
  3. data/.travis.yml +59 -0
  4. data/Gemfile +17 -0
  5. data/LICENSE +21 -0
  6. data/README.md +75 -0
  7. data/Rakefile +6 -0
  8. data/lib/low_card_tables.rb +72 -0
  9. data/lib/low_card_tables/active_record/base.rb +55 -0
  10. data/lib/low_card_tables/active_record/migrations.rb +223 -0
  11. data/lib/low_card_tables/active_record/relation.rb +35 -0
  12. data/lib/low_card_tables/active_record/scoping.rb +87 -0
  13. data/lib/low_card_tables/errors.rb +74 -0
  14. data/lib/low_card_tables/has_low_card_table/base.rb +114 -0
  15. data/lib/low_card_tables/has_low_card_table/low_card_association.rb +273 -0
  16. data/lib/low_card_tables/has_low_card_table/low_card_associations_manager.rb +143 -0
  17. data/lib/low_card_tables/has_low_card_table/low_card_dynamic_method_manager.rb +224 -0
  18. data/lib/low_card_tables/has_low_card_table/low_card_objects_manager.rb +80 -0
  19. data/lib/low_card_tables/low_card_table/base.rb +184 -0
  20. data/lib/low_card_tables/low_card_table/cache.rb +214 -0
  21. data/lib/low_card_tables/low_card_table/cache_expiration/exponential_cache_expiration_policy.rb +151 -0
  22. data/lib/low_card_tables/low_card_table/cache_expiration/fixed_cache_expiration_policy.rb +23 -0
  23. data/lib/low_card_tables/low_card_table/cache_expiration/has_cache_expiration.rb +100 -0
  24. data/lib/low_card_tables/low_card_table/cache_expiration/no_caching_expiration_policy.rb +13 -0
  25. data/lib/low_card_tables/low_card_table/cache_expiration/unlimited_cache_expiration_policy.rb +13 -0
  26. data/lib/low_card_tables/low_card_table/row_collapser.rb +175 -0
  27. data/lib/low_card_tables/low_card_table/row_manager.rb +681 -0
  28. data/lib/low_card_tables/low_card_table/table_unique_index.rb +134 -0
  29. data/lib/low_card_tables/version.rb +4 -0
  30. data/lib/low_card_tables/version_support.rb +52 -0
  31. data/low_card_tables.gemspec +69 -0
  32. data/spec/low_card_tables/helpers/database_helper.rb +148 -0
  33. data/spec/low_card_tables/helpers/query_spy_helper.rb +47 -0
  34. data/spec/low_card_tables/helpers/system_helpers.rb +63 -0
  35. data/spec/low_card_tables/system/basic_system_spec.rb +254 -0
  36. data/spec/low_card_tables/system/bulk_system_spec.rb +334 -0
  37. data/spec/low_card_tables/system/caching_system_spec.rb +531 -0
  38. data/spec/low_card_tables/system/migrations_system_spec.rb +747 -0
  39. data/spec/low_card_tables/system/options_system_spec.rb +581 -0
  40. data/spec/low_card_tables/system/queries_system_spec.rb +142 -0
  41. data/spec/low_card_tables/system/validations_system_spec.rb +88 -0
  42. data/spec/low_card_tables/unit/active_record/base_spec.rb +53 -0
  43. data/spec/low_card_tables/unit/active_record/migrations_spec.rb +207 -0
  44. data/spec/low_card_tables/unit/active_record/relation_spec.rb +47 -0
  45. data/spec/low_card_tables/unit/active_record/scoping_spec.rb +101 -0
  46. data/spec/low_card_tables/unit/has_low_card_table/base_spec.rb +79 -0
  47. data/spec/low_card_tables/unit/has_low_card_table/low_card_association_spec.rb +287 -0
  48. data/spec/low_card_tables/unit/has_low_card_table/low_card_associations_manager_spec.rb +190 -0
  49. data/spec/low_card_tables/unit/has_low_card_table/low_card_dynamic_method_manager_spec.rb +234 -0
  50. data/spec/low_card_tables/unit/has_low_card_table/low_card_objects_manager_spec.rb +70 -0
  51. data/spec/low_card_tables/unit/low_card_table/base_spec.rb +207 -0
  52. data/spec/low_card_tables/unit/low_card_table/cache_expiration/exponential_cache_expiration_policy_spec.rb +128 -0
  53. data/spec/low_card_tables/unit/low_card_table/cache_expiration/fixed_cache_expiration_policy_spec.rb +25 -0
  54. data/spec/low_card_tables/unit/low_card_table/cache_expiration/has_cache_expiration_policy_spec.rb +100 -0
  55. data/spec/low_card_tables/unit/low_card_table/cache_expiration/no_caching_expiration_policy_spec.rb +14 -0
  56. data/spec/low_card_tables/unit/low_card_table/cache_expiration/unlimited_cache_expiration_policy_spec.rb +14 -0
  57. data/spec/low_card_tables/unit/low_card_table/cache_spec.rb +282 -0
  58. data/spec/low_card_tables/unit/low_card_table/row_collapser_spec.rb +109 -0
  59. data/spec/low_card_tables/unit/low_card_table/row_manager_spec.rb +918 -0
  60. data/spec/low_card_tables/unit/low_card_table/table_unique_index_spec.rb +117 -0
  61. metadata +206 -0
@@ -0,0 +1,117 @@
1
+ require 'low_card_tables'
2
+
3
+ describe LowCardTables::LowCardTable::TableUniqueIndex do
4
+ def klass
5
+ LowCardTables::LowCardTable::TableUniqueIndex
6
+ end
7
+
8
+ it "should require a low-card model for instantiation" do
9
+ low_card_model = double("low_card_model")
10
+ lambda { klass.new(low_card_model) }.should raise_error(ArgumentError)
11
+
12
+ allow(low_card_model).to receive(:is_low_card_table?).and_return(false)
13
+ lambda { klass.new(low_card_model) }.should raise_error(ArgumentError)
14
+ end
15
+
16
+ context "with an instance" do
17
+ before :each do
18
+ @low_card_model = double("low_card_model")
19
+ allow(@low_card_model).to receive(:is_low_card_table?).and_return(true)
20
+ allow(@low_card_model).to receive(:table_name).and_return("foobar")
21
+ allow(@low_card_model).to receive(:low_card_value_column_names).and_return(%w{foo bar baz})
22
+ allow(@low_card_model).to receive(:table_exists?).and_return(true)
23
+
24
+ @connection = double("connection")
25
+ allow(@low_card_model).to receive(:connection).and_return(@connection)
26
+
27
+ @non_unique_index = double("non_unique_index")
28
+ allow(@non_unique_index).to receive(:unique).and_return(false)
29
+ allow(@non_unique_index).to receive(:name).and_return("nui")
30
+
31
+ @unique_index_wrong_columns = double("unique_index_wrong_columns")
32
+ allow(@unique_index_wrong_columns).to receive(:unique).and_return(true)
33
+ allow(@unique_index_wrong_columns).to receive(:columns).and_return(%w{foo bar})
34
+ allow(@unique_index_wrong_columns).to receive(:name).and_return("uiwc")
35
+
36
+ @unique_index_right_columns = double("unique_index_right_columns")
37
+ allow(@unique_index_right_columns).to receive(:unique).and_return(true)
38
+ allow(@unique_index_right_columns).to receive(:columns).and_return(%w{bar foo baz})
39
+ allow(@unique_index_right_columns).to receive(:name).and_return("uirc")
40
+
41
+ @instance = klass.new(@low_card_model)
42
+ end
43
+
44
+ describe "#ensure_present!" do
45
+ it "should do nothing if the table doesn't exist" do
46
+ allow(@low_card_model).to receive(:table_exists?).and_return(false)
47
+
48
+ @instance.ensure_present!(false)
49
+ @instance.ensure_present!(true)
50
+ end
51
+
52
+ it "should do nothing if the index does exist" do
53
+ allow(@connection).to receive(:indexes).with("foobar").and_return([ @non_unique_index, @unique_index_wrong_columns, @unique_index_right_columns ])
54
+ @instance.ensure_present!(false)
55
+ @instance.ensure_present!(true)
56
+ end
57
+
58
+ it "should raise if the index doesn't exist, and not told to create it" do
59
+ allow(@connection).to receive(:indexes).with("foobar").and_return([ @non_unique_index, @unique_index_wrong_columns ])
60
+ lambda { @instance.ensure_present!(false) }.should raise_error(LowCardTables::Errors::LowCardNoUniqueIndexError, /uiwc/i)
61
+ end
62
+
63
+ it "should create the index if it doesn't exist, and told to" do
64
+ index_return_values = [
65
+ [ @non_unique_index, @unique_index_wrong_columns ],
66
+ [ @non_unique_index, @unique_index_wrong_columns ],
67
+ [ @non_unique_index, @unique_index_wrong_columns, @unique_index_right_columns ]
68
+ ]
69
+
70
+ allow(@connection).to receive(:indexes).with("foobar") { index_return_values.shift }
71
+
72
+ our_migration_class = Class.new
73
+ allow(Class).to receive(:new).once.with(::ActiveRecord::Migration).and_return(our_migration_class)
74
+
75
+ expect(our_migration_class).to receive(:migrate).once.with(:up)
76
+
77
+ expect(@low_card_model).to receive(:reset_column_information).once
78
+ expect(::LowCardTables::VersionSupport).to receive(:clear_schema_cache!).once.with(@low_card_model)
79
+
80
+ @instance.ensure_present!(true)
81
+
82
+ expect(our_migration_class).to receive(:remove_index).once.with("foobar", :name => "index_foobar_lc_on_all")
83
+ expect(our_migration_class).to receive(:add_index).once.with("foobar", %w{bar baz foo}, :unique => true, :name => "index_foobar_lc_on_all")
84
+ our_migration_class.up
85
+ end
86
+ end
87
+
88
+ describe "#remove!" do
89
+ it "should do nothing if there is no such index" do
90
+ allow(@connection).to receive(:indexes).with("foobar").and_return([ @non_unique_index, @unique_index_wrong_columns ])
91
+ @instance.remove!
92
+ end
93
+
94
+ it "should remove the index if there is one" do
95
+ index_return_values = [
96
+ [ @non_unique_index, @unique_index_wrong_columns, @unique_index_right_columns ],
97
+ [ @non_unique_index, @unique_index_wrong_columns ]
98
+ ]
99
+
100
+ allow(@connection).to receive(:indexes).with("foobar") { index_return_values.shift }
101
+
102
+ our_migration_class = Class.new
103
+ allow(Class).to receive(:new).once.with(::ActiveRecord::Migration).and_return(our_migration_class)
104
+
105
+ expect(our_migration_class).to receive(:migrate).once.with(:up)
106
+
107
+ expect(@low_card_model).to receive(:reset_column_information).once
108
+ expect(::LowCardTables::VersionSupport).to receive(:clear_schema_cache!).once.with(@low_card_model)
109
+
110
+ @instance.remove!
111
+
112
+ expect(our_migration_class).to receive(:remove_index).once.with("foobar", :name => "uirc")
113
+ our_migration_class.up
114
+ end
115
+ end
116
+ end
117
+ end
metadata ADDED
@@ -0,0 +1,206 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: low_card_tables
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Andrew Geweke
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2013-12-03 00:00:00 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: bundler
16
+ prerelease: false
17
+ requirement: &id001 !ruby/object:Gem::Requirement
18
+ requirements:
19
+ - &id002
20
+ - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: "0"
23
+ type: :development
24
+ version_requirements: *id001
25
+ - !ruby/object:Gem::Dependency
26
+ name: rake
27
+ prerelease: false
28
+ requirement: &id003 !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - *id002
31
+ type: :development
32
+ version_requirements: *id003
33
+ - !ruby/object:Gem::Dependency
34
+ name: rspec
35
+ prerelease: false
36
+ requirement: &id004 !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: "2.14"
41
+ type: :development
42
+ version_requirements: *id004
43
+ - !ruby/object:Gem::Dependency
44
+ name: activerecord
45
+ prerelease: false
46
+ requirement: &id005 !ruby/object:Gem::Requirement
47
+ requirements:
48
+ - - ">="
49
+ - !ruby/object:Gem::Version
50
+ version: "3.0"
51
+ - - <=
52
+ - !ruby/object:Gem::Version
53
+ version: 4.99.99
54
+ type: :runtime
55
+ version_requirements: *id005
56
+ - !ruby/object:Gem::Dependency
57
+ name: activesupport
58
+ prerelease: false
59
+ requirement: &id006 !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ version: "3.0"
64
+ - - <=
65
+ - !ruby/object:Gem::Version
66
+ version: 4.99.99
67
+ type: :runtime
68
+ version_requirements: *id006
69
+ - !ruby/object:Gem::Dependency
70
+ name: activerecord-import
71
+ prerelease: false
72
+ requirement: &id007 !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - *id002
75
+ type: :runtime
76
+ version_requirements: *id007
77
+ - !ruby/object:Gem::Dependency
78
+ name: mysql2
79
+ prerelease: false
80
+ requirement: &id008 !ruby/object:Gem::Requirement
81
+ requirements:
82
+ - *id002
83
+ type: :development
84
+ version_requirements: *id008
85
+ description: "\"Bitfields for ActiveRecord\": store low-cardinality columns in a separate table for vastly more flexibility and better performance."
86
+ email:
87
+ - andrew@geweke.org
88
+ executables: []
89
+
90
+ extensions: []
91
+
92
+ extra_rdoc_files: []
93
+
94
+ files:
95
+ - .gitignore
96
+ - .travis.yml
97
+ - Gemfile
98
+ - LICENSE
99
+ - README.md
100
+ - Rakefile
101
+ - lib/low_card_tables.rb
102
+ - lib/low_card_tables/active_record/base.rb
103
+ - lib/low_card_tables/active_record/migrations.rb
104
+ - lib/low_card_tables/active_record/relation.rb
105
+ - lib/low_card_tables/active_record/scoping.rb
106
+ - lib/low_card_tables/errors.rb
107
+ - lib/low_card_tables/has_low_card_table/base.rb
108
+ - lib/low_card_tables/has_low_card_table/low_card_association.rb
109
+ - lib/low_card_tables/has_low_card_table/low_card_associations_manager.rb
110
+ - lib/low_card_tables/has_low_card_table/low_card_dynamic_method_manager.rb
111
+ - lib/low_card_tables/has_low_card_table/low_card_objects_manager.rb
112
+ - lib/low_card_tables/low_card_table/base.rb
113
+ - lib/low_card_tables/low_card_table/cache.rb
114
+ - lib/low_card_tables/low_card_table/cache_expiration/exponential_cache_expiration_policy.rb
115
+ - lib/low_card_tables/low_card_table/cache_expiration/fixed_cache_expiration_policy.rb
116
+ - lib/low_card_tables/low_card_table/cache_expiration/has_cache_expiration.rb
117
+ - lib/low_card_tables/low_card_table/cache_expiration/no_caching_expiration_policy.rb
118
+ - lib/low_card_tables/low_card_table/cache_expiration/unlimited_cache_expiration_policy.rb
119
+ - lib/low_card_tables/low_card_table/row_collapser.rb
120
+ - lib/low_card_tables/low_card_table/row_manager.rb
121
+ - lib/low_card_tables/low_card_table/table_unique_index.rb
122
+ - lib/low_card_tables/version.rb
123
+ - lib/low_card_tables/version_support.rb
124
+ - low_card_tables.gemspec
125
+ - spec/low_card_tables/helpers/database_helper.rb
126
+ - spec/low_card_tables/helpers/query_spy_helper.rb
127
+ - spec/low_card_tables/helpers/system_helpers.rb
128
+ - spec/low_card_tables/system/basic_system_spec.rb
129
+ - spec/low_card_tables/system/bulk_system_spec.rb
130
+ - spec/low_card_tables/system/caching_system_spec.rb
131
+ - spec/low_card_tables/system/migrations_system_spec.rb
132
+ - spec/low_card_tables/system/options_system_spec.rb
133
+ - spec/low_card_tables/system/queries_system_spec.rb
134
+ - spec/low_card_tables/system/validations_system_spec.rb
135
+ - spec/low_card_tables/unit/active_record/base_spec.rb
136
+ - spec/low_card_tables/unit/active_record/migrations_spec.rb
137
+ - spec/low_card_tables/unit/active_record/relation_spec.rb
138
+ - spec/low_card_tables/unit/active_record/scoping_spec.rb
139
+ - spec/low_card_tables/unit/has_low_card_table/base_spec.rb
140
+ - spec/low_card_tables/unit/has_low_card_table/low_card_association_spec.rb
141
+ - spec/low_card_tables/unit/has_low_card_table/low_card_associations_manager_spec.rb
142
+ - spec/low_card_tables/unit/has_low_card_table/low_card_dynamic_method_manager_spec.rb
143
+ - spec/low_card_tables/unit/has_low_card_table/low_card_objects_manager_spec.rb
144
+ - spec/low_card_tables/unit/low_card_table/base_spec.rb
145
+ - spec/low_card_tables/unit/low_card_table/cache_expiration/exponential_cache_expiration_policy_spec.rb
146
+ - spec/low_card_tables/unit/low_card_table/cache_expiration/fixed_cache_expiration_policy_spec.rb
147
+ - spec/low_card_tables/unit/low_card_table/cache_expiration/has_cache_expiration_policy_spec.rb
148
+ - spec/low_card_tables/unit/low_card_table/cache_expiration/no_caching_expiration_policy_spec.rb
149
+ - spec/low_card_tables/unit/low_card_table/cache_expiration/unlimited_cache_expiration_policy_spec.rb
150
+ - spec/low_card_tables/unit/low_card_table/cache_spec.rb
151
+ - spec/low_card_tables/unit/low_card_table/row_collapser_spec.rb
152
+ - spec/low_card_tables/unit/low_card_table/row_manager_spec.rb
153
+ - spec/low_card_tables/unit/low_card_table/table_unique_index_spec.rb
154
+ homepage: https://github.com/ageweke/low_card_tables
155
+ licenses:
156
+ - MIT
157
+ metadata: {}
158
+
159
+ post_install_message:
160
+ rdoc_options: []
161
+
162
+ require_paths:
163
+ - lib
164
+ required_ruby_version: !ruby/object:Gem::Requirement
165
+ requirements:
166
+ - *id002
167
+ required_rubygems_version: !ruby/object:Gem::Requirement
168
+ requirements:
169
+ - *id002
170
+ requirements: []
171
+
172
+ rubyforge_project:
173
+ rubygems_version: 2.0.13
174
+ signing_key:
175
+ specification_version: 4
176
+ summary: "\"Bitfields for ActiveRecord\": instead of storing multiple columns with low cardinality (few distinct values) directly in a table, which results in performance and maintainability problems, break them out into a separate table with almost zero overhead. Trivially add new columns without migrating a main, enormous table. Query on combinations of values very efficiently."
177
+ test_files:
178
+ - spec/low_card_tables/helpers/database_helper.rb
179
+ - spec/low_card_tables/helpers/query_spy_helper.rb
180
+ - spec/low_card_tables/helpers/system_helpers.rb
181
+ - spec/low_card_tables/system/basic_system_spec.rb
182
+ - spec/low_card_tables/system/bulk_system_spec.rb
183
+ - spec/low_card_tables/system/caching_system_spec.rb
184
+ - spec/low_card_tables/system/migrations_system_spec.rb
185
+ - spec/low_card_tables/system/options_system_spec.rb
186
+ - spec/low_card_tables/system/queries_system_spec.rb
187
+ - spec/low_card_tables/system/validations_system_spec.rb
188
+ - spec/low_card_tables/unit/active_record/base_spec.rb
189
+ - spec/low_card_tables/unit/active_record/migrations_spec.rb
190
+ - spec/low_card_tables/unit/active_record/relation_spec.rb
191
+ - spec/low_card_tables/unit/active_record/scoping_spec.rb
192
+ - spec/low_card_tables/unit/has_low_card_table/base_spec.rb
193
+ - spec/low_card_tables/unit/has_low_card_table/low_card_association_spec.rb
194
+ - spec/low_card_tables/unit/has_low_card_table/low_card_associations_manager_spec.rb
195
+ - spec/low_card_tables/unit/has_low_card_table/low_card_dynamic_method_manager_spec.rb
196
+ - spec/low_card_tables/unit/has_low_card_table/low_card_objects_manager_spec.rb
197
+ - spec/low_card_tables/unit/low_card_table/base_spec.rb
198
+ - spec/low_card_tables/unit/low_card_table/cache_expiration/exponential_cache_expiration_policy_spec.rb
199
+ - spec/low_card_tables/unit/low_card_table/cache_expiration/fixed_cache_expiration_policy_spec.rb
200
+ - spec/low_card_tables/unit/low_card_table/cache_expiration/has_cache_expiration_policy_spec.rb
201
+ - spec/low_card_tables/unit/low_card_table/cache_expiration/no_caching_expiration_policy_spec.rb
202
+ - spec/low_card_tables/unit/low_card_table/cache_expiration/unlimited_cache_expiration_policy_spec.rb
203
+ - spec/low_card_tables/unit/low_card_table/cache_spec.rb
204
+ - spec/low_card_tables/unit/low_card_table/row_collapser_spec.rb
205
+ - spec/low_card_tables/unit/low_card_table/row_manager_spec.rb
206
+ - spec/low_card_tables/unit/low_card_table/table_unique_index_spec.rb