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

📄 delete.c

📁 最新的sqlite3.6.2源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
  */  if( pWhere==0 && !triggers_exist && !IsVirtual(pTab) ){    if( db->flags & SQLITE_CountRows ){      /* If counting rows deleted, just count the total number of      ** entries in the table. */      int addr2;      if( !isView ){        sqlite3OpenTable(pParse, iCur, iDb, pTab, OP_OpenRead);      }      sqlite3VdbeAddOp2(v, OP_Rewind, iCur, sqlite3VdbeCurrentAddr(v)+2);      addr2 = sqlite3VdbeAddOp2(v, OP_AddImm, memCnt, 1);      sqlite3VdbeAddOp2(v, OP_Next, iCur, addr2);      sqlite3VdbeAddOp1(v, OP_Close, iCur);    }    if( !isView ){      sqlite3VdbeAddOp2(v, OP_Clear, pTab->tnum, iDb);      if( !pParse->nested ){        sqlite3VdbeChangeP4(v, -1, pTab->zName, P4_STATIC);      }      for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){        assert( pIdx->pSchema==pTab->pSchema );        sqlite3VdbeAddOp2(v, OP_Clear, pIdx->tnum, iDb);      }    }  }   /* The usual case: There is a WHERE clause so we have to scan through  ** the table and pick which records to delete.  */  else{    int iRowid = ++pParse->nMem;    /* Used for storing rowid values. */    /* Begin the database scan    */    pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0);    if( pWInfo==0 ) goto delete_from_cleanup;    /* Remember the rowid of every item to be deleted.    */    sqlite3VdbeAddOp2(v, IsVirtual(pTab) ? OP_VRowid : OP_Rowid, iCur, iRowid);    sqlite3VdbeAddOp1(v, OP_FifoWrite, iRowid);    if( db->flags & SQLITE_CountRows ){      sqlite3VdbeAddOp2(v, OP_AddImm, memCnt, 1);    }    /* End the database scan loop.    */    sqlite3WhereEnd(pWInfo);    /* Open the pseudo-table used to store OLD if there are triggers.    */    if( triggers_exist ){      sqlite3VdbeAddOp2(v, OP_SetNumColumns, 0, pTab->nCol);      sqlite3VdbeAddOp1(v, OP_OpenPseudo, oldIdx);    }    /* Delete every item whose key was written to the list during the    ** database scan.  We have to delete items after the scan is complete    ** because deleting an item can change the scan order.    */    end = sqlite3VdbeMakeLabel(v);    if( !isView ){      /* Open cursors for the table we are deleting from and       ** all its indices.      */      sqlite3OpenTableAndIndices(pParse, pTab, iCur, OP_OpenWrite);    }    /* This is the beginning of the delete loop. If a trigger encounters    ** an IGNORE constraint, it jumps back to here.    */    if( triggers_exist ){      sqlite3VdbeResolveLabel(v, addr);    }    addr = sqlite3VdbeAddOp2(v, OP_FifoRead, iRowid, end);    if( triggers_exist ){      int iData = ++pParse->nMem;   /* For storing row data of OLD table */      /* If the record is no longer present in the table, jump to the      ** next iteration of the loop through the contents of the fifo.      */      sqlite3VdbeAddOp3(v, OP_NotExists, iCur, addr, iRowid);      /* Populate the OLD.* pseudo-table */      if( old_col_mask ){        sqlite3VdbeAddOp2(v, OP_RowData, iCur, iData);      }else{        sqlite3VdbeAddOp2(v, OP_Null, 0, iData);      }      sqlite3VdbeAddOp3(v, OP_Insert, oldIdx, iData, iRowid);      /* Jump back and run the BEFORE triggers */      sqlite3VdbeAddOp2(v, OP_Goto, 0, iBeginBeforeTrigger);      sqlite3VdbeJumpHere(v, iEndBeforeTrigger);    }    if( !isView ){      /* Delete the row */#ifndef SQLITE_OMIT_VIRTUALTABLE      if( IsVirtual(pTab) ){        const char *pVtab = (const char *)pTab->pVtab;        sqlite3VtabMakeWritable(pParse, pTab);        sqlite3VdbeAddOp4(v, OP_VUpdate, 0, 1, iRowid, pVtab, P4_VTAB);      }else#endif      {        sqlite3GenerateRowDelete(pParse, pTab, iCur, iRowid, pParse->nested==0);      }    }    /* If there are row triggers, close all cursors then invoke    ** the AFTER triggers    */    if( triggers_exist ){      /* Jump back and run the AFTER triggers */      sqlite3VdbeAddOp2(v, OP_Goto, 0, iBeginAfterTrigger);      sqlite3VdbeJumpHere(v, iEndAfterTrigger);    }    /* End of the delete loop */    sqlite3VdbeAddOp2(v, OP_Goto, 0, addr);    sqlite3VdbeResolveLabel(v, end);    /* Close the cursors after the loop if there are no row triggers */    if( !isView  && !IsVirtual(pTab) ){      for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){        sqlite3VdbeAddOp2(v, OP_Close, iCur + i, pIdx->tnum);      }      sqlite3VdbeAddOp1(v, OP_Close, iCur);    }  }  /*  ** Return the number of rows that were deleted. 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, memCnt, 1);    sqlite3VdbeSetNumCols(v, 1);    sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows deleted", P4_STATIC);  }delete_from_cleanup:  sqlite3AuthContextPop(&sContext);  sqlite3SrcListDelete(db, pTabList);  sqlite3ExprDelete(db, pWhere);  return;}/*** This routine generates VDBE code that causes a single row of a** single table to be deleted.**** The VDBE must be in a particular state when this routine is called.** These are the requirements:****   1.  A read/write cursor pointing to pTab, the table containing the row**       to be deleted, must be opened as cursor number "base".****   2.  Read/write cursors for all indices of pTab must be open as**       cursor number base+i for the i-th index.****   3.  The record number of the row to be deleted must be stored in**       memory cell iRowid.**** This routine pops the top of the stack to remove the record number** and then generates code to remove both the table record and all index** entries that point to that record.*/void sqlite3GenerateRowDelete(  Parse *pParse,     /* Parsing context */  Table *pTab,       /* Table containing the row to be deleted */  int iCur,          /* Cursor number for the table */  int iRowid,        /* Memory cell that contains the rowid to delete */  int count          /* Increment the row change counter */){  int addr;  Vdbe *v;  v = pParse->pVdbe;  addr = sqlite3VdbeAddOp3(v, OP_NotExists, iCur, 0, iRowid);  sqlite3GenerateRowIndexDelete(pParse, pTab, iCur, 0);  sqlite3VdbeAddOp2(v, OP_Delete, iCur, (count?OPFLAG_NCHANGE:0));  if( count ){    sqlite3VdbeChangeP4(v, -1, pTab->zName, P4_STATIC);  }  sqlite3VdbeJumpHere(v, addr);}/*** This routine generates VDBE code that causes the deletion of all** index entries associated with a single row of a single table.**** The VDBE must be in a particular state when this routine is called.** These are the requirements:****   1.  A read/write cursor pointing to pTab, the table containing the row**       to be deleted, must be opened as cursor number "iCur".****   2.  Read/write cursors for all indices of pTab must be open as**       cursor number iCur+i for the i-th index.****   3.  The "iCur" cursor must be pointing to the row that is to be**       deleted.*/void sqlite3GenerateRowIndexDelete(  Parse *pParse,     /* Parsing and code generating context */  Table *pTab,       /* Table containing the row to be deleted */  int iCur,          /* Cursor number for the table */  int *aRegIdx       /* Only delete if aRegIdx!=0 && aRegIdx[i]>0 */){  int i;  Index *pIdx;  int r1;  for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){    if( aRegIdx!=0 && aRegIdx[i-1]==0 ) continue;    r1 = sqlite3GenerateIndexKey(pParse, pIdx, iCur, 0, 0);    sqlite3VdbeAddOp3(pParse->pVdbe, OP_IdxDelete, iCur+i, r1,pIdx->nColumn+1);  }}/*** Generate code that will assemble an index key and put it in register** regOut.  The key with be for index pIdx which is an index on pTab.** iCur is the index of a cursor open on the pTab table and pointing to** the entry that needs indexing.**** Return a register number which is the first in a block of** registers that holds the elements of the index key.  The** block of registers has already been deallocated by the time** this routine returns.*/int sqlite3GenerateIndexKey(  Parse *pParse,     /* Parsing context */  Index *pIdx,       /* The index for which to generate a key */  int iCur,          /* Cursor number for the pIdx->pTable table */  int regOut,        /* Write the new index key to this register */  int doMakeRec      /* Run the OP_MakeRecord instruction if true */){  Vdbe *v = pParse->pVdbe;  int j;  Table *pTab = pIdx->pTable;  int regBase;  int nCol;  nCol = pIdx->nColumn;  regBase = sqlite3GetTempRange(pParse, nCol+1);  sqlite3VdbeAddOp2(v, OP_Rowid, iCur, regBase+nCol);  for(j=0; j<nCol; j++){    int idx = pIdx->aiColumn[j];    if( idx==pTab->iPKey ){      sqlite3VdbeAddOp2(v, OP_SCopy, regBase+nCol, regBase+j);    }else{      sqlite3VdbeAddOp3(v, OP_Column, iCur, idx, regBase+j);      sqlite3ColumnDefault(v, pTab, idx);    }  }  if( doMakeRec ){    sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol+1, regOut);    sqlite3IndexAffinityStr(v, pIdx);    sqlite3ExprCacheAffinityChange(pParse, regBase, nCol+1);  }  sqlite3ReleaseTempRange(pParse, regBase, nCol+1);  return regBase;}/* 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 + -