1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-07-24 22:22:08 +03:00

Fix for ticket #41: Better handling of CREATE TRIGGER in the sqlite_complete()

function. (CVS 567)

FossilOrigin-Name: f45c4b767a6b1451787836060235ff7499dea0de
This commit is contained in:
drh
2002-05-15 14:17:44 +00:00
parent dc3794561f
commit ce9079c8f2
5 changed files with 168 additions and 35 deletions

View File

@ -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/func.c a31dcba85bc2ecb9b752980289cf7e6cd0cafbce
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/intpkey.test 31b5f28b2c44273e6695cf36ab2e4133aee7753c
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/speed.tcl da8afcc1d3ccc5696cfb388a68982bc3d9f7f00f
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

View File

@ -1 +1 @@
b10346818b25940c6dc85e94de8e36d20954161c
f45c4b767a6b1451787836060235ff7499dea0de

View File

@ -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 @@ void sqlite_close(sqlite *db){
/*
** 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 @@ int sqlite_complete(const char *zSql){
}
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;
}
/*

View File

@ -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) ::= OFFSET(X). {A = X;}
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 @@ trigger_cmd(A) ::= select(X). {A = sqliteTriggerSelectStep(X); }
cmd ::= DROP TRIGGER ids(X). {
sqliteDropTrigger(pParse,&X,0);
}

View File

@ -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.14 {
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.
#