Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Fix further problems with the feature on this branch. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | reuse-schema1 |
Files: | files | file ages | folders |
SHA3-256: |
6d7a7e5faf1c0ff19e4b0681bc25abb9 |
User & Date: | dan 2018-11-17 18:11:09.696 |
Context
2018-11-17
| ||
18:45 | Merge latest trunk changes into this branch. (check-in: 9fdd186897 user: dan tags: reuse-schema1) | |
18:11 | Fix further problems with the feature on this branch. (check-in: 6d7a7e5faf user: dan tags: reuse-schema1) | |
2018-11-16
| ||
17:04 | Fix further REUSE_SCHEMA issues. (check-in: 9780829a77 user: dan tags: reuse-schema1) | |
Changes
Changes to src/btmutex.c.
︙ | ︙ | |||
248 249 250 251 252 253 254 | ** ** If pSchema is not NULL, then iDb is computed from pSchema and ** db using sqlite3SchemaToIndex(). */ int sqlite3SchemaMutexHeld(sqlite3 *db, int iDb, Schema *pSchema){ Btree *p; assert( db!=0 ); | > | | 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 | ** ** If pSchema is not NULL, then iDb is computed from pSchema and ** db using sqlite3SchemaToIndex(). */ int sqlite3SchemaMutexHeld(sqlite3 *db, int iDb, Schema *pSchema){ Btree *p; assert( db!=0 ); if( pSchema && (db->openFlags & SQLITE_OPEN_REUSE_SCHEMA) ) return 1; if( pSchema ) iDb = sqlite3SchemaToIndex2(db, pSchema, 0); assert( iDb>=0 && iDb<db->nDb ); if( !sqlite3_mutex_held(db->mutex) ) return 0; if( iDb==1 ) return 1; p = db->aDb[iDb].pBt; assert( p!=0 ); return p->sharable==0 || p->locked==1; } |
︙ | ︙ |
Changes to src/build.c.
︙ | ︙ | |||
400 401 402 403 404 405 406 | if( pParse->iFixDb && pParse->iFixDb!=2 ){ zDb = pParse->db->aDb[pParse->iFixDb-1].zDbSName; assert( p->zDatabase==0 || sqlite3StrICmp(p->zDatabase, zDb)==0 ); if( p->zDatabase==0 ){ p->zDatabase = sqlite3DbStrDup(pParse->db, zDb); } }else if( p->pSchema ){ | | | 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 | if( pParse->iFixDb && pParse->iFixDb!=2 ){ zDb = pParse->db->aDb[pParse->iFixDb-1].zDbSName; assert( p->zDatabase==0 || sqlite3StrICmp(p->zDatabase, zDb)==0 ); if( p->zDatabase==0 ){ p->zDatabase = sqlite3DbStrDup(pParse->db, zDb); } }else if( p->pSchema ){ int iDb = sqlite3SchemaToIndex2(pParse->db, p->pSchema, 0); zDb = pParse->db->aDb[iDb].zDbSName; }else{ zDb = p->zDatabase; } return sqlite3LocateTable(pParse, flags, p->zName, zDb); } |
︙ | ︙ | |||
1970 1971 1972 1973 1974 1975 1976 | sqlite3ErrorMsg(pParse, "PRIMARY KEY missing on table %s", p->zName); }else{ p->tabFlags |= TF_WithoutRowid | TF_NoVisibleRowid; convertToWithoutRowidTable(pParse, p); } } | | | 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 | sqlite3ErrorMsg(pParse, "PRIMARY KEY missing on table %s", p->zName); }else{ p->tabFlags |= TF_WithoutRowid | TF_NoVisibleRowid; convertToWithoutRowidTable(pParse, p); } } iDb = sqlite3SchemaToIndex2(db, p->pSchema, 0); #ifndef SQLITE_OMIT_CHECK /* Resolve names in all CHECK constraint expressions. */ if( p->pCheck ){ sqlite3ResolveSelfReference(pParse, p, NC_IsCheck, 0, p->pCheck); } |
︙ | ︙ | |||
2190 2191 2192 2193 2194 2195 2196 | sqlite3ErrorMsg(pParse, "parameters are not allowed in views"); goto create_view_fail; } sqlite3StartTable(pParse, pName1, pName2, isTemp, 1, 0, noErr); p = pParse->pNewTable; if( p==0 || pParse->nErr ) goto create_view_fail; sqlite3TwoPartName(pParse, pName1, pName2, &pName); | | | 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 | sqlite3ErrorMsg(pParse, "parameters are not allowed in views"); goto create_view_fail; } sqlite3StartTable(pParse, pName1, pName2, isTemp, 1, 0, noErr); p = pParse->pNewTable; if( p==0 || pParse->nErr ) goto create_view_fail; sqlite3TwoPartName(pParse, pName1, pName2, &pName); iDb = sqlite3SchemaToIndex2(db, p->pSchema, 0); sqlite3FixInit(&sFix, pParse, iDb, "view", pName); if( sqlite3FixSelect(&sFix, pSelect) ) goto create_view_fail; /* Make a copy of the entire SELECT statement that defines the view. ** This will force all the Expr.token.z values to be dynamically ** allocated rather than point to the input string - which means that ** they will persist after the current sqlite3_exec() call returns. |
︙ | ︙ | |||
2507 2508 2509 2510 2511 2512 2513 | if( (iDestroyed==0 || (iIdx<iDestroyed)) && iIdx>iLargest ){ iLargest = iIdx; } } if( iLargest==0 ){ return; }else{ | | | 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 | if( (iDestroyed==0 || (iIdx<iDestroyed)) && iIdx>iLargest ){ iLargest = iIdx; } } if( iLargest==0 ){ return; }else{ int iDb = sqlite3SchemaToIndex2(pParse->db, pTab->pSchema, 0); assert( iDb>=0 && iDb<pParse->db->nDb ); destroyRootPage(pParse, iLargest, iDb); iDestroyed = iLargest; } } } |
︙ | ︙ | |||
2634 2635 2636 2637 2638 2639 2640 | pTab = sqlite3LocateTableItem(pParse, isView, &pName->a[0]); if( noErr ) db->suppressErr--; if( pTab==0 ){ if( noErr ) sqlite3CodeVerifyNamedSchema(pParse, pName->a[0].zDatabase); goto exit_drop_table; } | | | 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 | pTab = sqlite3LocateTableItem(pParse, isView, &pName->a[0]); if( noErr ) db->suppressErr--; if( pTab==0 ){ if( noErr ) sqlite3CodeVerifyNamedSchema(pParse, pName->a[0].zDatabase); goto exit_drop_table; } iDb = sqlite3SchemaToIndex2(db, pTab->pSchema, 0); assert( iDb>=0 && iDb<db->nDb ); sqlite3SchemaWritable(pParse, iDb); /* If pTab is a virtual table, call ViewGetColumnNames() to ensure ** it is initialized. */ if( IsVirtual(pTab) && sqlite3ViewGetColumnNames(pParse, pTab) ){ |
︙ | ︙ | |||
2883 2884 2885 2886 2887 2888 2889 | ** ** if memRootPage is not negative, it means that the index is newly ** created. The register specified by memRootPage contains the ** root page number of the index. If memRootPage is negative, then ** the index already exists and must be cleared before being refilled and ** the root page number of the index is taken from pIndex->tnum. */ | | > > > > > < | 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 | ** ** if memRootPage is not negative, it means that the index is newly ** created. The register specified by memRootPage contains the ** root page number of the index. If memRootPage is negative, then ** the index already exists and must be cleared before being refilled and ** the root page number of the index is taken from pIndex->tnum. */ static void sqlite3RefillIndex( Parse *pParse, int iDb, Index *pIndex, int memRootPage ){ Table *pTab = pIndex->pTable; /* The table that is indexed */ int iTab = pParse->nTab++; /* Btree cursor used for pTab */ int iIdx = pParse->nTab++; /* Btree cursor used for pIndex */ int iSorter; /* Cursor opened by OpenSorter (if in use) */ int addr1; /* Address of top of loop */ int addr2; /* Address to jump to for next iteration */ int tnum; /* Root page of index */ int iPartIdxLabel; /* Jump to this label to skip a row */ Vdbe *v; /* Generate code into this virtual machine */ KeyInfo *pKey; /* KeyInfo for index */ int regRecord; /* Register holding assembled index record */ sqlite3 *db = pParse->db; /* The database connection */ #ifndef SQLITE_OMIT_AUTHORIZATION if( sqlite3AuthCheck(pParse, SQLITE_REINDEX, pIndex->zName, 0, db->aDb[iDb].zDbSName ) ){ return; } #endif |
︙ | ︙ | |||
3095 3096 3097 3098 3099 3100 3101 | } if( !HasRowid(pTab) ) pPk = sqlite3PrimaryKeyIndex(pTab); }else{ assert( pName==0 ); assert( pStart==0 ); pTab = pParse->pNewTable; if( !pTab ) goto exit_create_index; | | | 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 | } if( !HasRowid(pTab) ) pPk = sqlite3PrimaryKeyIndex(pTab); }else{ assert( pName==0 ); assert( pStart==0 ); pTab = pParse->pNewTable; if( !pTab ) goto exit_create_index; iDb = sqlite3SchemaToIndex2(db, pTab->pSchema, 0); } pDb = &db->aDb[iDb]; assert( pTab!=0 ); assert( pParse->nErr==0 ); if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0 && db->init.busy==0 |
︙ | ︙ | |||
3518 3519 3520 3521 3522 3523 3524 | ); sqlite3DbFree(db, zStmt); /* Fill the index with data and reparse the schema. Code an OP_Expire ** to invalidate all pre-compiled statements. */ if( pTblName ){ | | | 3522 3523 3524 3525 3526 3527 3528 3529 3530 3531 3532 3533 3534 3535 3536 | ); sqlite3DbFree(db, zStmt); /* Fill the index with data and reparse the schema. Code an OP_Expire ** to invalidate all pre-compiled statements. */ if( pTblName ){ sqlite3RefillIndex(pParse, iDb, pIndex, iMem); sqlite3ChangeCookie(pParse, iDb); sqlite3VdbeAddParseSchemaOp(pParse, iDb, sqlite3MPrintf(db, "name='%q' AND type='index'", pIndex->zName)); sqlite3VdbeAddOp2(v, OP_Expire, 0, 1); } sqlite3VdbeJumpHere(v, pIndex->tnum); |
︙ | ︙ | |||
3644 3645 3646 3647 3648 3649 3650 | goto exit_drop_index; } if( pIndex->idxType!=SQLITE_IDXTYPE_APPDEF ){ sqlite3ErrorMsg(pParse, "index associated with UNIQUE " "or PRIMARY KEY constraint cannot be dropped", 0); goto exit_drop_index; } | | | 3648 3649 3650 3651 3652 3653 3654 3655 3656 3657 3658 3659 3660 3661 3662 | goto exit_drop_index; } if( pIndex->idxType!=SQLITE_IDXTYPE_APPDEF ){ sqlite3ErrorMsg(pParse, "index associated with UNIQUE " "or PRIMARY KEY constraint cannot be dropped", 0); goto exit_drop_index; } iDb = sqlite3SchemaToIndex2(db, pIndex->pSchema, 0); sqlite3SchemaWritable(pParse, iDb); #ifndef SQLITE_OMIT_AUTHORIZATION { int code = SQLITE_DROP_INDEX; Table *pTab = pIndex->pTable; const char *zDb = db->aDb[iDb].zDbSName; const char *zTab = SCHEMA_TABLE(iDb); |
︙ | ︙ | |||
4378 4379 4380 4381 4382 4383 4384 | #endif /* ** Recompute all indices of pTab that use the collating sequence pColl. ** If pColl==0 then recompute all indices of pTab. */ #ifndef SQLITE_OMIT_REINDEX | | > > > > > < | | 4382 4383 4384 4385 4386 4387 4388 4389 4390 4391 4392 4393 4394 4395 4396 4397 4398 4399 4400 4401 4402 4403 4404 4405 4406 4407 | #endif /* ** Recompute all indices of pTab that use the collating sequence pColl. ** If pColl==0 then recompute all indices of pTab. */ #ifndef SQLITE_OMIT_REINDEX static void reindexTable( Parse *pParse, int iDb, Table *pTab, char const *zColl ){ Index *pIndex; /* An index associated with pTab */ for(pIndex=pTab->pIndex; pIndex; pIndex=pIndex->pNext){ if( zColl==0 || collationMatch(zColl, pIndex) ){ sqlite3BeginWriteOperation(pParse, 0, iDb); sqlite3RefillIndex(pParse, iDb, pIndex, -1); } } } #endif /* ** Recompute all indices of all tables in all databases where the |
︙ | ︙ | |||
4409 4410 4411 4412 4413 4414 4415 | Table *pTab; /* A table in the database */ assert( sqlite3BtreeHoldsAllMutexes(db) ); /* Needed for schema access */ for(iDb=0, pDb=db->aDb; iDb<db->nDb; iDb++, pDb++){ assert( pDb!=0 ); for(k=sqliteHashFirst(&pDb->pSchema->tblHash); k; k=sqliteHashNext(k)){ pTab = (Table*)sqliteHashData(k); | | | 4417 4418 4419 4420 4421 4422 4423 4424 4425 4426 4427 4428 4429 4430 4431 | Table *pTab; /* A table in the database */ assert( sqlite3BtreeHoldsAllMutexes(db) ); /* Needed for schema access */ for(iDb=0, pDb=db->aDb; iDb<db->nDb; iDb++, pDb++){ assert( pDb!=0 ); for(k=sqliteHashFirst(&pDb->pSchema->tblHash); k; k=sqliteHashNext(k)){ pTab = (Table*)sqliteHashData(k); reindexTable(pParse, iDb, pTab, zColl); } } } #endif /* ** Generate code for the REINDEX command. |
︙ | ︙ | |||
4468 4469 4470 4471 4472 4473 4474 | iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pObjName); if( iDb<0 ) return; z = sqlite3NameFromToken(db, pObjName); if( z==0 ) return; zDb = db->aDb[iDb].zDbSName; pTab = sqlite3FindTable(db, z, zDb); if( pTab ){ | | | | 4476 4477 4478 4479 4480 4481 4482 4483 4484 4485 4486 4487 4488 4489 4490 4491 4492 4493 4494 4495 4496 4497 4498 | iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pObjName); if( iDb<0 ) return; z = sqlite3NameFromToken(db, pObjName); if( z==0 ) return; zDb = db->aDb[iDb].zDbSName; pTab = sqlite3FindTable(db, z, zDb); if( pTab ){ reindexTable(pParse, iDb, pTab, 0); sqlite3DbFree(db, z); return; } pIndex = sqlite3FindIndex(db, z, zDb); sqlite3DbFree(db, z); if( pIndex ){ sqlite3BeginWriteOperation(pParse, 0, iDb); sqlite3RefillIndex(pParse, iDb, pIndex, -1); return; } sqlite3ErrorMsg(pParse, "unable to identify the object to be reindexed"); } #endif /* |
︙ | ︙ |
Changes to src/delete.c.
︙ | ︙ | |||
744 745 746 747 748 749 750 | testcase( iIdxNoSeek>=0 ); iIdxNoSeek = -1; } /* Do FK processing. This call checks that any FK constraints that ** refer to this table (i.e. constraints attached to other tables) ** are not violated by deleting this row. */ | | | 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 | testcase( iIdxNoSeek>=0 ); iIdxNoSeek = -1; } /* Do FK processing. This call checks that any FK constraints that ** refer to this table (i.e. constraints attached to other tables) ** are not violated by deleting this row. */ sqlite3FkCheck(pParse, iDb, pTab, iOld, 0, 0, 0); } /* Delete the index and table entries. Skip this step if pTab is really ** a view (in which case the only effect of the DELETE statement is to ** fire the INSTEAD OF triggers). ** ** If variable 'count' is non-zero, then this OP_Delete instruction should |
︙ | ︙ |
Changes to src/expr.c.
︙ | ︙ | |||
2365 2366 2367 2368 2369 2370 2371 | assert( p->pEList!=0 ); /* Because of isCandidateForInOpt(p) */ assert( p->pEList->a[0].pExpr!=0 ); /* Because of isCandidateForInOpt(p) */ assert( p->pSrc!=0 ); /* Because of isCandidateForInOpt(p) */ pTab = p->pSrc->a[0].pTab; /* Code an OP_Transaction and OP_TableLock for <table>. */ | | | 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 | assert( p->pEList!=0 ); /* Because of isCandidateForInOpt(p) */ assert( p->pEList->a[0].pExpr!=0 ); /* Because of isCandidateForInOpt(p) */ assert( p->pSrc!=0 ); /* Because of isCandidateForInOpt(p) */ pTab = p->pSrc->a[0].pTab; /* Code an OP_Transaction and OP_TableLock for <table>. */ iDb = sqlite3SchemaToIndex2(db, pTab->pSchema, p->pSrc->a[0].zDatabase); sqlite3CodeVerifySchema(pParse, iDb); sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName); assert(v); /* sqlite3GetVdbe() has always been previously called */ if( nExpr==1 && pEList->a[0].pExpr->iColumn<0 ){ /* The "x IN (SELECT rowid FROM table)" case */ int iAddr = sqlite3VdbeAddOp0(v, OP_Once); |
︙ | ︙ |
Changes to src/fkey.c.
︙ | ︙ | |||
858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 | ** For an UPDATE operation, this function is called twice. Once before ** the original record is deleted from the table using the calling convention ** described for DELETE. Then again after the original record is deleted ** but before the new record is inserted using the INSERT convention. */ void sqlite3FkCheck( Parse *pParse, /* Parse context */ Table *pTab, /* Row is being deleted from this table */ int regOld, /* Previous row data is stored here */ int regNew, /* New row data is stored here */ int *aChange, /* Array indicating UPDATEd columns (or 0) */ int bChngRowid /* True if rowid is UPDATEd */ ){ sqlite3 *db = pParse->db; /* Database handle */ FKey *pFKey; /* Used to iterate through FKs */ | > < < < | 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 | ** For an UPDATE operation, this function is called twice. Once before ** the original record is deleted from the table using the calling convention ** described for DELETE. Then again after the original record is deleted ** but before the new record is inserted using the INSERT convention. */ void sqlite3FkCheck( Parse *pParse, /* Parse context */ int iDb, /* Database containing pTab */ Table *pTab, /* Row is being deleted from this table */ int regOld, /* Previous row data is stored here */ int regNew, /* New row data is stored here */ int *aChange, /* Array indicating UPDATEd columns (or 0) */ int bChngRowid /* True if rowid is UPDATEd */ ){ sqlite3 *db = pParse->db; /* Database handle */ FKey *pFKey; /* Used to iterate through FKs */ const char *zDb; /* Name of database containing pTab */ int isIgnoreErrors = pParse->disableTriggers; /* Exactly one of regOld and regNew should be non-zero. */ assert( (regOld==0)!=(regNew==0) ); /* If foreign-keys are disabled, this function is a no-op. */ if( (db->flags&SQLITE_ForeignKeys)==0 ) return; zDb = db->aDb[iDb].zDbSName; /* Loop through all the foreign key constraints for which pTab is the ** child table (the table that the foreign key definition is part of). */ for(pFKey=pTab->pFKey; pFKey; pFKey=pFKey->pNextFrom){ Table *pTo; /* Parent table of foreign key pFKey */ Index *pIdx = 0; /* Index on key columns in pTo */ |
︙ | ︙ |
Changes to src/insert.c.
︙ | ︙ | |||
1037 1038 1039 1040 1041 1042 1043 | { int isReplace; /* Set to true if constraints may cause a replace */ int bUseSeek; /* True to use OPFLAG_SEEKRESULT */ sqlite3GenerateConstraintChecks(pParse, iDb, pTab, aRegIdx, iDataCur, iIdxCur, regIns, 0, ipkColumn>=0, onError, endOfLoop, &isReplace, 0, pUpsert ); | | | 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 | { int isReplace; /* Set to true if constraints may cause a replace */ int bUseSeek; /* True to use OPFLAG_SEEKRESULT */ sqlite3GenerateConstraintChecks(pParse, iDb, pTab, aRegIdx, iDataCur, iIdxCur, regIns, 0, ipkColumn>=0, onError, endOfLoop, &isReplace, 0, pUpsert ); sqlite3FkCheck(pParse, iDb, pTab, 0, regIns, 0, 0); /* Set the OPFLAG_USESEEKRESULT flag if either (a) there are no REPLACE ** constraints or (b) there are no triggers and this table is not a ** parent table in a foreign key constraint. It is safe to set the ** flag in the second case as if any REPLACE constraint is hit, an ** OP_Delete or OP_IdxDelete instruction will be executed on each ** cursor that is disturbed. And these instructions both clear the |
︙ | ︙ | |||
2281 2282 2283 2284 2285 2286 2287 | /* If we get this far, it means that the xfer optimization is at ** least a possibility, though it might only work if the destination ** table (tab1) is initially empty. */ #ifdef SQLITE_TEST sqlite3_xferopt_count++; #endif | | | 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 | /* If we get this far, it means that the xfer optimization is at ** least a possibility, though it might only work if the destination ** table (tab1) is initially empty. */ #ifdef SQLITE_TEST sqlite3_xferopt_count++; #endif iDbSrc = sqlite3SchemaToIndex2(db, pSrc->pSchema, pItem->zDatabase); v = sqlite3GetVdbe(pParse); sqlite3CodeVerifySchema(pParse, iDbSrc); iSrc = pParse->nTab++; iDest = pParse->nTab++; regAutoinc = autoIncBegin(pParse, iDbDest, pDest); regData = sqlite3GetTempReg(pParse); regRowid = sqlite3GetTempReg(pParse); |
︙ | ︙ |
Changes to src/resolve.c.
︙ | ︙ | |||
192 193 194 195 196 197 198 199 200 201 202 203 204 205 | struct SrcList_item *pItem; /* Use for looping over pSrcList items */ struct SrcList_item *pMatch = 0; /* The matching pSrcList item */ NameContext *pTopNC = pNC; /* First namecontext in the list */ Schema *pSchema = 0; /* Schema of the expression */ int eNewExprOp = TK_COLUMN; /* New value for pExpr->op on success */ Table *pTab = 0; /* Table hold the row */ Column *pCol; /* A column of pTab */ assert( pNC ); /* the name context cannot be NULL. */ assert( zCol ); /* The Z in X.Y.Z cannot be NULL */ assert( !ExprHasProperty(pExpr, EP_TokenOnly|EP_Reduced) ); /* Initialize the node to no-match */ pExpr->iTable = -1; | > | 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 | struct SrcList_item *pItem; /* Use for looping over pSrcList items */ struct SrcList_item *pMatch = 0; /* The matching pSrcList item */ NameContext *pTopNC = pNC; /* First namecontext in the list */ Schema *pSchema = 0; /* Schema of the expression */ int eNewExprOp = TK_COLUMN; /* New value for pExpr->op on success */ Table *pTab = 0; /* Table hold the row */ Column *pCol; /* A column of pTab */ int iDb = -1; assert( pNC ); /* the name context cannot be NULL. */ assert( zCol ); /* The Z in X.Y.Z cannot be NULL */ assert( !ExprHasProperty(pExpr, EP_TokenOnly|EP_Reduced) ); /* Initialize the node to no-match */ pExpr->iTable = -1; |
︙ | ︙ | |||
219 220 221 222 223 224 225 226 227 228 229 230 231 232 | ** database name. */ zDb = 0; }else{ for(i=0; i<db->nDb; i++){ assert( db->aDb[i].zDbSName ); if( sqlite3StrICmp(db->aDb[i].zDbSName,zDb)==0 ){ pSchema = db->aDb[i].pSchema; break; } } } } /* Start at the inner-most context and move outward until a match is found */ | > | 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 | ** database name. */ zDb = 0; }else{ for(i=0; i<db->nDb; i++){ assert( db->aDb[i].zDbSName ); if( sqlite3StrICmp(db->aDb[i].zDbSName,zDb)==0 ){ pSchema = db->aDb[i].pSchema; iDb = i; break; } } } } /* Start at the inner-most context and move outward until a match is found */ |
︙ | ︙ | |||
250 251 252 253 254 255 256 | pMatch = pItem; pExpr->iColumn = j; hit = 1; } } if( hit || zTab==0 ) continue; } | | > > | 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 | pMatch = pItem; pExpr->iColumn = j; hit = 1; } } if( hit || zTab==0 ) continue; } if( zDb && iDb!=sqlite3SchemaToIndex2(db, pTab->pSchema, pItem->zDatabase) ){ continue; } if( zTab ){ const char *zTabName = pItem->zAlias ? pItem->zAlias : pTab->zName; assert( zTabName!=0 ); if( sqlite3StrICmp(zTabName, zTab)!=0 ){ continue; |
︙ | ︙ |
Changes to src/select.c.
︙ | ︙ | |||
4988 4989 4990 4991 4992 4993 4994 | } if( db->mallocFailed ) break; if( pSub==0 || (pSub->selFlags & SF_NestedFrom)==0 ){ pSub = 0; if( zTName && sqlite3StrICmp(zTName, zTabName)!=0 ){ continue; } | | | 4988 4989 4990 4991 4992 4993 4994 4995 4996 4997 4998 4999 5000 5001 5002 | } if( db->mallocFailed ) break; if( pSub==0 || (pSub->selFlags & SF_NestedFrom)==0 ){ pSub = 0; if( zTName && sqlite3StrICmp(zTName, zTabName)!=0 ){ continue; } iDb = sqlite3SchemaToIndex2(db, pTab->pSchema, pFrom->zDatabase); zSchemaName = iDb>=0 ? db->aDb[iDb].zDbSName : "*"; } for(j=0; j<pTab->nCol; j++){ char *zName = pTab->aCol[j].zName; char *zColname; /* The computed column name */ char *zToFree; /* Malloced string that needs to be freed */ Token sColname; /* Computed column name as a token */ |
︙ | ︙ | |||
6479 6480 6481 6482 6483 6484 6485 | ** ** This statement is so common that it is optimized specially. The ** OP_Count instruction is executed either on the intkey table that ** contains the data for table <tbl> or on one of its indexes. It ** is better to execute the op on an index, as indexes are almost ** always spread across less pages than their corresponding tables. */ | | > > | 6479 6480 6481 6482 6483 6484 6485 6486 6487 6488 6489 6490 6491 6492 6493 6494 6495 | ** ** This statement is so common that it is optimized specially. The ** OP_Count instruction is executed either on the intkey table that ** contains the data for table <tbl> or on one of its indexes. It ** is better to execute the op on an index, as indexes are almost ** always spread across less pages than their corresponding tables. */ const int iDb = sqlite3SchemaToIndex2( pParse->db, pTab->pSchema, pTabList->a[0].zDatabase ); const int iCsr = pParse->nTab++; /* Cursor to scan b-tree */ Index *pIdx; /* Iterator variable */ KeyInfo *pKeyInfo = 0; /* Keyinfo for scanned index */ Index *pBest = 0; /* Best index found so far */ int iRoot = pTab->tnum; /* Root page of scanned b-tree */ sqlite3CodeVerifySchema(pParse, iDb); |
︙ | ︙ |
Changes to src/sqliteInt.h.
︙ | ︙ | |||
4464 4465 4466 4467 4468 4469 4470 | ** no-op macros if OMIT_FOREIGN_KEY is defined. In this case no foreign ** key functionality is available. If OMIT_TRIGGER is defined but ** OMIT_FOREIGN_KEY is not, only some of the functions are no-oped. In ** this case foreign keys are parsed, but no other functionality is ** provided (enforcement of FK constraints requires the triggers sub-system). */ #if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER) | | | | 4464 4465 4466 4467 4468 4469 4470 4471 4472 4473 4474 4475 4476 4477 4478 4479 4480 4481 4482 4483 4484 4485 4486 | ** no-op macros if OMIT_FOREIGN_KEY is defined. In this case no foreign ** key functionality is available. If OMIT_TRIGGER is defined but ** OMIT_FOREIGN_KEY is not, only some of the functions are no-oped. In ** this case foreign keys are parsed, but no other functionality is ** provided (enforcement of FK constraints requires the triggers sub-system). */ #if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER) void sqlite3FkCheck(Parse*, int, Table*, int, int, int*, int); void sqlite3FkDropTable(Parse*, SrcList *, Table*); void sqlite3FkActions(Parse*, int, Table*, ExprList*, int, int*, int); int sqlite3FkRequired(Parse*, Table*, int*, int); u32 sqlite3FkOldmask(Parse*, Table*); FKey *sqlite3FkReferences(Table *); #else #define sqlite3FkActions(a,b,c,d,e,f,g) #define sqlite3FkCheck(a,b,c,d,e,f,g) #define sqlite3FkDropTable(a,b,c) #define sqlite3FkOldmask(a,b) 0 #define sqlite3FkRequired(a,b,c,d) 0 #define sqlite3FkReferences(a) 0 #endif #ifndef SQLITE_OMIT_FOREIGN_KEY void sqlite3FkDelete(sqlite3 *, Table*); |
︙ | ︙ |
Changes to src/trigger.c.
︙ | ︙ | |||
211 212 213 214 215 216 217 | sqlite3ErrorMsg(pParse, "cannot create INSTEAD OF" " trigger on table: %S", pTableName, 0); goto trigger_cleanup; } #ifndef SQLITE_OMIT_AUTHORIZATION if( !IN_RENAME_OBJECT ){ | | | 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 | sqlite3ErrorMsg(pParse, "cannot create INSTEAD OF" " trigger on table: %S", pTableName, 0); goto trigger_cleanup; } #ifndef SQLITE_OMIT_AUTHORIZATION if( !IN_RENAME_OBJECT ){ int iTabDb = sqlite3SchemaToIndex2(db, pTab->pSchema, 0); int code = SQLITE_CREATE_TRIGGER; const char *zDb = db->aDb[iTabDb].zDbSName; const char *zDbTrig = isTemp ? db->aDb[1].zDbSName : zDb; if( iTabDb==1 || isTemp ) code = SQLITE_CREATE_TEMP_TRIGGER; if( sqlite3AuthCheck(pParse, code, zName, pTab->zName, zDbTrig) ){ goto trigger_cleanup; } |
︙ | ︙ | |||
287 288 289 290 291 292 293 | DbFixer sFix; /* Fixer object */ int iDb; /* Database containing the trigger */ Token nameToken; /* Trigger name for error reporting */ pParse->pNewTrigger = 0; if( NEVER(pParse->nErr) || !pTrig ) goto triggerfinish_cleanup; zName = pTrig->zName; | | | 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 | DbFixer sFix; /* Fixer object */ int iDb; /* Database containing the trigger */ Token nameToken; /* Trigger name for error reporting */ pParse->pNewTrigger = 0; if( NEVER(pParse->nErr) || !pTrig ) goto triggerfinish_cleanup; zName = pTrig->zName; iDb = sqlite3SchemaToIndex2(pParse->db, pTrig->pSchema, 0); pTrig->step_list = pStepList; while( pStepList ){ pStepList->pTrig = pTrig; pStepList = pStepList->pNext; } sqlite3TokenInit(&nameToken, pTrig->zName); sqlite3FixInit(&sFix, pParse, iDb, "trigger", &nameToken); |
︙ | ︙ | |||
606 607 608 609 610 611 612 | */ void sqlite3DropTriggerPtr(Parse *pParse, Trigger *pTrigger){ Table *pTable; Vdbe *v; sqlite3 *db = pParse->db; int iDb; | | | 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 | */ void sqlite3DropTriggerPtr(Parse *pParse, Trigger *pTrigger){ Table *pTable; Vdbe *v; sqlite3 *db = pParse->db; int iDb; iDb = sqlite3SchemaToIndex2(pParse->db, pTrigger->pSchema, 0); assert( iDb>=0 && iDb<db->nDb ); sqlite3SchemaWritable(pParse, iDb); pTable = tableOfTrigger(pTrigger); assert( pTable ); assert( pTable->pSchema==pTrigger->pSchema || iDb==1 ); #ifndef SQLITE_OMIT_AUTHORIZATION { |
︙ | ︙ |
Changes to src/update.c.
︙ | ︙ | |||
712 713 714 715 716 717 718 | assert( regOldRowid>0 ); sqlite3GenerateConstraintChecks(pParse, iDb, pTab, aRegIdx, iDataCur, iIdxCur, regNewRowid, regOldRowid, chngKey, onError, labelContinue, &bReplace, aXRef, 0); /* Do FK constraint checks. */ if( hasFK ){ | | | 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 | assert( regOldRowid>0 ); sqlite3GenerateConstraintChecks(pParse, iDb, pTab, aRegIdx, iDataCur, iIdxCur, regNewRowid, regOldRowid, chngKey, onError, labelContinue, &bReplace, aXRef, 0); /* Do FK constraint checks. */ if( hasFK ){ sqlite3FkCheck(pParse, iDb, pTab, regOldRowid, 0, aXRef, chngKey); } /* Delete the index entries associated with the current record. */ if( bReplace || chngKey ){ if( pPk ){ addr1 = sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, 0, regKey, nKey); }else{ |
︙ | ︙ | |||
758 759 760 761 762 763 764 | } #endif if( bReplace || chngKey ){ sqlite3VdbeJumpHere(v, addr1); } if( hasFK ){ | | | 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 | } #endif if( bReplace || chngKey ){ sqlite3VdbeJumpHere(v, addr1); } if( hasFK ){ sqlite3FkCheck(pParse, iDb, pTab, 0, regNewRowid, aXRef, chngKey); } /* Insert the new index entries and the new record. */ sqlite3CompleteInsertion( pParse, pTab, iDataCur, iIdxCur, regNewRowid, aRegIdx, OPFLAG_ISUPDATE | (eOnePass==ONEPASS_MULTI ? OPFLAG_SAVEPOSITION : 0), 0, 0 |
︙ | ︙ |
Changes to src/vdbeblob.c.
︙ | ︙ | |||
179 180 181 182 183 184 185 | sParse.zErrMsg = 0; } rc = SQLITE_ERROR; sqlite3BtreeLeaveAll(db); goto blob_open_out; } pBlob->pTab = pTab; | | | 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 | sParse.zErrMsg = 0; } rc = SQLITE_ERROR; sqlite3BtreeLeaveAll(db); goto blob_open_out; } pBlob->pTab = pTab; pBlob->zDb = db->aDb[sqlite3SchemaToIndex2(db,pTab->pSchema,zDb)].zDbSName; /* Now search pTab for the exact column. */ for(iCol=0; iCol<pTab->nCol; iCol++) { if( sqlite3StrICmp(pTab->aCol[iCol].zName, zColumn)==0 ){ break; } } |
︙ | ︙ | |||
266 267 268 269 270 271 272 | /* blobSeekToRow() will initialize r[1] to the desired rowid */ {OP_NotExists, 0, 5, 1}, /* 2: Seek the cursor to rowid=r[1] */ {OP_Column, 0, 0, 1}, /* 3 */ {OP_ResultRow, 1, 0, 0}, /* 4 */ {OP_Halt, 0, 0, 0}, /* 5 */ }; Vdbe *v = (Vdbe *)pBlob->pStmt; | | | 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 | /* blobSeekToRow() will initialize r[1] to the desired rowid */ {OP_NotExists, 0, 5, 1}, /* 2: Seek the cursor to rowid=r[1] */ {OP_Column, 0, 0, 1}, /* 3 */ {OP_ResultRow, 1, 0, 0}, /* 4 */ {OP_Halt, 0, 0, 0}, /* 5 */ }; Vdbe *v = (Vdbe *)pBlob->pStmt; int iDb = sqlite3SchemaToIndex2(db, pTab->pSchema, zDb); VdbeOp *aOp; sqlite3VdbeAddOp4Int(v, OP_Transaction, iDb, wrFlag, pTab->pSchema->schema_cookie, pTab->pSchema->iGeneration); sqlite3VdbeChangeP5(v, 1); assert( sqlite3VdbeCurrentAddr(v)==2 || db->mallocFailed ); |
︙ | ︙ |
Changes to test/reuse1.test.
︙ | ︙ | |||
304 305 306 307 308 309 310 311 312 313 314 315 | 4 { ANALYZE main } 5 { ANALYZE main.t1 } 6 { ANALYZE main.i1 } } { do_catchsql_test 5.4.$tn $sql {1 {attempt to modify read-only schema}} } finish_test | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 | 4 { ANALYZE main } 5 { ANALYZE main.t1 } 6 { ANALYZE main.i1 } } { do_catchsql_test 5.4.$tn $sql {1 {attempt to modify read-only schema}} } #------------------------------------------------------------------------- # reset_db do_execsql_test 6.0 { CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c); CREATE VIEW v1 AS SELECT * FROM t1; } db close forcecopy test.db test.db2 sqlite3 db test.db -reuse-schema 1 execsql { ATTACH 'test.db2' AS aux } do_execsql_test 6.1 { INSERT INTO main.t1(a) VALUES(1), (2), (3); INSERT INTO aux.t1(a) VALUES(4), (5), (6); CREATE TEMP TABLE t2(i,t); INSERT INTO t2 VALUES(2, 'two'), (5, 'five'); } do_execsql_test 6.2 { SELECT t FROM t2 WHERE i IN (SELECT a FROM aux.t1) } {five} do_execsql_test 6.3 { SELECT t FROM t2 WHERE i IN (SELECT a FROM aux.v1) } {five} #------------------------------------------------------------------------- # reset_db do_execsql_test 7.0 { CREATE TABLE p1(a PRIMARY KEY, b); CREATE TABLE p2(a PRIMARY KEY, b); CREATE TABLE c1(x REFERENCES p1 ON UPDATE CASCADE ON DELETE CASCADE); } db close forcecopy test.db test.db2 sqlite3 db test.db -reuse-schema 1 execsql { ATTACH 'test.db2' AS aux } do_execsql_test 7.1 { INSERT INTO aux.p1 VALUES(1, 'one'); INSERT INTO aux.p1 VALUES(2, 'two'); PRAGMA foreign_keys = on; } do_execsql_test 7.2 { INSERT INTO aux.c1 VALUES(2); } do_execsql_test 7.3.1 { PRAGMA foreign_keys = off; INSERT INTO main.p2 SELECT * FROM aux.p1; } do_execsql_test 7.3.2 { SELECT * FROM main.p2; } {1 one 2 two} do_execsql_test 7.3.3 { INSERT INTO aux.p2 VALUES(1, 2); } do_execsql_test 7.3.4 { SELECT main.p2.a FROM main.p2, aux.p2; } {1 2} do_execsql_test 7.3.5 { SELECT * FROM main.p2, aux.p2; } {1 one 1 2 2 two 1 2} do_execsql_test 7.4 { SELECT count(*) FROM aux.p2; } {1} finish_test |