@@ -12390,11 +12390,18 @@ SQLITE_ORM_EXPORT namespace sqlite_orm {
1239012390 /**
1239112391 * old table is dropped and new is recreated. Reasons :
1239212392 * 1. delete excess columns in the table than storage if preseve = false
12393- * 2. Lacking columns in the table cannot be added due to NULL and DEFAULT constraint
12394- * 3. Reasons 1 and 2 both together
12395- * 4. data_type mismatch between table and storage .
12393+ * 2. Reasons 1 and 4 both together
12394+ * 3. data_type mismatch between table and storage.
12395+ * Data is preserved through a backup table when preserve = true .
1239612396 */
1239712397 dropped_and_recreated,
12398+
12399+ /**
12400+ * old table is dropped and new is recreated with data loss.
12401+ * Data cannot be preserved because a new NOT NULL column without
12402+ * a default value is being added, making backup impossible.
12403+ */
12404+ dropped_and_recreated_with_data_loss,
1239812405 };
1239912406
1240012407 inline std::ostream& operator<<(std::ostream& os, sync_schema_result value) {
@@ -12411,6 +12418,8 @@ SQLITE_ORM_EXPORT namespace sqlite_orm {
1241112418 return os << "old excess columns removed and new columns added";
1241212419 case sync_schema_result::dropped_and_recreated:
1241312420 return os << "old table dropped and recreated";
12421+ case sync_schema_result::dropped_and_recreated_with_data_loss:
12422+ return os << "old table dropped and recreated with data loss";
1241412423 }
1241512424 return os;
1241612425 }
@@ -19784,11 +19793,11 @@ namespace sqlite_orm::internal {
1978419793 (dbColumnInfo.hidden == 0) == (storageColumnInfo.hidden == 0);
1978519794 if (!columnsAreEqual) {
1978619795 notEqual = true;
19787- break;
19796+ } else {
19797+ dbTableInfo.erase(dbColumnInfoIt);
19798+ storageTableInfo.erase(storageTableInfo.begin() + storageColumnInfoIndex);
19799+ --storageColumnInfoIndex;
1978819800 }
19789- dbTableInfo.erase(dbColumnInfoIt);
19790- storageTableInfo.erase(storageTableInfo.begin() + storageColumnInfoIndex);
19791- --storageColumnInfoIndex;
1979219801 } else {
1979319802 columnsToAdd.push_back(&storageColumnInfo);
1979419803 }
@@ -25037,6 +25046,7 @@ namespace sqlite_orm::internal {
2503725046
2503825047 auto dbTableInfo = this->pragma.table_xinfo(table.name);
2503925048 auto res = sync_schema_result::already_in_sync;
25049+ bool canPreserveData = true;
2504025050
2504125051 // first let's see if table with such name exists..
2504225052 auto gottaCreateTable = !this->table_exists(db, table.name);
@@ -25068,7 +25078,20 @@ namespace sqlite_orm::internal {
2506825078 }
2506925079 }
2507025080 if (gottaCreateTable) {
25071- res = sync_schema_result::dropped_and_recreated;
25081+ // check if any new columns prevent data preservation
25082+ for (const table_xinfo* colInfo: columnsToAdd) {
25083+ if (!table.find_column_generated_storage_type(colInfo->name)) {
25084+ if (colInfo->notnull && colInfo->dflt_value.empty()) {
25085+ canPreserveData = false;
25086+ if (attempt_to_preserve) {
25087+ *attempt_to_preserve = false;
25088+ };
25089+ break;
25090+ }
25091+ }
25092+ }
25093+ res = canPreserveData ? sync_schema_result::dropped_and_recreated
25094+ : sync_schema_result::dropped_and_recreated_with_data_loss;
2507225095 } else {
2507325096 if (!columnsToAdd.empty()) {
2507425097 // extra storage columns than table columns
@@ -25084,6 +25107,7 @@ namespace sqlite_orm::internal {
2508425107 } else {
2508525108 if (colInfo->notnull && colInfo->dflt_value.empty()) {
2508625109 gottaCreateTable = true;
25110+ canPreserveData = false;
2508725111 // no matter if preserve is true or false, there is no way to preserve data, so we wont try!
2508825112 if (attempt_to_preserve) {
2508925113 *attempt_to_preserve = false;
@@ -25099,7 +25123,8 @@ namespace sqlite_orm::internal {
2509925123 res = sync_schema_result::new_columns_added;
2510025124 }
2510125125 } else {
25102- res = sync_schema_result::dropped_and_recreated;
25126+ res = canPreserveData ? sync_schema_result::dropped_and_recreated
25127+ : sync_schema_result::dropped_and_recreated_with_data_loss;
2510325128 }
2510425129 } else {
2510525130 if (res != sync_schema_result::old_columns_removed) {
@@ -26035,6 +26060,9 @@ namespace sqlite_orm::internal {
2603526060 this->drop_create_with_loss(db, table);
2603626061 }
2603726062 res = schema_stat;
26063+ } else if (schema_stat == sync_schema_result::dropped_and_recreated_with_data_loss) {
26064+ this->drop_create_with_loss(db, table);
26065+ res = schema_stat;
2603826066 }
2603926067 }
2604026068 }
0 commit comments