SQLite

Check-in [36b89d728f]
Login

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

Overview
Comment:Compute the correct column name even if the column identifier is the very last token in the SQL statement. This fixes a problem introduced by check-in [0fdf97efe5df745510c6b] and reported by the community during beta-testing.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 36b89d728ff13d395fe0e1db8e7c01263f73dccb278b3ece27f6ef78e909b492
User & Date: drh 2018-01-10 00:40:06.636
Context
2018-01-10
00:53
Rearrange some routines in shell.c to avoid the need to forward reference a static function. (check-in: fd7f51a107 user: drh tags: trunk)
00:40
Compute the correct column name even if the column identifier is the very last token in the SQL statement. This fixes a problem introduced by check-in [0fdf97efe5df745510c6b] and reported by the community during beta-testing. (check-in: 36b89d728f user: drh tags: trunk)
2018-01-09
22:23
When disconnecting from the 'swarmvtab' extension, close each database prior to invoking the 'openclose' function on it. (check-in: 3e5647cb6c user: mistachkin tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/build.c.
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
  p->pCheck = sqlite3ExprListDup(db, pCNames, EXPRDUP_REDUCE);
  if( db->mallocFailed ) goto create_view_fail;

  /* Locate the end of the CREATE VIEW statement.  Make sEnd point to
  ** the end.
  */
  sEnd = pParse->sLastToken;
  assert( sEnd.z[0]!=0 );
  if( sEnd.z[0]!=';' ){
    sEnd.z += sEnd.n;
  }
  sEnd.n = 0;
  n = (int)(sEnd.z - pBegin->z);
  assert( n>0 );
  z = pBegin->z;







|







2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
  p->pCheck = sqlite3ExprListDup(db, pCNames, EXPRDUP_REDUCE);
  if( db->mallocFailed ) goto create_view_fail;

  /* Locate the end of the CREATE VIEW statement.  Make sEnd point to
  ** the end.
  */
  sEnd = pParse->sLastToken;
  assert( sEnd.z[0]!=0 || sEnd.n==0 );
  if( sEnd.z[0]!=';' ){
    sEnd.z += sEnd.n;
  }
  sEnd.n = 0;
  n = (int)(sEnd.z - pBegin->z);
  assert( n>0 );
  z = pBegin->z;
Changes to src/parse.y.
27
28
29
30
31
32
33
34
35



36
37
38
39
40
41
42
// 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 {
  UNUSED_PARAMETER(yymajor);  /* Silence some compiler warnings */
  assert( TOKEN.z[0] );  /* The tokenizer always gives us a token */
  sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", &TOKEN);



}
%stack_overflow {
  sqlite3ErrorMsg(pParse, "parser stack overflow");
}

// The name of the generated procedure that implements the parser
// is as follows:







|
|
>
>
>







27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
// 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 {
  UNUSED_PARAMETER(yymajor);  /* Silence some compiler warnings */
  if( TOKEN.z[0] ){
    sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", &TOKEN);
  }else{
    sqlite3ErrorMsg(pParse, "incomplete input");
  }
}
%stack_overflow {
  sqlite3ErrorMsg(pParse, "parser stack overflow");
}

// The name of the generated procedure that implements the parser
// is as follows:
Changes to src/tokenize.c.
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
      if( lastTokenParsed==TK_SEMI ){
        tokenType = 0;
      }else if( lastTokenParsed==0 ){
        break;
      }else{
        tokenType = TK_SEMI;
      }
      zSql -= n;
    }
    if( tokenType>=TK_SPACE ){
      assert( tokenType==TK_SPACE || tokenType==TK_ILLEGAL );
      if( db->u1.isInterrupted ){
        pParse->rc = SQLITE_INTERRUPT;
        break;
      }







|







522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
      if( lastTokenParsed==TK_SEMI ){
        tokenType = 0;
      }else if( lastTokenParsed==0 ){
        break;
      }else{
        tokenType = TK_SEMI;
      }
      n = 0;
    }
    if( tokenType>=TK_SPACE ){
      assert( tokenType==TK_SPACE || tokenType==TK_ILLEGAL );
      if( db->u1.isInterrupted ){
        pParse->rc = SQLITE_INTERRUPT;
        break;
      }
Changes to test/capi2.test.
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
  lappend rc $msg $TAIL
} {1 {(1) no such column: bogus} {}}
do_test capi2-3.2 {
  set rc [catch {
      sqlite3_prepare $DB {select bogus from } -1 TAIL
  } msg]
  lappend rc $msg $TAIL
} {1 {(1) near " ": syntax error} {}}
do_test capi2-3.3 {
  set rc [catch {
      sqlite3_prepare $DB {;;;;select bogus from sqlite_master} -1 TAIL
  } msg]
  lappend rc $msg $TAIL
} {1 {(1) no such column: bogus} {}}
do_test capi2-3.4 {







|







159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
  lappend rc $msg $TAIL
} {1 {(1) no such column: bogus} {}}
do_test capi2-3.2 {
  set rc [catch {
      sqlite3_prepare $DB {select bogus from } -1 TAIL
  } msg]
  lappend rc $msg $TAIL
} {1 {(1) incomplete input} {}}
do_test capi2-3.3 {
  set rc [catch {
      sqlite3_prepare $DB {;;;;select bogus from sqlite_master} -1 TAIL
  } msg]
  lappend rc $msg $TAIL
} {1 {(1) no such column: bogus} {}}
do_test capi2-3.4 {
Changes to test/capi3.test.
645
646
647
648
649
650
651












652
653
654
655
656
657
658

check_header $STMT capi3-5.31 {x y z} {VARINT {} {}}
check_origin_header $STMT capi3-5.32 {main {} {}} {t1 {} {}} {a {} {}}
do_test capi3-5.33 {
  sqlite3_finalize $STMT
} SQLITE_OK














set ::ENC [execsql {pragma encoding}]
db close

do_test capi3-6.0 {
  sqlite3 db test.db
  set DB [sqlite3_connection_pointer db]







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







645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670

check_header $STMT capi3-5.31 {x y z} {VARINT {} {}}
check_origin_header $STMT capi3-5.32 {main {} {}} {t1 {} {}} {a {} {}}
do_test capi3-5.33 {
  sqlite3_finalize $STMT
} SQLITE_OK

# 2018-01-09:  If a column is the last token if a string, the column name
# was not being set correctly, due to changes in check-in
# https://sqlite.org/src/info/0fdf97efe5df7455
#
# This problem was detected by the community during beta-testing.
#
do_test capi3-5.34 {
  set STMT [sqlite3_prepare $DB {SELECT :a, :b} -1 TAIL]
  sqlite3_column_count $STMT
} 2
check_header $STMT capi-5.35 {:a :b} {{} {}}
sqlite3_finalize $STMT

set ::ENC [execsql {pragma encoding}]
db close

do_test capi3-6.0 {
  sqlite3 db test.db
  set DB [sqlite3_connection_pointer db]
Changes to test/icu.test.
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
  } {1 {wrong number of arguments to function regexp()}}
  do_catchsql_test icu-5.3 { 
    SELECT regexp('a[abc]c.*', 'abc', 'c') 
  } {1 {wrong number of arguments to function regexp()}}
  do_catchsql_test icu-5.4 { 
    SELECT 'abc' REGEXP 'a[abc]c.*'
  } {0 1}
  do_catchsql_test icu-5.4 {SELECT 'abc' REGEXP }   {1 {near " ": syntax error}}
  do_catchsql_test icu-5.5 {SELECT 'abc' REGEXP, 1} {1 {near ",": syntax error}}
 
  do_malloc_test icu-6.10 -sqlbody {
    SELECT upper(char(0xfb04,0xdf,0xfb04,0xe8,0xfb04));
  }
}

finish_test







|
|







134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
  } {1 {wrong number of arguments to function regexp()}}
  do_catchsql_test icu-5.3 { 
    SELECT regexp('a[abc]c.*', 'abc', 'c') 
  } {1 {wrong number of arguments to function regexp()}}
  do_catchsql_test icu-5.4 { 
    SELECT 'abc' REGEXP 'a[abc]c.*'
  } {0 1}
  do_catchsql_test icu-5.5 {SELECT 'abc' REGEXP }   {1 {incomplete input}}
  do_catchsql_test icu-5.6 {SELECT 'abc' REGEXP, 1} {1 {near ",": syntax error}}
 
  do_malloc_test icu-6.10 -sqlbody {
    SELECT upper(char(0xfb04,0xdf,0xfb04,0xe8,0xfb04));
  }
}

finish_test
Changes to test/main.test.
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
  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}







|







430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
  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 {incomplete input}}
do_test main-3.2.30 {
  catchsql {select 123--5}
} {0 123}


do_test main-3.3 {
  catch {db close}
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
do_test main-3.4 {
  set v [catch {execsql {create bogus}} msg]
  lappend v $msg
} {1 {near "bogus": syntax error}}
do_test main-3.5 {
  set v [catch {execsql {create}} msg]
  lappend v $msg
} {1 {near "create": syntax error}}
do_test main-3.6 {
  catchsql {SELECT 'abc' + #9}
} {1 {near "#9": syntax error}}

# The following test-case tests the linked list code used to manage
# sqlite3_vfs structures.
if {$::tcl_platform(platform)=="unix" 







|







463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
do_test main-3.4 {
  set v [catch {execsql {create bogus}} msg]
  lappend v $msg
} {1 {near "bogus": syntax error}}
do_test main-3.5 {
  set v [catch {execsql {create}} msg]
  lappend v $msg
} {1 {incomplete input}}
do_test main-3.6 {
  catchsql {SELECT 'abc' + #9}
} {1 {near "#9": syntax error}}

# The following test-case tests the linked list code used to manage
# sqlite3_vfs structures.
if {$::tcl_platform(platform)=="unix" 
Changes to test/select1.test.
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
  }} msg]
  lappend v $msg
} {1 {near "WHERE": syntax error}}
} ;# ifcapable compound
do_test select1-7.3 {
  set v [catch {execsql {SELECT f1 FROM test1 as 'hi', test2 as}} msg]
  lappend v $msg
} {1 {near "as": syntax error}}
do_test select1-7.4 {
  set v [catch {execsql {
     SELECT f1 FROM test1 ORDER BY;
  }} msg]
  lappend v $msg
} {1 {near ";": syntax error}}
do_test select1-7.5 {







|







684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
  }} msg]
  lappend v $msg
} {1 {near "WHERE": syntax error}}
} ;# ifcapable compound
do_test select1-7.3 {
  set v [catch {execsql {SELECT f1 FROM test1 as 'hi', test2 as}} msg]
  lappend v $msg
} {1 {incomplete input}}
do_test select1-7.4 {
  set v [catch {execsql {
     SELECT f1 FROM test1 ORDER BY;
  }} msg]
  lappend v $msg
} {1 {near ";": syntax error}}
do_test select1-7.5 {
Changes to test/shell3.test.
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
  catchcmd "foo.db \"CREATE TABLE t1(a); DROP TABLE t1;\""
} {0 {}}
do_test shell3-1.6 {
  catchcmd "foo.db" ".tables"
} {0 {}}
do_test shell3-1.7 {
  catchcmd "foo.db \"CREATE TABLE\""
} {1 {Error: near "TABLE": syntax error}}

#----------------------------------------------------------------------------
#   shell3-2.*: Basic tests for running SQL file from command line.
#

# Run SQL file from command line
do_test shell3-2.1 {







|







62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
  catchcmd "foo.db \"CREATE TABLE t1(a); DROP TABLE t1;\""
} {0 {}}
do_test shell3-1.6 {
  catchcmd "foo.db" ".tables"
} {0 {}}
do_test shell3-1.7 {
  catchcmd "foo.db \"CREATE TABLE\""
} {1 {Error: incomplete input}}

#----------------------------------------------------------------------------
#   shell3-2.*: Basic tests for running SQL file from command line.
#

# Run SQL file from command line
do_test shell3-2.1 {
92
93
94
95
96
97
98
99
100
101
  catchcmd "foo.db" "CREATE TABLE t1(a); DROP TABLE t1;"
} {0 {}}
do_test shell3-2.6 {
  catchcmd "foo.db" ".tables"
} {0 {}}
do_test shell3-2.7 {
  catchcmd "foo.db" "CREATE TABLE"
} {1 {Error: near line 1: near "TABLE": syntax error}}

finish_test







|


92
93
94
95
96
97
98
99
100
101
  catchcmd "foo.db" "CREATE TABLE t1(a); DROP TABLE t1;"
} {0 {}}
do_test shell3-2.6 {
  catchcmd "foo.db" ".tables"
} {0 {}}
do_test shell3-2.7 {
  catchcmd "foo.db" "CREATE TABLE"
} {1 {Error: near line 1: incomplete input}}

finish_test
Changes to test/with2.test.
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
do_catchsql_test 6.5 {
  WITH x AS (SELECT * FROM t1)
  DELETE FROM t2 WHERE;
} {1 {near ";": syntax error}}

do_catchsql_test 6.6 { 
  WITH x AS (SELECT * FROM t1) DELETE FROM t2 WHERE
} {/1 {near .* syntax error}/}

do_catchsql_test 6.7 { 
  WITH x AS (SELECT * FROM t1) DELETE FROM t2 WHRE 1;
} {/1 {near .* syntax error}/}

do_catchsql_test 6.8 { 
  WITH x AS (SELECT * FROM t1) UPDATE t2 SET a = 10, b = ;







|







322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
do_catchsql_test 6.5 {
  WITH x AS (SELECT * FROM t1)
  DELETE FROM t2 WHERE;
} {1 {near ";": syntax error}}

do_catchsql_test 6.6 { 
  WITH x AS (SELECT * FROM t1) DELETE FROM t2 WHERE
} {1 {incomplete input}}

do_catchsql_test 6.7 { 
  WITH x AS (SELECT * FROM t1) DELETE FROM t2 WHRE 1;
} {/1 {near .* syntax error}/}

do_catchsql_test 6.8 { 
  WITH x AS (SELECT * FROM t1) UPDATE t2 SET a = 10, b = ;