diff --git a/ext/notes.txt b/ext/notes.txt index 44e5815..702cc55 100644 --- a/ext/notes.txt +++ b/ext/notes.txt @@ -55,9 +55,9 @@ Core 'Objects' TODO: int sqlite3_busy_timeout(sqlite3*) TODO: void sqlite3_progress_hander(sqlite3*, int, int(*)(void*), void*) - TODO : tracing should be an IO object, if it is true then send it to STDERR - TODO : tracing should also yield a block like a transaction so that during the block the db has tracing turned on. - sqlite3_trace + *done* tracing should be an IO object, if it is true then send it to STDERR + *done* tracing should also yield a block like a transaction so that during the block the db has tracing turned on. + *done* sqlite3_trace TODO: create Table and Column classes TODO: int sqlite3_table_column_metadata(); diff --git a/lib/amalgalite/database.rb b/lib/amalgalite/database.rb index 1f68079..82824ad 100644 --- a/lib/amalgalite/database.rb +++ b/lib/amalgalite/database.rb @@ -298,6 +298,17 @@ def profile_tap=( tap_obj ) @api.register_profile_tap( @profile_tap ) @profile_tap.profile( 'registered as profile tap', 0.0 ) end + + ## + # :call-seq: + # db.schema( dbname = "main" ) -> Schema + # + # Returns a Schema object containing the table and column structure of the + # database. + # + def schema( dbname = "main" ) + @schema ||= ::Amalgalite::Schema.new( self, dbname ) + end end end diff --git a/lib/amalgalite/index.rb b/lib/amalgalite/index.rb new file mode 100644 index 0000000..aad0f56 --- /dev/null +++ b/lib/amalgalite/index.rb @@ -0,0 +1,22 @@ +#-- +# Copyright (c) 2008 Jeremy Hinegardner +# All rights reserved. See LICENSE and/or COPYING for details. +#++ + +module Amalgalite + # + # abstrace of the meta informationa about 1 Index + # + class Index + attr_reader :name + attr_reader :sql + attr_accessor :table + + def initialize( name, sql, table ) + @name = name + @sql = sql + @table = table + end + end +end + diff --git a/lib/amalgalite/schema.rb b/lib/amalgalite/schema.rb new file mode 100644 index 0000000..6b32050 --- /dev/null +++ b/lib/amalgalite/schema.rb @@ -0,0 +1,51 @@ +#-- +# Copyright (c) 2008 Jeremy Hinegardner +# All rights reserved. See LICENSE and/or COPYING for details. +#++ + +require 'amalgalite/table' +require 'amalgalite/index' + +module Amalgalite + # + # 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. + # + class Schema + + attr_reader :catalog + attr_reader :schema + + def initialize( db, catalog = 'main', schema = 'sqlite') + @db = db + @catalog = catalog + @schema = schema + + load_schema! + end + + # + # load the schema from the database + def load_schema! + load_tables + load_views + end + + ## + # load all the tables + # + def load_tables + @tables = {} + @db.execute("SELECT tbl_name, sql FROM sqlite_master WHERE type = 'table'") do |table_info| + table = Amalgalite::Table.new( table_info['name'], table_info['sql'] ) + table.columns = @db.pragma "table_info( #{table.name })" + + @db.execute("SELECT name, sql FROM sqlite_master WHERE type ='index' and tbl_name = @name") do |idx_info| + table.indexes << Amalgalite::Index.new( idx_info['name'], idx_info['sql'], table ) + end + @tables[table.name] = table + end + @tables + end + end +end diff --git a/lib/amalgalite/table.rb b/lib/amalgalite/table.rb new file mode 100644 index 0000000..bec9244 --- /dev/null +++ b/lib/amalgalite/table.rb @@ -0,0 +1,22 @@ +#-- +# Copyright (c) 2008 Jeremy Hinegardner +# All rights reserved. See LICENSE and/or COPYING for details. +#++ + +module Amalgalite + # + # abstrace of the meta informationa bout 1 table + # + class Table + attr_reader :name + attr_reader :sql + attr_accessor :indexes + + def initialize( name, sql ) + @name = name + @sql = sql + @indexes = [] + end + end +end + diff --git a/spec/database_spec.rb b/spec/database_spec.rb index 1fe1114..2ca3853 100644 --- a/spec/database_spec.rb +++ b/spec/database_spec.rb @@ -9,12 +9,14 @@ describe Amalgalite::Database do before(:each) do @schema = IO.read( SpecInfo.test_schema_file ) - @iso_db = SpecInfo.make_iso_db + @iso_db_file = SpecInfo.make_iso_db + @iso_db = Amalgalite::Database.new( SpecInfo.make_iso_db ) end after(:each) do File.unlink SpecInfo.test_db if File.exist?( SpecInfo.test_db ) - File.unlink @iso_db if File.exist?( @iso_db ) + @iso_db.close + File.unlink @iso_db_file if File.exist?( @iso_db_file ) end it "can create a new database" do diff --git a/spec/schema_spec.rb b/spec/schema_spec.rb new file mode 100644 index 0000000..f58f2ab --- /dev/null +++ b/spec/schema_spec.rb @@ -0,0 +1,26 @@ +require 'rubygems' +require 'spec' + +$: << File.expand_path(File.join(File.dirname(__FILE__),"..","lib")) +require 'amalgalite' +require 'amalgalite/schema' + +describe Amalgalite::Schema do + before(:each) do + @schema = IO.read( SpecInfo.test_schema_file ) + @iso_db_file = SpecInfo.make_iso_db + @iso_db = Amalgalite::Database.new( SpecInfo.make_iso_db ) + end + + after(:each) do + File.unlink SpecInfo.test_db if File.exist?( SpecInfo.test_db ) + @iso_db.close + File.unlink @iso_db_file if File.exist?( @iso_db_file ) + end + + it "loads the schema of a database" do + schema = @iso_db.schema + schema.tables.size.should == 2 + end + +end