diff options
author | drh <drh@noemail.net> | 2002-03-24 13:13:27 +0000 |
---|---|---|
committer | drh <drh@noemail.net> | 2002-03-24 13:13:27 +0000 |
commit | 17a7f8ddab5de4975e1141dfb7f0601751b5ce72 (patch) | |
tree | 9bc113fbe4631d800792f4b399919985148241fa /src | |
parent | 6b54e74cf4a7c41e252290247b61d462514a9292 (diff) | |
download | sqlite-17a7f8ddab5de4975e1141dfb7f0601751b5ce72.tar.gz sqlite-17a7f8ddab5de4975e1141dfb7f0601751b5ce72.zip |
Added support for CASE expressions - patches from Dan Kennedy. (CVS 437)
FossilOrigin-Name: 836b59d057c3fb4087b138c9bfbc03392ddfb89d
Diffstat (limited to 'src')
-rw-r--r-- | src/expr.c | 45 | ||||
-rw-r--r-- | src/parse.y | 25 | ||||
-rw-r--r-- | src/tokenize.c | 6 |
3 files changed, 71 insertions, 5 deletions
diff --git a/src/expr.c b/src/expr.c index 793a44ee7..5b0e732c6 100644 --- a/src/expr.c +++ b/src/expr.c @@ -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; } /* diff --git a/src/parse.y b/src/parse.y index ff24a585b..2343d0410 100644 --- a/src/parse.y +++ b/src/parse.y @@ -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($$);} diff --git a/src/tokenize.c b/src/tokenize.c index 5a541cf07..84eaab7f7 100644 --- a/src/tokenize.c +++ b/src/tokenize.c @@ -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 }, }; |