spqr 0.1.2 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (4) hide show
  1. data/CHANGES +12 -0
  2. data/VERSION +1 -1
  3. data/lib/rhubarb/rhubarb.rb +50 -32
  4. metadata +2 -2
data/CHANGES CHANGED
@@ -1,3 +1,15 @@
1
+ * This is a release featuring only minor enhancements to Rhubarb. If
2
+ you don't use Rhubarb, there is no need to upgrade.
3
+
4
+ * Rhubarb classes now support a delete_all method.
5
+
6
+ * Rhubarb now supports multiple backend databases, via an extra
7
+ parameter to Persistence::open and to the create_table class methods.
8
+ Note that it is not currently possible to have one class backed by
9
+ multiple databases.
10
+
11
+ version 0.1.2 (2c45fd4d693a396e9206607a6f053b1eb4696272)
12
+
1
13
  * Enhancements to SPQR/Rhubarb interoperability. (Rhubarb row_ids are
2
14
  now used for half of the QMF object ID).
3
15
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.2
1
+ 0.1.3
@@ -27,29 +27,39 @@ end
27
27
 
28
28
 
29
29
  module Persistence
30
- @@backend = nil
30
+ class DbCollection < Hash
31
+ alias orig_set []=
32
+
33
+ def []=(k,v)
34
+ v.results_as_hash = true if v
35
+ v.type_translation = true if v
36
+ orig_set(k,v)
37
+ end
38
+ end
31
39
 
32
- def self.open(filename)
33
- self.db = SQLite3::Database.new(filename)
40
+ @@dbs = DbCollection.new
41
+
42
+ def self.open(filename, which=:default)
43
+ dbs[which] = SQLite3::Database.new(filename)
34
44
  end
35
45
 
36
- def self.close
37
- self.db.close
38
- self.db = nil
46
+ def self.close(which=:default)
47
+ if dbs[which]
48
+ dbs[which].close
49
+ dbs.delete(which)
50
+ end
39
51
  end
40
52
 
41
53
  def self.db
42
- @@backend
54
+ dbs[:default]
43
55
  end
44
-
56
+
45
57
  def self.db=(d)
46
- @@backend = d
47
- self.db.results_as_hash = true if d != nil
48
- self.db.type_translation = true if d != nil
58
+ dbs[:default] = d
49
59
  end
50
-
51
- def self.execute(*query)
52
- db.execute(*query) if db != nil
60
+
61
+ def self.dbs
62
+ @@dbs
53
63
  end
54
64
  end
55
65
 
@@ -139,7 +149,7 @@ module PersistingClassMixins
139
149
  select_criteria = valid_cols.map {|col| "#{col.to_s} = #{col.inspect}"}.join(" AND ")
140
150
  arg_hash.each {|k,v| arg_hash[k] = v.row_id if v.respond_to? :row_id}
141
151
 
142
- Persistence::execute("select * from #{table_name} where #{select_criteria} order by row_id", arg_hash).map {|tup| self.new(tup) }
152
+ self.db.execute("select * from #{table_name} where #{select_criteria} order by row_id", arg_hash).map {|tup| self.new(tup) }
143
153
  end
144
154
 
145
155
  # args contains the following keys
@@ -186,12 +196,16 @@ SELECT __freshest.* FROM (
186
196
  ORDER BY row_id
187
197
  "
188
198
 
189
- Persistence::execute(query, query_params).map {|tup| self.new(tup) }
199
+ self.db.execute(query, query_params).map {|tup| self.new(tup) }
190
200
  end
191
201
 
192
202
  # Does what it says on the tin. Since this will allocate an object for each row, it isn't recomended for huge tables.
193
203
  def find_all
194
- Persistence::execute("SELECT * from #{table_name}").map {|tup| self.new(tup)}
204
+ self.db.execute("SELECT * from #{table_name}").map {|tup| self.new(tup)}
205
+ end
206
+
207
+ def delete_all
208
+ self.db.execute("DELETE from #{table_name}")
195
209
  end
196
210
 
197
211
  # Declares a query method named +name+ and adds it to this class. The query method returns a list of objects corresponding to the rows returned by executing "+SELECT * FROM+ _table_ +WHERE+ _query_" on the database.
@@ -202,7 +216,7 @@ SELECT __freshest.* FROM (
202
216
  # handle reference parameters
203
217
  args = args.map {|x| (x.row_id if x.class.ancestors.include? Persisting) or x}
204
218
 
205
- res = Persistence::execute("select * from #{table_name} where #{query}", args)
219
+ res = self.db.execute("select * from #{table_name} where #{query}", args)
206
220
  res.map {|row| self.new(row)}
207
221
  end
208
222
  end
@@ -216,7 +230,7 @@ SELECT __freshest.* FROM (
216
230
  # handle reference parameters
217
231
  args = args.map {|x| (x.row_id if x.class.ancestors.include? Persisting) or x}
218
232
 
219
- res = Persistence::execute(query.gsub("__TABLE__", "#{self.table_name}"), args)
233
+ res = self.db.execute(query.gsub("__TABLE__", "#{self.table_name}"), args)
220
234
  # XXX: should freshen each row?
221
235
  res.map {|row| self.new(row) }
222
236
  end
@@ -227,7 +241,7 @@ SELECT __freshest.* FROM (
227
241
  @creation_callbacks << Proc.new do
228
242
  idx_name = "idx_#{self.table_name}__#{fields.join('__')}__#{@creation_callbacks.size}"
229
243
  creation_cmd = "create index #{idx_name} on #{self.table_name} (#{fields.join(', ')})"
230
- Persistence.execute(creation_cmd)
244
+ self.db.execute(creation_cmd)
231
245
  end if fields.size > 0
232
246
  end
233
247
 
@@ -254,12 +268,12 @@ SELECT __freshest.* FROM (
254
268
  klass = (class << self; self end)
255
269
  klass.class_eval do
256
270
  define_method find_method_name do |arg|
257
- res = Persistence::execute("select * from #{table_name} where #{cname} = ?", arg)
271
+ res = self.db.execute("select * from #{table_name} where #{cname} = ?", arg)
258
272
  res.map {|row| self.new(row)}
259
273
  end
260
274
 
261
275
  define_method find_first_method_name do |arg|
262
- res = Persistence::execute("select * from #{table_name} where #{cname} = ?", arg)
276
+ res = self.db.execute("select * from #{table_name} where #{cname} = ?", arg)
263
277
  return self.new(res[0]) if res.size > 0
264
278
  nil
265
279
  end
@@ -311,9 +325,9 @@ SELECT __freshest.* FROM (
311
325
  insert_trigger_name = "ri_insert_#{self.table_name}_#{@ccount}_#{rf.referent.table_name}"
312
326
  delete_trigger_name = "ri_delete_#{self.table_name}_#{@ccount}_#{rf.referent.table_name}"
313
327
 
314
- Persistence::db.execute_batch("CREATE TRIGGER #{insert_trigger_name} BEFORE INSERT ON \"#{self.table_name}\" WHEN new.\"#{cname}\" IS NOT NULL AND NOT EXISTS (SELECT 1 FROM \"#{rf.referent.table_name}\" WHERE new.\"#{cname}\" == \"#{rf.column}\") BEGIN SELECT RAISE(ABORT, 'constraint #{insert_trigger_name} (#{rf.referent.table_name} missing foreign key row) failed'); END;")
328
+ self.db.execute_batch("CREATE TRIGGER #{insert_trigger_name} BEFORE INSERT ON \"#{self.table_name}\" WHEN new.\"#{cname}\" IS NOT NULL AND NOT EXISTS (SELECT 1 FROM \"#{rf.referent.table_name}\" WHERE new.\"#{cname}\" == \"#{rf.column}\") BEGIN SELECT RAISE(ABORT, 'constraint #{insert_trigger_name} (#{rf.referent.table_name} missing foreign key row) failed'); END;")
315
329
 
316
- Persistence::db.execute_batch("CREATE TRIGGER #{delete_trigger_name} BEFORE DELETE ON \"#{rf.referent.table_name}\" WHEN EXISTS (SELECT 1 FROM \"#{self.table_name}\" WHERE old.\"#{rf.column}\" == \"#{cname}\") BEGIN DELETE FROM \"#{self.table_name}\" WHERE \"#{cname}\" = old.\"#{rf.column}\"; END;") if rf.options[:on_delete] == :cascade
330
+ self.db.execute_batch("CREATE TRIGGER #{delete_trigger_name} BEFORE DELETE ON \"#{rf.referent.table_name}\" WHEN EXISTS (SELECT 1 FROM \"#{self.table_name}\" WHERE old.\"#{rf.column}\" == \"#{cname}\") BEGIN DELETE FROM \"#{self.table_name}\" WHERE \"#{cname}\" = old.\"#{rf.column}\"; END;") if rf.options[:on_delete] == :cascade
317
331
 
318
332
  @ccount = @ccount + 1
319
333
  end
@@ -344,7 +358,7 @@ SELECT __freshest.* FROM (
344
358
  new_row[k] = v.row_id if v.class.ancestors.include? Persisting
345
359
  end
346
360
 
347
- Persistence::db.transaction do |db|
361
+ self.db.transaction do |db|
348
362
  stmt = "insert into #{table_name} (#{colspec}) values (#{valspec})"
349
363
  # p stmt
350
364
  db.execute(stmt, new_row)
@@ -366,8 +380,9 @@ SELECT __freshest.* FROM (
366
380
  end
367
381
 
368
382
  # Creates a table in the database corresponding to this class.
369
- def create_table
370
- Persistence::execute(table_decl)
383
+ def create_table(dbkey=:default)
384
+ self.db = Persistence::dbs[dbkey]
385
+ self.db.execute(table_decl)
371
386
  @creation_callbacks.each {|func| func.call}
372
387
  end
373
388
 
@@ -382,7 +397,7 @@ SELECT __freshest.* FROM (
382
397
  # The API purposefully does not expose the ability to create a
383
398
  # row with a given id, and created and updated values are
384
399
  # maintained automatically by the API.
385
- attr_accessor :columns, :colnames, :constraints, :dirtied, :refs, :creation_callbacks
400
+ attr_accessor :columns, :colnames, :constraints, :dirtied, :refs, :creation_callbacks, :db
386
401
  end
387
402
  end
388
403
 
@@ -397,12 +412,12 @@ SELECT __freshest.* FROM (
397
412
 
398
413
  # Returns the number of rows in the table backing this class
399
414
  def count
400
- result = Persistence::execute("select count(row_id) from #{table_name}")[0]
415
+ result = self.db.execute("select count(row_id) from #{table_name}")[0]
401
416
  result[0].to_i
402
417
  end
403
418
 
404
419
  def find_tuple(id)
405
- res = Persistence::execute("select * from #{table_name} where row_id = ?", id)
420
+ res = self.db.execute("select * from #{table_name} where row_id = ?", id)
406
421
  if res.size == 0
407
422
  nil
408
423
  else
@@ -424,6 +439,9 @@ module Persisting
424
439
  end
425
440
  end
426
441
 
442
+ def db
443
+ self.class.db
444
+ end
427
445
 
428
446
  # Returns true if the row backing this object has been deleted from the database
429
447
  def deleted?
@@ -448,7 +466,7 @@ module Persisting
448
466
  # Deletes the row corresponding to this object from the database;
449
467
  # invalidates =self= and any other objects backed by this row
450
468
  def delete
451
- Persistence::execute("delete from #{self.class.table_name} where row_id = ?", @row_id)
469
+ self.db.execute("delete from #{self.class.table_name} where row_id = ?", @row_id)
452
470
  mark_dirty
453
471
  @tuple = nil
454
472
  @row_id = nil
@@ -496,7 +514,7 @@ module Persisting
496
514
  # Helper method to update the row in the database when one of our fields changes
497
515
  def update(attr_name, value)
498
516
  mark_dirty
499
- Persistence::execute("update #{self.class.table_name} set #{attr_name} = ?, updated = ? where row_id = ?", value, SQLBUtil::timestamp, @row_id)
517
+ self.db.execute("update #{self.class.table_name} set #{attr_name} = ?, updated = ? where row_id = ?", value, SQLBUtil::timestamp, @row_id)
500
518
  end
501
519
 
502
520
  # Resolve any fields that reference other tables, replacing row ids with referred objects
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: spqr
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - William Benton
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-12-21 00:00:00 -06:00
12
+ date: 2010-01-26 00:00:00 -06:00
13
13
  default_executable: spqr-gen.rb
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency