/ 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 Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/build.c.

    21     21   **     COPY
    22     22   **     VACUUM
    23     23   **     BEGIN TRANSACTION
    24     24   **     COMMIT
    25     25   **     ROLLBACK
    26     26   **     PRAGMA
    27     27   **
    28         -** $Id: build.c,v 1.42 2001/09/27 03:22:33 drh Exp $
           28  +** $Id: build.c,v 1.43 2001/09/27 15:11:54 drh Exp $
    29     29   */
    30     30   #include "sqliteInt.h"
    31     31   #include <ctype.h>
    32     32   
    33     33   /*
    34     34   ** This routine is called after a single SQL statement has been
    35     35   ** parsed and we want to execute the VDBE code to implement 
................................................................................
   339    339   ** more of the CREATE TABLE statement is parsed, additional action
   340    340   ** routines are called to build up more of the table.
   341    341   */
   342    342   void sqliteStartTable(Parse *pParse, Token *pStart, Token *pName){
   343    343     Table *pTable;
   344    344     char *zName;
   345    345     sqlite *db = pParse->db;
          346  +  Vdbe *v;
   346    347   
   347    348     pParse->sFirstToken = *pStart;
   348    349     zName = sqliteTableNameFromToken(pName);
   349    350     if( zName==0 ) return;
   350    351     pTable = sqliteFindTable(db, zName);
   351    352     if( pTable!=0 ){
   352    353       sqliteSetNString(&pParse->zErrMsg, "table ", 0, pName->z, pName->n,
................................................................................
   366    367     if( pTable==0 ) return;
   367    368     pTable->zName = zName;
   368    369     pTable->nCol = 0;
   369    370     pTable->aCol = 0;
   370    371     pTable->pIndex = 0;
   371    372     if( pParse->pNewTable ) sqliteDeleteTable(db, pParse->pNewTable);
   372    373     pParse->pNewTable = pTable;
   373         -  if( !pParse->initFlag && (db->flags & SQLITE_InTrans)==0 ){
   374         -    Vdbe *v = sqliteGetVdbe(pParse);
   375         -    if( v ){
          374  +  if( !pParse->initFlag && (v = sqliteGetVdbe(pParse))!=0 ){
          375  +    if( (db->flags & SQLITE_InTrans)==0 ){
   376    376         sqliteVdbeAddOp(v, OP_Transaction, 0, 0, 0, 0);
   377    377         sqliteVdbeAddOp(v, OP_VerifyCookie, db->schema_cookie, 0, 0, 0);
   378    378         pParse->schemaVerified = 1;
   379    379       }
          380  +    sqliteVdbeAddOp(v, OP_OpenWrite, 0, 2, MASTER_NAME, 0);
   380    381     }
   381    382   }
   382    383   
   383    384   /*
   384    385   ** Add a new column to the table currently being constructed.
   385    386   **
   386    387   ** The parser calls this routine once for each column declaration
................................................................................
   487    488     ** pParse->newTnum field.  (The page number should have been put
   488    489     ** there by the sqliteOpenCb routine.)  If the table has a primary
   489    490     ** key, the root page of the index associated with the primary key
   490    491     ** should be in pParse->newKnum.
   491    492     */
   492    493     if( pParse->initFlag ){
   493    494       p->tnum = pParse->newTnum;
   494         -    if( p->pIndex ){
   495         -      p->pIndex->tnum = pParse->newKnum;
   496         -    }
   497    495     }
   498    496   
   499    497     /* If not initializing, then create a record for the new table
   500    498     ** in the SQLITE_MASTER table of the database.
   501    499     */
   502    500     if( !pParse->initFlag ){
   503         -    int n, base;
          501  +    int n, addr;
   504    502       Vdbe *v;
   505    503   
   506    504       v = sqliteGetVdbe(pParse);
   507    505       if( v==0 ) return;
   508    506       n = (int)pEnd->z - (int)pParse->sFirstToken.z + 1;
   509         -    sqliteVdbeAddOp(v, OP_OpenWrite, 0, 2, MASTER_NAME, 0);
   510    507       sqliteVdbeAddOp(v, OP_NewRecno, 0, 0, 0, 0);
   511    508       sqliteVdbeAddOp(v, OP_String, 0, 0, "table", 0);
   512    509       sqliteVdbeAddOp(v, OP_String, 0, 0, p->zName, 0);
   513    510       sqliteVdbeAddOp(v, OP_String, 0, 0, p->zName, 0);
   514         -    sqliteVdbeAddOp(v, OP_CreateTable, 0, 0, 0, 0);
   515         -    sqliteVdbeTableRootAddr(v, &p->tnum);
   516         -    if( p->pIndex ){
   517         -      /* If the table has a primary key, create an index in the database
   518         -      ** for that key and record the root page of the index in the "knum"
   519         -      ** column of of the SQLITE_MASTER table.
   520         -      */
   521         -      Index *pIndex = p->pIndex;
   522         -      assert( pIndex->pNext==0 );
   523         -      assert( pIndex->tnum==0 );
   524         -      sqliteVdbeAddOp(v, OP_CreateIndex, 0, 0, 0, 0),
   525         -      sqliteVdbeIndexRootAddr(v, &pIndex->tnum);
   526         -    }else{
   527         -      /* If the table does not have a primary key, the "knum" column is 
   528         -      ** fill with a NULL value.
   529         -      */
   530         -      sqliteVdbeAddOp(v, OP_Null, 0, 0, 0, 0);
   531         -    }
   532         -    base = sqliteVdbeAddOp(v, OP_String, 0, 0, 0, 0);
   533         -    sqliteVdbeChangeP3(v, base, pParse->sFirstToken.z, n);
   534         -    sqliteVdbeAddOp(v, OP_MakeRecord, 6, 0, 0, 0);
          511  +    addr = sqliteVdbeAddOp(v, OP_CreateTable, 0, 0, 0, 0);
          512  +    sqliteVdbeChangeP3(v, addr, (char *)&p->tnum, -1);
          513  +    p->tnum = 0;
          514  +    addr = sqliteVdbeAddOp(v, OP_String, 0, 0, 0, 0);
          515  +    sqliteVdbeChangeP3(v, addr, pParse->sFirstToken.z, n);
          516  +    sqliteVdbeAddOp(v, OP_MakeRecord, 5, 0, 0, 0);
   535    517       sqliteVdbeAddOp(v, OP_Put, 0, 0, 0, 0);
   536    518       changeCookie(db);
   537    519       sqliteVdbeAddOp(v, OP_SetCookie, db->next_cookie, 0, 0, 0);
   538    520       sqliteVdbeAddOp(v, OP_Close, 0, 0, 0, 0);
   539    521       if( (db->flags & SQLITE_InTrans)==0 ){
   540    522         sqliteVdbeAddOp(v, OP_Commit, 0, 0, 0, 0);
   541    523       }
................................................................................
   630    612       db->flags |= SQLITE_InternChanges;
   631    613     }
   632    614   }
   633    615   
   634    616   /*
   635    617   ** Create a new index for an SQL table.  pIndex is the name of the index 
   636    618   ** and pTable is the name of the table that is to be indexed.  Both will 
   637         -** be NULL for a primary key.  In that case, use pParse->pNewTable as the 
   638         -** table to be indexed.
          619  +** be NULL for a primary key or an index that is created to satisfy a
          620  +** UNIQUE constraint.  If pTable and pIndex are NULL, use pParse->pNewTable
          621  +** as the table to be indexed.
   639    622   **
   640    623   ** pList is a list of columns to be indexed.  pList will be NULL if the
   641         -** most recently added column of the table is labeled as the primary key.
          624  +** most recently added column of the table is the primary key or has
          625  +** the UNIQUE constraint.
   642    626   */
   643    627   void sqliteCreateIndex(
   644    628     Parse *pParse,   /* All information about this parse */
   645    629     Token *pName,    /* Name of the index.  May be NULL */
   646    630     Token *pTable,   /* Name of the table to index.  Use pParse->pNewTable if 0 */
   647    631     IdList *pList,   /* A list of columns to be indexed */
   648    632     int isUnique,    /* True if all entries in this index must be unique */
................................................................................
   675    659       pParse->nErr++;
   676    660       goto exit_create_index;
   677    661     }
   678    662   
   679    663     /*
   680    664     ** Find the name of the index.  Make sure there is not already another
   681    665     ** index or table with the same name.  If pName==0 it means that we are
   682         -  ** dealing with a primary key, which has no name, so this step can be
   683         -  ** skipped.
          666  +  ** dealing with a primary key or UNIQUE constraint.  We have to invent our
          667  +  ** own name.
   684    668     */
   685    669     if( pName ){
   686    670       zName = sqliteTableNameFromToken(pName);
   687    671       if( zName==0 ) goto exit_create_index;
   688    672       if( sqliteFindIndex(db, zName) ){
   689    673         sqliteSetString(&pParse->zErrMsg, "index ", zName, 
   690    674            " already exists", 0);
................................................................................
   694    678       if( sqliteFindTable(db, zName) ){
   695    679         sqliteSetString(&pParse->zErrMsg, "there is already a table named ",
   696    680            zName, 0);
   697    681         pParse->nErr++;
   698    682         goto exit_create_index;
   699    683       }
   700    684     }else{
          685  +    char zBuf[30];
          686  +    int n;
          687  +    Index *pLoop;
          688  +    for(pLoop=pTab->pIndex, n=1; pLoop; pLoop=pLoop->pNext, n++){}
          689  +    sprintf(zBuf,"%d)",n);
   701    690       zName = 0;
   702         -    sqliteSetString(&zName, pTab->zName, " (primary key)", 0);
          691  +    sqliteSetString(&zName, "(", pTab->zName, " autoindex ", zBuf, 0);
   703    692       if( zName==0 ) goto exit_create_index;
   704    693     }
   705    694   
   706    695     /* If pList==0, it means this routine was called to make a primary
   707    696     ** key out of the last column added to the table under construction.
   708    697     ** So create a fake list to simulate this.
   709    698     */
................................................................................
   742    731         sqliteFree(pIndex);
   743    732         goto exit_create_index;
   744    733       }
   745    734       pIndex->aiColumn[i] = j;
   746    735     }
   747    736   
   748    737     /* Link the new Index structure to its table and to the other
   749         -  ** in-memory database structures.  Note that primary key indices
   750         -  ** do not appear in the index hash table.
          738  +  ** in-memory database structures. 
   751    739     */
   752         -  if( pParse->explain==0 ){
   753         -    if( pName!=0 ){
   754         -      char *zName = pIndex->zName;;
   755         -      sqliteHashInsert(&db->idxHash, zName, strlen(zName)+1, pIndex);
   756         -    }
   757         -    pIndex->pNext = pTab->pIndex;
   758         -    pTab->pIndex = pIndex;
          740  +  pIndex->pNext = pTab->pIndex;
          741  +  pTab->pIndex = pIndex;
          742  +  if( !pParse->explain ){
          743  +    sqliteHashInsert(&db->idxHash, pIndex->zName, strlen(zName)+1, pIndex);
   759    744       db->flags |= SQLITE_InternChanges;
   760    745     }
   761    746   
   762    747     /* If the initFlag is 1 it means we are reading the SQL off the
   763    748     ** "sqlite_master" table on the disk.  So do not write to the disk
   764    749     ** again.  Extract the table number from the pParse->newTnum field.
   765    750     */
   766         -  if( pParse->initFlag ){
          751  +  if( pParse->initFlag && pTable!=0 ){
   767    752       pIndex->tnum = pParse->newTnum;
   768    753     }
   769    754   
   770    755     /* If the initFlag is 0 then create the index on disk.  This
   771    756     ** involves writing the index into the master table and filling in the
   772    757     ** index with the current table contents.
   773    758     **
................................................................................
   774    759     ** The initFlag is 0 when the user first enters a CREATE INDEX 
   775    760     ** command.  The initFlag is 1 when a database is opened and 
   776    761     ** CREATE INDEX statements are read out of the master table.  In
   777    762     ** the latter case the index already exists on disk, which is why
   778    763     ** we don't want to recreate it.
   779    764     **
   780    765     ** If pTable==0 it means this index is generated as a primary key
   781         -  ** and those does not have a CREATE INDEX statement to add to the
   782         -  ** master table.  Also, since primary keys are created at the same
   783         -  ** time as tables, the table will be empty so there is no need to
   784         -  ** initialize the index.  Hence, skip all the code generation if
   785         -  ** pTable==0.
          766  +  ** or UNIQUE constraint of a CREATE TABLE statement.  The code generator
          767  +  ** for CREATE TABLE will have already opened cursor 0 for writing to
          768  +  ** the sqlite_master table and will take care of closing that cursor
          769  +  ** for us in the end.  So those steps are skipped when pTable==0
   786    770     */
   787         -  else if( pParse->initFlag==0 && pTable!=0 ){
   788         -    static VdbeOp addTable[] = {
   789         -      { OP_OpenWrite,   2, 2, MASTER_NAME},
   790         -      { OP_NewRecno,    2, 0, 0},
   791         -      { OP_String,      0, 0, "index"},
   792         -      { OP_String,      0, 0, 0},  /* 3 */
   793         -      { OP_String,      0, 0, 0},  /* 4 */
   794         -      { OP_CreateIndex, 1, 0, 0},
   795         -      { OP_Dup,         0, 0, 0},
   796         -      { OP_OpenWrite,   1, 0, 0},  /* 7 */
   797         -      { OP_Null,        0, 0, 0},
   798         -      { OP_String,      0, 0, 0},  /* 9 */
   799         -      { OP_MakeRecord,  6, 0, 0},
   800         -      { OP_Put,         2, 0, 0},
   801         -      { OP_SetCookie,   0, 0, 0},  /* 12 */
   802         -      { OP_Close,       2, 0, 0},
   803         -    };
          771  +  else if( pParse->initFlag==0 ){
   804    772       int n;
   805         -    Vdbe *v = pParse->pVdbe;
          773  +    Vdbe *v;
   806    774       int lbl1, lbl2;
   807    775       int i;
          776  +    int addr;
   808    777   
   809    778       v = sqliteGetVdbe(pParse);
   810    779       if( v==0 ) goto exit_create_index;
   811         -    if( pTable!=0 && (db->flags & SQLITE_InTrans)==0 ){
   812         -      sqliteVdbeAddOp(v, OP_Transaction, 0, 0, 0, 0);
   813         -      sqliteVdbeAddOp(v, OP_VerifyCookie, db->schema_cookie, 0, 0, 0);
   814         -      pParse->schemaVerified = 1;
          780  +    if( pTable!=0 ){
          781  +      if( (db->flags & SQLITE_InTrans)==0 ){
          782  +        sqliteVdbeAddOp(v, OP_Transaction, 0, 0, 0, 0);
          783  +        sqliteVdbeAddOp(v, OP_VerifyCookie, db->schema_cookie, 0, 0, 0);
          784  +        pParse->schemaVerified = 1;
          785  +      }
          786  +      sqliteVdbeAddOp(v, OP_OpenWrite, 0, 2, MASTER_NAME, 0);
          787  +    }
          788  +    sqliteVdbeAddOp(v, OP_NewRecno, 0, 0, 0, 0);
          789  +    sqliteVdbeAddOp(v, OP_String, 0, 0, "index", 0);
          790  +    sqliteVdbeAddOp(v, OP_String, 0, 0, pIndex->zName, 0);
          791  +    sqliteVdbeAddOp(v, OP_String, 0, 0, pTab->zName, 0);
          792  +    addr = sqliteVdbeAddOp(v, OP_CreateIndex, 0, 0, 0, 0);
          793  +    sqliteVdbeChangeP3(v, addr, (char*)&pIndex->tnum, -1);
          794  +    pIndex->tnum = 0;
          795  +    if( pTable ){
          796  +      sqliteVdbeAddOp(v, OP_Dup, 0, 0, 0, 0);
          797  +      sqliteVdbeAddOp(v, OP_OpenWrite, 1, 0, 0, 0);
   815    798       }
   816    799       if( pStart && pEnd ){
   817         -      int base;
   818    800         n = (int)pEnd->z - (int)pStart->z + 1;
   819         -      base = sqliteVdbeAddOpList(v, ArraySize(addTable), addTable);
   820         -      sqliteVdbeChangeP3(v, base+3, pIndex->zName, 0);
   821         -      sqliteVdbeChangeP3(v, base+4, pTab->zName, 0);
   822         -      sqliteVdbeIndexRootAddr(v, &pIndex->tnum);
   823         -      sqliteVdbeChangeP3(v, base+7, pIndex->zName, 0);
   824         -      sqliteVdbeChangeP3(v, base+9, pStart->z, n);
   825         -      changeCookie(db);
   826         -      sqliteVdbeChangeP1(v, base+12, db->next_cookie);
   827         -    }
   828         -    sqliteVdbeAddOp(v, OP_Open, 0, pTab->tnum, pTab->zName, 0);
   829         -    lbl1 = sqliteVdbeMakeLabel(v);
   830         -    lbl2 = sqliteVdbeMakeLabel(v);
   831         -    sqliteVdbeAddOp(v, OP_Rewind, 0, 0, 0, 0);
   832         -    sqliteVdbeAddOp(v, OP_Next, 0, lbl2, 0, lbl1);
   833         -    sqliteVdbeAddOp(v, OP_Recno, 0, 0, 0, 0);
   834         -    for(i=0; i<pIndex->nColumn; i++){
   835         -      sqliteVdbeAddOp(v, OP_Column, 0, pIndex->aiColumn[i], 0, 0);
   836         -    }
   837         -    sqliteVdbeAddOp(v, OP_MakeIdxKey, pIndex->nColumn, 0, 0, 0);
   838         -    sqliteVdbeAddOp(v, OP_PutIdx, 1, pIndex->isUnique, 0, 0);
   839         -    sqliteVdbeAddOp(v, OP_Goto, 0, lbl1, 0, 0);
   840         -    sqliteVdbeAddOp(v, OP_Noop, 0, 0, 0, lbl2);
          801  +      addr = sqliteVdbeAddOp(v, OP_String, 0, 0, "", 0);
          802  +      sqliteVdbeChangeP3(v, addr, pStart->z, n);
          803  +    }else{
          804  +      sqliteVdbeAddOp(v, OP_Null, 0, 0, 0, 0);
          805  +    }
          806  +    sqliteVdbeAddOp(v, OP_MakeRecord, 5, 0, 0, 0);
          807  +    sqliteVdbeAddOp(v, OP_Put, 0, 0, 0, 0);
          808  +    if( pTable ){
          809  +      sqliteVdbeAddOp(v, OP_Open, 2, pTab->tnum, pTab->zName, 0);
          810  +      lbl1 = sqliteVdbeMakeLabel(v);
          811  +      lbl2 = sqliteVdbeMakeLabel(v);
          812  +      sqliteVdbeAddOp(v, OP_Rewind, 2, 0, 0, 0);
          813  +      sqliteVdbeAddOp(v, OP_Next, 2, lbl2, 0, lbl1);
          814  +      sqliteVdbeAddOp(v, OP_Recno, 2, 0, 0, 0);
          815  +      for(i=0; i<pIndex->nColumn; i++){
          816  +        sqliteVdbeAddOp(v, OP_Column, 2, pIndex->aiColumn[i], 0, 0);
          817  +      }
          818  +      sqliteVdbeAddOp(v, OP_MakeIdxKey, pIndex->nColumn, 0, 0, 0);
          819  +      sqliteVdbeAddOp(v, OP_PutIdx, 1, pIndex->isUnique, 0, 0);
          820  +      sqliteVdbeAddOp(v, OP_Goto, 0, lbl1, 0, 0);
          821  +      sqliteVdbeAddOp(v, OP_Noop, 0, 0, 0, lbl2);
          822  +      sqliteVdbeAddOp(v, OP_Close, 2, 0, 0, 0);
          823  +    }
   841    824       sqliteVdbeAddOp(v, OP_Close, 1, 0, 0, 0);
   842         -    sqliteVdbeAddOp(v, OP_Close, 0, 0, 0, 0);
   843         -    if( pTable!=0 && (db->flags & SQLITE_InTrans)==0 ){
   844         -      sqliteVdbeAddOp(v, OP_Commit, 0, 0, 0, 0);
          825  +    if( pTable!=0 ){
          826  +      changeCookie(db);
          827  +      sqliteVdbeAddOp(v, OP_SetCookie, db->next_cookie, 0, 0, 0);
          828  +      sqliteVdbeAddOp(v, OP_Close, 0, 0, 0, 0);
          829  +      if( (db->flags & SQLITE_InTrans)==0 ){
          830  +        sqliteVdbeAddOp(v, OP_Commit, 0, 0, 0, 0);
          831  +      }
   845    832       }
   846    833     }
   847    834   
   848         -  /* Reclaim memory on an EXPLAIN call.
   849         -  */
   850         -  if( pParse->explain ){
   851         -    sqliteFree(pIndex);
   852         -  }
   853         -
   854    835     /* Clean up before exiting */
   855    836   exit_create_index:
   856    837     sqliteIdListDelete(pList);
   857    838     sqliteFree(zName);
   858    839     return;
   859    840   }
   860    841   

Changes to src/main.c.

    10     10   **
    11     11   *************************************************************************
    12     12   ** Main file for the SQLite library.  The routines in this file
    13     13   ** implement the programmer interface to the library.  Routines in
    14     14   ** other files are for internal use by SQLite and should not be
    15     15   ** accessed by users of the library.
    16     16   **
    17         -** $Id: main.c,v 1.41 2001/09/23 20:17:55 drh Exp $
           17  +** $Id: main.c,v 1.42 2001/09/27 15:11:54 drh Exp $
    18     18   */
    19     19   #include "sqliteInt.h"
    20     20   #include "os.h"
    21     21   
    22     22   /*
    23     23   ** This is the callback routine for the code that initializes the
    24     24   ** database.  Each callback contains the following information:
    25     25   **
    26     26   **     argv[0] = "meta" or "table" or "index"
    27     27   **     argv[1] = table or index name or meta statement type.
    28     28   **     argv[2] = root page number for table or index.  NULL for meta.
    29         -**     argv[3] = root page number of primary key for tables or NULL.
    30         -**     argv[4] = SQL create statement for the table or index
           29  +**     argv[3] = SQL create statement for the table or index
    31     30   **
    32     31   */
    33     32   static int sqliteOpenCb(void *pDb, int argc, char **argv, char **azColName){
    34     33     sqlite *db = (sqlite*)pDb;
    35     34     Parse sParse;
    36     35     int nErr = 0;
    37     36   
    38     37   /* TODO: Do some validity checks on all fields.  In particular,
    39     38   ** make sure fields do not contain NULLs. */
    40     39   
    41         -  assert( argc==5 );
           40  +  assert( argc==4 );
    42     41     switch( argv[0][0] ){
    43     42       case 'm': {  /* Meta information */
    44     43         if( strcmp(argv[1],"file-format")==0 ){
    45         -        db->file_format = atoi(argv[4]);
           44  +        db->file_format = atoi(argv[3]);
    46     45         }else if( strcmp(argv[1],"schema-cookie")==0 ){
    47         -        db->schema_cookie = atoi(argv[4]);
           46  +        db->schema_cookie = atoi(argv[3]);
    48     47           db->next_cookie = db->schema_cookie;
    49     48         }
    50     49         break;
    51     50       }
    52     51       case 'i':
    53     52       case 't': {  /* CREATE TABLE  and CREATE INDEX statements */
    54         -      memset(&sParse, 0, sizeof(sParse));
    55         -      sParse.db = db;
    56         -      sParse.initFlag = 1;
    57         -      sParse.newTnum = atoi(argv[2]);
    58         -      sParse.newKnum = argv[3] ? atoi(argv[3]) : 0;
    59         -      nErr = sqliteRunParser(&sParse, argv[4], 0);
           53  +      if( argv[3] && argv[3][0] ){
           54  +        memset(&sParse, 0, sizeof(sParse));
           55  +        sParse.db = db;
           56  +        sParse.initFlag = 1;
           57  +        sParse.newTnum = atoi(argv[2]);
           58  +        nErr = sqliteRunParser(&sParse, argv[3], 0);
           59  +      }else{
           60  +        Index *pIndex = sqliteFindIndex(db, argv[1]);
           61  +        if( pIndex==0 || pIndex->tnum!=0 ){
           62  +          nErr++;
           63  +        }else{
           64  +          pIndex->tnum = atoi(argv[2]);
           65  +        }
           66  +      }
    60     67         break;
    61     68       }
    62     69       default: {
    63     70         /* This can not happen! */
    64     71         nErr = 1;
    65     72         assert( nErr==0 );
    66     73       }
................................................................................
    88     95     ** The master database table has a structure like this
    89     96     */
    90     97     static char master_schema[] = 
    91     98        "CREATE TABLE " MASTER_NAME " (\n"
    92     99        "  type text,\n"
    93    100        "  name text,\n"
    94    101        "  tbl_name text,\n"
    95         -     "  tnum integer,\n"
    96         -     "  knum integer,\n"
          102  +     "  rootpage integer,\n"
    97    103        "  sql text\n"
    98    104        ")"
    99    105     ;
   100    106   
   101    107     /* The following program is used to initialize the internal
   102    108     ** structure holding the tables and indexes of the database.
   103    109     ** The database contains a special table named "sqlite_master"
   104    110     ** defined as follows:
   105    111     **
   106    112     **    CREATE TABLE sqlite_master (
   107    113     **        type       text,    --  Either "table" or "index" or "meta"
   108    114     **        name       text,    --  Name of table or index
   109    115     **        tbl_name   text,    --  Associated table 
   110         -  **        tnum       integer, --  The integer page number of root page
   111         -  **        knum       integer, --  Root page of primary key, or NULL
          116  +  **        rootpage   integer, --  The integer page number of root page
   112    117     **        sql        text     --  The CREATE statement for this object
   113    118     **    );
   114    119     **
   115    120     ** The sqlite_master table contains a single entry for each table
   116    121     ** and each index.  The "type" column tells whether the entry is
   117    122     ** a table or index.  The "name" column is the name of the object.
   118    123     ** The "tbl_name" is the name of the associated table.  For tables,
................................................................................
   132    137     ** SQL for each index.  The callback will invoke the
   133    138     ** parser to build the internal representation of the
   134    139     ** database scheme.
   135    140     */
   136    141     static VdbeOp initProg[] = {
   137    142       { OP_Open,     0, 2,  0},
   138    143       { OP_Rewind,   0, 0,  0},
   139         -    { OP_Next,     0, 13, 0},           /* 2 */
          144  +    { OP_Next,     0, 12, 0},           /* 2 */
   140    145       { OP_Column,   0, 0,  0},
   141    146       { OP_String,   0, 0,  "meta"},
   142    147       { OP_Ne,       0, 2,  0},
   143    148       { OP_Column,   0, 0,  0},
   144    149       { OP_Column,   0, 1,  0},
   145    150       { OP_Column,   0, 3,  0},
   146         -    { OP_Null,     0, 0,  0},
   147         -    { OP_Column,   0, 5,  0},
   148         -    { OP_Callback, 5, 0,  0},
          151  +    { OP_Column,   0, 4,  0},
          152  +    { OP_Callback, 4, 0,  0},
   149    153       { OP_Goto,     0, 2,  0},
   150         -    { OP_Rewind,   0, 0,  0},           /* 13 */
   151         -    { OP_Next,     0, 25, 0},           /* 14 */
          154  +    { OP_Rewind,   0, 0,  0},           /* 12 */
          155  +    { OP_Next,     0, 23, 0},           /* 13 */
   152    156       { OP_Column,   0, 0,  0},
   153    157       { OP_String,   0, 0,  "table"},
   154         -    { OP_Ne,       0, 14, 0},
          158  +    { OP_Ne,       0, 13, 0},
          159  +    { OP_Column,   0, 0,  0},
          160  +    { OP_Column,   0, 1,  0},
          161  +    { OP_Column,   0, 3,  0},
          162  +    { OP_Column,   0, 4,  0},
          163  +    { OP_Callback, 4, 0,  0},
          164  +    { OP_Goto,     0, 13, 0},
          165  +    { OP_Rewind,   0, 0,  0},           /* 23 */
          166  +    { OP_Next,     0, 34, 0},           /* 24 */
          167  +    { OP_Column,   0, 0,  0},
          168  +    { OP_String,   0, 0,  "index"},
          169  +    { OP_Ne,       0, 24, 0},
   155    170       { OP_Column,   0, 0,  0},
   156    171       { OP_Column,   0, 1,  0},
   157    172       { OP_Column,   0, 3,  0},
   158    173       { OP_Column,   0, 4,  0},
   159         -    { OP_Column,   0, 5,  0},
   160         -    { OP_Callback, 5, 0,  0},
   161         -    { OP_Goto,     0, 14, 0},
   162         -    { OP_Rewind,   0, 0,  0},           /* 25 */
   163         -    { OP_Next,     0, 37, 0},           /* 26 */
   164         -    { OP_Column,   0, 0,  0},
   165         -    { OP_String,   0, 0,  "index"},
   166         -    { OP_Ne,       0, 26, 0},
   167         -    { OP_Column,   0, 0,  0},
   168         -    { OP_Column,   0, 1,  0},
   169         -    { OP_Column,   0, 3,  0},
   170         -    { OP_Null,     0, 0,  0},
   171         -    { OP_Column,   0, 5,  0},
   172         -    { OP_Callback, 5, 0,  0},
   173         -    { OP_Goto,     0, 26, 0},
   174         -    { OP_String,   0, 0,  "meta"},      /* 37 */
          174  +    { OP_Callback, 4, 0,  0},
          175  +    { OP_Goto,     0, 24, 0},
          176  +    { OP_String,   0, 0,  "meta"},      /* 34 */
   175    177       { OP_String,   0, 0,  "schema-cookie"},
   176    178       { OP_Null,     0, 0,  0},
   177         -    { OP_Null,     0, 0,  0},
   178    179       { OP_ReadCookie,0,0,  0},
   179         -    { OP_Callback, 5, 0,  0},
          180  +    { OP_Callback, 4, 0,  0},
   180    181       { OP_Close,    0, 0,  0},
   181    182       { OP_Halt,     0, 0,  0},
   182    183     };
   183    184   
   184    185     /* Create a virtual machine to run the initialization program.  Run
   185    186     ** the program.  The delete the virtual machine.
   186    187     */
................................................................................
   199    200     }
   200    201     if( rc==SQLITE_OK ){
   201    202       Table *pTab;
   202    203       char *azArg[6];
   203    204       azArg[0] = "table";
   204    205       azArg[1] = MASTER_NAME;
   205    206       azArg[2] = "2";
   206         -    azArg[3] = 0;
   207         -    azArg[4] = master_schema;
   208         -    azArg[5] = 0;
   209         -    sqliteOpenCb(db, 5, azArg, 0);
          207  +    azArg[3] = master_schema;
          208  +    azArg[4] = 0;
          209  +    sqliteOpenCb(db, 4, azArg, 0);
   210    210       pTab = sqliteFindTable(db, MASTER_NAME);
   211    211       if( pTab ){
   212    212         pTab->readOnly = 1;
   213    213       }
   214    214       db->flags |= SQLITE_Initialized;
   215    215       sqliteCommitInternalChanges(db);
   216    216     }

Changes to src/parse.y.

    10     10   **
    11     11   *************************************************************************
    12     12   ** This file contains SQLite's grammar for SQL.  Process this file
    13     13   ** using the lemon parser generator to generate C code that runs
    14     14   ** the parser.  Lemon will also generate a header file containing
    15     15   ** numeric codes for all of the tokens.
    16     16   **
    17         -** @(#) $Id: parse.y,v 1.31 2001/09/27 03:22:33 drh Exp $
           17  +** @(#) $Id: parse.y,v 1.32 2001/09/27 15:11:54 drh Exp $
    18     18   */
    19     19   %token_prefix TK_
    20     20   %token_type {Token}
    21     21   %default_type {Token}
    22     22   %extra_argument {Parse *pParse}
    23     23   %syntax_error {
    24     24     sqliteSetString(&pParse->zErrMsg,"syntax error",0);
................................................................................
   121    121   carg ::= DEFAULT MINUS FLOAT(X).     {sqliteAddDefaultValue(pParse,&X,1);}
   122    122   carg ::= DEFAULT NULL. 
   123    123   
   124    124   // In addition to the type name, we also care about the primary key.
   125    125   //
   126    126   ccons ::= NOT NULL.
   127    127   ccons ::= PRIMARY KEY sortorder.     {sqliteCreateIndex(pParse,0,0,0,1,0,0);}
   128         -ccons ::= UNIQUE.
          128  +ccons ::= UNIQUE.                    {sqliteCreateIndex(pParse,0,0,0,1,0,0);}
   129    129   ccons ::= CHECK LP expr RP.
   130    130   
   131    131   // For the time being, the only constraint we care about is the primary
   132    132   // key.
   133    133   //
   134    134   conslist_opt ::= .
   135    135   conslist_opt ::= COMMA conslist.
   136    136   conslist ::= conslist COMMA tcons.
   137    137   conslist ::= conslist tcons.
   138    138   conslist ::= tcons.
   139    139   tcons ::= CONSTRAINT ids.
   140    140   tcons ::= PRIMARY KEY LP idxlist(X) RP. {sqliteCreateIndex(pParse,0,0,X,1,0,0);}
   141         -tcons ::= UNIQUE LP idlist RP.
          141  +tcons ::= UNIQUE LP idxlist(X) RP.      {sqliteCreateIndex(pParse,0,0,X,1,0,0);}
   142    142   tcons ::= CHECK expr.
   143         -idlist ::= idlist COMMA ids.
   144         -idlist ::= ids.
          143  +// idlist ::= idlist COMMA ids.
          144  +// idlist ::= ids.
   145    145   
   146    146   // The next command format is dropping tables.
   147    147   //
   148    148   cmd ::= DROP TABLE ids(X).          {sqliteDropTable(pParse,&X);}
   149    149   
   150    150   // The select statement
   151    151   //

Changes to src/shell.c.

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

Changes to src/sqliteInt.h.

     7      7   **    May you do good and not evil.
     8      8   **    May you find forgiveness for yourself and forgive others.
     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12     12   ** Internal interface definitions for SQLite.
    13     13   **
    14         -** @(#) $Id: sqliteInt.h,v 1.55 2001/09/27 03:22:33 drh Exp $
           14  +** @(#) $Id: sqliteInt.h,v 1.56 2001/09/27 15:11:54 drh Exp $
    15     15   */
    16     16   #include "sqlite.h"
    17     17   #include "hash.h"
    18     18   #include "vdbe.h"
    19     19   #include "parse.h"
    20     20   #include "btree.h"
    21     21   #include <stdio.h>
................................................................................
   440    440   void sqliteUpdate(Parse*, Token*, ExprList*, Expr*);
   441    441   WhereInfo *sqliteWhereBegin(Parse*, IdList*, Expr*, int);
   442    442   void sqliteWhereEnd(WhereInfo*);
   443    443   void sqliteExprCode(Parse*, Expr*);
   444    444   void sqliteExprIfTrue(Parse*, Expr*, int);
   445    445   void sqliteExprIfFalse(Parse*, Expr*, int);
   446    446   Table *sqliteFindTable(sqlite*,char*);
          447  +Index *sqliteFindIndex(sqlite*,char*);
   447    448   void sqliteCopy(Parse*, Token*, Token*, Token*);
   448    449   void sqliteVacuum(Parse*, Token*);
   449    450   int sqliteGlobCompare(const unsigned char*,const unsigned char*);
   450    451   int sqliteLikeCompare(const unsigned char*,const unsigned char*);
   451    452   char *sqliteTableNameFromToken(Token*);
   452    453   int sqliteExprCheck(Parse*, Expr*, int, int*);
   453    454   int sqliteExprCompare(Expr*, Expr*);

Changes to src/vdbe.c.

    26     26   ** type to the other occurs as necessary.
    27     27   ** 
    28     28   ** Most of the code in this file is taken up by the sqliteVdbeExec()
    29     29   ** function which does the work of interpreting a VDBE program.
    30     30   ** But other routines are also provided to help in building up
    31     31   ** a program instruction by instruction.
    32     32   **
    33         -** $Id: vdbe.c,v 1.78 2001/09/27 03:22:34 drh Exp $
           33  +** $Id: vdbe.c,v 1.79 2001/09/27 15:11:54 drh Exp $
    34     34   */
    35     35   #include "sqliteInt.h"
    36     36   #include <ctype.h>
    37     37   #include <unistd.h>
    38     38   
    39     39   /*
    40     40   ** SQL is translated into a sequence of instructions to be
................................................................................
   198    198     char *zLine;        /* A single line from the input file */
   199    199     int nLineAlloc;     /* Number of spaces allocated for zLine */
   200    200     int nMem;           /* Number of memory locations currently allocated */
   201    201     Mem *aMem;          /* The memory locations */
   202    202     Agg agg;            /* Aggregate information */
   203    203     int nSet;           /* Number of sets allocated */
   204    204     Set *aSet;          /* An array of sets */
   205         -  int *pTableRoot;    /* Write root page no. for new tables to this addr */
   206         -  int *pIndexRoot;    /* Write root page no. for new indices to this addr */
   207    205     int nFetch;         /* Number of OP_Fetch instructions executed */
   208    206   };
   209    207   
   210    208   /*
   211    209   ** Create a new virtual database engine.
   212    210   */
   213    211   Vdbe *sqliteVdbeCreate(sqlite *db){
................................................................................
   222    220   /*
   223    221   ** Turn tracing on or off
   224    222   */
   225    223   void sqliteVdbeTrace(Vdbe *p, FILE *trace){
   226    224     p->trace = trace;
   227    225   }
   228    226   
   229         -/*
   230         -** Cause the next OP_CreateTable or OP_CreateIndex instruction that executes
   231         -** to write the page number of the root page for the new table or index it
   232         -** creates into the memory location *pAddr.
   233         -**
   234         -** The pointer to the place to write the page number is cleared after
   235         -** the OP_Create* statement.  If OP_Create* is executed and the pointer
   236         -** is NULL, an error results.  Hence the address can only be used once.
   237         -** If the root address fields are set but OP_Create* operations never
   238         -** execute, that too is an error.
   239         -*/
   240         -void sqliteVdbeTableRootAddr(Vdbe *p, int *pAddr){
   241         -  p->pTableRoot = pAddr;
   242         -}
   243         -void sqliteVdbeIndexRootAddr(Vdbe *p, int *pAddr){
   244         -  p->pIndexRoot = pAddr;
   245         -}
   246         -
   247    227   /*
   248    228   ** Add a new instruction to the list of instructions current in the
   249    229   ** VDBE.  Return the address of the new instruction.
   250    230   **
   251    231   ** Parameters:
   252    232   **
   253    233   **    p               Pointer to the VDBE
................................................................................
   284    264     p->aOp[i].p1 = p1;
   285    265     if( p2<0 && (-1-p2)<p->nLabel && p->aLabel[-1-p2]>=0 ){
   286    266       p2 = p->aLabel[-1-p2];
   287    267     }
   288    268     p->aOp[i].p2 = p2;
   289    269     if( p3 && p3[0] ){
   290    270       p->aOp[i].p3 = sqliteStrDup(p3);
          271  +    p->aOp[i].p3dyn = 1;
   291    272     }else{
   292    273       p->aOp[i].p3 = 0;
   293    274     }
   294    275     if( lbl<0 && (-lbl)<=p->nLabel ){
   295    276       p->aLabel[-1-lbl] = i;
   296    277       for(j=0; j<i; j++){
   297    278         if( p->aOp[j].p2==lbl ) p->aOp[j].p2 = i;
................................................................................
   363    344   }
   364    345   
   365    346   /*
   366    347   ** Change the value of the P3 operand for a specific instruction.
   367    348   ** This routine is useful when a large program is loaded from a
   368    349   ** static array using sqliteVdbeAddOpList but we want to make a
   369    350   ** few minor changes to the program.
          351  +**
          352  +** If n>=0 then the P3 operand is dynamic, meaning that a copy of
          353  +** the string is made into memory obtained from sqliteMalloc().
          354  +** A value of n==0 means copy bytes of zP3 up to and including the
          355  +** first null byte.  If n>0 then copy n+1 bytes of zP3.
          356  +**
          357  +** If n<0 then zP3 is assumed to be a pointer to a static string.
          358  +** P3 is made to point directly to this string without any copying.
   370    359   */
   371         -void sqliteVdbeChangeP3(Vdbe *p, int addr, const char *zP3, int n){
          360  +void sqliteVdbeChangeP3(Vdbe *p, int addr, char *zP3, int n){
   372    361     if( p && addr>=0 && p->nOp>addr && zP3 ){
   373         -    sqliteSetNString(&p->aOp[addr].p3, zP3, n, 0);
          362  +    Op *pOp = &p->aOp[addr];
          363  +    if( pOp->p3 && pOp->p3dyn ){
          364  +      sqliteFree(pOp->p3);
          365  +    }
          366  +    if( n<0 ){
          367  +      pOp->p3 = zP3;
          368  +      pOp->p3dyn = 0;
          369  +    }else{
          370  +      sqliteSetNString(&p->aOp[addr].p3, zP3, n, 0);
          371  +      pOp->p3dyn = 1;
          372  +    }
   374    373     }
   375    374   }
   376    375   
   377    376   /*
   378    377   ** If the P3 operand to the specified instruction appears
   379    378   ** to be a quoted string token, then this procedure removes 
   380    379   ** the quotes.
   381    380   **
   382    381   ** The quoting operator can be either a grave ascent (ASCII 0x27)
   383    382   ** or a double quote character (ASCII 0x22).  Two quotes in a row
   384    383   ** resolve to be a single actual quote character within the string.
   385    384   */
   386    385   void sqliteVdbeDequoteP3(Vdbe *p, int addr){
   387         -  char *z;
          386  +  Op *pOp;
   388    387     if( addr<0 || addr>=p->nOp ) return;
   389         -  z = p->aOp[addr].p3;
   390         -  if( z ) sqliteDequote(z);
          388  +  pOp = &p->aOp[addr];
          389  +  if( pOp->p3==0 || pOp->p3[0]==0 ) return;
          390  +  if( !pOp->p3dyn ){
          391  +    pOp->p3 = sqliteStrDup(pOp->p3);
          392  +    pOp->p3dyn = 1;
          393  +  }
          394  +  if( pOp->p3 ) sqliteDequote(pOp->p3);
   391    395   }
   392    396   
   393    397   /*
   394    398   ** On the P3 argument of the given instruction, change all
   395    399   ** strings of whitespace characters into a single space and
   396    400   ** delete leading and trailing whitespace.
   397    401   */
   398    402   void sqliteVdbeCompressSpace(Vdbe *p, int addr){
   399    403     char *z;
   400    404     int i, j;
          405  +  Op *pOp;
   401    406     if( addr<0 || addr>=p->nOp ) return;
   402         -  z = p->aOp[addr].p3;
          407  +  pOp = &p->aOp[addr];
          408  +  if( !pOp->p3dyn ){
          409  +    pOp->p3 = sqliteStrDup(pOp->p3);
          410  +    pOp->p3dyn = 1;
          411  +  }
          412  +  z = pOp->p3;
   403    413     if( z==0 ) return;
   404    414     i = j = 0;
   405    415     while( isspace(z[i]) ){ i++; }
   406    416     while( z[i] ){
   407    417       if( isspace(z[i]) ){
   408    418         z[j++] = ' ';
   409    419         while( isspace(z[++i]) ){}
................................................................................
   743    753     AggReset(&p->agg);
   744    754     for(i=0; i<p->nSet; i++){
   745    755       sqliteHashClear(&p->aSet[i].hash);
   746    756     }
   747    757     sqliteFree(p->aSet);
   748    758     p->aSet = 0;
   749    759     p->nSet = 0;
   750         -  p->pTableRoot = 0;
   751         -  p->pIndexRoot = 0;
   752    760   }
   753    761   
   754    762   /*
   755    763   ** Delete an entire VDBE.
   756    764   */
   757    765   void sqliteVdbeDelete(Vdbe *p){
   758    766     int i;
................................................................................
   759    767     if( p==0 ) return;
   760    768     Cleanup(p);
   761    769     if( p->nOpAlloc==0 ){
   762    770       p->aOp = 0;
   763    771       p->nOp = 0;
   764    772     }
   765    773     for(i=0; i<p->nOp; i++){
   766         -    sqliteFree(p->aOp[i].p3);
          774  +    if( p->aOp[i].p3dyn ){
          775  +      sqliteFree(p->aOp[i].p3);
          776  +    }
   767    777     }
   768    778     sqliteFree(p->aOp);
   769    779     sqliteFree(p->aLabel);
   770    780     sqliteFree(p->aStack);
   771    781     sqliteFree(p->zStack);
   772    782     sqliteFree(p);
   773    783   }
................................................................................
  2614   2624     int res, rx;
  2615   2625     Cursor *pCrsr;
  2616   2626     VERIFY( if( tos<0 ) goto not_enough_stack; )
  2617   2627     if( i>=0 && i<p->nCursor && (pCrsr = &p->aCsr[i])->pCursor!=0 ){
  2618   2628       if( Stringify(p, tos) ) goto no_mem;
  2619   2629       if( pCrsr->zKey ) sqliteFree(pCrsr->zKey);
  2620   2630       pCrsr->nKey = aStack[tos].n;
  2621         -    pCrsr->zKey = sqliteMalloc( pCrsr->nKey );
         2631  +    pCrsr->zKey = sqliteMalloc( pCrsr->nKey+1 );
  2622   2632       if( pCrsr->zKey==0 ) goto no_mem;
  2623   2633       memcpy(pCrsr->zKey, zStack[tos], aStack[tos].n);
  2624   2634       pCrsr->zKey[aStack[tos].n] = 0;
  2625   2635       rx = sqliteBtreeMoveto(pCrsr->pCursor, zStack[tos], aStack[tos].n, &res);
  2626   2636       pCrsr->atFirst = rx==SQLITE_OK && res>0;
  2627   2637       pCrsr->recnoIsValid = 0;
  2628   2638     }
................................................................................
  2770   2780   ** See also: Destroy
  2771   2781   */
  2772   2782   case OP_Clear: {
  2773   2783     sqliteBtreeClearTable(pBt, pOp->p1);
  2774   2784     break;
  2775   2785   }
  2776   2786   
  2777         -/* Opcode: CreateTable * * *
         2787  +/* Opcode: CreateTable * * P3
  2778   2788   **
  2779   2789   ** Allocate a new table in the main database file.  Push the page number
  2780   2790   ** for the root page of the new table onto the stack.
  2781   2791   **
  2782         -** The root page number is also written to a memory location which has
  2783         -** be set up by the parser.  The difference between CreateTable and
  2784         -** CreateIndex is that each writes its root page number into a different
  2785         -** memory location.  This writing of the page number into a memory location
  2786         -** is used by the SQL parser to record the page number in its internal
  2787         -** data structures.
         2792  +** The root page number is also written to a memory location that P3
         2793  +** points to.  This is the mechanism is used to write the root page
         2794  +** number into the parser's internal data structures that describe the
         2795  +** new table.
  2788   2796   **
  2789   2797   ** See also: CreateIndex
  2790   2798   */
  2791   2799   case OP_CreateTable: {
  2792   2800     int i = ++p->tos;
  2793   2801     int pgno;
  2794   2802     VERIFY( if( NeedStack(p, p->tos) ) goto no_mem; )
  2795         -  if( p->pTableRoot==0 ){
  2796         -    rc = SQLITE_INTERNAL;
  2797         -    goto abort_due_to_error;
  2798         -  }
         2803  +  assert( pOp->p3!=0 && pOp->p3dyn==0 );
  2799   2804     rc = sqliteBtreeCreateTable(pBt, &pgno);
  2800   2805     if( rc==SQLITE_OK ){
  2801   2806       aStack[i].i = pgno;
  2802   2807       aStack[i].flags = STK_Int;
  2803         -    *p->pTableRoot = pgno;
  2804         -    p->pTableRoot = 0;
         2808  +    *(u32*)pOp->p3 = pgno;
         2809  +    pOp->p3 = 0;
  2805   2810     }
  2806   2811     break;
  2807   2812   }
  2808   2813   
  2809         -/* Opcode: CreateIndex P1 * *
         2814  +/* Opcode: CreateIndex * * P3
  2810   2815   **
  2811   2816   ** Allocate a new Index in the main database file.  Push the page number
  2812   2817   ** for the root page of the new table onto the stack.
  2813   2818   **
  2814         -** The root page number is also written to a memory location which has
  2815         -** be set up by the parser.  The difference between CreateTable and
  2816         -** CreateIndex is that each writes its root page number into a different
  2817         -** memory location.  This writing of the page number into a memory location
  2818         -** is used by the SQL parser to record the page number in its internal
  2819         -** data structures.
         2819  +** The root page number is also written to a memory location that P3
         2820  +** points to.  This is the mechanism is used to write the root page
         2821  +** number into the parser's internal data structures that describe the
         2822  +** new index.
  2820   2823   **
  2821   2824   ** See also: CreateTable
  2822   2825   */
  2823   2826   case OP_CreateIndex: {
  2824   2827     int i = ++p->tos;
  2825   2828     int pgno;
  2826   2829     VERIFY( if( NeedStack(p, p->tos) ) goto no_mem; )
  2827         -  if( p->pIndexRoot==0 ){
  2828         -    rc = SQLITE_INTERNAL;
  2829         -    goto abort_due_to_error;
  2830         -  }
         2830  +  assert( pOp->p3!=0 && pOp->p3dyn==0 );
  2831   2831     rc = sqliteBtreeCreateTable(pBt, &pgno);
  2832   2832     if( rc==SQLITE_OK ){
  2833   2833       aStack[i].i = pgno;
  2834   2834       aStack[i].flags = STK_Int;
  2835         -    *p->pIndexRoot = pgno;
  2836         -    p->pIndexRoot = 0;
         2835  +    *(u32*)pOp->p3 = pgno;
         2836  +    pOp->p3 = 0;
  2837   2837     }
  2838   2838     break;
  2839   2839   }
  2840   2840   
  2841   2841   /* Opcode: Reorganize P1 * *
  2842   2842   **
  2843   2843   ** Compress, optimize, and tidy up table or index whose root page in the
................................................................................
  3861   3861         fprintf(p->trace,"\n");
  3862   3862       }
  3863   3863   #endif
  3864   3864     }
  3865   3865   
  3866   3866   cleanup:
  3867   3867     Cleanup(p);
  3868         -  if( (p->pTableRoot || p->pIndexRoot) && rc==SQLITE_OK ){
  3869         -    rc = SQLITE_INTERNAL;
  3870         -    sqliteSetString(pzErrMsg, "table or index root page not set", 0);
  3871         -  }
  3872   3868     if( rc!=SQLITE_OK ){
  3873   3869       closeAllCursors(p);
  3874   3870       sqliteBtreeRollback(pBt);
  3875   3871       sqliteRollbackInternalChanges(db);
  3876   3872       db->flags &= ~SQLITE_InTrans;
  3877   3873     }
  3878   3874     return rc;

Changes to src/vdbe.h.

    11     11   *************************************************************************
    12     12   ** Header file for the Virtual DataBase Engine (VDBE)
    13     13   **
    14     14   ** This header defines the interface to the virtual database engine
    15     15   ** or VDBE.  The VDBE implements an abstract machine that runs a
    16     16   ** simple program to access and modify the underlying database.
    17     17   **
    18         -** $Id: vdbe.h,v 1.24 2001/09/23 02:35:53 drh Exp $
           18  +** $Id: vdbe.h,v 1.25 2001/09/27 15:11:55 drh Exp $
    19     19   */
    20     20   #ifndef _SQLITE_VDBE_H_
    21     21   #define _SQLITE_VDBE_H_
    22     22   #include <stdio.h>
    23     23   
    24     24   /*
    25     25   ** A single VDBE is an opaque structure named "Vdbe".  Only routines
................................................................................
    34     34   ** as an instance of the following structure:
    35     35   */
    36     36   struct VdbeOp {
    37     37     int opcode;         /* What operation to perform */
    38     38     int p1;             /* First operand */
    39     39     int p2;             /* Second parameter (often the jump destination) */
    40     40     char *p3;           /* Third parameter */
           41  +  int p3dyn;          /* True if p3 is malloced.  False if it is static */
    41     42   };
    42     43   typedef struct VdbeOp VdbeOp;
    43     44   
    44     45   /*
    45     46   ** The following macro converts a relative address in the p2 field
    46     47   ** of a VdbeOp structure into a negative number so that 
    47     48   ** sqliteVdbeAddOpList() knows that the address is relative.  Calling
................................................................................
   183    184   
   184    185   /*
   185    186   ** Prototypes for the VDBE interface.  See comments on the implementation
   186    187   ** for a description of what each of these routines does.
   187    188   */
   188    189   Vdbe *sqliteVdbeCreate(sqlite*);
   189    190   void sqliteVdbeCreateCallback(Vdbe*, int*);
   190         -void sqliteVdbeTableRootAddr(Vdbe*, int*);
   191         -void sqliteVdbeIndexRootAddr(Vdbe*, int*);
   192    191   int sqliteVdbeAddOp(Vdbe*,int,int,int,const char*,int);
   193    192   int sqliteVdbeAddOpList(Vdbe*, int nOp, VdbeOp const *aOp);
   194    193   void sqliteVdbeChangeP1(Vdbe*, int addr, int P1);
   195         -void sqliteVdbeChangeP3(Vdbe*, int addr, const char *zP1, int N);
          194  +void sqliteVdbeChangeP3(Vdbe*, int addr, char *zP1, int N);
   196    195   void sqliteVdbeDequoteP3(Vdbe*, int addr);
   197    196   int sqliteVdbeMakeLabel(Vdbe*);
   198    197   void sqliteVdbeDelete(Vdbe*);
   199    198   int sqliteVdbeOpcode(const char *zName);
   200    199   int sqliteVdbeExec(Vdbe*,sqlite_callback,void*,char**,void*,
   201    200                      int(*)(void*,const char*,int));
   202    201   int sqliteVdbeList(Vdbe*,sqlite_callback,void*,char**);
   203    202   void sqliteVdbeResolveLabel(Vdbe*, int);
   204    203   int sqliteVdbeCurrentAddr(Vdbe*);
   205    204   void sqliteVdbeTrace(Vdbe*,FILE*);
   206    205   void sqliteVdbeCompressSpace(Vdbe*,int);
   207    206   
   208    207   #endif

Changes to test/index.test.

     7      7   #    May you find forgiveness for yourself and forgive others.
     8      8   #    May you share freely, never taking more than you give.
     9      9   #
    10     10   #***********************************************************************
    11     11   # This file implements regression tests for SQLite library.  The
    12     12   # focus of this file is testing the CREATE INDEX statement.
    13     13   #
    14         -# $Id: index.test,v 1.13 2001/09/17 20:25:58 drh Exp $
           14  +# $Id: index.test,v 1.14 2001/09/27 15:11:55 drh Exp $
    15     15   
    16     16   set testdir [file dirname $argv0]
    17     17   source $testdir/tester.tcl
    18     18   
    19     19   # Create a basic index and verify it is added to sqlite_master
    20     20   #
    21     21   do_test index-1.1 {
................................................................................
   199    199     }
   200    200     execsql {SELECT count(*) FROM test1}
   201    201   } {19}
   202    202   do_test index-7.2 {
   203    203     execsql {SELECT f1 FROM test1 WHERE f2=65536}
   204    204   } {16}
   205    205   do_test index-7.3 {
   206         -  set code [execsql {EXPLAIN SELECT f1 FROM test1 WHERE f2=65536}]
   207         -  expr {[lsearch $code {test1 (primary key)}]>0}
   208         -} {1}
          206  +  execsql {
          207  +    SELECT name FROM sqlite_master 
          208  +    WHERE type='index' AND tbl_name='test1'
          209  +  }
          210  +} {{(test1 autoindex 1)}}
   209    211   do_test index-7.4 {
   210    212     execsql {DROP table test1}
   211    213     execsql {SELECT name FROM sqlite_master WHERE type!='meta'}
   212    214   } {}
   213    215   
   214    216   # Make sure we cannot drop a non-existant index.
   215    217   #

Changes to test/table.test.

     7      7   #    May you find forgiveness for yourself and forgive others.
     8      8   #    May you share freely, never taking more than you give.
     9      9   #
    10     10   #***********************************************************************
    11     11   # This file implements regression tests for SQLite library.  The
    12     12   # focus of this file is testing the CREATE TABLE statement.
    13     13   #
    14         -# $Id: table.test,v 1.12 2001/09/16 00:13:28 drh Exp $
           14  +# $Id: table.test,v 1.13 2001/09/27 15:11:55 drh Exp $
    15     15   
    16     16   set testdir [file dirname $argv0]
    17     17   source $testdir/tester.tcl
    18     18   
    19     19   # Create a basic table and verify it is added to sqlite_master
    20     20   #
    21     21   do_test table-1.1 {
................................................................................
   159    159     f17 text,
   160    160     f18 text,
   161    161     f19 text,
   162    162     f20 text
   163    163   )}
   164    164   do_test table-3.1 {
   165    165     execsql $big_table
   166         -  execsql {SELECT sql FROM sqlite_master WHERE type!='meta'}
          166  +  execsql {SELECT sql FROM sqlite_master WHERE type=='table'}
   167    167   } \{$big_table\}
   168    168   do_test table-3.2 {
   169    169     set v [catch {execsql {CREATE TABLE BIG(xyz foo)}} msg]
   170    170     lappend v $msg
   171    171   } {1 {table BIG already exists}}
   172    172   do_test table-3.3 {
   173    173     set v [catch {execsql {CREATE TABLE biG(xyz foo)}} msg]

Changes to test/tester.tcl.

     7      7   #    May you find forgiveness for yourself and forgive others.
     8      8   #    May you share freely, never taking more than you give.
     9      9   #
    10     10   #***********************************************************************
    11     11   # This file implements some common TCL routines used for regression
    12     12   # testing the SQLite library
    13     13   #
    14         -# $Id: tester.tcl,v 1.19 2001/09/20 01:44:43 drh Exp $
           14  +# $Id: tester.tcl,v 1.20 2001/09/27 15:11:55 drh Exp $
    15     15   
    16     16   # Make sure tclsqlite was compiled correctly.  Abort now with an
    17     17   # error message if not.
    18     18   #
    19     19   if {[sqlite -tcl-uses-utf]} {
    20     20     if {"\u1234"=="u1234"} {
    21     21       puts stderr "***** BUILD PROBLEM *****"
................................................................................
   169    169   
   170    170   # A procedure to execute SQL
   171    171   #
   172    172   proc execsql {sql {db db}} {
   173    173     # puts "SQL = $sql"
   174    174     return [$db eval $sql]
   175    175   }
          176  +
          177  +# Execute SQL and catch exceptions.
          178  +#
          179  +proc catchsql {sql {db db}} {
          180  +  # puts "SQL = $sql"
          181  +  set r [catch {$db eval $sql} msg]
          182  +  lappend r $msg
          183  +  return $r
          184  +}
   176    185   
   177    186   # Another procedure to execute SQL.  This one includes the field
   178    187   # names in the returned list.
   179    188   #
   180    189   proc execsql2 {sql} {
   181    190     set result {}
   182    191     db eval $sql data {

Added test/unique.test.

            1  +# 2001 September 27
            2  +#
            3  +# The author disclaims copyright to this source code.  In place of
            4  +# a legal notice, here is a blessing:
            5  +#
            6  +#    May you do good and not evil.
            7  +#    May you find forgiveness for yourself and forgive others.
            8  +#    May you share freely, never taking more than you give.
            9  +#
           10  +#***********************************************************************
           11  +# This file implements regression tests for SQLite library.  The
           12  +# focus of this file is testing the CREATE UNIQUE INDEX statement,
           13  +# and primary keys, and the UNIQUE constraint on table columns
           14  +#
           15  +# $Id: unique.test,v 1.1 2001/09/27 15:11:55 drh Exp $
           16  +
           17  +set testdir [file dirname $argv0]
           18  +source $testdir/tester.tcl
           19  +
           20  +# Try to create a table with two primary keys.
           21  +# (This is allowed in SQLite even that it is not valid SQL)
           22  +#
           23  +do_test unique-1.1 {
           24  +  catchsql {
           25  +    CREATE TABLE t1(
           26  +       a int PRIMARY KEY,
           27  +       b int PRIMARY KEY,
           28  +       c text
           29  +    );
           30  +  }
           31  +} {0 {}}
           32  +
           33  +finish_test