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

📄 insert.c

📁 sqlite-3.4.1,嵌入式数据库.是一个功能强大的开源数据库,给学习和研发以及小型公司的发展带来了全所未有的好处.
💻 C
📖 第 1 页 / 共 4 页
字号:
  assert( pTab!=0 );  /* If pTab is really a view, make sure it has been initialized.  ** ViewGetColumnNames() is a no-op if pTab is not a view (or virtual   ** module table).  */  if( sqlite3ViewGetColumnNames(pParse, pTab) ){    goto insert_cleanup;  }  /* Allocate a VDBE  */  v = sqlite3GetVdbe(pParse);  if( v==0 ) goto insert_cleanup;  if( pParse->nested==0 ) sqlite3VdbeCountChanges(v);  sqlite3BeginWriteOperation(pParse, pSelect || triggers_exist, iDb);  /* if there are row triggers, allocate a temp table for new.* references. */  if( triggers_exist ){    newIdx = pParse->nTab++;  }#ifndef SQLITE_OMIT_XFER_OPT  /* If the statement is of the form  **  **       INSERT INTO <table1> SELECT * FROM <table2>;  **  ** Then special optimizations can be applied that make the transfer  ** very fast and which reduce fragmentation of indices.  */  if( pColumn==0 && xferOptimization(pParse, pTab, pSelect, onError, iDb) ){    assert( !triggers_exist );    assert( pList==0 );    goto insert_cleanup;  }#endif /* SQLITE_OMIT_XFER_OPT */  /* If this is an AUTOINCREMENT table, look up the sequence number in the  ** sqlite_sequence table and store it in memory cell counterMem.  Also  ** remember the rowid of the sqlite_sequence table entry in memory cell  ** counterRowid.  */  counterMem = autoIncBegin(pParse, iDb, pTab);  /* Figure out how many columns of data are supplied.  If the data  ** is coming from a SELECT statement, then this step also generates  ** all the code to implement the SELECT statement and invoke a subroutine  ** to process each row of the result. (Template 2.) If the SELECT  ** statement uses the the table that is being inserted into, then the  ** subroutine is also coded here.  That subroutine stores the SELECT  ** results in a temporary table. (Template 3.)  */  if( pSelect ){    /* Data is coming from a SELECT.  Generate code to implement that SELECT    */    int rc, iInitCode;    iInitCode = sqlite3VdbeAddOp(v, OP_Goto, 0, 0);    iSelectLoop = sqlite3VdbeCurrentAddr(v);    iInsertBlock = sqlite3VdbeMakeLabel(v);    /* Resolve the expressions in the SELECT statement and execute it. */    rc = sqlite3Select(pParse, pSelect, SRT_Subroutine, iInsertBlock,0,0,0,0);    if( rc || pParse->nErr || sqlite3MallocFailed() ){      goto insert_cleanup;    }    iCleanup = sqlite3VdbeMakeLabel(v);    sqlite3VdbeAddOp(v, OP_Goto, 0, iCleanup);    assert( pSelect->pEList );    nColumn = pSelect->pEList->nExpr;    /* Set useTempTable to TRUE if the result of the SELECT statement    ** should be written into a temporary table.  Set to FALSE if each    ** row of the SELECT can be written directly into the result table.    **    ** A temp table must be used if the table being updated is also one    ** of the tables being read by the SELECT statement.  Also use a     ** temp table in the case of row triggers.    */    if( triggers_exist || selectReadsTable(pSelect,pTab->pSchema,pTab->tnum) ){      useTempTable = 1;    }    if( useTempTable ){      /* Generate the subroutine that SELECT calls to process each row of      ** the result.  Store the result in a temporary table      */      srcTab = pParse->nTab++;      sqlite3VdbeResolveLabel(v, iInsertBlock);      sqlite3VdbeAddOp(v, OP_MakeRecord, nColumn, 0);      sqlite3VdbeAddOp(v, OP_NewRowid, srcTab, 0);      sqlite3VdbeAddOp(v, OP_Pull, 1, 0);      sqlite3VdbeAddOp(v, OP_Insert, srcTab, OPFLAG_APPEND);      sqlite3VdbeAddOp(v, OP_Return, 0, 0);      /* The following code runs first because the GOTO at the very top      ** of the program jumps to it.  Create the temporary table, then jump      ** back up and execute the SELECT code above.      */      sqlite3VdbeJumpHere(v, iInitCode);      sqlite3VdbeAddOp(v, OP_OpenEphemeral, srcTab, 0);      sqlite3VdbeAddOp(v, OP_SetNumColumns, srcTab, nColumn);      sqlite3VdbeAddOp(v, OP_Goto, 0, iSelectLoop);      sqlite3VdbeResolveLabel(v, iCleanup);    }else{      sqlite3VdbeJumpHere(v, iInitCode);    }  }else{    /* This is the case if the data for the INSERT is coming from a VALUES    ** clause    */    NameContext sNC;    memset(&sNC, 0, sizeof(sNC));    sNC.pParse = pParse;    srcTab = -1;    useTempTable = 0;    nColumn = pList ? pList->nExpr : 0;    for(i=0; i<nColumn; i++){      if( sqlite3ExprResolveNames(&sNC, pList->a[i].pExpr) ){        goto insert_cleanup;      }    }  }  /* Make sure the number of columns in the source data matches the number  ** of columns to be inserted into the table.  */  if( IsVirtual(pTab) ){    for(i=0; i<pTab->nCol; i++){      nHidden += (IsHiddenColumn(&pTab->aCol[i]) ? 1 : 0);    }  }  if( pColumn==0 && nColumn && nColumn!=(pTab->nCol-nHidden) ){    sqlite3ErrorMsg(pParse,        "table %S has %d columns but %d values were supplied",       pTabList, 0, pTab->nCol, nColumn);    goto insert_cleanup;  }  if( pColumn!=0 && nColumn!=pColumn->nId ){    sqlite3ErrorMsg(pParse, "%d values for %d columns", nColumn, pColumn->nId);    goto insert_cleanup;  }  /* If the INSERT statement included an IDLIST term, then make sure  ** all elements of the IDLIST really are columns of the table and   ** remember the column indices.  **  ** If the table has an INTEGER PRIMARY KEY column and that column  ** is named in the IDLIST, then record in the keyColumn variable  ** the index into IDLIST of the primary key column.  keyColumn is  ** the index of the primary key as it appears in IDLIST, not as  ** is appears in the original table.  (The index of the primary  ** key in the original table is pTab->iPKey.)  */  if( pColumn ){    for(i=0; i<pColumn->nId; i++){      pColumn->a[i].idx = -1;    }    for(i=0; i<pColumn->nId; i++){      for(j=0; j<pTab->nCol; j++){        if( sqlite3StrICmp(pColumn->a[i].zName, pTab->aCol[j].zName)==0 ){          pColumn->a[i].idx = j;          if( j==pTab->iPKey ){            keyColumn = i;          }          break;        }      }      if( j>=pTab->nCol ){        if( sqlite3IsRowid(pColumn->a[i].zName) ){          keyColumn = i;        }else{          sqlite3ErrorMsg(pParse, "table %S has no column named %s",              pTabList, 0, pColumn->a[i].zName);          pParse->nErr++;          goto insert_cleanup;        }      }    }  }  /* 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 && nColumn>0 ){    keyColumn = pTab->iPKey;  }  /* Open the temp table for FOR EACH ROW triggers  */  if( triggers_exist ){    sqlite3VdbeAddOp(v, OP_OpenPseudo, newIdx, 0);    sqlite3VdbeAddOp(v, OP_SetNumColumns, newIdx, pTab->nCol);  }      /* Initialize the count of rows to be inserted  */  if( db->flags & SQLITE_CountRows ){    iCntMem = pParse->nMem++;    sqlite3VdbeAddOp(v, OP_MemInt, 0, iCntMem);  }  /* Open tables and indices if there are no row triggers */  if( !triggers_exist ){    base = pParse->nTab;    sqlite3OpenTableAndIndices(pParse, pTab, base, OP_OpenWrite);  }  /* 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 = sqlite3VdbeMakeLabel(v);    sqlite3VdbeAddOp(v, OP_Rewind, srcTab, iBreak);    iCont = sqlite3VdbeCurrentAddr(v);  }else if( pSelect ){    sqlite3VdbeAddOp(v, OP_Goto, 0, iSelectLoop);    sqlite3VdbeResolveLabel(v, iInsertBlock);  }  /* Run the BEFORE and INSTEAD OF triggers, if there are any  */  endOfLoop = sqlite3VdbeMakeLabel(v);  if( triggers_exist & TRIGGER_BEFORE ){    /* 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 ){      sqlite3VdbeAddOp(v, OP_Integer, -1, 0);    }else if( useTempTable ){      sqlite3VdbeAddOp(v, OP_Column, srcTab, keyColumn);    }else{      assert( pSelect==0 );  /* Otherwise useTempTable is true */      sqlite3ExprCode(pParse, pList->a[keyColumn].pExpr);      sqlite3VdbeAddOp(v, OP_NotNull, -1, sqlite3VdbeCurrentAddr(v)+3);      sqlite3VdbeAddOp(v, OP_Pop, 1, 0);      sqlite3VdbeAddOp(v, OP_Integer, -1, 0);      sqlite3VdbeAddOp(v, OP_MustBeInt, 0, 0);    }    /* Cannot have triggers on a virtual table. If it were possible,    ** this block would have to account for hidden column.    */    assert(!IsVirtual(pTab));    /* 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 ){        sqlite3ExprCode(pParse, pTab->aCol[i].pDflt);      }else if( useTempTable ){        sqlite3VdbeAddOp(v, OP_Column, srcTab, j);       }else{        assert( pSelect==0 ); /* Otherwise useTempTable is true */        sqlite3ExprCodeAndCache(pParse, pList->a[j].pExpr);      }    }    sqlite3VdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0);    /* If this is an INSERT on a view with an INSTEAD OF INSERT trigger,    ** do not attempt any conversions before assembling the record.    ** If this is a real table, attempt conversions as required by the    ** table column affinities.    */    if( !isView ){      sqlite3TableAffinityStr(v, pTab);    }    sqlite3VdbeAddOp(v, OP_Insert, newIdx, 0);    /* Fire BEFORE or INSTEAD OF triggers */    if( sqlite3CodeRowTrigger(pParse, TK_INSERT, 0, TRIGGER_BEFORE, pTab,         newIdx, -1, onError, endOfLoop) ){      goto insert_cleanup;    }  }  /* If any triggers exists, the opening of tables and indices is deferred  ** until now.  */  if( triggers_exist && !isView ){    base = pParse->nTab;    sqlite3OpenTableAndIndices(pParse, pTab, base, OP_OpenWrite);  }  /* Push the record number for the new entry onto the stack.  The  ** record number is a randomly generate integer created by NewRowid  ** 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( IsVirtual(pTab) ){      /* The row that the VUpdate opcode will delete:  none */      sqlite3VdbeAddOp(v, OP_Null, 0, 0);    }    if( keyColumn>=0 ){      if( useTempTable ){        sqlite3VdbeAddOp(v, OP_Column, srcTab, keyColumn);      }else if( pSelect ){        sqlite3VdbeAddOp(v, OP_Dup, nColumn - keyColumn - 1, 1);      }else{        VdbeOp *pOp;        sqlite3ExprCode(pParse, pList->a[keyColumn].pExpr);        pOp = sqlite3VdbeGetOp(v, sqlite3VdbeCurrentAddr(v) - 1);        if( pOp && pOp->opcode==OP_Null ){          appendFlag = 1;          pOp->opcode = OP_NewRowid;          pOp->p1 = base;          pOp->p2 = counterMem;        }      }      /* If the PRIMARY KEY expression is NULL, then use OP_NewRowid      ** to generate a unique primary key value.      */      if( !appendFlag ){        sqlite3VdbeAddOp(v, OP_NotNull, -1, sqlite3VdbeCurrentAddr(v)+3);        sqlite3VdbeAddOp(v, OP_Pop, 1, 0);        sqlite3VdbeAddOp(v, OP_NewRowid, base, counterMem);        sqlite3VdbeAddOp(v, OP_MustBeInt, 0, 0);      }    }else if( IsVirtual(pTab) ){      sqlite3VdbeAddOp(v, OP_Null, 0, 0);    }else{      sqlite3VdbeAddOp(v, OP_NewRowid, base, counterMem);      appendFlag = 1;    }    autoIncStep(pParse, counterMem);    /* Push onto the stack, data for all columns of the new entry, beginning    ** with the first column.    */    nHidden = 0;    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. */        sqlite3VdbeAddOp(v, OP_Null, 0, 0);        continue;      }      if( pColumn==0 ){        if( IsHiddenColumn(&pTab->aCol[i]) ){          assert( IsVirtual(pTab) );          j = -1;          nHidden++;        }else{          j = i - nHidden;        }      }else{        for(j=0; j<pColumn->nId; j++){          if( pColumn->a[j].idx==i ) break;        }      }      if( j<0 || nColumn==0 || (pColumn && j>=pColumn->nId) ){        sqlite3ExprCode(pParse, pTab->aCol[i].pDflt);      }else if( useTempTable ){        sqlite3VdbeAddOp(v, OP_Column, srcTab, j);       }else if( pSelect ){        sqlite3VdbeAddOp(v, OP_Dup, i+nColumn-j+IsVirtual(pTab), 1);      }else{        sqlite3ExprCode(pParse, pList->a[j].pExpr);      }    }    /* Generate code to check constraints and generate index keys and    ** do the insertion.    */#ifndef SQLITE_OMIT_VIRTUALTABLE    if( IsVirtual(pTab) ){      pParse->pVirtualLock = pTab;      sqlite3VdbeOp3(v, OP_VUpdate, 1, pTab->nCol+2,                     (const char*)pTab->pVtab, P3_VTAB);    }else#endif    {      sqlite3GenerateConstraintChecks(pParse, pTab, base, 0, keyColumn>=0,                                     0, onError, endOfLoop);      sqlite3CompleteInsertion(pParse, pTab, base, 0,0,0,                            (triggers_exist & TRIGGER_AFTER)!=0 ? newIdx : -1,                            appendFlag);    }  }  /* Update the count of rows that are inserted  */  if( (db->flags & SQLITE_CountRows)!=0 ){    sqlite3VdbeAddOp(v, OP_MemIncr, 1, iCntMem);  }

⌨️ 快捷键说明

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