Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Completed handling of array-style lhs in UPDATE. Some semantics need review. |
---|---|
Timelines: | family | ancestors | trunk |
Files: | files | file ages | folders |
SHA1: |
8facf6305cd38ca6e8ca5173950cb17a |
User & Date: | pnr 2011-08-11 23:04:38 |
Context
2011-08-11
| ||
23:04 | Completed handling of array-style lhs in UPDATE. Some semantics need review. Leaf check-in: 8facf6305c user: pnr tags: trunk | |
2011-08-09
| ||
21:44 | Added initial support for array-style lhs in the UPDATE command. Assignments that would grow an array are still unimplemented, as is accessing characters of a string using the array syntax. check-in: d5e5efe19b user: pnr tags: trunk | |
Changes
Changes to src/shell.c.
385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 |
static int shellRead(Shell *p, int argc, char **argv){
if( argc>=2 ){
int nErr = p->nErr;
String newFile;
char *zNew;
xjd1StringInit(&newFile, 0, 0);
if( argv[1][0]=='/' || strcmp(p->zFile,"-")==0 ){
xjd1StringAppend(&newFile, argv[1], 0);
}else{
int i, j;
for(i=j=0; p->zFile[i]; i++){ if( p->zFile[i]=='/' ) j = i; }
xjd1StringAppendF(&newFile, "%.*s/%s", j, p->zFile, argv[1]);
}
zNew = xjd1StringText(&newFile);
printf("BEGIN %s\n", zNew);
|
| |
385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 |
static int shellRead(Shell *p, int argc, char **argv){
if( argc>=2 ){
int nErr = p->nErr;
String newFile;
char *zNew;
xjd1StringInit(&newFile, 0, 0);
if( argv[1][0]=='/' || strcmp(p->zFile,"-")==0 ){
xjd1StringAppend(&newFile, argv[1], -1);
}else{
int i, j;
for(i=j=0; p->zFile[i]; i++){ if( p->zFile[i]=='/' ) j = i; }
xjd1StringAppendF(&newFile, "%.*s/%s", j, p->zFile, argv[1]);
}
zNew = xjd1StringText(&newFile);
printf("BEGIN %s\n", zNew);
|
Changes to src/update.c.
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 .. 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 .. 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 |
************************************************************************* ** Code to evaluate an UPDATE statement */ #include "xjd1Int.h" /* ** pBase is a JSON structure object. Or if it is not, it should be ** converted into one. Then lookup or insert the zField element. */ static JsonNode *findStructElement(JsonNode *pBase, const char *zField){ JsonStructElem *pElem; if( pBase==0 ) return 0; if( pBase->eJType!=XJD1_STRUCT ){ xjd1JsonToNull(pBase); pBase->eJType = XJD1_STRUCT; pBase->u.st.pFirst = 0; pBase->u.st.pLast = 0; } for(pElem=pBase->u.st.pFirst; pElem; pElem=pElem->pNext){ if( strcmp(pElem->zLabel, zField)==0 ){ ................................................................................ /* 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 reference node is 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 reference node is ** element y of array x. ** TBD: extending array size as needed ** ** ** If x is of type XJD1_STRING, then it is treated as an array of ** characters. Processing proceeds as for XJD1_ARRAY. ** TBD ** */ case TK_LB: { JsonNode *pBase = findOrCreateJsonNode(pRoot, p->u.bi.pLeft); switch( pBase->eJType ){ case XJD1_STRUCT: { JsonNode *pRes; String idx; ................................................................................ } case XJD1_ARRAY: { double rRight; int iIdx; if( xjd1JsonToReal(xjd1ExprEval(p->u.bi.pRight), &rRight) ) break; iIdx = (int)rRight; if( (double)iIdx==rRight && iIdx>=0 && iIdx<pBase->u.ar.nElem ){ return pBase->u.ar.apElem[iIdx]; } break; } case XJD1_STRING: { /* TBD */ break; } } } break; case TK_ID: { |
| > | > | | | | > > | > | > > > > > > > > > > > > > > | > > > | | |
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 .. 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 .. 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 |
************************************************************************* ** Code to evaluate an UPDATE statement */ #include "xjd1Int.h" /* ** pBase is a JSON structure object. If it is not, overwrite the current ** value with an empty structure object. [[TBD: If it is not, return 0;]] ** Otherwise, lookup or insert the zField element. */ static JsonNode *findStructElement(JsonNode *pBase, const char *zField){ JsonStructElem *pElem; if( pBase==0 ) return 0; if( pBase->eJType!=XJD1_STRUCT ){ // return 0; xjd1JsonToNull(pBase); pBase->eJType = XJD1_STRUCT; pBase->u.st.pFirst = 0; pBase->u.st.pLast = 0; } for(pElem=pBase->u.st.pFirst; pElem; pElem=pElem->pNext){ if( strcmp(pElem->zLabel, zField)==0 ){ ................................................................................ /* 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 reference node is 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 the reference node ** is element y of array x. Grow the array as needed. ** ** If x is of any other type the assignment is silently ignored. ** Note that individual string characters can be read, but not ** written using the x[y] syntax. ** TBD: should x===null throw an error? */ case TK_LB: { JsonNode *pBase = findOrCreateJsonNode(pRoot, p->u.bi.pLeft); switch( pBase->eJType ){ case XJD1_STRUCT: { JsonNode *pRes; String idx; ................................................................................ } case XJD1_ARRAY: { double rRight; int iIdx; if( xjd1JsonToReal(xjd1ExprEval(p->u.bi.pRight), &rRight) ) break; iIdx = (int)rRight; if( (double)iIdx==rRight && iIdx>=0 ){ if( iIdx<pBase->u.ar.nElem ){ return pBase->u.ar.apElem[iIdx]; }else{ JsonNode **pNewArray; int i; /* Grow the array as needed. TBD: find a way to handle very ** large, sparse arrays. As a temporary drafting precaution, ** assert that the value of iIdx is less than 1024. */ assert( iIdx<1024 ); pNewArray = xjd1_realloc(pBase->u.ar.apElem, sizeof(JsonNode*)*(iIdx+1)); if( pNewArray==0 ) break; pBase->u.ar.apElem = pNewArray; for(i=pBase->u.ar.nElem; i<=iIdx; i++) { pNewArray[i] = xjd1JsonNew(0); pNewArray[i]->eJType = XJD1_NULL; } pBase->u.ar.nElem = iIdx+1; return pBase->u.ar.apElem[iIdx]; } } break; } case XJD1_NULL: { /* TBD: throw error? */ break; } } } break; case TK_ID: { |
Added test/base11.test.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 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 62 63 64 65 66 67 68 |
-- Test UPDATE statement -- .new t1.db CREATE COLLECTION c1; INSERT INTO c1 VALUE null; INSERT INTO c1 VALUE true; INSERT INTO c1 VALUE 1; INSERT INTO c1 VALUE "abc"; INSERT INTO c1 VALUE [1,2,3,4]; INSERT INTO c1 VALUE {a: 1, b:2, c:3}; .testcase 0 SELECT FROM c1; .json null\ true\ 1\ "abc"\ [1,2,3,4]\ {"a":1,"b":2,"c":3} -- setting named properties on primitives or -- arrays is ignored .testcase 1 UPDATE c1 SET c1.a = 2; SELECT FROM c1; .json null\ true\ 1\ "abc"\ [1,2,3,4]\ {"a":2,"b":2,"c":3} -- setting named properties on primitives or -- arrays is ignored, also when x[y] syntax is used .testcase 2 UPDATE c1 SET c1["a"] = 3; SELECT FROM c1; .json null\ true\ 1\ "abc"\ [1,2,3,4]\ {"a":3,"b":2,"c":3} -- setting number properties on primitives is -- ignored, but honoured on arrays and objects .testcase 3 UPDATE c1 SET c1["2"] = 7; SELECT FROM c1; .json null\ true\ 1\ "abc"\ [1,2,7,4]\ {"a":3,"b":2,"c":3, "2":7} -- setting number properties on arrays potentially -- grows the array, padding skipped elements with null .testcase 4 UPDATE c1 SET c1["7"] = 9; SELECT FROM c1; .json null\ true\ 1\ "abc"\ [1,2,7,4,null,null,null,9]\ {"a":3,"b":2,"c":3, "2":7, "7":9} |