data_miner 0.4.31 → 0.4.32

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/VERSION CHANGED
@@ -1 +1 @@
1
- 0.4.31
1
+ 0.4.32
data/data_miner.gemspec CHANGED
@@ -5,7 +5,7 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{data_miner}
8
- s.version = "0.4.31"
8
+ s.version = "0.4.32"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Seamus Abshere", "Andy Rossmeissl"]
@@ -11,6 +11,10 @@ module DataMiner
11
11
  @configuration = configuration
12
12
  @position_in_run = position_in_run
13
13
  @create_table_options = create_table_options
14
+ @create_table_options.symbolize_keys!
15
+ DataMiner.log_or_raise ":id => true is not allowed in create_table_options." if @create_table_options[:id] === true
16
+ DataMiner.log_or_raise ":primary_key is not allowed in create_table_options. Use set_primary_key instead." if @create_table_options.has_key?(:primary_key)
17
+ @create_table_options[:id] = false # always
14
18
  end
15
19
 
16
20
  def connection
@@ -34,11 +38,11 @@ module DataMiner
34
38
  end
35
39
 
36
40
  def description
37
- "Define a table called #{table_name} with primary key #{primary_key}"
41
+ "Define a table called #{table_name} with primary key #{ideal_primary_key_name}"
38
42
  end
39
43
 
40
44
  def inspect
41
- "Block(#{resource}): #{description}"
45
+ "Schema(#{resource}): #{description}"
42
46
  end
43
47
 
44
48
  # lifted straight from activerecord-3.0.0.beta3/lib/active_record/connection_adapters/abstract/schema_definitions.rb
@@ -55,31 +59,46 @@ module DataMiner
55
59
  def column(*args)
56
60
  ideal_table.column(*args)
57
61
  end
58
- # class IndexDefinition < Struct.new(:table, :name, :unique, :columns)
59
62
  def index(columns, options = {})
60
63
  options.symbolize_keys!
61
64
  columns = Array.wrap columns
62
- name = connection.index_name table_name, options.merge(:columns => columns)
65
+ name = options[:name] || connection.index_name(table_name, options.merge(:column => columns))
63
66
  index_unique = options.has_key?(:unique) ? options[:unique] : true
64
67
  ideal_indexes.push ActiveRecord::ConnectionAdapters::IndexDefinition.new(table_name, name, index_unique, columns)
65
68
  end
66
-
67
- def primary_key
69
+
70
+ def ideal_primary_key_name
68
71
  resource.primary_key.to_s
69
72
  end
70
73
 
74
+ def actual_primary_key_name
75
+ connection.primary_key(table_name).to_s
76
+ end
77
+
71
78
  INDEX_PROPERTIES = %w{ name columns }
72
- COLUMN_PROPERTIES = %w{ name type }
79
+ def index_equivalent?(a, b)
80
+ return false unless a and b
81
+ INDEX_PROPERTIES.all? do |property|
82
+ DataMiner.log_debug "...comparing #{a.send(property).inspect}.to_s <-> #{b.send(property).inspect}.to_s"
83
+ a.send(property).to_s == b.send(property).to_s
84
+ end
85
+ end
86
+
87
+ # FIXME mysql only (assume integer primary keys)
88
+ def column_equivalent?(a, b)
89
+ return false unless a and b
90
+ a_type = a.type.to_s == 'primary_key' ? 'integer' : a.type.to_s
91
+ b_type = b.type.to_s == 'primary_key' ? 'integer' : b.type.to_s
92
+ a_type == b_type and a.name.to_s == b.name.to_s
93
+ end
94
+
73
95
  %w{ column index }.each do |i|
74
96
  eval %{
75
97
  def #{i}_needs_to_be_placed?(name)
76
98
  actual = actual_#{i} name
77
99
  return true unless actual
78
100
  ideal = ideal_#{i} name
79
- #{i.upcase}_PROPERTIES.any? do |property|
80
- DataMiner.log_debug "...comparing \#{actual.send(property).inspect}.to_s <-> \#{ideal.send(property).inspect}.to_s"
81
- actual.send(property).to_s != ideal.send(property).to_s
82
- end
101
+ not #{i}_equivalent? actual, ideal
83
102
  end
84
103
 
85
104
  def #{i}_needs_to_be_removed?(name)
@@ -107,13 +126,13 @@ module DataMiner
107
126
  def place_column(name)
108
127
  remove_column name if actual_column name
109
128
  ideal = ideal_column name
110
- DataMiner.log_info "adding column #{name}"
129
+ DataMiner.log_debug "ADDING COLUMN #{name}"
111
130
  connection.add_column table_name, name, ideal.type.to_sym # symbol type!
112
131
  resource.reset_column_information
113
132
  end
114
133
 
115
134
  def remove_column(name)
116
- DataMiner.log_info "removing column #{name}"
135
+ DataMiner.log_debug "REMOVING COLUMN #{name}"
117
136
  connection.remove_column table_name, name
118
137
  resource.reset_column_information
119
138
  end
@@ -121,17 +140,17 @@ module DataMiner
121
140
  def place_index(name)
122
141
  remove_index name if actual_index name
123
142
  ideal = ideal_index name
124
- DataMiner.log_info "adding index #{name}"
143
+ DataMiner.log_debug "ADDING INDEX #{name}"
125
144
  connection.add_index table_name, ideal.columns, :name => ideal.name
126
145
  resource.reset_column_information
127
146
  end
128
147
 
129
148
  def remove_index(name)
130
- DataMiner.log_info "removing index #{name}"
149
+ DataMiner.log_debug "REMOVING INDEX #{name}"
131
150
  connection.remove_index table_name, :name => name
132
151
  resource.reset_column_information
133
152
  end
134
-
153
+
135
154
  def run(run)
136
155
  _add_extra_columns
137
156
  _create_table
@@ -140,7 +159,7 @@ module DataMiner
140
159
  _add_columns
141
160
  _remove_indexes
142
161
  _add_indexes
143
- DataMiner.log_info "ran #{inspect}"
162
+ DataMiner.log_debug "ran #{inspect}"
144
163
  end
145
164
 
146
165
  EXTRA_COLUMNS = {
@@ -157,7 +176,7 @@ module DataMiner
157
176
 
158
177
  def _create_table
159
178
  if not resource.table_exists?
160
- DataMiner.log_info "creating table #{table_name} with #{create_table_options.inspect}"
179
+ DataMiner.log_debug "CREATING TABLE #{table_name} with #{create_table_options.inspect}"
161
180
  connection.create_table table_name, create_table_options do |t|
162
181
  t.integer :data_miner_placeholder
163
182
  end
@@ -167,26 +186,25 @@ module DataMiner
167
186
 
168
187
  # FIXME mysql only
169
188
  def _set_primary_key
170
- if column_needs_to_be_placed?(primary_key)
171
- retries_allowed = 1
172
- begin
173
- place_column primary_key
174
- DataMiner.log_info "adding primary key #{primary_key}"
175
- connection.execute "ALTER TABLE `#{table_name}` ADD PRIMARY KEY (`#{primary_key}`)"
176
- rescue
177
- if retries_allowed > 0 and $!.message =~ /primary/i
178
- DataMiner.log_info "looks like primary key changed, re-creating table from scratch"
179
- connection.drop_table table_name
180
- resource.reset_column_information
181
- _create_table
182
- retries_allowed -= 1
183
- retry
184
- else
185
- raise $!
186
- end
189
+ if ideal_primary_key_name == 'id' and not ideal_column('id')
190
+ DataMiner.log_debug "no special primary key set on #{table_name}, so using 'id'"
191
+ column 'id', :primary_key
192
+ end
193
+ actual = actual_column actual_primary_key_name
194
+ ideal = ideal_column ideal_primary_key_name
195
+ if not column_equivalent? actual, ideal
196
+ DataMiner.log_debug "looks like #{table_name} has a bad (or missing) primary key"
197
+ if actual
198
+ DataMiner.log_debug "looks like primary key needs to change from #{actual_primary_key_name} to #{ideal_primary_key_name}, re-creating #{table_name} from scratch"
199
+ connection.drop_table table_name
200
+ resource.reset_column_information
201
+ _create_table
187
202
  end
188
- resource.reset_column_information
203
+ place_column ideal_primary_key_name
204
+ DataMiner.log_debug "ADDING PRIMARY KEY #{ideal_primary_key_name}"
205
+ connection.execute "ALTER TABLE `#{table_name}` ADD PRIMARY KEY (`#{ideal_primary_key_name}`)"
189
206
  end
207
+ resource.reset_column_information
190
208
  end
191
209
 
192
210
  def _remove_columns
@@ -209,7 +227,7 @@ module DataMiner
209
227
 
210
228
  def _add_indexes
211
229
  ideal_indexes.each do |ideal|
212
- next if ideal.name == primary_key # this should already have been taken care of
230
+ next if ideal.name == ideal_primary_key_name # this should already have been taken care of
213
231
  place_index ideal.name if index_needs_to_be_placed? ideal.name
214
232
  end
215
233
  end
@@ -1123,7 +1123,19 @@ end
1123
1123
  class CensusDivisionTrois < ActiveRecord::Base
1124
1124
  set_primary_key :number_code
1125
1125
  data_miner do
1126
- schema :options => 'ENGINE=InnoDB default charset=utf8', :id => false do
1126
+ schema :options => 'ENGINE=InnoDB default charset=utf8' do
1127
+ string 'number_code'
1128
+ string 'name'
1129
+ string 'census_region_name'
1130
+ integer 'census_region_number'
1131
+ index 'census_region_name', :name => 'homefry'
1132
+ end
1133
+ end
1134
+ end
1135
+
1136
+ class CensusDivisionFour < ActiveRecord::Base
1137
+ data_miner do
1138
+ schema do
1127
1139
  string 'number_code'
1128
1140
  string 'name'
1129
1141
  string 'census_region_name'
@@ -1169,6 +1181,36 @@ class DataMinerTest < Test::Unit::TestCase
1169
1181
  end
1170
1182
  end
1171
1183
 
1184
+ should "let schemas work with default id primary keys" do
1185
+ ActiveRecord::Base.connection.create_table 'census_division_fours', :id => true, :force => true, :options => 'ENGINE=InnoDB default charset=utf8' do |t|
1186
+ t.string 'name'
1187
+ # t.datetime 'updated_at'
1188
+ # t.datetime 'created_at'
1189
+ t.string 'census_region_name'
1190
+ # t.integer 'census_region_number'
1191
+ # t.integer 'data_miner_touch_count'
1192
+ # t.integer 'data_miner_last_run_id'
1193
+ end
1194
+ ActiveRecord::Base.connection.execute 'ALTER TABLE census_division_fours ADD INDEX (census_region_name)'
1195
+ CensusDivisionFour.reset_column_information
1196
+ missing_columns = %w{ updated_at created_at census_region_number data_miner_last_run_id data_miner_touch_count }
1197
+
1198
+ # sanity check
1199
+ missing_columns.each do |column|
1200
+ assert_equal false, CensusDivisionFour.column_names.include?(column)
1201
+ end
1202
+ assert_equal false, ActiveRecord::Base.connection.indexes(CensusDivisionFour.table_name).any? { |index| index.name == 'homefry' }
1203
+
1204
+ 3.times do
1205
+ CensusDivisionFour.run_data_miner!
1206
+ missing_columns.each do |column|
1207
+ assert_equal true, CensusDivisionFour.column_names.include?(column)
1208
+ end
1209
+ assert_equal true, ActiveRecord::Base.connection.indexes(CensusDivisionFour.table_name).any? { |index| index.name == 'homefry' }
1210
+ assert_equal :integer, CensusDivisionFour.columns_hash[CensusDivisionFour.primary_key].type
1211
+ end
1212
+ end
1213
+
1172
1214
  should "allow specifying dictionaries explicitly" do
1173
1215
  CensusDivisionDeux.run_data_miner!
1174
1216
  assert_equal 'South Region', CensusDivisionDeux.find(5).census_region_name
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 4
8
- - 31
9
- version: 0.4.31
8
+ - 32
9
+ version: 0.4.32
10
10
  platform: ruby
11
11
  authors:
12
12
  - Seamus Abshere