class Amalgalite::Schema

An object view of the schema in the SQLite database. If the schema changes after this class is created, it has no knowledge of that.

Attributes

catalog[R]

The internal database that this schema is for. Most of the time this will be 'main' for the main database. For the temp tables, this will be 'temp' and for any attached databsae, this is the name of attached database.

db[R]

The Amalagalite::Database this schema is associated with.

schema_version[R]

The #schema_version at the time this schema was taken.

Public Class Methods

new( db, catalog = 'main', master_table = 'sqlite_master' ) click to toggle source

Create a new instance of Schema

# File lib/amalgalite/schema.rb, line 32
def initialize( db, catalog = 'main', master_table = 'sqlite_master' )
  @db             = db
  @catalog        = catalog
  @schema_version = nil
  @tables         = {}
  @views          = {}
  @master_table   = master_table

  if @master_table == 'sqlite_master' then
    @temp_schema = ::Amalgalite::Schema.new( db, 'temp', 'sqlite_temp_master')
  else
    @temp_schema = nil
  end
  load_schema!
end

Public Instance Methods

catalog_master_table() click to toggle source
# File lib/amalgalite/schema.rb, line 48
def catalog_master_table
  "#{catalog}.#{@master_table}"
end
current_version() click to toggle source
# File lib/amalgalite/schema.rb, line 62
def current_version
  @db.first_value_from("PRAGMA #{catalog}.schema_version")
end
dirty?() click to toggle source
# File lib/amalgalite/schema.rb, line 56
def dirty?()
  return true  if (@schema_version != self.current_version)
  return false unless @temp_schema
  return @temp_schema.dirty?
end
load_columns( table ) click to toggle source

load all the columns for a particular table

# File lib/amalgalite/schema.rb, line 154
def load_columns( table )
  cols = {}
  idx = 0
  @db.execute("PRAGMA #{catalog}.table_info(#{@db.quote(table.name)})") do |row|
    col = Amalgalite::Column.new( catalog,  table.name, row['name'], row['cid'])

    col.default_value       = row['dflt_value']

    col.declared_data_type  = row['type']
    col.not_null_constraint = row['notnull']
    col.primary_key         = row['pk']

    # need to remove leading and trailing ' or " from the default value
    if col.default_value and col.default_value.kind_of?( String ) and ( col.default_value.length >= 2 ) then
      fc = col.default_value[0].chr
      lc = col.default_value[-1].chr
      if fc == lc and ( fc == "'" || fc == '"' ) then
        col.default_value = col.default_value[1..-2]
      end
    end

    unless table.temporary? then
      # get more exact information
      @db.api.table_column_metadata( catalog, table.name, col.name ).each_pair do |key, value|
        col.send("#{key}=", value)
      end
    end
    col.schema = self
    cols[col.name] = col
    idx += 1
  end
  return cols
end
load_indexes( table ) click to toggle source

load all the indexes for a particular table

# File lib/amalgalite/schema.rb, line 123
def load_indexes( table )
  indexes = {}

  @db.prepare("SELECT name, sql FROM #{catalog_master_table} WHERE type ='index' and tbl_name = $name") do |idx_stmt|
    idx_stmt.execute( "$name" => table.name) do |idx_info|
      indexes[idx_info['name']] = Amalgalite::Index.new( idx_info['name'], idx_info['sql'], table )
    end
  end

  @db.execute("PRAGMA index_list( #{@db.quote(table.name)} );") do |idx_list|
    idx = indexes[idx_list['name']]

    # temporary indexes do not show up in the previous list
    if idx.nil? then
      idx = Amalgalite::Index.new( idx_list['name'], nil, table )
      indexes[idx_list['name']] = idx
    end

    idx.sequence_number = idx_list['seq']
    idx.unique          = Boolean.to_bool( idx_list['unique'] )

    @db.execute("PRAGMA index_info( #{@db.quote(idx.name)} );") do |col_info|
      idx.columns << table.columns[col_info['name']]
    end
  end
  return indexes
end
load_schema!() click to toggle source

load the schema from the database

# File lib/amalgalite/schema.rb, line 68
def load_schema!
  load_tables
  load_views
  if @temp_schema then
    @temp_schema.load_schema!
  end
  @schema_version = self.current_version
  nil
end
load_table( table_name ) click to toggle source

Load a single table

# File lib/amalgalite/schema.rb, line 106
def load_table( table_name )
  rows = @db.execute("SELECT tbl_name, sql FROM #{catalog_master_table} WHERE type = 'table' AND tbl_name = ?", table_name)
  table_info = rows.first
  table = nil
  if table_info then
    table = Amalgalite::Table.new( table_info['tbl_name'], table_info['sql'] )
    table.schema = self
    table.columns = load_columns( table )
    table.indexes = load_indexes( table )
    @tables[table.name] = table
  end
  return table
end
load_tables() click to toggle source

load all the tables

# File lib/amalgalite/schema.rb, line 94
def load_tables
  @tables = {}
  @db.execute("SELECT tbl_name FROM #{catalog_master_table} WHERE type = 'table' AND name != 'sqlite_sequence'") do |table_info|
    table = load_table( table_info['tbl_name'] )
    table.indexes = load_indexes( table )
    @tables[table.name] = table
  end
  return @tables
end
load_view( name ) click to toggle source

load a single view

# File lib/amalgalite/schema.rb, line 206
def load_view( name )
  rows = @db.execute("SELECT name, sql FROM #{catalog_master_table} WHERE type = 'view' AND name = ?", name )
  view_info = rows.first
  view = Amalgalite::View.new( view_info['name'], view_info['sql'] )
  view.schema = self
  return view
end
load_views() click to toggle source

load all the views for the database

# File lib/amalgalite/schema.rb, line 217
def load_views
  @db.execute("SELECT name, sql FROM #{catalog_master_table} WHERE type = 'view'") do |view_info|
    view = load_view( view_info['name'] )
    @views[view.name] = view
  end
  return @views
end
tables() click to toggle source

return the tables, reloading if dirty. If there is a temp table and a normal table with the same name, then the temp table is the one that is returned in the hash.

# File lib/amalgalite/schema.rb, line 82
def tables
  load_schema! if dirty?
  t = @tables
  if @temp_schema then
    t = @tables.merge( @temp_schema.tables )
  end
  return t
end
temporary?() click to toggle source
# File lib/amalgalite/schema.rb, line 52
def temporary?
  catalog == "temp"
end
views() click to toggle source

return the views, reloading if dirty

If there is a temp view, and a regular view of the same name, then the temporary view is the one that is returned in the hash.

# File lib/amalgalite/schema.rb, line 194
def views
  reload_schema! if dirty?
  v = @views
  if @temp_schema then
    v = @views.merge( @temp_schema.views )
  end
  return v
end