-C Version\s2.4.3\s(CVS\s440)
-D 2002-03-23T01:00:00
+C Added\ssupport\sfor\sCASE\sexpressions\s-\spatches\sfrom\sDan\sKennedy.\s(CVS\s437)
+D 2002-03-24T13:13:28
F Makefile.in 50f1b3351df109b5774771350d8c1b8d3640130d
F Makefile.template 89e373b2dad0321df00400fa968dc14b61a03296
F README a4c0ba11354ef6ba0776b400d057c59da47a4cc0
-F VERSION 50919ab26b7c119efb3f2fa5000696e75a9fb378
+F VERSION 709d6814e7f7be60eddfd0c173f583061695e9b6
F aclocal.m4 11faa843caa38fd451bc6aeb43e248d1723a269d
F config.guess f38b1e93d1e0fa6f5a6913e9e7b12774b9232588
F config.log 6a73d03433669b10a3f0c221198c3f26b9413914
F src/btree.h 8abeabfe6e0b1a990b64fa457592a6482f6674f3
F src/build.c d01b81f41481e733e27ab2fa8e1bfcc64f24257d
F src/delete.c 577da499162291c1855f0b304b211bffcf9da945
-F src/expr.c 0752b45ac5913575c9dfb47ef2d5ac4705df7f3b
+F src/expr.c e7a1e22bc2ebcd789f0f8c0db544cf16ad664054
F src/func.c 87516e7dc37190c24af77593931a5d09d797520a
F src/hash.c cc259475e358baaf299b00a2c7370f2b03dda892
F src/hash.h dca065dda89d4575f3176e75e9a3dc0f4b4fb8b9
F src/os.h 4a361fccfbc4e7609b3e1557f604f94c1e96ad10
F src/pager.c f136f5ba82c896d500a10b6a2e5caea62abf716b
F src/pager.h 6fddfddd3b73aa8abc081b973886320e3c614f0e
-F src/parse.y 9a8be2eebad16f636292967d328882c2d07e30a9
+F src/parse.y e6f300a355459fb29a71c30246be4cdb6ed5b6a7
F src/printf.c 300a90554345751f26e1fc0c0333b90a66110a1d
F src/random.c 19e8e00fe0df32a742f115773f57651be327cabe
F src/select.c 9323800e2937e84b52c198fffc51995d822b1779
F src/test2.c d410dbd8a90faa466c3ab694fa0aa57f5a773aa6
F src/test3.c 4e52fff8b01f08bd202f7633feda5639b7ba2b5e
F src/threadtest.c 81f0598e0f031c1bd506af337fdc1b7e8dff263f
-F src/tokenize.c 5015a5d4e65afb8cc6d18083d5f19a008e3842ce
+F src/tokenize.c 5624d342601f616157ba266abccc1368a5afee70
F src/update.c 7dd714a6a7fa47f849ebb36b6d915974d6c6accb
F src/util.c b34cd91387bbfdc79319ea451a7d120cef478120
F src/vdbe.c 9fbe84ea33dddb08d95f3288d995376d32863fa4
F test/conflict.test c794c6c8f6e59918107dbab2d201ae454bb47db8
F test/copy.test b3cefcb520c64d7e7dfedbab06b4d4c31fa5b99a
F test/delete.test c904a62129fe102b314a96111a8417f10249e4d8
-F test/expr.test c8a495050dcec3f9e68538c3ef466726933302c1
+F test/expr.test 846795016b5993a7411f772eebe82ab67bd7230a
F test/func.test 4359344586067e79abf4c710c4737d67ed3cf963
F test/in.test c09312672e3f0709fa02c8e2e9cd8fb4bd6269aa
F test/index.test c8a471243bbf878974b99baf5badd59407237cf3
F www/sqlite.tcl 8b5884354cb615049aed83039f8dfe1552a44279
F www/tclsqlite.tcl 829b393d1ab187fd7a5e978631b3429318885c49
F www/vdbe.tcl 2013852c27a02a091d39a766bc87cff329f21218
-P e2558c34034cf49524084ec819df58934a8af983
-R b3affb1ebed689441f43f9512795f044
+P 99d6764e57ddc7f0a321229cc1b7aa9a76f1aae5
+R 2c07c24bb32189e5643cb9ff23369e12
U drh
-Z d8af9dfdacb01b6b9297504ec54586e1
+Z efaaf0dd01ae4aa4e97af0ad8b65ddc7
-99d6764e57ddc7f0a321229cc1b7aa9a76f1aae5
\ No newline at end of file
+836b59d057c3fb4087b138c9bfbc03392ddfb89d
\ No newline at end of file
** This file contains routines used for analyzing expressions and
** for generating VDBE code that evaluates expressions in SQLite.
**
-** $Id: expr.c,v 1.56 2002/03/13 18:54:07 drh Exp $
+** $Id: expr.c,v 1.57 2002/03/24 13:13:29 drh Exp $
*/
#include "sqliteInt.h"
sqliteExprCode(pParse, pExpr->pLeft);
break;
}
+ case TK_CASE: {
+ int expr_end_label;
+ int next_when_label;
+ int i;
+
+ assert(pExpr->pList);
+ assert((pExpr->pList->nExpr % 2) == 0);
+ assert(pExpr->pList->nExpr > 0);
+ expr_end_label = sqliteVdbeMakeLabel(pParse->pVdbe);
+ if( pExpr->pLeft ){
+ sqliteExprCode(pParse, pExpr->pLeft);
+ }
+ for(i=0; i<pExpr->pList->nExpr; i=i+2){
+ if( i!=0 ){
+ sqliteVdbeResolveLabel(pParse->pVdbe, next_when_label);
+ }
+ next_when_label = sqliteVdbeMakeLabel(pParse->pVdbe);
+ if( pExpr->pLeft ){
+ sqliteVdbeAddOp(pParse->pVdbe, OP_Dup, 0, 1);
+ sqliteExprCode(pParse, pExpr->pList->a[i].pExpr);
+ sqliteVdbeAddOp(pParse->pVdbe, OP_Ne, 0, next_when_label);
+ }else{
+ sqliteExprIfFalse(pParse, pExpr->pList->a[i].pExpr, next_when_label);
+ }
+ if( pExpr->pLeft ){
+ sqliteVdbeAddOp(pParse->pVdbe, OP_Pop, 1, 0);
+ }
+ sqliteExprCode(pParse, pExpr->pList->a[i+1].pExpr);
+ sqliteVdbeAddOp(pParse->pVdbe, OP_Goto, 0, expr_end_label);
+ }
+ sqliteVdbeResolveLabel(pParse->pVdbe, next_when_label);
+ if( pExpr->pLeft ){
+ sqliteVdbeAddOp(pParse->pVdbe, OP_Pop, 1, 0);
+ }
+ if( pExpr->pRight ){
+ sqliteExprCode(pParse, pExpr->pRight);
+ }else{
+ sqliteVdbeAddOp(pParse->pVdbe, OP_String, 0, 0);
+ }
+ sqliteVdbeResolveLabel(pParse->pVdbe, expr_end_label);
+ }
+ break;
}
- return;
}
/*
** the parser. Lemon will also generate a header file containing
** numeric codes for all of the tokens.
**
-** @(#) $Id: parse.y,v 1.57 2002/03/13 18:54:08 drh Exp $
+** @(#) $Id: parse.y,v 1.58 2002/03/24 13:13:29 drh Exp $
*/
%token_prefix TK_
%token_type {Token}
sqliteExprSpan(A,&X->span,&E);
}
-
+/* CASE expressions */
+expr(A) ::= CASE(C) case_operand(X) case_exprlist(Y) case_else(Z) END(E). {
+ A = sqliteExpr(TK_CASE, X, Z, 0);
+ if( A ) A->pList = Y;
+ sqliteExprSpan(A, &C, &E);
+}
+%type case_exprlist {ExprList*}
+%destructor case_exprlist {sqliteExprListDelete($$);}
+case_exprlist(A) ::= case_exprlist(X) WHEN expr(Y) THEN expr(Z). {
+ A = sqliteExprListAppend(X, Y, 0);
+ A = sqliteExprListAppend(A, Z, 0);
+}
+case_exprlist(A) ::= WHEN expr(Y) THEN expr(Z). {
+ A = sqliteExprListAppend(0, Y, 0);
+ A = sqliteExprListAppend(A, Z, 0);
+}
+%type case_else {Expr*}
+case_else(A) ::= ELSE expr(X). {A = X;}
+case_else(A) ::= . {A = 0;}
+%type case_operand {Expr*}
+case_operand(A) ::= expr(X). {A = X;}
+case_operand(A) ::= . {A = 0;}
%type exprlist {ExprList*}
%destructor exprlist {sqliteExprListDelete($$);}
** individual tokens and sends those tokens one-by-one over to the
** parser for analysis.
**
-** $Id: tokenize.c,v 1.39 2002/03/13 18:54:08 drh Exp $
+** $Id: tokenize.c,v 1.40 2002/03/24 13:13:29 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
{ "BEGIN", 0, TK_BEGIN, 0 },
{ "BETWEEN", 0, TK_BETWEEN, 0 },
{ "BY", 0, TK_BY, 0 },
+ { "CASE", 0, TK_CASE, 0 },
{ "CHECK", 0, TK_CHECK, 0 },
{ "CLUSTER", 0, TK_CLUSTER, 0 },
{ "COMMIT", 0, TK_COMMIT, 0 },
{ "DISTINCT", 0, TK_DISTINCT, 0 },
{ "DROP", 0, TK_DROP, 0 },
{ "END", 0, TK_END, 0 },
+ { "ELSE", 0, TK_ELSE, 0 },
{ "EXCEPT", 0, TK_EXCEPT, 0 },
{ "EXPLAIN", 0, TK_EXPLAIN, 0 },
{ "FAIL", 0, TK_FAIL, 0 },
{ "TABLE", 0, TK_TABLE, 0 },
{ "TEMP", 0, TK_TEMP, 0 },
{ "TEMPORARY", 0, TK_TEMP, 0 },
+ { "THEN", 0, TK_THEN, 0 },
{ "TRANSACTION", 0, TK_TRANSACTION, 0 },
{ "UNION", 0, TK_UNION, 0 },
{ "UNIQUE", 0, TK_UNIQUE, 0 },
{ "VACUUM", 0, TK_VACUUM, 0 },
{ "VALUES", 0, TK_VALUES, 0 },
{ "VIEW", 0, TK_VIEW, 0 },
+ { "WHEN", 0, TK_WHEN, 0 },
{ "WHERE", 0, TK_WHERE, 0 },
};
# This file implements regression tests for SQLite library. The
# focus of this file is testing expressions.
#
-# $Id: expr.test,v 1.18 2002/01/15 18:39:45 drh Exp $
+# $Id: expr.test,v 1.19 2002/03/24 13:13:29 drh Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
test_expr expr-6.24 {t1='ac', t2='a*c'} {t1 GLOB t2} 1
test_expr expr-6.25 {t1='ac', t2='a*?c'} {t1 GLOB t2} 0
+test_expr expr-case.1 {i1=1, i2=2} \
+ {CASE WHEN i1 = i2 THEN 'eq' ELSE 'ne' END} ne
+test_expr expr-case.2 {i1=2, i2=2} \
+ {CASE WHEN i1 = i2 THEN 'eq' ELSE 'ne' END} eq
+test_expr expr-case.3 {i1=2} \
+ {CASE i1 WHEN 1 THEN 'one' WHEN 2 THEN 'two' ELSE 'error' END} two
+test_expr expr-case.4 {i1=3} \
+ {CASE i1 WHEN 1 THEN 'one' WHEN 2 THEN 'two' ELSE 'error' END} error
+test_expr expr-case.5 {i1=3} \
+ {CASE i1 WHEN 1 THEN 'one' WHEN 2 THEN 'two' END} {{}}
+test_expr expr-case.6 {i1=7} \
+ { CASE WHEN i1 < 5 THEN 'low'
+ WHEN i1 < 10 THEN 'medium'
+ WHEN i1 < 15 THEN 'high' ELSE 'error' END} medium
+
+
# These tests only work on versions of TCL that support Unicode
#
if {"\u1234"!="u1234" && [sqlite -encoding]=="UTF-8"} {