/ Check-in [ced90c3f]
Login

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

Overview
Comment:speed tweaks and documentation updates (CVS 167)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: ced90c3f93e5e0cf73ea77b62a1308cd8dd5f3b3
User & Date: drh 2000-12-10 18:23:49
Original User & Date: drh 2000-12-10 18:23:50
Context
2000-12-10
18:23
branches: 1.16.2; speed tweaks and documentation updates (CVS 168) check-in: af9673d1 user: drh tags: trunk
18:23
speed tweaks and documentation updates (CVS 167) check-in: ced90c3f user: drh tags: trunk
2000-11-28
21:00
Version 1.0.16 (CVS 487) check-in: 8c36b248 user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to VERSION.

1
1.0.15
|
1
1.0.17

Changes to src/dbbemem.c.

22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
**
*************************************************************************
** This file contains code to implement the database backend (DBBE)
** for sqlite.  The database backend is the interface between
** sqlite and the code that does the actually reading and writing
** of information to the disk.
**
** This file uses an in-memory hash talbe as the database backend. 
**
** $Id: dbbemem.c,v 1.4 2000/10/19 15:28:41 drh Exp $
*/
#include "sqliteInt.h"
#include <sys/stat.h>
#include <unistd.h>
#include <ctype.h>
#include <time.h>








|

|







22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
**
*************************************************************************
** This file contains code to implement the database backend (DBBE)
** for sqlite.  The database backend is the interface between
** 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. 
**
** $Id: dbbemem.c,v 1.5 2000/12/10 18:23:50 drh Exp $
*/
#include "sqliteInt.h"
#include <sys/stat.h>
#include <unistd.h>
#include <ctype.h>
#include <time.h>

Changes to src/main.c.

22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
...
253
254
255
256
257
258
259
260
261




262







263
264
265
266




267
268
269
270
271




272

273
274


275





276
277

278
279
280
281


282
283
284
285
286
287
288
289
**
*************************************************************************
** 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.21 2000/10/19 01:49:02 drh Exp $
*/
#include "sqliteInt.h"

/*
** This is the callback routine for the code that initializes the
** database.  Each callback contains text of a CREATE TABLE or
** CREATE INDEX statement that must be parsed to yield the internal
................................................................................
  sqliteFree(db);
}

/*
** Return TRUE if the given SQL string ends in a semicolon.
*/
int sqlite_complete(const char *zSql){
  int i;
  int lastWasSemi = 0;












  i = 0;
  while( i>=0 && zSql[i]!=0 ){
    int tokenType;
    int n;





    n = sqliteGetToken(&zSql[i], &tokenType);
    switch( tokenType ){
      case TK_SPACE:
      case TK_COMMENT:




        break;

      case TK_SEMI:
        lastWasSemi = 1;


        break;





      default:
        lastWasSemi = 0;

        break;
    }
    i += n;
  }


  return lastWasSemi;
}

/*
** Execute SQL code.  Return one of the SQLITE_ success/failure
** codes.  Also write an error message into memory obtained from
** malloc() and make *pzErrMsg point to that message.
**







|







 







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

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

|
<
|
>
>
|







22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
...
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274



275
276
277
278
279


280

281
282
283
284
285
286
287

288
289
290
291
292
293
294
295
296

297
298
299

300
301
302
303
304
305
306
307
308
309
310
**
*************************************************************************
** 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.22 2000/12/10 18:23:50 drh Exp $
*/
#include "sqliteInt.h"

/*
** This is the callback routine for the code that initializes the
** database.  Each callback contains text of a CREATE TABLE or
** CREATE INDEX statement that must be parsed to yield the internal
................................................................................
  sqliteFree(db);
}

/*
** Return TRUE if the given SQL string ends in a semicolon.
*/
int sqlite_complete(const char *zSql){
  int isComplete = 0;
  while( *zSql ){
    switch( *zSql ){
      case ';': {
        isComplete = 1;
        break;
      }
      case ' ':
      case '\t':
      case '\n':
      case '\f': {
        break;
      }
      case '\'': {
        isComplete = 0;



        zSql++;
        while( *zSql && *zSql!='\'' ){ zSql++; }
        if( *zSql==0 ) return 0;
        break;
      }


      case '"': {

        isComplete = 0;
        zSql++;
        while( *zSql && *zSql!='"' ){ zSql++; }
        if( *zSql==0 ) return 0;
        break;
      }
      case '-': {

        if( zSql[1]!='-' ){
          isComplete = 0;
          break;
        }
        while( *zSql && *zSql!='\n' ){ zSql++; }
        if( *zSql==0 ) return isComplete;
        break;
      } 
      default: {

        isComplete = 0;
        break;
      }

    }
    zSql++;
  }
  return isComplete;
}

/*
** Execute SQL code.  Return one of the SQLITE_ success/failure
** codes.  Also write an error message into memory obtained from
** malloc() and make *pzErrMsg point to that message.
**

Changes to src/sqliteInt.h.

19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
..
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
...
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
** Author contact information:
**   drh@hwaci.com
**   http://www.hwaci.com/drh/
**
*************************************************************************
** Internal interface definitions for SQLite.
**
** @(#) $Id: sqliteInt.h,v 1.32 2000/11/28 20:47:23 drh Exp $
*/
#include "sqlite.h"
#include "dbbe.h"
#include "vdbe.h"
#include "parse.h"
#include <gdbm.h>
#include <stdio.h>
................................................................................
  void sqliteStrRealloc(char**);
#else
# define sqliteStrRealloc(X)
#endif

/*
** The following global variables are used for testing and debugging
** only.  Thy only work if MEMORY_DEBUG is defined.
*/
#ifdef MEMORY_DEBUG
int sqlite_nMalloc;         /* Number of sqliteMalloc() calls */
int sqlite_nFree;           /* Number of sqliteFree() calls */
int sqlite_iMallocFail;     /* Fail sqliteMalloc() after this many calls */
#endif

/*
** The number of entries in the in-memory hash array holding the
** database schema.

*/
#define N_HASH        51

/*
** Name of the master database table.  The master database table
** is a special table that holds the names and attributes of all
** user tables and indices.
................................................................................
typedef struct AggExpr AggExpr;

/*
** Each database is an instance of the following structure
*/
struct sqlite {
  Dbbe *pBe;                 /* The backend driver */
  int flags;                 /* Miscellanous flags */
  int file_format;           /* What file format version is this database? */
  int nTable;                /* Number of tables in the database */
  void *pBusyArg;            /* 1st Argument to the busy callback */
  int (*xBusyCallback)(void *,const char*,int);  /* The busy callback */
  Table *apTblHash[N_HASH];  /* All tables of the database */
  Index *apIdxHash[N_HASH];  /* All indices of the database */
};







|







 







|


|
|
|




|
>







 







|







19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
..
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
...
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
** Author contact information:
**   drh@hwaci.com
**   http://www.hwaci.com/drh/
**
*************************************************************************
** Internal interface definitions for SQLite.
**
** @(#) $Id: sqliteInt.h,v 1.33 2000/12/10 18:23:51 drh Exp $
*/
#include "sqlite.h"
#include "dbbe.h"
#include "vdbe.h"
#include "parse.h"
#include <gdbm.h>
#include <stdio.h>
................................................................................
  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 */
extern int sqlite_iMallocFail;   /* Fail sqliteMalloc() after this many calls */
#endif

/*
** The number of entries in the in-memory hash array holding the
** database schema.  (Collision resolution is by chaining, so the
** table will hold more than this many entries.)
*/
#define N_HASH        51

/*
** Name of the master database table.  The master database table
** is a special table that holds the names and attributes of all
** user tables and indices.
................................................................................
typedef struct AggExpr AggExpr;

/*
** Each database is an instance of the following structure
*/
struct sqlite {
  Dbbe *pBe;                 /* The backend driver */
  int flags;                 /* Miscellanous flags. See below */
  int file_format;           /* What file format version is this database? */
  int nTable;                /* Number of tables in the database */
  void *pBusyArg;            /* 1st Argument to the busy callback */
  int (*xBusyCallback)(void *,const char*,int);  /* The busy callback */
  Table *apTblHash[N_HASH];  /* All tables of the database */
  Index *apIdxHash[N_HASH];  /* All indices of the database */
};

Changes to src/table.c.

1






















2
3
4
5
6
7
8
9
10
11
12
13
/*






















** This file contains the sqlite_get_table() and sqlite_free_table()
** interface routines.  These are just wrappers around the main
** interface routine of sqlite_exec().
**
** This routines are in a separate files to that they will not be linked
** if they are not used.
*/
#include <stdlib.h>
#include "sqlite.h"

/*
** This structure is used to pass data from sqlite_get_table() through

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




|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
/*
** Copyright (c) 2000 D. Richard Hipp
**
** This program is free software; you can redistribute it and/or
** modify it under the terms of the GNU General Public
** License as published by the Free Software Foundation; either
** version 2 of the License, or (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
** General Public License for more details.
** 
** You should have received a copy of the GNU General Public
** License along with this library; if not, write to the
** Free Software Foundation, Inc., 59 Temple Place - Suite 330,
** Boston, MA  02111-1307, USA.
**
** Author contact information:
**   drh@hwaci.com
**   http://www.hwaci.com/drh/
**
*************************************************************************
** This file contains the sqlite_get_table() and sqlite_free_table()
** interface routines.  These are just wrappers around the main
** interface routine of sqlite_exec().
**
** These routines are in a separate files so that they will not be linked
** if they are not used.
*/
#include <stdlib.h>
#include "sqlite.h"

/*
** This structure is used to pass data from sqlite_get_table() through

Changes to src/tokenize.c.

23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
..
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
*************************************************************************
** 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.15 2000/10/22 20:39:59 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 37
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.







|







 







|







23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
..
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
*************************************************************************
** 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.16 2000/12/10 18:23:51 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.

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
42
43
44
45
46
...
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
**
*************************************************************************
** Utility functions used throughout sqlite.
**
** This file contains functions for allocating memory, comparing
** strings, and stuff like that.
**
** $Id: util.c,v 1.16 2000/10/11 19:28:52 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










/*
** Allocate new memory and set it to zero.  Return NULL if
** no memory is available.
*/
void *sqliteMalloc_(int n, char *zFile, int line){
  void *p;
................................................................................
** Case is not significant.
*/
int sqliteHashNoCase(const char *z, int n){
  int h = 0;
  int c;
  if( n<=0 ) n = strlen(z);
  while( n-- > 0 && (c = *z++)!=0 ){
    h = h<<3 ^ h ^ UpperToLower[c];
  }
  if( h<0 ) h = -h;
  return h;
}

/*
** Some systems have stricmp().  Others have strcasecmp().  Because







|










>
>
>
>
>
>
>
>
>







 







|







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
...
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
**
*************************************************************************
** Utility functions used throughout sqlite.
**
** This file contains functions for allocating memory, comparing
** strings, and stuff like that.
**
** $Id: util.c,v 1.17 2000/12/10 18:23:51 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

/*
** For keeping track of the number of mallocs and frees.   This
** is used to check for memory leaks.
*/
int sqlite_nMalloc;         /* Number of sqliteMalloc() calls */
int sqlite_nFree;           /* Number of sqliteFree() calls */
int sqlite_iMallocFail;     /* Fail sqliteMalloc() after this many calls */


/*
** Allocate new memory and set it to zero.  Return NULL if
** no memory is available.
*/
void *sqliteMalloc_(int n, char *zFile, int line){
  void *p;
................................................................................
** Case is not significant.
*/
int sqliteHashNoCase(const char *z, int n){
  int h = 0;
  int c;
  if( n<=0 ) n = strlen(z);
  while( n-- > 0 && (c = *z++)!=0 ){
    h = (h<<3) ^ h ^ UpperToLower[c];
  }
  if( h<0 ) h = -h;
  return h;
}

/*
** Some systems have stricmp().  Others have strcasecmp().  Because

Changes to src/vdbe.c.

37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
...
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651








652
653
654
655
656
657
658
659
660
....
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
....
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
....
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
....
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
....
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
....
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
....
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
....
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
....
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
....
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
....
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
....
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
....
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
....
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
....
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
....
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
....
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
....
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
....
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
** 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.47 2000/10/23 13:16:33 drh Exp $
*/
#include "sqliteInt.h"
#include <unistd.h>
#include <ctype.h>

/*
** SQL is translated into a sequence of instructions to be
................................................................................
      sqliteFree(*pzStack);
    }
    pStack->flags = 0;
    *pzStack = 0;
    pStack--;
    pzStack--;
  }
#if 0  /* Older code was a little slower */
  while( p->tos>=0 && N-->0 ){
    int i = p->tos--;
    if( p->aStack[i].flags & STK_Dyn ){
      sqliteFree(p->zStack[i]);
    }
    p->aStack[i].flags = 0;
    p->zStack[i] = 0;
  }
#endif  








}

/*
** Make sure space has been allocated to hold at least N
** stack elements.  Allocate additional stack space if
** necessary.
**
** Return 0 on success and non-zero if there are memory
** allocation errors.
................................................................................
            case OP_Multiply:    b *= a;       break;
            default: {
              if( a==0.0 ) goto divide_by_zero;
              b /= a;
              break;
            }
          }
          PopStack(p, 1);
          Release(p, nos);
          aStack[nos].r = b;
          aStack[nos].flags = STK_Real;
        }
        break;

      divide_by_zero:
................................................................................
      ** false if it has zero length and true otherwise.
      */
      case OP_If: {
        int c;
        VERIFY( if( p->tos<0 ) goto not_enough_stack; )
        Integerify(p, p->tos);
        c = aStack[p->tos].i;
        PopStack(p, 1);
        if( c ) pc = pOp->p2-1;
        break;
      }

      /* Opcode: IsNull * P2 *
      **
      ** Pop a single value from the stack.  If the value popped is NULL
................................................................................
      ** then jump to p2.  Otherwise continue to the next 
      ** instruction.
      */
      case OP_IsNull: {
        int c;
        VERIFY( if( p->tos<0 ) goto not_enough_stack; )
        c = (aStack[p->tos].flags & STK_Null)!=0;
        PopStack(p, 1);
        if( c ) pc = pOp->p2-1;
        break;
      }

      /* Opcode: NotNull * P2 *
      **
      ** Pop a single value from the stack.  If the value popped is not an
................................................................................
      ** empty string, then jump to p2.  Otherwise continue to the next 
      ** instruction.
      */
      case OP_NotNull: {
        int c;
        VERIFY( if( p->tos<0 ) goto not_enough_stack; )
        c = (aStack[p->tos].flags & STK_Null)==0;
        PopStack(p, 1);
        if( c ) pc = pOp->p2-1;
        break;
      }

      /* Opcode: MakeRecord P1 * *
      **
      ** Convert the top P1 entries of the stack into a single entry
................................................................................
          }else{
            if( Stringify(p, tos) ) goto no_mem;
            pBe->Fetch(p->aCsr[i].pCursor, aStack[tos].n, 
                           zStack[tos]);
          }
          p->nFetch++;
        }
        PopStack(p, 1);
        break;
      }

      /* Opcode: Fcnt * * *
      **
      ** Push an integer onto the stack which is the total number of
      ** OP_Fetch opcodes that have been executed by this virtual machine.
................................................................................
        }
        if( pOp->opcode==OP_Found ){
          if( alreadyExists ) pc = pOp->p2 - 1;
        }else{
          if( !alreadyExists ) pc = pOp->p2 - 1;
        }
        if( pOp->opcode!=OP_Distinct ){
          PopStack(p, 1);
        }
        break;
      }

      /* Opcode: New P1 * *
      **
      ** Get a new integer key not previous used by the database file
................................................................................
          }else{
            if( Stringify(p, tos) ) goto no_mem;
            nKey = aStack[tos].n;
            zKey = zStack[tos];
          }
          pBe->Delete(p->aCsr[i].pCursor, nKey, zKey);
        }
        PopStack(p, 1);
        break;
      }

      /* Opcode: KeyAsData P1 P2 *
      **
      ** Turn the key-as-data mode for cursor P1 either on (if P2==1) or
      ** off (if P2==0).  In key-as-data mode, the OP_Field opcode pulls
................................................................................
              aStack[tos].flags = STK_Int;
              break;
            }
          }
          if( j>=k ){
            j = -1;
            pc = pOp->p2 - 1;
            PopStack(p, 1);
          }
          p->aCsr[i].index = j+1;
        }
        break;
      }

      /* Opcode: PutIdx P1 * *
................................................................................
        int i = pOp->p1;
        VERIFY( if( i<0 ) goto bad_instruction; )
        VERIFY( if( p->tos<0 ) goto not_enough_stack; )
        if( VERIFY( i<p->nList && ) p->apList[i]!=0 ){
          int val;
          Integerify(p, p->tos);
          val = aStack[p->tos].i;
          PopStack(p, 1);
          fwrite(&val, sizeof(int), 1, p->apList[i]);
        }
        break;
      }

      /* Opcode: ListRewind P1 * *
      **
................................................................................
        int i = p->tos;
        VERIFY( if( i<0 ) goto not_enough_stack; )
        if( xCallback!=0 ){
          if( xCallback(pArg, pOp->p1, (char**)zStack[i], p->azColName) ){
            rc = SQLITE_ABORT;
          }
        }
        PopStack(p, 1);
        break;
      }

      /* Opcode: SortClose P1 * *
      **
      ** Close the given sorter and remove all its elements.
      */
................................................................................
        }
        pMem->s = aStack[tos];
        if( pMem->s.flags & STK_Str ){
          pMem->z = sqliteStrNDup(zStack[tos], pMem->s.n);
          pMem->s.flags |= STK_Dyn;
        }
        if( zOld ) sqliteFree(zOld);
        PopStack(p, 1);
        break;
      }

      /* Opcode: MemLoad P1 * *
      **
      ** Push a copy of the value in memory location P1 onto the stack.
      */
................................................................................
        }
        if( pElem ){
          p->agg.pCurrent = pElem;
          pc = pOp->p2 - 1;
        }else{
          AggInsert(&p->agg, zKey);
        }
        PopStack(p, 1);
        break; 
      }

      /* Opcode: AggIncr P1 P2 *
      **
      ** Increase the integer value in the P2-th field of the aggregate
      ** element current in focus by an amount P1.
................................................................................
            pMem->z = sqliteMalloc( aStack[tos].n );
            if( pMem->z==0 ) goto no_mem;
            memcpy(pMem->z, zStack[tos], pMem->s.n);
            pMem->s.flags |= STK_Str|STK_Dyn;
          }
          if( zOld ) sqliteFree(zOld);
        }
        PopStack(p, 1);
        break;
      }

      /* Opcode: AggGet * P2 *
      **
      ** Push a new entry onto the stack which is a copy of the P2-th field
      ** of the current aggregate.  Strings are not duplicated so
................................................................................
        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(p, 1);
        }
        break;
      }

      /* Opcode: SetFound P1 P2 *
      **
      ** Pop the stack once and compare the value popped off with the
................................................................................
        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(p, 1);
        break;
      }

      /* Opcode: SetNotFound P1 P2 *
      **
      ** Pop the stack once and compare the value popped off with the
      ** contents of set P1.  If the element popped does not exists in 
................................................................................
        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(p, 1);
        break;
      }

      /* Opcode: Length * * *
      **
      ** 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);
        len = aStack[tos].n-1;
        PopStack(p, 1);
        p->tos++;
        aStack[tos].i = len;
        aStack[tos].flags = STK_Int;
        break;
      }

      /* Opcode: Substr P1 P2 *
................................................................................
        int n;
        char *z;

        if( pOp->p2==0 ){
          VERIFY( if( p->tos<0 ) goto not_enough_stack; )
          Integerify(p, p->tos);
          cnt = aStack[p->tos].i;
          PopStack(p, 1);
        }else{
          cnt = pOp->p2;
        }
        if( pOp->p1==0 ){
          VERIFY( if( p->tos<0 ) goto not_enough_stack; )
          Integerify(p, p->tos);
          start = aStack[p->tos].i - 1;
          PopStack(p, 1);
        }else{
          start = pOp->p1 - 1;
        }
        VERIFY( if( p->tos<0 ) goto not_enough_stack; )
        Stringify(p, p->tos);
        n = aStack[p->tos].n - 1;
        if( start<0 ){
................................................................................
        if( cnt > n ){
          cnt = n;
        }
        z = sqliteMalloc( cnt+1 );
        if( z==0 ) goto no_mem;
        strncpy(z, &zStack[p->tos][start], cnt);
        z[cnt] = 0;
        PopStack(p, 1);
        p->tos++;
        zStack[p->tos] = z;
        aStack[p->tos].n = cnt + 1;
        aStack[p->tos].flags = STK_Str|STK_Dyn;
        break;
      }








|







 







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







 







|







 







|







 







|







 







|







 







|







 







|







 







|







 







|







 







|







 







|







 







|







 







|







 







|







 







|







 







|







 







|







 







|







 







|







|







 







|







37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
...
635
636
637
638
639
640
641





642


643

644
645
646
647
648
649
650
651
652

653
654
655
656
657
658
659
....
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
....
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
....
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
....
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
....
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
....
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
....
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
....
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
....
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
....
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
....
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
....
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
....
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
....
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
....
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
....
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
....
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
....
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
....
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
** 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.48 2000/12/10 18:23:51 drh Exp $
*/
#include "sqliteInt.h"
#include <unistd.h>
#include <ctype.h>

/*
** SQL is translated into a sequence of instructions to be
................................................................................
      sqliteFree(*pzStack);
    }
    pStack->flags = 0;
    *pzStack = 0;
    pStack--;
    pzStack--;
  }





}




/*
** Here is a macro to handle the common case of popping the stack
** once.  This macro only works from within the sqliteVdbeExec()
** function.
*/
#define POPSTACK \
 if( aStack[p->tos].flags & STK_Dyn ) sqliteFree(zStack[p->tos]); \
 p->tos--;


/*
** Make sure space has been allocated to hold at least N
** stack elements.  Allocate additional stack space if
** necessary.
**
** Return 0 on success and non-zero if there are memory
** allocation errors.
................................................................................
            case OP_Multiply:    b *= a;       break;
            default: {
              if( a==0.0 ) goto divide_by_zero;
              b /= a;
              break;
            }
          }
          POPSTACK;
          Release(p, nos);
          aStack[nos].r = b;
          aStack[nos].flags = STK_Real;
        }
        break;

      divide_by_zero:
................................................................................
      ** false if it has zero length and true otherwise.
      */
      case OP_If: {
        int c;
        VERIFY( if( p->tos<0 ) goto not_enough_stack; )
        Integerify(p, p->tos);
        c = aStack[p->tos].i;
        POPSTACK;
        if( c ) pc = pOp->p2-1;
        break;
      }

      /* Opcode: IsNull * P2 *
      **
      ** Pop a single value from the stack.  If the value popped is NULL
................................................................................
      ** then jump to p2.  Otherwise continue to the next 
      ** instruction.
      */
      case OP_IsNull: {
        int c;
        VERIFY( if( p->tos<0 ) goto not_enough_stack; )
        c = (aStack[p->tos].flags & STK_Null)!=0;
        POPSTACK;
        if( c ) pc = pOp->p2-1;
        break;
      }

      /* Opcode: NotNull * P2 *
      **
      ** Pop a single value from the stack.  If the value popped is not an
................................................................................
      ** empty string, then jump to p2.  Otherwise continue to the next 
      ** instruction.
      */
      case OP_NotNull: {
        int c;
        VERIFY( if( p->tos<0 ) goto not_enough_stack; )
        c = (aStack[p->tos].flags & STK_Null)==0;
        POPSTACK;
        if( c ) pc = pOp->p2-1;
        break;
      }

      /* Opcode: MakeRecord P1 * *
      **
      ** Convert the top P1 entries of the stack into a single entry
................................................................................
          }else{
            if( Stringify(p, tos) ) goto no_mem;
            pBe->Fetch(p->aCsr[i].pCursor, aStack[tos].n, 
                           zStack[tos]);
          }
          p->nFetch++;
        }
        POPSTACK;
        break;
      }

      /* Opcode: Fcnt * * *
      **
      ** Push an integer onto the stack which is the total number of
      ** OP_Fetch opcodes that have been executed by this virtual machine.
................................................................................
        }
        if( pOp->opcode==OP_Found ){
          if( alreadyExists ) pc = pOp->p2 - 1;
        }else{
          if( !alreadyExists ) pc = pOp->p2 - 1;
        }
        if( pOp->opcode!=OP_Distinct ){
          POPSTACK;
        }
        break;
      }

      /* Opcode: New P1 * *
      **
      ** Get a new integer key not previous used by the database file
................................................................................
          }else{
            if( Stringify(p, tos) ) goto no_mem;
            nKey = aStack[tos].n;
            zKey = zStack[tos];
          }
          pBe->Delete(p->aCsr[i].pCursor, nKey, zKey);
        }
        POPSTACK;
        break;
      }

      /* Opcode: KeyAsData P1 P2 *
      **
      ** Turn the key-as-data mode for cursor P1 either on (if P2==1) or
      ** off (if P2==0).  In key-as-data mode, the OP_Field opcode pulls
................................................................................
              aStack[tos].flags = STK_Int;
              break;
            }
          }
          if( j>=k ){
            j = -1;
            pc = pOp->p2 - 1;
            POPSTACK;
          }
          p->aCsr[i].index = j+1;
        }
        break;
      }

      /* Opcode: PutIdx P1 * *
................................................................................
        int i = pOp->p1;
        VERIFY( if( i<0 ) goto bad_instruction; )
        VERIFY( if( p->tos<0 ) goto not_enough_stack; )
        if( VERIFY( i<p->nList && ) p->apList[i]!=0 ){
          int val;
          Integerify(p, p->tos);
          val = aStack[p->tos].i;
          POPSTACK;
          fwrite(&val, sizeof(int), 1, p->apList[i]);
        }
        break;
      }

      /* Opcode: ListRewind P1 * *
      **
................................................................................
        int i = p->tos;
        VERIFY( if( i<0 ) goto not_enough_stack; )
        if( xCallback!=0 ){
          if( xCallback(pArg, pOp->p1, (char**)zStack[i], p->azColName) ){
            rc = SQLITE_ABORT;
          }
        }
        POPSTACK;
        break;
      }

      /* Opcode: SortClose P1 * *
      **
      ** Close the given sorter and remove all its elements.
      */
................................................................................
        }
        pMem->s = aStack[tos];
        if( pMem->s.flags & STK_Str ){
          pMem->z = sqliteStrNDup(zStack[tos], pMem->s.n);
          pMem->s.flags |= STK_Dyn;
        }
        if( zOld ) sqliteFree(zOld);
        POPSTACK;
        break;
      }

      /* Opcode: MemLoad P1 * *
      **
      ** Push a copy of the value in memory location P1 onto the stack.
      */
................................................................................
        }
        if( pElem ){
          p->agg.pCurrent = pElem;
          pc = pOp->p2 - 1;
        }else{
          AggInsert(&p->agg, zKey);
        }
        POPSTACK;
        break; 
      }

      /* Opcode: AggIncr P1 P2 *
      **
      ** Increase the integer value in the P2-th field of the aggregate
      ** element current in focus by an amount P1.
................................................................................
            pMem->z = sqliteMalloc( aStack[tos].n );
            if( pMem->z==0 ) goto no_mem;
            memcpy(pMem->z, zStack[tos], pMem->s.n);
            pMem->s.flags |= STK_Str|STK_Dyn;
          }
          if( zOld ) sqliteFree(zOld);
        }
        POPSTACK;
        break;
      }

      /* Opcode: AggGet * P2 *
      **
      ** Push a new entry onto the stack which is a copy of the P2-th field
      ** of the current aggregate.  Strings are not duplicated so
................................................................................
        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
................................................................................
        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;
      }

      /* Opcode: SetNotFound P1 P2 *
      **
      ** Pop the stack once and compare the value popped off with the
      ** contents of set P1.  If the element popped does not exists in 
................................................................................
        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;
      }

      /* Opcode: Length * * *
      **
      ** 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);
        len = aStack[tos].n-1;
        POPSTACK;
        p->tos++;
        aStack[tos].i = len;
        aStack[tos].flags = STK_Int;
        break;
      }

      /* Opcode: Substr P1 P2 *
................................................................................
        int n;
        char *z;

        if( pOp->p2==0 ){
          VERIFY( if( p->tos<0 ) goto not_enough_stack; )
          Integerify(p, p->tos);
          cnt = aStack[p->tos].i;
          POPSTACK;
        }else{
          cnt = pOp->p2;
        }
        if( pOp->p1==0 ){
          VERIFY( if( p->tos<0 ) goto not_enough_stack; )
          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 = aStack[p->tos].n - 1;
        if( start<0 ){
................................................................................
        if( cnt > n ){
          cnt = n;
        }
        z = sqliteMalloc( cnt+1 );
        if( z==0 ) goto no_mem;
        strncpy(z, &zStack[p->tos][start], cnt);
        z[cnt] = 0;
        POPSTACK;
        p->tos++;
        zStack[p->tos] = z;
        aStack[p->tos].n = cnt + 1;
        aStack[p->tos].flags = STK_Str|STK_Dyn;
        break;
      }

Changes to test/all.test.

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







43
44
45
46
47
48
49
50
51





















52
53
54
# Author contact information:
#   drh@hwaci.com
#   http://www.hwaci.com/drh/
#
#***********************************************************************
# This file runs all tests.
#
# $Id: all.test,v 1.4 2000/10/19 14:21:43 drh Exp $

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

if {[file exists ./sqlite_test_count]} {
  set COUNT [exec cat ./sqlite_test_count]
} else {
  set COUNT 1
}

if {[file exists ./sqlite_test_prefixes]} {
  set PREFIXES [exec cat ./sqlite_test_prefixes]
} else {
  set PREFIXES {memory: gdbm:}
}








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
    }
  }





















}

really_finish_test







|




|




|







>
>
>
>
>
>
>









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



18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
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]} {
  set COUNT [exec cat ./sqlite_test_count]
} else {
  set COUNT 4
}

if {[file exists ./sqlite_test_prefixes]} {
  set PREFIXES [exec cat ./sqlite_test_prefixes]
} else {
  set PREFIXES {memory: gdbm:}
}

# LeakList will hold a list of the number of unfreed mallocs after
# each round of the test.  This number should be constant.  If it
# grows, it may mean there is a memory leak in the library.
#
set LeakList {}


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
  }
}

# Do one last test to look for a memory leak in the library.  This will
# only work if SQLite is compiled with the -DMEMORY_DEBUG=1 flag.
#
if {$LeakList!=""} {
  puts -nonewline memory-leak-test...
  incr ::nTest
  foreach x $LeakList {
    if {$x!=[lindex $LeakList 0]} {
       puts " failed!"
       puts "Expected: all values to be the same"
       puts "     Got: $LeakList"
       incr ::nErr
       break
    }
  }
  puts " Ok"
}

really_finish_test

Changes to test/main.test.

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




























50
51
52
53
54
55
56
#   drh@hwaci.com
#   http://www.hwaci.com/drh/
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is exercising the code in main.c.
#
# $Id: main.test,v 1.3 2000/06/16 20:51:26 drh Exp $

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

# Tests of the sqlite_complete() function.
#
do_test main-1.1 {
................................................................................
  }
} {0}
do_test main-1.4 {
  db complete {
     -- a comment ;
     ;
  }




























} {1}

# Try to open a database with a corrupt master file.
#
do_test main-2.0 {
  catch {db close}
  file delete -force testdb







|







 







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







19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
..
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#   drh@hwaci.com
#   http://www.hwaci.com/drh/
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is exercising the code in main.c.
#
# $Id: main.test,v 1.4 2000/12/10 18:23:52 drh Exp $

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

# Tests of the sqlite_complete() function.
#
do_test main-1.1 {
................................................................................
  }
} {0}
do_test main-1.4 {
  db complete {
     -- a comment ;
     ;
  }
} {1}
do_test main-1.5 {
  db complete {DROP TABLE 'xyz;}
} {0}
do_test main-1.6 {
  db complete {DROP TABLE 'xyz';}
} {1}
do_test main-1.7 {
  db complete {DROP TABLE "xyz;}
} {0}
do_test main-1.8 {
  db complete {DROP TABLE "xyz';}
} {0}
do_test main-1.9 {
  db complete {DROP TABLE "xyz";}
} {1}
do_test main-1.10 {
  db complete {DROP TABLE xyz; hi}
} {0}
do_test main-1.11 {
  db complete {DROP TABLE xyz; }
} {1}
do_test main-1.12 {
  db complete {DROP TABLE xyz; -- hi }
} {1}
do_test main-1.13 {
  db complete {DROP TABLE xyz; -- hi
  }
} {1}

# Try to open a database with a corrupt master file.
#
do_test main-2.0 {
  catch {db close}
  file delete -force testdb

Changes to test/tester.tcl.

19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
...
107
108
109
110
111
112
113














114
115
116
117
118

119
120
121
122
123
124
125
#   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.7 2000/10/19 14:10:09 drh Exp $

# Create a test database
#
if {![info exists dbprefix]} {
  if {[info exists env(SQLITE_PREFIX)]} {
    set dbprefix $env(SQLITE_PREFIX):
  } else {
................................................................................
    if {$::dbprefix==$a} {
      set ::skip_test 0
      return
    }
  }
  set ::skip_test 1
}















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

  catch {db close}
  puts "$nErr errors out of $nTest tests"
  exit $nErr
}

# A procedure to execute SQL
#







|







 







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





>







19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
...
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
#   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.8 2000/12/10 18:23:52 drh Exp $

# Create a test database
#
if {![info exists dbprefix]} {
  if {[info exists env(SQLITE_PREFIX)]} {
    set dbprefix $env(SQLITE_PREFIX):
  } else {
................................................................................
    if {$::dbprefix==$a} {
      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
  memleak_check
  catch {db close}
  puts "$nErr errors out of $nTest tests"
  exit $nErr
}

# A procedure to execute SQL
#

Changes to www/changes.tcl.

12
13
14
15
16
17
18










19
20
21
22
23
24
25
..
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
}


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











chng {2000 Oct 23 (1.0.15)} {
<li>Documentation updates</li>
<li>Some sanity checking code was removed from the inner loop of vdbe.c
    to help the library to run a little faster.  The code is only
    removed if you compile with -DNDEBUG.</li>
}
................................................................................
    in-memory hash table.</li>
}

chng {2000 Oct 18 (1.0.13)} {
<li>Break out the GDBM driver into a separate file in anticipation
    to added new drivers.</li>
<li>Allow the name of a database to be prefixed by the driver type.
    For now, the only driver type is "gdbm:".<li>
}

chng {2000 Oct 16 (1.0.12)} {
<li>Fixed an off-by-one error that was causing a coredump in 
    the '%q' format directive of the new
    <b>sqlite_..._printf()</b> routines.</li>
<li>Added the <b>sqlite_interrupt()</b> interface.</li>







>
>
>
>
>
>
>
>
>
>







 







|







12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
..
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
}


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

chng {2000 Dec 10 (1.0.17)} {
<li>Rewrote <b>sqlite_complete()</b> to make it faster.</li>
<li>Minor tweaks to other code to make it run a little faster.</li>
<li>Added new tests for <b>sqlite_complete()</b> and for memory leaks.</li>
}

chng {2000 Dec 4 (1.0.16)} {
<li>Documentation updates.  Mostly fixing of typos and spelling errors.</li>
}

chng {2000 Oct 23 (1.0.15)} {
<li>Documentation updates</li>
<li>Some sanity checking code was removed from the inner loop of vdbe.c
    to help the library to run a little faster.  The code is only
    removed if you compile with -DNDEBUG.</li>
}
................................................................................
    in-memory hash table.</li>
}

chng {2000 Oct 18 (1.0.13)} {
<li>Break out the GDBM driver into a separate file in anticipation
    to added new drivers.</li>
<li>Allow the name of a database to be prefixed by the driver type.
    For now, the only driver type is "gdbm:".</li>
}

chng {2000 Oct 16 (1.0.12)} {
<li>Fixed an off-by-one error that was causing a coredump in 
    the '%q' format directive of the new
    <b>sqlite_..._printf()</b> routines.</li>
<li>Added the <b>sqlite_interrupt()</b> interface.</li>