SQLite

Check-in [b2a9807fed]
Login

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

Overview
Comment:Change the SQLITE_MASTER format to version 2 in preparation for adding views. (CVS 386)
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: b2a9807fed544e83002366149b9a363759338c5d
User & Date: drh 2002-02-21 12:01:27.000
Context
2002-02-23
02:32
Code to implement CREATE VIEW is in place. A quick smoke test shows that it works, but there are probably still many bugs. (CVS 387) (check-in: 39fed2df11 user: drh tags: trunk)
2002-02-21
12:01
Change the SQLITE_MASTER format to version 2 in preparation for adding views. (CVS 386) (check-in: b2a9807fed user: drh tags: trunk)
02:25
Do not allow dot-commands to occur in the middle of a real SQL command. (CVS 385) (check-in: ffb00bf36a user: drh tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/build.c.
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
**     COPY
**     VACUUM
**     BEGIN TRANSACTION
**     COMMIT
**     ROLLBACK
**     PRAGMA
**
** $Id: build.c,v 1.77 2002/02/19 13:39:22 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 







|







21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
**     COPY
**     VACUUM
**     BEGIN TRANSACTION
**     COMMIT
**     ROLLBACK
**     PRAGMA
**
** $Id: build.c,v 1.78 2002/02/21 12:01:27 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 
469
470
471
472
473
474
475









476
477
478
479
480
481




482
483
484
485
486
487
488
  pTable->nCol = 0;
  pTable->aCol = 0;
  pTable->iPKey = -1;
  pTable->pIndex = 0;
  pTable->isTemp = isTemp;
  if( pParse->pNewTable ) sqliteDeleteTable(db, pParse->pNewTable);
  pParse->pNewTable = pTable;









  if( !pParse->initFlag && (v = sqliteGetVdbe(pParse))!=0 ){
    sqliteBeginWriteOperation(pParse);
    if( !isTemp ){
      sqliteVdbeAddOp(v, OP_SetCookie, db->file_format, 1);
      sqliteVdbeAddOp(v, OP_OpenWrite, 0, 2);
      sqliteVdbeChangeP3(v, -1, MASTER_NAME, P3_STATIC);




    }
  }
}

/*
** Add a new column to the table currently being constructed.
**







>
>
>
>
>
>
>
>
>






>
>
>
>







469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
  pTable->nCol = 0;
  pTable->aCol = 0;
  pTable->iPKey = -1;
  pTable->pIndex = 0;
  pTable->isTemp = isTemp;
  if( pParse->pNewTable ) sqliteDeleteTable(db, pParse->pNewTable);
  pParse->pNewTable = pTable;

  /* Begin generating the code that will insert the table record into
  ** the SQLITE_MASTER table.  Note in particular that we must go ahead
  ** and allocate the record number for the table entry now.  Before any
  ** PRIMARY KEY or UNIQUE keywords are parsed.  Those keywords will cause
  ** indices to be created and the table record must come before the 
  ** indices.  Hence, the record number for the table must be allocated
  ** now.
  */
  if( !pParse->initFlag && (v = sqliteGetVdbe(pParse))!=0 ){
    sqliteBeginWriteOperation(pParse);
    if( !isTemp ){
      sqliteVdbeAddOp(v, OP_SetCookie, db->file_format, 1);
      sqliteVdbeAddOp(v, OP_OpenWrite, 0, 2);
      sqliteVdbeChangeP3(v, -1, MASTER_NAME, P3_STATIC);
      sqliteVdbeAddOp(v, OP_NewRecno, 0, 0);
      sqliteVdbeAddOp(v, OP_Dup, 0, 0);
      sqliteVdbeAddOp(v, OP_String, 0, 0);
      sqliteVdbeAddOp(v, OP_PutIntKey, 0, 0);
    }
  }
}

/*
** Add a new column to the table currently being constructed.
**
653
654
655
656
657
658
659

660
661
662
663
664
665
666
667
668
669
670
671
672





673
674
675
676
677
678
679
680
681
682
683
684
685
/*
** Measure the number of characters needed to output the given
** identifier.  The number returned includes any quotes used
** but does not include the null terminator.
*/
static int identLength(const char *z){
  int n;

  for(n=2; *z; n++, z++){
    if( *z=='\'' ){ n++; }
  }
  return n;
}

/*
** Write an identifier onto the end of the given string.  Add
** quote characters as needed.
*/
static void identPut(char *z, int *pIdx, char *zIdent){
  int i, j;
  i = *pIdx;





  z[i++] = '\'';
  for(j=0; zIdent[j]; j++){
    z[i++] = zIdent[j];
    if( zIdent[j]=='\'' ) z[i++] = '\'';
  }
  z[i++] = '\'';
  z[i] = 0;
  *pIdx = i;
}

/*
** Generate a CREATE TABLE statement appropriate for the given
** table.  Memory to hold the text of the statement is obtained







>
|
|

|







|

>
>
>
>
>
|




|







666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
/*
** Measure the number of characters needed to output the given
** identifier.  The number returned includes any quotes used
** but does not include the null terminator.
*/
static int identLength(const char *z){
  int n;
  int needQuote = 0;
  for(n=0; *z; n++, z++){
    if( *z=='\'' ){ n++; needQuote=1; }
  }
  return n + needQuote*2;
}

/*
** Write an identifier onto the end of the given string.  Add
** quote characters as needed.
*/
static void identPut(char *z, int *pIdx, char *zIdent){
  int i, j, needQuote;
  i = *pIdx;
  for(j=0; zIdent[j]; j++){
    if( !isalnum(zIdent[j]) && zIdent[j]!='_' ) break;
  }
  needQuote =  zIdent[j]!=0 || isdigit(zIdent[0])
                  || sqliteKeywordCode(zIdent, j)!=TK_ID;
  if( needQuote ) z[i++] = '\'';
  for(j=0; zIdent[j]; j++){
    z[i++] = zIdent[j];
    if( zIdent[j]=='\'' ) z[i++] = '\'';
  }
  if( needQuote ) z[i++] = '\'';
  z[i] = 0;
  *pIdx = i;
}

/*
** Generate a CREATE TABLE statement appropriate for the given
** table.  Memory to hold the text of the statement is obtained
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
  }

  /* If the table is generated from a SELECT, then construct the
  ** list of columns and the text of the table.
  */
  if( pSelect ){
    Table *pSelTab = sqliteResultSetOfSelect(pParse, 0, pSelect);

    assert( p->aCol==0 );
    p->nCol = pSelTab->nCol;
    p->aCol = pSelTab->aCol;
    pSelTab->nCol = 0;
    pSelTab->aCol = 0;
    sqliteDeleteTable(0, pSelTab);
  }

  /* 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 root page number for the table from the 
  ** pParse->newTnum field.  (The page number should have been put
  ** there by the sqliteOpenCb routine.)
  */
  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 this is a TEMPORARY table, then just create the table.  Do not
  ** make an entry in SQLITE_MASTER.
  */
  if( !pParse->initFlag ){
    int n, addr;
    Vdbe *v;

    v = sqliteGetVdbe(pParse);
    if( v==0 ) return;
    addr = sqliteVdbeAddOp(v, OP_CreateTable, 0, p->isTemp);
    sqliteVdbeChangeP3(v, addr, (char *)&p->tnum, P3_POINTER);
    p->tnum = 0;
    if( !p->isTemp ){
      sqliteVdbeAddOp(v, OP_NewRecno, 0, 0);
      sqliteVdbeAddOp(v, OP_String, 0, 0);
      sqliteVdbeChangeP3(v, -1, "table", P3_STATIC);
      sqliteVdbeAddOp(v, OP_String, 0, 0);
      sqliteVdbeChangeP3(v, -1, p->zName, P3_STATIC);
      sqliteVdbeAddOp(v, OP_String, 0, 0);
      sqliteVdbeChangeP3(v, -1, p->zName, P3_STATIC);
      sqliteVdbeAddOp(v, OP_Dup, 4, 0);







>



















|
>














|







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
  }

  /* If the table is generated from a SELECT, then construct the
  ** list of columns and the text of the table.
  */
  if( pSelect ){
    Table *pSelTab = sqliteResultSetOfSelect(pParse, 0, pSelect);
    if( pSelTab==0 ) return;
    assert( p->aCol==0 );
    p->nCol = pSelTab->nCol;
    p->aCol = pSelTab->aCol;
    pSelTab->nCol = 0;
    pSelTab->aCol = 0;
    sqliteDeleteTable(0, pSelTab);
  }

  /* 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 root page number for the table from the 
  ** pParse->newTnum field.  (The page number should have been put
  ** there by the sqliteOpenCb routine.)
  */
  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.  The record number
  ** for the new table entry should already be on the stack.
  **
  ** If this is a TEMPORARY table, then just create the table.  Do not
  ** make an entry in SQLITE_MASTER.
  */
  if( !pParse->initFlag ){
    int n, addr;
    Vdbe *v;

    v = sqliteGetVdbe(pParse);
    if( v==0 ) return;
    addr = sqliteVdbeAddOp(v, OP_CreateTable, 0, p->isTemp);
    sqliteVdbeChangeP3(v, addr, (char *)&p->tnum, P3_POINTER);
    p->tnum = 0;
    if( !p->isTemp ){
      sqliteVdbeAddOp(v, OP_Pull, 1, 0);
      sqliteVdbeAddOp(v, OP_String, 0, 0);
      sqliteVdbeChangeP3(v, -1, "table", P3_STATIC);
      sqliteVdbeAddOp(v, OP_String, 0, 0);
      sqliteVdbeChangeP3(v, -1, p->zName, P3_STATIC);
      sqliteVdbeAddOp(v, OP_String, 0, 0);
      sqliteVdbeChangeP3(v, -1, p->zName, P3_STATIC);
      sqliteVdbeAddOp(v, OP_Dup, 4, 0);
Changes to src/main.c.
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
**
*************************************************************************
** 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.60 2002/02/19 22:42:05 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"

/*
** This is the callback routine for the code that initializes the
** database.  See sqliteInit() below for additional information.







|







10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
**
*************************************************************************
** 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.61 2002/02/21 12:01:27 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"

/*
** This is the callback routine for the code that initializes the
** database.  See sqliteInit() below for additional information.
47
48
49
50
51
52
53

54
55
56
57
58
59
60
61
62
63
64
65
66
67
      break;
    }
    case 's': { /* Schema cookie */
      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] ){
        /* Call the parser to process a CREATE TABLE or CREATE INDEX statement.
        ** But because sParse.initFlag is set to 1, no VDBE code is generated
        ** or executed.  All the parser does is build the internal data
        ** structures that describe the table or index.
        */
        memset(&sParse, 0, sizeof(sParse));
        sParse.db = db;
        sParse.initFlag = 1;
        sParse.newTnum = atoi(argv[2]);
        sqliteRunParser(&sParse, argv[3], 0);
      }else{







>

|

|


|







47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
      break;
    }
    case 's': { /* Schema cookie */
      db->schema_cookie = atoi(argv[3]);
      db->next_cookie = db->schema_cookie;
      break;
    }
    case 'v':
    case 'i':
    case 't': {  /* CREATE TABLE, CREATE INDEX, or CREATE VIEW statements */
      if( argv[3] && argv[3][0] ){
        /* Call the parser to process a CREATE TABLE, INDEX or VIEW.
        ** But because sParse.initFlag is set to 1, no VDBE code is generated
        ** or executed.  All the parser does is build the internal data
        ** structures that describe the table, index, or view.
        */
        memset(&sParse, 0, sizeof(sParse));
        sParse.db = db;
        sParse.initFlag = 1;
        sParse.newTnum = atoi(argv[2]);
        sqliteRunParser(&sParse, argv[3], 0);
      }else{
145
146
147
148
149
150
151
152
153
154


155




156
157
158
159
160
161
162
163


164
165
166
167
168
169



170
171
172
173
174














175
176













177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
  ** indexes.  The "rootpage" column holds the number of the root page
  ** for the b-tree for the table or index.  Finally, the "sql" column
  ** contains the complete text of the CREATE TABLE or CREATE INDEX
  ** statement that originally created the table or index.  If an index
  ** was created to fulfill a PRIMARY KEY or UNIQUE constraint on a table,
  ** then the "sql" column is NULL.
  **
  ** If the "type" column has the value "meta", then the "sql" column
  ** contains extra information about the database, such as the
  ** file format version number.  All meta information must be processed


  ** before any tables or indices are constructed.




  **
  ** The following program invokes its callback on the SQL for each
  ** table then goes back and invokes the callback on the
  ** 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_String,     0, 0,  "file-format"},
    { OP_String,     0, 0,  0},
    { OP_String,     0, 0,  0},
    { OP_ReadCookie, 0, 1,  0},
    { OP_Callback,   4, 0,  0},



    { OP_String,     0, 0,  "schema_cookie"},
    { OP_String,     0, 0,  0},
    { OP_String,     0, 0,  0},
    { OP_ReadCookie, 0, 0,  0},
    { OP_Callback,   4, 0,  0},














    { OP_Rewind,     0, 31, 0},
    { OP_Column,     0, 0,  0},           /* 12 */













    { OP_String,     0, 0,  "table"},
    { OP_Ne,         0, 20, 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_Next,       0, 12, 0},           /* 20 */
    { OP_Rewind,     0, 31, 0},           /* 21 */
    { OP_Column,     0, 0,  0},           /* 22 */
    { OP_String,     0, 0,  "index"},
    { OP_Ne,         0, 30, 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_Next,       0, 22, 0},           /* 30 */
    { OP_Close,      0, 0,  0},           /* 31 */
    { OP_Halt,       0, 0,  0},
  };

  /* Create a virtual machine to run the initialization program.  Run
  ** the program.  Then delete the virtual machine.
  */
  vdbe = sqliteVdbeCreate(db);
  if( vdbe==0 ){
    sqliteSetString(pzErrMsg, "out of memory", 0);
    return SQLITE_NOMEM;
  }
  sqliteVdbeAddOpList(vdbe, sizeof(initProg)/sizeof(initProg[0]), initProg);
  rc = sqliteVdbeExec(vdbe, sqliteOpenCb, db, pzErrMsg, 
                      db->pBusyArg, db->xBusyCallback);
  sqliteVdbeDelete(vdbe);
  if( rc==SQLITE_OK && db->nTable==0 ){
    db->file_format = FILE_FORMAT;
  }
  if( rc==SQLITE_OK && db->file_format>FILE_FORMAT ){
    sqliteSetString(pzErrMsg, "unsupported file format", 0);
    rc = SQLITE_ERROR;
  }

  /* The schema for the SQLITE_MASTER table is not stored in the
  ** database itself.  We have to invoke the callback one extra
  ** time to get it to process the SQLITE_MASTER table defintion.







<
|
|
>
>
|
>
>
>
>








>
>






>
>
>





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

|





|
|
|

|





|
|
















|

|







146
147
148
149
150
151
152

153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
  ** indexes.  The "rootpage" column holds the number of the root page
  ** for the b-tree for the table or index.  Finally, the "sql" column
  ** contains the complete text of the CREATE TABLE or CREATE INDEX
  ** statement that originally created the table or index.  If an index
  ** was created to fulfill a PRIMARY KEY or UNIQUE constraint on a table,
  ** then the "sql" column is NULL.
  **

  ** In format 1, entries in the sqlite_master table are in a random
  ** order.  Two passes must be made through the table to initialize
  ** internal data structures.  The first pass reads table definitions
  ** and the second pass read index definitions.  Having two passes
  ** insures that indices appear after their tables.
  **
  ** In format 2, entries appear in chronological order.  Only a single
  ** pass needs to be made through the table since everything will be
  ** in the write order.  VIEWs may only occur in format 2.
  **
  ** The following program invokes its callback on the SQL for each
  ** table then goes back and invokes the callback on the
  ** SQL for each index.  The callback will invoke the
  ** parser to build the internal representation of the
  ** database scheme.
  */
  static VdbeOp initProg[] = {
    /* Send the file format to the callback routine
    */
    { OP_Open,       0, 2,  0},
    { OP_String,     0, 0,  "file-format"},
    { OP_String,     0, 0,  0},
    { OP_String,     0, 0,  0},
    { OP_ReadCookie, 0, 1,  0},
    { OP_Callback,   4, 0,  0},

    /* Send the initial schema cookie to the callback
    */
    { OP_String,     0, 0,  "schema_cookie"},
    { OP_String,     0, 0,  0},
    { OP_String,     0, 0,  0},
    { OP_ReadCookie, 0, 0,  0},
    { OP_Callback,   4, 0,  0},

    /* Check the file format.  If the format number is 2 or more,
    ** then do a single pass through the SQLITE_MASTER table.  For
    ** a format number of less than 2, jump forward to a different
    ** algorithm that makes two passes through the SQLITE_MASTER table,
    ** once for tables and a second time for indices.
    */
    { OP_ReadCookie, 0, 1,  0},
    { OP_Integer,    2, 0,  0},
    { OP_Lt,         0, 23, 0},

    /* This is the code for doing a single scan through the SQLITE_MASTER
    ** table.  This code runs for format 2 and greater.
    */
    { OP_Rewind,     0, 21, 0},
    { OP_Column,     0, 0,  0},           /* 15 */
    { OP_Column,     0, 1,  0},
    { OP_Column,     0, 3,  0},
    { OP_Column,     0, 4,  0},
    { OP_Callback,   4, 0,  0},
    { OP_Next,       0, 15, 0},
    { OP_Close,      0, 0,  0},           /* 21 */
    { OP_Halt,       0, 0,  0},

    /* This is the code for doing two passes through SQLITE_MASTER.  This
    ** code runs for file format 1.
    */
    { OP_Rewind,     0, 43, 0},           /* 23 */
    { OP_Column,     0, 0,  0},           /* 24 */
    { OP_String,     0, 0,  "table"},
    { OP_Ne,         0, 32, 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_Next,       0, 24, 0},           /* 32 */
    { OP_Rewind,     0, 43, 0},           /* 33 */
    { OP_Column,     0, 0,  0},           /* 34 */
    { OP_String,     0, 0,  "index"},
    { OP_Ne,         0, 42, 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_Next,       0, 34, 0},           /* 42 */
    { OP_Close,      0, 0,  0},           /* 43 */
    { OP_Halt,       0, 0,  0},
  };

  /* Create a virtual machine to run the initialization program.  Run
  ** the program.  Then delete the virtual machine.
  */
  vdbe = sqliteVdbeCreate(db);
  if( vdbe==0 ){
    sqliteSetString(pzErrMsg, "out of memory", 0);
    return SQLITE_NOMEM;
  }
  sqliteVdbeAddOpList(vdbe, sizeof(initProg)/sizeof(initProg[0]), initProg);
  rc = sqliteVdbeExec(vdbe, sqliteOpenCb, db, pzErrMsg, 
                      db->pBusyArg, db->xBusyCallback);
  sqliteVdbeDelete(vdbe);
  if( rc==SQLITE_OK && db->nTable==0 ){
    db->file_format = 2;
  }
  if( rc==SQLITE_OK && db->file_format>2 ){
    sqliteSetString(pzErrMsg, "unsupported file format", 0);
    rc = SQLITE_ERROR;
  }

  /* The schema for the SQLITE_MASTER table is not stored in the
  ** database itself.  We have to invoke the callback one extra
  ** time to get it to process the SQLITE_MASTER table defintion.
Changes to src/select.c.
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle SELECT statements in SQLite.
**
** $Id: select.c,v 1.63 2002/02/19 22:42:05 drh Exp $
*/
#include "sqliteInt.h"

/*
** Allocate a new Select structure and return a pointer to that
** structure.
*/







|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle SELECT statements in SQLite.
**
** $Id: select.c,v 1.64 2002/02/21 12:01:27 drh Exp $
*/
#include "sqliteInt.h"

/*
** Allocate a new Select structure and return a pointer to that
** structure.
*/
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
  seekOp = pExpr->iColumn==FN_Min ? OP_Rewind : OP_Last;
  pExpr = pExpr->pList->a[0].pExpr;
  if( pExpr->op!=TK_COLUMN ) return 0;
  iCol = pExpr->iColumn;
  pTab = p->pSrc->a[0].pTab;

  /* If we get to here, it means the query is of the correct form.
  ** Check to make sure we have an index.



  */
  if( iCol<0 ){
    pIdx = 0;
  }else{
    for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
      assert( pIdx->nColumn>=1 );
      if( pIdx->aiColumn[0]==iCol ) break;
    }
    if( pIdx==0 ) return 0;
  }

  /* Identify column names if we will be using in the callback.  This
  ** step is skipped if the output is going to a table or a memory cell.
  */
  v = sqliteGetVdbe(pParse);
  if( v==0 ) return 0;
  if( eDest==SRT_Callback ){
    generateColumnNames(pParse, p->pSrc, p->pEList);
  }

  /* Begin generating code



  */
  if( !pParse->schemaVerified && (pParse->db->flags & SQLITE_InTrans)==0 ){
    sqliteVdbeAddOp(v, OP_VerifyCookie, pParse->db->schema_cookie, 0);
    pParse->schemaVerified = 1;
  }
  openOp = pTab->isTemp ? OP_OpenAux : OP_Open;
  base = pParse->nTab;







|
>
>
>











|








|
>
>
>







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
  seekOp = pExpr->iColumn==FN_Min ? OP_Rewind : OP_Last;
  pExpr = pExpr->pList->a[0].pExpr;
  if( pExpr->op!=TK_COLUMN ) return 0;
  iCol = pExpr->iColumn;
  pTab = p->pSrc->a[0].pTab;

  /* If we get to here, it means the query is of the correct form.
  ** Check to make sure we have an index and make pIdx point to the
  ** appropriate index.  If the min() or max() is on an INTEGER PRIMARY
  ** key column, no index is necessary so set pIdx to NULL.  If no
  ** usable index is found, return 0.
  */
  if( iCol<0 ){
    pIdx = 0;
  }else{
    for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
      assert( pIdx->nColumn>=1 );
      if( pIdx->aiColumn[0]==iCol ) break;
    }
    if( pIdx==0 ) return 0;
  }

  /* Identify column names if we will be using the callback.  This
  ** step is skipped if the output is going to a table or a memory cell.
  */
  v = sqliteGetVdbe(pParse);
  if( v==0 ) return 0;
  if( eDest==SRT_Callback ){
    generateColumnNames(pParse, p->pSrc, p->pEList);
  }

  /* Generating code to find the min or the max.  Basically all we have
  ** to do is find the first or the last entry in the chosen index.  If
  ** the min() or max() is on the INTEGER PRIMARY KEY, then find the first
  ** or last entry in the main table.
  */
  if( !pParse->schemaVerified && (pParse->db->flags & SQLITE_InTrans)==0 ){
    sqliteVdbeAddOp(v, OP_VerifyCookie, pParse->db->schema_cookie, 0);
    pParse->schemaVerified = 1;
  }
  openOp = pTab->isTemp ? OP_OpenAux : OP_Open;
  base = pParse->nTab;
Changes to src/sqliteInt.h.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
/*
** 2001 September 15
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** Internal interface definitions for SQLite.
**
** @(#) $Id: sqliteInt.h,v 1.88 2002/02/19 22:42:05 drh Exp $
*/
#include "sqlite.h"
#include "hash.h"
#include "vdbe.h"
#include "parse.h"
#include "btree.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>

/*
** The maximum number of in-memory pages to use for the main database
** table and for temporary tables.
*/
#define MAX_PAGES   100
#define TEMP_PAGES   25

/*
** File format version number
*/
#define FILE_FORMAT 1

/*
** Integers of known sizes.  These typedefs might change for architectures
** where the sizes very.  Preprocessor macros are available so that the
** types can be conveniently redefined at compile-type.  Like this:
**
**         cc '-DUINTPTR_TYPE=long long int' ...
*/













|


















<
<
<
<
<







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32





33
34
35
36
37
38
39
/*
** 2001 September 15
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** Internal interface definitions for SQLite.
**
** @(#) $Id: sqliteInt.h,v 1.89 2002/02/21 12:01:27 drh Exp $
*/
#include "sqlite.h"
#include "hash.h"
#include "vdbe.h"
#include "parse.h"
#include "btree.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>

/*
** The maximum number of in-memory pages to use for the main database
** table and for temporary tables.
*/
#define MAX_PAGES   100
#define TEMP_PAGES   25






/*
** Integers of known sizes.  These typedefs might change for architectures
** where the sizes very.  Preprocessor macros are available so that the
** types can be conveniently redefined at compile-type.  Like this:
**
**         cc '-DUINTPTR_TYPE=long long int' ...
*/
551
552
553
554
555
556
557

558
559
560
561
562
563
564
  void *sqliteRealloc(void*,int);
  char *sqliteStrDup(const char*);
  char *sqliteStrNDup(const char*, int);
#endif
void sqliteSetString(char **, const char *, ...);
void sqliteSetNString(char **, ...);
void sqliteDequote(char*);

int sqliteRunParser(Parse*, const char*, char **);
void sqliteExec(Parse*);
Expr *sqliteExpr(int, Expr*, Expr*, Token*);
void sqliteExprSpan(Expr*,Token*,Token*);
Expr *sqliteExprFunction(ExprList*, Token*);
void sqliteExprDelete(Expr*);
ExprList *sqliteExprListAppend(ExprList*,Expr*,Token*);







>







546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
  void *sqliteRealloc(void*,int);
  char *sqliteStrDup(const char*);
  char *sqliteStrNDup(const char*, int);
#endif
void sqliteSetString(char **, const char *, ...);
void sqliteSetNString(char **, ...);
void sqliteDequote(char*);
int sqliteKeywordCode(const char*, int);
int sqliteRunParser(Parse*, const char*, char **);
void sqliteExec(Parse*);
Expr *sqliteExpr(int, Expr*, Expr*, Token*);
void sqliteExprSpan(Expr*,Token*,Token*);
Expr *sqliteExprFunction(ExprList*, Token*);
void sqliteExprDelete(Expr*);
ExprList *sqliteExprListAppend(ExprList*,Expr*,Token*);
Changes to src/tokenize.c.
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
*************************************************************************
** An tokenizer for SQL
**
** This file contains C code that splits an SQL input string up into
** individual tokens and sends those tokens one-by-one over to the
** parser for analysis.
**
** $Id: tokenize.c,v 1.36 2002/02/17 00:30:36 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
#include <ctype.h>
#include <stdlib.h>

/*







|







11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
*************************************************************************
** An tokenizer for SQL
**
** This file contains C code that splits an SQL input string up into
** individual tokens and sends those tokens one-by-one over to the
** parser for analysis.
**
** $Id: tokenize.c,v 1.37 2002/02/21 12:01:27 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
#include <ctype.h>
#include <stdlib.h>

/*
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126


/*
** This function looks up an identifier to determine if it is a
** keyword.  If it is a keyword, the token code of that keyword is 
** returned.  If the input is not a keyword, TK_ID is returned.
*/
static int sqliteKeywordCode(const char *z, int n){
  int h;
  Keyword *p;
  if( aKeywordTable[0].len==0 ){
    /* Initialize the keyword hash table */
    sqliteOsEnterMutex();
    if( aKeywordTable[0].len==0 ){
      int i;







|







112
113
114
115
116
117
118
119
120
121
122
123
124
125
126


/*
** This function looks up an identifier to determine if it is a
** keyword.  If it is a keyword, the token code of that keyword is 
** returned.  If the input is not a keyword, TK_ID is returned.
*/
int sqliteKeywordCode(const char *z, int n){
  int h;
  Keyword *p;
  if( aKeywordTable[0].len==0 ){
    /* Initialize the keyword hash table */
    sqliteOsEnterMutex();
    if( aKeywordTable[0].len==0 ){
      int i;
Changes to src/vdbe.c.
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
** 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.120 2002/02/19 22:42:05 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

/*
** The following global variable is incremented every time a cursor
** moves, either by the OP_MoveTo or the OP_Next opcode.  The test







|







26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
** 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.121 2002/02/21 12:01:27 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

/*
** The following global variable is incremented every time a cursor
** moves, either by the OP_MoveTo or the OP_Next opcode.  The test
68
69
70
71
72
73
74

75
76
77
78
79
80
81
struct Cursor {
  BtCursor *pCursor;    /* The cursor structure of the backend */
  int lastRecno;        /* Last recno from a Next or NextIdx operation */
  Bool recnoIsValid;    /* True if lastRecno is valid */
  Bool keyAsData;       /* The OP_Column command works on key instead of data */
  Bool atFirst;         /* True if pointing to first entry */
  Bool useRandomRowid;  /* Generate new record numbers semi-randomly */

  Btree *pBt;           /* Separate file holding temporary table */
};
typedef struct Cursor Cursor;

/*
** A sorter builds a list of elements to be sorted.  Each element of
** the list is an instance of the following structure.







>







68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
struct Cursor {
  BtCursor *pCursor;    /* The cursor structure of the backend */
  int lastRecno;        /* Last recno from a Next or NextIdx operation */
  Bool recnoIsValid;    /* True if lastRecno is valid */
  Bool keyAsData;       /* The OP_Column command works on key instead of data */
  Bool atFirst;         /* True if pointing to first entry */
  Bool useRandomRowid;  /* Generate new record numbers semi-randomly */
  Bool nullRow;         /* True if pointing to a row with no data */
  Btree *pBt;           /* Separate file holding temporary table */
};
typedef struct Cursor Cursor;

/*
** A sorter builds a list of elements to be sorted.  Each element of
** the list is an instance of the following structure.
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
static char *zOpName[] = { 0,
  "Transaction",       "Checkpoint",        "Commit",            "Rollback",
  "ReadCookie",        "SetCookie",         "VerifyCookie",      "Open",
  "OpenTemp",          "OpenWrite",         "OpenAux",           "OpenWrAux",
  "Close",             "MoveTo",            "NewRecno",          "PutIntKey",
  "PutStrKey",         "Distinct",          "Found",             "NotFound",
  "IsUnique",          "NotExists",         "Delete",            "Column",
  "KeyAsData",         "Recno",             "FullKey",           "Last",
  "Rewind",            "Next",              "Destroy",           "Clear",
  "CreateIndex",       "CreateTable",       "IntegrityCk",       "IdxPut",
  "IdxDelete",         "IdxRecno",          "IdxGT",             "IdxGE",
  "MemLoad",           "MemStore",          "ListWrite",         "ListRewind",
  "ListRead",          "ListReset",         "SortPut",           "SortMakeRec",
  "SortMakeKey",       "Sort",              "SortNext",          "SortCallback",
  "SortReset",         "FileOpen",          "FileRead",          "FileColumn",
  "AggReset",          "AggFocus",          "AggIncr",           "AggNext",
  "AggSet",            "AggGet",            "SetInsert",         "SetFound",
  "SetNotFound",       "MakeRecord",        "MakeKey",           "MakeIdxKey",
  "IncrKey",           "Goto",              "If",                "Halt",
  "ColumnCount",       "ColumnName",        "Callback",          "NullCallback",
  "Integer",           "String",            "Pop",               "Dup",
  "Pull",              "Push",              "MustBeInt",         "Add",
  "AddImm",            "Subtract",          "Multiply",          "Divide",
  "Remainder",         "BitAnd",            "BitOr",             "BitNot",
  "ShiftLeft",         "ShiftRight",        "AbsValue",          "Precision",
  "Min",               "Max",               "Like",              "Glob",
  "Eq",                "Ne",                "Lt",                "Le",
  "Gt",                "Ge",                "IsNull",            "NotNull",
  "Negative",          "And",               "Or",                "Not",
  "Concat",            "Noop",              "Strlen",            "Substr",
  "Limit",           
};

/*
** Given the name of an opcode, return its number.  Return 0 if
** there is no match.
**
** This routine is used for testing and debugging.







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







864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
static char *zOpName[] = { 0,
  "Transaction",       "Checkpoint",        "Commit",            "Rollback",
  "ReadCookie",        "SetCookie",         "VerifyCookie",      "Open",
  "OpenTemp",          "OpenWrite",         "OpenAux",           "OpenWrAux",
  "Close",             "MoveTo",            "NewRecno",          "PutIntKey",
  "PutStrKey",         "Distinct",          "Found",             "NotFound",
  "IsUnique",          "NotExists",         "Delete",            "Column",
  "KeyAsData",         "Recno",             "FullKey",           "NullRow",
  "Last",              "Rewind",            "Next",              "Destroy",
  "Clear",             "CreateIndex",       "CreateTable",       "IntegrityCk",
  "IdxPut",            "IdxDelete",         "IdxRecno",          "IdxGT",
  "IdxGE",             "MemLoad",           "MemStore",          "ListWrite",
  "ListRewind",        "ListRead",          "ListReset",         "SortPut",
  "SortMakeRec",       "SortMakeKey",       "Sort",              "SortNext",
  "SortCallback",      "SortReset",         "FileOpen",          "FileRead",
  "FileColumn",        "AggReset",          "AggFocus",          "AggIncr",
  "AggNext",           "AggSet",            "AggGet",            "SetInsert",
  "SetFound",          "SetNotFound",       "MakeRecord",        "MakeKey",
  "MakeIdxKey",        "IncrKey",           "Goto",              "If",
  "Halt",              "ColumnCount",       "ColumnName",        "Callback",
  "NullCallback",      "Integer",           "String",            "Pop",
  "Dup",               "Pull",              "Push",              "MustBeInt",
  "Add",               "AddImm",            "Subtract",          "Multiply",
  "Divide",            "Remainder",         "BitAnd",            "BitOr",
  "BitNot",            "ShiftLeft",         "ShiftRight",        "AbsValue",
  "Precision",         "Min",               "Max",               "Like",
  "Glob",              "Eq",                "Ne",                "Lt",
  "Le",                "Gt",                "Ge",                "IsNull",
  "NotNull",           "Negative",          "And",               "Or",
  "Not",               "Concat",            "Noop",              "Strlen",
  "Substr",            "Limit",           
};

/*
** Given the name of an opcode, return its number.  Return 0 if
** there is no match.
**
** This routine is used for testing and debugging.
2587
2588
2589
2590
2591
2592
2593

2594
2595
2596
2597
2598
2599
2600
    for(j=p->nCursor; j<=i; j++){
      memset(&p->aCsr[j], 0, sizeof(Cursor));
    }
    p->nCursor = i+1;
  }
  cleanupCursor(&p->aCsr[i]);
  memset(&p->aCsr[i], 0, sizeof(Cursor));

  do{
    rc = sqliteBtreeCursor(pX, p2, wrFlag, &p->aCsr[i].pCursor);
    switch( rc ){
      case SQLITE_BUSY: {
        if( xBusy==0 || (*xBusy)(pBusyArg, pOp->p3, ++busy)==0 ){
          sqliteSetString(pzErrMsg, sqlite_error_string(rc), 0);
          busy = 0;







>







2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
    for(j=p->nCursor; j<=i; j++){
      memset(&p->aCsr[j], 0, sizeof(Cursor));
    }
    p->nCursor = i+1;
  }
  cleanupCursor(&p->aCsr[i]);
  memset(&p->aCsr[i], 0, sizeof(Cursor));
  p->aCsr[i].nullRow = 1;
  do{
    rc = sqliteBtreeCursor(pX, p2, wrFlag, &p->aCsr[i].pCursor);
    switch( rc ){
      case SQLITE_BUSY: {
        if( xBusy==0 || (*xBusy)(pBusyArg, pOp->p3, ++busy)==0 ){
          sqliteSetString(pzErrMsg, sqlite_error_string(rc), 0);
          busy = 0;
2644
2645
2646
2647
2648
2649
2650

2651
2652
2653
2654
2655
2656
2657
      memset(&p->aCsr[j], 0, sizeof(Cursor));
    }
    p->nCursor = i+1;
  }
  pCx = &p->aCsr[i];
  cleanupCursor(pCx);
  memset(pCx, 0, sizeof(*pCx));

  rc = sqliteBtreeOpen(0, 0, TEMP_PAGES, &pCx->pBt);
  if( rc==SQLITE_OK ){
    rc = sqliteBtreeBeginTrans(pCx->pBt);
  }
  if( rc==SQLITE_OK ){
    if( pOp->p2 ){
      int pgno;







>







2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
      memset(&p->aCsr[j], 0, sizeof(Cursor));
    }
    p->nCursor = i+1;
  }
  pCx = &p->aCsr[i];
  cleanupCursor(pCx);
  memset(pCx, 0, sizeof(*pCx));
  pCx->nullRow = 1;
  rc = sqliteBtreeOpen(0, 0, TEMP_PAGES, &pCx->pBt);
  if( rc==SQLITE_OK ){
    rc = sqliteBtreeBeginTrans(pCx->pBt);
  }
  if( rc==SQLITE_OK ){
    if( pOp->p2 ){
      int pgno;
2704
2705
2706
2707
2708
2709
2710

2711
2712
2713
2714
2715
2716
2717
      pC->lastRecno = aStack[tos].i;
      pC->recnoIsValid = res==0;
    }else{
      if( Stringify(p, tos) ) goto no_mem;
      sqliteBtreeMoveto(pC->pCursor, zStack[tos], aStack[tos].n, &res);
      pC->recnoIsValid = 0;
    }

    sqlite_search_count++;
    if( res<0 ){
      sqliteBtreeNext(pC->pCursor, &res);
      pC->recnoIsValid = 0;
      if( res && pOp->p2>0 ){
        pc = pOp->p2 - 1;
      }







>







2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
      pC->lastRecno = aStack[tos].i;
      pC->recnoIsValid = res==0;
    }else{
      if( Stringify(p, tos) ) goto no_mem;
      sqliteBtreeMoveto(pC->pCursor, zStack[tos], aStack[tos].n, &res);
      pC->recnoIsValid = 0;
    }
    pC->nullRow = 0;
    sqlite_search_count++;
    if( res<0 ){
      sqliteBtreeNext(pC->pCursor, &res);
      pC->recnoIsValid = 0;
      if( res && pOp->p2>0 ){
        pc = pOp->p2 - 1;
      }
2888
2889
2890
2891
2892
2893
2894



2895
2896

2897
2898
2899
2900
2901
2902
2903
  BtCursor *pCrsr;
  VERIFY( if( tos<0 ) goto not_enough_stack; )
  if( VERIFY( i>=0 && i<p->nCursor && ) (pCrsr = p->aCsr[i].pCursor)!=0 ){
    int res, rx, iKey;
    assert( aStack[tos].flags & STK_Int );
    iKey = intToKey(aStack[tos].i);
    rx = sqliteBtreeMoveto(pCrsr, (char*)&iKey, sizeof(int), &res);



    if( rx!=SQLITE_OK || res!=0 ){
       pc = pOp->p2 - 1;

    }
  }
  POPSTACK;
  break;
}

/* Opcode: NewRecno P1 * *







>
>
>

|
>







2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
  BtCursor *pCrsr;
  VERIFY( if( tos<0 ) goto not_enough_stack; )
  if( VERIFY( i>=0 && i<p->nCursor && ) (pCrsr = p->aCsr[i].pCursor)!=0 ){
    int res, rx, iKey;
    assert( aStack[tos].flags & STK_Int );
    iKey = intToKey(aStack[tos].i);
    rx = sqliteBtreeMoveto(pCrsr, (char*)&iKey, sizeof(int), &res);
    p->aCsr[i].lastRecno = aStack[tos].i;
    p->aCsr[i].recnoIsValid = res==0;
    p->aCsr[i].nullRow = 0;
    if( rx!=SQLITE_OK || res!=0 ){
      pc = pOp->p2 - 1;
      p->aCsr[i].recnoIsValid = 0;
    }
  }
  POPSTACK;
  break;
}

/* Opcode: NewRecno P1 * *
2978
2979
2980
2981
2982
2983
2984

2985
2986
2987
2988
2989
2990
2991
      }while( cnt<1000 && rx==SQLITE_OK && res==0 );
      db->priorNewRowid = v;
      if( rx==SQLITE_OK && res==0 ){
        rc = SQLITE_FULL;
        goto abort_due_to_error;
      }
    }

  }
  VERIFY( NeedStack(p, p->tos+1); )
  p->tos++;
  aStack[p->tos].i = v;
  aStack[p->tos].flags = STK_Int;
  break;
}







>







2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
      }while( cnt<1000 && rx==SQLITE_OK && res==0 );
      db->priorNewRowid = v;
      if( rx==SQLITE_OK && res==0 ){
        rc = SQLITE_FULL;
        goto abort_due_to_error;
      }
    }
    pC->recnoIsValid = 0;
  }
  VERIFY( NeedStack(p, p->tos+1); )
  p->tos++;
  aStack[p->tos].i = v;
  aStack[p->tos].flags = STK_Int;
  break;
}
3040
3041
3042
3043
3044
3045
3046

3047
3048
3049
3050
3051
3052
3053
      }
      if( rc!=SQLITE_OK ){
        goto abort_due_to_error;
      }
    }
    rc = sqliteBtreeInsert(p->aCsr[i].pCursor, zKey, nKey,
                        zStack[tos], aStack[tos].n);

  }
  POPSTACK;
  POPSTACK;
  break;
}

/* Opcode: Delete P1 * *







>







3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
      }
      if( rc!=SQLITE_OK ){
        goto abort_due_to_error;
      }
    }
    rc = sqliteBtreeInsert(p->aCsr[i].pCursor, zKey, nKey,
                        zStack[tos], aStack[tos].n);
    p->aCsr[i].recnoIsValid = 0;
  }
  POPSTACK;
  POPSTACK;
  break;
}

/* Opcode: Delete P1 * *
3109
3110
3111
3112
3113
3114
3115


3116
3117
3118
3119
3120
3121
3122
3123
  VERIFY( if( NeedStack(p, tos+1) ) goto no_mem; )
  if( VERIFY( i>=0 && i<p->nCursor && ) (pC = &p->aCsr[i])->pCursor!=0 ){

    /* Use different access functions depending on whether the information
    ** is coming from the key or the data of the record.
    */
    pCrsr = pC->pCursor;


    if( pC->keyAsData ){
      sqliteBtreeKeySize(pCrsr, &payloadSize);
      xRead = sqliteBtreeKey;
    }else{
      sqliteBtreeDataSize(pCrsr, &payloadSize);
      xRead = sqliteBtreeData;
    }








>
>
|







3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
  VERIFY( if( NeedStack(p, tos+1) ) goto no_mem; )
  if( VERIFY( i>=0 && i<p->nCursor && ) (pC = &p->aCsr[i])->pCursor!=0 ){

    /* Use different access functions depending on whether the information
    ** is coming from the key or the data of the record.
    */
    pCrsr = pC->pCursor;
    if( pC->nullRow ){
      payloadSize = 0;
    }else if( pC->keyAsData ){
      sqliteBtreeKeySize(pCrsr, &payloadSize);
      xRead = sqliteBtreeKey;
    }else{
      sqliteBtreeDataSize(pCrsr, &payloadSize);
      xRead = sqliteBtreeData;
    }

3195
3196
3197
3198
3199
3200
3201



3202
3203
3204
3205
3206
3207
3208
  BtCursor *pCrsr;

  VERIFY( if( NeedStack(p, p->tos) ) goto no_mem; )
  if( VERIFY( i>=0 && i<p->nCursor && ) (pCrsr = p->aCsr[i].pCursor)!=0 ){
    int v;
    if( p->aCsr[i].recnoIsValid ){
      v = p->aCsr[i].lastRecno;



    }else{
      sqliteBtreeKey(pCrsr, 0, sizeof(u32), (char*)&v);
      v = keyToInt(v);
    }
    aStack[tos].i = v;
    aStack[tos].flags = STK_Int;
  }







>
>
>







3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
  BtCursor *pCrsr;

  VERIFY( if( NeedStack(p, p->tos) ) goto no_mem; )
  if( VERIFY( i>=0 && i<p->nCursor && ) (pCrsr = p->aCsr[i].pCursor)!=0 ){
    int v;
    if( p->aCsr[i].recnoIsValid ){
      v = p->aCsr[i].lastRecno;
    }else if( p->aCsr[i].nullRow ){
      aStack[tos].flags = STK_Null;
      break;
    }else{
      sqliteBtreeKey(pCrsr, 0, sizeof(u32), (char*)&v);
      v = keyToInt(v);
    }
    aStack[tos].i = v;
    aStack[tos].flags = STK_Int;
  }
3243
3244
3245
3246
3247
3248
3249
















3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
    }
    sqliteBtreeKey(pCrsr, 0, amt, z);
    zStack[tos] = z;
    aStack[tos].n = amt;
  }
  break;
}

















/* Opcode: Last P1 P2 *
**
** The next use of the Recno or Column or Next instruction for P1 
** will refer to the last entry in the database table or index.
** If the table or index is empty and P2>0, then jump immediately to P2.
** If P2 is 0 or if the table or index is not empty, fall through
** to the following instruction.
*/
case OP_Last: {
  int i = pOp->p1;
  BtCursor *pCrsr;

  if( VERIFY( i>=0 && i<p->nCursor && ) (pCrsr = p->aCsr[i].pCursor)!=0 ){
    int res;
    sqliteBtreeLast(pCrsr, &res);
    p->aCsr[i].atFirst = res==0;
    if( res && pOp->p2>0 ){
      pc = pOp->p2 - 1;
    }
  }
  break;
}








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
















|







3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
    }
    sqliteBtreeKey(pCrsr, 0, amt, z);
    zStack[tos] = z;
    aStack[tos].n = amt;
  }
  break;
}

/* Opcode: NullRow P1 * *
**
** Move the cursor P1 to a null row.  Any OP_Column operations
** that occur while the cursor is on the null row will always push 
** a NULL onto the stack.
*/
case OP_NullRow: {
  int i = pOp->p1;
  BtCursor *pCrsr;

  if( VERIFY( i>=0 && i<p->nCursor && ) (pCrsr = p->aCsr[i].pCursor)!=0 ){
    p->aCsr[i].nullRow = 1;
  }
  break;
}

/* Opcode: Last P1 P2 *
**
** The next use of the Recno or Column or Next instruction for P1 
** will refer to the last entry in the database table or index.
** If the table or index is empty and P2>0, then jump immediately to P2.
** If P2 is 0 or if the table or index is not empty, fall through
** to the following instruction.
*/
case OP_Last: {
  int i = pOp->p1;
  BtCursor *pCrsr;

  if( VERIFY( i>=0 && i<p->nCursor && ) (pCrsr = p->aCsr[i].pCursor)!=0 ){
    int res;
    sqliteBtreeLast(pCrsr, &res);
    p->aCsr[i].nullRow = res;
    if( res && pOp->p2>0 ){
      pc = pOp->p2 - 1;
    }
  }
  break;
}

3283
3284
3285
3286
3287
3288
3289

3290
3291
3292
3293
3294
3295
3296
  int i = pOp->p1;
  BtCursor *pCrsr;

  if( VERIFY( i>=0 && i<p->nCursor && ) (pCrsr = p->aCsr[i].pCursor)!=0 ){
    int res;
    sqliteBtreeFirst(pCrsr, &res);
    p->aCsr[i].atFirst = res==0;

    if( res && pOp->p2>0 ){
      pc = pOp->p2 - 1;
    }
  }
  break;
}








>







3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
  int i = pOp->p1;
  BtCursor *pCrsr;

  if( VERIFY( i>=0 && i<p->nCursor && ) (pCrsr = p->aCsr[i].pCursor)!=0 ){
    int res;
    sqliteBtreeFirst(pCrsr, &res);
    p->aCsr[i].atFirst = res==0;
    p->aCsr[i].nullRow = res;
    if( res && pOp->p2>0 ){
      pc = pOp->p2 - 1;
    }
  }
  break;
}

3304
3305
3306
3307
3308
3309
3310

3311
3312
3313
3314
3315
3316
3317
case OP_Next: {
  int i = pOp->p1;
  BtCursor *pCrsr;

  if( VERIFY( i>=0 && i<p->nCursor && ) (pCrsr = p->aCsr[i].pCursor)!=0 ){
    int res;
    rc = sqliteBtreeNext(pCrsr, &res);

    if( res==0 ){
      pc = pOp->p2 - 1;
      sqlite_search_count++;
    }
    p->aCsr[i].recnoIsValid = 0;
  }
  break;







>







3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
case OP_Next: {
  int i = pOp->p1;
  BtCursor *pCrsr;

  if( VERIFY( i>=0 && i<p->nCursor && ) (pCrsr = p->aCsr[i].pCursor)!=0 ){
    int res;
    rc = sqliteBtreeNext(pCrsr, &res);
    p->aCsr[i].nullRow = res;
    if( res==0 ){
      pc = pOp->p2 - 1;
      sqlite_search_count++;
    }
    p->aCsr[i].recnoIsValid = 0;
  }
  break;
Changes to src/vdbe.h.
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
*************************************************************************
** 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.43 2002/02/19 15:00:08 drh Exp $
*/
#ifndef _SQLITE_VDBE_H_
#define _SQLITE_VDBE_H_
#include <stdio.h>

/*
** A single VDBE is an opaque structure named "Vdbe".  Only routines







|







11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
*************************************************************************
** 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.44 2002/02/21 12:01:28 drh Exp $
*/
#ifndef _SQLITE_VDBE_H_
#define _SQLITE_VDBE_H_
#include <stdio.h>

/*
** A single VDBE is an opaque structure named "Vdbe".  Only routines
93
94
95
96
97
98
99

100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
#define OP_IsUnique           21
#define OP_NotExists          22
#define OP_Delete             23
#define OP_Column             24
#define OP_KeyAsData          25
#define OP_Recno              26
#define OP_FullKey            27

#define OP_Last               28
#define OP_Rewind             29
#define OP_Next               30

#define OP_Destroy            31
#define OP_Clear              32
#define OP_CreateIndex        33
#define OP_CreateTable        34
#define OP_IntegrityCk        35

#define OP_IdxPut             36
#define OP_IdxDelete          37
#define OP_IdxRecno           38
#define OP_IdxGT              39
#define OP_IdxGE              40

#define OP_MemLoad            41
#define OP_MemStore           42

#define OP_ListWrite          43
#define OP_ListRewind         44
#define OP_ListRead           45
#define OP_ListReset          46

#define OP_SortPut            47
#define OP_SortMakeRec        48
#define OP_SortMakeKey        49
#define OP_Sort               50
#define OP_SortNext           51
#define OP_SortCallback       52
#define OP_SortReset          53

#define OP_FileOpen           54
#define OP_FileRead           55
#define OP_FileColumn         56

#define OP_AggReset           57
#define OP_AggFocus           58
#define OP_AggIncr            59
#define OP_AggNext            60
#define OP_AggSet             61
#define OP_AggGet             62

#define OP_SetInsert          63
#define OP_SetFound           64
#define OP_SetNotFound        65

#define OP_MakeRecord         66
#define OP_MakeKey            67
#define OP_MakeIdxKey         68
#define OP_IncrKey            69

#define OP_Goto               70
#define OP_If                 71
#define OP_Halt               72

#define OP_ColumnCount        73
#define OP_ColumnName         74
#define OP_Callback           75
#define OP_NullCallback       76

#define OP_Integer            77
#define OP_String             78
#define OP_Pop                79
#define OP_Dup                80
#define OP_Pull               81
#define OP_Push               82
#define OP_MustBeInt          83

#define OP_Add                84
#define OP_AddImm             85
#define OP_Subtract           86
#define OP_Multiply           87
#define OP_Divide             88
#define OP_Remainder          89
#define OP_BitAnd             90
#define OP_BitOr              91
#define OP_BitNot             92
#define OP_ShiftLeft          93
#define OP_ShiftRight         94
#define OP_AbsValue           95
#define OP_Precision          96
#define OP_Min                97
#define OP_Max                98
#define OP_Like               99
#define OP_Glob              100
#define OP_Eq                101
#define OP_Ne                102
#define OP_Lt                103
#define OP_Le                104
#define OP_Gt                105
#define OP_Ge                106
#define OP_IsNull            107
#define OP_NotNull           108
#define OP_Negative          109
#define OP_And               110
#define OP_Or                111
#define OP_Not               112
#define OP_Concat            113
#define OP_Noop              114

#define OP_Strlen            115
#define OP_Substr            116

#define OP_Limit             117

#define OP_MAX               117

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







>
|
|
|

|
|
|
|
|

|
|
|
|
|

|
|

|
|
|
|

|
|
|
|
|
|
|

|
|
|

|
|
|
|
|
|

|
|
|

|
|
|
|

|
|
|

|
|
|
|

|
|
|
|
|
|
|

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

|
|

|

|







93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
#define OP_IsUnique           21
#define OP_NotExists          22
#define OP_Delete             23
#define OP_Column             24
#define OP_KeyAsData          25
#define OP_Recno              26
#define OP_FullKey            27
#define OP_NullRow            28
#define OP_Last               29
#define OP_Rewind             30
#define OP_Next               31

#define OP_Destroy            32
#define OP_Clear              33
#define OP_CreateIndex        34
#define OP_CreateTable        35
#define OP_IntegrityCk        36

#define OP_IdxPut             37
#define OP_IdxDelete          38
#define OP_IdxRecno           39
#define OP_IdxGT              40
#define OP_IdxGE              41

#define OP_MemLoad            42
#define OP_MemStore           43

#define OP_ListWrite          44
#define OP_ListRewind         45
#define OP_ListRead           46
#define OP_ListReset          47

#define OP_SortPut            48
#define OP_SortMakeRec        49
#define OP_SortMakeKey        50
#define OP_Sort               51
#define OP_SortNext           52
#define OP_SortCallback       53
#define OP_SortReset          54

#define OP_FileOpen           55
#define OP_FileRead           56
#define OP_FileColumn         57

#define OP_AggReset           58
#define OP_AggFocus           59
#define OP_AggIncr            60
#define OP_AggNext            61
#define OP_AggSet             62
#define OP_AggGet             63

#define OP_SetInsert          64
#define OP_SetFound           65
#define OP_SetNotFound        66

#define OP_MakeRecord         67
#define OP_MakeKey            68
#define OP_MakeIdxKey         69
#define OP_IncrKey            70

#define OP_Goto               71
#define OP_If                 72
#define OP_Halt               73

#define OP_ColumnCount        74
#define OP_ColumnName         75
#define OP_Callback           76
#define OP_NullCallback       77

#define OP_Integer            78
#define OP_String             79
#define OP_Pop                80
#define OP_Dup                81
#define OP_Pull               82
#define OP_Push               83
#define OP_MustBeInt          84

#define OP_Add                85
#define OP_AddImm             86
#define OP_Subtract           87
#define OP_Multiply           88
#define OP_Divide             89
#define OP_Remainder          90
#define OP_BitAnd             91
#define OP_BitOr              92
#define OP_BitNot             93
#define OP_ShiftLeft          94
#define OP_ShiftRight         95
#define OP_AbsValue           96
#define OP_Precision          97
#define OP_Min                98
#define OP_Max                99
#define OP_Like              100
#define OP_Glob              101
#define OP_Eq                102
#define OP_Ne                103
#define OP_Lt                104
#define OP_Le                105
#define OP_Gt                106
#define OP_Ge                107
#define OP_IsNull            108
#define OP_NotNull           109
#define OP_Negative          110
#define OP_And               111
#define OP_Or                112
#define OP_Not               113
#define OP_Concat            114
#define OP_Noop              115

#define OP_Strlen            116
#define OP_Substr            117

#define OP_Limit             118

#define OP_MAX               118

/*
** Prototypes for the VDBE interface.  See comments on the implementation
** for a description of what each of these routines does.
*/
Vdbe *sqliteVdbeCreate(sqlite*);
void sqliteVdbeCreateCallback(Vdbe*, int*);
Changes to test/table.test.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 2001 September 15
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing the CREATE TABLE statement.
#
# $Id: table.test,v 1.14 2002/02/18 18:30:33 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 {













|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 2001 September 15
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing the CREATE TABLE statement.
#
# $Id: table.test,v 1.15 2002/02/21 12:01: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 {
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312













313
314
315
316
317
318
319
320
321
322
323
324
325





326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348



349


350
# 
do_test table-7.1 {
  set v [catch {execsql {
    CREATE TABLE weird(
      desc text,
      asc text,
      explain int,
      vacuum boolean,
      delimiters varchar(10),
      begin blob,
      end clob
    )
  }} msg]
  lappend v $msg
} {0 {}}
do_test table-7.2 {
  execsql {
    INSERT INTO weird VALUES('a','b',9,0,'xyz','hi','y''all');
    SELECT * FROM weird;
  }
} {a b 9 0 xyz hi y'all}
do_test table-7.3 {
  execsql2 {
    SELECT * FROM weird;
  }
} {desc a asc b explain 9 vacuum 0 delimiters xyz begin hi end y'all}

# Try out the CREATE TABLE AS syntax
#
do_test table-8.1 {
  execsql2 {
    CREATE TABLE t2 AS SELECT * FROM weird;
    SELECT * FROM t2;
  }
} {desc a asc b explain 9 vacuum 0 delimiters xyz begin hi end y'all}













do_test table-8.2 {
  execsql {
    CREATE TABLE 't3''xyz'(a,b,c);
    INSERT INTO [t3'xyz] VALUES(1,2,3);
    SELECT * FROM [t3'xyz];
  }
} {1 2 3}
do_test table-8.3 {
  execsql2 {
    CREATE TABLE [t4'abc] AS SELECT count(*), min(a), max(b+c) FROM [t3'xyz];
    SELECT * FROM [t4'abc];
  }
} {count(*) 1 min(a) 1 max(b+c) 5}





do_test table-8.4 {
  execsql2 {
    CREATE TEMPORARY TABLE t5 AS SELECT count(*) AS [y'all] FROM [t3'xyz];
    SELECT * FROM t5;
  }
} {y'all 1}
do_test table-8.5 {
  db close
  sqlite db test.db
  execsql2 {
    SELECT * FROM [t4'abc];
  }
} {count(*) 1 min(a) 1 max(b+c) 5}
do_test table-8.6 {
  execsql2 {
    SELECT * FROM t2;
  }
} {desc a asc b explain 9 vacuum 0 delimiters xyz begin hi end y'all}
do_test table-8.7 {
  catchsql {
    SELECT * FROM t5;
  }
} {1 {no such table: t5}}






finish_test







|
|
















|








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









|


|
>
>
>
>
>












|




|





>
>
>
|
>
>

278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
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
# 
do_test table-7.1 {
  set v [catch {execsql {
    CREATE TABLE weird(
      desc text,
      asc text,
      explain int,
      [14_vac] boolean,
      fuzzy_dog_12 varchar(10),
      begin blob,
      end clob
    )
  }} msg]
  lappend v $msg
} {0 {}}
do_test table-7.2 {
  execsql {
    INSERT INTO weird VALUES('a','b',9,0,'xyz','hi','y''all');
    SELECT * FROM weird;
  }
} {a b 9 0 xyz hi y'all}
do_test table-7.3 {
  execsql2 {
    SELECT * FROM weird;
  }
} {desc a asc b explain 9 14_vac 0 fuzzy_dog_12 xyz begin hi end y'all}

# Try out the CREATE TABLE AS syntax
#
do_test table-8.1 {
  execsql2 {
    CREATE TABLE t2 AS SELECT * FROM weird;
    SELECT * FROM t2;
  }
} {desc a asc b explain 9 14_vac 0 fuzzy_dog_12 xyz begin hi end y'all}
do_test table-8.1.1 {
  execsql {
    SELECT sql FROM sqlite_master WHERE name='t2';
  }
} {{CREATE TABLE t2(
  'desc',
  'asc',
  'explain',
  '14_vac',
  fuzzy_dog_12,
  'begin',
  'end'
)}}
do_test table-8.2 {
  execsql {
    CREATE TABLE 't3''xyz'(a,b,c);
    INSERT INTO [t3'xyz] VALUES(1,2,3);
    SELECT * FROM [t3'xyz];
  }
} {1 2 3}
do_test table-8.3 {
  execsql2 {
    CREATE TABLE [t4'abc] AS SELECT count(*) as cnt, max(b+c) FROM [t3'xyz];
    SELECT * FROM [t4'abc];
  }
} {cnt 1 max(b+c) 5}
do_test table-8.3.1 {
  execsql {
    SELECT sql FROM sqlite_master WHERE name='t4''abc'
  }
} {{CREATE TABLE 't4''abc'(cnt,'max(b+c)')}}
do_test table-8.4 {
  execsql2 {
    CREATE TEMPORARY TABLE t5 AS SELECT count(*) AS [y'all] FROM [t3'xyz];
    SELECT * FROM t5;
  }
} {y'all 1}
do_test table-8.5 {
  db close
  sqlite db test.db
  execsql2 {
    SELECT * FROM [t4'abc];
  }
} {cnt 1 max(b+c) 5}
do_test table-8.6 {
  execsql2 {
    SELECT * FROM t2;
  }
} {desc a asc b explain 9 14_vac 0 fuzzy_dog_12 xyz begin hi end y'all}
do_test table-8.7 {
  catchsql {
    SELECT * FROM t5;
  }
} {1 {no such table: t5}}
do_test table-8.8 {
  catchsql {
    CREATE TABLE t5 AS SELECT * FROM no_such_table;
  }
} {1 {no such table: no_such_table}}

finish_test
Changes to www/changes.tcl.
19
20
21
22
23
24
25


26
27
28
29
30
31
32

chng {2002 Feb * (2.3.4)} {
<li>Change the name of the sanity_check PRAGMA to <b>integrity_check</b>
    and make it available in all compiles.</li>
<li>SELECT min() or max() of an indexed column with no WHERE or GROUP BY
    clause is handled as a special case which avoids a complete table scan.</li>
<li>Automatically generated ROWIDs are now sequential.</li>


}

chng {2002 Feb 18 (2.3.3)} {
<li>Allow identifiers to be quoted in square brackets, for compatibility
    with MS-Access.</li>
<li>Added support for sub-queries in the FROM clause of a SELECT.</li>
<li>More efficient implementation of sqliteFileExists() under Windows.







>
>







19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

chng {2002 Feb * (2.3.4)} {
<li>Change the name of the sanity_check PRAGMA to <b>integrity_check</b>
    and make it available in all compiles.</li>
<li>SELECT min() or max() of an indexed column with no WHERE or GROUP BY
    clause is handled as a special case which avoids a complete table scan.</li>
<li>Automatically generated ROWIDs are now sequential.</li>
<li>Do not allow dot-commands of the command-line shell to occur in the
    middle of a real SQL command.</li>
}

chng {2002 Feb 18 (2.3.3)} {
<li>Allow identifiers to be quoted in square brackets, for compatibility
    with MS-Access.</li>
<li>Added support for sub-queries in the FROM clause of a SELECT.</li>
<li>More efficient implementation of sqliteFileExists() under Windows.