knjrbfw 0.0.32 → 0.0.33

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile CHANGED
@@ -2,6 +2,8 @@ source "http://rubygems.org"
2
2
  # Add dependencies required to use your gem here.
3
3
  # Example:
4
4
  # gem "activesupport", ">= 2.3.5"
5
+ gem "wref"
6
+ gem "tsafe"
5
7
 
6
8
  # Add dependencies to develop your gem here.
7
9
  # Include everything needed to run rake, tests, features, etc.
data/Gemfile.lock ADDED
@@ -0,0 +1,38 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ diff-lcs (1.1.3)
5
+ git (1.2.5)
6
+ jeweler (1.6.4)
7
+ bundler (~> 1.0)
8
+ git (>= 1.2.5)
9
+ rake
10
+ rake (0.9.2.2)
11
+ rcov (0.9.11)
12
+ rcov (0.9.11-java)
13
+ rmagick (2.13.1)
14
+ rspec (2.3.0)
15
+ rspec-core (~> 2.3.0)
16
+ rspec-expectations (~> 2.3.0)
17
+ rspec-mocks (~> 2.3.0)
18
+ rspec-core (2.3.1)
19
+ rspec-expectations (2.3.0)
20
+ diff-lcs (~> 1.1.2)
21
+ rspec-mocks (2.3.0)
22
+ sqlite3 (1.3.6)
23
+ tsafe (0.0.0)
24
+ wref (0.0.0)
25
+
26
+ PLATFORMS
27
+ java
28
+ ruby
29
+
30
+ DEPENDENCIES
31
+ bundler (>= 1.0.0)
32
+ jeweler (~> 1.6.3)
33
+ rcov
34
+ rmagick
35
+ rspec (~> 2.3.0)
36
+ sqlite3
37
+ tsafe
38
+ wref
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.32
1
+ 0.0.33
data/knjrbfw.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{knjrbfw}
8
- s.version = "0.0.32"
8
+ s.version = "0.0.33"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Kasper Johansen"]
12
- s.date = %q{2012-05-06}
12
+ s.date = %q{2012-05-18}
13
13
  s.description = %q{Including stuff for HTTP, SSH and much more.}
14
14
  s.email = %q{k@spernj.org}
15
15
  s.extra_rdoc_files = [
@@ -20,6 +20,7 @@ Gem::Specification.new do |s|
20
20
  ".document",
21
21
  ".rspec",
22
22
  "Gemfile",
23
+ "Gemfile.lock",
23
24
  "LICENSE.txt",
24
25
  "README.rdoc",
25
26
  "Rakefile",
@@ -50,6 +51,7 @@ Gem::Specification.new do |s|
50
51
  "lib/knj/autoload/sqlite3.rb",
51
52
  "lib/knj/autoload/tmail.rb",
52
53
  "lib/knj/autoload/tzinfo.rb",
54
+ "lib/knj/autoload/wref.rb",
53
55
  "lib/knj/autoload/xmlsimple.rb",
54
56
  "lib/knj/autoload/zip.rb",
55
57
  "lib/knj/cmd_gen.rb",
@@ -242,7 +244,6 @@ Gem::Specification.new do |s|
242
244
  "lib/knj/win.rb",
243
245
  "lib/knj/win_registry.rb",
244
246
  "lib/knj/win_tightvnc.rb",
245
- "lib/knj/wref.rb",
246
247
  "lib/knj/x11vnc.rb",
247
248
  "lib/knj/youtube.rb",
248
249
  "lib/knjrbfw.rb",
@@ -253,6 +254,7 @@ Gem::Specification.new do |s|
253
254
  "spec/db_spec_encoding_test_file.txt",
254
255
  "spec/http2_spec.rb",
255
256
  "spec/knjrbfw_spec.rb",
257
+ "spec/objects_spec.rb",
256
258
  "spec/php_spec.rb",
257
259
  "spec/process_meta_spec.rb",
258
260
  "spec/process_spec.rb",
@@ -260,7 +262,6 @@ Gem::Specification.new do |s|
260
262
  "spec/strings_spec.rb",
261
263
  "spec/threadsafe_spec.rb",
262
264
  "spec/web_spec.rb",
263
- "spec/wref_spec.rb",
264
265
  "testfiles/image.jpg"
265
266
  ]
266
267
  s.homepage = %q{http://github.com/kaspernj/knjrbfw}
@@ -273,6 +274,8 @@ Gem::Specification.new do |s|
273
274
  s.specification_version = 3
274
275
 
275
276
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
277
+ s.add_runtime_dependency(%q<wref>, [">= 0"])
278
+ s.add_runtime_dependency(%q<tsafe>, [">= 0"])
276
279
  s.add_development_dependency(%q<rspec>, ["~> 2.3.0"])
277
280
  s.add_development_dependency(%q<bundler>, [">= 1.0.0"])
278
281
  s.add_development_dependency(%q<jeweler>, ["~> 1.6.3"])
@@ -280,6 +283,8 @@ Gem::Specification.new do |s|
280
283
  s.add_development_dependency(%q<sqlite3>, [">= 0"])
281
284
  s.add_development_dependency(%q<rmagick>, [">= 0"])
282
285
  else
286
+ s.add_dependency(%q<wref>, [">= 0"])
287
+ s.add_dependency(%q<tsafe>, [">= 0"])
283
288
  s.add_dependency(%q<rspec>, ["~> 2.3.0"])
284
289
  s.add_dependency(%q<bundler>, [">= 1.0.0"])
285
290
  s.add_dependency(%q<jeweler>, ["~> 1.6.3"])
@@ -288,6 +293,8 @@ Gem::Specification.new do |s|
288
293
  s.add_dependency(%q<rmagick>, [">= 0"])
289
294
  end
290
295
  else
296
+ s.add_dependency(%q<wref>, [">= 0"])
297
+ s.add_dependency(%q<tsafe>, [">= 0"])
291
298
  s.add_dependency(%q<rspec>, ["~> 2.3.0"])
292
299
  s.add_dependency(%q<bundler>, [">= 1.0.0"])
293
300
  s.add_dependency(%q<jeweler>, ["~> 1.6.3"])
@@ -0,0 +1,6 @@
1
+ begin
2
+ require "wref"
3
+ rescue LoadError
4
+ require "rubygems"
5
+ require "wref"
6
+ end
data/lib/knj/autoload.rb CHANGED
@@ -6,7 +6,6 @@ module Knj
6
6
  autoload :Fs, $knjpath + "fs/fs"
7
7
  autoload :Php_parser, $knjpath + "php_parser/php_parser"
8
8
  autoload :SSHRobot, $knjpath + "sshrobot/sshrobot"
9
- autoload :Wref_map, $knjpath + "wref"
10
9
  end
11
10
 
12
11
  #ruby objects.
@@ -85,6 +84,9 @@ end
85
84
  autoload :Dictionary, $knjpath + "autoload/facets_dictionary"
86
85
 
87
86
  #gems
88
- autoload :Facebooker, $knjpath + "autoload/facebooker"
89
- autoload :Cinch, $knjpath + "autoload/cinch"
90
87
  autoload :ActiveSupport, $knjpath + "autoload/activesupport"
88
+ autoload :Cinch, $knjpath + "autoload/cinch"
89
+ autoload :Facebooker, $knjpath + "autoload/facebooker"
90
+ autoload :Tsafe, "tsafe"
91
+ autoload :Wref, $knjpath + "autoload/wref"
92
+ autoload :Wref_map, $knjpath + "autoload/wref"
data/lib/knj/datarow.rb CHANGED
@@ -5,7 +5,10 @@
5
5
  # user = ob.get(:User, 1) #=> <Models::User> that extends <Knj::Datarow>
6
6
  class Knj::Datarow
7
7
  #Returns the data-hash that contains all the data from the database.
8
- attr_reader :data
8
+ def data
9
+ self.reload if @should_reload
10
+ return @data
11
+ end
9
12
 
10
13
  #Returns the Knj::Objects which handels this model.
11
14
  attr_reader :ob
@@ -482,63 +485,92 @@ class Knj::Datarow
482
485
  @classname = newclassname
483
486
  end
484
487
 
485
- #Initializes the object. This should be called from Knj::Objects.
486
- def initialize(d)
487
- @ob = d.ob
488
- @db = d.ob.db
488
+ #Initializes the object. This should be called from 'Knj::Objects' and not manually.
489
+ #===Examples
490
+ # user = ob.get(:User, 3)
491
+ def initialize(data, args = nil)
492
+ @ob = self.class.ob
489
493
  raise "No ob given." if !@ob
494
+ @db = ob.db
490
495
 
491
- if d.data.is_a?(Hash)
492
- @data = d.data
493
- elsif d.data
494
- @data = {:id => d.data}
495
- self.reload
496
+ if data.is_a?(Hash) and data.key?(:id)
497
+ @data = data
498
+ @id = @data[:id].to_i
499
+ elsif data
500
+ @id = data.to_i
501
+
502
+ classname = self.class.classname.to_sym
503
+ if @ob.ids_cache_should.key?(classname)
504
+ #ID caching is enabled for this model - dont reload until first use.
505
+ raise Knj::Errors::NotFound, "ID was not found in cache: '#{id}'." if !@ob.ids_cache[classname].key?(@id)
506
+ @should_reload = true
507
+ else
508
+ #ID caching is not enabled - reload now to check if row exists. Else set 'should_reload'-variable if 'skip_reload' is set.
509
+ if !args or !args[:skip_reload]
510
+ self.reload
511
+ else
512
+ @should_reload = true
513
+ end
514
+ end
496
515
  else
497
- raise Knj::Errors::InvalidData, "Could not figure out the data from '#{d.data.class.name}'."
516
+ raise Knj::Errors::InvalidData, "Could not figure out the data from '#{data.class.name}'."
498
517
  end
518
+
519
+ raise "Invalid ID: '#{@id}'." if @id.to_i <= 0
499
520
  end
500
521
 
501
522
  #Reloads the data from the database.
523
+ #===Examples
502
524
  # old_username = user[:username]
503
525
  # user.reload
504
526
  # print "The username changed in the database!" if user[:username] != old_username
505
527
  def reload
506
- data = @db.single(self.table, {:id => @data[:id]})
507
- if !data
508
- raise Knj::Errors::NotFound, "Could not find any data for the object with ID: '#{@data[:id]}' in the table '#{self.table}'."
509
- end
510
-
511
- @data = data
528
+ @data = @db.single(self.table, {:id => @id})
529
+ raise Knj::Errors::NotFound, "Could not find any data for the object with ID: '#{@id}' in the table '#{self.table}'." if !@data
530
+ @should_reload = false
531
+ end
532
+
533
+ #Tells the object that it should reloads its data because it has changed. It wont reload before it is required though, which may save you a couple of SQL-calls.
534
+ #===Examples
535
+ # obj = _ob.get(:User, 5)
536
+ # obj.should_reload
537
+ def should_reload
538
+ @should_reload = true
539
+ @data = nil
512
540
  end
513
541
 
514
542
  #Writes/updates new data for the object.
515
543
  #===Examples
516
544
  # user.update(:username => 'New username', :date_changed => Time.now)
517
545
  def update(newdata)
518
- @db.update(self.table, newdata, {:id => @data[:id]})
519
- self.reload
520
-
521
- if @ob
522
- @ob.call("object" => self, "signal" => "update")
523
- end
546
+ @db.update(self.table, newdata, {:id => @id})
547
+ self.should_reload
548
+ @ob.call("object" => self, "signal" => "update") if @ob
524
549
  end
525
550
 
526
551
  #Forcefully destroys the object. This is done after deleting it and should not be called manually.
527
552
  def destroy
553
+ @id = nil
528
554
  @ob = nil
529
555
  @db = nil
530
556
  @data = nil
557
+ @should_reload = nil
531
558
  end
532
559
 
533
560
  #Returns true if that key exists on the object.
561
+ #===Examples
562
+ # print "Looks like the user has a name." if user.key?(:name)
534
563
  def key?(key)
564
+ self.reload if @should_reload
535
565
  return @data.key?(key.to_sym)
536
566
  end
537
567
  alias has_key? key?
538
568
 
539
569
  #Returns true if the object has been deleted.
570
+ #===Examples
571
+ # print "That user is deleted." if user.deleted?
540
572
  def deleted?
541
- return true if !@ob and !@data
573
+ return true if !@ob and !@data and !@id
542
574
  return false
543
575
  end
544
576
 
@@ -548,9 +580,11 @@ class Knj::Datarow
548
580
  # print "ID again: #{user.id}\n"
549
581
  def [](key)
550
582
  raise "Key was not a symbol: '#{key.class.name}'." if !key.is_a?(Symbol)
551
- raise "No data was loaded on the object? Maybe you are trying to call a deleted object?" if !@data
583
+ return @id if !@data and key == :id and @id
584
+ self.reload if @should_reload
585
+ raise "No data was loaded on the object? Maybe you are trying to call a deleted object? (#{self.class.classname}(#{@id}), #{@should_reload})" if !@data
552
586
  return @data[key] if @data.key?(key)
553
- raise "No such key: '#{key}' on '#{self.class.name}'."
587
+ raise "No such key: '#{key}' on '#{self.class.name}' (#{@data.keys.join(", ")}) (#{@should_reload})."
554
588
  end
555
589
 
556
590
  #Writes/updates a keys value on the object.
@@ -558,21 +592,26 @@ class Knj::Datarow
558
592
  # user[:username] = 'New username'
559
593
  def []=(key, value)
560
594
  self.update(key.to_sym => value)
561
- self.reload
595
+ self.should_reload
562
596
  end
563
597
 
564
598
  #Returns the objects ID.
565
599
  def id
566
600
  raise "This object has been deleted." if self.deleted?
567
- raise "No data on object." if !@data
568
- return @data[:id]
601
+ raise "No ID on object." if !@id
602
+ return @id
569
603
  end
570
604
 
571
- #This enable Knj::Wref to not return the wrong object.
572
- alias __object_unique_id__ id
605
+ #This enable Wref to not return the wrong object.
606
+ def __object_unique_id__
607
+ return 0 if self.deleted?
608
+ return self.id
609
+ end
573
610
 
574
611
  #Tries to figure out, and returns, the possible name or title for the object.
575
612
  def name
613
+ self.reload if @should_reload
614
+
576
615
  if @data.key?(:title)
577
616
  return @data[:title]
578
617
  elsif @data.key?(:name)
@@ -590,10 +629,7 @@ class Knj::Datarow
590
629
  #Calls the name-method and returns a HTML-escaped value. Also "[no name]" if the name is empty.
591
630
  def name_html
592
631
  name_str = self.name.to_s
593
- if name_str.length <= 0
594
- name_str = "[no name]"
595
- end
596
-
632
+ name_str = "[no name]" if name_str.length <= 0
597
633
  return name_str
598
634
  end
599
635
 
@@ -605,8 +641,9 @@ class Knj::Datarow
605
641
  # user.each do |key, val|
606
642
  # print "#{key}: #{val}\n" #=> username: John Doe
607
643
  # end
608
- def each(&args)
609
- return @data.each(&args)
644
+ def each(*args, &block)
645
+ self.reload if @should_reload
646
+ return @data.each(*args, &block)
610
647
  end
611
648
 
612
649
  private
data/lib/knj/errors.rb CHANGED
@@ -34,8 +34,11 @@ module Knj::Errors
34
34
  str = ""
35
35
 
36
36
  if args[:html]
37
- str << "<b>#{err.class.name}</b>: #{err.message}<br />\n<br />\n"
38
- str << err.backtrace.join("<br />\n")
37
+ str << "<b>#{Knj::Web.html(err.class.name)}</b>: #{Knj::Web.html(err.message)}<br />\n<br />\n"
38
+
39
+ err.backtrace.each do |bt|
40
+ str << "#{Knj::Web.html(bt)}<br />\n"
41
+ end
39
42
  else
40
43
  str << "#{err.class.name}: #{err.message}\n\n"
41
44
  str << err.backtrace.join("\n")
data/lib/knj/http2.rb CHANGED
@@ -273,16 +273,22 @@ class Knj::Http2
273
273
 
274
274
  if val.class.name == "Tempfile" and val.respond_to?("original_filename")
275
275
  praw << "Content-Disposition: form-data; name=\"#{key}\"; filename=\"#{val.original_filename}\";#{@nl}"
276
+ praw << "Content-Length: #{val.bytesize}#{@nl}"
277
+ elsif val.is_a?(Hash) and val[:filename]
278
+ praw << "Content-Disposition: form-data; name=\"#{key}\"; filename=\"#{val[:filename]}\";#{@nl}"
279
+ praw << "Content-Length: #{val[:content].bytesize}#{@nl}"
276
280
  else
277
281
  praw << "Content-Disposition: form-data; name=\"#{key}\";#{@nl}"
282
+ praw << "Content-Length: #{val.bytesize}#{@nl}"
278
283
  end
279
284
 
280
285
  praw << "Content-Type: text/plain#{@nl}"
281
- praw << "Content-Length: #{val.length}#{@nl}"
282
286
  praw << @nl
283
287
 
284
288
  if val.is_a?(StringIO)
285
289
  praw << val.read
290
+ elsif val.is_a?(Hash) and val[:content]
291
+ praw << val[:content].to_s
286
292
  else
287
293
  praw << val.to_s
288
294
  end
@@ -292,7 +298,7 @@ class Knj::Http2
292
298
 
293
299
  header_str = "POST /#{addr} HTTP/1.1#{@nl}"
294
300
  header_str << "Content-Type: multipart/form-data; boundary=#{boundary}#{@nl}"
295
- header_str << self.header_str(self.default_headers(args).merge("Content-Length" => praw.length), args)
301
+ header_str << self.header_str(self.default_headers(args).merge("Content-Length" => praw.bytesize), args)
296
302
  header_str << "#{@nl}"
297
303
  header_str << praw
298
304
  header_str << "--#{boundary}--"
data/lib/knj/knj.rb CHANGED
@@ -6,8 +6,6 @@ module Knj
6
6
  def self.const_missing(name)
7
7
  if name == :Db
8
8
  filepath = "#{$knjpath}knjdb/libknjdb"
9
- elsif name == :Wref_map
10
- filepath = "#{$knjpath}wref"
11
9
  else
12
10
  filepath = "#{$knjpath}#{name.to_s.downcase}"
13
11
  end
@@ -263,15 +263,15 @@ class KnjDB_mysql
263
263
  case @subtype
264
264
  when "mysql"
265
265
  @mutex.synchronize do
266
- return @conn.insert_id
266
+ return @conn.insert_id.to_i
267
267
  end
268
268
  when "mysql2"
269
269
  @mutex.synchronize do
270
- return @conn.last_id
270
+ return @conn.last_id.to_i
271
271
  end
272
272
  when "java"
273
273
  data = self.query("SELECT LAST_INSERT_ID() AS id").fetch
274
- return data[:id] if data.key?(:id)
274
+ return data[:id].to_i if data.key?(:id)
275
275
  raise "Could not figure out last inserted ID."
276
276
  end
277
277
  end
@@ -294,7 +294,8 @@ class KnjDB_mysql
294
294
  @port = nil
295
295
  end
296
296
 
297
- def insert_multi(tablename, arr_hashes)
297
+ #Inserts multiple rows in a table. Can return the inserted IDs if asked to in arguments.
298
+ def insert_multi(tablename, arr_hashes, args = nil)
298
299
  sql = "INSERT INTO `#{self.esc_table(tablename)}` ("
299
300
 
300
301
  first = true
@@ -329,6 +330,23 @@ class KnjDB_mysql
329
330
  sql << ")"
330
331
 
331
332
  self.query(sql)
333
+
334
+ if args and args[:return_id]
335
+ first_id = self.lastID
336
+ raise "Invalid ID: #{first_id}" if first_id.to_i <= 0
337
+ ids = [first_id]
338
+ 1.upto(arr_hashes.length - 1) do |count|
339
+ ids << first_id + count
340
+ end
341
+
342
+ ids_length = ids.length
343
+ arr_hashes_length = arr_hashes.length
344
+ raise "Invalid length (#{ids_length}, #{arr_hashes_length})." if ids_length != arr_hashes_length
345
+
346
+ return ids
347
+ else
348
+ return nil
349
+ end
332
350
  end
333
351
  end
334
352
 
@@ -1,5 +1,3 @@
1
- require "#{$knjpath}wref"
2
-
3
1
  class KnjDB_mysql::Tables
4
2
  attr_reader :db, :list
5
3
 
@@ -8,7 +6,7 @@ class KnjDB_mysql::Tables
8
6
  @db = @args[:db]
9
7
  @subtype = @db.opts[:subtype]
10
8
  @list_mutex = Mutex.new
11
- @list = Knj::Wref_map.new
9
+ @list = Wref_map.new
12
10
  @list_should_be_reloaded = true
13
11
  end
14
12
 
@@ -22,7 +20,7 @@ class KnjDB_mysql::Tables
22
20
 
23
21
  begin
24
22
  return @list[table_name]
25
- rescue Knj::Wref::Recycled
23
+ rescue Wref::Recycled
26
24
  #ignore.
27
25
  end
28
26
 
@@ -105,8 +103,8 @@ class KnjDB_mysql::Tables::Table
105
103
  @db = args[:db]
106
104
  @data = args[:data]
107
105
  @subtype = @db.opts[:subtype]
108
- @list = Knj::Wref_map.new
109
- @indexes_list = Knj::Wref_map.new
106
+ @list = Wref_map.new
107
+ @indexes_list = Wref_map.new
110
108
 
111
109
  raise "Could not figure out name from: '#{@data}'." if !@data[:Name]
112
110
  end
@@ -143,7 +141,7 @@ class KnjDB_mysql::Tables::Table
143
141
 
144
142
  begin
145
143
  return @list[name]
146
- rescue Knj::Wref::Recycled
144
+ rescue Wref::Recycled
147
145
  #ignore.
148
146
  end
149
147
 
@@ -223,7 +221,7 @@ class KnjDB_mysql::Tables::Table
223
221
 
224
222
  begin
225
223
  return @indexes_list[name]
226
- rescue Knj::Wref::Recycled
224
+ rescue Wref::Recycled
227
225
  #ignore.
228
226
  end
229
227
 
@@ -56,7 +56,7 @@ class KnjDB_sqlite3
56
56
  end
57
57
  rescue => e
58
58
  #Add SQL to the error message.
59
- raise e.class, "#{e.message}\n\nSQL: #{string}"
59
+ raise e.class, "#{e.message} (SQL: #{string})"
60
60
  end
61
61
  end
62
62
 
@@ -1,5 +1,3 @@
1
- require "#{$knjpath}wref"
2
-
3
1
  class KnjDB_sqlite3::Tables
4
2
  attr_reader :db, :driver
5
3
 
@@ -8,7 +6,7 @@ class KnjDB_sqlite3::Tables
8
6
  @db = @args[:db]
9
7
 
10
8
  @list_mutex = Mutex.new
11
- @list = Knj::Wref_map.new
9
+ @list = Wref_map.new
12
10
  end
13
11
 
14
12
  def [](table_name)
@@ -16,7 +14,7 @@ class KnjDB_sqlite3::Tables
16
14
 
17
15
  begin
18
16
  return @list[table_name]
19
- rescue Knj::Wref::Recycled
17
+ rescue Wref::Recycled
20
18
  #ignore.
21
19
  end
22
20
 
@@ -83,8 +81,8 @@ class KnjDB_sqlite3::Tables::Table
83
81
  @db = args[:db]
84
82
  @data = args[:data]
85
83
 
86
- @list = Knj::Wref_map.new
87
- @indexes_list = Knj::Wref_map.new
84
+ @list = Wref_map.new
85
+ @indexes_list = Wref_map.new
88
86
  end
89
87
 
90
88
  def name
@@ -267,13 +265,13 @@ class KnjDB_sqlite3::Tables::Table
267
265
 
268
266
  begin
269
267
  return @indexes_list[name]
270
- rescue Knj::Wref::Recycled
268
+ rescue Wref::Recycled
271
269
  if @db.opts[:index_append_table_name]
272
270
  tryname = "#{self.name}__#{name}"
273
271
 
274
272
  begin
275
273
  return @indexes_list[tryname]
276
- rescue Knj::Wref::Recycled
274
+ rescue Wref::Recycled
277
275
  #ignore.
278
276
  end
279
277
  else
@@ -1,3 +1,6 @@
1
+ require "rubygems"
2
+ require "wref"
3
+
1
4
  #A wrapper of several possible database-types.
2
5
  #
3
6
  #===Examples
@@ -28,7 +31,8 @@ class Knj::Db
28
31
  @int_types = ["int", "bigint", "tinyint", "smallint", "mediumint"]
29
32
 
30
33
  if !@opts[:threadsafe]
31
- @mutex = Mutex.new
34
+ require "monitor"
35
+ @mutex = Monitor.new
32
36
  end
33
37
 
34
38
  @debug = @opts[:debug]
@@ -209,7 +213,7 @@ class Knj::Db
209
213
  #===Examples
210
214
  # db.insert(:users, {:name => "John", :lastname => "Doe"})
211
215
  # id = db.insert(:users, {:name => "John", :lastname => "Doe"}, :return_id => true)
212
- def insert(tablename, arr_insert, args = {})
216
+ def insert(tablename, arr_insert, args = nil)
213
217
  self.conn_exec do |driver|
214
218
  sql = "INSERT INTO #{driver.escape_table}#{tablename.to_s}#{driver.escape_table} ("
215
219
 
@@ -240,25 +244,37 @@ class Knj::Db
240
244
  sql << ")"
241
245
 
242
246
  driver.query(sql)
243
- return driver.lastID if args[:return_id]
247
+ return driver.lastID if args and args[:return_id]
244
248
  end
245
249
  end
246
250
 
247
- #Simply and optimal insert multiple rows into a table in a single query.
251
+ #Simply and optimal insert multiple rows into a table in a single query. Uses the drivers functionality if supported or inserts each row manually.
248
252
  #
249
253
  #===Examples
250
254
  # db.insert_multi(:users, [
251
255
  # {:name => "John", :lastname => "Doe"},
252
256
  # {:name => "Kasper", :lastname => "Johansen"}
253
257
  # ])
254
- def insert_multi(tablename, arr_hashes)
258
+ def insert_multi(tablename, arr_hashes, args = nil)
259
+ return false if arr_hashes.empty?
260
+
255
261
  self.conn_exec do |driver|
256
262
  if driver.respond_to?(:insert_multi)
257
- return false if arr_hashes.empty?
258
- driver.insert_multi(tablename, arr_hashes)
263
+ return driver.insert_multi(tablename, arr_hashes, args)
259
264
  else
265
+ ids = [] if args and args[:return_id]
260
266
  arr_hashes.each do |hash|
261
- self.insert(tablename, hash)
267
+ if ids
268
+ ids << self.insert(tablename, hash, args)
269
+ else
270
+ self.insert(tablename, hash)
271
+ end
272
+ end
273
+
274
+ if ids
275
+ return ids
276
+ else
277
+ return nil
262
278
  end
263
279
  end
264
280
  end
@@ -416,18 +432,9 @@ class Knj::Db
416
432
  @conns.free(conn)
417
433
  end
418
434
  elsif @conn
419
- begin
420
- @mutex.synchronize do
421
- yield(@conn)
422
- return nil
423
- end
424
- rescue ThreadError => e
425
- if e.message != "deadlock; recursive locking"
426
- yield(@conn)
427
- return nil
428
- else
429
- raise e
430
- end
435
+ @mutex.synchronize do
436
+ yield(@conn)
437
+ return nil
431
438
  end
432
439
  end
433
440
 
@@ -217,7 +217,7 @@ class Knj::Db::Revision
217
217
  end
218
218
  end
219
219
 
220
- self.rows_init("db" => db, "table" => table_obj, "rows" => table_data["rows"]) if table_data and table_data["rows"]
220
+ rows_init("db" => db, "table" => table_obj, "rows" => table_data["rows"]) if table_data and table_data["rows"]
221
221
  rescue Knj::Errors::NotFound => e
222
222
  if table_data["renames"]
223
223
  table_data["renames"].each do |table_name_rename|