/ Check-in [14474fa1]
Login

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

Overview
Comment:Everything is working on Linux. This is release 2.0-Alpha-1. (CVS 246)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 14474fa144fe7c5dc63e0990d6cc92d769e6013e
User & Date: drh 2001-09-15 00:57:28
Context
2001-09-15
00:58
Release 2.0-alpha-1 (CVS 247) check-in: 264f2331 user: drh tags: trunk
00:57
Everything is working on Linux. This is release 2.0-Alpha-1. (CVS 246) check-in: 14474fa1 user: drh tags: trunk
2001-09-14
18:54
Added a PRAGMA statement. Took out the special comment parsing. (CVS 245) check-in: 5e372460 user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/TODO.

1
2
3
4
5
6
7
  *  Document all the changes and release Sqlite 2.0.
  *  Implement CLUSTER command like in PostgreSQL.
  *  "OPTIMIZE select" statement to automatically create indices and/or
     invoke a CLUSTER command.
  *  "CREATE INDEX FOR select" to automatically generate needed indices.
  *  Implement a PRAGMA command
  *  Parse and use constraints.





<

1
2
3
4
5

6
  *  Document all the changes and release Sqlite 2.0.
  *  Implement CLUSTER command like in PostgreSQL.
  *  "OPTIMIZE select" statement to automatically create indices and/or
     invoke a CLUSTER command.
  *  "CREATE INDEX FOR select" to automatically generate needed indices.

  *  Parse and use constraints.

Changes to src/build.c.

29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
..
63
64
65
66
67
68
69

70
71
72
73
74
75
76
...
274
275
276
277
278
279
280

281
282
283
284
285
286
287
...
310
311
312
313
314
315
316

317
318
319
320
321
322
323
...
394
395
396
397
398
399
400

401
402
403
404
405
406
407
...
445
446
447
448
449
450
451
























452
453
454
455
456
457
458
...
499
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
...
582
583
584
585
586
587
588

589
590
591
592
593

594
595
596
597


598
599
600
601
602
603
604
...
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
...
857
858
859
860
861
862
863

864
865
866
867
868
869

870
871
872
873


874
875
876
877
878
879
880
....
1033
1034
1035
1036
1037
1038
1039

1040
1041
1042
1043
1044
1045
1046
....
1105
1106
1107
1108
1109
1110
1111

1112
1113
1114
1115
1116
1117
1118
....
1143
1144
1145
1146
1147
1148
1149

1150
1151
1152
1153
1154
1155
1156
**     DROP TABLE
**     CREATE INDEX
**     DROP INDEX
**     creating expressions and ID lists
**     COPY
**     VACUUM
**
** $Id: build.c,v 1.34 2001/09/14 18:54:08 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

/*
** This routine is called after a single SQL statement has been
** parsed and we want to execute the VDBE code to implement 
................................................................................
                          &pParse->zErrMsg, db->pBusyArg,
                          db->xBusyCallback);
    }
    sqliteVdbeDelete(pParse->pVdbe);
    pParse->pVdbe = 0;
    pParse->colNamesSet = 0;
    pParse->rc = rc;

  }
}

/*
** Construct a new expression node and return a pointer to it.
*/
Expr *sqliteExpr(int op, Expr *pLeft, Expr *pRight, Token *pToken){
................................................................................
** deallocation. 
**
** See also: sqliteRollbackInternalChanges()
*/
void sqliteCommitInternalChanges(sqlite *db){
  int i;
  if( (db->flags & SQLITE_InternChanges)==0 ) return;

  for(i=0; i<N_HASH; i++){
    Table *pTable, *pNext;
    for(pTable = db->apTblHash[i]; pTable; pTable=pNext){
      pNext = pTable->pHash;
      if( pTable->isDelete ){
        sqliteUnlinkAndDeleteTable(db, pTable);
      }else if( pTable->isCommit==0 ){
................................................................................
** internal hash tables are undone.
**
** See also: sqliteCommitInternalChanges()
*/
void sqliteRollbackInternalChanges(sqlite *db){
  int i;
  if( (db->flags & SQLITE_InternChanges)==0 ) return;

  for(i=0; i<N_HASH; i++){
    Table *pTable, *pNext;
    for(pTable = db->apTblHash[i]; pTable; pTable=pNext){
      pNext = pTable->pHash;
      if( !pTable->isCommit ){
        sqliteUnlinkAndDeleteTable(db, pTable);
      }else if( pTable->isDelete ){
................................................................................
  pTable->pIndex = 0;
  if( pParse->pNewTable ) sqliteDeleteTable(db, pParse->pNewTable);
  pParse->pNewTable = pTable;
  if( !pParse->initFlag && (db->flags & SQLITE_InTrans)==0 ){
    Vdbe *v = sqliteGetVdbe(pParse);
    if( v ){
      sqliteVdbeAddOp(v, OP_Transaction, 0, 0, 0, 0);

    }
  }
}

/*
** Add a new column to the table currently being constructed.
**
................................................................................
  if( minusFlag ){
    sqliteSetNString(pz, "-", 1, pVal->z, pVal->n, 0);
  }else{
    sqliteSetNString(pz, pVal->z, pVal->n, 0);
  }
  sqliteDequote(*pz);
}

























/*
** This routine is called to report the final ")" that terminates
** a CREATE TABLE statement.
**
** The table structure is added to the internal hash tables.  
**
................................................................................
      { OP_String,      0, 0, "table"     },
      { OP_String,      0, 0, 0},            /* 3 */
      { OP_CreateTable, 0, 0, 0},
      { OP_String,      0, 0, 0},            /* 5 */
      { OP_String,      0, 0, 0},            /* 6 */
      { OP_MakeRecord,  5, 0, 0},
      { OP_Put,         0, 0, 0},

    };
    int n, base;
    Vdbe *v;

    v = sqliteGetVdbe(pParse);
    if( v==0 ) return;
    n = (int)pEnd->z - (int)pParse->sFirstToken.z + 1;
    base = sqliteVdbeAddOpList(v, ArraySize(addTable), addTable);
    sqliteVdbeChangeP3(v, base+3, p->zName, 0);
    sqliteVdbeTableRootAddr(v, &p->tnum);
    sqliteVdbeChangeP3(v, base+5, p->zName, 0);
    sqliteVdbeChangeP3(v, base+6, pParse->sFirstToken.z, n);


    sqliteVdbeAddOp(v, OP_Close, 0, 0, 0, 0);
    if( p->pIndex ){
      /* If the table has a primary key, create an index in the database
      ** for that key. */
      Index *pIndex = p->pIndex;
      assert( pIndex->pNext==0 );
      assert( pIndex->tnum==0 );
................................................................................
      { OP_Next,       0, ADDR(9),  0}, /* 3 */
      { OP_Dup,        0, 0,        0},
      { OP_Column,     0, 3,        0},
      { OP_Ne,         0, ADDR(3),  0},
      { OP_Delete,     0, 0,        0},
      { OP_Goto,       0, ADDR(3),  0},
      { OP_Destroy,    0, 0,        0}, /* 9 */

      { OP_Close,      0, 0,        0},
    };
    Index *pIdx;
    if( (db->flags & SQLITE_InTrans)==0 ){
      sqliteVdbeAddOp(v, OP_Transaction, 0, 0, 0, 0);

    }
    base = sqliteVdbeAddOpList(v, ArraySize(dropTable), dropTable);
    sqliteVdbeChangeP3(v, base+2, pTable->zName, 0);
    sqliteVdbeChangeP1(v, base+9, pTable->tnum);


    for(pIdx=pTable->pIndex; pIdx; pIdx=pIdx->pNext){
      sqliteVdbeAddOp(v, OP_Destroy, pIdx->tnum, 0, 0, 0);
    }
    if( (db->flags & SQLITE_InTrans)==0 ){
      sqliteVdbeAddOp(v, OP_Commit, 0, 0, 0, 0);
    }
  }
................................................................................
      { OP_CreateIndex, 1, 0, 0},
      { OP_Dup,         0, 0, 0},
      { OP_Open,        1, 0, 0},  /* 6 */
      { OP_String,      0, 0, 0},  /* 7 */
      { OP_String,      0, 0, 0},  /* 8 */
      { OP_MakeRecord,  5, 0, 0},
      { OP_Put,         2, 0, 0},

      { OP_Close,       2, 0, 0},
    };
    int n;
    Vdbe *v = pParse->pVdbe;
    int lbl1, lbl2;
    int i;

    v = sqliteGetVdbe(pParse);
    if( v==0 ) goto exit_create_index;
    if( pTable!=0 && (db->flags & SQLITE_InTrans)==0 ){
      sqliteVdbeAddOp(v, OP_Transaction, 0, 0, 0, 0);

    }
    if( pStart && pEnd ){
      int base;
      n = (int)pEnd->z - (int)pStart->z + 1;
      base = sqliteVdbeAddOpList(v, ArraySize(addTable), addTable);
      sqliteVdbeChangeP3(v, base+3, pIndex->zName, 0);
      sqliteVdbeIndexRootAddr(v, &pIndex->tnum);
      sqliteVdbeChangeP3(v, base+6, pIndex->zName, 0);
      sqliteVdbeChangeP3(v, base+7, pTab->zName, 0);
      sqliteVdbeChangeP3(v, base+8, pStart->z, n);


    }
    sqliteVdbeAddOp(v, OP_Open, 0, pTab->tnum, pTab->zName, 0);
    lbl1 = sqliteVdbeMakeLabel(v);
    lbl2 = sqliteVdbeMakeLabel(v);
    sqliteVdbeAddOp(v, OP_Rewind, 0, 0, 0, 0);
    sqliteVdbeAddOp(v, OP_Next, 0, lbl2, 0, lbl1);
    sqliteVdbeAddOp(v, OP_Recno, 0, 0, 0, 0);
................................................................................
      { OP_String,     0, 0,       0}, /* 2 */
      { OP_Next,       0, ADDR(8), 0}, /* 3 */
      { OP_Dup,        0, 0,       0},
      { OP_Column,     0, 1,       0},
      { OP_Ne,         0, ADDR(3), 0},
      { OP_Delete,     0, 0,       0},
      { OP_Destroy,    0, 0,       0}, /* 8 */

      { OP_Close,      0, 0,       0},
    };
    int base;

    if( (db->flags & SQLITE_InTrans)==0 ){
      sqliteVdbeAddOp(v, OP_Transaction, 0, 0, 0, 0);

    }
    base = sqliteVdbeAddOpList(v, ArraySize(dropIndex), dropIndex);
    sqliteVdbeChangeP3(v, base+2, pIndex->zName, 0);
    sqliteVdbeChangeP1(v, base+8, pIndex->tnum);


    if( (db->flags & SQLITE_InTrans)==0 ){
      sqliteVdbeAddOp(v, OP_Commit, 0, 0, 0, 0);
    }
  }

  /* Mark the internal Index structure for deletion by the
  ** sqliteCommitInternalChanges routine.
................................................................................
    pParse->nErr++;
    goto copy_cleanup;
  }
  v = sqliteGetVdbe(pParse);
  if( v ){
    if( (db->flags & SQLITE_InTrans)==0 ){
      sqliteVdbeAddOp(v, OP_Transaction, 0, 0, 0, 0);

    }
    addr = sqliteVdbeAddOp(v, OP_FileOpen, 0, 0, 0, 0);
    sqliteVdbeChangeP3(v, addr, pFilename->z, pFilename->n);
    sqliteVdbeDequoteP3(v, addr);
    sqliteVdbeAddOp(v, OP_Open, 0, pTab->tnum, pTab->zName, 0);
    for(i=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
      sqliteVdbeAddOp(v, OP_Open, i, pIdx->tnum, pIdx->zName, 0);
................................................................................
    pParse->nErr++;
    goto vacuum_cleanup;
  }
  v = sqliteGetVdbe(pParse);
  if( v==0 ) goto vacuum_cleanup;
  if( (db->flags & SQLITE_InTrans)==0 ){
    sqliteVdbeAddOp(v, OP_Transaction, 0, 0, 0, 0);

  }
  if( zName ){
    sqliteVdbeAddOp(v, OP_Reorganize, 0, 0, zName, 0);
  }else{
    int h;
    Table *pTab;
    Index *pIdx;
................................................................................

  if( pParse==0 || (db=pParse->db)==0 || db->pBe==0 ) return;
  if( pParse->nErr || sqlite_malloc_failed ) return;
  if( db->flags & SQLITE_InTrans ) return;
  v = sqliteGetVdbe(pParse);
  if( v ){
    sqliteVdbeAddOp(v, OP_Transaction, 1, 0, 0, 0);

  }
  db->flags |= SQLITE_InTrans;
}

/*
** Commit a transaction
*/







|







 







>







 







>







 







>







 







>







 







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







 







>












>
>







 







>





>




>
>







 







>











>










>
>







 







>






>




>
>







 







>







 







>







 







>







29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
..
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
...
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
...
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
...
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
...
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
...
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
...
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
...
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
...
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
....
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
....
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
....
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
**     DROP TABLE
**     CREATE INDEX
**     DROP INDEX
**     creating expressions and ID lists
**     COPY
**     VACUUM
**
** $Id: build.c,v 1.35 2001/09/15 00:57:28 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

/*
** This routine is called after a single SQL statement has been
** parsed and we want to execute the VDBE code to implement 
................................................................................
                          &pParse->zErrMsg, db->pBusyArg,
                          db->xBusyCallback);
    }
    sqliteVdbeDelete(pParse->pVdbe);
    pParse->pVdbe = 0;
    pParse->colNamesSet = 0;
    pParse->rc = rc;
    pParse->schemaVerified = 0;
  }
}

/*
** Construct a new expression node and return a pointer to it.
*/
Expr *sqliteExpr(int op, Expr *pLeft, Expr *pRight, Token *pToken){
................................................................................
** deallocation. 
**
** See also: sqliteRollbackInternalChanges()
*/
void sqliteCommitInternalChanges(sqlite *db){
  int i;
  if( (db->flags & SQLITE_InternChanges)==0 ) return;
  db->schema_cookie = db->next_cookie;
  for(i=0; i<N_HASH; i++){
    Table *pTable, *pNext;
    for(pTable = db->apTblHash[i]; pTable; pTable=pNext){
      pNext = pTable->pHash;
      if( pTable->isDelete ){
        sqliteUnlinkAndDeleteTable(db, pTable);
      }else if( pTable->isCommit==0 ){
................................................................................
** internal hash tables are undone.
**
** See also: sqliteCommitInternalChanges()
*/
void sqliteRollbackInternalChanges(sqlite *db){
  int i;
  if( (db->flags & SQLITE_InternChanges)==0 ) return;
  db->next_cookie = db->schema_cookie;
  for(i=0; i<N_HASH; i++){
    Table *pTable, *pNext;
    for(pTable = db->apTblHash[i]; pTable; pTable=pNext){
      pNext = pTable->pHash;
      if( !pTable->isCommit ){
        sqliteUnlinkAndDeleteTable(db, pTable);
      }else if( pTable->isDelete ){
................................................................................
  pTable->pIndex = 0;
  if( pParse->pNewTable ) sqliteDeleteTable(db, pParse->pNewTable);
  pParse->pNewTable = pTable;
  if( !pParse->initFlag && (db->flags & SQLITE_InTrans)==0 ){
    Vdbe *v = sqliteGetVdbe(pParse);
    if( v ){
      sqliteVdbeAddOp(v, OP_Transaction, 0, 0, 0, 0);
      sqliteVdbeAddOp(v, OP_VerifyCookie, db->schema_cookie, 0, 0, 0);
    }
  }
}

/*
** Add a new column to the table currently being constructed.
**
................................................................................
  if( minusFlag ){
    sqliteSetNString(pz, "-", 1, pVal->z, pVal->n, 0);
  }else{
    sqliteSetNString(pz, pVal->z, pVal->n, 0);
  }
  sqliteDequote(*pz);
}

/*
** 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
** database changes.  After each schema change, the cookie value
** changes.  When a process first reads the schema it records the
** cookie.  Thereafter, whenever it goes to access the database,
** it checks the cookie to make sure the schema has not changed
** since it was last read.
**
** This plan is not completely bullet-proof.  It is possible for
** the schema to change multiple times and for the cookie to be
** set back to prior value.  But schema changes are infrequent
** and the probability of hitting the same cookie value is only
** 1 chance in 2^32.  So we're safe enough.
*/
static void changeCookie(sqlite *db){
  if( db->next_cookie==db->schema_cookie ){
    db->next_cookie = db->schema_cookie + sqliteRandomByte() + 1;
    db->flags |= SQLITE_InternChanges;
  }
}

/*
** This routine is called to report the final ")" that terminates
** a CREATE TABLE statement.
**
** The table structure is added to the internal hash tables.  
**
................................................................................
      { OP_String,      0, 0, "table"     },
      { OP_String,      0, 0, 0},            /* 3 */
      { OP_CreateTable, 0, 0, 0},
      { OP_String,      0, 0, 0},            /* 5 */
      { OP_String,      0, 0, 0},            /* 6 */
      { OP_MakeRecord,  5, 0, 0},
      { OP_Put,         0, 0, 0},
      { OP_SetCookie,   0, 0, 0},            /* 9 */
    };
    int n, base;
    Vdbe *v;

    v = sqliteGetVdbe(pParse);
    if( v==0 ) return;
    n = (int)pEnd->z - (int)pParse->sFirstToken.z + 1;
    base = sqliteVdbeAddOpList(v, ArraySize(addTable), addTable);
    sqliteVdbeChangeP3(v, base+3, p->zName, 0);
    sqliteVdbeTableRootAddr(v, &p->tnum);
    sqliteVdbeChangeP3(v, base+5, p->zName, 0);
    sqliteVdbeChangeP3(v, base+6, pParse->sFirstToken.z, n);
    changeCookie(db);
    sqliteVdbeChangeP1(v, base+9, db->next_cookie);
    sqliteVdbeAddOp(v, OP_Close, 0, 0, 0, 0);
    if( p->pIndex ){
      /* If the table has a primary key, create an index in the database
      ** for that key. */
      Index *pIndex = p->pIndex;
      assert( pIndex->pNext==0 );
      assert( pIndex->tnum==0 );
................................................................................
      { OP_Next,       0, ADDR(9),  0}, /* 3 */
      { OP_Dup,        0, 0,        0},
      { OP_Column,     0, 3,        0},
      { OP_Ne,         0, ADDR(3),  0},
      { OP_Delete,     0, 0,        0},
      { OP_Goto,       0, ADDR(3),  0},
      { OP_Destroy,    0, 0,        0}, /* 9 */
      { OP_SetCookie,  0, 0,        0}, /* 10 */
      { OP_Close,      0, 0,        0},
    };
    Index *pIdx;
    if( (db->flags & SQLITE_InTrans)==0 ){
      sqliteVdbeAddOp(v, OP_Transaction, 0, 0, 0, 0);
      sqliteVdbeAddOp(v, OP_VerifyCookie, db->schema_cookie, 0, 0, 0);
    }
    base = sqliteVdbeAddOpList(v, ArraySize(dropTable), dropTable);
    sqliteVdbeChangeP3(v, base+2, pTable->zName, 0);
    sqliteVdbeChangeP1(v, base+9, pTable->tnum);
    changeCookie(db);
    sqliteVdbeChangeP1(v, base+10, db->next_cookie);
    for(pIdx=pTable->pIndex; pIdx; pIdx=pIdx->pNext){
      sqliteVdbeAddOp(v, OP_Destroy, pIdx->tnum, 0, 0, 0);
    }
    if( (db->flags & SQLITE_InTrans)==0 ){
      sqliteVdbeAddOp(v, OP_Commit, 0, 0, 0, 0);
    }
  }
................................................................................
      { OP_CreateIndex, 1, 0, 0},
      { OP_Dup,         0, 0, 0},
      { OP_Open,        1, 0, 0},  /* 6 */
      { OP_String,      0, 0, 0},  /* 7 */
      { OP_String,      0, 0, 0},  /* 8 */
      { OP_MakeRecord,  5, 0, 0},
      { OP_Put,         2, 0, 0},
      { OP_SetCookie,   0, 0, 0},  /* 11 */
      { OP_Close,       2, 0, 0},
    };
    int n;
    Vdbe *v = pParse->pVdbe;
    int lbl1, lbl2;
    int i;

    v = sqliteGetVdbe(pParse);
    if( v==0 ) goto exit_create_index;
    if( pTable!=0 && (db->flags & SQLITE_InTrans)==0 ){
      sqliteVdbeAddOp(v, OP_Transaction, 0, 0, 0, 0);
      sqliteVdbeAddOp(v, OP_VerifyCookie, db->schema_cookie, 0, 0, 0);
    }
    if( pStart && pEnd ){
      int base;
      n = (int)pEnd->z - (int)pStart->z + 1;
      base = sqliteVdbeAddOpList(v, ArraySize(addTable), addTable);
      sqliteVdbeChangeP3(v, base+3, pIndex->zName, 0);
      sqliteVdbeIndexRootAddr(v, &pIndex->tnum);
      sqliteVdbeChangeP3(v, base+6, pIndex->zName, 0);
      sqliteVdbeChangeP3(v, base+7, pTab->zName, 0);
      sqliteVdbeChangeP3(v, base+8, pStart->z, n);
      changeCookie(db);
      sqliteVdbeChangeP1(v, base+11, db->next_cookie);
    }
    sqliteVdbeAddOp(v, OP_Open, 0, pTab->tnum, pTab->zName, 0);
    lbl1 = sqliteVdbeMakeLabel(v);
    lbl2 = sqliteVdbeMakeLabel(v);
    sqliteVdbeAddOp(v, OP_Rewind, 0, 0, 0, 0);
    sqliteVdbeAddOp(v, OP_Next, 0, lbl2, 0, lbl1);
    sqliteVdbeAddOp(v, OP_Recno, 0, 0, 0, 0);
................................................................................
      { OP_String,     0, 0,       0}, /* 2 */
      { OP_Next,       0, ADDR(8), 0}, /* 3 */
      { OP_Dup,        0, 0,       0},
      { OP_Column,     0, 1,       0},
      { OP_Ne,         0, ADDR(3), 0},
      { OP_Delete,     0, 0,       0},
      { OP_Destroy,    0, 0,       0}, /* 8 */
      { OP_SetCookie,  0, 0,       0}, /* 9 */
      { OP_Close,      0, 0,       0},
    };
    int base;

    if( (db->flags & SQLITE_InTrans)==0 ){
      sqliteVdbeAddOp(v, OP_Transaction, 0, 0, 0, 0);
      sqliteVdbeAddOp(v, OP_VerifyCookie, db->schema_cookie, 0, 0, 0);
    }
    base = sqliteVdbeAddOpList(v, ArraySize(dropIndex), dropIndex);
    sqliteVdbeChangeP3(v, base+2, pIndex->zName, 0);
    sqliteVdbeChangeP1(v, base+8, pIndex->tnum);
    changeCookie(db);
    sqliteVdbeChangeP1(v, base+9, db->next_cookie);
    if( (db->flags & SQLITE_InTrans)==0 ){
      sqliteVdbeAddOp(v, OP_Commit, 0, 0, 0, 0);
    }
  }

  /* Mark the internal Index structure for deletion by the
  ** sqliteCommitInternalChanges routine.
................................................................................
    pParse->nErr++;
    goto copy_cleanup;
  }
  v = sqliteGetVdbe(pParse);
  if( v ){
    if( (db->flags & SQLITE_InTrans)==0 ){
      sqliteVdbeAddOp(v, OP_Transaction, 0, 0, 0, 0);
      sqliteVdbeAddOp(v, OP_VerifyCookie, db->schema_cookie, 0, 0, 0);
    }
    addr = sqliteVdbeAddOp(v, OP_FileOpen, 0, 0, 0, 0);
    sqliteVdbeChangeP3(v, addr, pFilename->z, pFilename->n);
    sqliteVdbeDequoteP3(v, addr);
    sqliteVdbeAddOp(v, OP_Open, 0, pTab->tnum, pTab->zName, 0);
    for(i=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
      sqliteVdbeAddOp(v, OP_Open, i, pIdx->tnum, pIdx->zName, 0);
................................................................................
    pParse->nErr++;
    goto vacuum_cleanup;
  }
  v = sqliteGetVdbe(pParse);
  if( v==0 ) goto vacuum_cleanup;
  if( (db->flags & SQLITE_InTrans)==0 ){
    sqliteVdbeAddOp(v, OP_Transaction, 0, 0, 0, 0);
    sqliteVdbeAddOp(v, OP_VerifyCookie, db->schema_cookie, 0, 0, 0);
  }
  if( zName ){
    sqliteVdbeAddOp(v, OP_Reorganize, 0, 0, zName, 0);
  }else{
    int h;
    Table *pTab;
    Index *pIdx;
................................................................................

  if( pParse==0 || (db=pParse->db)==0 || db->pBe==0 ) return;
  if( pParse->nErr || sqlite_malloc_failed ) return;
  if( db->flags & SQLITE_InTrans ) return;
  v = sqliteGetVdbe(pParse);
  if( v ){
    sqliteVdbeAddOp(v, OP_Transaction, 1, 0, 0, 0);
    sqliteVdbeAddOp(v, OP_VerifyCookie, db->schema_cookie, 0, 0, 0);
  }
  db->flags |= SQLITE_InTrans;
}

/*
** Commit a transaction
*/

Changes to src/delete.c.

20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
..
88
89
90
91
92
93
94

95
96
97
98
99
100
101
**   drh@hwaci.com
**   http://www.hwaci.com/drh/
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle DELETE FROM statements.
**
** $Id: delete.c,v 1.12 2001/09/13 21:53:10 drh Exp $
*/
#include "sqliteInt.h"

/*
** Process a DELETE FROM statement.
*/
void sqliteDeleteFrom(
................................................................................

  /* Begin generating code.
  */
  v = sqliteGetVdbe(pParse);
  if( v==0 ) goto delete_from_cleanup;
  if( (pParse->db->flags & SQLITE_InTrans)==0 ){
    sqliteVdbeAddOp(v, OP_Transaction, 0, 0, 0, 0);

  }


  /* Special case: A DELETE without a WHERE clause deletes everything.
  ** It is easier just to clear all information the database tables directly.
  */
  if( pWhere==0 ){







|







 







>







20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
..
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
**   drh@hwaci.com
**   http://www.hwaci.com/drh/
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle DELETE FROM statements.
**
** $Id: delete.c,v 1.13 2001/09/15 00:57:29 drh Exp $
*/
#include "sqliteInt.h"

/*
** Process a DELETE FROM statement.
*/
void sqliteDeleteFrom(
................................................................................

  /* Begin generating code.
  */
  v = sqliteGetVdbe(pParse);
  if( v==0 ) goto delete_from_cleanup;
  if( (pParse->db->flags & SQLITE_InTrans)==0 ){
    sqliteVdbeAddOp(v, OP_Transaction, 0, 0, 0, 0);
    sqliteVdbeAddOp(v, OP_VerifyCookie, pParse->db->schema_cookie, 0, 0, 0);
  }


  /* Special case: A DELETE without a WHERE clause deletes everything.
  ** It is easier just to clear all information the database tables directly.
  */
  if( pWhere==0 ){

Changes to src/insert.c.

20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
..
83
84
85
86
87
88
89

90
91
92
93
94
95
96
**   drh@hwaci.com
**   http://www.hwaci.com/drh/
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle INSERT statements.
**
** $Id: insert.c,v 1.16 2001/09/14 03:24:25 drh Exp $
*/
#include "sqliteInt.h"

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

  /* Allocate a VDBE
  */
  v = sqliteGetVdbe(pParse);
  if( v==0 ) goto insert_cleanup;
  if( (pParse->db->flags & SQLITE_InTrans)==0 ){
    sqliteVdbeAddOp(v, OP_Transaction, 0, 0, 0, 0);

  }

  /* Figure out how many columns of data are supplied.  If the data
  ** is comming from a SELECT statement, then this step has to generate
  ** all the code to implement the SELECT statement and leave the data
  ** in a temporary table.  If data is coming from an expression list,
  ** then we just have to count the number of expressions.







|







 







>







20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
..
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
**   drh@hwaci.com
**   http://www.hwaci.com/drh/
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle INSERT statements.
**
** $Id: insert.c,v 1.17 2001/09/15 00:57:29 drh Exp $
*/
#include "sqliteInt.h"

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

  /* Allocate a VDBE
  */
  v = sqliteGetVdbe(pParse);
  if( v==0 ) goto insert_cleanup;
  if( (pParse->db->flags & SQLITE_InTrans)==0 ){
    sqliteVdbeAddOp(v, OP_Transaction, 0, 0, 0, 0);
    sqliteVdbeAddOp(v, OP_VerifyCookie, pParse->db->schema_cookie, 0, 0, 0);
  }

  /* Figure out how many columns of data are supplied.  If the data
  ** is comming from a SELECT statement, then this step has to generate
  ** all the code to implement the SELECT statement and leave the data
  ** in a temporary table.  If data is coming from an expression list,
  ** then we just have to count the number of expressions.

Changes to src/main.c.

22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
..
47
48
49
50
51
52
53

54




55
56
57
58
59
60
61
...
166
167
168
169
170
171
172





173
174
175
176
177
178
179
180
...
277
278
279
280
281
282
283
284






285
286
287
288
289
290
291
292
293
294
295
296
297
298









299
300
301
302
303
304
305
...
383
384
385
386
387
388
389



390
391
392
393
394
395
396
**
*************************************************************************
** Main file for the SQLite library.  The routines in this file
** implement the programmer interface to the library.  Routines in
** other files are for internal use by SQLite and should not be
** accessed by users of the library.
**
** $Id: main.c,v 1.35 2001/09/14 16:42:12 drh Exp $
*/
#include "sqliteInt.h"
#if defined(HAVE_USLEEP) && HAVE_USLEEP
#include <unistd.h>
#endif

/*
................................................................................
  sqlite *db = (sqlite*)pDb;
  Parse sParse;
  int nErr = 0;

  assert( argc==4 );
  switch( argv[0][0] ){
    case 'm': {  /* Meta information */

      sscanf(argv[1],"file format %d",&db->file_format);




      break;
    }
    case 'i':
    case 't': {  /* CREATE TABLE  and CREATE INDEX statements */
      memset(&sParse, 0, sizeof(sParse));
      sParse.db = db;
      sParse.initFlag = 1;
................................................................................
    { OP_Ne,       0, 24, 0},
    { OP_Column,   0, 0,  0},
    { OP_Column,   0, 1,  0},
    { OP_Column,   0, 2,  0},
    { OP_Column,   0, 4,  0},
    { OP_Callback, 4, 0,  0},
    { OP_Goto,     0, 24, 0},





    { OP_Close,    0, 0,  0},           /* 34 */
    { OP_Halt,     0, 0,  0},
  };

  /* Create a virtual machine to run the initialization program.  Run
  ** the program.  The delete the virtual machine.
  */
  vdbe = sqliteVdbeCreate(db);
................................................................................
no_mem_on_open:
  sqliteSetString(pzErrMsg, "out of memory", 0);
  sqliteStrRealloc(pzErrMsg);
  return 0;
}

/*
** Close an existing SQLite database






*/
void sqlite_close(sqlite *db){
  int i;
  sqliteBtreeClose(db->pBe);
  for(i=0; i<N_HASH; i++){
    Table *pNext, *pList = db->apTblHash[i];
    db->apTblHash[i] = 0;
    while( pList ){
      pNext = pList->pHash;
      pList->pHash = 0;
      sqliteDeleteTable(db, pList);
      pList = pNext;
    }
  }









  sqliteFree(db);
}

/*
** Return TRUE if the given SQL string ends in a semicolon.
*/
int sqlite_complete(const char *zSql){
................................................................................
  sParse.pArg = pArg;
  sqliteRunParser(&sParse, zSql, pzErrMsg);
  if( sqlite_malloc_failed ){
    sqliteSetString(pzErrMsg, "out of memory", 0);
    sParse.rc = SQLITE_NOMEM;
  }
  sqliteStrRealloc(pzErrMsg);



  return sParse.rc;
}

/*
** This routine implements a busy callback that sleeps and tries
** again until a timeout value is reached.  The timeout value is
** an integer number of milliseconds passed in as the first







|







 







>
|
>
>
>
>







 







>
>
>
>
>
|







 







|
>
>
>
>
>
>

|

<










>
>
>
>
>
>
>
>
>







 







>
>
>







22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
..
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
...
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
...
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303

304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
...
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
**
*************************************************************************
** Main file for the SQLite library.  The routines in this file
** implement the programmer interface to the library.  Routines in
** other files are for internal use by SQLite and should not be
** accessed by users of the library.
**
** $Id: main.c,v 1.36 2001/09/15 00:57:29 drh Exp $
*/
#include "sqliteInt.h"
#if defined(HAVE_USLEEP) && HAVE_USLEEP
#include <unistd.h>
#endif

/*
................................................................................
  sqlite *db = (sqlite*)pDb;
  Parse sParse;
  int nErr = 0;

  assert( argc==4 );
  switch( argv[0][0] ){
    case 'm': {  /* Meta information */
      if( strcmp(argv[1],"file-format")==0 ){
        db->file_format = atoi(argv[3]);
      }else if( strcmp(argv[1],"schema-cookie")==0 ){
        db->schema_cookie = atoi(argv[3]);
        db->next_cookie = db->schema_cookie;
      }
      break;
    }
    case 'i':
    case 't': {  /* CREATE TABLE  and CREATE INDEX statements */
      memset(&sParse, 0, sizeof(sParse));
      sParse.db = db;
      sParse.initFlag = 1;
................................................................................
    { OP_Ne,       0, 24, 0},
    { OP_Column,   0, 0,  0},
    { OP_Column,   0, 1,  0},
    { OP_Column,   0, 2,  0},
    { OP_Column,   0, 4,  0},
    { OP_Callback, 4, 0,  0},
    { OP_Goto,     0, 24, 0},
    { OP_String,   0, 0,  "meta"},      /* 34 */
    { OP_String,   0, 0,  "schema-cookie"},
    { OP_String,   0, 0,  ""},
    { OP_ReadCookie,0,0,  0},
    { OP_Callback, 4, 0,  0},
    { OP_Close,    0, 0,  0},
    { OP_Halt,     0, 0,  0},
  };

  /* Create a virtual machine to run the initialization program.  Run
  ** the program.  The delete the virtual machine.
  */
  vdbe = sqliteVdbeCreate(db);
................................................................................
no_mem_on_open:
  sqliteSetString(pzErrMsg, "out of memory", 0);
  sqliteStrRealloc(pzErrMsg);
  return 0;
}

/*
** Erase all schema information from the schema hash table.
**
** The database schema is normally read in once when the database
** is first opened and stored in a hash table in the sqlite structure.
** This routine erases the stored schema.  This erasure occurs because
** either the database is being closed or because some other process
** changed the schema and this process needs to reread it.
*/
static void clearHashTable(sqlite *db){
  int i;

  for(i=0; i<N_HASH; i++){
    Table *pNext, *pList = db->apTblHash[i];
    db->apTblHash[i] = 0;
    while( pList ){
      pNext = pList->pHash;
      pList->pHash = 0;
      sqliteDeleteTable(db, pList);
      pList = pNext;
    }
  }
  db->flags &= ~SQLITE_Initialized;
}

/*
** Close an existing SQLite database
*/
void sqlite_close(sqlite *db){
  sqliteBtreeClose(db->pBe);
  clearHashTable(db);
  sqliteFree(db);
}

/*
** Return TRUE if the given SQL string ends in a semicolon.
*/
int sqlite_complete(const char *zSql){
................................................................................
  sParse.pArg = pArg;
  sqliteRunParser(&sParse, zSql, pzErrMsg);
  if( sqlite_malloc_failed ){
    sqliteSetString(pzErrMsg, "out of memory", 0);
    sParse.rc = SQLITE_NOMEM;
  }
  sqliteStrRealloc(pzErrMsg);
  if( sParse.rc==SQLITE_SCHEMA ){
    clearHashTable(db);
  }
  return sParse.rc;
}

/*
** This routine implements a busy callback that sleeps and tries
** again until a timeout value is reached.  The timeout value is
** an integer number of milliseconds passed in as the first

Changes to src/pager.c.

23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
...
678
679
680
681
682
683
684






















685
686
687
688
689
690
691
...
787
788
789
790
791
792
793
794
795
796
797
798
799
800








801
802






803
804
805
806
807
808
809
...
821
822
823
824
825
826
827


828
829
830
831
832
833
834
*************************************************************************
** This is the implementation of the page cache subsystem.
** 
** The page cache is used to access a database file.  The pager journals
** all writes in order to support rollback.  Locking is used to limit
** access to one or more reader or to one writer.
**
** @(#) $Id: pager.c,v 1.18 2001/09/14 18:54:09 drh Exp $
*/
#include "sqliteInt.h"
#include "pager.h"
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
#include <assert.h>
................................................................................
** a reference to the page data.
*/
int sqlitepager_ref(void *pData){
  PgHdr *pPg = DATA_TO_PGHDR(pData);
  page_ref(pPg);
  return SQLITE_OK;
}























/*
** Acquire a page.
**
** A read lock on the disk file is obtained when the first page acquired. 
** This read lock is dropped when the last page is released.
**
................................................................................
      pPg->pPrevAll = 0;
      pPager->pAll = pPg;
      pPager->nPage++;
    }else{
      /* Recycle an older page.  First locate the page to be recycled.
      ** Try to find one that is not dirty and is near the head of
      ** of the free list */
      /* int cnt = pPager->mxPage/2; */
      int cnt = 10;
      pPg = pPager->pFirst;
      while( pPg->dirty && 0<cnt-- && pPg->pNextFree ){
        pPg = pPg->pNextFree;
      }
      if( pPg==0 || pPg->dirty ) pPg = pPager->pFirst;








      assert( pPg->nRef==0 );







      /* If the page to be recycled is dirty, sync the journal and write 
      ** the old page into the database. */
      if( pPg->dirty ){
        int rc;
        assert( pPg->inJournal==1 );
        assert( pPager->state==SQLITE_WRITELOCK );
        if( pPager->needSync ){
................................................................................
        if( rc!=SQLITE_OK ){
          rc = sqlitepager_rollback(pPager);
          *ppPage = 0;
          if( rc==SQLITE_OK ) rc = SQLITE_FULL;
          return rc;
        }
      }



      /* Unlink the old page from the free list and the hash table
      */
      if( pPg->pPrevFree ){
        pPg->pPrevFree->pNextFree = pPg->pNextFree;
      }else{
        assert( pPager->pFirst==pPg );







|







 







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







 







|
<




|
>
>
>
>
>
>
>
>


>
>
>
>
>
>







 







>
>







23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
...
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
...
809
810
811
812
813
814
815
816

817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
...
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
*************************************************************************
** This is the implementation of the page cache subsystem.
** 
** The page cache is used to access a database file.  The pager journals
** all writes in order to support rollback.  Locking is used to limit
** access to one or more reader or to one writer.
**
** @(#) $Id: pager.c,v 1.19 2001/09/15 00:57:29 drh Exp $
*/
#include "sqliteInt.h"
#include "pager.h"
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
#include <assert.h>
................................................................................
** a reference to the page data.
*/
int sqlitepager_ref(void *pData){
  PgHdr *pPg = DATA_TO_PGHDR(pData);
  page_ref(pPg);
  return SQLITE_OK;
}

/*
** Sync the journal and write all free dirty pages to the database file.
*/
static int syncAllPages(Pager *pPager){
  PgHdr *pPg;
  int rc = SQLITE_OK;
  if( pPager->needSync ){
    rc = fsync(pPager->jfd);
    if( rc!=0 ) return rc;
    pPager->needSync = 0;
  }
  for(pPg=pPager->pFirst; pPg; pPg=pPg->pNextFree){
    if( pPg->dirty ){
      pager_seek(pPager->fd, (pPg->pgno-1)*SQLITE_PAGE_SIZE);
      rc = pager_write(pPager->fd, PGHDR_TO_DATA(pPg), SQLITE_PAGE_SIZE);
      if( rc!=SQLITE_OK ) break;
      pPg->dirty = 0;
    }
  }
  return SQLITE_OK;
}

/*
** Acquire a page.
**
** A read lock on the disk file is obtained when the first page acquired. 
** This read lock is dropped when the last page is released.
**
................................................................................
      pPg->pPrevAll = 0;
      pPager->pAll = pPg;
      pPager->nPage++;
    }else{
      /* Recycle an older page.  First locate the page to be recycled.
      ** Try to find one that is not dirty and is near the head of
      ** of the free list */
      int cnt = pPager->mxPage/2;

      pPg = pPager->pFirst;
      while( pPg->dirty && 0<cnt-- && pPg->pNextFree ){
        pPg = pPg->pNextFree;
      }
      if( pPg==0 || pPg->dirty ){
        int rc = syncAllPages(pPager);
        if( rc!=0 ){
          sqlitepager_rollback(pPager);
          *ppPage = 0;
          return SQLITE_IOERR;
        }
        pPg = pPager->pFirst;
      }
      assert( pPg->nRef==0 );


#if 0
      /****  Since putting in the call to syncAllPages() above, this code
      ** is no longer used.  I've kept it here for historical reference
      ** only.
      */
      /* If the page to be recycled is dirty, sync the journal and write 
      ** the old page into the database. */
      if( pPg->dirty ){
        int rc;
        assert( pPg->inJournal==1 );
        assert( pPager->state==SQLITE_WRITELOCK );
        if( pPager->needSync ){
................................................................................
        if( rc!=SQLITE_OK ){
          rc = sqlitepager_rollback(pPager);
          *ppPage = 0;
          if( rc==SQLITE_OK ) rc = SQLITE_FULL;
          return rc;
        }
      }
#endif
      assert( pPg->dirty==0 );

      /* Unlink the old page from the free list and the hash table
      */
      if( pPg->pPrevFree ){
        pPg->pPrevFree->pNextFree = pPg->pNextFree;
      }else{
        assert( pPager->pFirst==pPg );

Changes to src/sqlite.h.in.

20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
...
156
157
158
159
160
161
162

163
164
165
166
167
168
169
**   drh@hwaci.com
**   http://www.hwaci.com/drh/
**
*************************************************************************
** This header file defines the interface that the sqlite library
** presents to client programs.
**
** @(#) $Id: sqlite.h.in,v 1.14 2001/09/13 13:46:57 drh Exp $
*/
#ifndef _SQLITE_H_
#define _SQLITE_H_
#include <stdarg.h>     /* Needed for the definition of va_list */

/*
** The version of the SQLite library.
................................................................................
#define SQLITE_IOERR     9    /* Disk full or other I/O error */
#define SQLITE_CORRUPT   10   /* The database disk image is malformed */
#define SQLITE_NOTFOUND  11   /* Table or record not found */
#define SQLITE_FULL      12   /* Insertion failed because database is full */
#define SQLITE_CANTOPEN  13   /* Unable to open the database file */
#define SQLITE_PROTOCOL  14   /* Database lock protocol error */
#define SQLITE_EMPTY     15   /* Database table is empty */


/* This function causes any pending database operation to abort and
** return at its earliest opportunity.  This routine is typically
** called in response to a user action such as pressing "Cancel"
** or Ctrl-C where the user wants a long query operation to halt
** immediately.
*/







|







 







>







20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
...
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
**   drh@hwaci.com
**   http://www.hwaci.com/drh/
**
*************************************************************************
** This header file defines the interface that the sqlite library
** presents to client programs.
**
** @(#) $Id: sqlite.h.in,v 1.15 2001/09/15 00:57:29 drh Exp $
*/
#ifndef _SQLITE_H_
#define _SQLITE_H_
#include <stdarg.h>     /* Needed for the definition of va_list */

/*
** The version of the SQLite library.
................................................................................
#define SQLITE_IOERR     9    /* Disk full or other I/O error */
#define SQLITE_CORRUPT   10   /* The database disk image is malformed */
#define SQLITE_NOTFOUND  11   /* Table or record not found */
#define SQLITE_FULL      12   /* Insertion failed because database is full */
#define SQLITE_CANTOPEN  13   /* Unable to open the database file */
#define SQLITE_PROTOCOL  14   /* Database lock protocol error */
#define SQLITE_EMPTY     15   /* Database table is empty */
#define SQLITE_SCHEMA    16   /* The database schema changed */

/* This function causes any pending database operation to abort and
** return at its earliest opportunity.  This routine is typically
** called in response to a user action such as pressing "Cancel"
** or Ctrl-C where the user wants a long query operation to halt
** immediately.
*/

Changes to src/sqliteInt.h.

19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
...
139
140
141
142
143
144
145


146
147
148
149
150
151
152
...
372
373
374
375
376
377
378


379
380
381
382
383
384
385
** Author contact information:
**   drh@hwaci.com
**   http://www.hwaci.com/drh/
**
*************************************************************************
** Internal interface definitions for SQLite.
**
** @(#) $Id: sqliteInt.h,v 1.47 2001/09/14 18:54:09 drh Exp $
*/
#include "sqlite.h"
#include "vdbe.h"
#include "parse.h"
#include "btree.h"
#include <stdio.h>
#include <stdlib.h>
................................................................................
/*
** Each database is an instance of the following structure
*/
struct sqlite {
  Btree *pBe;                   /* The B*Tree backend */
  int flags;                    /* Miscellanous flags. See below */
  int file_format;              /* What file format version is this database? */


  int nTable;                   /* Number of tables in the database */
  void *pBusyArg;               /* 1st Argument to the busy callback */
  int (*xBusyCallback)(void *,const char*,int);  /* The busy callback */
  Table *apTblHash[N_HASH];     /* All tables of the database */
  Index *apIdxHash[N_HASH];     /* All indices of the database */
};

................................................................................
  int nMem;            /* Number of memory cells used so far */
  int nSet;            /* Number of sets used so far */
  int nAgg;            /* Number of aggregate expressions */
  AggExpr *aAgg;       /* An array of aggregate expressions */
  int iAggCount;       /* Index of the count(*) aggregate in aAgg[] */
  int useAgg;          /* If true, extract field values from the aggregator
                       ** while generating expressions.  Normally false */


};

/*
** Internal function prototypes
*/
int sqliteStrICmp(const char *, const char *);
int sqliteStrNICmp(const char *, const char *, int);







|







 







>
>







 







>
>







19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
...
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
...
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
** Author contact information:
**   drh@hwaci.com
**   http://www.hwaci.com/drh/
**
*************************************************************************
** Internal interface definitions for SQLite.
**
** @(#) $Id: sqliteInt.h,v 1.48 2001/09/15 00:57:29 drh Exp $
*/
#include "sqlite.h"
#include "vdbe.h"
#include "parse.h"
#include "btree.h"
#include <stdio.h>
#include <stdlib.h>
................................................................................
/*
** Each database is an instance of the following structure
*/
struct sqlite {
  Btree *pBe;                   /* The B*Tree backend */
  int flags;                    /* Miscellanous flags. See below */
  int file_format;              /* What file format version is this database? */
  int schema_cookie;            /* Magic number that changes with the schema */
  int next_cookie;              /* Value of schema_cookie after commit */
  int nTable;                   /* Number of tables in the database */
  void *pBusyArg;               /* 1st Argument to the busy callback */
  int (*xBusyCallback)(void *,const char*,int);  /* The busy callback */
  Table *apTblHash[N_HASH];     /* All tables of the database */
  Index *apIdxHash[N_HASH];     /* All indices of the database */
};

................................................................................
  int nMem;            /* Number of memory cells used so far */
  int nSet;            /* Number of sets used so far */
  int nAgg;            /* Number of aggregate expressions */
  AggExpr *aAgg;       /* An array of aggregate expressions */
  int iAggCount;       /* Index of the count(*) aggregate in aAgg[] */
  int useAgg;          /* If true, extract field values from the aggregator
                       ** while generating expressions.  Normally false */
  int schemaVerified;  /* True if an OP_VerifySchema has been coded someplace
                       ** other than after an OP_Transaction */
};

/*
** Internal function prototypes
*/
int sqliteStrICmp(const char *, const char *);
int sqliteStrNICmp(const char *, const char *, int);

Changes to src/update.c.

20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
...
142
143
144
145
146
147
148

149
150
151
152
153
154
155
**   drh@hwaci.com
**   http://www.hwaci.com/drh/
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle UPDATE statements.
**
** $Id: update.c,v 1.12 2001/09/13 13:46:57 drh Exp $
*/
#include "sqliteInt.h"

/*
** Process an UPDATE statement.
*/
void sqliteUpdate(
................................................................................

  /* Begin generating code.
  */
  v = sqliteGetVdbe(pParse);
  if( v==0 ) goto update_cleanup;
  if( (pParse->db->flags & SQLITE_InTrans)==0 ){
    sqliteVdbeAddOp(v, OP_Transaction, 0, 0, 0, 0);

  }

  /* Begin the database scan
  */
  sqliteVdbeAddOp(v, OP_ListOpen, 0, 0, 0, 0);
  pWInfo = sqliteWhereBegin(pParse, pTabList, pWhere, 1);
  if( pWInfo==0 ) goto update_cleanup;







|







 







>







20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
...
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
**   drh@hwaci.com
**   http://www.hwaci.com/drh/
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle UPDATE statements.
**
** $Id: update.c,v 1.13 2001/09/15 00:57:29 drh Exp $
*/
#include "sqliteInt.h"

/*
** Process an UPDATE statement.
*/
void sqliteUpdate(
................................................................................

  /* Begin generating code.
  */
  v = sqliteGetVdbe(pParse);
  if( v==0 ) goto update_cleanup;
  if( (pParse->db->flags & SQLITE_InTrans)==0 ){
    sqliteVdbeAddOp(v, OP_Transaction, 0, 0, 0, 0);
    sqliteVdbeAddOp(v, OP_VerifyCookie, pParse->db->schema_cookie, 0, 0, 0);
  }

  /* Begin the database scan
  */
  sqliteVdbeAddOp(v, OP_ListOpen, 0, 0, 0, 0);
  pWInfo = sqliteWhereBegin(pParse, pTabList, pWhere, 1);
  if( pWInfo==0 ) goto update_cleanup;

Changes to src/util.c.

22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
...
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999

1000
1001
1002
**
*************************************************************************
** Utility functions used throughout sqlite.
**
** This file contains functions for allocating memory, comparing
** strings, and stuff like that.
**
** $Id: util.c,v 1.22 2001/09/13 13:46:57 drh Exp $
*/
#include "sqliteInt.h"
#include <stdarg.h>
#include <ctype.h>

/*
** If malloc() ever fails, this global variable gets set to 1.
................................................................................
}

/*
** Return a static string that describes the kind of error specified in the
** argument.
*/
const char *sqliteErrStr(int rc){
  char *z = 0;
  switch( rc ){
    case SQLITE_OK:          z = "not an error";  break;
    case SQLITE_ERROR:       z = "SQL logic error or missing database"; break;
    case SQLITE_INTERNAL:    z = "internal SQLite implementation flaw"; break;
    case SQLITE_PERM:        z = "access permission denied"; break;
    case SQLITE_ABORT:       z = "callback requested query abort"; break;
    case SQLITE_BUSY:        z = "database in use by another process"; break;
    case SQLITE_NOMEM:       z = "out of memory"; break;
    case SQLITE_READONLY:    z = "attempt to write a readonly database"; break;
    case SQLITE_INTERRUPT:   z = "interrupted"; break;
    case SQLITE_IOERR:       z = "disk I/O error"; break;
    case SQLITE_CORRUPT:     z = "database disk image is malformed"; break;
    case SQLITE_NOTFOUND:    z = "table or record not found"; break;
    case SQLITE_FULL:        z = "database is full"; break;
    case SQLITE_CANTOPEN:    z = "unable to open database file"; break;
    case SQLITE_PROTOCOL:    z = "database locking protocol failure"; break;
    case SQLITE_EMPTY:       z = "table contains no data";
    default:

  }
  return z;
}







|







 







|

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



22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
...
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
**
*************************************************************************
** Utility functions used throughout sqlite.
**
** This file contains functions for allocating memory, comparing
** strings, and stuff like that.
**
** $Id: util.c,v 1.23 2001/09/15 00:57:29 drh Exp $
*/
#include "sqliteInt.h"
#include <stdarg.h>
#include <ctype.h>

/*
** If malloc() ever fails, this global variable gets set to 1.
................................................................................
}

/*
** Return a static string that describes the kind of error specified in the
** argument.
*/
const char *sqliteErrStr(int rc){
  const char *z;
  switch( rc ){
    case SQLITE_OK:         z = "not an error";                          break;
    case SQLITE_ERROR:      z = "SQL logic error or missing database";   break;
    case SQLITE_INTERNAL:   z = "internal SQLite implementation flaw";   break;
    case SQLITE_PERM:       z = "access permission denied";              break;
    case SQLITE_ABORT:      z = "callback requested query abort";        break;
    case SQLITE_BUSY:       z = "database in use by another process";    break;
    case SQLITE_NOMEM:      z = "out of memory";                         break;
    case SQLITE_READONLY:   z = "attempt to write a readonly database";  break;
    case SQLITE_INTERRUPT:  z = "interrupted";                           break;
    case SQLITE_IOERR:      z = "disk I/O error";                        break;
    case SQLITE_CORRUPT:    z = "database disk image is malformed";      break;
    case SQLITE_NOTFOUND:   z = "table or record not found";             break;
    case SQLITE_FULL:       z = "database is full";                      break;
    case SQLITE_CANTOPEN:   z = "unable to open database file";          break;
    case SQLITE_PROTOCOL:   z = "database locking protocol failure";     break;
    case SQLITE_EMPTY:      z = "table contains no data";                break;
    case SQLITE_SCHEMA:     z = "database schema has changed";           break;
    default:                z = "unknown error";                         break;
  }
  return z;
}

Changes to src/vdbe.c.

37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
...
754
755
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
...
867
868
869
870
871
872
873
874

875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
....
1969
1970
1971
1972
1973
1974
1975



































































1976
1977
1978
1979
1980
1981
1982
....
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018

2019
2020
2021
2022
2023
2024
2025
....
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064

2065
2066
2067
2068
2069
2070
2071
....
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
....
2519
2520
2521
2522
2523
2524
2525

2526
2527
2528
2529
2530
2531
2532
** inplicit conversion from one type to the other occurs as necessary.
** 
** Most of the code in this file is taken up by the sqliteVdbeExec()
** function which does the work of interpreting a VDBE program.
** But other routines are also provided to help in building up
** a program instruction by instruction.
**
** $Id: vdbe.c,v 1.66 2001/09/14 16:42:12 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
#include <unistd.h>

/*
** SQL is translated into a sequence of instructions to be
................................................................................
static void KeylistFree(Keylist *p){
  while( p ){
    Keylist *pNext = p->pNext;
    sqliteFree(p);
    p = pNext;
  }
}


















/*
** Clean up the VM after execution.
**
** This routine will automatically close any cursors, lists, and/or
** sorters that were left open.
*/
static void Cleanup(Vdbe *p){
  int i;
  PopStack(p, p->tos+1);
  sqliteFree(p->azColName);
  p->azColName = 0;
  for(i=0; i<p->nCursor; i++){
    Cursor *pCx = &p->aCsr[i];
    if( pCx->pCursor ){
      sqliteBtreeCloseCursor(pCx->pCursor);
      pCx->pCursor = 0;
    }
    if( pCx->zKey ){
      sqliteFree(pCx->zKey);
      pCx->zKey = 0;
    }
    if( pCx->pBt ){
      sqliteBtreeClose(pCx->pBt);
      pCx->pBt = 0;
    }
  }
  sqliteFree(p->aCsr);
  p->aCsr = 0;
  p->nCursor = 0;
  for(i=0; i<p->nMem; i++){
    if( p->aMem[i].s.flags & STK_Dyn ){
      sqliteFree(p->aMem[i].z);
................................................................................
**
** If any of the numeric OP_ values for opcodes defined in sqliteVdbe.h
** change, be sure to change this array to match.  You can use the
** "opNames.awk" awk script which is part of the source tree to regenerate
** this array, then copy and paste it into this file, if you want.
*/
static char *zOpName[] = { 0,
  "Transaction",       "Commit",            "Rollback",          "Open",

  "OpenTemp",          "Close",             "MoveTo",            "Fcnt",
  "NewRecno",          "Put",               "Distinct",          "Found",
  "NotFound",          "Delete",            "Column",            "KeyAsData",
  "Recno",             "FullKey",           "Rewind",            "Next",
  "Destroy",           "Clear",             "CreateIndex",       "CreateTable",
  "Reorganize",        "BeginIdx",          "NextIdx",           "PutIdx",
  "DeleteIdx",         "MemLoad",           "MemStore",          "ListOpen",
  "ListWrite",         "ListRewind",        "ListRead",          "ListClose",
  "SortOpen",          "SortPut",           "SortMakeRec",       "SortMakeKey",
  "Sort",              "SortNext",          "SortKey",           "SortCallback",
  "SortClose",         "FileOpen",          "FileRead",          "FileColumn",
  "FileClose",         "AggReset",          "AggFocus",          "AggIncr",
  "AggNext",           "AggSet",            "AggGet",            "SetInsert",
  "SetFound",          "SetNotFound",       "SetClear",          "MakeRecord",
  "MakeKey",           "MakeIdxKey",        "Goto",              "If",
  "Halt",              "ColumnCount",       "ColumnName",        "Callback",
  "Integer",           "String",            "Null",              "Pop",
  "Dup",               "Pull",              "Add",               "AddImm",
  "Subtract",          "Multiply",          "Divide",            "Min",
  "Max",               "Like",              "Glob",              "Eq",
  "Ne",                "Lt",                "Le",                "Gt",
  "Ge",                "IsNull",            "NotNull",           "Negative",
  "And",               "Or",                "Not",               "Concat",
  "Noop",              "Strlen",            "Substr",          
};

/*
** Given the name of an opcode, return its number.  Return 0 if
** there is no match.
**
** This routine is used for testing and debugging.
................................................................................
** are allowed until another transaction is started.
*/
case OP_Rollback: {
  rc = sqliteBtreeRollback(pBt);
  sqliteRollbackInternalChanges(db);
  break;
}




































































/* Opcode: Open P1 P2 P3
**
** Open a new cursor for the database table whose root page is
** P2 in the main database file.  Give the new cursor an identifier
** of P1.  The P1 values need not be contiguous but all P1 values
** should be small integers.  It is an error for P1 to be negative.
................................................................................
    int j;
    p->aCsr = sqliteRealloc( p->aCsr, (i+1)*sizeof(Cursor) );
    if( p->aCsr==0 ){ p->nCursor = 0; goto no_mem; }
    for(j=p->nCursor; j<=i; j++){
      memset(&p->aCsr[j], 0, sizeof(Cursor));
    }
    p->nCursor = i+1;
  }else if( p->aCsr[i].pCursor ){
    sqliteBtreeCloseCursor(p->aCsr[i].pCursor);
  }

  memset(&p->aCsr[i], 0, sizeof(Cursor));
  do{
    rc = sqliteBtreeCursor(pBt, p2, &p->aCsr[i].pCursor);
    switch( rc ){
      case SQLITE_BUSY: {
        if( xBusy==0 || (*xBusy)(pBusyArg, pOp->p3, ++busy)==0 ){
          sqliteSetString(pzErrMsg, sqliteErrStr(rc), 0);
................................................................................
    int j;
    p->aCsr = sqliteRealloc( p->aCsr, (i+1)*sizeof(Cursor) );
    if( p->aCsr==0 ){ p->nCursor = 0; goto no_mem; }
    for(j=p->nCursor; j<=i; j++){
      memset(&p->aCsr[j], 0, sizeof(Cursor));
    }
    p->nCursor = i+1;
  }else if( p->aCsr[i].pCursor ){
    sqliteBtreeCloseCursor(p->aCsr[i].pCursor);
  }
  pCx = &p->aCsr[i];

  memset(pCx, 0, sizeof(*pCx));
  rc = sqliteBtreeOpen(0, 0, TEMP_PAGES, &pCx->pBt);
  if( rc==SQLITE_OK ){
    rc = sqliteBtreeCursor(pCx->pBt, 2, &pCx->pCursor);
  }
  if( rc==SQLITE_OK ){
    rc = sqliteBtreeBeginTrans(pCx->pBt);
................................................................................
**
** Close a cursor previously opened as P1.  If P1 is not
** currently open, this instruction is a no-op.
*/
case OP_Close: {
  int i = pOp->p1;
  if( i>=0 && i<p->nCursor && p->aCsr[i].pCursor ){
    Cursor *pCx = &p->aCsr[i];
    sqliteBtreeCloseCursor(pCx->pCursor);
    pCx->pCursor = 0;
    if( pCx->zKey ){
      sqliteFree(pCx->zKey);
      pCx->zKey = 0;
    }
    if( pCx->pBt ){
      sqliteBtreeClose(pCx->pBt);
      pCx->pBt = 0;
    }
  }
  break;
}

/* Opcode: MoveTo P1 * *
**
** Pop the top of the stack and use its value as a key.  Reposition
................................................................................
  int i = pOp->p1;
  int tos = p->tos;
  int res, rx;
  Cursor *pCrsr;
  VERIFY( if( tos<0 ) goto not_enough_stack; )
  if( i>=0 && i<p->nCursor && (pCrsr = &p->aCsr[i])->pCursor!=0 ){
    if( Stringify(p, tos) ) goto no_mem;

    pCrsr->nKey = aStack[tos].n;
    pCrsr->zKey = sqliteMalloc( 2*(pCrsr->nKey + 1) );
    if( pCrsr->zKey==0 ) goto no_mem;
    pCrsr->zBuf = &pCrsr->zKey[pCrsr->nKey+1];
    strncpy(pCrsr->zKey, zStack[tos], aStack[tos].n);
    pCrsr->zKey[aStack[tos].n] = 0;
    rx = sqliteBtreeMoveto(pCrsr->pCursor, zStack[tos], aStack[tos].n, &res);







|







 







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













|
<
<
<
<
<
<
<
<
<
<
<
<







 







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







 







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







 







<
<

>







 







<
<


>







 







|
<
<
<
<
<
<
<
<
<
<







 







>







37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
...
754
755
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
...
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
....
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
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
....
2082
2083
2084
2085
2086
2087
2088


2089
2090
2091
2092
2093
2094
2095
2096
2097
....
2126
2127
2128
2129
2130
2131
2132


2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
....
2148
2149
2150
2151
2152
2153
2154
2155










2156
2157
2158
2159
2160
2161
2162
....
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
** inplicit conversion from one type to the other occurs as necessary.
** 
** Most of the code in this file is taken up by the sqliteVdbeExec()
** function which does the work of interpreting a VDBE program.
** But other routines are also provided to help in building up
** a program instruction by instruction.
**
** $Id: vdbe.c,v 1.67 2001/09/15 00:57:29 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
#include <unistd.h>

/*
** SQL is translated into a sequence of instructions to be
................................................................................
static void KeylistFree(Keylist *p){
  while( p ){
    Keylist *pNext = p->pNext;
    sqliteFree(p);
    p = pNext;
  }
}

/*
** Close a cursor and release all the resources that cursor happens
** to hold.
*/
static void cleanupCursor(Cursor *pCx){
  if( pCx->pCursor ){
    sqliteBtreeCloseCursor(pCx->pCursor);
  }
  if( pCx->zKey ){
    sqliteFree(pCx->zKey);
  }
  if( pCx->pBt ){
    sqliteBtreeClose(pCx->pBt);
  }
  memset(pCx, 0, sizeof(Cursor));
}

/*
** Clean up the VM after execution.
**
** This routine will automatically close any cursors, lists, and/or
** sorters that were left open.
*/
static void Cleanup(Vdbe *p){
  int i;
  PopStack(p, p->tos+1);
  sqliteFree(p->azColName);
  p->azColName = 0;
  for(i=0; i<p->nCursor; i++){
    cleanupCursor(&p->aCsr[i]);












  }
  sqliteFree(p->aCsr);
  p->aCsr = 0;
  p->nCursor = 0;
  for(i=0; i<p->nMem; i++){
    if( p->aMem[i].s.flags & STK_Dyn ){
      sqliteFree(p->aMem[i].z);
................................................................................
**
** If any of the numeric OP_ values for opcodes defined in sqliteVdbe.h
** change, be sure to change this array to match.  You can use the
** "opNames.awk" awk script which is part of the source tree to regenerate
** this array, then copy and paste it into this file, if you want.
*/
static char *zOpName[] = { 0,
  "Transaction",       "Commit",            "Rollback",          "ReadCookie",
  "SetCookie",         "VerifyCookie",      "Open",              "OpenTemp",
  "Close",             "MoveTo",            "Fcnt",              "NewRecno",
  "Put",               "Distinct",          "Found",             "NotFound",
  "Delete",            "Column",            "KeyAsData",         "Recno",
  "FullKey",           "Rewind",            "Next",              "Destroy",
  "Clear",             "CreateIndex",       "CreateTable",       "Reorganize",
  "BeginIdx",          "NextIdx",           "PutIdx",            "DeleteIdx",
  "MemLoad",           "MemStore",          "ListOpen",          "ListWrite",
  "ListRewind",        "ListRead",          "ListClose",         "SortOpen",
  "SortPut",           "SortMakeRec",       "SortMakeKey",       "Sort",
  "SortNext",          "SortKey",           "SortCallback",      "SortClose",
  "FileOpen",          "FileRead",          "FileColumn",        "FileClose",
  "AggReset",          "AggFocus",          "AggIncr",           "AggNext",
  "AggSet",            "AggGet",            "SetInsert",         "SetFound",
  "SetNotFound",       "SetClear",          "MakeRecord",        "MakeKey",
  "MakeIdxKey",        "Goto",              "If",                "Halt",
  "ColumnCount",       "ColumnName",        "Callback",          "Integer",
  "String",            "Null",              "Pop",               "Dup",
  "Pull",              "Add",               "AddImm",            "Subtract",
  "Multiply",          "Divide",            "Min",               "Max",
  "Like",              "Glob",              "Eq",                "Ne",
  "Lt",                "Le",                "Gt",                "Ge",
  "IsNull",            "NotNull",           "Negative",          "And",
  "Or",                "Not",               "Concat",            "Noop",
  "Strlen",            "Substr",          
};

/*
** Given the name of an opcode, return its number.  Return 0 if
** there is no match.
**
** This routine is used for testing and debugging.
................................................................................
** are allowed until another transaction is started.
*/
case OP_Rollback: {
  rc = sqliteBtreeRollback(pBt);
  sqliteRollbackInternalChanges(db);
  break;
}

/* Opcode: ReadCookie * * *
**
** Read the magic cookie from the database file and push it onto the
** stack.  The magic cookie is an integer that is used like a version
** number for the database schema.  Everytime the schema changes, the
** cookie changes to a new random value.  This opcode is used during
** initialization to read the initial cookie value so that subsequent
** database accesses can verify that the cookie has not changed.
**
** There must be a read-lock on the database (either a transaction
** must be started or there must be a prior OP_Open opcode) before
** executing this instruction.
*/
case OP_ReadCookie: {
  int i = ++p->tos;
  int aMeta[SQLITE_N_BTREE_META];
  VERIFY( if( NeedStack(p, p->tos) ) goto no_mem; )
  rc = sqliteBtreeGetMeta(pBt, aMeta);
  aStack[i].i = aMeta[1];
  aStack[i].flags = STK_Int;
  break;
}

/* Opcode: SetCookie P1 * *
**
** This operation changes the value of the cookie on the database.
** The new value is P1.
**
** The cookie changes its value whenever the database schema changes.
** That way, other processes can recognize when the schema has changed
** and reread it.
**
** A transaction must be started before executing this opcode.
*/
case OP_SetCookie: {
  int aMeta[SQLITE_N_BTREE_META];
  rc = sqliteBtreeGetMeta(pBt, aMeta);
  if( rc==SQLITE_OK ){
    aMeta[1] = pOp->p1;
    rc = sqliteBtreeUpdateMeta(pBt, aMeta);
  }
  break;
}

/* Opcode: VerifyCookie P1 * *
**
** Check the current value of the database cookie and make sure it is
** equal to P1.  If it is not, abort with an SQLITE_SCHEMA error.
**
** The cookie changes its value whenever the database schema changes.
** This operation is used to detech when that the cookie has changed
** and that the current process needs to reread the schema.
**
** Either a transaction needs to have been started or an OP_Open needs
** to be executed (to establish a read lock) before this opcode is
** invoked.
*/
case OP_VerifyCookie: {
  int aMeta[SQLITE_N_BTREE_META];
  rc = sqliteBtreeGetMeta(pBt, aMeta);
  if( rc==SQLITE_OK && aMeta[1]!=pOp->p1 ){
    sqliteSetString(pzErrMsg, "database schema has changed", 0);
    rc = SQLITE_SCHEMA;
  }
  break;
}

/* Opcode: Open P1 P2 P3
**
** Open a new cursor for the database table whose root page is
** P2 in the main database file.  Give the new cursor an identifier
** of P1.  The P1 values need not be contiguous but all P1 values
** should be small integers.  It is an error for P1 to be negative.
................................................................................
    int j;
    p->aCsr = sqliteRealloc( p->aCsr, (i+1)*sizeof(Cursor) );
    if( p->aCsr==0 ){ p->nCursor = 0; goto no_mem; }
    for(j=p->nCursor; j<=i; j++){
      memset(&p->aCsr[j], 0, sizeof(Cursor));
    }
    p->nCursor = i+1;


  }
  cleanupCursor(&p->aCsr[i]);
  memset(&p->aCsr[i], 0, sizeof(Cursor));
  do{
    rc = sqliteBtreeCursor(pBt, p2, &p->aCsr[i].pCursor);
    switch( rc ){
      case SQLITE_BUSY: {
        if( xBusy==0 || (*xBusy)(pBusyArg, pOp->p3, ++busy)==0 ){
          sqliteSetString(pzErrMsg, sqliteErrStr(rc), 0);
................................................................................
    int j;
    p->aCsr = sqliteRealloc( p->aCsr, (i+1)*sizeof(Cursor) );
    if( p->aCsr==0 ){ p->nCursor = 0; goto no_mem; }
    for(j=p->nCursor; j<=i; j++){
      memset(&p->aCsr[j], 0, sizeof(Cursor));
    }
    p->nCursor = i+1;


  }
  pCx = &p->aCsr[i];
  cleanupCursor(pCx);
  memset(pCx, 0, sizeof(*pCx));
  rc = sqliteBtreeOpen(0, 0, TEMP_PAGES, &pCx->pBt);
  if( rc==SQLITE_OK ){
    rc = sqliteBtreeCursor(pCx->pBt, 2, &pCx->pCursor);
  }
  if( rc==SQLITE_OK ){
    rc = sqliteBtreeBeginTrans(pCx->pBt);
................................................................................
**
** Close a cursor previously opened as P1.  If P1 is not
** currently open, this instruction is a no-op.
*/
case OP_Close: {
  int i = pOp->p1;
  if( i>=0 && i<p->nCursor && p->aCsr[i].pCursor ){
    cleanupCursor(&p->aCsr[i]);










  }
  break;
}

/* Opcode: MoveTo P1 * *
**
** Pop the top of the stack and use its value as a key.  Reposition
................................................................................
  int i = pOp->p1;
  int tos = p->tos;
  int res, rx;
  Cursor *pCrsr;
  VERIFY( if( tos<0 ) goto not_enough_stack; )
  if( i>=0 && i<p->nCursor && (pCrsr = &p->aCsr[i])->pCursor!=0 ){
    if( Stringify(p, tos) ) goto no_mem;
    if( pCrsr->zKey ) sqliteFree(pCrsr->zKey);
    pCrsr->nKey = aStack[tos].n;
    pCrsr->zKey = sqliteMalloc( 2*(pCrsr->nKey + 1) );
    if( pCrsr->zKey==0 ) goto no_mem;
    pCrsr->zBuf = &pCrsr->zKey[pCrsr->nKey+1];
    strncpy(pCrsr->zKey, zStack[tos], aStack[tos].n);
    pCrsr->zKey[aStack[tos].n] = 0;
    rx = sqliteBtreeMoveto(pCrsr->pCursor, zStack[tos], aStack[tos].n, &res);

Changes to src/vdbe.h.

23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
..
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
*************************************************************************
** Header file for the Virtual DataBase Engine (VDBE)
**
** This header defines the interface to the virtual database engine
** or VDBE.  The VDBE implements an abstract machine that runs a
** simple program to access and modify the underlying database.
**
** $Id: vdbe.h,v 1.21 2001/09/13 21:53:10 drh Exp $
*/
#ifndef _SQLITE_VDBE_H_
#define _SQLITE_VDBE_H_
#include <stdio.h>

/*
** A single VDBE is an opaque structure named "Vdbe".  Only routines
................................................................................
** The source tree contains an AWK script named renumberOps.awk that
** can be used to renumber these opcodes when new opcodes are inserted.
*/
#define OP_Transaction         1
#define OP_Commit              2
#define OP_Rollback            3





#define OP_Open                4
#define OP_OpenTemp            5
#define OP_Close               6
#define OP_MoveTo              7
#define OP_Fcnt                8
#define OP_NewRecno            9
#define OP_Put                10
#define OP_Distinct           11
#define OP_Found              12
#define OP_NotFound           13
#define OP_Delete             14
#define OP_Column             15
#define OP_KeyAsData          16
#define OP_Recno              17
#define OP_FullKey            18
#define OP_Rewind             19
#define OP_Next               20

#define OP_Destroy            21
#define OP_Clear              22
#define OP_CreateIndex        23
#define OP_CreateTable        24
#define OP_Reorganize         25

#define OP_BeginIdx           26
#define OP_NextIdx            27
#define OP_PutIdx             28
#define OP_DeleteIdx          29

#define OP_MemLoad            30
#define OP_MemStore           31

#define OP_ListOpen           32
#define OP_ListWrite          33
#define OP_ListRewind         34
#define OP_ListRead           35
#define OP_ListClose          36

#define OP_SortOpen           37
#define OP_SortPut            38
#define OP_SortMakeRec        39
#define OP_SortMakeKey        40
#define OP_Sort               41
#define OP_SortNext           42
#define OP_SortKey            43
#define OP_SortCallback       44
#define OP_SortClose          45

#define OP_FileOpen           46
#define OP_FileRead           47
#define OP_FileColumn         48
#define OP_FileClose          49

#define OP_AggReset           50
#define OP_AggFocus           51
#define OP_AggIncr            52
#define OP_AggNext            53
#define OP_AggSet             54
#define OP_AggGet             55

#define OP_SetInsert          56
#define OP_SetFound           57
#define OP_SetNotFound        58
#define OP_SetClear           59

#define OP_MakeRecord         60
#define OP_MakeKey            61
#define OP_MakeIdxKey         62

#define OP_Goto               63
#define OP_If                 64
#define OP_Halt               65

#define OP_ColumnCount        66
#define OP_ColumnName         67
#define OP_Callback           68

#define OP_Integer            69
#define OP_String             70
#define OP_Null               71
#define OP_Pop                72
#define OP_Dup                73
#define OP_Pull               74

#define OP_Add                75
#define OP_AddImm             76
#define OP_Subtract           77
#define OP_Multiply           78
#define OP_Divide             79
#define OP_Min                80
#define OP_Max                81
#define OP_Like               82
#define OP_Glob               83
#define OP_Eq                 84
#define OP_Ne                 85
#define OP_Lt                 86
#define OP_Le                 87
#define OP_Gt                 88
#define OP_Ge                 89
#define OP_IsNull             90
#define OP_NotNull            91
#define OP_Negative           92
#define OP_And                93
#define OP_Or                 94
#define OP_Not                95
#define OP_Concat             96
#define OP_Noop               97

#define OP_Strlen             98
#define OP_Substr             99

#define OP_MAX                99

/*
** Prototypes for the VDBE interface.  See comments on the implementation
** for a description of what each of these routines does.
*/
Vdbe *sqliteVdbeCreate(sqlite*);
void sqliteVdbeCreateCallback(Vdbe*, int*);







|







 







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

|
|
|
|
|

|
|
|
|

|
|

|
|
|
|
|

|
|
|
|
|
|
|
|
|

|
|
|
|

|
|
|
|
|
|

|
|
|
|

|
|
|

|
|
|

|
|
|

|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|

|







23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
..
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
*************************************************************************
** Header file for the Virtual DataBase Engine (VDBE)
**
** This header defines the interface to the virtual database engine
** or VDBE.  The VDBE implements an abstract machine that runs a
** simple program to access and modify the underlying database.
**
** $Id: vdbe.h,v 1.22 2001/09/15 00:57:29 drh Exp $
*/
#ifndef _SQLITE_VDBE_H_
#define _SQLITE_VDBE_H_
#include <stdio.h>

/*
** A single VDBE is an opaque structure named "Vdbe".  Only routines
................................................................................
** The source tree contains an AWK script named renumberOps.awk that
** can be used to renumber these opcodes when new opcodes are inserted.
*/
#define OP_Transaction         1
#define OP_Commit              2
#define OP_Rollback            3

#define OP_ReadCookie          4
#define OP_SetCookie           5
#define OP_VerifyCookie        6

#define OP_Open                7
#define OP_OpenTemp            8
#define OP_Close               9
#define OP_MoveTo             10
#define OP_Fcnt               11
#define OP_NewRecno           12
#define OP_Put                13
#define OP_Distinct           14
#define OP_Found              15
#define OP_NotFound           16
#define OP_Delete             17
#define OP_Column             18
#define OP_KeyAsData          19
#define OP_Recno              20
#define OP_FullKey            21
#define OP_Rewind             22
#define OP_Next               23

#define OP_Destroy            24
#define OP_Clear              25
#define OP_CreateIndex        26
#define OP_CreateTable        27
#define OP_Reorganize         28

#define OP_BeginIdx           29
#define OP_NextIdx            30
#define OP_PutIdx             31
#define OP_DeleteIdx          32

#define OP_MemLoad            33
#define OP_MemStore           34

#define OP_ListOpen           35
#define OP_ListWrite          36
#define OP_ListRewind         37
#define OP_ListRead           38
#define OP_ListClose          39

#define OP_SortOpen           40
#define OP_SortPut            41
#define OP_SortMakeRec        42
#define OP_SortMakeKey        43
#define OP_Sort               44
#define OP_SortNext           45
#define OP_SortKey            46
#define OP_SortCallback       47
#define OP_SortClose          48

#define OP_FileOpen           49
#define OP_FileRead           50
#define OP_FileColumn         51
#define OP_FileClose          52

#define OP_AggReset           53
#define OP_AggFocus           54
#define OP_AggIncr            55
#define OP_AggNext            56
#define OP_AggSet             57
#define OP_AggGet             58

#define OP_SetInsert          59
#define OP_SetFound           60
#define OP_SetNotFound        61
#define OP_SetClear           62

#define OP_MakeRecord         63
#define OP_MakeKey            64
#define OP_MakeIdxKey         65

#define OP_Goto               66
#define OP_If                 67
#define OP_Halt               68

#define OP_ColumnCount        69
#define OP_ColumnName         70
#define OP_Callback           71

#define OP_Integer            72
#define OP_String             73
#define OP_Null               74
#define OP_Pop                75
#define OP_Dup                76
#define OP_Pull               77

#define OP_Add                78
#define OP_AddImm             79
#define OP_Subtract           80
#define OP_Multiply           81
#define OP_Divide             82
#define OP_Min                83
#define OP_Max                84
#define OP_Like               85
#define OP_Glob               86
#define OP_Eq                 87
#define OP_Ne                 88
#define OP_Lt                 89
#define OP_Le                 90
#define OP_Gt                 91
#define OP_Ge                 92
#define OP_IsNull             93
#define OP_NotNull            94
#define OP_Negative           95
#define OP_And                96
#define OP_Or                 97
#define OP_Not                98
#define OP_Concat             99
#define OP_Noop              100

#define OP_Strlen            101
#define OP_Substr            102

#define OP_MAX               102

/*
** Prototypes for the VDBE interface.  See comments on the implementation
** for a description of what each of these routines does.
*/
Vdbe *sqliteVdbeCreate(sqlite*);
void sqliteVdbeCreateCallback(Vdbe*, int*);

Changes to src/where.c.

21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
...
295
296
297
298
299
300
301





302
303
304
305
306
307
308
**   http://www.hwaci.com/drh/
**
*************************************************************************
** This module contains C code that generates VDBE code used to process
** the WHERE clause of SQL statements.  Also found here are subroutines
** to generate VDBE code to evaluate expressions.
**
** $Id: where.c,v 1.18 2001/09/13 16:18:55 drh 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.
................................................................................
  }

  /* Open all tables in the pTabList and all indices in aIdx[].
  */
  for(i=0; i<pTabList->nId; i++){
    sqliteVdbeAddOp(v, OP_Open, base+i, pTabList->a[i].pTab->tnum,
         pTabList->a[i].pTab->zName, 0);





    if( i<ARRAYSIZE(aIdx) && aIdx[i]!=0 ){
      sqliteVdbeAddOp(v, OP_Open, base+pTabList->nId+i, aIdx[i]->tnum,
          aIdx[i]->zName, 0);
    }
  }
  memcpy(pWInfo->aIdx, aIdx, sizeof(aIdx));








|







 







>
>
>
>
>







21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
...
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
**   http://www.hwaci.com/drh/
**
*************************************************************************
** This module contains C code that generates VDBE code used to process
** the WHERE clause of SQL statements.  Also found here are subroutines
** to generate VDBE code to evaluate expressions.
**
** $Id: where.c,v 1.19 2001/09/15 00:57:29 drh 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.
................................................................................
  }

  /* Open all tables in the pTabList and all indices in aIdx[].
  */
  for(i=0; i<pTabList->nId; i++){
    sqliteVdbeAddOp(v, OP_Open, base+i, pTabList->a[i].pTab->tnum,
         pTabList->a[i].pTab->zName, 0);
    if( i==0 && !pParse->schemaVerified &&
          (pParse->db->flags & SQLITE_InTrans)==0 ){
      sqliteVdbeAddOp(v, OP_VerifyCookie, pParse->db->schema_cookie, 0, 0, 0);
      pParse->schemaVerified = 1;
    }
    if( i<ARRAYSIZE(aIdx) && aIdx[i]!=0 ){
      sqliteVdbeAddOp(v, OP_Open, base+pTabList->nId+i, aIdx[i]->tnum,
          aIdx[i]->zName, 0);
    }
  }
  memcpy(pWInfo->aIdx, aIdx, sizeof(aIdx));