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

📄 build.c

📁 sqlite数据库管理系统开放源码
💻 C
📖 第 1 页 / 共 5 页
字号:
      sqliteVdbeChangeP3(v, base+1, pTable->zName, 0);    }    if( pTable->iDb==0 ){      sqliteChangeCookie(db, v);    }    sqliteVdbeAddOp(v, OP_Close, 0, 0);    if( !isView ){      sqliteVdbeAddOp(v, OP_Destroy, pTable->tnum, pTable->iDb);      for(pIdx=pTable->pIndex; pIdx; pIdx=pIdx->pNext){        sqliteVdbeAddOp(v, OP_Destroy, pIdx->tnum, pIdx->iDb);      }    }    sqliteEndWriteOperation(pParse);  }  /* Delete the in-memory description of the table.  **  ** Exception: if the SQL statement began with the EXPLAIN keyword,  ** then no changes should be made.  */  if( !pParse->explain ){    sqliteUnlinkAndDeleteTable(db, pTable);    db->flags |= SQLITE_InternChanges;  }  sqliteViewResetAll(db, iDb);}/*** This routine constructs a P3 string suitable for an OP_MakeIdxKey** opcode and adds that P3 string to the most recently inserted instruction** in the virtual machine.  The P3 string consists of a single character** for each column in the index pIdx of table pTab.  If the column uses** a numeric sort order, then the P3 string character corresponding to** that column is 'n'.  If the column uses a text sort order, then the** P3 string is 't'.  See the OP_MakeIdxKey opcode documentation for** additional information.  See also the sqliteAddKeyType() routine.*/void sqliteAddIdxKeyType(Vdbe *v, Index *pIdx){  char *zType;  Table *pTab;  int i, n;  assert( pIdx!=0 && pIdx->pTable!=0 );  pTab = pIdx->pTable;  n = pIdx->nColumn;  zType = sqliteMallocRaw( n+1 );  if( zType==0 ) return;  for(i=0; i<n; i++){    int iCol = pIdx->aiColumn[i];    assert( iCol>=0 && iCol<pTab->nCol );    if( (pTab->aCol[iCol].sortOrder & SQLITE_SO_TYPEMASK)==SQLITE_SO_TEXT ){      zType[i] = 't';    }else{      zType[i] = 'n';    }  }  zType[n] = 0;  sqliteVdbeChangeP3(v, -1, zType, n);  sqliteFree(zType);}/*** 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 sqliteEndTable().**** The foreign key is set for IMMEDIATE processing.  A subsequent call** to sqliteDeferForeignKey() might change this to DEFERRED.*/void sqliteCreateForeignKey(  Parse *pParse,       /* Parsing context */  IdList *pFromCol,    /* Columns in this table that point to other table */  Token *pTo,          /* Name of the other table */  IdList *pToCol,      /* Columns in the other table */  int flags            /* Conflict resolution algorithms. */){  Table *p = pParse->pNewTable;  int nByte;  int i;  int nCol;  char *z;  FKey *pFKey = 0;  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->nId!=1 ){      sqliteErrorMsg(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->nId!=pFromCol->nId ){    sqliteErrorMsg(pParse,        "number of columns in foreign key does not match the number of "        "columns in the referenced table");    goto fk_end;  }else{    nCol = pFromCol->nId;  }  nByte = sizeof(*pFKey) + nCol*sizeof(pFKey->aCol[0]) + pTo->n + 1;  if( pToCol ){    for(i=0; i<pToCol->nId; 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( sqliteStrICmp(p->aCol[j].zName, pFromCol->a[i].zName)==0 ){          pFKey->aCol[i].iFrom = j;          break;        }      }      if( j>=p->nCol ){        sqliteErrorMsg(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);  sqliteIdListDelete(pFromCol);  sqliteIdListDelete(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 sqliteDeferForeignKey(Parse *pParse, int isDeferred){  Table *pTab;  FKey *pFKey;  if( (pTab = pParse->pNewTable)==0 || (pFKey = pTab->pFKey)==0 ) return;  pFKey->isDeferred = isDeferred;}/*** Create a new index for an SQL table.  pIndex is the name of the index ** and pTable 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 sqliteCreateIndex(  Parse *pParse,   /* All information about this parse */  Token *pName,    /* Name of the index.  May be NULL */  SrcList *pTable, /* Name of the table to index.  Use pParse->pNewTable if 0 */  IdList *pList,   /* A list of columns to be indexed */  int onError,     /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */  Token *pStart,   /* The CREATE token that begins a CREATE TABLE statement */  Token *pEnd      /* The ")" that closes the CREATE INDEX statement */){  Table *pTab;     /* Table to be indexed */  Index *pIndex;   /* The index to be created */  char *zName = 0;  int i, j;  Token nullId;    /* Fake token for an empty ID list */  DbFixer sFix;    /* For assigning database names to pTable */  int isTemp;      /* True for a temporary index */  sqlite *db = pParse->db;  if( pParse->nErr || sqlite_malloc_failed ) goto exit_create_index;  if( db->init.busy      && sqliteFixInit(&sFix, pParse, db->init.iDb, "index", pName)     && sqliteFixSrcList(&sFix, pTable)  ){    goto exit_create_index;  }  /*  ** Find the table that is to be indexed.  Return early if not found.  */  if( pTable!=0 ){    assert( pName!=0 );    assert( pTable->nSrc==1 );    pTab =  sqliteSrcListLookup(pParse, pTable);  }else{    assert( pName==0 );    pTab =  pParse->pNewTable;  }  if( pTab==0 || pParse->nErr ) goto exit_create_index;  if( pTab->readOnly ){    sqliteErrorMsg(pParse, "table %s may not be indexed", pTab->zName);    goto exit_create_index;  }  if( pTab->iDb>=2 && db->init.busy==0 ){    sqliteErrorMsg(pParse, "table %s may not have indices added", pTab->zName);    goto exit_create_index;  }  if( pTab->pSelect ){    sqliteErrorMsg(pParse, "views may not be indexed");    goto exit_create_index;  }  isTemp = pTab->iDb==1;  /*  ** Find the name of the index.  Make sure there is not already another  ** index or table with the same name.    **  ** Exception:  If we are reading the names of permanent indices from the  ** sqlite_master table (because some other process changed the schema) and  ** one of the index names collides with the name of a temporary table or  ** index, then we will continue to process this index.  **  ** If pName==0 it means that we are  ** dealing with a primary key or UNIQUE constraint.  We have to invent our  ** own name.  */  if( pName && !db->init.busy ){    Index *pISameName;    /* Another index with the same name */    Table *pTSameName;    /* A table with same name as the index */    zName = sqliteTableNameFromToken(pName);    if( zName==0 ) goto exit_create_index;    if( (pISameName = sqliteFindIndex(db, zName, 0))!=0 ){      sqliteErrorMsg(pParse, "index %s already exists", zName);      goto exit_create_index;    }    if( (pTSameName = sqliteFindTable(db, zName, 0))!=0 ){      sqliteErrorMsg(pParse, "there is already a table named %s", zName);      goto exit_create_index;    }  }else if( pName==0 ){    char zBuf[30];    int n;    Index *pLoop;    for(pLoop=pTab->pIndex, n=1; pLoop; pLoop=pLoop->pNext, n++){}    sprintf(zBuf,"%d)",n);    zName = 0;    sqliteSetString(&zName, "(", pTab->zName, " autoindex ", zBuf, (char*)0);    if( zName==0 ) goto exit_create_index;  }else{    zName = sqliteTableNameFromToken(pName);  }  /* Check for authorization to create an index.  */#ifndef SQLITE_OMIT_AUTHORIZATION  {    const char *zDb = db->aDb[pTab->iDb].zName;    assert( pTab->iDb==db->init.iDb || isTemp );    if( sqliteAuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(isTemp), 0, zDb) ){      goto exit_create_index;    }    i = SQLITE_CREATE_INDEX;    if( isTemp ) i = SQLITE_CREATE_TEMP_INDEX;    if( sqliteAuthCheck(pParse, i, zName, pTab->zName, zDb) ){      goto exit_create_index;    }  }#endif  /* If pList==0, it means this routine was called to make a primary  ** key out of the last column added to the table under construction.  ** So create a fake list to simulate this.  */  if( pList==0 ){    nullId.z = pTab->aCol[pTab->nCol-1].zName;    nullId.n = strlen(nullId.z);    pList = sqliteIdListAppend(0, &nullId);    if( pList==0 ) goto exit_create_index;  }  /*   ** Allocate the index structure.   */  pIndex = sqliteMalloc( sizeof(Index) + strlen(zName) + 1 +                        sizeof(int)*pList->nId );  if( pIndex==0 ) goto exit_create_index;  pIndex->aiColumn = (int*)&pIndex[1];  pIndex->zName = (char*)&pIndex->aiColumn[pList->nId];  strcpy(pIndex->zName, zName);  pIndex->pTable = pTab;  pIndex->nColumn = pList->nId;  pIndex->onError = onError;  pIndex->autoIndex = pName==0;  pIndex->iDb = isTemp ? 1 : db->init.iDb;  /* Scan the names of the columns of the table to be indexed and  ** load the column indices into the Index structure.  Report an error  ** if any column is not found.  */  for(i=0; i<pList->nId; i++){    for(j=0; j<pTab->nCol; j++){      if( sqliteStrICmp(pList->a[i].zName, pTab->aCol[j].zName)==0 ) break;    }    if( j>=pTab->nCol ){      sqliteErrorMsg(pParse, "table %s has no column named %s",        pTab->zName, pList->a[i].zName);      sqliteFree(pIndex);      goto exit_create_index;    }    pIndex->aiColumn[i] = j;  }  /* Link the new Index structure to its table and to the other  ** in-memory database structures.   */  if( !pParse->explain ){    Index *p;    p = sqliteHashInsert(&db->aDb[pIndex->iDb].idxHash,                          pIndex->zName, strlen(pIndex->zName)+1, pIndex);    if( p ){      assert( p==pIndex );  /* Malloc must have failed */      sqliteFree(pIndex);      goto exit_create_index;    }    db->flags |= SQLITE_InternChanges;  }  /* When adding an index to the list of indices for a table, make  ** sure all indices labeled OE_Replace come after all those labeled  ** OE_Ignore.  This is necessary for the correct operation of UPDATE  ** and INSERT.  */  if( onError!=OE_Replace || pTab->pIndex==0       || pTab->pIndex->onError==OE_Replace){    pIndex->pNext = pTab->pIndex;    pTab->pIndex = pIndex;  }else{    Index *pOther = pTab->pIndex;    while( pOther->pNext && pOther->pNext->onError!=OE_Replace ){      pOther = pOther->pNext;    }    pIndex->pNext = pOther->pNext;    pOther->pNext = pIndex;  }  /* If the db->init.busy is 1 it means we are reading the SQL off the  ** "sqlite_master" table on the disk.  So do not write to the disk  ** again.  Extract the table number from the db->init.newTnum field.  */  if( db->init.busy && pTable!=0 ){    pIndex->tnum = db->init.newTnum;  }  /* If the db->init.busy is 0 then create the index on disk.  This  ** involves writing the index into the master table and filling in the  ** index with the current table contents.  **  ** The db->init.busy is 0 when the user first enters a CREATE INDEX   ** command.  db->init.busy is 1 when a database is opened and   ** CREATE INDEX statements are read out of the master table.  In  ** the latter case the index already exists on disk, which is why  ** we don't want to recreate it.  **  ** If pTable==0 it means this index is generated as a primary key  ** or UNIQUE constraint of a CREATE TABLE statement.  Since the table  ** has just been created, it contains no data and the index initialization  ** step can be skipped.  */  else if( db->init.busy==0 ){    int n;    Vdbe *v;    int lbl1, lbl2;    int i;    int addr;    v = sqliteGetVdbe(pParse);    if( v==0 ) goto exit_create_index;    if( pTable!=0 ){      sqliteBeginWriteOperation(pParse, 0, isTemp);      sqliteOpenMasterTable(v, isTemp);    }

⌨️ 快捷键说明

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