Class: Baza::Db

Inherits:
Object
  • Object
show all
Defined in:
lib/baza/db.rb

Overview

A wrapper of several possible database-types.

Examples

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

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

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

print data[:name]

end

Constant Summary collapse

COPY_TO_ALLOWED_ARGS =
[:tables, :debug]
SELECT_ARGS_ALLOWED_KEYS =
[:limit, :limit_from, :limit_to]

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(opts) ⇒ Db

Returns a new instance of Db.



64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# File 'lib/baza/db.rb', line 64

def initialize(opts)
  @conn = opts.delete(:driver) if opts[:driver]
  self.opts = opts if opts != nil
  @int_types = [:int, :bigint, :tinyint, :smallint, :mediumint]

  unless @opts[:threadsafe]
    require 'monitor'
    @mutex = Monitor.new
  end

  @debug = @opts[:debug]

  conn_exec do |driver|
    @sep_table = driver.sep_table
    @sep_col = driver.sep_col
    @sep_val = driver.sep_val
    @esc_driver = driver
  end

  if block_given?
    begin
      yield self
    ensure
      close
    end
  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



864
865
866
867
868
869
870
871
872
# File 'lib/baza/db.rb', line 864

def method_missing(method_name, *args)
  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.



15
16
17
# File 'lib/baza/db.rb', line 15

def conn
  @conn
end

#connsObject (readonly)

Returns the value of attribute conns.



15
16
17
# File 'lib/baza/db.rb', line 15

def conns
  @conns
end

#int_typesObject (readonly)

Returns the value of attribute int_types.



15
16
17
# File 'lib/baza/db.rb', line 15

def int_types
  @int_types
end

#optsObject

Returns the value of attribute opts.



15
16
17
# File 'lib/baza/db.rb', line 15

def opts
  @opts
end

#sep_colObject (readonly)

Returns the value of attribute sep_col.



15
16
17
# File 'lib/baza/db.rb', line 15

def sep_col
  @sep_col
end

#sep_tableObject (readonly)

Returns the value of attribute sep_table.



15
16
17
# File 'lib/baza/db.rb', line 15

def sep_table
  @sep_table
end

#sep_valObject (readonly)

Returns the value of attribute sep_val.



15
16
17
# File 'lib/baza/db.rb', line 15

def sep_val
  @sep_val
end

Class Method Details

.driversObject

Returns an array containing hashes of information about each registered driver.



18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# File 'lib/baza/db.rb', line 18

def self.drivers
  path = "#{File.dirname(__FILE__)}/drivers"
  drivers = []

  Dir.foreach(path) do |file|
    next if file.to_s.slice(0, 1) == "."
    fp = "#{path}/#{file}"
    next unless File.directory?(fp)

    driver_file = "#{fp}/#{file}.rb"
    class_name = StringCases.snake_to_camel(file).to_sym

    drivers << {
      name: file,
      driver_path: driver_file,
      class_name: class_name
    }
  end

  return drivers
end

.from_object(args) ⇒ Object

Tries to create a database-object based on the given object which could be a SQLite3 object or a MySQL 2 object (or other supported).



41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/baza/db.rb', line 41

def self.from_object(args)
  args = {object: args} unless args.is_a?(Hash)
  raise "No :object was given." unless args[:object]

  Baza::Db.drivers.each do |driver|
    const = Baza::Driver.const_get(driver[:class_name])
    next unless const.respond_to?(:from_object)

    obj = const.from_object(args)
    if obj.is_a?(Hash) && obj[:type] == :success
      if obj[:args]
        new_args = obj[:args]
        new_args = new_args.merge(args[:new_args]) if args[:new_args]
        return Baza::Db.new(new_args)
      else
        raise "Didnt know what to do."
      end
    end
  end

  raise "Could not figure out what to do what object of type: '#{args[:object].class.name}'."
end

Instance Method Details

#add_sql_to_error(error, sql) ⇒ Object



345
346
347
# File 'lib/baza/db.rb', line 345

def add_sql_to_error(error, sql)
  error.message << " (SQL: #{sql})"
end

#argsObject



92
93
94
# File 'lib/baza/db.rb', line 92

def args
  return @opts
end

#cleanObject

Clean up various memory-stuff if possible.



181
182
183
184
185
186
187
188
189
# File 'lib/baza/db.rb', line 181

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.



207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
# File 'lib/baza/db.rb', line 207

def clone_conn(args = {})
  conn = Baza::Db.new(opts = @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



684
685
686
687
688
689
690
691
692
693
694
695
696
697
# File 'lib/baza/db.rb', line 684

def cloned_conn(args = nil, &block)
  clone_conn_args = {
    threadsafe: false
  }

  clone_conn_args.merge!(args[:clone_args]) if args && args[:clone_args]
  dbconn = self.clone_conn(clone_conn_args)

  begin
    yield(dbconn)
  ensure
    dbconn.close
  end
end

#closeObject

The all driver-database-connections.



192
193
194
195
196
197
198
199
200
# File 'lib/baza/db.rb', line 192

def close
  @conn.close if @conn
  @conns.destroy if @conns

  @conn = nil
  @conns = nil

  @closed = true
end

#closed?Boolean

Returns:

  • (Boolean)


202
203
204
# File 'lib/baza/db.rb', line 202

def closed?
  @closed
end

#colsObject

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



802
803
804
805
806
807
808
809
810
# File 'lib/baza/db.rb', line 802

def cols
  unless @cols
    @cols = Baza::Driver.const_get(@type_cc).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



597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
# File 'lib/baza/db.rb', line 597

def conn_exec
  raise "Call to closed database" if @closed

  if tcur = Thread.current && Thread.current[:baza]
    tid = self.__id__

    if tcur[:baza].key?(tid)
      yield(tcur[:baza][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 which driver to use?"
end

#connectObject

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



112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# File 'lib/baza/db.rb', line 112

def connect
  if @opts[:threadsafe]
    require "#{$knjpath}threadhandler"
    @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 Baza::Db.



225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
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
# File 'lib/baza/db.rb', line 225

def copy_to(db, args = {})
  debug = args[:debug]
  raise "No tables given." if !data[:tables]

  data[:tables].each do |table|
    table_args = nil
    table_args = args[:tables][table[:name.to_sym]] if args && args[:tables] && args[:tables][table[:name].to_sym]
    next if table_args && table_args[:skip]
    table.delete(:indexes) if table.key?(:indexes) && args[:skip_indexes]

    table_name = table.delete(:name)
    puts "Creating table: '#{table_name}'." if debug
    db.tables.create(table_name, table)

    limit_from = 0
    limit_incr = 1000

    loop do
      puts "Copying rows (#{limit_from}, #{limit_incr})." if debug
      ins_arr = []
      q_rows = self.select(table_name, {}, {limit_from: limit_from, limit_to: limit_incr}) do |d_rows|
        col_args = nil

        if table_args && table_args[:columns]
          d_rows.each do |col_name, col_data|
            col_args = table_args[:columns][col_name.to_sym] if table_args && table_args[:columns]
            d_rows[col_name] = "" if col_args && col_args[:empty]
          end
        end

        ins_arr << d_rows
      end

      break if ins_arr.empty?

      puts "Insertering #{ins_arr.length} rows." if debug
      db.insert_multi(table_name, ins_arr)
      limit_from += limit_incr
    end
  end
end

#count(tablename, arr_terms = nil) ⇒ Object



517
518
519
520
521
522
523
524
525
526
527
528
529
# File 'lib/baza/db.rb', line 517

def count(tablename, arr_terms = nil)
  #Set up vars.
  sql = ""
  args_q = nil

  sql = "SELECT COUNT(*) AS count FROM #{@sep_table}#{tablename}#{@sep_table}"

  if arr_terms != nil && !arr_terms.empty?
    sql << " WHERE #{self.makeWhere(arr_terms)}"
  end

  return q(sql).fetch.fetch(:count).to_i
end

#dataObject

Returns the data of this database in a hash.

Examples

data = db.data tables_hash = data



271
272
273
274
275
276
277
278
279
280
# File 'lib/baza/db.rb', line 271

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



782
783
784
785
786
787
788
# File 'lib/baza/db.rb', line 782

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”



771
772
773
774
775
776
777
# File 'lib/baza/db.rb', line 771

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”)



546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
# File 'lib/baza/db.rb', line 546

def delete(tablename, arr_terms, args = nil)
  sql = "DELETE FROM #{@sep_table}#{tablename}#{@sep_table}"

  if arr_terms != nil && !arr_terms.empty?
    sql << " WHERE #{self.makeWhere(arr_terms)}"
  end

  return sql if args && args[:return_sql]

  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.



759
760
761
# File 'lib/baza/db.rb', line 759

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.



764
765
766
# File 'lib/baza/db.rb', line 764

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 (‘#Baza::Db.dbdb.esc(’John’)‘)”)



752
753
754
# File 'lib/baza/db.rb', line 752

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

#free_threadObject

Frees the current driver from the current thread.



169
170
171
172
173
174
175
176
177
178
# File 'lib/baza/db.rb', line 169

def free_thread
  thread_cur = Thread.current
  tid = self.__id__

  if thread_cur[:baza] && thread_cur[:baza].key?(tid)
    db = thread_cur[:baza][tid]
    thread_cur[:baza].delete(tid)
    @conns.free(db) if @conns
  end
end

#get_and_register_threadObject

Registers a driver to the current thread.



144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
# File 'lib/baza/db.rb', line 144

def get_and_register_thread
  raise "Baza-object is not in threadding mode" unless @conns

  thread_cur = Thread.current
  tid = self.__id__
  thread_cur[:baza] = {} if !thread_cur[:baza]

  if thread_cur[:baza][tid]
    #An object has already been spawned - free that first to avoid endless "used" objects.
    self.free_thread
  end

  thread_cur[:baza][tid] = @conns.get_and_lock unless thread_cur[:baza][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.



813
814
815
816
817
818
819
820
821
# File 'lib/baza/db.rb', line 813

def indexes
  unless @indexes
    @indexes = Baza::Driver.const_get(@type_cc).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, name: “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’)”



288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
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/baza/db.rb', line 288

def insert(tablename, arr_insert, args = nil)
  sql = "INSERT INTO #{@sep_table}#{self.esc_table(tablename)}#{@sep_table}"

  if !arr_insert || arr_insert.empty?
    # This is the correct syntax for inserting a blank row in MySQL.
    if @opts[:type].to_s.include?("mysql")
      sql << " VALUES ()"
    elsif @opts[:type].to_s.include?("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}#{self.esc_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 && args[:return_sql]

  conn_exec do |driver|
    begin
      driver.query(sql)
    rescue => e
      self.add_sql_to_error(e, sql) if @opts[:sql_to_error]
      raise e
    end

    return driver.last_id if args && 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"}

])



373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
# File 'lib/baza/db.rb', line 373

def insert_multi(tablename, arr_hashes, args = nil)
  return false if arr_hashes.empty?

  if @esc_driver.respond_to?(:insert_multi)
    if args && args[:return_sql]
      res =  @esc_driver.insert_multi(tablename, arr_hashes, args)
      if res.is_a?(String)
        return [res]
      elsif res.is_a?(Array)
        return res
      else
        raise "Unknown result: '#{res.class.name}'."
      end
    end

    conn_exec do |driver|
      return driver.insert_multi(tablename, arr_hashes, args)
    end
  else
    transaction do
      arr_hashes.each do |hash|
        self.insert(tablename, hash, args)
      end
    end

    return nil
  end
end

#inspectObject



878
879
880
# File 'lib/baza/db.rb', line 878

def inspect
  to_s
end

#last_idObject

Returns the last inserted ID.

Examples

id = db.last_id



742
743
744
745
746
# File 'lib/baza/db.rb', line 742

def last_id
  conn_exec do |driver|
    return driver.last_id
  end
end

#makeWhere(arr_terms, driver = nil) ⇒ Object

Internally used to generate SQL.

Examples

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



566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
# File 'lib/baza/db.rb', line 566

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?
      values = value.map { |v| "'#{escape(v)}'" }.join(',')
      sql << "#{@sep_col}#{key}#{@sep_col} IN (#{values})"
    elsif value.is_a?(Hash)
      raise "Dont know how to handle hash."
    else
      sql << "#{@sep_col}#{key}#{@sep_col} = #{self.sqlval(value)}"
    end
  end

  return sql
end

#optimize(args = nil) ⇒ Object

Optimizes all tables in the database.



850
851
852
853
854
855
856
857
858
# File 'lib/baza/db.rb', line 850

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

  return nil
end

#q(sql, 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



705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
# File 'lib/baza/db.rb', line 705

def q(sql, args = nil, &block)
  #If the query should be executed in a new connection unbuffered.
  if args && args[:cloned_ubuf]
    raise "No block given." unless block

    self.cloned_conn(clone_args: args[:clone_args]) do |cloned_conn|
      ret = cloned_conn.query_ubuf(sql)
      ret.each(&block)
    end

    return nil
  end

  if args && args[:type] == :unbuffered
    ret = self.query_ubuf(sql)
  else
    ret = self.query(sql)
  end

  if block
    ret.each(&block)
    return nil
  end

  return ret
end

#q_buffer(args = {}, &block) ⇒ Object

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



733
734
735
736
# File 'lib/baza/db.rb', line 733

def q_buffer(args = {}, &block)
  Baza::QueryBuffer.new(args.merge(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



635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
# File 'lib/baza/db.rb', line 635

def query(string)
  if @debug
    print "SQL: #{string}\n"

    if @debug.is_a?(Fixnum) && @debug >= 2
      print caller.join("\n")
      print "\n"
    end
  end

  begin
    conn_exec do |driver|
      return driver.query(string)
    end
  rescue => e
    e.message << " (SQL: #{string})" if @opts[:sql_to_error]
    raise e
  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



661
662
663
664
665
666
667
668
669
670
671
672
673
674
# File 'lib/baza/db.rb', line 661

def query_ubuf(string, &block)
  ret = nil

  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.



458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
# File 'lib/baza/db.rb', line 458

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 && args[:cloned_ubuf]
    args_q = {cloned_ubuf: true}
  end

  #Set up IDQuery-stuff if that is given in arguments.
  if args && 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 && !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] && 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 && args[:idquery]
    res = Baza::Idquery.new(db: self, table: tablename, query: sql, col: col, &block)
  else
    res = q(sql, args_q, &block)
  end

  #Return result if a block wasnt given.
  if block
    return nil
  else
    return res
  end
end

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

Returns a single row from a database.

Examples

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



535
536
537
538
# File 'lib/baza/db.rb', line 535

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

#spawnObject

Spawns a new driver (useally done automatically).

Examples

driver_instance = db.spawn



136
137
138
139
140
141
# File 'lib/baza/db.rb', line 136

def spawn
  raise "No type given (#{@opts.keys.join(",")})." unless @opts[:type]
  rpath = "#{File.dirname(__FILE__)}/drivers/#{@opts[:type]}.rb"
  require rpath if File.exists?(rpath)
  return Baza::Driver.const_get(@type_cc).new(self)
end

#sqlspecsObject

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



824
825
826
827
828
829
830
831
832
# File 'lib/baza/db.rb', line 824

def sqlspecs
  unless @sqlspecs
    @sqlspecs = Baza::Driver.const_get(@type_cc).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.



350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
# File 'lib/baza/db.rb', line 350

def sqlval(val)
  return @conn.sqlval(val) if @conn.respond_to?(:sqlval)

  if val.is_a?(Fixnum) || 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) || 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.



791
792
793
794
795
796
797
798
799
# File 'lib/baza/db.rb', line 791

def tables
  unless @tables
    @tables = Baza::Driver.const_get(@type_cc).const_get(:Tables).new(
      db: self
    )
  end

  return @tables
end

#to_sObject



874
875
876
# File 'lib/baza/db.rb', line 874

def to_s
  "#<Baza::Db driver \"#{@opts[:type]}\">"
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



841
842
843
844
845
846
847
# File 'lib/baza/db.rb', line 841

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

  return nil
end

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

Simple updates rows.

Examples

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



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
# File 'lib/baza/db.rb', line 406

def update(tablename, hash_update, arr_terms = {}, args = nil)
  raise "'hash_update' was not a hash: '#{hash_update.class.name}'." if !hash_update.is_a?(Hash)
  return false if hash_update.empty?

  sql = ""
  sql << "UPDATE #{@sep_col}#{tablename}#{@sep_col} SET "

  first = true
  hash_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) || value.is_a?(Time)

    sql << "#{@sep_col}#{self.esc_col(key)}#{@sep_col} = "
    sql << self.sqlval(value)
  end

  if arr_terms && arr_terms.length > 0
    sql << " WHERE #{self.makeWhere(arr_terms)}"
  end

  return sql if args && args[:return_sql]

  conn_exec do |driver|
    driver.query(sql)
  end
end

#upsert(table, data, terms, args = nil) ⇒ Object

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



440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
# File 'lib/baza/db.rb', line 440

def upsert(table, data, terms, args = nil)
  row = self.single(table, terms)

  if args && args[:buffer]
    obj = args[:buffer]
  else
    obj = self
  end

  if row
    obj.update(table, data, terms)
  else
    obj.insert(table, terms.merge(data))
  end
end