class Flounder::Domain

Attributes

connection_pool[R]
logger[RW]
savepoints[R]

Public Class Methods

new(connection_pool) click to toggle source
# File lib/flounder/domain.rb, line 18
def initialize connection_pool
  @connection_pool = connection_pool

  # maps from plural/singular names to entities in this domain
  @plural = {}
  @singular = {}

  # Maps table names to entities
  @entity_by_table_name = {}

  # maps OIDs of entities to entities
  @oids_entity_map = Hash.new { |hash, oid|
    hash[oid] = entity_from_oid(oid)
  }

  @logger = Logger.new(NilDevice.new)

  @savepoints = Hash.new(0)
end

Public Instance Methods

[](name) click to toggle source

Returns the entity with the given plural name.

# File lib/flounder/domain.rb, line 84
def [] name
  raise NoSuchEntity, "No such entity #{name.inspect} in this domain." \
    unless @plural.has_key?(name)

  @plural.fetch(name)
end
by_oid(oid) click to toggle source

Returns an entity by table oid.

# File lib/flounder/domain.rb, line 129
def by_oid oid
  return nil if oid==0 # computed fields
  @oids_entity_map[oid]
end
entities() click to toggle source

Returns all entities as an array.

# File lib/flounder/domain.rb, line 93
def entities
  @plural.values
end
entity(plural, singular, table_name) { |e| ... } click to toggle source

Define a database entity and alias it to plural and singular names that will be used in the code.

# File lib/flounder/domain.rb, line 113
def entity plural, singular, table_name
  entity = Entity.new(self, plural, singular, table_name).
    tap { |e| yield e if block_given? }

  raise ArgumentError, "Table #{table_name} was already associated with an entity." \
    if @entity_by_table_name.has_key?(table_name)

  @plural[plural] = entity
  @singular[singular] = entity
  @entity_by_table_name[table_name] = entity

  entity
end
expr(&block) click to toggle source

Builds an SQL expression.

domain.expr { concat('1', '2') }
# File lib/flounder/domain.rb, line 61
def expr &block
  builder = Expression::Builder.new(self)
  builder.call(&block)
end
has_entity?(name) click to toggle source
# File lib/flounder/domain.rb, line 96
def has_entity? name
  @plural.has_key? name
end
log_bm(measure) click to toggle source
# File lib/flounder/domain.rb, line 105
def log_bm measure
  stats << measure.total * 1_000
  @logger.info "Query took #{measure}."
end
log_sql(sql) click to toggle source

Logs sql statements that are prepared for execution.

# File lib/flounder/domain.rb, line 102
def log_sql sql
  @logger.info sql
end
reset_stats() click to toggle source

Resets this threads stats.

# File lib/flounder/domain.rb, line 78
def reset_stats
  Thread.current[:__flounder_stats] = nil
end
stats() click to toggle source

Returns an aggregate of all query wall clock times. Please see github.com/josephruscio/aggregate for more information on this object.

@return [Aggregate] statistics for this thread

# File lib/flounder/domain.rb, line 72
def stats
  Thread.current[:__flounder_stats] ||= Aggregate.new
end
transaction(&block) click to toggle source
# File lib/flounder/domain.rb, line 45
def transaction &block
  with_connection do |conn|
    if in_transaction?(conn)
      savepoint(conn) { block.call(conn) }
    else
      conn.transaction do
        savepoint(conn) { block.call(conn) }
      end
    end
  end
end

Private Instance Methods

dec_sp(connection) click to toggle source
# File lib/flounder/domain.rb, line 141
def dec_sp connection
  savepoints[connection.object_id] -= 1
  if savepoints[connection.object_id] < 0
    fail "ASSERTION FAILURE: Savepoint count cannot drop below zero!"
  end

  nil
end
entity_from_oid(oid) click to toggle source
# File lib/flounder/domain.rb, line 167
def entity_from_oid oid
  connection_pool.with_connection do |conn|
    table_name = conn.exec(%Q(SELECT #{oid}::regclass)).
      getvalue(0,0)

    @entity_by_table_name[table_name]
  end
end
in_transaction?(connection) click to toggle source
# File lib/flounder/domain.rb, line 149
def in_transaction? connection
  sp_count(connection) > 0
end
inc_sp(connection) click to toggle source
# File lib/flounder/domain.rb, line 138
def inc_sp connection
  savepoints[connection.object_id] += 1
end
savepoint(connection) { || ... } click to toggle source
# File lib/flounder/domain.rb, line 152
def savepoint connection, &block
  sp_number = inc_sp(connection)
  sp_name = "s#{sp_number}"

  connection.exec("SAVEPOINT #{sp_name};")
  begin
    yield
  rescue Exception
    connection.exec("ROLLBACK TO SAVEPOINT #{sp_name};")
    raise
  ensure
    dec_sp(connection)
  end
end
sp_count(connection) click to toggle source
# File lib/flounder/domain.rb, line 135
def sp_count connection
  savepoints[connection.object_id]
end