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

📄 insert.c

📁 SQLite is a software library that implements a self-contained, serverless, zero-configuration, trans
💻 C
📖 第 1 页 / 共 4 页
字号:
      }else if( pSelect ){        sqlite3VdbeAddOp2(v, OP_SCopy, regFromSelect+j, iRegStore);      }else{        sqlite3ExprCode(pParse, pList->a[j].pExpr, iRegStore);      }    }    /* Generate code to check constraints and generate index keys and    ** do the insertion.    */#ifndef SQLITE_OMIT_VIRTUALTABLE    if( IsVirtual(pTab) ){      pParse->pVirtualLock = pTab;      sqlite3VdbeAddOp4(v, OP_VUpdate, 1, pTab->nCol+2, regIns,                     (const char*)pTab->pVtab, P4_VTAB);    }else#endif    {      sqlite3GenerateConstraintChecks(          pParse,          pTab,          baseCur,          regIns,          aRegIdx,          keyColumn>=0,          0,          onError,          endOfLoop      );      sqlite3CompleteInsertion(          pParse,          pTab,          baseCur,          regIns,          aRegIdx,          0,          0,          (triggers_exist & TRIGGER_AFTER)!=0 ? newIdx : -1,          appendFlag       );    }  }  /* Update the count of rows that are inserted  */  if( (db->flags & SQLITE_CountRows)!=0 ){    sqlite3VdbeAddOp2(v, OP_AddImm, regRowCount, 1);  }  if( triggers_exist ){    /* Code AFTER triggers */    if( sqlite3CodeRowTrigger(pParse, TK_INSERT, 0, TRIGGER_AFTER, pTab,          newIdx, -1, onError, endOfLoop, 0, 0) ){      goto insert_cleanup;    }  }  /* The bottom of the loop, if the data source is a SELECT statement  */  sqlite3VdbeResolveLabel(v, endOfLoop);  if( useTempTable ){    sqlite3VdbeAddOp2(v, OP_Next, srcTab, iCont);    sqlite3VdbeResolveLabel(v, iBreak);    sqlite3VdbeAddOp2(v, OP_Close, srcTab, 0);  }else if( pSelect ){    sqlite3VdbeAddOp2(v, OP_Return, 0, 0);    sqlite3VdbeResolveLabel(v, iCleanup);  }  if( !IsVirtual(pTab) && !isView ){    /* Close all tables opened */    sqlite3VdbeAddOp2(v, OP_Close, baseCur, 0);    for(idx=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, idx++){      sqlite3VdbeAddOp2(v, OP_Close, idx+baseCur, 0);    }  }  /* Update the sqlite_sequence table by storing the content of the  ** counter value in memory regAutoinc back into the sqlite_sequence  ** table.  */  autoIncEnd(pParse, iDb, pTab, regAutoinc);  /*  ** 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 ){    sqlite3VdbeAddOp2(v, OP_ResultRow, regRowCount, 1);    sqlite3VdbeSetNumCols(v, 1);    sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows inserted", P4_STATIC);  }insert_cleanup:  sqlite3SrcListDelete(pTabList);  sqlite3ExprListDelete(pList);  sqlite3SelectDelete(pSelect);  sqlite3IdListDelete(pColumn);  sqlite3_free(aRegIdx);}/*** Generate code to do constraint checks prior to an INSERT or an UPDATE.**** The input is a range of consecutive registers as follows:****    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 or writing to a virtual table.****    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 regRowid parameter is the index of the register containing (2).**** 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.  RowidChng means that the new rowid is explicitly specified by** the update or insert statement.  If rowidChng is false, it means that** the rowid is computed automatically in an insert or that the rowid value** is not modified by the update.**** The code generated by this routine store new index entries into** registers identified by aRegIdx[].  No index entry is created for** indices where aRegIdx[i]==0.  The order of indices in aRegIdx[] is** the same as the order of indices on the linked list of indices** attached to the table.**** 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 "baseCur".  All indices of pTab must also have open** read/write cursors with cursor number baseCur+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 aRegIdx[i]==0.*/void sqlite3GenerateConstraintChecks(  Parse *pParse,      /* The parser context */  Table *pTab,        /* the table into which we are inserting */  int baseCur,        /* Index of a read/write cursor pointing at pTab */  int regRowid,       /* Index of the range of input registers */  int *aRegIdx,       /* Register used by each index.  0 for unused indices */  int rowidChng,      /* True if the rowid might collide with existing entry */  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 j1, j2, j3;     /* Addresses of jump instructions */  int regData;        /* Register containing first data column */  int iCur;  Index *pIdx;  int seenReplace = 0;  int hasTwoRowids = (isUpdate && rowidChng);  v = sqlite3GetVdbe(pParse);  assert( v!=0 );  assert( pTab->pSelect==0 );  /* This table is not a VIEW */  nCol = pTab->nCol;  regData = regRowid + 1;  /* 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;    }    j1 = sqlite3VdbeAddOp1(v, OP_NotNull, regData+i);    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;        sqlite3VdbeAddOp2(v, OP_Halt, SQLITE_CONSTRAINT, onError);        sqlite3SetString(&zMsg, pTab->zName, ".", pTab->aCol[i].zName,                        " may not be NULL", (char*)0);        sqlite3VdbeChangeP4(v, -1, zMsg, P4_DYNAMIC);        break;      }      case OE_Ignore: {        sqlite3VdbeAddOp2(v, OP_Goto, 0, ignoreDest);        break;      }      case OE_Replace: {        sqlite3ExprCode(pParse, pTab->aCol[i].pDflt, regData+i);        break;      }    }    sqlite3VdbeJumpHere(v, j1);  }  /* Test all CHECK constraints  */#ifndef SQLITE_OMIT_CHECK  if( pTab->pCheck && (pParse->db->flags & SQLITE_IgnoreChecks)==0 ){    int allOk = sqlite3VdbeMakeLabel(v);    pParse->ckBase = regData;    sqlite3ExprIfTrue(pParse, pTab->pCheck, allOk, SQLITE_JUMPIFNULL);    onError = overrideError!=OE_Default ? overrideError : OE_Abort;    if( onError==OE_Ignore ){      sqlite3VdbeAddOp2(v, OP_Goto, 0, ignoreDest);    }else{      sqlite3VdbeAddOp2(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( onError!=OE_Replace || pTab->pIndex ){      if( isUpdate ){        j2 = sqlite3VdbeAddOp3(v, OP_Eq, regRowid, 0, regRowid-1);      }      j3 = sqlite3VdbeAddOp3(v, OP_NotExists, baseCur, 0, regRowid);      switch( onError ){        default: {          onError = OE_Abort;          /* Fall thru into the next case */        }        case OE_Rollback:        case OE_Abort:        case OE_Fail: {          sqlite3VdbeAddOp4(v, OP_Halt, SQLITE_CONSTRAINT, onError, 0,                           "PRIMARY KEY must be unique", P4_STATIC);          break;        }        case OE_Replace: {          sqlite3GenerateRowIndexDelete(pParse, pTab, baseCur, 0);          seenReplace = 1;          break;        }        case OE_Ignore: {          assert( seenReplace==0 );          sqlite3VdbeAddOp2(v, OP_Goto, 0, ignoreDest);          break;        }      }      sqlite3VdbeJumpHere(v, j3);      if( isUpdate ){        sqlite3VdbeJumpHere(v, j2);      }    }  }  /* 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.  */  for(iCur=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, iCur++){    int regIdx;    int regR;    if( aRegIdx[iCur]==0 ) continue;  /* Skip unused indices */    /* Create a key for accessing the index entry */    regIdx = sqlite3GetTempRange(pParse, pIdx->nColumn+1);    for(i=0; i<pIdx->nColumn; i++){      int idx = pIdx->aiColumn[i];      if( idx==pTab->iPKey ){        sqlite3VdbeAddOp2(v, OP_SCopy, regRowid, regIdx+i);      }else{        sqlite3VdbeAddOp2(v, OP_SCopy, regData+idx, regIdx+i);      }    }    sqlite3VdbeAddOp2(v, OP_SCopy, regRowid, regIdx+i);    sqlite3VdbeAddOp3(v, OP_MakeRecord, regIdx, pIdx->nColumn+1, aRegIdx[iCur]);    sqlite3IndexAffinityStr(v, pIdx);    sqlite3ExprCacheAffinityChange(pParse, regIdx, pIdx->nColumn+1);    sqlite3ReleaseTempRange(pParse, regIdx, pIdx->nColumn+1);    /* 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 */    j2 = sqlite3VdbeAddOp3(v, OP_IsNull, regIdx, 0, pIdx->nColumn);    regR = sqlite3GetTempReg(pParse);    sqlite3VdbeAddOp2(v, OP_SCopy, regRowid-hasTwoRowids, regR);    j3 = sqlite3VdbeAddOp4(v, OP_IsUnique, baseCur+iCur+1, 0,                           regR, (char*)(sqlite3_intptr_t)aRegIdx[iCur],                           P4_INT32);    /* 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");        sqlite3VdbeAddOp4(v, OP_Halt, SQLITE_CONSTRAINT, onError, 0, zErrMsg,0);        break;      }      case OE_Ignore: {        assert( seenReplace==0 );        sqlite3VdbeAddOp2(v, OP_Goto, 0, ignoreDest);        break;      }      case OE_Replace: {        sqlite3GenerateRowDelete(pParse, pTab, baseCur, regR, 0);        seenReplace = 1;        break;      }    }    sqlite3VdbeJumpHere(v, j2);    sqlite3VdbeJumpHere(v, j3);    sqlite3ReleaseTempReg(pParse, regR);  }}/*** This routine generates code to finish the INSERT or UPDATE operation** that was started by a prior call to sqlite3GenerateConstraintChecks.** A consecutive range of registers starting at regRowid contains the** rowid and the content to be inserted.**

⌨️ 快捷键说明

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