class FeideeUtils::Database
Constants
- AllHeaders
- AllKnownTables
- FeideeHeader_Android
- FeideeHeader_iOS
- Header
- NoDeleteSuffixTables
- PotentialUsefulTables
- Tables
Attributes
last_modified_at[R]
ledger[R]
ledger_name[R]
missing_tables[R]
platform[R]
sqlite_file[R]
Public Class Methods
new(private_sqlite, strip = false)
click to toggle source
Calls superclass method
# File lib/feidee_utils/database.rb, line 35 def initialize(private_sqlite, strip = false) @sqlite_file = Database.feidee_to_sqlite(private_sqlite) super(@sqlite_file.path) extract_metadata drop_unused_tables if strip # TODO: make Ledger a first class object. @ledger = Record.generate_subclasses(self) end
Private Class Methods
feidee_to_sqlite(private_sqlite, sqlite_file = nil)
click to toggle source
# File lib/feidee_utils/database.rb, line 121 def feidee_to_sqlite(private_sqlite, sqlite_file = nil) # Discard the first a few bytes content. private_header = private_sqlite.read(Header.length) unless AllHeaders.include? private_header raise "Unexpected private sqlite header #{private_header.inspect}." end # Write the rest to a tempfile. sqlite_file ||= Tempfile.new("kingdee_sqlite", binmode: true) sqlite_file.binmode sqlite_file.write(Header) sqlite_file.write(private_sqlite.read) sqlite_file.fsync sqlite_file end
open_file(file_name)
click to toggle source
# File lib/feidee_utils/database.rb, line 112 def open_file(file_name) Database.new(File.open(file_name)) end
sqlite_to_feidee(sqlite, feidee_file = nil, platform = :iOS)
click to toggle source
# File lib/feidee_utils/database.rb, line 138 def sqlite_to_feidee(sqlite, feidee_file = nil, platform = :iOS) sqlite.read(Header.length) private_header = if platform == :iOS FeideeHeader_iOS else FeideeHeader_Android end feidee_file ||= Tempfile.new("feidee_sqlite", binmode: true) feidee_file.binmode feidee_file.write(private_header) feidee_file.write(sqlite.read) feidee_file.fsync feidee_file end
trash_table_name(name)
click to toggle source
# File lib/feidee_utils/database.rb, line 161 def trash_table_name name NoDeleteSuffixTables.each do |core_name| if name == "t_" + core_name then return "t_" + "deleted_" + core_name; end end name + "_delete" end
Public Instance Methods
sqlite_backup(dest_file_path)
click to toggle source
# File lib/feidee_utils/database.rb, line 47 def sqlite_backup(dest_file_path) self.execute("vacuum;") backup_sqlite_db = SQLite3::Database.new(dest_file_path.to_s) backup_obj = SQLite3::Backup.new(backup_sqlite_db, "main", self, "main") backup_obj.step(-1) backup_obj.finish backup_sqlite_db.close end
validate_global_integrity()
click to toggle source
# File lib/feidee_utils/database.rb, line 57 def validate_global_integrity @ledger.constants.each do |const| @ledger.const_get(const).validate_global_integrity if const != :Database end end
Private Instance Methods
all_tables()
click to toggle source
# File lib/feidee_utils/database.rb, line 64 def all_tables rows = self.execute <<-SQL SELECT name FROM sqlite_master WHERE type IN ('table','view') AND name NOT LIKE 'sqlite_%' UNION ALL SELECT name FROM sqlite_temp_master WHERE type IN ('table','view') ORDER BY 1 SQL rows.map do |row| row[0] end.sort end
drop_unused_tables()
click to toggle source
# File lib/feidee_utils/database.rb, line 76 def drop_unused_tables useful_tables = Tables.values + PotentialUsefulTables useful_tables += useful_tables.map do |x| self.class.trash_table_name(x) end useful_tables.sort! # TODO: Record all tables droped. (all_tables - useful_tables).each do |table| self.execute("DROP TABLE IF EXISTS #{table}"); end @missing_tables = Tables.values - all_tables if !@missing_tables.empty? raise "Missing tables: #{@missing_tables} from kbf backup." end end
extract_metadata()
click to toggle source
# File lib/feidee_utils/database.rb, line 94 def extract_metadata @platform = self.execute( "SELECT platform from #{Tables[:metadata]}" )[0][0]; @ledger_name = self.get_first_row( "SELECT accountBookName FROM #{Tables[:profile]};" )[0]; # This is not recorded in the database, so the lastest lastUpdateTime of # all transactions is chosen. timestamp = self.get_first_row( "SELECT max(lastUpdateTime) FROM #{Tables[:transactions]};" )[0] @last_modified_at = Time.at((timestamp or 0.0) / 1000) end