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

📄 build.c

📁 sqlite-3.4.1,嵌入式数据库.是一个功能强大的开源数据库,给学习和研发以及小型公司的发展带来了全所未有的好处.
💻 C
📖 第 1 页 / 共 5 页
字号:
      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(sqlite3 *db, Vdbe *v, int iDb){  sqlite3VdbeAddOp(v, OP_Integer, db->aDb[iDb].pSchema->schema_cookie+1, 0);  sqlite3VdbeAddOp(v, OP_SetCookie, iDb, 0);}/*** 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(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 = sqliteMallocRaw( n );  if( zStmt==0 ) 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 || sqlite3MallocFailed() ) {    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( sqlite3ExprResolveNames(&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;    sqlite3VdbeAddOp(v, OP_Close, 0, 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 ){      Table *pSelTab;      sqlite3VdbeAddOp(v, OP_Dup, 0, 0);      sqlite3VdbeAddOp(v, OP_Integer, iDb, 0);      sqlite3VdbeAddOp(v, OP_OpenWrite, 1, 0);      pParse->nTab = 2;      sqlite3Select(pParse, pSelect, SRT_Table, 1, 0, 0, 0, 0);      sqlite3VdbeAddOp(v, OP_Close, 1, 0);      if( pParse->nErr==0 ){        pSelTab = sqlite3ResultSetOfSelect(pParse, 0, 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(p, p->pSchema==pParse->db->aDb[1].pSchema);    }else{      n = pEnd->z - pParse->sNameToken.z + 1;      zStmt = sqlite3MPrintf("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=#0, sql=%Q "       "WHERE rowid=#1",      db->aDb[iDb].zName, SCHEMA_TABLE(iDb),      zType,      p->zName,      p->zName,      zStmt    );    sqliteFree(zStmt);    sqlite3ChangeCookie(db, v, 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->autoInc ){      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 */    sqlite3VdbeOp3(v, OP_ParseSchema, iDb, 0,        sqlite3MPrintf("tbl_name='%q'",p->zName), P3_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() */      return;    }#ifndef SQLITE_OMIT_FOREIGN_KEY    for(pFKey=p->pFKey; pFKey; pFKey=pFKey->pNextFrom){      int nTo = strlen(pFKey->zTo) + 1;      pFKey->pNextTo = sqlite3HashFind(&pSchema->aFKey, pFKey->zTo, nTo);      sqlite3HashInsert(&pSchema->aFKey, pFKey->zTo, nTo, pFKey);    }#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 */  Token *pName2,     /* The token that holds the name of the view */  Select *pSelect,   /* A SELECT statement that will become the new view */  int isTemp,        /* TRUE for a TEMPORARY view */  int noErr          /* Suppress error messages if VIEW already exists */){  Table *p;  int n;  const unsigned char *z;  Token sEnd;  DbFixer sFix;  Token *pName;  int iDb;  if( pParse->nVar>0 ){    sqlite3ErrorMsg(pParse, "parameters are not allowed in views");    sqlite3SelectDelete(pSelect);    return;  }  sqlite3StartTable(pParse, pName1, pName2, isTemp, 1, 0, noErr);  p = pParse->pNewTable;  if( p==0 || pParse->nErr ){    sqlite3SelectDelete(pSelect);    return;  }  sqlite3TwoPartName(pParse, pName1, pName2, &pName);  iDb = sqlite3SchemaToIndex(pParse->db, p->pSchema);  if( sqlite3FixInit(&sFix, pParse, iDb, "view", pName)    && sqlite3FixSelect(&sFix, pSelect)  ){    sqlite3SelectDelete(pSelect);    return;  }  /* Make a copy of the entire SELECT statement that defines the view.  ** This will force all the Expr.token.z values to be dynamically  ** allocated rather than point to the input string - which means that  ** they will persist after the current sqlite3_exec() call returns.  */  p->pSelect = sqlite3SelectDup(pSelect);  sqlite3SelectDelete(pSelect);  if( sqlite3MallocFailed() ){    return;  }  if( !pParse->db->init.busy ){    sqlite3ViewGetColumnNames(pParse, p);  }  /* Locate the end of the CREATE VIEW statement.  Make sEnd point to  ** the end.  */  sEnd = pParse->sLastToken;  if( sEnd.z[0]!=0 && sEnd.z[0]!=';' ){    sEnd.z += sEnd.n;  }  sEnd.n = 0;  n = sEnd.z - pBegin->z;

⌨️ 快捷键说明

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