Class: Extralite::Changeset
- Inherits:
-
Object
- Object
- Extralite::Changeset
- Defined in:
- ext/extralite/changeset.c,
ext/extralite/changeset.c
Overview
This class implements a Changeset for tracking changes to the database.
Instance Method Summary collapse
-
#apply(db) ⇒ Extralite::Changeset
Applies the changeset to the given database.
-
#each ⇒ Extralite::Changeset
Iterates through the changeset, providing each change to the given block.
-
#initialize ⇒ void
constructor
Initializes an empty changeset.
-
#invert ⇒ Extralite::Changeset
Returns an inverted changeset.
-
#load(blob) ⇒ Extralite::Changeset
Loads a changeset from the given string.
-
#to_a ⇒ Array<Array>
Returns an array containing all changes in the changeset.
-
#to_blob ⇒ String
Returns a string BLOB containing the changeset in serialized form.
-
#track(db, tables) ⇒ Extralite::Changeset
Tracks changes in the given block and collects them into the changeset.
Constructor Details
#initialize ⇒ void
Initializes an empty changeset.
51 52 53 54 55 56 |
# File 'ext/extralite/changeset.c', line 51
VALUE Changeset_initialize(VALUE self) {
Changeset_t *changeset = self_to_changeset(self);
changeset->changeset_len = 0;
changeset->changeset_ptr = NULL;
return Qnil;
}
|
Instance Method Details
#apply(db) ⇒ Extralite::Changeset
Applies the changeset to the given database.
351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 |
# File 'ext/extralite/changeset.c', line 351
VALUE Changeset_apply(VALUE self, VALUE db) {
Changeset_t *changeset = self_to_changeset(self);
verify_changeset(changeset);
Database_t *db_struct = self_to_database(db);
sqlite3 *sqlite3_db = db_struct->sqlite3_db;
int rc = sqlite3changeset_apply(
sqlite3_db,
changeset->changeset_len,
changeset->changeset_ptr,
NULL,
xConflict,
(void*)1
);
if (rc != SQLITE_OK)
rb_raise(cError, "Error while applying changeset: %s", sqlite3_errstr(rc));
return self;
}
|
#each ⇒ Extralite::Changeset
Iterates through the changeset, providing each change to the given block. Each change entry is an array containing the operation (:insert / :update / :delete), the table name, an array containing the old values, and an array containing the new values.
changeset.each do |(op, table, old_values, new_values)|
...
end
308 309 310 311 312 313 314 315 316 317 318 319 |
# File 'ext/extralite/changeset.c', line 308
VALUE Changeset_each(VALUE self) {
Changeset_t *changeset = self_to_changeset(self);
verify_changeset(changeset);
struct each_ctx ctx = { .iter = NULL };
int rc = sqlite3changeset_start(&ctx.iter, changeset->changeset_len, changeset->changeset_ptr);
if (rc!=SQLITE_OK)
rb_raise(cError, "Error while starting iterator: %s", sqlite3_errstr(rc));
rb_ensure(SAFE(safe_each), (VALUE)&ctx, SAFE(cleanup_iter), (VALUE)&ctx);
return self;
}
|
#invert ⇒ Extralite::Changeset
Returns an inverted changeset. The inverted changeset can be used to undo the changes in the original changeset.
# undo changes
changeset.invert.apply(db)
380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 |
# File 'ext/extralite/changeset.c', line 380
VALUE Changeset_invert(VALUE self) {
Changeset_t *changeset = self_to_changeset(self);
verify_changeset(changeset);
VALUE inverted = rb_funcall(cChangeset, ID_new, 0);
Changeset_t *inverted_changeset = self_to_changeset(inverted);
int rc = sqlite3changeset_invert(
changeset->changeset_len, changeset->changeset_ptr,
&inverted_changeset->changeset_len, &inverted_changeset->changeset_ptr
);
if (rc != SQLITE_OK)
rb_raise(cError, "Error while inverting changeset: %s", sqlite3_errstr(rc));
RB_GC_GUARD(inverted);
return inverted;
}
|
#load(blob) ⇒ Extralite::Changeset
424 425 426 427 428 429 430 431 432 433 434 435 436 437 |
# File 'ext/extralite/changeset.c', line 424
VALUE Changeset_load(VALUE self, VALUE blob) {
Changeset_t *changeset = self_to_changeset(self);
if (changeset->changeset_ptr) {
sqlite3_free(changeset->changeset_ptr);
changeset->changeset_ptr = NULL;
changeset->changeset_len = 0;
}
changeset->changeset_len = RSTRING_LEN(blob);
changeset->changeset_ptr = sqlite3_malloc(changeset->changeset_len);
memcpy(changeset->changeset_ptr, RSTRING_PTR(blob), changeset->changeset_len);
return self;
}
|
#to_a ⇒ Array<Array>
Returns an array containing all changes in the changeset. Each change entry is an array containing the operation (:insert / :update / :delete), the table name, an array containing the old values, and an array containing the new values.
328 329 330 331 332 333 334 335 336 337 338 |
# File 'ext/extralite/changeset.c', line 328
VALUE Changeset_to_a(VALUE self) {
Changeset_t *changeset = self_to_changeset(self);
verify_changeset(changeset);
struct each_ctx ctx = { .iter = NULL };
int rc = sqlite3changeset_start(&ctx.iter, changeset->changeset_len, changeset->changeset_ptr);
if (rc!=SQLITE_OK)
rb_raise(cError, "Error while starting iterator: %s", sqlite3_errstr(rc));
return rb_ensure(SAFE(safe_to_a), (VALUE)&ctx, SAFE(cleanup_iter), (VALUE)&ctx);
}
|
#to_blob ⇒ String
Returns a string BLOB containing the changeset in serialized form. The changeset BLOB can be stored to file for later retrieval.
File.open('my.changes', 'w+') { |f| f << changeset.to_blob }
405 406 407 408 409 410 411 412 |
# File 'ext/extralite/changeset.c', line 405
VALUE Changeset_to_blob(VALUE self) {
Changeset_t *changeset = self_to_changeset(self);
if (changeset->changeset_ptr)
return rb_str_new(changeset->changeset_ptr, changeset->changeset_len);
else
return rb_str_new("", 0);
}
|
#track(db, tables) ⇒ Extralite::Changeset
Tracks changes in the given block and collects them into the changeset. Changes are tracked only for the given tables. If nil is supplied as the given tables, changes are tracked for all tables.
# track changes for the foo and bar tables
changeset.track(db, [:foo, :bar]) do
run_some_queries
end
store_changes(changeset.to_blob)
131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 |
# File 'ext/extralite/changeset.c', line 131
VALUE Changeset_track(VALUE self, VALUE db, VALUE tables) {
Changeset_t *changeset = self_to_changeset(self);
Database_t *db_struct = self_to_database(db);
sqlite3 *sqlite3_db = db_struct->sqlite3_db;
if (changeset->changeset_ptr) {
sqlite3_free(changeset->changeset_ptr);
changeset->changeset_len = 0;
changeset->changeset_ptr = NULL;
}
struct track_ctx ctx = {
.changeset = changeset,
.sqlite3_db = sqlite3_db,
.session = NULL,
.db = db,
.tables = tables
};
int rc = sqlite3session_create(sqlite3_db, "main", &ctx.session);
if (rc != SQLITE_OK)
rb_raise(cError, "Error while creating session: %s", sqlite3_errstr(rc));
rb_ensure(SAFE(safe_track), (VALUE)&ctx, SAFE(cleanup_track), (VALUE)&ctx);
return self;
}
|