UnQL

Check-in [0d3c641331]
Login

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

Overview
Comment:Reference counting of JsonNode objects.
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 0d3c641331dec56dbc73ab7e13dc1663851a0330
User & Date: drh 2011-06-27 17:27:31
Context
2011-06-27
17:56
Allow JSON strings in the column list. check-in: 51c49e25e9 user: drh tags: trunk
17:27
Reference counting of JsonNode objects. check-in: 0d3c641331 user: drh tags: trunk
16:01
Begin adding support for the expression list in between SELECT and FROM. check-in: 6d55502945 user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/expr.c.

20
21
22
23
24
25
26
27

28
29
30

31
32
33
34
35
36
37
..
48
49
50
51
52
53
54



55
56

57

58
59
60
61
62
63
64
..
74
75
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
106
107
108
109
110
111
112
113
114
115
...
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
...
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313


/*
** Information passed down into the expression walker.
*/
typedef struct WalkAction WalkAction;
struct WalkAction {
  int (*xQueryAction)(Expr*,WalkAction*);

  xjd1_stmt *pStmt;
  Query *pQuery;
  void *pArg;

};

/* forward reference */
static int walkExpr(Expr*,WalkAction*);

/*
** Walk an expression list 
................................................................................

/*
** Walk an expression tree
*/
static int walkExpr(Expr *p, WalkAction *pAction){
  int rc = XJD1_OK;
  if( p==0 ) return XJD1_OK;



  switch( p->eClass ){
    case XJD1_EXPR_Q: {

      if( pAction->xQueryAction ) rc = pAction->xQueryAction(p, pAction);

      break;
    }
    case XJD1_EXPR_FUNC: {
      walkExprList(p->u.func.args, pAction);
      break;
    }
    case XJD1_EXPR_BI: {
................................................................................
  return rc;
}


/*
** Callback for query expressions
*/
static int walkInitQueryCallback(Expr *p, WalkAction *pAction){

  assert( p );
  assert( p->eType==TK_SELECT );


  return xjd1QueryInit(p->u.q, pAction->pStmt, pAction->pQuery);


}


/*
** Initialize an expression in preparation for evaluation of a
** statement.
*/
int xjd1ExprInit(Expr *p, xjd1_stmt *pStmt, Query *pQuery){
  WalkAction sAction;
  memset(&sAction, 0, sizeof(sAction));
  sAction.xQueryAction = walkInitQueryCallback;
  sAction.pStmt = pStmt;
  sAction.pQuery = pQuery;
  return walkExpr(p, &sAction);
}

/*
** Initialize a list of expression in preparation for evaluation of a
** statement.
*/
int xjd1ExprListInit(ExprList *p, xjd1_stmt *pStmt, Query *pQuery){
  WalkAction sAction;
  memset(&sAction, 0, sizeof(sAction));
  sAction.xQueryAction = walkInitQueryCallback;
  sAction.pStmt = pStmt;
  sAction.pQuery = pQuery;
  return walkExprList(p, &sAction);
}


/* Walker callback for ExprClose() */
................................................................................
** 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){
  JsonNode *pRes;
  double rLeft, rRight;
  pRes = malloc( sizeof(*pRes) );
  if( pRes==0 ) return 0;
  memset(pRes, 0, sizeof(*pRes));
  if( p==0 ){
    pRes->eJType = XJD1_NULL;
    return pRes;
  }
  switch( p->eType ){
    case TK_INTEGER:
    case TK_FLOAT: {
................................................................................
*/
JsonNode *xjd1ExprListEval(ExprList *pList){
  JsonNode *pRes;
  JsonStructElem *pElem, **ppLast;
  int i;
  ExprItem *pItem;

  pRes = malloc( sizeof(*pRes) );
  if( pRes==0 ) return 0;
  memset(pRes, 0, sizeof(*pRes));
  pRes->eJType = XJD1_STRUCT;
  ppLast = &pRes->u.pStruct;
  if( pList==0 ) return pRes;
  for(i=0; i<pList->nEItem; i++){
    pItem = &pList->apEItem[i];
    pElem = malloc( sizeof(*pElem) );
    if( pElem==0 ) break;







|
>
|
<
|
>







 







>
>
>


>
|
>







 







|
>

<
>
>
|
>
>










|












|







 







|

<







 







|

<







20
21
22
23
24
25
26
27
28
29

30
31
32
33
34
35
36
37
38
..
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
..
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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
...
208
209
210
211
212
213
214
215
216

217
218
219
220
221
222
223
...
306
307
308
309
310
311
312
313
314

315
316
317
318
319
320
321


/*
** Information passed down into the expression walker.
*/
typedef struct WalkAction WalkAction;
struct WalkAction {
  int (*xQueryAction)(Expr*,WalkAction*);  /* Call for each EXPR_Q node */
  int (*xNodeAction)(Expr*,WalkAction*);   /* Call for every node */
  xjd1_stmt *pStmt;                        /* Stmt expr belongs to */

  Query *pQuery;                           /* Query expr belongs to */
  void *pArg;                              /* Some other argument */
};

/* forward reference */
static int walkExpr(Expr*,WalkAction*);

/*
** Walk an expression list 
................................................................................

/*
** Walk an expression tree
*/
static int walkExpr(Expr *p, WalkAction *pAction){
  int rc = XJD1_OK;
  if( p==0 ) return XJD1_OK;
  if( pAction->xNodeAction ){
    rc = pAction->xNodeAction(p, pAction);
  }
  switch( p->eClass ){
    case XJD1_EXPR_Q: {
      if( pAction->xQueryAction ){
        rc = pAction->xQueryAction(p, pAction);
      }
      break;
    }
    case XJD1_EXPR_FUNC: {
      walkExprList(p->u.func.args, pAction);
      break;
    }
    case XJD1_EXPR_BI: {
................................................................................
  return rc;
}


/*
** Callback for query expressions
*/
static int walkInitCallback(Expr *p, WalkAction *pAction){
  int rc = XJD1_OK;
  assert( p );

  p->pStmt = pAction->pStmt;
  if( p->eClass==XJD1_EXPR_Q ){
    rc = xjd1QueryInit(p->u.q, pAction->pStmt, pAction->pQuery);
  }
  return rc;
}


/*
** Initialize an expression in preparation for evaluation of a
** statement.
*/
int xjd1ExprInit(Expr *p, xjd1_stmt *pStmt, Query *pQuery){
  WalkAction sAction;
  memset(&sAction, 0, sizeof(sAction));
  sAction.xQueryAction = walkInitCallback;
  sAction.pStmt = pStmt;
  sAction.pQuery = pQuery;
  return walkExpr(p, &sAction);
}

/*
** Initialize a list of expression in preparation for evaluation of a
** statement.
*/
int xjd1ExprListInit(ExprList *p, xjd1_stmt *pStmt, Query *pQuery){
  WalkAction sAction;
  memset(&sAction, 0, sizeof(sAction));
  sAction.xQueryAction = walkInitCallback;
  sAction.pStmt = pStmt;
  sAction.pQuery = pQuery;
  return walkExprList(p, &sAction);
}


/* Walker callback for ExprClose() */
................................................................................
** 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){
  JsonNode *pRes;
  double rLeft, rRight;
  pRes = xjd1JsonNew();
  if( pRes==0 ) return 0;

  if( p==0 ){
    pRes->eJType = XJD1_NULL;
    return pRes;
  }
  switch( p->eType ){
    case TK_INTEGER:
    case TK_FLOAT: {
................................................................................
*/
JsonNode *xjd1ExprListEval(ExprList *pList){
  JsonNode *pRes;
  JsonStructElem *pElem, **ppLast;
  int i;
  ExprItem *pItem;

  pRes = xjd1JsonNew();
  if( pRes==0 ) return 0;

  pRes->eJType = XJD1_STRUCT;
  ppLast = &pRes->u.pStruct;
  if( pList==0 ) return pRes;
  for(i=0; i<pList->nEItem; i++){
    pItem = &pList->apEItem[i];
    pElem = malloc( sizeof(*pElem) );
    if( pElem==0 ) break;

Changes to src/json.c.

19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
..
47
48
49
50
51
52
53











































































54
55
56
57
58
59
60
...
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
#include "xjd1Int.h"


/*
** Reclaim memory used by JsonNode objects 
*/
void xjd1JsonFree(JsonNode *p){
  if( p ){
    switch( p->eJType ){
      case XJD1_STRING: {
        free(p->u.z);
        break;
      }
      case XJD1_ARRAY: {
        int i;
................................................................................
        }
        break;
      }
    }
    free(p);
  }
}












































































/* Render a string as a string literal.
*/
void renderString(String *pOut, const char *z){
  int n, i, j, c;
  char *zOut;
  for(i=n=0; (c=z[i])!=0; i++, n++){
................................................................................

/* Enter point to the first token of the JSON object.
** Exit pointing to the first token past end end of the
** JSON object.
*/
static JsonNode *parseJson(JsonStr *pIn){
  JsonNode *pNew;
  pNew = malloc( sizeof(*pNew) );
  if( pNew==0 ) return 0;
  memset(pNew, 0, sizeof(*pNew));
  pNew->eJType = tokenType(pIn);
  switch( pNew->eJType ){
    case JSON_BEGIN_STRUCT: {
      JsonStructElem **ppTail;
      tokenNext(pIn);
      if( tokenType(pIn)==JSON_END_STRUCT ) break;
      ppTail = &pNew->u.pStruct;







|







 







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







 







|

<







19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
..
47
48
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
84
85
86
87
88
89
90
91
92
93
94
95
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
...
431
432
433
434
435
436
437
438
439

440
441
442
443
444
445
446
#include "xjd1Int.h"


/*
** Reclaim memory used by JsonNode objects 
*/
void xjd1JsonFree(JsonNode *p){
  if( p && (--p->nRef)<=0 ){
    switch( p->eJType ){
      case XJD1_STRING: {
        free(p->u.z);
        break;
      }
      case XJD1_ARRAY: {
        int i;
................................................................................
        }
        break;
      }
    }
    free(p);
  }
}

/*
** Allocate a new Json node.
*/
JsonNode *xjd1JsonNew(void){
  JsonNode *p = malloc( sizeof(*p) );
  if( p ){
    memset(p, 0, sizeof(*p));
    p->nRef = 1;
  }
  return p;
}

/*
** Increase the reference count on a JSON object.  
**
** The object is freed when its reference count reaches zero.
*/
JsonNode *xjd1JsonRef(JsonNode *p){
  if( p ){
    p->nRef++;
  }
  return p;
}


/*
** Return an editable JSON object.  A JSON object is editable if its
** reference count is exactly 1.  If the input JSON object has a reference
** count greater than 1, then make a copy and return the copy.
*/
JsonNode *xjd1JsonEdit(JsonNode *p){
  JsonNode *pNew;
  if( p==0 ) return 0;
  if( p->nRef==1 ) return p;
  pNew = xjd1JsonNew();
  if( pNew==0 ) return 0;
  pNew->eJType = p->eJType;
  switch( pNew->eJType ){
    case XJD1_STRING: {
      pNew->u.z = xjd1PoolDup(0, p->u.z, -1);
      break;
    }
    case XJD1_ARRAY: {
      JsonNode **ap;
      pNew->u.array.apElem = ap = malloc( sizeof(JsonNode*)*p->u.array.nElem );
      if( ap==0 ){
        pNew->eJType = XJD1_NULL;
      }else{
        int i;
        pNew->u.array.nElem = p->u.array.nElem;
        for(i=0; i<p->u.array.nElem; i++){
          ap[i] = xjd1JsonEdit(p->u.array.apElem[i]);
        }
      }
      break;
    }
    case XJD1_STRUCT: {
      JsonStructElem *pSrc, *pDest, **ppPrev;
      ppPrev = &pNew->u.pStruct;
      for(pSrc=p->u.pStruct; pSrc; pSrc=pSrc->pNext){
        pDest = malloc( sizeof(*pDest) );
        if( pDest==0 ) break;
        memset(pDest, 0, sizeof(*pDest));
        *ppPrev = pDest;
        ppPrev = &pDest->pNext;
        pDest->zLabel = xjd1PoolDup(0, pSrc->zLabel, -1);
        pDest->pValue = xjd1JsonEdit(pSrc->pValue);
      }
      break;
    }
  }
  return pNew;
}


/* Render a string as a string literal.
*/
void renderString(String *pOut, const char *z){
  int n, i, j, c;
  char *zOut;
  for(i=n=0; (c=z[i])!=0; i++, n++){
................................................................................

/* Enter point to the first token of the JSON object.
** Exit pointing to the first token past end end of the
** JSON object.
*/
static JsonNode *parseJson(JsonStr *pIn){
  JsonNode *pNew;
  pNew = xjd1JsonNew();
  if( pNew==0 ) return 0;

  pNew->eJType = tokenType(pIn);
  switch( pNew->eJType ){
    case JSON_BEGIN_STRUCT: {
      JsonStructElem **ppTail;
      tokenNext(pIn);
      if( tokenType(pIn)==JSON_END_STRUCT ) break;
      ppTail = &pNew->u.pStruct;

Changes to src/xjd1Int.h.

131
132
133
134
135
136
137

138
139
140
141
142
143
144
...
257
258
259
260
261
262
263

264
265
266
267
268
269
270
...
303
304
305
306
307
308
309

310


311
312
313
314
315
316
317
  ExprItem *apEItem;        /* The expression in the list */
};

/* A node of an expression */
struct Expr {
  u16 eType;                /* Expression node type */
  u16 eClass;               /* Expression class */

  union {
    struct {                /* Binary or unary operator. eClass==XJD1_EXPR_BI */
      Expr *pLeft;             /* Left operand.  Only operand for unary ops */
      Expr *pRight;            /* Right operand.  NULL for unary ops */
    } bi;
    Token tk;               /* Token values. eClass=EXPR_TK */
    struct {                /* Function calls.  eClass=EXPR_FUNC */
................................................................................
  JsonStructElem *pNext;    /* Next element of the structure */
  JsonNode *pValue;         /* Value of this element */
};

/* A single element of a JSON value */
struct JsonNode {
  int eJType;               /* Element type */

  union {
    double r;               /* Real value */
    char *z;                /* String value */
    struct {                /* Array value */
      int nElem;               /* Number of elements */
      JsonNode **apElem;       /* Value of each element */
    } array;
................................................................................
JsonNode *xjd1ExprListEval(ExprList*);
int xjd1ExprTrue(Expr*);
int xjd1ExprClose(Expr*);
int xjd1ExprListClose(ExprList*);

/******************************** json.c *************************************/
JsonNode *xjd1JsonParse(const char *zIn, int mxIn);

void xjd1JsonRender(String*, JsonNode*);


void xjd1JsonFree(JsonNode*);

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







>







 







>







 







>

>
>







131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
...
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
...
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
  ExprItem *apEItem;        /* The expression in the list */
};

/* A node of an expression */
struct Expr {
  u16 eType;                /* Expression node type */
  u16 eClass;               /* Expression class */
  xjd1_stmt *pStmt;         /* Statement this expression belongs to */
  union {
    struct {                /* Binary or unary operator. eClass==XJD1_EXPR_BI */
      Expr *pLeft;             /* Left operand.  Only operand for unary ops */
      Expr *pRight;            /* Right operand.  NULL for unary ops */
    } bi;
    Token tk;               /* Token values. eClass=EXPR_TK */
    struct {                /* Function calls.  eClass=EXPR_FUNC */
................................................................................
  JsonStructElem *pNext;    /* Next element of the structure */
  JsonNode *pValue;         /* Value of this element */
};

/* A single element of a JSON value */
struct JsonNode {
  int eJType;               /* Element type */
  int nRef;                 /* Number of references */
  union {
    double r;               /* Real value */
    char *z;                /* String value */
    struct {                /* Array value */
      int nElem;               /* Number of elements */
      JsonNode **apElem;       /* Value of each element */
    } array;
................................................................................
JsonNode *xjd1ExprListEval(ExprList*);
int xjd1ExprTrue(Expr*);
int xjd1ExprClose(Expr*);
int xjd1ExprListClose(ExprList*);

/******************************** json.c *************************************/
JsonNode *xjd1JsonParse(const char *zIn, int mxIn);
JsonNode *xjd1JsonRef(JsonNode*);
void xjd1JsonRender(String*, JsonNode*);
JsonNode *xjd1JsonNew(void);
JsonNode *xjd1JsonEditable(JsonNode*);
void xjd1JsonFree(JsonNode*);

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