mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-01 06:27:03 +03:00
Added support for CASE expressions - patches from Dan Kennedy. (CVS 437)
FossilOrigin-Name: 836b59d057c3fb4087b138c9bfbc03392ddfb89d
This commit is contained in:
45
src/expr.c
45
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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
25
src/parse.y
25
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($$);}
|
||||
|
@ -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 },
|
||||
};
|
||||
|
||||
|
Reference in New Issue
Block a user