?? build.c
字號:
sqliteVdbeAddOp(v, OP_NewRecno, 0, 0); sqliteVdbeOp3(v, OP_String, 0, 0, "index", P3_STATIC); sqliteVdbeOp3(v, OP_String, 0, 0, pIndex->zName, 0); sqliteVdbeOp3(v, OP_String, 0, 0, pTab->zName, 0); sqliteVdbeOp3(v, OP_CreateIndex, 0, isTemp,(char*)&pIndex->tnum,P3_POINTER); pIndex->tnum = 0; if( pTable ){ sqliteVdbeCode(v, OP_Dup, 0, 0, OP_Integer, isTemp, 0, OP_OpenWrite, 1, 0, 0); } addr = sqliteVdbeAddOp(v, OP_String, 0, 0); if( pStart && pEnd ){ n = Addr(pEnd->z) - Addr(pStart->z) + 1; sqliteVdbeChangeP3(v, addr, pStart->z, n); } sqliteVdbeAddOp(v, OP_MakeRecord, 5, 0); sqliteVdbeAddOp(v, OP_PutIntKey, 0, 0); if( pTable ){ sqliteVdbeAddOp(v, OP_Integer, pTab->iDb, 0); sqliteVdbeOp3(v, OP_OpenRead, 2, pTab->tnum, pTab->zName, 0); lbl2 = sqliteVdbeMakeLabel(v); sqliteVdbeAddOp(v, OP_Rewind, 2, lbl2); lbl1 = sqliteVdbeAddOp(v, OP_Recno, 2, 0); for(i=0; i<pIndex->nColumn; i++){ int iCol = pIndex->aiColumn[i]; if( pTab->iPKey==iCol ){ sqliteVdbeAddOp(v, OP_Dup, i, 0); }else{ sqliteVdbeAddOp(v, OP_Column, 2, iCol); } } sqliteVdbeAddOp(v, OP_MakeIdxKey, pIndex->nColumn, 0); if( db->file_format>=4 ) sqliteAddIdxKeyType(v, pIndex); sqliteVdbeOp3(v, OP_IdxPut, 1, pIndex->onError!=OE_None, "indexed columns are not unique", P3_STATIC); sqliteVdbeAddOp(v, OP_Next, 2, lbl1); sqliteVdbeResolveLabel(v, lbl2); sqliteVdbeAddOp(v, OP_Close, 2, 0); sqliteVdbeAddOp(v, OP_Close, 1, 0); } if( pTable!=0 ){ if( !isTemp ){ sqliteChangeCookie(db, v); } sqliteVdbeAddOp(v, OP_Close, 0, 0); sqliteEndWriteOperation(pParse); } } /* Clean up before exiting */exit_create_index: sqliteIdListDelete(pList); sqliteSrcListDelete(pTable); sqliteFree(zName); return;}/*** This routine will drop an existing named index. This routine** implements the DROP INDEX statement.*/void sqliteDropIndex(Parse *pParse, SrcList *pName){ Index *pIndex; Vdbe *v; sqlite *db = pParse->db; if( pParse->nErr || sqlite_malloc_failed ) return; assert( pName->nSrc==1 ); pIndex = sqliteFindIndex(db, pName->a[0].zName, pName->a[0].zDatabase); if( pIndex==0 ){ sqliteErrorMsg(pParse, "no such index: %S", pName, 0); goto exit_drop_index; } if( pIndex->autoIndex ){ sqliteErrorMsg(pParse, "index associated with UNIQUE " "or PRIMARY KEY constraint cannot be dropped", 0); goto exit_drop_index; } if( pIndex->iDb>1 ){ sqliteErrorMsg(pParse, "cannot alter schema of attached " "databases", 0); goto exit_drop_index; }#ifndef SQLITE_OMIT_AUTHORIZATION { int code = SQLITE_DROP_INDEX; Table *pTab = pIndex->pTable; const char *zDb = db->aDb[pIndex->iDb].zName; const char *zTab = SCHEMA_TABLE(pIndex->iDb); if( sqliteAuthCheck(pParse, SQLITE_DELETE, zTab, 0, zDb) ){ goto exit_drop_index; } if( pIndex->iDb ) code = SQLITE_DROP_TEMP_INDEX; if( sqliteAuthCheck(pParse, code, pIndex->zName, pTab->zName, zDb) ){ goto exit_drop_index; } }#endif /* Generate code to remove the index and from the master table */ v = sqliteGetVdbe(pParse); if( v ){ static VdbeOpList dropIndex[] = { { OP_Rewind, 0, ADDR(9), 0}, { OP_String, 0, 0, 0}, /* 1 */ { OP_MemStore, 1, 1, 0}, { OP_MemLoad, 1, 0, 0}, /* 3 */ { OP_Column, 0, 1, 0}, { OP_Eq, 0, ADDR(8), 0}, { OP_Next, 0, ADDR(3), 0}, { OP_Goto, 0, ADDR(9), 0}, { OP_Delete, 0, 0, 0}, /* 8 */ }; int base; sqliteBeginWriteOperation(pParse, 0, pIndex->iDb); sqliteOpenMasterTable(v, pIndex->iDb); base = sqliteVdbeAddOpList(v, ArraySize(dropIndex), dropIndex); sqliteVdbeChangeP3(v, base+1, pIndex->zName, 0); if( pIndex->iDb==0 ){ sqliteChangeCookie(db, v); } sqliteVdbeAddOp(v, OP_Close, 0, 0); sqliteVdbeAddOp(v, OP_Destroy, pIndex->tnum, pIndex->iDb); sqliteEndWriteOperation(pParse); } /* Delete the in-memory description of this index. */ if( !pParse->explain ){ sqliteUnlinkAndDeleteIndex(db, pIndex); db->flags |= SQLITE_InternChanges; }exit_drop_index: sqliteSrcListDelete(pName);}/*** Append a new element to the given IdList. Create a new IdList if** need be.**** A new IdList is returned, or NULL if malloc() fails.*/IdList *sqliteIdListAppend(IdList *pList, Token *pToken){ if( pList==0 ){ pList = sqliteMalloc( sizeof(IdList) ); if( pList==0 ) return 0; pList->nAlloc = 0; } if( pList->nId>=pList->nAlloc ){ struct IdList_item *a; pList->nAlloc = pList->nAlloc*2 + 5; a = sqliteRealloc(pList->a, pList->nAlloc*sizeof(pList->a[0]) ); if( a==0 ){ sqliteIdListDelete(pList); return 0; } pList->a = a; } memset(&pList->a[pList->nId], 0, sizeof(pList->a[0])); if( pToken ){ char **pz = &pList->a[pList->nId].zName; sqliteSetNString(pz, pToken->z, pToken->n, 0); if( *pz==0 ){ sqliteIdListDelete(pList); return 0; }else{ sqliteDequote(*pz); } } pList->nId++; return pList;}/*** Append a new table name to the given SrcList. Create a new SrcList if** need be. A new entry is created in the SrcList even if pToken is NULL.**** A new SrcList is returned, or NULL if malloc() fails.**** If pDatabase is not null, it means that the table has an optional** database name prefix. Like this: "database.table". The pDatabase** points to the table name and the pTable points to the database name.** The SrcList.a[].zName field is filled with the table name which might** come from pTable (if pDatabase is NULL) or from pDatabase. ** SrcList.a[].zDatabase is filled with the database name from pTable,** or with NULL if no database is specified.**** In other words, if call like this:**** sqliteSrcListAppend(A,B,0);**** Then B is a table name and the database name is unspecified. If called** like this:**** sqliteSrcListAppend(A,B,C);**** Then C is the table name and B is the database name.*/SrcList *sqliteSrcListAppend(SrcList *pList, Token *pTable, Token *pDatabase){ if( pList==0 ){ pList = sqliteMalloc( sizeof(SrcList) ); if( pList==0 ) return 0; pList->nAlloc = 1; } if( pList->nSrc>=pList->nAlloc ){ SrcList *pNew; pList->nAlloc *= 2; pNew = sqliteRealloc(pList, sizeof(*pList) + (pList->nAlloc-1)*sizeof(pList->a[0]) ); if( pNew==0 ){ sqliteSrcListDelete(pList); return 0; } pList = pNew; } memset(&pList->a[pList->nSrc], 0, sizeof(pList->a[0])); if( pDatabase && pDatabase->z==0 ){ pDatabase = 0; } if( pDatabase && pTable ){ Token *pTemp = pDatabase; pDatabase = pTable; pTable = pTemp; } if( pTable ){ char **pz = &pList->a[pList->nSrc].zName; sqliteSetNString(pz, pTable->z, pTable->n, 0); if( *pz==0 ){ sqliteSrcListDelete(pList); return 0; }else{ sqliteDequote(*pz); } } if( pDatabase ){ char **pz = &pList->a[pList->nSrc].zDatabase; sqliteSetNString(pz, pDatabase->z, pDatabase->n, 0); if( *pz==0 ){ sqliteSrcListDelete(pList); return 0; }else{ sqliteDequote(*pz); } } pList->a[pList->nSrc].iCursor = -1; pList->nSrc++; return pList;}/*** Assign cursors to all tables in a SrcList*/void sqliteSrcListAssignCursors(Parse *pParse, SrcList *pList){ int i; for(i=0; i<pList->nSrc; i++){ if( pList->a[i].iCursor<0 ){ pList->a[i].iCursor = pParse->nTab++; } }}/*** Add an alias to the last identifier on the given identifier list.*/void sqliteSrcListAddAlias(SrcList *pList, Token *pToken){ if( pList && pList->nSrc>0 ){ int i = pList->nSrc - 1; sqliteSetNString(&pList->a[i].zAlias, pToken->z, pToken->n, 0); sqliteDequote(pList->a[i].zAlias); }}/*** Delete an IdList.*/void sqliteIdListDelete(IdList *pList){ int i; if( pList==0 ) return; for(i=0; i<pList->nId; i++){ sqliteFree(pList->a[i].zName); } sqliteFree(pList->a); sqliteFree(pList);}/*** Return the index in pList of the identifier named zId. Return -1** if not found.*/int sqliteIdListIndex(IdList *pList, const char *zName){ int i; if( pList==0 ) return -1; for(i=0; i<pList->nId; i++){ if( sqliteStrICmp(pList->a[i].zName, zName)==0 ) return i; } return -1;}/*** Delete an entire SrcList including all its substructure.*/void sqliteSrcListDelete(SrcList *pList){ int i; if( pList==0 ) return; for(i=0; i<pList->nSrc; i++){ sqliteFree(pList->a[i].zDatabase); sqliteFree(pList->a[i].zName); sqliteFree(pList->a[i].zAlias); if( pList->a[i].pTab && pList->a[i].pTab->isTransient ){ sqliteDeleteTable(0, pList->a[i].pTab); } sqliteSelectDelete(pList->a[i].pSelect); sqliteExprDelete(pList->a[i].pOn); sqliteIdListDelete(pList->a[i].pUsing); } sqliteFree(pList);}/*** Begin a transaction*/void sqliteBeginTransaction(Parse *pParse, int onError){ sqlite *db; if( pParse==0 || (db=pParse->db)==0 || db->aDb[0].pBt==0 ) return; if( pParse->nErr || sqlite_malloc_failed ) return; if( sqliteAuthCheck(pParse, SQLITE_TRANSACTION, "BEGIN", 0, 0) ) return; if( db->flags & SQLITE_InTrans ){ sqliteErrorMsg(pParse, "cannot start a transaction within a transaction"); return; } sqliteBeginWriteOperation(pParse, 0, 0); if( !pParse->explain ){ db->flags |= SQLITE_InTrans; db->onError = onError; }}/*** Commit a transaction*/void sqliteCommitTransaction(Parse *pParse){ sqlite *db; if( pParse==0 || (db=pParse->db)==0 || db->aDb[0].pBt==0 ) return; if( pParse->nErr || sqlite_malloc_failed ) return; if( sqliteAuthCheck(pParse, SQLITE_TRANSACTION, "COMMIT", 0, 0) ) return; if( (db->flags & SQLITE_InTrans)==0 ){ sqliteErrorMsg(pParse, "cannot commit - no transaction is active"); return; } if( !pParse->explain ){ db->flags &= ~SQLITE_InTrans; } sqliteEndWriteOperation(pParse); if( !pParse->explain ){ db->onError = OE_Default; }}/*** Rollback a transaction*/void sqliteRollbackTransaction(Parse *pParse){ sqlite *db; Vdbe *v; if( pParse==0 || (db=pParse->db)==0 || db->aDb[0].pBt==0 ) return; if( pParse->nErr || sqlite_malloc_failed ) return; if( sqliteAuthCheck(pParse, SQLITE_TRANSACTION, "ROLLBACK", 0, 0) ) return; if( (db->flags & SQLITE_InTrans)==0 ){ sqliteErrorMsg(pParse, "cannot rollback - no transaction is active"); return; } v = sqliteGetVdbe(pParse); if( v ){ sqliteVdbeAddOp(v, OP_Rollback, 0, 0); } if( !pParse->explain ){ db->flags &= ~SQLITE_InTrans; db->onError = OE_Default; }}/*** Generate VDBE code that will verify the schema cookie for all** named database files.*/void sqliteCodeVerifySchema(Parse *pParse, int iDb){ sqlite *db = pParse->db; Vdbe *v = sqliteGetVdbe(pParse); assert( iDb>=0 && iDb<db->nDb ); assert( db->aDb[iDb].pBt!=0 ); if( iDb!=1 && !DbHasProperty(db, iDb, DB_Cookie) ){ sqliteVdbeAddOp(v, OP_VerifyCookie, iDb, db->aDb[iDb].schema_cookie); DbSetProperty(db, iDb, DB_Cookie); }}/*** Generate VDBE code that prepares for doing an operation that** might change the database.**** This routine starts a new transaction if we are not already within** a transaction. If we are already within a transaction, then a checkpoint** is set if the setCheckpoint parameter is true. A checkpoint should** be set for operations that might fail (due to a constraint) part of** the way through and which will need to undo some writes without having to** rollback the whole transaction. For operations where all constraints** can be checked before any changes are made to the database, it is never** necessary to undo a write and the checkpoint should not be set.**** Only database iDb and the temp database are made writable by this call.** If iDb==0, then the main and te
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -