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

📄 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**     PRAGMA**** $Id: build.c,v 1.176.2.3 2004/08/28 14:53:34 drh Exp $*/#include "sqliteInt.h"#include <ctype.h>/*** This routine is called when a new SQL statement is beginning to** be parsed.  Check to see if the schema for the database needs** to be read from the SQLITE_MASTER and SQLITE_TEMP_MASTER tables.** If it does, then read it.*/void sqliteBeginParse(Parse *pParse, int explainFlag){  sqlite *db = pParse->db;  int i;  pParse->explain = explainFlag;  if((db->flags & SQLITE_Initialized)==0 && db->init.busy==0 ){    int rc = sqliteInit(db, &pParse->zErrMsg);    if( rc!=SQLITE_OK ){      pParse->rc = rc;      pParse->nErr++;    }  }  for(i=0; i<db->nDb; i++){    DbClearProperty(db, i, DB_Locked);    if( !db->aDb[i].inTrans ){      DbClearProperty(db, i, DB_Cookie);    }  }  pParse->nVar = 0;}/*** This routine is called after a single SQL statement has been** parsed and we want to execute the VDBE code to implement ** that statement.  Prior action routines should have already** constructed VDBE code to do the work of the SQL statement.** This routine just has to execute the VDBE code.**** Note that if an error occurred, it might be the case that** no VDBE code was generated.*/void sqliteExec(Parse *pParse){  sqlite *db = pParse->db;  Vdbe *v = pParse->pVdbe;  if( v==0 && (v = sqliteGetVdbe(pParse))!=0 ){    sqliteVdbeAddOp(v, OP_Halt, 0, 0);  }  if( sqlite_malloc_failed ) return;  if( v && pParse->nErr==0 ){    FILE *trace = (db->flags & SQLITE_VdbeTrace)!=0 ? stdout : 0;    sqliteVdbeTrace(v, trace);    sqliteVdbeMakeReady(v, pParse->nVar, pParse->explain);    pParse->rc = pParse->nErr ? SQLITE_ERROR : 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->nAgg = 0;  pParse->nVar = 0;}/*** 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 sqliteLocateTable().*/Table *sqliteFindTable(sqlite *db, const char *zName, const char *zDatabase){  Table *p = 0;  int i;  for(i=0; i<db->nDb; i++){    int j = (i<2) ? i^1 : i;   /* Search TEMP before MAIN */    if( zDatabase!=0 && sqliteStrICmp(zDatabase, db->aDb[j].zName) ) continue;    p = sqliteHashFind(&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 sqliteFindTable()** is that this routine leaves an error message in pParse->zErrMsg** where sqliteFindTable() does not.*/Table *sqliteLocateTable(Parse *pParse, const char *zName, const char *zDbase){  Table *p;  p = sqliteFindTable(pParse->db, zName, zDbase);  if( p==0 ){    if( zDbase ){      sqliteErrorMsg(pParse, "no such table: %s.%s", zDbase, zName);    }else if( sqliteFindTable(pParse->db, zName, 0)!=0 ){      sqliteErrorMsg(pParse, "table \"%s\" is not in database \"%s\"",         zName, zDbase);    }else{      sqliteErrorMsg(pParse, "no such table: %s", zName);    }  }  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 *sqliteFindIndex(sqlite *db, const char *zName, const char *zDb){  Index *p = 0;  int i;  for(i=0; i<db->nDb; i++){    int j = (i<2) ? i^1 : i;  /* Search TEMP before MAIN */    if( zDb && sqliteStrICmp(zDb, db->aDb[j].zName) ) continue;    p = sqliteHashFind(&db->aDb[j].idxHash, zName, strlen(zName)+1);    if( p ) break;  }  return 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(sqlite *db, Index *p){  Index *pOld;  assert( db!=0 && p->zName!=0 );  pOld = sqliteHashInsert(&db->aDb[p->iDb].idxHash, p->zName,                          strlen(p->zName)+1, 0);  if( pOld!=0 && pOld!=p ){    sqliteHashInsert(&db->aDb[p->iDb].idxHash, pOld->zName,                     strlen(pOld->zName)+1, pOld);  }  sqliteFree(p);}/*** Unlink the given index from its table, then remove** the index from the index hash table and free its memory** structures.*/void sqliteUnlinkAndDeleteIndex(sqlite *db, Index *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;    }  }  sqliteDeleteIndex(db, pIndex);}/*** Erase all schema information from the in-memory hash tables of** database connection.  This routine is called to reclaim memory** before the connection closes.  It is also called during a rollback** if there were schema changes during the transaction.**** 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 sqliteResetInternalSchema(sqlite *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;    sqliteHashInit(&pDb->trigHash, SQLITE_HASH_STRING, 0);    sqliteHashClear(&pDb->aFKey);    sqliteHashClear(&pDb->idxHash);    for(pElem=sqliteHashFirst(&temp2); pElem; pElem=sqliteHashNext(pElem)){      Trigger *pTrigger = sqliteHashData(pElem);      sqliteDeleteTrigger(pTrigger);    }    sqliteHashClear(&temp2);    sqliteHashInit(&pDb->tblHash, SQLITE_HASH_STRING, 0);    for(pElem=sqliteHashFirst(&temp1); pElem; pElem=sqliteHashNext(pElem)){      Table *pTab = sqliteHashData(pElem);      sqliteDeleteTable(db, pTab);    }    sqliteHashClear(&temp1);    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 sqliteRollbackInternalChanges(sqlite *db){  if( db->flags & SQLITE_InternChanges ){    sqliteResetInternalSchema(db, 0);  }}/*** This routine is called when a commit occurs.*/void sqliteCommitInternalChanges(sqlite *db){  db->aDb[0].schema_cookie = db->next_cookie;  db->flags &= ~SQLITE_InternChanges;}/*** 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.**** Indices associated with the table are unlinked from the "db"** data structure if db!=NULL.  If db==NULL, indices attached to** the table are deleted, but it is assumed they have already been** unlinked.*/void sqliteDeleteTable(sqlite *db, Table *pTable){  int i;  Index *pIndex, *pNext;  FKey *pFKey, *pNextFKey;  if( pTable==0 ) return;  /* Delete all indices associated with this table  */  for(pIndex = pTable->pIndex; pIndex; pIndex=pNext){    pNext = pIndex->pNext;    assert( pIndex->iDb==pTable->iDb || (pTable->iDb==0 && pIndex->iDb==1) );    sqliteDeleteIndex(db, pIndex);  }  /* Delete all foreign keys associated with this table.  The keys  ** should have already been unlinked from the db->aFKey hash table   */  for(pFKey=pTable->pFKey; pFKey; pFKey=pNextFKey){    pNextFKey = pFKey->pNextFrom;    assert( pTable->iDb<db->nDb );    assert( sqliteHashFind(&db->aDb[pTable->iDb].aFKey,                           pFKey->zTo, strlen(pFKey->zTo)+1)!=pFKey );    sqliteFree(pFKey);  }  /* Delete the Table structure itself.  */  for(i=0; i<pTable->nCol; i++){    sqliteFree(pTable->aCol[i].zName);    sqliteFree(pTable->aCol[i].zDflt);    sqliteFree(pTable->aCol[i].zType);  }  sqliteFree(pTable->zName);  sqliteFree(pTable->aCol);  sqliteSelectDelete(pTable->pSelect);  sqliteFree(pTable);}/*** Unlink the given table from the hash tables and the delete the** table structure with all its indices and foreign keys.*/static void sqliteUnlinkAndDeleteTable(sqlite *db, Table *p){  Table *pOld;  FKey *pF1, *pF2;  int i = p->iDb;  assert( db!=0 );  pOld = sqliteHashInsert(&db->aDb[i].tblHash, p->zName, strlen(p->zName)+1, 0);  assert( pOld==0 || pOld==p );  for(pF1=p->pFKey; pF1; pF1=pF1->pNextFrom){    int nTo = strlen(pF1->zTo) + 1;    pF2 = sqliteHashFind(&db->aDb[i].aFKey, pF1->zTo, nTo);    if( pF2==pF1 ){      sqliteHashInsert(&db->aDb[i].aFKey, pF1->zTo, nTo, pF1->pNextTo);    }else{      while( pF2 && pF2->pNextTo!=pF1 ){ pF2=pF2->pNextTo; }      if( pF2 ){        pF2->pNextTo = pF1->pNextTo;      }    }  }  sqliteDeleteTable(db, p);}/*** Construct the name of a user table or index from a token.**** Space to hold the name is obtained from sqliteMalloc() and must** be freed by the calling function.*/char *sqliteTableNameFromToken(Token *pName){  char *zName = sqliteStrNDup(pName->z, pName->n);  sqliteDequote(zName);  return zName;}/*** Generate code to open the appropriate master table.  The table** opened will be SQLITE_MASTER for persistent tables and ** SQLITE_TEMP_MASTER for temporary tables.  The table is opened** on cursor 0.*/void sqliteOpenMasterTable(Vdbe *v, int isTemp){  sqliteVdbeAddOp(v, OP_Integer, isTemp, 0);  sqliteVdbeAddOp(v, OP_OpenWrite, 0, 2);}/*** Begin constructing a new table representation in memory.  This is** the first of several action routines that get called in response** to a CREATE TABLE statement.  In particular, this routine is called** after seeing tokens "CREATE" and "TABLE" and the table name.  The** pStart token is the CREATE and pName is the table name.  The isTemp** flag is true if the table should be stored in the auxiliary database** file instead of in the main database file.  This is normally the case** when the "TEMP" or "TEMPORARY" keyword occurs in between** CREATE and TABLE.**** The new table record is initialized and put in pParse->pNewTable.** As more of the CREATE TABLE statement is parsed, additional action** routines will be called to add more information to this record.** At the end of the CREATE TABLE statement, the sqliteEndTable() routine** is called to complete the construction of the new table record.*/void sqliteStartTable(

⌨️ 快捷键说明

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