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

📄 insert.c

📁 sqlite的最新源码 This ZIP archive contains preprocessed C code for the SQLite library as individual sour
💻 C
📖 第 1 页 / 共 5 页
字号:
    aRegIdx = sqlite3DbMallocRaw(db, sizeof(int)*(nIdx+1));    if( aRegIdx==0 ){      goto insert_cleanup;    }    for(i=0; i<nIdx; i++){      aRegIdx[i] = ++pParse->nMem;    }  }  /* This is the top of the main insertion loop */  if( useTempTable ){    /* This block codes the top of loop only.  The complete loop is the    ** following pseudocode (template 4):    **    **         rewind temp table    **      C: loop over rows of intermediate table    **           transfer values form intermediate table into <table>    **         end loop    **      D: ...    */    addrInsTop = sqlite3VdbeAddOp1(v, OP_Rewind, srcTab);    addrCont = sqlite3VdbeCurrentAddr(v);  }else if( pSelect ){    /* This block codes the top of loop only.  The complete loop is the    ** following pseudocode (template 3):    **    **      C: yield X    **         if EOF goto D    **         insert the select result into <table> from R..R+n    **         goto C    **      D: ...    */    addrCont = sqlite3VdbeAddOp1(v, OP_Yield, dest.iParm);    addrInsTop = sqlite3VdbeAddOp1(v, OP_If, regEof);  }  /* Allocate registers for holding the rowid of the new row,  ** the content of the new row, and the assemblied row record.  */  regRecord = ++pParse->nMem;  regRowid = regIns = pParse->nMem+1;  pParse->nMem += pTab->nCol + 1;  if( IsVirtual(pTab) ){    regRowid++;    pParse->nMem++;  }  regData = regRowid+1;  /* Run the BEFORE and INSTEAD OF triggers, if there are any  */  endOfLoop = sqlite3VdbeMakeLabel(v);  if( triggers_exist & TRIGGER_BEFORE ){    int regRowid;    int regCols;    int regRec;    /* build the NEW.* reference row.  Note that if there is an INTEGER    ** PRIMARY KEY into which a NULL is being inserted, that NULL will be    ** translated into a unique ID for the row.  But on a BEFORE trigger,    ** we do not know what the unique ID will be (because the insert has    ** not happened yet) so we substitute a rowid of -1    */    regRowid = sqlite3GetTempReg(pParse);    if( keyColumn<0 ){      sqlite3VdbeAddOp2(v, OP_Integer, -1, regRowid);    }else if( useTempTable ){      sqlite3VdbeAddOp3(v, OP_Column, srcTab, keyColumn, regRowid);    }else{      int j1;      assert( pSelect==0 );  /* Otherwise useTempTable is true */      sqlite3ExprCode(pParse, pList->a[keyColumn].pExpr, regRowid);      j1 = sqlite3VdbeAddOp1(v, OP_NotNull, regRowid);      sqlite3VdbeAddOp2(v, OP_Integer, -1, regRowid);      sqlite3VdbeJumpHere(v, j1);      sqlite3VdbeAddOp1(v, OP_MustBeInt, regRowid);    }    /* Cannot have triggers on a virtual table. If it were possible,    ** this block would have to account for hidden column.    */    assert(!IsVirtual(pTab));    /* Create the new column data    */    regCols = sqlite3GetTempRange(pParse, pTab->nCol);    for(i=0; i<pTab->nCol; i++){      if( pColumn==0 ){        j = i;      }else{        for(j=0; j<pColumn->nId; j++){          if( pColumn->a[j].idx==i ) break;        }      }      if( pColumn && j>=pColumn->nId ){        sqlite3ExprCode(pParse, pTab->aCol[i].pDflt, regCols+i);      }else if( useTempTable ){        sqlite3VdbeAddOp3(v, OP_Column, srcTab, j, regCols+i);       }else{        assert( pSelect==0 ); /* Otherwise useTempTable is true */        sqlite3ExprCodeAndCache(pParse, pList->a[j].pExpr, regCols+i);      }    }    regRec = sqlite3GetTempReg(pParse);    sqlite3VdbeAddOp3(v, OP_MakeRecord, regCols, pTab->nCol, regRec);    /* If this is an INSERT on a view with an INSTEAD OF INSERT trigger,    ** do not attempt any conversions before assembling the record.    ** If this is a real table, attempt conversions as required by the    ** table column affinities.    */    if( !isView ){      sqlite3TableAffinityStr(v, pTab);    }    sqlite3VdbeAddOp3(v, OP_Insert, newIdx, regRec, regRowid);    sqlite3ReleaseTempReg(pParse, regRec);    sqlite3ReleaseTempReg(pParse, regRowid);    sqlite3ReleaseTempRange(pParse, regCols, pTab->nCol);    /* Fire BEFORE or INSTEAD OF triggers */    if( sqlite3CodeRowTrigger(pParse, TK_INSERT, 0, TRIGGER_BEFORE, pTab,         newIdx, -1, onError, endOfLoop, 0, 0) ){      goto insert_cleanup;    }  }  /* Push the record number for the new entry onto the stack.  The  ** record number is a randomly generate integer created by NewRowid  ** except when the table has an INTEGER PRIMARY KEY column, in which  ** case the record number is the same as that column.   */  if( !isView ){    if( IsVirtual(pTab) ){      /* The row that the VUpdate opcode will delete: none */      sqlite3VdbeAddOp2(v, OP_Null, 0, regIns);    }    if( keyColumn>=0 ){      if( useTempTable ){        sqlite3VdbeAddOp3(v, OP_Column, srcTab, keyColumn, regRowid);      }else if( pSelect ){        sqlite3VdbeAddOp2(v, OP_SCopy, regFromSelect+keyColumn, regRowid);      }else{        VdbeOp *pOp;        sqlite3ExprCode(pParse, pList->a[keyColumn].pExpr, regRowid);        pOp = sqlite3VdbeGetOp(v, sqlite3VdbeCurrentAddr(v) - 1);        if( pOp && pOp->opcode==OP_Null && !IsVirtual(pTab) ){          appendFlag = 1;          pOp->opcode = OP_NewRowid;          pOp->p1 = baseCur;          pOp->p2 = regRowid;          pOp->p3 = regAutoinc;        }      }      /* If the PRIMARY KEY expression is NULL, then use OP_NewRowid      ** to generate a unique primary key value.      */      if( !appendFlag ){        int j1;        if( !IsVirtual(pTab) ){          j1 = sqlite3VdbeAddOp1(v, OP_NotNull, regRowid);          sqlite3VdbeAddOp3(v, OP_NewRowid, baseCur, regRowid, regAutoinc);          sqlite3VdbeJumpHere(v, j1);        }else{          j1 = sqlite3VdbeCurrentAddr(v);          sqlite3VdbeAddOp2(v, OP_IsNull, regRowid, j1+2);        }        sqlite3VdbeAddOp1(v, OP_MustBeInt, regRowid);      }    }else if( IsVirtual(pTab) ){      sqlite3VdbeAddOp2(v, OP_Null, 0, regRowid);    }else{      sqlite3VdbeAddOp3(v, OP_NewRowid, baseCur, regRowid, regAutoinc);      appendFlag = 1;    }    autoIncStep(pParse, regAutoinc, regRowid);    /* Push onto the stack, data for all columns of the new entry, beginning    ** with the first column.    */    nHidden = 0;    for(i=0; i<pTab->nCol; i++){      int iRegStore = regRowid+1+i;      if( i==pTab->iPKey ){        /* The value of the INTEGER PRIMARY KEY column is always a NULL.        ** Whenever this column is read, the record number will be substituted        ** in its place.  So will fill this column with a NULL to avoid        ** taking up data space with information that will never be used. */        sqlite3VdbeAddOp2(v, OP_Null, 0, iRegStore);        continue;      }      if( pColumn==0 ){        if( IsHiddenColumn(&pTab->aCol[i]) ){          assert( IsVirtual(pTab) );          j = -1;          nHidden++;        }else{          j = i - nHidden;        }      }else{        for(j=0; j<pColumn->nId; j++){          if( pColumn->a[j].idx==i ) break;        }      }      if( j<0 || nColumn==0 || (pColumn && j>=pColumn->nId) ){        sqlite3ExprCode(pParse, pTab->aCol[i].pDflt, iRegStore);      }else if( useTempTable ){        sqlite3VdbeAddOp3(v, OP_Column, srcTab, j, iRegStore);       }else if( pSelect ){        sqlite3VdbeAddOp2(v, OP_SCopy, regFromSelect+j, iRegStore);      }else{        sqlite3ExprCode(pParse, pList->a[j].pExpr, iRegStore);      }    }    /* Generate code to check constraints and generate index keys and    ** do the insertion.    */#ifndef SQLITE_OMIT_VIRTUALTABLE    if( IsVirtual(pTab) ){      sqlite3VtabMakeWritable(pParse, pTab);      sqlite3VdbeAddOp4(v, OP_VUpdate, 1, pTab->nCol+2, regIns,                     (const char*)pTab->pVtab, P4_VTAB);    }else#endif    {      sqlite3GenerateConstraintChecks(          pParse,          pTab,          baseCur,          regIns,          aRegIdx,          keyColumn>=0,          0,          onError,          endOfLoop      );      sqlite3CompleteInsertion(          pParse,          pTab,          baseCur,          regIns,          aRegIdx,          0,          (triggers_exist & TRIGGER_AFTER)!=0 ? newIdx : -1,          appendFlag       );    }  }  /* Update the count of rows that are inserted  */  if( (db->flags & SQLITE_CountRows)!=0 ){    sqlite3VdbeAddOp2(v, OP_AddImm, regRowCount, 1);  }  if( triggers_exist ){    /* Code AFTER triggers */    if( sqlite3CodeRowTrigger(pParse, TK_INSERT, 0, TRIGGER_AFTER, pTab,          newIdx, -1, onError, endOfLoop, 0, 0) ){      goto insert_cleanup;    }  }  /* The bottom of the main insertion loop, if the data source  ** is a SELECT statement.  */  sqlite3VdbeResolveLabel(v, endOfLoop);  if( useTempTable ){    sqlite3VdbeAddOp2(v, OP_Next, srcTab, addrCont);    sqlite3VdbeJumpHere(v, addrInsTop);    sqlite3VdbeAddOp1(v, OP_Close, srcTab);  }else if( pSelect ){    sqlite3VdbeAddOp2(v, OP_Goto, 0, addrCont);    sqlite3VdbeJumpHere(v, addrInsTop);  }  if( !IsVirtual(pTab) && !isView ){    /* Close all tables opened */    sqlite3VdbeAddOp1(v, OP_Close, baseCur);    for(idx=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, idx++){      sqlite3VdbeAddOp1(v, OP_Close, idx+baseCur);    }  }  /* Update the sqlite_sequence table by storing the content of the  ** counter value in memory regAutoinc back into the sqlite_sequence  ** table.  */  autoIncEnd(pParse, iDb, pTab, regAutoinc);  /*  ** Return the number of rows inserted. If this routine is   ** generating code because of a call to sqlite3NestedParse(), do not  ** invoke the callback function.  */  if( db->flags & SQLITE_CountRows && pParse->nested==0 && !pParse->trigStack ){    sqlite3VdbeAddOp2(v, OP_ResultRow, regRowCount, 1);    sqlite3VdbeSetNumCols(v, 1);    sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows inserted", SQLITE_STATIC);  }insert_cleanup:  sqlite3SrcListDelete(db, pTabList);  sqlite3ExprListDelete(db, pList);  sqlite3SelectDelete(db, pSelect);  sqlite3IdListDelete(db, pColumn);  sqlite3DbFree(db, aRegIdx);}/*** Generate code to do constraint checks prior to an INSERT or an UPDATE.**** The input is a range of consecutive registers as follows:****    1.  The rowid of the row to be updated before the update.  This**        value is omitted unless we are doing an UPDATE that involves a**        change to the record number or writing to a virtual table.****    2.  The rowid of the row after the update.****    3.  The data in the first column of the entry after the update.****    i.  Data from middle columns...****    N.  The data in the last column of the entry after the update.**** The regRowid parameter is the index of the register containing (2).**** The old rowid shown as entry (1) above is omitted unless both isUpdate** and rowidChng are 1.  isUpdate is true for UPDATEs and false for** INSERTs.  RowidChng means that the new rowid is explicitly specified by** the update or insert statement.  If rowidChng is false, it means that** the rowid is computed automatically in an insert or that the rowid value** is not modified by the update.**** The code generated by this routine store new index entries into** registers identified by aRegIdx[].  No index entry is created for** indices where aRegIdx[i]==0.  The order of indices in aRegIdx[] is** the same as the order of indices on the linked list of indices** attached to the table.**** This routine also generates code to check constraints.  NOT NULL,** CHECK, and UNIQUE constraints are all checked.  If a constraint fails,** then the appropriate action is performed.  There are five possible** actions: ROLLBACK, ABORT, FAIL, REPLACE, and IGNORE.****  Constraint type  Action       What Happens**  ---------------  ----------   ----------------------------------------**  any              ROLLBACK     The current transaction is rolled back and

⌨️ 快捷键说明

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