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:
16
manifest
16
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/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
|
||||
|
@ -1 +1 @@
|
||||
b10346818b25940c6dc85e94de8e36d20954161c
|
||||
f45c4b767a6b1451787836060235ff7499dea0de
|
90
src/main.c
90
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 @@ 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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
#
|
||||
|
Reference in New Issue
Block a user