/ Check-in [1186e3ce]
Login

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

Overview
Comment:Various size optimizations. (CVS 1867)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:1186e3ce0b660f1cf8d03a275b0331da64d21f1b
User & Date: drh 2004-07-26 00:31:09
Context
2004-07-26
12:24
Fix problems for 64-bit machines and when SQLITE_OMIT_AUTHORIZATION is defined. (CVS 1868) check-in: e3cad1ab user: drh tags: trunk
00:31
Various size optimizations. (CVS 1867) check-in: 1186e3ce user: drh tags: trunk
2004-07-24
17:38
Prepared statements now work with CREATE and DROP. All tests pass. No memory leaks. (CVS 1866) check-in: ebdb661e user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/build.c.

19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
....
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
....
2399
2400
2401
2402
2403
2404
2405

2406
2407
2408
2409
2410
2411

2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
**     DROP INDEX
**     creating ID lists
**     BEGIN TRANSACTION
**     COMMIT
**     ROLLBACK
**     PRAGMA
**
** $Id: build.c,v 1.243 2004/07/24 17:38:29 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

/*
** This routine is called when a new SQL statement is beginning to
** be parsed.  Check to see if the schema for the database needs
................................................................................
    sqlite3EndWriteOperation(pParse);
  }

  /* Add the table to the in-memory representation of the database.
  */
  if( db->init.busy && pParse->nErr==0 ){
    Table *pOld;
    FKey *pFKey;
    pOld = sqlite3HashInsert(&db->aDb[p->iDb].tblHash, 
                            p->zName, strlen(p->zName)+1, p);
    if( pOld ){
      assert( p==pOld );  /* Malloc must have failed inside HashInsert() */
      return;
    }
    for(pFKey=p->pFKey; pFKey; pFKey=pFKey->pNextFrom){
      int nTo = strlen(pFKey->zTo) + 1;
      pFKey->pNextTo = sqlite3HashFind(&db->aDb[p->iDb].aFKey, pFKey->zTo, nTo);
      sqlite3HashInsert(&db->aDb[p->iDb].aFKey, pFKey->zTo, nTo, pFKey);
    }
    pParse->pNewTable = 0;
    db->nTable++;
    db->flags |= SQLITE_InternChanges;
  }
}

................................................................................
}

/*
** Delete an entire SrcList including all its substructure.
*/
void sqlite3SrcListDelete(SrcList *pList){
  int i;

  if( pList==0 ) return;
  for(i=0; i<pList->nSrc; i++){
    sqliteFree(pList->a[i].zDatabase);
    sqliteFree(pList->a[i].zName);
    sqliteFree(pList->a[i].zAlias);
    if( pList->a[i].pTab && pList->a[i].pTab->isTransient ){

      sqlite3DeleteTable(0, pList->a[i].pTab);
    }
    sqlite3SelectDelete(pList->a[i].pSelect);
    sqlite3ExprDelete(pList->a[i].pOn);
    sqlite3IdListDelete(pList->a[i].pUsing);
  }
  sqliteFree(pList);
}

/*
** Begin a transaction
*/







|







 







|
|
|






|
|







 







>

|
|
|
|
<
>
|

|
|
|







19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
....
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
....
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411

2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
**     DROP INDEX
**     creating ID lists
**     BEGIN TRANSACTION
**     COMMIT
**     ROLLBACK
**     PRAGMA
**
** $Id: build.c,v 1.244 2004/07/26 00:31:09 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

/*
** This routine is called when a new SQL statement is beginning to
** be parsed.  Check to see if the schema for the database needs
................................................................................
    sqlite3EndWriteOperation(pParse);
  }

  /* Add the table to the in-memory representation of the database.
  */
  if( db->init.busy && pParse->nErr==0 ){
    Table *pOld;
    FKey *pFKey; 
    Db *pDb = &db->aDb[p->iDb];
    pOld = sqlite3HashInsert(&pDb->tblHash, p->zName, strlen(p->zName)+1, p);
    if( pOld ){
      assert( p==pOld );  /* Malloc must have failed inside HashInsert() */
      return;
    }
    for(pFKey=p->pFKey; pFKey; pFKey=pFKey->pNextFrom){
      int nTo = strlen(pFKey->zTo) + 1;
      pFKey->pNextTo = sqlite3HashFind(&pDb->aFKey, pFKey->zTo, nTo);
      sqlite3HashInsert(&pDb->aFKey, pFKey->zTo, nTo, pFKey);
    }
    pParse->pNewTable = 0;
    db->nTable++;
    db->flags |= SQLITE_InternChanges;
  }
}

................................................................................
}

/*
** Delete an entire SrcList including all its substructure.
*/
void sqlite3SrcListDelete(SrcList *pList){
  int i;
  struct SrcList_item *pItem;
  if( pList==0 ) return;
  for(pItem=pList->a, i=0; i<pList->nSrc; i++, pItem++){
    sqliteFree(pItem->zDatabase);
    sqliteFree(pItem->zName);
    sqliteFree(pItem->zAlias);

    if( pItem->pTab && pItem->pTab->isTransient ){
      sqlite3DeleteTable(0, pItem->pTab);
    }
    sqlite3SelectDelete(pItem->pSelect);
    sqlite3ExprDelete(pItem->pOn);
    sqlite3IdListDelete(pItem->pUsing);
  }
  sqliteFree(pList);
}

/*
** Begin a transaction
*/

Changes to src/expr.c.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
166
167
168
169
170
171
172
















173
174
175
176
177
178
179
...
429
430
431
432
433
434
435

436
437
438
439
440
441
442
443
444
445
446
447
448
...
856
857
858
859
860
861
862

863
864
865

866
867
868
869
870
871
872
873
874
....
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159

1160
1161
1162
1163
1164
1165
1166
....
1277
1278
1279
1280
1281
1282
1283
1284
1285

1286
1287
1288
1289
1290
1291
1292


1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
....
1304
1305
1306
1307
1308
1309
1310


1311
1312
1313
1314
1315


1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
....
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443

1444
1445
1446
1447
1448
1449
1450
....
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468

1469
1470
1471
1472

1473
1474
1475
1476
1477
1478
1479
....
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537

1538
1539
1540
1541
1542
1543
1544
....
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562

1563
1564

1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
**    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.152 2004/07/21 02:53:30 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

char const *sqlite3AffinityString(char affinity){
  switch( affinity ){
    case SQLITE_AFF_INTEGER: return "i";
................................................................................
static CollSeq* binaryCompareCollSeq(Parse *pParse, Expr *pLeft, Expr *pRight){
  CollSeq *pColl = sqlite3ExprCollSeq(pParse, pLeft);
  if( !pColl ){
    pColl = sqlite3ExprCollSeq(pParse, pRight);
  }
  return pColl;
}

















/*
** Construct a new expression node and return a pointer to it.  Memory
** for this node is obtained from sqliteMalloc().  The calling function
** is responsible for making sure the node eventually gets freed.
*/
Expr *sqlite3Expr(int op, Expr *pLeft, Expr *pRight, Token *pToken){
................................................................................
}

/*
** Delete an entire expression list.
*/
void sqlite3ExprListDelete(ExprList *pList){
  int i;

  if( pList==0 ) return;
  assert( pList->a!=0 || (pList->nExpr==0 && pList->nAlloc==0) );
  assert( pList->nExpr<=pList->nAlloc );
  for(i=0; i<pList->nExpr; i++){
    sqlite3ExprDelete(pList->a[i].pExpr);
    sqliteFree(pList->a[i].zName);
  }
  sqliteFree(pList->a);
  sqliteFree(pList);
}

/*
** Walk an expression tree.  Return 1 if the expression is constant
................................................................................
      if( pExpr->pSelect ){
        /* Case 1:     expr IN (SELECT ...)
        **
        ** Generate code to write the results of the select into the temporary
        ** table allocated and opened above.
        */
        int iParm = pExpr->iTable +  (((int)affinity)<<16);

        assert( (pExpr->iTable&0x0000FFFF)==pExpr->iTable );
        sqlite3Select(pParse, pExpr->pSelect, SRT_Set, iParm, 0, 0, 0, 0);
        if( pExpr->pSelect->pEList && pExpr->pSelect->pEList->nExpr>0 ){ 

          keyInfo.aColl[0] = binaryCompareCollSeq(pParse, pExpr->pLeft,
              pExpr->pSelect->pEList->a[0].pExpr);
        }
      }else if( pExpr->pList ){
        /* Case 2:     expr IN (exprlist)
        **
	** For each expression, build an index key from the evaluation and
        ** store it in the temporary table. If <expr> is a column, then use
        ** that columns affinity when building index keys. If <expr> is not
................................................................................
    }
    case TK_LT:
    case TK_LE:
    case TK_GT:
    case TK_GE:
    case TK_NE:
    case TK_EQ: {
      int p1 = binaryCompareP1(pExpr->pLeft, pExpr->pRight, 0);
      CollSeq *p3 = binaryCompareCollSeq(pParse, pExpr->pLeft, pExpr->pRight);
      sqlite3ExprCode(pParse, pExpr->pLeft);
      sqlite3ExprCode(pParse, pExpr->pRight);
      sqlite3VdbeOp3(v, op, p1, 0, (void *)p3, P3_COLLSEQ);

      break;
    }
    case TK_AND:
    case TK_OR:
    case TK_PLUS:
    case TK_STAR:
    case TK_MINUS:
................................................................................
      sqlite3VdbeOp3(v, OP_MakeRecord, 1, 0, affStr, P3_STATIC); /* addr + 4 */
      sqlite3VdbeAddOp(v, OP_Found, pExpr->iTable, addr+7);
      sqlite3VdbeAddOp(v, OP_AddImm, -1, 0);                  /* addr + 6 */

      break;
    }
    case TK_BETWEEN: {
      int p1;
      CollSeq *p3;

      sqlite3ExprCode(pParse, pExpr->pLeft);
      sqlite3VdbeAddOp(v, OP_Dup, 0, 0);
      sqlite3ExprCode(pParse, pExpr->pList->a[0].pExpr);
      p1 = binaryCompareP1(pExpr->pLeft, pExpr->pList->a[0].pExpr, 0);
      p3 = binaryCompareCollSeq(pParse, pExpr->pLeft, pExpr->pList->a[0].pExpr);
      sqlite3VdbeOp3(v, OP_Ge, p1, 0, (void *)p3, P3_COLLSEQ);
      sqlite3VdbeAddOp(v, OP_Pull, 1, 0);


      sqlite3ExprCode(pParse, pExpr->pList->a[1].pExpr);
      p1 = binaryCompareP1(pExpr->pLeft, pExpr->pList->a[1].pExpr, 0);
      p3 = binaryCompareCollSeq(pParse, pExpr->pLeft, pExpr->pList->a[1].pExpr);
      sqlite3VdbeOp3(v, OP_Le, p1, 0, (void *)p3, P3_COLLSEQ);
      sqlite3VdbeAddOp(v, OP_And, 0, 0);
      break;
    }
    case TK_UPLUS:
    case TK_AS: {
      sqlite3ExprCode(pParse, pExpr->pLeft);
      break;
................................................................................
    }
    case TK_CASE: {
      int expr_end_label;
      int jumpInst;
      int addr;
      int nExpr;
      int i;



      assert(pExpr->pList);
      assert((pExpr->pList->nExpr % 2) == 0);
      assert(pExpr->pList->nExpr > 0);
      nExpr = pExpr->pList->nExpr;


      expr_end_label = sqlite3VdbeMakeLabel(v);
      if( pExpr->pLeft ){
        sqlite3ExprCode(pParse, pExpr->pLeft);
      }
      for(i=0; i<nExpr; i=i+2){
        sqlite3ExprCode(pParse, pExpr->pList->a[i].pExpr);
        if( pExpr->pLeft ){
          int p1 = binaryCompareP1(pExpr->pLeft, pExpr->pList->a[i].pExpr, 1);
          CollSeq *p3 = binaryCompareCollSeq(pParse, pExpr->pLeft, 
              pExpr->pList->a[i].pExpr);
          sqlite3VdbeAddOp(v, OP_Dup, 1, 1);
          jumpInst = sqlite3VdbeOp3(v, OP_Ne, p1, 0, (void *)p3, P3_COLLSEQ);
          sqlite3VdbeAddOp(v, OP_Pop, 1, 0);
        }else{
          jumpInst = sqlite3VdbeAddOp(v, OP_IfNot, 1, 0);
        }
        sqlite3ExprCode(pParse, pExpr->pList->a[i+1].pExpr);
        sqlite3VdbeAddOp(v, OP_Goto, 0, expr_end_label);
        addr = sqlite3VdbeCurrentAddr(v);
        sqlite3VdbeChangeP2(v, jumpInst, addr);
      }
      if( pExpr->pLeft ){
        sqlite3VdbeAddOp(v, OP_Pop, 1, 0);
      }
................................................................................
    }
    case TK_LT:
    case TK_LE:
    case TK_GT:
    case TK_GE:
    case TK_NE:
    case TK_EQ: {
      int p1 = binaryCompareP1(pExpr->pLeft, pExpr->pRight, jumpIfNull);
      CollSeq *p3 = binaryCompareCollSeq(pParse, pExpr->pLeft, pExpr->pRight);
      sqlite3ExprCode(pParse, pExpr->pLeft);
      sqlite3ExprCode(pParse, pExpr->pRight);
      sqlite3VdbeOp3(v, op, p1, dest, (void *)p3, P3_COLLSEQ);

      break;
    }
    case TK_ISNULL:
    case TK_NOTNULL: {
      sqlite3ExprCode(pParse, pExpr->pLeft);
      sqlite3VdbeAddOp(v, op, 1, dest);
      break;
................................................................................
      /* The expression "x BETWEEN y AND z" is implemented as:
      **
      ** 1 IF (x < y) GOTO 3
      ** 2 IF (x <= z) GOTO <dest>
      ** 3 ...
      */
      int addr;
      int p1;
      CollSeq *p3;
      sqlite3ExprCode(pParse, pExpr->pLeft);
      sqlite3VdbeAddOp(v, OP_Dup, 0, 0);
      sqlite3ExprCode(pParse, pExpr->pList->a[0].pExpr);
      p1 = binaryCompareP1(pExpr->pLeft, pExpr->pList->a[0].pExpr, !jumpIfNull);
      p3 = binaryCompareCollSeq(pParse, pExpr->pLeft, pExpr->pList->a[0].pExpr);
      addr = sqlite3VdbeOp3(v, OP_Lt, p1, 0, (void *)p3, P3_COLLSEQ);


      sqlite3ExprCode(pParse, pExpr->pList->a[1].pExpr);
      p1 = binaryCompareP1(pExpr->pLeft, pExpr->pList->a[1].pExpr, jumpIfNull);
      p3 = binaryCompareCollSeq(pParse, pExpr->pLeft, pExpr->pList->a[1].pExpr);
      sqlite3VdbeOp3(v, OP_Le, p1, dest, (void *)p3, P3_COLLSEQ);


      sqlite3VdbeAddOp(v, OP_Integer, 0, 0);
      sqlite3VdbeChangeP2(v, addr, sqlite3VdbeCurrentAddr(v));
      sqlite3VdbeAddOp(v, OP_Pop, 1, 0);
      break;
    }
    default: {
................................................................................
    }
    case TK_LT:
    case TK_LE:
    case TK_GT:
    case TK_GE:
    case TK_NE:
    case TK_EQ: {
      int p1 = binaryCompareP1(pExpr->pLeft, pExpr->pRight, jumpIfNull);
      CollSeq *p3 = binaryCompareCollSeq(pParse, pExpr->pLeft, pExpr->pRight);
      sqlite3ExprCode(pParse, pExpr->pLeft);
      sqlite3ExprCode(pParse, pExpr->pRight);
      sqlite3VdbeOp3(v, op, p1, dest, (void *)p3, P3_COLLSEQ);

      break;
    }
    case TK_ISNULL:
    case TK_NOTNULL: {
      sqlite3ExprCode(pParse, pExpr->pLeft);
      sqlite3VdbeAddOp(v, op, 1, dest);
      break;
................................................................................
      /* The expression is "x BETWEEN y AND z". It is implemented as:
      **
      ** 1 IF (x >= y) GOTO 3
      ** 2 GOTO <dest>
      ** 3 IF (x > z) GOTO <dest>
      */
      int addr;
      int p1;
      CollSeq *p3;
      sqlite3ExprCode(pParse, pExpr->pLeft);
      sqlite3VdbeAddOp(v, OP_Dup, 0, 0);
      sqlite3ExprCode(pParse, pExpr->pList->a[0].pExpr);
      addr = sqlite3VdbeCurrentAddr(v);
      p1 = binaryCompareP1(pExpr->pLeft, pExpr->pList->a[0].pExpr, !jumpIfNull);
      p3 = binaryCompareCollSeq(pParse, pExpr->pLeft, pExpr->pList->a[0].pExpr);
      sqlite3VdbeOp3(v, OP_Ge, p1, addr+3, (void *)p3, P3_COLLSEQ);

      sqlite3VdbeAddOp(v, OP_Pop, 1, 0);
      sqlite3VdbeAddOp(v, OP_Goto, 0, dest);

      sqlite3ExprCode(pParse, pExpr->pList->a[1].pExpr);
      p1 = binaryCompareP1(pExpr->pLeft, pExpr->pList->a[1].pExpr, jumpIfNull);
      p3 = binaryCompareCollSeq(pParse, pExpr->pLeft, pExpr->pList->a[1].pExpr);
      sqlite3VdbeOp3(v, OP_Gt, p1, dest, (void *)p3, P3_COLLSEQ);
      break;
    }
    default: {
      sqlite3ExprCode(pParse, pExpr);
      sqlite3VdbeAddOp(v, OP_IfNot, jumpIfNull, dest);
      break;
    }







|







 







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







 







>



|
|
|







 







>


|
>

|







 







<
<


<
>







 







|
|
>
|

|
<
|
<

>
>
|
<
|
<







 







>
>




|
>
>





|
|
|
|
|
<
<




|







 







<
<


<
>







 







|
|
|

|
|
<
<

>
|
<
<
<
>







 







<
<


<
>







 







|
|
|

|

|
<
<
>


>
|
|
<
<







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
...
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
...
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
....
1167
1168
1169
1170
1171
1172
1173


1174
1175

1176
1177
1178
1179
1180
1181
1182
1183
....
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306

1307

1308
1309
1310
1311

1312

1313
1314
1315
1316
1317
1318
1319
....
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345


1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
....
1450
1451
1452
1453
1454
1455
1456


1457
1458

1459
1460
1461
1462
1463
1464
1465
1466
....
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481


1482
1483
1484



1485
1486
1487
1488
1489
1490
1491
1492
....
1539
1540
1541
1542
1543
1544
1545


1546
1547

1548
1549
1550
1551
1552
1553
1554
1555
....
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571


1572
1573
1574
1575
1576
1577


1578
1579
1580
1581
1582
1583
1584
**    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.153 2004/07/26 00:31:09 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

char const *sqlite3AffinityString(char affinity){
  switch( affinity ){
    case SQLITE_AFF_INTEGER: return "i";
................................................................................
static CollSeq* binaryCompareCollSeq(Parse *pParse, Expr *pLeft, Expr *pRight){
  CollSeq *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 */
  Expr *pRight,     /* The right operand */
  int opcode,       /* The comparison opcode */
  int dest,         /* Jump here if true.  */
  int jumpIfNull    /* If true, jump if either operand is NULL */
){
  int p1 = binaryCompareP1(pLeft, pRight, jumpIfNull);
  CollSeq *p3 = binaryCompareCollSeq(pParse, pLeft, pRight);
  return sqlite3VdbeOp3(pParse->pVdbe, opcode, p1, dest, (void *)p3, P3_COLLSEQ);
}

/*
** Construct a new expression node and return a pointer to it.  Memory
** for this node is obtained from sqliteMalloc().  The calling function
** is responsible for making sure the node eventually gets freed.
*/
Expr *sqlite3Expr(int op, Expr *pLeft, Expr *pRight, Token *pToken){
................................................................................
}

/*
** Delete an entire expression list.
*/
void sqlite3ExprListDelete(ExprList *pList){
  int i;
  struct ExprList_item *pItem;
  if( pList==0 ) return;
  assert( pList->a!=0 || (pList->nExpr==0 && pList->nAlloc==0) );
  assert( pList->nExpr<=pList->nAlloc );
  for(pItem=pList->a, i=0; i<pList->nExpr; i++, pItem++){
    sqlite3ExprDelete(pItem->pExpr);
    sqliteFree(pItem->zName);
  }
  sqliteFree(pList->a);
  sqliteFree(pList);
}

/*
** Walk an expression tree.  Return 1 if the expression is constant
................................................................................
      if( pExpr->pSelect ){
        /* Case 1:     expr IN (SELECT ...)
        **
        ** Generate code to write the results of the select into the temporary
        ** table allocated and opened above.
        */
        int iParm = pExpr->iTable +  (((int)affinity)<<16);
        ExprList *pEList;
        assert( (pExpr->iTable&0x0000FFFF)==pExpr->iTable );
        sqlite3Select(pParse, pExpr->pSelect, SRT_Set, iParm, 0, 0, 0, 0);
        pEList = pExpr->pSelect->pEList;
        if( pEList && pEList->nExpr>0 ){ 
          keyInfo.aColl[0] = binaryCompareCollSeq(pParse, pExpr->pLeft,
              pEList->a[0].pExpr);
        }
      }else if( pExpr->pList ){
        /* Case 2:     expr IN (exprlist)
        **
	** For each expression, build an index key from the evaluation and
        ** store it in the temporary table. If <expr> is a column, then use
        ** that columns affinity when building index keys. If <expr> is not
................................................................................
    }
    case TK_LT:
    case TK_LE:
    case TK_GT:
    case TK_GE:
    case TK_NE:
    case TK_EQ: {


      sqlite3ExprCode(pParse, pExpr->pLeft);
      sqlite3ExprCode(pParse, pExpr->pRight);

      codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, 0, 0);
      break;
    }
    case TK_AND:
    case TK_OR:
    case TK_PLUS:
    case TK_STAR:
    case TK_MINUS:
................................................................................
      sqlite3VdbeOp3(v, OP_MakeRecord, 1, 0, affStr, P3_STATIC); /* addr + 4 */
      sqlite3VdbeAddOp(v, OP_Found, pExpr->iTable, addr+7);
      sqlite3VdbeAddOp(v, OP_AddImm, -1, 0);                  /* addr + 6 */

      break;
    }
    case TK_BETWEEN: {
      Expr *pLeft = pExpr->pLeft;
      struct ExprList_item *pLItem = pExpr->pList->a;
      Expr *pRight = pLItem->pExpr;
      sqlite3ExprCode(pParse, pLeft);
      sqlite3VdbeAddOp(v, OP_Dup, 0, 0);
      sqlite3ExprCode(pParse, pRight);

      codeCompare(pParse, pLeft, pRight, OP_Ge, 0, 0);

      sqlite3VdbeAddOp(v, OP_Pull, 1, 0);
      pLItem++;
      pRight = pLItem->pExpr;
      sqlite3ExprCode(pParse, pRight);

      codeCompare(pParse, pLeft, pRight, OP_Le, 0, 0);

      sqlite3VdbeAddOp(v, OP_And, 0, 0);
      break;
    }
    case TK_UPLUS:
    case TK_AS: {
      sqlite3ExprCode(pParse, pExpr->pLeft);
      break;
................................................................................
    }
    case TK_CASE: {
      int expr_end_label;
      int jumpInst;
      int addr;
      int nExpr;
      int i;
      ExprList *pEList;
      struct ExprList_item *aListelem;

      assert(pExpr->pList);
      assert((pExpr->pList->nExpr % 2) == 0);
      assert(pExpr->pList->nExpr > 0);
      pEList = pExpr->pList;
      aListelem = pEList->a;
      nExpr = pEList->nExpr;
      expr_end_label = sqlite3VdbeMakeLabel(v);
      if( pExpr->pLeft ){
        sqlite3ExprCode(pParse, pExpr->pLeft);
      }
      for(i=0; i<nExpr; i=i+2){
        sqlite3ExprCode(pParse, aListelem[i].pExpr);
        if( pExpr->pLeft ){
          sqlite3VdbeAddOp(v, OP_Dup, 1, 1);
          jumpInst = codeCompare(pParse, pExpr->pLeft, aListelem[i].pExpr,
                                 OP_Ne, 0, 1);


          sqlite3VdbeAddOp(v, OP_Pop, 1, 0);
        }else{
          jumpInst = sqlite3VdbeAddOp(v, OP_IfNot, 1, 0);
        }
        sqlite3ExprCode(pParse, aListelem[i+1].pExpr);
        sqlite3VdbeAddOp(v, OP_Goto, 0, expr_end_label);
        addr = sqlite3VdbeCurrentAddr(v);
        sqlite3VdbeChangeP2(v, jumpInst, addr);
      }
      if( pExpr->pLeft ){
        sqlite3VdbeAddOp(v, OP_Pop, 1, 0);
      }
................................................................................
    }
    case TK_LT:
    case TK_LE:
    case TK_GT:
    case TK_GE:
    case TK_NE:
    case TK_EQ: {


      sqlite3ExprCode(pParse, pExpr->pLeft);
      sqlite3ExprCode(pParse, pExpr->pRight);

      codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, dest, jumpIfNull);
      break;
    }
    case TK_ISNULL:
    case TK_NOTNULL: {
      sqlite3ExprCode(pParse, pExpr->pLeft);
      sqlite3VdbeAddOp(v, op, 1, dest);
      break;
................................................................................
      /* The expression "x BETWEEN y AND z" is implemented as:
      **
      ** 1 IF (x < y) GOTO 3
      ** 2 IF (x <= z) GOTO <dest>
      ** 3 ...
      */
      int addr;
      Expr *pLeft = pExpr->pLeft;
      Expr *pRight = pExpr->pList->a[0].pExpr;
      sqlite3ExprCode(pParse, pLeft);
      sqlite3VdbeAddOp(v, OP_Dup, 0, 0);
      sqlite3ExprCode(pParse, pRight);
      addr = codeCompare(pParse, pLeft, pRight, OP_Lt, 0, !jumpIfNull);



      pRight = pExpr->pList->a[1].pExpr;
      sqlite3ExprCode(pParse, pRight);



      codeCompare(pParse, pLeft, pRight, OP_Le, dest, jumpIfNull);

      sqlite3VdbeAddOp(v, OP_Integer, 0, 0);
      sqlite3VdbeChangeP2(v, addr, sqlite3VdbeCurrentAddr(v));
      sqlite3VdbeAddOp(v, OP_Pop, 1, 0);
      break;
    }
    default: {
................................................................................
    }
    case TK_LT:
    case TK_LE:
    case TK_GT:
    case TK_GE:
    case TK_NE:
    case TK_EQ: {


      sqlite3ExprCode(pParse, pExpr->pLeft);
      sqlite3ExprCode(pParse, pExpr->pRight);

      codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, dest, jumpIfNull);
      break;
    }
    case TK_ISNULL:
    case TK_NOTNULL: {
      sqlite3ExprCode(pParse, pExpr->pLeft);
      sqlite3VdbeAddOp(v, op, 1, dest);
      break;
................................................................................
      /* The expression is "x BETWEEN y AND z". It is implemented as:
      **
      ** 1 IF (x >= y) GOTO 3
      ** 2 GOTO <dest>
      ** 3 IF (x > z) GOTO <dest>
      */
      int addr;
      Expr *pLeft = pExpr->pLeft;
      Expr *pRight = pExpr->pList->a[0].pExpr;
      sqlite3ExprCode(pParse, pLeft);
      sqlite3VdbeAddOp(v, OP_Dup, 0, 0);
      sqlite3ExprCode(pParse, pRight);
      addr = sqlite3VdbeCurrentAddr(v);
      codeCompare(pParse, pLeft, pRight, OP_Ge, addr+3, !jumpIfNull);



      sqlite3VdbeAddOp(v, OP_Pop, 1, 0);
      sqlite3VdbeAddOp(v, OP_Goto, 0, dest);
      pRight = pExpr->pList->a[1].pExpr;
      sqlite3ExprCode(pParse, pRight);
      codeCompare(pParse, pLeft, pRight, OP_Gt, dest, jumpIfNull);


      break;
    }
    default: {
      sqlite3ExprCode(pParse, pExpr);
      sqlite3VdbeAddOp(v, OP_IfNot, jumpIfNull, dest);
      break;
    }