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

📄 insert.c

📁 sqlite的最新源码 This ZIP archive contains preprocessed C code for the SQLite library as individual sour
💻 C
📖 第 1 页 / 共 5 页
字号:
  if( IsVirtual(pTab) ) return 0;  iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);  v = sqlite3GetVdbe(pParse);  assert( v!=0 );  sqlite3OpenTable(pParse, baseCur, iDb, pTab, op);  for(i=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){    KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIdx);    assert( pIdx->pSchema==pTab->pSchema );    sqlite3VdbeAddOp4(v, op, i+baseCur, pIdx->tnum, iDb,                      (char*)pKey, P4_KEYINFO_HANDOFF);    VdbeComment((v, "%s", pIdx->zName));  }  if( pParse->nTab<=baseCur+i ){    pParse->nTab = baseCur+i;  }  return i-1;}#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 collating sequences */    }  }  /* 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 regAutoinc;                  /* Memory register used by AUTOINC */  int destHasUniqueIdx = 0;        /* True if pDest has a UNIQUE index */  int regData, regRowid;           /* Registers holding data and rowid */  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->tabFlags & TF_Virtual ){    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->selFlags & SF_Distinct ){    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, 0, 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->tabFlags & TF_Virtual ){    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++;  regAutoinc = 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 = sqlite3VdbeAddOp2(v, OP_Rewind, iDest, 0);    emptyDestTest = sqlite3VdbeAddOp2(v, OP_Goto, 0, 0);    sqlite3VdbeJumpHere(v, addr1);  }else{    emptyDestTest = 0;  }  sqlite3OpenTable(pParse, iSrc, iDbSrc, pSrc, OP_OpenRead);  emptySrcTest = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0);  regData = sqlite3GetTempReg(pParse);  regRowid = sqlite3GetTempReg(pParse);  if( pDest->iPKey>=0 ){    addr1 = sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, regRowid);    addr2 = sqlite3VdbeAddOp3(v, OP_NotExists, iDest, 0, regRowid);    sqlite3VdbeAddOp4(v, OP_Halt, SQLITE_CONSTRAINT, onError, 0,                      "PRIMARY KEY must be unique", P4_STATIC);    sqlite3VdbeJumpHere(v, addr2);    autoIncStep(pParse, regAutoinc, regRowid);  }else if( pDest->pIndex==0 ){    addr1 = sqlite3VdbeAddOp2(v, OP_NewRowid, iDest, regRowid);  }else{    addr1 = sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, regRowid);    assert( (pDest->tabFlags & TF_Autoincrement)==0 );  }  sqlite3VdbeAddOp2(v, OP_RowData, iSrc, regData);  sqlite3VdbeAddOp3(v, OP_Insert, iDest, regData, regRowid);  sqlite3VdbeChangeP5(v, OPFLAG_NCHANGE|OPFLAG_LASTROWID|OPFLAG_APPEND);  sqlite3VdbeChangeP4(v, -1, pDest->zName, 0);  sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1);  autoIncEnd(pParse, iDbDest, pDest, regAutoinc);  for(pDestIdx=pDest->pIndex; pDestIdx; pDestIdx=pDestIdx->pNext){    for(pSrcIdx=pSrc->pIndex; pSrcIdx; pSrcIdx=pSrcIdx->pNext){      if( xferCompatibleIndex(pDestIdx, pSrcIdx) ) break;    }    assert( pSrcIdx );    sqlite3VdbeAddOp2(v, OP_Close, iSrc, 0);    sqlite3VdbeAddOp2(v, OP_Close, iDest, 0);    pKey = sqlite3IndexKeyinfo(pParse, pSrcIdx);    sqlite3VdbeAddOp4(v, OP_OpenRead, iSrc, pSrcIdx->tnum, iDbSrc,                      (char*)pKey, P4_KEYINFO_HANDOFF);    VdbeComment((v, "%s", pSrcIdx->zName));    pKey = sqlite3IndexKeyinfo(pParse, pDestIdx);    sqlite3VdbeAddOp4(v, OP_OpenWrite, iDest, pDestIdx->tnum, iDbDest,                      (char*)pKey, P4_KEYINFO_HANDOFF);    VdbeComment((v, "%s", pDestIdx->zName));    addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0);    sqlite3VdbeAddOp2(v, OP_RowKey, iSrc, regData);    sqlite3VdbeAddOp3(v, OP_IdxInsert, iDest, regData, 1);    sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1+1);    sqlite3VdbeJumpHere(v, addr1);  }  sqlite3VdbeJumpHere(v, emptySrcTest);  sqlite3ReleaseTempReg(pParse, regRowid);  sqlite3ReleaseTempReg(pParse, regData);  sqlite3VdbeAddOp2(v, OP_Close, iSrc, 0);  sqlite3VdbeAddOp2(v, OP_Close, iDest, 0);  if( emptyDestTest ){    sqlite3VdbeAddOp2(v, OP_Halt, SQLITE_OK, 0);    sqlite3VdbeJumpHere(v, emptyDestTest);    sqlite3VdbeAddOp2(v, OP_Close, iDest, 0);    return 0;  }else{    return 1;  }}#endif /* SQLITE_OMIT_XFER_OPT *//* Make sure "isView" gets undefined in case this file becomes part of** the amalgamation - so that subsequent files do not see isView as a** macro. */#undef isView

⌨️ 快捷键说明

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