build.c.svn-base
上传用户:sunhongbo
上传日期:2022-01-25
资源大小:3010k
文件大小:110k
- /*
- ** 2001 September 15
- **
- ** The author disclaims copyright to this source code. In place of
- ** a legal notice, here is a blessing:
- **
- ** May you do good and not evil.
- ** May you find forgiveness for yourself and forgive others.
- ** May you share freely, never taking more than you give.
- **
- *************************************************************************
- ** This file contains C code routines that are called by the SQLite parser
- ** when syntax rules are reduced. The routines in this file handle the
- ** following kinds of SQL syntax:
- **
- ** CREATE TABLE
- ** DROP TABLE
- ** CREATE INDEX
- ** DROP INDEX
- ** creating ID lists
- ** BEGIN TRANSACTION
- ** COMMIT
- ** ROLLBACK
- **
- ** $Id: build.c,v 1.480 2008/04/11 17:11:27 danielk1977 Exp $
- */
- #include "sqliteInt.h"
- #include <ctype.h>
- /*
- ** This routine is called when a new SQL statement is beginning to
- ** be parsed. Initialize the pParse structure as needed.
- */
- void sqlite3BeginParse(Parse *pParse, int explainFlag){
- pParse->explain = explainFlag;
- pParse->nVar = 0;
- }
- #ifndef SQLITE_OMIT_SHARED_CACHE
- /*
- ** The TableLock structure is only used by the sqlite3TableLock() and
- ** codeTableLocks() functions.
- */
- struct TableLock {
- int iDb; /* The database containing the table to be locked */
- int iTab; /* The root page of the table to be locked */
- u8 isWriteLock; /* True for write lock. False for a read lock */
- const char *zName; /* Name of the table */
- };
- /*
- ** Record the fact that we want to lock a table at run-time.
- **
- ** The table to be locked has root page iTab and is found in database iDb.
- ** A read or a write lock can be taken depending on isWritelock.
- **
- ** This routine just records the fact that the lock is desired. The
- ** code to make the lock occur is generated by a later call to
- ** codeTableLocks() which occurs during sqlite3FinishCoding().
- */
- void sqlite3TableLock(
- Parse *pParse, /* Parsing context */
- int iDb, /* Index of the database containing the table to lock */
- int iTab, /* Root page number of the table to be locked */
- u8 isWriteLock, /* True for a write lock */
- const char *zName /* Name of the table to be locked */
- ){
- int i;
- int nBytes;
- TableLock *p;
- if( iDb<0 ){
- return;
- }
- for(i=0; i<pParse->nTableLock; i++){
- p = &pParse->aTableLock[i];
- if( p->iDb==iDb && p->iTab==iTab ){
- p->isWriteLock = (p->isWriteLock || isWriteLock);
- return;
- }
- }
- nBytes = sizeof(TableLock) * (pParse->nTableLock+1);
- pParse->aTableLock =
- sqlite3DbReallocOrFree(pParse->db, pParse->aTableLock, nBytes);
- if( pParse->aTableLock ){
- p = &pParse->aTableLock[pParse->nTableLock++];
- p->iDb = iDb;
- p->iTab = iTab;
- p->isWriteLock = isWriteLock;
- p->zName = zName;
- }else{
- pParse->nTableLock = 0;
- pParse->db->mallocFailed = 1;
- }
- }
- /*
- ** Code an OP_TableLock instruction for each table locked by the
- ** statement (configured by calls to sqlite3TableLock()).
- */
- static void codeTableLocks(Parse *pParse){
- int i;
- Vdbe *pVdbe;
- if( 0==(pVdbe = sqlite3GetVdbe(pParse)) ){
- return;
- }
- for(i=0; i<pParse->nTableLock; i++){
- TableLock *p = &pParse->aTableLock[i];
- int p1 = p->iDb;
- sqlite3VdbeAddOp4(pVdbe, OP_TableLock, p1, p->iTab, p->isWriteLock,
- p->zName, P4_STATIC);
- }
- }
- #else
- #define codeTableLocks(x)
- #endif
- /*
- ** This routine is called after a single SQL statement has been
- ** parsed and a VDBE program to execute that statement has been
- ** prepared. This routine puts the finishing touches on the
- ** VDBE program and resets the pParse structure for the next
- ** parse.
- **
- ** Note that if an error occurred, it might be the case that
- ** no VDBE code was generated.
- */
- void sqlite3FinishCoding(Parse *pParse){
- sqlite3 *db;
- Vdbe *v;
- db = pParse->db;
- if( db->mallocFailed ) return;
- if( pParse->nested ) return;
- if( pParse->nErr ) return;
- if( !pParse->pVdbe ){
- if( pParse->rc==SQLITE_OK && pParse->nErr ){
- pParse->rc = SQLITE_ERROR;
- return;
- }
- }
- /* Begin by generating some termination code at the end of the
- ** vdbe program
- */
- v = sqlite3GetVdbe(pParse);
- if( v ){
- sqlite3VdbeAddOp0(v, OP_Halt);
- /* The cookie mask contains one bit for each database file open.
- ** (Bit 0 is for main, bit 1 is for temp, and so forth.) Bits are
- ** set for each database that is used. Generate code to start a
- ** transaction on each used database and to verify the schema cookie
- ** on each used database.
- */
- if( pParse->cookieGoto>0 ){
- u32 mask;
- int iDb;
- sqlite3VdbeJumpHere(v, pParse->cookieGoto-1);
- for(iDb=0, mask=1; iDb<db->nDb; mask<<=1, iDb++){
- if( (mask & pParse->cookieMask)==0 ) continue;
- sqlite3VdbeUsesBtree(v, iDb);
- sqlite3VdbeAddOp2(v,OP_Transaction, iDb, (mask & pParse->writeMask)!=0);
- sqlite3VdbeAddOp2(v,OP_VerifyCookie, iDb, pParse->cookieValue[iDb]);
- }
- #ifndef SQLITE_OMIT_VIRTUALTABLE
- if( pParse->pVirtualLock ){
- char *vtab = (char *)pParse->pVirtualLock->pVtab;
- sqlite3VdbeAddOp4(v, OP_VBegin, 0, 0, 0, vtab, P4_VTAB);
- }
- #endif
- /* Once all the cookies have been verified and transactions opened,
- ** obtain the required table-locks. This is a no-op unless the
- ** shared-cache feature is enabled.
- */
- codeTableLocks(pParse);
- sqlite3VdbeAddOp2(v, OP_Goto, 0, pParse->cookieGoto);
- }
- #ifndef SQLITE_OMIT_TRACE
- if( !db->init.busy ){
- /* Change the P4 argument of the first opcode (which will always be
- ** an OP_Trace) to be the complete text of the current SQL statement.
- */
- VdbeOp *pOp = sqlite3VdbeGetOp(v, 0);
- if( pOp && pOp->opcode==OP_Trace ){
- sqlite3VdbeChangeP4(v, 0, pParse->zSql, pParse->zTail-pParse->zSql);
- }
- }
- #endif /* SQLITE_OMIT_TRACE */
- }
- /* Get the VDBE program ready for execution
- */
- if( v && pParse->nErr==0 && !db->mallocFailed ){
- #ifdef SQLITE_DEBUG
- FILE *trace = (db->flags & SQLITE_VdbeTrace)!=0 ? stdout : 0;
- sqlite3VdbeTrace(v, trace);
- #endif
- assert( pParse->disableColCache==0 ); /* Disables and re-enables match */
- sqlite3VdbeMakeReady(v, pParse->nVar, pParse->nMem+3,
- pParse->nTab+3, pParse->explain);
- pParse->rc = SQLITE_DONE;
- pParse->colNamesSet = 0;
- }else if( pParse->rc==SQLITE_OK ){
- pParse->rc = SQLITE_ERROR;
- }
- pParse->nTab = 0;
- pParse->nMem = 0;
- pParse->nSet = 0;
- pParse->nVar = 0;
- pParse->cookieMask = 0;
- pParse->cookieGoto = 0;
- }
- /*
- ** Run the parser and code generator recursively in order to generate
- ** code for the SQL statement given onto the end of the pParse context
- ** currently under construction. When the parser is run recursively
- ** this way, the final OP_Halt is not appended and other initialization
- ** and finalization steps are omitted because those are handling by the
- ** outermost parser.
- **
- ** Not everything is nestable. This facility is designed to permit
- ** INSERT, UPDATE, and DELETE operations against SQLITE_MASTER. Use
- ** care if you decide to try to use this routine for some other purposes.
- */
- void sqlite3NestedParse(Parse *pParse, const char *zFormat, ...){
- va_list ap;
- char *zSql;
- # define SAVE_SZ (sizeof(Parse) - offsetof(Parse,nVar))
- char saveBuf[SAVE_SZ];
- if( pParse->nErr ) return;
- assert( pParse->nested<10 ); /* Nesting should only be of limited depth */
- va_start(ap, zFormat);
- zSql = sqlite3VMPrintf(pParse->db, zFormat, ap);
- va_end(ap);
- if( zSql==0 ){
- pParse->db->mallocFailed = 1;
- return; /* A malloc must have failed */
- }
- pParse->nested++;
- memcpy(saveBuf, &pParse->nVar, SAVE_SZ);
- memset(&pParse->nVar, 0, SAVE_SZ);
- sqlite3RunParser(pParse, zSql, 0);
- sqlite3_free(zSql);
- memcpy(&pParse->nVar, saveBuf, SAVE_SZ);
- pParse->nested--;
- }
- /*
- ** Locate the in-memory structure that describes a particular database
- ** table given the name of that table and (optionally) the name of the
- ** database containing the table. Return NULL if not found.
- **
- ** If zDatabase is 0, all databases are searched for the table and the
- ** first matching table is returned. (No checking for duplicate table
- ** names is done.) The search order is TEMP first, then MAIN, then any
- ** auxiliary databases added using the ATTACH command.
- **
- ** See also sqlite3LocateTable().
- */
- Table *sqlite3FindTable(sqlite3 *db, const char *zName, const char *zDatabase){
- Table *p = 0;
- int i;
- assert( zName!=0 );
- for(i=OMIT_TEMPDB; i<db->nDb; i++){
- int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */
- if( zDatabase!=0 && sqlite3StrICmp(zDatabase, db->aDb[j].zName) ) continue;
- p = sqlite3HashFind(&db->aDb[j].pSchema->tblHash, zName, strlen(zName)+1);
- if( p ) break;
- }
- return p;
- }
- /*
- ** Locate the in-memory structure that describes a particular database
- ** table given the name of that table and (optionally) the name of the
- ** database containing the table. Return NULL if not found. Also leave an
- ** error message in pParse->zErrMsg.
- **
- ** The difference between this routine and sqlite3FindTable() is that this
- ** routine leaves an error message in pParse->zErrMsg where
- ** sqlite3FindTable() does not.
- */
- Table *sqlite3LocateTable(
- Parse *pParse, /* context in which to report errors */
- int isView, /* True if looking for a VIEW rather than a TABLE */
- const char *zName, /* Name of the table we are looking for */
- const char *zDbase /* Name of the database. Might be NULL */
- ){
- Table *p;
- /* Read the database schema. If an error occurs, leave an error message
- ** and code in pParse and return NULL. */
- if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){
- return 0;
- }
- p = sqlite3FindTable(pParse->db, zName, zDbase);
- if( p==0 ){
- const char *zMsg = isView ? "no such view" : "no such table";
- if( zDbase ){
- sqlite3ErrorMsg(pParse, "%s: %s.%s", zMsg, zDbase, zName);
- }else{
- sqlite3ErrorMsg(pParse, "%s: %s", zMsg, zName);
- }
- pParse->checkSchema = 1;
- }
- return p;
- }
- /*
- ** Locate the in-memory structure that describes
- ** a particular index given the name of that index
- ** and the name of the database that contains the index.
- ** Return NULL if not found.
- **
- ** If zDatabase is 0, all databases are searched for the
- ** table and the first matching index is returned. (No checking
- ** for duplicate index names is done.) The search order is
- ** TEMP first, then MAIN, then any auxiliary databases added
- ** using the ATTACH command.
- */
- Index *sqlite3FindIndex(sqlite3 *db, const char *zName, const char *zDb){
- Index *p = 0;
- int i;
- for(i=OMIT_TEMPDB; i<db->nDb; i++){
- int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */
- Schema *pSchema = db->aDb[j].pSchema;
- if( zDb && sqlite3StrICmp(zDb, db->aDb[j].zName) ) continue;
- assert( pSchema || (j==1 && !db->aDb[1].pBt) );
- if( pSchema ){
- p = sqlite3HashFind(&pSchema->idxHash, zName, strlen(zName)+1);
- }
- if( p ) break;
- }
- return p;
- }
- /*
- ** Reclaim the memory used by an index
- */
- static void freeIndex(Index *p){
- sqlite3_free(p->zColAff);
- sqlite3_free(p);
- }
- /*
- ** Remove the given index from the index hash table, and free
- ** its memory structures.
- **
- ** The index is removed from the database hash tables but
- ** it is not unlinked from the Table that it indexes.
- ** Unlinking from the Table must be done by the calling function.
- */
- static void sqliteDeleteIndex(Index *p){
- Index *pOld;
- const char *zName = p->zName;
- pOld = sqlite3HashInsert(&p->pSchema->idxHash, zName, strlen( zName)+1, 0);
- assert( pOld==0 || pOld==p );
- freeIndex(p);
- }
- /*
- ** For the index called zIdxName which is found in the database iDb,
- ** unlike that index from its Table then remove the index from
- ** the index hash table and free all memory structures associated
- ** with the index.
- */
- void sqlite3UnlinkAndDeleteIndex(sqlite3 *db, int iDb, const char *zIdxName){
- Index *pIndex;
- int len;
- Hash *pHash = &db->aDb[iDb].pSchema->idxHash;
- len = strlen(zIdxName);
- pIndex = sqlite3HashInsert(pHash, zIdxName, len+1, 0);
- if( pIndex ){
- if( pIndex->pTable->pIndex==pIndex ){
- pIndex->pTable->pIndex = pIndex->pNext;
- }else{
- Index *p;
- for(p=pIndex->pTable->pIndex; p && p->pNext!=pIndex; p=p->pNext){}
- if( p && p->pNext==pIndex ){
- p->pNext = pIndex->pNext;
- }
- }
- freeIndex(pIndex);
- }
- db->flags |= SQLITE_InternChanges;
- }
- /*
- ** Erase all schema information from the in-memory hash tables of
- ** a single database. This routine is called to reclaim memory
- ** before the database closes. It is also called during a rollback
- ** if there were schema changes during the transaction or if a
- ** schema-cookie mismatch occurs.
- **
- ** If iDb<=0 then reset the internal schema tables for all database
- ** files. If iDb>=2 then reset the internal schema for only the
- ** single file indicated.
- */
- void sqlite3ResetInternalSchema(sqlite3 *db, int iDb){
- int i, j;
- assert( iDb>=0 && iDb<db->nDb );
- if( iDb==0 ){
- sqlite3BtreeEnterAll(db);
- }
- for(i=iDb; i<db->nDb; i++){
- Db *pDb = &db->aDb[i];
- if( pDb->pSchema ){
- assert(i==1 || (pDb->pBt && sqlite3BtreeHoldsMutex(pDb->pBt)));
- sqlite3SchemaFree(pDb->pSchema);
- }
- if( iDb>0 ) return;
- }
- assert( iDb==0 );
- db->flags &= ~SQLITE_InternChanges;
- sqlite3BtreeLeaveAll(db);
- /* If one or more of the auxiliary database files has been closed,
- ** then remove them from the auxiliary database list. We take the
- ** opportunity to do this here since we have just deleted all of the
- ** schema hash tables and therefore do not have to make any changes
- ** to any of those tables.
- */
- for(i=0; i<db->nDb; i++){
- struct Db *pDb = &db->aDb[i];
- if( pDb->pBt==0 ){
- if( pDb->pAux && pDb->xFreeAux ) pDb->xFreeAux(pDb->pAux);
- pDb->pAux = 0;
- }
- }
- for(i=j=2; i<db->nDb; i++){
- struct Db *pDb = &db->aDb[i];
- if( pDb->pBt==0 ){
- sqlite3_free(pDb->zName);
- pDb->zName = 0;
- continue;
- }
- if( j<i ){
- db->aDb[j] = db->aDb[i];
- }
- j++;
- }
- memset(&db->aDb[j], 0, (db->nDb-j)*sizeof(db->aDb[j]));
- db->nDb = j;
- if( db->nDb<=2 && db->aDb!=db->aDbStatic ){
- memcpy(db->aDbStatic, db->aDb, 2*sizeof(db->aDb[0]));
- sqlite3_free(db->aDb);
- db->aDb = db->aDbStatic;
- }
- }
- /*
- ** This routine is called when a commit occurs.
- */
- void sqlite3CommitInternalChanges(sqlite3 *db){
- db->flags &= ~SQLITE_InternChanges;
- }
- /*
- ** Clear the column names from a table or view.
- */
- static void sqliteResetColumnNames(Table *pTable){
- int i;
- Column *pCol;
- assert( pTable!=0 );
- if( (pCol = pTable->aCol)!=0 ){
- for(i=0; i<pTable->nCol; i++, pCol++){
- sqlite3_free(pCol->zName);
- sqlite3ExprDelete(pCol->pDflt);
- sqlite3_free(pCol->zType);
- sqlite3_free(pCol->zColl);
- }
- sqlite3_free(pTable->aCol);
- }
- pTable->aCol = 0;
- pTable->nCol = 0;
- }
- /*
- ** Remove the memory data structures associated with the given
- ** Table. No changes are made to disk by this routine.
- **
- ** This routine just deletes the data structure. It does not unlink
- ** the table data structure from the hash table. Nor does it remove
- ** foreign keys from the sqlite.aFKey hash table. But it does destroy
- ** memory structures of the indices and foreign keys associated with
- ** the table.
- */
- void sqlite3DeleteTable(Table *pTable){
- Index *pIndex, *pNext;
- FKey *pFKey, *pNextFKey;
- if( pTable==0 ) return;
- /* Do not delete the table until the reference count reaches zero. */
- pTable->nRef--;
- if( pTable->nRef>0 ){
- return;
- }
- assert( pTable->nRef==0 );
- /* Delete all indices associated with this table
- */
- for(pIndex = pTable->pIndex; pIndex; pIndex=pNext){
- pNext = pIndex->pNext;
- assert( pIndex->pSchema==pTable->pSchema );
- sqliteDeleteIndex(pIndex);
- }
- #ifndef SQLITE_OMIT_FOREIGN_KEY
- /* Delete all foreign keys associated with this table. The keys
- ** should have already been unlinked from the pSchema->aFKey hash table
- */
- for(pFKey=pTable->pFKey; pFKey; pFKey=pNextFKey){
- pNextFKey = pFKey->pNextFrom;
- assert( sqlite3HashFind(&pTable->pSchema->aFKey,
- pFKey->zTo, strlen(pFKey->zTo)+1)!=pFKey );
- sqlite3_free(pFKey);
- }
- #endif
- /* Delete the Table structure itself.
- */
- sqliteResetColumnNames(pTable);
- sqlite3_free(pTable->zName);
- sqlite3_free(pTable->zColAff);
- sqlite3SelectDelete(pTable->pSelect);
- #ifndef SQLITE_OMIT_CHECK
- sqlite3ExprDelete(pTable->pCheck);
- #endif
- sqlite3VtabClear(pTable);
- sqlite3_free(pTable);
- }
- /*
- ** Unlink the given table from the hash tables and the delete the
- ** table structure with all its indices and foreign keys.
- */
- void sqlite3UnlinkAndDeleteTable(sqlite3 *db, int iDb, const char *zTabName){
- Table *p;
- FKey *pF1, *pF2;
- Db *pDb;
- assert( db!=0 );
- assert( iDb>=0 && iDb<db->nDb );
- assert( zTabName && zTabName[0] );
- pDb = &db->aDb[iDb];
- p = sqlite3HashInsert(&pDb->pSchema->tblHash, zTabName, strlen(zTabName)+1,0);
- if( p ){
- #ifndef SQLITE_OMIT_FOREIGN_KEY
- for(pF1=p->pFKey; pF1; pF1=pF1->pNextFrom){
- int nTo = strlen(pF1->zTo) + 1;
- pF2 = sqlite3HashFind(&pDb->pSchema->aFKey, pF1->zTo, nTo);
- if( pF2==pF1 ){
- sqlite3HashInsert(&pDb->pSchema->aFKey, pF1->zTo, nTo, pF1->pNextTo);
- }else{
- while( pF2 && pF2->pNextTo!=pF1 ){ pF2=pF2->pNextTo; }
- if( pF2 ){
- pF2->pNextTo = pF1->pNextTo;
- }
- }
- }
- #endif
- sqlite3DeleteTable(p);
- }
- db->flags |= SQLITE_InternChanges;
- }
- /*
- ** Given a token, return a string that consists of the text of that
- ** token with any quotations removed. Space to hold the returned string
- ** is obtained from sqliteMalloc() and must be freed by the calling
- ** function.
- **
- ** Tokens are often just pointers into the original SQL text and so
- ** are not