Class: Knj::Db

Inherits:
Object show all
Defined in:
lib/knj/knjdb/libknjdb.rb

Overview

A wrapper of several possible database-types.

Examples

db = Knj::Db.new(:type => “mysql”, :subtype => “mysql2”, :db => “mysql”, :user => “user”, :pass => “password”) mysql_table = db.tables name = mysql_table.name cols = mysql_table.columns

db = Knj::Db.new(:type => “sqlite3”, :path => “some_db.sqlite3”)

db.q(“SELECT * FROM users”) do |data|

print data[:name]

end

Defined Under Namespace

Classes: Dbtime, Dump, Idquery, Query_buffer, Revision, Sqlspecs

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(opts) ⇒ Db

Returns a new instance of Db.



26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/knj/knjdb/libknjdb.rb', line 26

def initialize(opts)
  require "#{$knjpath}threadhandler"
  
  self.setOpts(opts) if opts != nil
  
  @int_types = ["int", "bigint", "tinyint", "smallint", "mediumint"]
  
  if !@opts[:threadsafe]
    require "monitor"
    @mutex = Monitor.new
  end
  
  @debug = @opts[:debug]
  
  self.conn_exec do |driver|
    @sep_table = driver.sep_table
    @sep_col = driver.sep_col
    @sep_val = driver.sep_val
    @esc_driver = driver
  end
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method_name, *args) ⇒ Object

Proxies the method to the driver.

Examples

db.method_on_driver



788
789
790
791
792
793
794
795
796
# File 'lib/knj/knjdb/libknjdb.rb', line 788

def method_missing(method_name, *args)
  self.conn_exec do |driver|
    if driver.respond_to?(method_name.to_sym)
      return driver.send(method_name, *args)
    end
  end
  
  raise "Method not found: #{method_name}"
end

Instance Attribute Details

#connObject (readonly)

Returns the value of attribute conn.



24
25
26
# File 'lib/knj/knjdb/libknjdb.rb', line 24

def conn
  @conn
end

#connsObject (readonly)

Returns the value of attribute conns.



24
25
26
# File 'lib/knj/knjdb/libknjdb.rb', line 24

def conns
  @conns
end

#int_typesObject (readonly)

Returns the value of attribute int_types.



24
25
26
# File 'lib/knj/knjdb/libknjdb.rb', line 24

def int_types
  @int_types
end

#optsObject (readonly)

Returns the value of attribute opts.



24
25
26
# File 'lib/knj/knjdb/libknjdb.rb', line 24

def opts
  @opts
end

#sep_colObject (readonly)

Returns the value of attribute sep_col.



24
25
26
# File 'lib/knj/knjdb/libknjdb.rb', line 24

def sep_col
  @sep_col
end

#sep_tableObject (readonly)

Returns the value of attribute sep_table.



24
25
26
# File 'lib/knj/knjdb/libknjdb.rb', line 24

def sep_table
  @sep_table
end

#sep_valObject (readonly)

Returns the value of attribute sep_val.



24
25
26
# File 'lib/knj/knjdb/libknjdb.rb', line 24

def sep_val
  @sep_val
end

Class Method Details

.const_missing(name) ⇒ Object

Autoloader for subclasses..



18
19
20
21
22
# File 'lib/knj/knjdb/libknjdb.rb', line 18

def self.const_missing(name)
  require "#{$knjpath}knjdb/#{name.to_s.downcase}.rb"
  raise "Still not defined: '#{name}'." if !Knj::Db.const_defined?(name)
  return Knj::Db.const_get(name)
end

Instance Method Details

#argsObject



48
49
50
# File 'lib/knj/knjdb/libknjdb.rb', line 48

def args
  return @opts
end

#cleanObject

Clean up various memory-stuff if possible.



148
149
150
151
152
153
154
155
156
# File 'lib/knj/knjdb/libknjdb.rb', line 148

def clean
  if @conns
    @conns.objects.each do |data|
      data[:object].clean if data[:object].respond_to?("clean")
    end
  elsif @conn
    @conn.clean if @conn.respond_to?("clean")
  end
end

#clone_conn(args = {}) ⇒ Object

Clones the current database-connection with possible extra arguments.



168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
# File 'lib/knj/knjdb/libknjdb.rb', line 168

def clone_conn(args = {})
  conn = Knj::Db.new(@opts.clone.merge(args))
  
  if block_given?
    begin
      yield(conn)
    ensure
      conn.close
    end
    
    return nil
  else
    return conn
  end
end

#cloned_conn(args = nil, &block) ⇒ Object

Clones the connection, executes the given block and closes the connection again.

Examples

db.cloned_conn do |conn|

conn.q('SELCET * FROM users') do |data|
  print data[:name]
end

end



604
605
606
607
608
609
610
611
612
613
614
615
616
617
# File 'lib/knj/knjdb/libknjdb.rb', line 604

def cloned_conn(args = nil, &block)
  clone_conn_args = {
    :threadsafe => false
  }
  
  clone_conn_args.merge!(args[:clone_args]) if args and args[:clone_args]
  dbconn = self.clone_conn(clone_conn_args)
  
  begin
    yield(dbconn)
  ensure
    dbconn.close
  end
end

#closeObject

The all driver-database-connections.



159
160
161
162
163
164
165
# File 'lib/knj/knjdb/libknjdb.rb', line 159

def close
  @conn.close if @conn
  @conns.destroy if @conns
  
  @conn = nil
  @conns = nil
end

#colsObject

Returns the columns-module and spawns it if it isnt already spawned.



725
726
727
728
729
730
731
732
733
734
# File 'lib/knj/knjdb/libknjdb.rb', line 725

def cols
  if !@cols
    require "#{File.dirname(__FILE__)}/drivers/#{@opts[:type]}/knjdb_#{@opts[:type]}_columns" if (!@opts.key?(:require) or @opts[:require])
    @cols = Kernel.const_get("KnjDB_#{@opts[:type]}".to_sym).const_get(:Columns).new(
      :db => self
    )
  end
  
  return @cols
end

#conn_execObject

Returns a driver-object based on the current thread and free driver-objects.

Examples

db.conn_exec do |driver|

str = driver.escape('something̈́')

end



524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
# File 'lib/knj/knjdb/libknjdb.rb', line 524

def conn_exec
  if tcur = Thread.current and tcur[:knjdb]
    tid = self.__id__
    
    if tcur[:knjdb].key?(tid)
      yield(tcur[:knjdb][tid])
      return nil
    end
  end
  
  if @conns
    conn = @conns.get_and_lock
    
    begin
      yield(conn)
      return nil
    ensure
      @conns.free(conn)
    end
  elsif @conn
    @mutex.synchronize do
      yield(@conn)
      return nil
    end
  end
  
  raise "Could not figure out how to find a driver to use?"
end

#connectObject

Actually connects to the database. This is useually done automatically.



68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/knj/knjdb/libknjdb.rb', line 68

def connect
  if @opts[:threadsafe]
    @conns = Knj::Threadhandler.new
    
    @conns.on_spawn_new do
      self.spawn
    end
    
    @conns.on_inactive do |data|
      data[:obj].close
    end
    
    @conns.on_activate do |data|
      data[:obj].reconnect
    end
  else
    @conn = self.spawn
  end
end

#copy_to(db, args = {}) ⇒ Object

Copies the content of the current database to another instance of Knj::Db.



185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
# File 'lib/knj/knjdb/libknjdb.rb', line 185

def copy_to(db, args = {})
  data["tables"].each do |table|
    table_args = nil
    table_args = args["tables"][table["name"].to_s] if args and args["tables"] and args["tables"][table["name"].to_s]
    next if table_args and table_args["skip"]
    table.delete("indexes") if table.key?("indexes") and args["skip_indexes"]
    db.tables.create(table["name"], table)
    
    limit_from = 0
    limit_incr = 1000
    
    loop do
      ins_arr = []
      q_rows = self.select(table["name"], {}, {"limit_from" => limit_from, "limit_to" => limit_incr})
      while d_rows = q_rows.fetch
        col_args = nil
        
        if table_args and table_args["columns"]
          d_rows.each do |col_name, col_data|
            col_args = table_args["columns"][col_name.to_s] if table_args and table_args["columns"]
            d_rows[col_name] = "" if col_args and col_args["empty"]
          end
        end
        
        ins_arr << d_rows
      end
      
      break if ins_arr.empty?
      
      db.insert_multi(table["name"], ins_arr)
      limit_from += limit_incr
    end
  end
end

#dataObject

Returns the data of this database in a hash.

Examples

data = db.data tables_hash = data



224
225
226
227
228
229
230
231
232
233
# File 'lib/knj/knjdb/libknjdb.rb', line 224

def data
  tables_ret = []
  tables.list.each do |name, table|
    tables_ret << table.data
  end
  
  return {
    "tables" => tables_ret
  }
end

#date_in(date_obj) ⇒ Object

Takes a valid date-db-string and converts it into a Datet.

Examples

db.date_in(‘2012-05-20 22:06:09’) #=> 2012-05-20 22:06:09 +0200



704
705
706
707
708
709
710
# File 'lib/knj/knjdb/libknjdb.rb', line 704

def date_in(date_obj)
  if @esc_driver.respond_to?(:date_in)
    return @esc_driver.date_in(date_obj)
  end
  
  return Datet.in(date_obj)
end

#date_out(date_obj = Datet.new, args = {}) ⇒ Object

Returns a string which can be used in SQL with the current driver.

Examples

str = db.date_out(Time.now) #=> “2012-05-20 22:06:09”



693
694
695
696
697
698
699
# File 'lib/knj/knjdb/libknjdb.rb', line 693

def date_out(date_obj = Datet.new, args = {})
  if @esc_driver.respond_to?(:date_out)
    return @esc_driver.date_out(date_obj, args)
  end
  
  return Datet.in(date_obj).dbstr(args)
end

#delete(tablename, arr_terms, args = nil) ⇒ Object

Deletes rows from the database.

Examples

db.delete(:users, => “Doe”)



474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
# File 'lib/knj/knjdb/libknjdb.rb', line 474

def delete(tablename, arr_terms, args = nil)
  sql = "DELETE FROM #{@sep_table}#{tablename}#{@sep_table}"
  
  if arr_terms != nil and !arr_terms.empty?
    sql << " WHERE #{self.makeWhere(arr_terms)}"
  end
  
  return sql if args and args[:return_sql]
  
  self.conn_exec do |driver|
    driver.query(sql)
  end
  
  return nil
end

#esc_col(str) ⇒ Object

Escapes the given string to be used as a column.



681
682
683
# File 'lib/knj/knjdb/libknjdb.rb', line 681

def esc_col(str)
  return @esc_driver.esc_col(str)
end

#esc_table(str) ⇒ Object

Escapes the given string to be used as a table.



686
687
688
# File 'lib/knj/knjdb/libknjdb.rb', line 686

def esc_table(str)
  return @esc_driver.esc_table(str)
end

#escape(string) ⇒ Object Also known as: esc

Escapes a string to be safe-to-use in a query-string.

Examples

db.q(“INSERT INTO users (name) VALUES (‘#Knj::Db.dbdb.esc(’John’)‘)”)



674
675
676
# File 'lib/knj/knjdb/libknjdb.rb', line 674

def escape(string)
  return @esc_driver.escape(string)
end

#free_threadObject

Frees the current driver from the current thread.



136
137
138
139
140
141
142
143
144
145
# File 'lib/knj/knjdb/libknjdb.rb', line 136

def free_thread
  thread_cur = Thread.current
  tid = self.__id__
  
  if thread_cur[:knjdb] and thread_cur[:knjdb].key?(tid)
    db = thread_cur[:knjdb][tid]
    thread_cur[:knjdb].delete(tid)
    @conns.free(db) if @conns
  end
end

#get_and_register_threadObject

Registers a driver to the current thread.



111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
# File 'lib/knj/knjdb/libknjdb.rb', line 111

def get_and_register_thread
  raise "KnjDB-object is not in threadding mode." if !@conns
  
  thread_cur = Thread.current
  tid = self.__id__
  thread_cur[:knjdb] = {} if !thread_cur[:knjdb]
  
  if thread_cur[:knjdb][tid]
    #An object has already been spawned - free that first to avoid endless "used" objects.
    self.free_thread
  end
  
  thread_cur[:knjdb][tid] = @conns.get_and_lock if !thread_cur[:knjdb][tid]
  
  #If block given then be ensure to free thread after yielding.
  if block_given?
    begin
      yield
    ensure
      self.free_thread
    end
  end
end

#indexesObject

Returns the index-module and spawns it if it isnt already spawned.



737
738
739
740
741
742
743
744
745
746
# File 'lib/knj/knjdb/libknjdb.rb', line 737

def indexes
  if !@indexes
    require "#{File.dirname(__FILE__)}/drivers/#{@opts[:type]}/knjdb_#{@opts[:type]}_indexes" if (!@opts.key?(:require) or @opts[:require])
    @indexes = Kernel.const_get("KnjDB_#{@opts[:type]}".to_sym).const_get(:Indexes).new(
      :db => self
    )
  end
  
  return @indexes
end

#insert(tablename, arr_insert, args = nil) ⇒ Object

Simply inserts data into a table.

Examples

db.insert(:users, => “John”, :lastname => “Doe”) id = db.insert(:users, => “John”, :lastname => “Doe”, :return_id => true) sql = db.insert(:users, => “John”, :lastname => “Doe”, :return_sql => true) #=> “INSERT INTO ‘users` (`name`, `lastname`) VALUES (’John’, ‘Doe’)”



241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
# File 'lib/knj/knjdb/libknjdb.rb', line 241

def insert(tablename, arr_insert, args = nil)
  sql = "INSERT INTO #{@sep_table}#{tablename}#{@sep_table}"
  
  if !arr_insert or arr_insert.empty?
    #This is the correct syntax for inserting a blank row in MySQL.
    if @opts[:type].to_s == "mysql"
      sql << " VALUES ()"
    elsif @opts[:type].to_s == "sqlite3"
      sql << " DEFAULT VALUES"
    else
      raise "Unknown database-type: '#{@opts[:type]}'."
    end
  else
    sql << " ("
    
    first = true
    arr_insert.each do |key, value|
      if first
        first = false
      else
        sql << ", "
      end
      
      sql << "#{@sep_col}#{key}#{@sep_col}"
    end
    
    sql << ") VALUES ("
    
    first = true
    arr_insert.each do |key, value|
      if first
        first = false
      else
        sql << ", "
      end
      
      sql << self.sqlval(value)
    end
    
    sql << ")"
  end
  
  return sql if args and args[:return_sql]
  
  self.conn_exec do |driver|
    driver.query(sql)
    return driver.lastID if args and args[:return_id]
    return nil
  end
end

#insert_multi(tablename, arr_hashes, args = nil) ⇒ Object

Simply and optimal insert multiple rows into a table in a single query. Uses the drivers functionality if supported or inserts each row manually.

Examples

db.insert_multi(:users, [

{:name => "John", :lastname => "Doe"},
{:name => "Kasper", :lastname => "Johansen"}

])



316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
# File 'lib/knj/knjdb/libknjdb.rb', line 316

def insert_multi(tablename, arr_hashes, args = nil)
  return false if arr_hashes.empty?
  
  if @esc_driver.respond_to?(:insert_multi)
    if args and args[:return_sql]
      return [@esc_driver.insert_multi(tablename, arr_hashes, args)]
    end
    
    self.conn_exec do |driver|
      return driver.insert_multi(tablename, arr_hashes, args)
    end
  else
    ret = [] if args and (args[:return_id] or args[:return_sql])
    arr_hashes.each do |hash|
      if ret
        ret << self.insert(tablename, hash, args)
      else
        self.insert(tablename, hash, args)
      end
    end
    
    if ret
      return ret
    else
      return nil
    end
  end
end

#lastIDObject Also known as: last_id

Returns the last inserted ID.

Examples

id = db.last_id



662
663
664
665
666
# File 'lib/knj/knjdb/libknjdb.rb', line 662

def lastID
  self.conn_exec do |driver|
    return driver.lastID
  end
end

#makeWhere(arr_terms, driver = nil) ⇒ Object

Internally used to generate SQL.

Examples

sql = db.makeWhere(=> “Doe”, driver_obj)



494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
# File 'lib/knj/knjdb/libknjdb.rb', line 494

def makeWhere(arr_terms, driver = nil)
  sql = ""
  
  first = true
  arr_terms.each do |key, value|
    if first
      first = false
    else
      sql << " AND "
    end
    
    if value.is_a?(Array)
      raise "Array for column '#{key}' was empty." if value.empty?
      sql << "#{@sep_col}#{key}#{@sep_col} IN (#{Knj::ArrayExt.join(:arr => value, :sep => ",", :surr => "'", :callback => proc{|ele| self.esc(ele)})})"
    elsif value.is_a?(Hash)
      raise "Dont know how to handle hash."
    else
      sql << "#{@sep_col}#{key}#{@sep_col} = #{@sep_val}#{@esc_driver.escape(value)}#{@sep_val}"
    end
  end
  
  return sql
end

#optimize(args = nil) ⇒ Object

Optimizes all tables in the database.



774
775
776
777
778
779
780
781
782
# File 'lib/knj/knjdb/libknjdb.rb', line 774

def optimize(args = nil)
  STDOUT.puts "Beginning optimization of database." if @debug or (args and args[:debug])
  self.tables.list do |table|
    STDOUT.puts "Optimizing table: '#{table.name}'." if @debug or (args and args[:debug])
    table.optimize
  end
  
  return nil
end

#q(str, args = nil, &block) ⇒ Object

Executes a query and returns the result. If a block is given the result is iterated over that block instead and it returns nil.

Examples

db.q(‘SELECT * FROM users’) do |data|

print data[:name]

end



625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
# File 'lib/knj/knjdb/libknjdb.rb', line 625

def q(str, args = nil, &block)
  #If the query should be executed in a new connection unbuffered.
  if args
    if args[:cloned_ubuf]
      raise "No block given." if !block
      
      self.cloned_conn(:clone_args => args[:clone_args]) do |cloned_conn|
        ret = cloned_conn.query_ubuf(str)
        ret.each(&block)
      end
      
      return nil
    else
      raise "Invalid arguments given: '#{args}'."
    end
  end
  
  ret = self.query(str)
  
  if block
    ret.each(&block)
    return nil
  end
  
  return ret
end

#q_buffer(&block) ⇒ Object

Yields a query-buffer and flushes at the end of the block given.



653
654
655
656
# File 'lib/knj/knjdb/libknjdb.rb', line 653

def q_buffer(&block)
  Knj::Db::Query_buffer.new(:db => self, &block)
  return nil
end

#query(string) ⇒ Object

Executes a query and returns the result.

Examples

res = db.query(‘SELECT * FROM users’) while data = res.fetch

print data[:name]

end



560
561
562
563
564
565
566
567
568
569
570
571
572
573
# File 'lib/knj/knjdb/libknjdb.rb', line 560

def query(string)
  if @debug
    print "SQL: #{string}\n"
    
    if @debug.is_a?(Fixnum) and @debug >= 2
      print caller.join("\n")
      print "\n"
    end
  end
  
  self.conn_exec do |driver|
    return driver.query(string)
  end
end

#query_ubuf(string, &block) ⇒ Object

Execute an ubuffered query and returns the result.

Examples

db.query_ubuf(‘SELECT * FROM users’) do |data|

print data[:name]

end



581
582
583
584
585
586
587
588
589
590
591
592
593
594
# File 'lib/knj/knjdb/libknjdb.rb', line 581

def query_ubuf(string, &block)
  ret = nil
  
  self.conn_exec do |driver|
    ret = driver.query_ubuf(string, &block)
  end
  
  if block
    ret.each(&block)
    return nil
  end
  
  return ret
end

#select(tablename, arr_terms = nil, args = nil, &block) ⇒ Object

Makes a select from the given arguments: table-name, where-terms and other arguments as limits and orders. Also takes a block to avoid raping of memory.



394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
# File 'lib/knj/knjdb/libknjdb.rb', line 394

def select(tablename, arr_terms = nil, args = nil, &block)
  #Set up vars.
  sql = ""
  args_q = nil
  select_sql = "*"
  
  #Give 'cloned_ubuf' argument to 'q'-method.
  if args and args[:cloned_ubuf]
    args_q = {:cloned_ubuf => true}
  end
  
  #Set up IDQuery-stuff if that is given in arguments.
  if args and args[:idquery]
    if args[:idquery] == true
      select_sql = "`id`"
      col = :id
    else
      select_sql = "`#{self.esc_col(args[:idquery])}`"
      col = args[:idquery]
    end
  end
  
  sql = "SELECT #{select_sql} FROM #{@sep_table}#{tablename}#{@sep_table}"
  
  if arr_terms != nil and !arr_terms.empty?
    sql << " WHERE #{self.makeWhere(arr_terms)}"
  end
  
  if args != nil
    if args["orderby"]
      sql << " ORDER BY #{args["orderby"]}"
    end
    
    if args["limit"]
      sql << " LIMIT #{args["limit"]}"
    end
    
    if args["limit_from"] and args["limit_to"]
      raise "'limit_from' was not numeric: '#{args["limit_from"]}'." if !(Float(args["limit_from"]) rescue false)
      raise "'limit_to' was not numeric: '#{args["limit_to"]}'." if !(Float(args["limit_to"]) rescue false)
      sql << " LIMIT #{args["limit_from"]}, #{args["limit_to"]}"
    end
  end
  
  #Do IDQuery if given in arguments.
  if args and args[:idquery]
    res = Knj::Db::Idquery.new(:db => self, :table => tablename, :query => sql, :col => col, &block)
  else
    res = self.q(sql, args_q, &block)
  end
  
  #Return result if a block wasnt given.
  if block
    return nil
  else
    return res
  end
end

#setOpts(arr_opts) ⇒ Object



52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/knj/knjdb/libknjdb.rb', line 52

def setOpts(arr_opts)
  @opts = {}
  arr_opts.each do |key, val|
    @opts[key.to_sym] = val
  end
  
  if RUBY_PLATFORM == "java"
    @opts[:subtype] = "java"
  elsif @opts[:type] == "sqlite3" and RUBY_PLATFORM.index("mswin32") != nil
    @opts[:subtype] = "ironruby"
  end
  
  self.connect
end

#single(tablename, arr_terms = nil, args = {}) ⇒ Object Also known as: selectsingle

Returns a single row from a database.

Examples

row = db.single(:users, => “Doe”)



457
458
459
460
461
462
463
464
465
466
# File 'lib/knj/knjdb/libknjdb.rb', line 457

def single(tablename, arr_terms = nil, args = {})
  args["limit"] = 1
  
  #Experienced very weird memory leak if this was not done by block. Maybe bug in Ruby 1.9.2? - knj
  self.select(tablename, arr_terms, args) do |data|
    return data
  end
  
  return false
end

#spawnObject

Spawns a new driver (useally done automatically).

Examples

driver_instance = db.spawn



91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# File 'lib/knj/knjdb/libknjdb.rb', line 91

def spawn
  raise "No type given (#{@opts.keys.join(",")})." if !@opts[:type]
  
  fpaths = [
    "drivers/#{@opts[:type]}/knjdb_#{@opts[:type]}.rb",
    "libknjdb_#{@opts[:type]}.rb"
  ]
  fpaths.each do |fpath|
    rpath = "#{File.dirname(__FILE__)}/#{fpath}"
    
    if (!@opts.key?(:require) or @opts[:require]) and File.exists?(rpath)
      require rpath
      break
    end
  end
  
  return Kernel.const_get("KnjDB_#{@opts[:type]}").new(self)
end

#sqlspecsObject

Returns the SQLSpec-module and spawns it if it isnt already spawned.



749
750
751
752
753
754
755
756
757
758
# File 'lib/knj/knjdb/libknjdb.rb', line 749

def sqlspecs
  if !@sqlspecs
    require "#{File.dirname(__FILE__)}/drivers/#{@opts[:type]}/knjdb_#{@opts[:type]}_sqlspecs" if (!@opts.key?(:require) or @opts[:require])
    @sqlspecs = Kernel.const_get("KnjDB_#{@opts[:type]}".to_sym).const_get(:Sqlspecs).new(
      :db => self
    )
  end
  
  return @sqlspecs
end

#sqlval(val) ⇒ Object

Returns the correct SQL-value for the given value. If it is a number, then just the raw number as a string will be returned. nil’s will be NULL and strings will have quotes and will be escaped.



293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
# File 'lib/knj/knjdb/libknjdb.rb', line 293

def sqlval(val)
  return @conn.sqlval(val) if @conn.respond_to?(:sqlval)
  
  if val.is_a?(Fixnum) or val.is_a?(Integer)
    return val.to_s
  elsif val == nil
    return "NULL"
  elsif val.is_a?(Date)
    return "#{@sep_val}#{Datet.in(val).dbstr(:time => false)}#{@sep_val}"
  elsif val.is_a?(Time) or val.is_a?(DateTime)
    return "#{@sep_val}#{Datet.in(val).dbstr}#{@sep_val}"
  else
    return "#{@sep_val}#{self.escape(val)}#{@sep_val}"
  end
end

#tablesObject

Returns the table-module and spawns it if it isnt already spawned.



713
714
715
716
717
718
719
720
721
722
# File 'lib/knj/knjdb/libknjdb.rb', line 713

def tables
  if !@tables
    require "#{File.dirname(__FILE__)}/drivers/#{@opts[:type]}/knjdb_#{@opts[:type]}_tables" if (!@opts.key?(:require) or @opts[:require])
    @tables = Kernel.const_get("KnjDB_#{@opts[:type]}".to_sym).const_get(:Tables).new(
      :db => self
    )
  end
  
  return @tables
end

#transaction(&block) ⇒ Object

Beings a transaction and commits when the block ends.

Examples

db.transaction do |db|

db.insert(:users, {:name => "John"})
db.insert(:users, {:name => "Kasper"})

end



767
768
769
770
771
# File 'lib/knj/knjdb/libknjdb.rb', line 767

def transaction(&block)
  self.conn_exec do |driver|
    driver.transaction(&block)
  end
end

#update(tablename, arr_update, arr_terms = {}, args = nil) ⇒ Object

Simple updates rows.

Examples

db.update(:users, => “John”, => “Doe”)



349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
# File 'lib/knj/knjdb/libknjdb.rb', line 349

def update(tablename, arr_update, arr_terms = {}, args = nil)
  raise "'arr_update' was not a hash." if !arr_update.is_a?(Hash)
  return false if arr_update.empty?
  
  sql = ""
  sql << "UPDATE #{@sep_col}#{tablename}#{@sep_col} SET "
  
  first = true
  arr_update.each do |key, value|
    if first
      first = false
    else
      sql << ", "
    end
    
    #Convert dates to valid dbstr.
    value = self.date_out(value) if value.is_a?(Datet) or value.is_a?(Time)
    
    sql << "#{@sep_col}#{key}#{@sep_col} = "
    sql << "#{@sep_val}#{@esc_driver.escape(value)}#{@sep_val}"
  end
  
  if arr_terms and arr_terms.length > 0
    sql << " WHERE #{self.makeWhere(arr_terms)}"
  end
  
  return sql if args and args[:return_sql]
  
  self.conn_exec do |driver|
    driver.query(sql)
  end
end

#upsert(table, selector, data) ⇒ Object

Checks if a given selector exists. If it does, updates it to match data. If not inserts the row.



383
384
385
386
387
388
389
390
391
# File 'lib/knj/knjdb/libknjdb.rb', line 383

def upsert(table, selector, data)
  row = self.select(table, selector, "limit" => 1).fetch
  
  if row
    self.update(table, data, row)
  else
    self.insert(table, selector.merge(data))
  end
end