/ Check-in [91cc646e]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Fix the CSE mechanism so that it takes into account column affinity changes that might be imposed by comparison operators. (CVS 4949)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 91cc646e2b0c1d62a1989405cc9384a2c22d98d0
User & Date: drh 2008-04-01 05:07:15
References
2009-09-03
01:26 Fixed ticket [2ea2425d]: Assertion fault: Text encoding mismatch on value comparison plus 3 other changes artifact: f0bfe8a8 user: drh
Context
2008-04-01
12:24
Fix a problem with CASTs and the new CSE mechanism. (CVS 4950) check-in: e25939fb user: drh tags: trunk
05:07
Fix the CSE mechanism so that it takes into account column affinity changes that might be imposed by comparison operators. (CVS 4949) check-in: 91cc646e user: drh tags: trunk
03:27
More test cases and bug fixes with CSE. (CVS 4948) check-in: 7e815612 user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/delete.c.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** in order to generate code for DELETE FROM statements.
**
** $Id: delete.c,v 1.165 2008/03/31 23:48:04 drh Exp $
*/
#include "sqliteInt.h"

/*
** Look up every table that is named in pSrc.  If any table is not found,
** add an error message to pParse->zErrMsg and return NULL.  If all tables
** are found, return a pointer to the last table.
................................................................................
      sqlite3VdbeAddOp3(v, OP_Column, iCur, idx, regBase+j);
      sqlite3ColumnDefault(v, pTab, idx);
    }
  }
  if( doMakeRec ){
    sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol+1, regOut);
    sqlite3IndexAffinityStr(v, pIdx);
    sqlite3ExprExpireColumnCacheLines(pParse, regBase, regBase+nCol);
  }
  sqlite3ReleaseTempRange(pParse, regBase, nCol+1);
  return regBase;
}

/* Make sure "isView" gets undefined in case this file becomes part of
** the amalgamation - so that subsequent files do not see isView as a
** macro. */
#undef isView







|







 







|









8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** in order to generate code for DELETE FROM statements.
**
** $Id: delete.c,v 1.166 2008/04/01 05:07:15 drh Exp $
*/
#include "sqliteInt.h"

/*
** Look up every table that is named in pSrc.  If any table is not found,
** add an error message to pParse->zErrMsg and return NULL.  If all tables
** are found, return a pointer to the last table.
................................................................................
      sqlite3VdbeAddOp3(v, OP_Column, iCur, idx, regBase+j);
      sqlite3ColumnDefault(v, pTab, idx);
    }
  }
  if( doMakeRec ){
    sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol+1, regOut);
    sqlite3IndexAffinityStr(v, pIdx);
    sqlite3ExprCacheAffinityChange(pParse, regBase, nCol+1);
  }
  sqlite3ReleaseTempRange(pParse, regBase, nCol+1);
  return regBase;
}

/* Make sure "isView" gets undefined in case this file becomes part of
** the amalgamation - so that subsequent files do not see isView as a
** macro. */
#undef isView

Changes to src/expr.c.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
196
197
198
199
200
201
202
























203
204
205
206
207
208
209
...
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
....
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
....
1903
1904
1905
1906
1907
1908
1909






1910
1911
1912
1913
1914
1915
1916

1917
1918
1919

1920
1921
1922
1923

1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
....
1943
1944
1945
1946
1947
1948
1949
1950

1951
1952
1953
1954
1955
1956
1957
1958
1959
....
1976
1977
1978
1979
1980
1981
1982

1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998


1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
....
2043
2044
2045
2046
2047
2048
2049

2050
2051
2052
2053
2054
2055
2056
2057





2058
2059
2060
2061
2062
2063
2064
....
2104
2105
2106
2107
2108
2109
2110
2111

2112
2113
2114
2115
2116
2117
2118
....
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
....
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
....
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
....
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
....
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
....
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains routines used for analyzing expressions and
** for generating VDBE code that evaluates expressions in SQLite.
**
** $Id: expr.c,v 1.361 2008/04/01 03:27:39 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

/*
** Return the 'affinity' of the expression pExpr if any.
**
................................................................................
    pColl = sqlite3ExprCollSeq(pParse, pLeft);
    if( !pColl ){
      pColl = sqlite3ExprCollSeq(pParse, pRight);
    }
  }
  return pColl;
}

























/*
** Generate code for a comparison operator.
*/
static int codeCompare(
  Parse *pParse,    /* The parsing (and code generating) context */
  Expr *pLeft,      /* The left operand */
................................................................................

  p4 = sqlite3BinaryCompareCollSeq(pParse, pLeft, pRight);
  p5 = binaryCompareP5(pLeft, pRight, jumpIfNull);
  addr = sqlite3VdbeAddOp4(pParse->pVdbe, opcode, in2, dest, in1,
                           (void*)p4, P4_COLLSEQ);
  sqlite3VdbeChangeP5(pParse->pVdbe, p5);
  if( p5 & SQLITE_AFF_MASK ){
    sqlite3ExprExpireColumnCacheLines(pParse, in1, in1);
    sqlite3ExprExpireColumnCacheLines(pParse, in2, in2);
  }
  return addr;
}

/*
** Construct a new expression node and return a pointer to it.  Memory
** for this node is obtained from sqlite3_malloc().  The calling function
................................................................................
          }

          /* Evaluate the expression and insert it into the temp table */
          pParse->disableColCache++;
          sqlite3ExprCode(pParse, pE2, r1);
          pParse->disableColCache--;
          sqlite3VdbeAddOp4(v, OP_MakeRecord, r1, 1, r2, &affinity, 1);
          sqlite3ExprExpireColumnCacheLines(pParse, r1, r1);
          sqlite3VdbeAddOp2(v, OP_IdxInsert, pExpr->iTable, r2);
        }
        sqlite3ReleaseTempReg(pParse, r1);
        sqlite3ReleaseTempReg(pParse, r2);
      }
      sqlite3VdbeChangeP4(v, addr, (void *)&keyInfo, P4_KEYINFO);
      break;
................................................................................
** Generate code that will extract the iColumn-th column from
** table pTab and store the column value in a register.  An effort
** is made to store the column value in register iReg, but this is
** not guaranteed.  The location of the column value is returned.
**
** There must be an open cursor to pTab in iTable when this routine
** is called.  If iColumn<0 then code is generated that extracts the rowid.






*/
int sqlite3ExprCodeGetColumn(
  Parse *pParse,   /* Parsing and code generating context */
  Table *pTab,     /* Description of the table we are reading from */
  int iColumn,     /* Index of the table column */
  int iTable,      /* The cursor pointing to the table */
  int iReg         /* Store results here */

){
  Vdbe *v = pParse->pVdbe;
  int i;


  for(i=0; i<pParse->nColCache; i++){
    if( pParse->aColCache[i].iTable==iTable
     && pParse->aColCache[i].iColumn==iColumn ){

#if 0
      sqlite3VdbeAddOp0(v, OP_Noop);
      VdbeComment((v, "OPT: tab%d.col%d -> r%d",
                       iTable, iColumn, pParse->aColCache[i].iReg));
#endif
      return pParse->aColCache[i].iReg;
    }
  }  
  assert( v!=0 );
  if( iColumn<0 ){
    int op = (pTab && IsVirtual(pTab)) ? OP_VRowid : OP_Rowid;
    sqlite3VdbeAddOp2(v, op, iTable, iReg);
  }else if( pTab==0 ){
................................................................................
    if( pTab->aCol[iColumn].affinity==SQLITE_AFF_REAL ){
      sqlite3VdbeAddOp1(v, OP_RealAffinity, iReg);
    }
#endif
  }
  if( pParse->disableColCache==0 ){
    i = pParse->iColCache;
    pParse->aColCache[i].iTable = iTable;

    pParse->aColCache[i].iColumn = iColumn;
    pParse->aColCache[i].iReg = iReg;
    i++;
    if( i>=ArraySize(pParse->aColCache) ) i = 0;
    if( i>pParse->nColCache ) pParse->nColCache = i;
    pParse->iColCache = i;
  }
  return iReg;
}
................................................................................
    pParse->nColCache = 0;
    pParse->iColCache = 0;
  }else{
    int i;
    for(i=0; i<pParse->nColCache; i++){
      if( pParse->aColCache[i].iTable==iTable ){
        pParse->aColCache[i] = pParse->aColCache[--pParse->nColCache];

      }
    }
    pParse->iColCache = pParse->nColCache;
  }
}

/*
** Expire all column cache entry associated with register between
** iFrom and iTo, inclusive.  If there are no column cache entries 
** on those registers then this routine is a no-op.
**
** Call this routine when register contents are overwritten to
** make sure the new register value is not used in place of the
** value that was overwritten.
*/
void sqlite3ExprExpireColumnCacheLines(Parse *pParse, int iFrom, int iTo){


  int i;
  for(i=0; i<pParse->nColCache; i++){
    int r = pParse->aColCache[i].iReg;
    if( r>=iFrom && r<=iTo ){
      pParse->aColCache[i] = pParse->aColCache[--pParse->nColCache];
    }
  }
  pParse->iColCache = pParse->nColCache;
}

/*
** Generate code to moves content from one register to another.
** Keep the column cache up-to-date.
*/
void sqlite3ExprCodeMove(Parse *pParse, int iFrom, int iTo){
................................................................................
** is not a cached register.  If iCurrent is a cached register,
** then try to move the value over to iTarget.  If iTarget is a
** cached register, then clear the corresponding cache line.
**
** Return the register that the value ends up in.
*/
int sqlite3ExprWritableRegister(Parse *pParse, int iCurrent, int iTarget){

  assert( pParse->pVdbe!=0 );
  if( !usedAsColumnCache(pParse, iCurrent, iCurrent) ){
    return iCurrent;
  }
  if( iCurrent!=iTarget ){
    sqlite3VdbeAddOp2(pParse->pVdbe, OP_SCopy, iCurrent, iTarget);
  }
  sqlite3ExprExpireColumnCacheLines(pParse, iTarget, iTarget);





  return iTarget;
}

/*
** Generate code into the current Vdbe to evaluate the given
** expression.  Attempt to store the results in register "target".
** Return the register where results are stored.
................................................................................
    case TK_COLUMN: {
      if( pExpr->iTable<0 ){
        /* This only happens when coding check constraints */
        assert( pParse->ckBase>0 );
        inReg = pExpr->iColumn + pParse->ckBase;
      }else{
        inReg = sqlite3ExprCodeGetColumn(pParse, pExpr->pTab,
                                 pExpr->iColumn, pExpr->iTable, target);

      }
      break;
    }
    case TK_INTEGER: {
      codeInteger(v, (char*)pExpr->token.z, pExpr->token.n, 0, target);
      break;
    }
................................................................................
    case TK_EQ: {
      assert( TK_LT==OP_Lt );
      assert( TK_LE==OP_Le );
      assert( TK_GT==OP_Gt );
      assert( TK_GE==OP_Ge );
      assert( TK_EQ==OP_Eq );
      assert( TK_NE==OP_Ne );
      r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
      r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, &regFree2);
      codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
                  r1, r2, inReg, SQLITE_STOREP2);
      break;
    }
    case TK_AND:
    case TK_OR:
    case TK_PLUS:
................................................................................
      }
      sqlite3VdbeAddOp4(v, OP_Function, constMask, r1, target,
                        (char*)pDef, P4_FUNCDEF);
      sqlite3VdbeChangeP5(v, nExpr);
      if( nExpr ){
        sqlite3ReleaseTempRange(pParse, r1, nExpr);
      }
      sqlite3ExprExpireColumnCacheLines(pParse, r1, r1+nExpr-1);
      break;
    }
#ifndef SQLITE_OMIT_SUBQUERY
    case TK_EXISTS:
    case TK_SELECT: {
      if( pExpr->iColumn==0 ){
        sqlite3CodeSubselect(pParse, pExpr);
................................................................................
        j4 = sqlite3VdbeAddOp3(v, OP_NotExists, pExpr->iTable, 0, r1);
        j5 = sqlite3VdbeAddOp0(v, OP_Goto);
        sqlite3VdbeJumpHere(v, j3);
        sqlite3VdbeJumpHere(v, j4);
      }else{
        r2 = regFree2 = sqlite3GetTempReg(pParse);
        sqlite3VdbeAddOp4(v, OP_MakeRecord, r1, 1, r2, &affinity, 1);
        sqlite3ExprExpireColumnCacheLines(pParse, r1, r1);
        j5 = sqlite3VdbeAddOp3(v, OP_Found, pExpr->iTable, 0, r2);
      }
      sqlite3VdbeAddOp2(v, OP_AddImm, target, -1);
      sqlite3VdbeJumpHere(v, j2);
      sqlite3VdbeJumpHere(v, j5);
      break;
    }
................................................................................
    ** Z is stored in pExpr->pList->a[1].pExpr.
    */
    case TK_BETWEEN: {
      Expr *pLeft = pExpr->pLeft;
      struct ExprList_item *pLItem = pExpr->pList->a;
      Expr *pRight = pLItem->pExpr;

      r1 = sqlite3ExprCodeTemp(pParse, pLeft, &regFree1);
      r2 = sqlite3ExprCodeTemp(pParse, pRight, &regFree2);
      r3 = sqlite3GetTempReg(pParse);
      r4 = sqlite3GetTempReg(pParse);
      codeCompare(pParse, pLeft, pRight, OP_Ge,
                  r1, r2, r3, SQLITE_STOREP2);
      pLItem++;
      pRight = pLItem->pExpr;
      sqlite3ReleaseTempReg(pParse, regFree2);
................................................................................
    case TK_EQ: {
      assert( TK_LT==OP_Lt );
      assert( TK_LE==OP_Le );
      assert( TK_GT==OP_Gt );
      assert( TK_GE==OP_Ge );
      assert( TK_EQ==OP_Eq );
      assert( TK_NE==OP_Ne );
      r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
      r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, &regFree2);
      codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
                  r1, r2, dest, jumpIfNull);
      break;
    }
    case TK_ISNULL:
    case TK_NOTNULL: {
      assert( TK_ISNULL==OP_IsNull );
................................................................................
    }
    case TK_LT:
    case TK_LE:
    case TK_GT:
    case TK_GE:
    case TK_NE:
    case TK_EQ: {
      r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
      r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, &regFree2);
      codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
                  r1, r2, dest, jumpIfNull);
      break;
    }
    case TK_ISNULL:
    case TK_NOTNULL: {
      r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);







|







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







|
|







 







|







 







>
>
>
>
>
>






|
>



>

|
<
|
>


|
<

|







 







|
>
|
|







 







>


<




|
|
<
<
<
<
<

<
>
>



|
|


<







 







>







|
>
>
>
>
>







 







|
>







 







|
|







 







|







 







|







 







|
|







 







|
|







 







|
|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
...
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
....
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
....
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953

1954
1955
1956
1957
1958

1959
1960
1961
1962
1963
1964
1965
1966
1967
....
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
....
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017

2018
2019
2020
2021
2022
2023





2024

2025
2026
2027
2028
2029
2030
2031
2032
2033

2034
2035
2036
2037
2038
2039
2040
....
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
....
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
....
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
....
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
....
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
....
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
....
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
....
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains routines used for analyzing expressions and
** for generating VDBE code that evaluates expressions in SQLite.
**
** $Id: expr.c,v 1.362 2008/04/01 05:07:15 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

/*
** Return the 'affinity' of the expression pExpr if any.
**
................................................................................
    pColl = sqlite3ExprCollSeq(pParse, pLeft);
    if( !pColl ){
      pColl = sqlite3ExprCollSeq(pParse, pRight);
    }
  }
  return pColl;
}

/*
** Generate the operands for a comparison operation.  Before
** generating the code for each operand, set the EP_AnyAff
** flag on the expression so that it will be able to used a
** cached column value that has previously undergone an
** affinity change.
*/
static void codeCompareOperands(
  Parse *pParse,    /* Parsing and code generating context */
  Expr *pLeft,      /* The left operand */
  int *pRegLeft,    /* Register where left operand is stored */
  int *pFreeLeft,   /* Free this register when done */
  Expr *pRight,     /* The right operand */
  int *pRegRight,   /* Register where right operand is stored */
  int *pFreeRight   /* Write temp register for right operand there */
){
  while( pLeft->op==TK_UPLUS ) pLeft = pLeft->pLeft;
  pLeft->flags |= EP_AnyAff;
  *pRegLeft = sqlite3ExprCodeTemp(pParse, pLeft, pFreeLeft);
  while( pRight->op==TK_UPLUS ) pRight = pRight->pLeft;
  pRight->flags |= EP_AnyAff;
  *pRegRight = sqlite3ExprCodeTemp(pParse, pRight, pFreeRight);
}

/*
** Generate code for a comparison operator.
*/
static int codeCompare(
  Parse *pParse,    /* The parsing (and code generating) context */
  Expr *pLeft,      /* The left operand */
................................................................................

  p4 = sqlite3BinaryCompareCollSeq(pParse, pLeft, pRight);
  p5 = binaryCompareP5(pLeft, pRight, jumpIfNull);
  addr = sqlite3VdbeAddOp4(pParse->pVdbe, opcode, in2, dest, in1,
                           (void*)p4, P4_COLLSEQ);
  sqlite3VdbeChangeP5(pParse->pVdbe, p5);
  if( p5 & SQLITE_AFF_MASK ){
    sqlite3ExprCacheAffinityChange(pParse, in1, 1);
    sqlite3ExprCacheAffinityChange(pParse, in2, 1);
  }
  return addr;
}

/*
** Construct a new expression node and return a pointer to it.  Memory
** for this node is obtained from sqlite3_malloc().  The calling function
................................................................................
          }

          /* Evaluate the expression and insert it into the temp table */
          pParse->disableColCache++;
          sqlite3ExprCode(pParse, pE2, r1);
          pParse->disableColCache--;
          sqlite3VdbeAddOp4(v, OP_MakeRecord, r1, 1, r2, &affinity, 1);
          sqlite3ExprCacheAffinityChange(pParse, r1, 1);
          sqlite3VdbeAddOp2(v, OP_IdxInsert, pExpr->iTable, r2);
        }
        sqlite3ReleaseTempReg(pParse, r1);
        sqlite3ReleaseTempReg(pParse, r2);
      }
      sqlite3VdbeChangeP4(v, addr, (void *)&keyInfo, P4_KEYINFO);
      break;
................................................................................
** Generate code that will extract the iColumn-th column from
** table pTab and store the column value in a register.  An effort
** is made to store the column value in register iReg, but this is
** not guaranteed.  The location of the column value is returned.
**
** There must be an open cursor to pTab in iTable when this routine
** is called.  If iColumn<0 then code is generated that extracts the rowid.
**
** This routine might attempt to reuse the value of the column that
** has already been loaded into a register.  The value will always
** be used if it has not undergone any affinity changes.  But if
** an affinity change has occurred, then the cached value will only be
** used if allowAffChng is true.
*/
int sqlite3ExprCodeGetColumn(
  Parse *pParse,   /* Parsing and code generating context */
  Table *pTab,     /* Description of the table we are reading from */
  int iColumn,     /* Index of the table column */
  int iTable,      /* The cursor pointing to the table */
  int iReg,        /* Store results here */
  int allowAffChng /* True if prior affinity changes are OK */
){
  Vdbe *v = pParse->pVdbe;
  int i;
  struct yColCache *p;

  for(i=0, p=pParse->aColCache; i<pParse->nColCache; i++, p++){

    if( p->iTable==iTable && p->iColumn==iColumn
           && (!p->affChange || allowAffChng) ){
#if 0
      sqlite3VdbeAddOp0(v, OP_Noop);
      VdbeComment((v, "OPT: tab%d.col%d -> r%d", iTable, iColumn, p->iReg));

#endif
      return p->iReg;
    }
  }  
  assert( v!=0 );
  if( iColumn<0 ){
    int op = (pTab && IsVirtual(pTab)) ? OP_VRowid : OP_Rowid;
    sqlite3VdbeAddOp2(v, op, iTable, iReg);
  }else if( pTab==0 ){
................................................................................
    if( pTab->aCol[iColumn].affinity==SQLITE_AFF_REAL ){
      sqlite3VdbeAddOp1(v, OP_RealAffinity, iReg);
    }
#endif
  }
  if( pParse->disableColCache==0 ){
    i = pParse->iColCache;
    p = &pParse->aColCache[i];
    p->iTable = iTable;
    p->iColumn = iColumn;
    p->iReg = iReg;
    i++;
    if( i>=ArraySize(pParse->aColCache) ) i = 0;
    if( i>pParse->nColCache ) pParse->nColCache = i;
    pParse->iColCache = i;
  }
  return iReg;
}
................................................................................
    pParse->nColCache = 0;
    pParse->iColCache = 0;
  }else{
    int i;
    for(i=0; i<pParse->nColCache; i++){
      if( pParse->aColCache[i].iTable==iTable ){
        pParse->aColCache[i] = pParse->aColCache[--pParse->nColCache];
        pParse->iColCache = pParse->nColCache;
      }
    }

  }
}

/*
** Record the fact that an affinity change has occurred on iCount
** registers starting with iStart.





*/

void sqlite3ExprCacheAffinityChange(Parse *pParse, int iStart, int iCount){
  int iEnd = iStart + iCount - 1;
  int i;
  for(i=0; i<pParse->nColCache; i++){
    int r = pParse->aColCache[i].iReg;
    if( r>=iStart && r<=iEnd ){
      pParse->aColCache[i].affChange = 1;
    }
  }

}

/*
** Generate code to moves content from one register to another.
** Keep the column cache up-to-date.
*/
void sqlite3ExprCodeMove(Parse *pParse, int iFrom, int iTo){
................................................................................
** is not a cached register.  If iCurrent is a cached register,
** then try to move the value over to iTarget.  If iTarget is a
** cached register, then clear the corresponding cache line.
**
** Return the register that the value ends up in.
*/
int sqlite3ExprWritableRegister(Parse *pParse, int iCurrent, int iTarget){
  int i;
  assert( pParse->pVdbe!=0 );
  if( !usedAsColumnCache(pParse, iCurrent, iCurrent) ){
    return iCurrent;
  }
  if( iCurrent!=iTarget ){
    sqlite3VdbeAddOp2(pParse->pVdbe, OP_SCopy, iCurrent, iTarget);
  }
  for(i=0; i<pParse->nColCache; i++){
    if( pParse->aColCache[i].iReg==iTarget ){
      pParse->aColCache[i] = pParse->aColCache[--pParse->nColCache];
      pParse->iColCache = pParse->nColCache;
    }
  }
  return iTarget;
}

/*
** Generate code into the current Vdbe to evaluate the given
** expression.  Attempt to store the results in register "target".
** Return the register where results are stored.
................................................................................
    case TK_COLUMN: {
      if( pExpr->iTable<0 ){
        /* This only happens when coding check constraints */
        assert( pParse->ckBase>0 );
        inReg = pExpr->iColumn + pParse->ckBase;
      }else{
        inReg = sqlite3ExprCodeGetColumn(pParse, pExpr->pTab,
                                 pExpr->iColumn, pExpr->iTable, target,
                                 pExpr->flags & EP_AnyAff);
      }
      break;
    }
    case TK_INTEGER: {
      codeInteger(v, (char*)pExpr->token.z, pExpr->token.n, 0, target);
      break;
    }
................................................................................
    case TK_EQ: {
      assert( TK_LT==OP_Lt );
      assert( TK_LE==OP_Le );
      assert( TK_GT==OP_Gt );
      assert( TK_GE==OP_Ge );
      assert( TK_EQ==OP_Eq );
      assert( TK_NE==OP_Ne );
      codeCompareOperands(pParse, pExpr->pLeft, &r1, &regFree1,
                                  pExpr->pRight, &r2, &regFree2);
      codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
                  r1, r2, inReg, SQLITE_STOREP2);
      break;
    }
    case TK_AND:
    case TK_OR:
    case TK_PLUS:
................................................................................
      }
      sqlite3VdbeAddOp4(v, OP_Function, constMask, r1, target,
                        (char*)pDef, P4_FUNCDEF);
      sqlite3VdbeChangeP5(v, nExpr);
      if( nExpr ){
        sqlite3ReleaseTempRange(pParse, r1, nExpr);
      }
      sqlite3ExprCacheAffinityChange(pParse, r1, nExpr);
      break;
    }
#ifndef SQLITE_OMIT_SUBQUERY
    case TK_EXISTS:
    case TK_SELECT: {
      if( pExpr->iColumn==0 ){
        sqlite3CodeSubselect(pParse, pExpr);
................................................................................
        j4 = sqlite3VdbeAddOp3(v, OP_NotExists, pExpr->iTable, 0, r1);
        j5 = sqlite3VdbeAddOp0(v, OP_Goto);
        sqlite3VdbeJumpHere(v, j3);
        sqlite3VdbeJumpHere(v, j4);
      }else{
        r2 = regFree2 = sqlite3GetTempReg(pParse);
        sqlite3VdbeAddOp4(v, OP_MakeRecord, r1, 1, r2, &affinity, 1);
        sqlite3ExprCacheAffinityChange(pParse, r1, 1);
        j5 = sqlite3VdbeAddOp3(v, OP_Found, pExpr->iTable, 0, r2);
      }
      sqlite3VdbeAddOp2(v, OP_AddImm, target, -1);
      sqlite3VdbeJumpHere(v, j2);
      sqlite3VdbeJumpHere(v, j5);
      break;
    }
................................................................................
    ** Z is stored in pExpr->pList->a[1].pExpr.
    */
    case TK_BETWEEN: {
      Expr *pLeft = pExpr->pLeft;
      struct ExprList_item *pLItem = pExpr->pList->a;
      Expr *pRight = pLItem->pExpr;

      codeCompareOperands(pParse, pLeft, &r1, &regFree1,
                                  pRight, &r2, &regFree2);
      r3 = sqlite3GetTempReg(pParse);
      r4 = sqlite3GetTempReg(pParse);
      codeCompare(pParse, pLeft, pRight, OP_Ge,
                  r1, r2, r3, SQLITE_STOREP2);
      pLItem++;
      pRight = pLItem->pExpr;
      sqlite3ReleaseTempReg(pParse, regFree2);
................................................................................
    case TK_EQ: {
      assert( TK_LT==OP_Lt );
      assert( TK_LE==OP_Le );
      assert( TK_GT==OP_Gt );
      assert( TK_GE==OP_Ge );
      assert( TK_EQ==OP_Eq );
      assert( TK_NE==OP_Ne );
      codeCompareOperands(pParse, pExpr->pLeft, &r1, &regFree1,
                                  pExpr->pRight, &r2, &regFree2);
      codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
                  r1, r2, dest, jumpIfNull);
      break;
    }
    case TK_ISNULL:
    case TK_NOTNULL: {
      assert( TK_ISNULL==OP_IsNull );
................................................................................
    }
    case TK_LT:
    case TK_LE:
    case TK_GT:
    case TK_GE:
    case TK_NE:
    case TK_EQ: {
      codeCompareOperands(pParse, pExpr->pLeft, &r1, &regFree1,
                                  pExpr->pRight, &r2, &regFree2);
      codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
                  r1, r2, dest, jumpIfNull);
      break;
    }
    case TK_ISNULL:
    case TK_NOTNULL: {
      r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);

Changes to src/insert.c.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
....
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
....
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle INSERT statements in SQLite.
**
** $Id: insert.c,v 1.234 2008/03/31 23:48:05 drh Exp $
*/
#include "sqliteInt.h"

/*
** Set P4 of the most recently inserted opcode to a column affinity
** string for index pIdx. A column affinity string has one character
** for each column in the table, according to the affinity of the column:
................................................................................
      }else{
        sqlite3VdbeAddOp2(v, OP_SCopy, regData+idx, regIdx+i);
      }
    }
    sqlite3VdbeAddOp2(v, OP_SCopy, regRowid, regIdx+i);
    sqlite3VdbeAddOp3(v, OP_MakeRecord, regIdx, pIdx->nColumn+1, aRegIdx[iCur]);
    sqlite3IndexAffinityStr(v, pIdx);
    sqlite3ExprExpireColumnCacheLines(pParse, regIdx, regIdx+pIdx->nColumn);
    sqlite3ReleaseTempRange(pParse, regIdx, pIdx->nColumn+1);

    /* Find out what action to take in case there is an indexing conflict */
    onError = pIdx->onError;
    if( onError==OE_None ) continue;  /* pIdx is not a UNIQUE index */
    if( overrideError!=OE_Default ){
      onError = overrideError;
................................................................................
    if( aRegIdx[i]==0 ) continue;
    sqlite3VdbeAddOp2(v, OP_IdxInsert, baseCur+i+1, aRegIdx[i]);
  }
  regData = regRowid + 1;
  regRec = sqlite3GetTempReg(pParse);
  sqlite3VdbeAddOp3(v, OP_MakeRecord, regData, pTab->nCol, regRec);
  sqlite3TableAffinityStr(v, pTab);
  sqlite3ExprExpireColumnCacheLines(pParse, regData, regData+pTab->nCol-1);
#ifndef SQLITE_OMIT_TRIGGER
  if( newIdx>=0 ){
    sqlite3VdbeAddOp3(v, OP_Insert, newIdx, regRec, regRowid);
  }
#endif
  if( pParse->nested ){
    pik_flags = 0;







|







 







|







 







|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
....
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
....
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle INSERT statements in SQLite.
**
** $Id: insert.c,v 1.235 2008/04/01 05:07:15 drh Exp $
*/
#include "sqliteInt.h"

/*
** Set P4 of the most recently inserted opcode to a column affinity
** string for index pIdx. A column affinity string has one character
** for each column in the table, according to the affinity of the column:
................................................................................
      }else{
        sqlite3VdbeAddOp2(v, OP_SCopy, regData+idx, regIdx+i);
      }
    }
    sqlite3VdbeAddOp2(v, OP_SCopy, regRowid, regIdx+i);
    sqlite3VdbeAddOp3(v, OP_MakeRecord, regIdx, pIdx->nColumn+1, aRegIdx[iCur]);
    sqlite3IndexAffinityStr(v, pIdx);
    sqlite3ExprCacheAffinityChange(pParse, regIdx, pIdx->nColumn+1);
    sqlite3ReleaseTempRange(pParse, regIdx, pIdx->nColumn+1);

    /* Find out what action to take in case there is an indexing conflict */
    onError = pIdx->onError;
    if( onError==OE_None ) continue;  /* pIdx is not a UNIQUE index */
    if( overrideError!=OE_Default ){
      onError = overrideError;
................................................................................
    if( aRegIdx[i]==0 ) continue;
    sqlite3VdbeAddOp2(v, OP_IdxInsert, baseCur+i+1, aRegIdx[i]);
  }
  regData = regRowid + 1;
  regRec = sqlite3GetTempReg(pParse);
  sqlite3VdbeAddOp3(v, OP_MakeRecord, regData, pTab->nCol, regRec);
  sqlite3TableAffinityStr(v, pTab);
  sqlite3ExprCacheAffinityChange(pParse, regData, pTab->nCol);
#ifndef SQLITE_OMIT_TRIGGER
  if( newIdx>=0 ){
    sqlite3VdbeAddOp3(v, OP_Insert, newIdx, regRec, regRowid);
  }
#endif
  if( pParse->nested ){
    pik_flags = 0;

Changes to src/select.c.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
...
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
...
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
...
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
....
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
....
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle SELECT statements in SQLite.
**
** $Id: select.c,v 1.424 2008/03/31 23:48:05 drh Exp $
*/
#include "sqliteInt.h"


/*
** Delete all the content of a Select structure but do not deallocate
** the select structure itself.
................................................................................
        ** ORDER BY in this case since the order of entries in the set
        ** does not matter.  But there might be a LIMIT clause, in which
        ** case the order does matter */
        pushOntoSorter(pParse, pOrderBy, p, regResult);
      }else{
        int r1 = sqlite3GetTempReg(pParse);
        sqlite3VdbeAddOp4(v, OP_MakeRecord, regResult, 1, r1, &p->affinity, 1);
        sqlite3ExprExpireColumnCacheLines(pParse, regResult, regResult);
        sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, r1);
        sqlite3ReleaseTempReg(pParse, r1);
      }
      sqlite3VdbeJumpHere(v, addr2);
      break;
    }

................................................................................
        sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nColumn, r1);
        pushOntoSorter(pParse, pOrderBy, p, r1);
        sqlite3ReleaseTempReg(pParse, r1);
      }else if( eDest==SRT_Subroutine ){
        sqlite3VdbeAddOp2(v, OP_Gosub, 0, iParm);
      }else{
        sqlite3VdbeAddOp2(v, OP_ResultRow, regResult, nColumn);
        sqlite3ExprExpireColumnCacheLines(pParse,regResult,regResult+nColumn-1);
      }
      break;
    }

#if !defined(SQLITE_OMIT_TRIGGER)
    /* Discard the results.  This is used for SELECT statements inside
    ** the body of a TRIGGER.  The purpose of such selects is to call
................................................................................
    }
#ifndef SQLITE_OMIT_SUBQUERY
    case SRT_Set: {
      int j1;
      assert( nColumn==1 );
      j1 = sqlite3VdbeAddOp1(v, OP_IsNull, regRow);
      sqlite3VdbeAddOp4(v, OP_MakeRecord, regRow, 1, regRowid, &p->affinity, 1);
      sqlite3ExprExpireColumnCacheLines(pParse, regRow, regRow);
      sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, regRowid);
      sqlite3VdbeJumpHere(v, j1);
      break;
    }
    case SRT_Mem: {
      assert( nColumn==1 );
      sqlite3ExprCodeMove(pParse, regRow, iParm);
................................................................................
      sqlite3VdbeAddOp3(v, OP_Insert, pseudoTab, regRow, regRowid);
      for(i=0; i<nColumn; i++){
        assert( regRow!=pDest->iMem+i );
        sqlite3VdbeAddOp3(v, OP_Column, pseudoTab, i, pDest->iMem+i);
      }
      if( eDest==SRT_Callback ){
        sqlite3VdbeAddOp2(v, OP_ResultRow, pDest->iMem, nColumn);
        sqlite3ExprExpireColumnCacheLines(pParse, pDest->iMem,
                                                  pDest->iMem+nColumn-1);
      }else{
        sqlite3VdbeAddOp2(v, OP_Gosub, 0, iParm);
      }
      break;
    }
    default: {
      /* Do nothing */
................................................................................
      }
      sqlite3VdbeAddOp4(v, OP_CollSeq, 0, 0, 0, (char *)pColl, P4_COLLSEQ);
    }
    sqlite3VdbeAddOp4(v, OP_AggStep, 0, regAgg, pF->iMem,
                      (void*)pF->pFunc, P4_FUNCDEF);
    sqlite3VdbeChangeP5(v, nArg);
    sqlite3ReleaseTempRange(pParse, regAgg, nArg);
    sqlite3ExprExpireColumnCacheLines(pParse, regAgg, regAgg+nArg-1);
    if( addrNext ){
      sqlite3VdbeResolveLabel(v, addrNext);
    }
  }
  for(i=0, pC=pAggInfo->aCol; i<pAggInfo->nAccumulator; i++, pC++){
    sqlite3ExprCode(pParse, pC->pExpr, pC->iMem);
  }
................................................................................
        sqlite3VdbeAddOp2(v, OP_Sequence, sAggInfo.sortingIdx,regBase+nGroupBy);
        j = nGroupBy+1;
        for(i=0; i<sAggInfo.nColumn; i++){
          struct AggInfo_col *pCol = &sAggInfo.aCol[i];
          if( pCol->iSorterColumn>=j ){
            int r1 = j + regBase;
            int r2 = sqlite3ExprCodeGetColumn(pParse, 
                               pCol->pTab, pCol->iColumn,  pCol->iTable, r1);
            if( r1!=r2 ){
              sqlite3VdbeAddOp2(v, OP_SCopy, r2, r1);
            }
            j++;
          }
        }
        regRecord = sqlite3GetTempReg(pParse);







|







 







|







 







|







 







|







 







|
<







 







|







 







|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
...
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
...
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
...
854
855
856
857
858
859
860
861

862
863
864
865
866
867
868
....
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
....
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle SELECT statements in SQLite.
**
** $Id: select.c,v 1.425 2008/04/01 05:07:15 drh Exp $
*/
#include "sqliteInt.h"


/*
** Delete all the content of a Select structure but do not deallocate
** the select structure itself.
................................................................................
        ** ORDER BY in this case since the order of entries in the set
        ** does not matter.  But there might be a LIMIT clause, in which
        ** case the order does matter */
        pushOntoSorter(pParse, pOrderBy, p, regResult);
      }else{
        int r1 = sqlite3GetTempReg(pParse);
        sqlite3VdbeAddOp4(v, OP_MakeRecord, regResult, 1, r1, &p->affinity, 1);
        sqlite3ExprCacheAffinityChange(pParse, regResult, 1);
        sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, r1);
        sqlite3ReleaseTempReg(pParse, r1);
      }
      sqlite3VdbeJumpHere(v, addr2);
      break;
    }

................................................................................
        sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nColumn, r1);
        pushOntoSorter(pParse, pOrderBy, p, r1);
        sqlite3ReleaseTempReg(pParse, r1);
      }else if( eDest==SRT_Subroutine ){
        sqlite3VdbeAddOp2(v, OP_Gosub, 0, iParm);
      }else{
        sqlite3VdbeAddOp2(v, OP_ResultRow, regResult, nColumn);
        sqlite3ExprCacheAffinityChange(pParse, regResult, nColumn);
      }
      break;
    }

#if !defined(SQLITE_OMIT_TRIGGER)
    /* Discard the results.  This is used for SELECT statements inside
    ** the body of a TRIGGER.  The purpose of such selects is to call
................................................................................
    }
#ifndef SQLITE_OMIT_SUBQUERY
    case SRT_Set: {
      int j1;
      assert( nColumn==1 );
      j1 = sqlite3VdbeAddOp1(v, OP_IsNull, regRow);
      sqlite3VdbeAddOp4(v, OP_MakeRecord, regRow, 1, regRowid, &p->affinity, 1);
      sqlite3ExprCacheAffinityChange(pParse, regRow, 1);
      sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, regRowid);
      sqlite3VdbeJumpHere(v, j1);
      break;
    }
    case SRT_Mem: {
      assert( nColumn==1 );
      sqlite3ExprCodeMove(pParse, regRow, iParm);
................................................................................
      sqlite3VdbeAddOp3(v, OP_Insert, pseudoTab, regRow, regRowid);
      for(i=0; i<nColumn; i++){
        assert( regRow!=pDest->iMem+i );
        sqlite3VdbeAddOp3(v, OP_Column, pseudoTab, i, pDest->iMem+i);
      }
      if( eDest==SRT_Callback ){
        sqlite3VdbeAddOp2(v, OP_ResultRow, pDest->iMem, nColumn);
        sqlite3ExprCacheAffinityChange(pParse, pDest->iMem, nColumn);

      }else{
        sqlite3VdbeAddOp2(v, OP_Gosub, 0, iParm);
      }
      break;
    }
    default: {
      /* Do nothing */
................................................................................
      }
      sqlite3VdbeAddOp4(v, OP_CollSeq, 0, 0, 0, (char *)pColl, P4_COLLSEQ);
    }
    sqlite3VdbeAddOp4(v, OP_AggStep, 0, regAgg, pF->iMem,
                      (void*)pF->pFunc, P4_FUNCDEF);
    sqlite3VdbeChangeP5(v, nArg);
    sqlite3ReleaseTempRange(pParse, regAgg, nArg);
    sqlite3ExprCacheAffinityChange(pParse, regAgg, nArg);
    if( addrNext ){
      sqlite3VdbeResolveLabel(v, addrNext);
    }
  }
  for(i=0, pC=pAggInfo->aCol; i<pAggInfo->nAccumulator; i++, pC++){
    sqlite3ExprCode(pParse, pC->pExpr, pC->iMem);
  }
................................................................................
        sqlite3VdbeAddOp2(v, OP_Sequence, sAggInfo.sortingIdx,regBase+nGroupBy);
        j = nGroupBy+1;
        for(i=0; i<sAggInfo.nColumn; i++){
          struct AggInfo_col *pCol = &sAggInfo.aCol[i];
          if( pCol->iSorterColumn>=j ){
            int r1 = j + regBase;
            int r2 = sqlite3ExprCodeGetColumn(pParse, 
                               pCol->pTab, pCol->iColumn, pCol->iTable, r1, 0);
            if( r1!=r2 ){
              sqlite3VdbeAddOp2(v, OP_SCopy, r2, r1);
            }
            j++;
          }
        }
        regRecord = sqlite3GetTempReg(pParse);

Changes to src/sqliteInt.h.

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
....
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
....
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
....
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** Internal interface definitions for SQLite.
**
** @(#) $Id: sqliteInt.h,v 1.685 2008/04/01 03:27:39 drh Exp $
*/
#ifndef _SQLITEINT_H_
#define _SQLITEINT_H_

/*
** Include the configuration header output by 'configure' if it was run
** (otherwise we get an empty default).
................................................................................
#define EP_Resolved   0x0004  /* IDs have been resolved to COLUMNs */
#define EP_Error      0x0008  /* Expression contains one or more errors */
#define EP_Distinct   0x0010  /* Aggregate function with DISTINCT keyword */
#define EP_VarSelect  0x0020  /* pSelect is correlated, not constant */
#define EP_Dequoted   0x0040  /* True if the string has been dequoted */
#define EP_InfixFunc  0x0080  /* True for an infix function: LIKE, GLOB, etc */
#define EP_ExpCollate 0x0100  /* Collating sequence specified explicitly */
#define EP_Constant   0x0200  /* A constant expression */

/*
** These macros can be used to test, set, or clear bits in the 
** Expr.flags field.
*/
#define ExprHasProperty(E,P)     (((E)->flags&(P))==(P))
#define ExprHasAnyProperty(E,P)  (((E)->flags&(P))!=0)
................................................................................
  int ckBase;          /* Base register of data during check constraints */
  int disableColCache; /* True to disable adding to column cache */
  int nColCache;       /* Number of entries in the column cache */
  int iColCache;       /* Next entry of the cache to replace */
  struct yColCache {
    int iTable;           /* Table cursor number */
    int iColumn;          /* Table column number */
    char aff;             /* Affinity.  Or 0 if none specified */
    int iReg;             /* Register holding value of this column */
  } aColCache[10];     /* One for each valid column cache entry */
  u32 writeMask;       /* Start a write transaction on these databases */
  u32 cookieMask;      /* Bitmask of schema verified databases */
  int cookieGoto;      /* Address of OP_Goto to cookie verifier subroutine */
  int cookieValue[SQLITE_MAX_ATTACHED+2];  /* Values of cookies to verify */
#ifndef SQLITE_OMIT_SHARED_CACHE
................................................................................
Table *sqlite3SrcListLookup(Parse*, SrcList*);
int sqlite3IsReadOnly(Parse*, Table*, int);
void sqlite3OpenTable(Parse*, int iCur, int iDb, Table*, int);
void sqlite3DeleteFrom(Parse*, SrcList*, Expr*);
void sqlite3Update(Parse*, SrcList*, ExprList*, Expr*, int);
WhereInfo *sqlite3WhereBegin(Parse*, SrcList*, Expr*, ExprList**, u8);
void sqlite3WhereEnd(WhereInfo*);
int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int);
void sqlite3ExprCodeMove(Parse*, int, int);
void sqlite3ExprClearColumnCache(Parse*, int);
void sqlite3ExprColumnCacheDisable(Parse*, int);
void sqlite3ExprExpireColumnCacheLines(Parse*, int, int);
int sqlite3ExprWritableRegister(Parse*,int,int);
int sqlite3ExprCode(Parse*, Expr*, int);
int sqlite3ExprCodeTemp(Parse*, Expr*, int*);
int sqlite3ExprCodeTarget(Parse*, Expr*, int);
int sqlite3ExprCodeAndCache(Parse*, Expr*, int);
void sqlite3ExprCodeConstants(Parse*, Expr*);
int sqlite3ExprCodeExprList(Parse*, ExprList*, int);







|







 







|







 







|







 







|



|







7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
....
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
....
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
....
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** Internal interface definitions for SQLite.
**
** @(#) $Id: sqliteInt.h,v 1.686 2008/04/01 05:07:15 drh Exp $
*/
#ifndef _SQLITEINT_H_
#define _SQLITEINT_H_

/*
** Include the configuration header output by 'configure' if it was run
** (otherwise we get an empty default).
................................................................................
#define EP_Resolved   0x0004  /* IDs have been resolved to COLUMNs */
#define EP_Error      0x0008  /* Expression contains one or more errors */
#define EP_Distinct   0x0010  /* Aggregate function with DISTINCT keyword */
#define EP_VarSelect  0x0020  /* pSelect is correlated, not constant */
#define EP_Dequoted   0x0040  /* True if the string has been dequoted */
#define EP_InfixFunc  0x0080  /* True for an infix function: LIKE, GLOB, etc */
#define EP_ExpCollate 0x0100  /* Collating sequence specified explicitly */
#define EP_AnyAff     0x0200  /* Can take a cached column of any affinity */

/*
** These macros can be used to test, set, or clear bits in the 
** Expr.flags field.
*/
#define ExprHasProperty(E,P)     (((E)->flags&(P))==(P))
#define ExprHasAnyProperty(E,P)  (((E)->flags&(P))!=0)
................................................................................
  int ckBase;          /* Base register of data during check constraints */
  int disableColCache; /* True to disable adding to column cache */
  int nColCache;       /* Number of entries in the column cache */
  int iColCache;       /* Next entry of the cache to replace */
  struct yColCache {
    int iTable;           /* Table cursor number */
    int iColumn;          /* Table column number */
    char affChange;       /* True if this register has had an affinity change */
    int iReg;             /* Register holding value of this column */
  } aColCache[10];     /* One for each valid column cache entry */
  u32 writeMask;       /* Start a write transaction on these databases */
  u32 cookieMask;      /* Bitmask of schema verified databases */
  int cookieGoto;      /* Address of OP_Goto to cookie verifier subroutine */
  int cookieValue[SQLITE_MAX_ATTACHED+2];  /* Values of cookies to verify */
#ifndef SQLITE_OMIT_SHARED_CACHE
................................................................................
Table *sqlite3SrcListLookup(Parse*, SrcList*);
int sqlite3IsReadOnly(Parse*, Table*, int);
void sqlite3OpenTable(Parse*, int iCur, int iDb, Table*, int);
void sqlite3DeleteFrom(Parse*, SrcList*, Expr*);
void sqlite3Update(Parse*, SrcList*, ExprList*, Expr*, int);
WhereInfo *sqlite3WhereBegin(Parse*, SrcList*, Expr*, ExprList**, u8);
void sqlite3WhereEnd(WhereInfo*);
int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int, int);
void sqlite3ExprCodeMove(Parse*, int, int);
void sqlite3ExprClearColumnCache(Parse*, int);
void sqlite3ExprColumnCacheDisable(Parse*, int);
void sqlite3ExprCacheAffinityChange(Parse*, int, int);
int sqlite3ExprWritableRegister(Parse*,int,int);
int sqlite3ExprCode(Parse*, Expr*, int);
int sqlite3ExprCodeTemp(Parse*, Expr*, int*);
int sqlite3ExprCodeTarget(Parse*, Expr*, int);
int sqlite3ExprCodeAndCache(Parse*, Expr*, int);
void sqlite3ExprCodeConstants(Parse*, Expr*);
int sqlite3ExprCodeExprList(Parse*, ExprList*, int);

Changes to src/update.c.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle UPDATE statements.
**
** $Id: update.c,v 1.174 2008/03/31 23:48:05 drh Exp $
*/
#include "sqliteInt.h"

#ifndef SQLITE_OMIT_VIRTUALTABLE
/* Forward declaration */
static void updateVirtualTable(
  Parse *pParse,       /* The parsing context */
................................................................................
      }else{
        sqlite3VdbeAddOp2(v, OP_Null, 0, regCols+i);
      }
    }
    sqlite3VdbeAddOp3(v, OP_MakeRecord, regCols, pTab->nCol, regRow);
    if( !isView ){
      sqlite3TableAffinityStr(v, pTab);
      sqlite3ExprExpireColumnCacheLines(pParse, regCols, regCols+pTab->nCol-1);
    }
    sqlite3ReleaseTempRange(pParse, regCols, pTab->nCol);
    if( pParse->nErr ) goto update_cleanup;
    sqlite3VdbeAddOp3(v, OP_Insert, newIdx, regRow, regRowid);
    sqlite3ReleaseTempReg(pParse, regRowid);
    sqlite3ReleaseTempReg(pParse, regRow);








|







 







|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle UPDATE statements.
**
** $Id: update.c,v 1.175 2008/04/01 05:07:15 drh Exp $
*/
#include "sqliteInt.h"

#ifndef SQLITE_OMIT_VIRTUALTABLE
/* Forward declaration */
static void updateVirtualTable(
  Parse *pParse,       /* The parsing context */
................................................................................
      }else{
        sqlite3VdbeAddOp2(v, OP_Null, 0, regCols+i);
      }
    }
    sqlite3VdbeAddOp3(v, OP_MakeRecord, regCols, pTab->nCol, regRow);
    if( !isView ){
      sqlite3TableAffinityStr(v, pTab);
      sqlite3ExprCacheAffinityChange(pParse, regCols, pTab->nCol);
    }
    sqlite3ReleaseTempRange(pParse, regCols, pTab->nCol);
    if( pParse->nErr ) goto update_cleanup;
    sqlite3VdbeAddOp3(v, OP_Insert, newIdx, regRow, regRowid);
    sqlite3ReleaseTempReg(pParse, regRowid);
    sqlite3ReleaseTempReg(pParse, regRow);

Changes to src/where.c.

12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
....
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
** This module contains C code that generates VDBE code used to process
** the WHERE clause of SQL statements.  This module is reponsible for
** generating the code that loops through a table looking for applicable
** rows.  Indices are selected and used to speed the search when doing
** so is applicable.  Because this module is responsible for selecting
** indices, you might also think of this module as the "query optimizer".
**
** $Id: where.c,v 1.296 2008/03/31 23:48:05 drh Exp $
*/
#include "sqliteInt.h"

/*
** The number of bits in a Bitmask.  "BMS" means "BitMask Size".
*/
#define BMS  (sizeof(Bitmask)*8)
................................................................................
){
  Vdbe *v = pParse->pVdbe;
  assert( regSrc>0 );
  assert( regDest>0 );
  assert( v!=0 );
  sqlite3VdbeAddOp3(v, OP_MakeRecord, regSrc, nColumn, regDest);
  sqlite3IndexAffinityStr(v, pIdx);
  sqlite3ExprExpireColumnCacheLines(pParse, regSrc, regSrc+nColumn-1);
}


/*
** Generate code for a single equality term of the WHERE clause.  An equality
** term can be either X=expr or X IN (...).   pTerm is the term to be 
** coded.







|







 







|







12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
....
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
** This module contains C code that generates VDBE code used to process
** the WHERE clause of SQL statements.  This module is reponsible for
** generating the code that loops through a table looking for applicable
** rows.  Indices are selected and used to speed the search when doing
** so is applicable.  Because this module is responsible for selecting
** indices, you might also think of this module as the "query optimizer".
**
** $Id: where.c,v 1.297 2008/04/01 05:07:15 drh Exp $
*/
#include "sqliteInt.h"

/*
** The number of bits in a Bitmask.  "BMS" means "BitMask Size".
*/
#define BMS  (sizeof(Bitmask)*8)
................................................................................
){
  Vdbe *v = pParse->pVdbe;
  assert( regSrc>0 );
  assert( regDest>0 );
  assert( v!=0 );
  sqlite3VdbeAddOp3(v, OP_MakeRecord, regSrc, nColumn, regDest);
  sqlite3IndexAffinityStr(v, pIdx);
  sqlite3ExprCacheAffinityChange(pParse, regSrc, nColumn);
}


/*
** Generate code for a single equality term of the WHERE clause.  An equality
** term can be either X=expr or X IN (...).   pTerm is the term to be 
** coded.