@@ -871,12 +871,23 @@ int sqlcipher_codec_ctx_migrate(codec_ctx *ctx) {
871871 u32 meta ;
872872 int rc = 0 ;
873873 int command_idx = 0 ;
874+ int saved_flags ;
875+ int saved_nChange ;
876+ int saved_nTotalChange ;
877+ void (* saved_xTrace )(void * ,const char * );
878+ Db * pDb = 0 ;
874879 sqlite3 * db = ctx -> pBt -> db ;
875880 const char * db_filename = sqlite3_db_filename (db , "main" );
876881 const char * migrated_db_filename = sqlite3_mprintf ("%s-migrated" , db_filename );
877882 const char * key = ctx -> read_ctx -> pass ;
878- int db_idx = db -> nDb ;
879- CODEC_TRACE (("current database count:%d\n" , db_idx ));
883+ static const unsigned char aCopy [] = {
884+ BTREE_SCHEMA_VERSION , 1 , /* Add one to the old schema cookie */
885+ BTREE_DEFAULT_CACHE_SIZE , 0 , /* Preserve the default page cache size */
886+ BTREE_TEXT_ENCODING , 0 , /* Preserve the text encoding */
887+ BTREE_USER_VERSION , 0 , /* Preserve the user version */
888+ BTREE_APPLICATION_ID , 0 , /* Preserve the application id */
889+ };
890+
880891 if (db_filename ){
881892 char * attach_command = sqlite3_mprintf ("ATTACH DATABASE '%s-migrated' as migrate KEY '%s';" ,
882893 db_filename , key );
@@ -893,31 +904,39 @@ int sqlcipher_codec_ctx_migrate(codec_ctx *ctx) {
893904 }
894905 }
895906 sqlite3_free (attach_command );
907+
896908 if (rc == SQLITE_OK ){
909+ if ( !db -> autoCommit ){
910+ CODEC_TRACE (("cannot migrate from within a transaction" ));
911+ goto handle_error ;
912+ }
913+ if ( db -> activeVdbeCnt > 1 ){
914+ CODEC_TRACE (("cannot migrate - SQL statements in progress" ));
915+ goto handle_error ;
916+ }
917+
918+ /* Save the current value of the database flags so that it can be
919+ ** restored before returning. Then set the writable-schema flag, and
920+ ** disable CHECK and foreign key constraints. */
921+ saved_flags = db -> flags ;
922+ saved_nChange = db -> nChange ;
923+ saved_nTotalChange = db -> nTotalChange ;
924+ saved_xTrace = db -> xTrace ;
925+ db -> flags |= SQLITE_WriteSchema | SQLITE_IgnoreChecks | SQLITE_PreferBuiltin ;
926+ db -> flags &= ~(SQLITE_ForeignKeys | SQLITE_ReverseOrder );
927+ db -> xTrace = 0 ;
897928
898- static const unsigned char aCopy [] = {
899- BTREE_SCHEMA_VERSION , 1 , /* Add one to the old schema cookie */
900- BTREE_DEFAULT_CACHE_SIZE , 0 , /* Preserve the default page cache size */
901- BTREE_TEXT_ENCODING , 0 , /* Preserve the text encoding */
902- BTREE_USER_VERSION , 0 , /* Preserve the user version */
903- BTREE_APPLICATION_ID , 0 , /* Preserve the application id */
904- };
905-
906- CODEC_TRACE (("current database count:%d\n" , db -> nDb ));
907929 Btree * pDest = db -> aDb [0 ].pBt ;
908- Btree * pSrc = db -> aDb [db -> nDb - 1 ].pBt ;
909-
910- CODEC_TRACE (("pSrc is '%p'\n" , (void * )pSrc ));
911- CODEC_TRACE (("pDest is '%p'\n" , (void * )pDest ));
930+ pDb = & (db -> aDb [db -> nDb - 1 ]);
931+ Btree * pSrc = pDb -> pBt ;
912932
913- // rc = sqlite3_exec(db, "BEGIN;", NULL, NULL, NULL);
933+ rc = sqlite3_exec (db , "BEGIN;" , NULL , NULL , NULL );
914934 rc = sqlite3BtreeBeginTrans (pSrc , 2 );
915- rc = sqlite3BtreeBeginTrans (pDest , 2 );
935+ // rc = sqlite3BtreeBeginTrans(pDest, 2);
916936
917937 assert ( 1 == sqlite3BtreeIsInTrans (pDest ) );
918938 assert ( 1 == sqlite3BtreeIsInTrans (pSrc ) );
919939
920- CODEC_TRACE (("before metadata copy\n" ));
921940 int i = 0 ;
922941 for (i = 0 ; i < ArraySize (aCopy ); i += 2 ){
923942 sqlite3BtreeGetMeta (pSrc , aCopy [i ], & meta );
@@ -927,15 +946,28 @@ int sqlcipher_codec_ctx_migrate(codec_ctx *ctx) {
927946 rc = sqlite3BtreeCopyFile (pSrc , pDest );
928947 if ( rc != SQLITE_OK ) goto handle_error ;
929948 rc = sqlite3BtreeCommit (pDest );
930- rc = sqlite3_exec (db , "DETACH DATABASE migrate;" , NULL , NULL , NULL );
949+
950+ db -> flags = saved_flags ;
951+ db -> nChange = saved_nChange ;
952+ db -> nTotalChange = saved_nTotalChange ;
953+ db -> xTrace = saved_xTrace ;
954+ sqlite3BtreeSetPageSize (pDest , -1 , -1 , 1 );
955+ db -> autoCommit = 1 ;
956+ if ( pDb ){
957+ sqlite3BtreeClose (pDb -> pBt );
958+ pDb -> pBt = 0 ;
959+ pDb -> pSchema = 0 ;
960+ }
961+ sqlite3ResetAllSchemasOfConnection (db );
931962 remove (migrated_db_filename );
963+ sqlite3_free (migrated_db_filename );
932964 }
933- sqlite3_free (migrated_db_filename );
934965 }
935966 goto exit ;
936967
937968 handle_error :
938- CODEC_TRACE (("An error occurred\n" ));
969+ CODEC_TRACE (("an error occurred\n" ));
970+ rc = SQLITE_ERROR ;
939971
940972 exit :
941973 return rc ;
0 commit comments