baza 0.0.0 → 0.0.1
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/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
|