/ Check-in [86b30cd0]
Login

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

Overview
Comment:better handling of out-of-memory errors (CVS 207)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:86b30cd0975dfea9424b9f9f0d4194aa71ce508b
User & Date: drh 2001-04-11 14:28:42
Context
2001-04-11
14:29
:-) (CVS 208) check-in: 555351dd user: drh tags: trunk
14:28
better handling of out-of-memory errors (CVS 207) check-in: 86b30cd0 user: drh tags: trunk
2001-04-07
15:24
Added new tests (CVS 206) check-in: 2507ec40 user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/build.c.

29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
..
45
46
47
48
49
50
51

52
53
54
55
56
57
58
..
92
93
94
95
96
97
98

99
100

101
102
103
104
105
106
107
...
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
...
191
192
193
194
195
196
197





198
199
200
201
202
203
204
...
232
233
234
235
236
237
238

239
240
241
242
243
244
245
...
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
...
271
272
273
274
275
276
277
278
279
280
281

282
283
284
285
286
287
288
...
319
320
321
322
323
324
325
326
327

328
329
330
331
332
333
334
335
336
337
338
339
...
377
378
379
380
381
382
383


384

385
386
387
388
389
390
391
392
...
397
398
399
400
401
402
403

404
405
406
407
408
409
410
...
482
483
484
485
486
487
488


489
490
491
492
493
494
495
...
508
509
510
511
512
513
514

515
516
517
518
519
520
521
...
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
...
652
653
654
655
656
657
658

659

660
661
662
663
664
665
666
...
710
711
712
713
714
715
716
717
718

719
720
721
722
723
724
725
...
747
748
749
750
751
752
753


754
755
756
757
758
759
760
761
762
763

764
765
766
767
768
769





770

771
772
773
774
775
776
777
...
789
790
791
792
793
794
795





796
797
798
799
800
801
802
...
820
821
822
823
824
825
826

827
828
829
830
831
832
833
...
887
888
889
890
891
892
893

894
895
896
897
898
899
900
...
929
930
931
932
933
934
935

936
937
938
939
940
941
942
...
949
950
951
952
953
954
955

956
957
958
959
960
961
962
...
969
970
971
972
973
974
975

976
977
978
979
980
981
982
983
984
985
986
**     DROP TABLE
**     CREATE INDEX
**     DROP INDEX
**     creating expressions and ID lists
**     COPY
**     VACUUM
**
** $Id: build.c,v 1.26 2001/04/04 11:48:57 drh Exp $
*/
#include "sqliteInt.h"

/*
** This routine is called after a single SQL statement has been
** parsed and we want to execute the VDBE code to implement 
** that statement.  Prior action routines should have already
................................................................................
** This routine just has to execute the VDBE code.
**
** Note that if an error occurred, it might be the case that
** no VDBE code was generated.
*/
void sqliteExec(Parse *pParse){
  int rc = SQLITE_OK;

  if( pParse->pVdbe ){
    if( pParse->explain ){
      rc = sqliteVdbeList(pParse->pVdbe, pParse->xCallback, pParse->pArg, 
                          &pParse->zErrMsg);
    }else{
      FILE *trace = (pParse->db->flags & SQLITE_VdbeTrace)!=0 ? stderr : 0;
      sqliteVdbeTrace(pParse->pVdbe, trace);
................................................................................
}

/*
** Set the Expr.token field of the given expression to span all
** text between the two given tokens.
*/
void sqliteExprSpan(Expr *pExpr, Token *pLeft, Token *pRight){

  pExpr->span.z = pLeft->z;
  pExpr->span.n = pRight->n + (int)pRight->z - (int)pLeft->z;

}

/*
** Construct a new expression node for a function with multiple
** arguments.
*/
Expr *sqliteExprFunction(ExprList *pList, Token *pToken){
................................................................................
  return 0;
}

/*
** Remove the given index from the index hash table, and free
** its memory structures.
**
** The index is removed from the database hash table, but it is
** not unlinked from the Table that is being indexed.  Unlinking
** from the Table must be done by the calling function.
*/
static void sqliteDeleteIndex(sqlite *db, Index *pIndex){
  int h;
  if( pIndex->zName ){
    h = sqliteHashNoCase(pIndex->zName, 0) % N_HASH;
    if( db->apIdxHash[h]==pIndex ){
      db->apIdxHash[h] = pIndex->pHash;
    }else{
      Index *p;
      for(p=db->apIdxHash[h]; p && p->pHash!=pIndex; p=p->pHash){}
      if( p && p->pHash==pIndex ){
................................................................................
/*
** Remove the memory data structures associated with the given
** Table.  No changes are made to disk by this routine.
**
** This routine just deletes the data structure.  It does not unlink
** the table data structure from the hash table.  But does it destroy
** memory structures of the indices associated with the table.





*/
void sqliteDeleteTable(sqlite *db, Table *pTable){
  int i;
  Index *pIndex, *pNext;
  if( pTable==0 ) return;
  for(i=0; i<pTable->nCol; i++){
    sqliteFree(pTable->aCol[i].zName);
................................................................................
*/
void sqliteStartTable(Parse *pParse, Token *pStart, Token *pName){
  Table *pTable;
  char *zName;

  pParse->sFirstToken = *pStart;
  zName = sqliteTableNameFromToken(pName);

  pTable = sqliteFindTable(pParse->db, zName);
  if( pTable!=0 ){
    sqliteSetNString(&pParse->zErrMsg, "table ", 0, pName->z, pName->n,
        " already exists", 0, 0);
    sqliteFree(zName);
    pParse->nErr++;
    return;
................................................................................
    sqliteSetString(&pParse->zErrMsg, "there is already an index named ", 
       zName, 0);
    sqliteFree(zName);
    pParse->nErr++;
    return;
  }
  pTable = sqliteMalloc( sizeof(Table) );
  if( pTable==0 ){
    sqliteSetString(&pParse->zErrMsg, "out of memory", 0);
    pParse->nErr++;
    return;
  }
  pTable->zName = zName;
  pTable->pHash = 0;
  pTable->nCol = 0;
  pTable->aCol = 0;
  pTable->pIndex = 0;
  if( pParse->pNewTable ) sqliteDeleteTable(pParse->db, pParse->pNewTable);
  pParse->pNewTable = pTable;
................................................................................
*/
void sqliteAddColumn(Parse *pParse, Token *pName){
  Table *p;
  char **pz;
  if( (p = pParse->pNewTable)==0 ) return;
  if( (p->nCol & 0x7)==0 ){
    p->aCol = sqliteRealloc( p->aCol, (p->nCol+8)*sizeof(p->aCol[0]));
  }
  if( p->aCol==0 ){
    p->nCol = 0;
    return;

  }
  memset(&p->aCol[p->nCol], 0, sizeof(p->aCol[0]));
  pz = &p->aCol[p->nCol++].zName;
  sqliteSetNString(pz, pName->z, pName->n, 0);
  sqliteDequote(*pz);
}

................................................................................
** We do not want to create it again.
*/
void sqliteEndTable(Parse *pParse, Token *pEnd){
  Table *p;
  int h;
  int addMeta;       /* True to insert a meta records into the file */

  if( pParse->nErr ) return;
  p = pParse->pNewTable;

  addMeta =  p!=0 && pParse->db->nTable==1;

  /* Add the table to the in-memory representation of the database
  */
  if( p!=0 && pParse->explain==0 ){
    h = sqliteHashNoCase(p->zName, 0) % N_HASH;
    p->pHash = pParse->db->apTblHash[h];
    pParse->db->apTblHash[h] = p;
    pParse->pNewTable = 0;
    pParse->db->nTable++;
  }

................................................................................
}

/*
** Given a token, look up a table with that name.  If not found, leave
** an error for the parser to find and return NULL.
*/
Table *sqliteTableFromToken(Parse *pParse, Token *pTok){


  char *zName = sqliteTableNameFromToken(pTok);

  Table *pTab = sqliteFindTable(pParse->db, zName);
  sqliteFree(zName);
  if( pTab==0 ){
    sqliteSetNString(&pParse->zErrMsg, "no such table: ", 0, 
        pTok->z, pTok->n, 0);
    pParse->nErr++;
  }
  return pTab;
................................................................................
*/
void sqliteDropTable(Parse *pParse, Token *pName){
  Table *pTable;
  int h;
  Vdbe *v;
  int base;


  pTable = sqliteTableFromToken(pParse, pName);
  if( pTable==0 ) return;
  if( pTable->readOnly ){
    sqliteSetString(&pParse->zErrMsg, "table ", pTable->zName, 
       " may not be dropped", 0);
    pParse->nErr++;
    return;
................................................................................
){
  Table *pTab;     /* Table to be indexed */
  Index *pIndex;   /* The index to be created */
  char *zName = 0;
  int i, j, h;
  Token nullId;    /* Fake token for an empty ID list */



  /*
  ** Find the table that is to be indexed.  Return early if not found.
  */
  if( pTable!=0 ){
    pTab =  sqliteTableFromToken(pParse, pTable);
  }else{
    pTab =  pParse->pNewTable;
................................................................................
  */
  if( pName ){
    zName = sqliteTableNameFromToken(pName);
  }else{
    zName = 0;
    sqliteSetString(&zName, pTab->zName, "__primary_key", 0);
  }

  if( sqliteFindIndex(pParse->db, zName) ){
    sqliteSetString(&pParse->zErrMsg, "index ", zName, 
       " already exists", 0);
    pParse->nErr++;
    goto exit_create_index;
  }
  if( sqliteFindTable(pParse->db, zName) ){
................................................................................
  }

  /* 
  ** Allocate the index structure. 
  */
  pIndex = sqliteMalloc( sizeof(Index) + strlen(zName) + 1 +
                        sizeof(int)*pList->nId );
  if( pIndex==0 ){
    sqliteSetString(&pParse->zErrMsg, "out of memory", 0);
    pParse->nErr++;
    goto exit_create_index;
  }
  pIndex->aiColumn = (int*)&pIndex[1];
  pIndex->zName = (char*)&pIndex->aiColumn[pList->nId];
  strcpy(pIndex->zName, zName);
  pIndex->pTable = pTab;
  pIndex->nColumn = pList->nId;

  /* Scan the names of the columns of the table to be indexed and
................................................................................
** This routine will drop an existing named index.
*/
void sqliteDropIndex(Parse *pParse, Token *pName){
  Index *pIndex;
  char *zName;
  Vdbe *v;


  zName = sqliteTableNameFromToken(pName);

  pIndex = sqliteFindIndex(pParse->db, zName);
  sqliteFree(zName);
  if( pIndex==0 ){
    sqliteSetNString(&pParse->zErrMsg, "no such index: ", 0, 
        pName->z, pName->n, 0);
    pParse->nErr++;
    return;
................................................................................
** Add a new element to the end of an expression list.  If pList is
** initially NULL, then create a new expression list.
*/
ExprList *sqliteExprListAppend(ExprList *pList, Expr *pExpr, Token *pName){
  int i;
  if( pList==0 ){
    pList = sqliteMalloc( sizeof(ExprList) );
  }
  if( pList==0 ) return 0;

  if( (pList->nExpr & 7)==0 ){
    int n = pList->nExpr + 8;
    pList->a = sqliteRealloc(pList->a, n*sizeof(pList->a[0]));
    if( pList->a==0 ){
      pList->nExpr = 0;
      return pList;
    }
................................................................................
  sqliteFree(pList->a);
  sqliteFree(pList);
}

/*
** Append a new element to the given IdList.  Create a new IdList if
** need be.


*/
IdList *sqliteIdListAppend(IdList *pList, Token *pToken){
  if( pList==0 ){
    pList = sqliteMalloc( sizeof(IdList) );
    if( pList==0 ) return 0;
  }
  if( (pList->nId & 7)==0 ){
    pList->a = sqliteRealloc(pList->a, (pList->nId+8)*sizeof(pList->a[0]) );
    if( pList->a==0 ){
      pList->nId = 0;

      return pList;
    }
  }
  memset(&pList->a[pList->nId], 0, sizeof(pList->a[0]));
  if( pToken ){
    sqliteSetNString(&pList->a[pList->nId].zName, pToken->z, pToken->n, 0);





    sqliteDequote(pList->a[pList->nId].zName);

  }
  pList->nId++;
  return pList;
}

/*
** Add an alias to the last identifier on the given identifier list.
................................................................................
*/
void sqliteIdListDelete(IdList *pList){
  int i;
  if( pList==0 ) return;
  for(i=0; i<pList->nId; i++){
    sqliteFree(pList->a[i].zName);
    sqliteFree(pList->a[i].zAlias);





  }
  sqliteFree(pList->a);
  sqliteFree(pList);
}


/*
................................................................................
  char *zTab;
  int i, j;
  Vdbe *v;
  int addr, end;
  Index *pIdx;

  zTab = sqliteTableNameFromToken(pTableName);

  pTab = sqliteFindTable(pParse->db, zTab);
  sqliteFree(zTab);
  if( pTab==0 ){
    sqliteSetNString(&pParse->zErrMsg, "no such table: ", 0, 
        pTableName->z, pTableName->n, 0);
    pParse->nErr++;
    goto copy_cleanup;
................................................................................
** collapse free space, etc.  It is modelled after the VACUUM command
** in PostgreSQL.
*/
void sqliteVacuum(Parse *pParse, Token *pTableName){
  char *zName;
  Vdbe *v;


  if( pTableName ){
    zName = sqliteTableNameFromToken(pTableName);
  }else{
    zName = 0;
  }
  if( zName && sqliteFindIndex(pParse->db, zName)==0
    && sqliteFindTable(pParse->db, zName)==0 ){
................................................................................
** Begin a transaction
*/
void sqliteBeginTransaction(Parse *pParse){
  int rc;
  DbbeMethods *pM;
  sqlite *db;
  if( pParse==0 || (db=pParse->db)==0 || db->pBe==0 ) return;

  if( db->flags & SQLITE_InTrans ) return;
  pM = pParse->db->pBe->x;
  if( pM && pM->BeginTransaction ){
    rc = (*pM->BeginTransaction)(pParse->db->pBe);
  }else{
    rc = SQLITE_OK;
  }
................................................................................
** Commit a transaction
*/
void sqliteCommitTransaction(Parse *pParse){
  int rc;
  DbbeMethods *pM;
  sqlite *db;
  if( pParse==0 || (db=pParse->db)==0 || db->pBe==0 ) return;

  if( (db->flags & SQLITE_InTrans)==0 ) return;
  pM = pParse->db->pBe->x;
  if( pM && pM->Commit ){
    rc = (*pM->Commit)(pParse->db->pBe);
  }else{
    rc = SQLITE_OK;
  }
................................................................................
** Rollback a transaction
*/
void sqliteRollbackTransaction(Parse *pParse){
  int rc;
  DbbeMethods *pM;
  sqlite *db;
  if( pParse==0 || (db=pParse->db)==0 || db->pBe==0 ) return;

  if( (db->flags & SQLITE_InTrans)==0 ) return;
  pM = pParse->db->pBe->x;
  if( pM && pM->Rollback ){
    rc = (*pM->Rollback)(pParse->db->pBe);
  }else{
    rc = SQLITE_OK;
  }
  if( rc==SQLITE_OK ){
    db->flags &= ~SQLITE_InTrans;
  }
}







|







 







>







 







>
|
|
>







 







|
|
|



|







 







>
>
>
>
>







 







>







 







|
<
<
<
<







 







<
|
|
|
>







 







|

>
|



|







 







>
>
|
>
|







 







>







 







>
>







 







>







 







<
<
<
|
<







 







>

>







 







<
|
>







 







>
>










>
|




|
>
>
>
>
>
|
>







 







>
>
>
>
>







 







>







 







>







 







>







 







>







 







>











29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
..
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
..
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
...
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
...
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
...
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
...
257
258
259
260
261
262
263
264




265
266
267
268
269
270
271
...
276
277
278
279
280
281
282

283
284
285
286
287
288
289
290
291
292
293
...
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
...
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
...
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
...
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
...
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
...
550
551
552
553
554
555
556



557

558
559
560
561
562
563
564
...
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
...
721
722
723
724
725
726
727

728
729
730
731
732
733
734
735
736
...
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
...
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
...
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
...
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
...
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
...
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
...
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
**     DROP TABLE
**     CREATE INDEX
**     DROP INDEX
**     creating expressions and ID lists
**     COPY
**     VACUUM
**
** $Id: build.c,v 1.27 2001/04/11 14:28:42 drh Exp $
*/
#include "sqliteInt.h"

/*
** This routine is called after a single SQL statement has been
** parsed and we want to execute the VDBE code to implement 
** that statement.  Prior action routines should have already
................................................................................
** This routine just has to execute the VDBE code.
**
** Note that if an error occurred, it might be the case that
** no VDBE code was generated.
*/
void sqliteExec(Parse *pParse){
  int rc = SQLITE_OK;
  if( sqlite_malloc_failed ) return;
  if( pParse->pVdbe ){
    if( pParse->explain ){
      rc = sqliteVdbeList(pParse->pVdbe, pParse->xCallback, pParse->pArg, 
                          &pParse->zErrMsg);
    }else{
      FILE *trace = (pParse->db->flags & SQLITE_VdbeTrace)!=0 ? stderr : 0;
      sqliteVdbeTrace(pParse->pVdbe, trace);
................................................................................
}

/*
** Set the Expr.token field of the given expression to span all
** text between the two given tokens.
*/
void sqliteExprSpan(Expr *pExpr, Token *pLeft, Token *pRight){
  if( pExpr ){
    pExpr->span.z = pLeft->z;
    pExpr->span.n = pRight->n + (int)pRight->z - (int)pLeft->z;
  }
}

/*
** Construct a new expression node for a function with multiple
** arguments.
*/
Expr *sqliteExprFunction(ExprList *pList, Token *pToken){
................................................................................
  return 0;
}

/*
** Remove the given index from the index hash table, and free
** its memory structures.
**
** The index is removed from the database hash table if db!=NULL.
** But it is not unlinked from the Table that is being indexed.  
** Unlinking from the Table must be done by the calling function.
*/
static void sqliteDeleteIndex(sqlite *db, Index *pIndex){
  int h;
  if( pIndex->zName && db ){
    h = sqliteHashNoCase(pIndex->zName, 0) % N_HASH;
    if( db->apIdxHash[h]==pIndex ){
      db->apIdxHash[h] = pIndex->pHash;
    }else{
      Index *p;
      for(p=db->apIdxHash[h]; p && p->pHash!=pIndex; p=p->pHash){}
      if( p && p->pHash==pIndex ){
................................................................................
/*
** Remove the memory data structures associated with the given
** Table.  No changes are made to disk by this routine.
**
** This routine just deletes the data structure.  It does not unlink
** the table data structure from the hash table.  But does it destroy
** memory structures of the indices associated with the table.
**
** Indices associated with the table are unlinked from the "db"
** data structure if db!=NULL.  If db==NULL, indices attached to
** the table are deleted, but it is assumed they have already been
** unlinked.
*/
void sqliteDeleteTable(sqlite *db, Table *pTable){
  int i;
  Index *pIndex, *pNext;
  if( pTable==0 ) return;
  for(i=0; i<pTable->nCol; i++){
    sqliteFree(pTable->aCol[i].zName);
................................................................................
*/
void sqliteStartTable(Parse *pParse, Token *pStart, Token *pName){
  Table *pTable;
  char *zName;

  pParse->sFirstToken = *pStart;
  zName = sqliteTableNameFromToken(pName);
  if( zName==0 ) return;
  pTable = sqliteFindTable(pParse->db, zName);
  if( pTable!=0 ){
    sqliteSetNString(&pParse->zErrMsg, "table ", 0, pName->z, pName->n,
        " already exists", 0, 0);
    sqliteFree(zName);
    pParse->nErr++;
    return;
................................................................................
    sqliteSetString(&pParse->zErrMsg, "there is already an index named ", 
       zName, 0);
    sqliteFree(zName);
    pParse->nErr++;
    return;
  }
  pTable = sqliteMalloc( sizeof(Table) );
  if( pTable==0 ) return;




  pTable->zName = zName;
  pTable->pHash = 0;
  pTable->nCol = 0;
  pTable->aCol = 0;
  pTable->pIndex = 0;
  if( pParse->pNewTable ) sqliteDeleteTable(pParse->db, pParse->pNewTable);
  pParse->pNewTable = pTable;
................................................................................
*/
void sqliteAddColumn(Parse *pParse, Token *pName){
  Table *p;
  char **pz;
  if( (p = pParse->pNewTable)==0 ) return;
  if( (p->nCol & 0x7)==0 ){
    p->aCol = sqliteRealloc( p->aCol, (p->nCol+8)*sizeof(p->aCol[0]));

    if( p->aCol==0 ){
      p->nCol = 0;
      return;
    }
  }
  memset(&p->aCol[p->nCol], 0, sizeof(p->aCol[0]));
  pz = &p->aCol[p->nCol++].zName;
  sqliteSetNString(pz, pName->z, pName->n, 0);
  sqliteDequote(*pz);
}

................................................................................
** We do not want to create it again.
*/
void sqliteEndTable(Parse *pParse, Token *pEnd){
  Table *p;
  int h;
  int addMeta;       /* True to insert a meta records into the file */

  if( pEnd==0 || pParse->nErr || sqlite_malloc_failed ) return;
  p = pParse->pNewTable;
  if( p==0 ) return;
  addMeta =  pParse->db->nTable==1;

  /* Add the table to the in-memory representation of the database
  */
  if( pParse->explain==0 ){
    h = sqliteHashNoCase(p->zName, 0) % N_HASH;
    p->pHash = pParse->db->apTblHash[h];
    pParse->db->apTblHash[h] = p;
    pParse->pNewTable = 0;
    pParse->db->nTable++;
  }

................................................................................
}

/*
** Given a token, look up a table with that name.  If not found, leave
** an error for the parser to find and return NULL.
*/
Table *sqliteTableFromToken(Parse *pParse, Token *pTok){
  char *zName;
  Table *pTab;
  zName = sqliteTableNameFromToken(pTok);
  if( zName==0 ) return 0;
  pTab = sqliteFindTable(pParse->db, zName);
  sqliteFree(zName);
  if( pTab==0 ){
    sqliteSetNString(&pParse->zErrMsg, "no such table: ", 0, 
        pTok->z, pTok->n, 0);
    pParse->nErr++;
  }
  return pTab;
................................................................................
*/
void sqliteDropTable(Parse *pParse, Token *pName){
  Table *pTable;
  int h;
  Vdbe *v;
  int base;

  if( pParse->nErr || sqlite_malloc_failed ) return;
  pTable = sqliteTableFromToken(pParse, pName);
  if( pTable==0 ) return;
  if( pTable->readOnly ){
    sqliteSetString(&pParse->zErrMsg, "table ", pTable->zName, 
       " may not be dropped", 0);
    pParse->nErr++;
    return;
................................................................................
){
  Table *pTab;     /* Table to be indexed */
  Index *pIndex;   /* The index to be created */
  char *zName = 0;
  int i, j, h;
  Token nullId;    /* Fake token for an empty ID list */

  if( pParse->nErr || sqlite_malloc_failed ) goto exit_create_index;

  /*
  ** Find the table that is to be indexed.  Return early if not found.
  */
  if( pTable!=0 ){
    pTab =  sqliteTableFromToken(pParse, pTable);
  }else{
    pTab =  pParse->pNewTable;
................................................................................
  */
  if( pName ){
    zName = sqliteTableNameFromToken(pName);
  }else{
    zName = 0;
    sqliteSetString(&zName, pTab->zName, "__primary_key", 0);
  }
  if( zName==0 ) goto exit_create_index;
  if( sqliteFindIndex(pParse->db, zName) ){
    sqliteSetString(&pParse->zErrMsg, "index ", zName, 
       " already exists", 0);
    pParse->nErr++;
    goto exit_create_index;
  }
  if( sqliteFindTable(pParse->db, zName) ){
................................................................................
  }

  /* 
  ** Allocate the index structure. 
  */
  pIndex = sqliteMalloc( sizeof(Index) + strlen(zName) + 1 +
                        sizeof(int)*pList->nId );



  if( pIndex==0 ) goto exit_create_index;

  pIndex->aiColumn = (int*)&pIndex[1];
  pIndex->zName = (char*)&pIndex->aiColumn[pList->nId];
  strcpy(pIndex->zName, zName);
  pIndex->pTable = pTab;
  pIndex->nColumn = pList->nId;

  /* Scan the names of the columns of the table to be indexed and
................................................................................
** This routine will drop an existing named index.
*/
void sqliteDropIndex(Parse *pParse, Token *pName){
  Index *pIndex;
  char *zName;
  Vdbe *v;

  if( pParse->nErr || sqlite_malloc_failed ) return;
  zName = sqliteTableNameFromToken(pName);
  if( zName==0 ) return;
  pIndex = sqliteFindIndex(pParse->db, zName);
  sqliteFree(zName);
  if( pIndex==0 ){
    sqliteSetNString(&pParse->zErrMsg, "no such index: ", 0, 
        pName->z, pName->n, 0);
    pParse->nErr++;
    return;
................................................................................
** Add a new element to the end of an expression list.  If pList is
** initially NULL, then create a new expression list.
*/
ExprList *sqliteExprListAppend(ExprList *pList, Expr *pExpr, Token *pName){
  int i;
  if( pList==0 ){
    pList = sqliteMalloc( sizeof(ExprList) );

    if( pList==0 ) return 0;
  }
  if( (pList->nExpr & 7)==0 ){
    int n = pList->nExpr + 8;
    pList->a = sqliteRealloc(pList->a, n*sizeof(pList->a[0]));
    if( pList->a==0 ){
      pList->nExpr = 0;
      return pList;
    }
................................................................................
  sqliteFree(pList->a);
  sqliteFree(pList);
}

/*
** Append a new element to the given IdList.  Create a new IdList if
** need be.
**
** A new IdList is returned, or NULL if malloc() fails.
*/
IdList *sqliteIdListAppend(IdList *pList, Token *pToken){
  if( pList==0 ){
    pList = sqliteMalloc( sizeof(IdList) );
    if( pList==0 ) return 0;
  }
  if( (pList->nId & 7)==0 ){
    pList->a = sqliteRealloc(pList->a, (pList->nId+8)*sizeof(pList->a[0]) );
    if( pList->a==0 ){
      pList->nId = 0;
      sqliteIdListDelete(pList);
      return 0;
    }
  }
  memset(&pList->a[pList->nId], 0, sizeof(pList->a[0]));
  if( pToken ){
    char **pz = &pList->a[pList->nId].zName;
    sqliteSetNString(pz, pToken->z, pToken->n, 0);
    if( *pz==0 ){
      sqliteIdListDelete(pList);
      return 0;
    }else{
      sqliteDequote(*pz);
    }
  }
  pList->nId++;
  return pList;
}

/*
** Add an alias to the last identifier on the given identifier list.
................................................................................
*/
void sqliteIdListDelete(IdList *pList){
  int i;
  if( pList==0 ) return;
  for(i=0; i<pList->nId; i++){
    sqliteFree(pList->a[i].zName);
    sqliteFree(pList->a[i].zAlias);
    if( pList->a[i].pSelect ){
      sqliteFree(pList->a[i].zName);
      sqliteSelectDelete(pList->a[i].pSelect);
      sqliteDeleteTable(0, pList->a[i].pTab);
    }
  }
  sqliteFree(pList->a);
  sqliteFree(pList);
}


/*
................................................................................
  char *zTab;
  int i, j;
  Vdbe *v;
  int addr, end;
  Index *pIdx;

  zTab = sqliteTableNameFromToken(pTableName);
  if( sqlite_malloc_failed || zTab==0 ) goto copy_cleanup;
  pTab = sqliteFindTable(pParse->db, zTab);
  sqliteFree(zTab);
  if( pTab==0 ){
    sqliteSetNString(&pParse->zErrMsg, "no such table: ", 0, 
        pTableName->z, pTableName->n, 0);
    pParse->nErr++;
    goto copy_cleanup;
................................................................................
** collapse free space, etc.  It is modelled after the VACUUM command
** in PostgreSQL.
*/
void sqliteVacuum(Parse *pParse, Token *pTableName){
  char *zName;
  Vdbe *v;

  if( pParse->nErr || sqlite_malloc_failed ) return;
  if( pTableName ){
    zName = sqliteTableNameFromToken(pTableName);
  }else{
    zName = 0;
  }
  if( zName && sqliteFindIndex(pParse->db, zName)==0
    && sqliteFindTable(pParse->db, zName)==0 ){
................................................................................
** Begin a transaction
*/
void sqliteBeginTransaction(Parse *pParse){
  int rc;
  DbbeMethods *pM;
  sqlite *db;
  if( pParse==0 || (db=pParse->db)==0 || db->pBe==0 ) return;
  if( pParse->nErr || sqlite_malloc_failed ) return;
  if( db->flags & SQLITE_InTrans ) return;
  pM = pParse->db->pBe->x;
  if( pM && pM->BeginTransaction ){
    rc = (*pM->BeginTransaction)(pParse->db->pBe);
  }else{
    rc = SQLITE_OK;
  }
................................................................................
** Commit a transaction
*/
void sqliteCommitTransaction(Parse *pParse){
  int rc;
  DbbeMethods *pM;
  sqlite *db;
  if( pParse==0 || (db=pParse->db)==0 || db->pBe==0 ) return;
  if( pParse->nErr || sqlite_malloc_failed ) return;
  if( (db->flags & SQLITE_InTrans)==0 ) return;
  pM = pParse->db->pBe->x;
  if( pM && pM->Commit ){
    rc = (*pM->Commit)(pParse->db->pBe);
  }else{
    rc = SQLITE_OK;
  }
................................................................................
** Rollback a transaction
*/
void sqliteRollbackTransaction(Parse *pParse){
  int rc;
  DbbeMethods *pM;
  sqlite *db;
  if( pParse==0 || (db=pParse->db)==0 || db->pBe==0 ) return;
  if( pParse->nErr || sqlite_malloc_failed ) return;
  if( (db->flags & SQLITE_InTrans)==0 ) return;
  pM = pParse->db->pBe->x;
  if( pM && pM->Rollback ){
    rc = (*pM->Rollback)(pParse->db->pBe);
  }else{
    rc = SQLITE_OK;
  }
  if( rc==SQLITE_OK ){
    db->flags &= ~SQLITE_InTrans;
  }
}

Changes to src/dbbe.c.

26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
..
61
62
63
64
65
66
67

68
69
70
71
72
73
74
...
111
112
113
114
115
116
117

** 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.26 2001/04/04 21:22:14 drh Exp $
*/
#include "sqliteInt.h"
#include <unistd.h>
#include <ctype.h>

/*
** This routine opens a new database.  It looks at the first
................................................................................
  if( strncmp(zName, "memory:", 7)==0 ){
    extern Dbbe *sqliteMemOpen(const char*,int,int,char**);
    return sqliteMemOpen(&zName[7], writeFlag, createFlag, pzErrMsg);
  }
  return sqliteGdbmOpen(zName, writeFlag, createFlag, pzErrMsg);
}


/*
** Translate the name of an SQL table (or index) into the name 
** of a file that holds the key/data pairs for that table or
** index.  Space to hold the filename is obtained from
** sqliteMalloc() and must be freed by the calling function.
**
** zDir is the name of the directory in which the file should
................................................................................
  }
  for(k=0; (c = zSuffix[k])!=0; k++){
    zFile[i++] = c;
  }
  zFile[i] = 0;
  return zFile;
}








|







 







>







 







>
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
..
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
...
112
113
114
115
116
117
118
119
** 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.27 2001/04/11 14:28:42 drh Exp $
*/
#include "sqliteInt.h"
#include <unistd.h>
#include <ctype.h>

/*
** This routine opens a new database.  It looks at the first
................................................................................
  if( strncmp(zName, "memory:", 7)==0 ){
    extern Dbbe *sqliteMemOpen(const char*,int,int,char**);
    return sqliteMemOpen(&zName[7], writeFlag, createFlag, pzErrMsg);
  }
  return sqliteGdbmOpen(zName, writeFlag, createFlag, pzErrMsg);
}

#if 0  /* NOT USED */
/*
** Translate the name of an SQL table (or index) into the name 
** of a file that holds the key/data pairs for that table or
** index.  Space to hold the filename is obtained from
** sqliteMalloc() and must be freed by the calling function.
**
** zDir is the name of the directory in which the file should
................................................................................
  }
  for(k=0; (c = zSuffix[k])!=0; k++){
    zFile[i++] = c;
  }
  zFile[i] = 0;
  return zFile;
}
#endif /* NOT USED */

Changes to src/dbbegdbm.c.

26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
...
181
182
183
184
185
186
187

188
189
190
191
192
193
194
** 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: dbbegdbm.c,v 1.6 2001/04/04 11:48:57 drh Exp $
*/
#include "sqliteInt.h"
#include <gdbm.h>
#include <sys/stat.h>
#include <unistd.h>
#include <ctype.h>
#include <time.h>
................................................................................

  if( pBe->inTrans ) writeable = 1;
  *ppCursr = 0;
  pCursr = sqliteMalloc( sizeof(*pCursr) );
  if( pCursr==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;
  }







|







 







>







26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
...
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
** 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: dbbegdbm.c,v 1.7 2001/04/11 14:28:42 drh Exp $
*/
#include "sqliteInt.h"
#include <gdbm.h>
#include <sys/stat.h>
#include <unistd.h>
#include <ctype.h>
#include <time.h>
................................................................................

  if( pBe->inTrans ) writeable = 1;
  *ppCursr = 0;
  pCursr = sqliteMalloc( sizeof(*pCursr) );
  if( pCursr==0 ) return SQLITE_NOMEM;
  if( zTable ){
    zFile = sqliteFileOfTable(pBe, zTable);
    if( zFile==0 ) return SQLITE_NOMEM;
    for(pFile=pBe->pOpen; pFile; pFile=pFile->pNext){
      if( strcmp(pFile->zName,zFile)==0 ) break;
    }
  }else{
    pFile = 0;
    zFile = 0;
  }

Changes to src/dbbemem.c.

26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
...
152
153
154
155
156
157
158

159
160
161
162
163
164
165
...
301
302
303
304
305
306
307

308
309




310
311
312
313
314
315
316
...
464
465
466
467
468
469
470

471
472
473
474
475
476
477
...
686
687
688
689
690
691
692

693
694
695
696
697
698
699
** sqlite and the code that does the actually reading and writing
** of information to the disk.
**
** This file uses an in-memory hash table as the database backend. 
** Nothing is ever written to disk using this backend.  All information
** is forgotten when the program exits.
**
** $Id: dbbemem.c,v 1.13 2001/04/04 11:48:58 drh Exp $
*/
#include "sqliteInt.h"
#include <sys/stat.h>
#include <unistd.h>
#include <ctype.h>
#include <time.h>

................................................................................
static void ArrayRehash(Array *array, int new_size){
  struct _Array_ht *new_ht;       /* The new hash table */
  ArrayElem *elem, *next_elem;    /* For looping over existing elements */
  int i;                          /* Loop counter */
  ArrayElem *x;                   /* Element being copied to new hash table */

  new_ht = sqliteMalloc( new_size*sizeof(struct _Array_ht) );

  if( array->ht ) sqliteFree(array->ht);
  array->ht = new_ht;
  array->htsize = new_size;
  for(i=new_size-1; i>=0; i--){ 
    new_ht[i].count = 0;
    new_ht[i].chain = 0;
  }
................................................................................
  new_elem = (ArrayElem*)sqliteMalloc( sizeof(ArrayElem) + key.n );
  if( new_elem==0 ) return nil;
  new_elem->key.n = key.n;
  new_elem->key.p = (void*)&new_elem[1];
  memcpy(new_elem->key.p, key.p, key.n);
  array->count++;
  if( array->htsize==0 ) ArrayRehash(array,4);

  if( array->count > array->htsize ){
    ArrayRehash(array,array->htsize*2);




  }
  h = hraw & (array->htsize-1);
  elem = array->ht[h].chain;
  if( elem ){
    new_elem->next = elem;
    new_elem->prev = elem->prev;
    if( elem->prev ){ elem->prev->next = new_elem; }
................................................................................

  *ppCursr = 0;
  pCursr = sqliteMalloc( sizeof(*pCursr) );
  if( pCursr==0 ) return SQLITE_NOMEM;
  if( zTable ){
    Datum key;
    zName = sqliteNameOfTable(zTable);

    key.p = zName;
    key.n = strlen(zName);
    pTble = ArrayFind(&pBe->tables, key).p;
  }else{
    zName = 0;
    pTble = 0;
  }
................................................................................
  DbbeCursor *pCursr,       /* Write new entry into this database table */
  int nKey, char *pKey,     /* The key of the new entry */
  int nData, char *pData    /* The data of the new entry */
){
  Datum data, key;
  data.n = nData;
  data.p = sqliteMalloc( data.n );

  memcpy(data.p, pData, data.n);
  key.n = nKey;
  key.p = pKey;
  assert( nKey==4 || pCursr->pTble->intKeyOnly==0 );
  data = ArrayInsert(&pCursr->pTble->data, key, data);
  if( data.p ){
    sqliteFree(data.p);







|







 







>







 







>


>
>
>
>







 







>







 







>







26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
...
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
...
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
...
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
...
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
** sqlite and the code that does the actually reading and writing
** of information to the disk.
**
** This file uses an in-memory hash table as the database backend. 
** Nothing is ever written to disk using this backend.  All information
** is forgotten when the program exits.
**
** $Id: dbbemem.c,v 1.14 2001/04/11 14:28:42 drh Exp $
*/
#include "sqliteInt.h"
#include <sys/stat.h>
#include <unistd.h>
#include <ctype.h>
#include <time.h>

................................................................................
static void ArrayRehash(Array *array, int new_size){
  struct _Array_ht *new_ht;       /* The new hash table */
  ArrayElem *elem, *next_elem;    /* For looping over existing elements */
  int i;                          /* Loop counter */
  ArrayElem *x;                   /* Element being copied to new hash table */

  new_ht = sqliteMalloc( new_size*sizeof(struct _Array_ht) );
  if( new_ht==0 ){ ArrayClear(array); return; }
  if( array->ht ) sqliteFree(array->ht);
  array->ht = new_ht;
  array->htsize = new_size;
  for(i=new_size-1; i>=0; i--){ 
    new_ht[i].count = 0;
    new_ht[i].chain = 0;
  }
................................................................................
  new_elem = (ArrayElem*)sqliteMalloc( sizeof(ArrayElem) + key.n );
  if( new_elem==0 ) return nil;
  new_elem->key.n = key.n;
  new_elem->key.p = (void*)&new_elem[1];
  memcpy(new_elem->key.p, key.p, key.n);
  array->count++;
  if( array->htsize==0 ) ArrayRehash(array,4);
  if( array->htsize==0 ) return nil;
  if( array->count > array->htsize ){
    ArrayRehash(array,array->htsize*2);
    if( array->htsize==0 ){
      sqliteFree(new_elem);
      return nil;
    }
  }
  h = hraw & (array->htsize-1);
  elem = array->ht[h].chain;
  if( elem ){
    new_elem->next = elem;
    new_elem->prev = elem->prev;
    if( elem->prev ){ elem->prev->next = new_elem; }
................................................................................

  *ppCursr = 0;
  pCursr = sqliteMalloc( sizeof(*pCursr) );
  if( pCursr==0 ) return SQLITE_NOMEM;
  if( zTable ){
    Datum key;
    zName = sqliteNameOfTable(zTable);
    if( zName==0 ) return SQLITE_NOMEM;
    key.p = zName;
    key.n = strlen(zName);
    pTble = ArrayFind(&pBe->tables, key).p;
  }else{
    zName = 0;
    pTble = 0;
  }
................................................................................
  DbbeCursor *pCursr,       /* Write new entry into this database table */
  int nKey, char *pKey,     /* The key of the new entry */
  int nData, char *pData    /* The data of the new entry */
){
  Datum data, key;
  data.n = nData;
  data.p = sqliteMalloc( data.n );
  if( data.p==0 ) return SQLITE_NOMEM;
  memcpy(data.p, pData, data.n);
  key.n = nKey;
  key.p = pKey;
  assert( nKey==4 || pCursr->pTble->intKeyOnly==0 );
  data = ArrayInsert(&pCursr->pTble->data, key, data);
  if( data.p ){
    sqliteFree(data.p);

Changes to src/delete.c.

20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
..
40
41
42
43
44
45
46





47
48
49
50
51
52
53

54
55
56
57
58
59
60
**   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.8 2001/03/20 22:05:00 drh Exp $
*/
#include "sqliteInt.h"

/*
** Process a DELETE FROM statement.
*/
void sqliteDeleteFrom(
................................................................................
  Table *pTab;           /* The table from which records will be deleted */
  IdList *pTabList;      /* An ID list holding pTab and nothing else */
  int end, addr;         /* A couple addresses of generated code */
  int i;                 /* Loop counter */
  WhereInfo *pWInfo;     /* Information about the WHERE clause */
  Index *pIdx;           /* For looping over indices of the table */
  int base;              /* Index of the first available table cursor */






  /* Locate the table which we want to delete.  This table has to be
  ** put in an IdList structure because some of the subroutines we
  ** will be calling are designed to work with multiple tables and expect
  ** an IdList* parameter instead of just a Table* parameger.
  */
  pTabList = sqliteIdListAppend(0, pTableName);

  for(i=0; i<pTabList->nId; i++){
    pTabList->a[i].pTab = sqliteFindTable(pParse->db, pTabList->a[i].zName);
    if( pTabList->a[i].pTab==0 ){
      sqliteSetString(&pParse->zErrMsg, "no such table: ", 
         pTabList->a[i].zName, 0);
      pParse->nErr++;
      goto delete_from_cleanup;







|







 







>
>
>
>
>







>







20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
..
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
**   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.9 2001/04/11 14:28:42 drh Exp $
*/
#include "sqliteInt.h"

/*
** Process a DELETE FROM statement.
*/
void sqliteDeleteFrom(
................................................................................
  Table *pTab;           /* The table from which records will be deleted */
  IdList *pTabList;      /* An ID list holding pTab and nothing else */
  int end, addr;         /* A couple addresses of generated code */
  int i;                 /* Loop counter */
  WhereInfo *pWInfo;     /* Information about the WHERE clause */
  Index *pIdx;           /* For looping over indices of the table */
  int base;              /* Index of the first available table cursor */

  if( pParse->nErr || sqlite_malloc_failed ){
    pTabList = 0;
    goto delete_from_cleanup;
  }

  /* Locate the table which we want to delete.  This table has to be
  ** put in an IdList structure because some of the subroutines we
  ** will be calling are designed to work with multiple tables and expect
  ** an IdList* parameter instead of just a Table* parameger.
  */
  pTabList = sqliteIdListAppend(0, pTableName);
  if( pTabList==0 ) goto delete_from_cleanup;
  for(i=0; i<pTabList->nId; i++){
    pTabList->a[i].pTab = sqliteFindTable(pParse->db, pTabList->a[i].zName);
    if( pTabList->a[i].pTab==0 ){
      sqliteSetString(&pParse->zErrMsg, "no such table: ", 
         pTabList->a[i].zName, 0);
      pParse->nErr++;
      goto delete_from_cleanup;

Changes to src/expr.c.

20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
...
119
120
121
122
123
124
125
126
127
128
129
130
131
132

133
134
135
136
137
138
139
...
173
174
175
176
177
178
179





180
181
182
183
184
185
186
...
476
477
478
479
480
481
482

483
484
485
486
487
488
489
...
679
680
681
682
683
684
685

686
687
688
689
690
691
692
...
765
766
767
768
769
770
771

772
773
774
775
776
777
778
...
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
**   drh@hwaci.com
**   http://www.hwaci.com/drh/
**
*************************************************************************
** This file contains routines used for analyzing expressions and
** for generating VDBE code that evaluates expressions.
**
** $Id: expr.c,v 1.23 2001/04/04 21:22:14 drh Exp $
*/
#include "sqliteInt.h"

/*
** Walk an expression tree.  Return 1 if the expression is constant
** and 0 if it involves variables.
*/
................................................................................
** If it finds any, it generates code to write the value of that select
** into a memory cell.
**
** Unknown columns or tables provoke an error.  The function returns
** the number of errors seen and leaves an error message on pParse->zErrMsg.
*/
int sqliteExprResolveIds(Parse *pParse, IdList *pTabList, Expr *pExpr){
  if( pExpr==0 ) return 0;
  switch( pExpr->op ){
    /* A lone identifier */
    case TK_ID: {
      int cnt = 0;      /* Number of matches */
      int i;            /* Loop counter */
      char *z = sqliteStrNDup(pExpr->token.z, pExpr->token.n);

      for(i=0; i<pTabList->nId; i++){
        int j;
        Table *pTab = pTabList->a[i].pTab;
        if( pTab==0 ) continue;
        for(j=0; j<pTab->nCol; j++){
          if( sqliteStrICmp(pTab->aCol[j].zName, z)==0 ){
            cnt++;
................................................................................

      pLeft = pExpr->pLeft;
      pRight = pExpr->pRight;
      assert( pLeft && pLeft->op==TK_ID );
      assert( pRight && pRight->op==TK_ID );
      zLeft = sqliteStrNDup(pLeft->token.z, pLeft->token.n);
      zRight = sqliteStrNDup(pRight->token.z, pRight->token.n);





      pExpr->iTable = -1;
      for(i=0; i<pTabList->nId; i++){
        int j;
        char *zTab;
        Table *pTab = pTabList->a[i].pTab;
        if( pTab==0 ) continue;
        if( pTabList->a[i].zAlias ){
................................................................................
/*
** Generate code into the current Vdbe to evaluate the given
** expression and leave the result on the top of stack.
*/
void sqliteExprCode(Parse *pParse, Expr *pExpr){
  Vdbe *v = pParse->pVdbe;
  int op;

  switch( pExpr->op ){
    case TK_PLUS:     op = OP_Add;      break;
    case TK_MINUS:    op = OP_Subtract; break;
    case TK_STAR:     op = OP_Multiply; break;
    case TK_SLASH:    op = OP_Divide;   break;
    case TK_AND:      op = OP_And;      break;
    case TK_OR:       op = OP_Or;       break;
................................................................................
** Generate code for a boolean expression such that a jump is made
** to the label "dest" if the expression is true but execution
** continues straight thru if the expression is false.
*/
void sqliteExprIfTrue(Parse *pParse, Expr *pExpr, int dest){
  Vdbe *v = pParse->pVdbe;
  int op = 0;

  switch( pExpr->op ){
    case TK_LT:       op = OP_Lt;       break;
    case TK_LE:       op = OP_Le;       break;
    case TK_GT:       op = OP_Gt;       break;
    case TK_GE:       op = OP_Ge;       break;
    case TK_NE:       op = OP_Ne;       break;
    case TK_EQ:       op = OP_Eq;       break;
................................................................................
** Generate code for a boolean expression such that a jump is made
** to the label "dest" if the expression is false but execution
** continues straight thru if the expression is true.
*/
void sqliteExprIfFalse(Parse *pParse, Expr *pExpr, int dest){
  Vdbe *v = pParse->pVdbe;
  int op = 0;

  switch( pExpr->op ){
    case TK_LT:       op = OP_Ge;       break;
    case TK_LE:       op = OP_Gt;       break;
    case TK_GT:       op = OP_Le;       break;
    case TK_GE:       op = OP_Lt;       break;
    case TK_NE:       op = OP_Eq;       break;
    case TK_EQ:       op = OP_Ne;       break;
................................................................................
** Add a new element to the pParse->aAgg[] array and return its index.
*/
static int appendAggInfo(Parse *pParse){
  if( (pParse->nAgg & 0x7)==0 ){
    int amt = pParse->nAgg + 8;
    pParse->aAgg = sqliteRealloc(pParse->aAgg, amt*sizeof(pParse->aAgg[0]));
    if( pParse->aAgg==0 ){
      sqliteSetString(&pParse->zErrMsg, "out of memory", 0);
      pParse->nErr++;
      return -1;
    }
  }
  memset(&pParse->aAgg[pParse->nAgg], 0, sizeof(pParse->aAgg[0]));
  return pParse->nAgg++;
}








|







 







|






>







 







>
>
>
>
>







 







>







 







>







 







>







 







<
|







20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
...
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
...
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
...
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
...
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
...
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
...
901
902
903
904
905
906
907

908
909
910
911
912
913
914
915
**   drh@hwaci.com
**   http://www.hwaci.com/drh/
**
*************************************************************************
** This file contains routines used for analyzing expressions and
** for generating VDBE code that evaluates expressions.
**
** $Id: expr.c,v 1.24 2001/04/11 14:28:42 drh Exp $
*/
#include "sqliteInt.h"

/*
** Walk an expression tree.  Return 1 if the expression is constant
** and 0 if it involves variables.
*/
................................................................................
** If it finds any, it generates code to write the value of that select
** into a memory cell.
**
** Unknown columns or tables provoke an error.  The function returns
** the number of errors seen and leaves an error message on pParse->zErrMsg.
*/
int sqliteExprResolveIds(Parse *pParse, IdList *pTabList, Expr *pExpr){
  if( pExpr==0 || pTabList==0 ) return 0;
  switch( pExpr->op ){
    /* A lone identifier */
    case TK_ID: {
      int cnt = 0;      /* Number of matches */
      int i;            /* Loop counter */
      char *z = sqliteStrNDup(pExpr->token.z, pExpr->token.n);
      if( z==0 ) return 1;
      for(i=0; i<pTabList->nId; i++){
        int j;
        Table *pTab = pTabList->a[i].pTab;
        if( pTab==0 ) continue;
        for(j=0; j<pTab->nCol; j++){
          if( sqliteStrICmp(pTab->aCol[j].zName, z)==0 ){
            cnt++;
................................................................................

      pLeft = pExpr->pLeft;
      pRight = pExpr->pRight;
      assert( pLeft && pLeft->op==TK_ID );
      assert( pRight && pRight->op==TK_ID );
      zLeft = sqliteStrNDup(pLeft->token.z, pLeft->token.n);
      zRight = sqliteStrNDup(pRight->token.z, pRight->token.n);
      if( zLeft==0 || zRight==0 ){
        sqliteFree(zLeft);
        sqliteFree(zRight);
        return 1;
      }
      pExpr->iTable = -1;
      for(i=0; i<pTabList->nId; i++){
        int j;
        char *zTab;
        Table *pTab = pTabList->a[i].pTab;
        if( pTab==0 ) continue;
        if( pTabList->a[i].zAlias ){
................................................................................
/*
** Generate code into the current Vdbe to evaluate the given
** expression and leave the result on the top of stack.
*/
void sqliteExprCode(Parse *pParse, Expr *pExpr){
  Vdbe *v = pParse->pVdbe;
  int op;
  if( v==0 || pExpr==0 ) return;
  switch( pExpr->op ){
    case TK_PLUS:     op = OP_Add;      break;
    case TK_MINUS:    op = OP_Subtract; break;
    case TK_STAR:     op = OP_Multiply; break;
    case TK_SLASH:    op = OP_Divide;   break;
    case TK_AND:      op = OP_And;      break;
    case TK_OR:       op = OP_Or;       break;
................................................................................
** Generate code for a boolean expression such that a jump is made
** to the label "dest" if the expression is true but execution
** continues straight thru if the expression is false.
*/
void sqliteExprIfTrue(Parse *pParse, Expr *pExpr, int dest){
  Vdbe *v = pParse->pVdbe;
  int op = 0;
  if( v==0 || pExpr==0 ) return;
  switch( pExpr->op ){
    case TK_LT:       op = OP_Lt;       break;
    case TK_LE:       op = OP_Le;       break;
    case TK_GT:       op = OP_Gt;       break;
    case TK_GE:       op = OP_Ge;       break;
    case TK_NE:       op = OP_Ne;       break;
    case TK_EQ:       op = OP_Eq;       break;
................................................................................
** Generate code for a boolean expression such that a jump is made
** to the label "dest" if the expression is false but execution
** continues straight thru if the expression is true.
*/
void sqliteExprIfFalse(Parse *pParse, Expr *pExpr, int dest){
  Vdbe *v = pParse->pVdbe;
  int op = 0;
  if( v==0 || pExpr==0 ) return;
  switch( pExpr->op ){
    case TK_LT:       op = OP_Ge;       break;
    case TK_LE:       op = OP_Gt;       break;
    case TK_GT:       op = OP_Le;       break;
    case TK_GE:       op = OP_Lt;       break;
    case TK_NE:       op = OP_Eq;       break;
    case TK_EQ:       op = OP_Ne;       break;
................................................................................
** Add a new element to the pParse->aAgg[] array and return its index.
*/
static int appendAggInfo(Parse *pParse){
  if( (pParse->nAgg & 0x7)==0 ){
    int amt = pParse->nAgg + 8;
    pParse->aAgg = sqliteRealloc(pParse->aAgg, amt*sizeof(pParse->aAgg[0]));
    if( pParse->aAgg==0 ){

      pParse->nAgg = 0;
      return -1;
    }
  }
  memset(&pParse->aAgg[pParse->nAgg], 0, sizeof(pParse->aAgg[0]));
  return pParse->nAgg++;
}

Changes to src/insert.c.

20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
..
55
56
57
58
59
60
61


62
63
64
65

66
67
68
69
70
71
72
..
90
91
92
93
94
95
96
97
98
99
100

101
102
103
104
105
106
107
**   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.12 2001/01/15 22:51:11 drh Exp $
*/
#include "sqliteInt.h"

/*
** This routine is call to handle SQL of the following forms:
**
**    insert into TABLE (IDLIST) values(EXPRLIST)
................................................................................
  int i, j, idx;        /* Loop counters */
  Vdbe *v;              /* Generate code into this virtual machine */
  Index *pIdx;          /* For looping over indices of the table */
  int srcTab;           /* Date comes from this temporary cursor if >=0 */
  int nColumn;          /* Number of columns in the data */
  int base;             /* First available cursor */
  int iCont, iBreak;    /* Beginning and end of the loop over srcTab */



  /* Locate the table into which we will be inserting new information.
  */
  zTab = sqliteTableNameFromToken(pTableName);

  pTab = sqliteFindTable(pParse->db, zTab);
  sqliteFree(zTab);
  if( pTab==0 ){
    sqliteSetNString(&pParse->zErrMsg, "no such table: ", 0, 
        pTableName->z, pTableName->n, 0);
    pParse->nErr++;
    goto insert_cleanup;
................................................................................
  ** then we just have to count the number of expressions.
  */
  if( pSelect ){
    int rc;
    srcTab = pParse->nTab++;
    sqliteVdbeAddOp(v, OP_OpenTbl, srcTab, 1, 0, 0);
    rc = sqliteSelect(pParse, pSelect, SRT_Table, srcTab);
    if( rc ) goto insert_cleanup;
    assert( pSelect->pEList );
    nColumn = pSelect->pEList->nExpr;
  }else{

    srcTab = -1;
    assert( pList );
    nColumn = pList->nExpr;
  }

  /* Make sure the number of columns in the source data matches the number
  ** of columns to be inserted into the table.







|







 







>
>




>







 







|



>







20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
..
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
..
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
**   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.13 2001/04/11 14:28:42 drh Exp $
*/
#include "sqliteInt.h"

/*
** This routine is call to handle SQL of the following forms:
**
**    insert into TABLE (IDLIST) values(EXPRLIST)
................................................................................
  int i, j, idx;        /* Loop counters */
  Vdbe *v;              /* Generate code into this virtual machine */
  Index *pIdx;          /* For looping over indices of the table */
  int srcTab;           /* Date comes from this temporary cursor if >=0 */
  int nColumn;          /* Number of columns in the data */
  int base;             /* First available cursor */
  int iCont, iBreak;    /* Beginning and end of the loop over srcTab */

  if( pParse->nErr || sqlite_malloc_failed ) goto insert_cleanup;

  /* Locate the table into which we will be inserting new information.
  */
  zTab = sqliteTableNameFromToken(pTableName);
  if( zTab==0 ) goto insert_cleanup;
  pTab = sqliteFindTable(pParse->db, zTab);
  sqliteFree(zTab);
  if( pTab==0 ){
    sqliteSetNString(&pParse->zErrMsg, "no such table: ", 0, 
        pTableName->z, pTableName->n, 0);
    pParse->nErr++;
    goto insert_cleanup;
................................................................................
  ** then we just have to count the number of expressions.
  */
  if( pSelect ){
    int rc;
    srcTab = pParse->nTab++;
    sqliteVdbeAddOp(v, OP_OpenTbl, srcTab, 1, 0, 0);
    rc = sqliteSelect(pParse, pSelect, SRT_Table, srcTab);
    if( rc || pParse->nErr || sqlite_malloc_failed ) goto insert_cleanup;
    assert( pSelect->pEList );
    nColumn = pSelect->pEList->nExpr;
  }else{
    assert( pList!=0 );
    srcTab = -1;
    assert( pList );
    nColumn = pList->nExpr;
  }

  /* Make sure the number of columns in the source data matches the number
  ** of columns to be inserted into the table.

Changes to src/main.c.

22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
...
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
...
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
...
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
...
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
...
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
**
*************************************************************************
** 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.27 2001/04/06 16:13:43 drh Exp $
*/
#include "sqliteInt.h"
#include <unistd.h>

/*
** This is the callback routine for the code that initializes the
** database.  Each callback contains text of a CREATE TABLE or
................................................................................
  };

  /* Create a virtual machine to run the initialization program.  Run
  ** the program.  The delete the virtual machine.
  */
  vdbe = sqliteVdbeCreate(db);
  if( vdbe==0 ){
    sqliteSetString(pzErrMsg, "out of memory",0); 
    return 1;
  }
  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->file_format<2 && db->nTable>0 ){
    sqliteSetString(pzErrMsg, "obsolete file format", 0);
................................................................................
    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;
}

/*
** The version of the library
*/
................................................................................
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 ){
    sqliteStrRealloc(pzErrMsg);
    sqliteFree(db);

    return 0;
  }

  /* Assume file format 1 unless the database says otherwise */
  db->file_format = 1;

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


  if( rc!=SQLITE_OK && rc!=SQLITE_BUSY ){
    sqlite_close(db);
    return 0;
  }else /* if( pzErrMsg ) */{
    free(*pzErrMsg);
    *pzErrMsg = 0;
  }
  return db;





}

/*
** Close an existing SQLite database
*/
void sqlite_close(sqlite *db){
  int i;
................................................................................
  char **pzErrMsg             /* Write error messages here */
){
  Parse sParse;

  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;
  sqliteRunParser(&sParse, zSql, pzErrMsg);





  return sParse.rc;
}

/*
** This routine implements a busy callback that sleeps and tries
** again until a timeout value is reached.  The timeout value is
** an integer number of milliseconds passed in as the first
** argument.
*/
static int sqlite_default_busy_callback(
 void *Timeout,           /* Maximum amount of time to wait */
 const char *NotUsed,     /* The name of the table that is busy */
 int count                /* Number of times table has been busy */
){
#if defined(HAVE_USLEEP) && HAVE_USLEEP
  int delay = 10000;
  int prior_delay = 0;
................................................................................

/*
** This routine installs a default busy handler that waits for the
** specified number of milliseconds before returning 0.
*/
void sqlite_busy_timeout(sqlite *db, int ms){
  if( ms>0 ){
    sqlite_busy_handler(db, sqlite_default_busy_callback, (void*)ms);
  }else{
    sqlite_busy_handler(db, 0, 0);
  }
}

/*
** Cause any pending operation to stop at its earliest opportunity.
*/
void sqlite_interrupt(sqlite *db){
  db->flags |= SQLITE_Interrupt;
}







|







 







|
|







 







<
<







 







|
<
<
<
<




<

>








>
>
|



|



>
>
>
>
>







 







|
>
>
>






>
>
>
>
>









|







 







|











22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
...
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
...
175
176
177
178
179
180
181


182
183
184
185
186
187
188
...
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
...
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
...
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
**
*************************************************************************
** 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.28 2001/04/11 14:28:42 drh Exp $
*/
#include "sqliteInt.h"
#include <unistd.h>

/*
** This is the callback routine for the code that initializes the
** database.  Each callback contains text of a CREATE TABLE or
................................................................................
  };

  /* Create a virtual machine to run the initialization program.  Run
  ** the program.  The delete the virtual machine.
  */
  vdbe = sqliteVdbeCreate(db);
  if( vdbe==0 ){
    sqliteSetString(pzErrMsg, "out of memory");
    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->file_format<2 && db->nTable>0 ){
    sqliteSetString(pzErrMsg, "obsolete file format", 0);
................................................................................
    azArg[1] = 0;
    sqliteOpenCb(db, 1, azArg, 0);
    pTab = sqliteFindTable(db, MASTER_NAME);
    if( pTab ){
      pTab->readOnly = 1;
    }
    db->flags |= SQLITE_Initialized;


  }
  return rc;
}

/*
** The version of the library
*/
................................................................................
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 ) goto no_mem_on_open;




  
  /* Open the backend database driver */
  db->pBe = sqliteDbbeOpen(zFilename, (mode&0222)!=0, mode!=0, pzErrMsg);
  if( db->pBe==0 ){

    sqliteFree(db);
    sqliteStrRealloc(pzErrMsg);
    return 0;
  }

  /* Assume file format 1 unless the database says otherwise */
  db->file_format = 1;

  /* Attempt to read the schema */
  rc = sqliteInit(db, pzErrMsg);
  if( sqlite_malloc_failed ){
    goto no_mem_on_open;
  }else if( rc!=SQLITE_OK && rc!=SQLITE_BUSY ){
    sqlite_close(db);
    return 0;
  }else /* if( pzErrMsg ) */{
    sqliteFree(*pzErrMsg);
    *pzErrMsg = 0;
  }
  return db;

no_mem_on_open:
  sqliteSetString(pzErrMsg, "out of memory", 0);
  sqliteStrRealloc(pzErrMsg);
  return 0;
}

/*
** Close an existing SQLite database
*/
void sqlite_close(sqlite *db){
  int i;
................................................................................
  char **pzErrMsg             /* Write error messages here */
){
  Parse sParse;

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

/*
** This routine implements a busy callback that sleeps and tries
** again until a timeout value is reached.  The timeout value is
** an integer number of milliseconds passed in as the first
** argument.
*/
static int sqliteDefaultBusyCallback(
 void *Timeout,           /* Maximum amount of time to wait */
 const char *NotUsed,     /* The name of the table that is busy */
 int count                /* Number of times table has been busy */
){
#if defined(HAVE_USLEEP) && HAVE_USLEEP
  int delay = 10000;
  int prior_delay = 0;
................................................................................

/*
** This routine installs a default busy handler that waits for the
** specified number of milliseconds before returning 0.
*/
void sqlite_busy_timeout(sqlite *db, int ms){
  if( ms>0 ){
    sqlite_busy_handler(db, sqliteDefaultBusyCallback, (void*)ms);
  }else{
    sqlite_busy_handler(db, 0, 0);
  }
}

/*
** Cause any pending operation to stop at its earliest opportunity.
*/
void sqlite_interrupt(sqlite *db){
  db->flags |= SQLITE_Interrupt;
}

Changes to src/parse.y.

22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
...
166
167
168
169
170
171
172

173
174

175
176
177
178
179
180
181
182
...
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
...
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
...
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
**
*************************************************************************
** This file contains SQLite's grammar for SQL.  Process this file
** using the lemon parser generator to generate C code that runs
** the parser.  Lemon will also generate a header file containing
** numeric codes for all of the tokens.
**
** @(#) $Id: parse.y,v 1.27 2001/04/04 11:48:58 drh Exp $
*/
%token_prefix TK_
%token_type {Token}
%extra_argument {Parse *pParse}
%syntax_error {
  sqliteSetString(&pParse->zErrMsg,"syntax error",0);
  pParse->sErrToken = TOKEN;
................................................................................
%type select {Select*}
%destructor select {sqliteSelectDelete($$);}
%type oneselect {Select*}
%destructor oneselect {sqliteSelectDelete($$);}

select(A) ::= oneselect(X).                      {A = X;}
select(A) ::= select(X) joinop(Y) oneselect(Z).  {

    Z->op = Y;
    Z->pPrior = X;

    A = Z;
}
%type joinop {int}
joinop(A) ::= UNION.      {A = TK_UNION;}
joinop(A) ::= UNION ALL.  {A = TK_ALL;}
joinop(A) ::= INTERSECT.  {A = TK_INTERSECT;}
joinop(A) ::= EXCEPT.     {A = TK_EXCEPT;}
oneselect(A) ::= SELECT distinct(D) selcollist(W) from(X) where_opt(Y)
................................................................................
%type sortitem {Expr*}
%destructor sortitem {sqliteExprDelete($$);}

orderby_opt(A) ::= .                          {A = 0;}
orderby_opt(A) ::= ORDER BY sortlist(X).      {A = X;}
sortlist(A) ::= sortlist(X) COMMA sortitem(Y) sortorder(Z). {
  A = sqliteExprListAppend(X,Y,0);
  A->a[A->nExpr-1].sortOrder = Z;   /* 0 for ascending order, 1 for decending */
}
sortlist(A) ::= sortitem(Y) sortorder(Z). {
  A = sqliteExprListAppend(0,Y,0);
  A->a[0].sortOrder = Z;
}
sortitem(A) ::= expr(X).   {A = X;}

%type sortorder {int}

sortorder(A) ::= ASC.      {A = 0;}
sortorder(A) ::= DESC.     {A = 1;}
................................................................................

itemlist(A) ::= itemlist(X) COMMA item(Y).  {A = sqliteExprListAppend(X,Y,0);}
itemlist(A) ::= item(X).     {A = sqliteExprListAppend(0,X,0);}
item(A) ::= INTEGER(X).      {A = sqliteExpr(TK_INTEGER, 0, 0, &X);}
item(A) ::= PLUS INTEGER(X). {A = sqliteExpr(TK_INTEGER, 0, 0, &X);}
item(A) ::= MINUS INTEGER(X). {
  A = sqliteExpr(TK_UMINUS, 0, 0, 0);
  A->pLeft = sqliteExpr(TK_INTEGER, 0, 0, &X);
}
item(A) ::= FLOAT(X).        {A = sqliteExpr(TK_FLOAT, 0, 0, &X);}
item(A) ::= PLUS FLOAT(X).   {A = sqliteExpr(TK_FLOAT, 0, 0, &X);}
item(A) ::= MINUS FLOAT(X).  {
  A = sqliteExpr(TK_UMINUS, 0, 0, 0);
  A->pLeft = sqliteExpr(TK_FLOAT, 0, 0, &X);
}
item(A) ::= STRING(X).       {A = sqliteExpr(TK_STRING, 0, 0, &X);}
item(A) ::= NULL.            {A = sqliteExpr(TK_NULL, 0, 0, 0);}

%type inscollist_opt {IdList*}
%destructor inscollist_opt {sqliteIdListDelete($$);}
%type inscollist {IdList*}
................................................................................
}
expr(A) ::= PLUS(B) expr(X). [UMINUS] {
  A = X;
  sqliteExprSpan(A,&B,&X->span);
}
expr(A) ::= LP(B) select(X) RP(E). {
  A = sqliteExpr(TK_SELECT, 0, 0, 0);
  A->pSelect = X;
  sqliteExprSpan(A,&B,&E);
}
expr(A) ::= expr(W) BETWEEN expr(X) AND expr(Y). {
  ExprList *pList = sqliteExprListAppend(0, X, 0);
  pList = sqliteExprListAppend(pList, Y, 0);
  A = sqliteExpr(TK_BETWEEN, W, 0, 0);
  A->pList = pList;
  sqliteExprSpan(A,&W->span,&Y->span);
}
expr(A) ::= expr(W) NOT BETWEEN expr(X) AND expr(Y). {
  ExprList *pList = sqliteExprListAppend(0, X, 0);
  pList = sqliteExprListAppend(pList, Y, 0);
  A = sqliteExpr(TK_BETWEEN, W, 0, 0);
  A->pList = pList;
  A = sqliteExpr(TK_NOT, A, 0, 0);
  sqliteExprSpan(A,&W->span,&Y->span);
}
expr(A) ::= expr(X) IN LP exprlist(Y) RP(E).  {
  A = sqliteExpr(TK_IN, X, 0, 0);
  A->pList = Y;
  sqliteExprSpan(A,&X->span,&E);
}
expr(A) ::= expr(X) IN LP select(Y) RP(E).  {
  A = sqliteExpr(TK_IN, X, 0, 0);
  A->pSelect = Y;
  sqliteExprSpan(A,&X->span,&E);
}
expr(A) ::= expr(X) NOT IN LP exprlist(Y) RP(E).  {
  A = sqliteExpr(TK_IN, X, 0, 0);
  A->pList = Y;
  A = sqliteExpr(TK_NOT, A, 0, 0);
  sqliteExprSpan(A,&X->span,&E);
}
expr(A) ::= expr(X) NOT IN LP select(Y) RP(E).  {
  A = sqliteExpr(TK_IN, X, 0, 0);
  A->pSelect = Y;
  A = sqliteExpr(TK_NOT, A, 0, 0);
  sqliteExprSpan(A,&X->span,&E);
}



%type exprlist {ExprList*}







|







 







>


>
|







 







|



|







 







|





|







 







|






|






|





|




|




|





|







22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
...
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
...
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
...
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
...
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
**
*************************************************************************
** This file contains SQLite's grammar for SQL.  Process this file
** using the lemon parser generator to generate C code that runs
** the parser.  Lemon will also generate a header file containing
** numeric codes for all of the tokens.
**
** @(#) $Id: parse.y,v 1.28 2001/04/11 14:28:42 drh Exp $
*/
%token_prefix TK_
%token_type {Token}
%extra_argument {Parse *pParse}
%syntax_error {
  sqliteSetString(&pParse->zErrMsg,"syntax error",0);
  pParse->sErrToken = TOKEN;
................................................................................
%type select {Select*}
%destructor select {sqliteSelectDelete($$);}
%type oneselect {Select*}
%destructor oneselect {sqliteSelectDelete($$);}

select(A) ::= oneselect(X).                      {A = X;}
select(A) ::= select(X) joinop(Y) oneselect(Z).  {
  if( Z ){
    Z->op = Y;
    Z->pPrior = X;
  }
  A = Z;
}
%type joinop {int}
joinop(A) ::= UNION.      {A = TK_UNION;}
joinop(A) ::= UNION ALL.  {A = TK_ALL;}
joinop(A) ::= INTERSECT.  {A = TK_INTERSECT;}
joinop(A) ::= EXCEPT.     {A = TK_EXCEPT;}
oneselect(A) ::= SELECT distinct(D) selcollist(W) from(X) where_opt(Y)
................................................................................
%type sortitem {Expr*}
%destructor sortitem {sqliteExprDelete($$);}

orderby_opt(A) ::= .                          {A = 0;}
orderby_opt(A) ::= ORDER BY sortlist(X).      {A = X;}
sortlist(A) ::= sortlist(X) COMMA sortitem(Y) sortorder(Z). {
  A = sqliteExprListAppend(X,Y,0);
  if( A ) A->a[A->nExpr-1].sortOrder = Z;  /* 0=ascending, 1=decending */
}
sortlist(A) ::= sortitem(Y) sortorder(Z). {
  A = sqliteExprListAppend(0,Y,0);
  if( A ) A->a[0].sortOrder = Z;
}
sortitem(A) ::= expr(X).   {A = X;}

%type sortorder {int}

sortorder(A) ::= ASC.      {A = 0;}
sortorder(A) ::= DESC.     {A = 1;}
................................................................................

itemlist(A) ::= itemlist(X) COMMA item(Y).  {A = sqliteExprListAppend(X,Y,0);}
itemlist(A) ::= item(X).     {A = sqliteExprListAppend(0,X,0);}
item(A) ::= INTEGER(X).      {A = sqliteExpr(TK_INTEGER, 0, 0, &X);}
item(A) ::= PLUS INTEGER(X). {A = sqliteExpr(TK_INTEGER, 0, 0, &X);}
item(A) ::= MINUS INTEGER(X). {
  A = sqliteExpr(TK_UMINUS, 0, 0, 0);
  if( A ) A->pLeft = sqliteExpr(TK_INTEGER, 0, 0, &X);
}
item(A) ::= FLOAT(X).        {A = sqliteExpr(TK_FLOAT, 0, 0, &X);}
item(A) ::= PLUS FLOAT(X).   {A = sqliteExpr(TK_FLOAT, 0, 0, &X);}
item(A) ::= MINUS FLOAT(X).  {
  A = sqliteExpr(TK_UMINUS, 0, 0, 0);
  if( A ) A->pLeft = sqliteExpr(TK_FLOAT, 0, 0, &X);
}
item(A) ::= STRING(X).       {A = sqliteExpr(TK_STRING, 0, 0, &X);}
item(A) ::= NULL.            {A = sqliteExpr(TK_NULL, 0, 0, 0);}

%type inscollist_opt {IdList*}
%destructor inscollist_opt {sqliteIdListDelete($$);}
%type inscollist {IdList*}
................................................................................
}
expr(A) ::= PLUS(B) expr(X). [UMINUS] {
  A = X;
  sqliteExprSpan(A,&B,&X->span);
}
expr(A) ::= LP(B) select(X) RP(E). {
  A = sqliteExpr(TK_SELECT, 0, 0, 0);
  if( A ) A->pSelect = X;
  sqliteExprSpan(A,&B,&E);
}
expr(A) ::= expr(W) BETWEEN expr(X) AND expr(Y). {
  ExprList *pList = sqliteExprListAppend(0, X, 0);
  pList = sqliteExprListAppend(pList, Y, 0);
  A = sqliteExpr(TK_BETWEEN, W, 0, 0);
  if( A ) A->pList = pList;
  sqliteExprSpan(A,&W->span,&Y->span);
}
expr(A) ::= expr(W) NOT BETWEEN expr(X) AND expr(Y). {
  ExprList *pList = sqliteExprListAppend(0, X, 0);
  pList = sqliteExprListAppend(pList, Y, 0);
  A = sqliteExpr(TK_BETWEEN, W, 0, 0);
  if( A ) A->pList = pList;
  A = sqliteExpr(TK_NOT, A, 0, 0);
  sqliteExprSpan(A,&W->span,&Y->span);
}
expr(A) ::= expr(X) IN LP exprlist(Y) RP(E).  {
  A = sqliteExpr(TK_IN, X, 0, 0);
  if( A ) A->pList = Y;
  sqliteExprSpan(A,&X->span,&E);
}
expr(A) ::= expr(X) IN LP select(Y) RP(E).  {
  A = sqliteExpr(TK_IN, X, 0, 0);
  if( A ) A->pSelect = Y;
  sqliteExprSpan(A,&X->span,&E);
}
expr(A) ::= expr(X) NOT IN LP exprlist(Y) RP(E).  {
  A = sqliteExpr(TK_IN, X, 0, 0);
  if( A ) A->pList = Y;
  A = sqliteExpr(TK_NOT, A, 0, 0);
  sqliteExprSpan(A,&X->span,&E);
}
expr(A) ::= expr(X) NOT IN LP select(Y) RP(E).  {
  A = sqliteExpr(TK_IN, X, 0, 0);
  if( A ) A->pSelect = Y;
  A = sqliteExpr(TK_NOT, A, 0, 0);
  sqliteExprSpan(A,&X->span,&E);
}



%type exprlist {ExprList*}

Changes to src/printf.c.

559
560
561
562
563
564
565

566
567
568
569
570
571
572
          if( arg==0 ) arg = "(NULL)";
          for(i=n=0; (c=arg[i])!=0; i++){
            if( c=='\'' )  n++;
          }
          n += i + 1;
          if( n>etBUFSIZE ){
            bufpt = zExtra = sqliteMalloc( n );

          }else{
            bufpt = buf;
          }
          for(i=j=0; (c=arg[i])!=0; i++){
            bufpt[j++] = c;
            if( c=='\'' ) bufpt[j++] = c;
          }







>







559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
          if( arg==0 ) arg = "(NULL)";
          for(i=n=0; (c=arg[i])!=0; i++){
            if( c=='\'' )  n++;
          }
          n += i + 1;
          if( n>etBUFSIZE ){
            bufpt = zExtra = sqliteMalloc( n );
            if( bufpt==0 ) return -1;
          }else{
            bufpt = buf;
          }
          for(i=j=0; (c=arg[i])!=0; i++){
            bufpt[j++] = c;
            if( c=='\'' ) bufpt[j++] = c;
          }

Changes to src/select.c.

20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46







47
48
49
50
51
52
53
54

55
56
57
58
59
60
61
..
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
...
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
...
295
296
297
298
299
300
301




302
303
304
305
306
307
308
309
310











311
312
313
314
315
316
317
...
322
323
324
325
326
327
328

329

330
331
332

333
334
335
336
337
338
339
...
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
...
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
...
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
...
646
647
648
649
650
651
652


653
654
655
656
657
658
659
...
682
683
684
685
686
687
688

689
690
691
692
693
694
695
...
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
**   drh@hwaci.com
**   http://www.hwaci.com/drh/
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle SELECT statements.
**
** $Id: select.c,v 1.30 2001/04/04 11:48:58 drh Exp $
*/
#include "sqliteInt.h"

/*
** Allocate a new Select structure and return a pointer to that
** structure.
*/
Select *sqliteSelectNew(
  ExprList *pEList,
  IdList *pSrc,
  Expr *pWhere,
  ExprList *pGroupBy,
  Expr *pHaving,
  ExprList *pOrderBy,
  int isDistinct
){
  Select *pNew;
  pNew = sqliteMalloc( sizeof(*pNew) );
  if( pNew==0 ) return 0;







  pNew->pEList = pEList;
  pNew->pSrc = pSrc;
  pNew->pWhere = pWhere;
  pNew->pGroupBy = pGroupBy;
  pNew->pHaving = pHaving;
  pNew->pOrderBy = pOrderBy;
  pNew->isDistinct = isDistinct;
  pNew->op = TK_SELECT;

  return pNew;
}

/*
** Delete the given Select structure and all of its substructures.
*/
void sqliteSelectDelete(Select *p){
................................................................................
  int eDest,              /* How to dispose of the results */
  int iParm,              /* An argument to the disposal method */
  int iContinue,          /* Jump here to continue with next row */
  int iBreak              /* Jump here to break out of the inner loop */
){
  Vdbe *v = pParse->pVdbe;
  int i;


  /* Pull the requested columns.
  */
  if( pEList ){
    for(i=0; i<pEList->nExpr; i++){
      sqliteExprCode(pParse, pEList->a[i].pExpr);
    }
................................................................................
    nColumn = pEList->nExpr;
  }else{
    for(i=0; i<nColumn; i++){
      sqliteVdbeAddOp(v, OP_Field, srcTab, i, 0, 0);
    }
  }

  /* If the current result is not distinct, skip the rest
  ** of the processing for the current row.

  */
  if( distinct>=0 ){
    int lbl = sqliteVdbeMakeLabel(v);
    sqliteVdbeAddOp(v, OP_MakeKey, pEList->nExpr, 1, 0, 0);
    sqliteVdbeAddOp(v, OP_Distinct, distinct, lbl, 0, 0);
    sqliteVdbeAddOp(v, OP_Pop, pEList->nExpr+1, 0, 0, 0);
    sqliteVdbeAddOp(v, OP_Goto, 0, iContinue, 0, 0);
................................................................................
** are in the result and the name for each column.  This information
** is used to provide "argc" and "azCol[]" values in the callback.
*/
static 
void generateColumnNames(Parse *pParse, IdList *pTabList, ExprList *pEList){
  Vdbe *v = pParse->pVdbe;
  int i;
  if( pParse->colNamesSet ) return;
  pParse->colNamesSet = 1;
  sqliteVdbeAddOp(v, OP_ColumnCount, pEList->nExpr, 0, 0, 0);
  for(i=0; i<pEList->nExpr; i++){
    Expr *p;
    int addr;
    if( pEList->a[i].zName ){
      char *zName = pEList->a[i].zName;
      sqliteVdbeAddOp(v, OP_ColumnName, i, 0, zName, 0);
      continue;
    }
    p = pEList->a[i].pExpr;

    if( p->span.z && p->span.z[0] ){
      addr = sqliteVdbeAddOp(v,OP_ColumnName, i, 0, 0, 0);
      sqliteVdbeChangeP3(v, addr, p->span.z, p->span.n);
      sqliteVdbeCompressSpace(v, addr);
    }else if( p->op!=TK_COLUMN || pTabList==0 ){
      char zName[30];
      sprintf(zName, "column%d", i+1);
................................................................................
**         of all tables.
**
** Return 0 on success.  If there are problems, leave an error message
** in pParse and return non-zero.
*/
static int fillInColumnList(Parse *pParse, Select *p){
  int i, j;




  IdList *pTabList = p->pSrc;
  ExprList *pEList = p->pEList;

  /* Look up every table in the table list.
  */
  for(i=0; i<pTabList->nId; i++){
    if( pTabList->a[i].pTab ){
      /* This routine has run before!  No need to continue */
      return 0;











    }
    pTabList->a[i].pTab = sqliteFindTable(pParse->db, pTabList->a[i].zName);
    if( pTabList->a[i].pTab==0 ){
      sqliteSetString(&pParse->zErrMsg, "no such table: ", 
         pTabList->a[i].zName, 0);
      pParse->nErr++;
      return 1;
................................................................................
  ** a list of all columns from all tables.
  */
  if( pEList==0 ){
    for(i=0; i<pTabList->nId; i++){
      Table *pTab = pTabList->a[i].pTab;
      for(j=0; j<pTab->nCol; j++){
        Expr *pExpr = sqliteExpr(TK_DOT, 0, 0, 0);

        pExpr->pLeft = sqliteExpr(TK_ID, 0, 0, 0);

        pExpr->pLeft->token.z = pTab->zName;
        pExpr->pLeft->token.n = strlen(pTab->zName);
        pExpr->pRight = sqliteExpr(TK_ID, 0, 0, 0);

        pExpr->pRight->token.z = pTab->aCol[j].zName;
        pExpr->pRight->token.n = strlen(pTab->aCol[j].zName);
        pExpr->span.z = "";
        pExpr->span.n = 0;
        pEList = sqliteExprListAppend(pEList, pExpr, 0);
      }
    }
................................................................................
  int iTable,             /* Insert this this value in iTable */
  int mustComplete        /* If TRUE all ORDER BYs must match */
){
  int nErr = 0;
  int i, j;
  ExprList *pEList;

  assert( pSelect && pOrderBy );
  if( mustComplete ){
    for(i=0; i<pOrderBy->nExpr; i++){ pOrderBy->a[i].done = 0; }
  }
  if( fillInColumnList(pParse, pSelect) ){
    return 1;
  }
  if( pSelect->pPrior ){
................................................................................
** If an error occurs, return NULL and leave a message in pParse.
*/
Vdbe *sqliteGetVdbe(Parse *pParse){
  Vdbe *v = pParse->pVdbe;
  if( v==0 ){
    v = pParse->pVdbe = sqliteVdbeCreate(pParse->db);
  }
  if( v==0 ){
    sqliteSetString(&pParse->zErrMsg, "out of memory", 0);
    pParse->nErr++;
  }
  return v;
}
    

/*
** This routine is called to process a query that is really the union
** or intersection of two or more separate queries.
................................................................................
  Select *pPrior;     /* Another SELECT immediately to our left */
  Vdbe *v;            /* Generate code to this VDBE */
  int base;           /* Baseline value for pParse->nTab */

  /* Make sure there is no ORDER BY clause on prior SELECTs.  Only the 
  ** last SELECT in the series may have an ORDER BY.
  */
  assert( p->pPrior!=0 );
  pPrior = p->pPrior;
  if( pPrior->pOrderBy ){
    sqliteSetString(&pParse->zErrMsg,"ORDER BY clause should come after ",
      selectOpName(p->op), " not before", 0);
    pParse->nErr++;
    return 1;
  }
................................................................................
  Expr *pWhere;          /* The WHERE clause.  May be NULL */
  ExprList *pOrderBy;    /* The ORDER BY clause.  May be NULL */
  ExprList *pGroupBy;    /* The GROUP BY clause.  May be NULL */
  Expr *pHaving;         /* The HAVING clause.  May be NULL */
  int isDistinct;        /* True if the DISTINCT keyword is present */
  int distinct;          /* Table to use for the distinct set */
  int base;              /* First cursor available for use */



  /* If there is are a sequence of queries, do the earlier ones first.
  */
  if( p->pPrior ){
    return multiSelect(pParse, p, eDest, iParm);
  }

................................................................................
  ** columnlist in pEList if there isn't one already.  (The parser leaves
  ** a NULL in the p->pEList if the SQL said "SELECT * FROM ...")
  */
  if( fillInColumnList(pParse, p) ){
    return 1;
  }
  pEList = p->pEList;


  /* Allocate a temporary table to use for the DISTINCT set, if
  ** necessary.  This must be done early to allocate the cursor before
  ** any calls to sqliteExprResolveIds().
  */
  if( isDistinct ){
    distinct = pParse->nTab++;
................................................................................
        }
      }
    }
  }

  /* Begin generating code.
  */
  v = pParse->pVdbe;
  if( v==0 ){
    v = pParse->pVdbe = sqliteVdbeCreate(pParse->db);
  }
  if( v==0 ){
    sqliteSetString(&pParse->zErrMsg, "out of memory", 0);
    pParse->nErr++;
    return 1;
  }
  if( pOrderBy ){
    sqliteVdbeAddOp(v, OP_SortOpen, 0, 0, 0, 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.
  */







|








|
|
|
|
|
|
|



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







 







>







 







|
|
>







 







|











>







 







>
>
>
>
|
|







>
>
>
>
>
>
>
>
>
>
>







 







>

>



>







 







|







 







<
<
<
<







 







|







 







>
>







 







>







 







|
|
<
<
<
<
<
<
<







20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
...
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
...
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
...
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
...
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
...
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
...
451
452
453
454
455
456
457




458
459
460
461
462
463
464
...
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
...
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
...
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
...
844
845
846
847
848
849
850
851
852







853
854
855
856
857
858
859
**   drh@hwaci.com
**   http://www.hwaci.com/drh/
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle SELECT statements.
**
** $Id: select.c,v 1.31 2001/04/11 14:28:42 drh Exp $
*/
#include "sqliteInt.h"

/*
** Allocate a new Select structure and return a pointer to that
** structure.
*/
Select *sqliteSelectNew(
  ExprList *pEList,     /* which columns to include in the result */
  IdList *pSrc,         /* the FROM clause -- which tables to scan */
  Expr *pWhere,         /* the WHERE clause */
  ExprList *pGroupBy,   /* the GROUP BY clause */
  Expr *pHaving,        /* the HAVING clause */
  ExprList *pOrderBy,   /* the ORDER BY clause */
  int isDistinct        /* true if the DISTINCT keyword is present */
){
  Select *pNew;
  pNew = sqliteMalloc( sizeof(*pNew) );
  if( pNew==0 ){
    sqliteExprListDelete(pEList);
    sqliteIdListDelete(pSrc);
    sqliteExprDelete(pWhere);
    sqliteExprListDelete(pGroupBy);
    sqliteExprDelete(pHaving);
    sqliteExprListDelete(pOrderBy);
  }else{
    pNew->pEList = pEList;
    pNew->pSrc = pSrc;
    pNew->pWhere = pWhere;
    pNew->pGroupBy = pGroupBy;
    pNew->pHaving = pHaving;
    pNew->pOrderBy = pOrderBy;
    pNew->isDistinct = isDistinct;
    pNew->op = TK_SELECT;
  }
  return pNew;
}

/*
** Delete the given Select structure and all of its substructures.
*/
void sqliteSelectDelete(Select *p){
................................................................................
  int eDest,              /* How to dispose of the results */
  int iParm,              /* An argument to the disposal method */
  int iContinue,          /* Jump here to continue with next row */
  int iBreak              /* Jump here to break out of the inner loop */
){
  Vdbe *v = pParse->pVdbe;
  int i;
  if( v==0 ) return 0;

  /* Pull the requested columns.
  */
  if( pEList ){
    for(i=0; i<pEList->nExpr; i++){
      sqliteExprCode(pParse, pEList->a[i].pExpr);
    }
................................................................................
    nColumn = pEList->nExpr;
  }else{
    for(i=0; i<nColumn; i++){
      sqliteVdbeAddOp(v, OP_Field, srcTab, i, 0, 0);
    }
  }

  /* If the DISTINCT keyword was present on the SELECT statement
  ** and this row has been seen before, then do not make this row
  ** part of the result.
  */
  if( distinct>=0 ){
    int lbl = sqliteVdbeMakeLabel(v);
    sqliteVdbeAddOp(v, OP_MakeKey, pEList->nExpr, 1, 0, 0);
    sqliteVdbeAddOp(v, OP_Distinct, distinct, lbl, 0, 0);
    sqliteVdbeAddOp(v, OP_Pop, pEList->nExpr+1, 0, 0, 0);
    sqliteVdbeAddOp(v, OP_Goto, 0, iContinue, 0, 0);
................................................................................
** are in the result and the name for each column.  This information
** is used to provide "argc" and "azCol[]" values in the callback.
*/
static 
void generateColumnNames(Parse *pParse, IdList *pTabList, ExprList *pEList){
  Vdbe *v = pParse->pVdbe;
  int i;
  if( pParse->colNamesSet || v==0 || sqlite_malloc_failed ) return;
  pParse->colNamesSet = 1;
  sqliteVdbeAddOp(v, OP_ColumnCount, pEList->nExpr, 0, 0, 0);
  for(i=0; i<pEList->nExpr; i++){
    Expr *p;
    int addr;
    if( pEList->a[i].zName ){
      char *zName = pEList->a[i].zName;
      sqliteVdbeAddOp(v, OP_ColumnName, i, 0, zName, 0);
      continue;
    }
    p = pEList->a[i].pExpr;
    if( p==0 ) continue;
    if( p->span.z && p->span.z[0] ){
      addr = sqliteVdbeAddOp(v,OP_ColumnName, i, 0, 0, 0);
      sqliteVdbeChangeP3(v, addr, p->span.z, p->span.n);
      sqliteVdbeCompressSpace(v, addr);
    }else if( p->op!=TK_COLUMN || pTabList==0 ){
      char zName[30];
      sprintf(zName, "column%d", i+1);
................................................................................
**         of all tables.
**
** Return 0 on success.  If there are problems, leave an error message
** in pParse and return non-zero.
*/
static int fillInColumnList(Parse *pParse, Select *p){
  int i, j;
  IdList *pTabList;
  ExprList *pEList;

  if( p==0 || p->pSrc==0 ) return 1;
  pTabList = p->pSrc;
  pEList = p->pEList;

  /* Look up every table in the table list.
  */
  for(i=0; i<pTabList->nId; i++){
    if( pTabList->a[i].pTab ){
      /* This routine has run before!  No need to continue */
      return 0;
    }
    if( pTabList->a[i].zName==0 ){
      /* No table name is given.  Instead, there is a (SELECT ...) statement
      ** the results of which should be used in place of the table.  The
      ** was this is implemented is that the (SELECT ...) writes its results
      ** into a temporary table which is then scanned like any other table.
      */
      sqliteSetString(&pParse->zErrMsg, 
          "(SELECT...) in a FROM clause is not yet implemented.", 0);
      pParse->nErr++;
      return 1;
    }
    pTabList->a[i].pTab = sqliteFindTable(pParse->db, pTabList->a[i].zName);
    if( pTabList->a[i].pTab==0 ){
      sqliteSetString(&pParse->zErrMsg, "no such table: ", 
         pTabList->a[i].zName, 0);
      pParse->nErr++;
      return 1;
................................................................................
  ** a list of all columns from all tables.
  */
  if( pEList==0 ){
    for(i=0; i<pTabList->nId; i++){
      Table *pTab = pTabList->a[i].pTab;
      for(j=0; j<pTab->nCol; j++){
        Expr *pExpr = sqliteExpr(TK_DOT, 0, 0, 0);
        if( pExpr==0 ) break;
        pExpr->pLeft = sqliteExpr(TK_ID, 0, 0, 0);
        if( pExpr->pLeft==0 ) break;
        pExpr->pLeft->token.z = pTab->zName;
        pExpr->pLeft->token.n = strlen(pTab->zName);
        pExpr->pRight = sqliteExpr(TK_ID, 0, 0, 0);
        if( pExpr->pRight==0 ) break;
        pExpr->pRight->token.z = pTab->aCol[j].zName;
        pExpr->pRight->token.n = strlen(pTab->aCol[j].zName);
        pExpr->span.z = "";
        pExpr->span.n = 0;
        pEList = sqliteExprListAppend(pEList, pExpr, 0);
      }
    }
................................................................................
  int iTable,             /* Insert this this value in iTable */
  int mustComplete        /* If TRUE all ORDER BYs must match */
){
  int nErr = 0;
  int i, j;
  ExprList *pEList;

  if( pSelect==0 || pOrderBy==0 ) return 1;
  if( mustComplete ){
    for(i=0; i<pOrderBy->nExpr; i++){ pOrderBy->a[i].done = 0; }
  }
  if( fillInColumnList(pParse, pSelect) ){
    return 1;
  }
  if( pSelect->pPrior ){
................................................................................
** If an error occurs, return NULL and leave a message in pParse.
*/
Vdbe *sqliteGetVdbe(Parse *pParse){
  Vdbe *v = pParse->pVdbe;
  if( v==0 ){
    v = pParse->pVdbe = sqliteVdbeCreate(pParse->db);
  }




  return v;
}
    

/*
** This routine is called to process a query that is really the union
** or intersection of two or more separate queries.
................................................................................
  Select *pPrior;     /* Another SELECT immediately to our left */
  Vdbe *v;            /* Generate code to this VDBE */
  int base;           /* Baseline value for pParse->nTab */

  /* Make sure there is no ORDER BY clause on prior SELECTs.  Only the 
  ** last SELECT in the series may have an ORDER BY.
  */
  if( p==0 || p->pPrior==0 ) return 1;
  pPrior = p->pPrior;
  if( pPrior->pOrderBy ){
    sqliteSetString(&pParse->zErrMsg,"ORDER BY clause should come after ",
      selectOpName(p->op), " not before", 0);
    pParse->nErr++;
    return 1;
  }
................................................................................
  Expr *pWhere;          /* The WHERE clause.  May be NULL */
  ExprList *pOrderBy;    /* The ORDER BY clause.  May be NULL */
  ExprList *pGroupBy;    /* The GROUP BY clause.  May be NULL */
  Expr *pHaving;         /* The HAVING clause.  May be NULL */
  int isDistinct;        /* True if the DISTINCT keyword is present */
  int distinct;          /* Table to use for the distinct set */
  int base;              /* First cursor available for use */

  if( sqlite_malloc_failed || pParse->nErr || p==0 ) return 1;

  /* If there is are a sequence of queries, do the earlier ones first.
  */
  if( p->pPrior ){
    return multiSelect(pParse, p, eDest, iParm);
  }

................................................................................
  ** columnlist in pEList if there isn't one already.  (The parser leaves
  ** a NULL in the p->pEList if the SQL said "SELECT * FROM ...")
  */
  if( fillInColumnList(pParse, p) ){
    return 1;
  }
  pEList = p->pEList;
  if( pEList==0 ) return 1;

  /* Allocate a temporary table to use for the DISTINCT set, if
  ** necessary.  This must be done early to allocate the cursor before
  ** any calls to sqliteExprResolveIds().
  */
  if( isDistinct ){
    distinct = pParse->nTab++;
................................................................................
        }
      }
    }
  }

  /* Begin generating code.
  */
  v = sqliteGetVdbe(pParse);
  if( v==0 ) return 1;







  if( pOrderBy ){
    sqliteVdbeAddOp(v, OP_SortOpen, 0, 0, 0, 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.
  */

Changes to src/shell.c.

20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
..
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
..
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
...
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
...
129
130
131
132
133
134
135

136
137
138
139
140
141
142
...
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416

417
418
419
420
421
422
423
424
425
426



427
428
429
430
431
432
433



434
435
436
437
438
439
440
...
486
487
488
489
490
491
492















493
494
495
496
497
498
499
...
555
556
557
558
559
560
561


562
563
564
565
566
567
568
...
572
573
574
575
576
577
578












































579
580
581
582
583
584
585
...
680
681
682
683
684
685
686
687





















































688
689
690
691
692
693

694
695
696
697
698
699
700
...
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
...
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785

786
787
788
789
790
791

792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
**   drh@hwaci.com
**   http://www.hwaci.com/drh/
**
*************************************************************************
** This file contains code to implement the "sqlite" command line
** utility for accessing SQLite databases.
**
** $Id: shell.c,v 1.30 2001/04/04 21:22:14 drh Exp $
*/
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "sqlite.h"
#include <unistd.h>
#include <ctype.h>
................................................................................
** the text in memory obtained from malloc() and returns a pointer
** to the text.  NULL is returned at end of file, or if malloc()
** fails.
**
** The interface is like "readline" but no command-line editing
** is done.
*/
static char *getline(char *zPrompt){
  char *zLine;
  int nLine;
  int n;
  int eol;

  if( zPrompt && *zPrompt ){
    printf("%s",zPrompt);
................................................................................
  eol = 0;
  while( !eol ){
    if( n+100>nLine ){
      nLine = nLine*2 + 100;
      zLine = realloc(zLine, nLine);
      if( zLine==0 ) return 0;
    }
    if( fgets(&zLine[n], nLine - n, stdin)==0 ){
      if( n==0 ){
        free(zLine);
        return 0;
      }
      zLine[n] = 0;
      eol = 1;
      break;
................................................................................
** is coming from a terminal.  In that case, we issue a prompt and
** attempt to use "readline" for command-line editing.  If "isatty"
** is false, use "getline" instead of "readline" and issue to prompt.
**
** zPrior is a string of prior text retrieved.  If not the empty
** string, then issue a continuation prompt.
*/
static char *one_input_line(const char *zPrior, int isatty){
  char *zPrompt;
  char *zResult;
  if( !isatty ){
    return getline(0);
  }
  if( zPrior && zPrior[0] ){
    zPrompt = "   ...> ";
  }else{
    zPrompt = "sqlite> ";
  }
  zResult = readline(zPrompt);
................................................................................
/*
** An pointer to an instance of this structure is passed from
** the main program to the callback.  This is used to communicate
** state and mode information.
*/
struct callback_data {
  sqlite *db;            /* The database */

  int cnt;               /* Number of records displayed so far */
  FILE *out;             /* Write results here */
  int mode;              /* An output mode setting */
  int showHeader;        /* True to show column names in List or Column mode */
  int escape;            /* Escape this character when in MODE_List */
  char zDestTable[250];  /* Name of destination table when MODE_Insert */
  char separator[20];    /* Separator character for MODE_List */
................................................................................
/*
** This is a different callback routine used for dumping the database.
** Each row received by this callback consists of a table name,
** the table type ("index" or "table") and SQL to create the table.
** This routine should print text sufficient to recreate the table.
*/
static int dump_callback(void *pArg, int nArg, char **azArg, char **azCol){
  struct callback_data *pData = (struct callback_data *)pArg;
  if( nArg!=3 ) return 1;
  fprintf(pData->out, "%s;\n", azArg[2]);
  if( strcmp(azArg[1],"table")==0 ){
    struct callback_data d2;
    d2 = *pData;
    d2.mode = MODE_List;
    d2.escape = '\t';
    strcpy(d2.separator,"\t");
    fprintf(pData->out, "COPY '%s' FROM STDIN;\n", azArg[0]);
    sqlite_exec_printf(pData->db, 
       "SELECT * FROM '%q'",
       callback, &d2, 0, azArg[0]
    );
    fprintf(pData->out, "\\.\n");
  }
  fprintf(pData->out, "VACUUM '%s';\n", azArg[0]);
  return 0;
}

/*
** Text of a help message
*/
static char zHelp[] = 
  ".dump ?TABLE? ...      Dump the database in an text format\n"

  ".exit                  Exit this program\n"
  ".explain               Set output mode suitable for EXPLAIN\n"
  ".header ON|OFF         Turn display of headers on or off\n"
  ".help                  Show this message\n"
  ".indices TABLE         Show names of all indices on TABLE\n"
  ".mode MODE             Set mode to one of \"line\", \"column\", \n"
  "                       \"insert\", \"list\", or \"html\"\n"
  ".mode insert TABLE     Generate SQL insert statements for TABLE\n"
  ".output FILENAME       Send output to FILENAME\n"
  ".output stdout         Send output to the screen\n"



  ".schema ?TABLE?        Show the CREATE statements\n"
  ".separator STRING      Change separator string for \"list\" mode\n"
  ".tables ?PATTERN?      List names of tables matching a pattern\n"
  ".timeout MS            Try opening locked tables for MS milliseconds\n"
  ".width NUM NUM ...     Set column widths for \"column\" mode\n"
;




/*
** If an input line begins with "." then invoke this routine to
** process that line.
*/
static void do_meta_command(char *zLine, sqlite *db, struct callback_data *p){
  int i = 1;
  int nArg = 0;
................................................................................
      }
    }
    if( zErrMsg ){
      fprintf(stderr,"Error: %s\n", zErrMsg);
      free(zErrMsg);
    }
  }else
















  if( c=='e' && strncmp(azArg[0], "exit", n)==0 ){
    exit(0);
  }else

  if( c=='e' && strncmp(azArg[0], "explain", n)==0 ){
    p->mode = MODE_Column;
................................................................................
    }else if( strncmp(azArg[1],"insert",n2)==0 ){
      p->mode = MODE_Insert;
      if( nArg>=3 ){
        sprintf(p->zDestTable,"%.*s", (int)(sizeof(p->zDestTable)-1), azArg[2]);
      }else{
        sprintf(p->zDestTable,"table");
      }


    }
  }else

  if( c=='o' && strncmp(azArg[0], "output", n)==0 && nArg==2 ){
    if( p->out!=stdout ){
      fclose(p->out);
    }
................................................................................
      p->out = fopen(azArg[1], "w");
      if( p->out==0 ){
        fprintf(stderr,"can't write to \"%s\"\n", azArg[1]);
        p->out = stdout;
      }
    }
  }else













































  if( c=='s' && strncmp(azArg[0], "schema", n)==0 ){
    struct callback_data data;
    char *zErrMsg = 0;
    memcpy(&data, p, sizeof(data));
    data.showHeader = 0;
    data.mode = MODE_Semi;
................................................................................
  }else

  {
    fprintf(stderr, "unknown command: \"%s\". Enter \".help\" for help\n",
      azArg[0]);
  }
}






















































int main(int argc, char **argv){
  char *zErrMsg = 0;
  char *argv0 = argv[0];
  struct callback_data data;
  int echo = 0;


  memset(&data, 0, sizeof(data));
  data.mode = MODE_List;
  strcpy(data.separator,"|");
  data.showHeader = 0;
#ifdef SIGINT
  signal(SIGINT, interrupt_handler);
#endif
................................................................................
      argc--;
      argv++;
    }else if( strcmp(argv[1],"-noheader")==0 ){
      data.showHeader = 0;
      argc--;
      argv++;
    }else if( strcmp(argv[1],"-echo")==0 ){
      echo = 1;
      argc--;
      argv++;
    }else{
      fprintf(stderr,"%s: unknown option: %s\n", argv0, argv[1]);
      return 1;
    }
  }
  if( argc!=2 && argc!=3 ){
    fprintf(stderr,"Usage: %s ?OPTIONS? FILENAME ?SQL?\n", argv0);
    exit(1);
  }
  data.db = db = sqlite_open(argv[1], 0666, &zErrMsg);
  if( db==0 ){
    data.db = db = sqlite_open(argv[1], 0444, &zErrMsg);
    if( db==0 ){
      if( zErrMsg ){
................................................................................
  data.out = stdout;
  if( argc==3 ){
    if( sqlite_exec(db, argv[2], callback, &data, &zErrMsg)!=0 && zErrMsg!=0 ){
      fprintf(stderr,"SQL error: %s\n", zErrMsg);
      exit(1);
    }
  }else{
    char *zLine;
    char *zSql = 0;
    int nSql = 0;
    int istty = isatty(0);
    if( istty ){
      printf(
        "SQLite version %s\n"
        "Enter \".help\" for instructions\n",
        sqlite_version
      );
    }
    while( (zLine = one_input_line(zSql, istty))!=0 ){
      if( echo ) printf("%s\n", zLine);
      if( zLine && zLine[0]=='.' ){
        do_meta_command(zLine, db, &data);
        free(zLine);
        continue;
      }
      if( zSql==0 ){
        int i;
        for(i=0; zLine[i] && isspace(zLine[i]); i++){}
        if( zLine[i]!=0 ){
          nSql = strlen(zLine);
          zSql = malloc( nSql+1 );
          strcpy(zSql, zLine);
        }

      }else{
        int len = strlen(zLine);
        zSql = realloc( zSql, nSql + len + 2 );
        if( zSql==0 ){
          fprintf(stderr,"%s: out of memory!\n", argv0);
          exit(1);

        }
        strcpy(&zSql[nSql++], "\n");
        strcpy(&zSql[nSql], zLine);
        nSql += len;
      }
      free(zLine);
      if( zSql && sqlite_complete(zSql) ){
        data.cnt = 0;
        if( sqlite_exec(db, zSql, callback, &data, &zErrMsg)!=0 
             && zErrMsg!=0 ){
          if( !istty && !echo ) printf("%s\n",zSql);
          printf("SQL error: %s\n", zErrMsg);
          free(zErrMsg);
          zErrMsg = 0;
        }
        free(zSql);
        zSql = 0;
        nSql = 0;
      }
    }
  }
  sqlite_close(db);
  return 0;
}







|







 







|







 







|







 







|


|
|







 







>







 







|

|


|



|
|



|

|








>










>
>
>







>
>
>







 







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







 







>
>







 







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







 








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


<

<

>







 







|



|




|







 







<
<
<
|
<





<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
>
|
<
<
<
<
<
>
|
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<



20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
..
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
..
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
...
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
...
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
...
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
...
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
...
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
...
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
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
...
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811

812

813
814
815
816
817
818
819
820
821
...
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
...
874
875
876
877
878
879
880



881

882
883
884
885
886
















887
888





889
890



891
















892
893
894
**   drh@hwaci.com
**   http://www.hwaci.com/drh/
**
*************************************************************************
** This file contains code to implement the "sqlite" command line
** utility for accessing SQLite databases.
**
** $Id: shell.c,v 1.31 2001/04/11 14:28:42 drh Exp $
*/
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "sqlite.h"
#include <unistd.h>
#include <ctype.h>
................................................................................
** the text in memory obtained from malloc() and returns a pointer
** to the text.  NULL is returned at end of file, or if malloc()
** fails.
**
** The interface is like "readline" but no command-line editing
** is done.
*/
static char *getline(char *zPrompt, FILE *in){
  char *zLine;
  int nLine;
  int n;
  int eol;

  if( zPrompt && *zPrompt ){
    printf("%s",zPrompt);
................................................................................
  eol = 0;
  while( !eol ){
    if( n+100>nLine ){
      nLine = nLine*2 + 100;
      zLine = realloc(zLine, nLine);
      if( zLine==0 ) return 0;
    }
    if( fgets(&zLine[n], nLine - n, in)==0 ){
      if( n==0 ){
        free(zLine);
        return 0;
      }
      zLine[n] = 0;
      eol = 1;
      break;
................................................................................
** is coming from a terminal.  In that case, we issue a prompt and
** attempt to use "readline" for command-line editing.  If "isatty"
** is false, use "getline" instead of "readline" and issue to prompt.
**
** zPrior is a string of prior text retrieved.  If not the empty
** string, then issue a continuation prompt.
*/
static char *one_input_line(const char *zPrior, FILE *in){
  char *zPrompt;
  char *zResult;
  if( in!=0 ){
    return getline(0, in);
  }
  if( zPrior && zPrior[0] ){
    zPrompt = "   ...> ";
  }else{
    zPrompt = "sqlite> ";
  }
  zResult = readline(zPrompt);
................................................................................
/*
** An pointer to an instance of this structure is passed from
** the main program to the callback.  This is used to communicate
** state and mode information.
*/
struct callback_data {
  sqlite *db;            /* The database */
  int echoOn;            /* True to echo input commands */
  int cnt;               /* Number of records displayed so far */
  FILE *out;             /* Write results here */
  int mode;              /* An output mode setting */
  int showHeader;        /* True to show column names in List or Column mode */
  int escape;            /* Escape this character when in MODE_List */
  char zDestTable[250];  /* Name of destination table when MODE_Insert */
  char separator[20];    /* Separator character for MODE_List */
................................................................................
/*
** This is a different callback routine used for dumping the database.
** Each row received by this callback consists of a table name,
** the table type ("index" or "table") and SQL to create the table.
** This routine should print text sufficient to recreate the table.
*/
static int dump_callback(void *pArg, int nArg, char **azArg, char **azCol){
  struct callback_data *p = (struct callback_data *)pArg;
  if( nArg!=3 ) return 1;
  fprintf(p->out, "%s;\n", azArg[2]);
  if( strcmp(azArg[1],"table")==0 ){
    struct callback_data d2;
    d2 = *p;
    d2.mode = MODE_List;
    d2.escape = '\t';
    strcpy(d2.separator,"\t");
    fprintf(p->out, "COPY '%s' FROM STDIN;\n", azArg[0]);
    sqlite_exec_printf(p->db, 
       "SELECT * FROM '%q'",
       callback, &d2, 0, azArg[0]
    );
    fprintf(p->out, "\\.\n");
  }
  fprintf(p->out, "VACUUM '%s';\n", azArg[0]);
  return 0;
}

/*
** Text of a help message
*/
static char zHelp[] = 
  ".dump ?TABLE? ...      Dump the database in an text format\n"
  ".echo ON|OFF           Turn command echo on or off\n"
  ".exit                  Exit this program\n"
  ".explain               Set output mode suitable for EXPLAIN\n"
  ".header ON|OFF         Turn display of headers on or off\n"
  ".help                  Show this message\n"
  ".indices TABLE         Show names of all indices on TABLE\n"
  ".mode MODE             Set mode to one of \"line\", \"column\", \n"
  "                       \"insert\", \"list\", or \"html\"\n"
  ".mode insert TABLE     Generate SQL insert statements for TABLE\n"
  ".output FILENAME       Send output to FILENAME\n"
  ".output stdout         Send output to the screen\n"
  ".read FILENAME         Execute SQL in FILENAME\n"
  ".reindex ?TABLE?       Rebuild indices\n"
/*  ".rename OLD NEW        Change the name of a table or index\n" */
  ".schema ?TABLE?        Show the CREATE statements\n"
  ".separator STRING      Change separator string for \"list\" mode\n"
  ".tables ?PATTERN?      List names of tables matching a pattern\n"
  ".timeout MS            Try opening locked tables for MS milliseconds\n"
  ".width NUM NUM ...     Set column widths for \"column\" mode\n"
;

/* Forward reference */
static void process_input(struct callback_data *p, FILE *in);

/*
** If an input line begins with "." then invoke this routine to
** process that line.
*/
static void do_meta_command(char *zLine, sqlite *db, struct callback_data *p){
  int i = 1;
  int nArg = 0;
................................................................................
      }
    }
    if( zErrMsg ){
      fprintf(stderr,"Error: %s\n", zErrMsg);
      free(zErrMsg);
    }
  }else

  if( c=='e' && strncmp(azArg[0], "echo", n)==0 && nArg>1 ){
    int j;
    char *z = azArg[1];
    int val = atoi(azArg[1]);
    for(j=0; z[j]; j++){
      if( isupper(z[j]) ) z[j] = tolower(z[j]);
    }
    if( strcmp(z,"on")==0 ){
      val = 1;
    }else if( strcmp(z,"yes")==0 ){
      val = 1;
    } 
    p->echoOn = val;
  }else

  if( c=='e' && strncmp(azArg[0], "exit", n)==0 ){
    exit(0);
  }else

  if( c=='e' && strncmp(azArg[0], "explain", n)==0 ){
    p->mode = MODE_Column;
................................................................................
    }else if( strncmp(azArg[1],"insert",n2)==0 ){
      p->mode = MODE_Insert;
      if( nArg>=3 ){
        sprintf(p->zDestTable,"%.*s", (int)(sizeof(p->zDestTable)-1), azArg[2]);
      }else{
        sprintf(p->zDestTable,"table");
      }
    }else {
      fprintf(stderr,"mode should be on of: column html insert line list\n");
    }
  }else

  if( c=='o' && strncmp(azArg[0], "output", n)==0 && nArg==2 ){
    if( p->out!=stdout ){
      fclose(p->out);
    }
................................................................................
      p->out = fopen(azArg[1], "w");
      if( p->out==0 ){
        fprintf(stderr,"can't write to \"%s\"\n", azArg[1]);
        p->out = stdout;
      }
    }
  }else

  if( c=='r' && strncmp(azArg[0], "read", n)==0 && nArg==2 ){
    FILE *alt = fopen(azArg[1], "r");
    if( alt==0 ){
      fprintf(stderr,"can't open \"%s\"\n", azArg[1]);
    }else{
      process_input(p, alt);
      fclose(alt);
    }
  }else

  if( c=='r' && strncmp(azArg[0], "reindex", n)==0 ){
    char **azResult;
    int nRow, rc;
    char *zErrMsg;
    int i;
    char *zSql;
    if( nArg==1 ){
      rc = sqlite_get_table(db,
        "SELECT name, sql FROM sqlite_master "
        "WHERE type='index'",
        &azResult, &nRow, 0, &zErrMsg
      );
    }else{
      rc = sqlite_get_table_printf(db,
        "SELECT name, sql FROM sqlite_master "
        "WHERE type='index' AND tbl_name LIKE '%q'",
        &azResult, &nRow, 0, &zErrMsg, azArg[1]
      );
    }
    for(i=1; rc==SQLITE_OK && i<=nRow; i++){
      extern char *sqlite_mprintf(const char *, ...);
      zSql = sqlite_mprintf(
         "DROP INDEX '%q';\n%s;\nVACUUM '%q';",
         azResult[i*2], azResult[i*2+1], azResult[i*2]);
      if( p->echoOn ) printf("%s\n", zSql);
      rc = sqlite_exec(db, zSql, 0, 0, &zErrMsg);
    }
    sqlite_free_table(azResult);
    if( zErrMsg ){
      fprintf(stderr,"Error: %s\n", zErrMsg);
      free(zErrMsg);
    }
  }else

  if( c=='s' && strncmp(azArg[0], "schema", n)==0 ){
    struct callback_data data;
    char *zErrMsg = 0;
    memcpy(&data, p, sizeof(data));
    data.showHeader = 0;
    data.mode = MODE_Semi;
................................................................................
  }else

  {
    fprintf(stderr, "unknown command: \"%s\". Enter \".help\" for help\n",
      azArg[0]);
  }
}

static char *Argv0;
static void process_input(struct callback_data *p, FILE *in){
  char *zLine;
  char *zSql = 0;
  int nSql = 0;
  char *zErrMsg;
  while( (zLine = one_input_line(zSql, in))!=0 ){
    if( p->echoOn ) printf("%s\n", zLine);
    if( zLine && zLine[0]=='.' ){
      do_meta_command(zLine, db, p);
      free(zLine);
      continue;
    }
    if( zSql==0 ){
      int i;
      for(i=0; zLine[i] && isspace(zLine[i]); i++){}
      if( zLine[i]!=0 ){
        nSql = strlen(zLine);
        zSql = malloc( nSql+1 );
        strcpy(zSql, zLine);
      }
    }else{
      int len = strlen(zLine);
      zSql = realloc( zSql, nSql + len + 2 );
      if( zSql==0 ){
        fprintf(stderr,"%s: out of memory!\n", Argv0);
        exit(1);
      }
      strcpy(&zSql[nSql++], "\n");
      strcpy(&zSql[nSql], zLine);
      nSql += len;
    }
    free(zLine);
    if( zSql && sqlite_complete(zSql) ){
      p->cnt = 0;
      if( sqlite_exec(db, zSql, callback, p, &zErrMsg)!=0 
           && zErrMsg!=0 ){
        if( in!=0 && !p->echoOn ) printf("%s\n",zSql);
        printf("SQL error: %s\n", zErrMsg);
        free(zErrMsg);
        zErrMsg = 0;
      }
      free(zSql);
      zSql = 0;
      nSql = 0;
    }
  }
  if( zSql ){
    printf("Incomplete SQL: %s\n", zSql);
    free(zSql);
  }
}

int main(int argc, char **argv){
  char *zErrMsg = 0;

  struct callback_data data;


  Argv0 = argv[0];
  memset(&data, 0, sizeof(data));
  data.mode = MODE_List;
  strcpy(data.separator,"|");
  data.showHeader = 0;
#ifdef SIGINT
  signal(SIGINT, interrupt_handler);
#endif
................................................................................
      argc--;
      argv++;
    }else if( strcmp(argv[1],"-noheader")==0 ){
      data.showHeader = 0;
      argc--;
      argv++;
    }else if( strcmp(argv[1],"-echo")==0 ){
      data.echoOn = 1;
      argc--;
      argv++;
    }else{
      fprintf(stderr,"%s: unknown option: %s\n", Argv0, argv[1]);
      return 1;
    }
  }
  if( argc!=2 && argc!=3 ){
    fprintf(stderr,"Usage: %s ?OPTIONS? FILENAME ?SQL?\n", Argv0);
    exit(1);
  }
  data.db = db = sqlite_open(argv[1], 0666, &zErrMsg);
  if( db==0 ){
    data.db = db = sqlite_open(argv[1], 0444, &zErrMsg);
    if( db==0 ){
      if( zErrMsg ){
................................................................................
  data.out = stdout;
  if( argc==3 ){
    if( sqlite_exec(db, argv[2], callback, &data, &zErrMsg)!=0 && zErrMsg!=0 ){
      fprintf(stderr,"SQL error: %s\n", zErrMsg);
      exit(1);
    }
  }else{



    if( isatty(0) ){

      printf(
        "SQLite version %s\n"
        "Enter \".help\" for instructions\n",
        sqlite_version
      );
















      process_input(&data, 0);
    }else{





      process_input(&data, stdin);
    }



  }
















  sqlite_close(db);
  return 0;
}

Changes to src/sqliteInt.h.

19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
..
61
62
63
64
65
66
67






68
69
70
71
72
73
74
...
253
254
255
256
257
258
259
260
261


262
263
264
265
266
267
268
** Author contact information:
**   drh@hwaci.com
**   http://www.hwaci.com/drh/
**
*************************************************************************
** Internal interface definitions for SQLite.
**
** @(#) $Id: sqliteInt.h,v 1.40 2001/04/07 15:24:33 drh Exp $
*/
#include "sqlite.h"
#include "dbbe.h"
#include "vdbe.h"
#include "parse.h"
#include <gdbm.h>
#include <stdio.h>
................................................................................
# define sqliteStrDup(X)    sqliteStrDup_(X,__FILE__,__LINE__)
# define sqliteStrNDup(X,Y) sqliteStrNDup_(X,Y,__FILE__,__LINE__)
  void sqliteStrRealloc(char**);
#else
# define sqliteStrRealloc(X)
#endif







/*
** The following global variables are used for testing and debugging
** only.  They only work if MEMORY_DEBUG is defined.
*/
#ifdef MEMORY_DEBUG
extern int sqlite_nMalloc;       /* Number of sqliteMalloc() calls */
extern int sqlite_nFree;         /* Number of sqliteFree() calls */
................................................................................
** A list of identifiers.
*/
struct IdList {
  int nId;         /* Number of identifiers on the list */
  struct {
    char *zName;      /* Text of the identifier. */
    char *zAlias;     /* The "B" part of a "A AS B" phrase.  zName is the "A" */
    Table *pTab;      /* An SQL table corresponding to zName */
    int idx;          /* Index in some Table.aCol[] of a column named zName */


  } *a;            /* One entry for each identifier on the list */
};

/*
** The WHERE clause processing routine has two halves.  The
** first part does the start of the WHERE loop and the second
** half does the tail of the WHERE loop.  An instance of







|







 







>
>
>
>
>
>







 







<

>
>







19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
..
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
...
259
260
261
262
263
264
265

266
267
268
269
270
271
272
273
274
275
** Author contact information:
**   drh@hwaci.com
**   http://www.hwaci.com/drh/
**
*************************************************************************
** Internal interface definitions for SQLite.
**
** @(#) $Id: sqliteInt.h,v 1.41 2001/04/11 14:28:43 drh Exp $
*/
#include "sqlite.h"
#include "dbbe.h"
#include "vdbe.h"
#include "parse.h"
#include <gdbm.h>
#include <stdio.h>
................................................................................
# define sqliteStrDup(X)    sqliteStrDup_(X,__FILE__,__LINE__)
# define sqliteStrNDup(X,Y) sqliteStrNDup_(X,Y,__FILE__,__LINE__)
  void sqliteStrRealloc(char**);
#else
# define sqliteStrRealloc(X)
#endif

/*
** This variable gets set if malloc() ever fails.  After it gets set,
** the SQLite library shuts down permanently.
*/
extern int sqlite_malloc_failed;

/*
** The following global variables are used for testing and debugging
** only.  They only work if MEMORY_DEBUG is defined.
*/
#ifdef MEMORY_DEBUG
extern int sqlite_nMalloc;       /* Number of sqliteMalloc() calls */
extern int sqlite_nFree;         /* Number of sqliteFree() calls */
................................................................................
** A list of identifiers.
*/
struct IdList {
  int nId;         /* Number of identifiers on the list */
  struct {
    char *zName;      /* Text of the identifier. */
    char *zAlias;     /* The "B" part of a "A AS B" phrase.  zName is the "A" */

    int idx;          /* Index in some Table.aCol[] of a column named zName */
    Table *pTab;      /* An SQL table corresponding to zName */
    Select *pSelect;  /* A SELECT statement used in place of a table name */
  } *a;            /* One entry for each identifier on the list */
};

/*
** The WHERE clause processing routine has two halves.  The
** first part does the start of the WHERE loop and the second
** half does the tail of the WHERE loop.  An instance of

Changes to src/table.c.

136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
  *pazResult = 0;
  if( pnColumn ) *pnColumn = 0;
  if( pnRow ) *pnRow = 0;
  res.nResult = 0;
  res.nRow = 0;
  res.nColumn = 0;
  res.nData = 1;
  res.nAlloc = 200;
  res.rc = SQLITE_OK;
  res.azResult = malloc( sizeof(char*)*res.nAlloc );
  if( res.azResult==0 ){
    return SQLITE_NOMEM;
  }
  res.azResult[0] = 0;
  rc = sqlite_exec(db, zSql, sqlite_get_table_cb, &res, pzErrMsg);







|







136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
  *pazResult = 0;
  if( pnColumn ) *pnColumn = 0;
  if( pnRow ) *pnRow = 0;
  res.nResult = 0;
  res.nRow = 0;
  res.nColumn = 0;
  res.nData = 1;
  res.nAlloc = 20;
  res.rc = SQLITE_OK;
  res.azResult = malloc( sizeof(char*)*res.nAlloc );
  if( res.azResult==0 ){
    return SQLITE_NOMEM;
  }
  res.azResult[0] = 0;
  rc = sqlite_exec(db, zSql, sqlite_get_table_cb, &res, pzErrMsg);

Changes to src/test1.c.

21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
...
263
264
265
266
267
268
269












































270
271
272
273
274
275
276
277
278
279
280
281




282
283
**   http://www.hwaci.com/drh/
**
*************************************************************************
** Code for testing the printf() interface to SQLite.  This code
** is not included in the SQLite library.  It is used for automated
** testing of the SQLite library.
**
** $Id: test1.c,v 1.1 2001/04/07 15:24:33 drh Exp $
*/
#include "sqliteInt.h"
#include "tcl.h"
#include <stdlib.h>
#include <string.h>

/*
................................................................................
  if( Tcl_GetDouble(interp, argv[4], &r) ) return TCL_ERROR;
  z = sqlite_mprintf(argv[1], a[0], a[1], r);
  Tcl_AppendResult(interp, z, 0);
  sqliteFree(z);
  return TCL_OK;
}













































/*
** Register commands with the TCL interpreter.
*/
int Sqlitetest1_Init(Tcl_Interp *interp){
  Tcl_CreateCommand(interp, "sqlite_mprintf_int", sqlite_mprintf_int, 0, 0);
  Tcl_CreateCommand(interp, "sqlite_mprintf_str", sqlite_mprintf_str, 0, 0);
  Tcl_CreateCommand(interp, "sqlite_mprintf_double", sqlite_mprintf_double,0,0);
  Tcl_CreateCommand(interp, "sqlite_open", sqlite_test_open, 0, 0);
  Tcl_CreateCommand(interp, "sqlite_exec_printf", test_exec_printf, 0, 0);
  Tcl_CreateCommand(interp, "sqlite_get_table_printf", test_get_table_printf,
      0, 0);
  Tcl_CreateCommand(interp, "sqlite_close", sqlite_test_close, 0, 0);




  return TCL_OK;
}







|







 







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












>
>
>
>


21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
...
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
322
323
324
325
326
327
328
329
330
331
**   http://www.hwaci.com/drh/
**
*************************************************************************
** Code for testing the printf() interface to SQLite.  This code
** is not included in the SQLite library.  It is used for automated
** testing of the SQLite library.
**
** $Id: test1.c,v 1.2 2001/04/11 14:28:43 drh Exp $
*/
#include "sqliteInt.h"
#include "tcl.h"
#include <stdlib.h>
#include <string.h>

/*
................................................................................
  if( Tcl_GetDouble(interp, argv[4], &r) ) return TCL_ERROR;
  z = sqlite_mprintf(argv[1], a[0], a[1], r);
  Tcl_AppendResult(interp, z, 0);
  sqliteFree(z);
  return TCL_OK;
}

/*
** Usage: sqlite_malloc_fail N
**
** Rig sqliteMalloc() to fail on the N-th call.  Turn of this mechanism
** and reset the sqlite_malloc_failed variable is N==0.
*/
#ifdef MEMORY_DEBUG
static int sqlite_malloc_fail(
  void *NotUsed,
  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  int argc,              /* Number of arguments */
  char **argv            /* Text of each argument */
){
  int n;
  if( argc!=2 ){
    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " N\"", 0);
    return TCL_ERROR;
  }
  if( Tcl_GetInt(interp, argv[1], &n) ) return TCL_ERROR;
  sqlite_iMallocFail = n;
  sqlite_malloc_failed = 0;
  return TCL_OK;
}
#endif

/*
** Usage: sqlite_malloc_stat
**
** Return the number of prior calls to sqliteMalloc() and sqliteFree().
*/
#ifdef MEMORY_DEBUG
static int sqlite_malloc_stat(
  void *NotUsed,
  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  int argc,              /* Number of arguments */
  char **argv            /* Text of each argument */
){
  char zBuf[200];
  sprintf(zBuf, "%d %d %d", sqlite_nMalloc, sqlite_nFree, sqlite_iMallocFail);
  Tcl_AppendResult(interp, zBuf, 0);
  return TCL_OK;
}
#endif

/*
** Register commands with the TCL interpreter.
*/
int Sqlitetest1_Init(Tcl_Interp *interp){
  Tcl_CreateCommand(interp, "sqlite_mprintf_int", sqlite_mprintf_int, 0, 0);
  Tcl_CreateCommand(interp, "sqlite_mprintf_str", sqlite_mprintf_str, 0, 0);
  Tcl_CreateCommand(interp, "sqlite_mprintf_double", sqlite_mprintf_double,0,0);
  Tcl_CreateCommand(interp, "sqlite_open", sqlite_test_open, 0, 0);
  Tcl_CreateCommand(interp, "sqlite_exec_printf", test_exec_printf, 0, 0);
  Tcl_CreateCommand(interp, "sqlite_get_table_printf", test_get_table_printf,
      0, 0);
  Tcl_CreateCommand(interp, "sqlite_close", sqlite_test_close, 0, 0);
#ifdef MEMORY_DEBUG
  Tcl_CreateCommand(interp, "sqlite_malloc_fail", sqlite_malloc_fail, 0, 0);
  Tcl_CreateCommand(interp, "sqlite_malloc_stat", sqlite_malloc_stat, 0, 0);
#endif
  return TCL_OK;
}

Changes to src/tokenize.c.

23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
...
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
...
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
...
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
...
433
434
435
436
437
438
439
440
441
442
443
444
445
*************************************************************************
** 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.18 2001/04/04 11:48:58 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
#include <stdlib.h>

/*
** All the keywords of the SQL language are stored as in a hash
................................................................................
  { "VALUES",            0, TK_VALUES,           0 },
  { "WHERE",             0, TK_WHERE,            0 },
};

/*
** This is the hash table
*/
#define KEY_HASH_SIZE 69
static Keyword *apHashTable[KEY_HASH_SIZE];


/*
** 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.
................................................................................
  if( pEngine==0 ){
    sqliteSetString(pzErrMsg, "out of memory", 0);
    return 1;
  }
#ifndef NDEBUG
  sqliteParserTrace(trace, "parser: ");
#endif
  while( nErr==0 && i>=0 && zSql[i]!=0 ){
    int tokenType;
    
    if( (pParse->db->flags & SQLITE_Interrupt)!=0 ){
      pParse->rc = SQLITE_INTERRUPT;
      sqliteSetString(pzErrMsg, "interrupt", 0);
      break;
    }
................................................................................
        }else if( sqliteStrNICmp(z,"--parser-trace-off--", 20)==0 ){
          trace = 0;
          sqliteParserTrace(trace, "parser: ");
        }else if( sqliteStrNICmp(z,"--vdbe-trace-on--",17)==0 ){
          pParse->db->flags |= SQLITE_VdbeTrace;
        }else if( sqliteStrNICmp(z,"--vdbe-trace-off--", 18)==0 ){
          pParse->db->flags &= ~SQLITE_VdbeTrace;
#ifdef MEMORY_DEBUG
        }else if( sqliteStrNICmp(z,"--malloc-fail=",14)==0 ){
          sqlite_iMallocFail = atoi(&z[14]);
        }else if( sqliteStrNICmp(z,"--malloc-stats--", 16)==0 ){
          if( pParse->xCallback ){
            static char *azName[4] = {"malloc", "free", "to_fail", 0 };
            char *azArg[4];
            char zVal[3][30];
            sprintf(zVal[0],"%d", sqlite_nMalloc);
            sprintf(zVal[1],"%d", sqlite_nFree);
            sprintf(zVal[2],"%d", sqlite_iMallocFail);
            azArg[0] = zVal[0];
            azArg[1] = zVal[1];
            azArg[2] = zVal[2];
            azArg[3] = 0;
            pParse->xCallback(pParse->pArg, 3, azArg, azName);
          }
#endif
        }
#endif
        break;
      }
      case TK_ILLEGAL:
        sqliteSetNString(pzErrMsg, "unrecognized token: \"", -1, 
           pParse->sLastToken.z, pParse->sLastToken.n, "\"", 1, 0);
................................................................................
    pParse->pVdbe = 0;
  }
  if( pParse->pNewTable ){
    sqliteDeleteTable(pParse->db, pParse->pNewTable);
    pParse->pNewTable = 0;
  }
  sqliteParseInfoReset(pParse);
  sqliteStrRealloc(pzErrMsg);
  if( nErr>0 && pParse->rc==SQLITE_OK ){
    pParse->rc = SQLITE_ERROR;
  }
  return nErr;
}







|







 







|







 







|







 







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







 







<





23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
...
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
...
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
...
359
360
361
362
363
364
365


















366
367
368
369
370
371
372
...
415
416
417
418
419
420
421

422
423
424
425
426
*************************************************************************
** 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.19 2001/04/11 14:28:43 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
#include <stdlib.h>

/*
** All the keywords of the SQL language are stored as in a hash
................................................................................
  { "VALUES",            0, TK_VALUES,           0 },
  { "WHERE",             0, TK_WHERE,            0 },
};

/*
** This is the hash table
*/
#define KEY_HASH_SIZE 71
static Keyword *apHashTable[KEY_HASH_SIZE];


/*
** 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.
................................................................................
  if( pEngine==0 ){
    sqliteSetString(pzErrMsg, "out of memory", 0);
    return 1;
  }
#ifndef NDEBUG
  sqliteParserTrace(trace, "parser: ");
#endif
  while( sqlite_malloc_failed==0 && nErr==0 && i>=0 && zSql[i]!=0 ){
    int tokenType;
    
    if( (pParse->db->flags & SQLITE_Interrupt)!=0 ){
      pParse->rc = SQLITE_INTERRUPT;
      sqliteSetString(pzErrMsg, "interrupt", 0);
      break;
    }
................................................................................
        }else if( sqliteStrNICmp(z,"--parser-trace-off--", 20)==0 ){
          trace = 0;
          sqliteParserTrace(trace, "parser: ");
        }else if( sqliteStrNICmp(z,"--vdbe-trace-on--",17)==0 ){
          pParse->db->flags |= SQLITE_VdbeTrace;
        }else if( sqliteStrNICmp(z,"--vdbe-trace-off--", 18)==0 ){
          pParse->db->flags &= ~SQLITE_VdbeTrace;


















        }
#endif
        break;
      }
      case TK_ILLEGAL:
        sqliteSetNString(pzErrMsg, "unrecognized token: \"", -1, 
           pParse->sLastToken.z, pParse->sLastToken.n, "\"", 1, 0);
................................................................................
    pParse->pVdbe = 0;
  }
  if( pParse->pNewTable ){
    sqliteDeleteTable(pParse->db, pParse->pNewTable);
    pParse->pNewTable = 0;
  }
  sqliteParseInfoReset(pParse);

  if( nErr>0 && pParse->rc==SQLITE_OK ){
    pParse->rc = SQLITE_ERROR;
  }
  return nErr;
}

Changes to src/update.c.

20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
..
46
47
48
49
50
51
52


53
54
55
56
57
58
59

60
61
62
63
64
65
66
**   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.10 2001/03/14 12:35:57 drh Exp $
*/
#include "sqliteInt.h"

/*
** Process an UPDATE statement.
*/
void sqliteUpdate(
................................................................................
  Index *pIdx;           /* For looping over indices */
  int nIdx;              /* Number of indices that need updating */
  int base;              /* Index of first available table cursor */
  Index **apIdx = 0;     /* An array of indices that need updating too */
  int *aXRef = 0;        /* aXRef[i] is the index in pChanges->a[] of the
                         ** an expression for the i-th column of the table.
                         ** aXRef[i]==-1 if the i-th column is not changed. */



  /* Locate the table which we want to update.  This table has to be
  ** put in an IdList structure because some of the subroutines we
  ** will be calling are designed to work with multiple tables and expect
  ** an IdList* parameter instead of just a Table* parameger.
  */
  pTabList = sqliteIdListAppend(0, pTableName);

  for(i=0; i<pTabList->nId; i++){
    pTabList->a[i].pTab = sqliteFindTable(pParse->db, pTabList->a[i].zName);
    if( pTabList->a[i].pTab==0 ){
      sqliteSetString(&pParse->zErrMsg, "no such table: ", 
         pTabList->a[i].zName, 0);
      pParse->nErr++;
      goto update_cleanup;







|







 







>
>







>







20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
..
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
**   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.11 2001/04/11 14:28:43 drh Exp $
*/
#include "sqliteInt.h"

/*
** Process an UPDATE statement.
*/
void sqliteUpdate(
................................................................................
  Index *pIdx;           /* For looping over indices */
  int nIdx;              /* Number of indices that need updating */
  int base;              /* Index of first available table cursor */
  Index **apIdx = 0;     /* An array of indices that need updating too */
  int *aXRef = 0;        /* aXRef[i] is the index in pChanges->a[] of the
                         ** an expression for the i-th column of the table.
                         ** aXRef[i]==-1 if the i-th column is not changed. */

  if( pParse->nErr || sqlite_malloc_failed ) goto update_cleanup;

  /* Locate the table which we want to update.  This table has to be
  ** put in an IdList structure because some of the subroutines we
  ** will be calling are designed to work with multiple tables and expect
  ** an IdList* parameter instead of just a Table* parameger.
  */
  pTabList = sqliteIdListAppend(0, pTableName);
  if( pTabList==0 ) goto update_cleanup;
  for(i=0; i<pTabList->nId; i++){
    pTabList->a[i].pTab = sqliteFindTable(pParse->db, pTabList->a[i].zName);
    if( pTabList->a[i].pTab==0 ){
      sqliteSetString(&pParse->zErrMsg, "no such table: ", 
         pTabList->a[i].zName, 0);
      pParse->nErr++;
      goto update_cleanup;

Changes to src/util.c.

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






35
36
37
38
39
40
41
..
54
55
56
57
58
59
60
61



62
63
64
65
66



67
68
69
70
71
72
73
...
127
128
129
130
131
132
133




134
135
136
137
138
139
140
...
147
148
149
150
151
152
153




154
155
156
157
158





159
160
161
162
163
164
165
166
...
187
188
189
190
191
192
193
194



195
196
197
198
199
200
201
...
214
215
216
217
218
219
220
221




222
223
224
225
226
227
228
...
321
322
323
324
325
326
327

328
329
330
331
332
333
334
**
*************************************************************************
** Utility functions used throughout sqlite.
**
** This file contains functions for allocating memory, comparing
** strings, and stuff like that.
**
** $Id: util.c,v 1.20 2001/04/05 15:57:13 drh Exp $
*/
#include "sqliteInt.h"
#include <stdarg.h>
#include <ctype.h>







/*
** If MEMORY_DEBUG is defined, then use versions of malloc() and
** free() that track memory usage and check for buffer overruns.
*/
#ifdef MEMORY_DEBUG

/*
................................................................................
void *sqliteMalloc_(int n, char *zFile, int line){
  void *p;
  int *pi;
  int k;
  sqlite_nMalloc++;
  if( sqlite_iMallocFail>=0 ){
    sqlite_iMallocFail--;
    if( sqlite_iMallocFail==0 ) return 0;



  }
  if( n==0 ) return 0;
  k = (n+sizeof(int)-1)/sizeof(int);
  pi = malloc( (3+k)*sizeof(int));
  if( pi==0 ) return 0;



  pi[0] = 0xdead1122;
  pi[1] = n;
  pi[k+2] = 0xdead3344;
  p = &pi[2];
  memset(p, 0, n);
#if MEMORY_DEBUG>1
  fprintf(stderr,"malloc %d bytes at 0x%x from %s:%d\n", n, (int)p, zFile,line);
................................................................................
  oldK = (oldN+sizeof(int)-1)/sizeof(int);
  if( oldPi[oldK+2]!=0xdead3344 ){
    fprintf(stderr,"High-end memory corruption in realloc at 0x%x\n", (int)p);
    return 0;
  }
  k = (n + sizeof(int) - 1)/sizeof(int);
  pi = malloc( (k+3)*sizeof(int) );




  pi[0] = 0xdead1122;
  pi[1] = n;
  pi[k+2] = 0xdead3344;
  p = &pi[2];
  memcpy(p, oldP, n>oldN ? oldN : n);
  if( n>oldN ){
    memset(&((char*)p)[oldN], 0, n-oldN);
................................................................................
#endif
  return p;
}

/*
** Make a duplicate of a string into memory obtained from malloc()
** Free the original string using sqliteFree().




*/
void sqliteStrRealloc(char **pz){
  char *zNew;
  if( pz==0 || *pz==0 ) return;
  zNew = malloc( strlen(*pz) + 1 );





  if( zNew ) strcpy(zNew, *pz);
  sqliteFree(*pz);
  *pz = zNew;
}

/*
** Make a copy of a string in memory obtained from sqliteMalloc()
*/
................................................................................

/*
** Allocate new memory and set it to zero.  Return NULL if
** no memory is available.
*/
void *sqliteMalloc(int n){
  void *p = malloc(n);
  if( p==0 ) return 0;



  memset(p, 0, n);
  return p;
}

/*
** Free memory previously obtained from sqliteMalloc()
*/
................................................................................
  if( p==0 ){
    return sqliteMalloc(n);
  }
  if( n==0 ){
    sqliteFree(p);
    return 0;
  }
  return realloc(p, n);




}

/*
** Make a copy of a string in memory obtained from sqliteMalloc()
*/
char *sqliteStrDup(const char *z){
  char *zNew = sqliteMalloc(strlen(z)+1);
................................................................................
** the quote characters.  The conversion is done in-place.  If the
** input does not begin with a quote character, then this routine
** is a no-op.
*/
void sqliteDequote(char *z){
  int quote;
  int i, j;

  quote = z[0];
  if( quote!='\'' && quote!='"' ) return;
  for(i=1, j=0; z[i]; i++){
    if( z[i]==quote ){
      if( z[i+1]==quote ){
        z[j++] = quote;
        i++;







|





>
>
>
>
>
>







 







|
>
>
>




|
>
>
>







 







>
>
>
>







 







>
>
>
>





>
>
>
>
>
|







 







|
>
>
>







 







|
>
>
>
>







 







>







22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
..
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
...
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
...
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
...
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
...
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
...
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
**
*************************************************************************
** Utility functions used throughout sqlite.
**
** This file contains functions for allocating memory, comparing
** strings, and stuff like that.
**
** $Id: util.c,v 1.21 2001/04/11 14:28:43 drh Exp $
*/
#include "sqliteInt.h"
#include <stdarg.h>
#include <ctype.h>

/*
** If malloc() ever fails, this global variable gets set to 1.
** This causes the library to abort and never again function.
*/
int sqlite_malloc_failed = 0;

/*
** If MEMORY_DEBUG is defined, then use versions of malloc() and
** free() that track memory usage and check for buffer overruns.
*/
#ifdef MEMORY_DEBUG

/*
................................................................................
void *sqliteMalloc_(int n, char *zFile, int line){
  void *p;
  int *pi;
  int k;
  sqlite_nMalloc++;
  if( sqlite_iMallocFail>=0 ){
    sqlite_iMallocFail--;
    if( sqlite_iMallocFail==0 ){
      sqlite_malloc_failed++;
      return 0;
    }
  }
  if( n==0 ) return 0;
  k = (n+sizeof(int)-1)/sizeof(int);
  pi = malloc( (3+k)*sizeof(int));
  if( pi==0 ){
    sqlite_malloc_failed++;
    return 0;
  }
  pi[0] = 0xdead1122;
  pi[1] = n;
  pi[k+2] = 0xdead3344;
  p = &pi[2];
  memset(p, 0, n);
#if MEMORY_DEBUG>1
  fprintf(stderr,"malloc %d bytes at 0x%x from %s:%d\n", n, (int)p, zFile,line);
................................................................................
  oldK = (oldN+sizeof(int)-1)/sizeof(int);
  if( oldPi[oldK+2]!=0xdead3344 ){
    fprintf(stderr,"High-end memory corruption in realloc at 0x%x\n", (int)p);
    return 0;
  }
  k = (n + sizeof(int) - 1)/sizeof(int);
  pi = malloc( (k+3)*sizeof(int) );
  if( pi==0 ){
    sqlite_malloc_failed++;
    return 0;
  }
  pi[0] = 0xdead1122;
  pi[1] = n;
  pi[k+2] = 0xdead3344;
  p = &pi[2];
  memcpy(p, oldP, n>oldN ? oldN : n);
  if( n>oldN ){
    memset(&((char*)p)[oldN], 0, n-oldN);
................................................................................
#endif
  return p;
}

/*
** Make a duplicate of a string into memory obtained from malloc()
** Free the original string using sqliteFree().
**
** This routine is called on all strings that are passed outside of
** the SQLite library.  That way clients can free the string using free()
** rather than having to call sqliteFree().
*/
void sqliteStrRealloc(char **pz){
  char *zNew;
  if( pz==0 || *pz==0 ) return;
  zNew = malloc( strlen(*pz) + 1 );
  if( zNew==0 ){
    sqlite_malloc_failed++;
    sqliteFree(*pz);
    *pz = 0;
  }
  strcpy(zNew, *pz);
  sqliteFree(*pz);
  *pz = zNew;
}

/*
** Make a copy of a string in memory obtained from sqliteMalloc()
*/
................................................................................

/*
** Allocate new memory and set it to zero.  Return NULL if
** no memory is available.
*/
void *sqliteMalloc(int n){
  void *p = malloc(n);
  if( p==0 ){
    sqlite_malloc_failed++;
    return 0;
  }
  memset(p, 0, n);
  return p;
}

/*
** Free memory previously obtained from sqliteMalloc()
*/
................................................................................
  if( p==0 ){
    return sqliteMalloc(n);
  }
  if( n==0 ){
    sqliteFree(p);
    return 0;
  }
  p = realloc(p, n);
  if( p==0 ){
    sqlite_malloc_failed++;
  }
  return p;
}

/*
** Make a copy of a string in memory obtained from sqliteMalloc()
*/
char *sqliteStrDup(const char *z){
  char *zNew = sqliteMalloc(strlen(z)+1);
................................................................................
** the quote characters.  The conversion is done in-place.  If the
** input does not begin with a quote character, then this routine
** is a no-op.
*/
void sqliteDequote(char *z){
  int quote;
  int i, j;
  if( z==0 ) return;
  quote = z[0];
  if( quote!='\'' && quote!='"' ) return;
  for(i=1, j=0; z[i]; i++){
    if( z[i]==quote ){
      if( z[i+1]==quote ){
        z[j++] = quote;
        i++;

Changes to src/vdbe.c.

37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
...
219
220
221
222
223
224
225
226
227

228
229
230
231
232
233
234
...
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383

384
385
386
387
388
389
390
...
458
459
460
461
462
463
464




465
466
467
468
469
470
471
...
530
531
532
533
534
535
536
537



538
539
540
541
542
543
544
....
1000
1001
1002
1003
1004
1005
1006

1007
1008
1009
1010
1011
1012
1013
....
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
....
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
....
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
....
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
....
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
....
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
....
3082
3083
3084
3085
3086
3087
3088

3089
3090
3091
3092
3093
3094
3095
....
3237
3238
3239
3240
3241
3242
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
....
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
....
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
....
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
** 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.56 2001/04/05 15:57:13 drh Exp $
*/
#include "sqliteInt.h"
#include <unistd.h>
#include <ctype.h>

/*
** SQL is translated into a sequence of instructions to be
................................................................................
};

/*
** Create a new virtual database engine.
*/
Vdbe *sqliteVdbeCreate(sqlite *db){
  Vdbe *p;

  p = sqliteMalloc( sizeof(Vdbe) );

  p->pBe = db->pBe;
  p->db = db;
  return p;
}

/*
** Turn tracing on or off
................................................................................
** or a double quote character (ASCII 0x22).  Two quotes in a row
** resolve to be a single actual quote character within the string.
*/
void sqliteVdbeDequoteP3(Vdbe *p, int addr){
  char *z;
  if( addr<0 || addr>=p->nOp ) return;
  z = p->aOp[addr].p3;
  sqliteDequote(z);
}

/*
** On the P3 argument of the given instruction, change all
** strings of whitespace characters into a single space and
** delete leading and trailing whitespace.
*/
void sqliteVdbeCompressSpace(Vdbe *p, int addr){
  char *z;
  int i, j;
  if( addr<0 || addr>=p->nOp ) return;
  z = p->aOp[addr].p3;

  i = j = 0;
  while( isspace(z[i]) ){ i++; }
  while( z[i] ){
    if( isspace(z[i]) ){
      z[j++] = ' ';
      while( isspace(z[++i]) ){}
    }else{
................................................................................
*/
static void AggRehash(Agg *p, int nHash){
  int size;
  AggElem *pElem;
  if( p->nHash==nHash ) return;
  size = nHash * sizeof(AggElem*);
  p->apHash = sqliteRealloc(p->apHash, size );




  memset(p->apHash, 0, size);
  p->nHash = nHash;
  for(pElem=p->pFirst; pElem; pElem=pElem->pNext){
    AggEnhash(p, pElem);
  }
}

................................................................................
static void SetInsert(Set *p, char *zKey){
  SetElem *pElem;
  int h = sqliteHashNoCase(zKey, 0) % ArraySize(p->apHash);
  for(pElem=p->apHash[h]; pElem; pElem=pElem->pHash){
    if( strcmp(pElem->zKey, zKey)==0 ) return;
  }
  pElem = sqliteMalloc( sizeof(*pElem) + strlen(zKey) );
  if( pElem==0 ) return;



  strcpy(pElem->zKey, zKey);
  pElem->pNext = p->pAll;
  p->pAll = pElem;
  pElem->pHash = p->apHash[h];
  p->apHash[h] = pElem;
}

................................................................................
  rc = SQLITE_OK;
#ifdef MEMORY_DEBUG
  if( access("vdbe_trace",0)==0 ){
    p->trace = stderr;
  }
#endif
  /* if( pzErrMsg ){ *pzErrMsg = 0; } */

  for(pc=0; rc==SQLITE_OK && pc<p->nOp VERIFY(&& pc>=0); pc++){
    pOp = &p->aOp[pc];

    /* Interrupt processing if requested.
    */
    if( db->flags & SQLITE_Interrupt ){
      db->flags &= ~SQLITE_Interrupt;
................................................................................
        }else if( (ft & fn & STK_Int)==STK_Int ){
          copy = aStack[nos].i<aStack[tos].i;
        }else if( ( (ft|fn) & (STK_Int|STK_Real) ) !=0 ){
          Realify(p, tos);
          Realify(p, nos);
          copy = aStack[tos].r>aStack[nos].r;
        }else{
          Stringify(p, tos);
          Stringify(p, nos);
          copy = sqliteCompare(zStack[tos],zStack[nos])>0;
        }
        if( copy ){
          Release(p, nos);
          aStack[nos] = aStack[tos];
          zStack[nos] = zStack[tos];
          zStack[tos] = 0;
................................................................................
        }else if( (ft & fn & STK_Int)==STK_Int ){
          copy = aStack[nos].i>aStack[tos].i;
        }else if( ( (ft|fn) & (STK_Int|STK_Real) ) !=0 ){
          Realify(p, tos);
          Realify(p, nos);
          copy = aStack[tos].r<aStack[nos].r;
        }else{
          Stringify(p, tos);
          Stringify(p, nos);
          copy = sqliteCompare(zStack[tos],zStack[nos])<0;
        }
        if( copy ){
          Release(p, nos);
          aStack[nos] = aStack[tos];
          zStack[nos] = zStack[tos];
          zStack[tos] = 0;
................................................................................
        int ft, fn;
        VERIFY( if( nos<0 ) goto not_enough_stack; )
        ft = aStack[tos].flags;
        fn = aStack[nos].flags;
        if( (ft & fn)==STK_Int ){
          c = aStack[nos].i - aStack[tos].i;
        }else{
          Stringify(p, tos);
          Stringify(p, nos);
          c = sqliteCompare(zStack[nos], zStack[tos]);
        }
        switch( pOp->opcode ){
          case OP_Eq:    c = c==0;     break;
          case OP_Ne:    c = c!=0;     break;
          case OP_Lt:    c = c<0;      break;
          case OP_Le:    c = c<=0;     break;
................................................................................
      ** are different.
      */
      case OP_Like: {
        int tos = p->tos;
        int nos = tos - 1;
        int c;
        VERIFY( if( nos<0 ) goto not_enough_stack; )
        Stringify(p, tos);
        Stringify(p, nos);
        c = sqliteLikeCompare(zStack[tos], zStack[nos]);
        POPSTACK;
        POPSTACK;
        if( pOp->p1 ) c = !c;
        if( c ) pc = pOp->p2-1;
        break;
      }
................................................................................
      ** are different.
      */
      case OP_Glob: {
        int tos = p->tos;
        int nos = tos - 1;
        int c;
        VERIFY( if( nos<0 ) goto not_enough_stack; )
        Stringify(p, tos);
        Stringify(p, nos);
        c = sqliteGlobCompare(zStack[tos], zStack[nos]);
        POPSTACK;
        POPSTACK;
        if( pOp->p1 ) c = !c;
        if( c ) pc = pOp->p2-1;
        break;
      }
................................................................................
      case OP_AggFocus: {
        int tos = p->tos;
        AggElem *pElem;
        char *zKey;
        int nKey;

        VERIFY( if( tos<0 ) goto not_enough_stack; )
        Stringify(p, tos);
        zKey = zStack[tos]; 
        nKey = aStack[tos].n;
        if( p->agg.nHash<=0 ){
          pElem = 0;
        }else{
          int h = sqliteHashNoCase(zKey, nKey-1) % p->agg.nHash;
          for(pElem=p->agg.apHash[h]; pElem; pElem=pElem->pHash){
................................................................................
          }
        }
        if( pElem ){
          p->agg.pCurrent = pElem;
          pc = pOp->p2 - 1;
        }else{
          AggInsert(&p->agg, zKey);

        }
        POPSTACK;
        break; 
      }

      /* Opcode: AggIncr P1 P2 *
      **
................................................................................
          p->nSet = i+1;
        }
        if( pOp->p3 ){
          SetInsert(&p->aSet[i], pOp->p3);
        }else{
          int tos = p->tos;
          if( tos<0 ) goto not_enough_stack;
          Stringify(p, tos);
          SetInsert(&p->aSet[i], zStack[tos]);
          POPSTACK;
        }

        break;
      }

      /* Opcode: SetFound P1 P2 *
      **
      ** Pop the stack once and compare the value popped off with the
      ** contents of set P1.  If the element popped exists in set P1,
      ** then jump to P2.  Otherwise fall through.
      */
      case OP_SetFound: {
        int i = pOp->p1;
        int tos = p->tos;
        VERIFY( if( tos<0 ) goto not_enough_stack; )
        Stringify(p, tos);
        if( VERIFY( i>=0 && i<p->nSet &&) SetTest(&p->aSet[i], zStack[tos])){
          pc = pOp->p2 - 1;
        }
        POPSTACK;
        break;
      }

................................................................................
      ** contents of set P1.  If the element popped does not exists in 
      ** set P1, then jump to P2.  Otherwise fall through.
      */
      case OP_SetNotFound: {
        int i = pOp->p1;
        int tos = p->tos;
        VERIFY( if( tos<0 ) goto not_enough_stack; )
        Stringify(p, tos);
        if(VERIFY( i>=0 && i<p->nSet &&) !SetTest(&p->aSet[i], zStack[tos])){
          pc = pOp->p2 - 1;
        }
        POPSTACK;
        break;
      }

................................................................................
      ** Interpret the top of the stack as a string.  Replace the top of
      ** stack with an integer which is the length of the string.
      */
      case OP_Strlen: {
        int tos = p->tos;
        int len;
        VERIFY( if( tos<0 ) goto not_enough_stack; )
        Stringify(p, tos);
#ifdef SQLITE_UTF8
        {
          char *z = zStack[tos];
          for(len=0; *z; z++){ if( (0xc0&*z)!=0x80 ) len++; }
        }
#else
        len = aStack[tos].n-1;
................................................................................
          Integerify(p, p->tos);
          start = aStack[p->tos].i - 1;
          POPSTACK;
        }else{
          start = pOp->p1 - 1;
        }
        VERIFY( if( p->tos<0 ) goto not_enough_stack; )
        Stringify(p, p->tos);

        /* "n" will be the number of characters in the input string.
        ** For iso8859, the number of characters is the number of bytes.
        ** Buf for UTF-8, some characters can use multiple bytes and the
        ** situation is more complex. 
        */
#ifdef SQLITE_UTF8







|







 







<

>







 







|












>







 







>
>
>
>







 







|
>
>
>







 







>







 







|
<







 







|
<







 







|
<







 







|
<







 







|
<







 







|







 







>







 







|



>













|







 







|







 







|







 







|







37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
...
219
220
221
222
223
224
225

226
227
228
229
230
231
232
233
234
...
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
...
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
...
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
....
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
....
1369
1370
1371
1372
1373
1374
1375
1376

1377
1378
1379
1380
1381
1382
1383
....
1409
1410
1411
1412
1413
1414
1415
1416

1417
1418
1419
1420
1421
1422
1423
....
1488
1489
1490
1491
1492
1493
1494
1495

1496
1497
1498
1499
1500
1501
1502
....
1525
1526
1527
1528
1529
1530
1531
1532

1533
1534
1535
1536
1537
1538
1539
....
1557
1558
1559
1560
1561
1562
1563
1564

1565
1566
1567
1568
1569
1570
1571
....
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
....
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
....
3242
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
3274
....
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
....
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
....
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
** 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.57 2001/04/11 14:28:43 drh Exp $
*/
#include "sqliteInt.h"
#include <unistd.h>
#include <ctype.h>

/*
** SQL is translated into a sequence of instructions to be
................................................................................
};

/*
** Create a new virtual database engine.
*/
Vdbe *sqliteVdbeCreate(sqlite *db){
  Vdbe *p;

  p = sqliteMalloc( sizeof(Vdbe) );
  if( p==0 ) return 0;
  p->pBe = db->pBe;
  p->db = db;
  return p;
}

/*
** Turn tracing on or off
................................................................................
** or a double quote character (ASCII 0x22).  Two quotes in a row
** resolve to be a single actual quote character within the string.
*/
void sqliteVdbeDequoteP3(Vdbe *p, int addr){
  char *z;
  if( addr<0 || addr>=p->nOp ) return;
  z = p->aOp[addr].p3;
  if( z ) sqliteDequote(z);
}

/*
** On the P3 argument of the given instruction, change all
** strings of whitespace characters into a single space and
** delete leading and trailing whitespace.
*/
void sqliteVdbeCompressSpace(Vdbe *p, int addr){
  char *z;
  int i, j;
  if( addr<0 || addr>=p->nOp ) return;
  z = p->aOp[addr].p3;
  if( z==0 ) return;
  i = j = 0;
  while( isspace(z[i]) ){ i++; }
  while( z[i] ){
    if( isspace(z[i]) ){
      z[j++] = ' ';
      while( isspace(z[++i]) ){}
    }else{
................................................................................
*/
static void AggRehash(Agg *p, int nHash){
  int size;
  AggElem *pElem;
  if( p->nHash==nHash ) return;
  size = nHash * sizeof(AggElem*);
  p->apHash = sqliteRealloc(p->apHash, size );
  if( p->apHash==0 ){
    AggReset(p);
    return;
  }
  memset(p->apHash, 0, size);
  p->nHash = nHash;
  for(pElem=p->pFirst; pElem; pElem=pElem->pNext){
    AggEnhash(p, pElem);
  }
}

................................................................................
static void SetInsert(Set *p, char *zKey){
  SetElem *pElem;
  int h = sqliteHashNoCase(zKey, 0) % ArraySize(p->apHash);
  for(pElem=p->apHash[h]; pElem; pElem=pElem->pHash){
    if( strcmp(pElem->zKey, zKey)==0 ) return;
  }
  pElem = sqliteMalloc( sizeof(*pElem) + strlen(zKey) );
  if( pElem==0 ){
    SetClear(p);
    return;
  }
  strcpy(pElem->zKey, zKey);
  pElem->pNext = p->pAll;
  p->pAll = pElem;
  pElem->pHash = p->apHash[h];
  p->apHash[h] = pElem;
}

................................................................................
  rc = SQLITE_OK;
#ifdef MEMORY_DEBUG
  if( access("vdbe_trace",0)==0 ){
    p->trace = stderr;
  }
#endif
  /* if( pzErrMsg ){ *pzErrMsg = 0; } */
  if( sqlite_malloc_failed ) rc = SQLITE_NOMEM;
  for(pc=0; rc==SQLITE_OK && pc<p->nOp VERIFY(&& pc>=0); pc++){
    pOp = &p->aOp[pc];

    /* Interrupt processing if requested.
    */
    if( db->flags & SQLITE_Interrupt ){
      db->flags &= ~SQLITE_Interrupt;
................................................................................
        }else if( (ft & fn & STK_Int)==STK_Int ){
          copy = aStack[nos].i<aStack[tos].i;
        }else if( ( (ft|fn) & (STK_Int|STK_Real) ) !=0 ){
          Realify(p, tos);
          Realify(p, nos);
          copy = aStack[tos].r>aStack[nos].r;
        }else{
          if( Stringify(p, tos) || Stringify(p, nos) ) goto no_mem;

          copy = sqliteCompare(zStack[tos],zStack[nos])>0;
        }
        if( copy ){
          Release(p, nos);
          aStack[nos] = aStack[tos];
          zStack[nos] = zStack[tos];
          zStack[tos] = 0;
................................................................................
        }else if( (ft & fn & STK_Int)==STK_Int ){
          copy = aStack[nos].i>aStack[tos].i;
        }else if( ( (ft|fn) & (STK_Int|STK_Real) ) !=0 ){
          Realify(p, tos);
          Realify(p, nos);
          copy = aStack[tos].r<aStack[nos].r;
        }else{
          if( Stringify(p, tos) || Stringify(p, nos) ) goto no_mem;

          copy = sqliteCompare(zStack[tos],zStack[nos])<0;
        }
        if( copy ){
          Release(p, nos);
          aStack[nos] = aStack[tos];
          zStack[nos] = zStack[tos];
          zStack[tos] = 0;
................................................................................
        int ft, fn;
        VERIFY( if( nos<0 ) goto not_enough_stack; )
        ft = aStack[tos].flags;
        fn = aStack[nos].flags;
        if( (ft & fn)==STK_Int ){
          c = aStack[nos].i - aStack[tos].i;
        }else{
          if( Stringify(p, tos) || Stringify(p, nos) ) goto no_mem;

          c = sqliteCompare(zStack[nos], zStack[tos]);
        }
        switch( pOp->opcode ){
          case OP_Eq:    c = c==0;     break;
          case OP_Ne:    c = c!=0;     break;
          case OP_Lt:    c = c<0;      break;
          case OP_Le:    c = c<=0;     break;
................................................................................
      ** are different.
      */
      case OP_Like: {
        int tos = p->tos;
        int nos = tos - 1;
        int c;
        VERIFY( if( nos<0 ) goto not_enough_stack; )
        if( Stringify(p, tos) || Stringify(p, nos) ) goto no_mem;

        c = sqliteLikeCompare(zStack[tos], zStack[nos]);
        POPSTACK;
        POPSTACK;
        if( pOp->p1 ) c = !c;
        if( c ) pc = pOp->p2-1;
        break;
      }
................................................................................
      ** are different.
      */
      case OP_Glob: {
        int tos = p->tos;
        int nos = tos - 1;
        int c;
        VERIFY( if( nos<0 ) goto not_enough_stack; )
        if( Stringify(p, tos) || Stringify(p, nos) ) goto no_mem;

        c = sqliteGlobCompare(zStack[tos], zStack[nos]);
        POPSTACK;
        POPSTACK;
        if( pOp->p1 ) c = !c;
        if( c ) pc = pOp->p2-1;
        break;
      }
................................................................................
      case OP_AggFocus: {
        int tos = p->tos;
        AggElem *pElem;
        char *zKey;
        int nKey;

        VERIFY( if( tos<0 ) goto not_enough_stack; )
        if( Stringify(p, tos) ) goto no_mem;
        zKey = zStack[tos]; 
        nKey = aStack[tos].n;
        if( p->agg.nHash<=0 ){
          pElem = 0;
        }else{
          int h = sqliteHashNoCase(zKey, nKey-1) % p->agg.nHash;
          for(pElem=p->agg.apHash[h]; pElem; pElem=pElem->pHash){
................................................................................
          }
        }
        if( pElem ){
          p->agg.pCurrent = pElem;
          pc = pOp->p2 - 1;
        }else{
          AggInsert(&p->agg, zKey);
          if( sqlite_malloc_failed ) goto no_mem;
        }
        POPSTACK;
        break; 
      }

      /* Opcode: AggIncr P1 P2 *
      **
................................................................................
          p->nSet = i+1;
        }
        if( pOp->p3 ){
          SetInsert(&p->aSet[i], pOp->p3);
        }else{
          int tos = p->tos;
          if( tos<0 ) goto not_enough_stack;
          if( Stringify(p, tos) ) goto no_mem;
          SetInsert(&p->aSet[i], zStack[tos]);
          POPSTACK;
        }
        if( sqlite_malloc_failed ) goto no_mem;
        break;
      }

      /* Opcode: SetFound P1 P2 *
      **
      ** Pop the stack once and compare the value popped off with the
      ** contents of set P1.  If the element popped exists in set P1,
      ** then jump to P2.  Otherwise fall through.
      */
      case OP_SetFound: {
        int i = pOp->p1;
        int tos = p->tos;
        VERIFY( if( tos<0 ) goto not_enough_stack; )
        if( Stringify(p, tos) ) goto no_mem;
        if( VERIFY( i>=0 && i<p->nSet &&) SetTest(&p->aSet[i], zStack[tos])){
          pc = pOp->p2 - 1;
        }
        POPSTACK;
        break;
      }

................................................................................
      ** contents of set P1.  If the element popped does not exists in 
      ** set P1, then jump to P2.  Otherwise fall through.
      */
      case OP_SetNotFound: {
        int i = pOp->p1;
        int tos = p->tos;
        VERIFY( if( tos<0 ) goto not_enough_stack; )
        if( Stringify(p, tos) ) goto no_mem;
        if(VERIFY( i>=0 && i<p->nSet &&) !SetTest(&p->aSet[i], zStack[tos])){
          pc = pOp->p2 - 1;
        }
        POPSTACK;
        break;
      }

................................................................................
      ** Interpret the top of the stack as a string.  Replace the top of
      ** stack with an integer which is the length of the string.
      */
      case OP_Strlen: {
        int tos = p->tos;
        int len;
        VERIFY( if( tos<0 ) goto not_enough_stack; )
        if( Stringify(p, tos) ) goto no_mem;
#ifdef SQLITE_UTF8
        {
          char *z = zStack[tos];
          for(len=0; *z; z++){ if( (0xc0&*z)!=0x80 ) len++; }
        }
#else
        len = aStack[tos].n-1;
................................................................................
          Integerify(p, p->tos);
          start = aStack[p->tos].i - 1;
          POPSTACK;
        }else{
          start = pOp->p1 - 1;
        }
        VERIFY( if( p->tos<0 ) goto not_enough_stack; )
        if( Stringify(p, p->tos) ) goto no_mem;

        /* "n" will be the number of characters in the input string.
        ** For iso8859, the number of characters is the number of bytes.
        ** Buf for UTF-8, some characters can use multiple bytes and the
        ** situation is more complex. 
        */
#ifdef SQLITE_UTF8

Changes to src/where.c.

21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
...
166
167
168
169
170
171
172
173
174

175
176
177
178
179
180
181
**   http://www.hwaci.com/drh/
**
*************************************************************************
** This module contains C code that generates VDBE code used to process
** the WHERE clause of SQL statements.  Also found here are subroutines
** to generate VDBE code to evaluate expressions.
**
** $Id: where.c,v 1.13 2001/04/04 11:48:58 drh Exp $
*/
#include "sqliteInt.h"

/*
** The query generator uses an array of instances of this structure to
** help it analyze the subexpressions of the WHERE clause.  Each WHERE
** clause subexpression is separated from the others by an AND operator.
................................................................................
  /* Allocate space for aOrder[]. */
  aOrder = sqliteMalloc( sizeof(int) * pTabList->nId );

  /* Allocate and initialize the WhereInfo structure that will become the
  ** return value.
  */
  pWInfo = sqliteMalloc( sizeof(WhereInfo) );
  if( pWInfo==0 ){
    sqliteFree(aOrder);

    return 0;
  }
  pWInfo->pParse = pParse;
  pWInfo->pTabList = pTabList;
  base = pWInfo->base = pParse->nTab;

  /* Split the WHERE clause into as many as 32 separate subexpressions







|







 







|

>







21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
...
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
**   http://www.hwaci.com/drh/
**
*************************************************************************
** This module contains C code that generates VDBE code used to process
** the WHERE clause of SQL statements.  Also found here are subroutines
** to generate VDBE code to evaluate expressions.
**
** $Id: where.c,v 1.14 2001/04/11 14:28:43 drh Exp $
*/
#include "sqliteInt.h"

/*
** The query generator uses an array of instances of this structure to
** help it analyze the subexpressions of the WHERE clause.  Each WHERE
** clause subexpression is separated from the others by an AND operator.
................................................................................
  /* Allocate space for aOrder[]. */
  aOrder = sqliteMalloc( sizeof(int) * pTabList->nId );

  /* Allocate and initialize the WhereInfo structure that will become the
  ** return value.
  */
  pWInfo = sqliteMalloc( sizeof(WhereInfo) );
  if( sqlite_malloc_failed ){
    sqliteFree(aOrder);
    sqliteFree(pWInfo);
    return 0;
  }
  pWInfo->pParse = pParse;
  pWInfo->pTabList = pTabList;
  base = pWInfo->base = pParse->nTab;

  /* Split the WHERE clause into as many as 32 separate subexpressions

Changes to test/all.test.

18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
..
49
50
51
52
53
54
55

56
57
58
59
60
61
62
..
74
75
76
77
78
79
80
81









82
# Author contact information:
#   drh@hwaci.com
#   http://www.hwaci.com/drh/
#
#***********************************************************************
# This file runs all tests.
#
# $Id: all.test,v 1.5 2000/12/10 18:23:51 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl
rename finish_test really_finish_test
proc finish_test {} {memleak_check}

if {[file exists ./sqlite_test_count]} {
................................................................................


for {set Counter 0} {$Counter<$COUNT} {incr Counter} {
  foreach p $PREFIXES {
    set dbprefix $p
    foreach testfile [lsort -dictionary [glob $testdir/*.test]] {
      if {[file tail $testfile]=="all.test"} continue

      source $testfile
    }
  }
  if {[info exists Leak]} {
    lappend LeakList $Leak
  }
}
................................................................................
       puts "     Got: $LeakList"
       incr ::nErr
       break
    }
  }
  puts " Ok"
}










really_finish_test







|







 







>







 








>
>
>
>
>
>
>
>
>

18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
..
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
..
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# Author contact information:
#   drh@hwaci.com
#   http://www.hwaci.com/drh/
#
#***********************************************************************
# This file runs all tests.
#
# $Id: all.test,v 1.6 2001/04/11 14:28:43 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl
rename finish_test really_finish_test
proc finish_test {} {memleak_check}

if {[file exists ./sqlite_test_count]} {
................................................................................


for {set Counter 0} {$Counter<$COUNT} {incr Counter} {
  foreach p $PREFIXES {
    set dbprefix $p
    foreach testfile [lsort -dictionary [glob $testdir/*.test]] {
      if {[file tail $testfile]=="all.test"} continue
      if {[file tail $testfile]=="malloc.test"} continue
      source $testfile
    }
  }
  if {[info exists Leak]} {
    lappend LeakList $Leak
  }
}
................................................................................
       puts "     Got: $LeakList"
       incr ::nErr
       break
    }
  }
  puts " Ok"
}

if {[file readable $testdir/malloc.test]} {
  for {set Counter 0} {$Counter<$COUNT} {incr Counter} {
    foreach p $PREFIXES {
      set dbprefix $p
      source $testdir/malloc.test
    }
  }
}

really_finish_test

Changes to test/printf.test.

19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
..
35
36
37
38
39
40
41









42
43
44
45
46
47
48
..
85
86
87
88
89
90
91











92
#   drh@hwaci.com
#   http://www.hwaci.com/drh/
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing the sqlite_*_printf() interface.
#
# $Id: printf.test,v 1.1 2001/04/07 15:24:33 drh Exp $

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

set n 1
foreach v {1 2 5 10 99 100 1000000 999999999 0 -1 -2 -5 -10 -99 -100 -9999999} {
  do_test printf-1.$n.1 [subst {
................................................................................
  }] [format {Three integers: %d %x %o} $v $v $v]
  do_test printf-1.$n.2 [subst {
    sqlite_mprintf_int {Three integers: (%6d) (%6x) (%6o)} $v $v $v
  }] [format {Three integers: (%6d) (%6x) (%6o)} $v $v $v]
  do_test printf-1.$n.3 [subst {
    sqlite_mprintf_int {Three integers: (%-6d) (%-6x) (%-6o)} $v $v $v
  }] [format {Three integers: (%-6d) (%-6x) (%-6o)} $v $v $v]









  incr n
}

set m 1
foreach {a b} {1 1 5 5 10 10 10 5} {
  set n 1
  foreach x {0.001 1.0e-20 1.0 0.0 100.0 9.99999 -0.00543 -1.0 -99.99999} {
................................................................................
  sqlite_mprintf_str {%d %d A String: (%-30s)} 1 2 {This is the string}
} [format {%d %d A String: (%-30s)} 1 2 {This is the string}]

do_test printf-4.1 {
  sqlite_mprintf_str {%d %d A quoted string: '%q'} 1 2 {Hi Y'all}
} {1 2 A quoted string: 'Hi Y''all'}












finish_test







|







 







>
>
>
>
>
>
>
>
>







 







>
>
>
>
>
>
>
>
>
>
>

19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
..
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
..
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
#   drh@hwaci.com
#   http://www.hwaci.com/drh/
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing the sqlite_*_printf() interface.
#
# $Id: printf.test,v 1.2 2001/04/11 14:28:43 drh Exp $

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

set n 1
foreach v {1 2 5 10 99 100 1000000 999999999 0 -1 -2 -5 -10 -99 -100 -9999999} {
  do_test printf-1.$n.1 [subst {
................................................................................
  }] [format {Three integers: %d %x %o} $v $v $v]
  do_test printf-1.$n.2 [subst {
    sqlite_mprintf_int {Three integers: (%6d) (%6x) (%6o)} $v $v $v
  }] [format {Three integers: (%6d) (%6x) (%6o)} $v $v $v]
  do_test printf-1.$n.3 [subst {
    sqlite_mprintf_int {Three integers: (%-6d) (%-6x) (%-6o)} $v $v $v
  }] [format {Three integers: (%-6d) (%-6x) (%-6o)} $v $v $v]
  do_test printf-1.$n.4 [subst {
    sqlite_mprintf_int {Three integers: (%+6d) (%+6x) (%+6o)} $v $v $v
  }] [format {Three integers: (%+6d) (%+6x) (%+6o)} $v $v $v]
  do_test printf-1.$n.5 [subst {
    sqlite_mprintf_int {Three integers: (%06d) (%06x) (%06o)} $v $v $v
  }] [format {Three integers: (%06d) (%06x) (%06o)} $v $v $v]
  do_test printf-1.$n.6 [subst {
    sqlite_mprintf_int {Three integers: (% 6d) (% 6x) (% 6o)} $v $v $v
  }] [format {Three integers: (% 6d) (% 6x) (% 6o)} $v $v $v]
  incr n
}

set m 1
foreach {a b} {1 1 5 5 10 10 10 5} {
  set n 1
  foreach x {0.001 1.0e-20 1.0 0.0 100.0 9.99999 -0.00543 -1.0 -99.99999} {
................................................................................
  sqlite_mprintf_str {%d %d A String: (%-30s)} 1 2 {This is the string}
} [format {%d %d A String: (%-30s)} 1 2 {This is the string}]

do_test printf-4.1 {
  sqlite_mprintf_str {%d %d A quoted string: '%q'} 1 2 {Hi Y'all}
} {1 2 A quoted string: 'Hi Y''all'}

do_test printf-5.1 {
  set x [sqlite_mprintf_str {%d %d %100000s} 0 0 {Hello}]
  string length $x
} {994}
do_test printf-5.2 {
  sqlite_mprintf_str {%d %d (%-10.10s) %} -9 -10 {HelloHelloHello}
} {-9 -10 (HelloHello) %}
do_test printf-5.3 {
  sqlite_mprintf_str {%% %d %d (%=10s)} 5 6 Hello
} {% 5 6 (  Hello   )}

finish_test

Changes to test/tableapi.test.

20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
..
44
45
46
47
48
49
50











































51
52
53
54
55
56
#   http://www.hwaci.com/drh/
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing the sqlite_exec_printf() and
# sqlite_get_table_printf() APIs.
#
# $Id: tableapi.test,v 1.1 2001/04/07 15:24:34 drh Exp $

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

do_test tableapi-1.0 {
  set ::dbx [sqlite_open testdb]
  catch {sqlite_exec_printf $::dbx {DROP TABLE xyz} {}}
................................................................................
} {0 {a b 1 {Hi Y'all}}}

do_test tableapi-2.1 {
  sqlite_get_table_printf $::dbx {
    SELECT * FROM xyz WHERE b='%q'
  } {Hi Y'all}
} {0 1 2 a b 1 {Hi Y'all}}












































do_test tableapi-99.0 {
  sqlite_close $::dbx
} {}

finish_test







|







 







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






20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
..
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
#   http://www.hwaci.com/drh/
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing the sqlite_exec_printf() and
# sqlite_get_table_printf() APIs.
#
# $Id: tableapi.test,v 1.2 2001/04/11 14:28:43 drh Exp $

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

do_test tableapi-1.0 {
  set ::dbx [sqlite_open testdb]
  catch {sqlite_exec_printf $::dbx {DROP TABLE xyz} {}}
................................................................................
} {0 {a b 1 {Hi Y'all}}}

do_test tableapi-2.1 {
  sqlite_get_table_printf $::dbx {
    SELECT * FROM xyz WHERE b='%q'
  } {Hi Y'all}
} {0 1 2 a b 1 {Hi Y'all}}
do_test tableapi-2.2 {
  sqlite_get_table_printf $::dbx {
    SELECT * FROM xyz
  } {}
} {0 1 2 a b 1 {Hi Y'all}}
do_test tableapi-2.3 {
  for {set i 2} {$i<=50} {incr i} {
    sqlite_get_table_printf $::dbx \
       "INSERT INTO xyz VALUES($i,'(%s)')" $i
  }
  sqlite_get_table_printf $::dbx {
    SELECT * FROM xyz ORDER BY a
  } {}
} {0 50 2 a b 1 {Hi Y'all} 2 (2) 3 (3) 4 (4) 5 (5) 6 (6) 7 (7) 8 (8) 9 (9) 10 (10) 11 (11) 12 (12) 13 (13) 14 (14) 15 (15) 16 (16) 17 (17) 18 (18) 19 (19) 20 (20) 21 (21) 22 (22) 23 (23) 24 (24) 25 (25) 26 (26) 27 (27) 28 (28) 29 (29) 30 (30) 31 (31) 32 (32) 33 (33) 34 (34) 35 (35) 36 (36) 37 (37) 38 (38) 39 (39) 40 (40) 41 (41) 42 (42) 43 (43) 44 (44) 45 (45) 46 (46) 47 (47) 48 (48) 49 (49) 50 (50)}
do_test tableapi-2.3.1 {
  sqlite_get_table_printf $::dbx {
    SELECT * FROM xyz  WHERE a>49 ORDER BY a
  } {}
} {0 1 2 a b 50 (50)}
do_test tableapi-2.3.2 {
  sqlite_get_table_printf $::dbx {
    SELECT * FROM xyz WHERE a>47 ORDER BY a
  } {}
} {0 3 2 a b 48 (48) 49 (49) 50 (50)}
do_test tableapi-2.4 {
  set ::big_str [sqlite_mprintf_str {%500'* Hello %500'*} 0 0 {}]
  sqlite_get_table_printf $::dbx {
    INSERT INTO xyz VALUES(51,'%q')
  } $::big_str
} {0 0 0}
do_test tableapi-2.5 {
  sqlite_get_table_printf $::dbx {
    SELECT * FROM xyz WHERE a>49 ORDER BY a;
  } {}
} "0 2 2 a b 50 (50) 51 \173$::big_str\175"
do_test tableapi-2.6 {
  sqlite_get_table_printf $::dbx {
    INSERT INTO xyz VALUES(52,NULL)
  } {}
  sqlite_get_table_printf $::dbx {
    SELECT * FROM xyz WHERE a IN (42,50,52) ORDER BY a DESC
  } {}
} {0 3 2 a b 52 NULL 50 (50) 42 (42)}

do_test tableapi-99.0 {
  sqlite_close $::dbx
} {}

finish_test

Changes to test/tester.tcl.

19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
...
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
#   drh@hwaci.com
#   http://www.hwaci.com/drh/
#
#***********************************************************************
# This file implements some common TCL routines used for regression
# testing the SQLite library
#
# $Id: tester.tcl,v 1.14 2001/04/06 16:13:43 drh Exp $

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

# The procedure uses the special "--malloc-stats--" macro of SQLite
# (which is only available if SQLite is compiled with -DMEMORY_DEBUG=1)
# to see how many malloc()s have not been free()ed.  The number
# of surplus malloc()s is stored in the global variable $::Leak.
# If the value in $::Leak grows, it may mean there is a memory leak
# in the library.
#
proc memleak_check {} {
  set r [execsql {--malloc-stats--}]
  if {$r==""} return
  set ::Leak [expr {[lindex $r 0]-[lindex $r 1]}]
  # puts "*** $::Leak mallocs have not been freed ***"

}

# Run this routine last
#
proc finish_test {} {
  global nTest nErr nProb
  memleak_check







|







 







|







|
|
|
<
>







19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
...
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
#   drh@hwaci.com
#   http://www.hwaci.com/drh/
#
#***********************************************************************
# This file implements some common TCL routines used for regression
# testing the SQLite library
#
# $Id: tester.tcl,v 1.15 2001/04/11 14:28:43 drh Exp $

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

# The procedure uses the special "sqlite_malloc_stat" command
# (which is only available if SQLite is compiled with -DMEMORY_DEBUG=1)
# to see how many malloc()s have not been free()ed.  The number
# of surplus malloc()s is stored in the global variable $::Leak.
# If the value in $::Leak grows, it may mean there is a memory leak
# in the library.
#
proc memleak_check {} {
  if {[info command sqlite_malloc_stat]!=""} {
    set r [sqlite_malloc_stat]
    set ::Leak [expr {[lindex $r 0]-[lindex $r 1]}]

  }
}

# Run this routine last
#
proc finish_test {} {
  global nTest nErr nProb
  memleak_check

Changes to www/changes.tcl.

13
14
15
16
17
18
19
20

21
22
23
24
25
26
27


proc chng {date desc} {
  puts "<DT><B>$date</B></DT>"
  puts "<DD><P><UL>$desc</UL></P></DD>"
}

chng {2001 Apr 6 (1.0.31)} {

<li>New tests added to the test suite.</li>
}

chng {2001 Apr 6 (1.0.30)} {
<li>Remove the <b>sqlite_encoding</b> TCL variable that was introduced
    in the previous version.</li>
<li>Add options <b>-encoding</b> and <b>-tcl-uses-utf</b> to the







|
>







13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28


proc chng {date desc} {
  puts "<DT><B>$date</B></DT>"
  puts "<DD><P><UL>$desc</UL></P></DD>"
}

chng {2001 Apr 11 (1.0.31)} {
<li>More robust handling of out-of-memory errors.</li>
<li>New tests added to the test suite.</li>
}

chng {2001 Apr 6 (1.0.30)} {
<li>Remove the <b>sqlite_encoding</b> TCL variable that was introduced
    in the previous version.</li>
<li>Add options <b>-encoding</b> and <b>-tcl-uses-utf</b> to the