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

📄 build.c

📁 sqlite 嵌入式数据库的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
  ** location iTable. The following code modifies the sqlite_master table to  ** reflect this.  **  ** The "#0" in the SQL is a special constant that means whatever value  ** is on the top of the stack.  See sqlite3RegisterExpr().  */  sqlite3NestedParse(pParse,      "UPDATE %Q.%s SET rootpage=%d WHERE #0 AND rootpage=#0",     pParse->db->aDb[iDb].zName, SCHEMA_TABLE(iDb), iTable);#endif}/*** Write VDBE code to erase table pTab and all associated indices on disk.** Code to update the sqlite_master tables and internal schema definitions** in case a root-page belonging to another table is moved by the btree layer** is also added (this can happen with an auto-vacuum database).*/static void destroyTable(Parse *pParse, Table *pTab){#ifdef SQLITE_OMIT_AUTOVACUUM  Index *pIdx;  destroyRootPage(pParse, pTab->tnum, pTab->iDb);  for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){    destroyRootPage(pParse, pIdx->tnum, pIdx->iDb);  }#else  /* If the database may be auto-vacuum capable (if SQLITE_OMIT_AUTOVACUUM  ** is not defined), then it is important to call OP_Destroy on the  ** table and index root-pages in order, starting with the numerically   ** largest root-page number. This guarantees that none of the root-pages  ** to be destroyed is relocated by an earlier OP_Destroy. i.e. if the  ** following were coded:  **  ** OP_Destroy 4 0  ** ...  ** OP_Destroy 5 0  **  ** and root page 5 happened to be the largest root-page number in the  ** database, then root page 5 would be moved to page 4 by the   ** "OP_Destroy 4 0" opcode. The subsequent "OP_Destroy 5 0" would hit  ** a free-list page.  */  int iTab = pTab->tnum;  int iDestroyed = 0;  while( 1 ){    Index *pIdx;    int iLargest = 0;    if( iDestroyed==0 || iTab<iDestroyed ){      iLargest = iTab;    }    for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){      int iIdx = pIdx->tnum;      assert( pIdx->iDb==pTab->iDb );      if( (iDestroyed==0 || (iIdx<iDestroyed)) && iIdx>iLargest ){        iLargest = iIdx;      }    }    if( iLargest==0 ) return;    destroyRootPage(pParse, iLargest, pTab->iDb);    iDestroyed = iLargest;  }#endif}/*** This routine is called to do the work of a DROP TABLE statement.** pName is the name of the table to be dropped.*/void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView){  Table *pTab;  Vdbe *v;  sqlite3 *db = pParse->db;  int iDb;  if( pParse->nErr || sqlite3_malloc_failed ) goto exit_drop_table;  assert( pName->nSrc==1 );  pTab = sqlite3LocateTable(pParse, pName->a[0].zName, pName->a[0].zDatabase);  if( pTab==0 ) goto exit_drop_table;  iDb = pTab->iDb;  assert( iDb>=0 && iDb<db->nDb );#ifndef SQLITE_OMIT_AUTHORIZATION  {    int code;    const char *zTab = SCHEMA_TABLE(pTab->iDb);    const char *zDb = db->aDb[pTab->iDb].zName;    if( sqlite3AuthCheck(pParse, SQLITE_DELETE, zTab, 0, zDb)){      goto exit_drop_table;    }    if( isView ){      if( !OMIT_TEMPDB && iDb==1 ){        code = SQLITE_DROP_TEMP_VIEW;      }else{        code = SQLITE_DROP_VIEW;      }    }else{      if( !OMIT_TEMPDB && iDb==1 ){        code = SQLITE_DROP_TEMP_TABLE;      }else{        code = SQLITE_DROP_TABLE;      }    }    if( sqlite3AuthCheck(pParse, code, pTab->zName, 0, zDb) ){      goto exit_drop_table;    }    if( sqlite3AuthCheck(pParse, SQLITE_DELETE, pTab->zName, 0, zDb) ){      goto exit_drop_table;    }  }#endif  if( pTab->readOnly || pTab==db->aDb[iDb].pSeqTab ){    sqlite3ErrorMsg(pParse, "table %s may not be dropped", pTab->zName);    goto exit_drop_table;  }#ifndef SQLITE_OMIT_VIEW  /* Ensure DROP TABLE is not used on a view, and DROP VIEW is not used  ** on a table.  */  if( isView && pTab->pSelect==0 ){    sqlite3ErrorMsg(pParse, "use DROP TABLE to delete table %s", pTab->zName);    goto exit_drop_table;  }  if( !isView && pTab->pSelect ){    sqlite3ErrorMsg(pParse, "use DROP VIEW to delete view %s", pTab->zName);    goto exit_drop_table;  }#endif  /* Generate code to remove the table from the master table  ** on disk.  */  v = sqlite3GetVdbe(pParse);  if( v ){    Trigger *pTrigger;    int iDb = pTab->iDb;    Db *pDb = &db->aDb[iDb];    sqlite3BeginWriteOperation(pParse, 0, iDb);    /* Drop all triggers associated with the table being dropped. Code    ** is generated to remove entries from sqlite_master and/or    ** sqlite_temp_master if required.    */    pTrigger = pTab->pTrigger;    while( pTrigger ){      assert( pTrigger->iDb==iDb || pTrigger->iDb==1 );      sqlite3DropTriggerPtr(pParse, pTrigger, 1);      pTrigger = pTrigger->pNext;    }#ifndef SQLITE_OMIT_AUTOINCREMENT    /* Remove any entries of the sqlite_sequence table associated with    ** the table being dropped. This is done before the table is dropped    ** at the btree level, in case the sqlite_sequence table needs to    ** move as a result of the drop (can happen in auto-vacuum mode).    */    if( pTab->autoInc ){      sqlite3NestedParse(pParse,        "DELETE FROM %s.sqlite_sequence WHERE name=%Q",        pDb->zName, pTab->zName      );    }#endif    /* Drop all SQLITE_MASTER table and index entries that refer to the    ** table. The program name loops through the master table and deletes    ** every row that refers to a table of the same name as the one being    ** dropped. Triggers are handled seperately because a trigger can be    ** created in the temp database that refers to a table in another    ** database.    */    sqlite3NestedParse(pParse,         "DELETE FROM %Q.%s WHERE tbl_name=%Q and type!='trigger'",        pDb->zName, SCHEMA_TABLE(iDb), pTab->zName);    if( !isView ){      destroyTable(pParse, pTab);    }    /* Remove the table entry from SQLite's internal schema and modify    ** the schema cookie.    */    sqlite3VdbeOp3(v, OP_DropTable, iDb, 0, pTab->zName, 0);    sqlite3ChangeCookie(db, v, iDb);  }  sqliteViewResetAll(db, iDb);exit_drop_table:  sqlite3SrcListDelete(pName);}/*** This routine is called to create a new foreign key on the table** currently under construction.  pFromCol determines which columns** in the current table point to the foreign key.  If pFromCol==0 then** connect the key to the last column inserted.  pTo is the name of** the table referred to.  pToCol is a list of tables in the other** pTo table that the foreign key points to.  flags contains all** information about the conflict resolution algorithms specified** in the ON DELETE, ON UPDATE and ON INSERT clauses.**** An FKey structure is created and added to the table currently** under construction in the pParse->pNewTable field.  The new FKey** is not linked into db->aFKey at this point - that does not happen** until sqlite3EndTable().**** The foreign key is set for IMMEDIATE processing.  A subsequent call** to sqlite3DeferForeignKey() might change this to DEFERRED.*/void sqlite3CreateForeignKey(  Parse *pParse,       /* Parsing context */  ExprList *pFromCol,  /* Columns in this table that point to other table */  Token *pTo,          /* Name of the other table */  ExprList *pToCol,    /* Columns in the other table */  int flags            /* Conflict resolution algorithms. */){#ifndef SQLITE_OMIT_FOREIGN_KEY  FKey *pFKey = 0;  Table *p = pParse->pNewTable;  int nByte;  int i;  int nCol;  char *z;  assert( pTo!=0 );  if( p==0 || pParse->nErr ) goto fk_end;  if( pFromCol==0 ){    int iCol = p->nCol-1;    if( iCol<0 ) goto fk_end;    if( pToCol && pToCol->nExpr!=1 ){      sqlite3ErrorMsg(pParse, "foreign key on %s"         " should reference only one column of table %T",         p->aCol[iCol].zName, pTo);      goto fk_end;    }    nCol = 1;  }else if( pToCol && pToCol->nExpr!=pFromCol->nExpr ){    sqlite3ErrorMsg(pParse,        "number of columns in foreign key does not match the number of "        "columns in the referenced table");    goto fk_end;  }else{    nCol = pFromCol->nExpr;  }  nByte = sizeof(*pFKey) + nCol*sizeof(pFKey->aCol[0]) + pTo->n + 1;  if( pToCol ){    for(i=0; i<pToCol->nExpr; i++){      nByte += strlen(pToCol->a[i].zName) + 1;    }  }  pFKey = sqliteMalloc( nByte );  if( pFKey==0 ) goto fk_end;  pFKey->pFrom = p;  pFKey->pNextFrom = p->pFKey;  z = (char*)&pFKey[1];  pFKey->aCol = (struct sColMap*)z;  z += sizeof(struct sColMap)*nCol;  pFKey->zTo = z;  memcpy(z, pTo->z, pTo->n);  z[pTo->n] = 0;  z += pTo->n+1;  pFKey->pNextTo = 0;  pFKey->nCol = nCol;  if( pFromCol==0 ){    pFKey->aCol[0].iFrom = p->nCol-1;  }else{    for(i=0; i<nCol; i++){      int j;      for(j=0; j<p->nCol; j++){        if( sqlite3StrICmp(p->aCol[j].zName, pFromCol->a[i].zName)==0 ){          pFKey->aCol[i].iFrom = j;          break;        }      }      if( j>=p->nCol ){        sqlite3ErrorMsg(pParse,           "unknown column \"%s\" in foreign key definition",           pFromCol->a[i].zName);        goto fk_end;      }    }  }  if( pToCol ){    for(i=0; i<nCol; i++){      int n = strlen(pToCol->a[i].zName);      pFKey->aCol[i].zCol = z;      memcpy(z, pToCol->a[i].zName, n);      z[n] = 0;      z += n+1;    }  }  pFKey->isDeferred = 0;  pFKey->deleteConf = flags & 0xff;  pFKey->updateConf = (flags >> 8 ) & 0xff;  pFKey->insertConf = (flags >> 16 ) & 0xff;  /* Link the foreign key to the table as the last step.  */  p->pFKey = pFKey;  pFKey = 0;fk_end:  sqliteFree(pFKey);#endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */  sqlite3ExprListDelete(pFromCol);  sqlite3ExprListDelete(pToCol);}/*** This routine is called when an INITIALLY IMMEDIATE or INITIALLY DEFERRED** clause is seen as part of a foreign key definition.  The isDeferred** parameter is 1 for INITIALLY DEFERRED and 0 for INITIALLY IMMEDIATE.** The behavior of the most recently created foreign key is adjusted** accordingly.*/void sqlite3DeferForeignKey(Parse *pParse, int isDeferred){#ifndef SQLITE_OMIT_FOREIGN_KEY  Table *pTab;  FKey *pFKey;  if( (pTab = pParse->pNewTable)==0 || (pFKey = pTab->pFKey)==0 ) return;  pFKey->isDeferred = isDeferred;#endif}/*** Generate code that will erase and refill index *pIdx.  This is** used to initialize a newly created index or to recompute the** content of an index in response to a REINDEX command.**** if memRootPage is not negative, it means that the index is newly** created.  The memory cell specified by memRootPage contains the** root page number of the index.  If memRootPage is negative, then** the index already exists and must be cleared before being refilled and** the root page number of the index is taken from pIndex->tnum.*/static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){  Table *pTab = pIndex->pTable;  /* The table that is indexed */  int iTab = pParse->nTab;       /* Btree cursor used for pTab */  int iIdx = pParse->nTab+1;     /* Btree cursor used for pIndex */  int addr1;                     /* Address of top of loop */  int tnum;                      /* Root page of index */  Vdbe *v;                       /* Generate code into this virtual machine */  int isUnique;                  /* True for a unique index */#ifndef SQLITE_OMIT_AUTHORIZATION  if( sqlite3AuthCheck(pParse, SQLITE_REINDEX, pIndex->zName, 0,      pParse->db->aDb[pIndex->iDb].zName ) ){    return;  }#endif  /* Ensure all the required collation sequences are available. This  ** routine will invoke the collation-needed callback if necessary (and  ** if one has been registered).  */  if( sqlite3CheckIndexCollSeq(pParse, pIndex) ){    return;  }  v = sqlite3GetVdbe(pParse);  if( v==0 ) return;  if( memRootPage>=0 ){    sqlite3VdbeAddOp(v, OP_MemLoad, memRootPage, 0);    tnum = 0;  }else{    tnum = pIndex->tnum;    sqlite3VdbeAddOp(v, OP_Clear, tnum, pIndex->iDb);  }  sqlite3VdbeAddOp(v, OP_Integer, pIndex->iDb, 0);  sqlite3VdbeOp3(v, OP_OpenWrite, iIdx, tnum,                    (char*)&pIndex->keyInfo, P3_KEYINFO);  sqlite3VdbeAddOp(v, OP_Integer, pTab->iDb, 0);  sqlite3VdbeAddOp(v, OP_OpenRead, iTab, pTab->tnum);  sqlite3VdbeAddOp(v, OP_SetNumColumns, iTab, pTab->nCol);  addr1 = sqlite3VdbeAddOp(v, OP_Rewind, iTab, 0);  sqlite3GenerateIndexKey(v, pIndex, iTab);  isUnique = pIndex->onError!=OE_None;  sqlite3VdbeAddOp(v, OP_IdxInsert, iIdx, isUnique);  if( isUnique ){    sqlite3VdbeChangeP3(v, -1, "indexed columns are not unique", P3_STATIC);  }  sqlite3VdbeAddOp(v, OP_Next, iTab, addr1+1);  sqlite3VdbeChangeP2(v, addr1, sqlite3VdbeCurrentAddr(v));  sqlite3VdbeAddOp(v, OP_Close, iTab, 0);  sqlite3VdbeAddOp(v, OP_Close, iIdx, 0);}/*** Create a new index for an SQL table.  pName1.pName2 is the name of the index ** and pTblList is the name of the table that is to be indexed.  Both will ** be NULL for a primary key or an index that is created to satisfy a** UNIQUE constraint.  If pTable and pIndex are NULL, use pParse->pNewTable** as the table to be indexed.  pParse->pNewTable is a table that is** currently being constructed by a CREATE TABLE statement.**** pList is a list of columns to be indexed.  pList will be NULL if this** is a primary key or unique-constraint on the most recent column added** to the table currently under construction.  */void sqlite3CreateIndex(  Parse *pParse,     /* All information about this parse */  Token *pName1,     /* First part of index name. May be NULL */  Token *pName2,     /* Second part of index name. May be NULL */  SrcList *pTblName, /* Table to index. Use

⌨️ 快捷键说明

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