📄 insert.c
字号:
/* 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 ){ keyColumn = pTab->iPKey; } /* Open the temp table for FOR EACH ROW triggers */ if( row_triggers_exist ){ sqliteVdbeAddOp(v, OP_OpenPseudo, newIdx, 0); } /* Initialize the count of rows to be inserted */ if( db->flags & SQLITE_CountRows ){ iCntMem = pParse->nMem++; sqliteVdbeAddOp(v, OP_Integer, 0, 0); sqliteVdbeAddOp(v, OP_MemStore, iCntMem, 1); } /* Open tables and indices if there are no row triggers */ if( !row_triggers_exist ){ base = pParse->nTab; idx = sqliteOpenTableAndIndices(pParse, pTab, base); pParse->nTab += idx; } /* If the data source is a temporary table, then we have to create ** a loop because there might be multiple rows of data. If the data ** source is a subroutine call from the SELECT statement, then we need ** to launch the SELECT statement processing. */ if( useTempTable ){ iBreak = sqliteVdbeMakeLabel(v); sqliteVdbeAddOp(v, OP_Rewind, srcTab, iBreak); iCont = sqliteVdbeCurrentAddr(v); }else if( pSelect ){ sqliteVdbeAddOp(v, OP_Goto, 0, iSelectLoop); sqliteVdbeResolveLabel(v, iInsertBlock); } /* Run the BEFORE and INSTEAD OF triggers, if there are any */ endOfLoop = sqliteVdbeMakeLabel(v); if( before_triggers ){ /* 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 */ if( keyColumn<0 ){ sqliteVdbeAddOp(v, OP_Integer, -1, 0); }else if( useTempTable ){ sqliteVdbeAddOp(v, OP_Column, srcTab, keyColumn); }else if( pSelect ){ sqliteVdbeAddOp(v, OP_Dup, nColumn - keyColumn - 1, 1); }else{ sqliteExprCode(pParse, pList->a[keyColumn].pExpr); sqliteVdbeAddOp(v, OP_NotNull, -1, sqliteVdbeCurrentAddr(v)+3); sqliteVdbeAddOp(v, OP_Pop, 1, 0); sqliteVdbeAddOp(v, OP_Integer, -1, 0); sqliteVdbeAddOp(v, OP_MustBeInt, 0, 0); } /* Create the new column data */ 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 ){ sqliteVdbeOp3(v, OP_String, 0, 0, pTab->aCol[i].zDflt, P3_STATIC); }else if( useTempTable ){ sqliteVdbeAddOp(v, OP_Column, srcTab, j); }else if( pSelect ){ sqliteVdbeAddOp(v, OP_Dup, nColumn-j-1, 1); }else{ sqliteExprCode(pParse, pList->a[j].pExpr); } } sqliteVdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0); sqliteVdbeAddOp(v, OP_PutIntKey, newIdx, 0); /* Fire BEFORE or INSTEAD OF triggers */ if( sqliteCodeRowTrigger(pParse, TK_INSERT, 0, TK_BEFORE, pTab, newIdx, -1, onError, endOfLoop) ){ goto insert_cleanup; } } /* If any triggers exists, the opening of tables and indices is deferred ** until now. */ if( row_triggers_exist && !isView ){ base = pParse->nTab; idx = sqliteOpenTableAndIndices(pParse, pTab, base); pParse->nTab += idx; } /* Push the record number for the new entry onto the stack. The ** record number is a randomly generate integer created by NewRecno ** 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( keyColumn>=0 ){ if( useTempTable ){ sqliteVdbeAddOp(v, OP_Column, srcTab, keyColumn); }else if( pSelect ){ sqliteVdbeAddOp(v, OP_Dup, nColumn - keyColumn - 1, 1); }else{ sqliteExprCode(pParse, pList->a[keyColumn].pExpr); } /* If the PRIMARY KEY expression is NULL, then use OP_NewRecno ** to generate a unique primary key value. */ sqliteVdbeAddOp(v, OP_NotNull, -1, sqliteVdbeCurrentAddr(v)+3); sqliteVdbeAddOp(v, OP_Pop, 1, 0); sqliteVdbeAddOp(v, OP_NewRecno, base, 0); sqliteVdbeAddOp(v, OP_MustBeInt, 0, 0); }else{ sqliteVdbeAddOp(v, OP_NewRecno, base, 0); } /* Push onto the stack, data for all columns of the new entry, beginning ** with the first column. */ for(i=0; i<pTab->nCol; 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. */ sqliteVdbeAddOp(v, OP_String, 0, 0); continue; } 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 ){ sqliteVdbeOp3(v, OP_String, 0, 0, pTab->aCol[i].zDflt, P3_STATIC); }else if( useTempTable ){ sqliteVdbeAddOp(v, OP_Column, srcTab, j); }else if( pSelect ){ sqliteVdbeAddOp(v, OP_Dup, i+nColumn-j, 1); }else{ sqliteExprCode(pParse, pList->a[j].pExpr); } } /* Generate code to check constraints and generate index keys and ** do the insertion. */ sqliteGenerateConstraintChecks(pParse, pTab, base, 0, keyColumn>=0, 0, onError, endOfLoop); sqliteCompleteInsertion(pParse, pTab, base, 0,0,0, after_triggers ? newIdx : -1); } /* Update the count of rows that are inserted */ if( (db->flags & SQLITE_CountRows)!=0 ){ sqliteVdbeAddOp(v, OP_MemIncr, iCntMem, 0); } if( row_triggers_exist ){ /* Close all tables opened */ if( !isView ){ sqliteVdbeAddOp(v, OP_Close, base, 0); for(idx=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, idx++){ sqliteVdbeAddOp(v, OP_Close, idx+base, 0); } } /* Code AFTER triggers */ if( sqliteCodeRowTrigger(pParse, TK_INSERT, 0, TK_AFTER, pTab, newIdx, -1, onError, endOfLoop) ){ goto insert_cleanup; } } /* The bottom of the loop, if the data source is a SELECT statement */ sqliteVdbeResolveLabel(v, endOfLoop); if( useTempTable ){ sqliteVdbeAddOp(v, OP_Next, srcTab, iCont); sqliteVdbeResolveLabel(v, iBreak); sqliteVdbeAddOp(v, OP_Close, srcTab, 0); }else if( pSelect ){ sqliteVdbeAddOp(v, OP_Pop, nColumn, 0); sqliteVdbeAddOp(v, OP_Return, 0, 0); sqliteVdbeResolveLabel(v, iCleanup); } if( !row_triggers_exist ){ /* Close all tables opened */ sqliteVdbeAddOp(v, OP_Close, base, 0); for(idx=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, idx++){ sqliteVdbeAddOp(v, OP_Close, idx+base, 0); } } sqliteVdbeAddOp(v, OP_SetCounts, 0, 0); sqliteEndWriteOperation(pParse); /* ** Return the number of rows inserted. */ if( db->flags & SQLITE_CountRows ){ sqliteVdbeOp3(v, OP_ColumnName, 0, 1, "rows inserted", P3_STATIC); sqliteVdbeAddOp(v, OP_MemLoad, iCntMem, 0); sqliteVdbeAddOp(v, OP_Callback, 1, 0); }insert_cleanup: sqliteSrcListDelete(pTabList); if( pList ) sqliteExprListDelete(pList); if( pSelect ) sqliteSelectDelete(pSelect); sqliteIdListDelete(pColumn);}/*** Generate code to do a constraint check prior to an INSERT or an UPDATE.**** When this routine is called, the stack contains (from bottom to top)** the following values:**** 1. The recno 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.**** 2. The recno 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 old recno shown as entry (1) above is omitted unless both isUpdate** and recnoChng are 1. isUpdate is true for UPDATEs and false for** INSERTs and recnoChng is true if the record number is being changed.**** The code generated by this routine pushes additional entries onto** the stack which are the keys for new index entries for the new record.** The order of index keys is the same as the order of the indices on** the pTable->pIndex list. A key is only created for index i if ** aIdxUsed!=0 and aIdxUsed[i]!=0.**** 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** sqlite_exec() returns immediately with a** return code of SQLITE_CONSTRAINT.**** any ABORT Back out changes from the current command** only (do not do a complete rollback) then** cause sqlite_exec() to return immediately** with SQLITE_CONSTRAINT.**** any FAIL Sqlite_exec() returns immediately with a** return code of SQLITE_CONSTRAINT. The** transaction is not rolled back and any** prior changes are retained.**** any IGNORE The record number and data is popped from** the stack and there is an immediate jump** to label ignoreDest.**** NOT NULL REPLACE The NULL value is replace by the default** value for that column. If the default value** is NULL, the action is the same as ABORT.**** UNIQUE REPLACE The other row that conflicts with the row** being inserted is removed.**** CHECK REPLACE Illegal. The results in an exception.**** Which action to take is determined by the overrideError parameter.** Or if overrideError==OE_Default, then the pParse->onError parameter** is used. Or if pParse->onError==OE_Default then the onError value** for the constraint is used.**** The calling routine must open a read/write cursor for pTab with** cursor number "base". All indices of pTab must also have open** read/write cursors with cursor number base+i for the i-th cursor.** Except, if there is no possibility of a REPLACE action then** cursors do not need to be open for indices where aIdxUsed[i]==0.**** If the isUpdate flag is true, it means that the "base" cursor is
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -