SQLite

Check-in [a4af838f8d]
Login

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

Overview
Comment:More changes to support the manifest type model. A few things are currently broken. (CVS 1385)
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: a4af838f8d1b81ec6c8db97655c6876aca0738d9
User & Date: danielk1977 2004-05-16 11:15:36.000
Context
2004-05-16
11:57
Fix two bugs that were causing lots of tests to fail. (CVS 1386) (check-in: 5cba8a510c user: danielk1977 tags: trunk)
11:15
More changes to support the manifest type model. A few things are currently broken. (CVS 1385) (check-in: a4af838f8d user: danielk1977 tags: trunk)
2004-05-15
00:29
More speed improvements to btree. (CVS 1384) (check-in: aab4b794b4 user: drh tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/build.c.
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
**     DROP INDEX
**     creating ID lists
**     BEGIN TRANSACTION
**     COMMIT
**     ROLLBACK
**     PRAGMA
**
** $Id: build.c,v 1.183 2004/05/14 11:00:53 danielk1977 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







|







19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
**     DROP INDEX
**     creating ID lists
**     BEGIN TRANSACTION
**     COMMIT
**     ROLLBACK
**     PRAGMA
**
** $Id: build.c,v 1.184 2004/05/16 11:15:36 danielk1977 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
180
181
182
183
184
185
186



187
188
189
190
191
192
193
  assert( db!=0 && p->zName!=0 );
  pOld = sqlite3HashInsert(&db->aDb[p->iDb].idxHash, p->zName,
                          strlen(p->zName)+1, 0);
  if( pOld!=0 && pOld!=p ){
    sqlite3HashInsert(&db->aDb[p->iDb].idxHash, pOld->zName,
                     strlen(pOld->zName)+1, pOld);
  }



  sqliteFree(p);
}

/*
** Unlink the given index from its table, then remove
** the index from the index hash table and free its memory
** structures.







>
>
>







180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
  assert( db!=0 && p->zName!=0 );
  pOld = sqlite3HashInsert(&db->aDb[p->iDb].idxHash, p->zName,
                          strlen(p->zName)+1, 0);
  if( pOld!=0 && pOld!=p ){
    sqlite3HashInsert(&db->aDb[p->iDb].idxHash, pOld->zName,
                     strlen(pOld->zName)+1, pOld);
  }
  if( p->zColAff ){
    sqliteFree(p->zColAff);
  }
  sqliteFree(p);
}

/*
** Unlink the given index from its table, then remove
** the index from the index hash table and free its memory
** structures.
577
578
579
580
581
582
583
584





585
586
587
588
589
590
591
    aNew = sqliteRealloc( p->aCol, (p->nCol+8)*sizeof(p->aCol[0]));
    if( aNew==0 ) return;
    p->aCol = aNew;
  }
  pCol = &p->aCol[p->nCol];
  memset(pCol, 0, sizeof(p->aCol[0]));
  pCol->zName = z;
  pCol->sortOrder = SQLITE_SO_NUM;





  p->nCol++;
}

/*
** This routine is called by the parser while in the middle of
** parsing a CREATE TABLE statement.  A "NOT NULL" constraint has
** been seen on a column.  This routine sets the notNull flag on







|
>
>
>
>
>







580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
    aNew = sqliteRealloc( p->aCol, (p->nCol+8)*sizeof(p->aCol[0]));
    if( aNew==0 ) return;
    p->aCol = aNew;
  }
  pCol = &p->aCol[p->nCol];
  memset(pCol, 0, sizeof(p->aCol[0]));
  pCol->zName = z;
 
  /* If there is no type specified, columns have the default affinity
  ** 'NONE'. If there is a type specified, then sqlite3AddColumnType()
  ** will be called next to set pCol->affinity correctly.
  */
  pCol->affinity = SQLITE_AFF_NONE;
  p->nCol++;
}

/*
** This routine is called by the parser while in the middle of
** parsing a CREATE TABLE statement.  A "NOT NULL" constraint has
** been seen on a column.  This routine sets the notNull flag on
625
626
627
628
629
630
631
632

633
634
635
636
637
638
639
  if( z==0 ) return;
  for(i=j=0; z[i]; i++){
    int c = z[i];
    if( isspace(c) ) continue;
    z[j++] = c;
  }
  z[j] = 0;
  pCol->sortOrder = sqlite3CollateType(z, n);

}

/*
** The given token is the default value for the last column added to
** the table currently under construction.  If "minusFlag" is true, it
** means the value token was preceded by a minus sign.
**







|
>







633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
  if( z==0 ) return;
  for(i=j=0; z[i]; i++){
    int c = z[i];
    if( isspace(c) ) continue;
    z[j++] = c;
  }
  z[j] = 0;
//  pCol->sortOrder = sqlite3CollateType(z, n);
  pCol->affinity = sqlite3AffinityType(z, n);
}

/*
** The given token is the default value for the last column added to
** the table currently under construction.  If "minusFlag" is true, it
** means the value token was preceded by a minus sign.
**
747
748
749
750
751
752
753


754

































755
756
757
758
759
760
761
** the column currently under construction.
*/
void sqlite3AddCollateType(Parse *pParse, int collType){
  Table *p;
  int i;
  if( (p = pParse->pNewTable)==0 ) return;
  i = p->nCol-1;


  if( i>=0 ) p->aCol[i].sortOrder = collType;

































}

/*
** Come up with a new random value for the schema cookie.  Make sure
** the new value is different from the old.
**
** The schema cookie is used to determine when the schema for the







>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
** the column currently under construction.
*/
void sqlite3AddCollateType(Parse *pParse, int collType){
  Table *p;
  int i;
  if( (p = pParse->pNewTable)==0 ) return;
  i = p->nCol-1;

  /* FIX ME */
  /* if( i>=0 ) p->aCol[i].sortOrder = collType; */
}

/*
** Parse the column type name zType (length nType) and return the
** associated affinity type.
*/
char sqlite3AffinityType(const char *zType, int nType){
  /* FIX ME: This could be done more efficiently */
  int n, i;
  struct {
    const char *zSub;
    int nSub;
    char affinity;
  } substrings[] = {
    {"INT", 3, SQLITE_AFF_INTEGER},
    {"REAL", 4, SQLITE_AFF_NUMERIC},
    {"FLOAT", 5, SQLITE_AFF_NUMERIC},
    {"DOUBLE", 6, SQLITE_AFF_NUMERIC},
    {"NUM", 3, SQLITE_AFF_NUMERIC},
    {"CHAR", 4, SQLITE_AFF_TEXT},
    {"CLOB", 4, SQLITE_AFF_TEXT},
    {"TEXT", 4, SQLITE_AFF_TEXT}
  };

  for(n=0; n<(nType-3); n++){
    for(i=0; i<sizeof(substrings)/sizeof(substrings[0]); i++){
      if( 0==sqlite3StrNICmp(zType, substrings[i].zSub, substrings[i].nSub) ){
        return substrings[i].affinity;
      }
    }
  }

  return SQLITE_AFF_NONE;
}

/*
** Come up with a new random value for the schema cookie.  Make sure
** the new value is different from the old.
**
** The schema cookie is used to determine when the schema for the
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
  if( !pParse->explain ){
    sqliteUnlinkAndDeleteTable(db, pTable);
    db->flags |= SQLITE_InternChanges;
  }
  sqliteViewResetAll(db, iDb);
}

/*
** This routine constructs a P3 string suitable for an OP_MakeIdxKey
** opcode and adds that P3 string to the most recently inserted instruction
** in the virtual machine.  The P3 string consists of a single character
** for each column in the index pIdx of table pTab.  If the column uses
** a numeric sort order, then the P3 string character corresponding to
** that column is 'n'.  If the column uses a text sort order, then the
** P3 string is 't'.  See the OP_MakeIdxKey opcode documentation for
** additional information.  See also the sqlite3AddKeyType() routine.
*/
void sqlite3AddIdxKeyType(Vdbe *v, Index *pIdx){
  char *zType;
  Table *pTab;
  int i, n;
  assert( pIdx!=0 && pIdx->pTable!=0 );
  pTab = pIdx->pTable;
  n = pIdx->nColumn;
  zType = sqliteMallocRaw( n+1 );
  if( zType==0 ) return;
  for(i=0; i<n; i++){
    int iCol = pIdx->aiColumn[i];
    assert( iCol>=0 && iCol<pTab->nCol );
    if( (pTab->aCol[iCol].sortOrder & SQLITE_SO_TYPEMASK)==SQLITE_SO_TEXT ){
      zType[i] = 't';
    }else{
      zType[i] = 'n';
    }
  }
  zType[n] = 0;
  sqlite3VdbeChangeP3(v, -1, zType, n);
  sqliteFree(zType);
}

/*
** This routine is called to create a new foreign key on the table
** currently under construction.  pFromCol determines which columns
** in the current table point to the foreign key.  If pFromCol==0 then
** connect the key to the last column inserted.  pTo is the name of
** the table referred to.  pToCol is a list of tables in the other
** pTo table that the foreign key points to.  flags contains all







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







1335
1336
1337
1338
1339
1340
1341

































1342
1343
1344
1345
1346
1347
1348
  if( !pParse->explain ){
    sqliteUnlinkAndDeleteTable(db, pTable);
    db->flags |= SQLITE_InternChanges;
  }
  sqliteViewResetAll(db, iDb);
}


































/*
** This routine is called to create a new foreign key on the table
** currently under construction.  pFromCol determines which columns
** in the current table point to the foreign key.  If pFromCol==0 then
** connect the key to the last column inserted.  pTo is the name of
** the table referred to.  pToCol is a list of tables in the other
** pTo table that the foreign key points to.  flags contains all
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
        if( pTab->iPKey==iCol ){
          sqlite3VdbeAddOp(v, OP_Dup, i, 0);
        }else{
          sqlite3VdbeAddOp(v, OP_Column, 2, iCol);
        }
      }
      sqlite3VdbeAddOp(v, OP_MakeIdxKey, pIndex->nColumn, 0);
      sqlite3AddIdxKeyType(v, pIndex);
      sqlite3VdbeOp3(v, OP_IdxPut, 1, pIndex->onError!=OE_None,
                      "indexed columns are not unique", P3_STATIC);
      sqlite3VdbeAddOp(v, OP_Next, 2, lbl1);
      sqlite3VdbeResolveLabel(v, lbl2);
      sqlite3VdbeAddOp(v, OP_Close, 2, 0);
      sqlite3VdbeAddOp(v, OP_Close, 1, 0);
    }







|







1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
        if( pTab->iPKey==iCol ){
          sqlite3VdbeAddOp(v, OP_Dup, i, 0);
        }else{
          sqlite3VdbeAddOp(v, OP_Column, 2, iCol);
        }
      }
      sqlite3VdbeAddOp(v, OP_MakeIdxKey, pIndex->nColumn, 0);
      sqlite3IndexAffinityStr(v, pIndex);
      sqlite3VdbeOp3(v, OP_IdxPut, 1, pIndex->onError!=OE_None,
                      "indexed columns are not unique", P3_STATIC);
      sqlite3VdbeAddOp(v, OP_Next, 2, lbl1);
      sqlite3VdbeResolveLabel(v, lbl2);
      sqlite3VdbeAddOp(v, OP_Close, 2, 0);
      sqlite3VdbeAddOp(v, OP_Close, 1, 0);
    }
Changes to src/delete.c.
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
**    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 DELETE FROM statements.
**
** $Id: delete.c,v 1.64 2004/05/11 07:11:53 danielk1977 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.







|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
**    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 DELETE FROM statements.
**
** $Id: delete.c,v 1.65 2004/05/16 11:15:37 danielk1977 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.
383
384
385
386
387
388
389
390
391
392
393
394
395
396
      if( idx==pTab->iPKey ){
        sqlite3VdbeAddOp(v, OP_Dup, j, 0);
      }else{
        sqlite3VdbeAddOp(v, OP_Column, iCur, idx);
      }
    }
    sqlite3VdbeAddOp(v, OP_MakeIdxKey, pIdx->nColumn, 0);
    sqlite3AddIdxKeyType(v, pIdx);
    sqlite3VdbeAddOp(v, OP_IdxDelete, iCur+i, 0);
  }
}










|






383
384
385
386
387
388
389
390
391
392
393
394
395
396
      if( idx==pTab->iPKey ){
        sqlite3VdbeAddOp(v, OP_Dup, j, 0);
      }else{
        sqlite3VdbeAddOp(v, OP_Column, iCur, idx);
      }
    }
    sqlite3VdbeAddOp(v, OP_MakeIdxKey, pIdx->nColumn, 0);
    sqlite3IndexAffinityStr(v, pIdx);
    sqlite3VdbeAddOp(v, OP_IdxDelete, iCur+i, 0);
  }
}



Changes to src/expr.c.
8
9
10
11
12
13
14
15
16
17
18








































19
20
21
22
23
24
25
**    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.117 2004/05/11 07:11:53 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>









































/*
** 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){







|



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







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
**    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.118 2004/05/16 11:15:37 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

static char exprAffinity(Expr *pExpr){
  if( pExpr->op==TK_AS ){
    return exprAffinity(pExpr->pLeft);
  }
  if( pExpr->op==TK_SELECT ){
    return exprAffinity(pExpr->pSelect->pEList->a[0].pExpr);
  }
  return pExpr->affinity;
}

/*
** Return the P1 value that should be used for a binary comparison
** opcode (OP_Eq, OP_Ge etc.) used to compare pExpr1 and pExpr2.
** If jumpIfNull is true, then set the low byte of the returned
** P1 value to tell the opcode to jump if either expression
** evaluates to NULL.
*/
int binaryCompareP1(Expr *pExpr1, Expr *pExpr2, int jumpIfNull){
  char aff1 = exprAffinity(pExpr1);
  char aff2 = exprAffinity(pExpr2);

  if( aff1 && aff2 ){
    /* Both sides of the comparison are columns. If one has numeric or
    ** integer affinity, use that. Otherwise use no affinity.
    */
    if( aff1==SQLITE_AFF_INTEGER || aff2==SQLITE_AFF_INTEGER ){
      aff1 = SQLITE_AFF_INTEGER;
    }else
    if( aff1==SQLITE_AFF_NUMERIC || aff2==SQLITE_AFF_NUMERIC ){
      aff1 = SQLITE_AFF_NUMERIC;
    }else{
      aff1 = SQLITE_AFF_NONE;
    }
  }else if( !aff1 ){
    aff1 = aff2;
  }

  return (((int)aff1)<<8)+(jumpIfNull?1:0);
}

/*
** 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){
468
469
470
471
472
473
474



475

476
477
478
479
480
481
482
    for(j=0, pCol=pTab->aCol; j<pTab->nCol; j++, pCol++){
      if( sqlite3StrICmp(pCol->zName, zCol)==0 ){
        cnt++;
        pExpr->iTable = pItem->iCursor;
        pExpr->iDb = pTab->iDb;
        /* Substitute the rowid (column -1) for the INTEGER PRIMARY KEY */
        pExpr->iColumn = j==pTab->iPKey ? -1 : j;



        pExpr->dataType = pCol->sortOrder & SQLITE_SO_TYPEMASK;

        break;
      }
    }
  }

  /* If we have not already resolved the name, then maybe 
  ** it is a new.* or old.* trigger argument reference







>
>
>
|
>







508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
    for(j=0, pCol=pTab->aCol; j<pTab->nCol; j++, pCol++){
      if( sqlite3StrICmp(pCol->zName, zCol)==0 ){
        cnt++;
        pExpr->iTable = pItem->iCursor;
        pExpr->iDb = pTab->iDb;
        /* Substitute the rowid (column -1) for the INTEGER PRIMARY KEY */
        pExpr->iColumn = j==pTab->iPKey ? -1 : j;
        pExpr->affinity = pTab->aCol[j].affinity;

        /* FIX ME: Expr::dataType will be removed... */
        pExpr->dataType =
            (pCol->affinity==SQLITE_AFF_TEXT?SQLITE_SO_TEXT:SQLITE_SO_NUM);
        break;
      }
    }
  }

  /* If we have not already resolved the name, then maybe 
  ** it is a new.* or old.* trigger argument reference
500
501
502
503
504
505
506


507

508
509
510
511
512
513
514
515
516
517
518
519
520

521
522
523
524
525
526
527
      
      pExpr->iDb = pTab->iDb;
      cntTab++;
      for(j=0; j < pTab->nCol; j++, pCol++) {
        if( sqlite3StrICmp(pCol->zName, zCol)==0 ){
          cnt++;
          pExpr->iColumn = j==pTab->iPKey ? -1 : j;


          pExpr->dataType = pCol->sortOrder & SQLITE_SO_TYPEMASK;

          break;
        }
      }
    }
  }

  /*
  ** Perhaps the name is a reference to the ROWID
  */
  if( cnt==0 && cntTab==1 && sqlite3IsRowid(zCol) ){
    cnt = 1;
    pExpr->iColumn = -1;
    pExpr->dataType = SQLITE_SO_NUM;

  }

  /*
  ** If the input is of the form Z (not Y.Z or X.Y.Z) then the name Z
  ** might refer to an result-set alias.  This happens, for example, when
  ** we are resolving names in the WHERE clause of the following command:
  **







>
>
|
>













>







544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
      
      pExpr->iDb = pTab->iDb;
      cntTab++;
      for(j=0; j < pTab->nCol; j++, pCol++) {
        if( sqlite3StrICmp(pCol->zName, zCol)==0 ){
          cnt++;
          pExpr->iColumn = j==pTab->iPKey ? -1 : j;
          pExpr->affinity = pTab->aCol[j].affinity;
          /* FIX ME: Expr::dataType will be removed... */
          pExpr->dataType =
              (pCol->affinity==SQLITE_AFF_TEXT?SQLITE_SO_TEXT:SQLITE_SO_NUM);
          break;
        }
      }
    }
  }

  /*
  ** Perhaps the name is a reference to the ROWID
  */
  if( cnt==0 && cntTab==1 && sqlite3IsRowid(zCol) ){
    cnt = 1;
    pExpr->iColumn = -1;
    pExpr->dataType = SQLITE_SO_NUM;
    pExpr->affinity = SQLITE_AFF_INTEGER;
  }

  /*
  ** If the input is of the form Z (not Y.Z or X.Y.Z) then the name Z
  ** might refer to an result-set alias.  This happens, for example, when
  ** we are resolving names in the WHERE clause of the following command:
  **
1046
1047
1048
1049
1050
1051
1052


1053
1054
1055
1056
1057
1058
1059
      break;
    }
    case TK_STRING:
    case TK_FLOAT:
    case TK_INTEGER: {
      if( pExpr->op==TK_INTEGER && sqlite3FitsIn32Bits(pExpr->token.z) ){
        sqlite3VdbeAddOp(v, OP_Integer, atoi(pExpr->token.z), 0);


      }else{
        sqlite3VdbeAddOp(v, OP_String, 0, 0);
      }
      assert( pExpr->token.z );
      sqlite3VdbeChangeP3(v, -1, pExpr->token.z, pExpr->token.n);
      sqlite3VdbeDequoteP3(v, -1);
      break;







>
>







1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
      break;
    }
    case TK_STRING:
    case TK_FLOAT:
    case TK_INTEGER: {
      if( pExpr->op==TK_INTEGER && sqlite3FitsIn32Bits(pExpr->token.z) ){
        sqlite3VdbeAddOp(v, OP_Integer, atoi(pExpr->token.z), 0);
      }else if( pExpr->op==TK_FLOAT ){
        sqlite3VdbeAddOp(v, OP_Real, 0, 0);
      }else{
        sqlite3VdbeAddOp(v, OP_String, 0, 0);
      }
      assert( pExpr->token.z );
      sqlite3VdbeChangeP3(v, -1, pExpr->token.z, pExpr->token.n);
      sqlite3VdbeDequoteP3(v, -1);
      break;
1068
1069
1070
1071
1072
1073
1074






1075
1076
1077
1078

1079
1080
1081
1082
1083
1084
1085
    }
    case TK_LT:
    case TK_LE:
    case TK_GT:
    case TK_GE:
    case TK_NE:
    case TK_EQ: {






      if( sqlite3ExprType(pExpr)==SQLITE_SO_TEXT ){
        op += 6;  /* Convert numeric opcodes to text opcodes */
      }
      /* Fall through into the next case */

    }
    case TK_AND:
    case TK_OR:
    case TK_PLUS:
    case TK_STAR:
    case TK_MINUS:
    case TK_REM:







>
>
>
>
>
>




>







1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
    }
    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);
      sqlite3ExprCode(pParse, pExpr->pLeft);
      sqlite3ExprCode(pParse, pExpr->pRight);
      sqlite3VdbeAddOp(v, op, p1, 0);
      break;
#if 0
      if( sqlite3ExprType(pExpr)==SQLITE_SO_TEXT ){
        op += 6;  /* Convert numeric opcodes to text opcodes */
      }
      /* Fall through into the next case */
#endif
    }
    case TK_AND:
    case TK_OR:
    case TK_PLUS:
    case TK_STAR:
    case TK_MINUS:
    case TK_REM:
1131
1132
1133
1134
1135
1136
1137
1138
1139

1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155





1156

1157
1158
1159
1160
1161
1162
1163
    case TK_NOTNULL: {
      int dest;
      sqlite3VdbeAddOp(v, OP_Integer, 1, 0);
      sqlite3ExprCode(pParse, pExpr->pLeft);
      dest = sqlite3VdbeCurrentAddr(v) + 2;
      sqlite3VdbeAddOp(v, op, 1, dest);
      sqlite3VdbeAddOp(v, OP_AddImm, -1, 0);
      break;
    }

    case TK_AGG_FUNCTION: {
      sqlite3VdbeAddOp(v, OP_AggGet, 0, pExpr->iAgg);
      break;
    }
    case TK_GLOB:
    case TK_LIKE:
    case TK_FUNCTION: {
      ExprList *pList = pExpr->pList;
      int nExpr = pList ? pList->nExpr : 0;
      FuncDef *pDef;
      int nId;
      const char *zId;
      getFunctionName(pExpr, &zId, &nId);
      pDef = sqlite3FindFunction(pParse->db, zId, nId, nExpr, 0);
      assert( pDef!=0 );
      nExpr = sqlite3ExprCodeExprList(pParse, pList, pDef->includeTypes);





      sqlite3VdbeOp3(v, OP_Function, nExpr, 0, (char*)pDef, P3_POINTER);

      break;
    }
    case TK_SELECT: {
      sqlite3VdbeAddOp(v, OP_MemLoad, pExpr->iColumn, 0);
      break;
    }
    case TK_IN: {







<

>
















>
>
>
>
>
|
>







1188
1189
1190
1191
1192
1193
1194

1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
    case TK_NOTNULL: {
      int dest;
      sqlite3VdbeAddOp(v, OP_Integer, 1, 0);
      sqlite3ExprCode(pParse, pExpr->pLeft);
      dest = sqlite3VdbeCurrentAddr(v) + 2;
      sqlite3VdbeAddOp(v, op, 1, dest);
      sqlite3VdbeAddOp(v, OP_AddImm, -1, 0);

    }
    break;
    case TK_AGG_FUNCTION: {
      sqlite3VdbeAddOp(v, OP_AggGet, 0, pExpr->iAgg);
      break;
    }
    case TK_GLOB:
    case TK_LIKE:
    case TK_FUNCTION: {
      ExprList *pList = pExpr->pList;
      int nExpr = pList ? pList->nExpr : 0;
      FuncDef *pDef;
      int nId;
      const char *zId;
      getFunctionName(pExpr, &zId, &nId);
      pDef = sqlite3FindFunction(pParse->db, zId, nId, nExpr, 0);
      assert( pDef!=0 );
      nExpr = sqlite3ExprCodeExprList(pParse, pList, pDef->includeTypes);
      /* FIX ME: The following is a temporary hack. */
      if( 0==sqlite3StrNICmp(zId, "classof", nId) ){
        assert( nExpr==1 );
        sqlite3VdbeOp3(v, OP_Class, nExpr, 0, 0, 0);
      }else{
        sqlite3VdbeOp3(v, OP_Function, nExpr, 0, (char*)pDef, P3_POINTER);
      }
      break;
    }
    case TK_SELECT: {
      sqlite3VdbeAddOp(v, OP_MemLoad, pExpr->iColumn, 0);
      break;
    }
    case TK_IN: {
1328
1329
1330
1331
1332
1333
1334

1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
    }
    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);
      if( sqlite3ExprType(pExpr)==SQLITE_SO_TEXT ){
        op += 6;  /* Convert numeric opcodes to text opcodes */
      }
      sqlite3VdbeAddOp(v, op, jumpIfNull, dest);
      break;
    }
    case TK_ISNULL:
    case TK_NOTNULL: {
      sqlite3ExprCode(pParse, pExpr->pLeft);
      sqlite3VdbeAddOp(v, op, 1, dest);
      break;







>


<
<
<
|







1391
1392
1393
1394
1395
1396
1397
1398
1399
1400



1401
1402
1403
1404
1405
1406
1407
1408
    }
    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);
      sqlite3ExprCode(pParse, pExpr->pLeft);
      sqlite3ExprCode(pParse, pExpr->pRight);



      sqlite3VdbeAddOp(v, op, p1, dest);
      break;
    }
    case TK_ISNULL:
    case TK_NOTNULL: {
      sqlite3ExprCode(pParse, pExpr->pLeft);
      sqlite3VdbeAddOp(v, op, 1, dest);
      break;
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
    }
    case TK_LT:
    case TK_LE:
    case TK_GT:
    case TK_GE:
    case TK_NE:
    case TK_EQ: {
      if( sqlite3ExprType(pExpr)==SQLITE_SO_TEXT ){
        /* Convert numeric comparison opcodes into text comparison opcodes.
        ** This step depends on the fact that the text comparision opcodes are
        ** always 6 greater than their corresponding numeric comparison
        ** opcodes.
        */
        assert( OP_Eq+6 == OP_StrEq );
        op += 6;
      }
      sqlite3ExprCode(pParse, pExpr->pLeft);
      sqlite3ExprCode(pParse, pExpr->pRight);
      sqlite3VdbeAddOp(v, op, jumpIfNull, dest);
      break;
    }
    case TK_ISNULL:
    case TK_NOTNULL: {
      sqlite3ExprCode(pParse, pExpr->pLeft);
      sqlite3VdbeAddOp(v, op, 1, dest);
      break;







|
<
<
<
<
<
<
<
<


|







1484
1485
1486
1487
1488
1489
1490
1491








1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
    }
    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);








      sqlite3ExprCode(pParse, pExpr->pLeft);
      sqlite3ExprCode(pParse, pExpr->pRight);
      sqlite3VdbeAddOp(v, op, p1, dest);
      break;
    }
    case TK_ISNULL:
    case TK_NOTNULL: {
      sqlite3ExprCode(pParse, pExpr->pLeft);
      sqlite3VdbeAddOp(v, op, 1, dest);
      break;
Changes to src/func.c.
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
** This file contains the C functions that implement various SQL
** functions of SQLite.  
**
** There is only one exported symbol in this file - the function
** sqliteRegisterBuildinFunctions() found at the bottom of the file.
** All other code has file scope.
**
** $Id: func.c,v 1.47 2004/05/14 11:00:53 danielk1977 Exp $
*/
#include <ctype.h>
#include <math.h>
#include <stdlib.h>
#include <assert.h>
#include "sqliteInt.h"
#include "os.h"







|







12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
** This file contains the C functions that implement various SQL
** functions of SQLite.  
**
** There is only one exported symbol in this file - the function
** sqliteRegisterBuildinFunctions() found at the bottom of the file.
** All other code has file scope.
**
** $Id: func.c,v 1.48 2004/05/16 11:15:38 danielk1977 Exp $
*/
#include <ctype.h>
#include <math.h>
#include <stdlib.h>
#include <assert.h>
#include "sqliteInt.h"
#include "os.h"
567
568
569
570
571
572
573

574
575
576
577
578
579
580
     void (*xFunc)(sqlite_func*,int,const char**);
  } aFuncs[] = {
    { "min",       -1, SQLITE_ARGS,    0, minmaxFunc },
    { "min",        0, 0,              0, 0          },
    { "max",       -1, SQLITE_ARGS,    2, minmaxFunc },
    { "max",        0, 0,              2, 0          },
    { "typeof",     1, SQLITE_TEXT,    0, typeofFunc },

    { "length",     1, SQLITE_NUMERIC, 0, lengthFunc },
    { "substr",     3, SQLITE_TEXT,    0, substrFunc },
    { "abs",        1, SQLITE_NUMERIC, 0, absFunc    },
    { "round",      1, SQLITE_NUMERIC, 0, roundFunc  },
    { "round",      2, SQLITE_NUMERIC, 0, roundFunc  },
    { "upper",      1, SQLITE_TEXT,    0, upperFunc  },
    { "lower",      1, SQLITE_TEXT,    0, lowerFunc  },







>







567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
     void (*xFunc)(sqlite_func*,int,const char**);
  } aFuncs[] = {
    { "min",       -1, SQLITE_ARGS,    0, minmaxFunc },
    { "min",        0, 0,              0, 0          },
    { "max",       -1, SQLITE_ARGS,    2, minmaxFunc },
    { "max",        0, 0,              2, 0          },
    { "typeof",     1, SQLITE_TEXT,    0, typeofFunc },
    { "classof",    1, SQLITE_TEXT,    0, typeofFunc }, /* FIX ME: hack */
    { "length",     1, SQLITE_NUMERIC, 0, lengthFunc },
    { "substr",     3, SQLITE_TEXT,    0, substrFunc },
    { "abs",        1, SQLITE_NUMERIC, 0, absFunc    },
    { "round",      1, SQLITE_NUMERIC, 0, roundFunc  },
    { "round",      2, SQLITE_NUMERIC, 0, roundFunc  },
    { "upper",      1, SQLITE_TEXT,    0, upperFunc  },
    { "lower",      1, SQLITE_TEXT,    0, lowerFunc  },
Changes to src/insert.c.
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30











31









32

33















34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
**    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.98 2004/05/14 11:00:53 danielk1977 Exp $
*/
#include "sqliteInt.h"

/*
** Set P3 of the most recently inserted opcode to a column affinity
** string for table pTab. A column affinity string has one character
** for each column in the table, according to the affinity of the column:
**
**  Character      Column affinity
**  ------------------------------
**  'n'            NUMERIC
**  'i'            INTEGER
**  't'            TEXT
**  'o'            NONE
*/











int sqlite3AddRecordType(Vdbe *v, Table *pTab){









  assert( pTab );

 















  /* The first time a column affinity string for a particular table
  ** is required, it is allocated and populated here. It is then 
  ** stored as a member of the Table structure for subsequent use.
  **
  ** The column affinity string will eventually be deleted by
  ** sqlite3DeleteTable() when the Table structure itself is cleaned up.
  */
  if( !pTab->zColAff ){
    char *zColAff;
    int i;

    zColAff = sqliteMalloc(pTab->nCol+1);
    if( !zColAff ){
      return SQLITE_NOMEM;
    }

    for(i=0; i<pTab->nCol; i++){
      if( pTab->aCol[i].sortOrder&SQLITE_SO_TEXT ){
        zColAff[i] = 't';
      }else{
        zColAff[i] = 'n';
      }
    }
    zColAff[pTab->nCol] = '\0';

    pTab->zColAff = zColAff;
  }

  /* Set the memory management at the vdbe to P3_STATIC, as the column
  ** affinity string is managed as part of the Table structure.
  */
  sqlite3VdbeChangeP3(v, -1, pTab->zColAff, P3_STATIC);
  return SQLITE_OK;
}


/*
** This routine is call to handle SQL of the following forms:
**
**    insert into TABLE (IDLIST) values(EXPRLIST)







|





|









>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
|
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>











|

|



<
|
<
<
<






<
<
<

<







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86

87



88
89
90
91
92
93



94

95
96
97
98
99
100
101
**    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.99 2004/05/16 11:15:38 danielk1977 Exp $
*/
#include "sqliteInt.h"

/*
** Set P3 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:
**
**  Character      Column affinity
**  ------------------------------
**  'n'            NUMERIC
**  'i'            INTEGER
**  't'            TEXT
**  'o'            NONE
*/
void sqlite3IndexAffinityStr(Vdbe *v, Index *pIdx){
  if( !pIdx->zColAff ){
    /* The first time a column affinity string for a particular table is
    ** required, it is allocated and populated here. It is then stored as
    ** a member of the Table structure for subsequent use.
    **
    ** The column affinity string will eventually be deleted by
    ** sqliteDeleteIndex() when the Table structure itself is cleaned
    ** up.
    */
    int n;
    Table *pTab = pIdx->pTable;
    pIdx->zColAff = (char *)sqliteMalloc(pIdx->nColumn+1);
    if( !pIdx->zColAff ){
      return;
    }
    for(n=0; n<pIdx->nColumn; n++){
      pIdx->zColAff[n] = pTab->aCol[pIdx->aiColumn[n]].affinity;
    }
    pIdx->zColAff[pIdx->nColumn] = '\0';
  }
 
  sqlite3VdbeChangeP3(v, -1, pIdx->zColAff, P3_STATIC);
}

/*
** Set P3 of the most recently inserted opcode to a column affinity
** string for table pTab. A column affinity string has one character
** for each column indexed by the index, according to the affinity of the
** column:
**
**  Character      Column affinity
**  ------------------------------
**  'n'            NUMERIC
**  'i'            INTEGER
**  't'            TEXT
**  'o'            NONE
*/
void sqlite3TableAffinityStr(Vdbe *v, Table *pTab){
  /* The first time a column affinity string for a particular table
  ** is required, it is allocated and populated here. It is then 
  ** stored as a member of the Table structure for subsequent use.
  **
  ** The column affinity string will eventually be deleted by
  ** sqlite3DeleteTable() when the Table structure itself is cleaned up.
  */
  if( !pTab->zColAff ){
    char *zColAff;
    int i;

    zColAff = (char *)sqliteMalloc(pTab->nCol+1);
    if( !zColAff ){
      return;
    }

    for(i=0; i<pTab->nCol; i++){

      zColAff[i] = pTab->aCol[i].affinity;



    }
    zColAff[pTab->nCol] = '\0';

    pTab->zColAff = zColAff;
  }




  sqlite3VdbeChangeP3(v, -1, pTab->zColAff, P3_STATIC);

}


/*
** This routine is call to handle SQL of the following forms:
**
**    insert into TABLE (IDLIST) values(EXPRLIST)
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
    if( useTempTable ){
      /* Generate the subroutine that SELECT calls to process each row of
      ** the result.  Store the result in a temporary table
      */
      srcTab = pParse->nTab++;
      sqlite3VdbeResolveLabel(v, iInsertBlock);
      sqlite3VdbeAddOp(v, OP_MakeRecord, nColumn, 0);
      sqlite3AddRecordType(v, pTab);
      sqlite3VdbeAddOp(v, OP_NewRecno, srcTab, 0);
      sqlite3VdbeAddOp(v, OP_Pull, 1, 0);
      sqlite3VdbeAddOp(v, OP_PutIntKey, srcTab, 0);
      sqlite3VdbeAddOp(v, OP_Return, 0, 0);

      /* The following code runs first because the GOTO at the very top
      ** of the program jumps to it.  Create the temporary table, then jump







|







291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
    if( useTempTable ){
      /* Generate the subroutine that SELECT calls to process each row of
      ** the result.  Store the result in a temporary table
      */
      srcTab = pParse->nTab++;
      sqlite3VdbeResolveLabel(v, iInsertBlock);
      sqlite3VdbeAddOp(v, OP_MakeRecord, nColumn, 0);
      sqlite3TableAffinityStr(v, pTab);
      sqlite3VdbeAddOp(v, OP_NewRecno, srcTab, 0);
      sqlite3VdbeAddOp(v, OP_Pull, 1, 0);
      sqlite3VdbeAddOp(v, OP_PutIntKey, srcTab, 0);
      sqlite3VdbeAddOp(v, OP_Return, 0, 0);

      /* The following code runs first because the GOTO at the very top
      ** of the program jumps to it.  Create the temporary table, then jump
442
443
444
445
446
447
448
449








450
451
452
453
454
455
456
      }else if( pSelect ){
        sqlite3VdbeAddOp(v, OP_Dup, nColumn-j-1, 1);
      }else{
        sqlite3ExprCode(pParse, pList->a[j].pExpr);
      }
    }
    sqlite3VdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0);
    sqlite3AddRecordType(v, pTab);








    sqlite3VdbeAddOp(v, OP_PutIntKey, newIdx, 0);

    /* Fire BEFORE or INSTEAD OF triggers */
    if( sqlite3CodeRowTrigger(pParse, TK_INSERT, 0, TK_BEFORE, pTab, 
        newIdx, -1, onError, endOfLoop) ){
      goto insert_cleanup;
    }







|
>
>
>
>
>
>
>
>







470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
      }else if( pSelect ){
        sqlite3VdbeAddOp(v, OP_Dup, nColumn-j-1, 1);
      }else{
        sqlite3ExprCode(pParse, pList->a[j].pExpr);
      }
    }
    sqlite3VdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0);

    /* If this is an INSERT on a view with an INSTEAD OF INSERT trigger,
    ** do not attempt any conversions before assembling the record.
    ** If this is a real table, attempt conversions as required by the
    ** table column affinities.
    */
    if( !isView ){
      sqlite3TableAffinityStr(v, pTab);
    }
    sqlite3VdbeAddOp(v, OP_PutIntKey, newIdx, 0);

    /* Fire BEFORE or INSTEAD OF triggers */
    if( sqlite3CodeRowTrigger(pParse, TK_INSERT, 0, TK_BEFORE, pTab, 
        newIdx, -1, onError, endOfLoop) ){
      goto insert_cleanup;
    }
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
      if( idx==pTab->iPKey ){
        sqlite3VdbeAddOp(v, OP_Dup, i+extra+nCol+1, 1);
      }else{
        sqlite3VdbeAddOp(v, OP_Dup, i+extra+nCol-idx, 1);
      }
    }
    jumpInst1 = sqlite3VdbeAddOp(v, OP_MakeIdxKey, pIdx->nColumn, 0);
    sqlite3AddIdxKeyType(v, pIdx);

    /* 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;
    }else if( pParse->db->onError!=OE_Default ){







|







858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
      if( idx==pTab->iPKey ){
        sqlite3VdbeAddOp(v, OP_Dup, i+extra+nCol+1, 1);
      }else{
        sqlite3VdbeAddOp(v, OP_Dup, i+extra+nCol-idx, 1);
      }
    }
    jumpInst1 = sqlite3VdbeAddOp(v, OP_MakeIdxKey, pIdx->nColumn, 0);
    sqlite3IndexAffinityStr(v, pIdx);

    /* 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;
    }else if( pParse->db->onError!=OE_Default ){
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
  assert( pTab->pSelect==0 );  /* This table is not a VIEW */
  for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){}
  for(i=nIdx-1; i>=0; i--){
    if( aIdxUsed && aIdxUsed[i]==0 ) continue;
    sqlite3VdbeAddOp(v, OP_IdxPut, base+i+1, 0);
  }
  sqlite3VdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0);
  sqlite3AddRecordType(v, pTab);
  if( newIdx>=0 ){
    sqlite3VdbeAddOp(v, OP_Dup, 1, 0);
    sqlite3VdbeAddOp(v, OP_Dup, 1, 0);
    sqlite3VdbeAddOp(v, OP_PutIntKey, newIdx, 0);
  }
  sqlite3VdbeAddOp(v, OP_PutIntKey, base,
    (pParse->trigStack?0:OPFLAG_NCHANGE) |







|







968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
  assert( pTab->pSelect==0 );  /* This table is not a VIEW */
  for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){}
  for(i=nIdx-1; i>=0; i--){
    if( aIdxUsed && aIdxUsed[i]==0 ) continue;
    sqlite3VdbeAddOp(v, OP_IdxPut, base+i+1, 0);
  }
  sqlite3VdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0);
  sqlite3TableAffinityStr(v, pTab);
  if( newIdx>=0 ){
    sqlite3VdbeAddOp(v, OP_Dup, 1, 0);
    sqlite3VdbeAddOp(v, OP_Dup, 1, 0);
    sqlite3VdbeAddOp(v, OP_PutIntKey, newIdx, 0);
  }
  sqlite3VdbeAddOp(v, OP_PutIntKey, base,
    (pParse->trigStack?0:OPFLAG_NCHANGE) |
Changes to src/pragma.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/*
** 2003 April 6
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    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.
**
*************************************************************************
** This file contains code used to implement the PRAGMA command.
**
** $Id: pragma.c,v 1.22 2004/05/11 08:48:11 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

/*
** Interpret the given string as a boolean value.
*/













|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/*
** 2003 April 6
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    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.
**
*************************************************************************
** This file contains code used to implement the PRAGMA command.
**
** $Id: pragma.c,v 1.23 2004/05/16 11:15:38 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

/*
** Interpret the given string as a boolean value.
*/
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
            if( idx==pTab->iPKey ){
              sqlite3VdbeAddOp(v, OP_Recno, 1, 0);
            }else{
              sqlite3VdbeAddOp(v, OP_Column, 1, idx);
            }
          }
          sqlite3VdbeAddOp(v, OP_MakeIdxKey, pIdx->nColumn, 0);
          sqlite3AddIdxKeyType(v, pIdx);
          jmp2 = sqlite3VdbeAddOp(v, OP_Found, j+2, 0);
          addr = sqlite3VdbeAddOpList(v, ArraySize(idxErr), idxErr);
          sqlite3VdbeChangeP3(v, addr+4, pIdx->zName, P3_STATIC);
          sqlite3VdbeChangeP2(v, jmp2, sqlite3VdbeCurrentAddr(v));
        }
        sqlite3VdbeAddOp(v, OP_Next, 1, loopTop+1);
        sqlite3VdbeChangeP2(v, loopTop, sqlite3VdbeCurrentAddr(v));







|







663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
            if( idx==pTab->iPKey ){
              sqlite3VdbeAddOp(v, OP_Recno, 1, 0);
            }else{
              sqlite3VdbeAddOp(v, OP_Column, 1, idx);
            }
          }
          sqlite3VdbeAddOp(v, OP_MakeIdxKey, pIdx->nColumn, 0);
          sqlite3IndexAffinityStr(v, pIdx);
          jmp2 = sqlite3VdbeAddOp(v, OP_Found, j+2, 0);
          addr = sqlite3VdbeAddOpList(v, ArraySize(idxErr), idxErr);
          sqlite3VdbeChangeP3(v, addr+4, pIdx->zName, P3_STATIC);
          sqlite3VdbeChangeP2(v, jmp2, sqlite3VdbeCurrentAddr(v));
        }
        sqlite3VdbeAddOp(v, OP_Next, 1, loopTop+1);
        sqlite3VdbeChangeP2(v, loopTop, sqlite3VdbeCurrentAddr(v));
Changes to src/sqliteInt.h.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/*
** 2001 September 15
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    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.233 2004/05/14 16:50:06 drh Exp $
*/
#include "config.h"
#include "sqlite.h"
#include "hash.h"
#include "parse.h"
#include <stdio.h>
#include <stdlib.h>













|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/*
** 2001 September 15
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    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.234 2004/05/16 11:15:39 danielk1977 Exp $
*/
#include "config.h"
#include "sqlite.h"
#include "hash.h"
#include "parse.h"
#include <stdio.h>
#include <stdlib.h>
453
454
455
456
457
458
459
460

461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476









477
478
479
480
481
482
483
*/
struct Column {
  char *zName;     /* Name of this column */
  char *zDflt;     /* Default value of this column */
  char *zType;     /* Data type for this column */
  u8 notNull;      /* True if there is a NOT NULL constraint */
  u8 isPrimKey;    /* True if this column is part of the PRIMARY KEY */
  u8 sortOrder;    /* Some combination of SQLITE_SO_... values */

  u8 dottedName;   /* True if zName contains a "." character */
};

/*
** The allowed sort orders.
**
** The TEXT and NUM values use bits that do not overlap with DESC and ASC.
** That way the two can be combined into a single number.
*/
#define SQLITE_SO_UNK       0  /* Use the default collating type.  (SCT_NUM) */
#define SQLITE_SO_TEXT      2  /* Sort using memcmp() */
#define SQLITE_SO_NUM       4  /* Sort using sqlite3Compare() */
#define SQLITE_SO_TYPEMASK  6  /* Mask to extract the collating sequence */
#define SQLITE_SO_ASC       0  /* Sort in ascending order */
#define SQLITE_SO_DESC      1  /* Sort in descending order */
#define SQLITE_SO_DIRMASK   1  /* Mask to extract the sort direction */










/*
** Each SQL table is represented in memory by an instance of the
** following structure.
**
** Table.zName is the name of the table.  The case of the original
** CREATE TABLE statement is stored, but case is not significant for







|
>
















>
>
>
>
>
>
>
>
>







453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
*/
struct Column {
  char *zName;     /* Name of this column */
  char *zDflt;     /* Default value of this column */
  char *zType;     /* Data type for this column */
  u8 notNull;      /* True if there is a NOT NULL constraint */
  u8 isPrimKey;    /* True if this column is part of the PRIMARY KEY */
//  u8 sortOrder;    /* Some combination of SQLITE_SO_... values */ 
  char affinity;   /* One of the SQLITE_AFF_... values */
  u8 dottedName;   /* True if zName contains a "." character */
};

/*
** The allowed sort orders.
**
** The TEXT and NUM values use bits that do not overlap with DESC and ASC.
** That way the two can be combined into a single number.
*/
#define SQLITE_SO_UNK       0  /* Use the default collating type.  (SCT_NUM) */
#define SQLITE_SO_TEXT      2  /* Sort using memcmp() */
#define SQLITE_SO_NUM       4  /* Sort using sqlite3Compare() */
#define SQLITE_SO_TYPEMASK  6  /* Mask to extract the collating sequence */
#define SQLITE_SO_ASC       0  /* Sort in ascending order */
#define SQLITE_SO_DESC      1  /* Sort in descending order */
#define SQLITE_SO_DIRMASK   1  /* Mask to extract the sort direction */

/*
** Column affinity types.
*/
#define SQLITE_AFF_INTEGER  'i'
#define SQLITE_AFF_NUMERIC  'n'
#define SQLITE_AFF_TEXT     't'
#define SQLITE_AFF_NONE     'o'


/*
** Each SQL table is represented in memory by an instance of the
** following structure.
**
** Table.zName is the name of the table.  The case of the original
** CREATE TABLE statement is stored, but case is not significant for
634
635
636
637
638
639
640

641
642
643
644
645
646
647
  int nColumn;     /* Number of columns in the table used by this index */
  int *aiColumn;   /* Which columns are used by this index.  1st is 0 */
  Table *pTable;   /* The SQL table being indexed */
  int tnum;        /* Page containing root of this index in database file */
  u8 onError;      /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */
  u8 autoIndex;    /* True if is automatically created (ex: by UNIQUE) */
  u8 iDb;          /* Index in sqlite.aDb[] of where this index is stored */

  Index *pNext;    /* The next index associated with the same table */
};

/*
** Each token coming out of the lexer is an instance of
** this structure.  Tokens are also used as part of an expression.
**







>







644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
  int nColumn;     /* Number of columns in the table used by this index */
  int *aiColumn;   /* Which columns are used by this index.  1st is 0 */
  Table *pTable;   /* The SQL table being indexed */
  int tnum;        /* Page containing root of this index in database file */
  u8 onError;      /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */
  u8 autoIndex;    /* True if is automatically created (ex: by UNIQUE) */
  u8 iDb;          /* Index in sqlite.aDb[] of where this index is stored */
  char *zColAff;   /* String defining the affinity of each column */
  Index *pNext;    /* The next index associated with the same table */
};

/*
** Each token coming out of the lexer is an instance of
** this structure.  Tokens are also used as part of an expression.
**
703
704
705
706
707
708
709

710
711
712
713
714
715
716
  Token span;            /* Complete text of the expression */
  int iTable, iColumn;   /* When op==TK_COLUMN, then this expr node means the
                         ** iColumn-th field of the iTable-th table. */
  int iAgg;              /* When op==TK_COLUMN and pParse->useAgg==TRUE, pull
                         ** result from the iAgg-th element of the aggregator */
  Select *pSelect;       /* When the expression is a sub-select.  Also the
                         ** right side of "<expr> IN (<select>)" */

};

/*
** The following are the meanings of bits in the Expr.flags field.
*/
#define EP_FromJoin     0x0001  /* Originated in ON or USING clause of a join */








>







714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
  Token span;            /* Complete text of the expression */
  int iTable, iColumn;   /* When op==TK_COLUMN, then this expr node means the
                         ** iColumn-th field of the iTable-th table. */
  int iAgg;              /* When op==TK_COLUMN and pParse->useAgg==TRUE, pull
                         ** result from the iAgg-th element of the aggregator */
  Select *pSelect;       /* When the expression is a sub-select.  Also the
                         ** right side of "<expr> IN (<select>)" */
  char affinity;         /* The affinity of the column or 0 if not a column */
};

/*
** The following are the meanings of bits in the Expr.flags field.
*/
#define EP_FromJoin     0x0001  /* Originated in ON or USING clause of a join */

1287
1288
1289
1290
1291
1292
1293



1294
void *sqlite3utf8to16le(const unsigned char *pIn, int N);
void sqlite3utf16to16le(void *pData, int N);
void sqlite3utf16to16be(void *pData, int N);
int sqlite3PutVarint(unsigned char *, u64);
int sqlite3GetVarint(const unsigned char *, u64 *);
int sqlite3GetVarint32(const unsigned char *, u32 *);
int sqlite3VarintLen(u64 v);



int sqlite3AddRecordType(Vdbe*, Table*);







>
>
>
|
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
void *sqlite3utf8to16le(const unsigned char *pIn, int N);
void sqlite3utf16to16le(void *pData, int N);
void sqlite3utf16to16be(void *pData, int N);
int sqlite3PutVarint(unsigned char *, u64);
int sqlite3GetVarint(const unsigned char *, u64 *);
int sqlite3GetVarint32(const unsigned char *, u32 *);
int sqlite3VarintLen(u64 v);
char sqlite3AffinityType(const char *, int);
void sqlite3IndexAffinityStr(Vdbe *, Index *);
void sqlite3TableAffinityStr(Vdbe *, Table *);

Changes to src/update.c.
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
**    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.73 2004/05/14 11:00:53 danielk1977 Exp $
*/
#include "sqliteInt.h"

/*
** Process an UPDATE statement.
**
**   UPDATE OR IGNORE table_wxyz SET a=b, c=d WHERE e<5 AND f NOT NULL;







|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
**    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.74 2004/05/16 11:15:39 danielk1977 Exp $
*/
#include "sqliteInt.h"

/*
** Process an UPDATE statement.
**
**   UPDATE OR IGNORE table_wxyz SET a=b, c=d WHERE e<5 AND f NOT NULL;
283
284
285
286
287
288
289

290


291
292
293
294
295
296
297
      if( j<0 ){
        sqlite3VdbeAddOp(v, OP_Column, iCur, i);
      }else{
        sqlite3ExprCode(pParse, pChanges->a[j].pExpr);
      }
    }
    sqlite3VdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0);

    sqlite3AddRecordType(v, pTab);


    sqlite3VdbeAddOp(v, OP_PutIntKey, newIdx, 0);
    if( !isView ){
      sqlite3VdbeAddOp(v, OP_Close, iCur, 0);
    }

    /* Fire the BEFORE and INSTEAD OF triggers
    */







>
|
>
>







283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
      if( j<0 ){
        sqlite3VdbeAddOp(v, OP_Column, iCur, i);
      }else{
        sqlite3ExprCode(pParse, pChanges->a[j].pExpr);
      }
    }
    sqlite3VdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0);
    if( !isView ){
      sqlite3TableAffinityStr(v, pTab);
    }
    if( pParse->nErr ) goto update_cleanup;
    sqlite3VdbeAddOp(v, OP_PutIntKey, newIdx, 0);
    if( !isView ){
      sqlite3VdbeAddOp(v, OP_Close, iCur, 0);
    }

    /* Fire the BEFORE and INSTEAD OF triggers
    */
Changes to src/vdbe.c.
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
**
** Various scripts scan this source file in order to generate HTML
** documentation, headers files, or other derived files.  The formatting
** of the code in this file is, therefore, important.  See other comments
** in this file for details.  If in doubt, do not deviate from existing
** commenting and indentation practices when changing or adding code.
**
** $Id: vdbe.c,v 1.293 2004/05/14 21:59:40 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
#include <ctype.h>
#include "vdbeInt.h"

/*







|







39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
**
** Various scripts scan this source file in order to generate HTML
** documentation, headers files, or other derived files.  The formatting
** of the code in this file is, therefore, important.  See other comments
** in this file for details.  If in doubt, do not deviate from existing
** commenting and indentation practices when changing or adding code.
**
** $Id: vdbe.c,v 1.294 2004/05/16 11:15:40 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "os.h"
#include <ctype.h>
#include "vdbeInt.h"

/*
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439

440
441
442
443
444
445
446
447
448
449
450
451
452
453










454

455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
  return 0;
}

/*
** Apply any conversion required by the supplied column affinity to
** memory cell pRec. affinity may be one of:
**
** SQLITE_AFF_NUM
** SQLITE_AFF_TEXT
** SQLITE_AFF_NONE
** SQLITE_AFF_INTEGER
**
*/
static void applyAffinity(Mem *pRec, int affinity){
  switch( affinity ){
    case SQLITE_SO_NUM:

      if( 0==(pRec->flags&(MEM_Real|MEM_Int)) ){
        /* pRec does not have a valid integer or real representation. 
        ** Attempt a conversion if pRec has a string representation and
        ** it looks like a number.
        */
        int realnum;
        if( pRec->flags&MEM_Str && sqlite3IsNumber(pRec->z, &realnum) ){
          if( realnum ){
            Realify(pRec);
          }else{
            Integerify(pRec);
          }
        }
      }










      break;

    case SQLITE_SO_TEXT:
      /* Only attempt the conversion if there is an integer or real
      ** representation (blob and NULL do not get converted) but no string
      ** representation.
      */
      if( 0==(pRec->flags&MEM_Str) && (pRec->flags&(MEM_Real|MEM_Int)) ){
        Stringify(pRec);
      }
      pRec->flags &= ~(MEM_Real|MEM_Int);

      break;

/*
    case SQLITE_AFF_INTEGER:
    case SQLITE_AFF_NONE:
      break;
*/
    default:
      assert(0);
  }
}

/*
** This function interprets the character 'affinity' according to the 
** following table and calls the applyAffinity() function.
*/
static void applyAffinityByChar(Mem *pRec, char affinity){
  switch( affinity ){
    case 'n': return applyAffinity(pRec, SQLITE_SO_NUM);
    case 't': return applyAffinity(pRec, SQLITE_SO_TEXT);
    default: assert(0);
  }
}

#ifdef VDBE_PROFILE
/*
** The following routine only works on pentium-class processors.
** It uses the RDTSC opcode to read cycle count value out of the
** processor and returns that value.  This can be used for high-res
** profiling.
*/







|





|

|
>














>
>
>
>
>
>
>
>
>
>

>
|











<
|
|

|





<
<
<
<
<
<
<
<
<
<
<
<







424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478

479
480
481
482
483
484
485
486
487












488
489
490
491
492
493
494
  return 0;
}

/*
** Apply any conversion required by the supplied column affinity to
** memory cell pRec. affinity may be one of:
**
** SQLITE_AFF_NUMERIC
** SQLITE_AFF_TEXT
** SQLITE_AFF_NONE
** SQLITE_AFF_INTEGER
**
*/
static void applyAffinity(Mem *pRec, char affinity){
  switch( affinity ){
    case SQLITE_AFF_INTEGER:
    case SQLITE_AFF_NUMERIC:
      if( 0==(pRec->flags&(MEM_Real|MEM_Int)) ){
        /* pRec does not have a valid integer or real representation. 
        ** Attempt a conversion if pRec has a string representation and
        ** it looks like a number.
        */
        int realnum;
        if( pRec->flags&MEM_Str && sqlite3IsNumber(pRec->z, &realnum) ){
          if( realnum ){
            Realify(pRec);
          }else{
            Integerify(pRec);
          }
        }
      }

      if( affinity==SQLITE_AFF_INTEGER ){
        /* For INTEGER affinity, try to convert a real value to an int */
        if( pRec->flags&MEM_Real ){
          pRec->i = pRec->r;
          if( ((double)pRec->i)==pRec->r ){
            pRec->flags |= MEM_Int;
          }
        }
      }
      break;

    case SQLITE_AFF_TEXT:
      /* Only attempt the conversion if there is an integer or real
      ** representation (blob and NULL do not get converted) but no string
      ** representation.
      */
      if( 0==(pRec->flags&MEM_Str) && (pRec->flags&(MEM_Real|MEM_Int)) ){
        Stringify(pRec);
      }
      pRec->flags &= ~(MEM_Real|MEM_Int);

      break;


    case SQLITE_AFF_NONE:
      /* Affinity NONE. Do nothing. */
      break;

    default:
      assert(0);
  }
}













#ifdef VDBE_PROFILE
/*
** The following routine only works on pentium-class processors.
** It uses the RDTSC opcode to read cycle count value out of the
** processor and returns that value.  This can be used for high-res
** profiling.
*/
768
769
770
771
772
773
774


















775
776
777
778
779
780
781
  }else{
    pTos->z = z;
    pTos->n = strlen(z) + 1;
    pTos->flags = MEM_Str | MEM_Static;
  }
  break;
}



















/* Opcode: Variable P1 * *
**
** Push the value of variable P1 onto the stack.  A variable is
** an unknown in the original SQL string as handed to sqlite3_compile().
** Any occurance of the '?' character in the original SQL is considered
** a variable.  Variables in the SQL string are number from left to







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







767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
  }else{
    pTos->z = z;
    pTos->n = strlen(z) + 1;
    pTos->flags = MEM_Str | MEM_Static;
  }
  break;
}

/* Opcode: Real * * P3
**
** The string value P3 is converted to a real and pushed on to the stack.
*/
case OP_Real: {
  char *z = pOp->p3;

  assert( z );
  assert( sqlite3IsNumber(z, 0) );

  pTos++;
  pTos->r = sqlite3AtoF(z, 0);
  pTos->z = z;
  pTos->n = strlen(z)+1;
  pTos->flags = MEM_Real|MEM_Str|MEM_Static;
  break;
}

/* Opcode: Variable P1 * *
**
** Push the value of variable P1 onto the stack.  A variable is
** an unknown in the original SQL string as handed to sqlite3_compile().
** Any occurance of the '?' character in the original SQL is considered
** a variable.  Variables in the SQL string are number from left to
1354
1355
1356
1357
1358
1359
1360

1361
1362
1363


1364
1365





1366
1367





1368
1369
1370
1371

1372
1373
1374
1375
1376
1377
1378
}

/* Opcode: Eq P1 P2 *
**
** Pop the top two elements from the stack.  If they are equal, then
** jump to instruction P2.  Otherwise, continue to the next instruction.
**

** If either operand is NULL (and thus if the result is unknown) then
** take the jump if P1 is true.
**


** If both values are numeric, they are converted to doubles using atof()
** and compared for equality that way.  Otherwise the strcmp() library





** routine is used for the comparison.  For a pure text comparison
** use OP_StrEq.





**
** If P2 is zero, do not jump.  Instead, push an integer 1 onto the
** stack if the jump would have been taken, or a 0 if not.  Push a
** NULL if either operand was NULL.

*/
/* Opcode: Ne P1 P2 *
**
** Pop the top two elements from the stack.  If they are not equal, then
** jump to instruction P2.  Otherwise, continue to the next instruction.
**
** If either operand is NULL (and thus if the result is unknown) then







>
|
|

>
>
|
|
>
>
>
>
>
|
|
>
>
>
>
>




>







1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
}

/* Opcode: Eq P1 P2 *
**
** Pop the top two elements from the stack.  If they are equal, then
** jump to instruction P2.  Otherwise, continue to the next instruction.
**
** The least significant byte of P1 may be either 0x00 or 0x01. If either
** operand is NULL (and thus if the result is unknown) then take the jump
** only if the least significant byte of P1 is 0x01.
**
** The second least significant byte of P1 determines whether any
** conversions are applied to the two values before the comparison is made.
** If this byte is 0x00, and one of the values being compared is numeric
** and the other text, an attempt is made to convert the text value to 
** a numeric form.
**
** If the second least significant byte of P1 is not 0x00, then it must
** be an affinity character - 'n', 't', 'i' or 'o'. In this case an 
** attempt is made to coerce both values according to the affinity before
** the comparison is made.
**
** Once any conversions have taken place, and neither value is NULL, 
** the values are compared. If both values are blobs, or both are text,
** then memcmp() is used to determine the results of the comparison. If
** both values are numeric, then a numeric comparison is used. If the
** two values are of different types, then they are inequal.
**
** If P2 is zero, do not jump.  Instead, push an integer 1 onto the
** stack if the jump would have been taken, or a 0 if not.  Push a
** NULL if either operand was NULL.
**
*/
/* Opcode: Ne P1 P2 *
**
** Pop the top two elements from the stack.  If they are not equal, then
** jump to instruction P2.  Otherwise, continue to the next instruction.
**
** If either operand is NULL (and thus if the result is unknown) then
1459
1460
1461
1462
1463
1464
1465


1466
1467
1468
1469
1470
1471
1472
























































1473
1474
1475
1476
1477
1478
1479
** non-numeric values.  If both operands are non-numeric, the strcmp() library
** routine is used for the comparison.  For a pure text comparison
** use OP_StrGe.
**
** If P2 is zero, do not jump.  Instead, push an integer 1 onto the
** stack if the jump would have been taken, or a 0 if not.  Push a
** NULL if either operand was NULL.


*/
case OP_Eq:
case OP_Ne:
case OP_Lt:
case OP_Le:
case OP_Gt:
case OP_Ge: {
























































  Mem *pNos = &pTos[-1];
  i64 c, v;
  int ft, fn;
  assert( pNos>=p->aStack );
  ft = pTos->flags;
  fn = pNos->flags;
  if( (ft | fn) & MEM_Null ){







>
>







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







1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
** non-numeric values.  If both operands are non-numeric, the strcmp() library
** routine is used for the comparison.  For a pure text comparison
** use OP_StrGe.
**
** If P2 is zero, do not jump.  Instead, push an integer 1 onto the
** stack if the jump would have been taken, or a 0 if not.  Push a
** NULL if either operand was NULL.
**
** FIX ME: The comment for OP_Eq is up to date, but none of the others are.
*/
case OP_Eq:
case OP_Ne:
case OP_Lt:
case OP_Le:
case OP_Gt:
case OP_Ge: {
  Mem *pNos;
  int flags;
  int res;
  char affinity;

  pNos = &pTos[-1];
  flags = pTos->flags|pNos->flags;

  /* If either value is a NULL P2 is not zero, take the jump if the least
  ** significant byte of P1 is true. If P2 is zero, then push a NULL onto
  ** the stack.
  */
  if( flags&MEM_Null ){
    popStack(&pTos, 2);
    if( pOp->p2 ){
      if( pOp->p1 ) pc = pOp->p2-1;
    }else{
      pTos++;
      pTos->flags = MEM_Null;
    }
    break;
  }

  affinity = (pOp->p1>>8)&0xFF;
  if( !affinity && (flags&(MEM_Real|MEM_Int)) ){
    affinity = SQLITE_AFF_NUMERIC;
  }
  if( affinity ){
    applyAffinity(pNos, affinity);
    applyAffinity(pTos, affinity);
  }

  res = sqlite3MemCompare(pNos, pTos);
  switch( pOp->opcode ){
    case OP_Eq:    res = res==0;     break;
    case OP_Ne:    res = res!=0;     break;
    case OP_Lt:    res = res<0;      break;
    case OP_Le:    res = res<=0;     break;
    case OP_Gt:    res = res>0;      break;
    default:       res = res>=0;     break;
  }

  popStack(&pTos, 2);
  if( pOp->p2 ){
    if( res ){
      pc = pOp->p2-1;
    }
  }else{
    pTos++;
    pTos->flags = MEM_Int;
    pTos->i = res;
  }
  break;
}

#if 0
  Mem *pNos = &pTos[-1];
  i64 c, v;
  int ft, fn;
  assert( pNos>=p->aStack );
  ft = pTos->flags;
  fn = pNos->flags;
  if( (ft | fn) & MEM_Null ){
1510
1511
1512
1513
1514
1515
1516

1517
1518
1519
1520
1521
1522
1523
  }else{
    pTos++;
    pTos->i = c;
    pTos->flags = MEM_Int;
  }
  break;
}

/* INSERT NO CODE HERE!
**
** The opcode numbers are extracted from this source file by doing
**
**    grep '^case OP_' vdbe.c | ... >opcodes.h
**
** The opcodes are numbered in the order that they appear in this file.







>







1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
  }else{
    pTos++;
    pTos->i = c;
    pTos->flags = MEM_Int;
  }
  break;
}
#endif
/* INSERT NO CODE HERE!
**
** The opcode numbers are extracted from this source file by doing
**
**    grep '^case OP_' vdbe.c | ... >opcodes.h
**
** The opcodes are numbered in the order that they appear in this file.
1869
1870
1871
1872
1873
1874
1875






































1876
1877
1878
1879
1880
1881
1882
  if( cnt<0 ) cnt = -cnt;
  assert( &pTos[1-cnt] >= p->aStack );
  for(i=0; i<cnt && (pTos[1+i-cnt].flags & MEM_Null)==0; i++){}
  if( i>=cnt ) pc = pOp->p2-1;
  if( pOp->p1>0 ) popStack(&pTos, cnt);
  break;
}







































/* Opcode: Column P1 P2 *
**
** Interpret the data that cursor P1 points to as a structure built using
** the MakeRecord instruction.  (See the MakeRecord opcode for additional
** information about the format of the data.) Push onto the stack the value
** of the P2-th column contained in the data.







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







1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
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
  if( cnt<0 ) cnt = -cnt;
  assert( &pTos[1-cnt] >= p->aStack );
  for(i=0; i<cnt && (pTos[1+i-cnt].flags & MEM_Null)==0; i++){}
  if( i>=cnt ) pc = pOp->p2-1;
  if( pOp->p1>0 ) popStack(&pTos, cnt);
  break;
}

/* Opcode: Class * * *
**
** Pop a single value from the top of the stack and push on one of the
** following strings, according to the storage class of the value just
** popped:
**
** "NULL", "INTEGER", "REAL", "TEXT", "BLOB"
**
** This opcode is probably temporary.
*/
case OP_Class: {
  int flags = pTos->flags;
  int i;

  struct {
    int mask;
    char * zClass;
  } classes[] = {
    {MEM_Null, "NULL"},
    {MEM_Int, "INTEGER"},
    {MEM_Real, "REAL"},
    {MEM_Str, "TEXT"},
    {MEM_Blob, "BLOB"}
  };

  Release(pTos);
  pTos->flags = MEM_Str|MEM_Static;

  for(i=0; i<5; i++){
    if( classes[i].mask&flags ){
      pTos->z = classes[i].zClass;
      break;
    }
  }
  assert( i<5 );
  break;
}

/* Opcode: Column P1 P2 *
**
** Interpret the data that cursor P1 points to as a structure built using
** the MakeRecord instruction.  (See the MakeRecord opcode for additional
** information about the format of the data.) Push onto the stack the value
** of the P2-th column contained in the data.
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
  ** into the record header cache fields of the cursor.
  */
  if( !pC->cacheValid ){
    pC->payloadSize = payloadSize;
    if( zRec ){
      zData = zRec;
    }else{
      /* We can assume that 9 bytes (maximum length of a varint) fits
      ** on the main page in all cases.
      */
      int n = 9;
      if( payloadSize<9 ) n = payloadSize;
      if( pC->keyAsData ){
        zData = (char *)sqlite3BtreeKeyFetch(pCrsr, n);
      }else{
        zData = (char *)sqlite3BtreeDataFetch(pCrsr, n);
      }
      assert( zData );
    }







|


|
|







2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
  ** into the record header cache fields of the cursor.
  */
  if( !pC->cacheValid ){
    pC->payloadSize = payloadSize;
    if( zRec ){
      zData = zRec;
    }else{
      /* We can assume that 10 bytes (maximum length of a varint) fits
      ** on the main page in all cases.
      */
      int n = 10;
      if( payloadSize<10 ) n = payloadSize;
      if( pC->keyAsData ){
        zData = (char *)sqlite3BtreeKeyFetch(pCrsr, n);
      }else{
        zData = (char *)sqlite3BtreeDataFetch(pCrsr, n);
      }
      assert( zData );
    }
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
  /* Loop through the elements that will make up the record to figure
  ** out how much space is required for the new record.
  */
  nBytes = sqlite3VarintLen(nField);
  for(pRec=pData0; pRec<=pTos; pRec++){
    u64 serial_type;
    if( zAffinity ){
      applyAffinityByChar(pRec, zAffinity[pRec-pData0]);
    }
    serial_type = sqlite3VdbeSerialType(pRec);
    nBytes += sqlite3VdbeSerialTypeLen(serial_type);
    nBytes += sqlite3VarintLen(serial_type);
  }

  if( nBytes>MAX_BYTES_PER_ROW ){







|







2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
  /* Loop through the elements that will make up the record to figure
  ** out how much space is required for the new record.
  */
  nBytes = sqlite3VarintLen(nField);
  for(pRec=pData0; pRec<=pTos; pRec++){
    u64 serial_type;
    if( zAffinity ){
      applyAffinity(pRec, zAffinity[pRec-pData0]);
    }
    serial_type = sqlite3VdbeSerialType(pRec);
    nBytes += sqlite3VdbeSerialTypeLen(serial_type);
    nBytes += sqlite3VarintLen(serial_type);
  }

  if( nBytes>MAX_BYTES_PER_ROW ){
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
  **
  ** TODO: Figure out if the in-place coercion causes a problem for
  ** OP_MakeKey when P2 is 0 (used by DISTINCT).
  */
  for(pRec=pData0; pRec<=pTos; pRec++){
    u64 serial_type;
    if( zAffinity ){
      applyAffinityByChar(pRec, zAffinity[pRec-pData0]);
    }else{
      applyAffinity(pRec, SQLITE_SO_NUM);
    }
    if( pRec->flags&MEM_Null ){
      containsNull = 1;
    }
    serial_type = sqlite3VdbeSerialType(pRec);







|







2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
  **
  ** TODO: Figure out if the in-place coercion causes a problem for
  ** OP_MakeKey when P2 is 0 (used by DISTINCT).
  */
  for(pRec=pData0; pRec<=pTos; pRec++){
    u64 serial_type;
    if( zAffinity ){
      applyAffinity(pRec, zAffinity[pRec-pData0]);
    }else{
      applyAffinity(pRec, SQLITE_SO_NUM);
    }
    if( pRec->flags&MEM_Null ){
      containsNull = 1;
    }
    serial_type = sqlite3VdbeSerialType(pRec);
Changes to src/vdbeInt.h.
329
330
331
332
333
334
335

u64 sqlite3VdbeSerialType(const Mem *);
int sqlite3VdbeSerialPut(unsigned char *, const Mem *);
int sqlite3VdbeSerialGet(const unsigned char *, u64, Mem *);

int sqlite2BtreeKeyCompare(BtCursor *, const void *, int, int, int *);
int sqlite3VdbeIdxKeyCompare(Cursor*, int , const unsigned char*, int, int*);
int sqlite3VdbeIdxRowid(BtCursor *, i64 *);








>
329
330
331
332
333
334
335
336
u64 sqlite3VdbeSerialType(const Mem *);
int sqlite3VdbeSerialPut(unsigned char *, const Mem *);
int sqlite3VdbeSerialGet(const unsigned char *, u64, Mem *);

int sqlite2BtreeKeyCompare(BtCursor *, const void *, int, int, int *);
int sqlite3VdbeIdxKeyCompare(Cursor*, int , const unsigned char*, int, int*);
int sqlite3VdbeIdxRowid(BtCursor *, i64 *);
int sqlite3MemCompare(Mem *, Mem *);
Changes to src/vdbeaux.c.
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
** negative, zero or positive if pMem1 is less than, equal to, or greater
** than pMem2. Sorting order is NULL's first, followed by numbers (integers
** and reals) sorted numerically, followed by text ordered by memcmp() and
** finally blob's ordered by memcmp().
**
** Two NULL values are considered equal by this function.
*/
int compareMemCells(Mem *pMem1, Mem *pMem2){
  int rc;
  int combined_flags = pMem1->flags|pMem2->flags; 
 
  /* If one value is NULL, it is less than the other. If both values
  ** are NULL, return 0.
  */
  if( combined_flags&MEM_Null ){







|







1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
** negative, zero or positive if pMem1 is less than, equal to, or greater
** than pMem2. Sorting order is NULL's first, followed by numbers (integers
** and reals) sorted numerically, followed by text ordered by memcmp() and
** finally blob's ordered by memcmp().
**
** Two NULL values are considered equal by this function.
*/
int sqlite3MemCompare(Mem *pMem1, Mem *pMem2){
  int rc;
  int combined_flags = pMem1->flags|pMem2->flags; 
 
  /* If one value is NULL, it is less than the other. If both values
  ** are NULL, return 0.
  */
  if( combined_flags&MEM_Null ){
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
    ** data to go with the serial type just read. This assert may fail if
    ** the file is corrupted.  Then read the value from each key into mem1
    ** and mem2 respectively.
    */
    offset1 += sqlite3VdbeSerialGet(&aKey1[offset1], serial_type1, &mem1);
    offset2 += sqlite3VdbeSerialGet(&aKey2[offset2], serial_type2, &mem2);

    rc = compareMemCells(&mem1, &mem2);
    if( mem1.flags&MEM_Dyn ){
      sqliteFree(mem1.z);
    }
    if( mem2.flags&MEM_Dyn ){
      sqliteFree(mem2.z);
    }
    if( rc!=0 ){







|







1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
    ** data to go with the serial type just read. This assert may fail if
    ** the file is corrupted.  Then read the value from each key into mem1
    ** and mem2 respectively.
    */
    offset1 += sqlite3VdbeSerialGet(&aKey1[offset1], serial_type1, &mem1);
    offset2 += sqlite3VdbeSerialGet(&aKey2[offset2], serial_type2, &mem2);

    rc = sqlite3MemCompare(&mem1, &mem2);
    if( mem1.flags&MEM_Dyn ){
      sqliteFree(mem1.z);
    }
    if( mem2.flags&MEM_Dyn ){
      sqliteFree(mem2.z);
    }
    if( rc!=0 ){
Changes to src/where.c.
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This module contains C code that generates VDBE code used to process
** the WHERE clause of SQL statements.
**
** $Id: where.c,v 1.93 2004/05/14 11:16:56 danielk1977 Exp $
*/
#include "sqliteInt.h"

/*
** The query generator uses an array of instances of this structure to
** help it analyze the subexpressions of the WHERE clause.  Each WHERE
** clause subexpression is separated from the others by an AND operator.







|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This module contains C code that generates VDBE code used to process
** the WHERE clause of SQL statements.
**
** $Id: where.c,v 1.94 2004/05/16 11:15:41 danielk1977 Exp $
*/
#include "sqliteInt.h"

/*
** The query generator uses an array of instances of this structure to
** help it analyze the subexpressions of the WHERE clause.  Each WHERE
** clause subexpression is separated from the others by an AND operator.
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
      }
      pLevel->iMem = pParse->nMem++;
      cont = pLevel->cont = sqlite3VdbeMakeLabel(v);
      sqlite3VdbeAddOp(v, OP_NotNull, -nColumn, sqlite3VdbeCurrentAddr(v)+3);
      sqlite3VdbeAddOp(v, OP_Pop, nColumn, 0);
      sqlite3VdbeAddOp(v, OP_Goto, 0, brk);
      sqlite3VdbeAddOp(v, OP_MakeKey, nColumn, 0);
      sqlite3AddIdxKeyType(v, pIdx);
      sqlite3VdbeAddOp(v, OP_MemStore, pLevel->iMem, 0);
      if( nColumn==pIdx->nColumn || pLevel->bRev ){
        testOp = OP_IdxGT;
      }else{
        testOp = OP_IdxGE;
      }
      if( pLevel->bRev ){







|







794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
      }
      pLevel->iMem = pParse->nMem++;
      cont = pLevel->cont = sqlite3VdbeMakeLabel(v);
      sqlite3VdbeAddOp(v, OP_NotNull, -nColumn, sqlite3VdbeCurrentAddr(v)+3);
      sqlite3VdbeAddOp(v, OP_Pop, nColumn, 0);
      sqlite3VdbeAddOp(v, OP_Goto, 0, brk);
      sqlite3VdbeAddOp(v, OP_MakeKey, nColumn, 0);
      sqlite3IndexAffinityStr(v, pIdx);
      sqlite3VdbeAddOp(v, OP_MemStore, pLevel->iMem, 0);
      if( nColumn==pIdx->nColumn || pLevel->bRev ){
        testOp = OP_IdxGT;
      }else{
        testOp = OP_IdxGE;
      }
      if( pLevel->bRev ){
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
      if( testOp!=OP_Noop ){
        int nCol = nEqColumn + (score & 1);
        pLevel->iMem = pParse->nMem++;
        sqlite3VdbeAddOp(v, OP_NotNull, -nCol, sqlite3VdbeCurrentAddr(v)+3);
        sqlite3VdbeAddOp(v, OP_Pop, nCol, 0);
        sqlite3VdbeAddOp(v, OP_Goto, 0, brk);
        sqlite3VdbeAddOp(v, OP_MakeKey, nCol, 0);
        sqlite3AddIdxKeyType(v, pIdx);
        if( pLevel->bRev ){
          sqlite3VdbeAddOp(v, OP_MoveLt, pLevel->iCur, brk);
          if( !geFlag ){
            sqlite3VdbeChangeP3(v, -1, "+", P3_STATIC);
          }
        }else{
          sqlite3VdbeAddOp(v, OP_MemStore, pLevel->iMem, 1);







|







999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
      if( testOp!=OP_Noop ){
        int nCol = nEqColumn + (score & 1);
        pLevel->iMem = pParse->nMem++;
        sqlite3VdbeAddOp(v, OP_NotNull, -nCol, sqlite3VdbeCurrentAddr(v)+3);
        sqlite3VdbeAddOp(v, OP_Pop, nCol, 0);
        sqlite3VdbeAddOp(v, OP_Goto, 0, brk);
        sqlite3VdbeAddOp(v, OP_MakeKey, nCol, 0);
        sqlite3IndexAffinityStr(v, pIdx);
        if( pLevel->bRev ){
          sqlite3VdbeAddOp(v, OP_MoveLt, pLevel->iCur, brk);
          if( !geFlag ){
            sqlite3VdbeChangeP3(v, -1, "+", P3_STATIC);
          }
        }else{
          sqlite3VdbeAddOp(v, OP_MemStore, pLevel->iMem, 1);
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
      }
      if( nEqColumn>0 || (score&2)!=0 ){
        int nCol = nEqColumn + ((score&2)!=0);
        sqlite3VdbeAddOp(v, OP_NotNull, -nCol, sqlite3VdbeCurrentAddr(v)+3);
        sqlite3VdbeAddOp(v, OP_Pop, nCol, 0);
        sqlite3VdbeAddOp(v, OP_Goto, 0, brk);
        sqlite3VdbeAddOp(v, OP_MakeKey, nCol, 0);
        sqlite3AddIdxKeyType(v, pIdx);
        if( pLevel->bRev ){
          pLevel->iMem = pParse->nMem++;
          sqlite3VdbeAddOp(v, OP_MemStore, pLevel->iMem, 1);
          testOp = OP_IdxLT;
        }else{
          sqlite3VdbeAddOp(v, OP_MoveTo, pLevel->iCur, brk);
          if( !geFlag ){







|







1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
      }
      if( nEqColumn>0 || (score&2)!=0 ){
        int nCol = nEqColumn + ((score&2)!=0);
        sqlite3VdbeAddOp(v, OP_NotNull, -nCol, sqlite3VdbeCurrentAddr(v)+3);
        sqlite3VdbeAddOp(v, OP_Pop, nCol, 0);
        sqlite3VdbeAddOp(v, OP_Goto, 0, brk);
        sqlite3VdbeAddOp(v, OP_MakeKey, nCol, 0);
        sqlite3IndexAffinityStr(v, pIdx);
        if( pLevel->bRev ){
          pLevel->iMem = pParse->nMem++;
          sqlite3VdbeAddOp(v, OP_MemStore, pLevel->iMem, 1);
          testOp = OP_IdxLT;
        }else{
          sqlite3VdbeAddOp(v, OP_MoveTo, pLevel->iCur, brk);
          if( !geFlag ){
Changes to test/types.test.
1
2
3
4
5
6
7
8
9
10
11


12
13
14
15
16
17
18

19















20
21
22
23

24




25














26


















27


















28



29

















30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
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
196
197
198
199
200

# 2001 September 15
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    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.
#
#***********************************************************************
# This file implements regression tests for SQLite library. 


#
# $Id:


set testdir [file dirname $argv0]
source $testdir/tester.tcl


#















# Test cases are organized as follows:
#
# types-1.*: Insert some records with integers of various sizes, checking 
#            that the integers are stored correctly and can be retrieved.

# types-2.*: Insert and retrieve some records with reals.




# types-3.*: Insert and retrieve some records with NULLs.














# types-4.*: Insert and retrieve some records with strings of various sizes.


















# types-5.*: Some tests inserting and retrieving records with several


















#            fields each.



#


















# Open the table with root-page $rootpage at the btree
# level. Return a list that is the length of each record
# in the table, in the tables default scanning order.
proc record_sizes {rootpage} {
  set bt [btree_open test.db 10 0]
  set c [btree_cursor $bt $rootpage 0]
  btree_first $c
  while 1 {
    lappend res [btree_payload_size $c]
    if {[btree_next $c]} break
  }
  btree_close_cursor $c
  btree_close $bt
  set res
}


# Create a table and insert some 1-byte integers. Make sure they 
# can be read back OK. These should be 3 byte records.
do_test types-1.1 {
  execsql {
    CREATE TABLE t1(a integer);
    INSERT INTO t1 VALUES(0);
    INSERT INTO t1 VALUES(120);
    INSERT INTO t1 VALUES(-120);
  }
} {}
do_test types-1.2 {
  execsql {
    SELECT a FROM t1;
  }
} {0 120 -120}

# Try some 2-byte integers (4 byte records)
do_test types-1.3 {
  execsql {
    INSERT INTO t1 VALUES(30000);
    INSERT INTO t1 VALUES(-30000);
  }
} {}
do_test types-1.4 {
  execsql {
    SELECT a FROM t1;
  }
} {0 120 -120 30000 -30000}

# 4-byte integers (6 byte records)
do_test types-1.5 {
  execsql {
    INSERT INTO t1 VALUES(2100000000);
    INSERT INTO t1 VALUES(-2100000000);
  }
} {}
do_test types-1.6 {
  execsql {
    SELECT a FROM t1;
  }
} {0 120 -120 30000 -30000 2100000000 -2100000000}

# 8-byte integers (10 byte records)
do_test types-1.7 {
  execsql {
    INSERT INTO t1 VALUES(9000000*1000000*1000000);
    INSERT INTO t1 VALUES(-9000000*1000000*1000000);
  }
} {}
do_test types-1.8 {
  execsql {
    SELECT a FROM t1;
  }
} [list 0 120 -120 30000 -30000 2100000000 -2100000000 \
        9000000000000000000 -9000000000000000000]

# Check that all the record sizes are as we expected.
do_test types-1.9 {
  set root [db eval {select rootpage from sqlite_master where name = 't1'}]
  record_sizes $root
} {3 3 3 4 4 6 6 10 10}

# Insert some reals. These should be 10 byte records.
do_test types-2.1 {
  execsql {
    CREATE TABLE t2(a float);
    INSERT INTO t2 VALUES(0.0 + 0.0);
    INSERT INTO t2 VALUES(12345.678 + 0.0);
    INSERT INTO t2 VALUES(-12345.678 + 0.0);
  }
} {}
do_test types-2.2 {
  execsql {
    SELECT a FROM t2;
  }
} {0 12345.678 -12345.678}

# Check that all the record sizes are as we expected.
do_test types-2.3 {
  set root [db eval {select rootpage from sqlite_master where name = 't2'}]
  record_sizes $root
} {10 10 10}

# Insert a NULL. This should be a two byte record.
do_test types-3.1 {
  execsql {
    CREATE TABLE t3(a nullvalue);
    INSERT INTO t3 VALUES(NULL);
  }
} {}
do_test types-3.2 {
  execsql {
    SELECT a ISNULL FROM t3;
  }
} {1}

# Check that all the record sizes are as we expected.
do_test types-3.3 {
  set root [db eval {select rootpage from sqlite_master where name = 't3'}]
  record_sizes $root
} {2}

# Insert a couple of strings.
do_test types-4.1 {
  set string10 abcdefghij
  set string500 [string repeat $string10 50]
  set string500000 [string repeat $string10 50000]

  execsql "
    CREATE TABLE t4(a string);
    INSERT INTO t4 VALUES('$string10');
    INSERT INTO t4 VALUES('$string500');
    INSERT INTO t4 VALUES('$string500000');
  "
} {}
do_test types-4.2 {
  execsql {
    SELECT a FROM t4;
  }
} [list $string10 $string500 $string500000]

# Check that all the record sizes are as we expected.
do_test types-4.3 {
  set root [db eval {select rootpage from sqlite_master where name = 't4'}]
  record_sizes $root
} {13 504 500005}

do_test types-5.1 {
  execsql {
    DROP TABLE t1;
    DROP TABLE t2;
    DROP TABLE t3;
    DROP TABLE t4;
    CREATE TABLE t1(a, b, c);
  }
} {}
do_test types-5.2 {
  set string10 abcdefghij
  set string500 [string repeat $string10 50]
  set string500000 [string repeat $string10 50000]

  execsql "INSERT INTO t1 VALUES(NULL, '$string10', 4000);"
  execsql "INSERT INTO t1 VALUES('$string500', 4000, NULL);"
  execsql "INSERT INTO t1 VALUES(4000, NULL, '$string500000');"
} {}
do_test types-5.3 {
  execsql {
    SELECT * FROM t1;
  }
} [list {} $string10 4000 $string500 4000 {} 4000 {} $string500000]


finish_test











|
>
>

<
|




>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|

|
|
>
|
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>

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




















|







|






|





|






|





|






|





|







|





|


|
|
|


|






|





|





|






|





|











|






|




|








|








|





<

>
1
2
3
4
5
6
7
8
9
10
11
12
13
14

15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
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
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
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290

291
292
# 2001 September 15
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    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.
#
#***********************************************************************
# This file implements regression tests for SQLite library. Specfically
# it tests that the different storage classes (integer, real, text etc.)
# all work correctly.
#

# $Id: types.test,v 1.2 2004/05/16 11:15:42 danielk1977 Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Tests in this file are organized roughly as follows:
#
# types-1.*.*: Test that values are stored using the expected storage
#              classes when various forms of literals are inserted into
#              columns with different affinities.
# types-1.1.*: INSERT INTO <table> VALUES(...)
# types-1.2.*: INSERT INTO <table> SELECT...
# types-1.3.*: UPDATE <table> SET...
#
# types-2.*.*: Check that values can be stored and retrieving using the
#              various storage classes.
# types-2.1.*: INTEGER
# types-2.2.*: REAL
# types-2.3.*: NULL
# types-2.4.*: TEXT
# types-2.5.*: Records with a few different storage classes.
#
# types-3.*: Test that the '=' operator respects manifest types.
#


# Create a table with one column for each type of affinity
do_test types-1.1.0 {
  execsql {
    CREATE TABLE t1(i integer, n numeric, t text, o);
  }
} {}

# Each element of the following list represents one test case.
#
# The first value of each sub-list is an SQL literal. The following
# four value are the storage classes that would be used if the
# literal were inserted into a column with affinity INTEGER, NUMERIC, TEXT
# or NONE, respectively.
set values [list \
  [list 5.0   INTEGER REAL    TEXT REAL] \
  [list 5     INTEGER INTEGER TEXT INTEGER] \
  [list '5.0' INTEGER REAL    TEXT TEXT] \
  [list '5'   INTEGER INTEGER TEXT TEXT] \
  [list 'abc' TEXT    TEXT    TEXT TEXT] \
  [list NULL  NULL    NULL    NULL NULL] \
]

# This code tests that the storage classes specified above (in the $values
# table) are correctly assigned when values are inserted using a statement
# of the form:
#
# INSERT INTO <table> VALUE(<values>);
#
set tnum 1
foreach val $values {
  set lit [lindex $val 0]
  execsql "DELETE FROM t1;"
  execsql "INSERT INTO t1 VALUES($lit, $lit, $lit, $lit);"
  do_test types-1.1.$tnum {
    execsql {
      SELECT classof(i), classof(n), classof(t), classof(o) FROM t1;
    }
  } [lrange $val 1 end]
  incr tnum
}

# This code tests that the storage classes specified above (in the $values
# table) are correctly assigned when values are inserted using a statement
# of the form:
#
# INSERT INTO t1 SELECT ....
#
set tnum 1
foreach val $values {
  set lit [lindex $val 0]
  execsql "DELETE FROM t1;"
  execsql "INSERT INTO t1 SELECT $lit, $lit, $lit, $lit;"
  do_test types-1.2.$tnum {
    execsql {
      SELECT classof(i), classof(n), classof(t), classof(o) FROM t1;
    }
  } [lrange $val 1 end]
  incr tnum
}

# This code tests that the storage classes specified above (in the $values
# table) are correctly assigned when values are inserted using a statement
# of the form:
#
# UPDATE <table> SET <column> = <value>;
#
set tnum 1
foreach val $values {
  set lit [lindex $val 0]
  execsql "UPDATE t1 SET i = $lit, n = $lit, t = $lit, o = $lit;"
  do_test types-1.3.$tnum {
    execsql {
      SELECT classof(i), classof(n), classof(t), classof(o) FROM t1;
    }
  } [lrange $val 1 end]
  incr tnum
}

execsql {
  DROP TABLE t1;
}

# Open the table with root-page $rootpage at the btree
# level. Return a list that is the length of each record
# in the table, in the tables default scanning order.
proc record_sizes {rootpage} {
  set bt [btree_open test.db 10 0]
  set c [btree_cursor $bt $rootpage 0]
  btree_first $c
  while 1 {
    lappend res [btree_payload_size $c]
    if {[btree_next $c]} break
  }
  btree_close_cursor $c
  btree_close $bt
  set res
}


# Create a table and insert some 1-byte integers. Make sure they 
# can be read back OK. These should be 3 byte records.
do_test types-2.1.1 {
  execsql {
    CREATE TABLE t1(a integer);
    INSERT INTO t1 VALUES(0);
    INSERT INTO t1 VALUES(120);
    INSERT INTO t1 VALUES(-120);
  }
} {}
do_test types-2.1.2 {
  execsql {
    SELECT a FROM t1;
  }
} {0 120 -120}

# Try some 2-byte integers (4 byte records)
do_test types-2.1.3 {
  execsql {
    INSERT INTO t1 VALUES(30000);
    INSERT INTO t1 VALUES(-30000);
  }
} {}
do_test types-2.1.4 {
  execsql {
    SELECT a FROM t1;
  }
} {0 120 -120 30000 -30000}

# 4-byte integers (6 byte records)
do_test types-2.1.5 {
  execsql {
    INSERT INTO t1 VALUES(2100000000);
    INSERT INTO t1 VALUES(-2100000000);
  }
} {}
do_test types-2.1.6 {
  execsql {
    SELECT a FROM t1;
  }
} {0 120 -120 30000 -30000 2100000000 -2100000000}

# 8-byte integers (10 byte records)
do_test types-2.1.7 {
  execsql {
    INSERT INTO t1 VALUES(9000000*1000000*1000000);
    INSERT INTO t1 VALUES(-9000000*1000000*1000000);
  }
} {}
do_test types-2.1.8 {
  execsql {
    SELECT a FROM t1;
  }
} [list 0 120 -120 30000 -30000 2100000000 -2100000000 \
        9000000000000000000 -9000000000000000000]

# Check that all the record sizes are as we expected.
do_test types-2.1.9 {
  set root [db eval {select rootpage from sqlite_master where name = 't1'}]
  record_sizes $root
} {3 3 3 4 4 6 6 10 10}

# Insert some reals. These should be 10 byte records.
do_test types-2.2.1 {
  execsql {
    CREATE TABLE t2(a float);
    INSERT INTO t2 VALUES(0.0);
    INSERT INTO t2 VALUES(12345.678);
    INSERT INTO t2 VALUES(-12345.678);
  }
} {}
do_test types-2.2.2 {
  execsql {
    SELECT a FROM t2;
  }
} {0 12345.678 -12345.678}

# Check that all the record sizes are as we expected.
do_test types-2.2.3 {
  set root [db eval {select rootpage from sqlite_master where name = 't2'}]
  record_sizes $root
} {10 10 10}

# Insert a NULL. This should be a two byte record.
do_test types-2.3.1 {
  execsql {
    CREATE TABLE t3(a nullvalue);
    INSERT INTO t3 VALUES(NULL);
  }
} {}
do_test types-2.3.2 {
  execsql {
    SELECT a ISNULL FROM t3;
  }
} {1}

# Check that all the record sizes are as we expected.
do_test types-2.3.3 {
  set root [db eval {select rootpage from sqlite_master where name = 't3'}]
  record_sizes $root
} {2}

# Insert a couple of strings.
do_test types-2.4.1 {
  set string10 abcdefghij
  set string500 [string repeat $string10 50]
  set string500000 [string repeat $string10 50000]

  execsql "
    CREATE TABLE t4(a string);
    INSERT INTO t4 VALUES('$string10');
    INSERT INTO t4 VALUES('$string500');
    INSERT INTO t4 VALUES('$string500000');
  "
} {}
do_test types-2.4.2 {
  execsql {
    SELECT a FROM t4;
  }
} [list $string10 $string500 $string500000]

# Check that all the record sizes are as we expected.
do_test types-2.4.3 {
  set root [db eval {select rootpage from sqlite_master where name = 't4'}]
  record_sizes $root
} {13 504 500005}

do_test types-2.5.1 {
  execsql {
    DROP TABLE t1;
    DROP TABLE t2;
    DROP TABLE t3;
    DROP TABLE t4;
    CREATE TABLE t1(a, b, c);
  }
} {}
do_test types-2.5.2 {
  set string10 abcdefghij
  set string500 [string repeat $string10 50]
  set string500000 [string repeat $string10 50000]

  execsql "INSERT INTO t1 VALUES(NULL, '$string10', 4000);"
  execsql "INSERT INTO t1 VALUES('$string500', 4000, NULL);"
  execsql "INSERT INTO t1 VALUES(4000, NULL, '$string500000');"
} {}
do_test types-2.5.3 {
  execsql {
    SELECT * FROM t1;
  }
} [list {} $string10 4000 $string500 4000 {} 4000 {} $string500000]


finish_test

Added test/types2.test.


























































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
# 2001 September 15
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    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.
#
#***********************************************************************
# This file implements regression tests for SQLite library. The focus
# of this file is testing the interaction of manifest types, type affinity
# and comparison expressions.
#
# $Id: types2.test,v 1.1 2004/05/16 11:15:42 danielk1977 Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Tests in this file are organized roughly as follows:
#
# types2-1.*: The '=' operator in the absence of an index.
# types2-2.*: The '=' operator implemented using an index.
# types2-2.*: The '<' operator implemented using an index.
# types2-3.*: The '>' operator in the absense of an index.
#

execsql {
  CREATE TABLE t1(
    i1 INTEGER,
    i2 INTEGER,
    n1 NUMERIC,
    n2 NUMERIC,
    t1 TEXT,
    t2 TEXT,
    o1,
    o2
  );
  INSERT INTO t1 VALUES(NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
}

proc test_bool {testname vars expr res} {
  if { $vars != "" } {
    execsql "UPDATE t1 SET $vars"
  }

  foreach {t e r} [list $testname $expr $res] {}

  do_test $t.1 "execsql {SELECT $e FROM t1}" $r
  do_test $t.2 "execsql {SELECT 1 FROM t1 WHERE $expr}" [expr $r?"1":""]
  do_test $t.3 "execsql {SELECT 1 FROM t1 WHERE NOT ($e)}" [expr $r?"":"1"]
}

# Compare literals against literals
test_bool types2-1.1 "" {500 = 500.0} 1
test_bool types2-1.2 "" {'500' = 500.0} 1
test_bool types2-1.3 "" {500 = '500.0'} 1
test_bool types2-1.4 "" {'500' = '500.0'} 0

# Compare literals against a column with TEXT affinity
test_bool types2-1.5 {t1=500} {500 = t1} 1
test_bool types2-1.6 {t1=500} {'500' = t1} 1
test_bool types2-1.7 {t1=500} {500.0 = t1} 0
test_bool types2-1.8 {t1=500} {'500.0' = t1} 0
test_bool types2-1.9 {t1='500'} {500 = t1} 1
test_bool types2-1.10 {t1='500'} {'500' = t1} 1
test_bool types2-1.11 {t1='500'} {500.0 = t1} 0
test_bool types2-1.12 {t1='500'} {'500.0' = t1} 0

# Compare literals against a column with NUMERIC affinity
test_bool types2-1.13 {n1=500} {500 = n1} 1
test_bool types2-1.14 {n1=500} {'500' = n1} 1
test_bool types2-1.15 {n1=500} {500.0 = n1} 1
test_bool types2-1.16 {n1=500} {'500.0' = n1} 1
test_bool types2-1.17 {n1='500'} {500 = n1} 1
test_bool types2-1.18 {n1='500'} {'500' = n1} 1
test_bool types2-1.19 {n1='500'} {500.0 = n1} 1
test_bool types2-1.20 {n1='500'} {'500.0' = n1} 1

# Compare literals against a column with affinity NONE
test_bool types2-1.21 {o1=500} {500 = o1} 1
test_bool types2-1.22 {o1=500} {'500' = o1} 0
test_bool types2-1.23 {o1=500} {500.0 = o1} 1
test_bool types2-1.24 {o1=500} {'500.0' = o1} 0
test_bool types2-1.25 {o1='500'} {500 = o1} 0
test_bool types2-1.26 {o1='500'} {'500' = o1} 1
test_bool types2-1.27 {o1='500'} {500.0 = o1} 0
test_bool types2-1.28 {o1='500'} {'500.0' = o1} 0

set vals [list 10 10.0 '10' '10.0' 20 20.0 '20' '20.0' 30 30.0 '30' '30.0']
#              1  2    3    4      5  6    7    8      9  10   11   12

execsql {
  CREATE TABLE t2(i INTEGER, n NUMERIC, t TEXT, o);
  CREATE INDEX t2i1 ON t2(i);
  CREATE INDEX t2i2 ON t2(n);
  CREATE INDEX t2i3 ON t2(t);
  CREATE INDEX t2i4 ON t2(o);
}
foreach v $vals {
  execsql "INSERT INTO t2 VALUES($v, $v, $v, $v);"
}

proc test_boolset {testname where set} {
  set ::tb_sql "SELECT rowid FROM t2 WHERE $where"
  do_test $testname {
    lsort -integer [execsql $::tb_sql]
  } $set
}

test_boolset types2-2.1 {i = 10} {1 2 3 4}
test_boolset types2-2.2 {i = 10.0} {1 2 3 4}
test_boolset types2-2.3 {i = '10'} {1 2 3 4}
test_boolset types2-2.4 {i = '10.0'} {1 2 3 4}

test_boolset types2-2.5 {n = 20} {5 6 7 8}
test_boolset types2-2.6 {n = 20.0} {5 6 7 8}
test_boolset types2-2.7 {n = '20'} {5 6 7 8}
test_boolset types2-2.8 {n = '20.0'} {5 6 7 8}

test_boolset types2-2.9 {t = 20} {5 7}
test_boolset types2-2.10 {t = 20.0} {6 8}
test_boolset types2-2.11 {t = '20'} {5 7}
test_boolset types2-2.12 {t = '20.0'} {6 8}

test_boolset types2-2.10 {o = 30} {9 10}
test_boolset types2-2.11 {o = 30.0} {9 10}
test_boolset types2-2.12 {o = '30'} 11
test_boolset types2-2.13 {o = '30.0'} 12

test_boolset types2-3.1 {i < 20} {1 2 3 4}
test_boolset types2-3.2 {i < 20.0} {1 2 3 4}
test_boolset types2-3.3 {i < '20'} {1 2 3 4}
test_boolset types2-3.4 {i < '20.0'} {1 2 3 4}

test_boolset types2-3.1 {n < 20} {1 2 3 4}
test_boolset types2-3.2 {n < 20.0} {1 2 3 4}
test_boolset types2-3.3 {n < '20'} {1 2 3 4}
test_boolset types2-3.4 {n < '20.0'} {1 2 3 4}

test_boolset types2-3.1 {t < 20} {1 2 3 4}
test_boolset types2-3.2 {t < 20.0} {1 2 3 4 5 7}
test_boolset types2-3.3 {t < '20'} {1 2 3 4}
test_boolset types2-3.4 {t < '20.0'} {1 2 3 4 5 7}

test_boolset types2-3.1 {o < 20} {1 2}
test_boolset types2-3.2 {o < 20.0} {1 2}
test_boolset types2-3.3 {o < '20'} {1 2 3 4 5 6 9 10}
test_boolset types2-3.3 {o < '20.0'} {1 2 3 4 5 6 7 9 10}

# Compare literals against literals
test_bool types2-4.1 "" {500 > 60.0} 1
test_bool types2-4.2 "" {'500' > 60.0} 1
test_bool types2-4.3 "" {500 > '60.0'} 1
test_bool types2-4.4 "" {'500' > '60.0'} 0

# Compare literals against a column with TEXT affinity
test_bool types2-4.5 {t1=500.0} {t1 > 500} 1
test_bool types2-4.6 {t1=500.0} {t1 > '500' } 1
test_bool types2-4.7 {t1=500.0} {t1 > 500.0 } 0
test_bool types2-4.8 {t1=500.0} {t1 > '500.0' } 0
test_bool types2-4.9 {t1='500.0'} {t1 > 500 } 1
test_bool types2-4.10 {t1='500.0'} {t1 > '500' } 1
test_bool types2-4.11 {t1='500.0'} {t1 > 500.0 } 0
test_bool types2-4.12 {t1='500.0'} {t1 > '500.0' } 0

# Compare literals against a column with NUMERIC affinity
test_bool types2-4.13 {n1=400} {500 > n1} 1
test_bool types2-4.14 {n1=400} {'500' > n1} 1
test_bool types2-4.15 {n1=400} {500.0 > n1} 1
test_bool types2-4.16 {n1=400} {'500.0' > n1} 1
test_bool types2-4.17 {n1='400'} {500 > n1} 1
test_bool types2-4.18 {n1='400'} {'500' > n1} 1
test_bool types2-4.19 {n1='400'} {500.0 > n1} 1
test_bool types2-4.20 {n1='400'} {'500.0' > n1} 1

# Compare literals against a column with affinity NONE
test_bool types2-4.21 {o1=500} {500 > o1} 0
test_bool types2-4.22 {o1=500} {'500' > o1} 1
test_bool types2-4.23 {o1=500} {500.0 > o1} 0
test_bool types2-4.24 {o1=500} {'500.0' > o1} 1
test_bool types2-4.25 {o1='500'} {500 > o1} 0
test_bool types2-4.26 {o1='500'} {'500' > o1} 0
test_bool types2-4.27 {o1='500'} {500.0 > o1} 0
test_bool types2-4.28 {o1='500'} {'500.0' > o1} 1

finish_test