/ Check-in [116fdad0]
Login

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

Overview
Comment:Fixed the support of UNIQUE and PRIMARY KEY. (CVS 268)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 116fdad06868acf6aca9e75c2c3497c0511a42c3
User & Date: drh 2001-09-27 15:11:54
Context
2001-09-27
15:13
Alpha-3 (CVS 269) check-in: a70d4450 user: drh tags: trunk
15:11
Fixed the support of UNIQUE and PRIMARY KEY. (CVS 268) check-in: 116fdad0 user: drh tags: trunk
03:22
Added basic support for enforcement of UNIQUE on indices and primary keys. Support for addition constraints is to follow. (CVS 267) check-in: 34c42967 user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Show Whitespace Changes Patch

Changes to src/build.c.

21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
...
339
340
341
342
343
344
345

346
347
348
349
350
351
352
...
366
367
368
369
370
371
372
373
374
375
376
377
378
379

380
381
382
383
384
385
386
...
487
488
489
490
491
492
493
494
495
496
497
498
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
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
...
630
631
632
633
634
635
636
637

638
639
640
641

642
643
644
645
646
647
648
...
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
...
694
695
696
697
698
699
700





701
702
703
704
705
706
707
708
709
...
742
743
744
745
746
747
748
749
750
751
752
753
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
799
800
801
802
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



842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
**     COPY
**     VACUUM
**     BEGIN TRANSACTION
**     COMMIT
**     ROLLBACK
**     PRAGMA
**
** $Id: build.c,v 1.42 2001/09/27 03:22:33 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 
................................................................................
** more of the CREATE TABLE statement is parsed, additional action
** routines are called to build up more of the table.
*/
void sqliteStartTable(Parse *pParse, Token *pStart, Token *pName){
  Table *pTable;
  char *zName;
  sqlite *db = pParse->db;


  pParse->sFirstToken = *pStart;
  zName = sqliteTableNameFromToken(pName);
  if( zName==0 ) return;
  pTable = sqliteFindTable(db, zName);
  if( pTable!=0 ){
    sqliteSetNString(&pParse->zErrMsg, "table ", 0, pName->z, pName->n,
................................................................................
  if( pTable==0 ) return;
  pTable->zName = zName;
  pTable->nCol = 0;
  pTable->aCol = 0;
  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);
      pParse->schemaVerified = 1;
    }

  }
}

/*
** Add a new column to the table currently being constructed.
**
** The parser calls this routine once for each column declaration
................................................................................
  ** pParse->newTnum field.  (The page number should have been put
  ** there by the sqliteOpenCb routine.)  If the table has a primary
  ** key, the root page of the index associated with the primary key
  ** should be in pParse->newKnum.
  */
  if( pParse->initFlag ){
    p->tnum = pParse->newTnum;
    if( p->pIndex ){
      p->pIndex->tnum = pParse->newKnum;
    }
  }

  /* If not initializing, then create a record for the new table
  ** in the SQLITE_MASTER table of the database.
  */
  if( !pParse->initFlag ){
    int n, base;
    Vdbe *v;

    v = sqliteGetVdbe(pParse);
    if( v==0 ) return;
    n = (int)pEnd->z - (int)pParse->sFirstToken.z + 1;
    sqliteVdbeAddOp(v, OP_OpenWrite, 0, 2, MASTER_NAME, 0);
    sqliteVdbeAddOp(v, OP_NewRecno, 0, 0, 0, 0);
    sqliteVdbeAddOp(v, OP_String, 0, 0, "table", 0);
    sqliteVdbeAddOp(v, OP_String, 0, 0, p->zName, 0);
    sqliteVdbeAddOp(v, OP_String, 0, 0, p->zName, 0);
    sqliteVdbeAddOp(v, OP_CreateTable, 0, 0, 0, 0);
    sqliteVdbeTableRootAddr(v, &p->tnum);
    if( p->pIndex ){
      /* If the table has a primary key, create an index in the database
      ** for that key and record the root page of the index in the "knum"
      ** column of of the SQLITE_MASTER table.
      */
      Index *pIndex = p->pIndex;
      assert( pIndex->pNext==0 );
      assert( pIndex->tnum==0 );
      sqliteVdbeAddOp(v, OP_CreateIndex, 0, 0, 0, 0),
      sqliteVdbeIndexRootAddr(v, &pIndex->tnum);
    }else{
      /* If the table does not have a primary key, the "knum" column is 
      ** fill with a NULL value.
      */
      sqliteVdbeAddOp(v, OP_Null, 0, 0, 0, 0);
    }
    base = sqliteVdbeAddOp(v, OP_String, 0, 0, 0, 0);
    sqliteVdbeChangeP3(v, base, pParse->sFirstToken.z, n);
    sqliteVdbeAddOp(v, OP_MakeRecord, 6, 0, 0, 0);
    sqliteVdbeAddOp(v, OP_Put, 0, 0, 0, 0);
    changeCookie(db);
    sqliteVdbeAddOp(v, OP_SetCookie, db->next_cookie, 0, 0, 0);
    sqliteVdbeAddOp(v, OP_Close, 0, 0, 0, 0);
    if( (db->flags & SQLITE_InTrans)==0 ){
      sqliteVdbeAddOp(v, OP_Commit, 0, 0, 0, 0);
    }
................................................................................
    db->flags |= SQLITE_InternChanges;
  }
}

/*
** Create a new index for an SQL table.  pIndex is the name of the index 
** and pTable is the name of the table that is to be indexed.  Both will 
** be NULL for a primary key.  In that case, use pParse->pNewTable as the 

** table to be indexed.
**
** pList is a list of columns to be indexed.  pList will be NULL if the
** most recently added column of the table is labeled as the primary key.

*/
void sqliteCreateIndex(
  Parse *pParse,   /* All information about this parse */
  Token *pName,    /* Name of the index.  May be NULL */
  Token *pTable,   /* Name of the table to index.  Use pParse->pNewTable if 0 */
  IdList *pList,   /* A list of columns to be indexed */
  int isUnique,    /* True if all entries in this index must be unique */
................................................................................
    pParse->nErr++;
    goto exit_create_index;
  }

  /*
  ** Find the name of the index.  Make sure there is not already another
  ** index or table with the same name.  If pName==0 it means that we are
  ** dealing with a primary key, which has no name, so this step can be
  ** skipped.
  */
  if( pName ){
    zName = sqliteTableNameFromToken(pName);
    if( zName==0 ) goto exit_create_index;
    if( sqliteFindIndex(db, zName) ){
      sqliteSetString(&pParse->zErrMsg, "index ", zName, 
         " already exists", 0);
................................................................................
    if( sqliteFindTable(db, zName) ){
      sqliteSetString(&pParse->zErrMsg, "there is already a table named ",
         zName, 0);
      pParse->nErr++;
      goto exit_create_index;
    }
  }else{





    zName = 0;
    sqliteSetString(&zName, pTab->zName, " (primary key)", 0);
    if( zName==0 ) goto exit_create_index;
  }

  /* If pList==0, it means this routine was called to make a primary
  ** key out of the last column added to the table under construction.
  ** So create a fake list to simulate this.
  */
................................................................................
      sqliteFree(pIndex);
      goto exit_create_index;
    }
    pIndex->aiColumn[i] = j;
  }

  /* Link the new Index structure to its table and to the other
  ** in-memory database structures.  Note that primary key indices
  ** do not appear in the index hash table.
  */
  if( pParse->explain==0 ){
    if( pName!=0 ){
      char *zName = pIndex->zName;;
      sqliteHashInsert(&db->idxHash, zName, strlen(zName)+1, pIndex);
    }
    pIndex->pNext = pTab->pIndex;
    pTab->pIndex = pIndex;


    db->flags |= SQLITE_InternChanges;
  }

  /* If the initFlag is 1 it means we are reading the SQL off the
  ** "sqlite_master" table on the disk.  So do not write to the disk
  ** again.  Extract the table number from the pParse->newTnum field.
  */
  if( pParse->initFlag ){
    pIndex->tnum = pParse->newTnum;
  }

  /* If the initFlag is 0 then create the index on disk.  This
  ** involves writing the index into the master table and filling in the
  ** index with the current table contents.
  **
................................................................................
  ** The initFlag is 0 when the user first enters a CREATE INDEX 
  ** command.  The initFlag is 1 when a database is opened and 
  ** CREATE INDEX statements are read out of the master table.  In
  ** the latter case the index already exists on disk, which is why
  ** we don't want to recreate it.
  **
  ** If pTable==0 it means this index is generated as a primary key
  ** and those does not have a CREATE INDEX statement to add to the
  ** master table.  Also, since primary keys are created at the same
  ** time as tables, the table will be empty so there is no need to
  ** initialize the index.  Hence, skip all the code generation if
  ** pTable==0.
  */
  else if( pParse->initFlag==0 && pTable!=0 ){
    static VdbeOp addTable[] = {
      { OP_OpenWrite,   2, 2, MASTER_NAME},
      { OP_NewRecno,    2, 0, 0},
      { OP_String,      0, 0, "index"},
      { OP_String,      0, 0, 0},  /* 3 */
      { OP_String,      0, 0, 0},  /* 4 */
      { OP_CreateIndex, 1, 0, 0},
      { OP_Dup,         0, 0, 0},
      { OP_OpenWrite,   1, 0, 0},  /* 7 */
      { OP_Null,        0, 0, 0},
      { OP_String,      0, 0, 0},  /* 9 */
      { OP_MakeRecord,  6, 0, 0},
      { OP_Put,         2, 0, 0},
      { OP_SetCookie,   0, 0, 0},  /* 12 */
      { 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);
      pParse->schemaVerified = 1;
    }
    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);
      sqliteVdbeChangeP3(v, base+4, pTab->zName, 0);
      sqliteVdbeIndexRootAddr(v, &pIndex->tnum);
      sqliteVdbeChangeP3(v, base+7, pIndex->zName, 0);
      sqliteVdbeChangeP3(v, base+9, pStart->z, n);
      changeCookie(db);
      sqliteVdbeChangeP1(v, base+12, 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);
    for(i=0; i<pIndex->nColumn; i++){
      sqliteVdbeAddOp(v, OP_Column, 0, pIndex->aiColumn[i], 0, 0);











    }
    sqliteVdbeAddOp(v, OP_MakeIdxKey, pIndex->nColumn, 0, 0, 0);
    sqliteVdbeAddOp(v, OP_PutIdx, 1, pIndex->isUnique, 0, 0);
    sqliteVdbeAddOp(v, OP_Goto, 0, lbl1, 0, 0);
    sqliteVdbeAddOp(v, OP_Noop, 0, 0, 0, lbl2);


    sqliteVdbeAddOp(v, OP_Close, 1, 0, 0, 0);



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

  /* Reclaim memory on an EXPLAIN call.
  */
  if( pParse->explain ){
    sqliteFree(pIndex);
  }

  /* Clean up before exiting */
exit_create_index:
  sqliteIdListDelete(pList);
  sqliteFree(zName);
  return;







|







 







>







 







|
|
<




>







 







<
<
<






|





<




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







 







|
>
|


|
>







 







|
|







 







>
>
>
>
>

|







 







|
<

<
<
<
<
<
|
|
>
>







|







 







|
|
|
|
<

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

|


>



>
|




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





>
>

>
>
>
|
|



<
<
<
<
<







21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
...
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
...
367
368
369
370
371
372
373
374
375

376
377
378
379
380
381
382
383
384
385
386
387
...
488
489
490
491
492
493
494



495
496
497
498
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
...
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
...
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
...
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
...
731
732
733
734
735
736
737
738

739





740
741
742
743
744
745
746
747
748
749
750
751
752
753
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
799
800
801
802
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
**     COPY
**     VACUUM
**     BEGIN TRANSACTION
**     COMMIT
**     ROLLBACK
**     PRAGMA
**
** $Id: build.c,v 1.43 2001/09/27 15:11:54 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 
................................................................................
** more of the CREATE TABLE statement is parsed, additional action
** routines are called to build up more of the table.
*/
void sqliteStartTable(Parse *pParse, Token *pStart, Token *pName){
  Table *pTable;
  char *zName;
  sqlite *db = pParse->db;
  Vdbe *v;

  pParse->sFirstToken = *pStart;
  zName = sqliteTableNameFromToken(pName);
  if( zName==0 ) return;
  pTable = sqliteFindTable(db, zName);
  if( pTable!=0 ){
    sqliteSetNString(&pParse->zErrMsg, "table ", 0, pName->z, pName->n,
................................................................................
  if( pTable==0 ) return;
  pTable->zName = zName;
  pTable->nCol = 0;
  pTable->aCol = 0;
  pTable->pIndex = 0;
  if( pParse->pNewTable ) sqliteDeleteTable(db, pParse->pNewTable);
  pParse->pNewTable = pTable;
  if( !pParse->initFlag && (v = sqliteGetVdbe(pParse))!=0 ){
    if( (db->flags & SQLITE_InTrans)==0 ){

      sqliteVdbeAddOp(v, OP_Transaction, 0, 0, 0, 0);
      sqliteVdbeAddOp(v, OP_VerifyCookie, db->schema_cookie, 0, 0, 0);
      pParse->schemaVerified = 1;
    }
    sqliteVdbeAddOp(v, OP_OpenWrite, 0, 2, MASTER_NAME, 0);
  }
}

/*
** Add a new column to the table currently being constructed.
**
** The parser calls this routine once for each column declaration
................................................................................
  ** pParse->newTnum field.  (The page number should have been put
  ** there by the sqliteOpenCb routine.)  If the table has a primary
  ** key, the root page of the index associated with the primary key
  ** should be in pParse->newKnum.
  */
  if( pParse->initFlag ){
    p->tnum = pParse->newTnum;



  }

  /* If not initializing, then create a record for the new table
  ** in the SQLITE_MASTER table of the database.
  */
  if( !pParse->initFlag ){
    int n, addr;
    Vdbe *v;

    v = sqliteGetVdbe(pParse);
    if( v==0 ) return;
    n = (int)pEnd->z - (int)pParse->sFirstToken.z + 1;

    sqliteVdbeAddOp(v, OP_NewRecno, 0, 0, 0, 0);
    sqliteVdbeAddOp(v, OP_String, 0, 0, "table", 0);
    sqliteVdbeAddOp(v, OP_String, 0, 0, p->zName, 0);
    sqliteVdbeAddOp(v, OP_String, 0, 0, p->zName, 0);
    addr = sqliteVdbeAddOp(v, OP_CreateTable, 0, 0, 0, 0);
    sqliteVdbeChangeP3(v, addr, (char *)&p->tnum, -1);
    p->tnum = 0;















    addr = sqliteVdbeAddOp(v, OP_String, 0, 0, 0, 0);
    sqliteVdbeChangeP3(v, addr, pParse->sFirstToken.z, n);
    sqliteVdbeAddOp(v, OP_MakeRecord, 5, 0, 0, 0);
    sqliteVdbeAddOp(v, OP_Put, 0, 0, 0, 0);
    changeCookie(db);
    sqliteVdbeAddOp(v, OP_SetCookie, db->next_cookie, 0, 0, 0);
    sqliteVdbeAddOp(v, OP_Close, 0, 0, 0, 0);
    if( (db->flags & SQLITE_InTrans)==0 ){
      sqliteVdbeAddOp(v, OP_Commit, 0, 0, 0, 0);
    }
................................................................................
    db->flags |= SQLITE_InternChanges;
  }
}

/*
** Create a new index for an SQL table.  pIndex is the name of the index 
** and pTable is the name of the table that is to be indexed.  Both will 
** be NULL for a primary key or an index that is created to satisfy a
** UNIQUE constraint.  If pTable and pIndex are NULL, use pParse->pNewTable
** as the table to be indexed.
**
** pList is a list of columns to be indexed.  pList will be NULL if the
** most recently added column of the table is the primary key or has
** the UNIQUE constraint.
*/
void sqliteCreateIndex(
  Parse *pParse,   /* All information about this parse */
  Token *pName,    /* Name of the index.  May be NULL */
  Token *pTable,   /* Name of the table to index.  Use pParse->pNewTable if 0 */
  IdList *pList,   /* A list of columns to be indexed */
  int isUnique,    /* True if all entries in this index must be unique */
................................................................................
    pParse->nErr++;
    goto exit_create_index;
  }

  /*
  ** Find the name of the index.  Make sure there is not already another
  ** index or table with the same name.  If pName==0 it means that we are
  ** dealing with a primary key or UNIQUE constraint.  We have to invent our
  ** own name.
  */
  if( pName ){
    zName = sqliteTableNameFromToken(pName);
    if( zName==0 ) goto exit_create_index;
    if( sqliteFindIndex(db, zName) ){
      sqliteSetString(&pParse->zErrMsg, "index ", zName, 
         " already exists", 0);
................................................................................
    if( sqliteFindTable(db, zName) ){
      sqliteSetString(&pParse->zErrMsg, "there is already a table named ",
         zName, 0);
      pParse->nErr++;
      goto exit_create_index;
    }
  }else{
    char zBuf[30];
    int n;
    Index *pLoop;
    for(pLoop=pTab->pIndex, n=1; pLoop; pLoop=pLoop->pNext, n++){}
    sprintf(zBuf,"%d)",n);
    zName = 0;
    sqliteSetString(&zName, "(", pTab->zName, " autoindex ", zBuf, 0);
    if( zName==0 ) goto exit_create_index;
  }

  /* If pList==0, it means this routine was called to make a primary
  ** key out of the last column added to the table under construction.
  ** So create a fake list to simulate this.
  */
................................................................................
      sqliteFree(pIndex);
      goto exit_create_index;
    }
    pIndex->aiColumn[i] = j;
  }

  /* Link the new Index structure to its table and to the other
  ** in-memory database structures. 

  */





  pIndex->pNext = pTab->pIndex;
  pTab->pIndex = pIndex;
  if( !pParse->explain ){
    sqliteHashInsert(&db->idxHash, pIndex->zName, strlen(zName)+1, pIndex);
    db->flags |= SQLITE_InternChanges;
  }

  /* If the initFlag is 1 it means we are reading the SQL off the
  ** "sqlite_master" table on the disk.  So do not write to the disk
  ** again.  Extract the table number from the pParse->newTnum field.
  */
  if( pParse->initFlag && pTable!=0 ){
    pIndex->tnum = pParse->newTnum;
  }

  /* If the initFlag is 0 then create the index on disk.  This
  ** involves writing the index into the master table and filling in the
  ** index with the current table contents.
  **
................................................................................
  ** The initFlag is 0 when the user first enters a CREATE INDEX 
  ** command.  The initFlag is 1 when a database is opened and 
  ** CREATE INDEX statements are read out of the master table.  In
  ** the latter case the index already exists on disk, which is why
  ** we don't want to recreate it.
  **
  ** If pTable==0 it means this index is generated as a primary key
  ** or UNIQUE constraint of a CREATE TABLE statement.  The code generator
  ** for CREATE TABLE will have already opened cursor 0 for writing to
  ** the sqlite_master table and will take care of closing that cursor
  ** for us in the end.  So those steps are skipped when pTable==0

  */
  else if( pParse->initFlag==0 ){
















    int n;
    Vdbe *v;
    int lbl1, lbl2;
    int i;
    int addr;

    v = sqliteGetVdbe(pParse);
    if( v==0 ) goto exit_create_index;
    if( pTable!=0 ){
      if( (db->flags & SQLITE_InTrans)==0 ){
        sqliteVdbeAddOp(v, OP_Transaction, 0, 0, 0, 0);
        sqliteVdbeAddOp(v, OP_VerifyCookie, db->schema_cookie, 0, 0, 0);
        pParse->schemaVerified = 1;
      }
      sqliteVdbeAddOp(v, OP_OpenWrite, 0, 2, MASTER_NAME, 0);
    }
    sqliteVdbeAddOp(v, OP_NewRecno, 0, 0, 0, 0);
    sqliteVdbeAddOp(v, OP_String, 0, 0, "index", 0);
    sqliteVdbeAddOp(v, OP_String, 0, 0, pIndex->zName, 0);
    sqliteVdbeAddOp(v, OP_String, 0, 0, pTab->zName, 0);
    addr = sqliteVdbeAddOp(v, OP_CreateIndex, 0, 0, 0, 0);
    sqliteVdbeChangeP3(v, addr, (char*)&pIndex->tnum, -1);
    pIndex->tnum = 0;
    if( pTable ){
      sqliteVdbeAddOp(v, OP_Dup, 0, 0, 0, 0);
      sqliteVdbeAddOp(v, OP_OpenWrite, 1, 0, 0, 0);
    }
    if( pStart && pEnd ){
      n = (int)pEnd->z - (int)pStart->z + 1;
      addr = sqliteVdbeAddOp(v, OP_String, 0, 0, "", 0);
      sqliteVdbeChangeP3(v, addr, pStart->z, n);
    }else{
      sqliteVdbeAddOp(v, OP_Null, 0, 0, 0, 0);
    }
    sqliteVdbeAddOp(v, OP_MakeRecord, 5, 0, 0, 0);
    sqliteVdbeAddOp(v, OP_Put, 0, 0, 0, 0);
    if( pTable ){
      sqliteVdbeAddOp(v, OP_Open, 2, pTab->tnum, pTab->zName, 0);
      lbl1 = sqliteVdbeMakeLabel(v);
      lbl2 = sqliteVdbeMakeLabel(v);
      sqliteVdbeAddOp(v, OP_Rewind, 2, 0, 0, 0);
      sqliteVdbeAddOp(v, OP_Next, 2, lbl2, 0, lbl1);
      sqliteVdbeAddOp(v, OP_Recno, 2, 0, 0, 0);
      for(i=0; i<pIndex->nColumn; i++){
        sqliteVdbeAddOp(v, OP_Column, 2, pIndex->aiColumn[i], 0, 0);
      }
      sqliteVdbeAddOp(v, OP_MakeIdxKey, pIndex->nColumn, 0, 0, 0);
      sqliteVdbeAddOp(v, OP_PutIdx, 1, pIndex->isUnique, 0, 0);
      sqliteVdbeAddOp(v, OP_Goto, 0, lbl1, 0, 0);
      sqliteVdbeAddOp(v, OP_Noop, 0, 0, 0, lbl2);
      sqliteVdbeAddOp(v, OP_Close, 2, 0, 0, 0);
    }
    sqliteVdbeAddOp(v, OP_Close, 1, 0, 0, 0);
    if( pTable!=0 ){
      changeCookie(db);
      sqliteVdbeAddOp(v, OP_SetCookie, db->next_cookie, 0, 0, 0);
      sqliteVdbeAddOp(v, OP_Close, 0, 0, 0, 0);
      if( (db->flags & SQLITE_InTrans)==0 ){
        sqliteVdbeAddOp(v, OP_Commit, 0, 0, 0, 0);
      }
    }





  }

  /* Clean up before exiting */
exit_create_index:
  sqliteIdListDelete(pList);
  sqliteFree(zName);
  return;

Changes to src/main.c.

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
..
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
...
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
...
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
**
*************************************************************************
** 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.41 2001/09/23 20:17:55 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"

/*
** This is the callback routine for the code that initializes the
** database.  Each callback contains the following information:
**
**     argv[0] = "meta" or "table" or "index"
**     argv[1] = table or index name or meta statement type.
**     argv[2] = root page number for table or index.  NULL for meta.
**     argv[3] = root page number of primary key for tables or NULL.
**     argv[4] = SQL create statement for the table or index
**
*/
static int sqliteOpenCb(void *pDb, int argc, char **argv, char **azColName){
  sqlite *db = (sqlite*)pDb;
  Parse sParse;
  int nErr = 0;

/* TODO: Do some validity checks on all fields.  In particular,
** make sure fields do not contain NULLs. */

  assert( argc==5 );
  switch( argv[0][0] ){
    case 'm': {  /* Meta information */
      if( strcmp(argv[1],"file-format")==0 ){
        db->file_format = atoi(argv[4]);
      }else if( strcmp(argv[1],"schema-cookie")==0 ){
        db->schema_cookie = atoi(argv[4]);
        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;
      sParse.newTnum = atoi(argv[2]);
      sParse.newKnum = argv[3] ? atoi(argv[3]) : 0;
      nErr = sqliteRunParser(&sParse, argv[4], 0);








      break;
    }
    default: {
      /* This can not happen! */
      nErr = 1;
      assert( nErr==0 );
    }
................................................................................
  ** The master database table has a structure like this
  */
  static char master_schema[] = 
     "CREATE TABLE " MASTER_NAME " (\n"
     "  type text,\n"
     "  name text,\n"
     "  tbl_name text,\n"
     "  tnum integer,\n"
     "  knum integer,\n"
     "  sql text\n"
     ")"
  ;

  /* The following program is used to initialize the internal
  ** structure holding the tables and indexes of the database.
  ** The database contains a special table named "sqlite_master"
  ** defined as follows:
  **
  **    CREATE TABLE sqlite_master (
  **        type       text,    --  Either "table" or "index" or "meta"
  **        name       text,    --  Name of table or index
  **        tbl_name   text,    --  Associated table 
  **        tnum       integer, --  The integer page number of root page
  **        knum       integer, --  Root page of primary key, or NULL
  **        sql        text     --  The CREATE statement for this object
  **    );
  **
  ** The sqlite_master table contains a single entry for each table
  ** and each index.  The "type" column tells whether the entry is
  ** a table or index.  The "name" column is the name of the object.
  ** The "tbl_name" is the name of the associated table.  For tables,
................................................................................
  ** SQL for each index.  The callback will invoke the
  ** parser to build the internal representation of the
  ** database scheme.
  */
  static VdbeOp initProg[] = {
    { OP_Open,     0, 2,  0},
    { OP_Rewind,   0, 0,  0},
    { OP_Next,     0, 13, 0},           /* 2 */
    { OP_Column,   0, 0,  0},
    { OP_String,   0, 0,  "meta"},
    { OP_Ne,       0, 2,  0},
    { OP_Column,   0, 0,  0},
    { OP_Column,   0, 1,  0},
    { OP_Column,   0, 3,  0},
    { OP_Null,     0, 0,  0},
    { OP_Column,   0, 5,  0},
    { OP_Callback, 5, 0,  0},
    { OP_Goto,     0, 2,  0},
    { OP_Rewind,   0, 0,  0},           /* 13 */
    { OP_Next,     0, 25, 0},           /* 14 */
    { OP_Column,   0, 0,  0},
    { OP_String,   0, 0,  "table"},
    { OP_Ne,       0, 14, 0},
    { OP_Column,   0, 0,  0},
    { OP_Column,   0, 1,  0},
    { OP_Column,   0, 3,  0},
    { OP_Column,   0, 4,  0},
    { OP_Column,   0, 5,  0},
    { OP_Callback, 5, 0,  0},
    { OP_Goto,     0, 14, 0},
    { OP_Rewind,   0, 0,  0},           /* 25 */
    { OP_Next,     0, 37, 0},           /* 26 */
    { OP_Column,   0, 0,  0},
    { OP_String,   0, 0,  "index"},
    { OP_Ne,       0, 26, 0},
    { OP_Column,   0, 0,  0},
    { OP_Column,   0, 1,  0},
    { OP_Column,   0, 3,  0},
    { OP_Null,     0, 0,  0},
    { OP_Column,   0, 5,  0},
    { OP_Callback, 5, 0,  0},
    { OP_Goto,     0, 26, 0},
    { OP_String,   0, 0,  "meta"},      /* 37 */
    { OP_String,   0, 0,  "schema-cookie"},
    { OP_Null,     0, 0,  0},
    { OP_Null,     0, 0,  0},
    { OP_ReadCookie,0,0,  0},
    { OP_Callback, 5, 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.
  */
................................................................................
  }
  if( rc==SQLITE_OK ){
    Table *pTab;
    char *azArg[6];
    azArg[0] = "table";
    azArg[1] = MASTER_NAME;
    azArg[2] = "2";
    azArg[3] = 0;
    azArg[4] = master_schema;
    azArg[5] = 0;
    sqliteOpenCb(db, 5, azArg, 0);
    pTab = sqliteFindTable(db, MASTER_NAME);
    if( pTab ){
      pTab->readOnly = 1;
    }
    db->flags |= SQLITE_Initialized;
    sqliteCommitInternalChanges(db);
  }







|











<
|










|



|

|






>




<
|
>
>
>
>
>
>
>
>







 







|
<













|
<







 







|






<
|
|

|
|


|




<
|
|
|
|


|



<
|
|
|
|


<

|







 







<
|
|
|







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
..
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
...
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
...
200
201
202
203
204
205
206

207
208
209
210
211
212
213
214
215
216
**
*************************************************************************
** 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.42 2001/09/27 15:11:54 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"

/*
** This is the callback routine for the code that initializes the
** database.  Each callback contains the following information:
**
**     argv[0] = "meta" or "table" or "index"
**     argv[1] = table or index name or meta statement type.
**     argv[2] = root page number for table or index.  NULL for meta.

**     argv[3] = SQL create statement for the table or index
**
*/
static int sqliteOpenCb(void *pDb, int argc, char **argv, char **azColName){
  sqlite *db = (sqlite*)pDb;
  Parse sParse;
  int nErr = 0;

/* TODO: Do some validity checks on all fields.  In particular,
** make sure fields do not contain NULLs. */

  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 */
      if( argv[3] && argv[3][0] ){
        memset(&sParse, 0, sizeof(sParse));
        sParse.db = db;
        sParse.initFlag = 1;
        sParse.newTnum = atoi(argv[2]);

        nErr = sqliteRunParser(&sParse, argv[3], 0);
      }else{
        Index *pIndex = sqliteFindIndex(db, argv[1]);
        if( pIndex==0 || pIndex->tnum!=0 ){
          nErr++;
        }else{
          pIndex->tnum = atoi(argv[2]);
        }
      }
      break;
    }
    default: {
      /* This can not happen! */
      nErr = 1;
      assert( nErr==0 );
    }
................................................................................
  ** The master database table has a structure like this
  */
  static char master_schema[] = 
     "CREATE TABLE " MASTER_NAME " (\n"
     "  type text,\n"
     "  name text,\n"
     "  tbl_name text,\n"
     "  rootpage integer,\n"

     "  sql text\n"
     ")"
  ;

  /* The following program is used to initialize the internal
  ** structure holding the tables and indexes of the database.
  ** The database contains a special table named "sqlite_master"
  ** defined as follows:
  **
  **    CREATE TABLE sqlite_master (
  **        type       text,    --  Either "table" or "index" or "meta"
  **        name       text,    --  Name of table or index
  **        tbl_name   text,    --  Associated table 
  **        rootpage   integer, --  The integer page number of root page

  **        sql        text     --  The CREATE statement for this object
  **    );
  **
  ** The sqlite_master table contains a single entry for each table
  ** and each index.  The "type" column tells whether the entry is
  ** a table or index.  The "name" column is the name of the object.
  ** The "tbl_name" is the name of the associated table.  For tables,
................................................................................
  ** SQL for each index.  The callback will invoke the
  ** parser to build the internal representation of the
  ** database scheme.
  */
  static VdbeOp initProg[] = {
    { OP_Open,     0, 2,  0},
    { OP_Rewind,   0, 0,  0},
    { OP_Next,     0, 12, 0},           /* 2 */
    { OP_Column,   0, 0,  0},
    { OP_String,   0, 0,  "meta"},
    { OP_Ne,       0, 2,  0},
    { OP_Column,   0, 0,  0},
    { OP_Column,   0, 1,  0},
    { OP_Column,   0, 3,  0},

    { OP_Column,   0, 4,  0},
    { OP_Callback, 4, 0,  0},
    { OP_Goto,     0, 2,  0},
    { OP_Rewind,   0, 0,  0},           /* 12 */
    { OP_Next,     0, 23, 0},           /* 13 */
    { OP_Column,   0, 0,  0},
    { OP_String,   0, 0,  "table"},
    { OP_Ne,       0, 13, 0},
    { OP_Column,   0, 0,  0},
    { OP_Column,   0, 1,  0},
    { OP_Column,   0, 3,  0},
    { OP_Column,   0, 4,  0},

    { OP_Callback, 4, 0,  0},
    { OP_Goto,     0, 13, 0},
    { OP_Rewind,   0, 0,  0},           /* 23 */
    { OP_Next,     0, 34, 0},           /* 24 */
    { OP_Column,   0, 0,  0},
    { OP_String,   0, 0,  "index"},
    { OP_Ne,       0, 24, 0},
    { OP_Column,   0, 0,  0},
    { OP_Column,   0, 1,  0},
    { OP_Column,   0, 3,  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_Null,     0, 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.
  */
................................................................................
  }
  if( rc==SQLITE_OK ){
    Table *pTab;
    char *azArg[6];
    azArg[0] = "table";
    azArg[1] = MASTER_NAME;
    azArg[2] = "2";

    azArg[3] = master_schema;
    azArg[4] = 0;
    sqliteOpenCb(db, 4, azArg, 0);
    pTab = sqliteFindTable(db, MASTER_NAME);
    if( pTab ){
      pTab->readOnly = 1;
    }
    db->flags |= SQLITE_Initialized;
    sqliteCommitInternalChanges(db);
  }

Changes to src/parse.y.

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
...
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
**
*************************************************************************
** This file contains SQLite's grammar for SQL.  Process this file
** using the lemon parser generator to generate C code that runs
** the parser.  Lemon will also generate a header file containing
** numeric codes for all of the tokens.
**
** @(#) $Id: parse.y,v 1.31 2001/09/27 03:22:33 drh Exp $
*/
%token_prefix TK_
%token_type {Token}
%default_type {Token}
%extra_argument {Parse *pParse}
%syntax_error {
  sqliteSetString(&pParse->zErrMsg,"syntax error",0);
................................................................................
carg ::= DEFAULT MINUS FLOAT(X).     {sqliteAddDefaultValue(pParse,&X,1);}
carg ::= DEFAULT NULL. 

// In addition to the type name, we also care about the primary key.
//
ccons ::= NOT NULL.
ccons ::= PRIMARY KEY sortorder.     {sqliteCreateIndex(pParse,0,0,0,1,0,0);}
ccons ::= UNIQUE.
ccons ::= CHECK LP expr RP.

// For the time being, the only constraint we care about is the primary
// key.
//
conslist_opt ::= .
conslist_opt ::= COMMA conslist.
conslist ::= conslist COMMA tcons.
conslist ::= conslist tcons.
conslist ::= tcons.
tcons ::= CONSTRAINT ids.
tcons ::= PRIMARY KEY LP idxlist(X) RP. {sqliteCreateIndex(pParse,0,0,X,1,0,0);}
tcons ::= UNIQUE LP idlist RP.
tcons ::= CHECK expr.
idlist ::= idlist COMMA ids.
idlist ::= ids.

// The next command format is dropping tables.
//
cmd ::= DROP TABLE ids(X).          {sqliteDropTable(pParse,&X);}

// The select statement
//







|







 







|












|

|
|







10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
...
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
**
*************************************************************************
** This file contains SQLite's grammar for SQL.  Process this file
** using the lemon parser generator to generate C code that runs
** the parser.  Lemon will also generate a header file containing
** numeric codes for all of the tokens.
**
** @(#) $Id: parse.y,v 1.32 2001/09/27 15:11:54 drh Exp $
*/
%token_prefix TK_
%token_type {Token}
%default_type {Token}
%extra_argument {Parse *pParse}
%syntax_error {
  sqliteSetString(&pParse->zErrMsg,"syntax error",0);
................................................................................
carg ::= DEFAULT MINUS FLOAT(X).     {sqliteAddDefaultValue(pParse,&X,1);}
carg ::= DEFAULT NULL. 

// In addition to the type name, we also care about the primary key.
//
ccons ::= NOT NULL.
ccons ::= PRIMARY KEY sortorder.     {sqliteCreateIndex(pParse,0,0,0,1,0,0);}
ccons ::= UNIQUE.                    {sqliteCreateIndex(pParse,0,0,0,1,0,0);}
ccons ::= CHECK LP expr RP.

// For the time being, the only constraint we care about is the primary
// key.
//
conslist_opt ::= .
conslist_opt ::= COMMA conslist.
conslist ::= conslist COMMA tcons.
conslist ::= conslist tcons.
conslist ::= tcons.
tcons ::= CONSTRAINT ids.
tcons ::= PRIMARY KEY LP idxlist(X) RP. {sqliteCreateIndex(pParse,0,0,X,1,0,0);}
tcons ::= UNIQUE LP idxlist(X) RP.      {sqliteCreateIndex(pParse,0,0,X,1,0,0);}
tcons ::= CHECK expr.
// idlist ::= idlist COMMA ids.
// idlist ::= ids.

// The next command format is dropping tables.
//
cmd ::= DROP TABLE ids(X).          {sqliteDropTable(pParse,&X);}

// The select statement
//

Changes to src/shell.c.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
644
645
646
647
648
649
650

651
652
653
654
655
656
657
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains code to implement the "sqlite" command line
** utility for accessing SQLite databases.
**
** $Id: shell.c,v 1.33 2001/09/16 00:13:27 drh Exp $
*/
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "sqlite.h"
#include <unistd.h>
#include <ctype.h>
................................................................................
      extern int sqliteStrICmp(const char*,const char*);
      if( sqliteStrICmp(azArg[1],"sqlite_master")==0 ){
        char *new_argv[2], *new_colv[2];
        new_argv[0] = "CREATE TABLE sqlite_master (\n"
                      "  type text,\n"
                      "  name text,\n"
                      "  tbl_name text,\n"

                      "  sql text\n"
                      ")";
        new_argv[1] = 0;
        new_colv[0] = "sql";
        new_colv[1] = 0;
        callback(&data, 1, new_argv, new_colv);
      }else{







|







 







>







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains code to implement the "sqlite" command line
** utility for accessing SQLite databases.
**
** $Id: shell.c,v 1.34 2001/09/27 15:11:54 drh Exp $
*/
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "sqlite.h"
#include <unistd.h>
#include <ctype.h>
................................................................................
      extern int sqliteStrICmp(const char*,const char*);
      if( sqliteStrICmp(azArg[1],"sqlite_master")==0 ){
        char *new_argv[2], *new_colv[2];
        new_argv[0] = "CREATE TABLE sqlite_master (\n"
                      "  type text,\n"
                      "  name text,\n"
                      "  tbl_name text,\n"
                      "  rootpage integer,\n"
                      "  sql text\n"
                      ")";
        new_argv[1] = 0;
        new_colv[0] = "sql";
        new_colv[1] = 0;
        callback(&data, 1, new_argv, new_colv);
      }else{

Changes to src/sqliteInt.h.

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
440
441
442
443
444
445
446

447
448
449
450
451
452
453
**    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.55 2001/09/27 03:22:33 drh Exp $
*/
#include "sqlite.h"
#include "hash.h"
#include "vdbe.h"
#include "parse.h"
#include "btree.h"
#include <stdio.h>
................................................................................
void sqliteUpdate(Parse*, Token*, ExprList*, Expr*);
WhereInfo *sqliteWhereBegin(Parse*, IdList*, Expr*, int);
void sqliteWhereEnd(WhereInfo*);
void sqliteExprCode(Parse*, Expr*);
void sqliteExprIfTrue(Parse*, Expr*, int);
void sqliteExprIfFalse(Parse*, Expr*, int);
Table *sqliteFindTable(sqlite*,char*);

void sqliteCopy(Parse*, Token*, Token*, Token*);
void sqliteVacuum(Parse*, Token*);
int sqliteGlobCompare(const unsigned char*,const unsigned char*);
int sqliteLikeCompare(const unsigned char*,const unsigned char*);
char *sqliteTableNameFromToken(Token*);
int sqliteExprCheck(Parse*, Expr*, int, int*);
int sqliteExprCompare(Expr*, Expr*);







|







 







>







7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
**    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.56 2001/09/27 15:11:54 drh Exp $
*/
#include "sqlite.h"
#include "hash.h"
#include "vdbe.h"
#include "parse.h"
#include "btree.h"
#include <stdio.h>
................................................................................
void sqliteUpdate(Parse*, Token*, ExprList*, Expr*);
WhereInfo *sqliteWhereBegin(Parse*, IdList*, Expr*, int);
void sqliteWhereEnd(WhereInfo*);
void sqliteExprCode(Parse*, Expr*);
void sqliteExprIfTrue(Parse*, Expr*, int);
void sqliteExprIfFalse(Parse*, Expr*, int);
Table *sqliteFindTable(sqlite*,char*);
Index *sqliteFindIndex(sqlite*,char*);
void sqliteCopy(Parse*, Token*, Token*, Token*);
void sqliteVacuum(Parse*, Token*);
int sqliteGlobCompare(const unsigned char*,const unsigned char*);
int sqliteLikeCompare(const unsigned char*,const unsigned char*);
char *sqliteTableNameFromToken(Token*);
int sqliteExprCheck(Parse*, Expr*, int, int*);
int sqliteExprCompare(Expr*, Expr*);

Changes to src/vdbe.c.

26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
...
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
...
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
...
284
285
286
287
288
289
290

291
292
293
294
295
296
297
...
363
364
365
366
367
368
369








370
371
372








373


374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389





390
391
392
393
394
395
396
397
398
399
400

401
402





403
404
405
406
407
408
409
...
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
...
759
760
761
762
763
764
765

766
767

768
769
770
771
772
773
774
....
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
....
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
....
3861
3862
3863
3864
3865
3866
3867
3868
3869
3870
3871
3872
3873
3874
3875
3876
3877
3878
** 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.78 2001/09/27 03:22:34 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
#include <unistd.h>

/*
** SQL is translated into a sequence of instructions to be
................................................................................
  char *zLine;        /* A single line from the input file */
  int nLineAlloc;     /* Number of spaces allocated for zLine */
  int nMem;           /* Number of memory locations currently allocated */
  Mem *aMem;          /* The memory locations */
  Agg agg;            /* Aggregate information */
  int nSet;           /* Number of sets allocated */
  Set *aSet;          /* An array of sets */
  int *pTableRoot;    /* Write root page no. for new tables to this addr */
  int *pIndexRoot;    /* Write root page no. for new indices to this addr */
  int nFetch;         /* Number of OP_Fetch instructions executed */
};

/*
** Create a new virtual database engine.
*/
Vdbe *sqliteVdbeCreate(sqlite *db){
................................................................................
/*
** Turn tracing on or off
*/
void sqliteVdbeTrace(Vdbe *p, FILE *trace){
  p->trace = trace;
}

/*
** Cause the next OP_CreateTable or OP_CreateIndex instruction that executes
** to write the page number of the root page for the new table or index it
** creates into the memory location *pAddr.
**
** The pointer to the place to write the page number is cleared after
** the OP_Create* statement.  If OP_Create* is executed and the pointer
** is NULL, an error results.  Hence the address can only be used once.
** If the root address fields are set but OP_Create* operations never
** execute, that too is an error.
*/
void sqliteVdbeTableRootAddr(Vdbe *p, int *pAddr){
  p->pTableRoot = pAddr;
}
void sqliteVdbeIndexRootAddr(Vdbe *p, int *pAddr){
  p->pIndexRoot = pAddr;
}

/*
** Add a new instruction to the list of instructions current in the
** VDBE.  Return the address of the new instruction.
**
** Parameters:
**
**    p               Pointer to the VDBE
................................................................................
  p->aOp[i].p1 = p1;
  if( p2<0 && (-1-p2)<p->nLabel && p->aLabel[-1-p2]>=0 ){
    p2 = p->aLabel[-1-p2];
  }
  p->aOp[i].p2 = p2;
  if( p3 && p3[0] ){
    p->aOp[i].p3 = sqliteStrDup(p3);

  }else{
    p->aOp[i].p3 = 0;
  }
  if( lbl<0 && (-lbl)<=p->nLabel ){
    p->aLabel[-1-lbl] = i;
    for(j=0; j<i; j++){
      if( p->aOp[j].p2==lbl ) p->aOp[j].p2 = i;
................................................................................
}

/*
** Change the value of the P3 operand for a specific instruction.
** This routine is useful when a large program is loaded from a
** static array using sqliteVdbeAddOpList but we want to make a
** few minor changes to the program.








*/
void sqliteVdbeChangeP3(Vdbe *p, int addr, const char *zP3, int n){
  if( p && addr>=0 && p->nOp>addr && zP3 ){








    sqliteSetNString(&p->aOp[addr].p3, zP3, n, 0);


  }
}

/*
** If the P3 operand to the specified instruction appears
** to be a quoted string token, then this procedure removes 
** the quotes.
**
** The quoting operator can be either a grave ascent (ASCII 0x27)
** or a double quote character (ASCII 0x22).  Two quotes in a row
** resolve to be a single actual quote character within the string.
*/
void sqliteVdbeDequoteP3(Vdbe *p, int addr){
  char *z;
  if( addr<0 || addr>=p->nOp ) return;
  z = p->aOp[addr].p3;





  if( z ) sqliteDequote(z);
}

/*
** On the P3 argument of the given instruction, change all
** strings of whitespace characters into a single space and
** delete leading and trailing whitespace.
*/
void sqliteVdbeCompressSpace(Vdbe *p, int addr){
  char *z;
  int i, j;

  if( addr<0 || addr>=p->nOp ) return;
  z = p->aOp[addr].p3;





  if( z==0 ) return;
  i = j = 0;
  while( isspace(z[i]) ){ i++; }
  while( z[i] ){
    if( isspace(z[i]) ){
      z[j++] = ' ';
      while( isspace(z[++i]) ){}
................................................................................
  AggReset(&p->agg);
  for(i=0; i<p->nSet; i++){
    sqliteHashClear(&p->aSet[i].hash);
  }
  sqliteFree(p->aSet);
  p->aSet = 0;
  p->nSet = 0;
  p->pTableRoot = 0;
  p->pIndexRoot = 0;
}

/*
** Delete an entire VDBE.
*/
void sqliteVdbeDelete(Vdbe *p){
  int i;
................................................................................
  if( p==0 ) return;
  Cleanup(p);
  if( p->nOpAlloc==0 ){
    p->aOp = 0;
    p->nOp = 0;
  }
  for(i=0; i<p->nOp; i++){

    sqliteFree(p->aOp[i].p3);
  }

  sqliteFree(p->aOp);
  sqliteFree(p->aLabel);
  sqliteFree(p->aStack);
  sqliteFree(p->zStack);
  sqliteFree(p);
}

................................................................................
  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( pCrsr->nKey );
    if( pCrsr->zKey==0 ) goto no_mem;
    memcpy(pCrsr->zKey, zStack[tos], aStack[tos].n);
    pCrsr->zKey[aStack[tos].n] = 0;
    rx = sqliteBtreeMoveto(pCrsr->pCursor, zStack[tos], aStack[tos].n, &res);
    pCrsr->atFirst = rx==SQLITE_OK && res>0;
    pCrsr->recnoIsValid = 0;
  }
................................................................................
** See also: Destroy
*/
case OP_Clear: {
  sqliteBtreeClearTable(pBt, pOp->p1);
  break;
}

/* Opcode: CreateTable * * *
**
** Allocate a new table in the main database file.  Push the page number
** for the root page of the new table onto the stack.
**
** The root page number is also written to a memory location which has
** be set up by the parser.  The difference between CreateTable and
** CreateIndex is that each writes its root page number into a different
** memory location.  This writing of the page number into a memory location
** is used by the SQL parser to record the page number in its internal
** data structures.
**
** See also: CreateIndex
*/
case OP_CreateTable: {
  int i = ++p->tos;
  int pgno;
  VERIFY( if( NeedStack(p, p->tos) ) goto no_mem; )
  if( p->pTableRoot==0 ){
    rc = SQLITE_INTERNAL;
    goto abort_due_to_error;
  }
  rc = sqliteBtreeCreateTable(pBt, &pgno);
  if( rc==SQLITE_OK ){
    aStack[i].i = pgno;
    aStack[i].flags = STK_Int;
    *p->pTableRoot = pgno;
    p->pTableRoot = 0;
  }
  break;
}

/* Opcode: CreateIndex P1 * *
**
** Allocate a new Index in the main database file.  Push the page number
** for the root page of the new table onto the stack.
**
** The root page number is also written to a memory location which has
** be set up by the parser.  The difference between CreateTable and
** CreateIndex is that each writes its root page number into a different
** memory location.  This writing of the page number into a memory location
** is used by the SQL parser to record the page number in its internal
** data structures.
**
** See also: CreateTable
*/
case OP_CreateIndex: {
  int i = ++p->tos;
  int pgno;
  VERIFY( if( NeedStack(p, p->tos) ) goto no_mem; )
  if( p->pIndexRoot==0 ){
    rc = SQLITE_INTERNAL;
    goto abort_due_to_error;
  }
  rc = sqliteBtreeCreateTable(pBt, &pgno);
  if( rc==SQLITE_OK ){
    aStack[i].i = pgno;
    aStack[i].flags = STK_Int;
    *p->pIndexRoot = pgno;
    p->pIndexRoot = 0;
  }
  break;
}

/* Opcode: Reorganize P1 * *
**
** Compress, optimize, and tidy up table or index whose root page in the
................................................................................
      fprintf(p->trace,"\n");
    }
#endif
  }

cleanup:
  Cleanup(p);
  if( (p->pTableRoot || p->pIndexRoot) && rc==SQLITE_OK ){
    rc = SQLITE_INTERNAL;
    sqliteSetString(pzErrMsg, "table or index root page not set", 0);
  }
  if( rc!=SQLITE_OK ){
    closeAllCursors(p);
    sqliteBtreeRollback(pBt);
    sqliteRollbackInternalChanges(db);
    db->flags &= ~SQLITE_InTrans;
  }
  return rc;







|







 







<
<







 







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







 







>







 







>
>
>
>
>
>
>
>

|

>
>
>
>
>
>
>
>
|
>
>













|

|
>
>
>
>
>
|










>

|
>
>
>
>
>







 







<
<







 







>
|
|
>







 







|







 







|




|
|
|
|
<
<







|
<
<
<




|
|




|




|
|
|
|
<
<







|
<
<
<




|
|







 







<
<
<
<







26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
...
198
199
200
201
202
203
204


205
206
207
208
209
210
211
...
220
221
222
223
224
225
226


















227
228
229
230
231
232
233
...
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
...
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
...
753
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
....
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
....
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795


2796
2797
2798
2799
2800
2801
2802
2803



2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822


2823
2824
2825
2826
2827
2828
2829
2830



2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
....
3861
3862
3863
3864
3865
3866
3867




3868
3869
3870
3871
3872
3873
3874
** 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.79 2001/09/27 15:11:54 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
#include <unistd.h>

/*
** SQL is translated into a sequence of instructions to be
................................................................................
  char *zLine;        /* A single line from the input file */
  int nLineAlloc;     /* Number of spaces allocated for zLine */
  int nMem;           /* Number of memory locations currently allocated */
  Mem *aMem;          /* The memory locations */
  Agg agg;            /* Aggregate information */
  int nSet;           /* Number of sets allocated */
  Set *aSet;          /* An array of sets */


  int nFetch;         /* Number of OP_Fetch instructions executed */
};

/*
** Create a new virtual database engine.
*/
Vdbe *sqliteVdbeCreate(sqlite *db){
................................................................................
/*
** Turn tracing on or off
*/
void sqliteVdbeTrace(Vdbe *p, FILE *trace){
  p->trace = trace;
}



















/*
** Add a new instruction to the list of instructions current in the
** VDBE.  Return the address of the new instruction.
**
** Parameters:
**
**    p               Pointer to the VDBE
................................................................................
  p->aOp[i].p1 = p1;
  if( p2<0 && (-1-p2)<p->nLabel && p->aLabel[-1-p2]>=0 ){
    p2 = p->aLabel[-1-p2];
  }
  p->aOp[i].p2 = p2;
  if( p3 && p3[0] ){
    p->aOp[i].p3 = sqliteStrDup(p3);
    p->aOp[i].p3dyn = 1;
  }else{
    p->aOp[i].p3 = 0;
  }
  if( lbl<0 && (-lbl)<=p->nLabel ){
    p->aLabel[-1-lbl] = i;
    for(j=0; j<i; j++){
      if( p->aOp[j].p2==lbl ) p->aOp[j].p2 = i;
................................................................................
}

/*
** Change the value of the P3 operand for a specific instruction.
** This routine is useful when a large program is loaded from a
** static array using sqliteVdbeAddOpList but we want to make a
** few minor changes to the program.
**
** If n>=0 then the P3 operand is dynamic, meaning that a copy of
** the string is made into memory obtained from sqliteMalloc().
** A value of n==0 means copy bytes of zP3 up to and including the
** first null byte.  If n>0 then copy n+1 bytes of zP3.
**
** If n<0 then zP3 is assumed to be a pointer to a static string.
** P3 is made to point directly to this string without any copying.
*/
void sqliteVdbeChangeP3(Vdbe *p, int addr, char *zP3, int n){
  if( p && addr>=0 && p->nOp>addr && zP3 ){
    Op *pOp = &p->aOp[addr];
    if( pOp->p3 && pOp->p3dyn ){
      sqliteFree(pOp->p3);
    }
    if( n<0 ){
      pOp->p3 = zP3;
      pOp->p3dyn = 0;
    }else{
      sqliteSetNString(&p->aOp[addr].p3, zP3, n, 0);
      pOp->p3dyn = 1;
    }
  }
}

/*
** If the P3 operand to the specified instruction appears
** to be a quoted string token, then this procedure removes 
** the quotes.
**
** The quoting operator can be either a grave ascent (ASCII 0x27)
** or a double quote character (ASCII 0x22).  Two quotes in a row
** resolve to be a single actual quote character within the string.
*/
void sqliteVdbeDequoteP3(Vdbe *p, int addr){
  Op *pOp;
  if( addr<0 || addr>=p->nOp ) return;
  pOp = &p->aOp[addr];
  if( pOp->p3==0 || pOp->p3[0]==0 ) return;
  if( !pOp->p3dyn ){
    pOp->p3 = sqliteStrDup(pOp->p3);
    pOp->p3dyn = 1;
  }
  if( pOp->p3 ) sqliteDequote(pOp->p3);
}

/*
** On the P3 argument of the given instruction, change all
** strings of whitespace characters into a single space and
** delete leading and trailing whitespace.
*/
void sqliteVdbeCompressSpace(Vdbe *p, int addr){
  char *z;
  int i, j;
  Op *pOp;
  if( addr<0 || addr>=p->nOp ) return;
  pOp = &p->aOp[addr];
  if( !pOp->p3dyn ){
    pOp->p3 = sqliteStrDup(pOp->p3);
    pOp->p3dyn = 1;
  }
  z = pOp->p3;
  if( z==0 ) return;
  i = j = 0;
  while( isspace(z[i]) ){ i++; }
  while( z[i] ){
    if( isspace(z[i]) ){
      z[j++] = ' ';
      while( isspace(z[++i]) ){}
................................................................................
  AggReset(&p->agg);
  for(i=0; i<p->nSet; i++){
    sqliteHashClear(&p->aSet[i].hash);
  }
  sqliteFree(p->aSet);
  p->aSet = 0;
  p->nSet = 0;


}

/*
** Delete an entire VDBE.
*/
void sqliteVdbeDelete(Vdbe *p){
  int i;
................................................................................
  if( p==0 ) return;
  Cleanup(p);
  if( p->nOpAlloc==0 ){
    p->aOp = 0;
    p->nOp = 0;
  }
  for(i=0; i<p->nOp; i++){
    if( p->aOp[i].p3dyn ){
      sqliteFree(p->aOp[i].p3);
    }
  }
  sqliteFree(p->aOp);
  sqliteFree(p->aLabel);
  sqliteFree(p->aStack);
  sqliteFree(p->zStack);
  sqliteFree(p);
}

................................................................................
  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( pCrsr->nKey+1 );
    if( pCrsr->zKey==0 ) goto no_mem;
    memcpy(pCrsr->zKey, zStack[tos], aStack[tos].n);
    pCrsr->zKey[aStack[tos].n] = 0;
    rx = sqliteBtreeMoveto(pCrsr->pCursor, zStack[tos], aStack[tos].n, &res);
    pCrsr->atFirst = rx==SQLITE_OK && res>0;
    pCrsr->recnoIsValid = 0;
  }
................................................................................
** See also: Destroy
*/
case OP_Clear: {
  sqliteBtreeClearTable(pBt, pOp->p1);
  break;
}

/* Opcode: CreateTable * * P3
**
** Allocate a new table in the main database file.  Push the page number
** for the root page of the new table onto the stack.
**
** The root page number is also written to a memory location that P3
** points to.  This is the mechanism is used to write the root page
** number into the parser's internal data structures that describe the
** new table.


**
** See also: CreateIndex
*/
case OP_CreateTable: {
  int i = ++p->tos;
  int pgno;
  VERIFY( if( NeedStack(p, p->tos) ) goto no_mem; )
  assert( pOp->p3!=0 && pOp->p3dyn==0 );



  rc = sqliteBtreeCreateTable(pBt, &pgno);
  if( rc==SQLITE_OK ){
    aStack[i].i = pgno;
    aStack[i].flags = STK_Int;
    *(u32*)pOp->p3 = pgno;
    pOp->p3 = 0;
  }
  break;
}

/* Opcode: CreateIndex * * P3
**
** Allocate a new Index in the main database file.  Push the page number
** for the root page of the new table onto the stack.
**
** The root page number is also written to a memory location that P3
** points to.  This is the mechanism is used to write the root page
** number into the parser's internal data structures that describe the
** new index.


**
** See also: CreateTable
*/
case OP_CreateIndex: {
  int i = ++p->tos;
  int pgno;
  VERIFY( if( NeedStack(p, p->tos) ) goto no_mem; )
  assert( pOp->p3!=0 && pOp->p3dyn==0 );



  rc = sqliteBtreeCreateTable(pBt, &pgno);
  if( rc==SQLITE_OK ){
    aStack[i].i = pgno;
    aStack[i].flags = STK_Int;
    *(u32*)pOp->p3 = pgno;
    pOp->p3 = 0;
  }
  break;
}

/* Opcode: Reorganize P1 * *
**
** Compress, optimize, and tidy up table or index whose root page in the
................................................................................
      fprintf(p->trace,"\n");
    }
#endif
  }

cleanup:
  Cleanup(p);




  if( rc!=SQLITE_OK ){
    closeAllCursors(p);
    sqliteBtreeRollback(pBt);
    sqliteRollbackInternalChanges(db);
    db->flags &= ~SQLITE_InTrans;
  }
  return rc;

Changes to src/vdbe.h.

11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
..
34
35
36
37
38
39
40

41
42
43
44
45
46
47
...
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
*************************************************************************
** 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.24 2001/09/23 02:35:53 drh Exp $
*/
#ifndef _SQLITE_VDBE_H_
#define _SQLITE_VDBE_H_
#include <stdio.h>

/*
** A single VDBE is an opaque structure named "Vdbe".  Only routines
................................................................................
** as an instance of the following structure:
*/
struct VdbeOp {
  int opcode;         /* What operation to perform */
  int p1;             /* First operand */
  int p2;             /* Second parameter (often the jump destination) */
  char *p3;           /* Third parameter */

};
typedef struct VdbeOp VdbeOp;

/*
** The following macro converts a relative address in the p2 field
** of a VdbeOp structure into a negative number so that 
** sqliteVdbeAddOpList() knows that the address is relative.  Calling
................................................................................

/*
** 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*);
void sqliteVdbeTableRootAddr(Vdbe*, int*);
void sqliteVdbeIndexRootAddr(Vdbe*, int*);
int sqliteVdbeAddOp(Vdbe*,int,int,int,const char*,int);
int sqliteVdbeAddOpList(Vdbe*, int nOp, VdbeOp const *aOp);
void sqliteVdbeChangeP1(Vdbe*, int addr, int P1);
void sqliteVdbeChangeP3(Vdbe*, int addr, const char *zP1, int N);
void sqliteVdbeDequoteP3(Vdbe*, int addr);
int sqliteVdbeMakeLabel(Vdbe*);
void sqliteVdbeDelete(Vdbe*);
int sqliteVdbeOpcode(const char *zName);
int sqliteVdbeExec(Vdbe*,sqlite_callback,void*,char**,void*,
                   int(*)(void*,const char*,int));
int sqliteVdbeList(Vdbe*,sqlite_callback,void*,char**);
void sqliteVdbeResolveLabel(Vdbe*, int);
int sqliteVdbeCurrentAddr(Vdbe*);
void sqliteVdbeTrace(Vdbe*,FILE*);
void sqliteVdbeCompressSpace(Vdbe*,int);

#endif







|







 







>







 







<
<



|













11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
..
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
...
184
185
186
187
188
189
190


191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
*************************************************************************
** 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.25 2001/09/27 15:11:55 drh Exp $
*/
#ifndef _SQLITE_VDBE_H_
#define _SQLITE_VDBE_H_
#include <stdio.h>

/*
** A single VDBE is an opaque structure named "Vdbe".  Only routines
................................................................................
** as an instance of the following structure:
*/
struct VdbeOp {
  int opcode;         /* What operation to perform */
  int p1;             /* First operand */
  int p2;             /* Second parameter (often the jump destination) */
  char *p3;           /* Third parameter */
  int p3dyn;          /* True if p3 is malloced.  False if it is static */
};
typedef struct VdbeOp VdbeOp;

/*
** The following macro converts a relative address in the p2 field
** of a VdbeOp structure into a negative number so that 
** sqliteVdbeAddOpList() knows that the address is relative.  Calling
................................................................................

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


int sqliteVdbeAddOp(Vdbe*,int,int,int,const char*,int);
int sqliteVdbeAddOpList(Vdbe*, int nOp, VdbeOp const *aOp);
void sqliteVdbeChangeP1(Vdbe*, int addr, int P1);
void sqliteVdbeChangeP3(Vdbe*, int addr, char *zP1, int N);
void sqliteVdbeDequoteP3(Vdbe*, int addr);
int sqliteVdbeMakeLabel(Vdbe*);
void sqliteVdbeDelete(Vdbe*);
int sqliteVdbeOpcode(const char *zName);
int sqliteVdbeExec(Vdbe*,sqlite_callback,void*,char**,void*,
                   int(*)(void*,const char*,int));
int sqliteVdbeList(Vdbe*,sqlite_callback,void*,char**);
void sqliteVdbeResolveLabel(Vdbe*, int);
int sqliteVdbeCurrentAddr(Vdbe*);
void sqliteVdbeTrace(Vdbe*,FILE*);
void sqliteVdbeCompressSpace(Vdbe*,int);

#endif

Changes to test/index.test.

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
199
200
201
202
203
204
205
206
207
208


209
210
211
212
213
214
215
#    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 CREATE INDEX statement.
#
# $Id: index.test,v 1.13 2001/09/17 20:25:58 drh Exp $

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

# Create a basic index and verify it is added to sqlite_master
#
do_test index-1.1 {
................................................................................
  }
  execsql {SELECT count(*) FROM test1}
} {19}
do_test index-7.2 {
  execsql {SELECT f1 FROM test1 WHERE f2=65536}
} {16}
do_test index-7.3 {
  set code [execsql {EXPLAIN SELECT f1 FROM test1 WHERE f2=65536}]
  expr {[lsearch $code {test1 (primary key)}]>0}
} {1}


do_test index-7.4 {
  execsql {DROP table test1}
  execsql {SELECT name FROM sqlite_master WHERE type!='meta'}
} {}

# Make sure we cannot drop a non-existant index.
#







|







 







|
|
|
>
>







7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
#    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 CREATE INDEX statement.
#
# $Id: index.test,v 1.14 2001/09/27 15:11:55 drh Exp $

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

# Create a basic index and verify it is added to sqlite_master
#
do_test index-1.1 {
................................................................................
  }
  execsql {SELECT count(*) FROM test1}
} {19}
do_test index-7.2 {
  execsql {SELECT f1 FROM test1 WHERE f2=65536}
} {16}
do_test index-7.3 {
  execsql {
    SELECT name FROM sqlite_master 
    WHERE type='index' AND tbl_name='test1'
  }
} {{(test1 autoindex 1)}}
do_test index-7.4 {
  execsql {DROP table test1}
  execsql {SELECT name FROM sqlite_master WHERE type!='meta'}
} {}

# Make sure we cannot drop a non-existant index.
#

Changes to test/table.test.

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
#    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 CREATE TABLE statement.
#
# $Id: table.test,v 1.12 2001/09/16 00:13:28 drh Exp $

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

# Create a basic table and verify it is added to sqlite_master
#
do_test table-1.1 {
................................................................................
  f17 text,
  f18 text,
  f19 text,
  f20 text
)}
do_test table-3.1 {
  execsql $big_table
  execsql {SELECT sql FROM sqlite_master WHERE type!='meta'}
} \{$big_table\}
do_test table-3.2 {
  set v [catch {execsql {CREATE TABLE BIG(xyz foo)}} msg]
  lappend v $msg
} {1 {table BIG already exists}}
do_test table-3.3 {
  set v [catch {execsql {CREATE TABLE biG(xyz foo)}} msg]







|







 







|







7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
#    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 CREATE TABLE statement.
#
# $Id: table.test,v 1.13 2001/09/27 15:11:55 drh Exp $

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

# Create a basic table and verify it is added to sqlite_master
#
do_test table-1.1 {
................................................................................
  f17 text,
  f18 text,
  f19 text,
  f20 text
)}
do_test table-3.1 {
  execsql $big_table
  execsql {SELECT sql FROM sqlite_master WHERE type=='table'}
} \{$big_table\}
do_test table-3.2 {
  set v [catch {execsql {CREATE TABLE BIG(xyz foo)}} msg]
  lappend v $msg
} {1 {table BIG already exists}}
do_test table-3.3 {
  set v [catch {execsql {CREATE TABLE biG(xyz foo)}} msg]

Changes to test/tester.tcl.

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
169
170
171
172
173
174
175









176
177
178
179
180
181
182
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements some common TCL routines used for regression
# testing the SQLite library
#
# $Id: tester.tcl,v 1.19 2001/09/20 01:44:43 drh Exp $

# Make sure tclsqlite was compiled correctly.  Abort now with an
# error message if not.
#
if {[sqlite -tcl-uses-utf]} {
  if {"\u1234"=="u1234"} {
    puts stderr "***** BUILD PROBLEM *****"
................................................................................

# A procedure to execute SQL
#
proc execsql {sql {db db}} {
  # puts "SQL = $sql"
  return [$db eval $sql]
}










# Another procedure to execute SQL.  This one includes the field
# names in the returned list.
#
proc execsql2 {sql} {
  set result {}
  db eval $sql data {







|







 







>
>
>
>
>
>
>
>
>







7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements some common TCL routines used for regression
# testing the SQLite library
#
# $Id: tester.tcl,v 1.20 2001/09/27 15:11:55 drh Exp $

# Make sure tclsqlite was compiled correctly.  Abort now with an
# error message if not.
#
if {[sqlite -tcl-uses-utf]} {
  if {"\u1234"=="u1234"} {
    puts stderr "***** BUILD PROBLEM *****"
................................................................................

# A procedure to execute SQL
#
proc execsql {sql {db db}} {
  # puts "SQL = $sql"
  return [$db eval $sql]
}

# Execute SQL and catch exceptions.
#
proc catchsql {sql {db db}} {
  # puts "SQL = $sql"
  set r [catch {$db eval $sql} msg]
  lappend r $msg
  return $r
}

# Another procedure to execute SQL.  This one includes the field
# names in the returned list.
#
proc execsql2 {sql} {
  set result {}
  db eval $sql data {

Added test/unique.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
# 2001 September 27
#
# 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 CREATE UNIQUE INDEX statement,
# and primary keys, and the UNIQUE constraint on table columns
#
# $Id: unique.test,v 1.1 2001/09/27 15:11:55 drh Exp $

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

# Try to create a table with two primary keys.
# (This is allowed in SQLite even that it is not valid SQL)
#
do_test unique-1.1 {
  catchsql {
    CREATE TABLE t1(
       a int PRIMARY KEY,
       b int PRIMARY KEY,
       c text
    );
  }
} {0 {}}

finish_test