| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168 | #ifdef HAVE_SQLITE3_BACKUP_INIT#include <sqlite3_ruby.h>#define REQUIRE_OPEN_BACKUP(_ctxt) \  if(!_ctxt->p) \    rb_raise(rb_path2class("SQLite3::Exception"), "cannot use a closed backup");VALUE cSqlite3Backup;static void deallocate(void * ctx){  sqlite3BackupRubyPtr c = (sqlite3BackupRubyPtr)ctx;  xfree(c);}static VALUE allocate(VALUE klass){  sqlite3BackupRubyPtr ctx = xcalloc((size_t)1, sizeof(sqlite3BackupRuby));  return Data_Wrap_Struct(klass, NULL, deallocate, ctx);}/* call-seq: SQLite3::Backup.new(dstdb, dstname, srcdb, srcname) * * Initialize backup the backup. * * dstdb: *   the destination SQLite3::Database object. * dstname: *   the destination's database name. * srcdb: *   the source SQLite3::Database object. * srcname: *   the source's database name. * * The database name is "main", "temp", or the name specified in an * ATTACH statement. * * This feature requires SQLite 3.6.11 or later. * *   require 'sqlite3' *   sdb = SQLite3::Database.new('src.sqlite3') * *   ddb = SQLite3::Database.new(':memory:') *   b = SQLite3::Backup.new(ddb, 'main', sdb, 'main') *   p [b.remaining, b.pagecount] # invalid value; for example [0, 0] *   begin *     p b.step(1) #=> OK or DONE *     p [b.remaining, b.pagecount] *   end while b.remaining > 0 *   b.finish * *   ddb = SQLite3::Database.new(':memory:') *   b = SQLite3::Backup.new(ddb, 'main', sdb, 'main') *   b.step(-1) #=> DONE *   b.finish * */static VALUE initialize(VALUE self, VALUE dstdb, VALUE dstname, VALUE srcdb, VALUE srcname){  sqlite3BackupRubyPtr ctx;  sqlite3RubyPtr ddb_ctx, sdb_ctx;  sqlite3_backup *pBackup;  Data_Get_Struct(self, sqlite3BackupRuby, ctx);  Data_Get_Struct(dstdb, sqlite3Ruby, ddb_ctx);  Data_Get_Struct(srcdb, sqlite3Ruby, sdb_ctx);  if(!sdb_ctx->db)    rb_raise(rb_eArgError, "cannot backup from a closed database");  if(!ddb_ctx->db)    rb_raise(rb_eArgError, "cannot backup to a closed database");  pBackup = sqlite3_backup_init(ddb_ctx->db, StringValuePtr(dstname),    sdb_ctx->db, StringValuePtr(srcname));  if( pBackup ){    ctx->p = pBackup;  }  else {    CHECK(ddb_ctx->db, sqlite3_errcode(ddb_ctx->db));  }  return self;}/* call-seq: SQLite3::Backup#step(nPage) * * Copy database pages up to +nPage+. * If negative, copy all remaining source pages. * * If all pages are copied, it returns SQLite3::Constants::ErrorCode::DONE. * When coping is not done, it returns SQLite3::Constants::ErrorCode::OK. * When some errors occur, it returns the error code. */static VALUE step(VALUE self, VALUE nPage){  sqlite3BackupRubyPtr ctx;  int status;  Data_Get_Struct(self, sqlite3BackupRuby, ctx);  REQUIRE_OPEN_BACKUP(ctx);  status = sqlite3_backup_step(ctx->p, NUM2INT(nPage));  return INT2NUM(status);}/* call-seq: SQLite3::Backup#finish * * Destroy the backup object. */static VALUE finish(VALUE self){  sqlite3BackupRubyPtr ctx;  Data_Get_Struct(self, sqlite3BackupRuby, ctx);  REQUIRE_OPEN_BACKUP(ctx);  (void)sqlite3_backup_finish(ctx->p);  ctx->p = NULL;  return Qnil;}/* call-seq: SQLite3::Backup#remaining * * Returns the number of pages still to be backed up. * * Note that the value is only updated after step() is called, * so before calling step() returned value is invalid. */static VALUE remaining(VALUE self){  sqlite3BackupRubyPtr ctx;  Data_Get_Struct(self, sqlite3BackupRuby, ctx);  REQUIRE_OPEN_BACKUP(ctx);  return INT2NUM(sqlite3_backup_remaining(ctx->p));}/* call-seq: SQLite3::Backup#pagecount * * Returns the total number of pages in the source database file. * * Note that the value is only updated after step() is called, * so before calling step() returned value is invalid. */static VALUE pagecount(VALUE self){  sqlite3BackupRubyPtr ctx;  Data_Get_Struct(self, sqlite3BackupRuby, ctx);  REQUIRE_OPEN_BACKUP(ctx);  return INT2NUM(sqlite3_backup_pagecount(ctx->p));}void init_sqlite3_backup(){#if 0  VALUE mSqlite3 = rb_define_module("SQLite3");#endif  cSqlite3Backup = rb_define_class_under(mSqlite3, "Backup", rb_cObject);  rb_define_alloc_func(cSqlite3Backup, allocate);  rb_define_method(cSqlite3Backup, "initialize", initialize, 4);  rb_define_method(cSqlite3Backup, "step", step, 1);  rb_define_method(cSqlite3Backup, "finish", finish, 0);  rb_define_method(cSqlite3Backup, "remaining", remaining, 0);  rb_define_method(cSqlite3Backup, "pagecount", pagecount, 0);}#endif
 |