]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Added support for CASE expressions - patches from Dan Kennedy. (CVS 437)
authordrh <drh@noemail.net>
Sun, 24 Mar 2002 13:13:27 +0000 (13:13 +0000)
committerdrh <drh@noemail.net>
Sun, 24 Mar 2002 13:13:27 +0000 (13:13 +0000)
FossilOrigin-Name: 836b59d057c3fb4087b138c9bfbc03392ddfb89d

VERSION
manifest
manifest.uuid
src/expr.c
src/parse.y
src/tokenize.c
test/expr.test

diff --git a/VERSION b/VERSION
index 35cee72dcbf498e180718336516112fda9d8b3c8..79a614418f747a2c5e6c8a8a4c42d12e16b06607 100644 (file)
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-2.4.3
+2.4.4
index 191e12ac53557b1307079ffe59fb513172da657a..937cf195edee7ed252e1f280d65bb14e6c5d0016 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,9 +1,9 @@
-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
@@ -23,7 +23,7 @@ F src/btree.c 7dd7ddc66459982dd0cb9800958c1f8d65a32d9f
 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
@@ -34,7 +34,7 @@ F src/os.c 5ab8b6b4590d0c1ab8e96c67996c170e4462e0fc
 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
@@ -48,7 +48,7 @@ F src/test1.c d46ab7a82a9c16a3b1ee363cb4c0f98c5ff65743
 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
@@ -62,7 +62,7 @@ F test/btree3.test 9caa9e22491dd8cd8aa36d7ac3b48b089817c895
 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
@@ -130,7 +130,7 @@ F www/speed.tcl da8afcc1d3ccc5696cfb388a68982bc3d9f7f00f
 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
index c871fa44334db842d6161b83dc5ef8ff9e3ecacd..1f53f083b769de6c95fdedaa78b2f7e23af9969d 100644 (file)
@@ -1 +1 @@
-99d6764e57ddc7f0a321229cc1b7aa9a76f1aae5
\ No newline at end of file
+836b59d057c3fb4087b138c9bfbc03392ddfb89d
\ No newline at end of file
index 793a44ee7b46b5bdfe5b7eb1f959caa541aa32f4..5b0e732c66200af9b105caf94a511a1ccceb2f4a 100644 (file)
@@ -12,7 +12,7 @@
 ** 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"
 
@@ -877,8 +877,49 @@ void sqliteExprCode(Parse *pParse, Expr *pExpr){
       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;
 }
 
 /*
index ff24a585b1a16b83f9ea017672360718d460d2fe..2343d04108c7ac216ac328a8074c2f8837425531 100644 (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.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}
@@ -520,7 +520,28 @@ expr(A) ::= expr(X) NOT IN LP select(Y) RP(E).  {
   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($$);}
index 5a541cf072c12ec3f6c215f51472bc6e2631beb2..84eaab7f7d7641e190a760c1185518a91ae8da25 100644 (file)
@@ -15,7 +15,7 @@
 ** 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"
@@ -46,6 +46,7 @@ static Keyword aKeywordTable[] = {
   { "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 },
@@ -60,6 +61,7 @@ static Keyword aKeywordTable[] = {
   { "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 },
@@ -94,6 +96,7 @@ static Keyword aKeywordTable[] = {
   { "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 },
@@ -102,6 +105,7 @@ static Keyword aKeywordTable[] = {
   { "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 },
 };
 
index baed96eb8e4c886a4c11c9240e4a81e7e1da1b04..784b802986b7d6bc343ec43b0d4353817d483b9c 100644 (file)
@@ -11,7 +11,7 @@
 # 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
@@ -233,6 +233,22 @@ test_expr expr-6.23 {t1='abcdefg', t2='a*?g'} {t1 GLOB t2} 1
 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"} {