⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 build.c

📁 sqlite 嵌入式数据库的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
/*** 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.326 2005/06/12 21:35:52 drh 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;}/*** 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;  if( sqlite3_malloc_failed ) return;  if( pParse->nested ) 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  */  db = pParse->db;  v = sqlite3GetVdbe(pParse);  if( v ){    sqlite3VdbeAddOp(v, OP_Halt, 0, 0);    /* 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;      sqlite3VdbeChangeP2(v, pParse->cookieGoto-1, sqlite3VdbeCurrentAddr(v));      for(iDb=0, mask=1; iDb<db->nDb; mask<<=1, iDb++){        if( (mask & pParse->cookieMask)==0 ) continue;        sqlite3VdbeAddOp(v, OP_Transaction, iDb, (mask & pParse->writeMask)!=0);        sqlite3VdbeAddOp(v, OP_VerifyCookie, iDb, pParse->cookieValue[iDb]);      }      sqlite3VdbeAddOp(v, OP_Goto, 0, pParse->cookieGoto);    }    /* Add a No-op that contains the complete text of the compiled SQL    ** statement as its P3 argument.  This does not change the functionality    ** of the program.     **    ** This is used to implement sqlite3_trace().    */    sqlite3VdbeOp3(v, OP_Noop, 0, 0, pParse->zSql, pParse->zTail-pParse->zSql);  }  /* Get the VDBE program ready for execution  */  if( v && pParse->nErr==0 ){    FILE *trace = (db->flags & SQLITE_VdbeTrace)!=0 ? stdout : 0;    sqlite3VdbeTrace(v, trace);    sqlite3VdbeMakeReady(v, pParse->nVar, pParse->nMem+3,                         pParse->nTab+3, pParse->nMaxDepth+1, 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;  int rc;# 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(zFormat, ap);  va_end(ap);  if( zSql==0 ){    return;   /* A malloc must have failed */  }  pParse->nested++;  memcpy(saveBuf, &pParse->nVar, SAVE_SZ);  memset(&pParse->nVar, 0, SAVE_SZ);  rc = sqlite3RunParser(pParse, zSql, 0);  sqliteFree(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 );  assert( (db->flags & SQLITE_Initialized) || db->init.busy );  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].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, const char *zName, const char *zDbase){  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 ){    if( zDbase ){      sqlite3ErrorMsg(pParse, "no such table: %s.%s", zDbase, zName);    }else if( sqlite3FindTable(pParse->db, zName, 0)!=0 ){      sqlite3ErrorMsg(pParse, "table \"%s\" is not in database \"%s\"",         zName, zDbase);    }else{      sqlite3ErrorMsg(pParse, "no such table: %s", 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;  assert( (db->flags & SQLITE_Initialized) || db->init.busy );  for(i=OMIT_TEMPDB; i<db->nDb; i++){    int j = (i<2) ? i^1 : i;  /* Search TEMP before MAIN */    if( zDb && sqlite3StrICmp(zDb, db->aDb[j].zName) ) continue;    p = sqlite3HashFind(&db->aDb[j].idxHash, zName, strlen(zName)+1);    if( p ) break;  }  return p;}/*** Reclaim the memory used by an index*/static void freeIndex(Index *p){  sqliteFree(p->zColAff);  sqliteFree(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(sqlite3 *db, Index *p){  Index *pOld;  assert( db!=0 && p->zName!=0 );  pOld = sqlite3HashInsert(&db->aDb[p->iDb].idxHash, p->zName,                          strlen(p->zName)+1, 0);  if( pOld!=0 && pOld!=p ){    sqlite3HashInsert(&db->aDb[p->iDb].idxHash, pOld->zName,                     strlen(pOld->zName)+1, pOld);  }  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;  len = strlen(zIdxName);  pIndex = sqlite3HashInsert(&db->aDb[iDb].idxHash, 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){  HashElem *pElem;  Hash temp1;  Hash temp2;  int i, j;  assert( iDb>=0 && iDb<db->nDb );  db->flags &= ~SQLITE_Initialized;  for(i=iDb; i<db->nDb; i++){    Db *pDb = &db->aDb[i];    temp1 = pDb->tblHash;    temp2 = pDb->trigHash;    sqlite3HashInit(&pDb->trigHash, SQLITE_HASH_STRING, 0);    sqlite3HashClear(&pDb->aFKey);    sqlite3HashClear(&pDb->idxHash);    for(pElem=sqliteHashFirst(&temp2); pElem; pElem=sqliteHashNext(pElem)){      sqlite3DeleteTrigger((Trigger*)sqliteHashData(pElem));    }    sqlite3HashClear(&temp2);    sqlite3HashInit(&pDb->tblHash, SQLITE_HASH_STRING, 0);    for(pElem=sqliteHashFirst(&temp1); pElem; pElem=sqliteHashNext(pElem)){      Table *pTab = sqliteHashData(pElem);      sqlite3DeleteTable(db, pTab);    }    sqlite3HashClear(&temp1);    pDb->pSeqTab = 0;    DbClearProperty(db, i, DB_SchemaLoaded);    if( iDb>0 ) return;  }  assert( iDb==0 );  db->flags &= ~SQLITE_InternChanges;  /* If one or more of the auxiliary database files has been closed,  ** then remove then 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 ){      sqliteFree(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]));    sqliteFree(db->aDb);    db->aDb = db->aDbStatic;  }}/*** This routine is called whenever a rollback occurs.  If there were** schema changes during the transaction, then we have to reset the** internal hash tables and reload them from disk.*/void sqlite3RollbackInternalChanges(sqlite3 *db){  if( db->flags & SQLITE_InternChanges ){    sqlite3ResetInternalSchema(db, 0);  }}/*** 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++){      sqliteFree(pCol->zName);      sqlite3ExprDelete(pCol->pDflt);      sqliteFree(pCol->zType);    }    sqliteFree(pTable->aCol);  }  pTable->aCol = 0;  pTable->nCol = 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -