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

📄 insert.c

📁 sqlite-source-2_8_16.zip 轻量级嵌入式数据库源码
💻 C
📖 第 1 页 / 共 3 页
字号:
** 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 sqliteGenerateConstraintChecks(  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 recnoChng,      /* 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, jumpInst2;  int contAddr;  int hasTwoRecnos = (isUpdate && recnoChng);  v = sqliteGetVdbe(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( pParse->db->onError!=OE_Default ){      onError = pParse->db->onError;    }else if( onError==OE_Default ){      onError = OE_Abort;    }    if( onError==OE_Replace && pTab->aCol[i].zDflt==0 ){      onError = OE_Abort;    }    sqliteVdbeAddOp(v, OP_Dup, nCol-1-i, 1);    addr = sqliteVdbeAddOp(v, OP_NotNull, 1, 0);    switch( onError ){      case OE_Rollback:      case OE_Abort:      case OE_Fail: {        char *zMsg = 0;        sqliteVdbeAddOp(v, OP_Halt, SQLITE_CONSTRAINT, onError);        sqliteSetString(&zMsg, pTab->zName, ".", pTab->aCol[i].zName,                        " may not be NULL", (char*)0);        sqliteVdbeChangeP3(v, -1, zMsg, P3_DYNAMIC);        break;      }      case OE_Ignore: {        sqliteVdbeAddOp(v, OP_Pop, nCol+1+hasTwoRecnos, 0);        sqliteVdbeAddOp(v, OP_Goto, 0, ignoreDest);        break;      }      case OE_Replace: {        sqliteVdbeOp3(v, OP_String, 0, 0, pTab->aCol[i].zDflt, P3_STATIC);        sqliteVdbeAddOp(v, OP_Push, nCol-i, 0);        break;      }      default: assert(0);    }    sqliteVdbeChangeP2(v, addr, sqliteVdbeCurrentAddr(v));  }  /* Test all CHECK constraints  */  /**** TBD ****/  /* 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( recnoChng ){    onError = pTab->keyConf;    if( overrideError!=OE_Default ){      onError = overrideError;    }else if( pParse->db->onError!=OE_Default ){      onError = pParse->db->onError;    }else if( onError==OE_Default ){      onError = OE_Abort;    }        if( isUpdate ){      sqliteVdbeAddOp(v, OP_Dup, nCol+1, 1);      sqliteVdbeAddOp(v, OP_Dup, nCol+1, 1);      jumpInst1 = sqliteVdbeAddOp(v, OP_Eq, 0, 0);    }    sqliteVdbeAddOp(v, OP_Dup, nCol, 1);    jumpInst2 = sqliteVdbeAddOp(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: {        sqliteVdbeOp3(v, OP_Halt, SQLITE_CONSTRAINT, onError,                         "PRIMARY KEY must be unique", P3_STATIC);        break;      }      case OE_Replace: {        sqliteGenerateRowIndexDelete(pParse->db, v, pTab, base, 0);        if( isUpdate ){          sqliteVdbeAddOp(v, OP_Dup, nCol+hasTwoRecnos, 1);          sqliteVdbeAddOp(v, OP_MoveTo, base, 0);        }        seenReplace = 1;        break;      }      case OE_Ignore: {        assert( seenReplace==0 );        sqliteVdbeAddOp(v, OP_Pop, nCol+1+hasTwoRecnos, 0);        sqliteVdbeAddOp(v, OP_Goto, 0, ignoreDest);        break;      }    }    contAddr = sqliteVdbeCurrentAddr(v);    sqliteVdbeChangeP2(v, jumpInst2, contAddr);    if( isUpdate ){      sqliteVdbeChangeP2(v, jumpInst1, contAddr);      sqliteVdbeAddOp(v, OP_Dup, nCol+1, 1);      sqliteVdbeAddOp(v, OP_MoveTo, 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 */    sqliteVdbeAddOp(v, OP_Dup, nCol+extra, 1);    for(i=0; i<pIdx->nColumn; i++){      int idx = pIdx->aiColumn[i];      if( idx==pTab->iPKey ){        sqliteVdbeAddOp(v, OP_Dup, i+extra+nCol+1, 1);      }else{        sqliteVdbeAddOp(v, OP_Dup, i+extra+nCol-idx, 1);      }    }    jumpInst1 = sqliteVdbeAddOp(v, OP_MakeIdxKey, pIdx->nColumn, 0);    if( pParse->db->file_format>=4 ) sqliteAddIdxKeyType(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( pParse->db->onError!=OE_Default ){      onError = pParse->db->onError;    }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 */    sqliteVdbeAddOp(v, OP_Dup, extra+nCol+1+hasTwoRecnos, 1);    jumpInst2 = sqliteVdbeAddOp(v, OP_IsUnique, base+iCur+1, 0);    /* Generate code that executes if the new index entry is not unique */    switch( onError ){      case OE_Rollback:      case OE_Abort:      case OE_Fail: {        int j, n1, n2;        char zErrMsg[200];        strcpy(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 ){            strcpy(&zErrMsg[n1], ", ");            n1 += 2;          }          if( n1+n2>sizeof(zErrMsg)-30 ){            strcpy(&zErrMsg[n1], "...");            n1 += 3;            break;          }else{            strcpy(&zErrMsg[n1], zCol);            n1 += n2;          }        }        strcpy(&zErrMsg[n1],             pIdx->nColumn>1 ? " are not unique" : " is not unique");        sqliteVdbeOp3(v, OP_Halt, SQLITE_CONSTRAINT, onError, zErrMsg, 0);        break;      }      case OE_Ignore: {        assert( seenReplace==0 );        sqliteVdbeAddOp(v, OP_Pop, nCol+extra+3+hasTwoRecnos, 0);        sqliteVdbeAddOp(v, OP_Goto, 0, ignoreDest);        break;      }      case OE_Replace: {        sqliteGenerateRowDelete(pParse->db, v, pTab, base, 0);        if( isUpdate ){          sqliteVdbeAddOp(v, OP_Dup, nCol+extra+1+hasTwoRecnos, 1);          sqliteVdbeAddOp(v, OP_MoveTo, base, 0);        }        seenReplace = 1;        break;      }      default: assert(0);    }    contAddr = sqliteVdbeCurrentAddr(v);#if NULL_DISTINCT_FOR_UNIQUE    sqliteVdbeChangeP2(v, jumpInst1, contAddr);#endif    sqliteVdbeChangeP2(v, jumpInst2, contAddr);  }}/*** This routine generates code to finish the INSERT or UPDATE operation** that was started by a prior call to sqliteGenerateConstraintChecks.** The stack must contain keys for all active indices followed by data** and the recno 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 sqliteGenerateConstraintChecks.*/void sqliteCompleteInsertion(  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 recnoChng,      /* True if the record number will change */  int isUpdate,       /* True for UPDATE, False for INSERT */  int newIdx          /* Index of NEW table for triggers.  -1 if none */){  int i;  Vdbe *v;  int nIdx;  Index *pIdx;  v = sqliteGetVdbe(pParse);  assert( v!=0 );  assert( pTab->pSelect==0 );  /* This table is not a VIEW */  for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){}  for(i=nIdx-1; i>=0; i--){    if( aIdxUsed && aIdxUsed[i]==0 ) continue;    sqliteVdbeAddOp(v, OP_IdxPut, base+i+1, 0);  }  sqliteVdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0);  if( newIdx>=0 ){    sqliteVdbeAddOp(v, OP_Dup, 1, 0);    sqliteVdbeAddOp(v, OP_Dup, 1, 0);    sqliteVdbeAddOp(v, OP_PutIntKey, newIdx, 0);  }  sqliteVdbeAddOp(v, OP_PutIntKey, base,    (pParse->trigStack?0:OPFLAG_NCHANGE) |    (isUpdate?0:OPFLAG_LASTROWID) | OPFLAG_CSCHANGE);  if( isUpdate && recnoChng ){    sqliteVdbeAddOp(v, OP_Pop, 1, 0);  }}/*** Generate code that will open write cursors for a table and for all** indices of that table.  The "base" parameter is the cursor number used** for the table.  Indices are opened on subsequent cursors.**** Return the total number of cursors opened.  This is always at least** 1 (for the main table) plus more for each cursor.*/int sqliteOpenTableAndIndices(Parse *pParse, Table *pTab, int base){  int i;  Index *pIdx;  Vdbe *v = sqliteGetVdbe(pParse);  assert( v!=0 );  sqliteVdbeAddOp(v, OP_Integer, pTab->iDb, 0);  sqliteVdbeOp3(v, OP_OpenWrite, base, pTab->tnum, pTab->zName, P3_STATIC);  for(i=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){    sqliteVdbeAddOp(v, OP_Integer, pIdx->iDb, 0);    sqliteVdbeOp3(v, OP_OpenWrite, i+base, pIdx->tnum, pIdx->zName, P3_STATIC);  }  return i;}

⌨️ 快捷键说明

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