Class: Amalgalite::Schema
- Inherits:
-
Object
- Object
- Amalgalite::Schema
- Defined in:
- lib/amalgalite/schema.rb
Overview
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.
Instance Attribute Summary collapse
-
#catalog ⇒ Object
readonly
The internal database that this schema is for.
-
#db ⇒ Object
readonly
The Amalagalite::Database this schema is associated with.
-
#schema_version ⇒ Object
readonly
The schema_version at the time this schema was taken.
Instance Method Summary collapse
- #catalog_master_table ⇒ Object
- #current_version ⇒ Object
- #dirty? ⇒ Boolean
-
#initialize(db, catalog = 'main', master_table = 'sqlite_master') ⇒ Schema
constructor
Create a new instance of Schema.
-
#load_columns(table) ⇒ Object
load all the columns for a particular table.
-
#load_indexes(table) ⇒ Object
load all the indexes for a particular table.
-
#load_schema! ⇒ Object
load the schema from the database.
-
#load_table(table_name) ⇒ Object
Load a single table.
-
#load_tables ⇒ Object
load all the tables.
-
#load_view(name) ⇒ Object
load a single view.
-
#load_views ⇒ Object
load all the views for the database.
-
#tables ⇒ Object
return the tables, reloading if dirty.
- #temporary? ⇒ Boolean
-
#views ⇒ Object
return the views, reloading if dirty.
Constructor Details
#initialize(db, catalog = 'main', master_table = 'sqlite_master') ⇒ Schema
Create a new instance of Schema
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
# 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 |
Instance Attribute Details
#catalog ⇒ Object (readonly)
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.
21 22 23 |
# File 'lib/amalgalite/schema.rb', line 21 def catalog @catalog end |
#db ⇒ Object (readonly)
The Amalagalite::Database this schema is associated with.
27 28 29 |
# File 'lib/amalgalite/schema.rb', line 27 def db @db end |
#schema_version ⇒ Object (readonly)
The schema_version at the time this schema was taken.
24 25 26 |
# File 'lib/amalgalite/schema.rb', line 24 def schema_version @schema_version end |
Instance Method Details
#catalog_master_table ⇒ Object
48 49 50 |
# File 'lib/amalgalite/schema.rb', line 48 def catalog_master_table "#{catalog}.#{@master_table}" end |
#current_version ⇒ Object
62 63 64 |
# File 'lib/amalgalite/schema.rb', line 62 def current_version @db.first_value_from("PRAGMA #{catalog}.schema_version") end |
#dirty? ⇒ Boolean
56 57 58 59 60 |
# 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) ⇒ Object
load all the columns for a particular table
154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 |
# 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.( 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) ⇒ Object
load all the indexes for a particular table
123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 |
# 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! ⇒ Object
load the schema from the database
68 69 70 71 72 73 74 75 76 |
# 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) ⇒ Object
Load a single table
106 107 108 109 110 111 112 113 114 115 116 117 118 |
# 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 ⇒ Object
load all the tables
94 95 96 97 98 99 100 101 102 |
# 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) ⇒ Object
load a single view
206 207 208 209 210 211 212 |
# 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 ⇒ Object
load all the views for the database
217 218 219 220 221 222 223 |
# 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 ⇒ Object
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.
82 83 84 85 86 87 88 89 |
# 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? ⇒ Boolean
52 53 54 |
# File 'lib/amalgalite/schema.rb', line 52 def temporary? catalog == "temp" end |
#views ⇒ Object
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.
194 195 196 197 198 199 200 201 |
# 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 |