?? insert.c
字號:
}
}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;
useTempTable = 0;
nColumn = pList ? pList->nExpr : 0;
for(i=0; i<nColumn; i++){
if( sqlite3ExprResolveNames(&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( pColumn==0 && nColumn && nColumn!=pTab->nCol ){
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 ){
sqlite3VdbeAddOp(v, OP_OpenPseudo, newIdx, 0);
sqlite3VdbeAddOp(v, OP_SetNumColumns, newIdx, pTab->nCol);
}
/* Initialize the count of rows to be inserted
*/
if( db->flags & SQLITE_CountRows ){
iCntMem = pParse->nMem++;
sqlite3VdbeAddOp(v, OP_MemInt, 0, iCntMem);
}
/* Open tables and indices if there are no row triggers */
if( !triggers_exist ){
base = pParse->nTab;
sqlite3OpenTableAndIndices(pParse, pTab, base, OP_OpenWrite);
}
/* 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 = sqlite3VdbeMakeLabel(v);
sqlite3VdbeAddOp(v, OP_Rewind, srcTab, iBreak);
iCont = sqlite3VdbeCurrentAddr(v);
}else if( pSelect ){
sqlite3VdbeAddOp(v, OP_Goto, 0, iSelectLoop);
sqlite3VdbeResolveLabel(v, iInsertBlock);
}
/* Run the BEFORE and INSTEAD OF triggers, if there are any
*/
endOfLoop = sqlite3VdbeMakeLabel(v);
if( triggers_exist & TRIGGER_BEFORE ){
/* 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 ){
sqlite3VdbeAddOp(v, OP_Integer, -1, 0);
}else if( useTempTable ){
sqlite3VdbeAddOp(v, OP_Column, srcTab, keyColumn);
}else{
assert( pSelect==0 ); /* Otherwise useTempTable is true */
sqlite3ExprCode(pParse, pList->a[keyColumn].pExpr);
sqlite3VdbeAddOp(v, OP_NotNull, -1, sqlite3VdbeCurrentAddr(v)+3);
sqlite3VdbeAddOp(v, OP_Pop, 1, 0);
sqlite3VdbeAddOp(v, OP_Integer, -1, 0);
sqlite3VdbeAddOp(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 ){
sqlite3ExprCode(pParse, pTab->aCol[i].pDflt);
}else if( useTempTable ){
sqlite3VdbeAddOp(v, OP_Column, srcTab, j);
}else{
assert( pSelect==0 ); /* Otherwise useTempTable is true */
sqlite3ExprCodeAndCache(pParse, pList->a[j].pExpr);
}
}
sqlite3VdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0);
/* 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);
}
sqlite3VdbeAddOp(v, OP_Insert, newIdx, 0);
/* Fire BEFORE or INSTEAD OF triggers */
if( sqlite3CodeRowTrigger(pParse, TK_INSERT, 0, TRIGGER_BEFORE, pTab,
newIdx, -1, onError, endOfLoop) ){
goto insert_cleanup;
}
}
/* If any triggers exists, the opening of tables and indices is deferred
** until now.
*/
if( triggers_exist && !isView ){
base = pParse->nTab;
sqlite3OpenTableAndIndices(pParse, pTab, base, OP_OpenWrite);
}
/* 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 */
sqlite3VdbeAddOp(v, OP_Null, 0, 0);
}
if( keyColumn>=0 ){
if( useTempTable ){
sqlite3VdbeAddOp(v, OP_Column, srcTab, keyColumn);
}else if( pSelect ){
sqlite3VdbeAddOp(v, OP_Dup, nColumn - keyColumn - 1, 1);
}else{
sqlite3ExprCode(pParse, pList->a[keyColumn].pExpr);
}
/* If the PRIMARY KEY expression is NULL, then use OP_NewRowid
** to generate a unique primary key value.
*/
sqlite3VdbeAddOp(v, OP_NotNull, -1, sqlite3VdbeCurrentAddr(v)+3);
sqlite3VdbeAddOp(v, OP_Pop, 1, 0);
sqlite3VdbeAddOp(v, OP_NewRowid, base, counterMem);
sqlite3VdbeAddOp(v, OP_MustBeInt, 0, 0);
}else if( IsVirtual(pTab) ){
sqlite3VdbeAddOp(v, OP_Null, 0, 0);
}else{
sqlite3VdbeAddOp(v, OP_NewRowid, base, counterMem);
}
#ifndef SQLITE_OMIT_AUTOINCREMENT
if( pTab->autoInc ){
sqlite3VdbeAddOp(v, OP_MemMax, counterMem, 0);
}
#endif /* SQLITE_OMIT_AUTOINCREMENT */
/* 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. */
sqlite3VdbeAddOp(v, OP_Null, 0, 0);
continue;
}
if( pColumn==0 ){
j = i;
}else{
for(j=0; j<pColumn->nId; j++){
if( pColumn->a[j].idx==i ) break;
}
}
if( nColumn==0 || (pColumn && j>=pColumn->nId) ){
sqlite3ExprCode(pParse, pTab->aCol[i].pDflt);
}else if( useTempTable ){
sqlite3VdbeAddOp(v, OP_Column, srcTab, j);
}else if( pSelect ){
sqlite3VdbeAddOp(v, OP_Dup, i+nColumn-j+IsVirtual(pTab), 1);
}else{
sqlite3ExprCode(pParse, pList->a[j].pExpr);
}
}
/* Generate code to check constraints and generate index keys and
** do the insertion.
*/
#ifndef SQLITE_OMIT_VIRTUALTABLE
if( IsVirtual(pTab) ){
pParse->pVirtualLock = pTab;
sqlite3VdbeOp3(v, OP_VUpdate, 1, pTab->nCol+2,
(const char*)pTab->pVtab, P3_VTAB);
}else
#endif
{
sqlite3GenerateConstraintChecks(pParse, pTab, base, 0, keyColumn>=0,
0, onError, endOfLoop);
sqlite3CompleteInsertion(pParse, pTab, base, 0,0,0,
(triggers_exist & TRIGGER_AFTER)!=0 ? newIdx : -1);
}
}
/* Update the count of rows that are inserted
*/
if( (db->flags & SQLITE_CountRows)!=0 ){
sqlite3VdbeAddOp(v, OP_MemIncr, 1, iCntMem);
}
if( triggers_exist ){
/* Close all tables opened */
if( !isView ){
sqlite3VdbeAddOp(v, OP_Close, base, 0);
for(idx=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, idx++){
sqlite3VdbeAddOp(v, OP_Close, idx+base, 0);
}
}
/* Code AFTER triggers */
if( sqlite3CodeRowTrigger(pParse, TK_INSERT, 0, TRIGGER_AFTER, pTab,
newIdx, -1, onError, endOfLoop) ){
goto insert_cleanup;
}
}
/* The bottom of the loop, if the data source is a SELECT statement
*/
sqlite3VdbeResolveLabel(v, endOfLoop);
if( useTempTable ){
sqlite3VdbeAddOp(v, OP_Next, srcTab, iCont);
sqlite3VdbeResolveLabel(v, iBreak);
sqlite3VdbeAddOp(v, OP_Close, srcTab, 0);
}else if( pSelect ){
sqlite3VdbeAddOp(v, OP_Pop, nColumn, 0);
sqlite3VdbeAddOp(v, OP_Return, 0, 0);
sqlite3VdbeResolveLabel(v, iCleanup);
}
if( !triggers_exist && !IsVirtual(pTab) ){
/* Close all tables opened */
sqlite3VdbeAddOp(v, OP_Close, base, 0);
for(idx=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, idx++){
sqlite3VdbeAddOp(v, OP_Close, idx+base, 0);
}
}
#ifndef SQLITE_OMIT_AUTOINCREMENT
/* Update the sqlite_sequence table by storing the content of the
** counter value in memory counterMem back into the sqlite_sequence
** table.
*/
if( pTab->autoInc ){
int iCur = pParse->nTab;
int addr = sqlite3VdbeCurrentAddr(v);
sqlite3OpenTable(pParse, iCur, iDb, pDb->pSchema->pSeqTab, OP_OpenWrite);
sqlite3VdbeAddOp(v, OP_MemLoad, counterRowid, 0);
sqlite3VdbeAddOp(v, OP_NotNull, -1, addr+7);
sqlite3VdbeAddOp(v, OP_Pop, 1, 0);
sqlite3VdbeAddOp(v, OP_NewRowid, iCur, 0);
sqlite3VdbeOp3(v, OP_String8, 0, 0, pTab->zName, 0);
sqlite3VdbeAddOp(v, OP_MemLoad, counterMem, 0);
sqlite3VdbeAddOp(v, OP_MakeRecord, 2, 0);
sqlite3VdbeAddOp(v, OP_Insert, iCur, 0);
sqlite3VdbeAddOp(v, OP_Close, iCur, 0);
}
#endif
/*
** 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 ){
sqlite3VdbeAddOp(v, OP_MemLoad, iCntMem, 0);
sqlite3VdbeAddOp(v, OP_Callback, 1, 0);
sqlite3VdbeSetNumCols(v, 1);
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows inserted", P3_STATIC);
}
insert_cleanup:
sqlite3SrcListDelete(pTabList);
sqlite3ExprListDelete(pList);
sqlite3SelectDelete(pSelect);
sqlite3IdListDelete(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 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.
**
** 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 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 and rowidChng 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.
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -