Skip to content

Commit 37d9914

Browse files
committed
Refactored begin/commit ALTER
1 parent 7d1fb60 commit 37d9914

File tree

5 files changed

+142
-159
lines changed

5 files changed

+142
-159
lines changed

src/cloudsync.c

Lines changed: 126 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -391,18 +391,6 @@ db_int64 cloudsync_dbversion_next (cloudsync_context *data, db_int64 merging_ver
391391
return result;
392392
}
393393

394-
// MARK: -
395-
396-
void *cloudsync_get_auxdata (sqlite3_context *context) {
397-
cloudsync_context *data = (context) ? (cloudsync_context *)sqlite3_user_data(context) : NULL;
398-
return (data) ? data->aux_data : NULL;
399-
}
400-
401-
void cloudsync_set_auxdata (sqlite3_context *context, void *xdata) {
402-
cloudsync_context *data = (context) ? (cloudsync_context *)sqlite3_user_data(context) : NULL;
403-
if (data) data->aux_data = xdata;
404-
}
405-
406394
// MARK: - PK Context -
407395

408396
char *cloudsync_pk_context_tbl (cloudsync_pk_decode_bind_context *ctx, int64_t *tbl_len) {
@@ -532,7 +520,13 @@ int cloudsync_set_error (cloudsync_context *data, const char *err_user, int err_
532520
if (err_user == NULL) {
533521
snprintf(data->errmsg, sizeof(data->errmsg), "%s", database_errmsg(db));
534522
} else {
535-
snprintf(data->errmsg, sizeof(data->errmsg), "%s (%s)", err_user, database_errmsg(db));
523+
const char *db_error = database_errmsg(db);
524+
int rc = database_errcode(db);
525+
if (rc == DBRES_OK) {
526+
snprintf(data->errmsg, sizeof(data->errmsg), "%s", err_user);
527+
} else {
528+
snprintf(data->errmsg, sizeof(data->errmsg), "%s (%s)", err_user, db_error);
529+
}
536530
}
537531

538532
return err_code;
@@ -548,6 +542,12 @@ const char *cloudsync_errmsg (cloudsync_context *data) {
548542

549543
// MARK: - Table Utils -
550544

545+
void table_pknames_free (char **names, int nrows) {
546+
if (!names) return;
547+
for (int i = 0; i < nrows; ++i) {dbmem_free(names[i]);}
548+
dbmem_free(names);
549+
}
550+
551551
char *table_build_values_sql (db_t *db, cloudsync_table_context *table) {
552552
char *sql = NULL;
553553

@@ -726,8 +726,8 @@ void table_free (cloudsync_table_context *table) {
726726
}
727727
}
728728

729-
if (table->pk_name) sqlite3_free_table(table->pk_name);
730729
if (table->name) cloudsync_memory_free(table->name);
730+
if (table->pk_name) table_pknames_free(table->pk_name, table->npks);
731731
if (table->meta_pkexists_stmt) database_finalize(table->meta_pkexists_stmt);
732732
if (table->meta_sentinel_update_stmt) database_finalize(table->meta_sentinel_update_stmt);
733733
if (table->meta_sentinel_insert_stmt) database_finalize(table->meta_sentinel_insert_stmt);
@@ -1124,8 +1124,7 @@ char **table_pknames (cloudsync_table_context *table) {
11241124
}
11251125

11261126
void table_set_pknames (cloudsync_table_context *table, char **pknames) {
1127-
// TODO: fix me
1128-
if (table->pk_name) sqlite3_free_table(table->pk_name);
1127+
table_pknames_free(table->pk_name, table->npks);
11291128
table->pk_name = pknames;
11301129
}
11311130

@@ -1621,7 +1620,66 @@ void cloudsync_rollback_hook (void *ctx) {
16211620
data->seq = 0;
16221621
}
16231622

1624-
int cloudsync_finalize_alter (sqlite3_context *context, cloudsync_context *data, cloudsync_table_context *table) {
1623+
int cloudsync_begin_alter (cloudsync_context *data, const char *table_name) {
1624+
db_t *db = data->db;
1625+
1626+
// init cloudsync_settings
1627+
if (cloudsync_context_init(data, db, NULL) == NULL) {
1628+
return cloudsync_set_error(data, "Unable to initialize cloudsync context", SQLITE_MISUSE);
1629+
}
1630+
1631+
// lookup table
1632+
cloudsync_table_context *table = table_lookup(data, table_name);
1633+
if (!table) {
1634+
char buffer[1024];
1635+
snprintf(buffer, sizeof(buffer), "Unable to find table %s", table_name);
1636+
return cloudsync_set_error(data, buffer, SQLITE_MISUSE);
1637+
}
1638+
1639+
// create a savepoint to manage the alter operations as a transaction
1640+
int rc = database_exec(db, "SAVEPOINT cloudsync_alter;");
1641+
if (rc != SQLITE_OK) {
1642+
return cloudsync_set_error(data, "Unable to create cloudsync_begin_alter savepoint", SQLITE_MISUSE);
1643+
}
1644+
1645+
// retrieve primary key(s)
1646+
char **names = NULL;
1647+
int nrows = 0;
1648+
rc = database_pk_names(db, table_name, &names, &nrows);
1649+
if (rc != DBRES_OK) {
1650+
char buffer[1024];
1651+
snprintf(buffer, sizeof(buffer), "Unable to get primary keys for table %s", table_name);
1652+
cloudsync_set_error(data, buffer, SQLITE_MISUSE);
1653+
goto rollback_begin_alter;
1654+
}
1655+
1656+
// sanity check the number of primary keys
1657+
if (nrows != table_count_pks(table)) {
1658+
char buffer[1024];
1659+
snprintf(buffer, sizeof(buffer), "Number of primary keys for table %s changed before ALTER", table_name);
1660+
cloudsync_set_error(data, buffer, SQLITE_MISUSE);
1661+
goto rollback_begin_alter;
1662+
}
1663+
1664+
// drop original triggers
1665+
dbutils_delete_triggers(db, table_name);
1666+
if (rc != SQLITE_OK) {
1667+
char buffer[1024];
1668+
snprintf(buffer, sizeof(buffer), "Unable to delete triggers for table %s in cloudsync_begin_alter.", table_name);
1669+
cloudsync_set_error(data, buffer, SQLITE_ERROR);
1670+
goto rollback_begin_alter;
1671+
}
1672+
1673+
table_set_pknames(table, names);
1674+
return DBRES_OK;
1675+
1676+
rollback_begin_alter:
1677+
database_exec(db, "ROLLBACK TO cloudsync_alter; RELEASE cloudsync_alter;");
1678+
if (names) table_pknames_free(names, nrows);
1679+
return rc;
1680+
}
1681+
1682+
int cloudsync_finalize_alter (cloudsync_context *data, cloudsync_table_context *table) {
16251683
// check if dbversion needed to be updated
16261684
cloudsync_dbversion_check_uptodate(data);
16271685

@@ -1640,24 +1698,6 @@ int cloudsync_finalize_alter (sqlite3_context *context, cloudsync_context *data,
16401698
goto finalize;
16411699
}
16421700

1643-
/*
1644-
char *errmsg = NULL;
1645-
char **result = NULL;
1646-
int nrows, ncols;
1647-
char *sql = cloudsync_memory_mprintf("SELECT name FROM pragma_table_info('%q') WHERE pk>0 ORDER BY pk;", table->name);
1648-
1649-
sqlite3 *db = data->db;
1650-
int rc = sqlite3_get_table(db, sql, &result, &nrows, &ncols, NULL);
1651-
cloudsync_memory_free(sql);
1652-
if (rc != SQLITE_OK) {
1653-
DEBUG_SQLITE_ERROR(rc, "cloudsync_finalize_alter", db);
1654-
goto finalize;
1655-
} else if (errmsg || ncols != 1) {
1656-
rc = SQLITE_MISUSE;
1657-
goto finalize;
1658-
}
1659-
*/
1660-
16611701
// check if there are differences
16621702
bool pk_diff = (nrows != table->npks);
16631703
if (!pk_diff) {
@@ -1669,20 +1709,6 @@ int cloudsync_finalize_alter (sqlite3_context *context, cloudsync_context *data,
16691709
}
16701710
}
16711711

1672-
/*
1673-
bool pk_diff = false;
1674-
if (nrows != table->npks) {
1675-
pk_diff = true;
1676-
} else {
1677-
for (int i=0; i<nrows; ++i) {
1678-
if (strcmp(table->pk_name[i], result[i]) != 0) {
1679-
pk_diff = true;
1680-
break;
1681-
}
1682-
}
1683-
}
1684-
*/
1685-
16861712
// TODO: FIX SQL
16871713
if (pk_diff) {
16881714
// drop meta-table, it will be recreated
@@ -1732,13 +1758,60 @@ int cloudsync_finalize_alter (sqlite3_context *context, cloudsync_context *data,
17321758
// update key to be later used in cloudsync_dbversion_rebuild
17331759
char buf[256];
17341760
snprintf(buf, sizeof(buf), "%lld", data->db_version);
1735-
dbutils_settings_set_key_value(db, context, "pre_alter_dbversion", buf);
1761+
dbutils_settings_set_key_value(db, NULL, "pre_alter_dbversion", buf);
17361762

17371763
finalize:
1738-
// free result
1739-
for (int i = 0; i < nrows; ++i) {dbmem_free(result[i]);}
1740-
dbmem_free(result);
1764+
table_pknames_free(result, nrows);
1765+
return rc;
1766+
}
1767+
1768+
int cloudsync_commit_alter (cloudsync_context *data, const char *table_name) {
1769+
db_t *db = data->db;
1770+
int rc = DBRES_MISUSE;
1771+
cloudsync_table_context *table = NULL;
1772+
1773+
// init cloudsync_settings
1774+
if (cloudsync_context_init(data, db, NULL) == NULL) {
1775+
cloudsync_set_error(data, "Unable to initialize cloudsync context", DBRES_MISUSE);
1776+
goto rollback_finalize_alter;
1777+
}
1778+
1779+
// lookup table
1780+
table = table_lookup(data, table_name);
1781+
if (!table) {
1782+
char buffer[1024];
1783+
snprintf(buffer, sizeof(buffer), "Unable to find table %s", table_name);
1784+
cloudsync_set_error(data, buffer, DBRES_MISUSE);
1785+
goto rollback_finalize_alter;
1786+
}
1787+
1788+
rc = cloudsync_finalize_alter(data, table);
1789+
if (rc != SQLITE_OK) goto rollback_finalize_alter;
1790+
1791+
// the table is outdated, delete it and it will be reloaded in the cloudsync_init_internal
1792+
table_remove(data, table);
1793+
table_free(table);
1794+
table = NULL;
1795+
1796+
// init again cloudsync for the table
1797+
table_algo algo_current = dbutils_table_settings_get_algo(db, table_name);
1798+
if (algo_current == table_algo_none) algo_current = dbutils_table_settings_get_algo(db, "*");
1799+
rc = cloudsync_init_table(data, table_name, crdt_algo_name(algo_current), true);
1800+
if (rc != SQLITE_OK) goto rollback_finalize_alter;
1801+
1802+
// release savepoint
1803+
rc = database_exec(db, "RELEASE cloudsync_alter;");
1804+
if (rc != SQLITE_OK) {
1805+
cloudsync_set_dberror(data);
1806+
goto rollback_finalize_alter;
1807+
}
1808+
1809+
cloudsync_update_schema_hash(data);
1810+
return DBRES_OK;
17411811

1812+
rollback_finalize_alter:
1813+
database_exec(db, "ROLLBACK TO cloudsync_alter; RELEASE cloudsync_alter;");
1814+
if (table) table_set_pknames(table, NULL);
17421815
return rc;
17431816
}
17441817

src/cloudsync.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ db_int64 cloudsync_dbversion (cloudsync_context *data);
4040
void cloudsync_update_schema_hash (cloudsync_context *data);
4141
int cloudsync_dbversion_check_uptodate (cloudsync_context *data);
4242

43+
int cloudsync_begin_alter (cloudsync_context *data, const char *table_name);
44+
int cloudsync_commit_alter (cloudsync_context *data, const char *table_name);
45+
4346
void *cloudsync_db (cloudsync_context *data);
4447
void *cloudsync_dbcontext (cloudsync_context *data);
4548
void cloudsync_set_db (cloudsync_context *data, void *value);

src/cloudsync_private.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,6 @@ typedef struct cloudsync_pk_decode_bind_context cloudsync_pk_decode_bind_context
4040
void cloudsync_sync_key (cloudsync_context *data, const char *key, const char *value);
4141

4242
// used by network layer
43-
void *cloudsync_get_auxdata (sqlite3_context *context);
44-
void cloudsync_set_auxdata (sqlite3_context *context, void *xdata);
4543
int cloudsync_payload_apply (sqlite3_context *context, const char *payload, int blen);
4644
int cloudsync_payload_get (cloudsync_context *data, char **blob, int *blob_size, int *db_version, int *seq, db_int64 *new_db_version, db_int64 *new_seq);
4745

0 commit comments

Comments
 (0)