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{ |