SQLite

Check-in [0e6700f43f]
Login

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

Overview
Comment:Allow "_" characters to appear between any two digits in an integer, real or hexadecimal SQL literal.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 0e6700f43f133510c8049b2c5a2610cb3be29da7ed4d39b1fa65dc22c4cf529b
User & Date: dan 2024-02-27 10:52:41.798
Context
2024-02-27
11:02
Extend sqlite3.c makefile rule to support EXTRA_SRC=list-of-c-files to append to the generated sqlite3.c, as discussed in/around forum post ccda88cf6f1754c5. (check-in: 61676f1e18 user: stephan tags: trunk)
10:52
Allow "_" characters to appear between any two digits in an integer, real or hexadecimal SQL literal. (check-in: 0e6700f43f user: dan tags: trunk)
2024-02-26
22:28
The quote() SQL function should convert +Inf into 9.0e+999 and -Inf into -9.0e+999. See forum post 6675b25108. (check-in: 85dd79a6ed user: drh tags: trunk)
2024-01-23
11:20
Add extra checks for the validity of a numeric literal to sqlite3DequoteNumber(). (Closed-Leaf check-in: d57407ef59 user: dan tags: digit-separators)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/parse.y.
1931
1932
1933
1934
1935
1936
1937






1938
1939
1940
1941
1942
1943
1944
  VECTOR          /* Vector */
  SELECT_COLUMN   /* Choose a single column from a multi-column SELECT */
  IF_NULL_ROW     /* the if-null-row operator */
  ASTERISK        /* The "*" in count(*) and similar */
  SPAN            /* The span operator */
  ERROR           /* An expression containing an error */
.






/* There must be no more than 255 tokens defined above.  If this grammar
** is extended with new rules and tokens, they must either be so few in
** number that TK_SPAN is no more than 255, or else the new tokens must
** appear after this line.
*/
%include {
#if TK_SPAN>255







>
>
>
>
>
>







1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
  VECTOR          /* Vector */
  SELECT_COLUMN   /* Choose a single column from a multi-column SELECT */
  IF_NULL_ROW     /* the if-null-row operator */
  ASTERISK        /* The "*" in count(*) and similar */
  SPAN            /* The span operator */
  ERROR           /* An expression containing an error */
.

term(A) ::= QNUMBER(X). {
  A=tokenExpr(pParse,@X,X);
  sqlite3DequoteNumber(pParse, A);
}

/* There must be no more than 255 tokens defined above.  If this grammar
** is extended with new rules and tokens, they must either be so few in
** number that TK_SPAN is no more than 255, or else the new tokens must
** appear after this line.
*/
%include {
#if TK_SPAN>255
Changes to src/sqliteInt.h.
605
606
607
608
609
610
611


612
613
614
615
616
617
618
/*
** SQLITE_OMIT_VIRTUALTABLE implies SQLITE_OMIT_ALTERTABLE
*/
#if defined(SQLITE_OMIT_VIRTUALTABLE) && !defined(SQLITE_OMIT_ALTERTABLE)
# define SQLITE_OMIT_ALTERTABLE
#endif



/*
** Return true (non-zero) if the input is an integer that is too large
** to fit in 32-bits.  This macro is used inside of various testcase()
** macros to verify that we have tested SQLite for large-file support.
*/
#define IS_BIG_INT(X)  (((X)&~(i64)0xffffffff)!=0)








>
>







605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
/*
** SQLITE_OMIT_VIRTUALTABLE implies SQLITE_OMIT_ALTERTABLE
*/
#if defined(SQLITE_OMIT_VIRTUALTABLE) && !defined(SQLITE_OMIT_ALTERTABLE)
# define SQLITE_OMIT_ALTERTABLE
#endif

#define SQLITE_DIGIT_SEPARATOR '_'

/*
** Return true (non-zero) if the input is an integer that is too large
** to fit in 32-bits.  This macro is used inside of various testcase()
** macros to verify that we have tested SQLite for large-file support.
*/
#define IS_BIG_INT(X)  (((X)&~(i64)0xffffffff)!=0)

4791
4792
4793
4794
4795
4796
4797

4798
4799
4800
4801
4802
4803
4804
void sqlite3SetString(char **, sqlite3*, const char*);
void sqlite3ProgressCheck(Parse*);
void sqlite3ErrorMsg(Parse*, const char*, ...);
int sqlite3ErrorToParser(sqlite3*,int);
void sqlite3Dequote(char*);
void sqlite3DequoteExpr(Expr*);
void sqlite3DequoteToken(Token*);

void sqlite3TokenInit(Token*,char*);
int sqlite3KeywordCode(const unsigned char*, int);
int sqlite3RunParser(Parse*, const char*);
void sqlite3FinishCoding(Parse*);
int sqlite3GetTempReg(Parse*);
void sqlite3ReleaseTempReg(Parse*,int);
int sqlite3GetTempRange(Parse*,int);







>







4793
4794
4795
4796
4797
4798
4799
4800
4801
4802
4803
4804
4805
4806
4807
void sqlite3SetString(char **, sqlite3*, const char*);
void sqlite3ProgressCheck(Parse*);
void sqlite3ErrorMsg(Parse*, const char*, ...);
int sqlite3ErrorToParser(sqlite3*,int);
void sqlite3Dequote(char*);
void sqlite3DequoteExpr(Expr*);
void sqlite3DequoteToken(Token*);
void sqlite3DequoteNumber(Parse*, Expr*);
void sqlite3TokenInit(Token*,char*);
int sqlite3KeywordCode(const unsigned char*, int);
int sqlite3RunParser(Parse*, const char*);
void sqlite3FinishCoding(Parse*);
int sqlite3GetTempReg(Parse*);
void sqlite3ReleaseTempReg(Parse*,int);
int sqlite3GetTempRange(Parse*,int);
Changes to src/tokenize.c.
433
434
435
436
437
438
439

440



441
442



443


444







445
446

447
448

449


450



451
452
453
454
455

456
457

458


459



460

461
462
463
464
465
466
467
      testcase( z[0]=='0' );  testcase( z[0]=='1' );  testcase( z[0]=='2' );
      testcase( z[0]=='3' );  testcase( z[0]=='4' );  testcase( z[0]=='5' );
      testcase( z[0]=='6' );  testcase( z[0]=='7' );  testcase( z[0]=='8' );
      testcase( z[0]=='9' );  testcase( z[0]=='.' );
      *tokenType = TK_INTEGER;
#ifndef SQLITE_OMIT_HEX_INTEGER
      if( z[0]=='0' && (z[1]=='x' || z[1]=='X') && sqlite3Isxdigit(z[2]) ){

        for(i=3; sqlite3Isxdigit(z[i]); i++){}



        return i;
      }



#endif


      for(i=0; sqlite3Isdigit(z[i]); i++){}







#ifndef SQLITE_OMIT_FLOATING_POINT
      if( z[i]=='.' ){

        i++;
        while( sqlite3Isdigit(z[i]) ){ i++; }

        *tokenType = TK_FLOAT;


      }



      if( (z[i]=='e' || z[i]=='E') &&
           ( sqlite3Isdigit(z[i+1]) 
            || ((z[i+1]=='+' || z[i+1]=='-') && sqlite3Isdigit(z[i+2]))
           )
      ){

        i += 2;
        while( sqlite3Isdigit(z[i]) ){ i++; }

        *tokenType = TK_FLOAT;


      }



#endif

      while( IdChar(z[i]) ){
        *tokenType = TK_ILLEGAL;
        i++;
      }
      return i;
    }
    case CC_QUOTE2: {







>
|
>
>
>
|
|
>
>
>

>
>
|
>
>
>
>
>
>
>

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

>







433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
      testcase( z[0]=='0' );  testcase( z[0]=='1' );  testcase( z[0]=='2' );
      testcase( z[0]=='3' );  testcase( z[0]=='4' );  testcase( z[0]=='5' );
      testcase( z[0]=='6' );  testcase( z[0]=='7' );  testcase( z[0]=='8' );
      testcase( z[0]=='9' );  testcase( z[0]=='.' );
      *tokenType = TK_INTEGER;
#ifndef SQLITE_OMIT_HEX_INTEGER
      if( z[0]=='0' && (z[1]=='x' || z[1]=='X') && sqlite3Isxdigit(z[2]) ){
        for(i=3; 1; i++){
          if( sqlite3Isxdigit(z[i])==0 ){
            if( z[i]==SQLITE_DIGIT_SEPARATOR ){
              *tokenType = TK_QNUMBER;
            }else{
              break;
            }
          }
        }
      }else
#endif
        {
        for(i=0; 1; i++){
          if( sqlite3Isdigit(z[i])==0 ){
            if( z[i]==SQLITE_DIGIT_SEPARATOR ){
              *tokenType = TK_QNUMBER;
            }else{
              break;
            }
          }
        }
#ifndef SQLITE_OMIT_FLOATING_POINT
        if( z[i]=='.' ){
          if( *tokenType==TK_INTEGER ) *tokenType = TK_FLOAT;
          for(i++; 1; i++){
            if( sqlite3Isdigit(z[i])==0 ){
              if( z[i]==SQLITE_DIGIT_SEPARATOR ){
                *tokenType = TK_QNUMBER;
              }else{
                break;
              }
            }
          }
        }
        if( (z[i]=='e' || z[i]=='E') &&
             ( sqlite3Isdigit(z[i+1]) 
              || ((z[i+1]=='+' || z[i+1]=='-') && sqlite3Isdigit(z[i+2]))
             )
        ){
          if( *tokenType==TK_INTEGER ) *tokenType = TK_FLOAT;
          for(i+=2; 1; i++){
            if( sqlite3Isdigit(z[i])==0 ){
              if( z[i]==SQLITE_DIGIT_SEPARATOR ){
                *tokenType = TK_QNUMBER;
              }else{
                break;
              }
            }
          }
        }
#endif
      }
      while( IdChar(z[i]) ){
        *tokenType = TK_ILLEGAL;
        i++;
      }
      return i;
    }
    case CC_QUOTE2: {
618
619
620
621
622
623
624

625
626
627
628


629
630
631
632
633
634
635
      pParse->nErr++;
      break;
    }
#ifndef SQLITE_OMIT_WINDOWFUNC
    if( tokenType>=TK_WINDOW ){
      assert( tokenType==TK_SPACE || tokenType==TK_OVER || tokenType==TK_FILTER
           || tokenType==TK_ILLEGAL || tokenType==TK_WINDOW 

      );
#else
    if( tokenType>=TK_SPACE ){
      assert( tokenType==TK_SPACE || tokenType==TK_ILLEGAL );


#endif /* SQLITE_OMIT_WINDOWFUNC */
      if( AtomicLoad(&db->u1.isInterrupted) ){
        pParse->rc = SQLITE_INTERRUPT;
        pParse->nErr++;
        break;
      }
      if( tokenType==TK_SPACE ){







>



|
>
>







649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
      pParse->nErr++;
      break;
    }
#ifndef SQLITE_OMIT_WINDOWFUNC
    if( tokenType>=TK_WINDOW ){
      assert( tokenType==TK_SPACE || tokenType==TK_OVER || tokenType==TK_FILTER
           || tokenType==TK_ILLEGAL || tokenType==TK_WINDOW 
           || tokenType==TK_QNUMBER
      );
#else
    if( tokenType>=TK_SPACE ){
      assert( tokenType==TK_SPACE || tokenType==TK_ILLEGAL 
           || tokenType==TK_QNUMBER 
      );
#endif /* SQLITE_OMIT_WINDOWFUNC */
      if( AtomicLoad(&db->u1.isInterrupted) ){
        pParse->rc = SQLITE_INTERRUPT;
        pParse->nErr++;
        break;
      }
      if( tokenType==TK_SPACE ){
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
      }else if( tokenType==TK_OVER ){
        assert( n==4 );
        tokenType = analyzeOverKeyword((const u8*)&zSql[4], lastTokenParsed);
      }else if( tokenType==TK_FILTER ){
        assert( n==6 );
        tokenType = analyzeFilterKeyword((const u8*)&zSql[6], lastTokenParsed);
#endif /* SQLITE_OMIT_WINDOWFUNC */
      }else{
        Token x;
        x.z = zSql;
        x.n = n;
        sqlite3ErrorMsg(pParse, "unrecognized token: \"%T\"", &x);
        break;
      }
    }







|







688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
      }else if( tokenType==TK_OVER ){
        assert( n==4 );
        tokenType = analyzeOverKeyword((const u8*)&zSql[4], lastTokenParsed);
      }else if( tokenType==TK_FILTER ){
        assert( n==6 );
        tokenType = analyzeFilterKeyword((const u8*)&zSql[6], lastTokenParsed);
#endif /* SQLITE_OMIT_WINDOWFUNC */
      }else if( tokenType!=TK_QNUMBER ){
        Token x;
        x.z = zSql;
        x.n = n;
        sqlite3ErrorMsg(pParse, "unrecognized token: \"%T\"", &x);
        break;
      }
    }
Changes to src/util.c.
306
307
308
309
310
311
312




























313
314
315
316
317
318
319
}
void sqlite3DequoteExpr(Expr *p){
  assert( !ExprHasProperty(p, EP_IntValue) );
  assert( sqlite3Isquote(p->u.zToken[0]) );
  p->flags |= p->u.zToken[0]=='"' ? EP_Quoted|EP_DblQuoted : EP_Quoted;
  sqlite3Dequote(p->u.zToken);
}





























/*
** If the input token p is quoted, try to adjust the token to remove
** the quotes.  This is not always possible:
**
**     "abc"     ->   abc
**     "ab""cd"  ->   (not possible because of the interior "")







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







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
}
void sqlite3DequoteExpr(Expr *p){
  assert( !ExprHasProperty(p, EP_IntValue) );
  assert( sqlite3Isquote(p->u.zToken[0]) );
  p->flags |= p->u.zToken[0]=='"' ? EP_Quoted|EP_DblQuoted : EP_Quoted;
  sqlite3Dequote(p->u.zToken);
}

/*
** Expression p is a QNUMBER (quoted number). Dequote the value in p->u.zToken
** and set the type to INTEGER or FLOAT. "Quoted" integers or floats are those
** that contain '_' characters that must be removed before further processing.
*/
void sqlite3DequoteNumber(Parse *pParse, Expr *p){
  if( p ){
    const char *pIn = p->u.zToken;
    char *pOut = p->u.zToken;
    int bHex = (pIn[0]=='0' && (pIn[1]=='x' || pIn[1]=='X'));
    assert( p->op==TK_QNUMBER );
    p->op = TK_INTEGER;
    do {
      if( *pIn!=SQLITE_DIGIT_SEPARATOR ){
        *pOut++ = *pIn;
        if( *pIn=='e' || *pIn=='E' || *pIn=='.' ) p->op = TK_FLOAT;
      }else{
        if( (bHex==0 && (!sqlite3Isdigit(pIn[-1]) || !sqlite3Isdigit(pIn[1])))
         || (bHex==1 && (!sqlite3Isxdigit(pIn[-1]) || !sqlite3Isxdigit(pIn[1])))
        ){
          sqlite3ErrorMsg(pParse, "unrecognized token: \"%s\"", p->u.zToken);
        }
      }
    }while( *pIn++ );
    if( bHex ) p->op = TK_INTEGER;
  }
}

/*
** If the input token p is quoted, try to adjust the token to remove
** the quotes.  This is not always possible:
**
**     "abc"     ->   abc
**     "ab""cd"  ->   (not possible because of the interior "")
Changes to test/literal.test.
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
    DROP TABLE IF EXISTS x1;
    CREATE TABLE x1(a DEFAULT $lit);
    INSERT INTO x1 DEFAULT VALUES;
    SELECT typeof(a), a FROM x1;
  " [list $type $val]
}






test_literal 1.0 45                  integer 45
test_literal 1.1 0xFF                integer 255
test_literal 1.2 0xFFFFFFFF          integer [expr 0xFFFFFFFF]
test_literal 1.3 0x123FFFFFFFF       integer [expr 0x123FFFFFFFF]
test_literal 1.4 -0x123FFFFFFFF      integer [expr -1 * 0x123FFFFFFFF]
test_literal 1.5 0xFFFFFFFFFFFFFFFF  integer -1
test_literal 1.7 0x7FFFFFFFFFFFFFFF  integer  [expr 0x7FFFFFFFFFFFFFFF]
test_literal 1.8 -0x7FFFFFFFFFFFFFFF integer [expr -0x7FFFFFFFFFFFFFFF]
test_literal 1.9 +0x7FFFFFFFFFFFFFFF integer [expr +0x7FFFFFFFFFFFFFFF]
test_literal 1.10 -45                integer -45
test_literal 1.11 '0xFF'             text 0xFF
test_literal 1.12 '-0xFF'            text -0xFF
test_literal 1.13 -'0xFF'            integer 0

test_literal 1.14 -9223372036854775808 integer -9223372036854775808

test_literal 2.1  1e12    real    1000000000000.0
test_literal 2.2  1.0     real    1.0
test_literal 2.3  1e1000  real    Inf
test_literal 2.4  -1e1000  real   -Inf
































finish_test







>
>
>
>














<







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

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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
    DROP TABLE IF EXISTS x1;
    CREATE TABLE x1(a DEFAULT $lit);
    INSERT INTO x1 DEFAULT VALUES;
    SELECT typeof(a), a FROM x1;
  " [list $type $val]
}

proc test_literal_error {tn lit unrec} {
  do_catchsql_test $tn "SELECT $lit" "1 {unrecognized token: \"$unrec\"}"
}


test_literal 1.0 45                  integer 45
test_literal 1.1 0xFF                integer 255
test_literal 1.2 0xFFFFFFFF          integer [expr 0xFFFFFFFF]
test_literal 1.3 0x123FFFFFFFF       integer [expr 0x123FFFFFFFF]
test_literal 1.4 -0x123FFFFFFFF      integer [expr -1 * 0x123FFFFFFFF]
test_literal 1.5 0xFFFFFFFFFFFFFFFF  integer -1
test_literal 1.7 0x7FFFFFFFFFFFFFFF  integer  [expr 0x7FFFFFFFFFFFFFFF]
test_literal 1.8 -0x7FFFFFFFFFFFFFFF integer [expr -0x7FFFFFFFFFFFFFFF]
test_literal 1.9 +0x7FFFFFFFFFFFFFFF integer [expr +0x7FFFFFFFFFFFFFFF]
test_literal 1.10 -45                integer -45
test_literal 1.11 '0xFF'             text 0xFF
test_literal 1.12 '-0xFF'            text -0xFF
test_literal 1.13 -'0xFF'            integer 0

test_literal 1.14 -9223372036854775808 integer -9223372036854775808

test_literal 2.1  1e12    real    1000000000000.0
test_literal 2.2  1.0     real    1.0
test_literal 2.3  1e1000  real    Inf
test_literal 2.4  -1e1000  real   -Inf

test_literal 3.1  1_000   integer 1000
test_literal 3.2  1.1_1   real    1.11
test_literal 3.3  1_0.1_1 real    10.11
test_literal 3.4  1e1_000 real    Inf
test_literal 3.5  12_3_456.7_8_9 real 123456.789
test_literal 3.6  9_223_372_036_854_775_807 integer 9223372036854775807
test_literal 3.7  9_223_372_036_854_775_808 real 9.22337203685478e+18
test_literal 3.8  -9_223_372_036_854_775_808 integer -9223372036854775808

foreach {tn lit unrec} {
  0    123a456       123a456
  1    1_            1_
  2    1_.4          1_.4
  3    1e_4          1e_4
  4    1_e4          1_e4
  5    1.4_e4        1.4_e4
  6    1.4e+_4       1.4e
  7    1.4e-_4       1.4e
  8    1.4e4_        1.4e4_
  9    1.4_e4        1.4_e4
  10   1.4e_4        1.4e_4
  11   12__34        12__34
  12   1234_         1234_
  13   12._34        12._34
  14   12_.34        12_.34
  15   12.34_        12.34_
  16   1.0e1_______2 1.0e1_______2 
} {
  test_literal_error 4.$tn $lit $unrec
}

finish_test
Added test/literal2.tcl.
















































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# 2018 May 19
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
#

source [file join [file dirname $argv0] pg_common.tcl]

#=========================================================================


start_test literal2 "2024 Jan 23"

execsql_test  1.0 { SELECT 123_456 }
errorsql_test 1.1 { SELECT 123__456 }

execsql_float_test 2.1 { SELECT 1.0e1_2 }


execsql_test  3.0.0 { SELECT 0xFF_FF }
execsql_test  3.0.1 { SELECT 0xFF_EF }
errorsql_test  3.0.2 { SELECT 0xFF__EF }
# errorsql_test   3.0.3 { SELECT 0x_FFEF }
errorsql_test  3.0.4 { SELECT 0xFFEF_ }

execsql_test  3.1.0 { SELECT 0XFF_FF }
execsql_test  3.1.1 { SELECT 0XFF_EF }
errorsql_test  3.1.2 { SELECT 0XFF__EF }
# errorsql_test   3.1.3 { SELECT 0X_FFEF }
errorsql_test  3.1.4 { SELECT 0XFFEF_ }

finish_test


Added test/literal2.test.








































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
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
# 2024 Jan 23
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.
#

####################################################
# DO NOT EDIT! THIS FILE IS AUTOMATICALLY GENERATED!
####################################################

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

do_execsql_test 1.0 {
  SELECT 123_456
} {123456}

# PG says ERROR:  trailing junk after numeric literal at or near "123_"
do_test 1.1 { catch { execsql {
  SELECT 123__456
} } } 1


do_test 2.1 {
  set myres {}
  foreach r [db eval {SELECT 1.0e1_2}] {
    lappend myres [format %.4f [set r]]
  }
  set res2 {1000000000000.0000}
  set i 0
  foreach r [set myres] r2 [set res2] {
    if {[set r]<([set r2]-0.0001) || [set r]>([set r2]+0.0001)} {
      error "list element [set i] does not match: got=[set r] expected=[set r2]"
    }
    incr i
  }
  set {} {}
} {}

do_execsql_test 3.0.0 {
  SELECT 0xFF_FF
} {65535}

do_execsql_test 3.0.1 {
  SELECT 0xFF_EF
} {65519}

# PG says ERROR:  trailing junk after numeric literal at or near "0xFF_"
do_test 3.0.2 { catch { execsql {
  SELECT 0xFF__EF
} } } 1

# PG says ERROR:  trailing junk after numeric literal at or near "0xFFEF_"
do_test 3.0.4 { catch { execsql {
  SELECT 0xFFEF_
} } } 1

do_execsql_test 3.1.0 {
  SELECT 0XFF_FF
} {65535}

do_execsql_test 3.1.1 {
  SELECT 0XFF_EF
} {65519}

# PG says ERROR:  trailing junk after numeric literal at or near "0XFF_"
do_test 3.1.2 { catch { execsql {
  SELECT 0XFF__EF
} } } 1

# PG says ERROR:  trailing junk after numeric literal at or near "0XFFEF_"
do_test 3.1.4 { catch { execsql {
  SELECT 0XFFEF_
} } } 1

finish_test
Changes to test/misc1.test.
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
# 2015-03-22: NULL pointer dereference after a syntax error
#
do_catchsql_test misc1-21.1 {
  select''like''like''like#0;
} {1 {near "#0": syntax error}}
do_catchsql_test misc1-21.2 {
  VALUES(0,0x0MATCH#0;
} {1 {near ";": syntax error}}

# 2015-04-15
do_execsql_test misc1-22.1 {
  SELECT ''+3 FROM (SELECT ''+5);
} {3}

# 2015-04-19: NULL pointer dereference on a corrupt schema







|







650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
# 2015-03-22: NULL pointer dereference after a syntax error
#
do_catchsql_test misc1-21.1 {
  select''like''like''like#0;
} {1 {near "#0": syntax error}}
do_catchsql_test misc1-21.2 {
  VALUES(0,0x0MATCH#0;
} {1 {unrecognized token: "0x0MATCH"}}

# 2015-04-15
do_execsql_test misc1-22.1 {
  SELECT ''+3 FROM (SELECT ''+5);
} {3}

# 2015-04-19: NULL pointer dereference on a corrupt schema
Changes to test/speedtest1.c.
2145
2146
2147
2148
2149
2150
2151












































2152
2153
2154
2155
2156
2157
2158
  for(i=1; i<=n; i++){
    x1 = swizzle(i, n);
    x2 = swizzle(x1, n);
    speedtest1_numbername(x1, zNum, sizeof(zNum));
    printf("%5d %5d %5d %s\n", i, x1, x2, zNum);
  }
}













































#ifdef __linux__
#include <sys/types.h>
#include <unistd.h>

/*
** Attempt to display I/O stats on Linux using /proc/PID/io







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







2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
  for(i=1; i<=n; i++){
    x1 = swizzle(i, n);
    x2 = swizzle(x1, n);
    speedtest1_numbername(x1, zNum, sizeof(zNum));
    printf("%5d %5d %5d %s\n", i, x1, x2, zNum);
  }
}

/*
** This testset focuses on the speed of parsing numeric literals (integers
** and real numbers). This was added to test the impact of allowing "_"
** characters to appear in numeric SQL literals to make them easier to read. 
** For example, "SELECT 1_000_000;" instead of "SELECT 1000000;".
*/
void testset_parsenumber(void){
  const char *zSql1 = "SELECT 1, 12, 123, 1234, 12345, 123456";
  const char *zSql2 = "SELECT 8227256643844975616, 7932208612563860480, "
                      "2010730661871032832, 9138463067404021760, "
                      "2557616153664746496, 2557616153664746496";
  const char *zSql3 = "SELECT 1.0, 1.2, 1.23, 123.4, 1.2345, 1.23456";
  const char *zSql4 = "SELECT 8.227256643844975616, 7.932208612563860480, "
                      "2.010730661871032832, 9.138463067404021760, "
                      "2.557616153664746496, 2.557616153664746496";

  const int NROW = 100*g.szTest;
  int ii;

  speedtest1_begin_test(100, "parsing small integers");
  for(ii=0; ii<NROW; ii++){
    sqlite3_exec(g.db, zSql1, 0, 0, 0);
  }
  speedtest1_end_test();

  speedtest1_begin_test(110, "parsing large integers");
  for(ii=0; ii<NROW; ii++){
    sqlite3_exec(g.db, zSql2, 0, 0, 0);
  }
  speedtest1_end_test();

  speedtest1_begin_test(200, "parsing small reals");
  for(ii=0; ii<NROW; ii++){
    sqlite3_exec(g.db, zSql3, 0, 0, 0);
  }
  speedtest1_end_test();

  speedtest1_begin_test(210, "parsing large reals");
  for(ii=0; ii<NROW; ii++){
    sqlite3_exec(g.db, zSql4, 0, 0, 0);
  }
  speedtest1_end_test();
}

#ifdef __linux__
#include <sys/types.h>
#include <unistd.h>

/*
** Attempt to display I/O stats on Linux using /proc/PID/io
2553
2554
2555
2556
2557
2558
2559


2560
2561
2562
2563
2564
2565
2566
      testset_orm();
    }else if( strcmp(zThisTest,"cte")==0 ){
      testset_cte();
    }else if( strcmp(zThisTest,"fp")==0 ){
      testset_fp();
    }else if( strcmp(zThisTest,"trigger")==0 ){
      testset_trigger();


    }else if( strcmp(zThisTest,"rtree")==0 ){
#ifdef SQLITE_ENABLE_RTREE
      testset_rtree(6, 147);
#else
      fatal_error("compile with -DSQLITE_ENABLE_RTREE to enable "
                  "the R-Tree tests\n");
#endif







>
>







2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
      testset_orm();
    }else if( strcmp(zThisTest,"cte")==0 ){
      testset_cte();
    }else if( strcmp(zThisTest,"fp")==0 ){
      testset_fp();
    }else if( strcmp(zThisTest,"trigger")==0 ){
      testset_trigger();
    }else if( strcmp(zThisTest,"parsenumber")==0 ){
      testset_parsenumber();
    }else if( strcmp(zThisTest,"rtree")==0 ){
#ifdef SQLITE_ENABLE_RTREE
      testset_rtree(6, 147);
#else
      fatal_error("compile with -DSQLITE_ENABLE_RTREE to enable "
                  "the R-Tree tests\n");
#endif
Changes to tool/speed-check.sh.
157
158
159
160
161
162
163



164
165
166
167
168
169
170
        ;;
    --cte)
        SPEEDTEST_OPTS="$SPEEDTEST_OPTS --testset cte"
        ;;
    --fp)
        SPEEDTEST_OPTS="$SPEEDTEST_OPTS --testset fp"
        ;;



    --stmtscanstatus)
        SPEEDTEST_OPTS="$SPEEDTEST_OPTS --stmtscanstatus"
        ;;
    -*)
        CC_OPTS="$CC_OPTS $1"
        ;;
    *)







>
>
>







157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
        ;;
    --cte)
        SPEEDTEST_OPTS="$SPEEDTEST_OPTS --testset cte"
        ;;
    --fp)
        SPEEDTEST_OPTS="$SPEEDTEST_OPTS --testset fp"
        ;;
    --parsenumber)
        SPEEDTEST_OPTS="$SPEEDTEST_OPTS --testset parsenumber"
        ;;
    --stmtscanstatus)
        SPEEDTEST_OPTS="$SPEEDTEST_OPTS --stmtscanstatus"
        ;;
    -*)
        CC_OPTS="$CC_OPTS $1"
        ;;
    *)