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

📄 insert.c

📁 sqlite数据库管理系统开放源码
💻 C
📖 第 1 页 / 共 3 页
字号:
  /* If there is no IDLIST term but the table has an integer primary  ** key, the set the keyColumn variable to the primary key column index  ** in the original table definition.  */  if( pColumn==0 ){    keyColumn = pTab->iPKey;  }  /* Open the temp table for FOR EACH ROW triggers  */  if( row_triggers_exist ){    sqliteVdbeAddOp(v, OP_OpenPseudo, newIdx, 0);  }      /* Initialize the count of rows to be inserted  */  if( db->flags & SQLITE_CountRows ){    iCntMem = pParse->nMem++;    sqliteVdbeAddOp(v, OP_Integer, 0, 0);    sqliteVdbeAddOp(v, OP_MemStore, iCntMem, 1);  }  /* Open tables and indices if there are no row triggers */  if( !row_triggers_exist ){    base = pParse->nTab;    idx = sqliteOpenTableAndIndices(pParse, pTab, base);    pParse->nTab += idx;  }  /* If the data source is a temporary table, then we have to create  ** a loop because there might be multiple rows of data.  If the data  ** source is a subroutine call from the SELECT statement, then we need  ** to launch the SELECT statement processing.  */  if( useTempTable ){    iBreak = sqliteVdbeMakeLabel(v);    sqliteVdbeAddOp(v, OP_Rewind, srcTab, iBreak);    iCont = sqliteVdbeCurrentAddr(v);  }else if( pSelect ){    sqliteVdbeAddOp(v, OP_Goto, 0, iSelectLoop);    sqliteVdbeResolveLabel(v, iInsertBlock);  }  /* Run the BEFORE and INSTEAD OF triggers, if there are any  */  endOfLoop = sqliteVdbeMakeLabel(v);  if( before_triggers ){    /* build the NEW.* reference row.  Note that if there is an INTEGER    ** PRIMARY KEY into which a NULL is being inserted, that NULL will be    ** translated into a unique ID for the row.  But on a BEFORE trigger,    ** we do not know what the unique ID will be (because the insert has    ** not happened yet) so we substitute a rowid of -1    */    if( keyColumn<0 ){      sqliteVdbeAddOp(v, OP_Integer, -1, 0);    }else if( useTempTable ){      sqliteVdbeAddOp(v, OP_Column, srcTab, keyColumn);    }else if( pSelect ){      sqliteVdbeAddOp(v, OP_Dup, nColumn - keyColumn - 1, 1);    }else{      sqliteExprCode(pParse, pList->a[keyColumn].pExpr);      sqliteVdbeAddOp(v, OP_NotNull, -1, sqliteVdbeCurrentAddr(v)+3);      sqliteVdbeAddOp(v, OP_Pop, 1, 0);      sqliteVdbeAddOp(v, OP_Integer, -1, 0);      sqliteVdbeAddOp(v, OP_MustBeInt, 0, 0);    }    /* Create the new column data    */    for(i=0; i<pTab->nCol; i++){      if( pColumn==0 ){        j = i;      }else{        for(j=0; j<pColumn->nId; j++){          if( pColumn->a[j].idx==i ) break;        }      }      if( pColumn && j>=pColumn->nId ){        sqliteVdbeOp3(v, OP_String, 0, 0, pTab->aCol[i].zDflt, P3_STATIC);      }else if( useTempTable ){        sqliteVdbeAddOp(v, OP_Column, srcTab, j);       }else if( pSelect ){        sqliteVdbeAddOp(v, OP_Dup, nColumn-j-1, 1);      }else{        sqliteExprCode(pParse, pList->a[j].pExpr);      }    }    sqliteVdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0);    sqliteVdbeAddOp(v, OP_PutIntKey, newIdx, 0);    /* Fire BEFORE or INSTEAD OF triggers */    if( sqliteCodeRowTrigger(pParse, TK_INSERT, 0, TK_BEFORE, pTab,         newIdx, -1, onError, endOfLoop) ){      goto insert_cleanup;    }  }  /* If any triggers exists, the opening of tables and indices is deferred  ** until now.  */  if( row_triggers_exist && !isView ){    base = pParse->nTab;    idx = sqliteOpenTableAndIndices(pParse, pTab, base);    pParse->nTab += idx;  }  /* Push the record number for the new entry onto the stack.  The  ** record number is a randomly generate integer created by NewRecno  ** except when the table has an INTEGER PRIMARY KEY column, in which  ** case the record number is the same as that column.   */  if( !isView ){    if( keyColumn>=0 ){      if( useTempTable ){        sqliteVdbeAddOp(v, OP_Column, srcTab, keyColumn);      }else if( pSelect ){        sqliteVdbeAddOp(v, OP_Dup, nColumn - keyColumn - 1, 1);      }else{        sqliteExprCode(pParse, pList->a[keyColumn].pExpr);      }      /* If the PRIMARY KEY expression is NULL, then use OP_NewRecno      ** to generate a unique primary key value.      */      sqliteVdbeAddOp(v, OP_NotNull, -1, sqliteVdbeCurrentAddr(v)+3);      sqliteVdbeAddOp(v, OP_Pop, 1, 0);      sqliteVdbeAddOp(v, OP_NewRecno, base, 0);      sqliteVdbeAddOp(v, OP_MustBeInt, 0, 0);    }else{      sqliteVdbeAddOp(v, OP_NewRecno, base, 0);    }    /* Push onto the stack, data for all columns of the new entry, beginning    ** with the first column.    */    for(i=0; i<pTab->nCol; i++){      if( i==pTab->iPKey ){        /* The value of the INTEGER PRIMARY KEY column is always a NULL.        ** Whenever this column is read, the record number will be substituted        ** in its place.  So will fill this column with a NULL to avoid        ** taking up data space with information that will never be used. */        sqliteVdbeAddOp(v, OP_String, 0, 0);        continue;      }      if( pColumn==0 ){        j = i;      }else{        for(j=0; j<pColumn->nId; j++){          if( pColumn->a[j].idx==i ) break;        }      }      if( pColumn && j>=pColumn->nId ){        sqliteVdbeOp3(v, OP_String, 0, 0, pTab->aCol[i].zDflt, P3_STATIC);      }else if( useTempTable ){        sqliteVdbeAddOp(v, OP_Column, srcTab, j);       }else if( pSelect ){        sqliteVdbeAddOp(v, OP_Dup, i+nColumn-j, 1);      }else{        sqliteExprCode(pParse, pList->a[j].pExpr);      }    }    /* Generate code to check constraints and generate index keys and    ** do the insertion.    */    sqliteGenerateConstraintChecks(pParse, pTab, base, 0, keyColumn>=0,                                   0, onError, endOfLoop);    sqliteCompleteInsertion(pParse, pTab, base, 0,0,0,                            after_triggers ? newIdx : -1);  }  /* Update the count of rows that are inserted  */  if( (db->flags & SQLITE_CountRows)!=0 ){    sqliteVdbeAddOp(v, OP_MemIncr, iCntMem, 0);  }  if( row_triggers_exist ){    /* Close all tables opened */    if( !isView ){      sqliteVdbeAddOp(v, OP_Close, base, 0);      for(idx=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, idx++){        sqliteVdbeAddOp(v, OP_Close, idx+base, 0);      }    }    /* Code AFTER triggers */    if( sqliteCodeRowTrigger(pParse, TK_INSERT, 0, TK_AFTER, pTab, newIdx, -1,           onError, endOfLoop) ){      goto insert_cleanup;    }  }  /* The bottom of the loop, if the data source is a SELECT statement  */  sqliteVdbeResolveLabel(v, endOfLoop);  if( useTempTable ){    sqliteVdbeAddOp(v, OP_Next, srcTab, iCont);    sqliteVdbeResolveLabel(v, iBreak);    sqliteVdbeAddOp(v, OP_Close, srcTab, 0);  }else if( pSelect ){    sqliteVdbeAddOp(v, OP_Pop, nColumn, 0);    sqliteVdbeAddOp(v, OP_Return, 0, 0);    sqliteVdbeResolveLabel(v, iCleanup);  }  if( !row_triggers_exist ){    /* Close all tables opened */    sqliteVdbeAddOp(v, OP_Close, base, 0);    for(idx=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, idx++){      sqliteVdbeAddOp(v, OP_Close, idx+base, 0);    }  }  sqliteVdbeAddOp(v, OP_SetCounts, 0, 0);  sqliteEndWriteOperation(pParse);  /*  ** Return the number of rows inserted.  */  if( db->flags & SQLITE_CountRows ){    sqliteVdbeOp3(v, OP_ColumnName, 0, 1, "rows inserted", P3_STATIC);    sqliteVdbeAddOp(v, OP_MemLoad, iCntMem, 0);    sqliteVdbeAddOp(v, OP_Callback, 1, 0);  }insert_cleanup:  sqliteSrcListDelete(pTabList);  if( pList ) sqliteExprListDelete(pList);  if( pSelect ) sqliteSelectDelete(pSelect);  sqliteIdListDelete(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 recno 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 recno 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 recno shown as entry (1) above is omitted unless both isUpdate** and recnoChng are 1.  isUpdate is true for UPDATEs and false for** INSERTs and recnoChng 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**                                sqlite_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 sqlite_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

⌨️ 快捷键说明

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