/ Check-in [c82033fa]
Login
SQLite training in Houston TX on 2019-11-05 (details)
Part of the 2019 Tcl Conference

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

Overview
Comment:Improved test coverage for the tokenizer and sqlite3_complete() interface. Fix bugs in parsing blob literals and SQL variables beginning with $. (CVS 4743)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: c82033faf8bdb83ce43f0dd1611408e7796d53de
User & Date: drh 2008-01-22 23:37:10
Context
2008-01-23
03:03
Make sqlite3SafetyOn() and sqlite3SafetyOff() macros which disappear when compiling without -DSQLITE_DEBUG=1. (CVS 4744) check-in: 5375ad6b user: drh tags: trunk
2008-01-22
23:37
Improved test coverage for the tokenizer and sqlite3_complete() interface. Fix bugs in parsing blob literals and SQL variables beginning with $. (CVS 4743) check-in: c82033fa user: drh tags: trunk
21:30
Add the fault injector module in fault.c. Use it as a basis for memory allocation failure testing. (CVS 4742) check-in: 1a335e18 user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/parse.y.

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
..
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
**
*************************************************************************
** 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.239 2008/01/22 14:50:17 drh Exp $
*/

// All token codes are small integers with #defines that begin with "TK_"
%token_prefix TK_

// The type of the data attached to each token is Token.  This is also the
// default type for non-terminals.
................................................................................

// The generated parser function takes a 4th argument as follows:
%extra_argument {Parse *pParse}

// This code runs whenever there is a syntax error
//
%syntax_error {
  if( !pParse->parseError ){
    assert( TOKEN.z[0] );  /* The tokenizer always gives us a token */
    sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", &TOKEN);
    pParse->parseError = 1;
  }
}
%stack_overflow {
  sqlite3ErrorMsg(pParse, "parser stack overflow");
  pParse->parseError = 1;
}

// The name of the generated procedure that implements the parser







|







 







<
|
|
|
<







10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
..
28
29
30
31
32
33
34

35
36
37

38
39
40
41
42
43
44
**
*************************************************************************
** 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.240 2008/01/22 23:37:10 drh Exp $
*/

// All token codes are small integers with #defines that begin with "TK_"
%token_prefix TK_

// The type of the data attached to each token is Token.  This is also the
// default type for non-terminals.
................................................................................

// The generated parser function takes a 4th argument as follows:
%extra_argument {Parse *pParse}

// This code runs whenever there is a syntax error
//
%syntax_error {

  assert( TOKEN.z[0] );  /* The tokenizer always gives us a token */
  sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", &TOKEN);
  pParse->parseError = 1;

}
%stack_overflow {
  sqlite3ErrorMsg(pParse, "parser stack overflow");
  pParse->parseError = 1;
}

// The name of the generated procedure that implements the parser

Changes to src/test_config.c.

12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
...
364
365
366
367
368
369
370

371
372

373
374
375
376
377
378
379
** 
** This file contains code used for testing the SQLite system.
** None of the code in this file goes into a deliverable build.
** 
** The focus of this file is providing the TCL testing layer
** access to compile-time constants.
**
** $Id: test_config.c,v 1.17 2008/01/22 21:30:53 drh Exp $
*/

#include "sqliteLimit.h"

int sqlite3MAX_LENGTH = SQLITE_MAX_LENGTH;
int sqlite3MAX_COLUMN = SQLITE_MAX_COLUMN;
int sqlite3MAX_SQL_LENGTH = SQLITE_MAX_SQL_LENGTH;
................................................................................
  Tcl_SetVar2(interp, "sqlite_options", "tclvar", "0", TCL_GLOBAL_ONLY);
#else
  Tcl_SetVar2(interp, "sqlite_options", "tclvar", "1", TCL_GLOBAL_ONLY);
#endif

#if SQLITE_THREADSAFE
  Tcl_SetVar2(interp, "sqlite_options", "threadsafe", "1", TCL_GLOBAL_ONLY);

#else
  Tcl_SetVar2(interp, "sqlite_options", "threadsafe", "0", TCL_GLOBAL_ONLY);

#endif

#ifdef SQLITE_OMIT_TRACE
  Tcl_SetVar2(interp, "sqlite_options", "trace", "0", TCL_GLOBAL_ONLY);
#else
  Tcl_SetVar2(interp, "sqlite_options", "trace", "1", TCL_GLOBAL_ONLY);
#endif







|







 







>


>







12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
...
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
** 
** This file contains code used for testing the SQLite system.
** None of the code in this file goes into a deliverable build.
** 
** The focus of this file is providing the TCL testing layer
** access to compile-time constants.
**
** $Id: test_config.c,v 1.18 2008/01/22 23:37:10 drh Exp $
*/

#include "sqliteLimit.h"

int sqlite3MAX_LENGTH = SQLITE_MAX_LENGTH;
int sqlite3MAX_COLUMN = SQLITE_MAX_COLUMN;
int sqlite3MAX_SQL_LENGTH = SQLITE_MAX_SQL_LENGTH;
................................................................................
  Tcl_SetVar2(interp, "sqlite_options", "tclvar", "0", TCL_GLOBAL_ONLY);
#else
  Tcl_SetVar2(interp, "sqlite_options", "tclvar", "1", TCL_GLOBAL_ONLY);
#endif

#if SQLITE_THREADSAFE
  Tcl_SetVar2(interp, "sqlite_options", "threadsafe", "1", TCL_GLOBAL_ONLY);
  assert( sqlite3_threadsafe() );
#else
  Tcl_SetVar2(interp, "sqlite_options", "threadsafe", "0", TCL_GLOBAL_ONLY);
  assert( !sqlite3_threadsafe() );
#endif

#ifdef SQLITE_OMIT_TRACE
  Tcl_SetVar2(interp, "sqlite_options", "trace", "0", TCL_GLOBAL_ONLY);
#else
  Tcl_SetVar2(interp, "sqlite_options", "trace", "1", TCL_GLOBAL_ONLY);
#endif

Changes to src/tokenize.c.

11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
...
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
...
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
...
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
*************************************************************************
** 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.137 2007/12/17 16:20:07 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
#include <stdlib.h>

/*
** The charMap() macro maps alphabetic characters into their
................................................................................
        *tokenType = TK_ILLEGAL;
        i++;
      }
      return i;
    }
    case '[': {
      for(i=1, c=z[0]; c!=']' && (c=z[i])!=0; i++){}
      *tokenType = TK_ID;
      return i;
    }
    case '?': {
      *tokenType = TK_VARIABLE;
      for(i=1; isdigit(z[i]); i++){}
      return i;
    }
................................................................................
        }
      }
      if( n==0 ) *tokenType = TK_ILLEGAL;
      return i;
    }
#ifndef SQLITE_OMIT_BLOB_LITERAL
    case 'x': case 'X': {
      if( (c=z[1])=='\'' || c=='"' ){
        int delim = c;
        *tokenType = TK_BLOB;
        for(i=2; (c=z[i])!=0; i++){
          if( c==delim ){
            if( i%2 ) *tokenType = TK_ILLEGAL;
            break;
          }
          if( !isxdigit(c) ){
            *tokenType = TK_ILLEGAL;
            return i;
          }
        }

        if( c ) i++;
        return i;
      }
      /* Otherwise fall through to the next case */
    }
#endif
    default: {
................................................................................
  if( pParse->zErrMsg ){
    if( pzErrMsg && *pzErrMsg==0 ){
      *pzErrMsg = pParse->zErrMsg;
    }else{
      sqlite3_free(pParse->zErrMsg);
    }
    pParse->zErrMsg = 0;
    if( !nErr ) nErr++;
  }
  if( pParse->pVdbe && pParse->nErr>0 && pParse->nested==0 ){
    sqlite3VdbeDelete(pParse->pVdbe);
    pParse->pVdbe = 0;
  }
#ifndef SQLITE_OMIT_SHARED_CACHE
  if( pParse->nested==0 ){







|







 







|







 







|
<

|
<
<
<
<


<


>







 







|







11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
...
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
...
340
341
342
343
344
345
346
347

348
349




350
351

352
353
354
355
356
357
358
359
360
361
...
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
*************************************************************************
** 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.138 2008/01/22 23:37:10 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
#include <stdlib.h>

/*
** The charMap() macro maps alphabetic characters into their
................................................................................
        *tokenType = TK_ILLEGAL;
        i++;
      }
      return i;
    }
    case '[': {
      for(i=1, c=z[0]; c!=']' && (c=z[i])!=0; i++){}
      *tokenType = c==']' ? TK_ID : TK_ILLEGAL;
      return i;
    }
    case '?': {
      *tokenType = TK_VARIABLE;
      for(i=1; isdigit(z[i]); i++){}
      return i;
    }
................................................................................
        }
      }
      if( n==0 ) *tokenType = TK_ILLEGAL;
      return i;
    }
#ifndef SQLITE_OMIT_BLOB_LITERAL
    case 'x': case 'X': {
      if( z[1]=='\'' ){

        *tokenType = TK_BLOB;
        for(i=2; (c=z[i])!=0 && c!='\''; i++){




          if( !isxdigit(c) ){
            *tokenType = TK_ILLEGAL;

          }
        }
        if( i%2 || !c ) *tokenType = TK_ILLEGAL;
        if( c ) i++;
        return i;
      }
      /* Otherwise fall through to the next case */
    }
#endif
    default: {
................................................................................
  if( pParse->zErrMsg ){
    if( pzErrMsg && *pzErrMsg==0 ){
      *pzErrMsg = pParse->zErrMsg;
    }else{
      sqlite3_free(pParse->zErrMsg);
    }
    pParse->zErrMsg = 0;
    nErr++;
  }
  if( pParse->pVdbe && pParse->nErr>0 && pParse->nested==0 ){
    sqlite3VdbeDelete(pParse->pVdbe);
    pParse->pVdbe = 0;
  }
#ifndef SQLITE_OMIT_SHARED_CACHE
  if( pParse->nested==0 ){

Changes to test/blob.test.

6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
..
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.
#
# $Id: blob.test,v 1.5 2006/01/03 00:33:50 drh Exp $

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

ifcapable {!bloblit} {
  finish_test
  return
................................................................................
  set blob [execsql {SELECT x'abcdEF12';}]
  bin_to_hex [lindex $blob 0]
} {ABCDEF12}

# Try some syntax errors in blob literals.
do_test blob-1.4 {
  catchsql {SELECT X'01020k304', 100}
} {1 {unrecognized token: "X'01020"}}
do_test blob-1.5 {
  catchsql {SELECT X'01020, 100}
} {1 {unrecognized token: "X'01020"}}
do_test blob-1.6 {
  catchsql {SELECT X'01020 100'}
} {1 {unrecognized token: "X'01020"}}
do_test blob-1.7 {
  catchsql {SELECT X'01001'}
} {1 {unrecognized token: "X'01001'"}}

# Insert a blob into a table and retrieve it.
do_test blob-2.0 {
  execsql {







|







 







|


|


|







6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
..
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.
#
# $Id: blob.test,v 1.6 2008/01/22 23:37:10 drh Exp $

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

ifcapable {!bloblit} {
  finish_test
  return
................................................................................
  set blob [execsql {SELECT x'abcdEF12';}]
  bin_to_hex [lindex $blob 0]
} {ABCDEF12}

# Try some syntax errors in blob literals.
do_test blob-1.4 {
  catchsql {SELECT X'01020k304', 100}
} {1 {unrecognized token: "X'01020k304'"}}
do_test blob-1.5 {
  catchsql {SELECT X'01020, 100}
} {1 {unrecognized token: "X'01020, 100"}}
do_test blob-1.6 {
  catchsql {SELECT X'01020 100'}
} {1 {unrecognized token: "X'01020 100'"}}
do_test blob-1.7 {
  catchsql {SELECT X'01001'}
} {1 {unrecognized token: "X'01001'"}}

# Insert a blob into a table and retrieve it.
do_test blob-2.0 {
  execsql {

Changes to test/main.test.

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
...
190
191
192
193
194
195
196



197
198
199
200
201
202
203
...
238
239
240
241
242
243
244






245
246












247
248
249
250
251
252
253
...
278
279
280
281
282
283
284










































































































285
286
287
288
289
290
291
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is exercising the code in main.c.
#
# $Id: main.test,v 1.27 2007/09/03 15:42:48 drh Exp $

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

# Only do the next group of tests if the sqlite3_complete API is available
#
ifcapable {complete} {
................................................................................
      CREATE TRIGGER xyz AFTER DELETE [;end;] BEGIN
         UPDATE pqr;
    }
  } {0}
  do_test main-1.25 {
    db complete {
      CREATE TRIGGER xyz AFTER DELETE backend BEGIN
         UPDATE pqr SET a=[;end;];;;
    }
  } {0}
  do_test main-1.26 {
    db complete {
      CREATE -- a comment
      TRIGGER xyz AFTER DELETE backend BEGIN
         UPDATE pqr SET a=5;
    }
  } {0}
  do_test main-1.27.1 {
    db complete {
      CREATE -- a comment
      TRIGGERX xyz AFTER DELETE backend BEGIN
         UPDATE pqr SET a=5;
    }
  } {1}
  do_test main-1.27.2 {
    db complete {
      CREATE/**/TRIGGER xyz AFTER DELETE backend BEGIN
         UPDATE pqr SET a=5;
    }
  } {0}
  ifcapable {explain} {
    do_test main-1.27.3 {
      db complete {
        /* */ EXPLAIN -- A comment
        CREATE/**/TRIGGER xyz AFTER DELETE backend BEGIN
           UPDATE pqr SET a=5;
      }
    } {0}
  }
  do_test main-1.27.4 {
    db complete {
      BOGUS token
................................................................................
  do_test main-1.29 {
    db complete {
      CREATE TRIGGER xyz AFTER DELETE backend BEGIN
         UPDATE pqr SET a=5;
         EXPLAIN select * from xyz;
    }
  } {0}



}
do_test main-1.30 {
  db complete {
     CREATE TABLE /* In comment ; */
  }
} {0}
do_test main-1.31 {
................................................................................
} {1}
do_test main-1.35 {
  db complete {hi /**/ there;}
} {1}
do_test main-1.36 {
  db complete {hi there/***/;}
} {1}







} ;# end ifcapable {complete}














# Try to open a database with a corrupt database file.
#
do_test main-2.0 {
  catch {db close}
  file delete -force test.db
................................................................................
} {1 {unrecognized token: "^"}}
do_test main-3.2.2 {
  catchsql {select 'abc}
} {1 {unrecognized token: "'abc"}}
do_test main-3.2.3 {
  catchsql {select "abc}
} {1 {unrecognized token: ""abc"}}











































































































do_test main-3.3 {
  catch {db close}
  foreach f [glob -nocomplain testdb/*] {file delete -force $f}
  file delete -force testdb
  sqlite3 db testdb
  execsql {







|







 







|





|






|





|







|







 







>
>
>







 







>
>
>
>
>
>

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







 







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







7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
...
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
...
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
...
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
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
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is exercising the code in main.c.
#
# $Id: main.test,v 1.28 2008/01/22 23:37:10 drh Exp $

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

# Only do the next group of tests if the sqlite3_complete API is available
#
ifcapable {complete} {
................................................................................
      CREATE TRIGGER xyz AFTER DELETE [;end;] BEGIN
         UPDATE pqr;
    }
  } {0}
  do_test main-1.25 {
    db complete {
      CREATE TRIGGER xyz AFTER DELETE backend BEGIN
         UPDATE cantor SET a=[;end;];;;
    }
  } {0}
  do_test main-1.26 {
    db complete {
      CREATE -- a comment
      TRIGGER exy AFTER DELETE backend BEGIN
         UPDATE pqr SET a=5;
    }
  } {0}
  do_test main-1.27.1 {
    db complete {
      CREATE -- a comment
      TRIGGERX tangentxx AFTER DELETE backend BEGIN
         UPDATE pqr SET a=5;
    }
  } {1}
  do_test main-1.27.2 {
    db complete {
      CREATE/**/TRIGGER tiger00 AFTER DELETE backend BEGIN
         UPDATE pqr SET a=5;
    }
  } {0}
  ifcapable {explain} {
    do_test main-1.27.3 {
      db complete {
        /* */ EXPLAIN -- A comment
        CREATE/**/TRIGGER ezxyz12 AFTER DELETE backend BEGIN
           UPDATE pqr SET a=5;
      }
    } {0}
  }
  do_test main-1.27.4 {
    db complete {
      BOGUS token
................................................................................
  do_test main-1.29 {
    db complete {
      CREATE TRIGGER xyz AFTER DELETE backend BEGIN
         UPDATE pqr SET a=5;
         EXPLAIN select * from xyz;
    }
  } {0}

} ;# end ifcapable {complete}

}
do_test main-1.30 {
  db complete {
     CREATE TABLE /* In comment ; */
  }
} {0}
do_test main-1.31 {
................................................................................
} {1}
do_test main-1.35 {
  db complete {hi /**/ there;}
} {1}
do_test main-1.36 {
  db complete {hi there/***/;}
} {1}
do_test main-1.37 {
  db complete {hi there/**}
} {0}
do_test main-1.38 {
  db complete {hi [there}
} {0}

ifcapable {trigger} {
  # Characters less than \040 can never be part of an identifier.
  # Characters greater than \u177 are always identifier characters.
  do_test main-1.100 {
    db complete "create \037\036\035\034trigger\001\002;"
  } {1}
  do_test main-1.101 {
    db complete "create trigger\200;"
  } {1}
  do_test main-1.102 {
    db complete "create \200trigger;"
  } {1}
}


# Try to open a database with a corrupt database file.
#
do_test main-2.0 {
  catch {db close}
  file delete -force test.db
................................................................................
} {1 {unrecognized token: "^"}}
do_test main-3.2.2 {
  catchsql {select 'abc}
} {1 {unrecognized token: "'abc"}}
do_test main-3.2.3 {
  catchsql {select "abc}
} {1 {unrecognized token: ""abc"}}
do_test main-3.2.4 {
  catchsql {select [abc}
} {1 {unrecognized token: "[abc"}}
do_test main-3.2.5 {
  catchsql {select x'4869}
} {1 {unrecognized token: "x'4869"}}
do_test main-3.2.6 {
  catchsql {select x'4869'}
} {0 Hi}
do_test main-3.2.7 {
  catchsql {select x'48695'}
} {1 {unrecognized token: "x'48695'"}}
do_test main-3.2.8 {
  catchsql {select x'486x'}
} {1 {unrecognized token: "x'486x'"}}
do_test main-3.2.9 {
  catchsql {select $abc(}
} {1 {unrecognized token: "$abc("}}
do_test main-3.2.10 {
  catchsql {select $abc(x}
} {1 {unrecognized token: "$abc(x"}}
set xyz 123
do_test main-3.2.11 {
  catchsql {select $::xyz}
} {0 123}
namespace eval ::testnamespace {
  variable xyz 321
}
do_test main-3.2.12 {
  catchsql {select $testnamespace::xyz}
} {0 321}
do_test main-3.2.13 {
  catchsql {select $(abc)}
} {1 {unrecognized token: "$"}}
breakpoint
do_test main-3.2.14 {
  set hi\u1234x 987
  db eval "select \$hi\u1234x"
} {987}
do_test main-3.2.15 {
  catchsql "select 456\u1234"
} [list 1 "unrecognized token: \"456\u1234\""]
do_test main-3.2.16 {
  catchsql {select cast(3.14e+4 AS integer)}
} {0 31400}
do_test main-3.2.17 {
  catchsql {select cast(3.14e+04 AS integer)}
} {0 31400}
do_test main-3.2.18 {
  catchsql {select cast(3.14e+004 AS integer)}
} {0 31400}
do_test main-3.2.19 {
  catchsql {select cast(3.14e4 AS integer)}
} {0 31400}
do_test main-3.2.20 {
  catchsql {select cast(3.14e04 AS integer)}
} {0 31400}
do_test main-3.2.21 {
  catchsql {select cast(3.14e004 AS integer)}
} {0 31400}
do_test main-3.2.16 {
  catchsql {select cast(3.14E+4 AS integer)}
} {0 31400}
do_test main-3.2.17 {
  catchsql {select cast(3.14E+04 AS integer)}
} {0 31400}
do_test main-3.2.18 {
  catchsql {select cast(3.14E+004 AS integer)}
} {0 31400}
do_test main-3.2.19 {
  catchsql {select cast(3.14E4 AS integer)}
} {0 31400}
do_test main-3.2.20 {
  catchsql {select cast(3.14E04 AS integer)}
} {0 31400}
do_test main-3.2.21 {
  catchsql {select cast(3.14E004 AS integer)}
} {0 31400}
do_test main-3.2.22 {
  catchsql {select cast(3.14e-4 * 1e8 AS integer)}
} {0 31400}
do_test main-3.2.23 {
  catchsql {select cast(3.14E-04 * 1E08 AS integer)}
} {0 31400}
do_test main-3.2.24 {
  catchsql {select cast(3.14e-004 * 01.0E+8 AS integer)}
} {0 31400}
do_test main-3.2.25 {
  catchsql {select 123/*abc}
} {0 123}
do_test main-3.2.26 {
  catchsql {select 123/***abc}
} {0 123}
do_test main-3.2.27 {
  catchsql {select 123/*/*2}
} {0 123}
do_test main-3.2.28 {
  catchsql {select 123/**/*2}
} {0 246}
do_test main-3.2.29 {
  catchsql {select 123/}
} {1 {near "/": syntax error}}
do_test main-3.2.30 {
  catchsql {select 123--5}
} {0 123}


do_test main-3.3 {
  catch {db close}
  foreach f [glob -nocomplain testdb/*] {file delete -force $f}
  file delete -force testdb
  sqlite3 db testdb
  execsql {

Changes to tool/lempar.c.

558
559
560
561
562
563
564

565
566
567
568
569
570
571
572
      yymsp->major = yygoto;
      yymsp->minor = yygotominor;
    }else
#endif
    {
      yy_shift(yypParser,yyact,yygoto,&yygotominor);
    }

  }else if( yyact == YYNSTATE + YYNRULE + 1 ){
    yy_accept(yypParser);
  }
}

/*
** The following code executes when the parse fails
*/







>
|







558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
      yymsp->major = yygoto;
      yymsp->minor = yygotominor;
    }else
#endif
    {
      yy_shift(yypParser,yyact,yygoto,&yygotominor);
    }
  }else{
    assert( yyact == YYNSTATE + YYNRULE + 1 );
    yy_accept(yypParser);
  }
}

/*
** The following code executes when the parse fails
*/