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

📄 build.c

📁 最新的sqlite3.6.2源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
        pIdx->azColl[0] = p->aCol[i].zColl;      }    }  }else{    sqlite3DbFree(db, zColl);  }}/*** This function returns the collation sequence for database native text** encoding identified by the string zName, length nName.**** If the requested collation sequence is not available, or not available** in the database native encoding, the collation factory is invoked to** request it. If the collation factory does not supply such a sequence,** and the sequence is available in another text encoding, then that is** returned instead.**** If no versions of the requested collations sequence are available, or** another error occurs, NULL is returned and an error message written into** pParse.**** This routine is a wrapper around sqlite3FindCollSeq().  This routine** invokes the collation factory if the named collation cannot be found** and generates an error message.*/CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char *zName, int nName){  sqlite3 *db = pParse->db;  u8 enc = ENC(db);  u8 initbusy = db->init.busy;  CollSeq *pColl;  pColl = sqlite3FindCollSeq(db, enc, zName, nName, initbusy);  if( !initbusy && (!pColl || !pColl->xCmp) ){    pColl = sqlite3GetCollSeq(db, pColl, zName, nName);    if( !pColl ){      if( nName<0 ){        nName = sqlite3Strlen(db, zName);      }      sqlite3ErrorMsg(pParse, "no such collation sequence: %.*s", nName, zName);      pColl = 0;    }  }  return pColl;}/*** Generate code that will increment the schema cookie.**** The schema cookie is used to determine when the schema for the** database changes.  After each schema change, the cookie value** changes.  When a process first reads the schema it records the** cookie.  Thereafter, whenever it goes to access the database,** it checks the cookie to make sure the schema has not changed** since it was last read.**** This plan is not completely bullet-proof.  It is possible for** the schema to change multiple times and for the cookie to be** set back to prior value.  But schema changes are infrequent** and the probability of hitting the same cookie value is only** 1 chance in 2^32.  So we're safe enough.*/void sqlite3ChangeCookie(Parse *pParse, int iDb){  int r1 = sqlite3GetTempReg(pParse);  sqlite3 *db = pParse->db;  Vdbe *v = pParse->pVdbe;  sqlite3VdbeAddOp2(v, OP_Integer, db->aDb[iDb].pSchema->schema_cookie+1, r1);  sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, 0, r1);  sqlite3ReleaseTempReg(pParse, r1);}/*** Measure the number of characters needed to output the given** identifier.  The number returned includes any quotes used** but does not include the null terminator.**** The estimate is conservative.  It might be larger that what is** really needed.*/static int identLength(const char *z){  int n;  for(n=0; *z; n++, z++){    if( *z=='"' ){ n++; }  }  return n + 2;}/*** Write an identifier onto the end of the given string.  Add** quote characters as needed.*/static void identPut(char *z, int *pIdx, char *zSignedIdent){  unsigned char *zIdent = (unsigned char*)zSignedIdent;  int i, j, needQuote;  i = *pIdx;  for(j=0; zIdent[j]; j++){    if( !isalnum(zIdent[j]) && zIdent[j]!='_' ) break;  }  needQuote =  zIdent[j]!=0 || isdigit(zIdent[0])                  || sqlite3KeywordCode(zIdent, j)!=TK_ID;  if( needQuote ) z[i++] = '"';  for(j=0; zIdent[j]; j++){    z[i++] = zIdent[j];    if( zIdent[j]=='"' ) z[i++] = '"';  }  if( needQuote ) z[i++] = '"';  z[i] = 0;  *pIdx = i;}/*** Generate a CREATE TABLE statement appropriate for the given** table.  Memory to hold the text of the statement is obtained** from sqliteMalloc() and must be freed by the calling function.*/static char *createTableStmt(sqlite3 *db, Table *p, int isTemp){  int i, k, n;  char *zStmt;  char *zSep, *zSep2, *zEnd, *z;  Column *pCol;  n = 0;  for(pCol = p->aCol, i=0; i<p->nCol; i++, pCol++){    n += identLength(pCol->zName);    z = pCol->zType;    if( z ){      n += (strlen(z) + 1);    }  }  n += identLength(p->zName);  if( n<50 ){    zSep = "";    zSep2 = ",";    zEnd = ")";  }else{    zSep = "\n  ";    zSep2 = ",\n  ";    zEnd = "\n)";  }  n += 35 + 6*p->nCol;  zStmt = sqlite3Malloc( n );  if( zStmt==0 ){    db->mallocFailed = 1;    return 0;  }  sqlite3_snprintf(n, zStmt,                  !OMIT_TEMPDB&&isTemp ? "CREATE TEMP TABLE ":"CREATE TABLE ");  k = strlen(zStmt);  identPut(zStmt, &k, p->zName);  zStmt[k++] = '(';  for(pCol=p->aCol, i=0; i<p->nCol; i++, pCol++){    sqlite3_snprintf(n-k, &zStmt[k], zSep);    k += strlen(&zStmt[k]);    zSep = zSep2;    identPut(zStmt, &k, pCol->zName);    if( (z = pCol->zType)!=0 ){      zStmt[k++] = ' ';      assert( strlen(z)+k+1<=n );      sqlite3_snprintf(n-k, &zStmt[k], "%s", z);      k += strlen(z);    }  }  sqlite3_snprintf(n-k, &zStmt[k], "%s", zEnd);  return zStmt;}/*** This routine is called to report the final ")" that terminates** a CREATE TABLE statement.**** The table structure that other action routines have been building** is added to the internal hash tables, assuming no errors have** occurred.**** An entry for the table is made in the master table on disk, unless** this is a temporary table or db->init.busy==1.  When db->init.busy==1** it means we are reading the sqlite_master table because we just** connected to the database or because the sqlite_master table has** recently changed, so the entry for this table already exists in** the sqlite_master table.  We do not want to create it again.**** If the pSelect argument is not NULL, it means that this routine** was called to create a table generated from a ** "CREATE TABLE ... AS SELECT ..." statement.  The column names of** the new table will match the result set of the SELECT.*/void sqlite3EndTable(  Parse *pParse,          /* Parse context */  Token *pCons,           /* The ',' token after the last column defn. */  Token *pEnd,            /* The final ')' token in the CREATE TABLE */  Select *pSelect         /* Select from a "CREATE ... AS SELECT" */){  Table *p;  sqlite3 *db = pParse->db;  int iDb;  if( (pEnd==0 && pSelect==0) || pParse->nErr || db->mallocFailed ) {    return;  }  p = pParse->pNewTable;  if( p==0 ) return;  assert( !db->init.busy || !pSelect );  iDb = sqlite3SchemaToIndex(db, p->pSchema);#ifndef SQLITE_OMIT_CHECK  /* Resolve names in all CHECK constraint expressions.  */  if( p->pCheck ){    SrcList sSrc;                   /* Fake SrcList for pParse->pNewTable */    NameContext sNC;                /* Name context for pParse->pNewTable */    memset(&sNC, 0, sizeof(sNC));    memset(&sSrc, 0, sizeof(sSrc));    sSrc.nSrc = 1;    sSrc.a[0].zName = p->zName;    sSrc.a[0].pTab = p;    sSrc.a[0].iCursor = -1;    sNC.pParse = pParse;    sNC.pSrcList = &sSrc;    sNC.isCheck = 1;    if( sqlite3ResolveExprNames(&sNC, p->pCheck) ){      return;    }  }#endif /* !defined(SQLITE_OMIT_CHECK) */  /* If the db->init.busy is 1 it means we are reading the SQL off the  ** "sqlite_master" or "sqlite_temp_master" table on the disk.  ** So do not write to the disk again.  Extract the root page number  ** for the table from the db->init.newTnum field.  (The page number  ** should have been put there by the sqliteOpenCb routine.)  */  if( db->init.busy ){    p->tnum = db->init.newTnum;  }  /* If not initializing, then create a record for the new table  ** in the SQLITE_MASTER table of the database.  The record number  ** for the new table entry should already be on the stack.  **  ** If this is a TEMPORARY table, write the entry into the auxiliary  ** file instead of into the main database file.  */  if( !db->init.busy ){    int n;    Vdbe *v;    char *zType;    /* "view" or "table" */    char *zType2;   /* "VIEW" or "TABLE" */    char *zStmt;    /* Text of the CREATE TABLE or CREATE VIEW statement */    v = sqlite3GetVdbe(pParse);    if( v==0 ) return;    sqlite3VdbeAddOp1(v, OP_Close, 0);    /* Create the rootpage for the new table and push it onto the stack.    ** A view has no rootpage, so just push a zero onto the stack for    ** views.  Initialize zType at the same time.    */    if( p->pSelect==0 ){      /* A regular table */      zType = "table";      zType2 = "TABLE";#ifndef SQLITE_OMIT_VIEW    }else{      /* A view */      zType = "view";      zType2 = "VIEW";#endif    }    /* If this is a CREATE TABLE xx AS SELECT ..., execute the SELECT    ** statement to populate the new table. The root-page number for the    ** new table is on the top of the vdbe stack.    **    ** Once the SELECT has been coded by sqlite3Select(), it is in a    ** suitable state to query for the column names and types to be used    ** by the new table.    **    ** A shared-cache write-lock is not required to write to the new table,    ** as a schema-lock must have already been obtained to create it. Since    ** a schema-lock excludes all other database users, the write-lock would    ** be redundant.    */    if( pSelect ){      SelectDest dest;      Table *pSelTab;      assert(pParse->nTab==0);      sqlite3VdbeAddOp3(v, OP_OpenWrite, 1, pParse->regRoot, iDb);      sqlite3VdbeChangeP5(v, 1);      pParse->nTab = 2;      sqlite3SelectDestInit(&dest, SRT_Table, 1);      sqlite3Select(pParse, pSelect, &dest);      sqlite3VdbeAddOp1(v, OP_Close, 1);      if( pParse->nErr==0 ){        pSelTab = sqlite3ResultSetOfSelect(pParse, pSelect);        if( pSelTab==0 ) return;        assert( p->aCol==0 );        p->nCol = pSelTab->nCol;        p->aCol = pSelTab->aCol;        pSelTab->nCol = 0;        pSelTab->aCol = 0;        sqlite3DeleteTable(pSelTab);      }    }    /* Compute the complete text of the CREATE statement */    if( pSelect ){      zStmt = createTableStmt(db, p, p->pSchema==db->aDb[1].pSchema);    }else{      n = pEnd->z - pParse->sNameToken.z + 1;      zStmt = sqlite3MPrintf(db,           "CREATE %s %.*s", zType2, n, pParse->sNameToken.z      );    }    /* A slot for the record has already been allocated in the     ** SQLITE_MASTER table.  We just need to update that slot with all    ** the information we've collected.  The rowid for the preallocated    ** slot is the 2nd item on the stack.  The top of the stack is the    ** root page for the new table (or a 0 if this is a view).    */    sqlite3NestedParse(pParse,      "UPDATE %Q.%s "         "SET type='%s', name=%Q, tbl_name=%Q, rootpage=#%d, sql=%Q "       "WHERE rowid=#%d",      db->aDb[iDb].zName, SCHEMA_TABLE(iDb),      zType,      p->zName,      p->zName,      pParse->regRoot,      zStmt,      pParse->regRowid    );    sqlite3DbFree(db, zStmt);    sqlite3ChangeCookie(pParse, iDb);#ifndef SQLITE_OMIT_AUTOINCREMENT    /* Check to see if we need to create an sqlite_sequence table for    ** keeping track of autoincrement keys.    */    if( p->tabFlags & TF_Autoincrement ){      Db *pDb = &db->aDb[iDb];      if( pDb->pSchema->pSeqTab==0 ){        sqlite3NestedParse(pParse,          "CREATE TABLE %Q.sqlite_sequence(name,seq)",          pDb->zName        );      }    }#endif    /* Reparse everything to update our internal data structures */    sqlite3VdbeAddOp4(v, OP_ParseSchema, iDb, 0, 0,        sqlite3MPrintf(db, "tbl_name='%q'",p->zName), P4_DYNAMIC);  }  /* Add the table to the in-memory representation of the database.  */  if( db->init.busy && pParse->nErr==0 ){    Table *pOld;    FKey *pFKey;     Schema *pSchema = p->pSchema;    pOld = sqlite3HashInsert(&pSchema->tblHash, p->zName, strlen(p->zName)+1,p);    if( pOld ){      assert( p==pOld );  /* Malloc must have failed inside HashInsert() */      db->mallocFailed = 1;      return;    }#ifndef SQLITE_OMIT_FOREIGN_KEY    for(pFKey=p->pFKey; pFKey; pFKey=pFKey->pNextFrom){      void *data;      int nTo = strlen(pFKey->zTo) + 1;      pFKey->pNextTo = sqlite3HashFind(&pSchema->aFKey, pFKey->zTo, nTo);      data = sqlite3HashInsert(&pSchema->aFKey, pFKey->zTo, nTo, pFKey);      if( data==(void *)pFKey ){        db->mallocFailed = 1;      }    }#endif    pParse->pNewTable = 0;    db->nTable++;    db->flags |= SQLITE_InternChanges;#ifndef SQLITE_OMIT_ALTERTABLE    if( !p->pSelect ){      const char *zName = (const char *)pParse->sNameToken.z;      int nName;      assert( !pSelect && pCons && pEnd );      if( pCons->z==0 ){        pCons = pEnd;      }      nName = (const char *)pCons->z - zName;      p->addColOffset = 13 + sqlite3Utf8CharLen(zName, nName);    }#endif  }}#ifndef SQLITE_OMIT_VIEW/*** The parser calls this routine in order to create a new VIEW*/void sqlite3CreateView(  Parse *pParse,     /* The parsing context */  Token *pBegin,     /* The CREATE token that begins the statement */  Token *pName1,     /* The token that holds the name of the view */

⌨️ 快捷键说明

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