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

📄 insert.c

📁 sqlite-3.4.1,嵌入式数据库.是一个功能强大的开源数据库,给学习和研发以及小型公司的发展带来了全所未有的好处.
💻 C
📖 第 1 页 / 共 4 页
字号:
  if( triggers_exist ){    /* Close all tables opened */    if( !isView ){      sqlite3VdbeAddOp(v, OP_Close, base, 0);      for(idx=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, idx++){        sqlite3VdbeAddOp(v, OP_Close, idx+base, 0);      }    }    /* Code AFTER triggers */    if( sqlite3CodeRowTrigger(pParse, TK_INSERT, 0, TRIGGER_AFTER, pTab,          newIdx, -1, onError, endOfLoop) ){      goto insert_cleanup;    }  }  /* The bottom of the loop, if the data source is a SELECT statement  */  sqlite3VdbeResolveLabel(v, endOfLoop);  if( useTempTable ){    sqlite3VdbeAddOp(v, OP_Next, srcTab, iCont);    sqlite3VdbeResolveLabel(v, iBreak);    sqlite3VdbeAddOp(v, OP_Close, srcTab, 0);  }else if( pSelect ){    sqlite3VdbeAddOp(v, OP_Pop, nColumn, 0);    sqlite3VdbeAddOp(v, OP_Return, 0, 0);    sqlite3VdbeResolveLabel(v, iCleanup);  }  if( !triggers_exist && !IsVirtual(pTab) ){    /* Close all tables opened */    sqlite3VdbeAddOp(v, OP_Close, base, 0);    for(idx=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, idx++){      sqlite3VdbeAddOp(v, OP_Close, idx+base, 0);    }  }  /* Update the sqlite_sequence table by storing the content of the  ** counter value in memory counterMem back into the sqlite_sequence  ** table.  */  autoIncEnd(pParse, iDb, pTab, counterMem);  /*  ** Return the number of rows inserted. 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 ){    sqlite3VdbeAddOp(v, OP_MemLoad, iCntMem, 0);    sqlite3VdbeAddOp(v, OP_Callback, 1, 0);    sqlite3VdbeSetNumCols(v, 1);    sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows inserted", P3_STATIC);  }insert_cleanup:  sqlite3SrcListDelete(pTabList);  sqlite3ExprListDelete(pList);  sqlite3SelectDelete(pSelect);  sqlite3IdListDelete(pColumn);}/*** Generate code to do a constraint check prior to an INSERT or an UPDATE.**** When this routine is called, the stack contains (from bottom to top)** the following values:****    1.  The rowid of the row to be updated before the update.  This**        value is omitted unless we are doing an UPDATE that involves a**        change to the record number.****    2.  The rowid of the row after the update.****    3.  The data in the first column of the entry after the update.****    i.  Data from middle columns...****    N.  The data in the last column of the entry after the update.**** The old rowid shown as entry (1) above is omitted unless both isUpdate** and rowidChng are 1.  isUpdate is true for UPDATEs and false for** INSERTs and rowidChng is true if the record number is being changed.**** The code generated by this routine pushes additional entries onto** the stack which are the keys for new index entries for the new record.** The order of index keys is the same as the order of the indices on** the pTable->pIndex list.  A key is only created for index i if ** aIdxUsed!=0 and aIdxUsed[i]!=0.**** This routine also generates code to check constraints.  NOT NULL,** CHECK, and UNIQUE constraints are all checked.  If a constraint fails,** then the appropriate action is performed.  There are five possible** actions: ROLLBACK, ABORT, FAIL, REPLACE, and IGNORE.****  Constraint type  Action       What Happens**  ---------------  ----------   ----------------------------------------**  any              ROLLBACK     The current transaction is rolled back and**                                sqlite3_exec() returns immediately with a**                                return code of SQLITE_CONSTRAINT.****  any              ABORT        Back out changes from the current command**                                only (do not do a complete rollback) then**                                cause sqlite3_exec() to return immediately**                                with SQLITE_CONSTRAINT.****  any              FAIL         Sqlite_exec() returns immediately with a**                                return code of SQLITE_CONSTRAINT.  The**                                transaction is not rolled back and any**                                prior changes are retained.****  any              IGNORE       The record number and data is popped from**                                the stack and there is an immediate jump**                                to label ignoreDest.****  NOT NULL         REPLACE      The NULL value is replace by the default**                                value for that column.  If the default value**                                is NULL, the action is the same as ABORT.****  UNIQUE           REPLACE      The other row that conflicts with the row**                                being inserted is removed.****  CHECK            REPLACE      Illegal.  The results in an exception.**** Which action to take is determined by the overrideError parameter.** Or if overrideError==OE_Default, then the pParse->onError parameter** is used.  Or if pParse->onError==OE_Default then the onError value** for the constraint is used.**** The calling routine must open a read/write cursor for pTab with** cursor number "base".  All indices of pTab must also have open** read/write cursors with cursor number base+i for the i-th cursor.** Except, if there is no possibility of a REPLACE action then** cursors do not need to be open for indices where aIdxUsed[i]==0.**** If the isUpdate flag is true, it means that the "base" cursor is** initially pointing to an entry that is being updated.  The isUpdate** flag causes extra code to be generated so that the "base" cursor** is still pointing at the same entry after the routine returns.** Without the isUpdate flag, the "base" cursor might be moved.*/void sqlite3GenerateConstraintChecks(  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 overrideError,  /* Override onError to this if not OE_Default */  int ignoreDest      /* Jump to this label on an OE_Ignore resolution */){  int i;  Vdbe *v;  int nCol;  int onError;  int addr;  int extra;  int iCur;  Index *pIdx;  int seenReplace = 0;  int jumpInst1=0, jumpInst2;  int hasTwoRowids = (isUpdate && rowidChng);  v = sqlite3GetVdbe(pParse);  assert( v!=0 );  assert( pTab->pSelect==0 );  /* This table is not a VIEW */  nCol = pTab->nCol;  /* Test all NOT NULL constraints.  */  for(i=0; i<nCol; i++){    if( i==pTab->iPKey ){      continue;    }    onError = pTab->aCol[i].notNull;    if( onError==OE_None ) continue;    if( overrideError!=OE_Default ){      onError = overrideError;    }else if( onError==OE_Default ){      onError = OE_Abort;    }    if( onError==OE_Replace && pTab->aCol[i].pDflt==0 ){      onError = OE_Abort;    }    sqlite3VdbeAddOp(v, OP_Dup, nCol-1-i, 1);    addr = sqlite3VdbeAddOp(v, OP_NotNull, 1, 0);    assert( onError==OE_Rollback || onError==OE_Abort || onError==OE_Fail        || onError==OE_Ignore || onError==OE_Replace );    switch( onError ){      case OE_Rollback:      case OE_Abort:      case OE_Fail: {        char *zMsg = 0;        sqlite3VdbeAddOp(v, OP_Halt, SQLITE_CONSTRAINT, onError);        sqlite3SetString(&zMsg, pTab->zName, ".", pTab->aCol[i].zName,                        " may not be NULL", (char*)0);        sqlite3VdbeChangeP3(v, -1, zMsg, P3_DYNAMIC);        break;      }      case OE_Ignore: {        sqlite3VdbeAddOp(v, OP_Pop, nCol+1+hasTwoRowids, 0);        sqlite3VdbeAddOp(v, OP_Goto, 0, ignoreDest);        break;      }      case OE_Replace: {        sqlite3ExprCode(pParse, pTab->aCol[i].pDflt);        sqlite3VdbeAddOp(v, OP_Push, nCol-i, 0);        break;      }    }    sqlite3VdbeJumpHere(v, addr);  }  /* Test all CHECK constraints  */#ifndef SQLITE_OMIT_CHECK  if( pTab->pCheck && (pParse->db->flags & SQLITE_IgnoreChecks)==0 ){    int allOk = sqlite3VdbeMakeLabel(v);    assert( pParse->ckOffset==0 );    pParse->ckOffset = nCol;    sqlite3ExprIfTrue(pParse, pTab->pCheck, allOk, 1);    assert( pParse->ckOffset==nCol );    pParse->ckOffset = 0;    onError = overrideError!=OE_Default ? overrideError : OE_Abort;    if( onError==OE_Ignore || onError==OE_Replace ){      sqlite3VdbeAddOp(v, OP_Pop, nCol+1+hasTwoRowids, 0);      sqlite3VdbeAddOp(v, OP_Goto, 0, ignoreDest);    }else{      sqlite3VdbeAddOp(v, OP_Halt, SQLITE_CONSTRAINT, onError);    }    sqlite3VdbeResolveLabel(v, allOk);  }#endif /* !defined(SQLITE_OMIT_CHECK) */  /* If we have an INTEGER PRIMARY KEY, make sure the primary key  ** of the new record does not previously exist.  Except, if this  ** is an UPDATE and the primary key is not changing, that is OK.  */  if( rowidChng ){    onError = pTab->keyConf;    if( overrideError!=OE_Default ){      onError = overrideError;    }else if( onError==OE_Default ){      onError = OE_Abort;    }        if( isUpdate ){      sqlite3VdbeAddOp(v, OP_Dup, nCol+1, 1);      sqlite3VdbeAddOp(v, OP_Dup, nCol+1, 1);      jumpInst1 = sqlite3VdbeAddOp(v, OP_Eq, 0, 0);    }    sqlite3VdbeAddOp(v, OP_Dup, nCol, 1);    jumpInst2 = sqlite3VdbeAddOp(v, OP_NotExists, base, 0);    switch( onError ){      default: {        onError = OE_Abort;        /* Fall thru into the next case */      }      case OE_Rollback:      case OE_Abort:      case OE_Fail: {        sqlite3VdbeOp3(v, OP_Halt, SQLITE_CONSTRAINT, onError,                         "PRIMARY KEY must be unique", P3_STATIC);        break;      }      case OE_Replace: {        sqlite3GenerateRowIndexDelete(v, pTab, base, 0);        if( isUpdate ){          sqlite3VdbeAddOp(v, OP_Dup, nCol+hasTwoRowids, 1);          sqlite3VdbeAddOp(v, OP_MoveGe, base, 0);        }        seenReplace = 1;        break;      }      case OE_Ignore: {        assert( seenReplace==0 );        sqlite3VdbeAddOp(v, OP_Pop, nCol+1+hasTwoRowids, 0);        sqlite3VdbeAddOp(v, OP_Goto, 0, ignoreDest);        break;      }    }    sqlite3VdbeJumpHere(v, jumpInst2);    if( isUpdate ){      sqlite3VdbeJumpHere(v, jumpInst1);      sqlite3VdbeAddOp(v, OP_Dup, nCol+1, 1);      sqlite3VdbeAddOp(v, OP_MoveGe, base, 0);    }  }  /* Test all UNIQUE constraints by creating entries for each UNIQUE  ** index and making sure that duplicate entries do not already exist.  ** Add the new records to the indices as we go.  */  extra = -1;  for(iCur=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, iCur++){    if( aIdxUsed && aIdxUsed[iCur]==0 ) continue;  /* Skip unused indices */    extra++;    /* Create a key for accessing the index entry */    sqlite3VdbeAddOp(v, OP_Dup, nCol+extra, 1);    for(i=0; i<pIdx->nColumn; i++){      int idx = pIdx->aiColumn[i];      if( idx==pTab->iPKey ){        sqlite3VdbeAddOp(v, OP_Dup, i+extra+nCol+1, 1);      }else{        sqlite3VdbeAddOp(v, OP_Dup, i+extra+nCol-idx, 1);      }    }    jumpInst1 = sqlite3VdbeAddOp(v, OP_MakeIdxRec, pIdx->nColumn, 0);    sqlite3IndexAffinityStr(v, pIdx);    /* Find out what action to take in case there is an indexing conflict */    onError = pIdx->onError;    if( onError==OE_None ) continue;  /* pIdx is not a UNIQUE index */    if( overrideError!=OE_Default ){      onError = overrideError;    }else if( onError==OE_Default ){      onError = OE_Abort;    }    if( seenReplace ){      if( onError==OE_Ignore ) onError = OE_Replace;      else if( onError==OE_Fail ) onError = OE_Abort;    }        /* Check to see if the new index entry will be unique */    sqlite3VdbeAddOp(v, OP_Dup, extra+nCol+1+hasTwoRowids, 1);    jumpInst2 = sqlite3VdbeAddOp(v, OP_IsUnique, base+iCur+1, 0);    /* Generate code that executes if the new index entry is not unique */    assert( onError==OE_Rollback || onError==OE_Abort || onError==OE_Fail        || onError==OE_Ignore || onError==OE_Replace );    switch( onError ){      case OE_Rollback:      case OE_Abort:      case OE_Fail: {        int j, n1, n2;        char zErrMsg[200];        sqlite3_snprintf(sizeof(zErrMsg), zErrMsg,                         pIdx->nColumn>1 ? "columns " : "column ");        n1 = strlen(zErrMsg);        for(j=0; j<pIdx->nColumn && n1<sizeof(zErrMsg)-30; j++){          char *zCol = pTab->aCol[pIdx->aiColumn[j]].zName;          n2 = strlen(zCol);          if( j>0 ){            sqlite3_snprintf(sizeof(zErrMsg)-n1, &zErrMsg[n1], ", ");            n1 += 2;          }          if( n1+n2>sizeof(zErrMsg)-30 ){            sqlite3_snprintf(sizeof(zErrMsg)-n1, &zErrMsg[n1], "...");            n1 += 3;            break;          }else{            sqlite3_snprintf(sizeof(zErrMsg)-n1, &zErrMsg[n1], "%s", zCol);            n1 += n2;          }        }        sqlite3_snprintf(sizeof(zErrMsg)-n1, &zErrMsg[n1],             pIdx->nColumn>1 ? " are not unique" : " is not unique");        sqlite3VdbeOp3(v, OP_Halt, SQLITE_CONSTRAINT, onError, zErrMsg, 0);        break;      }      case OE_Ignore: {        assert( seenReplace==0 );        sqlite3VdbeAddOp(v, OP_Pop, nCol+extra+3+hasTwoRowids, 0);        sqlite3VdbeAddOp(v, OP_Goto, 0, ignoreDest);        break;      }      case OE_Replace: {        sqlite3GenerateRowDelete(pParse->db, v, pTab, base, 0);        if( isUpdate ){          sqlite3VdbeAddOp(v, OP_Dup, nCol+extra+1+hasTwoRowids, 1);          sqlite3VdbeAddOp(v, OP_MoveGe, base, 0);        }        seenReplace = 1;        break;      }    }#if NULL_DISTINCT_FOR_UNIQUE    sqlite3VdbeJumpHere(v, jumpInst1);#endif    sqlite3VdbeJumpHere(v, jumpInst2);  }}/*** This routine generates code to finish the INSERT or UPDATE operation** that was started by a prior call to sqlite3GenerateConstraintChecks.** The stack must contain keys for all active indices followed by data** and the rowid for the new entry.  This routine creates the new** entries in all indices and in the main table.**** The arguments to this routine should be the same as the first six** 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 */

⌨️ 快捷键说明

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