📄 insert.c
字号:
** arguments to sqlite3GenerateConstraintChecks.*/void sqlite3CompleteInsertion( Parse *pParse, /* The parser context */ Table *pTab, /* the table into which we are inserting */ int base, /* Index of a read/write cursor pointing at pTab */ char *aIdxUsed, /* Which indices are used. NULL means all are used */ int rowidChng, /* True if the record number will change */ int isUpdate, /* True for UPDATE, False for INSERT */ int newIdx, /* Index of NEW table for triggers. -1 if none */ int appendBias /* True if this is likely to be an append */){ int i; Vdbe *v; int nIdx; Index *pIdx; int pik_flags; v = sqlite3GetVdbe(pParse); assert( v!=0 ); assert( pTab->pSelect==0 ); /* This table is not a VIEW */ for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){} for(i=nIdx-1; i>=0; i--){ if( aIdxUsed && aIdxUsed[i]==0 ) continue; sqlite3VdbeAddOp(v, OP_IdxInsert, base+i+1, 0); } sqlite3VdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0); sqlite3TableAffinityStr(v, pTab);#ifndef SQLITE_OMIT_TRIGGER if( newIdx>=0 ){ sqlite3VdbeAddOp(v, OP_Dup, 1, 0); sqlite3VdbeAddOp(v, OP_Dup, 1, 0); sqlite3VdbeAddOp(v, OP_Insert, newIdx, 0); }#endif if( pParse->nested ){ pik_flags = 0; }else{ pik_flags = OPFLAG_NCHANGE; pik_flags |= (isUpdate?OPFLAG_ISUPDATE:OPFLAG_LASTROWID); } if( appendBias ){ pik_flags |= OPFLAG_APPEND; } sqlite3VdbeAddOp(v, OP_Insert, base, pik_flags); if( !pParse->nested ){ sqlite3VdbeChangeP3(v, -1, pTab->zName, P3_STATIC); } if( isUpdate && rowidChng ){ sqlite3VdbeAddOp(v, OP_Pop, 1, 0); }}/*** Generate code that will open cursors for a table and for all** indices of that table. The "base" parameter is the cursor number used** for the table. Indices are opened on subsequent cursors.*/void sqlite3OpenTableAndIndices( Parse *pParse, /* Parsing context */ Table *pTab, /* Table to be opened */ int base, /* Cursor number assigned to the table */ int op /* OP_OpenRead or OP_OpenWrite */){ int i; int iDb; Index *pIdx; Vdbe *v; if( IsVirtual(pTab) ) return; iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); v = sqlite3GetVdbe(pParse); assert( v!=0 ); sqlite3OpenTable(pParse, base, iDb, pTab, op); for(i=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){ KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIdx); assert( pIdx->pSchema==pTab->pSchema ); sqlite3VdbeAddOp(v, OP_Integer, iDb, 0); VdbeComment((v, "# %s", pIdx->zName)); sqlite3VdbeOp3(v, op, i+base, pIdx->tnum, (char*)pKey, P3_KEYINFO_HANDOFF); } if( pParse->nTab<=base+i ){ pParse->nTab = base+i; }}#ifdef SQLITE_TEST/*** The following global variable is incremented whenever the** transfer optimization is used. This is used for testing** purposes only - to make sure the transfer optimization really** is happening when it is suppose to.*/int sqlite3_xferopt_count;#endif /* SQLITE_TEST */#ifndef SQLITE_OMIT_XFER_OPT/*** Check to collation names to see if they are compatible.*/static int xferCompatibleCollation(const char *z1, const char *z2){ if( z1==0 ){ return z2==0; } if( z2==0 ){ return 0; } return sqlite3StrICmp(z1, z2)==0;}/*** Check to see if index pSrc is compatible as a source of data** for index pDest in an insert transfer optimization. The rules** for a compatible index:**** * The index is over the same set of columns** * The same DESC and ASC markings occurs on all columns** * The same onError processing (OE_Abort, OE_Ignore, etc)** * The same collating sequence on each column*/static int xferCompatibleIndex(Index *pDest, Index *pSrc){ int i; assert( pDest && pSrc ); assert( pDest->pTable!=pSrc->pTable ); if( pDest->nColumn!=pSrc->nColumn ){ return 0; /* Different number of columns */ } if( pDest->onError!=pSrc->onError ){ return 0; /* Different conflict resolution strategies */ } for(i=0; i<pSrc->nColumn; i++){ if( pSrc->aiColumn[i]!=pDest->aiColumn[i] ){ return 0; /* Different columns indexed */ } if( pSrc->aSortOrder[i]!=pDest->aSortOrder[i] ){ return 0; /* Different sort orders */ } if( pSrc->azColl[i]!=pDest->azColl[i] ){ return 0; /* Different sort orders */ } } /* If no test above fails then the indices must be compatible */ return 1;}/*** Attempt the transfer optimization on INSERTs of the form**** INSERT INTO tab1 SELECT * FROM tab2;**** This optimization is only attempted if**** (1) tab1 and tab2 have identical schemas including all the** same indices and constraints**** (2) tab1 and tab2 are different tables**** (3) There must be no triggers on tab1**** (4) The result set of the SELECT statement is "*"**** (5) The SELECT statement has no WHERE, HAVING, ORDER BY, GROUP BY,** or LIMIT clause.**** (6) The SELECT statement is a simple (not a compound) select that** contains only tab2 in its FROM clause**** This method for implementing the INSERT transfers raw records from** tab2 over to tab1. The columns are not decoded. Raw records from** the indices of tab2 are transfered to tab1 as well. In so doing,** the resulting tab1 has much less fragmentation.**** This routine returns TRUE if the optimization is attempted. If any** of the conditions above fail so that the optimization should not** be attempted, then this routine returns FALSE.*/static int xferOptimization( Parse *pParse, /* Parser context */ Table *pDest, /* The table we are inserting into */ Select *pSelect, /* A SELECT statement to use as the data source */ int onError, /* How to handle constraint errors */ int iDbDest /* The database of pDest */){ ExprList *pEList; /* The result set of the SELECT */ Table *pSrc; /* The table in the FROM clause of SELECT */ Index *pSrcIdx, *pDestIdx; /* Source and destination indices */ struct SrcList_item *pItem; /* An element of pSelect->pSrc */ int i; /* Loop counter */ int iDbSrc; /* The database of pSrc */ int iSrc, iDest; /* Cursors from source and destination */ int addr1, addr2; /* Loop addresses */ int emptyDestTest; /* Address of test for empty pDest */ int emptySrcTest; /* Address of test for empty pSrc */ Vdbe *v; /* The VDBE we are building */ KeyInfo *pKey; /* Key information for an index */ int counterMem; /* Memory register used by AUTOINC */ int destHasUniqueIdx = 0; /* True if pDest has a UNIQUE index */ if( pSelect==0 ){ return 0; /* Must be of the form INSERT INTO ... SELECT ... */ } if( pDest->pTrigger ){ return 0; /* tab1 must not have triggers */ }#ifndef SQLITE_OMIT_VIRTUALTABLE if( pDest->isVirtual ){ return 0; /* tab1 must not be a virtual table */ }#endif if( onError==OE_Default ){ onError = OE_Abort; } if( onError!=OE_Abort && onError!=OE_Rollback ){ return 0; /* Cannot do OR REPLACE or OR IGNORE or OR FAIL */ } assert(pSelect->pSrc); /* allocated even if there is no FROM clause */ if( pSelect->pSrc->nSrc!=1 ){ return 0; /* FROM clause must have exactly one term */ } if( pSelect->pSrc->a[0].pSelect ){ return 0; /* FROM clause cannot contain a subquery */ } if( pSelect->pWhere ){ return 0; /* SELECT may not have a WHERE clause */ } if( pSelect->pOrderBy ){ return 0; /* SELECT may not have an ORDER BY clause */ } /* Do not need to test for a HAVING clause. If HAVING is present but ** there is no ORDER BY, we will get an error. */ if( pSelect->pGroupBy ){ return 0; /* SELECT may not have a GROUP BY clause */ } if( pSelect->pLimit ){ return 0; /* SELECT may not have a LIMIT clause */ } assert( pSelect->pOffset==0 ); /* Must be so if pLimit==0 */ if( pSelect->pPrior ){ return 0; /* SELECT may not be a compound query */ } if( pSelect->isDistinct ){ return 0; /* SELECT may not be DISTINCT */ } pEList = pSelect->pEList; assert( pEList!=0 ); if( pEList->nExpr!=1 ){ return 0; /* The result set must have exactly one column */ } assert( pEList->a[0].pExpr ); if( pEList->a[0].pExpr->op!=TK_ALL ){ return 0; /* The result set must be the special operator "*" */ } /* At this point we have established that the statement is of the ** correct syntactic form to participate in this optimization. Now ** we have to check the semantics. */ pItem = pSelect->pSrc->a; pSrc = sqlite3LocateTable(pParse, pItem->zName, pItem->zDatabase); if( pSrc==0 ){ return 0; /* FROM clause does not contain a real table */ } if( pSrc==pDest ){ return 0; /* tab1 and tab2 may not be the same table */ }#ifndef SQLITE_OMIT_VIRTUALTABLE if( pSrc->isVirtual ){ return 0; /* tab2 must not be a virtual table */ }#endif if( pSrc->pSelect ){ return 0; /* tab2 may not be a view */ } if( pDest->nCol!=pSrc->nCol ){ return 0; /* Number of columns must be the same in tab1 and tab2 */ } if( pDest->iPKey!=pSrc->iPKey ){ return 0; /* Both tables must have the same INTEGER PRIMARY KEY */ } for(i=0; i<pDest->nCol; i++){ if( pDest->aCol[i].affinity!=pSrc->aCol[i].affinity ){ return 0; /* Affinity must be the same on all columns */ } if( !xferCompatibleCollation(pDest->aCol[i].zColl, pSrc->aCol[i].zColl) ){ return 0; /* Collating sequence must be the same on all columns */ } if( pDest->aCol[i].notNull && !pSrc->aCol[i].notNull ){ return 0; /* tab2 must be NOT NULL if tab1 is */ } } for(pDestIdx=pDest->pIndex; pDestIdx; pDestIdx=pDestIdx->pNext){ if( pDestIdx->onError!=OE_None ){ destHasUniqueIdx = 1; } for(pSrcIdx=pSrc->pIndex; pSrcIdx; pSrcIdx=pSrcIdx->pNext){ if( xferCompatibleIndex(pDestIdx, pSrcIdx) ) break; } if( pSrcIdx==0 ){ return 0; /* pDestIdx has no corresponding index in pSrc */ } }#ifndef SQLITE_OMIT_CHECK if( pDest->pCheck && !sqlite3ExprCompare(pSrc->pCheck, pDest->pCheck) ){ return 0; /* Tables have different CHECK constraints. Ticket #2252 */ }#endif /* If we get this far, it means either: ** ** * We can always do the transfer if the table contains an ** an integer primary key ** ** * We can conditionally do the transfer if the destination ** table is empty. */#ifdef SQLITE_TEST sqlite3_xferopt_count++;#endif iDbSrc = sqlite3SchemaToIndex(pParse->db, pSrc->pSchema); v = sqlite3GetVdbe(pParse); sqlite3CodeVerifySchema(pParse, iDbSrc); iSrc = pParse->nTab++; iDest = pParse->nTab++; counterMem = autoIncBegin(pParse, iDbDest, pDest); sqlite3OpenTable(pParse, iDest, iDbDest, pDest, OP_OpenWrite); if( (pDest->iPKey<0 && pDest->pIndex!=0) || destHasUniqueIdx ){ /* If tables do not have an INTEGER PRIMARY KEY and there ** are indices to be copied and the destination is not empty, ** we have to disallow the transfer optimization because the ** the rowids might change which will mess up indexing. ** ** Or if the destination has a UNIQUE index and is not empty, ** we also disallow the transfer optimization because we cannot ** insure that all entries in the union of DEST and SRC will be ** unique. */ addr1 = sqlite3VdbeAddOp(v, OP_Rewind, iDest, 0); emptyDestTest = sqlite3VdbeAddOp(v, OP_Goto, 0, 0); sqlite3VdbeJumpHere(v, addr1); }else{ emptyDestTest = 0; } sqlite3OpenTable(pParse, iSrc, iDbSrc, pSrc, OP_OpenRead); emptySrcTest = sqlite3VdbeAddOp(v, OP_Rewind, iSrc, 0); if( pDest->iPKey>=0 ){ addr1 = sqlite3VdbeAddOp(v, OP_Rowid, iSrc, 0); sqlite3VdbeAddOp(v, OP_Dup, 0, 0); addr2 = sqlite3VdbeAddOp(v, OP_NotExists, iDest, 0); sqlite3VdbeOp3(v, OP_Halt, SQLITE_CONSTRAINT, onError, "PRIMARY KEY must be unique", P3_STATIC); sqlite3VdbeJumpHere(v, addr2); autoIncStep(pParse, counterMem); }else if( pDest->pIndex==0 ){ addr1 = sqlite3VdbeAddOp(v, OP_NewRowid, iDest, 0); }else{ addr1 = sqlite3VdbeAddOp(v, OP_Rowid, iSrc, 0); assert( pDest->autoInc==0 ); } sqlite3VdbeAddOp(v, OP_RowData, iSrc, 0); sqlite3VdbeOp3(v, OP_Insert, iDest, OPFLAG_NCHANGE|OPFLAG_LASTROWID|OPFLAG_APPEND, pDest->zName, 0); sqlite3VdbeAddOp(v, OP_Next, iSrc, addr1); autoIncEnd(pParse, iDbDest, pDest, counterMem); for(pDestIdx=pDest->pIndex; pDestIdx; pDestIdx=pDestIdx->pNext){ for(pSrcIdx=pSrc->pIndex; pSrcIdx; pSrcIdx=pSrcIdx->pNext){ if( xferCompatibleIndex(pDestIdx, pSrcIdx) ) break; } assert( pSrcIdx ); sqlite3VdbeAddOp(v, OP_Close, iSrc, 0); sqlite3VdbeAddOp(v, OP_Close, iDest, 0); sqlite3VdbeAddOp(v, OP_Integer, iDbSrc, 0); pKey = sqlite3IndexKeyinfo(pParse, pSrcIdx); VdbeComment((v, "# %s", pSrcIdx->zName)); sqlite3VdbeOp3(v, OP_OpenRead, iSrc, pSrcIdx->tnum, (char*)pKey, P3_KEYINFO_HANDOFF); sqlite3VdbeAddOp(v, OP_Integer, iDbDest, 0); pKey = sqlite3IndexKeyinfo(pParse, pDestIdx); VdbeComment((v, "# %s", pDestIdx->zName)); sqlite3VdbeOp3(v, OP_OpenWrite, iDest, pDestIdx->tnum, (char*)pKey, P3_KEYINFO_HANDOFF); addr1 = sqlite3VdbeAddOp(v, OP_Rewind, iSrc, 0); sqlite3VdbeAddOp(v, OP_RowKey, iSrc, 0); sqlite3VdbeAddOp(v, OP_IdxInsert, iDest, 1); sqlite3VdbeAddOp(v, OP_Next, iSrc, addr1+1); sqlite3VdbeJumpHere(v, addr1); } sqlite3VdbeJumpHere(v, emptySrcTest); sqlite3VdbeAddOp(v, OP_Close, iSrc, 0); sqlite3VdbeAddOp(v, OP_Close, iDest, 0); if( emptyDestTest ){ sqlite3VdbeAddOp(v, OP_Halt, SQLITE_OK, 0); sqlite3VdbeJumpHere(v, emptyDestTest); sqlite3VdbeAddOp(v, OP_Close, iDest, 0); return 0; }else{ return 1; }}#endif /* SQLITE_OMIT_XFER_OPT */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -