繁体   English   中英

使用Marshal将Sqlite内存数据库转储到磁盘

[英]Dump a Sqlite memory database to disk with Marshal

我想用Marshal将Sqlite内存数据库转储到磁盘上,但出现下面的错误,这里是完整的测试。 用于保存内存数据库的Sqlite API似乎仅在C语言中可用。

require 'sqlite3'
require 'active_record'

ActiveRecord::Base.establish_connection(
:adapter => "sqlite3",
:database  => ":memory:"
)

ActiveRecord::Schema.define do
  create_table :tests do |table|
    table.column :word, :string
  end
end

class Test < ActiveRecord::Base;end
Test.create(word: 'test')

puts Test.all.length
c = ::ActiveRecord::Base.connection
File.open('sqlite_db.marshal','wb') { |f| f.write(Marshal.dump(c)) }
# => error `dump': can't dump hash with default proc (TypeError)

您可以使用sqlite3的Backup类。

# populate ActiveRecord here...

sdb = ::ActiveRecord::Base.connection.raw_connection

ddb = SQLite3::Database.new('backup.sqlite3')

b = SQLite3::Backup.new(ddb, 'main', sdb, 'main')
b.step(-1)
b.finish

目前,我使用以下方法,这不是对我的问题的正确答案,所以我将其保持打开状态,也许有人确实使用Marshal找到了解决方案。在这里,我打开了与磁盘数据库的第二个连接,然后加载并写入之前和之后的连接。

require 'sqlite3'
require 'active_record'

class Test < ActiveRecord::Base
  establish_connection(
    :adapter  => "sqlite3",
    :database => ":memory:"
  )
end

class Test2 < ActiveRecord::Base
  establish_connection(
    :adapter  => "sqlite3",
    :database => "testing.db"
  )
  self.table_name    = :tests
end

def db_load
  ActiveRecord::Schema.define do
    @connection = Test.connection
    create_table :tests do |table|
      table.column :word, :string
    end
  end
  Test2.all.each do |m|
    Test.create m.attributes
  end
end

def db_write
  Test2.delete_all
  Test.all.each do |m|
    Test2.create m.attributes
  end
end

def db_test klasse
  klasse.all.each do |record|
    p record
  end
end

db_load
db_test Test
Test.create(word: 'test3')
db_write
db_test Test2

-- create_table(:tests)
   -> 0.0060s
#<Test id: 1, word: "test">
#<Test id: 2, word: "test2">
#<Test2 id: 1, word: "test">
#<Test2 id: 2, word: "test2">
#<Test2 id: 3, word: "test3">

这是Max提出的技术示例。 它不是使用元帅,也不是用于Activerecord,而是使用ussefull,因此这里供参考

require 'sqlite3'
require 'active_record'

ActiveRecord::Base.establish_connection(:adapter => "sqlite3",:database  => ":memory:")

sdb = SQLite3::Database.new(':memory:')

sdb.execute "CREATE TABLE IF NOT EXISTS Cars(Id INTEGER PRIMARY KEY, Name TEXT, Price INT)"
sdb.execute "INSERT INTO Cars VALUES(1,'Audi',52642)"
sdb.execute "INSERT INTO Cars VALUES(2,'Mercedes',57127)"
sdb.execute "INSERT INTO Cars VALUES(3,'Skoda',9000)"
sdb.execute "INSERT INTO Cars VALUES(4,'Volvo',29000)"
sdb.execute "INSERT INTO Cars VALUES(5,'Bentley',350000)"
sdb.execute "INSERT INTO Cars VALUES(6,'Citroen',21000)"
sdb.execute "INSERT INTO Cars VALUES(7,'Hummer',41400)"
sdb.execute "INSERT INTO Cars VALUES(8,'Volkswagen',21600)"


ddb = SQLite3::Database.new('backup.sqlite3')

b = SQLite3::Backup.new(ddb, 'main', sdb, 'main')
b.step(-1)
b.finish

stm = ddb.prepare "SELECT * FROM Cars LIMIT 5" 
rs = stm.execute 

rs.each do |row|
  puts row.join "\s"
end

1 Audi 52642
2 Mercedes 57127
3 Skoda 9000
4 Volvo 29000
5 Bentley 350000

为了参考和完整性,这里基于Max编辑的答案的最终解决方案

require 'sqlite3'
require 'active_record'

ActiveRecord::Base.establish_connection(
  :adapter => "sqlite3",
  :database  => ":memory:"
)

ActiveRecord::Schema.define do
  create_table :tests do |table|
    table.column :word, :string
    table.column :index, :string
  end
end

class Test < ActiveRecord::Base;end
Test.create(word: 'test', index: 0)
Test.create(word: 'test2', index: 1)

sdb = ::ActiveRecord::Base.connection.raw_connection
ddb = SQLite3::Database.new('backup_sqlite3.db')

backup = SQLite3::Backup.new(ddb, 'main', sdb, 'main')
backup.step(-1)
backup.finish

ddb.execute("select * from tests").each do |record|
  p record
end

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM