backup.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. #ifdef HAVE_SQLITE3_BACKUP_INIT
  2. #include <sqlite3_ruby.h>
  3. #define REQUIRE_OPEN_BACKUP(_ctxt) \
  4. if(!_ctxt->p) \
  5. rb_raise(rb_path2class("SQLite3::Exception"), "cannot use a closed backup");
  6. VALUE cSqlite3Backup;
  7. static void deallocate(void * ctx)
  8. {
  9. sqlite3BackupRubyPtr c = (sqlite3BackupRubyPtr)ctx;
  10. xfree(c);
  11. }
  12. static VALUE allocate(VALUE klass)
  13. {
  14. sqlite3BackupRubyPtr ctx = xcalloc((size_t)1, sizeof(sqlite3BackupRuby));
  15. return Data_Wrap_Struct(klass, NULL, deallocate, ctx);
  16. }
  17. /* call-seq: SQLite3::Backup.new(dstdb, dstname, srcdb, srcname)
  18. *
  19. * Initialize backup the backup.
  20. *
  21. * dstdb:
  22. * the destination SQLite3::Database object.
  23. * dstname:
  24. * the destination's database name.
  25. * srcdb:
  26. * the source SQLite3::Database object.
  27. * srcname:
  28. * the source's database name.
  29. *
  30. * The database name is "main", "temp", or the name specified in an
  31. * ATTACH statement.
  32. *
  33. * This feature requires SQLite 3.6.11 or later.
  34. *
  35. * require 'sqlite3'
  36. * sdb = SQLite3::Database.new('src.sqlite3')
  37. *
  38. * ddb = SQLite3::Database.new(':memory:')
  39. * b = SQLite3::Backup.new(ddb, 'main', sdb, 'main')
  40. * p [b.remaining, b.pagecount] # invalid value; for example [0, 0]
  41. * begin
  42. * p b.step(1) #=> OK or DONE
  43. * p [b.remaining, b.pagecount]
  44. * end while b.remaining > 0
  45. * b.finish
  46. *
  47. * ddb = SQLite3::Database.new(':memory:')
  48. * b = SQLite3::Backup.new(ddb, 'main', sdb, 'main')
  49. * b.step(-1) #=> DONE
  50. * b.finish
  51. *
  52. */
  53. static VALUE initialize(VALUE self, VALUE dstdb, VALUE dstname, VALUE srcdb, VALUE srcname)
  54. {
  55. sqlite3BackupRubyPtr ctx;
  56. sqlite3RubyPtr ddb_ctx, sdb_ctx;
  57. sqlite3_backup *pBackup;
  58. Data_Get_Struct(self, sqlite3BackupRuby, ctx);
  59. Data_Get_Struct(dstdb, sqlite3Ruby, ddb_ctx);
  60. Data_Get_Struct(srcdb, sqlite3Ruby, sdb_ctx);
  61. if(!sdb_ctx->db)
  62. rb_raise(rb_eArgError, "cannot backup from a closed database");
  63. if(!ddb_ctx->db)
  64. rb_raise(rb_eArgError, "cannot backup to a closed database");
  65. pBackup = sqlite3_backup_init(ddb_ctx->db, StringValuePtr(dstname),
  66. sdb_ctx->db, StringValuePtr(srcname));
  67. if( pBackup ){
  68. ctx->p = pBackup;
  69. }
  70. else {
  71. CHECK(ddb_ctx->db, sqlite3_errcode(ddb_ctx->db));
  72. }
  73. return self;
  74. }
  75. /* call-seq: SQLite3::Backup#step(nPage)
  76. *
  77. * Copy database pages up to +nPage+.
  78. * If negative, copy all remaining source pages.
  79. *
  80. * If all pages are copied, it returns SQLite3::Constants::ErrorCode::DONE.
  81. * When coping is not done, it returns SQLite3::Constants::ErrorCode::OK.
  82. * When some errors occur, it returns the error code.
  83. */
  84. static VALUE step(VALUE self, VALUE nPage)
  85. {
  86. sqlite3BackupRubyPtr ctx;
  87. int status;
  88. Data_Get_Struct(self, sqlite3BackupRuby, ctx);
  89. REQUIRE_OPEN_BACKUP(ctx);
  90. status = sqlite3_backup_step(ctx->p, NUM2INT(nPage));
  91. return INT2NUM(status);
  92. }
  93. /* call-seq: SQLite3::Backup#finish
  94. *
  95. * Destroy the backup object.
  96. */
  97. static VALUE finish(VALUE self)
  98. {
  99. sqlite3BackupRubyPtr ctx;
  100. Data_Get_Struct(self, sqlite3BackupRuby, ctx);
  101. REQUIRE_OPEN_BACKUP(ctx);
  102. (void)sqlite3_backup_finish(ctx->p);
  103. ctx->p = NULL;
  104. return Qnil;
  105. }
  106. /* call-seq: SQLite3::Backup#remaining
  107. *
  108. * Returns the number of pages still to be backed up.
  109. *
  110. * Note that the value is only updated after step() is called,
  111. * so before calling step() returned value is invalid.
  112. */
  113. static VALUE remaining(VALUE self)
  114. {
  115. sqlite3BackupRubyPtr ctx;
  116. Data_Get_Struct(self, sqlite3BackupRuby, ctx);
  117. REQUIRE_OPEN_BACKUP(ctx);
  118. return INT2NUM(sqlite3_backup_remaining(ctx->p));
  119. }
  120. /* call-seq: SQLite3::Backup#pagecount
  121. *
  122. * Returns the total number of pages in the source database file.
  123. *
  124. * Note that the value is only updated after step() is called,
  125. * so before calling step() returned value is invalid.
  126. */
  127. static VALUE pagecount(VALUE self)
  128. {
  129. sqlite3BackupRubyPtr ctx;
  130. Data_Get_Struct(self, sqlite3BackupRuby, ctx);
  131. REQUIRE_OPEN_BACKUP(ctx);
  132. return INT2NUM(sqlite3_backup_pagecount(ctx->p));
  133. }
  134. void init_sqlite3_backup()
  135. {
  136. #if 0
  137. VALUE mSqlite3 = rb_define_module("SQLite3");
  138. #endif
  139. cSqlite3Backup = rb_define_class_under(mSqlite3, "Backup", rb_cObject);
  140. rb_define_alloc_func(cSqlite3Backup, allocate);
  141. rb_define_method(cSqlite3Backup, "initialize", initialize, 4);
  142. rb_define_method(cSqlite3Backup, "step", step, 1);
  143. rb_define_method(cSqlite3Backup, "finish", finish, 0);
  144. rb_define_method(cSqlite3Backup, "remaining", remaining, 0);
  145. rb_define_method(cSqlite3Backup, "pagecount", pagecount, 0);
  146. }
  147. #endif