baza 0.0.0 → 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +1 -0
- data/Gemfile.lock +2 -0
- data/README.rdoc +106 -1
- data/VERSION +1 -1
- data/baza.gemspec +103 -0
- data/include/db.rb +108 -29
- data/include/drivers/mysql/mysql.rb +52 -47
- data/include/drivers/mysql/mysql_columns.rb +48 -41
- data/include/drivers/mysql/mysql_indexes.rb +2 -2
- data/include/drivers/mysql/mysql_tables.rb +91 -59
- data/include/drivers/sqlite3/sqlite3.rb +66 -45
- data/include/drivers/sqlite3/sqlite3_columns.rb +41 -39
- data/include/drivers/sqlite3/sqlite3_indexes.rb +2 -2
- data/include/drivers/sqlite3/sqlite3_tables.rb +86 -54
- data/include/dump.rb +5 -2
- data/include/revision.rb +130 -90
- data/spec/baza_spec.rb +312 -263
- data/spec/info_mysql_example.rb +6 -0
- data/spec/info_sqlite3.rb +20 -0
- metadata +22 -3
data/include/revision.rb
CHANGED
@@ -28,53 +28,71 @@ class Baza::Revision
|
|
28
28
|
@args = args
|
29
29
|
end
|
30
30
|
|
31
|
+
INIT_DB_ALLOWED_ARGS = [:db, :schema, :tables_cache, :debug]
|
32
|
+
INIT_DB_SCHEMA_ALLOWED_ARGS = [:tables]
|
33
|
+
INIT_DB_TABLE_ALLOWED_ARGS = [:columns, :indexes, :rows, :renames]
|
31
34
|
#This initializes a database-structure and content based on a schema-hash.
|
32
35
|
#===Examples
|
33
36
|
# dbrev = Baza::Revision.new
|
34
37
|
# dbrev.init_db("db" => db_obj, "schema" => schema_hash)
|
35
38
|
def init_db(args)
|
36
|
-
|
37
|
-
|
39
|
+
args.each do |key, val|
|
40
|
+
raise "Invalid key: '#{key}' (#{key.class.name})." unless INIT_DB_ALLOWED_ARGS.include?(key)
|
41
|
+
end
|
42
|
+
|
43
|
+
schema = args[:schema]
|
44
|
+
db = args[:db]
|
45
|
+
|
46
|
+
schema.each do |key, val|
|
47
|
+
raise "Invalid key for schema: '#{key}' (#{key.class.name})." unless INIT_DB_SCHEMA_ALLOWED_ARGS.include?(key)
|
48
|
+
end
|
38
49
|
|
39
50
|
#Check for normal bugs and raise apropiate error.
|
40
51
|
raise "'schema' argument was not a Hash: '#{schema.class.name}'." if !schema.is_a?(Hash)
|
41
|
-
raise "
|
42
|
-
raise "No tables given." if !schema.has_key?("tables")
|
52
|
+
raise "No tables given." if !schema.has_key?(:tables)
|
43
53
|
|
44
54
|
#Cache tables to avoid constant reloading.
|
45
|
-
if !args.key?(
|
46
|
-
|
55
|
+
if !args.key?(:tables_cache) or args[:tables_cache]
|
56
|
+
puts "Caching tables-list." if args[:debug]
|
47
57
|
tables = db.tables.list
|
48
58
|
else
|
49
|
-
|
59
|
+
puts "Skipping tables-cache." if args[:debug]
|
50
60
|
end
|
51
61
|
|
52
|
-
schema[
|
62
|
+
schema[:tables].each do |table_name, table_data|
|
63
|
+
table_data.each do |key, val|
|
64
|
+
raise "Invalid key: '#{key}' (#{key.class.name})." unless INIT_DB_TABLE_ALLOWED_ARGS.include?(key)
|
65
|
+
end
|
66
|
+
|
53
67
|
begin
|
54
68
|
begin
|
69
|
+
table_name = table_name.to_sym
|
70
|
+
|
71
|
+
puts "Getting table-object for table: '#{table_name}'." if args[:debug]
|
55
72
|
table_obj = db.tables[table_name]
|
56
73
|
|
57
74
|
#Cache indexes- and column-objects to avoid constant reloading.
|
58
75
|
cols = table_obj.columns
|
59
76
|
indexes = table_obj.indexes
|
60
77
|
|
61
|
-
if table_data[
|
78
|
+
if table_data[:columns]
|
62
79
|
first_col = true
|
63
|
-
table_data[
|
80
|
+
table_data[:columns].each do |col_data|
|
64
81
|
begin
|
65
|
-
|
82
|
+
col_name = col_data[:name].to_sym
|
83
|
+
col_obj = table_obj.column(col_name)
|
66
84
|
col_str = "#{table_name}.#{col_obj.name}"
|
67
|
-
type = col_data[
|
85
|
+
type = col_data[:type].to_sym
|
68
86
|
dochange = false
|
69
87
|
|
70
|
-
if !first_col and !col_data[
|
88
|
+
if !first_col and !col_data[:after]
|
71
89
|
#Try to find out the previous column - if so we can set "after" which makes the column being created in the right order as defined.
|
72
|
-
if !col_data.has_key?(
|
73
|
-
prev_no = table_data[
|
90
|
+
if !col_data.has_key?(:after)
|
91
|
+
prev_no = table_data[:columns].index(col_data)
|
74
92
|
if prev_no != nil and prev_no != 0
|
75
93
|
prev_no = prev_no - 1
|
76
|
-
prev_col_data = table_data[
|
77
|
-
col_data[
|
94
|
+
prev_col_data = table_data[:columns][prev_no]
|
95
|
+
col_data[:after] = prev_col_data[:name]
|
78
96
|
end
|
79
97
|
end
|
80
98
|
|
@@ -88,63 +106,66 @@ class Baza::Revision
|
|
88
106
|
end
|
89
107
|
end
|
90
108
|
|
91
|
-
if actual_after != col_data[
|
92
|
-
print "Changing '#{col_str}' after from '#{actual_after}' to '#{col_data[
|
109
|
+
if actual_after != col_data[:after]
|
110
|
+
print "Changing '#{col_str}' after from '#{actual_after}' to '#{col_data[:after]}'.\n" if args[:debug]
|
93
111
|
dochange = true
|
94
112
|
end
|
95
113
|
end
|
96
114
|
|
97
115
|
#BUGFIX: When using SQLite3 the primary-column or a autoincr-column may never change type from int... This will break it!
|
98
|
-
if db.opts[:type] == "sqlite3" and col_obj.type.to_s == "int" and (col_data[
|
99
|
-
type =
|
116
|
+
if db.opts[:type] == "sqlite3" and col_obj.type.to_s == "int" and (col_data[:primarykey] or col_data[:autoincr]) and db.int_types.index(col_data[:type].to_s)
|
117
|
+
type = :int
|
100
118
|
end
|
101
119
|
|
102
120
|
if type and col_obj.type.to_s != type
|
103
|
-
print "Type mismatch on #{col_str}: #{col_data[
|
121
|
+
print "Type mismatch on #{col_str}: #{col_data[:type]}, #{col_obj.type}\n" if args[:debug]
|
104
122
|
dochange = true
|
105
123
|
end
|
106
124
|
|
107
|
-
if col_data.has_key?(
|
108
|
-
print "Primary-key mismatch for #{col_str}: #{col_data[
|
125
|
+
if col_data.has_key?(:primarykey) and col_obj.primarykey? != col_data[:primarykey]
|
126
|
+
print "Primary-key mismatch for #{col_str}: #{col_data[:primarykey]}, #{col_obj.primarykey?}\n" if args[:debug]
|
109
127
|
dochange = true
|
110
128
|
end
|
111
129
|
|
112
|
-
if col_data.has_key?(
|
113
|
-
print "Auto-increment mismatch for #{col_str}: #{col_data[
|
130
|
+
if col_data.has_key?(:autoincr) and col_obj.autoincr? != col_data[:autoincr]
|
131
|
+
print "Auto-increment mismatch for #{col_str}: #{col_data[:autoincr]}, #{col_obj.autoincr?}\n" if args[:debug]
|
114
132
|
dochange = true
|
115
133
|
end
|
116
134
|
|
117
|
-
if col_data.has_key?(
|
118
|
-
print "Maxlength mismatch on #{col_str}: #{col_data[
|
135
|
+
if col_data.has_key?(:maxlength) and col_obj.maxlength.to_s != col_data[:maxlength].to_s
|
136
|
+
print "Maxlength mismatch on #{col_str}: #{col_data[:maxlength]}, #{col_obj.maxlength}\n" if args[:debug]
|
119
137
|
dochange = true
|
120
138
|
end
|
121
139
|
|
122
|
-
if col_data.has_key?(
|
123
|
-
print "Null mismatch on #{col_str}: #{col_data[
|
140
|
+
if col_data.has_key?(:null) and col_obj.null?.to_s != col_data[:null].to_s
|
141
|
+
print "Null mismatch on #{col_str}: #{col_data[:null]}, #{col_obj.null?}\n" if args[:debug]
|
124
142
|
dochange = true
|
125
143
|
end
|
126
144
|
|
127
|
-
if col_data.has_key?(
|
128
|
-
print "Default mismatch on #{col_str}: #{col_data[
|
145
|
+
if col_data.has_key?(:default) and col_obj.default.to_s != col_data[:default].to_s
|
146
|
+
print "Default mismatch on #{col_str}: #{col_data[:default]}, #{col_obj.default}\n" if args[:debug]
|
129
147
|
dochange = true
|
130
148
|
end
|
131
149
|
|
132
|
-
if col_data.has_key?(
|
133
|
-
print "Comment mismatch on #{col_str}: #{col_data[
|
150
|
+
if col_data.has_key?(:comment) and col_obj.respond_to?(:comment) and col_obj.comment.to_s != col_data[:comment].to_s
|
151
|
+
print "Comment mismatch on #{col_str}: #{col_data[:comment]}, #{col_obj.comment}\n" if args[:debug]
|
134
152
|
dochange = true
|
135
153
|
end
|
136
154
|
|
137
|
-
if col_data.is_a?(Hash) and col_data[
|
138
|
-
callback_data = col_data[
|
139
|
-
if callback_data and callback_data[
|
140
|
-
if callback_data[
|
155
|
+
if col_data.is_a?(Hash) and col_data[:on_before_alter]
|
156
|
+
callback_data = col_data[:on_before_alter].call(:db => db, :table => table_obj, :col => col_obj, :col_data => col_data)
|
157
|
+
if callback_data and callback_data[:action]
|
158
|
+
if callback_data[:action] == :retry
|
141
159
|
raise Knj::Errors::Retry
|
142
160
|
end
|
143
161
|
end
|
144
162
|
end
|
145
163
|
|
146
164
|
if dochange
|
147
|
-
|
165
|
+
col_data_change = col_data.clone
|
166
|
+
col_data_change.delete(:renames)
|
167
|
+
|
168
|
+
col_obj.change(col_data_change)
|
148
169
|
|
149
170
|
#Change has been made - update cache.
|
150
171
|
cols = table_obj.columns
|
@@ -152,31 +173,34 @@ class Baza::Revision
|
|
152
173
|
|
153
174
|
first_col = false
|
154
175
|
rescue Errno::ENOENT => e
|
155
|
-
print "Column not found: #{table_obj.name}.#{col_data[
|
176
|
+
print "Column not found: #{table_obj.name}.#{col_data[:name]}.\n" if args[:debug]
|
156
177
|
|
157
|
-
if col_data.has_key?(
|
158
|
-
raise "'renames' was not an array for column '#{table_obj.name}.#{col_data[
|
178
|
+
if col_data.has_key?(:renames)
|
179
|
+
raise "'renames' was not an array for column '#{table_obj.name}.#{col_data[:name]}'." if !col_data[:renames].is_a?(Array)
|
159
180
|
|
160
181
|
rename_found = false
|
161
|
-
col_data[
|
182
|
+
col_data[:renames].each do |col_name|
|
162
183
|
begin
|
163
184
|
col_rename = table_obj.column(col_name)
|
164
185
|
rescue Errno::ENOENT => e
|
165
186
|
next
|
166
187
|
end
|
167
188
|
|
168
|
-
print "Rename #{table_obj.name}.#{col_name} to #{table_obj.name}.#{col_data[
|
169
|
-
if col_data.is_a?(Hash) and col_data[
|
170
|
-
col_data[
|
189
|
+
print "Rename #{table_obj.name}.#{col_name} to #{table_obj.name}.#{col_data[:name]}\n" if args[:debug]
|
190
|
+
if col_data.is_a?(Hash) and col_data[:on_before_rename]
|
191
|
+
col_data[:on_before_rename].call(:db => db, :table => table_obj, :col => col_rename, :col_data => col_data)
|
171
192
|
end
|
172
193
|
|
173
|
-
|
194
|
+
col_data_change = col_data.clone
|
195
|
+
col_data_change.delete(:renames)
|
196
|
+
|
197
|
+
col_rename.change(col_data_change)
|
174
198
|
|
175
199
|
#Change has been made - update cache.
|
176
200
|
cols = table_obj.columns
|
177
201
|
|
178
|
-
if col_data.is_a?(Hash) and col_data[
|
179
|
-
col_data[
|
202
|
+
if col_data.is_a?(Hash) and col_data[:on_after_rename]
|
203
|
+
col_data[:on_after_rename].call(:db => db, :table => table_obj, :col => col_rename, :col_data => col_data)
|
180
204
|
end
|
181
205
|
|
182
206
|
rename_found = true
|
@@ -186,42 +210,46 @@ class Baza::Revision
|
|
186
210
|
retry if rename_found
|
187
211
|
end
|
188
212
|
|
189
|
-
oncreated = col_data[
|
190
|
-
col_data.delete(
|
213
|
+
oncreated = col_data[:on_created]
|
214
|
+
col_data.delete(:on_created) if col_data[:oncreated]
|
215
|
+
|
216
|
+
col_data_create = col_data
|
217
|
+
col_data_create.delete(:renames)
|
218
|
+
|
191
219
|
col_obj = table_obj.create_columns([col_data])
|
192
220
|
|
193
221
|
#Change has been made - update cache.
|
194
222
|
cols = table_obj.columns
|
195
223
|
|
196
|
-
oncreated.call(
|
224
|
+
oncreated.call(:db => db, :table => table_obj) if oncreated
|
197
225
|
end
|
198
226
|
end
|
199
227
|
end
|
200
228
|
|
201
|
-
if table_data[
|
202
|
-
table_data[
|
229
|
+
if table_data[:columns_remove]
|
230
|
+
table_data[:columns_remove].each do |column_name, column_data|
|
203
231
|
begin
|
204
232
|
col_obj = table_obj.column(column_name)
|
205
233
|
rescue Errno::ENOENT => e
|
206
234
|
next
|
207
235
|
end
|
208
236
|
|
209
|
-
column_data[
|
237
|
+
column_data[:callback].call if column_data.is_a?(Hash) and column_data[:callback]
|
210
238
|
col_obj.drop
|
211
239
|
end
|
212
240
|
end
|
213
241
|
|
214
|
-
if table_data[
|
215
|
-
table_data[
|
242
|
+
if table_data[:indexes]
|
243
|
+
table_data[:indexes].each do |index_data|
|
216
244
|
if index_data.is_a?(String)
|
217
|
-
index_data = {
|
245
|
+
index_data = {:name => index_data, :columns => [index_data]}
|
218
246
|
end
|
219
247
|
|
220
248
|
begin
|
221
|
-
index_obj = table_obj.index(index_data[
|
249
|
+
index_obj = table_obj.index(index_data[:name])
|
222
250
|
|
223
251
|
rewrite_index = false
|
224
|
-
rewrite_index = true if index_data.key?(
|
252
|
+
rewrite_index = true if index_data.key?(:unique) and index_data[:unique] != index_obj.unique?
|
225
253
|
|
226
254
|
if rewrite_index
|
227
255
|
index_obj.drop
|
@@ -233,27 +261,30 @@ class Baza::Revision
|
|
233
261
|
end
|
234
262
|
end
|
235
263
|
|
236
|
-
if table_data[
|
237
|
-
table_data[
|
264
|
+
if table_data[:indexes_remove]
|
265
|
+
table_data[:indexes_remove].each do |index_name, index_data|
|
238
266
|
begin
|
239
267
|
index_obj = table_obj.index(index_name)
|
240
268
|
rescue Errno::ENOENT => e
|
241
269
|
next
|
242
270
|
end
|
243
271
|
|
244
|
-
if index_data.is_a?(Hash) and index_data[
|
245
|
-
index_data[
|
272
|
+
if index_data.is_a?(Hash) and index_data[:callback]
|
273
|
+
index_data[:callback].call if index_data[:callback]
|
246
274
|
end
|
247
275
|
|
248
276
|
index_obj.drop
|
249
277
|
end
|
250
278
|
end
|
251
279
|
|
252
|
-
rows_init(
|
280
|
+
rows_init(:db => db, :table => table_obj, :rows => table_data[:rows]) if table_data and table_data[:rows]
|
253
281
|
rescue Errno::ENOENT => e
|
254
|
-
|
255
|
-
|
282
|
+
puts "Table did not exist: '#{table_name}'." if args[:debug]
|
283
|
+
|
284
|
+
if table_data.key?(:renames)
|
285
|
+
table_data[:renames].each do |table_name_rename|
|
256
286
|
begin
|
287
|
+
puts "Renaming table: '#{table_name_rename}' to '#{table_name}'." if args[:debug]
|
257
288
|
table_rename = db.tables[table_name_rename.to_sym]
|
258
289
|
table_rename.rename(table_name)
|
259
290
|
raise Knj::Errors::Retry
|
@@ -263,34 +294,38 @@ class Baza::Revision
|
|
263
294
|
end
|
264
295
|
end
|
265
296
|
|
266
|
-
if !table_data.key?(
|
297
|
+
if !table_data.key?(:columns)
|
267
298
|
print "Notice: Skipping creation of '#{table_name}' because no columns were given in hash.\n"
|
268
299
|
next
|
269
300
|
end
|
270
301
|
|
271
|
-
if table_data[
|
272
|
-
table_data[
|
302
|
+
if table_data[:on_create]
|
303
|
+
table_data[:on_create].call(:db => db, :table_name => table_name, :table_data => table_data)
|
273
304
|
end
|
274
305
|
|
275
|
-
|
306
|
+
table_data_create = table_data.clone
|
307
|
+
table_data_create.delete(:rows)
|
308
|
+
|
309
|
+
puts "Creating table: '#{table_name}'." if args[:debug]
|
310
|
+
db.tables.create(table_name, table_data_create)
|
276
311
|
table_obj = db.tables[table_name.to_sym]
|
277
312
|
|
278
|
-
if table_data[
|
279
|
-
table_data[
|
313
|
+
if table_data[:on_create_after]
|
314
|
+
table_data[:on_create_after].call(:db => db, :table_name => table_name, :table_data => table_data)
|
280
315
|
end
|
281
316
|
|
282
|
-
rows_init(
|
317
|
+
rows_init(:db => db, :table => table_obj, :rows => table_data[:rows]) if table_data[:rows]
|
283
318
|
end
|
284
319
|
rescue Knj::Errors::Retry
|
285
320
|
retry
|
286
321
|
end
|
287
322
|
end
|
288
323
|
|
289
|
-
if schema[
|
290
|
-
schema[
|
324
|
+
if schema[:tables_remove]
|
325
|
+
schema[:tables_remove].each do |table_name, table_data|
|
291
326
|
begin
|
292
327
|
table_obj = db.tables[table_name.to_sym]
|
293
|
-
table_data[
|
328
|
+
table_data[:callback].call(:db => db, :table => table_obj) if table_data.is_a?(Hash) and table_data[:callback]
|
294
329
|
table_obj.drop
|
295
330
|
rescue Errno::ENOENT => e
|
296
331
|
next
|
@@ -306,36 +341,41 @@ class Baza::Revision
|
|
306
341
|
|
307
342
|
private
|
308
343
|
|
344
|
+
ROWS_INIT_ALLOWED_ARGS = [:db, :table, :rows]
|
309
345
|
#This method checks if certain rows are present in a table based on a hash.
|
310
346
|
def rows_init(args)
|
311
|
-
|
312
|
-
|
347
|
+
args.each do |key, val|
|
348
|
+
raise "Invalid key: '#{key}' (#{key.class.name})." unless ROWS_INIT_ALLOWED_ARGS.include?(key)
|
349
|
+
end
|
350
|
+
|
351
|
+
db = args[:db]
|
352
|
+
table = args[:table]
|
313
353
|
|
314
354
|
raise "No db given." if !db
|
315
355
|
raise "No table given." if !table
|
316
356
|
|
317
|
-
args[
|
318
|
-
if row_data[
|
319
|
-
find_by = row_data[
|
320
|
-
elsif row_data[
|
321
|
-
find_by = row_data[
|
357
|
+
args[:rows].each do |row_data|
|
358
|
+
if row_data[:find_by]
|
359
|
+
find_by = row_data[:find_by]
|
360
|
+
elsif row_data[:data]
|
361
|
+
find_by = row_data[:data]
|
322
362
|
else
|
323
363
|
raise "Could not figure out the find-by."
|
324
364
|
end
|
325
365
|
|
326
366
|
rows_found = 0
|
327
|
-
args[
|
367
|
+
args[:db].select(table.name, find_by) do |d_rows|
|
328
368
|
rows_found += 1
|
329
369
|
|
330
|
-
if Knj::ArrayExt.hash_diff?(Knj::ArrayExt.hash_sym(row_data[
|
331
|
-
print "Data was not right - updating row: #{JSON.generate(row_data[
|
332
|
-
args[
|
370
|
+
if Knj::ArrayExt.hash_diff?(Knj::ArrayExt.hash_sym(row_data[:data]), Knj::ArrayExt.hash_sym(d_rows), {"h2_to_h1" => false})
|
371
|
+
print "Data was not right - updating row: #{JSON.generate(row_data[:data])}\n" if args[:debug]
|
372
|
+
args[:db].update(table.name, row_data[:data], d_rows)
|
333
373
|
end
|
334
374
|
end
|
335
375
|
|
336
376
|
if rows_found == 0
|
337
|
-
print "Inserting row: #{JSON.generate(row_data[
|
338
|
-
table.insert(row_data[
|
377
|
+
print "Inserting row: #{JSON.generate(row_data[:data])}\n" if args[:debug]
|
378
|
+
table.insert(row_data[:data])
|
339
379
|
end
|
340
380
|
end
|
341
381
|
end
|