class Baza::Db

A wrapper of several possible database-types.

Examples

db = Baza::Db.new(type: :mysql2, db: "mysql", user: "user", pass: "password")
mysql_table = db.tables['mysql']
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

Constants

COPY_TO_ALLOWED_ARGS
DRIVER_PARTS

Defines all the driver methods: tables, columns and so on

Attributes

driver[R]
int_types[R]
opts[R]
sep_col[R]
sep_database[R]
sep_index[R]
sep_table[R]
sep_val[R]

Public Class Methods

drivers() click to toggle source

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

# File lib/baza/db.rb, line 24
def self.drivers
  path = "#{File.dirname(__FILE__)}/driver"
  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

  drivers
end
from_object(args) click to toggle source

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

# File lib/baza/db.rb, line 47
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)
    next unless 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

  raise "Could not figure out what to do what object of type: '#{args[:object].class.name}'."
end
new(opts) { |self| ... } click to toggle source
# File lib/baza/db.rb, line 69
def initialize(opts)
  @driver = opts.delete(:driver) if opts[:driver]
  Baza.load_driver(opts.fetch(:type))
  self.opts = opts unless opts.nil?
  @int_types = [:int, :bigint, :tinyint, :smallint, :mediumint]

  @debug = @opts[:debug]
  @driver = spawn
  @sep_database = @driver.sep_database
  @sep_table = @driver.sep_table
  @sep_col = @driver.sep_col
  @sep_index = @driver.sep_index
  @sep_val = @driver.sep_val

  return unless block_given?

  begin
    yield self
  ensure
    close
  end
end

Public Instance Methods

add_sql_to_error(error, sql) click to toggle source
# File lib/baza/db.rb, line 230
def add_sql_to_error(error, sql)
  error.message << " (SQL: #{sql})"
end
args() click to toggle source
# File lib/baza/db.rb, line 92
def args
  @opts
end
clone_conn(args = {}) { |conn| ... } click to toggle source

Clones the current database-connection with possible extra arguments.

# File lib/baza/db.rb, line 157
def clone_conn(args = {})
  conn = Baza::Db.new(@opts.merge(args))

  if block_given?
    begin
      yield(conn)
    ensure
      conn.close
    end

    return nil
  else
    return conn
  end
end
close() click to toggle source

The all driver-database-connections.

# File lib/baza/db.rb, line 146
def close
  @driver.close if @driver
  @driver = nil
  @closed = true
end
closed?() click to toggle source
# File lib/baza/db.rb, line 152
def closed?
  @closed
end
copy_to(db, args = {}) click to toggle source

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

# File lib/baza/db.rb, line 175
def copy_to(db, args = {})
  debug = args[:debug]
  raise "No tables given." unless data[:tables]

  data[:tables].each do |table|
    table_args = nil
    table_args = args[:tables][table[:name]] 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 = []
      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] 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
data() click to toggle source
Returns the data of this database in a hash.

Examples

data = db.data
tables_hash = data['tables']
# File lib/baza/db.rb, line 221
def data
  tables_ret = []
  tables.list do |table|
    tables_ret << table.data
  end

  {tables: tables_ret}
end
date_in(date_obj) click to toggle source
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
# File lib/baza/db.rb, line 368
def date_in(date_obj)
  return @driver.date_in(date_obj) if @driver.respond_to?(:date_in)
  Datet.in(date_obj)
end
date_out(date_obj = Datet.new, args = {}) click to toggle source
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"
# File lib/baza/db.rb, line 360
def date_out(date_obj = Datet.new, args = {})
  return @driver.date_out(date_obj, args) if @driver.respond_to?(:date_out)
  Datet.in(date_obj).dbstr(args)
end
in_transaction?() click to toggle source
# File lib/baza/db.rb, line 288
def in_transaction?
  @in_transaction
end
insert_multi(tablename, arr_hashes, args = {}) click to toggle source
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"}
])
# File lib/baza/db.rb, line 241
def insert_multi(tablename, arr_hashes, args = {})
  return false if arr_hashes.empty?

  if @driver.respond_to?(:insert_multi)
    if args && args[:return_sql]
      res = @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

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

    return nil
  end
end
inspect() click to toggle source
# File lib/baza/db.rb, line 438
def inspect
  to_s
end
mssql?() click to toggle source
# File lib/baza/db.rb, line 454
def mssql?
  @driver.class.name.downcase.include?("tiny")
end
mysql?() click to toggle source
# File lib/baza/db.rb, line 450
def mysql?
  @driver.class.name.downcase.include?("mysql")
end
new_query() click to toggle source
# File lib/baza/db.rb, line 442
def new_query
  Baza::SqlQueries::Select.new(db: self)
end
optimize(args = nil) click to toggle source

Optimizes all tables in the database.

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

  self
end
opts=(arr_opts) click to toggle source
# File lib/baza/db.rb, line 96
def opts=(arr_opts)
  @opts = {}
  arr_opts.each do |key, val|
    @opts[key.to_sym] = val
  end

  if RUBY_PLATFORM == "java"
    @opts[:type] = :sqlite3_java if @opts[:type] == :sqlite3
    @opts[:type] = :mysql_java if @opts[:type] == :mysql || @opts[:type] == :mysql2
  end

  @type_cc = StringCases.snake_to_camel(@opts[:type])
end
postgres?() click to toggle source
# File lib/baza/db.rb, line 458
def postgres?
  @driver.class.name.downcase.include?("pg")
end
q(string, args = nil, &block)
Alias for: query
q_buffer(args = {}, &block) click to toggle source

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

# File lib/baza/db.rb, line 352
def q_buffer(args = {}, &block)
  Baza::QueryBuffer.new(args.merge(db: self), &block)
  nil
end
query(string, args = nil, &block) click to toggle source
Executes a query and returns the result.

Examples

res = db.query('SELECT * FROM users')
while data = res.fetch
  print data[:name]
end
# File lib/baza/db.rb, line 299
def query(string, args = nil, &block)
  if @debug
    print "SQL: #{string}\n"

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

  # If the query should be executed in a new connection unbuffered.
  if args && args[:cloned_ubuf]
    raise "No block given." unless block

    cloned_conn(clone_args: args[:clone_args]) do |cloned_conn|
      return cloned_conn.query_ubuf(string, args, &block)
    end

    return nil
  end

  return query_ubuf(string, args, &block) if args && args[:type] == :unbuffered

  ret = @driver.query(string)

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

  ret
end
Also aliased as: q
query_ubuf(string, _args = nil, &block) click to toggle source
Execute an ubuffered query and returns the result.

Examples

db.query_ubuf('SELECT * FROM users') do |data|
  print data[:name]
end
# File lib/baza/db.rb, line 340
def query_ubuf(string, _args = nil, &block)
  ret = @driver.query_ubuf(string)

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

  ret
end
register_thread() { || ... } click to toggle source

Registers a driver to the current thread.

# File lib/baza/db.rb, line 121
def register_thread
  raise "Baza-object is not in threadding mode" unless @conns

  thread_cur = Thread.current
  tid = __id__
  thread_cur[:baza] = {} unless thread_cur[:baza]

  if thread_cur[:baza][tid]
    # An object has already been spawned - free that first to avoid endless "used" objects.
    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.
  return unless block_given?

  begin
    yield
  ensure
    free_thread
  end
end
spawn() click to toggle source
Spawns a new driver (useally done automatically).

Examples

driver_instance = db.spawn
# File lib/baza/db.rb, line 113
def spawn
  raise "No type given (#{@opts.keys.join(",")})." unless @opts[:type]
  rpath = "#{File.dirname(__FILE__)}/driver/#{@opts.fetch(:type)}.rb"
  require rpath if File.exist?(rpath)
  Baza::Driver.const_get(@type_cc).new(self)
end
sqlite?() click to toggle source
# File lib/baza/db.rb, line 446
def sqlite?
  @driver.class.name.downcase.include?("sqlite")
end
supports_multiple_databases?() click to toggle source
# File lib/baza/db.rb, line 389
def supports_multiple_databases?
  if @driver.respond_to?(:supports_multiple_databases?)
    @driver.supports_multiple_databases?
  else
    false
  end
end
supports_type_translation?() click to toggle source
# File lib/baza/db.rb, line 397
def supports_type_translation?
  if @driver.respond_to?(:supports_type_translation?)
    @driver.supports_multiple_databases?
  else
    false
  end
end
to_s() click to toggle source
# File lib/baza/db.rb, line 434
def to_s
  "#<Baza::Db driver=\"#{@opts.fetch(:type)}\">"
end
transaction(&block) click to toggle source
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
# File lib/baza/db.rb, line 412
def transaction(&block)
  @in_transaction = true
  begin
    @driver.transaction(&block)
  ensure
    @in_transaction = false
  end

  self
end
update(table_name, data, terms = {}, args = {}) click to toggle source
Simple updates rows.

Examples

db.update(:users, {name: "John"}, {lastname: "Doe"})
# File lib/baza/db.rb, line 272
def update(table_name, data, terms = {}, args = {})
  command = Baza::SqlQueries::GenericUpdate.new(
    db: self,
    table_name: table_name,
    data: data,
    terms: terms,
    buffer: args[:buffer]
  )

  if args[:return_sql]
    command.to_sql
  else
    command.execute
  end
end