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

📄 insert.c

📁 sqlite的最新源码 This ZIP archive contains preprocessed C code for the SQLite library as individual sour
💻 C
📖 第 1 页 / 共 5 页
字号:
**         if EOF goto M**         insert row from R..R+n into temp table**         goto L**      M: open write cursor to <table> and its indices**         rewind temp table**      C: loop over rows of intermediate table**           transfer values form intermediate table into <table>**         end loop**      D: cleanup*/void sqlite3Insert(  Parse *pParse,        /* Parser context */  SrcList *pTabList,    /* Name of table into which we are inserting */  ExprList *pList,      /* List of values to be inserted */  Select *pSelect,      /* A SELECT statement to use as the data source */  IdList *pColumn,      /* Column names corresponding to IDLIST. */  int onError           /* How to handle constraint errors */){  sqlite3 *db;          /* The main database structure */  Table *pTab;          /* The table to insert into.  aka TABLE */  char *zTab;           /* Name of the table into which we are inserting */  const char *zDb;      /* Name of the database holding this table */  int i, j, idx;        /* Loop counters */  Vdbe *v;              /* Generate code into this virtual machine */  Index *pIdx;          /* For looping over indices of the table */  int nColumn;          /* Number of columns in the data */  int nHidden = 0;      /* Number of hidden columns if TABLE is virtual */  int baseCur = 0;      /* VDBE Cursor number for pTab */  int keyColumn = -1;   /* Column that is the INTEGER PRIMARY KEY */  int endOfLoop;        /* Label for the end of the insertion loop */  int useTempTable = 0; /* Store SELECT results in intermediate table */  int srcTab = 0;       /* Data comes from this temporary cursor if >=0 */  int addrInsTop = 0;   /* Jump to label "D" */  int addrCont = 0;     /* Top of insert loop. Label "C" in templates 3 and 4 */  int addrSelect = 0;   /* Address of coroutine that implements the SELECT */  SelectDest dest;      /* Destination for SELECT on rhs of INSERT */  int newIdx = -1;      /* Cursor for the NEW pseudo-table */  int iDb;              /* Index of database holding TABLE */  Db *pDb;              /* The database containing table being inserted into */  int appendFlag = 0;   /* True if the insert is likely to be an append */  /* Register allocations */  int regFromSelect;    /* Base register for data coming from SELECT */  int regAutoinc = 0;   /* Register holding the AUTOINCREMENT counter */  int regRowCount = 0;  /* Memory cell used for the row counter */  int regIns;           /* Block of regs holding rowid+data being inserted */  int regRowid;         /* registers holding insert rowid */  int regData;          /* register holding first column to insert */  int regRecord;        /* Holds the assemblied row record */  int regEof;           /* Register recording end of SELECT data */  int *aRegIdx = 0;     /* One register allocated to each index */#ifndef SQLITE_OMIT_TRIGGER  int isView;                 /* True if attempting to insert into a view */  int triggers_exist = 0;     /* True if there are FOR EACH ROW triggers */#endif  db = pParse->db;  if( pParse->nErr || db->mallocFailed ){    goto insert_cleanup;  }  /* Locate the table into which we will be inserting new information.  */  assert( pTabList->nSrc==1 );  zTab = pTabList->a[0].zName;  if( zTab==0 ) goto insert_cleanup;  pTab = sqlite3SrcListLookup(pParse, pTabList);  if( pTab==0 ){    goto insert_cleanup;  }  iDb = sqlite3SchemaToIndex(db, pTab->pSchema);  assert( iDb<db->nDb );  pDb = &db->aDb[iDb];  zDb = pDb->zName;  if( sqlite3AuthCheck(pParse, SQLITE_INSERT, pTab->zName, 0, zDb) ){    goto insert_cleanup;  }  /* Figure out if we have any triggers and if the table being  ** inserted into is a view  */#ifndef SQLITE_OMIT_TRIGGER  triggers_exist = sqlite3TriggersExist(pTab, TK_INSERT, 0);  isView = pTab->pSelect!=0;#else# define triggers_exist 0# define isView 0#endif#ifdef SQLITE_OMIT_VIEW# undef isView# define isView 0#endif  /* Ensure that:  *  (a) the table is not read-only,   *  (b) that if it is a view then ON INSERT triggers exist  */  if( sqlite3IsReadOnly(pParse, pTab, triggers_exist) ){    goto insert_cleanup;  }  assert( pTab!=0 );  /* If pTab is really a view, make sure it has been initialized.  ** ViewGetColumnNames() is a no-op if pTab is not a view (or virtual   ** module table).  */  if( sqlite3ViewGetColumnNames(pParse, pTab) ){    goto insert_cleanup;  }  /* Allocate a VDBE  */  v = sqlite3GetVdbe(pParse);  if( v==0 ) goto insert_cleanup;  if( pParse->nested==0 ) sqlite3VdbeCountChanges(v);  sqlite3BeginWriteOperation(pParse, pSelect || triggers_exist, iDb);  /* if there are row triggers, allocate a temp table for new.* references. */  if( triggers_exist ){    newIdx = pParse->nTab++;  }#ifndef SQLITE_OMIT_XFER_OPT  /* If the statement is of the form  **  **       INSERT INTO <table1> SELECT * FROM <table2>;  **  ** Then special optimizations can be applied that make the transfer  ** very fast and which reduce fragmentation of indices.  **  ** This is the 2nd template.  */  if( pColumn==0 && xferOptimization(pParse, pTab, pSelect, onError, iDb) ){    assert( !triggers_exist );    assert( pList==0 );    goto insert_cleanup;  }#endif /* SQLITE_OMIT_XFER_OPT */  /* If this is an AUTOINCREMENT table, look up the sequence number in the  ** sqlite_sequence table and store it in memory cell regAutoinc.  */  regAutoinc = autoIncBegin(pParse, iDb, pTab);  /* Figure out how many columns of data are supplied.  If the data  ** is coming from a SELECT statement, then generate a co-routine that  ** produces a single row of the SELECT on each invocation.  The  ** co-routine is the common header to the 3rd and 4th templates.  */  if( pSelect ){    /* Data is coming from a SELECT.  Generate code to implement that SELECT    ** as a co-routine.  The code is common to both the 3rd and 4th    ** templates:    **    **         EOF <- 0    **         X <- A    **         goto B    **      A: setup for the SELECT    **         loop over the tables in the SELECT    **           load value into register R..R+n    **           yield X    **         end loop    **         cleanup after the SELECT    **         EOF <- 1    **         yield X    **         halt-error    **    ** On each invocation of the co-routine, it puts a single row of the    ** SELECT result into registers dest.iMem...dest.iMem+dest.nMem-1.    ** (These output registers are allocated by sqlite3Select().)  When    ** the SELECT completes, it sets the EOF flag stored in regEof.    */    int rc, j1;    regEof = ++pParse->nMem;    sqlite3VdbeAddOp2(v, OP_Integer, 0, regEof);      /* EOF <- 0 */    VdbeComment((v, "SELECT eof flag"));    sqlite3SelectDestInit(&dest, SRT_Coroutine, ++pParse->nMem);    addrSelect = sqlite3VdbeCurrentAddr(v)+2;    sqlite3VdbeAddOp2(v, OP_Integer, addrSelect-1, dest.iParm);    j1 = sqlite3VdbeAddOp2(v, OP_Goto, 0, 0);    VdbeComment((v, "Jump over SELECT coroutine"));    /* Resolve the expressions in the SELECT statement and execute it. */    rc = sqlite3Select(pParse, pSelect, &dest);    if( rc || pParse->nErr || db->mallocFailed ){      goto insert_cleanup;    }    sqlite3VdbeAddOp2(v, OP_Integer, 1, regEof);         /* EOF <- 1 */    sqlite3VdbeAddOp1(v, OP_Yield, dest.iParm);   /* yield X */    sqlite3VdbeAddOp2(v, OP_Halt, SQLITE_INTERNAL, OE_Abort);    VdbeComment((v, "End of SELECT coroutine"));    sqlite3VdbeJumpHere(v, j1);                          /* label B: */    regFromSelect = dest.iMem;    assert( pSelect->pEList );    nColumn = pSelect->pEList->nExpr;    assert( dest.nMem==nColumn );    /* Set useTempTable to TRUE if the result of the SELECT statement    ** should be written into a temporary table (template 4).  Set to    ** FALSE if each* row of the SELECT can be written directly into    ** the destination table (template 3).    **    ** A temp table must be used if the table being updated is also one    ** of the tables being read by the SELECT statement.  Also use a     ** temp table in the case of row triggers.    */    if( triggers_exist || readsTable(v, addrSelect, iDb, pTab) ){      useTempTable = 1;    }    if( useTempTable ){      /* Invoke the coroutine to extract information from the SELECT      ** and add it to a transient table srcTab.  The code generated      ** here is from the 4th template:      **      **      B: open temp table      **      L: yield X      **         if EOF goto M      **         insert row from R..R+n into temp table      **         goto L      **      M: ...      */      int regRec;      /* Register to hold packed record */      int regRowid;    /* Register to hold temp table ROWID */      int addrTop;     /* Label "L" */      int addrIf;      /* Address of jump to M */      srcTab = pParse->nTab++;      regRec = sqlite3GetTempReg(pParse);      regRowid = sqlite3GetTempReg(pParse);      sqlite3VdbeAddOp2(v, OP_OpenEphemeral, srcTab, nColumn);      addrTop = sqlite3VdbeAddOp1(v, OP_Yield, dest.iParm);      addrIf = sqlite3VdbeAddOp1(v, OP_If, regEof);      sqlite3VdbeAddOp3(v, OP_MakeRecord, regFromSelect, nColumn, regRec);      sqlite3VdbeAddOp2(v, OP_NewRowid, srcTab, regRowid);      sqlite3VdbeAddOp3(v, OP_Insert, srcTab, regRec, regRowid);      sqlite3VdbeAddOp2(v, OP_Goto, 0, addrTop);      sqlite3VdbeJumpHere(v, addrIf);      sqlite3ReleaseTempReg(pParse, regRec);      sqlite3ReleaseTempReg(pParse, regRowid);    }  }else{    /* This is the case if the data for the INSERT is coming from a VALUES    ** clause    */    NameContext sNC;    memset(&sNC, 0, sizeof(sNC));    sNC.pParse = pParse;    srcTab = -1;    assert( useTempTable==0 );    nColumn = pList ? pList->nExpr : 0;    for(i=0; i<nColumn; i++){      if( sqlite3ResolveExprNames(&sNC, pList->a[i].pExpr) ){        goto insert_cleanup;      }    }  }  /* Make sure the number of columns in the source data matches the number  ** of columns to be inserted into the table.  */  if( IsVirtual(pTab) ){    for(i=0; i<pTab->nCol; i++){      nHidden += (IsHiddenColumn(&pTab->aCol[i]) ? 1 : 0);    }  }  if( pColumn==0 && nColumn && nColumn!=(pTab->nCol-nHidden) ){    sqlite3ErrorMsg(pParse,        "table %S has %d columns but %d values were supplied",       pTabList, 0, pTab->nCol, nColumn);    goto insert_cleanup;  }  if( pColumn!=0 && nColumn!=pColumn->nId ){    sqlite3ErrorMsg(pParse, "%d values for %d columns", nColumn, pColumn->nId);    goto insert_cleanup;  }  /* If the INSERT statement included an IDLIST term, then make sure  ** all elements of the IDLIST really are columns of the table and   ** remember the column indices.  **  ** If the table has an INTEGER PRIMARY KEY column and that column  ** is named in the IDLIST, then record in the keyColumn variable  ** the index into IDLIST of the primary key column.  keyColumn is  ** the index of the primary key as it appears in IDLIST, not as  ** is appears in the original table.  (The index of the primary  ** key in the original table is pTab->iPKey.)  */  if( pColumn ){    for(i=0; i<pColumn->nId; i++){      pColumn->a[i].idx = -1;    }    for(i=0; i<pColumn->nId; i++){      for(j=0; j<pTab->nCol; j++){        if( sqlite3StrICmp(pColumn->a[i].zName, pTab->aCol[j].zName)==0 ){          pColumn->a[i].idx = j;          if( j==pTab->iPKey ){            keyColumn = i;          }          break;        }      }      if( j>=pTab->nCol ){        if( sqlite3IsRowid(pColumn->a[i].zName) ){          keyColumn = i;        }else{          sqlite3ErrorMsg(pParse, "table %S has no column named %s",              pTabList, 0, pColumn->a[i].zName);          pParse->nErr++;          goto insert_cleanup;        }      }    }  }  /* If there is no IDLIST term but the table has an integer primary  ** key, the set the keyColumn variable to the primary key column index  ** in the original table definition.  */  if( pColumn==0 && nColumn>0 ){    keyColumn = pTab->iPKey;  }  /* Open the temp table for FOR EACH ROW triggers  */  if( triggers_exist ){    sqlite3VdbeAddOp2(v, OP_SetNumColumns, 0, pTab->nCol);    sqlite3VdbeAddOp2(v, OP_OpenPseudo, newIdx, 0);  }      /* Initialize the count of rows to be inserted  */  if( db->flags & SQLITE_CountRows ){    regRowCount = ++pParse->nMem;    sqlite3VdbeAddOp2(v, OP_Integer, 0, regRowCount);  }  /* If this is not a view, open the table and and all indices */  if( !isView ){    int nIdx;    int i;    baseCur = pParse->nTab;    nIdx = sqlite3OpenTableAndIndices(pParse, pTab, baseCur, OP_OpenWrite);

⌨️ 快捷键说明

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