Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Add support for the [] operator on arrays and strings. |
---|---|
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
0d9044c3817efdb0bb282d440f06bf72 |
User & Date: | dan 2011-07-16 15:47:11 |
Context
2011-07-16
| ||
16:12 | Fix problems with arrays and objects with zero members. check-in: 5b31aa5264 user: dan tags: trunk | |
15:47 | Add support for the [] operator on arrays and strings. check-in: 0d9044c381 user: dan tags: trunk | |
15:28 | Add a FIX ME comment on the unfinished "\uXXXX" translator. check-in: b77b043f2d user: drh tags: trunk | |
Changes
Changes to src/expr.c.
306 307 308 309 310 311 312 313 314 315 316 317 318 319 ... 343 344 345 346 347 348 349 350 351 352 353 354 355 356 ... 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 |
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){ ................................................................................ } 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){ ................................................................................ } /* The x[y] operator. The result depends on the type of value x. ** ** If x is of type XJD1_STRUCT, then expression y is converted to ** a string. The value returned is the value of property y of ** object x. */ case TK_LB: { pJLeft = xjd1ExprEval(p->u.bi.pLeft); pJRight = xjd1ExprEval(p->u.bi.pRight); switch( pJLeft->eJType ){ case XJD1_STRUCT: { String idx; xjd1StringInit(&idx, 0, 0); xjd1JsonToString(pJRight, &idx); pRes = getProperty(pJLeft, idx.zBuf); xjd1StringClear(&idx); break; } case XJD1_ARRAY: case XJD1_STRING: { break; } default: pRes = nullJson(); break; } xjd1JsonFree(pJLeft); xjd1JsonFree(pJRight); return pRes; } case TK_ID: { if( p->pQuery ){ return xjd1QueryDoc(p->pQuery, p->u.id.zId); }else{ |
> > > > > > > > > > > > > > > > > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > < > |
306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 ... 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 ... 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 |
rc = 0; } } return rc; } /* ** Evaluate an expression. Return the result as a JSON object. ** 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){ ................................................................................ } default: { rc = 0; } } return rc; } /* ** Assuming zIn points to the first byte of a UTF-8 character, ** advance zIn to point to the first byte of the next UTF-8 character. */ #define XJD1_SKIP_UTF8(zIn) { \ if( (*(zIn++))>=0xc0 ){ \ while( (*zIn & 0xc0)==0x80 ){ zIn++; } \ } \ } /* ** 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){ ................................................................................ } /* The x[y] operator. The result depends on the type of value x. ** ** If x is of type XJD1_STRUCT, then expression y is converted to ** a string. The value returned is the value of property y of ** object x. ** ** If x is of type XJD1_ARRAY, then expression y is converted to ** a number. If that number is an integer, then it is the index of ** the array element to return. ** ** If x is of type XJD1_STRING, then it is treated as an array of ** characters. Processing proceeds as for XJD1_ARRAY. */ case TK_LB: { pJLeft = xjd1ExprEval(p->u.bi.pLeft); pJRight = xjd1ExprEval(p->u.bi.pRight); pRes = 0; switch( pJLeft->eJType ){ case XJD1_STRUCT: { String idx; xjd1StringInit(&idx, 0, 0); xjd1JsonToString(pJRight, &idx); pRes = getProperty(pJLeft, idx.zBuf); xjd1StringClear(&idx); break; } case XJD1_ARRAY: { int iIdx; if( xjd1JsonToReal(pJRight, &rRight) ) break; iIdx = (int)rRight; if( (double)iIdx==rRight && iIdx>=0 && iIdx<pJLeft->u.ar.nElem ){ pRes = xjd1JsonRef(pJLeft->u.ar.apElem[iIdx]); } break; } case XJD1_STRING: { int iIdx; if( xjd1JsonToReal(pJRight, &rRight) ) break; iIdx = (int)rRight; if( (double)iIdx==rRight && iIdx>=0 ){ char *z = pJLeft->u.z; for(z=pJLeft->u.z; *z && iIdx!=0; iIdx--){ XJD1_SKIP_UTF8(z); } if( *z ){ String x; char *zEnd = z; pRes = xjd1JsonNew(0); if( pRes ){ XJD1_SKIP_UTF8(zEnd); xjd1StringInit(&x, 0, 0); xjd1StringAppend(&x, z, zEnd-z); pRes->eJType = XJD1_STRING; pRes->u.z = xjd1StringGet(&x); } } } break; } default: break; } xjd1JsonFree(pJLeft); xjd1JsonFree(pJRight); if( pRes==0 ) pRes = nullJson(); return pRes; } case TK_ID: { if( p->pQuery ){ return xjd1QueryDoc(p->pQuery, p->u.id.zId); }else{ |
Changes to test/base02.test.
118 119 120 121 122 123 124 125 126 127 |
.testcase 17 CREATE COLLECTION c2; INSERT INTO c2 VALUE { a:1, b:2, c:"d", d:3 }; SELECT c2.a FROM c2; SELECT c2["b"] FROM c2; SELECT c2[c2.c] FROM c2; .result 1 2 3 |
> | > > > > > > > > > > > > > > > > > > > > > > > |
118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 |
.testcase 17 CREATE COLLECTION c2; INSERT INTO c2 VALUE { a:1, b:2, c:"d", d:3 }; SELECT c2.a FROM c2; SELECT c2["b"] FROM c2; SELECT c2[c2.c] FROM c2; SELECT c2["e"] FROM c2; .result 1 2 3 null .testcase 18 DELETE FROM c2; INSERT INTO c2 VALUE { x: [10,11,12,13,14,15,16] }; SELECT c2.x[0] FROM c2; SELECT c2.x["1"] FROM c2; SELECT c2.x[2.01] FROM c2; SELECT c2.x[c2.x[6]-13] FROM c2; SELECT c2.x[-1] FROM c2; SELECT c2.x[7] FROM c2; .result 10 11 null 13 null null .testcase 19 DELETE FROM c2; INSERT INTO c2 VALUE { x: "abcdefg" }; SELECT c2.x[0] FROM c2; SELECT c2.x["1"] FROM c2; SELECT c2.x[2.01] FROM c2; SELECT c2.x[1+1+1] FROM c2; SELECT c2.x[-1] FROM c2; SELECT c2.x[7] FROM c2; SELECT c2.x[0][0][0] FROM c2; .result "a" "b" null "d" null null "a" |