/* ** This routine is called to create a connection to a database BTree ** driver. If zFilename is the name of a file, then that file is ** opened and used. If zFilename is the magic name ":memory:" then ** the database is stored in memory (and is thus forgotten as soon as ** the connection is closed.) If zFilename is NULL then the database ** is a "virtual" database for transient use only and is deleted as ** soon as the connection is closed. ** ** A virtual database can be either a disk file (that is automatically ** deleted when the file is closed) or it an be held entirely in memory, ** depending on the values of the TEMP_STORE compile-time macro and the ** db->temp_store variable, according to the following chart: ** ** TEMP_STORE db->temp_store Location of temporary database ** ---------- -------------- ------------------------------ ** 0 any file ** 1 1 file ** 1 2 memory ** 1 0 file ** 2 1 file ** 2 2 memory ** 2 0 memory ** 3 any memory */ int sqlite3BtreeFactory( const sqlite3 *db, /* Main database when opening aux otherwise 0 */ const char *zFilename, /* Name of the file containing the BTree database */ int omitJournal, /* if TRUE then do not journal this file */ int nCache, /* How many pages in the page cache */ int vfsFlags, /* Flags passed through to vfsOpen */ Btree **ppBtree /* Pointer to new Btree object written here */ ){ int btFlags = 0; int rc; assert( sqlite3_mutex_held(db->mutex) ); assert( ppBtree != 0); if( omitJournal ){ btFlags |= BTREE_OMIT_JOURNAL; } if( db->flags & SQLITE_NoReadlock ){ btFlags |= BTREE_NO_READLOCK; } if( zFilename==0 ){ #if TEMP_STORE==0 /* Do nothing */ #endif #ifndef SQLITE_OMIT_MEMORYDB #if TEMP_STORE==1 if( db->temp_store==2 ) zFilename = ":memory:"; #endif #if TEMP_STORE==2 if( db->temp_store!=1 ) zFilename = ":memory:"; #endif #if TEMP_STORE==3 zFilename = ":memory:"; #endif #endif /* SQLITE_OMIT_MEMORYDB */ } if( (vfsFlags & SQLITE_OPEN_MAIN_DB)!=0 && (zFilename==0 || *zFilename==0) ){ vfsFlags = (vfsFlags & ~SQLITE_OPEN_MAIN_DB) | SQLITE_OPEN_TEMP_DB; } rc = sqlite3BtreeOpen(zFilename, (sqlite3 *)db, ppBtree, btFlags, vfsFlags); if( rc==SQLITE_OK ){ sqlite3BtreeSetCacheSize(*ppBtree, nCache); } return rc; }
/* ** This routine is called to create a connection to a database BTree ** driver. If zFilename is the name of a file, then that file is ** opened and used. If zFilename is the magic name ":memory:" then ** the database is stored in memory (and is thus forgotten as soon as ** the connection is closed.) If zFilename is NULL then the database ** is a "virtual" database for transient use only and is deleted as ** soon as the connection is closed. ** ** A virtual database can be either a disk file (that is automatically ** deleted when the file is closed) or it an be held entirely in memory, ** depending on the values of the TEMP_STORE compile-time macro and the ** db->temp_store variable, according to the following chart: ** ** TEMP_STORE db->temp_store Location of temporary database ** ---------- -------------- ------------------------------ ** 0 any file ** 1 1 file ** 1 2 memory ** 1 0 file ** 2 1 file ** 2 2 memory ** 2 0 memory ** 3 any memory */ int sqlite3BtreeFactory( const sqlite3 *db, /* Main database when opening aux otherwise 0 */ const char *zFilename, /* Name of the file containing the BTree database */ int omitJournal, /* if TRUE then do not journal this file */ int nCache, /* How many pages in the page cache */ Btree **ppBtree /* Pointer to new Btree object written here */ ){ int btree_flags = 0; int rc; assert( ppBtree != 0); if( omitJournal ){ btree_flags |= BTREE_OMIT_JOURNAL; } if( db->flags & SQLITE_NoReadlock ){ btree_flags |= BTREE_NO_READLOCK; } if( zFilename==0 ){ #if TEMP_STORE==0 /* Do nothing */ #endif #ifndef SQLITE_OMIT_MEMORYDB #if TEMP_STORE==1 if( db->temp_store==2 ) zFilename = ":memory:"; #endif #if TEMP_STORE==2 if( db->temp_store!=1 ) zFilename = ":memory:"; #endif #if TEMP_STORE==3 zFilename = ":memory:"; #endif #endif /* SQLITE_OMIT_MEMORYDB */ } rc = sqlite3BtreeOpen(zFilename, (sqlite3 *)db, ppBtree, btree_flags); if( rc==SQLITE_OK ){ sqlite3BtreeSetBusyHandler(*ppBtree, (void*)&db->busyHandler); sqlite3BtreeThreadLockHandlers(*ppBtree, (void*)&db->lockEventHandlers); sqlite3BtreeSetCacheSize(*ppBtree, nCache); } return rc; }
/* ** Usage: btree_open FILENAME NCACHE ** ** Open a new database */ static int btree_open( void *NotUsed, Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ int argc, /* Number of arguments */ const char **argv /* Text of each argument */ ){ Btree *pBt; int rc, nCache; char zBuf[100]; int n; char *zFilename; if( argc!=3 ){ Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " FILENAME NCACHE FLAGS\"", 0); return TCL_ERROR; } if( Tcl_GetInt(interp, argv[2], &nCache) ) return TCL_ERROR; nRefSqlite3++; if( nRefSqlite3==1 ){ sDb.pVfs = sqlite3_vfs_find(0); sDb.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_RECURSIVE); sqlite3_mutex_enter(sDb.mutex); } n = (int)strlen(argv[1]); zFilename = sqlite3_malloc( n+2 ); if( zFilename==0 ) return TCL_ERROR; memcpy(zFilename, argv[1], n+1); zFilename[n+1] = 0; rc = sqlite3BtreeOpen(sDb.pVfs, zFilename, &sDb, &pBt, 0, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_MAIN_DB); sqlite3_free(zFilename); if( rc!=SQLITE_OK ){ Tcl_AppendResult(interp, sqlite3ErrName(rc), 0); return TCL_ERROR; } sqlite3BtreeSetCacheSize(pBt, nCache); sqlite3_snprintf(sizeof(zBuf), zBuf,"%p", pBt); Tcl_AppendResult(interp, zBuf, 0); return TCL_OK; }
/* ** An SQL user-function registered to do the work of an ATTACH statement. The ** three arguments to the function come directly from an attach statement: ** ** ATTACH DATABASE x AS y KEY z ** ** SELECT sqlite_attach(x, y, z) ** ** If the optional "KEY z" syntax is omitted, an SQL NULL is passed as the ** third argument. */ static void attachFunc( sqlite3_context *context, int NotUsed, sqlite3_value **argv ){ int i; int rc = 0; sqlite3 *db = sqlite3_context_db_handle(context); const char *zName; const char *zFile; char *zPath = 0; char *zErr = 0; unsigned int flags; Db *aNew; char *zErrDyn = 0; sqlite3_vfs *pVfs; UNUSED_PARAMETER(NotUsed); zFile = (const char *)sqlite3_value_text(argv[0]); zName = (const char *)sqlite3_value_text(argv[1]); if( zFile==0 ) zFile = ""; if( zName==0 ) zName = ""; /* Check for the following errors: ** ** * Too many attached databases, ** * Transaction currently open ** * Specified database name already being used. */ if( db->nDb>=db->aLimit[SQLITE_LIMIT_ATTACHED]+2 ){ zErrDyn = sqlite3MPrintf(db, "too many attached databases - max %d", db->aLimit[SQLITE_LIMIT_ATTACHED] ); goto attach_error; } if( !db->autoCommit ){ zErrDyn = sqlite3MPrintf(db, "cannot ATTACH database within transaction"); goto attach_error; } for(i=0; i<db->nDb; i++){ char *z = db->aDb[i].zName; assert( z && zName ); if( sqlite3StrICmp(z, zName)==0 ){ zErrDyn = sqlite3MPrintf(db, "database %s is already in use", zName); goto attach_error; } } /* Allocate the new entry in the db->aDb[] array and initialize the schema ** hash tables. */ if( db->aDb==db->aDbStatic ){ aNew = sqlite3DbMallocRaw(db, sizeof(db->aDb[0])*3 ); if( aNew==0 ) return; memcpy(aNew, db->aDb, sizeof(db->aDb[0])*2); }else{ aNew = sqlite3DbRealloc(db, db->aDb, sizeof(db->aDb[0])*(db->nDb+1) ); if( aNew==0 ) return; } db->aDb = aNew; aNew = &db->aDb[db->nDb]; memset(aNew, 0, sizeof(*aNew)); /* Open the database file. If the btree is successfully opened, use ** it to obtain the database schema. At this point the schema may ** or may not be initialized. */ flags = db->openFlags; rc = sqlite3ParseUri(db->pVfs->zName, zFile, &flags, &pVfs, &zPath, &zErr); if( rc!=SQLITE_OK ){ if( rc==SQLITE_NOMEM ) db->mallocFailed = 1; sqlite3_result_error(context, zErr, -1); sqlite3_free(zErr); return; } assert( pVfs ); flags |= SQLITE_OPEN_MAIN_DB; rc = sqlite3BtreeOpen(pVfs, zPath, db, &aNew->pBt, 0, flags); sqlite3_free( zPath ); db->nDb++; if( rc==SQLITE_CONSTRAINT ){ rc = SQLITE_ERROR; zErrDyn = sqlite3MPrintf(db, "database is already attached"); }else if( rc==SQLITE_OK ){ Pager *pPager; aNew->pSchema = sqlite3SchemaGet(db, aNew->pBt); if( !aNew->pSchema ){ rc = SQLITE_NOMEM; }else if( aNew->pSchema->file_format && aNew->pSchema->enc!=ENC(db) ){ zErrDyn = sqlite3MPrintf(db, "attached databases must use the same text encoding as main database"); rc = SQLITE_ERROR; } sqlite3BtreeEnter(aNew->pBt); pPager = sqlite3BtreePager(aNew->pBt); sqlite3PagerLockingMode(pPager, db->dfltLockMode); sqlite3BtreeSecureDelete(aNew->pBt, sqlite3BtreeSecureDelete(db->aDb[0].pBt,-1) ); #ifndef SQLITE_OMIT_PAGER_PRAGMAS sqlite3BtreeSetPagerFlags(aNew->pBt, 3 | (db->flags & PAGER_FLAGS_MASK)); #endif sqlite3BtreeLeave(aNew->pBt); } aNew->safety_level = 3; aNew->zName = sqlite3DbStrDup(db, zName); if( rc==SQLITE_OK && aNew->zName==0 ){ rc = SQLITE_NOMEM; } #ifdef SQLITE_HAS_CODEC if( rc==SQLITE_OK ){ extern int sqlite3CodecAttach(sqlite3*, int, const void*, int); extern void sqlite3CodecGetKey(sqlite3*, int, void**, int*); int nKey; char *zKey; int t = sqlite3_value_type(argv[2]); switch( t ){ case SQLITE_INTEGER: case SQLITE_FLOAT: zErrDyn = sqlite3DbStrDup(db, "Invalid key value"); rc = SQLITE_ERROR; break; case SQLITE_TEXT: case SQLITE_BLOB: nKey = sqlite3_value_bytes(argv[2]); zKey = (char *)sqlite3_value_blob(argv[2]); rc = sqlite3CodecAttach(db, db->nDb-1, zKey, nKey); break; case SQLITE_NULL: /* No key specified. Use the key from the main database */ sqlite3CodecGetKey(db, 0, (void**)&zKey, &nKey); if( nKey>0 || sqlite3BtreeGetOptimalReserve(db->aDb[0].pBt)>0 ){ rc = sqlite3CodecAttach(db, db->nDb-1, zKey, nKey); } break; } } #endif /* If the file was opened successfully, read the schema for the new database. ** If this fails, or if opening the file failed, then close the file and ** remove the entry from the db->aDb[] array. i.e. put everything back the way ** we found it. */ if( rc==SQLITE_OK ){ sqlite3BtreeEnterAll(db); rc = sqlite3Init(db, &zErrDyn); sqlite3BtreeLeaveAll(db); } #ifdef SQLITE_USER_AUTHENTICATION if( rc==SQLITE_OK ){ u8 newAuth = 0; rc = sqlite3UserAuthCheckLogin(db, zName, &newAuth); if( newAuth<db->auth.authLevel ){ rc = SQLITE_AUTH_USER; } } #endif if( rc ){ int iDb = db->nDb - 1; assert( iDb>=2 ); if( db->aDb[iDb].pBt ){ sqlite3BtreeClose(db->aDb[iDb].pBt); db->aDb[iDb].pBt = 0; db->aDb[iDb].pSchema = 0; } sqlite3ResetAllSchemasOfConnection(db); db->nDb = iDb; if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){ db->mallocFailed = 1; sqlite3DbFree(db, zErrDyn); zErrDyn = sqlite3MPrintf(db, "out of memory"); }else if( zErrDyn==0 ){ zErrDyn = sqlite3MPrintf(db, "unable to open database: %s", zFile); } goto attach_error; } return; attach_error: /* Return an error if we get here */ if( zErrDyn ){ sqlite3_result_error(context, zErrDyn, -1); sqlite3DbFree(db, zErrDyn); } if( rc ) sqlite3_result_error_code(context, rc); }
static void attachFunc( sqlite3_context *context, int NotUsed, sqlite3_value **argv ){ int i; int rc = 0; sqlite3 *db = sqlite3_context_db_handle(context); const char *zName; const char *zFile; Db *aNew; char *zErrDyn = 0; UNUSED_PARAMETER(NotUsed); zFile = (const char *)sqlite3_value_text(argv[0]); zName = (const char *)sqlite3_value_text(argv[1]); if( zFile==0 ) zFile = ""; if( zName==0 ) zName = ""; if( db->nDb>=db->aLimit[SQLITE_LIMIT_ATTACHED]+2 ){ zErrDyn = sqlite3MPrintf(db, "too many attached databases - max %d", db->aLimit[SQLITE_LIMIT_ATTACHED] ); goto attach_error; } if( !db->autoCommit ){ zErrDyn = sqlite3MPrintf(db, "cannot ATTACH database within transaction"); goto attach_error; } for(i=0; i<db->nDb; i++){ char *z = db->aDb[i].zName; assert( z && zName ); if( sqlite3StrICmp(z, zName)==0 ){ zErrDyn = sqlite3MPrintf(db, "database %s is already in use", zName); goto attach_error; } } if( db->aDb==db->aDbStatic ){ aNew = sqlite3DbMallocRaw(db, sizeof(db->aDb[0])*3 ); if( aNew==0 ) return; memcpy(aNew, db->aDb, sizeof(db->aDb[0])*2); }else{ aNew = sqlite3DbRealloc(db, db->aDb, sizeof(db->aDb[0])*(db->nDb+1) ); if( aNew==0 ) return; } db->aDb = aNew; aNew = &db->aDb[db->nDb]; memset(aNew, 0, sizeof(*aNew)); rc = sqlite3BtreeOpen(zFile, db, &aNew->pBt, 0, db->openFlags | SQLITE_OPEN_MAIN_DB); db->nDb++; if( rc==SQLITE_CONSTRAINT ){ rc = SQLITE_ERROR; zErrDyn = sqlite3MPrintf(db, "database is already attached"); }else if( rc==SQLITE_OK ){ Pager *pPager; aNew->pSchema = sqlite3SchemaGet(db, aNew->pBt); if( !aNew->pSchema ){ rc = SQLITE_NOMEM; }else if( aNew->pSchema->file_format && aNew->pSchema->enc!=ENC(db) ){ zErrDyn = sqlite3MPrintf(db, "attached databases must use the same text encoding as main database"); rc = SQLITE_ERROR; } pPager = sqlite3BtreePager(aNew->pBt); sqlite3PagerLockingMode(pPager, db->dfltLockMode); sqlite3BtreeSecureDelete(aNew->pBt, sqlite3BtreeSecureDelete(db->aDb[0].pBt,-1) ); } aNew->safety_level = 3; aNew->zName = sqlite3DbStrDup(db, zName); if( rc==SQLITE_OK && aNew->zName==0 ){ rc = SQLITE_NOMEM; } #ifdef SQLITE_HAS_CODEC if( rc==SQLITE_OK ){ extern int sqlite3CodecAttach(sqlite3*, int, const void*, int); extern void sqlite3CodecGetKey(sqlite3*, int, void**, int*); int nKey; char *zKey; int t = sqlite3_value_type(argv[2]); switch( t ){ case SQLITE_INTEGER: case SQLITE_FLOAT: zErrDyn = sqlite3DbStrDup(db, "Invalid key value"); rc = SQLITE_ERROR; break; case SQLITE_TEXT: case SQLITE_BLOB: nKey = sqlite3_value_bytes(argv[2]); zKey = (char *)sqlite3_value_blob(argv[2]); rc = sqlite3CodecAttach(db, db->nDb-1, zKey, nKey); break; case SQLITE_NULL: sqlite3CodecGetKey(db, 0, (void**)&zKey, &nKey); if( nKey>0 || sqlite3BtreeGetReserve(db->aDb[0].pBt)>0 ){ rc = sqlite3CodecAttach(db, db->nDb-1, zKey, nKey); } break; } } #endif if( rc==SQLITE_OK ){ sqlite3BtreeEnterAll(db); rc = sqlite3Init(db, &zErrDyn); sqlite3BtreeLeaveAll(db); } if( rc ){ int iDb = db->nDb - 1; assert( iDb>=2 ); if( db->aDb[iDb].pBt ){ sqlite3BtreeClose(db->aDb[iDb].pBt); db->aDb[iDb].pBt = 0; db->aDb[iDb].pSchema = 0; } sqlite3ResetInternalSchema(db, -1); db->nDb = iDb; if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){ db->mallocFailed = 1; sqlite3DbFree(db, zErrDyn); zErrDyn = sqlite3MPrintf(db, "out of memory"); }else if( zErrDyn==0 ){ zErrDyn = sqlite3MPrintf(db, "unable to open database: %s", zFile); } goto attach_error; } return; attach_error: if( zErrDyn ){ sqlite3_result_error(context, zErrDyn, -1); sqlite3DbFree(db, zErrDyn); } if( rc ) sqlite3_result_error_code(context, rc); }
/* ** Copy nPage pages from the source b-tree to the destination. */ int sqlite3_backup_step(sqlite3_backup *p, int nPage) { int returnCode, pages; Parse parse; DB_ENV *dbenv; BtShared *pBtDest, *pBtSrc; pBtDest = pBtSrc = NULL; if (p->rc != SQLITE_OK || nPage == 0) return p->rc; sqlite3_mutex_enter(p->pSrcDb->mutex); sqlite3_mutex_enter(p->pDestDb->mutex); /* * Make sure the schema has been read in, so the keyInfo * can be retrieved for the indexes. No-op if already read. * If the schema has not been read then an update must have * changed it, so backup will restart. */ memset(&parse, 0, sizeof(parse)); parse.db = p->pSrcDb; p->rc = sqlite3ReadSchema(&parse); if (p->rc != SQLITE_OK) goto err; /* * This process updated the source database, so * the backup process has to restart. */ if (p->pSrc->updateDuringBackup > p->lastUpdate) { p->rc = SQLITE_LOCKED; if ((p->rc = backupCleanup(p)) != SQLITE_OK) goto err; else backupReset(p); } pages = nPage; if (!p->cleaned) { const char *home; const char inmem[9] = ":memory:"; int storage; pBtDest = p->pDest->pBt; storage = p->pDest->pBt->dbStorage; if (storage == DB_STORE_NAMED) p->openDest = 1; p->rc = btreeDeleteEnvironment(p->pDest, p->fullName, 1); if (storage == DB_STORE_INMEM && strcmp(p->destName, "temp") != 0) home = inmem; else home = p->fullName; p->pDest = p->pDestDb->aDb[p->iDb].pBt; if (p->rc != SQLITE_OK) goto err; /* * Call sqlite3OpenTempDatabase instead of * sqlite3BtreeOpen, because sqlite3OpenTempDatabase * automatically chooses the right flags before calling * sqlite3BtreeOpen. */ if (strcmp(p->destName, "temp") == 0) { memset(&parse, 0, sizeof(parse)); parse.db = p->pDestDb; p->rc = sqlite3OpenTempDatabase(&parse); p->pDest = p->pDestDb->aDb[p->iDb].pBt; } else { p->rc = sqlite3BtreeOpen(home, p->pDestDb, &p->pDest, SQLITE_DEFAULT_CACHE_SIZE | SQLITE_OPEN_MAIN_DB, p->pDestDb->openFlags); p->pDestDb->aDb[p->iDb].pBt = p->pDest; if (p->rc == SQLITE_OK) { p->pDestDb->aDb[p->iDb].pSchema = sqlite3SchemaGet(p->pDestDb, p->pDest); if (!p->pDestDb->aDb[p->iDb].pSchema) p->rc = SQLITE_NOMEM; } else p->pDestDb->aDb[p->iDb].pSchema = NULL; } if (p->pDest) p->pDest->nBackup++; #ifdef SQLITE_HAS_CODEC /* * In the case of a temporary source database, use the * encryption of the main database. */ if (strcmp(p->srcName, "temp") == 0) { int iDb = sqlite3FindDbName(p->pSrcDb, "main"); pBtSrc = p->pSrcDb->aDb[iDb].pBt->pBt; } else pBtSrc = p->pSrc->pBt; if (p->rc == SQLITE_OK) { if (p->iDb == 0) p->rc = sqlite3_key(p->pDestDb, pBtSrc->encrypt_pwd, pBtSrc->encrypt_pwd_len); else p->rc = sqlite3CodecAttach(p->pDestDb, p->iDb, pBtSrc->encrypt_pwd, pBtSrc->encrypt_pwd_len); } #endif if (p->rc != SQLITE_OK) goto err; p->cleaned = 1; } /* * Begin a transaction, unfortuantely the lock on * the schema has to be released to allow the sqlite_master * table to be cleared, which could allow another thread to * alter it, however accessing the backup database during * backup is already an illegal condition with undefined * results. */ if (!sqlite3BtreeIsInTrans(p->pDest)) { if (!p->pDest->connected) { p->rc = btreeOpenEnvironment(p->pDest, 1); if (p->rc != SQLITE_OK) goto err; } if ((p->rc = sqlite3BtreeBeginTrans(p->pDest, 2)) != SQLITE_OK) goto err; } /* Only this process should be accessing the backup environment. */ if (p->pDest->pBt->nRef > 1) { p->rc = SQLITE_BUSY; goto err; } /* * Begin a transaction, a lock error or update could have caused * it to be released in a previous call to step. */ if (!p->srcTxn) { dbenv = p->pSrc->pBt->dbenv; if ((p->rc = dberr2sqlite(dbenv->txn_begin(dbenv, p->pSrc->family_txn, &p->srcTxn, 0))) != SQLITE_OK) goto err; } /* * An update could have dropped or created a table, so recalculate * the list of tables. */ if (!p->tables) { if ((p->rc = btreeGetPageCount(p->pSrc, &p->tables, &p->nPagecount, p->srcTxn)) != SQLITE_OK) { sqlite3Error(p->pSrcDb, p->rc, 0); goto err; } p->nRemaining = p->nPagecount; } /* Copy the pages. */ p->rc = btreeCopyPages(p, &pages); if (p->rc == SQLITE_DONE) { p->nRemaining = 0; sqlite3ResetInternalSchema(p->pDestDb, p->iDb); memset(&parse, 0, sizeof(parse)); parse.db = p->pDestDb; p->rc = sqlite3ReadSchema(&parse); if (p->rc == SQLITE_OK) p->rc = SQLITE_DONE; } else if (p->rc != SQLITE_OK) goto err; /* * The number of pages left to copy is an estimate, so * do not let the number go to zero unless we are really * done. */ if (p->rc != SQLITE_DONE) { if ((u32)pages >= p->nRemaining) p->nRemaining = 1; else p->nRemaining -= pages; } err: /* * This process updated the source database, so * the backup process has to restart. */ if (p->pSrc->updateDuringBackup > p->lastUpdate && (p->rc == SQLITE_OK || p->rc == SQLITE_DONE)) { int cleanCode; returnCode = p->rc; p->rc = SQLITE_LOCKED; if ((cleanCode = backupCleanup(p)) != SQLITE_OK) returnCode = p->rc = cleanCode; else backupReset(p); } else { returnCode = backupCleanup(p); if (returnCode == SQLITE_OK || (p->rc != SQLITE_OK && p->rc != SQLITE_DONE)) returnCode = p->rc; else p->rc = returnCode; } /* * On a locked or busy error the backup process is rolled back, * but can be restarted by the user. */ if ( returnCode == SQLITE_LOCKED || returnCode == SQLITE_BUSY ) backupReset(p); else if ( returnCode != SQLITE_OK && returnCode != SQLITE_DONE ) { sqlite3Error(p->pDestDb, p->rc, 0); } sqlite3_mutex_leave(p->pDestDb->mutex); sqlite3_mutex_leave(p->pSrcDb->mutex); return (returnCode); }
/* Close or free all handles and commit or rollback the transaction. */ static int backupCleanup(sqlite3_backup *p) { int rc, rc2, ret; void *app; DB *db; rc = rc2 = SQLITE_OK; if (!p || p->rc == SQLITE_OK) return rc; rc2 = sqlite3BtreeCloseCursor(&p->destCur); if (rc2 != SQLITE_OK) rc = rc2; if (p->srcCur) { db = p->srcCur->dbp; app = db->app_private; if ((ret = p->srcCur->close(p->srcCur)) == 0) ret = db->close(db, DB_NOSYNC); rc2 = dberr2sqlite(ret); /* * The KeyInfo was allocated in btreeSetupIndex, * so have to deallocate it here. */ if (app) sqlite3DbFree(p->pSrcDb, app); } if (rc2 != SQLITE_OK) rc = rc2; p->srcCur = 0; /* * May retry on a locked or busy error, so keep * these values. */ if (p->rc != SQLITE_LOCKED && p->rc != SQLITE_BUSY) { if (p->srcName) sqlite3_free(p->srcName); if (p->destName != 0) sqlite3_free(p->destName); p->srcName = p->destName = NULL; } if (p->tables != 0) sqlite3_free(p->tables); p->tables = NULL; if (p->pSrc->nBackup) p->pSrc->nBackup--; if (p->pDest != NULL && p->pDest->nBackup) p->pDest->nBackup--; if (p->srcTxn) { if (p->rc == SQLITE_DONE) ret = p->srcTxn->commit(p->srcTxn, 0); else ret = p->srcTxn->abort(p->srcTxn); rc2 = dberr2sqlite(ret); } p->srcTxn = 0; if (rc2 != SQLITE_OK && sqlite3BtreeIsInTrans(p->pDest)) { rc = rc2; if (p->rc == SQLITE_DONE) rc2 = sqlite3BtreeCommit(p->pDest); else rc2 = sqlite3BtreeRollback(p->pDest); if (rc2 != SQLITE_OK) rc = rc2; } if (p->pDest && p->openDest) { char path[512]; /* * If successfully done then delete the old backup, if * an error then delete the current database and restore * the old backup. */ sqlite3_snprintf(sizeof(path), path, "%s%s", p->fullName, BACKUP_SUFFIX); if (p->rc == SQLITE_DONE) { rc2 = btreeDeleteEnvironment(p->pDest, path, 0); } else { rc2 = btreeDeleteEnvironment(p->pDest, p->fullName, 0); if (!__os_exists(NULL, path, 0)) __os_rename(NULL, path, p->fullName, 0); } if (rc == SQLITE_OK) rc = rc2; if (rc == SQLITE_OK) { p->pDest = NULL; p->pDestDb->aDb[p->iDb].pBt = NULL; p->openDest = 0; rc = sqlite3BtreeOpen(p->fullName, p->pDestDb, &p->pDest, SQLITE_DEFAULT_CACHE_SIZE | SQLITE_OPEN_MAIN_DB, p->pDestDb->openFlags); p->pDestDb->aDb[p->iDb].pBt = p->pDest; if (rc == SQLITE_OK) { p->pDestDb->aDb[p->iDb].pSchema = sqlite3SchemaGet(p->pDestDb, p->pDest); if (!p->pDestDb->aDb[p->iDb].pSchema) p->rc = SQLITE_NOMEM; } else p->pDestDb->aDb[p->iDb].pSchema = NULL; if (rc == SQLITE_OK) p->pDest->pBt->db_oflags |= DB_CREATE; /* * Have to delete the schema here on error to avoid * assert failure. */ if (p->pDest == NULL && p->pDestDb->aDb[p->iDb].pSchema != NULL) { sqlite3SchemaClear( p->pDestDb->aDb[p->iDb].pSchema); p->pDestDb->aDb[p->iDb].pSchema = NULL; } #ifdef SQLITE_HAS_CODEC if (rc == SQLITE_OK) { if (p->iDb == 0) rc = sqlite3_key(p->pDestDb, p->pSrc->pBt->encrypt_pwd, p->pSrc->pBt->encrypt_pwd_len); else rc = sqlite3CodecAttach(p->pDestDb, p->iDb, p->pSrc->pBt->encrypt_pwd, p->pSrc->pBt->encrypt_pwd_len); } #endif } } if (p->rc != SQLITE_LOCKED && p->rc != SQLITE_BUSY) { if (p->fullName != 0) sqlite3_free(p->fullName); p->fullName = NULL; } p->lastUpdate = p->pSrc->updateDuringBackup; return rc; }
static int openDatabase( const char *zFilename, /* Database filename UTF-8 encoded */ sqlite3 **ppDb, /* OUT: Returned database handle */ unsigned int flags, /* Operational flags */ const char *zVfs /* Name of the VFS to use */ ){ sqlite3 *db; /* Store allocated handle here */ int rc; /* Return code */ int isThreadsafe; /* True for threadsafe connections */ char *zOpen = 0; /* Filename argument to pass to BtreeOpen() */ char *zErrMsg = 0; /* Error message from sqlite3ParseUri() */ #ifdef SQLITE_ENABLE_API_ARMOR if( ppDb==0 ) return SQLITE_MISUSE_BKPT; #endif *ppDb = 0; #ifndef SQLITE_OMIT_AUTOINIT rc = sqlite3_initialize(); if( rc ) return rc; #endif /* Only allow sensible combinations of bits in the flags argument. ** Throw an error if any non-sense combination is used. If we ** do not block illegal combinations here, it could trigger ** assert() statements in deeper layers. Sensible combinations ** are: ** ** 1: SQLITE_OPEN_READONLY ** 2: SQLITE_OPEN_READWRITE ** 6: SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE */ assert( SQLITE_OPEN_READONLY == 0x01 ); assert( SQLITE_OPEN_READWRITE == 0x02 ); assert( SQLITE_OPEN_CREATE == 0x04 ); testcase( (1<<(flags&7))==0x02 ); /* READONLY */ testcase( (1<<(flags&7))==0x04 ); /* READWRITE */ testcase( (1<<(flags&7))==0x40 ); /* READWRITE | CREATE */ if( ((1<<(flags&7)) & 0x46)==0 ){ return SQLITE_MISUSE_BKPT; /* IMP: R-65497-44594 */ } if( sqlite3GlobalConfig.bCoreMutex==0 ){ isThreadsafe = 0; }else if( flags & SQLITE_OPEN_NOMUTEX ){ isThreadsafe = 0; }else if( flags & SQLITE_OPEN_FULLMUTEX ){ isThreadsafe = 1; }else{ isThreadsafe = sqlite3GlobalConfig.bFullMutex; } if( flags & SQLITE_OPEN_PRIVATECACHE ){ flags &= ~SQLITE_OPEN_SHAREDCACHE; }else if( sqlite3GlobalConfig.sharedCacheEnabled ){ flags |= SQLITE_OPEN_SHAREDCACHE; } /* Remove harmful bits from the flags parameter ** ** The SQLITE_OPEN_NOMUTEX and SQLITE_OPEN_FULLMUTEX flags were ** dealt with in the previous code block. Besides these, the only ** valid input flags for sqlite3_open_v2() are SQLITE_OPEN_READONLY, ** SQLITE_OPEN_READWRITE, SQLITE_OPEN_CREATE, SQLITE_OPEN_SHAREDCACHE, ** SQLITE_OPEN_PRIVATECACHE, and some reserved bits. Silently mask ** off all other flags. */ flags &= ~( SQLITE_OPEN_DELETEONCLOSE | SQLITE_OPEN_EXCLUSIVE | SQLITE_OPEN_MAIN_DB | SQLITE_OPEN_TEMP_DB | SQLITE_OPEN_TRANSIENT_DB | SQLITE_OPEN_MAIN_JOURNAL | SQLITE_OPEN_TEMP_JOURNAL | SQLITE_OPEN_SUBJOURNAL | SQLITE_OPEN_MASTER_JOURNAL | SQLITE_OPEN_NOMUTEX | SQLITE_OPEN_FULLMUTEX | SQLITE_OPEN_WAL ); /* Allocate the sqlite data structure */ db = sqlite3MallocZero( sizeof(sqlite3) ); if( db==0 ) goto opendb_out; if( isThreadsafe ){ db->mutex = sqlite3MutexAlloc(SQLITE_MUTEX_RECURSIVE); if( db->mutex==0 ){ sqlite3_free(db); db = 0; goto opendb_out; } } sqlite3_mutex_enter(db->mutex); db->errMask = 0xff; db->nDb = 2; db->magic = SQLITE_MAGIC_BUSY; db->aDb = db->aDbStatic; assert( sizeof(db->aLimit)==sizeof(aHardLimit) ); memcpy(db->aLimit, aHardLimit, sizeof(db->aLimit)); db->aLimit[SQLITE_LIMIT_WORKER_THREADS] = SQLITE_DEFAULT_WORKER_THREADS; db->autoCommit = 1; db->nextAutovac = -1; db->szMmap = sqlite3GlobalConfig.szMmap; db->nextPagesize = 0; db->nMaxSorterMmap = 0x7FFFFFFF; db->flags |= SQLITE_ShortColNames | SQLITE_EnableTrigger | SQLITE_CacheSpill #if !defined(SQLITE_DEFAULT_AUTOMATIC_INDEX) || SQLITE_DEFAULT_AUTOMATIC_INDEX | SQLITE_AutoIndex #endif #if SQLITE_DEFAULT_CKPTFULLFSYNC | SQLITE_CkptFullFSync #endif #if SQLITE_DEFAULT_FILE_FORMAT<4 | SQLITE_LegacyFileFmt #endif #ifdef SQLITE_ENABLE_LOAD_EXTENSION | SQLITE_LoadExtension #endif #if SQLITE_DEFAULT_RECURSIVE_TRIGGERS | SQLITE_RecTriggers #endif #if defined(SQLITE_DEFAULT_FOREIGN_KEYS) && SQLITE_DEFAULT_FOREIGN_KEYS | SQLITE_ForeignKeys #endif #if defined(SQLITE_REVERSE_UNORDERED_SELECTS) | SQLITE_ReverseOrder #endif ; sqlite3HashInit(&db->aCollSeq); #ifndef SQLITE_OMIT_VIRTUALTABLE sqlite3HashInit(&db->aModule); #endif /* Add the default collation sequence BINARY. BINARY works for both UTF-8 ** and UTF-16, so add a version for each to avoid any unnecessary ** conversions. The only error that can occur here is a malloc() failure. ** ** EVIDENCE-OF: R-52786-44878 SQLite defines three built-in collating ** functions: */ createCollation(db, "BINARY", SQLITE_UTF8, 0, binCollFunc, 0); createCollation(db, "BINARY", SQLITE_UTF16BE, 0, binCollFunc, 0); createCollation(db, "BINARY", SQLITE_UTF16LE, 0, binCollFunc, 0); createCollation(db, "NOCASE", SQLITE_UTF8, 0, nocaseCollatingFunc, 0); createCollation(db, "RTRIM", SQLITE_UTF8, (void*)1, binCollFunc, 0); if( db->mallocFailed ){ goto opendb_out; } /* EVIDENCE-OF: R-08308-17224 The default collating function for all ** strings is BINARY. */ db->pDfltColl = sqlite3FindCollSeq(db, SQLITE_UTF8, "BINARY", 0); assert( db->pDfltColl!=0 ); /* Parse the filename/URI argument. */ db->openFlags = flags; rc = sqlite3ParseUri(zVfs, zFilename, &flags, &db->pVfs, &zOpen, &zErrMsg); if( rc!=SQLITE_OK ){ if( rc==SQLITE_NOMEM ) db->mallocFailed = 1; sqlite3ErrorWithMsg(db, rc, zErrMsg ? "%s" : 0, zErrMsg); sqlite3_free(zErrMsg); goto opendb_out; } /* Open the backend database driver */ rc = sqlite3BtreeOpen(db->pVfs, zOpen, db, &db->aDb[0].pBt, 0, flags | SQLITE_OPEN_MAIN_DB); if( rc!=SQLITE_OK ){ if( rc==SQLITE_IOERR_NOMEM ){ rc = SQLITE_NOMEM; } sqlite3Error(db, rc); goto opendb_out; } sqlite3BtreeEnter(db->aDb[0].pBt); db->aDb[0].pSchema = sqlite3SchemaGet(db, db->aDb[0].pBt); if( !db->mallocFailed ) ENC(db) = SCHEMA_ENC(db); sqlite3BtreeLeave(db->aDb[0].pBt); db->aDb[1].pSchema = sqlite3SchemaGet(db, 0); /* The default safety_level for the main database is 'full'; for the temp ** database it is 'NONE'. This matches the pager layer defaults. */ db->aDb[0].zName = "main"; db->aDb[0].safety_level = 3; db->aDb[1].zName = "temp"; db->aDb[1].safety_level = 1; db->magic = SQLITE_MAGIC_OPEN; if( db->mallocFailed ){ goto opendb_out; } /* Register all built-in functions, but do not attempt to read the ** database schema yet. This is delayed until the first time the database ** is accessed. */ sqlite3Error(db, SQLITE_OK); sqlite3RegisterBuiltinFunctions(db); /* Load automatic extensions - extensions that have been registered ** using the sqlite3_automatic_extension() API. */ rc = sqlite3_errcode(db); if( rc==SQLITE_OK ){ sqlite3AutoLoadExtensions(db); rc = sqlite3_errcode(db); if( rc!=SQLITE_OK ){ goto opendb_out; } } #ifdef SQLITE_ENABLE_FTS1 if( !db->mallocFailed ){ extern int sqlite3Fts1Init(sqlite3*); rc = sqlite3Fts1Init(db); } #endif #ifdef SQLITE_ENABLE_FTS2 if( !db->mallocFailed && rc==SQLITE_OK ){ extern int sqlite3Fts2Init(sqlite3*); rc = sqlite3Fts2Init(db); } #endif #ifdef SQLITE_ENABLE_FTS3 if( !db->mallocFailed && rc==SQLITE_OK ){ rc = sqlite3Fts3Init(db); } #endif #ifdef SQLITE_ENABLE_ICU if( !db->mallocFailed && rc==SQLITE_OK ){ rc = sqlite3IcuInit(db); } #endif #ifdef SQLITE_ENABLE_RTREE if( !db->mallocFailed && rc==SQLITE_OK){ rc = sqlite3RtreeInit(db); } #endif #ifdef SQLITE_ENABLE_DBSTAT_VTAB if( !db->mallocFailed && rc==SQLITE_OK){ int sqlite3_dbstat_register(sqlite3*); rc = sqlite3_dbstat_register(db); } #endif /* -DSQLITE_DEFAULT_LOCKING_MODE=1 makes EXCLUSIVE the default locking ** mode. -DSQLITE_DEFAULT_LOCKING_MODE=0 make NORMAL the default locking ** mode. Doing nothing at all also makes NORMAL the default. */ #ifdef SQLITE_DEFAULT_LOCKING_MODE db->dfltLockMode = SQLITE_DEFAULT_LOCKING_MODE; sqlite3PagerLockingMode(sqlite3BtreePager(db->aDb[0].pBt), SQLITE_DEFAULT_LOCKING_MODE); #endif if( rc ) sqlite3Error(db, rc); /* Enable the lookaside-malloc subsystem */ setupLookaside(db, 0, sqlite3GlobalConfig.szLookaside, sqlite3GlobalConfig.nLookaside); sqlite3_wal_autocheckpoint(db, SQLITE_DEFAULT_WAL_AUTOCHECKPOINT); opendb_out: sqlite3_free(zOpen); if( db ){ assert( db->mutex!=0 || isThreadsafe==0 || sqlite3GlobalConfig.bFullMutex==0 ); sqlite3_mutex_leave(db->mutex); } rc = sqlite3_errcode(db); assert( db!=0 || rc==SQLITE_NOMEM ); if( rc==SQLITE_NOMEM ){ sqlite3_close(db); db = 0; }else if( rc!=SQLITE_OK ){ db->magic = SQLITE_MAGIC_SICK; } *ppDb = db; #ifdef SQLITE_ENABLE_SQLLOG if( sqlite3GlobalConfig.xSqllog ){ /* Opening a db handle. Fourth parameter is passed 0. */ void *pArg = sqlite3GlobalConfig.pSqllogArg; sqlite3GlobalConfig.xSqllog(pArg, db, zFilename, 0); } #endif return sqlite3ApiExit(0, rc); }