Skip to content

Commit b7215b9

Browse files
committed
fix(cloudsync): make begin_alter and commit_alter idempotent
Add is_altering flag to cloudsync_table_context to prevent duplicate calls from creating nested savepoints or triggering errors on missing pk_name. The flag is set in begin_alter and cleared on commit or rollback.
1 parent 5217d71 commit b7215b9

File tree

1 file changed

+30
-13
lines changed

1 file changed

+30
-13
lines changed

src/cloudsync.c

Lines changed: 30 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,9 @@ typedef struct {
143143
sqlite3_stmt *real_col_values_stmt; // retrieve all column values based on pk
144144
sqlite3_stmt *real_merge_delete_stmt;
145145
sqlite3_stmt *real_merge_sentinel_stmt;
146-
146+
147+
bool is_altering;
148+
147149
} cloudsync_table_context;
148150

149151
struct cloudsync_pk_decode_bind_context {
@@ -3300,21 +3302,23 @@ void cloudsync_begin_alter (sqlite3_context *context, int argc, sqlite3_value **
33003302
return;
33013303
}
33023304

3305+
cloudsync_table_context *table = table_lookup(data, table_name);
3306+
if (!table) {
3307+
dbutils_context_result_error(context, "Unable to find table %s", table_name);
3308+
sqlite3_result_error_code(context, SQLITE_MISUSE);
3309+
return;
3310+
}
3311+
3312+
if (table->is_altering) return;
3313+
33033314
// create a savepoint to manage the alter operations as a transaction
33043315
int rc = sqlite3_exec(db, "SAVEPOINT cloudsync_alter", NULL, NULL, NULL);
33053316
if (rc != SQLITE_OK) {
33063317
sqlite3_result_error(context, "Unable to create cloudsync_alter savepoint.", -1);
33073318
sqlite3_result_error_code(context, rc);
33083319
goto rollback_begin_alter;
33093320
}
3310-
3311-
cloudsync_table_context *table = table_lookup(data, table_name);
3312-
if (!table) {
3313-
dbutils_context_result_error(context, "Unable to find table %s", table_name);
3314-
sqlite3_result_error_code(context, SQLITE_MISUSE);
3315-
goto rollback_begin_alter;
3316-
}
3317-
3321+
33183322
int nrows, ncols;
33193323
char *sql = cloudsync_memory_mprintf("SELECT name FROM pragma_table_info('%q') WHERE pk>0 ORDER BY pk;", table_name);
33203324
rc = sqlite3_get_table(db, sql, &result, &nrows, &ncols, &errmsg);
@@ -3335,6 +3339,7 @@ void cloudsync_begin_alter (sqlite3_context *context, int argc, sqlite3_value **
33353339

33363340
if (table->pk_name) sqlite3_free_table(table->pk_name);
33373341
table->pk_name = result;
3342+
table->is_altering = true;
33383343
return;
33393344

33403345
rollback_begin_alter:
@@ -3365,12 +3370,20 @@ void cloudsync_commit_alter (sqlite3_context *context, int argc, sqlite3_value *
33653370
}
33663371

33673372
table = table_lookup(data, table_name);
3368-
if (!table || !table->pk_name) {
3373+
if (!table) {
33693374
dbutils_context_result_error(context, "Unable to find table context.");
33703375
sqlite3_result_error_code(context, SQLITE_MISUSE);
33713376
goto rollback_finalize_alter;
33723377
}
3373-
3378+
3379+
if (!table->is_altering) return;
3380+
3381+
if (!table->pk_name) {
3382+
dbutils_context_result_error(context, "Unable to find table context.");
3383+
sqlite3_result_error_code(context, SQLITE_MISUSE);
3384+
goto rollback_finalize_alter;
3385+
}
3386+
33743387
int rc = cloudsync_finalize_alter(context, data, table);
33753388
if (rc != SQLITE_OK) goto rollback_finalize_alter;
33763389

@@ -3394,14 +3407,18 @@ void cloudsync_commit_alter (sqlite3_context *context, int argc, sqlite3_value *
33943407
}
33953408

33963409
dbutils_update_schema_hash(db, &data->schema_hash);
3397-
3410+
3411+
// flag is reset here; note that table_remove + table_free destroyed the old table,
3412+
// and cloudsync_init_internal created a fresh one with is_altering = false (zero-alloc).
3413+
33983414
return;
3399-
3415+
34003416
rollback_finalize_alter:
34013417
sqlite3_exec(db, "ROLLBACK TO cloudsync_alter; RELEASE cloudsync_alter;", NULL, NULL, NULL);
34023418
if (table) {
34033419
sqlite3_free_table(table->pk_name);
34043420
table->pk_name = NULL;
3421+
table->is_altering = false;
34053422
}
34063423
}
34073424

0 commit comments

Comments
 (0)