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

📄 build.c

📁 调用sqlite开源数据的小程序
💻 C
📖 第 1 页 / 共 5 页
字号:
      zStmt[k++] = ' ';      strcpy(&zStmt[k], z);      k += strlen(z);    }  }  strcpy(&zStmt[k], 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;  if( (pEnd==0 && pSelect==0) || pParse->nErr || sqlite3_malloc_failed ) return;  p = pParse->pNewTable;  if( p==0 ) return;  assert( !db->init.busy || !pSelect );  /* 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.    */    if( pSelect ){      Table *pSelTab;      sqlite3VdbeAddOp(v, OP_Dup, 0, 0);      sqlite3VdbeAddOp(v, OP_Integer, p->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(0, pSelTab);      }    }    /* Compute the complete text of the CREATE statement */    if( pSelect ){      zStmt = createTableStmt(p);    }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[p->iDb].zName, SCHEMA_TABLE(p->iDb),      zType,      p->zName,      p->zName,      zStmt    );    sqliteFree(zStmt);    sqlite3ChangeCookie(db, v, p->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[p->iDb];      if( pDb->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, p->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;     Db *pDb = &db->aDb[p->iDb];    pOld = sqlite3HashInsert(&pDb->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(&pDb->aFKey, pFKey->zTo, nTo);      sqlite3HashInsert(&pDb->aFKey, pFKey->zTo, nTo, pFKey);    }#endif    pParse->pNewTable = 0;    db->nTable++;    db->flags |= SQLITE_InternChanges;#ifndef SQLITE_OMIT_ALTERTABLE    if( !p->pSelect ){      assert( !pSelect && pCons && pEnd );      if( pCons->z==0 ) pCons = pEnd;      p->addColOffset = 13 + (pCons->z - pParse->sNameToken.z);    }#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 */){  Table *p;  int n;  const unsigned char *z;  Token sEnd;  DbFixer sFix;  Token *pName;  if( pParse->nVar>0 ){    sqlite3ErrorMsg(pParse, "parameters are not allowed in views");    sqlite3SelectDelete(pSelect);    return;  }  sqlite3StartTable(pParse, pBegin, pName1, pName2, isTemp, 1);  p = pParse->pNewTable;  if( p==0 || pParse->nErr ){    sqlite3SelectDelete(pSelect);    return;  }  sqlite3TwoPartName(pParse, pName1, pName2, &pName);  if( sqlite3FixInit(&sFix, pParse, p->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( !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;  z = (const unsigned char*)pBegin->z;  while( n>0 && (z[n-1]==';' || isspace(z[n-1])) ){ n--; }  sEnd.z = &z[n-1];  sEnd.n = 1;  /* Use sqlite3EndTable() to add the view to the SQLITE_MASTER table */  sqlite3EndTable(pParse, 0, &sEnd, 0);  return;}#endif /* SQLITE_OMIT_VIEW */#ifndef SQLITE_OMIT_VIEW/*** The Table structure pTable is really a VIEW.  Fill in the names of** the columns of the view in the pTable structure.  Return the number** of errors.  If an error is seen leave an error message in pParse->zErrMsg.*/int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){  Table *pSelTab;   /* A fake table from which we get the result set */  Select *pSel;     /* Copy of the SELECT that implements the view */  int nErr = 0;     /* Number of errors encountered */  int n;            /* Temporarily holds the number of cursors assigned */  assert( pTable );  /* A positive nCol means the columns names for this view are  ** already known.  */  if( pTable->nCol>0 ) return 0;  /* A negative nCol is a special marker meaning that we are currently  ** trying to compute the column names.  If we enter this routine with  ** a negative nCol, it means two or more views form a loop, like this:  **  **     CREATE VIEW one AS SELECT * FROM two;  **     CREATE VIEW two AS SELECT * FROM one;  **  ** Actually, this error is caught previously and so the following test  ** should always fail.  But we will leave it in place just to be safe.  */#if 0  if( pTable->nCol<0 ){    sqlite3ErrorMsg(pParse, "view %s is circularly defined", pTable->zName);    return 1;  }#endif  assert( pTable->nCol>=0 );  /* If we get this far, it means we need to compute the table names.  ** Note that the call to sqlite3ResultSetOfSelect() will expand any  ** "*" elements in the results set of the view and will assign cursors  ** to the elements of the FROM clause.  But we do not want these changes  ** to be permanent.  So the computation is done on a copy of the SELECT  ** statement that defines the view.  */  assert( pTable->pSelect );  pSel = sqlite3SelectDup(pTable->pSelect);  n = pParse->nTab;  sqlite3SrcListAssignCursors(pParse, pSel->pSrc);  pTable->nCol = -1;  pSelTab = sqlite3ResultSetOfSelect(pParse, 0, pSel);  pParse->nTab = n;  if( pSelTab ){    assert( pTable->aCol==0 );    pTable->nCol = pSelTab->nCol;    pTable->aCol = pSelTab->aCol;    pSelTab->nCol = 0;    pSelTab->aCol = 0;    sqlite3DeleteTable(0, pSelTab);    DbSetProperty(pParse->db, pTable->iDb, DB_UnresetViews);  }else{    pTable->nCol = 0;    nErr++;  }  sqlite3SelectDelete(pSel);  return nErr;  }#endif /* SQLITE_OMIT_VIEW */#ifndef SQLITE_OMIT_VIEW/*** Clear the column names from every VIEW in database idx.*/static void sqliteViewResetAll(sqlite3 *db, int idx){  HashElem *i;  if( !DbHasProperty(db, idx, DB_UnresetViews) ) return;  for(i=sqliteHashFirst(&db->aDb[idx].tblHash); i; i=sqliteHashNext(i)){    Table *pTab = sqliteHashData(i);    if( pTab->pSelect ){      sqliteResetColumnNames(pTab);    }  }  DbClearProperty(db, idx, DB_UnresetViews);}#else# define sqliteViewResetAll(A,B)#endif /* SQLITE_OMIT_VIEW *//*** This function is called by the VDBE to adjust the internal schema** used by SQLite when the btree layer moves a table root page. The** root-page of a table or index in database iDb has changed from iFrom** to iTo.*/#ifndef SQLITE_OMIT_AUTOVACUUMvoid sqlite3RootPageMoved(Db *pDb, int iFrom, int iTo){  HashElem *pElem;    for(pElem=sqliteHashFirst(&pDb->tblHash); pElem; pElem=sqliteHashNext(pElem)){    Table *pTab = sqliteHashData(pElem);    if( pTab->tnum==iFrom ){      pTab->tnum = iTo;      return;    }  }  for(pElem=sqliteHashFirst(&pDb->idxHash); pElem; pElem=sqliteHashNext(pElem)){    Index *pIdx = sqliteHashData(pElem);    if( pIdx->tnum==iFrom ){      pIdx->tnum = iTo;      return;    }  }  assert(0);}#endif/*** Write code to erase the table with root-page iTable from database iDb.** Also write code to modify the sqlite_master table and internal schema** if a root-page of another table is moved by the btree-layer whilst** erasing iTable (this can happen with an auto-vacuum database).*/ static void destroyRootPage(Parse *pParse, int iTable, int iDb){  Vdbe *v = sqlite3GetVdbe(pParse);  sqlite3VdbeAddOp(v, OP_Destroy, iTable, iDb);#ifndef SQLITE_OMIT_AUTOVACUUM  /* OP_Destroy pushes an integer onto the stack. If this integer  ** is non-zero, then it is the root page number of a table moved to  ** 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

⌨️ 快捷键说明

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