UnQL

Check-in [423cc63722]
Login

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

Overview
Comment:Got all test cases passing again.
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 423cc63722042f628fc4acb40ca0ecabcfbb4052
User & Date: drh 2011-06-28 15:15:54
Context
2011-06-29
17:53
Change DATASET to COLLECTION. check-in: 1db9558acf user: drh tags: trunk
2011-06-28
15:15
Got all test cases passing again. check-in: 423cc63722 user: drh tags: trunk
13:46
Change the syntax so that the result specified in between SELECT and FROM keywords is a single JSON structure (actually any expression) rather than a SQL-style list. This check-in compiles and runs, but there are bugs so that the tests fail. check-in: 56a739ec3b user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/expr.c.

218
219
220
221
222
223
224

225
































226
227
228
229
230
231
232
    return pRes;
  }
  if( p->eType==TK_JVALUE ){
    return xjd1JsonRef(p->u.json.p);
  }
  pRes = xjd1JsonNew(0);
  if( pRes==0 ) return 0;

  switch( p->eType ){
































    case TK_PLUS: {
      rLeft = realFromExpr(p->u.bi.pLeft);
      rRight = realFromExpr(p->u.bi.pRight);
      pRes->eJType = XJD1_REAL;
      pRes->u.r = rLeft+rRight;  break;
      break;
    }







>

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







218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
    return pRes;
  }
  if( p->eType==TK_JVALUE ){
    return xjd1JsonRef(p->u.json.p);
  }
  pRes = xjd1JsonNew(0);
  if( pRes==0 ) return 0;
  pRes->eJType = XJD1_NULL;
  switch( p->eType ){
    case TK_STRUCT: {
      int i;
      JsonStructElem *pElem, **ppPrev;
      ExprList *pList = p->u.st;
      ppPrev = &pRes->u.st.pFirst;
      pRes->eJType = XJD1_STRUCT;
      for(i=0; i<pList->nEItem; i++){
        ExprItem *pItem = &pList->apEItem[i];
        pElem = malloc( sizeof(*pElem) );
        if( pElem==0 ) break;
        *ppPrev = pRes->u.st.pLast = pElem;
        ppPrev = &pElem->pNext;
        memset(pElem, 0, sizeof(*pElem));
        pElem->zLabel = xjd1PoolDup(0, pItem->tkAs.z, pItem->tkAs.n);
        pElem->pValue = xjd1ExprEval(pItem->pExpr);
      }
      break;
    }
    case TK_ARRAY: {
      int i;
      ExprList *pList = p->u.st;
      pRes->u.ar.apElem = malloc( pList->nEItem*sizeof(JsonNode*) );
      if( pRes->u.ar.apElem ){
        pRes->u.ar.nElem = pList->nEItem;
        pRes->eJType = XJD1_ARRAY;
        for(i=0; i<pList->nEItem; i++){
          ExprItem *pItem = &pList->apEItem[i];
          pRes->u.ar.apElem[i] = xjd1ExprEval(pItem->pExpr);
        }
      }
      break;
    }
    case TK_PLUS: {
      rLeft = realFromExpr(p->u.bi.pLeft);
      rRight = realFromExpr(p->u.bi.pRight);
      pRes->eJType = XJD1_REAL;
      pRes->u.r = rLeft+rRight;  break;
      break;
    }

Changes to src/json.c.

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
  return;

token_eof:
  p->n = 0;
  p->eType = JSON_EOF;
  return;
}



































/* Convert the current token (which must be a string) into a true
** string (resolving all of the backslash escapes) and return a pointer
** to the true string.  Space is obtained form malloc().
*/
static char *tokenDequoteString(JsonStr *pIn){
  const char *zIn;
  char *zOut;
  int i, j, n;
  char c;
  zIn = &pIn->zIn[pIn->iCur];
  zOut = malloc( pIn->n );
  if( zOut==0 ) return 0;
  assert( zIn[0]=='"' && zIn[pIn->n-1]=='"' );
  n = pIn->n-1;
  for(i=1, j=0; i<n; i++){
    if( zIn[i]!='\\' ){
      zOut[j++] = zIn[i];
    }else{
      i++;
      c = zIn[i];
      if( c=='b' ){
        zOut[j++] = '\b';
      }else if( c=='f' ){
        zOut[j++] = '\f';
      }else if( c=='n' ){
        zOut[j++] = '\n';
      }else if( c=='r' ){
        zOut[j++] = '\r';
      }else if( c=='t' ){
        zOut[j++] = '\t';
      }else if( c=='u' && i<n-4 ){

      }else{
        zOut[j++] = c;
      }
    }
  }
  zOut[j] = 0;
  return zOut;
}


/* Enter point to the first token of the JSON object.
** Exit pointing to the first token past end end of the
** JSON object.







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








|
<





|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







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
  return;

token_eof:
  p->n = 0;
  p->eType = JSON_EOF;
  return;
}

/*
** Dequote a string in-place.
*/
void xjd1DequoteString(char *z, int n){
  int i, j;
  char c;
  assert( n>=2 );
  assert( z[0]=='"' && z[n-1]=='"' );
  for(i=1, j=0; i<n-1; i++){
    if( z[i]!='\\' ){
      z[j++] = z[i];
    }else{
      i++;
      c = z[i];
      if( c=='b' ){
        z[j++] = '\b';
      }else if( c=='f' ){
        z[j++] = '\f';
      }else if( c=='n' ){
        z[j++] = '\n';
      }else if( c=='r' ){
        z[j++] = '\r';
      }else if( c=='t' ){
        z[j++] = '\t';
      }else if( c=='u' && i<n-4 ){

      }else{
        z[j++] = c;
      }
    }
  }
  z[j] = 0;
}

/* Convert the current token (which must be a string) into a true
** string (resolving all of the backslash escapes) and return a pointer
** to the true string.  Space is obtained form malloc().
*/
static char *tokenDequoteString(JsonStr *pIn){
  const char *zIn;
  char *zOut;
  int n;

  zIn = &pIn->zIn[pIn->iCur];
  zOut = malloc( pIn->n );
  if( zOut==0 ) return 0;
  assert( zIn[0]=='"' && zIn[pIn->n-1]=='"' );
  n = pIn->n-1;
  memcpy(zOut, zIn, pIn->n);
  xjd1DequoteString(zOut, pIn->n);






















  return zOut;
}


/* Enter point to the first token of the JSON object.
** Exit pointing to the first token past end end of the
** JSON object.

Changes to src/parse.y.

80
81
82
83
84
85
86

87
88
89
90
91
92
93

  /* 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 = xjd1PoolDup(p->pPool, pTok->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);







>







80
81
82
83
84
85
86
87
88
89
90
91
92
93
94

  /* 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 = xjd1PoolDup(p->pPool, pTok->z, pTok->n);
      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);

Changes to src/trace.c.

23
24
25
26
27
28
29






30
31
32
33
34
35
36
..
49
50
51
52
53
54
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
..
94
95
96
97
98
99
100

101
102
103
104
105
106
107
...
300
301
302
303
304
305
306

























307
308
309
310
311
312
313
*/
static const struct {
  int code;
  const char *zName;
} aToken[] = {
  /* Begin paste of parse_txt.h */
  { TK_SEMI,             "TK_SEMI"            },






  { TK_OR,               "TK_OR"              },
  { TK_AND,              "TK_AND"             },
  { TK_NOT,              "TK_NOT"             },
  { TK_IS,               "TK_IS"              },
  { TK_LIKEOP,           "TK_LIKEOP"          },
  { TK_BETWEEN,          "TK_BETWEEN"         },
  { TK_IN,               "TK_IN"              },
................................................................................
  { TK_MINUS,            "TK_MINUS"           },
  { TK_STAR,             "TK_STAR"            },
  { TK_SLASH,            "TK_SLASH"           },
  { TK_REM,              "TK_REM"             },
  { TK_CONCAT,           "TK_CONCAT"          },
  { TK_COLLATE,          "TK_COLLATE"         },
  { TK_BITNOT,           "TK_BITNOT"          },
  { TK_INTEGER,          "TK_INTEGER"         },
  { TK_FLOAT,            "TK_FLOAT"           },
  { TK_STRING,           "TK_STRING"          },
  { TK_TRUE,             "TK_TRUE"            },
  { TK_FALSE,            "TK_FALSE"           },
  { TK_NULL,             "TK_NULL"            },
  { TK_JVALUE,           "TK_JVALUE"          },
  { TK_ID,               "TK_ID"              },
  { TK_DOT,              "TK_DOT"             },
  { TK_LB,               "TK_LB"              },
  { TK_RB,               "TK_RB"              },




  { TK_LP,               "TK_LP"              },
  { TK_RP,               "TK_RP"              },
  { TK_COMMA,            "TK_COMMA"           },
  { TK_UNION,            "TK_UNION"           },
  { TK_EXCEPT,           "TK_EXCEPT"          },
  { TK_INTERSECT,        "TK_INTERSECT"       },
  { TK_ALL,              "TK_ALL"             },
  { TK_SELECT,           "TK_SELECT"          },
  { TK_AS,               "TK_AS"              },
  { TK_FROM,             "TK_FROM"            },

  { TK_FLATTENOP,        "TK_FLATTENOP"       },
  { TK_GROUP,            "TK_GROUP"           },
  { TK_BY,               "TK_BY"              },
  { TK_HAVING,           "TK_HAVING"          },
  { TK_ORDER,            "TK_ORDER"           },
  { TK_ASCENDING,        "TK_ASCENDING"       },
  { TK_DESCENDING,       "TK_DESCENDING"      },
................................................................................
  { TK_DROP,             "TK_DROP"            },
  { TK_DELETE,           "TK_DELETE"          },
  { TK_UPDATE,           "TK_UPDATE"          },
  { TK_SET,              "TK_SET"             },
  { TK_INSERT,           "TK_INSERT"          },
  { TK_INTO,             "TK_INTO"            },
  { TK_VALUE,            "TK_VALUE"           },

  /* End paste of parse_txt.h */
  { TK_NOT_LIKEOP,       "TK_NOT_LIKEOP"      },
  { TK_NOT_IS,           "TK_NOT_IS"          },
  { TK_FUNCTION,         "TK_FUNCTION"        },
  { TK_SPACE,            "TK_SPACE"           },
  { TK_ILLEGAL,          "TK_ILLEGAL"         },
  { TK_CREATEDATASET,    "TK_CREATEDATASET"   },
................................................................................
*/
void xjd1TraceExpr(String *pOut, const Expr *p){
  if( p==0 ) return;
  switch( p->eType ){
    case TK_JVALUE: {
      xjd1JsonRender(pOut, p->u.json.p);
      break;

























    }
    case TK_DOT:
    case TK_AND:
    case TK_OR:
    case TK_LT:
    case TK_LE:
    case TK_GT:







>
>
>
>
>
>







 







<
<
<
<
<
<
<




>
>
>
>


<





<

>







 







>







 







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







23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
..
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
..
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
...
303
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
*/
static const struct {
  int code;
  const char *zName;
} aToken[] = {
  /* Begin paste of parse_txt.h */
  { TK_SEMI,             "TK_SEMI"            },
  { TK_INTEGER,          "TK_INTEGER"         },
  { TK_FLOAT,            "TK_FLOAT"           },
  { TK_STRING,           "TK_STRING"          },
  { TK_TRUE,             "TK_TRUE"            },
  { TK_FALSE,            "TK_FALSE"           },
  { TK_NULL,             "TK_NULL"            },
  { TK_OR,               "TK_OR"              },
  { TK_AND,              "TK_AND"             },
  { TK_NOT,              "TK_NOT"             },
  { TK_IS,               "TK_IS"              },
  { TK_LIKEOP,           "TK_LIKEOP"          },
  { TK_BETWEEN,          "TK_BETWEEN"         },
  { TK_IN,               "TK_IN"              },
................................................................................
  { TK_MINUS,            "TK_MINUS"           },
  { TK_STAR,             "TK_STAR"            },
  { TK_SLASH,            "TK_SLASH"           },
  { TK_REM,              "TK_REM"             },
  { TK_CONCAT,           "TK_CONCAT"          },
  { TK_COLLATE,          "TK_COLLATE"         },
  { TK_BITNOT,           "TK_BITNOT"          },







  { TK_ID,               "TK_ID"              },
  { TK_DOT,              "TK_DOT"             },
  { TK_LB,               "TK_LB"              },
  { TK_RB,               "TK_RB"              },
  { TK_LC,               "TK_LC"              },
  { TK_RC,               "TK_RC"              },
  { TK_COLON,            "TK_COLON"           },
  { TK_COMMA,            "TK_COMMA"           },
  { TK_LP,               "TK_LP"              },
  { TK_RP,               "TK_RP"              },

  { TK_UNION,            "TK_UNION"           },
  { TK_EXCEPT,           "TK_EXCEPT"          },
  { TK_INTERSECT,        "TK_INTERSECT"       },
  { TK_ALL,              "TK_ALL"             },
  { TK_SELECT,           "TK_SELECT"          },

  { TK_FROM,             "TK_FROM"            },
  { TK_AS,               "TK_AS"              },
  { TK_FLATTENOP,        "TK_FLATTENOP"       },
  { TK_GROUP,            "TK_GROUP"           },
  { TK_BY,               "TK_BY"              },
  { TK_HAVING,           "TK_HAVING"          },
  { TK_ORDER,            "TK_ORDER"           },
  { TK_ASCENDING,        "TK_ASCENDING"       },
  { TK_DESCENDING,       "TK_DESCENDING"      },
................................................................................
  { TK_DROP,             "TK_DROP"            },
  { TK_DELETE,           "TK_DELETE"          },
  { TK_UPDATE,           "TK_UPDATE"          },
  { TK_SET,              "TK_SET"             },
  { TK_INSERT,           "TK_INSERT"          },
  { TK_INTO,             "TK_INTO"            },
  { TK_VALUE,            "TK_VALUE"           },
  { TK_PRAGMA,           "TK_PRAGMA"          },
  /* End paste of parse_txt.h */
  { TK_NOT_LIKEOP,       "TK_NOT_LIKEOP"      },
  { TK_NOT_IS,           "TK_NOT_IS"          },
  { TK_FUNCTION,         "TK_FUNCTION"        },
  { TK_SPACE,            "TK_SPACE"           },
  { TK_ILLEGAL,          "TK_ILLEGAL"         },
  { TK_CREATEDATASET,    "TK_CREATEDATASET"   },
................................................................................
*/
void xjd1TraceExpr(String *pOut, const Expr *p){
  if( p==0 ) return;
  switch( p->eType ){
    case TK_JVALUE: {
      xjd1JsonRender(pOut, p->u.json.p);
      break;
    }
    case TK_STRUCT: {
      int i;
      ExprList *pList = p->u.st;
      xjd1StringAppend(pOut, "{", 1);
      for(i=0; i<pList->nEItem; i++){
        ExprItem *pItem = &pList->apEItem[i];
        if( i>0 ) xjd1StringAppend(pOut, ",", 1);
        xjd1StringAppendF(pOut, "%.*s:", pItem->tkAs.n, pItem->tkAs.z);
        xjd1TraceExpr(pOut, pItem->pExpr);
      }
      xjd1StringAppend(pOut, "}", 1);
      break;
    }
    case TK_ARRAY: {
      int i;
      ExprList *pList = p->u.st;
      xjd1StringAppend(pOut, "[", 1);
      for(i=0; i<pList->nEItem; i++){
        ExprItem *pItem = &pList->apEItem[i];
        if( i>0 ) xjd1StringAppend(pOut, ",", 1);
        xjd1TraceExpr(pOut, pItem->pExpr);
      }
      xjd1StringAppend(pOut, "]", 1);
      break;
    }
    case TK_DOT:
    case TK_AND:
    case TK_OR:
    case TK_LT:
    case TK_LE:
    case TK_GT:

Changes to src/xjd1Int.h.

328
329
330
331
332
333
334

335
336
337
338
339
340
341
/******************************** json.c *************************************/
JsonNode *xjd1JsonParse(const char *zIn, int mxIn);
JsonNode *xjd1JsonRef(JsonNode*);
void xjd1JsonRender(String*, JsonNode*);
JsonNode *xjd1JsonNew(Pool*);
JsonNode *xjd1JsonEdit(JsonNode*);
void xjd1JsonFree(JsonNode*);


/******************************** malloc.c ***********************************/
Pool *xjd1PoolNew(void);
void xjd1PoolClear(Pool*);
void xjd1PoolDelete(Pool*);
void *xjd1PoolMalloc(Pool*, int);
void *xjd1PoolMallocZero(Pool*, int);







>







328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
/******************************** json.c *************************************/
JsonNode *xjd1JsonParse(const char *zIn, int mxIn);
JsonNode *xjd1JsonRef(JsonNode*);
void xjd1JsonRender(String*, JsonNode*);
JsonNode *xjd1JsonNew(Pool*);
JsonNode *xjd1JsonEdit(JsonNode*);
void xjd1JsonFree(JsonNode*);
void xjd1DequoteString(char*,int);

/******************************** malloc.c ***********************************/
Pool *xjd1PoolNew(void);
void xjd1PoolClear(Pool*);
void xjd1PoolDelete(Pool*);
void *xjd1PoolMalloc(Pool*, int);
void *xjd1PoolMallocZero(Pool*, int);

Changes to test/base01.test.

19
20
21
22
23
24
25
26
27
.testcase 130
SELECT { p:1, q:2 } FROM abc;
.result {"p":1,"q":2}
.testcase 131
SELECT {p:1, q:2+3} FROM abc;
.result {"p":1,"q":5}
.testcase 132
SELECT {p:1, q:{x:[1,2,3],y:11} FROM abc;
.result {"p":1,"q":{"x":[1,2,3],"y":11}}







|

19
20
21
22
23
24
25
26
27
.testcase 130
SELECT { p:1, q:2 } FROM abc;
.result {"p":1,"q":2}
.testcase 131
SELECT {p:1, q:2+3} FROM abc;
.result {"p":1,"q":5}
.testcase 132
SELECT {p:1, q:{x:[1,2,3],y:11}} FROM abc;
.result {"p":1,"q":{"x":[1,2,3],"y":11}}