spqr 0.1.2 → 0.1.3

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.
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