Fix for ticket #41: Better handling of CREATE TRIGGER in the sqlite_complete()
function. (CVS 567)
FossilOrigin-Name: f45c4b767a6b1451787836060235ff7499dea0de
diff --git a/manifest b/manifest
index 8dcb603..7039832 100644
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Beginning\sto\sclean\sup\sthe\strigger\scode.\s\sStill\slots\sof\swork\sto\sdo.\s(CVS\s566)
-D 2002-05-15T12:45:43
+C Fix\sfor\sticket\s#41:\sBetter\shandling\sof\sCREATE\sTRIGGER\sin\sthe\ssqlite_complete()\nfunction.\s(CVS\s567)
+D 2002-05-15T14:17:45
F Makefile.in 6291a33b87d2a395aafd7646ee1ed562c6f2c28c
F Makefile.template 4e11752e0b5c7a043ca50af4296ec562857ba495
F README a4c0ba11354ef6ba0776b400d057c59da47a4cc0
@@ -28,13 +28,13 @@
F src/hash.c cc259475e358baaf299b00a2c7370f2b03dda892
F src/hash.h dca065dda89d4575f3176e75e9a3dc0f4b4fb8b9
F src/insert.c 26ca700fb4055c34970ebac1d9a9a067bebef3b0
-F src/main.c 9e9ba7d8491928c46c6a70d9b7c30bbf7e60d499
+F src/main.c de486c893c0a34a91aa5660c3ab5ce3d08746eaf
F src/md5.c 0ae1f3e2cac92d06fc6246d1b4b8f61a2fe66d3b
F src/os.c 5ab8b6b4590d0c1ab8e96c67996c170e4462e0fc
F src/os.h 4a361fccfbc4e7609b3e1557f604f94c1e96ad10
F src/pager.c ba5740104cc27b342cd43eebfdc44d60f64a3ded
F src/pager.h 6fddfddd3b73aa8abc081b973886320e3c614f0e
-F src/parse.y 164789531d0c6a2c28fb4baded14afc1be4bd4aa
+F src/parse.y 12d6f6c0d12c868b366e3758e62578e686623394
F src/printf.c d8032ee18b860c812eeff596c9bebfdacb7930fd
F src/random.c 19e8e00fe0df32a742f115773f57651be327cabe
F src/select.c 1b623a7d826ec7c245bc542b665d61724da2a62d
@@ -73,7 +73,7 @@
F test/ioerr.test 57d9bffaca18b34f9e976f786eadc2591d6efc6a
F test/limit.test a930f3eba2a7691c8397ccab33710b931589566a
F test/lock.test 3fcfd46a73119f6a18094673328a32c7b3047a8f
-F test/main.test e121fed34ebf67f595290776162e322b08470127
+F test/main.test c66b564554b770ee7fdbf6a66c0cd90329bc2c85
F test/malloc.test 70fdd0812e2a57eb746aaf015350f58bb8eee0b1
F test/minmax.test fb6ab400271ae1f5bc88617c2882f2f081ea8e6d
F test/misc1.test a03214118429b40ca5548bc1fae0ebd5c34dabe6
@@ -134,7 +134,7 @@
F www/sqlite.tcl 8b5884354cb615049aed83039f8dfe1552a44279
F www/tclsqlite.tcl 1db15abeb446aad0caf0b95b8b9579720e4ea331
F www/vdbe.tcl 2013852c27a02a091d39a766bc87cff329f21218
-P 690f9a163173c4c7af7e8e92e942cee4184c7974
-R 2c7fa77b8b0294150616cb3ad535e3be
+P b10346818b25940c6dc85e94de8e36d20954161c
+R 8c54c69d6079e01fd5f95accd48faacf
U drh
-Z 2f79a3bdfbaced77f180a80585eae438
+Z f5897975828e35ff1e0f4db008fa1bf2
diff --git a/manifest.uuid b/manifest.uuid
index d6e41fb..7dfc43d 100644
--- a/manifest.uuid
+++ b/manifest.uuid
@@ -1 +1 @@
-b10346818b25940c6dc85e94de8e36d20954161c
\ No newline at end of file
+f45c4b767a6b1451787836060235ff7499dea0de
\ No newline at end of file
diff --git a/src/main.c b/src/main.c
index 3d277e8..7ec9cd1 100644
--- a/src/main.c
+++ b/src/main.c
@@ -14,10 +14,11 @@
** other files are for internal use by SQLite and should not be
** accessed by users of the library.
**
-** $Id: main.c,v 1.73 2002/05/15 11:44:14 drh Exp $
+** $Id: main.c,v 1.74 2002/05/15 14:17:45 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
+#include <ctype.h>
/*
** This is the callback routine for the code that initializes the
@@ -476,14 +477,22 @@
/*
** Return TRUE if the given SQL string ends in a semicolon.
+**
+** Special handling is require for CREATE TRIGGER statements.
+** Whenever the CREATE TRIGGER keywords are seen, the statement
+** must end with ";END;".
*/
int sqlite_complete(const char *zSql){
- int isComplete = 0;
+ int isComplete = 1;
+ int requireEnd = 0;
+ int seenText = 0;
int seenCreate = 0;
while( *zSql ){
switch( *zSql ){
case ';': {
isComplete = 1;
+ seenText = 1;
+ seenCreate = 0;
break;
}
case ' ':
@@ -494,53 +503,88 @@
}
case '[': {
isComplete = 0;
+ seenText = 1;
+ seenCreate = 0;
zSql++;
while( *zSql && *zSql!=']' ){ zSql++; }
if( *zSql==0 ) return 0;
break;
}
+ case '"':
case '\'': {
+ int c = *zSql;
isComplete = 0;
+ seenText = 1;
+ seenCreate = 0;
zSql++;
- while( *zSql && *zSql!='\'' ){ zSql++; }
- if( *zSql==0 ) return 0;
- break;
- }
- case '"': {
- isComplete = 0;
- zSql++;
- while( *zSql && *zSql!='"' ){ zSql++; }
+ while( *zSql && *zSql!=c ){ zSql++; }
if( *zSql==0 ) return 0;
break;
}
case '-': {
if( zSql[1]!='-' ){
isComplete = 0;
+ seenCreate = 0;
break;
}
while( *zSql && *zSql!='\n' ){ zSql++; }
- if( *zSql==0 ) return isComplete;
+ if( *zSql==0 ) return seenText && isComplete && requireEnd==0;
+ break;
+ }
+ case 'c':
+ case 'C': {
+ seenText = 1;
+ if( !isComplete ) break;
+ isComplete = 0;
+ if( sqliteStrNICmp(zSql, "create", 6)!=0 ) break;
+ if( !isspace(zSql[6]) ) break;
+ zSql += 5;
+ seenCreate = 1;
+ while( isspace(zSql[1]) ) zSql++;
+ if( sqliteStrNICmp(&zSql[1],"trigger", 7)!=0 ) break;
+ zSql += 7;
+ requireEnd++;
+ break;
+ }
+ case 't':
+ case 'T': {
+ seenText = 1;
+ if( !seenCreate ) break;
+ seenCreate = 0;
+ isComplete = 0;
+ if( sqliteStrNICmp(zSql, "trigger", 7)!=0 ) break;
+ if( !isspace(zSql[7]) ) break;
+ zSql += 6;
+ requireEnd++;
+ break;
+ }
+ case 'e':
+ case 'E': {
+ seenCreate = 0;
+ seenText = 1;
+ if( !isComplete ) break;
+ isComplete = 0;
+ if( requireEnd==0 ) break;
+ if( sqliteStrNICmp(zSql, "end", 3)!=0 ) break;
+ zSql += 2;
+ while( isspace(zSql[1]) ) zSql++;
+ if( zSql[1]==';' ){
+ zSql++;
+ isComplete = 1;
+ requireEnd--;
+ }
break;
}
default: {
- if (seenCreate && !sqliteStrNICmp(zSql, "trigger", 7)){
- while (sqliteStrNICmp(zSql, "end", 3)){
- if (!*++zSql) return 0;
- }
- }
- if (!sqliteStrNICmp(zSql, "create", 6)) {
- zSql = zSql + 5;
- seenCreate = 1;
- }else{
- seenCreate = 0;
- }
+ seenCreate = 0;
+ seenText = 1;
isComplete = 0;
break;
}
}
zSql++;
}
- return isComplete;
+ return seenText && isComplete && requireEnd==0;
}
/*
diff --git a/src/parse.y b/src/parse.y
index b790746..bc60a78 100644
--- a/src/parse.y
+++ b/src/parse.y
@@ -14,7 +14,7 @@
** the parser. Lemon will also generate a header file containing
** numeric codes for all of the tokens.
**
-** @(#) $Id: parse.y,v 1.64 2002/05/15 08:30:14 danielk1977 Exp $
+** @(#) $Id: parse.y,v 1.65 2002/05/15 14:17:45 drh Exp $
*/
%token_prefix TK_
%token_type {Token}
@@ -120,6 +120,7 @@
id(A) ::= PRAGMA(X). {A = X;}
id(A) ::= REPLACE(X). {A = X;}
id(A) ::= TEMP(X). {A = X;}
+id(A) ::= TRIGGER(X). {A = X;}
id(A) ::= VACUUM(X). {A = X;}
id(A) ::= VIEW(X). {A = X;}
@@ -692,4 +693,3 @@
cmd ::= DROP TRIGGER ids(X). {
sqliteDropTrigger(pParse,&X,0);
}
-
diff --git a/test/main.test b/test/main.test
index 4eceab0..fdcfcbc 100644
--- a/test/main.test
+++ b/test/main.test
@@ -11,7 +11,7 @@
# 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.10 2002/05/10 13:14:08 drh Exp $
+# $Id: main.test,v 1.11 2002/05/15 14:17:45 drh Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
@@ -70,6 +70,95 @@
do_test main-1.15 {
db complete {SELECT a-b FROM t1 }
} {0}
+do_test main-1.16 {
+ db complete {
+ CREATE TABLE abc(x,y);
+ }
+} {1}
+do_test main-1.17 {
+ db complete {
+ CREATE TRIGGER xyz AFTER DELETE abc BEGIN UPDATE pqr;
+ }
+} {0}
+do_test main-1.18 {
+ db complete {
+ CREATE TRIGGER xyz AFTER DELETE abc BEGIN UPDATE pqr; END;
+ }
+} {1}
+do_test main-1.19 {
+ db complete {
+ CREATE TRIGGER xyz AFTER DELETE abc BEGIN
+ UPDATE pqr;
+ unknown command;
+ }
+} {0}
+do_test main-1.20 {
+ db complete {
+ CREATE TRIGGER xyz AFTER DELETE backend BEGIN
+ UPDATE pqr;
+ }
+} {0}
+do_test main-1.21 {
+ db complete {
+ CREATE TRIGGER xyz AFTER DELETE end BEGIN
+ SELECT a, b FROM end;
+ }
+} {0}
+do_test main-1.22 {
+ db complete {
+ CREATE TRIGGER xyz AFTER DELETE end BEGIN
+ SELECT a, b FROM end;
+ END;
+ }
+} {1}
+do_test main-1.23 {
+ db complete {
+ CREATE TRIGGER xyz AFTER DELETE end BEGIN
+ SELECT a, b FROM end;
+ END;
+ SELECT a, b FROM end;
+ }
+} {1}
+do_test main-1.24 {
+ db 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 {
+ db complete {
+ CREATE -- a comment
+ TRIGGERX xyz AFTER DELETE backend BEGIN
+ UPDATE pqr SET a=5;
+ }
+} {1}
+do_test main-1.28 {
+ db complete {
+ CREATE TEMP TRIGGER xyz AFTER DELETE backend BEGIN
+ UPDATE pqr SET a=5;
+ }
+} {1}
+do_test main-1.29 {
+ db complete {
+ CREATE TRIGGER xyz AFTER DELETE backend BEGIN
+ UPDATE pqr SET a=5;
+ EXPLAIN select * from xyz;
+ }
+} {0}
+
# Try to open a database with a corrupt database file.
#