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

📄 delete.c

📁 最新的sqlite3.6.2源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*** 2001 September 15**** The author disclaims copyright to this source code.  In place of** a legal notice, here is a blessing:****    May you do good and not evil.**    May you find forgiveness for yourself and forgive others.**    May you share freely, never taking more than you give.***************************************************************************** This file contains C code routines that are called by the parser** in order to generate code for DELETE FROM statements.**** $Id: delete.c,v 1.174 2008/08/29 02:14:03 drh Exp $*/#include "sqliteInt.h"/*** Look up every table that is named in pSrc.  If any table is not found,** add an error message to pParse->zErrMsg and return NULL.  If all tables** are found, return a pointer to the last table.*/Table *sqlite3SrcListLookup(Parse *pParse, SrcList *pSrc){  Table *pTab = 0;  int i;  struct SrcList_item *pItem;  for(i=0, pItem=pSrc->a; i<pSrc->nSrc; i++, pItem++){    pTab = sqlite3LocateTable(pParse, 0, pItem->zName, pItem->zDatabase);    sqlite3DeleteTable(pItem->pTab);    pItem->pTab = pTab;    if( pTab ){      pTab->nRef++;    }  }  return pTab;}/*** Check to make sure the given table is writable.  If it is not** writable, generate an error message and return 1.  If it is** writable return 0;*/int sqlite3IsReadOnly(Parse *pParse, Table *pTab, int viewOk){  if( ((pTab->tabFlags & TF_Readonly)!=0        && (pParse->db->flags & SQLITE_WriteSchema)==0        && pParse->nested==0) #ifndef SQLITE_OMIT_VIRTUALTABLE      || (pTab->pMod && pTab->pMod->pModule->xUpdate==0)#endif  ){    sqlite3ErrorMsg(pParse, "table %s may not be modified", pTab->zName);    return 1;  }#ifndef SQLITE_OMIT_VIEW  if( !viewOk && pTab->pSelect ){    sqlite3ErrorMsg(pParse,"cannot modify %s because it is a view",pTab->zName);    return 1;  }#endif  return 0;}/*** Generate code that will open a table for reading.*/void sqlite3OpenTable(  Parse *p,       /* Generate code into this VDBE */  int iCur,       /* The cursor number of the table */  int iDb,        /* The database index in sqlite3.aDb[] */  Table *pTab,    /* The table to be opened */  int opcode      /* OP_OpenRead or OP_OpenWrite */){  Vdbe *v;  if( IsVirtual(pTab) ) return;  v = sqlite3GetVdbe(p);  assert( opcode==OP_OpenWrite || opcode==OP_OpenRead );  sqlite3TableLock(p, iDb, pTab->tnum, (opcode==OP_OpenWrite), pTab->zName);  sqlite3VdbeAddOp2(v, OP_SetNumColumns, 0, pTab->nCol);  sqlite3VdbeAddOp3(v, opcode, iCur, pTab->tnum, iDb);  VdbeComment((v, "%s", pTab->zName));}#if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER)/*** Evaluate a view and store its result in an ephemeral table.  The** pWhere argument is an optional WHERE clause that restricts the** set of rows in the view that are to be added to the ephemeral table.*/void sqlite3MaterializeView(  Parse *pParse,       /* Parsing context */  Table *pView,        /* View definition */  Expr *pWhere,        /* Optional WHERE clause to be added */  int iCur             /* Cursor number for ephemerial table */){  SelectDest dest;  Select *pDup;  sqlite3 *db = pParse->db;  pDup = sqlite3SelectDup(db, pView->pSelect);  if( pWhere ){    SrcList *pFrom;    Token viewName;        pWhere = sqlite3ExprDup(db, pWhere);    viewName.z = (u8*)pView->zName;    viewName.n = (unsigned int)strlen((const char*)viewName.z);    pFrom = sqlite3SrcListAppendFromTerm(pParse, 0, 0, 0, &viewName, pDup, 0,0);    pDup = sqlite3SelectNew(pParse, 0, pFrom, pWhere, 0, 0, 0, 0, 0, 0);  }  sqlite3SelectDestInit(&dest, SRT_EphemTab, iCur);  sqlite3Select(pParse, pDup, &dest);  sqlite3SelectDelete(db, pDup);}#endif /* !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER) *//*** Generate code for a DELETE FROM statement.****     DELETE FROM table_wxyz WHERE a<5 AND b NOT NULL;**                 \________/       \________________/**                  pTabList              pWhere*/void sqlite3DeleteFrom(  Parse *pParse,         /* The parser context */  SrcList *pTabList,     /* The table from which we should delete things */  Expr *pWhere           /* The WHERE clause.  May be null */){  Vdbe *v;               /* The virtual database engine */  Table *pTab;           /* The table from which records will be deleted */  const char *zDb;       /* Name of database holding pTab */  int end, addr = 0;     /* A couple addresses of generated code */  int i;                 /* Loop counter */  WhereInfo *pWInfo;     /* Information about the WHERE clause */  Index *pIdx;           /* For looping over indices of the table */  int iCur;              /* VDBE Cursor number for pTab */  sqlite3 *db;           /* Main database structure */  AuthContext sContext;  /* Authorization context */  int oldIdx = -1;       /* Cursor for the OLD table of AFTER triggers */  NameContext sNC;       /* Name context to resolve expressions in */  int iDb;               /* Database number */  int memCnt = 0;        /* Memory cell used for change counting */#ifndef SQLITE_OMIT_TRIGGER  int isView;                  /* True if attempting to delete from a view */  int triggers_exist = 0;      /* True if any triggers exist */#endif  int iBeginAfterTrigger;      /* Address of after trigger program */  int iEndAfterTrigger;        /* Exit of after trigger program */  int iBeginBeforeTrigger;     /* Address of before trigger program */  int iEndBeforeTrigger;       /* Exit of before trigger program */  u32 old_col_mask = 0;        /* Mask of OLD.* columns in use */  sContext.pParse = 0;  db = pParse->db;  if( pParse->nErr || db->mallocFailed ){    goto delete_from_cleanup;  }  assert( pTabList->nSrc==1 );  /* Locate the table which we want to delete.  This table has to be  ** put in an SrcList structure because some of the subroutines we  ** will be calling are designed to work with multiple tables and expect  ** an SrcList* parameter instead of just a Table* parameter.  */  pTab = sqlite3SrcListLookup(pParse, pTabList);  if( pTab==0 )  goto delete_from_cleanup;  /* Figure out if we have any triggers and if the table being  ** deleted from is a view  */#ifndef SQLITE_OMIT_TRIGGER  triggers_exist = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0);  isView = pTab->pSelect!=0;#else# define triggers_exist 0# define isView 0#endif#ifdef SQLITE_OMIT_VIEW# undef isView# define isView 0#endif  if( sqlite3IsReadOnly(pParse, pTab, triggers_exist) ){    goto delete_from_cleanup;  }  iDb = sqlite3SchemaToIndex(db, pTab->pSchema);  assert( iDb<db->nDb );  zDb = db->aDb[iDb].zName;  if( sqlite3AuthCheck(pParse, SQLITE_DELETE, pTab->zName, 0, zDb) ){    goto delete_from_cleanup;  }  /* If pTab is really a view, make sure it has been initialized.  */  if( sqlite3ViewGetColumnNames(pParse, pTab) ){    goto delete_from_cleanup;  }  /* Allocate a cursor used to store the old.* data for a trigger.  */  if( triggers_exist ){     oldIdx = pParse->nTab++;  }  /* Assign  cursor number to the table and all its indices.  */  assert( pTabList->nSrc==1 );  iCur = pTabList->a[0].iCursor = pParse->nTab++;  for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){    pParse->nTab++;  }  /* Start the view context  */  if( isView ){    sqlite3AuthContextPush(pParse, &sContext, pTab->zName);  }  /* Begin generating code.  */  v = sqlite3GetVdbe(pParse);  if( v==0 ){    goto delete_from_cleanup;  }  if( pParse->nested==0 ) sqlite3VdbeCountChanges(v);  sqlite3BeginWriteOperation(pParse, triggers_exist, iDb);  if( triggers_exist ){    int orconf = ((pParse->trigStack)?pParse->trigStack->orconf:OE_Default);    int iGoto = sqlite3VdbeAddOp0(v, OP_Goto);    addr = sqlite3VdbeMakeLabel(v);    iBeginBeforeTrigger = sqlite3VdbeCurrentAddr(v);    (void)sqlite3CodeRowTrigger(pParse, TK_DELETE, 0, TRIGGER_BEFORE, pTab,        -1, oldIdx, orconf, addr, &old_col_mask, 0);    iEndBeforeTrigger = sqlite3VdbeAddOp0(v, OP_Goto);    iBeginAfterTrigger = sqlite3VdbeCurrentAddr(v);    (void)sqlite3CodeRowTrigger(pParse, TK_DELETE, 0, TRIGGER_AFTER, pTab, -1,        oldIdx, orconf, addr, &old_col_mask, 0);    iEndAfterTrigger = sqlite3VdbeAddOp0(v, OP_Goto);    sqlite3VdbeJumpHere(v, iGoto);  }  /* If we are trying to delete from a view, realize that view into  ** a ephemeral table.  */  if( isView ){    sqlite3MaterializeView(pParse, pTab, pWhere, iCur);  }  /* Resolve the column names in the WHERE clause.  */  memset(&sNC, 0, sizeof(sNC));  sNC.pParse = pParse;  sNC.pSrcList = pTabList;  if( sqlite3ResolveExprNames(&sNC, pWhere) ){    goto delete_from_cleanup;  }  /* Initialize the counter of the number of rows deleted, if  ** we are counting rows.  */  if( db->flags & SQLITE_CountRows ){    memCnt = ++pParse->nMem;    sqlite3VdbeAddOp2(v, OP_Integer, 0, memCnt);  }  /* Special case: A DELETE without a WHERE clause deletes everything.  ** It is easier just to erase the whole table.  Note, however, that  ** this means that the row change count will be incorrect.

⌨️ 快捷键说明

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