require 'ostruct' require 'binary_struct' require_relative 'MiqSqlite3Util' require_relative 'MiqSqlite3Page' require_relative 'MiqSqlite3Cell' module MiqSqlite3DB class MiqSqlite3Table def self.table_names(db) names = [] MiqSqlite3Table.each(db) do |table| names << table.name if 'table' == table.type end names end def self.index_names(db) names = [] MiqSqlite3Table.each(db) do |table| names << table.name if 'index' == table.type end names end def self.getTable(db, name) MiqSqlite3Table.each(db) do |table| return table if name == table.name end nil end def self.each(db) root_page = MiqSqlite3Page.getPage(db, 1) root_page.each_child do |child| page = MiqSqlite3Page.getPage(db, child) page.each_cell do |cell| yield MiqSqlite3Table.new(db, child, cell) end end end ##################################### ## Instance Methods ##################################### attr_reader :name, :type def initialize(db, pagenum, cell) @pagenum = pagenum @db = db @fields = cell.fields @type = @fields[0]['data'] @name = @fields[1]['data'] @desc = @fields[2]['data'] @data = @fields[3]['data'] @sql = @fields[4]['data'] @columns = nil decodeSchema end def decodeSchema return if @type != "table" || @name[0..6] == "sqlite_" # Names beginning with sqlite_ are internal to engine @columns = [] sql = @sql.gsub(/[\n\r]/, "") re1 = /\s*CREATE\s+TABLE\s+(\w+)\s*\((.*)\)\s*/ m = re1.match(sql) tname = m[1].to_s.chomp raise "Inconsistent Table Name" if tname != @name cols = m[2].to_s cols.split(",").each do |c| words = c.split defn = {} defn['name'] = words[0] defn['type'] = words[1].downcase defn['type'] = "key" if words[2] && words[2].upcase == "PRIMARY" if defn['type'] == "key" @key = defn['name'] else @columns << defn end end end def each_row MiqSqlite3Page.getPage(@db, @data).leaves do |leaf| leaf.each_cell do |cell| row = {} row[@key] = cell.key if @key i = @key ? 1 : 0 each_column do |col| row[col['name']] = cell.fields[i]['data'] i += 1 end yield row end end end def each_column @columns.each { |col| yield col } end def dump puts "=================" puts "Page: #{@pagenum}" puts "Length: #{@len}" puts "Type: #{@type}" puts "Name: #{@name}" puts "Description: #{@desc}" puts "Data Begins on Page: #{@data}" puts "SQL: #{@sql}" puts "Key: #{@key}" if @key if @columns for i in 1..@columns.size puts "Column #{i}: #{@columns[i - 1]['name']} => #{@columns[i - 1]['type']}" end end end end end