| Index: third_party/sqlite/src/src/attach.c
|
| diff --git a/third_party/sqlite/src/src/attach.c b/third_party/sqlite/src/src/attach.c
|
| index bda1c874454e437c37bdb43f83ec3e4228074287..cf52bb24b126f84efde80f77f51c8fcaeaa992b7 100644
|
| --- a/third_party/sqlite/src/src/attach.c
|
| +++ b/third_party/sqlite/src/src/attach.c
|
| @@ -38,10 +38,6 @@ static int resolveAttachExpr(NameContext *pName, Expr *pExpr)
|
| if( pExpr ){
|
| if( pExpr->op!=TK_ID ){
|
| rc = sqlite3ResolveExprNames(pName, pExpr);
|
| - if( rc==SQLITE_OK && !sqlite3ExprIsConstant(pExpr) ){
|
| - sqlite3ErrorMsg(pName->pParse, "invalid name: \"%s\"", pExpr->u.zToken);
|
| - return SQLITE_ERROR;
|
| - }
|
| }else{
|
| pExpr->op = TK_STRING;
|
| }
|
| @@ -70,8 +66,12 @@ static void attachFunc(
|
| 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);
|
|
|
| @@ -105,7 +105,7 @@ static void attachFunc(
|
| }
|
| }
|
|
|
| - /* Allocate the new entry in the db->aDb[] array and initialise the schema
|
| + /* Allocate the new entry in the db->aDb[] array and initialize the schema
|
| ** hash tables.
|
| */
|
| if( db->aDb==db->aDbStatic ){
|
| @@ -122,10 +122,20 @@ static void attachFunc(
|
|
|
| /* 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 initialised.
|
| + ** or may not be initialized.
|
| */
|
| - rc = sqlite3BtreeOpen(zFile, db, &aNew->pBt, 0,
|
| - db->openFlags | SQLITE_OPEN_MAIN_DB);
|
| + 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;
|
| @@ -144,6 +154,9 @@ static void attachFunc(
|
| 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
|
| }
|
| aNew->safety_level = 3;
|
| aNew->zName = sqlite3DbStrDup(db, zName);
|
| @@ -194,6 +207,15 @@ static void attachFunc(
|
| 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 );
|
| @@ -202,7 +224,7 @@ static void attachFunc(
|
| db->aDb[iDb].pBt = 0;
|
| db->aDb[iDb].pSchema = 0;
|
| }
|
| - sqlite3ResetInternalSchema(db, -1);
|
| + sqlite3ResetAllSchemasOfConnection(db);
|
| db->nDb = iDb;
|
| if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){
|
| db->mallocFailed = 1;
|
| @@ -274,7 +296,7 @@ static void detachFunc(
|
| sqlite3BtreeClose(pDb->pBt);
|
| pDb->pBt = 0;
|
| pDb->pSchema = 0;
|
| - sqlite3ResetInternalSchema(db, -1);
|
| + sqlite3ResetAllSchemasOfConnection(db);
|
| return;
|
|
|
| detach_error:
|
| @@ -362,8 +384,7 @@ attach_end:
|
| void sqlite3Detach(Parse *pParse, Expr *pDbname){
|
| static const FuncDef detach_func = {
|
| 1, /* nArg */
|
| - SQLITE_UTF8, /* iPrefEnc */
|
| - 0, /* flags */
|
| + SQLITE_UTF8, /* funcFlags */
|
| 0, /* pUserData */
|
| 0, /* pNext */
|
| detachFunc, /* xFunc */
|
| @@ -384,8 +405,7 @@ void sqlite3Detach(Parse *pParse, Expr *pDbname){
|
| void sqlite3Attach(Parse *pParse, Expr *p, Expr *pDbname, Expr *pKey){
|
| static const FuncDef attach_func = {
|
| 3, /* nArg */
|
| - SQLITE_UTF8, /* iPrefEnc */
|
| - 0, /* flags */
|
| + SQLITE_UTF8, /* funcFlags */
|
| 0, /* pUserData */
|
| 0, /* pNext */
|
| attachFunc, /* xFunc */
|
| @@ -402,11 +422,8 @@ void sqlite3Attach(Parse *pParse, Expr *p, Expr *pDbname, Expr *pKey){
|
| /*
|
| ** Initialize a DbFixer structure. This routine must be called prior
|
| ** to passing the structure to one of the sqliteFixAAAA() routines below.
|
| -**
|
| -** The return value indicates whether or not fixation is required. TRUE
|
| -** means we do need to fix the database references, FALSE means we do not.
|
| */
|
| -int sqlite3FixInit(
|
| +void sqlite3FixInit(
|
| DbFixer *pFix, /* The fixer to be initialized */
|
| Parse *pParse, /* Error messages will be written here */
|
| int iDb, /* This is the database that must be used */
|
| @@ -415,14 +432,14 @@ int sqlite3FixInit(
|
| ){
|
| sqlite3 *db;
|
|
|
| - if( NEVER(iDb<0) || iDb==1 ) return 0;
|
| db = pParse->db;
|
| assert( db->nDb>iDb );
|
| pFix->pParse = pParse;
|
| pFix->zDb = db->aDb[iDb].zName;
|
| + pFix->pSchema = db->aDb[iDb].pSchema;
|
| pFix->zType = zType;
|
| pFix->pName = pName;
|
| - return 1;
|
| + pFix->bVarOnly = (iDb==1);
|
| }
|
|
|
| /*
|
| @@ -450,13 +467,16 @@ int sqlite3FixSrcList(
|
| if( NEVER(pList==0) ) return 0;
|
| zDb = pFix->zDb;
|
| for(i=0, pItem=pList->a; i<pList->nSrc; i++, pItem++){
|
| - if( pItem->zDatabase==0 ){
|
| - pItem->zDatabase = sqlite3DbStrDup(pFix->pParse->db, zDb);
|
| - }else if( sqlite3StrICmp(pItem->zDatabase,zDb)!=0 ){
|
| - sqlite3ErrorMsg(pFix->pParse,
|
| - "%s %T cannot reference objects in database %s",
|
| - pFix->zType, pFix->pName, pItem->zDatabase);
|
| - return 1;
|
| + if( pFix->bVarOnly==0 ){
|
| + if( pItem->zDatabase && sqlite3StrICmp(pItem->zDatabase, zDb) ){
|
| + sqlite3ErrorMsg(pFix->pParse,
|
| + "%s %T cannot reference objects in database %s",
|
| + pFix->zType, pFix->pName, pItem->zDatabase);
|
| + return 1;
|
| + }
|
| + sqlite3DbFree(pFix->pParse->db, pItem->zDatabase);
|
| + pItem->zDatabase = 0;
|
| + pItem->pSchema = pFix->pSchema;
|
| }
|
| #if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER)
|
| if( sqlite3FixSelect(pFix, pItem->pSelect) ) return 1;
|
| @@ -480,9 +500,21 @@ int sqlite3FixSelect(
|
| if( sqlite3FixExpr(pFix, pSelect->pWhere) ){
|
| return 1;
|
| }
|
| + if( sqlite3FixExprList(pFix, pSelect->pGroupBy) ){
|
| + return 1;
|
| + }
|
| if( sqlite3FixExpr(pFix, pSelect->pHaving) ){
|
| return 1;
|
| }
|
| + if( sqlite3FixExprList(pFix, pSelect->pOrderBy) ){
|
| + return 1;
|
| + }
|
| + if( sqlite3FixExpr(pFix, pSelect->pLimit) ){
|
| + return 1;
|
| + }
|
| + if( sqlite3FixExpr(pFix, pSelect->pOffset) ){
|
| + return 1;
|
| + }
|
| pSelect = pSelect->pPrior;
|
| }
|
| return 0;
|
| @@ -492,7 +524,15 @@ int sqlite3FixExpr(
|
| Expr *pExpr /* The expression to be fixed to one database */
|
| ){
|
| while( pExpr ){
|
| - if( ExprHasAnyProperty(pExpr, EP_TokenOnly) ) break;
|
| + if( pExpr->op==TK_VARIABLE ){
|
| + if( pFix->pParse->db->init.busy ){
|
| + pExpr->op = TK_NULL;
|
| + }else{
|
| + sqlite3ErrorMsg(pFix->pParse, "%s cannot use variables", pFix->zType);
|
| + return 1;
|
| + }
|
| + }
|
| + if( ExprHasProperty(pExpr, EP_TokenOnly) ) break;
|
| if( ExprHasProperty(pExpr, EP_xIsSelect) ){
|
| if( sqlite3FixSelect(pFix, pExpr->x.pSelect) ) return 1;
|
| }else{
|
|
|