/ Check-in [52338f4a]
Login

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

Overview
Comment::-) (CVS 34)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 52338f4ab5990fefc61f615cd65c3a724b365199
User & Date: drh 2000-06-02 01:17:37
Context
2000-06-02
01:36
:-) (CVS 35) check-in: a57ecd60 user: drh tags: trunk
01:17
:-) (CVS 34) check-in: 52338f4a user: drh tags: trunk
2000-06-01
11:16
:-) (CVS 33) check-in: 6b905636 user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/build.c.

20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
...
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
...
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
...
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
...
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
...
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
...
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
**   drh@hwaci.com
**   http://www.hwaci.com/drh/
**
*************************************************************************
** This file contains C code routines that are called by the parser
** when syntax rules are reduced.
**
** $Id: build.c,v 1.11 2000/05/31 15:34:52 drh Exp $
*/
#include "sqliteInt.h"

/*
** This routine is called after a single SQL statement has been
** parsed and we want to execute the code to implement 
** the statement.  Prior action routines should have already
................................................................................
    pParse->pNewTable = 0;
  }

  /* If not initializing, then create the table on disk.
  */
  if( !pParse->initFlag ){
    static VdbeOp addTable[] = {
      { OP_Open,        0, 0, MASTER_NAME },
      { OP_New,         0, 0, 0},
      { OP_String,      0, 0, "table"     },
      { OP_String,      0, 0, 0},            /* 3 */
      { OP_String,      0, 0, 0},            /* 4 */
      { OP_String,      0, 0, 0},            /* 5 */
      { OP_MakeRecord,  4, 0, 0},
      { OP_Put,         0, 0, 0},
................................................................................
  /* Generate code to remove the table and its reference in sys_master */
  v = pParse->pVdbe;
  if( v==0 ){
    v = pParse->pVdbe = sqliteVdbeCreate(pParse->db->pBe);
  }
  if( v ){
    static VdbeOp dropTable[] = {
      { OP_Open,       0, 0,        MASTER_NAME },
      { OP_ListOpen,   0, 0,        0},
      { OP_String,     0, 0,        0}, /* 2 */
      { OP_Next,       0, ADDR(10), 0}, /* 3 */
      { OP_Dup,        0, 0,        0},
      { OP_Field,      0, 2,        0},
      { OP_Ne,         0, ADDR(3),  0},
      { OP_Key,        0, 0,        0},
................................................................................
  ** command.  The initFlag is 1 when a database is opened and 
  ** CREATE INDEX statements are read out of the master table.  In
  ** the latter case the index already exists on disk, which is why
  ** we don't want to recreate it.
  */
  if( pParse->initFlag==0 ){
    static VdbeOp addTable[] = {
      { OP_Open,        0, 0, MASTER_NAME},
      { OP_New,         0, 0, 0},
      { OP_String,      0, 0, "index"},
      { OP_String,      0, 0, 0},  /* 3 */
      { OP_String,      0, 0, 0},  /* 4 */
      { OP_String,      0, 0, 0},  /* 5 */
      { OP_MakeRecord,  4, 0, 0},
      { OP_Put,         0, 0, 0},
................................................................................
      n = (int)pEnd->z - (int)pStart->z + 1;
      base = sqliteVdbeAddOpList(v, ArraySize(addTable), addTable);
      sqliteVdbeChangeP3(v, base+3, pIndex->zName, 0);
      sqliteVdbeChangeP3(v, base+4, pTab->zName, 0);
      sqliteVdbeChangeP3(v, base+5, pStart->z, n);
    }
    sqliteVdbeAddOp(v, OP_Open, 0, 0, pTab->zName, 0);
    sqliteVdbeAddOp(v, OP_Open, 1, 0, pIndex->zName, 0);
    lbl1 = sqliteVdbeMakeLabel(v);
    lbl2 = sqliteVdbeMakeLabel(v);
    sqliteVdbeAddOp(v, OP_Next, 0, lbl2, 0, lbl1);
    sqliteVdbeAddOp(v, OP_Key, 0, 0, 0, 0);
    for(i=0; i<pIndex->nField; i++){
      sqliteVdbeAddOp(v, OP_Field, 0, pIndex->aiField[i], 0, 0);
    }
................................................................................
    return;
  }

  /* Generate code to remove the index and from the master table */
  v = pParse->pVdbe = sqliteVdbeCreate(pParse->db->pBe);
  if( v ){
    static VdbeOp dropIndex[] = {
      { OP_Open,       0, 0,       MASTER_NAME},
      { OP_ListOpen,   0, 0,       0},
      { OP_String,     0, 0,       0}, /* 2 */
      { OP_Next,       0, ADDR(9), 0}, /* 3 */
      { OP_Dup,        0, 0,       0},
      { OP_Field,      0, 1,       0},
      { OP_Ne,         0, ADDR(3), 0},
      { OP_Key,        0, 0,       0},
................................................................................
    goto copy_cleanup;
  }
  v = pParse->pVdbe = sqliteVdbeCreate(pParse->db->pBe);
  if( v ){
    addr = sqliteVdbeAddOp(v, OP_FileOpen, 0, 0, 0, 0);
    sqliteVdbeChangeP3(v, addr, pFilename->z, pFilename->n);
    sqliteVdbeDequoteP3(v, addr);
    sqliteVdbeAddOp(v, OP_Open, 0, 0, pTab->zName, 0);
    for(i=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
      sqliteVdbeAddOp(v, OP_Open, i, 0, pIdx->zName, 0);
    }
    end = sqliteVdbeMakeLabel(v);
    addr = sqliteVdbeAddOp(v, OP_FileRead, pTab->nCol, end, 0, 0);
    if( pDelimiter ){
      sqliteVdbeChangeP3(v, addr, pDelimiter->z, pDelimiter->n);
      sqliteVdbeDequoteP3(v, addr);
    }else{







|







 







|







 







|







 







|







 







|







 







|







 







|

|







20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
...
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
...
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
...
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
...
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
...
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
...
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
**   drh@hwaci.com
**   http://www.hwaci.com/drh/
**
*************************************************************************
** This file contains C code routines that are called by the parser
** when syntax rules are reduced.
**
** $Id: build.c,v 1.12 2000/06/02 01:17:37 drh Exp $
*/
#include "sqliteInt.h"

/*
** This routine is called after a single SQL statement has been
** parsed and we want to execute the code to implement 
** the statement.  Prior action routines should have already
................................................................................
    pParse->pNewTable = 0;
  }

  /* If not initializing, then create the table on disk.
  */
  if( !pParse->initFlag ){
    static VdbeOp addTable[] = {
      { OP_Open,        0, 1, MASTER_NAME },
      { OP_New,         0, 0, 0},
      { OP_String,      0, 0, "table"     },
      { OP_String,      0, 0, 0},            /* 3 */
      { OP_String,      0, 0, 0},            /* 4 */
      { OP_String,      0, 0, 0},            /* 5 */
      { OP_MakeRecord,  4, 0, 0},
      { OP_Put,         0, 0, 0},
................................................................................
  /* Generate code to remove the table and its reference in sys_master */
  v = pParse->pVdbe;
  if( v==0 ){
    v = pParse->pVdbe = sqliteVdbeCreate(pParse->db->pBe);
  }
  if( v ){
    static VdbeOp dropTable[] = {
      { OP_Open,       0, 1,        MASTER_NAME },
      { OP_ListOpen,   0, 0,        0},
      { OP_String,     0, 0,        0}, /* 2 */
      { OP_Next,       0, ADDR(10), 0}, /* 3 */
      { OP_Dup,        0, 0,        0},
      { OP_Field,      0, 2,        0},
      { OP_Ne,         0, ADDR(3),  0},
      { OP_Key,        0, 0,        0},
................................................................................
  ** command.  The initFlag is 1 when a database is opened and 
  ** CREATE INDEX statements are read out of the master table.  In
  ** the latter case the index already exists on disk, which is why
  ** we don't want to recreate it.
  */
  if( pParse->initFlag==0 ){
    static VdbeOp addTable[] = {
      { OP_Open,        0, 1, MASTER_NAME},
      { OP_New,         0, 0, 0},
      { OP_String,      0, 0, "index"},
      { OP_String,      0, 0, 0},  /* 3 */
      { OP_String,      0, 0, 0},  /* 4 */
      { OP_String,      0, 0, 0},  /* 5 */
      { OP_MakeRecord,  4, 0, 0},
      { OP_Put,         0, 0, 0},
................................................................................
      n = (int)pEnd->z - (int)pStart->z + 1;
      base = sqliteVdbeAddOpList(v, ArraySize(addTable), addTable);
      sqliteVdbeChangeP3(v, base+3, pIndex->zName, 0);
      sqliteVdbeChangeP3(v, base+4, pTab->zName, 0);
      sqliteVdbeChangeP3(v, base+5, pStart->z, n);
    }
    sqliteVdbeAddOp(v, OP_Open, 0, 0, pTab->zName, 0);
    sqliteVdbeAddOp(v, OP_Open, 1, 1, pIndex->zName, 0);
    lbl1 = sqliteVdbeMakeLabel(v);
    lbl2 = sqliteVdbeMakeLabel(v);
    sqliteVdbeAddOp(v, OP_Next, 0, lbl2, 0, lbl1);
    sqliteVdbeAddOp(v, OP_Key, 0, 0, 0, 0);
    for(i=0; i<pIndex->nField; i++){
      sqliteVdbeAddOp(v, OP_Field, 0, pIndex->aiField[i], 0, 0);
    }
................................................................................
    return;
  }

  /* Generate code to remove the index and from the master table */
  v = pParse->pVdbe = sqliteVdbeCreate(pParse->db->pBe);
  if( v ){
    static VdbeOp dropIndex[] = {
      { OP_Open,       0, 1,       MASTER_NAME},
      { OP_ListOpen,   0, 0,       0},
      { OP_String,     0, 0,       0}, /* 2 */
      { OP_Next,       0, ADDR(9), 0}, /* 3 */
      { OP_Dup,        0, 0,       0},
      { OP_Field,      0, 1,       0},
      { OP_Ne,         0, ADDR(3), 0},
      { OP_Key,        0, 0,       0},
................................................................................
    goto copy_cleanup;
  }
  v = pParse->pVdbe = sqliteVdbeCreate(pParse->db->pBe);
  if( v ){
    addr = sqliteVdbeAddOp(v, OP_FileOpen, 0, 0, 0, 0);
    sqliteVdbeChangeP3(v, addr, pFilename->z, pFilename->n);
    sqliteVdbeDequoteP3(v, addr);
    sqliteVdbeAddOp(v, OP_Open, 0, 1, pTab->zName, 0);
    for(i=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
      sqliteVdbeAddOp(v, OP_Open, i, 1, pIdx->zName, 0);
    }
    end = sqliteVdbeMakeLabel(v);
    addr = sqliteVdbeAddOp(v, OP_FileRead, pTab->nCol, end, 0, 0);
    if( pDelimiter ){
      sqliteVdbeChangeP3(v, addr, pDelimiter->z, pDelimiter->n);
      sqliteVdbeDequoteP3(v, addr);
    }else{

Changes to src/dbbe.c.

26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
..
44
45
46
47
48
49
50

51
52
53
54
55
56
57
...
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
...
208
209
210
211
212
213
214
215
216
217
218

219
220
221
222



223

224
225
226
227
228
229
230
231
232
233
234
235







236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263



264







265

266
267
268
269



270
271
272
273
274

275
276
277
278
279
280
281
282
...
289
290
291
292
293
294
295
296


297
298
299
300
301
302
303
...
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
...
508
509
510
511
512
513
514

515
516
517
518
519
520

521
522
523
524
525
526
527
528
529
530

531
532
533
534
535
536

537
538
539
540
541
542
543
544
545
546
547

548
549
550
551
552
553
554
555
556



557
558
559
560
561
562
563
564
565



566
567
568
569
570
571
572
573
574
** sqlite and the code that does the actually reading and writing
** of information to the disk.
**
** This file uses GDBM as the database backend.  It should be
** relatively simple to convert to a different database such
** as NDBM, SDBM, or BerkeleyDB.
**
** $Id: dbbe.c,v 1.6 2000/05/31 22:58:39 drh Exp $
*/
#include "sqliteInt.h"
#include <gdbm.h>
#include <sys/stat.h>
#include <unistd.h>
#include <ctype.h>
#include <time.h>
................................................................................
*/
typedef struct BeFile BeFile;
struct BeFile {
  char *zName;            /* Name of the file */
  GDBM_FILE dbf;          /* The file itself */
  int nRef;               /* Number of references */
  int delOnClose;         /* Delete when closing */

  BeFile *pNext, *pPrev;  /* Next and previous on list of open files */
};

/*
** The following are state variables for the RC4 algorithm.  We
** use RC4 as a random number generator.  Each call to RC4 gives
** a random 8-bit number.
................................................................................
/*
** This routine opens a new database.  For the current driver scheme,
** the database name is the name of the directory
** containing all the files of the database.
*/
Dbbe *sqliteDbbeOpen(
  const char *zName,     /* The name of the database */
  int write,             /* True if we will be writing to the database */
  int create,            /* True to create database if it doesn't exist */
  char **pzErrMsg        /* Write error messages (if any) here */
){
  Dbbe *pNew;
  struct stat statbuf;



  if( stat(zName, &statbuf)!=0 ){


    sqliteSetString(pzErrMsg, "can't find file \"", zName, "\"", 0);

    return 0;

  }
  if( !S_ISDIR(statbuf.st_mode) ){
    sqliteSetString(pzErrMsg, "not a directory: \"", zName, "\"", 0);
    return 0;
  }













  pNew = sqliteMalloc(sizeof(Dbbe) + strlen(zName) + 1);
  if( pNew==0 ){
    sqliteSetString(pzErrMsg, "out of memory", 0);
    return 0;
  }
  pNew->zDir = (char*)&pNew[1];
  strcpy(pNew->zDir, zName);
  pNew->write = write;
  pNew->pOpen = 0;
  time(&statbuf.st_ctime);
  rc4init(&pNew->rc4, (char*)&statbuf, sizeof(statbuf));
  return pNew;
}

/*
................................................................................
  zBuf[j] = 0;
}


/*
** Open a new table cursor
*/
DbbeTable *sqliteDbbeOpenTable(
  Dbbe *pBe,              /* The database the table belongs to */
  const char *zTable,     /* The name of the table */
  int writeable           /* True to open for writing */

){
  char *zFile;            /* Name of the table file */
  DbbeTable *pTable;      /* The new table cursor */
  BeFile *pFile;          /* The underlying data file for this table */





  pTable = sqliteMalloc( sizeof(*pTable) );
  if( pTable==0 ) return 0;
  if( zTable ){
    zFile = sqliteFileOfTable(pBe, zTable);
    for(pFile=pBe->pOpen; pFile; pFile=pFile->pNext){
      if( strcmp(pFile->zName,zFile)==0 ) break;
    }
  }else{
    pFile = 0;
    zFile = 0;
  }
  if( pFile==0 ){







    pFile = sqliteMalloc( sizeof(*pFile) );
    if( pFile==0 ){
      sqliteFree(zFile);
      return 0;
    }
    pFile->zName = zFile;
    pFile->nRef = 1;
    pFile->pPrev = 0;
    if( pBe->pOpen ){
      pBe->pOpen->pPrev = pFile;
    }
    pFile->pNext = pBe->pOpen;
    pBe->pOpen = pFile;
    if( pFile->zName ){
      pFile->dbf = gdbm_open(pFile->zName, 0, GDBM_WRCREAT|GDBM_FAST, 0640, 0);
    }else{
      int limit;
      struct rc4 *pRc4;
      char zRandom[50];
      pRc4 = &pBe->rc4;
      zFile = 0;
      limit = 5;
      do {
        randomName(&pBe->rc4, zRandom, "_temp_table_");
        sqliteFree(zFile);
        zFile = sqliteFileOfTable(pBe, zRandom);
        pFile->dbf = gdbm_open(zFile, 0, GDBM_WRCREAT|GDBM_FAST, 0640, 0);
      }while( pFile->dbf==0 && limit-- >= 0);



      pFile->zName = zFile;







      pFile->delOnClose = 1;

    }
  }else{
    sqliteFree(zFile);
    pFile->nRef++;



  }
  pTable->pBe = pBe;
  pTable->pFile = pFile;
  pTable->readPending = 0;
  pTable->needRewind = 1;

  return pTable;
}

/*
** Drop a table from the database.
*/
void sqliteDbbeDropTable(Dbbe *pBe, const char *zTable){
  char *zFile;            /* Name of the table file */
................................................................................
/*
** Reorganize a table to reduce search times and disk usage.
*/
void sqliteDbbeReorganizeTable(Dbbe *pBe, const char *zTable){
  char *zFile;            /* Name of the table file */
  DbbeTable *pTab;

  pTab = sqliteDbbeOpenTable(pBe, zTable, 1);


  if( pTab && pTab->pFile && pTab->pFile->dbf ){
    gdbm_reorganize(pTab->pFile->dbf);
  }
  if( pTab ){
    sqliteDbbeCloseTable(pTab);
  }
}
................................................................................

/*
** Make is so that the next call to sqliteNextKey() finds the first
** key of the table.
*/
int sqliteDbbeRewind(DbbeTable *pTable){
  pTable->needRewind = 1;
  return 0;
}

/*
** Read the next key from the table.  Return 1 on success.  Return
** 0 if there are no more keys.
*/
int sqliteDbbeNextKey(DbbeTable *pTable){
................................................................................

/*
** Write an entry into the table.  Overwrite any prior entry with the
** same key.
*/
int sqliteDbbePut(DbbeTable *pTable, int nKey,char *pKey,int nData,char *pData){
  datum data, key;

  if( pTable->pFile==0 || pTable->pFile->dbf==0 ) return 0;
  data.dsize = nData;
  data.dptr = pData;
  key.dsize = nKey;
  key.dptr = pKey;
  gdbm_store(pTable->pFile->dbf, key, data, GDBM_REPLACE);

  datumClear(&pTable->key);
  datumClear(&pTable->data);
  return 1;
}

/*
** Remove an entry from a table, if the entry exists.
*/
int sqliteDbbeDelete(DbbeTable *pTable, int nKey, char *pKey){
  datum key;

  datumClear(&pTable->key);
  datumClear(&pTable->data);
  if( pTable->pFile==0 || pTable->pFile->dbf==0 ) return 0;
  key.dsize = nKey;
  key.dptr = pKey;
  gdbm_delete(pTable->pFile->dbf, key);

  return 1;
}

/*
** Open a temporary file.
*/
FILE *sqliteDbbeOpenTempFile(Dbbe *pBe){
  char *zFile;
  char zBuf[50];
  int i, j;
  int limit;


  for(i=0; i<pBe->nTemp; i++){
    if( pBe->apTemp[i]==0 ) break;
  }
  if( i>=pBe->nTemp ){
    pBe->nTemp++;
    pBe->apTemp = sqliteRealloc(pBe->apTemp, pBe->nTemp*sizeof(FILE*) );
  }
  if( pBe->apTemp==0 ) return 0;



  limit = 4;
  zFile = 0;
  do{
    randomName(&pBe->rc4, zBuf, "/_temp_file_");
    sqliteFree(zFile);
    zFile = 0;
    sqliteSetString(&zFile, pBe->zDir, zBuf, 0);
  }while( access(zFile,0)==0 && limit-- >= 0 );
  pBe->apTemp[i] = fopen(zFile, "w+");



  sqliteFree(zFile);
  return pBe->apTemp[i];
}

/*
** Close a temporary file opened using sqliteDbbeOpenTempFile()
*/
void sqliteDbbeCloseTempFile(Dbbe *pBe, FILE *f){
  int i;







|







 







>







 







|
|




>

>

>
>
|
>
|
>





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







|







 







|


|
>




>
>
>

>

|










>
>
>
>
>
>
>



|

<
<
<
<
<
<
<
<

|











|

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




>
>
>





>
|







 







|
>
>







 







|







 







>
|




|
>


|







>


|


|
>
|





|




>








|
>
>
>








|
>
>
>

|







26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
..
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
...
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
...
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272








273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
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
...
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
...
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
...
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
** sqlite and the code that does the actually reading and writing
** of information to the disk.
**
** This file uses GDBM as the database backend.  It should be
** relatively simple to convert to a different database such
** as NDBM, SDBM, or BerkeleyDB.
**
** $Id: dbbe.c,v 1.7 2000/06/02 01:17:37 drh Exp $
*/
#include "sqliteInt.h"
#include <gdbm.h>
#include <sys/stat.h>
#include <unistd.h>
#include <ctype.h>
#include <time.h>
................................................................................
*/
typedef struct BeFile BeFile;
struct BeFile {
  char *zName;            /* Name of the file */
  GDBM_FILE dbf;          /* The file itself */
  int nRef;               /* Number of references */
  int delOnClose;         /* Delete when closing */
  int writeable;          /* Opened for writing */
  BeFile *pNext, *pPrev;  /* Next and previous on list of open files */
};

/*
** The following are state variables for the RC4 algorithm.  We
** use RC4 as a random number generator.  Each call to RC4 gives
** a random 8-bit number.
................................................................................
/*
** This routine opens a new database.  For the current driver scheme,
** the database name is the name of the directory
** containing all the files of the database.
*/
Dbbe *sqliteDbbeOpen(
  const char *zName,     /* The name of the database */
  int writeFlag,         /* True if we will be writing to the database */
  int createFlag,        /* True to create database if it doesn't exist */
  char **pzErrMsg        /* Write error messages (if any) here */
){
  Dbbe *pNew;
  struct stat statbuf;
  char *zMaster;

  if( !writeFlag ) createFlag = 0;
  if( stat(zName, &statbuf)!=0 ){
    if( createFlag ) mkdir(zName, 0750);
    if( stat(zName, &statbuf)!=0 ){
      sqliteSetString(pzErrMsg, "can't find or make directory \"", 
         zName, "\"", 0);
      return 0;
    }
  }
  if( !S_ISDIR(statbuf.st_mode) ){
    sqliteSetString(pzErrMsg, "not a directory: \"", zName, "\"", 0);
    return 0;
  }
  if( access(zName, writeFlag ? (X_OK|W_OK|R_OK) : (X_OK|R_OK)) ){
    sqliteSetString(pzErrMsg, "access permission denied", 0);
    return 0;
  }
  zMaster = 0;
  sqliteSetString(&zMaster, zName, "/" MASTER_NAME, 0);
  if( stat(zMaster, &statbuf)==0
   && access(zMaster, writeFlag ? (W_OK|R_OK) : R_OK)!=0 ){
    sqliteSetString(pzErrMsg, "access permission denied for ", zMaster, 0);
    sqliteFree(zMaster);
    return 0;
  }
  sqliteFree(zMaster);
  pNew = sqliteMalloc(sizeof(Dbbe) + strlen(zName) + 1);
  if( pNew==0 ){
    sqliteSetString(pzErrMsg, "out of memory", 0);
    return 0;
  }
  pNew->zDir = (char*)&pNew[1];
  strcpy(pNew->zDir, zName);
  pNew->write = writeFlag;
  pNew->pOpen = 0;
  time(&statbuf.st_ctime);
  rc4init(&pNew->rc4, (char*)&statbuf, sizeof(statbuf));
  return pNew;
}

/*
................................................................................
  zBuf[j] = 0;
}


/*
** Open a new table cursor
*/
int sqliteDbbeOpenTable(
  Dbbe *pBe,              /* The database the table belongs to */
  const char *zTable,     /* The name of the table */
  int writeable,          /* True to open for writing */
  DbbeTable **ppTable     /* Write the resulting table pointer here */
){
  char *zFile;            /* Name of the table file */
  DbbeTable *pTable;      /* The new table cursor */
  BeFile *pFile;          /* The underlying data file for this table */
  int rc = SQLITE_OK;     /* Return value */
  int rw_mask;            /* Permissions mask for opening a table */
  int mode;               /* Mode for opening a table */

  *ppTable = 0;
  pTable = sqliteMalloc( sizeof(*pTable) );
  if( pTable==0 ) return SQLITE_NOMEM;
  if( zTable ){
    zFile = sqliteFileOfTable(pBe, zTable);
    for(pFile=pBe->pOpen; pFile; pFile=pFile->pNext){
      if( strcmp(pFile->zName,zFile)==0 ) break;
    }
  }else{
    pFile = 0;
    zFile = 0;
  }
  if( pFile==0 ){
    if( writeable ){
      rw_mask = GDBM_WRCREAT | GDBM_FAST;
      mode = 0640;
    }else{
      rw_mask = GDBM_READER;
      mode = 0640;
    }
    pFile = sqliteMalloc( sizeof(*pFile) );
    if( pFile==0 ){
      sqliteFree(zFile);
      return SQLITE_NOMEM;
    }








    if( pFile->zName ){
      pFile->dbf = gdbm_open(pFile->zName, 0, rw_mask, mode, 0);
    }else{
      int limit;
      struct rc4 *pRc4;
      char zRandom[50];
      pRc4 = &pBe->rc4;
      zFile = 0;
      limit = 5;
      do {
        randomName(&pBe->rc4, zRandom, "_temp_table_");
        sqliteFree(zFile);
        zFile = sqliteFileOfTable(pBe, zRandom);
        pFile->dbf = gdbm_open(zFile, 0, rw_mask, mode, 0);
      }while( pFile->dbf==0 && limit-- >= 0);
      pFile->delOnClose = 1;
    }
    pFile->writeable = writeable;
    pFile->zName = zFile;
    pFile->nRef = 1;
    pFile->pPrev = 0;
    if( pBe->pOpen ){
      pBe->pOpen->pPrev = pFile;
    }
    pFile->pNext = pBe->pOpen;
    pBe->pOpen = pFile;
    if( pFile->dbf==0 ){
      rc = SQLITE_BUSY;
    }
  }else{
    sqliteFree(zFile);
    pFile->nRef++;
    if( writeable && !pFile->writeable ){
      rc = SQLITE_READONLY;
    }
  }
  pTable->pBe = pBe;
  pTable->pFile = pFile;
  pTable->readPending = 0;
  pTable->needRewind = 1;
  *ppTable = pTable;
  return rc;
}

/*
** Drop a table from the database.
*/
void sqliteDbbeDropTable(Dbbe *pBe, const char *zTable){
  char *zFile;            /* Name of the table file */
................................................................................
/*
** Reorganize a table to reduce search times and disk usage.
*/
void sqliteDbbeReorganizeTable(Dbbe *pBe, const char *zTable){
  char *zFile;            /* Name of the table file */
  DbbeTable *pTab;

  if( sqliteDbbeOpenTable(pBe, zTable, 1, &pTab)!=SQLITE_OK ){
    return;
  }
  if( pTab && pTab->pFile && pTab->pFile->dbf ){
    gdbm_reorganize(pTab->pFile->dbf);
  }
  if( pTab ){
    sqliteDbbeCloseTable(pTab);
  }
}
................................................................................

/*
** Make is so that the next call to sqliteNextKey() finds the first
** key of the table.
*/
int sqliteDbbeRewind(DbbeTable *pTable){
  pTable->needRewind = 1;
  return SQLITE_OK;
}

/*
** Read the next key from the table.  Return 1 on success.  Return
** 0 if there are no more keys.
*/
int sqliteDbbeNextKey(DbbeTable *pTable){
................................................................................

/*
** Write an entry into the table.  Overwrite any prior entry with the
** same key.
*/
int sqliteDbbePut(DbbeTable *pTable, int nKey,char *pKey,int nData,char *pData){
  datum data, key;
  int rc;
  if( pTable->pFile==0 || pTable->pFile->dbf==0 ) return SQLITE_ERROR;
  data.dsize = nData;
  data.dptr = pData;
  key.dsize = nKey;
  key.dptr = pKey;
  rc = gdbm_store(pTable->pFile->dbf, key, data, GDBM_REPLACE);
  if( rc ) rc = SQLITE_ERROR;
  datumClear(&pTable->key);
  datumClear(&pTable->data);
  return rc;
}

/*
** Remove an entry from a table, if the entry exists.
*/
int sqliteDbbeDelete(DbbeTable *pTable, int nKey, char *pKey){
  datum key;
  int rc;
  datumClear(&pTable->key);
  datumClear(&pTable->data);
  if( pTable->pFile==0 || pTable->pFile->dbf==0 ) return SQLITE_ERROR;
  key.dsize = nKey;
  key.dptr = pKey;
  rc = gdbm_delete(pTable->pFile->dbf, key);
  if( rc ) rc = SQLITE_ERROR;
  return rc;
}

/*
** Open a temporary file.
*/
int sqliteDbbeOpenTempFile(Dbbe *pBe, FILE **ppFile){
  char *zFile;
  char zBuf[50];
  int i, j;
  int limit;
  int rc = SQLITE_OK;

  for(i=0; i<pBe->nTemp; i++){
    if( pBe->apTemp[i]==0 ) break;
  }
  if( i>=pBe->nTemp ){
    pBe->nTemp++;
    pBe->apTemp = sqliteRealloc(pBe->apTemp, pBe->nTemp*sizeof(FILE*) );
  }
  if( pBe->apTemp==0 ){
    *ppFile = 0;
    return SQLITE_NOMEM;
  }
  limit = 4;
  zFile = 0;
  do{
    randomName(&pBe->rc4, zBuf, "/_temp_file_");
    sqliteFree(zFile);
    zFile = 0;
    sqliteSetString(&zFile, pBe->zDir, zBuf, 0);
  }while( access(zFile,0)==0 && limit-- >= 0 );
  *ppFile = pBe->apTemp[i] = fopen(zFile, "w+");
  if( pBe->apTemp[i]==0 ){
    rc = SQLITE_ERROR;
  }
  sqliteFree(zFile);
  return rc;
}

/*
** Close a temporary file opened using sqliteDbbeOpenTempFile()
*/
void sqliteDbbeCloseTempFile(Dbbe *pBe, FILE *f){
  int i;

Changes to src/dbbe.h.

24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
..
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
...
118
119
120
121
122
123
124
125
126
127
128
129
130
** This file defines the interface to the database backend (Dbbe).
**
** The database backend is designed to be as general as possible
** so that it can easily be replaced by a different backend.
** This library was originally designed to support the following
** backends: GDBM, NDBM, SDBM, Berkeley DB.
**
** $Id: dbbe.h,v 1.3 2000/05/31 20:00:52 drh Exp $
*/
#ifndef _SQLITE_DBBE_H_
#define _SQLITE_DBBE_H_
#include <stdio.h>

/*
** The database backend supports two opaque structures.  A Dbbe is
................................................................................

/* Open a particular table of a previously opened database.
** Create the table if it doesn't already exist and writeable!=0.
**
** If zTableName is 0 or "", then a temporary table is created that
** will be deleted when closed.
*/
DbbeTable *sqliteDbbeOpenTable(Dbbe*, const char *zTableName, int writeable);

/* Delete a table from the database */
void sqliteDbbeDropTable(Dbbe*, const char *zTableName);

/* Reorganize a table to speed access or reduce its disk usage */
void sqliteDbbeReorganizeTable(Dbbe*, const char *zTableName);

................................................................................
*/
int sqliteDbbePut(DbbeTable*, int nKey, char *pKey, int nData, char *pData);

/* Remove an entry from the table */
int sqliteDbbeDelete(DbbeTable*, int nKey, char *pKey);

/* Open a file suitable for temporary storage */
FILE *sqliteDbbeOpenTempFile(Dbbe*);

/* Close a temporary file */
void sqliteDbbeCloseTempFile(Dbbe *, FILE *);

#endif /* defined(_SQLITE_DBBE_H_) */







|







 







|







 







|





24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
..
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
...
118
119
120
121
122
123
124
125
126
127
128
129
130
** This file defines the interface to the database backend (Dbbe).
**
** The database backend is designed to be as general as possible
** so that it can easily be replaced by a different backend.
** This library was originally designed to support the following
** backends: GDBM, NDBM, SDBM, Berkeley DB.
**
** $Id: dbbe.h,v 1.4 2000/06/02 01:17:37 drh Exp $
*/
#ifndef _SQLITE_DBBE_H_
#define _SQLITE_DBBE_H_
#include <stdio.h>

/*
** The database backend supports two opaque structures.  A Dbbe is
................................................................................

/* Open a particular table of a previously opened database.
** Create the table if it doesn't already exist and writeable!=0.
**
** If zTableName is 0 or "", then a temporary table is created that
** will be deleted when closed.
*/
int sqliteDbbeOpenTable(Dbbe*, const char *zName, int writeable, DbbeTable **);

/* Delete a table from the database */
void sqliteDbbeDropTable(Dbbe*, const char *zTableName);

/* Reorganize a table to speed access or reduce its disk usage */
void sqliteDbbeReorganizeTable(Dbbe*, const char *zTableName);

................................................................................
*/
int sqliteDbbePut(DbbeTable*, int nKey, char *pKey, int nData, char *pData);

/* Remove an entry from the table */
int sqliteDbbeDelete(DbbeTable*, int nKey, char *pKey);

/* Open a file suitable for temporary storage */
int sqliteDbbeOpenTempFile(Dbbe*, FILE**);

/* Close a temporary file */
void sqliteDbbeCloseTempFile(Dbbe *, FILE *);

#endif /* defined(_SQLITE_DBBE_H_) */

Changes to src/delete.c.

20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
..
99
100
101
102
103
104
105

106
107
108
109
110
111
112
113
114
**   drh@hwaci.com
**   http://www.hwaci.com/drh/
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle DELETE FROM statements.
**
** $Id: delete.c,v 1.1 2000/05/31 15:34:53 drh Exp $
*/
#include "sqliteInt.h"

/*
** Process a DELETE FROM statement.
*/
void sqliteDeleteFrom(
................................................................................
  /* End the database scan loop.
  */
  sqliteWhereEnd(pWInfo);

  /* Delete every item identified in the list.
  */
  sqliteVdbeAddOp(v, OP_ListRewind, 0, 0, 0, 0);

  for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
    sqliteVdbeAddOp(v, OP_Open, i, 0, pIdx->zName, 0);
  }
  end = sqliteVdbeMakeLabel(v);
  addr = sqliteVdbeAddOp(v, OP_ListRead, 0, end, 0, 0);
  if( pTab->pIndex ){
    sqliteVdbeAddOp(v, OP_Dup, 0, 0, 0, 0);
    sqliteVdbeAddOp(v, OP_Fetch, 0, 0, 0, 0);
    for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){







|







 







>

|







20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
..
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
**   drh@hwaci.com
**   http://www.hwaci.com/drh/
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle DELETE FROM statements.
**
** $Id: delete.c,v 1.2 2000/06/02 01:17:37 drh Exp $
*/
#include "sqliteInt.h"

/*
** Process a DELETE FROM statement.
*/
void sqliteDeleteFrom(
................................................................................
  /* End the database scan loop.
  */
  sqliteWhereEnd(pWInfo);

  /* Delete every item identified in the list.
  */
  sqliteVdbeAddOp(v, OP_ListRewind, 0, 0, 0, 0);
  sqliteVdbeAddOp(v, OP_Open, 0, 1, pTab->zName, 0);
  for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
    sqliteVdbeAddOp(v, OP_Open, i, 1, pIdx->zName, 0);
  }
  end = sqliteVdbeMakeLabel(v);
  addr = sqliteVdbeAddOp(v, OP_ListRead, 0, end, 0, 0);
  if( pTab->pIndex ){
    sqliteVdbeAddOp(v, OP_Dup, 0, 0, 0, 0);
    sqliteVdbeAddOp(v, OP_Fetch, 0, 0, 0, 0);
    for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){

Changes to src/insert.c.

20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
...
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
...
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
**   drh@hwaci.com
**   http://www.hwaci.com/drh/
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle INSERT statements.
**
** $Id: insert.c,v 1.1 2000/05/31 15:34:53 drh Exp $
*/
#include "sqliteInt.h"

/*
** This routine is call to handle SQL of the following form:
**
**    insert into TABLE (IDLIST) values(EXPRLIST)
................................................................................
        goto insert_cleanup;
      }
    }
  }
  v = pParse->pVdbe = sqliteVdbeCreate(pParse->db->pBe);
  if( v ){
    Index *pIdx;
    sqliteVdbeAddOp(v, OP_Open, 0, 0, pTab->zName, 0);
    sqliteVdbeAddOp(v, OP_New, 0, 0, 0, 0);
    if( pTab->pIndex ){
      sqliteVdbeAddOp(v, OP_Dup, 0, 0, 0, 0);
    }
    for(i=0; i<pTab->nCol; i++){
      if( pField==0 ){
        j = i;
................................................................................
    sqliteVdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0, 0, 0);
    sqliteVdbeAddOp(v, OP_Put, 0, 0, 0, 0);
    sqliteVdbeAddOp(v, OP_Close, 0, 0, 0, 0);
    for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
      if( pIdx->pNext ){
        sqliteVdbeAddOp(v, OP_Dup, 0, 0, 0, 0);
      }
      sqliteVdbeAddOp(v, OP_Open, 0, 0, pIdx->zName, 0);
      for(i=0; i<pIdx->nField; i++){
        int idx = pIdx->aiField[i];
        if( pField==0 ){
          j = idx;
        }else{
          for(j=0; j<pField->nId; j++){
            if( pField->a[j].idx==idx ) break;







|







 







|







 







|







20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
...
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
...
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
**   drh@hwaci.com
**   http://www.hwaci.com/drh/
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle INSERT statements.
**
** $Id: insert.c,v 1.2 2000/06/02 01:17:37 drh Exp $
*/
#include "sqliteInt.h"

/*
** This routine is call to handle SQL of the following form:
**
**    insert into TABLE (IDLIST) values(EXPRLIST)
................................................................................
        goto insert_cleanup;
      }
    }
  }
  v = pParse->pVdbe = sqliteVdbeCreate(pParse->db->pBe);
  if( v ){
    Index *pIdx;
    sqliteVdbeAddOp(v, OP_Open, 0, 1, pTab->zName, 0);
    sqliteVdbeAddOp(v, OP_New, 0, 0, 0, 0);
    if( pTab->pIndex ){
      sqliteVdbeAddOp(v, OP_Dup, 0, 0, 0, 0);
    }
    for(i=0; i<pTab->nCol; i++){
      if( pField==0 ){
        j = i;
................................................................................
    sqliteVdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0, 0, 0);
    sqliteVdbeAddOp(v, OP_Put, 0, 0, 0, 0);
    sqliteVdbeAddOp(v, OP_Close, 0, 0, 0, 0);
    for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
      if( pIdx->pNext ){
        sqliteVdbeAddOp(v, OP_Dup, 0, 0, 0, 0);
      }
      sqliteVdbeAddOp(v, OP_Open, 0, 1, pIdx->zName, 0);
      for(i=0; i<pIdx->nField; i++){
        int idx = pIdx->aiField[i];
        if( pField==0 ){
          j = idx;
        }else{
          for(j=0; j<pField->nId; j++){
            if( pField->a[j].idx==idx ) break;

Changes to src/main.c.

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

56
57
58
59
60
61




62
63
64
65
66
67
68
...
112
113
114
115
116
117
118
119





































120
121
122
123
124
125
126
...
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
...
204
205
206
207
208
209
210
211
212
213




214
215
216
217
218
219
220
221
**
*************************************************************************
** 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.2 2000/05/31 22:58:39 drh Exp $
*/
#include "sqliteInt.h"

/*
** This is the callback routine for the code that initializes the
** database.  Each callback contains text of a CREATE TABLE or
** CREATE INDEX statement that must be parsed to yield the internal
................................................................................
  sParse.db = db;
  sParse.initFlag = 1;
  nErr = sqliteRunParser(&sParse, argv[0], &zErrMsg);
  return nErr;
}

/*
** Open a new SQLite database.  Construct an "sqlite" structure to define
** the state of this database and return a pointer to that structure.

*/
sqlite *sqlite_open(const char *zFilename, int mode, char **pzErrMsg){
  sqlite *db;
  Vdbe *vdbe;
  Table *pTab;
  char *azArg[2];




  static char master_schema[] = 
     "CREATE TABLE " MASTER_NAME " (\n"
     "  type text,\n"
     "  name text,\n"
     "  tbl_name text,\n"
     "  sql text\n"
     ")"
................................................................................
    { OP_Ne,       0, 9,  0},
    { OP_Field,    0, 3,  0},
    { OP_Callback, 1, 0,  0},
    { OP_Goto,     0, 9,  0},
    { OP_Halt,     0, 0,  0},           /* 16 */
  };

  /* Allocate space to hold the main database structure */





































  db = sqliteMalloc( sizeof(sqlite) );
  if( pzErrMsg ) *pzErrMsg = 0;
  if( db==0 ){
    sqliteSetString(pzErrMsg, "out of memory", 0);
    sqliteStrRealloc(pzErrMsg);
    return 0;
  }
................................................................................
  /* Open the backend database driver */
  db->pBe = sqliteDbbeOpen(zFilename, (mode&0222)!=0, mode!=0, pzErrMsg);
  if( db->pBe==0 ){
    sqliteFree(db);
    return 0;
  }

  /* Create a virtual machine to run the initialization program.  Run
  ** the program.  The delete the virtual machine.
  */

  azArg[0] = master_schema;
  azArg[1] = 0;
  sqliteOpenCb(db, 1, azArg, 0);
  pTab = sqliteFindTable(db, MASTER_NAME);
  if( pTab ){
    pTab->readOnly = 1;
  }
  vdbe = sqliteVdbeCreate(db->pBe);
  sqliteVdbeAddOpList(vdbe, sizeof(initProg)/sizeof(initProg[0]), initProg);
  sqliteVdbeExec(vdbe, sqliteOpenCb, db, pzErrMsg);
  sqliteVdbeDelete(vdbe);
  return db;
}

/*
** Close an existing SQLite database
*/
void sqlite_close(sqlite *db){
................................................................................
  sqlite *db,                 /* The database on which the SQL executes */
  char *zSql,                 /* The SQL to be executed */
  sqlite_callback xCallback,  /* Invoke this callback routine */
  void *pArg,                 /* First argument to xCallback() */
  char **pzErrMsg             /* Write error messages here */
){
  Parse sParse;
  int nErr;

  if( pzErrMsg ) *pzErrMsg = 0;




  memset(&sParse, 0, sizeof(sParse));
  sParse.db = db;
  sParse.xCallback = xCallback;
  sParse.pArg = pArg;
  nErr = sqliteRunParser(&sParse, zSql, pzErrMsg);
  sqliteStrRealloc(pzErrMsg);
  return nErr;
}







|







 







|
|
>

<
|

|
<
>
>
>
>







 







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







 







|
|
<
>
|
|
<
<
<
<

<
<
<
<







 







|


>
>
>
>




|

|

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

58
59
60

61
62
63
64
65
66
67
68
69
70
71
...
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
...
168
169
170
171
172
173
174
175
176

177
178
179




180




181
182
183
184
185
186
187
...
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
**
*************************************************************************
** 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.3 2000/06/02 01:17:37 drh Exp $
*/
#include "sqliteInt.h"

/*
** This is the callback routine for the code that initializes the
** database.  Each callback contains text of a CREATE TABLE or
** CREATE INDEX statement that must be parsed to yield the internal
................................................................................
  sParse.db = db;
  sParse.initFlag = 1;
  nErr = sqliteRunParser(&sParse, argv[0], &zErrMsg);
  return nErr;
}

/*
** Attempt to read the database schema and initialize internal
** data structures.  Return one of the SQLITE_ error codes to
** indicate success or failure.
*/

static int sqliteInit(sqlite *db, char **pzErrMsg){
  Vdbe *vdbe;
  int rc;


  /*
  ** The master database table has a structure like this
  */
  static char master_schema[] = 
     "CREATE TABLE " MASTER_NAME " (\n"
     "  type text,\n"
     "  name text,\n"
     "  tbl_name text,\n"
     "  sql text\n"
     ")"
................................................................................
    { OP_Ne,       0, 9,  0},
    { OP_Field,    0, 3,  0},
    { OP_Callback, 1, 0,  0},
    { OP_Goto,     0, 9,  0},
    { OP_Halt,     0, 0,  0},           /* 16 */
  };

  /* Create a virtual machine to run the initialization program.  Run
  ** the program.  The delete the virtual machine.
  */
  vdbe = sqliteVdbeCreate(db->pBe);
  sqliteVdbeAddOpList(vdbe, sizeof(initProg)/sizeof(initProg[0]), initProg);
  rc = sqliteVdbeExec(vdbe, sqliteOpenCb, db, pzErrMsg);
  sqliteVdbeDelete(vdbe);
  if( rc==SQLITE_OK ){
    Table *pTab;
    char *azArg[2];
    azArg[0] = master_schema;
    azArg[1] = 0;
    sqliteOpenCb(db, 1, azArg, 0);
    pTab = sqliteFindTable(db, MASTER_NAME);
    if( pTab ){
      pTab->readOnly = 1;
    }
    db->flags |= SQLITE_Initialized;
  }else{
    sqliteStrRealloc(pzErrMsg);
  }
  return rc;
}

/*
** Open a new SQLite database.  Construct an "sqlite" structure to define
** the state of this database and return a pointer to that structure.
**
** An attempt is made to initialize the in-memory data structures that
** hold the database schema.  But if this fails (because the schema file
** is locked) then that step is deferred until the first call to
** sqlite_exec().
*/
sqlite *sqlite_open(const char *zFilename, int mode, char **pzErrMsg){
  sqlite *db;
  int rc;

  /* Allocate the sqlite data structure */
  db = sqliteMalloc( sizeof(sqlite) );
  if( pzErrMsg ) *pzErrMsg = 0;
  if( db==0 ){
    sqliteSetString(pzErrMsg, "out of memory", 0);
    sqliteStrRealloc(pzErrMsg);
    return 0;
  }
................................................................................
  /* Open the backend database driver */
  db->pBe = sqliteDbbeOpen(zFilename, (mode&0222)!=0, mode!=0, pzErrMsg);
  if( db->pBe==0 ){
    sqliteFree(db);
    return 0;
  }

  /* Attempt to read the schema */
  rc = sqliteInit(db, pzErrMsg);

  if( rc!=SQLITE_OK && rc!=SQLITE_BUSY ){
    sqlite_close(db);
    return 0;




  }




  return db;
}

/*
** Close an existing SQLite database
*/
void sqlite_close(sqlite *db){
................................................................................
  sqlite *db,                 /* The database on which the SQL executes */
  char *zSql,                 /* The SQL to be executed */
  sqlite_callback xCallback,  /* Invoke this callback routine */
  void *pArg,                 /* First argument to xCallback() */
  char **pzErrMsg             /* Write error messages here */
){
  Parse sParse;
  int rc;

  if( pzErrMsg ) *pzErrMsg = 0;
  if( (db->flags & SQLITE_Initialized)==0 ){
    int rc = sqliteInit(db, pzErrMsg);
    if( rc!=SQLITE_OK ) return rc;
  }
  memset(&sParse, 0, sizeof(sParse));
  sParse.db = db;
  sParse.xCallback = xCallback;
  sParse.pArg = pArg;
  rc = sqliteRunParser(&sParse, zSql, pzErrMsg);
  sqliteStrRealloc(pzErrMsg);
  return rc;
}

Changes to src/sqlite.h.

20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
..
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
..
91
92
93
94
95
96
97
98





99
100
101
102
103
104
105
106
107










108
109
110
111
112
113
114
115
116
117
118
**   drh@hwaci.com
**   http://www.hwaci.com/drh/
**
*************************************************************************
** This header file defines the interface that the sqlite library
** presents to client programs.
**
** @(#) $Id: sqlite.h,v 1.1 2000/05/29 14:26:01 drh Exp $
*/
#ifndef _SQLITE_H_
#define _SQLITE_H_

/*
** Each open sqlite database is represented by an instance of the
** following opaque structure.
................................................................................
** A function to executes one or more statements of SQL.
**
** If one or more of the SQL statements are queries, then
** the callback function specified by the 3rd parameter is
** invoked once for each row of the query result.  This callback
** should normally return 0.  If the callback returns a non-zero
** value then the query is aborted, all subsequent SQL statements
** are skipped and the sqlite_exec() function returns the same
** value that the callback returned.
**
** The 4th parameter is an arbitrary pointer that is passed
** to the callback function as its first parameter.
**
** The 2nd parameter to the callback function is the number of
** columns in the query result.  The 3rd parameter is an array
** of string holding the values for each column.  The 4th parameter
................................................................................
** will be invoked.
**
** If an error occurs while parsing or evaluating the SQL (but
** not while executing the callback) then an appropriate error
** message is written into memory obtained from malloc() and
** *errmsg is made to point to that message.  If errmsg==NULL,
** then no error message is ever written.  The return value is
** non-zero if an error occurs.





*/
int sqlite_exec(
  sqlite*,                      /* An open database */
  char *sql,                    /* SQL to be executed */
  sqlite_callback,              /* Callback function */
  void *,                       /* 1st argument to callback function */
  char **errmsg                 /* Error msg written here */
);












/* This function returns true if the given input string comprises
** one or more complete SQL statements.
**
** The algorithm is simple.  If the last token other than spaces
** and comments is a semicolon, then return true.  otherwise return
** false.
*/
int sqlite_complete(const char *sql);

#endif /* _SQLITE_H_ */







|







 







|
<







 







|
>
>
>
>
>









>
>
>
>
>
>
>
>
>
>











20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
..
71
72
73
74
75
76
77
78

79
80
81
82
83
84
85
..
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
**   drh@hwaci.com
**   http://www.hwaci.com/drh/
**
*************************************************************************
** This header file defines the interface that the sqlite library
** presents to client programs.
**
** @(#) $Id: sqlite.h,v 1.2 2000/06/02 01:17:38 drh Exp $
*/
#ifndef _SQLITE_H_
#define _SQLITE_H_

/*
** Each open sqlite database is represented by an instance of the
** following opaque structure.
................................................................................
** A function to executes one or more statements of SQL.
**
** If one or more of the SQL statements are queries, then
** the callback function specified by the 3rd parameter is
** invoked once for each row of the query result.  This callback
** should normally return 0.  If the callback returns a non-zero
** value then the query is aborted, all subsequent SQL statements
** are skipped and the sqlite_exec() function returns the SQLITE_ABORT.

**
** The 4th parameter is an arbitrary pointer that is passed
** to the callback function as its first parameter.
**
** The 2nd parameter to the callback function is the number of
** columns in the query result.  The 3rd parameter is an array
** of string holding the values for each column.  The 4th parameter
................................................................................
** will be invoked.
**
** If an error occurs while parsing or evaluating the SQL (but
** not while executing the callback) then an appropriate error
** message is written into memory obtained from malloc() and
** *errmsg is made to point to that message.  If errmsg==NULL,
** then no error message is ever written.  The return value is
** SQLITE_ERROR if an error occurs.
**
** If the query could not be executed because a database file is
** locked or busy, then this function returns SQLITE_BUSY.  If
** the query could not be executed because a file is missing or
** has incorrect permissions, this function returns SQLITE_ERROR.
*/
int sqlite_exec(
  sqlite*,                      /* An open database */
  char *sql,                    /* SQL to be executed */
  sqlite_callback,              /* Callback function */
  void *,                       /* 1st argument to callback function */
  char **errmsg                 /* Error msg written here */
);

/*
** Return values fro sqlite_exec()
*/
#define SQLITE_OK        0    /* Successful result */
#define SQLITE_INTERNAL  1    /* An internal logic error in SQLite */
#define SQLITE_ERROR     2    /* SQL error or missing database */
#define SQLITE_ABORT     3    /* Callback routine requested an abort */
#define SQLITE_BUSY      4    /* One or more database files are locked */
#define SQLITE_NOMEM     5    /* A malloc() failed */


/* This function returns true if the given input string comprises
** one or more complete SQL statements.
**
** The algorithm is simple.  If the last token other than spaces
** and comments is a semicolon, then return true.  otherwise return
** false.
*/
int sqlite_complete(const char *sql);

#endif /* _SQLITE_H_ */

Changes to src/sqliteInt.h.

19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
..
97
98
99
100
101
102
103








104
105
106
107
108
109
110
** Author contact information:
**   drh@hwaci.com
**   http://www.hwaci.com/drh/
**
*************************************************************************
** Internal interface definitions for SQLite.
**
** @(#) $Id: sqliteInt.h,v 1.7 2000/05/31 22:58:39 drh Exp $
*/
#include "sqlite.h"
#include "dbbe.h"
#include "vdbe.h"
#include "parse.h"
#include <gdbm.h>
#include <stdio.h>
................................................................................
  Index *apIdxHash[N_HASH];  /* All indices of the database */
};

/*
** Possible values for the flags field of sqlite
*/
#define SQLITE_VdbeTrace    0x00000001









/*
** Each table is represented in memory by
** an instance of the following structure
*/
struct Table {
  char *zName;        /* Name of the table */







|







 







>
>
>
>
>
>
>
>







19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
..
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
** Author contact information:
**   drh@hwaci.com
**   http://www.hwaci.com/drh/
**
*************************************************************************
** Internal interface definitions for SQLite.
**
** @(#) $Id: sqliteInt.h,v 1.8 2000/06/02 01:17:38 drh Exp $
*/
#include "sqlite.h"
#include "dbbe.h"
#include "vdbe.h"
#include "parse.h"
#include <gdbm.h>
#include <stdio.h>
................................................................................
  Index *apIdxHash[N_HASH];  /* All indices of the database */
};

/*
** Possible values for the flags field of sqlite
*/
#define SQLITE_VdbeTrace    0x00000001
#define SQLITE_Initialized  0x00000002

/*
** Values for SQLITE_OK, SQLITE_ERROR, etc are defined in sqlite.h.
** The following are several new return codes that are used internally
** only.  Take care that these values do not overlap.
*/
#define SQLITE_READONLY   6    /* Table already opened as read-only */

/*
** Each table is represented in memory by
** an instance of the following structure
*/
struct Table {
  char *zName;        /* Name of the table */

Changes to src/tclsqlite.c.

19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
...
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
** Author contact information:
**   drh@hwaci.com
**   http://www.hwaci.com/drh/
**
*************************************************************************
** A TCL Interface to SQLite
**
** $Id: tclsqlite.c,v 1.3 2000/05/30 13:44:20 drh Exp $
*/
#include "sqlite.h"
#include <tcl.h>
#include <stdlib.h>
#include <string.h>

/*
................................................................................
  char *zErrMsg;
  if( argc!=3 && argc!=4 ){
    Tcl_AppendResult(interp,"wrong # args: should be \"", argv[0],
       " HANDLE FILENAME ?MODE?\"", 0);
    return TCL_ERROR;
  }
  if( argc==3 ){
    mode = 0;
  }else if( Tcl_GetInt(interp, argv[3], &mode)!=TCL_OK ){
    return TCL_ERROR;
  }
  zErrMsg = 0;
  p = sqlite_open(argv[2], mode, &zErrMsg);
  if( p==0 ){
    Tcl_SetResult(interp, zErrMsg, TCL_VOLATILE);







|







 







|







19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
...
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
** Author contact information:
**   drh@hwaci.com
**   http://www.hwaci.com/drh/
**
*************************************************************************
** A TCL Interface to SQLite
**
** $Id: tclsqlite.c,v 1.4 2000/06/02 01:17:38 drh Exp $
*/
#include "sqlite.h"
#include <tcl.h>
#include <stdlib.h>
#include <string.h>

/*
................................................................................
  char *zErrMsg;
  if( argc!=3 && argc!=4 ){
    Tcl_AppendResult(interp,"wrong # args: should be \"", argv[0],
       " HANDLE FILENAME ?MODE?\"", 0);
    return TCL_ERROR;
  }
  if( argc==3 ){
    mode = 0666;
  }else if( Tcl_GetInt(interp, argv[3], &mode)!=TCL_OK ){
    return TCL_ERROR;
  }
  zErrMsg = 0;
  p = sqlite_open(argv[2], mode, &zErrMsg);
  if( p==0 ){
    Tcl_SetResult(interp, zErrMsg, TCL_VOLATILE);

Changes to src/update.c.

20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
...
151
152
153
154
155
156
157

158
159
160
161
162
163
164
165
166
**   drh@hwaci.com
**   http://www.hwaci.com/drh/
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle UPDATE statements.
**
** $Id: update.c,v 1.1 2000/05/31 15:34:53 drh Exp $
*/
#include "sqliteInt.h"

/*
** Process an UPDATE statement.
*/
void sqliteUpdate(
................................................................................
  */
  sqliteWhereEnd(pWInfo);

  /* Rewind the list of records that need to be updated and
  ** open every index that needs updating.
  */
  sqliteVdbeAddOp(v, OP_ListRewind, 0, 0, 0, 0);

  for(i=0; i<nIdx; i++){
    sqliteVdbeAddOp(v, OP_Open, i+1, 0, apIdx[i]->zName, 0);
  }

  /* Loop over every record that needs updating.  We have to load
  ** the old data for each record to be updated because some fields
  ** might not change and we will need to copy the old value, therefore.
  ** Also, the old data is needed to delete the old index entires.
  */







|







 







>

|







20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
...
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
**   drh@hwaci.com
**   http://www.hwaci.com/drh/
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle UPDATE statements.
**
** $Id: update.c,v 1.2 2000/06/02 01:17:38 drh Exp $
*/
#include "sqliteInt.h"

/*
** Process an UPDATE statement.
*/
void sqliteUpdate(
................................................................................
  */
  sqliteWhereEnd(pWInfo);

  /* Rewind the list of records that need to be updated and
  ** open every index that needs updating.
  */
  sqliteVdbeAddOp(v, OP_ListRewind, 0, 0, 0, 0);
  sqliteVdbeAddOp(v, OP_Open, 0, 1, pTab->zName, 0);
  for(i=0; i<nIdx; i++){
    sqliteVdbeAddOp(v, OP_Open, i+1, 1, apIdx[i]->zName, 0);
  }

  /* Loop over every record that needs updating.  We have to load
  ** the old data for each record to be updated because some fields
  ** might not change and we will need to copy the old value, therefore.
  ** Also, the old data is needed to delete the old index entires.
  */

Changes to src/vdbe.c.

37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
...
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464


465
466
467
468
469
470
471
...
562
563
564
565
566
567
568
569
570







571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
...
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
...
739
740
741
742
743
744
745
746


747
748
749
750
751
752
753
...
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
...
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
....
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
....
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
....
1347
1348
1349
1350
1351
1352
1353
1354

1355
1356
1357
1358
1359
1360
1361
....
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
....
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
....
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
....
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
....
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
....
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
....
2014
2015
2016
2017
2018
2019
2020
2021


2022
2023
2024
2025
2026
2027
2028
....
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
....
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
....
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200




2201
2202
2203
2204
2205
2206
2207
....
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
** inplicit conversion from one type to the other occurs as necessary.
** 
** Most of the code in this file is taken up by the sqliteVdbeExec()
** function which does the work of interpreting a VDBE program.
** But other routines are also provided to help in building up
** a program instruction by instruction.
**
** $Id: vdbe.c,v 1.6 2000/06/01 11:16:52 drh Exp $
*/
#include "sqliteInt.h"

/*
** SQL is translated into a sequence of instructions to be
** executed by a virtual machine.  Each instruction is an instance
** of the following structure.
................................................................................
  };

  if( xCallback==0 ) return 0;
  azField[0] = zAddr;
  azField[2] = zP1;
  azField[3] = zP2;
  azField[5] = 0;
  rc = 0;
  if( pzErrMsg ){ *pzErrMsg = 0; }
  for(i=0; rc==0 && i<p->nOp; i++){
    sprintf(zAddr,"%d",i);
    sprintf(zP1,"%d", p->aOp[i].p1);
    sprintf(zP2,"%d", p->aOp[i].p2);
    azField[4] = p->aOp[i].p3;
    if( azField[4]==0 ) azField[4] = "";
    azField[1] = zOpName[p->aOp[i].opcode];
    rc = xCallback(pArg, 5, azField, azColumnNames);


  }
  return rc;
}

/*
** Make sure space has been allocated to hold at least N
** stack elements.  Allocate additional stack space if
................................................................................
** Execute the program in the VDBE.
**
** If an error occurs, an error message is written to memory obtained
** from sqliteMalloc() and *pzErrMsg is made to point to that memory.
** The return parameter is the number of errors.
**
** If the callback every returns non-zero, then the program exits
** immediately.  No error message is written but the return value
** from the callback because the return value of this routine.







*/
int sqliteVdbeExec(
  Vdbe *p,                   /* The VDBE */
  sqlite_callback xCallback, /* The callback */
  void *pArg,                /* 1st argument to callback */
  char **pzErrMsg            /* Error msg written here */
){
  int pc;                    /* The program counter */
  Op *pOp;                   /* Current operation */
  int rc;                    /* Value to return */
  char zBuf[100];            /* Space to sprintf() and integer */

  p->tos = -1;
  rc = 0;
  if( pzErrMsg ){ *pzErrMsg = 0; }
  for(pc=0; rc==0 && pc<p->nOp && pc>=0; pc++){
    pOp = &p->aOp[pc];
    if( p->trace ){
      fprintf(p->trace,"%4d %-12s %4d %4d %s\n",
        pc, zOpName[pOp->opcode], pOp->p1, pOp->p2,
           pOp->p3 ? pOp->p3 : "");
    }
    switch( pOp->opcode ){
................................................................................
      **
      ** An unconditional jump to address P2.
      ** The next instruction executed will be 
      ** the one at index P2 from the beginning of
      ** the program.
      */
      case OP_Goto: {
        pc = pOp->p2;
        if( pc<0 || pc>p->nOp ){
          sqliteSetString(pzErrMsg, "jump destination out of range", 0);
          rc = 1;
        }
        pc--;
        break;
      }

      /* Opcode:  Halt * * *
      **
      ** Exit immediately.  All open DBs, Lists, Sorts, etc are closed
      ** automatically.
................................................................................
        int j;
        if( i<0 ) goto not_enough_stack;
        if( NeedStack(p, p->tos+2) ) goto no_mem;
        for(j=i; j<=p->tos; j++){
          if( Stringify(p, j) ) goto no_mem;
        }
        p->zStack[p->tos+1] = 0;
        rc = xCallback(pArg, pOp->p1, &p->zStack[i], p->azColName);


        PopStack(p, pOp->p1);
        break;
      }

      /* Opcode: Concat * * *
      **
      ** Pop two elements from the stack.  Append the first (what used
................................................................................
          switch( pOp->opcode ){
            case OP_Add:         b += a;       break;
            case OP_Subtract:    b -= a;       break;
            case OP_Multiply:    b *= a;       break;
            default: {
              if( a==0 ){ 
                sqliteSetString(pzErrMsg, "division by zero", 0);
                rc = 1;
                goto cleanup;
              }
              b /= a;
              break;
            }
          }
          PopStack(p, 1);
................................................................................
          switch( pOp->opcode ){
            case OP_Add:         b += a;       break;
            case OP_Subtract:    b -= a;       break;
            case OP_Multiply:    b *= a;       break;
            default: {
              if( a==0.0 ){ 
                sqliteSetString(pzErrMsg, "division by zero", 0);
                rc = 1;
                goto cleanup;
              }
              b /= a;
              break;
            }
          }
          sprintf(zBuf,"%g",b);
................................................................................
        NeedStack(p, p->tos+1);
        p->tos++;
        p->iStack[p->tos] = nByte;
        p->zStack[p->tos] = zNewKey;
        break;
      }

      /*  Open P1 P3 P2
      **
      ** Open a new database table named P3.  Give it an identifier P1.
      ** Open readonly if P2==0 and for reading and writing if P2!=0.
      ** The table is created if it does not already exist and P2!=0.
      ** If there is already another table opened on P1, then the old
      ** table is closed first.  All tables are automatically closed when
      ** the VDBE finishes execution.  The P1 values need not be
................................................................................
          p->aTab = sqliteRealloc( p->aTab, (i+1)*sizeof(VdbeTable) );
          if( p->aTab==0 ){ p->nTable = 0; goto no_mem; }
          for(j=p->nTable; j<=i; j++) p->aTab[j].pTable = 0;
          p->nTable = i+1;
        }else if( p->aTab[i].pTable ){
          sqliteDbbeCloseTable(p->aTab[i].pTable);
        }
        p->aTab[i].pTable = sqliteDbbeOpenTable(p->pBe, pOp->p3, pOp->p2);
        p->aTab[i].index = 0;
        break;
      }

      /* Opcode: Close P1 * *
      **
      ** Close a database table previously opened as P1.  If P1 is not
................................................................................
        int tos = p->tos;
        if( tos<0 ) goto not_enough_stack;
        if( i>=0 && i<p->nTable && p->aTab[i].pTable ){
          if( p->zStack[tos]==0 ){
            sqliteDbbeFetch(p->aTab[i].pTable, sizeof(int), 
                           (char*)&p->iStack[tos]);
          }else{
            sqliteDbbeFetch(p->aTab[i].pTable, p->iStack[tos], p->zStack[tos]);

          }
        }
        PopStack(p, 1);
        break;
      }

      /* Opcode: Distinct P1 P2 *
................................................................................
                                          (char*)&p->iStack[tos]);
          }else{
            alreadyExists = sqliteDbbeTest(p->aTab[i].pTable, p->iStack[tos], 
                                           p->zStack[tos]);
          }
        }
        if( !alreadyExists ){
          pc = pOp->p2;
          if( pc<0 || pc>p->nOp ){
            sqliteSetString(pzErrMsg, "jump destination out of range", 0);
            rc = 1;
          }
          pc--;
        }
        break;
      }

      /* Opcode: New P1 * *
      **
      ** Get a new integer key not previous used by table P1 and
................................................................................
      ** Advance P1 to the next entry in the table.  Or, if there are no
      ** more entries, rewind P1 and jump to location P2.
      */
      case OP_Next: {
        int i = pOp->p1;
        if( i>=0 && i<p->nTable && p->aTab[i].pTable!=0 ){
          if( sqliteDbbeNextKey(p->aTab[i].pTable)==0 ){
            pc = pOp->p2;
            if( pc<0 || pc>p->nOp ){
              sqliteSetString(pzErrMsg, "jump destination out of range", 0);
              rc = 1;
            }
            pc--;
          }
        }
        break;
      }

      /* Opcode: ResetIdx P1 * *
      **
................................................................................
            if( aIdx[j]!=0 ){
              p->iStack[tos] = aIdx[j];
              break;
            }
          }
          if( j>=nIdx ){
            j = -1;
            pc = pOp->p2;
            if( pc<0 || pc>p->nOp ){
              sqliteSetString(pzErrMsg, "jump destination out of range", 0);
              rc = 1;
            }
            pc--;
            PopStack(p, 1);
          }
          p->aTab[i].index = j+1;
        }
        break;
      }

................................................................................
          p->apList = sqliteRealloc( p->apList, (i+1)*sizeof(FILE*) );
          if( p->apList==0 ){ p->nList = 0; goto no_mem; }
          for(j=p->nList; j<=i; j++) p->apList[j] = 0;
          p->nList = i+1;
        }else if( p->apList[i] ){
          sqliteDbbeCloseTempFile(p->pBe, p->apList[i]);
        }
        p->apList[i] = sqliteDbbeOpenTempFile(p->pBe);
        break;
      }

      /* Opcode: ListWrite P1 * *
      **
      ** Write the integer on the top of the stack
      ** into the temporary storage file P1.
................................................................................
        amt = fread(&val, sizeof(int), 1, p->apList[i]);
        if( amt==1 ){
          p->tos++;
          if( NeedStack(p, p->tos) ) goto no_mem;
          p->iStack[p->tos] = val;
          p->zStack[p->tos] = 0;
        }else{
          pc = pOp->p2;
          if( pc<0 || pc>p->nOp ){
            sqliteSetString(pzErrMsg, "jump destination out of range", 0);
            rc = 1;
          }
          pc--;
        }
        break;
      }

      /* Opcode: ListClose P1 * *
      **
      ** Close the temporary storage buffer and discard its contents.
................................................................................
          p->tos++;
          NeedStack(p, p->tos);
          p->zStack[p->tos] = pSorter->pData;
          p->iStack[p->tos] = pSorter->nData;
          sqliteFree(pSorter->zKey);
          sqliteFree(pSorter);
        }else{
          pc = pOp->p2;
          if( pc<0 || pc>p->nOp ){
            sqliteSetString(pzErrMsg, "jump destination out of range", 0);
            rc = 1;
          }
          pc--;
        }
        break;
      }

      /* Opcode: SortKey P1 * *
      **
      ** Push the key for the topmost element of the sorter onto the stack.
................................................................................
      ** the SortMakeRec operation with the same P1 value as this
      ** instruction.  Pop this record from the stack and invoke the
      ** callback on it.
      */
      case OP_SortCallback: {
        int i = p->tos;
        if( i<0 ) goto not_enough_stack;
        rc = xCallback(pArg, pOp->p1, (char**)p->zStack[i], p->azColName);


        PopStack(p, 1);
        break;
      }

      /* Opcode: SortClose P1 * *
      **
      ** Close the given sorter and remove all its elements.
................................................................................
        if( sqliteStrICmp(pOp->p3,"stdin")==0 ){
          p->pFile = stdin;
        }else{
          p->pFile = fopen(pOp->p3, "r");
        }
        if( p->pFile==0 ){
          sqliteSetString(pzErrMsg,"unable to open file: ", pOp->p3, 0);
          rc = 1;
          goto cleanup;
        }
        break;
      }

      /* Opcode: FileClose * * *
      **
................................................................................
          p->azField[i++] = "";
        }
        break;

        /* If we reach end-of-file, or if anything goes wrong, jump here.
        ** This code will cause a jump to P2 */
      fileread_jump:
        pc = pOp->p2;
        if( pc<0 || pc>p->nOp ){
          sqliteSetString(pzErrMsg, "jump destination out of range", 0);
          rc = 1;
        }
        pc--;
        break;
      }

      /* Opcode: FileField P1 * *
      **
      ** Push onto the stack the P1-th field of the most recently read line
      ** from the file.
................................................................................
      }

      /* An other opcode is illegal...
      */
      default: {
        sprintf(zBuf,"%d",pOp->opcode);
        sqliteSetString(pzErrMsg, "unknown opcode ", zBuf, 0);
        rc = 1;
        break;
      }




    }
    if( p->trace && p->tos>=0 ){
      int i;
      fprintf(p->trace, "Stack:");
      for(i=p->tos; i>=0 && i>p->tos-5; i--){
        if( p->zStack[i] ){
          fprintf(p->trace, " [%.11s]", p->zStack[i]);
................................................................................

  /* Jump to here if a operator is encountered that requires more stack
  ** operands than are currently available on the stack.
  */
not_enough_stack:
  sprintf(zBuf,"%d",pc);
  sqliteSetString(pzErrMsg, "too few operands on stack at ", zBuf, 0);
  rc = 1;
  goto cleanup;

  /* Jump here if an illegal or illformed instruction is executed.
  */
bad_instruction:
  sprintf(zBuf,"%d",pc);
  sqliteSetString(pzErrMsg, "illegal operation at ", zBuf, 0);
  rc = 1;
  goto cleanup;

}







|







 







|

|






|
>
>







 







|
|
>
>
>
>
>
>
>













|

|







 







|
<
<
<
<
<







 







|
>
>







 







|







 







|







 







|







 







|







 







|
>







 







|
<
<
<
<
<







 







|
<
<
<
<
<







 







|
<
<
<
<
<







 







|







 







|
<
<
<
<
<







 







|
<
<
<
<
<







 







|
>
>







 







|







 







|
<
<
<
<
<







 







|


>
>
>
>







 







|







|



37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
...
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
...
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
...
604
605
606
607
608
609
610
611





612
613
614
615
616
617
618
...
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
...
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
...
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
....
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
....
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
....
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
....
1383
1384
1385
1386
1387
1388
1389
1390





1391
1392
1393
1394
1395
1396
1397
....
1534
1535
1536
1537
1538
1539
1540
1541





1542
1543
1544
1545
1546
1547
1548
....
1580
1581
1582
1583
1584
1585
1586
1587





1588
1589
1590
1591
1592
1593
1594
....
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
....
1760
1761
1762
1763
1764
1765
1766
1767





1768
1769
1770
1771
1772
1773
1774
....
1963
1964
1965
1966
1967
1968
1969
1970





1971
1972
1973
1974
1975
1976
1977
....
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
....
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
....
2140
2141
2142
2143
2144
2145
2146
2147





2148
2149
2150
2151
2152
2153
2154
....
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
....
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
** inplicit conversion from one type to the other occurs as necessary.
** 
** Most of the code in this file is taken up by the sqliteVdbeExec()
** function which does the work of interpreting a VDBE program.
** But other routines are also provided to help in building up
** a program instruction by instruction.
**
** $Id: vdbe.c,v 1.7 2000/06/02 01:17:38 drh Exp $
*/
#include "sqliteInt.h"

/*
** SQL is translated into a sequence of instructions to be
** executed by a virtual machine.  Each instruction is an instance
** of the following structure.
................................................................................
  };

  if( xCallback==0 ) return 0;
  azField[0] = zAddr;
  azField[2] = zP1;
  azField[3] = zP2;
  azField[5] = 0;
  rc = SQLITE_OK;
  if( pzErrMsg ){ *pzErrMsg = 0; }
  for(i=0; rc==SQLITE_OK && i<p->nOp; i++){
    sprintf(zAddr,"%d",i);
    sprintf(zP1,"%d", p->aOp[i].p1);
    sprintf(zP2,"%d", p->aOp[i].p2);
    azField[4] = p->aOp[i].p3;
    if( azField[4]==0 ) azField[4] = "";
    azField[1] = zOpName[p->aOp[i].opcode];
    if( xCallback(pArg, 5, azField, azColumnNames) ){
      rc = SQLITE_ABORT;
    }
  }
  return rc;
}

/*
** Make sure space has been allocated to hold at least N
** stack elements.  Allocate additional stack space if
................................................................................
** Execute the program in the VDBE.
**
** If an error occurs, an error message is written to memory obtained
** from sqliteMalloc() and *pzErrMsg is made to point to that memory.
** The return parameter is the number of errors.
**
** If the callback every returns non-zero, then the program exits
** immediately.  No error message but the function does return SQLITE_ABORT.
**
** A memory allocation error causes this routine to return SQLITE_NOMEM
** and abandon furture processing.
**
** Other fatal errors return SQLITE_ERROR.
**
** If a database file could not be opened because it is locked by
** another database instance, then this routine returns SQLITE_BUSY.
*/
int sqliteVdbeExec(
  Vdbe *p,                   /* The VDBE */
  sqlite_callback xCallback, /* The callback */
  void *pArg,                /* 1st argument to callback */
  char **pzErrMsg            /* Error msg written here */
){
  int pc;                    /* The program counter */
  Op *pOp;                   /* Current operation */
  int rc;                    /* Value to return */
  char zBuf[100];            /* Space to sprintf() and integer */

  p->tos = -1;
  rc = SQLITE_OK;
  if( pzErrMsg ){ *pzErrMsg = 0; }
  for(pc=0; rc==SQLITE_OK && pc<p->nOp && pc>=0; pc++){
    pOp = &p->aOp[pc];
    if( p->trace ){
      fprintf(p->trace,"%4d %-12s %4d %4d %s\n",
        pc, zOpName[pOp->opcode], pOp->p1, pOp->p2,
           pOp->p3 ? pOp->p3 : "");
    }
    switch( pOp->opcode ){
................................................................................
      **
      ** An unconditional jump to address P2.
      ** The next instruction executed will be 
      ** the one at index P2 from the beginning of
      ** the program.
      */
      case OP_Goto: {
        pc = pOp->p2 - 1;





        break;
      }

      /* Opcode:  Halt * * *
      **
      ** Exit immediately.  All open DBs, Lists, Sorts, etc are closed
      ** automatically.
................................................................................
        int j;
        if( i<0 ) goto not_enough_stack;
        if( NeedStack(p, p->tos+2) ) goto no_mem;
        for(j=i; j<=p->tos; j++){
          if( Stringify(p, j) ) goto no_mem;
        }
        p->zStack[p->tos+1] = 0;
        if( xCallback(pArg, pOp->p1, &p->zStack[i], p->azColName)!=0 ){
          rc = SQLITE_ABORT;
        }
        PopStack(p, pOp->p1);
        break;
      }

      /* Opcode: Concat * * *
      **
      ** Pop two elements from the stack.  Append the first (what used
................................................................................
          switch( pOp->opcode ){
            case OP_Add:         b += a;       break;
            case OP_Subtract:    b -= a;       break;
            case OP_Multiply:    b *= a;       break;
            default: {
              if( a==0 ){ 
                sqliteSetString(pzErrMsg, "division by zero", 0);
                rc = SQLITE_ERROR;
                goto cleanup;
              }
              b /= a;
              break;
            }
          }
          PopStack(p, 1);
................................................................................
          switch( pOp->opcode ){
            case OP_Add:         b += a;       break;
            case OP_Subtract:    b -= a;       break;
            case OP_Multiply:    b *= a;       break;
            default: {
              if( a==0.0 ){ 
                sqliteSetString(pzErrMsg, "division by zero", 0);
                rc = SQLITE_ERROR;
                goto cleanup;
              }
              b /= a;
              break;
            }
          }
          sprintf(zBuf,"%g",b);
................................................................................
        NeedStack(p, p->tos+1);
        p->tos++;
        p->iStack[p->tos] = nByte;
        p->zStack[p->tos] = zNewKey;
        break;
      }

      /* Opcode: Open P1 P2 P3
      **
      ** Open a new database table named P3.  Give it an identifier P1.
      ** Open readonly if P2==0 and for reading and writing if P2!=0.
      ** The table is created if it does not already exist and P2!=0.
      ** If there is already another table opened on P1, then the old
      ** table is closed first.  All tables are automatically closed when
      ** the VDBE finishes execution.  The P1 values need not be
................................................................................
          p->aTab = sqliteRealloc( p->aTab, (i+1)*sizeof(VdbeTable) );
          if( p->aTab==0 ){ p->nTable = 0; goto no_mem; }
          for(j=p->nTable; j<=i; j++) p->aTab[j].pTable = 0;
          p->nTable = i+1;
        }else if( p->aTab[i].pTable ){
          sqliteDbbeCloseTable(p->aTab[i].pTable);
        }
        rc = sqliteDbbeOpenTable(p->pBe, pOp->p3, pOp->p2, &p->aTab[i].pTable);
        p->aTab[i].index = 0;
        break;
      }

      /* Opcode: Close P1 * *
      **
      ** Close a database table previously opened as P1.  If P1 is not
................................................................................
        int tos = p->tos;
        if( tos<0 ) goto not_enough_stack;
        if( i>=0 && i<p->nTable && p->aTab[i].pTable ){
          if( p->zStack[tos]==0 ){
            sqliteDbbeFetch(p->aTab[i].pTable, sizeof(int), 
                           (char*)&p->iStack[tos]);
          }else{
            sqliteDbbeFetch(p->aTab[i].pTable, p->iStack[tos], 
                           p->zStack[tos]);
          }
        }
        PopStack(p, 1);
        break;
      }

      /* Opcode: Distinct P1 P2 *
................................................................................
                                          (char*)&p->iStack[tos]);
          }else{
            alreadyExists = sqliteDbbeTest(p->aTab[i].pTable, p->iStack[tos], 
                                           p->zStack[tos]);
          }
        }
        if( !alreadyExists ){
          pc = pOp->p2 - 1;





        }
        break;
      }

      /* Opcode: New P1 * *
      **
      ** Get a new integer key not previous used by table P1 and
................................................................................
      ** Advance P1 to the next entry in the table.  Or, if there are no
      ** more entries, rewind P1 and jump to location P2.
      */
      case OP_Next: {
        int i = pOp->p1;
        if( i>=0 && i<p->nTable && p->aTab[i].pTable!=0 ){
          if( sqliteDbbeNextKey(p->aTab[i].pTable)==0 ){
            pc = pOp->p2 - 1;





          }
        }
        break;
      }

      /* Opcode: ResetIdx P1 * *
      **
................................................................................
            if( aIdx[j]!=0 ){
              p->iStack[tos] = aIdx[j];
              break;
            }
          }
          if( j>=nIdx ){
            j = -1;
            pc = pOp->p2 - 1;





            PopStack(p, 1);
          }
          p->aTab[i].index = j+1;
        }
        break;
      }

................................................................................
          p->apList = sqliteRealloc( p->apList, (i+1)*sizeof(FILE*) );
          if( p->apList==0 ){ p->nList = 0; goto no_mem; }
          for(j=p->nList; j<=i; j++) p->apList[j] = 0;
          p->nList = i+1;
        }else if( p->apList[i] ){
          sqliteDbbeCloseTempFile(p->pBe, p->apList[i]);
        }
        rc = sqliteDbbeOpenTempFile(p->pBe, &p->apList[i]);
        break;
      }

      /* Opcode: ListWrite P1 * *
      **
      ** Write the integer on the top of the stack
      ** into the temporary storage file P1.
................................................................................
        amt = fread(&val, sizeof(int), 1, p->apList[i]);
        if( amt==1 ){
          p->tos++;
          if( NeedStack(p, p->tos) ) goto no_mem;
          p->iStack[p->tos] = val;
          p->zStack[p->tos] = 0;
        }else{
          pc = pOp->p2 - 1;





        }
        break;
      }

      /* Opcode: ListClose P1 * *
      **
      ** Close the temporary storage buffer and discard its contents.
................................................................................
          p->tos++;
          NeedStack(p, p->tos);
          p->zStack[p->tos] = pSorter->pData;
          p->iStack[p->tos] = pSorter->nData;
          sqliteFree(pSorter->zKey);
          sqliteFree(pSorter);
        }else{
          pc = pOp->p2 - 1;





        }
        break;
      }

      /* Opcode: SortKey P1 * *
      **
      ** Push the key for the topmost element of the sorter onto the stack.
................................................................................
      ** the SortMakeRec operation with the same P1 value as this
      ** instruction.  Pop this record from the stack and invoke the
      ** callback on it.
      */
      case OP_SortCallback: {
        int i = p->tos;
        if( i<0 ) goto not_enough_stack;
        if( xCallback(pArg, pOp->p1, (char**)p->zStack[i], p->azColName) ){
          rc = SQLITE_ABORT;
        }
        PopStack(p, 1);
        break;
      }

      /* Opcode: SortClose P1 * *
      **
      ** Close the given sorter and remove all its elements.
................................................................................
        if( sqliteStrICmp(pOp->p3,"stdin")==0 ){
          p->pFile = stdin;
        }else{
          p->pFile = fopen(pOp->p3, "r");
        }
        if( p->pFile==0 ){
          sqliteSetString(pzErrMsg,"unable to open file: ", pOp->p3, 0);
          rc = SQLITE_ERROR;
          goto cleanup;
        }
        break;
      }

      /* Opcode: FileClose * * *
      **
................................................................................
          p->azField[i++] = "";
        }
        break;

        /* If we reach end-of-file, or if anything goes wrong, jump here.
        ** This code will cause a jump to P2 */
      fileread_jump:
        pc = pOp->p2 - 1;





        break;
      }

      /* Opcode: FileField P1 * *
      **
      ** Push onto the stack the P1-th field of the most recently read line
      ** from the file.
................................................................................
      }

      /* An other opcode is illegal...
      */
      default: {
        sprintf(zBuf,"%d",pOp->opcode);
        sqliteSetString(pzErrMsg, "unknown opcode ", zBuf, 0);
        rc = SQLITE_INTERNAL;
        break;
      }
    }
    if( pc<-1 || pc>=p->nOp ){
      sqliteSetString(pzErrMsg, "jump destination out of range", 0);
      rc = SQLITE_INTERNAL;
    }
    if( p->trace && p->tos>=0 ){
      int i;
      fprintf(p->trace, "Stack:");
      for(i=p->tos; i>=0 && i>p->tos-5; i--){
        if( p->zStack[i] ){
          fprintf(p->trace, " [%.11s]", p->zStack[i]);
................................................................................

  /* Jump to here if a operator is encountered that requires more stack
  ** operands than are currently available on the stack.
  */
not_enough_stack:
  sprintf(zBuf,"%d",pc);
  sqliteSetString(pzErrMsg, "too few operands on stack at ", zBuf, 0);
  rc = SQLITE_INTERNAL;
  goto cleanup;

  /* Jump here if an illegal or illformed instruction is executed.
  */
bad_instruction:
  sprintf(zBuf,"%d",pc);
  sqliteSetString(pzErrMsg, "illegal operation at ", zBuf, 0);
  rc = SQLITE_INTERNAL;
  goto cleanup;

}