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

📄 delete.c

📁 sqlite的最新源码 This ZIP archive contains preprocessed C code for the SQLite library as individual sour
💻 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.187 2008/11/19 09:05:27 danielk1977 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){  struct SrcList_item *pItem = pSrc->a;  Table *pTab;  assert( pItem && pSrc->nSrc==1 );  pTab = sqlite3LocateTable(pParse, 0, pItem->zName, pItem->zDatabase);  sqlite3DeleteTable(pItem->pTab);  pItem->pTab = pTab;  if( pTab ){    pTab->nRef++;  }  if( sqlite3IndexedByLookup(pParse, pItem) ){    pTab = 0;  }  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) */#if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY)/*** Generate an expression tree to implement the WHERE, ORDER BY,** and LIMIT/OFFSET portion of DELETE and UPDATE statements.****     DELETE FROM table_wxyz WHERE a<5 ORDER BY a LIMIT 1;**                            \__________________________/**                               pLimitWhere (pInClause)*/Expr *sqlite3LimitWhere(  Parse *pParse,               /* The parser context */  SrcList *pSrc,               /* the FROM clause -- which tables to scan */  Expr *pWhere,                /* The WHERE clause.  May be null */  ExprList *pOrderBy,          /* The ORDER BY clause.  May be null */  Expr *pLimit,                /* The LIMIT clause.  May be null */  Expr *pOffset,               /* The OFFSET clause.  May be null */  char *zStmtType              /* Either DELETE or UPDATE.  For error messages. */){  Expr *pWhereRowid = NULL;    /* WHERE rowid .. */  Expr *pInClause = NULL;      /* WHERE rowid IN ( select ) */  Expr *pSelectRowid = NULL;   /* SELECT rowid ... */  ExprList *pEList = NULL;     /* Expression list contaning only pSelectRowid */  SrcList *pSelectSrc = NULL;  /* SELECT rowid FROM x ... (dup of pSrc) */  Select *pSelect = NULL;      /* Complete SELECT tree */  /* Check that there isn't an ORDER BY without a LIMIT clause.  */  if( pOrderBy && (pLimit == 0) ) {    sqlite3ErrorMsg(pParse, "ORDER BY without LIMIT on %s", zStmtType);    pParse->parseError = 1;    goto limit_where_cleanup_2;  }  /* We only need to generate a select expression if there  ** is a limit/offset term to enforce.  */  if( pLimit == 0 ) {    /* if pLimit is null, pOffset will always be null as well. */    assert( pOffset == 0 );    return pWhere;  }  /* Generate a select expression tree to enforce the limit/offset   ** term for the DELETE or UPDATE statement.  For example:  **   DELETE FROM table_a WHERE col1=1 ORDER BY col2 LIMIT 1 OFFSET 1  ** becomes:  **   DELETE FROM table_a WHERE rowid IN (   **     SELECT rowid FROM table_a WHERE col1=1 ORDER BY col2 LIMIT 1 OFFSET 1  **   );  */  pSelectRowid = sqlite3Expr(pParse->db, TK_ROW, 0, 0, 0);  if( pSelectRowid == 0 ) goto limit_where_cleanup_2;  pEList = sqlite3ExprListAppend(pParse, 0, pSelectRowid, 0);  if( pEList == 0 ) goto limit_where_cleanup_2;  /* duplicate the FROM clause as it is needed by both the DELETE/UPDATE tree  ** and the SELECT subtree. */  pSelectSrc = sqlite3SrcListDup(pParse->db, pSrc);  if( pSelectSrc == 0 ) {    sqlite3ExprListDelete(pParse->db, pEList);    goto limit_where_cleanup_2;  }  /* generate the SELECT expression tree. */  pSelect = sqlite3SelectNew(pParse,pEList,pSelectSrc,pWhere,0,0,pOrderBy,0,pLimit,pOffset);  if( pSelect == 0 ) return 0;  /* now generate the new WHERE rowid IN clause for the DELETE/UDPATE */  pWhereRowid = sqlite3Expr(pParse->db, TK_ROW, 0, 0, 0);  if( pWhereRowid == 0 ) goto limit_where_cleanup_1;  pInClause = sqlite3PExpr(pParse, TK_IN, pWhereRowid, 0, 0);  if( pInClause == 0 ) goto limit_where_cleanup_1;  pInClause->pSelect = pSelect;  sqlite3ExprSetHeight(pParse, pInClause);  return pInClause;  /* something went wrong. clean up anything allocated. */limit_where_cleanup_1:  sqlite3SelectDelete(pParse->db, pSelect);  return 0;limit_where_cleanup_2:  sqlite3ExprDelete(pParse->db, pWhere);  sqlite3ExprListDelete(pParse->db, pOrderBy);  sqlite3ExprDelete(pParse->db, pLimit);  sqlite3ExprDelete(pParse->db, pOffset);  return 0;}#endif /* defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY) *//*** 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 = -1;       /* Memory cell used for change counting */  int rcauth;            /* Value returned by authorization callback */#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(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;  rcauth = sqlite3AuthCheck(pParse, SQLITE_DELETE, pTab->zName, 0, zDb);  assert( rcauth==SQLITE_OK || rcauth==SQLITE_DENY || rcauth==SQLITE_IGNORE );  if( rcauth==SQLITE_DENY ){    goto delete_from_cleanup;  }  assert(!isView || triggers_exist);  /* 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.

⌨️ 快捷键说明

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