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 +1 -1
- data/data_miner.gemspec +1 -1
- data/lib/data_miner/schema.rb +55 -37
- data/test/data_miner_test.rb +43 -1
- metadata +2 -2
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.4.
|
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.
|
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"]
|
data/lib/data_miner/schema.rb
CHANGED
@@ -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 #{
|
41
|
+
"Define a table called #{table_name} with primary key #{ideal_primary_key_name}"
|
38
42
|
end
|
39
43
|
|
40
44
|
def inspect
|
41
|
-
"
|
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
|
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
|
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
|
-
|
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
|
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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
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
|
-
|
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 ==
|
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
|
data/test/data_miner_test.rb
CHANGED
@@ -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'
|
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
|