engine/sqlite/src/insert.cpp
author skip
Thu, 25 Feb 2010 14:29:19 +0000
changeset 2 29cda98b007e
permissions -rw-r--r--
Initial import of Podcatcher from the Bergamot project
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
     1
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
     2
** 2001 September 15
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
     3
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
     4
** The author disclaims copyright to this source code.  In place of
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
     5
** a legal notice, here is a blessing:
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
     6
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
     7
**    May you do good and not evil.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
     8
**    May you find forgiveness for yourself and forgive others.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
     9
**    May you share freely, never taking more than you give.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    10
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    11
*************************************************************************
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    12
** This file contains C code routines that are called by the parser
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    13
** to handle INSERT statements in SQLite.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    14
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    15
** $Id: insert.cpp 1282 2008-11-13 09:31:33Z LarsPson $
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    16
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    17
#include "sqliteInt.h"
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    18
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    19
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    20
** Set P3 of the most recently inserted opcode to a column affinity
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    21
** string for index pIdx. A column affinity string has one character
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    22
** for each column in the table, according to the affinity of the column:
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    23
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    24
**  Character      Column affinity
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    25
**  ------------------------------
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    26
**  'a'            TEXT
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    27
**  'b'            NONE
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    28
**  'c'            NUMERIC
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    29
**  'd'            INTEGER
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    30
**  'e'            REAL
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    31
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    32
void sqlite3IndexAffinityStr(Vdbe *v, Index *pIdx){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    33
  if( !pIdx->zColAff ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    34
    /* The first time a column affinity string for a particular index is
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    35
    ** required, it is allocated and populated here. It is then stored as
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    36
    ** a member of the Index structure for subsequent use.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    37
    **
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    38
    ** The column affinity string will eventually be deleted by
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    39
    ** sqliteDeleteIndex() when the Index structure itself is cleaned
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    40
    ** up.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    41
    */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    42
    int n;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    43
    Table *pTab = pIdx->pTable;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    44
    sqlite3 *db = sqlite3VdbeDb(v);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    45
    pIdx->zColAff = (char *)sqlite3DbMallocZero(db, pIdx->nColumn+1);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    46
    if( !pIdx->zColAff ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    47
      return;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    48
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    49
    for(n=0; n<pIdx->nColumn; n++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    50
      pIdx->zColAff[n] = pTab->aCol[pIdx->aiColumn[n]].affinity;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    51
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    52
    pIdx->zColAff[pIdx->nColumn] = '\0';
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    53
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    54
 
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    55
  sqlite3VdbeChangeP3(v, -1, pIdx->zColAff, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    56
}
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    57
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    58
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    59
** Set P3 of the most recently inserted opcode to a column affinity
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    60
** string for table pTab. A column affinity string has one character
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    61
** for each column indexed by the index, according to the affinity of the
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    62
** column:
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    63
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    64
**  Character      Column affinity
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    65
**  ------------------------------
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    66
**  'a'            TEXT
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    67
**  'b'            NONE
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    68
**  'c'            NUMERIC
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    69
**  'd'            INTEGER
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    70
**  'e'            REAL
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    71
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    72
void sqlite3TableAffinityStr(Vdbe *v, Table *pTab){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    73
  /* The first time a column affinity string for a particular table
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    74
  ** is required, it is allocated and populated here. It is then 
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    75
  ** stored as a member of the Table structure for subsequent use.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    76
  **
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    77
  ** The column affinity string will eventually be deleted by
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    78
  ** sqlite3DeleteTable() when the Table structure itself is cleaned up.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    79
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    80
  if( !pTab->zColAff ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    81
    char *zColAff;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    82
    int i;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    83
    sqlite3 *db = sqlite3VdbeDb(v);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    84
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    85
    zColAff = (char *)sqlite3DbMallocZero(db, pTab->nCol+1);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    86
    if( !zColAff ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    87
      return;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    88
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    89
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    90
    for(i=0; i<pTab->nCol; i++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    91
      zColAff[i] = pTab->aCol[i].affinity;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    92
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    93
    zColAff[pTab->nCol] = '\0';
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    94
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    95
    pTab->zColAff = zColAff;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    96
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    97
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    98
  sqlite3VdbeChangeP3(v, -1, pTab->zColAff, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
    99
}
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   100
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   101
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   102
** Return non-zero if the table pTab in database iDb or any of its indices
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   103
** have been opened at any point in the VDBE program beginning at location
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   104
** iStartAddr throught the end of the program.  This is used to see if 
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   105
** a statement of the form  "INSERT INTO <iDb, pTab> SELECT ..." can 
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   106
** run without using temporary table for the results of the SELECT. 
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   107
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   108
static int readsTable(Vdbe *v, int iStartAddr, int iDb, Table *pTab){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   109
  int i;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   110
  int iEnd = sqlite3VdbeCurrentAddr(v);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   111
  for(i=iStartAddr; i<iEnd; i++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   112
    VdbeOp *pOp = sqlite3VdbeGetOp(v, i);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   113
    assert( pOp!=0 );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   114
    if( pOp->opcode==OP_OpenRead ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   115
      VdbeOp *pPrior = &pOp[-1];
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   116
      int tnum = pOp->p2;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   117
      assert( i>iStartAddr );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   118
      assert( pPrior->opcode==OP_Integer );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   119
      if( pPrior->p1==iDb ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   120
        Index *pIndex;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   121
        if( tnum==pTab->tnum ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   122
          return 1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   123
        }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   124
        for(pIndex=pTab->pIndex; pIndex; pIndex=pIndex->pNext){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   125
          if( tnum==pIndex->tnum ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   126
            return 1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   127
          }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   128
        }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   129
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   130
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   131
#ifndef SQLITE_OMIT_VIRTUALTABLE
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   132
    if( pOp->opcode==OP_VOpen && pOp->p3==(const char*)pTab->pVtab ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   133
      assert( pOp->p3!=0 );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   134
      assert( pOp->p3type==P3_VTAB );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   135
      return 1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   136
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   137
#endif
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   138
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   139
  return 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   140
}
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   141
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   142
#ifndef SQLITE_OMIT_AUTOINCREMENT
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   143
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   144
** Write out code to initialize the autoincrement logic.  This code
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   145
** looks up the current autoincrement value in the sqlite_sequence
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   146
** table and stores that value in a memory cell.  Code generated by
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   147
** autoIncStep() will keep that memory cell holding the largest
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   148
** rowid value.  Code generated by autoIncEnd() will write the new
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   149
** largest value of the counter back into the sqlite_sequence table.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   150
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   151
** This routine returns the index of the mem[] cell that contains
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   152
** the maximum rowid counter.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   153
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   154
** Two memory cells are allocated.  The next memory cell after the
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   155
** one returned holds the rowid in sqlite_sequence where we will
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   156
** write back the revised maximum rowid.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   157
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   158
static int autoIncBegin(
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   159
  Parse *pParse,      /* Parsing context */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   160
  int iDb,            /* Index of the database holding pTab */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   161
  Table *pTab         /* The table we are writing to */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   162
){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   163
  int memId = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   164
  if( pTab->autoInc ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   165
    Vdbe *v = pParse->pVdbe;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   166
    Db *pDb = &pParse->db->aDb[iDb];
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   167
    int iCur = pParse->nTab;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   168
    int addr;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   169
    assert( v );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   170
    addr = sqlite3VdbeCurrentAddr(v);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   171
    memId = pParse->nMem+1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   172
    pParse->nMem += 2;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   173
    sqlite3OpenTable(pParse, iCur, iDb, pDb->pSchema->pSeqTab, OP_OpenRead);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   174
    sqlite3VdbeAddOp(v, OP_Rewind, iCur, addr+13);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   175
    sqlite3VdbeAddOp(v, OP_Column, iCur, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   176
    sqlite3VdbeOp3(v, OP_String8, 0, 0, pTab->zName, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   177
    sqlite3VdbeAddOp(v, OP_Ne, 0x100, addr+12);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   178
    sqlite3VdbeAddOp(v, OP_Rowid, iCur, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   179
    sqlite3VdbeAddOp(v, OP_MemStore, memId-1, 1);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   180
    sqlite3VdbeAddOp(v, OP_Column, iCur, 1);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   181
    sqlite3VdbeAddOp(v, OP_MemStore, memId, 1);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   182
    sqlite3VdbeAddOp(v, OP_Goto, 0, addr+13);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   183
    sqlite3VdbeAddOp(v, OP_Next, iCur, addr+4);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   184
    sqlite3VdbeAddOp(v, OP_Close, iCur, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   185
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   186
  return memId;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   187
}
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   188
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   189
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   190
** Update the maximum rowid for an autoincrement calculation.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   191
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   192
** This routine should be called when the top of the stack holds a
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   193
** new rowid that is about to be inserted.  If that new rowid is
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   194
** larger than the maximum rowid in the memId memory cell, then the
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   195
** memory cell is updated.  The stack is unchanged.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   196
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   197
static void autoIncStep(Parse *pParse, int memId){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   198
  if( memId>0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   199
    sqlite3VdbeAddOp(pParse->pVdbe, OP_MemMax, memId, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   200
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   201
}
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   202
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   203
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   204
** After doing one or more inserts, the maximum rowid is stored
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   205
** in mem[memId].  Generate code to write this value back into the
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   206
** the sqlite_sequence table.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   207
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   208
static void autoIncEnd(
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   209
  Parse *pParse,     /* The parsing context */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   210
  int iDb,           /* Index of the database holding pTab */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   211
  Table *pTab,       /* Table we are inserting into */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   212
  int memId          /* Memory cell holding the maximum rowid */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   213
){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   214
  if( pTab->autoInc ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   215
    int iCur = pParse->nTab;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   216
    Vdbe *v = pParse->pVdbe;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   217
    Db *pDb = &pParse->db->aDb[iDb];
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   218
    int addr;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   219
    assert( v );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   220
    addr = sqlite3VdbeCurrentAddr(v);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   221
    sqlite3OpenTable(pParse, iCur, iDb, pDb->pSchema->pSeqTab, OP_OpenWrite);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   222
    sqlite3VdbeAddOp(v, OP_MemLoad, memId-1, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   223
    sqlite3VdbeAddOp(v, OP_NotNull, -1, addr+7);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   224
    sqlite3VdbeAddOp(v, OP_Pop, 1, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   225
    sqlite3VdbeAddOp(v, OP_NewRowid, iCur, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   226
    sqlite3VdbeOp3(v, OP_String8, 0, 0, pTab->zName, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   227
    sqlite3VdbeAddOp(v, OP_MemLoad, memId, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   228
    sqlite3VdbeAddOp(v, OP_MakeRecord, 2, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   229
    sqlite3VdbeAddOp(v, OP_Insert, iCur, OPFLAG_APPEND);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   230
    sqlite3VdbeAddOp(v, OP_Close, iCur, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   231
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   232
}
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   233
#else
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   234
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   235
** If SQLITE_OMIT_AUTOINCREMENT is defined, then the three routines
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   236
** above are all no-ops
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   237
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   238
# define autoIncBegin(A,B,C) (0)
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   239
# define autoIncStep(A,B)
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   240
# define autoIncEnd(A,B,C,D)
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   241
#endif /* SQLITE_OMIT_AUTOINCREMENT */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   242
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   243
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   244
/* Forward declaration */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   245
static int xferOptimization(
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   246
  Parse *pParse,        /* Parser context */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   247
  Table *pDest,         /* The table we are inserting into */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   248
  Select *pSelect,      /* A SELECT statement to use as the data source */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   249
  int onError,          /* How to handle constraint errors */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   250
  int iDbDest           /* The database of pDest */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   251
);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   252
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   253
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   254
** This routine is call to handle SQL of the following forms:
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   255
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   256
**    insert into TABLE (IDLIST) values(EXPRLIST)
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   257
**    insert into TABLE (IDLIST) select
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   258
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   259
** The IDLIST following the table name is always optional.  If omitted,
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   260
** then a list of all columns for the table is substituted.  The IDLIST
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   261
** appears in the pColumn parameter.  pColumn is NULL if IDLIST is omitted.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   262
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   263
** The pList parameter holds EXPRLIST in the first form of the INSERT
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   264
** statement above, and pSelect is NULL.  For the second form, pList is
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   265
** NULL and pSelect is a pointer to the select statement used to generate
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   266
** data for the insert.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   267
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   268
** The code generated follows one of four templates.  For a simple
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   269
** select with data coming from a VALUES clause, the code executes
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   270
** once straight down through.  The template looks like this:
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   271
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   272
**         open write cursor to <table> and its indices
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   273
**         puts VALUES clause expressions onto the stack
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   274
**         write the resulting record into <table>
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   275
**         cleanup
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   276
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   277
** The three remaining templates assume the statement is of the form
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   278
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   279
**   INSERT INTO <table> SELECT ...
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   280
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   281
** If the SELECT clause is of the restricted form "SELECT * FROM <table2>" -
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   282
** in other words if the SELECT pulls all columns from a single table
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   283
** and there is no WHERE or LIMIT or GROUP BY or ORDER BY clauses, and
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   284
** if <table2> and <table1> are distinct tables but have identical
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   285
** schemas, including all the same indices, then a special optimization
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   286
** is invoked that copies raw records from <table2> over to <table1>.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   287
** See the xferOptimization() function for the implementation of this
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   288
** template.  This is the second template.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   289
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   290
**         open a write cursor to <table>
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   291
**         open read cursor on <table2>
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   292
**         transfer all records in <table2> over to <table>
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   293
**         close cursors
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   294
**         foreach index on <table>
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   295
**           open a write cursor on the <table> index
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   296
**           open a read cursor on the corresponding <table2> index
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   297
**           transfer all records from the read to the write cursors
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   298
**           close cursors
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   299
**         end foreach
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   300
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   301
** The third template is for when the second template does not apply
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   302
** and the SELECT clause does not read from <table> at any time.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   303
** The generated code follows this template:
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   304
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   305
**         goto B
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   306
**      A: setup for the SELECT
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   307
**         loop over the rows in the SELECT
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   308
**           gosub C
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   309
**         end loop
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   310
**         cleanup after the SELECT
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   311
**         goto D
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   312
**      B: open write cursor to <table> and its indices
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   313
**         goto A
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   314
**      C: insert the select result into <table>
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   315
**         return
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   316
**      D: cleanup
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   317
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   318
** The fourth template is used if the insert statement takes its
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   319
** values from a SELECT but the data is being inserted into a table
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   320
** that is also read as part of the SELECT.  In the third form,
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   321
** we have to use a intermediate table to store the results of
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   322
** the select.  The template is like this:
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   323
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   324
**         goto B
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   325
**      A: setup for the SELECT
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   326
**         loop over the tables in the SELECT
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   327
**           gosub C
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   328
**         end loop
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   329
**         cleanup after the SELECT
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   330
**         goto D
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   331
**      C: insert the select result into the intermediate table
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   332
**         return
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   333
**      B: open a cursor to an intermediate table
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   334
**         goto A
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   335
**      D: open write cursor to <table> and its indices
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   336
**         loop over the intermediate table
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   337
**           transfer values form intermediate table into <table>
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   338
**         end the loop
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   339
**         cleanup
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   340
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   341
void sqlite3Insert(
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   342
  Parse *pParse,        /* Parser context */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   343
  SrcList *pTabList,    /* Name of table into which we are inserting */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   344
  ExprList *pList,      /* List of values to be inserted */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   345
  Select *pSelect,      /* A SELECT statement to use as the data source */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   346
  IdList *pColumn,      /* Column names corresponding to IDLIST. */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   347
  int onError           /* How to handle constraint errors */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   348
){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   349
  Table *pTab;          /* The table to insert into */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   350
  char *zTab;           /* Name of the table into which we are inserting */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   351
  const char *zDb;      /* Name of the database holding this table */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   352
  int i, j, idx;        /* Loop counters */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   353
  Vdbe *v;              /* Generate code into this virtual machine */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   354
  Index *pIdx;          /* For looping over indices of the table */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   355
  int nColumn;          /* Number of columns in the data */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   356
  int base = 0;         /* VDBE Cursor number for pTab */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   357
  int iCont=0,iBreak=0; /* Beginning and end of the loop over srcTab */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   358
  sqlite3 *db;          /* The main database structure */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   359
  int keyColumn = -1;   /* Column that is the INTEGER PRIMARY KEY */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   360
  int endOfLoop;        /* Label for the end of the insertion loop */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   361
  int useTempTable = 0; /* Store SELECT results in intermediate table */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   362
  int srcTab = 0;       /* Data comes from this temporary cursor if >=0 */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   363
  int iSelectLoop = 0;  /* Address of code that implements the SELECT */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   364
  int iCleanup = 0;     /* Address of the cleanup code */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   365
  int iInsertBlock = 0; /* Address of the subroutine used to insert data */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   366
  int iCntMem = 0;      /* Memory cell used for the row counter */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   367
  int newIdx = -1;      /* Cursor for the NEW table */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   368
  Db *pDb;              /* The database containing table being inserted into */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   369
  int counterMem = 0;   /* Memory cell holding AUTOINCREMENT counter */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   370
  int appendFlag = 0;   /* True if the insert is likely to be an append */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   371
  int iDb;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   372
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   373
  int nHidden = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   374
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   375
#ifndef SQLITE_OMIT_TRIGGER
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   376
  int isView;                 /* True if attempting to insert into a view */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   377
  int triggers_exist = 0;     /* True if there are FOR EACH ROW triggers */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   378
#endif
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   379
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   380
  db = pParse->db;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   381
  if( pParse->nErr || db->mallocFailed ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   382
    goto insert_cleanup;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   383
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   384
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   385
  /* Locate the table into which we will be inserting new information.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   386
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   387
  assert( pTabList->nSrc==1 );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   388
  zTab = pTabList->a[0].zName;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   389
  if( zTab==0 ) goto insert_cleanup;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   390
  pTab = sqlite3SrcListLookup(pParse, pTabList);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   391
  if( pTab==0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   392
    goto insert_cleanup;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   393
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   394
  iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   395
  assert( iDb<db->nDb );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   396
  pDb = &db->aDb[iDb];
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   397
  zDb = pDb->zName;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   398
  if( sqlite3AuthCheck(pParse, SQLITE_INSERT, pTab->zName, 0, zDb) ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   399
    goto insert_cleanup;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   400
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   401
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   402
  /* Figure out if we have any triggers and if the table being
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   403
  ** inserted into is a view
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   404
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   405
#ifndef SQLITE_OMIT_TRIGGER
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   406
  triggers_exist = sqlite3TriggersExist(pParse, pTab, TK_INSERT, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   407
  isView = pTab->pSelect!=0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   408
#else
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   409
# define triggers_exist 0
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   410
# define isView 0
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   411
#endif
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   412
#ifdef SQLITE_OMIT_VIEW
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   413
# undef isView
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   414
# define isView 0
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   415
#endif
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   416
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   417
  /* Ensure that:
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   418
  *  (a) the table is not read-only, 
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   419
  *  (b) that if it is a view then ON INSERT triggers exist
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   420
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   421
  if( sqlite3IsReadOnly(pParse, pTab, triggers_exist) ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   422
    goto insert_cleanup;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   423
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   424
  assert( pTab!=0 );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   425
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   426
  /* If pTab is really a view, make sure it has been initialized.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   427
  ** ViewGetColumnNames() is a no-op if pTab is not a view (or virtual 
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   428
  ** module table).
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   429
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   430
  if( sqlite3ViewGetColumnNames(pParse, pTab) ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   431
    goto insert_cleanup;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   432
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   433
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   434
  /* Allocate a VDBE
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   435
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   436
  v = sqlite3GetVdbe(pParse);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   437
  if( v==0 ) goto insert_cleanup;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   438
  if( pParse->nested==0 ) sqlite3VdbeCountChanges(v);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   439
  sqlite3BeginWriteOperation(pParse, pSelect || triggers_exist, iDb);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   440
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   441
  /* if there are row triggers, allocate a temp table for new.* references. */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   442
  if( triggers_exist ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   443
    newIdx = pParse->nTab++;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   444
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   445
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   446
#ifndef SQLITE_OMIT_XFER_OPT
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   447
  /* If the statement is of the form
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   448
  **
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   449
  **       INSERT INTO <table1> SELECT * FROM <table2>;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   450
  **
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   451
  ** Then special optimizations can be applied that make the transfer
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   452
  ** very fast and which reduce fragmentation of indices.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   453
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   454
  if( pColumn==0 && xferOptimization(pParse, pTab, pSelect, onError, iDb) ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   455
    assert( !triggers_exist );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   456
    assert( pList==0 );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   457
    goto insert_cleanup;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   458
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   459
#endif /* SQLITE_OMIT_XFER_OPT */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   460
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   461
  /* If this is an AUTOINCREMENT table, look up the sequence number in the
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   462
  ** sqlite_sequence table and store it in memory cell counterMem.  Also
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   463
  ** remember the rowid of the sqlite_sequence table entry in memory cell
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   464
  ** counterRowid.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   465
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   466
  counterMem = autoIncBegin(pParse, iDb, pTab);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   467
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   468
  /* Figure out how many columns of data are supplied.  If the data
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   469
  ** is coming from a SELECT statement, then this step also generates
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   470
  ** all the code to implement the SELECT statement and invoke a subroutine
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   471
  ** to process each row of the result. (Template 2.) If the SELECT
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   472
  ** statement uses the the table that is being inserted into, then the
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   473
  ** subroutine is also coded here.  That subroutine stores the SELECT
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   474
  ** results in a temporary table. (Template 3.)
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   475
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   476
  if( pSelect ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   477
    /* Data is coming from a SELECT.  Generate code to implement that SELECT
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   478
    */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   479
    int rc, iInitCode;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   480
    iInitCode = sqlite3VdbeAddOp(v, OP_Goto, 0, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   481
    iSelectLoop = sqlite3VdbeCurrentAddr(v);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   482
    iInsertBlock = sqlite3VdbeMakeLabel(v);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   483
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   484
    /* Resolve the expressions in the SELECT statement and execute it. */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   485
    rc = sqlite3Select(pParse, pSelect, SRT_Subroutine, iInsertBlock,0,0,0,0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   486
    if( rc || pParse->nErr || db->mallocFailed ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   487
      goto insert_cleanup;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   488
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   489
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   490
    iCleanup = sqlite3VdbeMakeLabel(v);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   491
    sqlite3VdbeAddOp(v, OP_Goto, 0, iCleanup);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   492
    assert( pSelect->pEList );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   493
    nColumn = pSelect->pEList->nExpr;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   494
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   495
    /* Set useTempTable to TRUE if the result of the SELECT statement
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   496
    ** should be written into a temporary table.  Set to FALSE if each
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   497
    ** row of the SELECT can be written directly into the result table.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   498
    **
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   499
    ** A temp table must be used if the table being updated is also one
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   500
    ** of the tables being read by the SELECT statement.  Also use a 
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   501
    ** temp table in the case of row triggers.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   502
    */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   503
    if( triggers_exist || readsTable(v, iSelectLoop, iDb, pTab) ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   504
      useTempTable = 1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   505
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   506
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   507
    if( useTempTable ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   508
      /* Generate the subroutine that SELECT calls to process each row of
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   509
      ** the result.  Store the result in a temporary table
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   510
      */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   511
      srcTab = pParse->nTab++;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   512
      sqlite3VdbeResolveLabel(v, iInsertBlock);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   513
      sqlite3VdbeAddOp(v, OP_StackDepth, -1, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   514
      sqlite3VdbeAddOp(v, OP_MakeRecord, nColumn, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   515
      sqlite3VdbeAddOp(v, OP_NewRowid, srcTab, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   516
      sqlite3VdbeAddOp(v, OP_Pull, 1, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   517
      sqlite3VdbeAddOp(v, OP_Insert, srcTab, OPFLAG_APPEND);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   518
      sqlite3VdbeAddOp(v, OP_Return, 0, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   519
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   520
      /* The following code runs first because the GOTO at the very top
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   521
      ** of the program jumps to it.  Create the temporary table, then jump
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   522
      ** back up and execute the SELECT code above.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   523
      */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   524
      sqlite3VdbeJumpHere(v, iInitCode);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   525
      sqlite3VdbeAddOp(v, OP_OpenEphemeral, srcTab, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   526
      sqlite3VdbeAddOp(v, OP_SetNumColumns, srcTab, nColumn);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   527
      sqlite3VdbeAddOp(v, OP_Goto, 0, iSelectLoop);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   528
      sqlite3VdbeResolveLabel(v, iCleanup);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   529
    }else{
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   530
      sqlite3VdbeJumpHere(v, iInitCode);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   531
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   532
  }else{
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   533
    /* This is the case if the data for the INSERT is coming from a VALUES
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   534
    ** clause
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   535
    */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   536
    NameContext sNC;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   537
    memset(&sNC, 0, sizeof(sNC));
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   538
    sNC.pParse = pParse;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   539
    srcTab = -1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   540
    assert( useTempTable==0 );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   541
    nColumn = pList ? pList->nExpr : 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   542
    for(i=0; i<nColumn; i++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   543
      if( sqlite3ExprResolveNames(&sNC, pList->a[i].pExpr) ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   544
        goto insert_cleanup;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   545
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   546
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   547
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   548
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   549
  /* Make sure the number of columns in the source data matches the number
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   550
  ** of columns to be inserted into the table.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   551
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   552
  if( IsVirtual(pTab) ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   553
    for(i=0; i<pTab->nCol; i++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   554
      nHidden += (IsHiddenColumn(&pTab->aCol[i]) ? 1 : 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   555
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   556
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   557
  if( pColumn==0 && nColumn && nColumn!=(pTab->nCol-nHidden) ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   558
    sqlite3ErrorMsg(pParse, 
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   559
       "table %S has %d columns but %d values were supplied",
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   560
       pTabList, 0, pTab->nCol, nColumn);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   561
    goto insert_cleanup;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   562
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   563
  if( pColumn!=0 && nColumn!=pColumn->nId ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   564
    sqlite3ErrorMsg(pParse, "%d values for %d columns", nColumn, pColumn->nId);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   565
    goto insert_cleanup;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   566
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   567
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   568
  /* If the INSERT statement included an IDLIST term, then make sure
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   569
  ** all elements of the IDLIST really are columns of the table and 
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   570
  ** remember the column indices.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   571
  **
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   572
  ** If the table has an INTEGER PRIMARY KEY column and that column
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   573
  ** is named in the IDLIST, then record in the keyColumn variable
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   574
  ** the index into IDLIST of the primary key column.  keyColumn is
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   575
  ** the index of the primary key as it appears in IDLIST, not as
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   576
  ** is appears in the original table.  (The index of the primary
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   577
  ** key in the original table is pTab->iPKey.)
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   578
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   579
  if( pColumn ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   580
    for(i=0; i<pColumn->nId; i++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   581
      pColumn->a[i].idx = -1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   582
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   583
    for(i=0; i<pColumn->nId; i++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   584
      for(j=0; j<pTab->nCol; j++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   585
        if( sqlite3StrICmp(pColumn->a[i].zName, pTab->aCol[j].zName)==0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   586
          pColumn->a[i].idx = j;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   587
          if( j==pTab->iPKey ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   588
            keyColumn = i;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   589
          }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   590
          break;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   591
        }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   592
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   593
      if( j>=pTab->nCol ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   594
        if( sqlite3IsRowid(pColumn->a[i].zName) ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   595
          keyColumn = i;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   596
        }else{
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   597
          sqlite3ErrorMsg(pParse, "table %S has no column named %s",
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   598
              pTabList, 0, pColumn->a[i].zName);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   599
          pParse->nErr++;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   600
          goto insert_cleanup;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   601
        }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   602
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   603
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   604
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   605
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   606
  /* If there is no IDLIST term but the table has an integer primary
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   607
  ** key, the set the keyColumn variable to the primary key column index
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   608
  ** in the original table definition.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   609
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   610
  if( pColumn==0 && nColumn>0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   611
    keyColumn = pTab->iPKey;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   612
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   613
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   614
  /* Open the temp table for FOR EACH ROW triggers
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   615
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   616
  if( triggers_exist ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   617
    sqlite3VdbeAddOp(v, OP_OpenPseudo, newIdx, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   618
    sqlite3VdbeAddOp(v, OP_SetNumColumns, newIdx, pTab->nCol);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   619
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   620
    
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   621
  /* Initialize the count of rows to be inserted
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   622
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   623
  if( db->flags & SQLITE_CountRows ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   624
    iCntMem = pParse->nMem++;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   625
    sqlite3VdbeAddOp(v, OP_MemInt, 0, iCntMem);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   626
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   627
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   628
  /* Open tables and indices if there are no row triggers */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   629
  if( !triggers_exist ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   630
    base = pParse->nTab;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   631
    sqlite3OpenTableAndIndices(pParse, pTab, base, OP_OpenWrite);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   632
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   633
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   634
  /* If the data source is a temporary table, then we have to create
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   635
  ** a loop because there might be multiple rows of data.  If the data
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   636
  ** source is a subroutine call from the SELECT statement, then we need
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   637
  ** to launch the SELECT statement processing.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   638
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   639
  if( useTempTable ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   640
    iBreak = sqlite3VdbeMakeLabel(v);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   641
    sqlite3VdbeAddOp(v, OP_Rewind, srcTab, iBreak);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   642
    iCont = sqlite3VdbeCurrentAddr(v);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   643
  }else if( pSelect ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   644
    sqlite3VdbeAddOp(v, OP_Goto, 0, iSelectLoop);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   645
    sqlite3VdbeResolveLabel(v, iInsertBlock);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   646
    sqlite3VdbeAddOp(v, OP_StackDepth, -1, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   647
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   648
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   649
  /* Run the BEFORE and INSTEAD OF triggers, if there are any
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   650
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   651
  endOfLoop = sqlite3VdbeMakeLabel(v);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   652
  if( triggers_exist & TRIGGER_BEFORE ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   653
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   654
    /* build the NEW.* reference row.  Note that if there is an INTEGER
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   655
    ** PRIMARY KEY into which a NULL is being inserted, that NULL will be
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   656
    ** translated into a unique ID for the row.  But on a BEFORE trigger,
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   657
    ** we do not know what the unique ID will be (because the insert has
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   658
    ** not happened yet) so we substitute a rowid of -1
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   659
    */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   660
    if( keyColumn<0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   661
      sqlite3VdbeAddOp(v, OP_Integer, -1, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   662
    }else if( useTempTable ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   663
      sqlite3VdbeAddOp(v, OP_Column, srcTab, keyColumn);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   664
    }else{
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   665
      assert( pSelect==0 );  /* Otherwise useTempTable is true */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   666
      sqlite3ExprCode(pParse, pList->a[keyColumn].pExpr);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   667
      sqlite3VdbeAddOp(v, OP_NotNull, -1, sqlite3VdbeCurrentAddr(v)+3);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   668
      sqlite3VdbeAddOp(v, OP_Pop, 1, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   669
      sqlite3VdbeAddOp(v, OP_Integer, -1, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   670
      sqlite3VdbeAddOp(v, OP_MustBeInt, 0, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   671
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   672
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   673
    /* Cannot have triggers on a virtual table. If it were possible,
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   674
    ** this block would have to account for hidden column.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   675
    */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   676
    assert(!IsVirtual(pTab));
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   677
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   678
    /* Create the new column data
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   679
    */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   680
    for(i=0; i<pTab->nCol; i++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   681
      if( pColumn==0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   682
        j = i;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   683
      }else{
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   684
        for(j=0; j<pColumn->nId; j++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   685
          if( pColumn->a[j].idx==i ) break;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   686
        }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   687
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   688
      if( pColumn && j>=pColumn->nId ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   689
        sqlite3ExprCode(pParse, pTab->aCol[i].pDflt);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   690
      }else if( useTempTable ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   691
        sqlite3VdbeAddOp(v, OP_Column, srcTab, j); 
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   692
      }else{
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   693
        assert( pSelect==0 ); /* Otherwise useTempTable is true */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   694
        sqlite3ExprCodeAndCache(pParse, pList->a[j].pExpr);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   695
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   696
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   697
    sqlite3VdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   698
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   699
    /* If this is an INSERT on a view with an INSTEAD OF INSERT trigger,
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   700
    ** do not attempt any conversions before assembling the record.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   701
    ** If this is a real table, attempt conversions as required by the
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   702
    ** table column affinities.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   703
    */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   704
    if( !isView ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   705
      sqlite3TableAffinityStr(v, pTab);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   706
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   707
    sqlite3VdbeAddOp(v, OP_Insert, newIdx, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   708
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   709
    /* Fire BEFORE or INSTEAD OF triggers */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   710
    if( sqlite3CodeRowTrigger(pParse, TK_INSERT, 0, TRIGGER_BEFORE, pTab, 
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   711
        newIdx, -1, onError, endOfLoop) ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   712
      goto insert_cleanup;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   713
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   714
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   715
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   716
  /* If any triggers exists, the opening of tables and indices is deferred
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   717
  ** until now.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   718
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   719
  if( triggers_exist && !isView ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   720
    base = pParse->nTab;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   721
    sqlite3OpenTableAndIndices(pParse, pTab, base, OP_OpenWrite);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   722
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   723
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   724
  /* Push the record number for the new entry onto the stack.  The
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   725
  ** record number is a randomly generate integer created by NewRowid
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   726
  ** except when the table has an INTEGER PRIMARY KEY column, in which
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   727
  ** case the record number is the same as that column. 
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   728
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   729
  if( !isView ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   730
    if( IsVirtual(pTab) ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   731
      /* The row that the VUpdate opcode will delete:  none */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   732
      sqlite3VdbeAddOp(v, OP_Null, 0, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   733
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   734
    if( keyColumn>=0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   735
      if( useTempTable ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   736
        sqlite3VdbeAddOp(v, OP_Column, srcTab, keyColumn);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   737
      }else if( pSelect ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   738
        sqlite3VdbeAddOp(v, OP_Dup, nColumn - keyColumn - 1, 1);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   739
      }else{
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   740
        VdbeOp *pOp;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   741
        sqlite3ExprCode(pParse, pList->a[keyColumn].pExpr);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   742
        pOp = sqlite3VdbeGetOp(v, sqlite3VdbeCurrentAddr(v) - 1);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   743
        if( pOp && pOp->opcode==OP_Null ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   744
          appendFlag = 1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   745
          pOp->opcode = OP_NewRowid;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   746
          pOp->p1 = base;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   747
          pOp->p2 = counterMem;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   748
        }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   749
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   750
      /* If the PRIMARY KEY expression is NULL, then use OP_NewRowid
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   751
      ** to generate a unique primary key value.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   752
      */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   753
      if( !appendFlag ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   754
        sqlite3VdbeAddOp(v, OP_NotNull, -1, sqlite3VdbeCurrentAddr(v)+3);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   755
        sqlite3VdbeAddOp(v, OP_Pop, 1, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   756
        sqlite3VdbeAddOp(v, OP_NewRowid, base, counterMem);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   757
        sqlite3VdbeAddOp(v, OP_MustBeInt, 0, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   758
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   759
    }else if( IsVirtual(pTab) ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   760
      sqlite3VdbeAddOp(v, OP_Null, 0, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   761
    }else{
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   762
      sqlite3VdbeAddOp(v, OP_NewRowid, base, counterMem);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   763
      appendFlag = 1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   764
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   765
    autoIncStep(pParse, counterMem);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   766
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   767
    /* Push onto the stack, data for all columns of the new entry, beginning
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   768
    ** with the first column.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   769
    */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   770
    nHidden = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   771
    for(i=0; i<pTab->nCol; i++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   772
      if( i==pTab->iPKey ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   773
        /* The value of the INTEGER PRIMARY KEY column is always a NULL.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   774
        ** Whenever this column is read, the record number will be substituted
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   775
        ** in its place.  So will fill this column with a NULL to avoid
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   776
        ** taking up data space with information that will never be used. */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   777
        sqlite3VdbeAddOp(v, OP_Null, 0, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   778
        continue;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   779
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   780
      if( pColumn==0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   781
        if( IsHiddenColumn(&pTab->aCol[i]) ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   782
          assert( IsVirtual(pTab) );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   783
          j = -1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   784
          nHidden++;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   785
        }else{
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   786
          j = i - nHidden;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   787
        }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   788
      }else{
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   789
        for(j=0; j<pColumn->nId; j++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   790
          if( pColumn->a[j].idx==i ) break;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   791
        }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   792
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   793
      if( j<0 || nColumn==0 || (pColumn && j>=pColumn->nId) ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   794
        sqlite3ExprCode(pParse, pTab->aCol[i].pDflt);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   795
      }else if( useTempTable ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   796
        sqlite3VdbeAddOp(v, OP_Column, srcTab, j); 
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   797
      }else if( pSelect ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   798
        sqlite3VdbeAddOp(v, OP_Dup, i+nColumn-j+IsVirtual(pTab), 1);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   799
      }else{
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   800
        sqlite3ExprCode(pParse, pList->a[j].pExpr);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   801
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   802
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   803
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   804
    /* Generate code to check constraints and generate index keys and
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   805
    ** do the insertion.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   806
    */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   807
#ifndef SQLITE_OMIT_VIRTUALTABLE
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   808
    if( IsVirtual(pTab) ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   809
      pParse->pVirtualLock = pTab;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   810
      sqlite3VdbeOp3(v, OP_VUpdate, 1, pTab->nCol+2,
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   811
                     (const char*)pTab->pVtab, P3_VTAB);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   812
    }else
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   813
#endif
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   814
    {
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   815
      sqlite3GenerateConstraintChecks(pParse, pTab, base, 0, keyColumn>=0,
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   816
                                     0, onError, endOfLoop);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   817
      sqlite3CompleteInsertion(pParse, pTab, base, 0,0,0,
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   818
                            (triggers_exist & TRIGGER_AFTER)!=0 ? newIdx : -1,
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   819
                            appendFlag);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   820
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   821
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   822
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   823
  /* Update the count of rows that are inserted
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   824
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   825
  if( (db->flags & SQLITE_CountRows)!=0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   826
    sqlite3VdbeAddOp(v, OP_MemIncr, 1, iCntMem);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   827
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   828
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   829
  if( triggers_exist ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   830
    /* Close all tables opened */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   831
    if( !isView ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   832
      sqlite3VdbeAddOp(v, OP_Close, base, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   833
      for(idx=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, idx++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   834
        sqlite3VdbeAddOp(v, OP_Close, idx+base, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   835
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   836
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   837
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   838
    /* Code AFTER triggers */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   839
    if( sqlite3CodeRowTrigger(pParse, TK_INSERT, 0, TRIGGER_AFTER, pTab,
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   840
          newIdx, -1, onError, endOfLoop) ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   841
      goto insert_cleanup;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   842
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   843
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   844
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   845
  /* The bottom of the loop, if the data source is a SELECT statement
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   846
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   847
  sqlite3VdbeResolveLabel(v, endOfLoop);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   848
  if( useTempTable ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   849
    sqlite3VdbeAddOp(v, OP_Next, srcTab, iCont);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   850
    sqlite3VdbeResolveLabel(v, iBreak);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   851
    sqlite3VdbeAddOp(v, OP_Close, srcTab, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   852
  }else if( pSelect ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   853
    sqlite3VdbeAddOp(v, OP_Pop, nColumn, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   854
    sqlite3VdbeAddOp(v, OP_Return, 0, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   855
    sqlite3VdbeResolveLabel(v, iCleanup);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   856
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   857
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   858
  if( !triggers_exist && !IsVirtual(pTab) ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   859
    /* Close all tables opened */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   860
    sqlite3VdbeAddOp(v, OP_Close, base, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   861
    for(idx=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, idx++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   862
      sqlite3VdbeAddOp(v, OP_Close, idx+base, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   863
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   864
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   865
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   866
  /* Update the sqlite_sequence table by storing the content of the
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   867
  ** counter value in memory counterMem back into the sqlite_sequence
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   868
  ** table.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   869
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   870
  autoIncEnd(pParse, iDb, pTab, counterMem);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   871
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   872
  /*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   873
  ** Return the number of rows inserted. If this routine is 
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   874
  ** generating code because of a call to sqlite3NestedParse(), do not
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   875
  ** invoke the callback function.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   876
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   877
  if( db->flags & SQLITE_CountRows && pParse->nested==0 && !pParse->trigStack ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   878
    sqlite3VdbeAddOp(v, OP_MemLoad, iCntMem, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   879
    sqlite3VdbeAddOp(v, OP_Callback, 1, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   880
    sqlite3VdbeSetNumCols(v, 1);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   881
    sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows inserted", P3_STATIC);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   882
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   883
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   884
insert_cleanup:
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   885
  sqlite3SrcListDelete(pTabList);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   886
  sqlite3ExprListDelete(pList);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   887
  sqlite3SelectDelete(pSelect);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   888
  sqlite3IdListDelete(pColumn);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   889
}
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   890
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   891
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   892
** Generate code to do a constraint check prior to an INSERT or an UPDATE.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   893
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   894
** When this routine is called, the stack contains (from bottom to top)
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   895
** the following values:
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   896
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   897
**    1.  The rowid of the row to be updated before the update.  This
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   898
**        value is omitted unless we are doing an UPDATE that involves a
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   899
**        change to the record number.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   900
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   901
**    2.  The rowid of the row after the update.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   902
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   903
**    3.  The data in the first column of the entry after the update.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   904
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   905
**    i.  Data from middle columns...
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   906
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   907
**    N.  The data in the last column of the entry after the update.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   908
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   909
** The old rowid shown as entry (1) above is omitted unless both isUpdate
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   910
** and rowidChng are 1.  isUpdate is true for UPDATEs and false for
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   911
** INSERTs and rowidChng is true if the record number is being changed.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   912
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   913
** The code generated by this routine pushes additional entries onto
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   914
** the stack which are the keys for new index entries for the new record.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   915
** The order of index keys is the same as the order of the indices on
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   916
** the pTable->pIndex list.  A key is only created for index i if 
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   917
** aIdxUsed!=0 and aIdxUsed[i]!=0.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   918
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   919
** This routine also generates code to check constraints.  NOT NULL,
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   920
** CHECK, and UNIQUE constraints are all checked.  If a constraint fails,
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   921
** then the appropriate action is performed.  There are five possible
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   922
** actions: ROLLBACK, ABORT, FAIL, REPLACE, and IGNORE.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   923
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   924
**  Constraint type  Action       What Happens
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   925
**  ---------------  ----------   ----------------------------------------
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   926
**  any              ROLLBACK     The current transaction is rolled back and
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   927
**                                sqlite3_exec() returns immediately with a
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   928
**                                return code of SQLITE_CONSTRAINT.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   929
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   930
**  any              ABORT        Back out changes from the current command
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   931
**                                only (do not do a complete rollback) then
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   932
**                                cause sqlite3_exec() to return immediately
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   933
**                                with SQLITE_CONSTRAINT.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   934
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   935
**  any              FAIL         Sqlite_exec() returns immediately with a
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   936
**                                return code of SQLITE_CONSTRAINT.  The
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   937
**                                transaction is not rolled back and any
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   938
**                                prior changes are retained.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   939
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   940
**  any              IGNORE       The record number and data is popped from
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   941
**                                the stack and there is an immediate jump
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   942
**                                to label ignoreDest.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   943
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   944
**  NOT NULL         REPLACE      The NULL value is replace by the default
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   945
**                                value for that column.  If the default value
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   946
**                                is NULL, the action is the same as ABORT.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   947
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   948
**  UNIQUE           REPLACE      The other row that conflicts with the row
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   949
**                                being inserted is removed.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   950
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   951
**  CHECK            REPLACE      Illegal.  The results in an exception.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   952
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   953
** Which action to take is determined by the overrideError parameter.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   954
** Or if overrideError==OE_Default, then the pParse->onError parameter
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   955
** is used.  Or if pParse->onError==OE_Default then the onError value
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   956
** for the constraint is used.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   957
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   958
** The calling routine must open a read/write cursor for pTab with
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   959
** cursor number "base".  All indices of pTab must also have open
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   960
** read/write cursors with cursor number base+i for the i-th cursor.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   961
** Except, if there is no possibility of a REPLACE action then
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   962
** cursors do not need to be open for indices where aIdxUsed[i]==0.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   963
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   964
** If the isUpdate flag is true, it means that the "base" cursor is
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   965
** initially pointing to an entry that is being updated.  The isUpdate
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   966
** flag causes extra code to be generated so that the "base" cursor
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   967
** is still pointing at the same entry after the routine returns.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   968
** Without the isUpdate flag, the "base" cursor might be moved.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   969
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   970
void sqlite3GenerateConstraintChecks(
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   971
  Parse *pParse,      /* The parser context */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   972
  Table *pTab,        /* the table into which we are inserting */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   973
  int base,           /* Index of a read/write cursor pointing at pTab */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   974
  char *aIdxUsed,     /* Which indices are used.  NULL means all are used */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   975
  int rowidChng,      /* True if the record number will change */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   976
  int isUpdate,       /* True for UPDATE, False for INSERT */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   977
  int overrideError,  /* Override onError to this if not OE_Default */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   978
  int ignoreDest      /* Jump to this label on an OE_Ignore resolution */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   979
){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   980
  int i;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   981
  Vdbe *v;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   982
  int nCol;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   983
  int onError;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   984
  int addr;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   985
  int extra;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   986
  int iCur;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   987
  Index *pIdx;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   988
  int seenReplace = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   989
  int jumpInst1=0, jumpInst2;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   990
  int hasTwoRowids = (isUpdate && rowidChng);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   991
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   992
  v = sqlite3GetVdbe(pParse);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   993
  assert( v!=0 );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   994
  assert( pTab->pSelect==0 );  /* This table is not a VIEW */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   995
  nCol = pTab->nCol;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   996
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   997
  /* Test all NOT NULL constraints.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   998
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
   999
  for(i=0; i<nCol; i++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1000
    if( i==pTab->iPKey ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1001
      continue;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1002
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1003
    onError = pTab->aCol[i].notNull;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1004
    if( onError==OE_None ) continue;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1005
    if( overrideError!=OE_Default ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1006
      onError = overrideError;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1007
    }else if( onError==OE_Default ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1008
      onError = OE_Abort;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1009
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1010
    if( onError==OE_Replace && pTab->aCol[i].pDflt==0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1011
      onError = OE_Abort;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1012
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1013
    sqlite3VdbeAddOp(v, OP_Dup, nCol-1-i, 1);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1014
    addr = sqlite3VdbeAddOp(v, OP_NotNull, 1, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1015
    assert( onError==OE_Rollback || onError==OE_Abort || onError==OE_Fail
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1016
        || onError==OE_Ignore || onError==OE_Replace );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1017
    switch( onError ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1018
      case OE_Rollback:
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1019
      case OE_Abort:
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1020
      case OE_Fail: {
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1021
        char *zMsg = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1022
        sqlite3VdbeAddOp(v, OP_Halt, SQLITE_CONSTRAINT, onError);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1023
        sqlite3SetString(&zMsg, pTab->zName, ".", pTab->aCol[i].zName,
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1024
                        " may not be NULL", (char*)0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1025
        sqlite3VdbeChangeP3(v, -1, zMsg, P3_DYNAMIC);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1026
        break;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1027
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1028
      case OE_Ignore: {
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1029
        sqlite3VdbeAddOp(v, OP_Pop, nCol+1+hasTwoRowids, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1030
        sqlite3VdbeAddOp(v, OP_Goto, 0, ignoreDest);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1031
        break;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1032
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1033
      case OE_Replace: {
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1034
        sqlite3ExprCode(pParse, pTab->aCol[i].pDflt);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1035
        sqlite3VdbeAddOp(v, OP_Push, nCol-i, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1036
        break;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1037
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1038
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1039
    sqlite3VdbeJumpHere(v, addr);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1040
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1041
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1042
  /* Test all CHECK constraints
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1043
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1044
#ifndef SQLITE_OMIT_CHECK
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1045
  if( pTab->pCheck && (pParse->db->flags & SQLITE_IgnoreChecks)==0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1046
    int allOk = sqlite3VdbeMakeLabel(v);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1047
    assert( pParse->ckOffset==0 );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1048
    pParse->ckOffset = nCol;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1049
    sqlite3ExprIfTrue(pParse, pTab->pCheck, allOk, 1);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1050
    assert( pParse->ckOffset==nCol );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1051
    pParse->ckOffset = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1052
    onError = overrideError!=OE_Default ? overrideError : OE_Abort;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1053
    if( onError==OE_Ignore ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1054
      sqlite3VdbeAddOp(v, OP_Pop, nCol+1+hasTwoRowids, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1055
      sqlite3VdbeAddOp(v, OP_Goto, 0, ignoreDest);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1056
    }else{
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1057
      sqlite3VdbeAddOp(v, OP_Halt, SQLITE_CONSTRAINT, onError);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1058
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1059
    sqlite3VdbeResolveLabel(v, allOk);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1060
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1061
#endif /* !defined(SQLITE_OMIT_CHECK) */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1062
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1063
  /* If we have an INTEGER PRIMARY KEY, make sure the primary key
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1064
  ** of the new record does not previously exist.  Except, if this
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1065
  ** is an UPDATE and the primary key is not changing, that is OK.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1066
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1067
  if( rowidChng ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1068
    onError = pTab->keyConf;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1069
    if( overrideError!=OE_Default ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1070
      onError = overrideError;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1071
    }else if( onError==OE_Default ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1072
      onError = OE_Abort;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1073
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1074
    
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1075
    if( isUpdate ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1076
      sqlite3VdbeAddOp(v, OP_Dup, nCol+1, 1);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1077
      sqlite3VdbeAddOp(v, OP_Dup, nCol+1, 1);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1078
      jumpInst1 = sqlite3VdbeAddOp(v, OP_Eq, 0, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1079
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1080
    sqlite3VdbeAddOp(v, OP_Dup, nCol, 1);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1081
    jumpInst2 = sqlite3VdbeAddOp(v, OP_NotExists, base, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1082
    switch( onError ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1083
      default: {
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1084
        onError = OE_Abort;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1085
        /* Fall thru into the next case */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1086
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1087
      case OE_Rollback:
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1088
      case OE_Abort:
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1089
      case OE_Fail: {
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1090
        sqlite3VdbeOp3(v, OP_Halt, SQLITE_CONSTRAINT, onError,
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1091
                         "PRIMARY KEY must be unique", P3_STATIC);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1092
        break;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1093
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1094
      case OE_Replace: {
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1095
        sqlite3GenerateRowIndexDelete(v, pTab, base, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1096
        if( isUpdate ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1097
          sqlite3VdbeAddOp(v, OP_Dup, nCol+hasTwoRowids, 1);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1098
          sqlite3VdbeAddOp(v, OP_MoveGe, base, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1099
        }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1100
        seenReplace = 1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1101
        break;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1102
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1103
      case OE_Ignore: {
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1104
        assert( seenReplace==0 );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1105
        sqlite3VdbeAddOp(v, OP_Pop, nCol+1+hasTwoRowids, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1106
        sqlite3VdbeAddOp(v, OP_Goto, 0, ignoreDest);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1107
        break;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1108
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1109
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1110
    sqlite3VdbeJumpHere(v, jumpInst2);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1111
    if( isUpdate ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1112
      sqlite3VdbeJumpHere(v, jumpInst1);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1113
      sqlite3VdbeAddOp(v, OP_Dup, nCol+1, 1);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1114
      sqlite3VdbeAddOp(v, OP_MoveGe, base, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1115
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1116
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1117
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1118
  /* Test all UNIQUE constraints by creating entries for each UNIQUE
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1119
  ** index and making sure that duplicate entries do not already exist.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1120
  ** Add the new records to the indices as we go.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1121
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1122
  extra = -1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1123
  for(iCur=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, iCur++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1124
    if( aIdxUsed && aIdxUsed[iCur]==0 ) continue;  /* Skip unused indices */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1125
    extra++;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1126
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1127
    /* Create a key for accessing the index entry */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1128
    sqlite3VdbeAddOp(v, OP_Dup, nCol+extra, 1);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1129
    for(i=0; i<pIdx->nColumn; i++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1130
      int idx = pIdx->aiColumn[i];
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1131
      if( idx==pTab->iPKey ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1132
        sqlite3VdbeAddOp(v, OP_Dup, i+extra+nCol+1, 1);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1133
      }else{
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1134
        sqlite3VdbeAddOp(v, OP_Dup, i+extra+nCol-idx, 1);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1135
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1136
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1137
    jumpInst1 = sqlite3VdbeAddOp(v, OP_MakeIdxRec, pIdx->nColumn, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1138
    sqlite3IndexAffinityStr(v, pIdx);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1139
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1140
    /* Find out what action to take in case there is an indexing conflict */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1141
    onError = pIdx->onError;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1142
    if( onError==OE_None ) continue;  /* pIdx is not a UNIQUE index */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1143
    if( overrideError!=OE_Default ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1144
      onError = overrideError;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1145
    }else if( onError==OE_Default ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1146
      onError = OE_Abort;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1147
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1148
    if( seenReplace ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1149
      if( onError==OE_Ignore ) onError = OE_Replace;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1150
      else if( onError==OE_Fail ) onError = OE_Abort;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1151
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1152
    
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1153
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1154
    /* Check to see if the new index entry will be unique */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1155
    sqlite3VdbeAddOp(v, OP_Dup, extra+nCol+1+hasTwoRowids, 1);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1156
    jumpInst2 = sqlite3VdbeAddOp(v, OP_IsUnique, base+iCur+1, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1157
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1158
    /* Generate code that executes if the new index entry is not unique */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1159
    assert( onError==OE_Rollback || onError==OE_Abort || onError==OE_Fail
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1160
        || onError==OE_Ignore || onError==OE_Replace );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1161
    switch( onError ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1162
      case OE_Rollback:
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1163
      case OE_Abort:
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1164
      case OE_Fail: {
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1165
        int j, n1, n2;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1166
        char zErrMsg[200];
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1167
        sqlite3_snprintf(sizeof(zErrMsg), zErrMsg,
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1168
                         pIdx->nColumn>1 ? "columns " : "column ");
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1169
        n1 = strlen(zErrMsg);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1170
        for(j=0; j<pIdx->nColumn && n1<sizeof(zErrMsg)-30; j++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1171
          char *zCol = pTab->aCol[pIdx->aiColumn[j]].zName;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1172
          n2 = strlen(zCol);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1173
          if( j>0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1174
            sqlite3_snprintf(sizeof(zErrMsg)-n1, &zErrMsg[n1], ", ");
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1175
            n1 += 2;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1176
          }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1177
          if( n1+n2>sizeof(zErrMsg)-30 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1178
            sqlite3_snprintf(sizeof(zErrMsg)-n1, &zErrMsg[n1], "...");
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1179
            n1 += 3;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1180
            break;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1181
          }else{
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1182
            sqlite3_snprintf(sizeof(zErrMsg)-n1, &zErrMsg[n1], "%s", zCol);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1183
            n1 += n2;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1184
          }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1185
        }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1186
        sqlite3_snprintf(sizeof(zErrMsg)-n1, &zErrMsg[n1], 
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1187
            pIdx->nColumn>1 ? " are not unique" : " is not unique");
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1188
        sqlite3VdbeOp3(v, OP_Halt, SQLITE_CONSTRAINT, onError, zErrMsg, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1189
        break;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1190
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1191
      case OE_Ignore: {
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1192
        assert( seenReplace==0 );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1193
        sqlite3VdbeAddOp(v, OP_Pop, nCol+extra+3+hasTwoRowids, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1194
        sqlite3VdbeAddOp(v, OP_Goto, 0, ignoreDest);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1195
        break;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1196
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1197
      case OE_Replace: {
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1198
        sqlite3GenerateRowDelete(pParse->db, v, pTab, base, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1199
        if( isUpdate ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1200
          sqlite3VdbeAddOp(v, OP_Dup, nCol+extra+1+hasTwoRowids, 1);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1201
          sqlite3VdbeAddOp(v, OP_MoveGe, base, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1202
        }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1203
        seenReplace = 1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1204
        break;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1205
      }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1206
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1207
#if NULL_DISTINCT_FOR_UNIQUE
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1208
    sqlite3VdbeJumpHere(v, jumpInst1);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1209
#endif
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1210
    sqlite3VdbeJumpHere(v, jumpInst2);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1211
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1212
}
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1213
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1214
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1215
** This routine generates code to finish the INSERT or UPDATE operation
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1216
** that was started by a prior call to sqlite3GenerateConstraintChecks.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1217
** The stack must contain keys for all active indices followed by data
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1218
** and the rowid for the new entry.  This routine creates the new
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1219
** entries in all indices and in the main table.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1220
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1221
** The arguments to this routine should be the same as the first six
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1222
** arguments to sqlite3GenerateConstraintChecks.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1223
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1224
void sqlite3CompleteInsertion(
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1225
  Parse *pParse,      /* The parser context */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1226
  Table *pTab,        /* the table into which we are inserting */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1227
  int base,           /* Index of a read/write cursor pointing at pTab */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1228
  char *aIdxUsed,     /* Which indices are used.  NULL means all are used */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1229
  int rowidChng,      /* True if the record number will change */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1230
  int isUpdate,       /* True for UPDATE, False for INSERT */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1231
  int newIdx,         /* Index of NEW table for triggers.  -1 if none */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1232
  int appendBias      /* True if this is likely to be an append */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1233
){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1234
  int i;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1235
  Vdbe *v;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1236
  int nIdx;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1237
  Index *pIdx;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1238
  int pik_flags;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1239
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1240
  v = sqlite3GetVdbe(pParse);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1241
  assert( v!=0 );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1242
  assert( pTab->pSelect==0 );  /* This table is not a VIEW */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1243
  for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){}
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1244
  for(i=nIdx-1; i>=0; i--){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1245
    if( aIdxUsed && aIdxUsed[i]==0 ) continue;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1246
    sqlite3VdbeAddOp(v, OP_IdxInsert, base+i+1, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1247
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1248
  sqlite3VdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1249
  sqlite3TableAffinityStr(v, pTab);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1250
#ifndef SQLITE_OMIT_TRIGGER
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1251
  if( newIdx>=0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1252
    sqlite3VdbeAddOp(v, OP_Dup, 1, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1253
    sqlite3VdbeAddOp(v, OP_Dup, 1, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1254
    sqlite3VdbeAddOp(v, OP_Insert, newIdx, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1255
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1256
#endif
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1257
  if( pParse->nested ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1258
    pik_flags = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1259
  }else{
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1260
    pik_flags = OPFLAG_NCHANGE;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1261
    pik_flags |= (isUpdate?OPFLAG_ISUPDATE:OPFLAG_LASTROWID);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1262
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1263
  if( appendBias ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1264
    pik_flags |= OPFLAG_APPEND;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1265
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1266
  sqlite3VdbeAddOp(v, OP_Insert, base, pik_flags);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1267
  if( !pParse->nested ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1268
    sqlite3VdbeChangeP3(v, -1, pTab->zName, P3_STATIC);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1269
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1270
  
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1271
  if( isUpdate && rowidChng ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1272
    sqlite3VdbeAddOp(v, OP_Pop, 1, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1273
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1274
}
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1275
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1276
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1277
** Generate code that will open cursors for a table and for all
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1278
** indices of that table.  The "base" parameter is the cursor number used
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1279
** for the table.  Indices are opened on subsequent cursors.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1280
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1281
void sqlite3OpenTableAndIndices(
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1282
  Parse *pParse,   /* Parsing context */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1283
  Table *pTab,     /* Table to be opened */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1284
  int base,        /* Cursor number assigned to the table */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1285
  int op           /* OP_OpenRead or OP_OpenWrite */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1286
){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1287
  int i;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1288
  int iDb;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1289
  Index *pIdx;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1290
  Vdbe *v;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1291
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1292
  if( IsVirtual(pTab) ) return;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1293
  iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1294
  v = sqlite3GetVdbe(pParse);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1295
  assert( v!=0 );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1296
  sqlite3OpenTable(pParse, base, iDb, pTab, op);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1297
  for(i=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1298
    KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIdx);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1299
    assert( pIdx->pSchema==pTab->pSchema );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1300
    sqlite3VdbeAddOp(v, OP_Integer, iDb, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1301
    VdbeComment((v, "# %s", pIdx->zName));
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1302
    sqlite3VdbeOp3(v, op, i+base, pIdx->tnum, (char*)pKey, P3_KEYINFO_HANDOFF);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1303
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1304
  if( pParse->nTab<=base+i ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1305
    pParse->nTab = base+i;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1306
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1307
}
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1308
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1309
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1310
#ifdef SQLITE_TEST
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1311
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1312
** The following global variable is incremented whenever the
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1313
** transfer optimization is used.  This is used for testing
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1314
** purposes only - to make sure the transfer optimization really
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1315
** is happening when it is suppose to.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1316
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1317
int sqlite3_xferopt_count;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1318
#endif /* SQLITE_TEST */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1319
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1320
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1321
#ifndef SQLITE_OMIT_XFER_OPT
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1322
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1323
** Check to collation names to see if they are compatible.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1324
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1325
static int xferCompatibleCollation(const char *z1, const char *z2){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1326
  if( z1==0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1327
    return z2==0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1328
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1329
  if( z2==0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1330
    return 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1331
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1332
  return sqlite3StrICmp(z1, z2)==0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1333
}
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1334
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1335
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1336
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1337
** Check to see if index pSrc is compatible as a source of data
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1338
** for index pDest in an insert transfer optimization.  The rules
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1339
** for a compatible index:
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1340
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1341
**    *   The index is over the same set of columns
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1342
**    *   The same DESC and ASC markings occurs on all columns
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1343
**    *   The same onError processing (OE_Abort, OE_Ignore, etc)
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1344
**    *   The same collating sequence on each column
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1345
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1346
static int xferCompatibleIndex(Index *pDest, Index *pSrc){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1347
  int i;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1348
  assert( pDest && pSrc );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1349
  assert( pDest->pTable!=pSrc->pTable );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1350
  if( pDest->nColumn!=pSrc->nColumn ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1351
    return 0;   /* Different number of columns */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1352
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1353
  if( pDest->onError!=pSrc->onError ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1354
    return 0;   /* Different conflict resolution strategies */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1355
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1356
  for(i=0; i<pSrc->nColumn; i++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1357
    if( pSrc->aiColumn[i]!=pDest->aiColumn[i] ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1358
      return 0;   /* Different columns indexed */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1359
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1360
    if( pSrc->aSortOrder[i]!=pDest->aSortOrder[i] ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1361
      return 0;   /* Different sort orders */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1362
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1363
    if( pSrc->azColl[i]!=pDest->azColl[i] ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1364
      return 0;   /* Different sort orders */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1365
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1366
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1367
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1368
  /* If no test above fails then the indices must be compatible */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1369
  return 1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1370
}
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1371
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1372
/*
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1373
** Attempt the transfer optimization on INSERTs of the form
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1374
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1375
**     INSERT INTO tab1 SELECT * FROM tab2;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1376
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1377
** This optimization is only attempted if
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1378
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1379
**    (1)  tab1 and tab2 have identical schemas including all the
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1380
**         same indices and constraints
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1381
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1382
**    (2)  tab1 and tab2 are different tables
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1383
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1384
**    (3)  There must be no triggers on tab1
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1385
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1386
**    (4)  The result set of the SELECT statement is "*"
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1387
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1388
**    (5)  The SELECT statement has no WHERE, HAVING, ORDER BY, GROUP BY,
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1389
**         or LIMIT clause.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1390
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1391
**    (6)  The SELECT statement is a simple (not a compound) select that
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1392
**         contains only tab2 in its FROM clause
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1393
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1394
** This method for implementing the INSERT transfers raw records from
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1395
** tab2 over to tab1.  The columns are not decoded.  Raw records from
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1396
** the indices of tab2 are transfered to tab1 as well.  In so doing,
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1397
** the resulting tab1 has much less fragmentation.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1398
**
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1399
** This routine returns TRUE if the optimization is attempted.  If any
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1400
** of the conditions above fail so that the optimization should not
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1401
** be attempted, then this routine returns FALSE.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1402
*/
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1403
static int xferOptimization(
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1404
  Parse *pParse,        /* Parser context */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1405
  Table *pDest,         /* The table we are inserting into */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1406
  Select *pSelect,      /* A SELECT statement to use as the data source */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1407
  int onError,          /* How to handle constraint errors */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1408
  int iDbDest           /* The database of pDest */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1409
){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1410
  ExprList *pEList;                /* The result set of the SELECT */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1411
  Table *pSrc;                     /* The table in the FROM clause of SELECT */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1412
  Index *pSrcIdx, *pDestIdx;       /* Source and destination indices */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1413
  SrcList::SrcList_item *pItem;      /* An element of pSelect->pSrc */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1414
  int i;                           /* Loop counter */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1415
  int iDbSrc;                      /* The database of pSrc */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1416
  int iSrc, iDest;                 /* Cursors from source and destination */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1417
  int addr1, addr2;                /* Loop addresses */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1418
  int emptyDestTest;               /* Address of test for empty pDest */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1419
  int emptySrcTest;                /* Address of test for empty pSrc */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1420
  Vdbe *v;                         /* The VDBE we are building */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1421
  KeyInfo *pKey;                   /* Key information for an index */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1422
  int counterMem;                  /* Memory register used by AUTOINC */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1423
  int destHasUniqueIdx = 0;        /* True if pDest has a UNIQUE index */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1424
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1425
  if( pSelect==0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1426
    return 0;   /* Must be of the form  INSERT INTO ... SELECT ... */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1427
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1428
  if( pDest->pTrigger ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1429
    return 0;   /* tab1 must not have triggers */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1430
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1431
#ifndef SQLITE_OMIT_VIRTUALTABLE
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1432
  if( pDest->isVirtual ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1433
    return 0;   /* tab1 must not be a virtual table */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1434
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1435
#endif
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1436
  if( onError==OE_Default ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1437
    onError = OE_Abort;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1438
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1439
  if( onError!=OE_Abort && onError!=OE_Rollback ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1440
    return 0;   /* Cannot do OR REPLACE or OR IGNORE or OR FAIL */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1441
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1442
  assert(pSelect->pSrc);   /* allocated even if there is no FROM clause */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1443
  if( pSelect->pSrc->nSrc!=1 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1444
    return 0;   /* FROM clause must have exactly one term */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1445
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1446
  if( pSelect->pSrc->a[0].pSelect ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1447
    return 0;   /* FROM clause cannot contain a subquery */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1448
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1449
  if( pSelect->pWhere ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1450
    return 0;   /* SELECT may not have a WHERE clause */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1451
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1452
  if( pSelect->pOrderBy ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1453
    return 0;   /* SELECT may not have an ORDER BY clause */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1454
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1455
  /* Do not need to test for a HAVING clause.  If HAVING is present but
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1456
  ** there is no ORDER BY, we will get an error. */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1457
  if( pSelect->pGroupBy ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1458
    return 0;   /* SELECT may not have a GROUP BY clause */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1459
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1460
  if( pSelect->pLimit ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1461
    return 0;   /* SELECT may not have a LIMIT clause */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1462
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1463
  assert( pSelect->pOffset==0 );  /* Must be so if pLimit==0 */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1464
  if( pSelect->pPrior ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1465
    return 0;   /* SELECT may not be a compound query */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1466
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1467
  if( pSelect->isDistinct ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1468
    return 0;   /* SELECT may not be DISTINCT */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1469
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1470
  pEList = pSelect->pEList;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1471
  assert( pEList!=0 );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1472
  if( pEList->nExpr!=1 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1473
    return 0;   /* The result set must have exactly one column */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1474
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1475
  assert( pEList->a[0].pExpr );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1476
  if( pEList->a[0].pExpr->op!=TK_ALL ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1477
    return 0;   /* The result set must be the special operator "*" */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1478
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1479
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1480
  /* At this point we have established that the statement is of the
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1481
  ** correct syntactic form to participate in this optimization.  Now
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1482
  ** we have to check the semantics.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1483
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1484
  pItem = pSelect->pSrc->a;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1485
  pSrc = sqlite3LocateTable(pParse, pItem->zName, pItem->zDatabase);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1486
  if( pSrc==0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1487
    return 0;   /* FROM clause does not contain a real table */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1488
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1489
  if( pSrc==pDest ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1490
    return 0;   /* tab1 and tab2 may not be the same table */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1491
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1492
#ifndef SQLITE_OMIT_VIRTUALTABLE
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1493
  if( pSrc->isVirtual ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1494
    return 0;   /* tab2 must not be a virtual table */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1495
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1496
#endif
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1497
  if( pSrc->pSelect ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1498
    return 0;   /* tab2 may not be a view */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1499
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1500
  if( pDest->nCol!=pSrc->nCol ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1501
    return 0;   /* Number of columns must be the same in tab1 and tab2 */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1502
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1503
  if( pDest->iPKey!=pSrc->iPKey ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1504
    return 0;   /* Both tables must have the same INTEGER PRIMARY KEY */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1505
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1506
  for(i=0; i<pDest->nCol; i++){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1507
    if( pDest->aCol[i].affinity!=pSrc->aCol[i].affinity ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1508
      return 0;    /* Affinity must be the same on all columns */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1509
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1510
    if( !xferCompatibleCollation(pDest->aCol[i].zColl, pSrc->aCol[i].zColl) ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1511
      return 0;    /* Collating sequence must be the same on all columns */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1512
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1513
    if( pDest->aCol[i].notNull && !pSrc->aCol[i].notNull ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1514
      return 0;    /* tab2 must be NOT NULL if tab1 is */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1515
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1516
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1517
  for(pDestIdx=pDest->pIndex; pDestIdx; pDestIdx=pDestIdx->pNext){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1518
    if( pDestIdx->onError!=OE_None ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1519
      destHasUniqueIdx = 1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1520
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1521
    for(pSrcIdx=pSrc->pIndex; pSrcIdx; pSrcIdx=pSrcIdx->pNext){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1522
      if( xferCompatibleIndex(pDestIdx, pSrcIdx) ) break;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1523
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1524
    if( pSrcIdx==0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1525
      return 0;    /* pDestIdx has no corresponding index in pSrc */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1526
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1527
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1528
#ifndef SQLITE_OMIT_CHECK
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1529
  if( pDest->pCheck && !sqlite3ExprCompare(pSrc->pCheck, pDest->pCheck) ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1530
    return 0;   /* Tables have different CHECK constraints.  Ticket #2252 */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1531
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1532
#endif
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1533
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1534
  /* If we get this far, it means either:
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1535
  **
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1536
  **    *   We can always do the transfer if the table contains an
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1537
  **        an integer primary key
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1538
  **
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1539
  **    *   We can conditionally do the transfer if the destination
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1540
  **        table is empty.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1541
  */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1542
#ifdef SQLITE_TEST
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1543
  sqlite3_xferopt_count++;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1544
#endif
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1545
  iDbSrc = sqlite3SchemaToIndex(pParse->db, pSrc->pSchema);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1546
  v = sqlite3GetVdbe(pParse);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1547
  sqlite3CodeVerifySchema(pParse, iDbSrc);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1548
  iSrc = pParse->nTab++;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1549
  iDest = pParse->nTab++;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1550
  counterMem = autoIncBegin(pParse, iDbDest, pDest);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1551
  sqlite3OpenTable(pParse, iDest, iDbDest, pDest, OP_OpenWrite);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1552
  if( (pDest->iPKey<0 && pDest->pIndex!=0) || destHasUniqueIdx ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1553
    /* If tables do not have an INTEGER PRIMARY KEY and there
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1554
    ** are indices to be copied and the destination is not empty,
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1555
    ** we have to disallow the transfer optimization because the
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1556
    ** the rowids might change which will mess up indexing.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1557
    **
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1558
    ** Or if the destination has a UNIQUE index and is not empty,
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1559
    ** we also disallow the transfer optimization because we cannot
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1560
    ** insure that all entries in the union of DEST and SRC will be
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1561
    ** unique.
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1562
    */
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1563
    addr1 = sqlite3VdbeAddOp(v, OP_Rewind, iDest, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1564
    emptyDestTest = sqlite3VdbeAddOp(v, OP_Goto, 0, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1565
    sqlite3VdbeJumpHere(v, addr1);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1566
  }else{
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1567
    emptyDestTest = 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1568
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1569
  sqlite3OpenTable(pParse, iSrc, iDbSrc, pSrc, OP_OpenRead);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1570
  emptySrcTest = sqlite3VdbeAddOp(v, OP_Rewind, iSrc, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1571
  if( pDest->iPKey>=0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1572
    addr1 = sqlite3VdbeAddOp(v, OP_Rowid, iSrc, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1573
    sqlite3VdbeAddOp(v, OP_Dup, 0, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1574
    addr2 = sqlite3VdbeAddOp(v, OP_NotExists, iDest, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1575
    sqlite3VdbeOp3(v, OP_Halt, SQLITE_CONSTRAINT, onError, 
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1576
                      "PRIMARY KEY must be unique", P3_STATIC);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1577
    sqlite3VdbeJumpHere(v, addr2);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1578
    autoIncStep(pParse, counterMem);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1579
  }else if( pDest->pIndex==0 ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1580
    addr1 = sqlite3VdbeAddOp(v, OP_NewRowid, iDest, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1581
  }else{
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1582
    addr1 = sqlite3VdbeAddOp(v, OP_Rowid, iSrc, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1583
    assert( pDest->autoInc==0 );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1584
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1585
  sqlite3VdbeAddOp(v, OP_RowData, iSrc, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1586
  sqlite3VdbeOp3(v, OP_Insert, iDest,
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1587
                    OPFLAG_NCHANGE|OPFLAG_LASTROWID|OPFLAG_APPEND,
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1588
                    pDest->zName, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1589
  sqlite3VdbeAddOp(v, OP_Next, iSrc, addr1);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1590
  autoIncEnd(pParse, iDbDest, pDest, counterMem);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1591
  for(pDestIdx=pDest->pIndex; pDestIdx; pDestIdx=pDestIdx->pNext){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1592
    for(pSrcIdx=pSrc->pIndex; pSrcIdx; pSrcIdx=pSrcIdx->pNext){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1593
      if( xferCompatibleIndex(pDestIdx, pSrcIdx) ) break;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1594
    }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1595
    assert( pSrcIdx );
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1596
    sqlite3VdbeAddOp(v, OP_Close, iSrc, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1597
    sqlite3VdbeAddOp(v, OP_Close, iDest, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1598
    sqlite3VdbeAddOp(v, OP_Integer, iDbSrc, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1599
    pKey = sqlite3IndexKeyinfo(pParse, pSrcIdx);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1600
    VdbeComment((v, "# %s", pSrcIdx->zName));
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1601
    sqlite3VdbeOp3(v, OP_OpenRead, iSrc, pSrcIdx->tnum, 
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1602
                   (char*)pKey, P3_KEYINFO_HANDOFF);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1603
    sqlite3VdbeAddOp(v, OP_Integer, iDbDest, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1604
    pKey = sqlite3IndexKeyinfo(pParse, pDestIdx);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1605
    VdbeComment((v, "# %s", pDestIdx->zName));
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1606
    sqlite3VdbeOp3(v, OP_OpenWrite, iDest, pDestIdx->tnum, 
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1607
                   (char*)pKey, P3_KEYINFO_HANDOFF);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1608
    addr1 = sqlite3VdbeAddOp(v, OP_Rewind, iSrc, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1609
    sqlite3VdbeAddOp(v, OP_RowKey, iSrc, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1610
    sqlite3VdbeAddOp(v, OP_IdxInsert, iDest, 1);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1611
    sqlite3VdbeAddOp(v, OP_Next, iSrc, addr1+1);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1612
    sqlite3VdbeJumpHere(v, addr1);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1613
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1614
  sqlite3VdbeJumpHere(v, emptySrcTest);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1615
  sqlite3VdbeAddOp(v, OP_Close, iSrc, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1616
  sqlite3VdbeAddOp(v, OP_Close, iDest, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1617
  if( emptyDestTest ){
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1618
    sqlite3VdbeAddOp(v, OP_Halt, SQLITE_OK, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1619
    sqlite3VdbeJumpHere(v, emptyDestTest);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1620
    sqlite3VdbeAddOp(v, OP_Close, iDest, 0);
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1621
    return 0;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1622
  }else{
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1623
    return 1;
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1624
  }
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1625
}
29cda98b007e Initial import of Podcatcher from the Bergamot project
skip
parents:
diff changeset
  1626
#endif /* SQLITE_OMIT_XFER_OPT */