@@ -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
149151struct 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
33403345rollback_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+
34003416rollback_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