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

📄 build.c

📁 sqlite 嵌入式数据库的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
/*** 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 sqlite3DeleteTable(sqlite3 *db, 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->iDb==pTable->iDb || (pTable->iDb==0 && pIndex->iDb==1) );    sqliteDeleteIndex(db, pIndex);  }#ifndef SQLITE_OMIT_FOREIGN_KEY  /* 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( sqlite3HashFind(&db->aDb[pTable->iDb].aFKey,                           pFKey->zTo, strlen(pFKey->zTo)+1)!=pFKey );    sqliteFree(pFKey);  }#endif  /* Delete the Table structure itself.  */  sqliteResetColumnNames(pTable);  sqliteFree(pTable->zName);  sqliteFree(pTable->zColAff);  sqlite3SelectDelete(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.*/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->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->aFKey, pF1->zTo, nTo);      if( pF2==pF1 ){        sqlite3HashInsert(&pDb->aFKey, pF1->zTo, nTo, pF1->pNextTo);      }else{        while( pF2 && pF2->pNextTo!=pF1 ){ pF2=pF2->pNextTo; }        if( pF2 ){          pF2->pNextTo = pF1->pNextTo;        }      }    }#endif    sqlite3DeleteTable(db, 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 \000 terminated and are not persistent.  The returned string** is \000 terminated and is persistent.*/char *sqlite3NameFromToken(Token *pName){  char *zName;  if( pName ){    zName = sqliteStrNDup(pName->z, pName->n);    sqlite3Dequote(zName);  }else{    zName = 0;  }  return zName;}/*** Open the sqlite_master table stored in database number iDb for** writing. The table is opened using cursor 0.*/void sqlite3OpenMasterTable(Vdbe *v, int iDb){  sqlite3VdbeAddOp(v, OP_Integer, iDb, 0);  sqlite3VdbeAddOp(v, OP_OpenWrite, 0, MASTER_ROOT);  sqlite3VdbeAddOp(v, OP_SetNumColumns, 0, 5); /* sqlite_master has 5 columns */}/*** The token *pName contains the name of a database (either "main" or** "temp" or the name of an attached db). This routine returns the** index of the named database in db->aDb[], or -1 if the named db ** does not exist.*/static int findDb(sqlite3 *db, Token *pName){  int i = -1;    /* Database number */  int n;         /* Number of characters in the name */  Db *pDb;       /* A database whose name space is being searched */  char *zName;   /* Name we are searching for */  zName = sqlite3NameFromToken(pName);  if( zName ){    n = strlen(zName);    for(i=(db->nDb-1), pDb=&db->aDb[i]; i>=0; i--, pDb--){      if( (!OMIT_TEMPDB || i!=1 ) && n==strlen(pDb->zName) &&           0==sqlite3StrICmp(pDb->zName, zName) ){        break;      }    }    sqliteFree(zName);  }  return i;}/* The table or view or trigger name is passed to this routine via tokens** pName1 and pName2. If the table name was fully qualified, for example:**** CREATE TABLE xxx.yyy (...);** ** Then pName1 is set to "xxx" and pName2 "yyy". On the other hand if** the table name is not fully qualified, i.e.:**** CREATE TABLE yyy(...);**** Then pName1 is set to "yyy" and pName2 is "".**** This routine sets the *ppUnqual pointer to point at the token (pName1 or** pName2) that stores the unqualified table name.  The index of the** database "xxx" is returned.*/int sqlite3TwoPartName(  Parse *pParse,      /* Parsing and code generating context */  Token *pName1,      /* The "xxx" in the name "xxx.yyy" or "xxx" */  Token *pName2,      /* The "yyy" in the name "xxx.yyy" */  Token **pUnqual     /* Write the unqualified object name here */){  int iDb;                    /* Database holding the object */  sqlite3 *db = pParse->db;  if( pName2 && pName2->n>0 ){    assert( !db->init.busy );    *pUnqual = pName2;    iDb = findDb(db, pName1);    if( iDb<0 ){      sqlite3ErrorMsg(pParse, "unknown database %T", pName1);      pParse->nErr++;      return -1;    }  }else{    assert( db->init.iDb==0 || db->init.busy );    iDb = db->init.iDb;    *pUnqual = pName1;  }  return iDb;}/*** This routine is used to check if the UTF-8 string zName is a legal** unqualified name for a new schema object (table, index, view or** trigger). All names are legal except those that begin with the string** "sqlite_" (in upper, lower or mixed case). This portion of the namespace** is reserved for internal use.*/int sqlite3CheckObjectName(Parse *pParse, const char *zName){  if( !pParse->db->init.busy && pParse->nested==0           && (pParse->db->flags & SQLITE_WriteSchema)==0          && 0==sqlite3StrNICmp(zName, "sqlite_", 7) ){    sqlite3ErrorMsg(pParse, "object name reserved for internal use: %s", zName);    return SQLITE_ERROR;  }  return SQLITE_OK;}/*** 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 sqlite3EndTable() routine** is called to complete the construction of the new table record.*/void sqlite3StartTable(  Parse *pParse,   /* Parser context */  Token *pStart,   /* The "CREATE" token */  Token *pName1,   /* First part of the name of the table or view */  Token *pName2,   /* Second part of the name of the table or view */  int isTemp,      /* True if this is a TEMP table */  int isView       /* True if this is a VIEW */){  Table *pTable;  Index *pIdx;  char *zName = 0; /* The name of the new table */  sqlite3 *db = pParse->db;  Vdbe *v;  int iDb;         /* Database number to create the table in */  Token *pName;    /* Unqualified name of the table to create */  /* The table or view name to create is passed to this routine via tokens  ** pName1 and pName2. If the table name was fully qualified, for example:  **  ** CREATE TABLE xxx.yyy (...);  **   ** Then pName1 is set to "xxx" and pName2 "yyy". On the other hand if  ** the table name is not fully qualified, i.e.:  **  ** CREATE TABLE yyy(...);  **  ** Then pName1 is set to "yyy" and pName2 is "".  **  ** The call below sets the pName pointer to point at the token (pName1 or  ** pName2) that stores the unqualified table name. The variable iDb is  ** set to the index of the database that the table or view is to be  ** created in.  */  iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pName);  if( iDb<0 ) return;  if( !OMIT_TEMPDB && isTemp && iDb>1 ){    /* If creating a temp table, the name may not be qualified */    sqlite3ErrorMsg(pParse, "temporary table name must be unqualified");    return;  }  if( !OMIT_TEMPDB && isTemp ) iDb = 1;  pParse->sNameToken = *pName;  zName = sqlite3NameFromToken(pName);  if( zName==0 ) return;  if( SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){    goto begin_table_error;  }  if( db->init.iDb==1 ) isTemp = 1;#ifndef SQLITE_OMIT_AUTHORIZATION  assert( (isTemp & 1)==isTemp );  {    int code;    char *zDb = db->aDb[iDb].zName;    if( sqlite3AuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(isTemp), 0, zDb) ){      goto begin_table_error;    }    if( isView ){      if( !OMIT_TEMPDB && isTemp ){        code = SQLITE_CREATE_TEMP_VIEW;      }else{        code = SQLITE_CREATE_VIEW;      }    }else{      if( !OMIT_TEMPDB && isTemp ){        code = SQLITE_CREATE_TEMP_TABLE;      }else{        code = SQLITE_CREATE_TABLE;      }    }    if( sqlite3AuthCheck(pParse, code, zName, 0, zDb) ){      goto begin_table_error;    }  }#endif  /* Make sure the new table name does not collide with an existing  ** index or table name in the same database.  Issue an error message if  ** it does.  */  if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){    goto begin_table_error;  }  pTable = sqlite3FindTable(db, zName, db->aDb[iDb].zName);  if( pTable ){    sqlite3ErrorMsg(pParse, "table %T already exists", pName);    goto begin_table_error;  }  if( (pIdx = sqlite3FindIndex(db, zName, 0))!=0 &&       ( iDb==0 || !db->init.busy) ){    sqlite3ErrorMsg(pParse, "there is already an index named %s", zName);    goto begin_table_error;  }  pTable = sqliteMalloc( sizeof(Table) );  if( pTable==0 ){    pParse->rc = SQLITE_NOMEM;    pParse->nErr++;    goto begin_table_error;  }  pTable->zName = zName;  pTable->nCol = 0;  pTable->aCol = 0;  pTable->iPKey = -1;  pTable->pIndex = 0;  pTable->iDb = iDb;  pTable->nRef = 1;  if( pParse->pNewTable ) sqlite3DeleteTable(db, pParse->pNewTable);  pParse->pNewTable = pTable;  /* If this is the magic sqlite_sequence table used by autoincrement,  ** then record a pointer to this table in the main database structure  ** so that INSERT can find the table easily.  */#ifndef SQLITE_OMIT_AUTOINCREMENT  if( strcmp(zName, "sqlite_sequence")==0 ){    db->aDb[iDb].pSeqTab = pTable;  }#endif  /* Begin generating the code that will insert the table record into  ** the SQLITE_MASTER table.  Note in particular that we must go ahead  ** and allocate the record number for the table entry now.  Before any  ** PRIMARY KEY or UNIQUE keywords are parsed.  Those keywords will cause  ** indices to be created and the table record must come before the   ** indices.  Hence, the record number for the table must be allocated  ** now.  */  if( !db->init.busy && (v = sqlite3GetVdbe(pParse))!=0 ){    int lbl;    sqlite3BeginWriteOperation(pParse, 0, iDb);    /* If the file format and encoding in the database have not been set,     ** set them now.    */    sqlite3VdbeAddOp(v, OP_ReadCookie, iDb, 1);   /* file_format */    lbl = sqlite3VdbeMakeLabel(v);    sqlite3VdbeAddOp(v, OP_If, 0, lbl);    sqlite3VdbeAddOp(v, OP_Integer, db->file_format, 0);    sqlite3VdbeAddOp(v, OP_SetCookie, iDb, 1);    sqlite3VdbeAddOp(v, OP_Integer, db->enc, 0);    sqlite3VdbeAddOp(v, OP_SetCookie, iDb, 4);    sqlite3VdbeResolveLabel(v, lbl);    /* This just creates a place-holder record in the sqlite_master table.    ** The record created does not contain anything yet.  It will be replaced    ** by the real entry in code generated at sqlite3EndTable().    **    ** The rowid for the new entry is left on the top of the stack.    ** The rowid value is needed by the code that sqlite3EndTable will    ** generate.    */#ifndef SQLITE_OMIT_VIEW    if( isView ){      sqlite3VdbeAddOp(v, OP_Integer, 0, 0);    }else#endif    {      sqlite3VdbeAddOp(v, OP_CreateTable, iDb, 0);    }    sqlite3OpenMasterTable(v, iDb);    sqlite3VdbeAddOp(v, OP_NewRowid, 0, 0);    sqlite3VdbeAddOp(v, OP_Dup, 0, 0);    sqlite3VdbeAddOp(v, OP_Null, 0, 0);    sqlite3VdbeAddOp(v, OP_Insert, 0, 0);    sqlite3VdbeAddOp(v, OP_Close, 0, 0);    sqlite3VdbeAddOp(v, OP_Pull, 1, 0);  }  /* Normal (non-error) return. */  return;  /* If an error occurs, we jump here */begin_table_error:  sqliteFree(zName);  return;}/*** This macro is used to compare two strings in a case-insensitive manner.** It is slightly faster than calling sqlite3StrICmp() directly, but** produces larger code.**** WARNING: This macro is not compatible with the strcmp() family. It

⌨️ 快捷键说明

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