UnQL

Check-in [4f893cfaf7]
Login

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

Overview
Comment:Provide an implementation for the "in" operator.
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 4f893cfaf74a80ae447b0e640268d4b3300dcc1c
User & Date: drh 2011-07-16 14:53:19
Context
2011-07-16
15:12
Implement the WITHIN operator. check-in: 0eba200fb2 user: drh tags: trunk
14:53
Provide an implementation for the "in" operator. check-in: 4f893cfaf7 user: drh tags: trunk
12:26
Add support for the [] operator on objects. Using the [] operator with an array or string does not work yet. check-in: e049952168 user: dan tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/expr.c.

251
252
253
254
255
256
257





















































258
259
260
261
262
263
264
...
532
533
534
535
536
537
538









539
540
541
542
543
544
545
  }

  if( pRes==0 ){
    pRes = nullJson();
  }
  return pRes;
}






















































/*
** Evaluate an expression.  Return the result as a JSON object.
**
** The caller must free the returned JSON by a call xjdJsonFree().
*/
JsonNode *xjd1ExprEval(Expr *p){
................................................................................
      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;







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







 







>
>
>
>
>
>
>
>
>







251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
...
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
  }

  if( pRes==0 ){
    pRes = nullJson();
  }
  return pRes;
}

/*
** Return TRUE if and only if all of the following are true:
**
**   (1)  pA exists
**   (2)  pB exists and is either an array or a structure
**   (3)  pA is a label within pB
*/
static int inOperator(JsonNode *pA, JsonNode *pB){
  char *zLHS;
  int rc = 0;
  char zBuf[100];
  if( pA==0 ) return 0;
  if( pB==0 ) return 0;
  switch( pA->eJType ){
    case XJD1_FALSE:
    case XJD1_TRUE:
    case XJD1_NULL:
    case XJD1_ARRAY:
    case XJD1_STRUCT:
      return 0;
    case XJD1_REAL:
      sqlite3_snprintf(sizeof(zBuf), zBuf, "%g", pA->u.r);
      zLHS = zBuf;
      break;
    case XJD1_STRING:
      zLHS = pA->u.z;
      break;
  }
  switch( pB->eJType ){
    case XJD1_ARRAY: {
      char *zTail;
      int x = strtol(zLHS, &zTail, 0);
      if( zTail[0]!=0 ) return 0;
      rc = (x>=0 && x<pB->u.ar.nElem);
      break;
    }
    case XJD1_STRUCT: {
      JsonStructElem *p;
      for(p=pB->u.st.pFirst; p; p=p->pNext){
        if( strcmp(p->zLabel, zLHS)==0 ){
          rc = 1;
          break;
        }
      }
      break;
    }
    default: {
      rc = 0;
    }
  }
  return rc;
}

/*
** Evaluate an expression.  Return the result as a JSON object.
**
** The caller must free the returned JSON by a call xjdJsonFree().
*/
JsonNode *xjd1ExprEval(Expr *p){
................................................................................
      if( xjd1ExprTrue(p->u.tri.pTest) ){
        pRes = xjd1ExprEval(p->u.tri.pIfTrue);
      }else{
        pRes = xjd1ExprEval(p->u.tri.pIfFalse);
      }
      break;
    }

    case TK_IN: {
      pJLeft = xjd1ExprEval(p->u.bi.pLeft);
      pJRight = xjd1ExprEval(p->u.bi.pRight);
      pRes->eJType = inOperator(pJLeft, pJRight) ? XJD1_TRUE : XJD1_FALSE;
      xjd1JsonFree(pJLeft);
      xjd1JsonFree(pJRight);
      break;
    }

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

Changes to test/base03.test.

16
17
18
19
20
21
22








































.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














































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61

.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

.testcase 200
SELECT 1 in [2,3,4];
.result true
.testcase 201
SELECT 3 in [2,3,4];
.result false
.testcase 202
SELECT "1" in [2,3,4];
.result true
.testcase 203
SELECT "3" in [2,3,4];
.result false

.testcase 210
SELECT "a" in {b:1, c:2, d:3};
.result false
.testcase 211
SELECT "b" in {b:1, c:2, d:3};
.result true
.testcase 212
SELECT "c" in {b:1, c:2, d:3};
.result true
.testcase 213
SELECT "d" in {b:1, c:2, d:3};
.result true
.testcase 214
SELECT "e" in {b:1, c:2, d:3};
.result false

.testcase 220
SELECT null in [1,2,3];
.result false
.testcase 221
SELECT 1 in null;
.result false
.testcase 222
SELECT 1 in 1;
.result false