X-Git-Url: https://projects.mako.cc/source/selectricity-live/blobdiff_plain/5637ec97922038fa7a7cfe9f8aa13b1e3002abcd..90a5a1b95e6ec0b5f9aa2db522215463a2909920:/vendor/plugins/yaml_db/lib/yaml_db.rb diff --git a/vendor/plugins/yaml_db/lib/yaml_db.rb b/vendor/plugins/yaml_db/lib/yaml_db.rb new file mode 100644 index 0000000..1cd485e --- /dev/null +++ b/vendor/plugins/yaml_db/lib/yaml_db.rb @@ -0,0 +1,180 @@ +require 'rubygems' +require 'yaml' +require 'active_record' + + +module YamlDb + def self.dump(filename) + disable_logger + YamlDb::Dump.dump(File.new(filename, "w")) + reenable_logger + end + + def self.load(filename) + disable_logger + YamlDb::Load.load(File.new(filename, "r")) + reenable_logger + end + + def self.disable_logger + @@old_logger = ActiveRecord::Base.logger + ActiveRecord::Base.logger = nil + end + + def self.reenable_logger + ActiveRecord::Base.logger = @@old_logger + end +end + + +module YamlDb::Utils + def self.chunk_records(records) + yaml = [ records ].to_yaml + yaml.sub!("--- \n", "") + yaml.sub!('- - -', ' - -') + yaml + end + + def self.unhash(hash, keys) + keys.map { |key| hash[key] } + end + + def self.unhash_records(records, keys) + records.each_with_index do |record, index| + records[index] = unhash(record, keys) + end + + records + end + + def self.convert_booleans(records, columns) + records.each do |record| + columns.each do |column| + next if is_boolean(record[column]) + record[column] = (record[column] == 't' or record[column] == '1') + end + end + records + end + + def self.boolean_columns(table) + columns = ActiveRecord::Base.connection.columns(table).reject { |c| c.type != :boolean } + columns.map { |c| c.name } + end + + def self.is_boolean(value) + value.kind_of?(TrueClass) or value.kind_of?(FalseClass) + end + + def self.quote_table(table) + ActiveRecord::Base.connection.quote_table_name(table) + end +end + + +module YamlDb::Dump + def self.dump(io) + tables.each do |table| + dump_table(io, table) + end + end + + def self.tables + ActiveRecord::Base.connection.tables.reject { |table| ['schema_info', 'schema_migrations'].include?(table) } + end + + def self.dump_table(io, table) + return if table_record_count(table).zero? + + dump_table_columns(io, table) + dump_table_records(io, table) + end + + def self.dump_table_columns(io, table) + io.write("\n") + io.write({ table => { 'columns' => table_column_names(table) } }.to_yaml) + end + + def self.dump_table_records(io, table) + table_record_header(io) + + column_names = table_column_names(table) + + each_table_page(table) do |records| + rows = YamlDb::Utils.unhash_records(records, column_names) + io.write(YamlDb::Utils.chunk_records(records)) + end + end + + def self.table_record_header(io) + io.write(" records: \n") + end + + def self.table_column_names(table) + ActiveRecord::Base.connection.columns(table).map { |c| c.name } + end + + def self.each_table_page(table, records_per_page=1000) + total_count = table_record_count(table) + pages = (total_count.to_f / records_per_page).ceil - 1 + id = table_column_names(table).first + boolean_columns = YamlDb::Utils.boolean_columns(table) + quoted_table_name = YamlDb::Utils.quote_table(table) + + (0..pages).to_a.each do |page| + sql = ActiveRecord::Base.connection.add_limit_offset!("SELECT * FROM #{quoted_table_name} ORDER BY #{id}", + :limit => records_per_page, :offset => records_per_page * page + ) + records = ActiveRecord::Base.connection.select_all(sql) + records = YamlDb::Utils.convert_booleans(records, boolean_columns) + yield records + end + end + + def self.table_record_count(table) + ActiveRecord::Base.connection.select_one("SELECT COUNT(*) FROM #{YamlDb::Utils.quote_table(table)}").values.first.to_i + end +end + + +module YamlDb::Load + def self.load(io) + ActiveRecord::Base.connection.transaction do + YAML.load_documents(io) do |ydoc| + ydoc.keys.each do |table_name| + next if ydoc[table_name].nil? + load_table(table_name, ydoc[table_name]) + end + end + end + end + + def self.truncate_table(table) + begin + ActiveRecord::Base.connection.execute("TRUNCATE #{YamlDb::Utils.quote_table(table)}") + rescue Exception + ActiveRecord::Base.connection.execute("DELETE FROM #{YamlDb::Utils.quote_table(table)}") + end + end + + def self.load_table(table, data) + column_names = data['columns'] + truncate_table(table) + load_records(table, column_names, data['records']) + reset_pk_sequence!(table) + end + + def self.load_records(table, column_names, records) + quoted_column_names = column_names.map { |column| ActiveRecord::Base.connection.quote_column_name(column) }.join(',') + quoted_table_name = YamlDb::Utils.quote_table(table) + records.each do |record| + ActiveRecord::Base.connection.execute("INSERT INTO #{quoted_table_name} (#{quoted_column_names}) VALUES (#{record.map { |r| ActiveRecord::Base.connection.quote(r) }.join(',')})") + end + end + + def self.reset_pk_sequence!(table_name) + if ActiveRecord::Base.connection.respond_to?(:reset_pk_sequence!) + ActiveRecord::Base.connection.reset_pk_sequence!(table_name) + end + end +end