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

📄 insert.c

📁 sqlite 嵌入式数据库的源码
💻 C
📖 第 1 页 / 共 3 页
字号:
      ** of the program jumps to it.  Create the temporary table, then jump      ** back up and execute the SELECT code above.      */      sqlite3VdbeChangeP2(v, iInitCode, sqlite3VdbeCurrentAddr(v));      sqlite3VdbeAddOp(v, OP_OpenTemp, srcTab, 0);      sqlite3VdbeAddOp(v, OP_SetNumColumns, srcTab, nColumn);      sqlite3VdbeAddOp(v, OP_Goto, 0, iSelectLoop);      sqlite3VdbeResolveLabel(v, iCleanup);    }else{      sqlite3VdbeChangeP2(v, iInitCode, sqlite3VdbeCurrentAddr(v));    }  }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;    assert( pList!=0 );    srcTab = -1;    useTempTable = 0;    assert( pList );    nColumn = pList->nExpr;    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( pColumn==0 && nColumn!=pTab->nCol ){    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 ){    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_Integer, 0, 0);    sqlite3VdbeAddOp(v, OP_MemStore, iCntMem, 1);  }  /* 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);    }    /* 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( keyColumn>=0 ){      if( useTempTable ){        sqlite3VdbeAddOp(v, OP_Column, srcTab, keyColumn);      }else if( pSelect ){        sqlite3VdbeAddOp(v, OP_Dup, nColumn - keyColumn - 1, 1);      }else{        sqlite3ExprCode(pParse, pList->a[keyColumn].pExpr);      }      /* If the PRIMARY KEY expression is NULL, then use OP_NewRowid      ** to generate a unique primary key value.      */      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{      sqlite3VdbeAddOp(v, OP_NewRowid, base, counterMem);    }#ifndef SQLITE_OMIT_AUTOINCREMENT    if( pTab->autoInc ){      sqlite3VdbeAddOp(v, OP_MemMax, counterMem, 0);    }#endif /* SQLITE_OMIT_AUTOINCREMENT */    /* 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. */        sqlite3VdbeAddOp(v, OP_Null, 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 ){        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, 1);      }else{        sqlite3ExprCode(pParse, pList->a[j].pExpr);      }    }    /* Generate code to check constraints and generate index keys and    ** do the insertion.    */    sqlite3GenerateConstraintChecks(pParse, pTab, base, 0, keyColumn>=0,                                   0, onError, endOfLoop);    sqlite3CompleteInsertion(pParse, pTab, base, 0,0,0,                            (triggers_exist & TRIGGER_AFTER)!=0 ? newIdx : -1);  }  /* Update the count of rows that are inserted  */  if( (db->flags & SQLITE_CountRows)!=0 ){    sqlite3VdbeAddOp(v, OP_MemIncr, iCntMem, 0);  }  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 ){    /* 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);    }  }#ifndef SQLITE_OMIT_AUTOINCREMENT  /* Update the sqlite_sequence table by storing the content of the  ** counter value in memory counterMem back into the sqlite_sequence  ** table.  */  if( pTab->autoInc ){    int iCur = pParse->nTab;    int base = sqlite3VdbeCurrentAddr(v);    sqlite3VdbeAddOp(v, OP_Integer, pTab->iDb, 0);    sqlite3VdbeAddOp(v, OP_OpenWrite, iCur, pDb->pSeqTab->tnum);    sqlite3VdbeAddOp(v, OP_SetNumColumns, iCur, 2);    sqlite3VdbeAddOp(v, OP_MemLoad, counterRowid, 0);    sqlite3VdbeAddOp(v, OP_NotNull, -1, base+7);    sqlite3VdbeAddOp(v, OP_Pop, 1, 0);    sqlite3VdbeAddOp(v, OP_NewRowid, iCur, 0);    sqlite3VdbeOp3(v, OP_String8, 0, 0, pTab->zName, 0);    sqlite3VdbeAddOp(v, OP_MemLoad, counterMem, 0);    sqlite3VdbeAddOp(v, OP_MakeRecord, 2, 0);    sqlite3VdbeAddOp(v, OP_Insert, iCur, 0);    sqlite3VdbeAddOp(v, OP_Close, iCur, 0);  }#endif  /*  ** 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, "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.**

⌨️ 快捷键说明

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