UnQL

Check-in [a9a0c2d16e]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Added support for the ?: operator.
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: a9a0c2d16e4ab03347dc35720755a2b2595d8482
User & Date: drh 2011-07-15 21:15:41
Context
2011-07-16
06:53
Add support for SELECT queries with no FROM clause (i.e. "SELECT <expr>;"). check-in: 61dc9bee92 user: dan tags: trunk
2011-07-15
21:15
Added support for the ?: operator. check-in: a9a0c2d16e user: drh tags: trunk
20:41
Parser changes to bring expression processing closer to javascript. check-in: 47a517ea6e user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/expr.c.

57
58
59
60
61
62
63






64
65
66
67
68
69
70
...
460
461
462
463
464
465
466
467
468
469
470
471
472










473
474
475
476
477
478
479
    rc = pAction->xNodeAction(p, pAction);
  }
  switch( p->eClass ){
    case XJD1_EXPR_BI: {
      walkExpr(p->u.bi.pLeft, pAction);
      walkExpr(p->u.bi.pRight, pAction);
      break;






    }
    case XJD1_EXPR_TK: {
      /* Nothing to do */
      break;
    }
    case XJD1_EXPR_FUNC: {
      walkExprList(p->u.func.args, pAction);
................................................................................
        case TK_BITAND: pRes->u.r = (double)(iLeft & iRight); break;
        case TK_BITOR:  pRes->u.r = (double)(iLeft | iRight); break;
        case TK_REM:    pRes->u.r = (double)(iLeft % iRight); break;
      }
      break;
    }

    case TK_BITNOT:
      pJLeft = xjd1ExprEval(p->u.bi.pLeft);
      xjd1JsonToReal(pJLeft, &rLeft);
      pRes->eJType = XJD1_REAL;
      pRes->u.r = (double)(~((int)rLeft));
      break;











    default: {
      pRes->eJType = XJD1_NULL;
      break;
    }
  }
  return pRes;







>
>
>
>
>
>







 







|





>
>
>
>
>
>
>
>
>
>







57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
...
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
    rc = pAction->xNodeAction(p, pAction);
  }
  switch( p->eClass ){
    case XJD1_EXPR_BI: {
      walkExpr(p->u.bi.pLeft, pAction);
      walkExpr(p->u.bi.pRight, pAction);
      break;
    }
    case XJD1_EXPR_TRI: {
      walkExpr(p->u.tri.pTest, pAction);
      walkExpr(p->u.tri.pIfTrue, pAction);
      walkExpr(p->u.tri.pIfFalse, pAction);
      break;
    }
    case XJD1_EXPR_TK: {
      /* Nothing to do */
      break;
    }
    case XJD1_EXPR_FUNC: {
      walkExprList(p->u.func.args, pAction);
................................................................................
        case TK_BITAND: pRes->u.r = (double)(iLeft & iRight); break;
        case TK_BITOR:  pRes->u.r = (double)(iLeft | iRight); break;
        case TK_REM:    pRes->u.r = (double)(iLeft % iRight); break;
      }
      break;
    }

    case TK_BITNOT: {
      pJLeft = xjd1ExprEval(p->u.bi.pLeft);
      xjd1JsonToReal(pJLeft, &rLeft);
      pRes->eJType = XJD1_REAL;
      pRes->u.r = (double)(~((int)rLeft));
      break;
    }

    case TK_QM: {
      if( xjd1ExprTrue(p->u.tri.pTest) ){
        pRes = xjd1ExprEval(p->u.tri.pIfTrue);
      }else{
        pRes = xjd1ExprEval(p->u.tri.pIfFalse);
      }
      break;
    }

    default: {
      pRes->eJType = XJD1_NULL;
      break;
    }
  }
  return pRes;

Changes to src/parse.y.

145
146
147
148
149
150
151














152
153
154
155
156
157
158
...
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
      pNew->eType = eOp; 
      pNew->eClass = XJD1_EXPR_BI;
      pNew->u.bi.pLeft = pLeft;
      pNew->u.bi.pRight = pRight;
    }
    return pNew;
  }














  /* Generate an Expr object for an lvalue */
  static Expr *lvalueExpr(Parse *p, Expr *pLeft, Token *pId){
    Expr *pNew = xjd1PoolMallocZero(p->pPool, sizeof(*pNew));
    if( pNew ){
      pNew->eType = TK_DOT; 
      pNew->eClass = XJD1_EXPR_LVALUE;
      pNew->u.lvalue.pLeft = pLeft;
................................................................................
expr(A) ::= BANG(OP) expr(X).                    {A = biExpr(p,X,@OP,0);}
expr(A) ::= BITNOT(OP) expr(X).                  {A = biExpr(p,X,@OP,0);}
expr(A) ::= MINUS(OP) expr(X). [BITNOT]          {A = biExpr(p,X,@OP,0);}
expr(A) ::= PLUS(OP) expr(X). [BITNOT]           {A = biExpr(p,X,@OP,0);}
expr(A) ::= LP select(X) RP.                     {A = subqExpr(p,X);}
expr(A) ::= LP expr(X) RP.                       {A = X;}
expr(A) ::= expr(X) COLLATE ID|STRING.           {A = X;}
expr ::= expr QM expr COLON expr.


%type exprlist {ExprList*}
%type nexprlist {ExprList*}
exprlist(A) ::= nexprlist(X).     {A = X;}
exprlist(A) ::= .                 {A = 0;}
nexprlist(A) ::= expr(X).                     {A = apndExpr(p,0,X,0);}
nexprlist(A) ::= nexprlist(X) COMMA expr(Y).  {A = apndExpr(p,X,Y,0);}







>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







|
<







145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
...
296
297
298
299
300
301
302
303

304
305
306
307
308
309
310
      pNew->eType = eOp; 
      pNew->eClass = XJD1_EXPR_BI;
      pNew->u.bi.pLeft = pLeft;
      pNew->u.bi.pRight = pRight;
    }
    return pNew;
  }

  /* Generate an Expr object that is a tertiary operator */
  static Expr *triExpr(Parse *p, Expr *pTest, Expr *pTrue, Expr *pFalse){
    Expr *pNew = xjd1PoolMallocZero(p->pPool, sizeof(*pNew));
    if( pNew ){
      pNew->eType = TK_QM; 
      pNew->eClass = XJD1_EXPR_TRI;
      pNew->u.tri.pTest = pTest;
      pNew->u.tri.pIfTrue = pTrue;
      pNew->u.tri.pIfFalse = pFalse;
    }
    return pNew;
  }

  /* Generate an Expr object for an lvalue */
  static Expr *lvalueExpr(Parse *p, Expr *pLeft, Token *pId){
    Expr *pNew = xjd1PoolMallocZero(p->pPool, sizeof(*pNew));
    if( pNew ){
      pNew->eType = TK_DOT; 
      pNew->eClass = XJD1_EXPR_LVALUE;
      pNew->u.lvalue.pLeft = pLeft;
................................................................................
expr(A) ::= BANG(OP) expr(X).                    {A = biExpr(p,X,@OP,0);}
expr(A) ::= BITNOT(OP) expr(X).                  {A = biExpr(p,X,@OP,0);}
expr(A) ::= MINUS(OP) expr(X). [BITNOT]          {A = biExpr(p,X,@OP,0);}
expr(A) ::= PLUS(OP) expr(X). [BITNOT]           {A = biExpr(p,X,@OP,0);}
expr(A) ::= LP select(X) RP.                     {A = subqExpr(p,X);}
expr(A) ::= LP expr(X) RP.                       {A = X;}
expr(A) ::= expr(X) COLLATE ID|STRING.           {A = X;}
expr(A) ::= expr(X) QM expr(Y) COLON expr(Z).    {A = triExpr(p,X,Y,Z);}


%type exprlist {ExprList*}
%type nexprlist {ExprList*}
exprlist(A) ::= nexprlist(X).     {A = X;}
exprlist(A) ::= .                 {A = 0;}
nexprlist(A) ::= expr(X).                     {A = apndExpr(p,0,X,0);}
nexprlist(A) ::= nexprlist(X) COMMA expr(Y).  {A = apndExpr(p,X,Y,0);}

Changes to src/xjd1Int.h.

161
162
163
164
165
166
167





168
169
170
171
172
173
174
175
176
177

178
179
180
181
182
183
184
      Query *p;                /* The subquery */
    } subq;
    struct {                /* Literal value.  eClass=EXPR_JSON */
      JsonNode *p;             /* The value */
    } json;
    ExprList *ar;           /* Array literal.  eClass=EXPR_ARRAY */
    ExprList *st;           /* Struct literal.  eClass=EXPR_STRUCT */





  } u;
};
#define XJD1_EXPR_BI      1
#define XJD1_EXPR_TK      2
#define XJD1_EXPR_FUNC    3
#define XJD1_EXPR_Q       4
#define XJD1_EXPR_JSON    5
#define XJD1_EXPR_ARRAY   6
#define XJD1_EXPR_STRUCT  7
#define XJD1_EXPR_LVALUE  8


/* A single element of a JSON structure */
struct JsonStructElem {
  char *zLabel;             /* Label on this element */
  JsonStructElem *pNext;    /* Next element of the structure */
  JsonNode *pValue;         /* Value of this element */
};







>
>
>
>
>










>







161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
      Query *p;                /* The subquery */
    } subq;
    struct {                /* Literal value.  eClass=EXPR_JSON */
      JsonNode *p;             /* The value */
    } json;
    ExprList *ar;           /* Array literal.  eClass=EXPR_ARRAY */
    ExprList *st;           /* Struct literal.  eClass=EXPR_STRUCT */
    struct {                /* Tertiary operator.  eClass==EXPR_TRI */
      Expr *pTest;          /* A in A?B:C */
      Expr *pIfTrue;        /* B in A?B:C */
      Expr *pIfFalse;       /* C in A?B:C */
    } tri;
  } u;
};
#define XJD1_EXPR_BI      1
#define XJD1_EXPR_TK      2
#define XJD1_EXPR_FUNC    3
#define XJD1_EXPR_Q       4
#define XJD1_EXPR_JSON    5
#define XJD1_EXPR_ARRAY   6
#define XJD1_EXPR_STRUCT  7
#define XJD1_EXPR_LVALUE  8
#define XJD1_EXPR_TRI     9

/* A single element of a JSON structure */
struct JsonStructElem {
  char *zLabel;             /* Label on this element */
  JsonStructElem *pNext;    /* Next element of the structure */
  JsonNode *pValue;         /* Value of this element */
};

Changes to test/all.test.

1
2
3
4

-- Run all test scripts
--
.read base01.test
.read base02.test





>
1
2
3
4
5
-- Run all test scripts
--
.read base01.test
.read base02.test
.read base03.test

Added test/base03.test.













































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
-- Basic sanity checking.
--
.new t1.db
.testcase 100
CREATE COLLECTION c1;
INSERT INTO c1 VALUE {a:1, b:2, c:3};
INSERT INTO c1 VALUE {a:4, b:5, c:6};
INSERT INTO c1 VALUE {a:7, b:8, c:9};
INSERT INTO c1 VALUE {a:10, b:11, c:12};
SELECT c1.a==7 ? c1.b : c1.c FROM c1;
.result 3 6 8 12

.testcase 110
SELECT {x: c1.a==7 ? c1.b : c1.c} FROM c1;
.result {"x":3} {"x":6} {"x":8} {"x":12}

.testcase 120
SELECT c1.a FROM c1 WHERE (c1.a==7 ? c1.b : c2.c)==9;
.result
.testcase 121
SELECT c1.a FROM c1 WHERE (c1.a==7 ? c1.b : c2.c)!=8;
.result 1 4 10