Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Implement the WITHIN operator. |
---|---|
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
0eba200fb28d9c455c3d3cf837e1c88d |
User & Date: | drh 2011-07-16 15:12:48 |
Context
2011-07-16
| ||
15:28 | Add a FIX ME comment on the unfinished "\uXXXX" translator. check-in: b77b043f2d user: drh tags: trunk | |
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 | |
Changes
Changes to src/expr.c.
304
305
306
307
308
309
310
311
312
313
314
315
316
317
...
594
595
596
597
598
599
600
601
602
603
604
605
606
607
|
}
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){
................................................................................
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;
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
...
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
|
} default: { rc = 0; } } return rc; } /* ** Return TRUE if and only if all of the following are true: ** ** (1) pA exists ** (2) pB exists and is an array or structure. ** (3) pA is value contained within pB */ static int withinOperator(JsonNode *pA, JsonNode *pB){ int rc = 0; if( pA==0 ) return 0; if( pB==0 ) return 0; switch( pB->eJType ){ case XJD1_ARRAY: { int i; for(i=0; i<pB->u.ar.nElem; i++){ if( xjd1JsonCompare(pA, pB->u.ar.apElem[i])==0 ){ rc = 1; break; } } break; } case XJD1_STRUCT: { JsonStructElem *p; for(p=pB->u.st.pFirst; p; p=p->pNext){ if( xjd1JsonCompare(pA, p->pValue)==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){ ................................................................................ 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; } case TK_WITHIN: { pJLeft = xjd1ExprEval(p->u.bi.pLeft); pJRight = xjd1ExprEval(p->u.bi.pRight); pRes->eJType = withinOperator(pJLeft, pJRight) ? XJD1_TRUE : XJD1_FALSE; xjd1JsonFree(pJLeft); xjd1JsonFree(pJRight); break; } default: { pRes->eJType = XJD1_NULL; break; } } return pRes; |
Changes to src/parse.y.
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 |
pNew->u.r = atof(pTok->z); } return pNew; } /* Convert a token into a zero-terminated string */ static char *tokenStr(Parse *p, Token *pTok){ return pTok ? xjd1PoolDup(p->pPool, pTok->z, pTok->n) : 0; } /* A JSON literal for a string */ static JsonNode *jsonString(Parse *p, Token *pTok){ JsonNode *pNew = xjd1JsonNew(p->pPool); if( pNew ){ pNew->eJType = XJD1_STRING; pNew->u.z = tokenStr(p, pTok); xjd1DequoteString(pNew->u.z, pTok->n); } return pNew; } /* A JSON literal for a boolean or NULL */ static JsonNode *jsonType(Parse *p, int eJType){ JsonNode *pNew = xjd1JsonNew(p->pPool); |
> > | > > > > > < |
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 |
pNew->u.r = atof(pTok->z); } return pNew; } /* Convert a token into a zero-terminated string */ static char *tokenStr(Parse *p, Token *pTok){ char *z; if( pTok ){ z = xjd1PoolDup(p->pPool, pTok->z, pTok->n); if( z && z[0]=='"' ) xjd1DequoteString(z, pTok->n); }else{ z = 0; } return z; } /* A JSON literal for a string */ static JsonNode *jsonString(Parse *p, Token *pTok){ JsonNode *pNew = xjd1JsonNew(p->pPool); if( pNew ){ pNew->eJType = XJD1_STRING; pNew->u.z = tokenStr(p, pTok); } return pNew; } /* A JSON literal for a boolean or NULL */ static JsonNode *jsonType(Parse *p, int eJType){ JsonNode *pNew = xjd1JsonNew(p->pPool); |
Changes to test/base03.test.
55 56 57 58 59 60 61 |
.result false .testcase 221 SELECT 1 in null; .result false .testcase 222 SELECT 1 in 1; .result false |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > |
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
.result false .testcase 221 SELECT 1 in null; .result false .testcase 222 SELECT 1 in 1; .result false .testcase 300 SELECT 0 WITHIN [1,2,3]; .result false .testcase 301 SELECT 1 WITHIN [1,2,3]; .result true .testcase 302 SELECT 2 WITHIN [1,2,3]; .result true .testcase 303 SELECT 3 WITHIN [1,2,3]; .result true .testcase 304 SELECT 4 WITHIN [1,2,3]; .result false .testcase 305 SELECT "2" WITHIN [1,2,3]; .result false .testcase 310 SELECT true WITHIN {a:false, b:null, c:true, d:123, e:{x:10}}; .result true .breakpoint .testcase 311 SELECT {"x": 10} WITHIN {a:false, b:null, c:true, d:123, e:{x:10}}; .result true .testcase 312 SELECT {"x": 11} WITHIN {a:false, b:null, c:true, d:123, e:{x:10}}; .result false |