mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-07 02:42:48 +03:00
Add the ESCAPE clause to the LIKE operator. Not fully tested yet. (CVS 2107)
FossilOrigin-Name: 49268c2b7a84c4c618214dac8bef0f541440fe6b
This commit is contained in:
19
manifest
19
manifest
@@ -1,5 +1,5 @@
|
|||||||
C Extra\stests\sand\sresulting\sbugfixes\sfor\sbtree\scursors.\s(CVS\s2106)
|
C Add\sthe\sESCAPE\sclause\sto\sthe\sLIKE\soperator.\sNot\sfully\stested\syet.\s(CVS\s2107)
|
||||||
D 2004-11-17T10:22:03
|
D 2004-11-17T16:41:29
|
||||||
F Makefile.in e747bb5ba34ccbdd81f79dcf1b2b33c02817c21d
|
F Makefile.in e747bb5ba34ccbdd81f79dcf1b2b33c02817c21d
|
||||||
F Makefile.linux-gcc a9e5a0d309fa7c38e7c14d3ecf7690879d3a5457
|
F Makefile.linux-gcc a9e5a0d309fa7c38e7c14d3ecf7690879d3a5457
|
||||||
F README a01693e454a00cc117967e3f9fdab2d4d52e9bc1
|
F README a01693e454a00cc117967e3f9fdab2d4d52e9bc1
|
||||||
@@ -35,7 +35,7 @@ F src/build.c a95eb1181247368b0ffe2eed121a43735976a964
|
|||||||
F src/date.c 65536e7ea04fdde6e0551264fca15966966e171f
|
F src/date.c 65536e7ea04fdde6e0551264fca15966966e171f
|
||||||
F src/delete.c be9d039b819f4a5d0fdfaeceace139ba189ef819
|
F src/delete.c be9d039b819f4a5d0fdfaeceace139ba189ef819
|
||||||
F src/expr.c 4ee3e47358c92a919062255b14057a7a8f641e01
|
F src/expr.c 4ee3e47358c92a919062255b14057a7a8f641e01
|
||||||
F src/func.c 181ea4b8bbc621457838494a440d2e4e2307ab70
|
F src/func.c 897c1c130af08b29cdd89dd89f8c1832bab766b4
|
||||||
F src/hash.c a97721a55440b7bea31ffe471bb2f6b4123cddd5
|
F src/hash.c a97721a55440b7bea31ffe471bb2f6b4123cddd5
|
||||||
F src/hash.h 1b0c445e1c89ff2aaad9b4605ba61375af001e84
|
F src/hash.h 1b0c445e1c89ff2aaad9b4605ba61375af001e84
|
||||||
F src/insert.c 9524a6c3e86cbdbae3313f6a083bb9a3e7a2462b
|
F src/insert.c 9524a6c3e86cbdbae3313f6a083bb9a3e7a2462b
|
||||||
@@ -54,7 +54,7 @@ F src/os_win.c 9482dfc92f289b68205bb2c9315757c7e3946bfb
|
|||||||
F src/os_win.h 41a946bea10f61c158ce8645e7646b29d44f122b
|
F src/os_win.h 41a946bea10f61c158ce8645e7646b29d44f122b
|
||||||
F src/pager.c ee88fcecb081e3635c281bc09d604e934429e2f5
|
F src/pager.c ee88fcecb081e3635c281bc09d604e934429e2f5
|
||||||
F src/pager.h 9eba8c53dd91eae7f3f90743b2ee242da02a9862
|
F src/pager.h 9eba8c53dd91eae7f3f90743b2ee242da02a9862
|
||||||
F src/parse.y 3282026b619e1c7f932fd8ecef9627fa86da048a
|
F src/parse.y 0a4bdfd7b65d9761b41a862d09a17c90c1f526f7
|
||||||
F src/pragma.c 0b43b8cac4870bfa041bf2ca29d7ce47b76362d6
|
F src/pragma.c 0b43b8cac4870bfa041bf2ca29d7ce47b76362d6
|
||||||
F src/printf.c 3d20b21cfecadacecac3fb7274e746cb81d3d357
|
F src/printf.c 3d20b21cfecadacecac3fb7274e746cb81d3d357
|
||||||
F src/random.c eff68e3f257e05e81eae6c4d50a51eb88beb4ff3
|
F src/random.c eff68e3f257e05e81eae6c4d50a51eb88beb4ff3
|
||||||
@@ -122,7 +122,7 @@ F test/diskfull.test e2f6cfd868713ead06dc82b84a4938e868128fc0
|
|||||||
F test/enc.test 7a03417a1051fe8bc6c7641cf4c8c3f7e0066d52
|
F test/enc.test 7a03417a1051fe8bc6c7641cf4c8c3f7e0066d52
|
||||||
F test/enc2.test 6d1a2650e9da43eab499d18ca694a0cb6ec69dee
|
F test/enc2.test 6d1a2650e9da43eab499d18ca694a0cb6ec69dee
|
||||||
F test/enc3.test f6a5f0b7b7f3a88f030d3143729b87cd5c86d837
|
F test/enc3.test f6a5f0b7b7f3a88f030d3143729b87cd5c86d837
|
||||||
F test/expr.test 8a96b21644b9702cabc3695f2b73ae0861376765
|
F test/expr.test bf826516ea0ba159eb9680fbcea955148bfe9bc3
|
||||||
F test/fkey1.test 81bb13caaa78f58d7d191d7f535529f7c91d821a
|
F test/fkey1.test 81bb13caaa78f58d7d191d7f535529f7c91d821a
|
||||||
F test/func.test 830d352574c7f5cd15149a9be58a6dcc2b995c05
|
F test/func.test 830d352574c7f5cd15149a9be58a6dcc2b995c05
|
||||||
F test/hook.test f8605cde4c77b2c6a4a73723bf6c507796a64dda
|
F test/hook.test f8605cde4c77b2c6a4a73723bf6c507796a64dda
|
||||||
@@ -143,6 +143,7 @@ F test/limit.test f7c06fccd76755e8d083b61c06bc31cf461b9c35
|
|||||||
F test/lock.test ba72c211499b0874c56643b9ede1df4018bb20de
|
F test/lock.test ba72c211499b0874c56643b9ede1df4018bb20de
|
||||||
F test/lock2.test 59c3dd7d9b24d1bf7ec91b2d1541c37e97939d5f
|
F test/lock2.test 59c3dd7d9b24d1bf7ec91b2d1541c37e97939d5f
|
||||||
F test/lock3.test 615111293cf32aa2ed16d01c6611737651c96fb9
|
F test/lock3.test 615111293cf32aa2ed16d01c6611737651c96fb9
|
||||||
|
F test/lock4.test 07768b4d4e942693d6036f1e6502199a3fa22a4f
|
||||||
F test/main.test 5f9deae11b93336da1ccc5f91cf8be075c91ddf1
|
F test/main.test 5f9deae11b93336da1ccc5f91cf8be075c91ddf1
|
||||||
F test/malloc.test 769b240d89a7ef3320d88919fdb6765f9395a51f
|
F test/malloc.test 769b240d89a7ef3320d88919fdb6765f9395a51f
|
||||||
F test/memdb.test 34ee8598de307a16ccc3ac91b85cee9c668ae5ed
|
F test/memdb.test 34ee8598de307a16ccc3ac91b85cee9c668ae5ed
|
||||||
@@ -206,7 +207,7 @@ F tool/lempar.c 1e61d2b6cb9d8affa264a13336bc0c088498caa4
|
|||||||
F tool/memleak.awk b744b6109566206c746d826f6ecdba34662216bc
|
F tool/memleak.awk b744b6109566206c746d826f6ecdba34662216bc
|
||||||
F tool/memleak2.awk 9cc20c8e8f3c675efac71ea0721ee6874a1566e8
|
F tool/memleak2.awk 9cc20c8e8f3c675efac71ea0721ee6874a1566e8
|
||||||
F tool/memleak3.tcl 336eb50b0849dbf99b1d5462d9c37291b01b2b43
|
F tool/memleak3.tcl 336eb50b0849dbf99b1d5462d9c37291b01b2b43
|
||||||
F tool/mkkeywordhash.c 5f0d8bd4928e84e736469f9c989dae239314138e
|
F tool/mkkeywordhash.c c2254c191456316ce5d3f72a6b44fbf3c6492816
|
||||||
F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e x
|
F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e x
|
||||||
F tool/opcodeDoc.awk b3a2a3d5d3075b8bd90b7afe24283efdd586659c
|
F tool/opcodeDoc.awk b3a2a3d5d3075b8bd90b7afe24283efdd586659c
|
||||||
F tool/report1.txt 9eae07f26a8fc53889b45fc833a66a33daa22816
|
F tool/report1.txt 9eae07f26a8fc53889b45fc833a66a33daa22816
|
||||||
@@ -258,7 +259,7 @@ F www/tclsqlite.tcl 560ecd6a916b320e59f2917317398f3d59b7cc25
|
|||||||
F www/vdbe.tcl 095f106d93875c94b47367384ebc870517431618
|
F www/vdbe.tcl 095f106d93875c94b47367384ebc870517431618
|
||||||
F www/version3.tcl 092a01f5ef430d2c4acc0ae558d74c4bb89638a0
|
F www/version3.tcl 092a01f5ef430d2c4acc0ae558d74c4bb89638a0
|
||||||
F www/whentouse.tcl fdacb0ba2d39831e8a6240d05a490026ad4c4e4c
|
F www/whentouse.tcl fdacb0ba2d39831e8a6240d05a490026ad4c4e4c
|
||||||
P e05f52d907e267b4f9ea204427229e7d7ef58641
|
P e1530854c9004c25f5ffa21f9cfb9c44c83cc7f0
|
||||||
R 41b0c2001282ed7479703649a89b1f7a
|
R fc41b89835631b13a4149106e5db9d17
|
||||||
U danielk1977
|
U danielk1977
|
||||||
Z f5df5e3af5cd05954b652b1bc18662f8
|
Z a4a4e7382bd227dede1f241a7eed092d
|
||||||
|
@@ -1 +1 @@
|
|||||||
e1530854c9004c25f5ffa21f9cfb9c44c83cc7f0
|
49268c2b7a84c4c618214dac8bef0f541440fe6b
|
47
src/func.c
47
src/func.c
@@ -16,7 +16,7 @@
|
|||||||
** sqliteRegisterBuildinFunctions() found at the bottom of the file.
|
** sqliteRegisterBuildinFunctions() found at the bottom of the file.
|
||||||
** All other code has file scope.
|
** All other code has file scope.
|
||||||
**
|
**
|
||||||
** $Id: func.c,v 1.87 2004/11/14 21:56:30 drh Exp $
|
** $Id: func.c,v 1.88 2004/11/17 16:41:30 danielk1977 Exp $
|
||||||
*/
|
*/
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
@@ -347,10 +347,11 @@ static const struct compareInfo likeInfo = { '%', '_', 0, 1 };
|
|||||||
**
|
**
|
||||||
** abc[*]xyz Matches "abc*xyz" only
|
** abc[*]xyz Matches "abc*xyz" only
|
||||||
*/
|
*/
|
||||||
int patternCompare(
|
static int patternCompare(
|
||||||
const u8 *zPattern, /* The glob pattern */
|
const u8 *zPattern, /* The glob pattern */
|
||||||
const u8 *zString, /* The string to compare against the glob */
|
const u8 *zString, /* The string to compare against the glob */
|
||||||
const struct compareInfo *pInfo /* Information about how to do the compare */
|
const struct compareInfo *pInfo, /* Information about how to do the compare */
|
||||||
|
const int esc /* The escape character */
|
||||||
){
|
){
|
||||||
register int c;
|
register int c;
|
||||||
int invert;
|
int invert;
|
||||||
@@ -360,9 +361,10 @@ int patternCompare(
|
|||||||
u8 matchAll = pInfo->matchAll;
|
u8 matchAll = pInfo->matchAll;
|
||||||
u8 matchSet = pInfo->matchSet;
|
u8 matchSet = pInfo->matchSet;
|
||||||
u8 noCase = pInfo->noCase;
|
u8 noCase = pInfo->noCase;
|
||||||
|
int prevEscape = 0; /* True if the previous character was 'escape' */
|
||||||
|
|
||||||
while( (c = *zPattern)!=0 ){
|
while( (c = *zPattern)!=0 ){
|
||||||
if( c==matchAll ){
|
if( !prevEscape && c==matchAll ){
|
||||||
while( (c=zPattern[1]) == matchAll || c == matchOne ){
|
while( (c=zPattern[1]) == matchAll || c == matchOne ){
|
||||||
if( c==matchOne ){
|
if( c==matchOne ){
|
||||||
if( *zString==0 ) return 0;
|
if( *zString==0 ) return 0;
|
||||||
@@ -370,9 +372,15 @@ int patternCompare(
|
|||||||
}
|
}
|
||||||
zPattern++;
|
zPattern++;
|
||||||
}
|
}
|
||||||
|
if( c && sqlite3ReadUtf8(&zPattern[1])==esc ){
|
||||||
|
u8 const *zTemp = &zPattern[1];
|
||||||
|
sqliteNextChar(zTemp);
|
||||||
|
c = *zTemp;
|
||||||
|
}
|
||||||
if( c==0 ) return 1;
|
if( c==0 ) return 1;
|
||||||
if( c==matchSet ){
|
if( c==matchSet ){
|
||||||
while( *zString && patternCompare(&zPattern[1],zString,pInfo)==0 ){
|
assert( esc==0 ); /* This is GLOB, not LIKE */
|
||||||
|
while( *zString && patternCompare(&zPattern[1],zString,pInfo,esc)==0 ){
|
||||||
sqliteNextChar(zString);
|
sqliteNextChar(zString);
|
||||||
}
|
}
|
||||||
return *zString!=0;
|
return *zString!=0;
|
||||||
@@ -386,17 +394,18 @@ int patternCompare(
|
|||||||
while( c2 != 0 && c2 != c ){ c2 = *++zString; }
|
while( c2 != 0 && c2 != c ){ c2 = *++zString; }
|
||||||
}
|
}
|
||||||
if( c2==0 ) return 0;
|
if( c2==0 ) return 0;
|
||||||
if( patternCompare(&zPattern[1],zString,pInfo) ) return 1;
|
if( patternCompare(&zPattern[1],zString,pInfo,esc) ) return 1;
|
||||||
sqliteNextChar(zString);
|
sqliteNextChar(zString);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}else if( c==matchOne ){
|
}else if( !prevEscape && c==matchOne ){
|
||||||
if( *zString==0 ) return 0;
|
if( *zString==0 ) return 0;
|
||||||
sqliteNextChar(zString);
|
sqliteNextChar(zString);
|
||||||
zPattern++;
|
zPattern++;
|
||||||
}else if( c==matchSet ){
|
}else if( c==matchSet ){
|
||||||
int prior_c = 0;
|
int prior_c = 0;
|
||||||
|
assert( esc==0 ); /* This only occurs for GLOB, not LIKE */
|
||||||
seen = 0;
|
seen = 0;
|
||||||
invert = 0;
|
invert = 0;
|
||||||
c = sqliteCharVal(zString);
|
c = sqliteCharVal(zString);
|
||||||
@@ -424,6 +433,9 @@ int patternCompare(
|
|||||||
if( c2==0 || (seen ^ invert)==0 ) return 0;
|
if( c2==0 || (seen ^ invert)==0 ) return 0;
|
||||||
sqliteNextChar(zString);
|
sqliteNextChar(zString);
|
||||||
zPattern++;
|
zPattern++;
|
||||||
|
}else if( !prevEscape && sqlite3ReadUtf8(zPattern)==esc){
|
||||||
|
prevEscape = 1;
|
||||||
|
sqliteNextChar(zPattern);
|
||||||
}else{
|
}else{
|
||||||
if( noCase ){
|
if( noCase ){
|
||||||
if( sqlite3UpperToLower[c] != sqlite3UpperToLower[*zString] ) return 0;
|
if( sqlite3UpperToLower[c] != sqlite3UpperToLower[*zString] ) return 0;
|
||||||
@@ -432,6 +444,7 @@ int patternCompare(
|
|||||||
}
|
}
|
||||||
zPattern++;
|
zPattern++;
|
||||||
zString++;
|
zString++;
|
||||||
|
prevEscape = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return *zString==0;
|
return *zString==0;
|
||||||
@@ -457,8 +470,21 @@ static void likeFunc(
|
|||||||
){
|
){
|
||||||
const unsigned char *zA = sqlite3_value_text(argv[0]);
|
const unsigned char *zA = sqlite3_value_text(argv[0]);
|
||||||
const unsigned char *zB = sqlite3_value_text(argv[1]);
|
const unsigned char *zB = sqlite3_value_text(argv[1]);
|
||||||
|
int escape = 0;
|
||||||
|
if( argc==3 ){
|
||||||
|
/* The escape character string must consist of a single UTF-8 character.
|
||||||
|
** Otherwise, return an error.
|
||||||
|
*/
|
||||||
|
const unsigned char *zEsc = sqlite3_value_text(argv[2]);
|
||||||
|
if( sqlite3utf8CharLen(zEsc, -1)!=1 ){
|
||||||
|
sqlite3_result_error(context,
|
||||||
|
"ESCAPE expression must be a single character", -1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
escape = sqlite3ReadUtf8(zEsc);
|
||||||
|
}
|
||||||
if( zA && zB ){
|
if( zA && zB ){
|
||||||
sqlite3_result_int(context, patternCompare(zA, zB, &likeInfo));
|
sqlite3_result_int(context, patternCompare(zA, zB, &likeInfo, escape));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -469,13 +495,13 @@ static void likeFunc(
|
|||||||
**
|
**
|
||||||
** A GLOB B
|
** A GLOB B
|
||||||
**
|
**
|
||||||
** is implemented as glob(A,B).
|
** is implemented as glob(B,A).
|
||||||
*/
|
*/
|
||||||
static void globFunc(sqlite3_context *context, int arg, sqlite3_value **argv){
|
static void globFunc(sqlite3_context *context, int arg, sqlite3_value **argv){
|
||||||
const unsigned char *zA = sqlite3_value_text(argv[0]);
|
const unsigned char *zA = sqlite3_value_text(argv[0]);
|
||||||
const unsigned char *zB = sqlite3_value_text(argv[1]);
|
const unsigned char *zB = sqlite3_value_text(argv[1]);
|
||||||
if( zA && zB ){
|
if( zA && zB ){
|
||||||
sqlite3_result_int(context, patternCompare(zA, zB, &globInfo));
|
sqlite3_result_int(context, patternCompare(zA, zB, &globInfo, 0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -992,6 +1018,7 @@ void sqlite3RegisterBuiltinFunctions(sqlite3 *db){
|
|||||||
{ "ifnull", 2, 0, SQLITE_UTF8, 1, ifnullFunc },
|
{ "ifnull", 2, 0, SQLITE_UTF8, 1, ifnullFunc },
|
||||||
{ "random", -1, 0, SQLITE_UTF8, 0, randomFunc },
|
{ "random", -1, 0, SQLITE_UTF8, 0, randomFunc },
|
||||||
{ "like", 2, 0, SQLITE_UTF8, 0, likeFunc },
|
{ "like", 2, 0, SQLITE_UTF8, 0, likeFunc },
|
||||||
|
{ "like", 3, 0, SQLITE_UTF8, 0, likeFunc },
|
||||||
{ "glob", 2, 0, SQLITE_UTF8, 0, globFunc },
|
{ "glob", 2, 0, SQLITE_UTF8, 0, globFunc },
|
||||||
{ "nullif", 2, 0, SQLITE_UTF8, 1, nullifFunc },
|
{ "nullif", 2, 0, SQLITE_UTF8, 1, nullifFunc },
|
||||||
{ "sqlite_version", 0, 0, SQLITE_UTF8, 0, versionFunc},
|
{ "sqlite_version", 0, 0, SQLITE_UTF8, 0, versionFunc},
|
||||||
|
12
src/parse.y
12
src/parse.y
@@ -14,7 +14,7 @@
|
|||||||
** the parser. Lemon will also generate a header file containing
|
** the parser. Lemon will also generate a header file containing
|
||||||
** numeric codes for all of the tokens.
|
** numeric codes for all of the tokens.
|
||||||
**
|
**
|
||||||
** @(#) $Id: parse.y,v 1.156 2004/11/13 15:59:15 drh Exp $
|
** @(#) $Id: parse.y,v 1.157 2004/11/17 16:41:30 danielk1977 Exp $
|
||||||
*/
|
*/
|
||||||
%token_prefix TK_
|
%token_prefix TK_
|
||||||
%token_type {Token}
|
%token_type {Token}
|
||||||
@@ -169,6 +169,7 @@ id(A) ::= ID(X). {A = X;}
|
|||||||
%right NOT.
|
%right NOT.
|
||||||
%left IS LIKE GLOB BETWEEN IN ISNULL NOTNULL NE EQ.
|
%left IS LIKE GLOB BETWEEN IN ISNULL NOTNULL NE EQ.
|
||||||
%left GT LE LT GE.
|
%left GT LE LT GE.
|
||||||
|
%right ESCAPE.
|
||||||
%left BITAND BITOR LSHIFT RSHIFT.
|
%left BITAND BITOR LSHIFT RSHIFT.
|
||||||
%left PLUS MINUS.
|
%left PLUS MINUS.
|
||||||
%left STAR SLASH REM.
|
%left STAR SLASH REM.
|
||||||
@@ -637,14 +638,21 @@ likeop(A) ::= LIKE. {A.opcode = TK_LIKE; A.not = 0;}
|
|||||||
likeop(A) ::= GLOB. {A.opcode = TK_GLOB; A.not = 0;}
|
likeop(A) ::= GLOB. {A.opcode = TK_GLOB; A.not = 0;}
|
||||||
likeop(A) ::= NOT LIKE. {A.opcode = TK_LIKE; A.not = 1;}
|
likeop(A) ::= NOT LIKE. {A.opcode = TK_LIKE; A.not = 1;}
|
||||||
likeop(A) ::= NOT GLOB. {A.opcode = TK_GLOB; A.not = 1;}
|
likeop(A) ::= NOT GLOB. {A.opcode = TK_GLOB; A.not = 1;}
|
||||||
expr(A) ::= expr(X) likeop(OP) expr(Y). [LIKE] {
|
%type escape {Expr*}
|
||||||
|
escape(X) ::= ESCAPE expr(A). [ESCAPE] {X = A;}
|
||||||
|
escape(X) ::= . [ESCAPE] {X = 0;}
|
||||||
|
expr(A) ::= expr(X) likeop(OP) expr(Y) escape(E). [LIKE] {
|
||||||
ExprList *pList = sqlite3ExprListAppend(0, Y, 0);
|
ExprList *pList = sqlite3ExprListAppend(0, Y, 0);
|
||||||
pList = sqlite3ExprListAppend(pList, X, 0);
|
pList = sqlite3ExprListAppend(pList, X, 0);
|
||||||
|
if( E ){
|
||||||
|
pList = sqlite3ExprListAppend(pList, E, 0);
|
||||||
|
}
|
||||||
A = sqlite3ExprFunction(pList, 0);
|
A = sqlite3ExprFunction(pList, 0);
|
||||||
if( A ) A->op = OP.opcode;
|
if( A ) A->op = OP.opcode;
|
||||||
if( OP.not ) A = sqlite3Expr(TK_NOT, A, 0, 0);
|
if( OP.not ) A = sqlite3Expr(TK_NOT, A, 0, 0);
|
||||||
sqlite3ExprSpan(A, &X->span, &Y->span);
|
sqlite3ExprSpan(A, &X->span, &Y->span);
|
||||||
}
|
}
|
||||||
|
|
||||||
expr(A) ::= expr(X) ISNULL(E). {
|
expr(A) ::= expr(X) ISNULL(E). {
|
||||||
A = sqlite3Expr(TK_ISNULL, X, 0, 0);
|
A = sqlite3Expr(TK_ISNULL, X, 0, 0);
|
||||||
sqlite3ExprSpan(A,&X->span,&E);
|
sqlite3ExprSpan(A,&X->span,&E);
|
||||||
|
@@ -11,7 +11,7 @@
|
|||||||
# This file implements regression tests for SQLite library. The
|
# This file implements regression tests for SQLite library. The
|
||||||
# focus of this file is testing expressions.
|
# focus of this file is testing expressions.
|
||||||
#
|
#
|
||||||
# $Id: expr.test,v 1.39 2004/11/15 01:40:48 drh Exp $
|
# $Id: expr.test,v 1.40 2004/11/17 16:41:29 danielk1977 Exp $
|
||||||
|
|
||||||
set testdir [file dirname $argv0]
|
set testdir [file dirname $argv0]
|
||||||
source $testdir/tester.tcl
|
source $testdir/tester.tcl
|
||||||
@@ -267,6 +267,45 @@ test_expr expr-5.55 {t1='abc', t2=NULL} {t1 NOT LIKE t2} {{}}
|
|||||||
test_expr expr-5.56 {t1='abc', t2=NULL} {t2 LIKE t1} {{}}
|
test_expr expr-5.56 {t1='abc', t2=NULL} {t2 LIKE t1} {{}}
|
||||||
test_expr expr-5.57 {t1='abc', t2=NULL} {t2 NOT LIKE t1} {{}}
|
test_expr expr-5.57 {t1='abc', t2=NULL} {t2 NOT LIKE t1} {{}}
|
||||||
|
|
||||||
|
# LIKE expressions that use ESCAPE characters.
|
||||||
|
test_expr expr-5.58 {t1='abc', t2='A_C'} {t1 LIKE t2 ESCAPE '7'} 1
|
||||||
|
test_expr expr-5.59 {t1='a_c', t2='A7_C'} {t1 LIKE t2 ESCAPE '7'} 1
|
||||||
|
test_expr expr-5.60 {t1='abc', t2='A7_C'} {t1 LIKE t2 ESCAPE '7'} 0
|
||||||
|
test_expr expr-5.61 {t1='a7Xc', t2='A7_C'} {t1 LIKE t2 ESCAPE '7'} 0
|
||||||
|
test_expr expr-5.62 {t1='abcde', t2='A%E'} {t1 LIKE t2 ESCAPE '7'} 1
|
||||||
|
test_expr expr-5.63 {t1='abcde', t2='A7%E'} {t1 LIKE t2 ESCAPE '7'} 0
|
||||||
|
test_expr expr-5.64 {t1='a7cde', t2='A7%E'} {t1 LIKE t2 ESCAPE '7'} 0
|
||||||
|
test_expr expr-5.65 {t1='a7cde', t2='A77%E'} {t1 LIKE t2 ESCAPE '7'} 1
|
||||||
|
test_expr expr-5.66 {t1='abc7', t2='A%77'} {t1 LIKE t2 ESCAPE '7'} 1
|
||||||
|
test_expr expr-5.67 {t1='abc_', t2='A%7_'} {t1 LIKE t2 ESCAPE '7'} 1
|
||||||
|
test_expr expr-5.68 {t1='abc7', t2='A%7_'} {t1 LIKE t2 ESCAPE '7'} 0
|
||||||
|
|
||||||
|
# These are the same test as the block above, but using a multi-byte
|
||||||
|
# character as the escape character.
|
||||||
|
if {"\u1234"!="u1234"} {
|
||||||
|
test_expr expr-5.69 "t1='abc', t2='A_C'" \
|
||||||
|
"t1 LIKE t2 ESCAPE '\u1234'" 1
|
||||||
|
test_expr expr-5.70 "t1='a_c', t2='A\u1234_C'" \
|
||||||
|
"t1 LIKE t2 ESCAPE '\u1234'" 1
|
||||||
|
test_expr expr-5.71 "t1='abc', t2='A\u1234_C'" \
|
||||||
|
"t1 LIKE t2 ESCAPE '\u1234'" 0
|
||||||
|
test_expr expr-5.72 "t1='a\u1234Xc', t2='A\u1234_C'" \
|
||||||
|
"t1 LIKE t2 ESCAPE '\u1234'" 0
|
||||||
|
test_expr expr-5.73 "t1='abcde', t2='A%E'" \
|
||||||
|
"t1 LIKE t2 ESCAPE '\u1234'" 1
|
||||||
|
test_expr expr-5.74 "t1='abcde', t2='A\u1234%E'" \
|
||||||
|
"t1 LIKE t2 ESCAPE '\u1234'" 0
|
||||||
|
test_expr expr-5.75 "t1='a\u1234cde', t2='A\u1234%E'" \
|
||||||
|
"t1 LIKE t2 ESCAPE '\u1234'" 0
|
||||||
|
test_expr expr-5.76 "t1='a\u1234cde', t2='A\u1234\u1234%E'" \
|
||||||
|
"t1 LIKE t2 ESCAPE '\u1234'" 1
|
||||||
|
test_expr expr-5.77 "t1='abc\u1234', t2='A%\u1234\u1234'" \
|
||||||
|
"t1 LIKE t2 ESCAPE '\u1234'" 1
|
||||||
|
test_expr expr-5.78 "t1='abc_', t2='A%\u1234_'" \
|
||||||
|
"t1 LIKE t2 ESCAPE '\u1234'" 1
|
||||||
|
test_expr expr-5.79 "t1='abc\u1234', t2='A%\u1234_'" \
|
||||||
|
"t1 LIKE t2 ESCAPE '\u1234'" 0
|
||||||
|
}
|
||||||
|
|
||||||
test_expr expr-6.1 {t1='abc', t2='xyz'} {t1 GLOB t2} 0
|
test_expr expr-6.1 {t1='abc', t2='xyz'} {t1 GLOB t2} 0
|
||||||
test_expr expr-6.2 {t1='abc', t2='ABC'} {t1 GLOB t2} 0
|
test_expr expr-6.2 {t1='abc', t2='ABC'} {t1 GLOB t2} 0
|
||||||
|
117
test/lock4.test
Normal file
117
test/lock4.test
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
# 2001 September 15
|
||||||
|
#
|
||||||
|
# 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. The focus
|
||||||
|
# of this file is modifications made to tables while SELECT queries are
|
||||||
|
# active on the tables. Using this capability in a program is tricky
|
||||||
|
# because results can be difficult to predict, but can be useful.
|
||||||
|
#
|
||||||
|
# $Id: lock4.test,v 1.1 2004/11/17 16:41:29 danielk1977 Exp $
|
||||||
|
#
|
||||||
|
|
||||||
|
set testdir [file dirname $argv0]
|
||||||
|
source $testdir/tester.tcl
|
||||||
|
|
||||||
|
do_test lock4-1.0 {
|
||||||
|
execsql {
|
||||||
|
CREATE TABLE t1(a, b);
|
||||||
|
INSERT INTO t1 VALUES(1, 2);
|
||||||
|
}
|
||||||
|
} {}
|
||||||
|
|
||||||
|
# Check that we can INSERT into a table while doing a SELECT on it.
|
||||||
|
do_test lock4-1.1 {
|
||||||
|
db eval {SELECT * FROM t1} {
|
||||||
|
if {$a<5} {
|
||||||
|
execsql "INSERT INTO t1 VALUES($a+1, ($a+1)*2)"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} {}
|
||||||
|
do_test lock4-1.2 {
|
||||||
|
execsql {
|
||||||
|
SELECT * FROM t1
|
||||||
|
}
|
||||||
|
} {1 2 2 4 3 6 4 8 5 10}
|
||||||
|
|
||||||
|
# Check that we can UPDATE a table while doing a SELECT on it.
|
||||||
|
do_test lock4-1.3 {
|
||||||
|
db eval {SELECT * FROM t1 WHERE (a%2)=0} {
|
||||||
|
execsql "UPDATE t1 SET b = b/2 WHERE a = $a"
|
||||||
|
}
|
||||||
|
} {}
|
||||||
|
do_test lock4-1.4 {
|
||||||
|
execsql {
|
||||||
|
SELECT * FROM t1
|
||||||
|
}
|
||||||
|
} {1 2 2 2 3 6 4 4 5 10}
|
||||||
|
|
||||||
|
# Check that we can DELETE from a table while doing a SELECT on it.
|
||||||
|
do_test lock4-1.5 {
|
||||||
|
db eval {SELECT * FROM t1 WHERE (a%2)=0} {
|
||||||
|
execsql "DELETE FROM t1 WHERE a = $a"
|
||||||
|
}
|
||||||
|
} {}
|
||||||
|
do_test lock4-1.6 {
|
||||||
|
execsql {
|
||||||
|
SELECT * FROM t1
|
||||||
|
}
|
||||||
|
} {1 2 3 6 5 10}
|
||||||
|
|
||||||
|
# Check what happens when a row is deleted while a cursor is still using
|
||||||
|
# the row (because of a SELECT that does a join).
|
||||||
|
do_test lock4-2.0 {
|
||||||
|
execsql {
|
||||||
|
CREATE TABLE t2(c);
|
||||||
|
INSERT INTO t2 VALUES('one');
|
||||||
|
INSERT INTO t2 VALUES('two');
|
||||||
|
}
|
||||||
|
} {}
|
||||||
|
do_test lock4-2.1 {
|
||||||
|
set res [list]
|
||||||
|
db eval {SELECT a, b, c FROM t1, t2} {
|
||||||
|
lappend res $a $b $c
|
||||||
|
if {0==[string compare $c one]} {
|
||||||
|
execsql "DELETE FROM t1 WHERE a = $a"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
set res
|
||||||
|
} {1 2 one 1 2 two 3 6 one 3 6 two 5 10 one 5 10 two}
|
||||||
|
do_test lock4-2.2 {
|
||||||
|
execsql {
|
||||||
|
SELECT * FROM t1;
|
||||||
|
}
|
||||||
|
} {}
|
||||||
|
|
||||||
|
# do_test lock4-2.3 {
|
||||||
|
# execsql "
|
||||||
|
# INSERT INTO t1 VALUES('[string repeat 1 750]', '[string repeat 2 750]')
|
||||||
|
# "
|
||||||
|
# } {}
|
||||||
|
# do_test lock4-2.4 {
|
||||||
|
# set res [list]
|
||||||
|
# db eval {SELECT a, b, c FROM t1, t2} {
|
||||||
|
# lappend res $a $b $c
|
||||||
|
# if {0==[string compare $c one]} {
|
||||||
|
# execsql "DELETE FROM t1 WHERE a = '$a'"
|
||||||
|
# }
|
||||||
|
# }
|
||||||
|
# set res
|
||||||
|
# } [list \
|
||||||
|
# [string repeat 1 750] [string repeat 2 750] one \
|
||||||
|
# [string repeat 1 750] [string repeat 2 750] two
|
||||||
|
# ]
|
||||||
|
# do_test lock4-2.5 {
|
||||||
|
# execsql {
|
||||||
|
# SELECT * FROM t1;
|
||||||
|
# }
|
||||||
|
# } {}
|
||||||
|
|
||||||
|
finish_test
|
||||||
|
|
@@ -133,6 +133,7 @@ static Keyword aKeywordTable[] = {
|
|||||||
{ "END", "TK_END", ALWAYS },
|
{ "END", "TK_END", ALWAYS },
|
||||||
{ "EACH", "TK_EACH", TRIGGER },
|
{ "EACH", "TK_EACH", TRIGGER },
|
||||||
{ "ELSE", "TK_ELSE", ALWAYS },
|
{ "ELSE", "TK_ELSE", ALWAYS },
|
||||||
|
{ "ESCAPE", "TK_ESCAPE", ALWAYS },
|
||||||
{ "EXCEPT", "TK_EXCEPT", COMPOUND },
|
{ "EXCEPT", "TK_EXCEPT", COMPOUND },
|
||||||
{ "EXCLUSIVE", "TK_EXCLUSIVE", ALWAYS },
|
{ "EXCLUSIVE", "TK_EXCLUSIVE", ALWAYS },
|
||||||
{ "EXPLAIN", "TK_EXPLAIN", EXPLAIN },
|
{ "EXPLAIN", "TK_EXPLAIN", EXPLAIN },
|
||||||
|
Reference in New Issue
Block a user