UnQL

Check-in [6299c43154]
Login

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

Overview
Comment:Begin adding error message handling logic and code to implement statements. Incremental check-in because I have to stop to work on something else.
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 6299c431541e9e93ed6d5e2e6ebd7dee9576e418
User & Date: drh 2011-06-14 17:16:02
Context
2011-06-14
18:47
Get INSERT working. Improved error messages. check-in: c9b9b54e59 user: drh tags: trunk
17:16
Begin adding error message handling logic and code to implement statements. Incremental check-in because I have to stop to work on something else. check-in: 6299c43154 user: drh tags: trunk
14:33
JSON string parsing and rendering appears to work. check-in: 52ddc082d1 user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to main.mk.

26
27
28
29
30
31
32
33


34
35
36
37
38
39
40
#
# Once the macros above are defined, the rest of this make script will
# build the product
################################################################################

# This is how we compile
#
TCCX =  $(TCC) $(OPTS) -I. -I$(TOP)/src -I$(TOP) 



# Object files for the SQLite library.
#
LIBOBJ+= complete.o conn.o context.o
LIBOBJ+= json.o
LIBOBJ+= memory.o
LIBOBJ+= parse.o







|
>
>







26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#
# Once the macros above are defined, the rest of this make script will
# build the product
################################################################################

# This is how we compile
#
TCCX =  $(TCC) $(OPTS) -I. -I$(TOP)/src -I$(TOP)
TCCX += -DSQLITE_OMIT_LOAD_EXTENSION
TCCX += -DSQLITE_THREADSAFE=0

# Object files for the SQLite library.
#
LIBOBJ+= complete.o conn.o context.o
LIBOBJ+= json.o
LIBOBJ+= memory.o
LIBOBJ+= parse.o

Changes to src/conn.c.

14
15
16
17
18
19
20



21
22

23
24
25
26
27








28
29



30
31
32
33
34
35
36
..
40
41
42
43
44
45
46





47
48
49
50
51


52
53
54
55














56
57
58
59

















**   http://www.hwaci.com/drh/
**
*************************************************************************
** Main interfaces
*/
#include "xjd1Int.h"




int xjd1_open(xjd1_context *pContext, const char *zURI, xjd1 **ppNewConn){
  xjd1 *pConn;


  *ppNewConn = pConn = malloc( sizeof(*pConn) );
  if( pConn==0 ) return XJD1_NOMEM;
  memset(pConn, 0, sizeof(*pConn));
  pConn->pContext = pContext;








  return XJD1_OK;
}



int xjd1_config(xjd1 *pConn, int op, ...){
  int rc = XJD1_UNKNOWN;
  va_list ap;
  va_start(ap, op); 
  switch( op ){
    case XJD1_CONFIG_PARSERTRACE: {
      pConn->parserTrace = va_arg(ap, int);
................................................................................
    default: {
      break;
    }
  }
  va_end(ap);
  return rc;
}





int xjd1_close(xjd1 *pConn){
  if( pConn==0 ) return XJD1_OK;
  pConn->isDying = 1;
  if( pConn->nRef>0 ) return XJD1_OK;
  xjd1ContextUnref(pConn->pContext);


  free(pConn);
  return XJD1_OK;
}















PRIVATE void xjd1Unref(xjd1 *pConn){
  pConn->nRef--;
  if( pConn->nRef<=0 && pConn->isDying ) xjd1_close(pConn);
}
























>
>
>


>





>
>
>
>
>
>
>
>
|
|
>
>
>







 







>
>
>
>
>





>
>




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




>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
..
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
**   http://www.hwaci.com/drh/
**
*************************************************************************
** Main interfaces
*/
#include "xjd1Int.h"

/*
** Open a new database connection
*/
int xjd1_open(xjd1_context *pContext, const char *zURI, xjd1 **ppNewConn){
  xjd1 *pConn;
  int rc;

  *ppNewConn = pConn = malloc( sizeof(*pConn) );
  if( pConn==0 ) return XJD1_NOMEM;
  memset(pConn, 0, sizeof(*pConn));
  pConn->pContext = pContext;
  rc = sqlite3_open_v2(zURI, &pConn->db, 
            SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_URI, 0);
  if( rc ){
    xjd1Error(pConn, XJD1_ERROR, "%s", sqlite3_errmsg(pConn->db));
    sqlite3_close(pConn->db);
    pConn->db = 0;
    return XJD1_ERROR;
  }else{
    return XJD1_OK;
  }
}

/* Configure a database connection */
int xjd1_config(xjd1 *pConn, int op, ...){
  int rc = XJD1_UNKNOWN;
  va_list ap;
  va_start(ap, op); 
  switch( op ){
    case XJD1_CONFIG_PARSERTRACE: {
      pConn->parserTrace = va_arg(ap, int);
................................................................................
    default: {
      break;
    }
  }
  va_end(ap);
  return rc;
}

/* Close a database connection.  The close does not actually
** occur until all references to the connection also close.  This
** means that any prepared statements must also be closed.
*/
int xjd1_close(xjd1 *pConn){
  if( pConn==0 ) return XJD1_OK;
  pConn->isDying = 1;
  if( pConn->nRef>0 ) return XJD1_OK;
  xjd1ContextUnref(pConn->pContext);
  sqlite3_free(pConn->db);
  xjd1StringClear(&pConn->errMsg);
  free(pConn);
  return XJD1_OK;
}

/*
** Report the most recent error.
*/
int xjd1_errcode(xjd1 *pConn){
  return pConn ? pConn->errCode : XJD1_ERROR;
}
const char *xjd1_errmsg(xjd1 *pConn){
  if( pConn==0 ) return "out of memory";
  return xjd1StringText(&pConn->errMsg);
}

/* Remove a reference to a database connection.  When the last reference
** is removed and the database is closed, then memory is deallocated.
*/
PRIVATE void xjd1Unref(xjd1 *pConn){
  pConn->nRef--;
  if( pConn->nRef<=0 && pConn->isDying ) xjd1_close(pConn);
}

/*
** Change the error message and error code.
*/
PRIVATE void xjd1Error(xjd1 *pConn, int errCode, const char *zFormat, ...){
  va_list ap;
  if( pConn==0 ) return;
  if( pConn->appendErr ){
    xjd1StringTruncate(&pConn->errMsg);
  }else if( xjd1StringLen(&pConn->errMsg) ){
    xjd1StringAppend(&pConn->errMsg, "\n", 1);
  }
  pConn->errCode = errCode;
  va_start(ap, zFormat);
  xjd1StringVAppendF(&pConn->errMsg, zFormat, ap);
  va_end(ap);
}

Changes to src/parse.y.

28
29
30
31
32
33
34







35
36
37
38
39
40
41

// The generated parser function takes a 4th argument as follows:
%extra_argument {Parse *p}

// The name of the generated procedure that implements the parser
// is as follows:
%name xjd1Parser








// The following text is included near the beginning of the C source
// code file that implements the parser.
//
%include {
#include "xjd1Int.h"








>
>
>
>
>
>
>







28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48

// The generated parser function takes a 4th argument as follows:
%extra_argument {Parse *p}

// The name of the generated procedure that implements the parser
// is as follows:
%name xjd1Parser

// Handle syntax errors.
%syntax_error {
  p->errCode = XJD1_SYNTAX;
  xjd1Error(p->pConn, XJD1_SYNTAX, "syntax error near \"%.*s\"",
            p->sTok.n, p->sTok.z);
}

// The following text is included near the beginning of the C source
// code file that implements the parser.
//
%include {
#include "xjd1Int.h"

Changes to src/shell.c.

111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
...
145
146
147
148
149
150
151
152


153
154
155
156
157
158
159
  char zLine[2000];

  parserTrace = find_option(argv, &argc, "trace", 0, 0)!=0;
  testJson = find_option(argv, &argc, "json", 0, 0)!=0;
  if( argc!=2 ) usage(argv[0]);
  rc = xjd1_open(0, argv[1], &pDb);
  if( rc!=XJD1_OK ){
    fprintf(stderr, "cannot open \"%s\"\n", argv[1]);
    exit(1);
  }
  xjd1_config(pDb, XJD1_CONFIG_PARSERTRACE, parserTrace);
  isTTY = isatty(0);
  while( !feof(stdin) ){
    if( isTTY ) printf("%s", zPrompt);
    if( fgets(zLine, sizeof(zLine), stdin)==0 ) break;
................................................................................
      }
    }
    memcpy(&zStmt[nStmt], zLine, n+1);
    nStmt += n;
    if( xjd1_complete(zStmt) ){
      xjd1_stmt *pStmt;
      rc = xjd1_stmt_new(pDb, zStmt, &pStmt, &n);
      if( rc==XJD1_OK ){


        char *zTrace = xjd1_stmt_debug_listing(pStmt);
        if( zTrace ) printf("%s", zTrace);
        free(zTrace);
        while( xjd1_stmt_step(pStmt)==XJD1_ROW ){
          const char *zVal;
          xjd1_stmt_value(pStmt, &zVal);
          printf("%s\n", zVal);







|







 







|
>
>







111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
...
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
  char zLine[2000];

  parserTrace = find_option(argv, &argc, "trace", 0, 0)!=0;
  testJson = find_option(argv, &argc, "json", 0, 0)!=0;
  if( argc!=2 ) usage(argv[0]);
  rc = xjd1_open(0, argv[1], &pDb);
  if( rc!=XJD1_OK ){
    fprintf(stderr, "cannot open \"%s\": %s\n", argv[1], xjd1_errmsg(pDb));
    exit(1);
  }
  xjd1_config(pDb, XJD1_CONFIG_PARSERTRACE, parserTrace);
  isTTY = isatty(0);
  while( !feof(stdin) ){
    if( isTTY ) printf("%s", zPrompt);
    if( fgets(zLine, sizeof(zLine), stdin)==0 ) break;
................................................................................
      }
    }
    memcpy(&zStmt[nStmt], zLine, n+1);
    nStmt += n;
    if( xjd1_complete(zStmt) ){
      xjd1_stmt *pStmt;
      rc = xjd1_stmt_new(pDb, zStmt, &pStmt, &n);
      if( rc!=XJD1_OK ){
        fprintf(stderr, "ERROR: %s\n", xjd1_errmsg(pDb));
      }else{
        char *zTrace = xjd1_stmt_debug_listing(pStmt);
        if( zTrace ) printf("%s", zTrace);
        free(zTrace);
        while( xjd1_stmt_step(pStmt)==XJD1_ROW ){
          const char *zVal;
          xjd1_stmt_value(pStmt, &zVal);
          printf("%s\n", zVal);

Changes to src/stmt.c.

30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
..
69
70
71
72
73
74
75

76


























77
78
79
80
81
82
83
  *pN = strlen(zStmt);
  *ppNew = p = malloc( sizeof(*p) );
  if( p==0 ) return XJD1_NOMEM;
  memset(p, 0, sizeof(*p));
  p->pConn = pConn;
  p->pNext = pConn->pStmt;
  pConn->pStmt = p;
  if( pN==0 ) pN = &dummy;
  xjd1RunParser(pConn, p, zStmt, pN);
  return XJD1_OK;
}

/*
** Configure a prepared statement.
*/
int xdj1_stmt_config(xjd1_stmt *pStmt, int op, ...){
  return XJD1_UNKNOWN;
................................................................................
}

/*
** Execute a prepared statement up to its next return value or until
** it completes.
*/
int xjd1_stmt_step(xjd1_stmt *pStmt){

  return XJD1_DONE;


























}

/*
** Rewind a prepared statement back to the beginning.
*/
int xjd1_stmt_rewind(xjd1_stmt *pStmt){
  return XJD1_OK;







|
|
|







 







>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
..
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
  *pN = strlen(zStmt);
  *ppNew = p = malloc( sizeof(*p) );
  if( p==0 ) return XJD1_NOMEM;
  memset(p, 0, sizeof(*p));
  p->pConn = pConn;
  p->pNext = pConn->pStmt;
  pConn->pStmt = p;
  p->zCode = xjd1PoolDup(&p->sPool, zStmt, -1);
  if( pN==0 ) pN = &dummy;
  return xjd1RunParser(pConn, p, p->zCode, pN);
}

/*
** Configure a prepared statement.
*/
int xdj1_stmt_config(xjd1_stmt *pStmt, int op, ...){
  return XJD1_UNKNOWN;
................................................................................
}

/*
** Execute a prepared statement up to its next return value or until
** it completes.
*/
int xjd1_stmt_step(xjd1_stmt *pStmt){
  Command *pCmd;
  int rc = XJD1_DONE;
  if( pStmt==0 ) return rc;
  pCmd = pStmt->pCmd;
  if( pCmd==0 ) return rc;
  switch( pCmd->eCmdType ){
    case TK_CREATETABLE: {
      char *zSql;
      int res;
      zSql = sqlite3_mprintf("CREATE TABLE %s \"%!.*w\"(x)",
                 pCmd->u.crtab.ifExists ? "IF NOT EXISTS" : "",
                 pCmd->u.crtab.name.n, pCmd->u.crtab.name.z);
      res = sqlite3_exec(pStmt->pConn->db, zSql, 0, 0, 0);
      sqlite3_free(zSql);
      break;
    }
    case TK_DROPTABLE: {
      char *zSql;
      int res;
      zSql = sqlite3_mprintf("DROP TABLE %s \"%!.*w\"",
                 pCmd->u.crtab.ifExists ? "IF EXISTS" : "",
                 pCmd->u.crtab.name.n, pCmd->u.crtab.name.z);
      res = sqlite3_exec(pStmt->pConn->db, zSql, 0, 0, 0);
      sqlite3_free(zSql);
      break;
    }
  }
  return rc;
}

/*
** Rewind a prepared statement back to the beginning.
*/
int xjd1_stmt_rewind(xjd1_stmt *pStmt){
  return XJD1_OK;

Changes to src/tokenize.c.

405
406
407
408
409
410
411

412
413
414
415
416
417
418
419
420
421
...
434
435
436
437
438
439
440

441
442


443
444
445
446
447
448
449
450
    xjd1ParserTrace(stdout, "parser> ");
  }
#endif
  *pN = 0;
  pEngine = xjd1ParserAlloc(malloc);
  if( pEngine==0 ) return XJD1_NOMEM;
  memset(&sParse, 0, sizeof(sParse));

  sParse.pPool = &pStmt->sPool;
  xjd1StringInit(&sParse.errMsg, &pStmt->sPool, 0);
  while( zCode[i] ){
    assert( i>=0 );
    sParse.sTok.z = &zCode[i];
    sParse.sTok.n = xjd1GetToken((unsigned char*)&zCode[i], &tokenType);
    i += sParse.sTok.n;
    switch( tokenType ){
      case TK_SPACE: {
        break;
................................................................................
        if( sParse.errCode || tokenType==TK_SEMI ) goto abort_parse;
        break;
      }
    }
  }
abort_parse:
  *pN = i;

  if( nErr==0 && sParse.errCode==XJD1_OK ){
    if( lastTokenParsed!=TK_SEMI ){


      xjd1Parser(pEngine, TK_SEMI, sParse.sTok, &sParse);
    }
    xjd1Parser(pEngine, 0, sParse.sTok, &sParse);
  }
  pStmt->pCmd = sParse.pCmd;
  xjd1ParserFree(pEngine, free);
  return nErr;
}







>


|







 







>


>
>






|

405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
...
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
    xjd1ParserTrace(stdout, "parser> ");
  }
#endif
  *pN = 0;
  pEngine = xjd1ParserAlloc(malloc);
  if( pEngine==0 ) return XJD1_NOMEM;
  memset(&sParse, 0, sizeof(sParse));
  sParse.pConn = pConn;
  sParse.pPool = &pStmt->sPool;
  xjd1StringInit(&sParse.errMsg, &pStmt->sPool, 0);
  while( zCode[i] && sParse.errCode ){
    assert( i>=0 );
    sParse.sTok.z = &zCode[i];
    sParse.sTok.n = xjd1GetToken((unsigned char*)&zCode[i], &tokenType);
    i += sParse.sTok.n;
    switch( tokenType ){
      case TK_SPACE: {
        break;
................................................................................
        if( sParse.errCode || tokenType==TK_SEMI ) goto abort_parse;
        break;
      }
    }
  }
abort_parse:
  *pN = i;
  if( sParse.errCode ) nErr++;
  if( nErr==0 && sParse.errCode==XJD1_OK ){
    if( lastTokenParsed!=TK_SEMI ){
      sParse.sTok.z = ";";
      sParse.sTok.n = 1;
      xjd1Parser(pEngine, TK_SEMI, sParse.sTok, &sParse);
    }
    xjd1Parser(pEngine, 0, sParse.sTok, &sParse);
  }
  pStmt->pCmd = sParse.pCmd;
  xjd1ParserFree(pEngine, free);
  return nErr==0 && sParse.errCode==0 && sParse.pCmd!=0 ? XJD1_OK : XJD1_ERROR;
}

Changes to src/xjd1.h.

21
22
23
24
25
26
27

28
29
30
31
32
33
34
..
51
52
53
54
55
56
57




58
59
60
61
62
63
64

/* Return codes */
#define XJD1_OK       0      /* No error */
#define XJD1_ERROR    1      /* Generic error */
#define XJD1_MISUSE   2      /* Misuse of the interface */
#define XJD1_NOMEM    3      /* Out of heap memory */
#define XJD1_UNKNOWN  4      /* Unknown configuration option */


#define XJD1_ROW      200    /* Another row available */
#define XJD1_DONE     201    /* query complete */


/* Execution context */
typedef struct xjd1_context xjd1_context;
................................................................................
int xjd1_open(xjd1_context*, const char *zURI, xjd1**);
int xjd1_config(xjd1*, int, ...);
int xjd1_close(xjd1*);

/* Operators for xjd1_config() */
#define XJD1_CONFIG_PARSERTRACE    1





/* Create a new prepared statement */
int xjd1_stmt_new(xjd1*, const char*, xjd1_stmt**, int*);
int xjd1_stmt_delete(xjd1_stmt*);
int xjd1_stmt_config(xjd1_stmt*, int, ...);

/* Process a prepared statement */
int xjd1_stmt_step(xjd1_stmt*);







>







 







>
>
>
>







21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
..
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69

/* Return codes */
#define XJD1_OK       0      /* No error */
#define XJD1_ERROR    1      /* Generic error */
#define XJD1_MISUSE   2      /* Misuse of the interface */
#define XJD1_NOMEM    3      /* Out of heap memory */
#define XJD1_UNKNOWN  4      /* Unknown configuration option */
#define XJD1_SYNTAX   5      /* Syntax error */

#define XJD1_ROW      200    /* Another row available */
#define XJD1_DONE     201    /* query complete */


/* Execution context */
typedef struct xjd1_context xjd1_context;
................................................................................
int xjd1_open(xjd1_context*, const char *zURI, xjd1**);
int xjd1_config(xjd1*, int, ...);
int xjd1_close(xjd1*);

/* Operators for xjd1_config() */
#define XJD1_CONFIG_PARSERTRACE    1

/* Report on recent errors */
int xjd1_errcode(xjd1*);
const char *xjd1_errmsg(xjd1*);

/* Create a new prepared statement */
int xjd1_stmt_new(xjd1*, const char*, xjd1_stmt**, int*);
int xjd1_stmt_delete(xjd1_stmt*);
int xjd1_stmt_config(xjd1_stmt*, int, ...);

/* Process a prepared statement */
int xjd1_stmt_step(xjd1_stmt*);

Changes to src/xjd1Int.h.

17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
..
63
64
65
66
67
68
69








70
71
72
73
74
75
76
..
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
...
139
140
141
142
143
144
145

146
147
148
149
150
151
152
...
256
257
258
259
260
261
262

263
264
265
266
267
268
269
** Internal definitions for XJD1
*/
#ifndef _XJD1INT_H
#define _XJD1INT_H

#include "xjd1.h"
#include "parse.h"
#include "xjd1.h"
#include <assert.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>

/* Marker for routines not intended for external use */
#define PRIVATE
................................................................................

/* A memory allocation pool */
struct Pool {
  PoolChunk *pChunk;                /* List of all memory allocations */
  char *pSpace;                     /* Space available for allocation */
  int nSpace;                       /* Bytes available in pSpace */
};









/* Execution context */
struct xjd1_context {
  int nRef;                         /* Reference count */
  u8 isDying;                       /* True if has been deleted */
  int (*xLog)(const char*,void*);   /* Error logging function */
  void *pLogArg;                    /* 2nd argument to xLog() */
................................................................................

/* An open database connection */
struct xjd1 {
  xjd1_context *pContext;           /* Execution context */
  int nRef;                         /* Reference count */
  u8 isDying;                       /* True if has been closed */
  u8 parserTrace;                   /* True to enable parser tracing */

  xjd1_stmt *pStmt;                 /* list of all prepared statements */



};

/* A prepared statement */
struct xjd1_stmt {
  xjd1 *pConn;                      /* Database connection */
  xjd1_stmt *pNext, *pPrev;         /* List of all statements */
  Pool sPool;                       /* Memory pool used for parsing */
................................................................................
  int nRef;                         /* Reference count */
  u8 isDying;                       /* True if has been closed */
  char *zCode;                      /* Text of the query */
  Command *pCmd;                    /* Parsed command */
  char *zErrMsg;                    /* Error message */
};

/* A variable length string */
struct String {
  Pool *pPool;                      /* Memory allocation pool or NULL */
  char *zBuf;                       /* String content */
  int nUsed;                        /* Slots used.  Not counting final 0 */
  int nAlloc;                       /* Space allocated */
};

/* A token into to the parser */
struct Token {
  const char *z;                    /* Text of the token */
  int n;                            /* Number of characters */
};

/* A single element of an expression list */
................................................................................
    } func;
    Query *q;               /* Subqueries */
  } u;
};

/* Parsing context */
struct Parse {

  Pool *pPool;                    /* Memory allocation pool */
  Command *pCmd;                  /* Results */
  Token sTok;                     /* Last token seen */
  int errCode;                    /* Error code */
  String errMsg;                  /* Error message string */
};

................................................................................
#define XJD1_STRUCT    6

/******************************** context.c **********************************/
void xjd1ContextUnref(xjd1_context*);

/******************************** conn.c *************************************/
void xjd1Unref(xjd1*);


/******************************** json.c *************************************/
JsonNode *xjd1JsonParse(const char *zIn);
void xjd1JsonRender(String*, JsonNode*);
void xjd1JsonFree(JsonNode*);

/******************************** malloc.c ***********************************/







|







 







>
>
>
>
>
>
>
>







 







>

>
>
>







 







<
<
<
<
<
<
<
<







 







>







 







>







17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
..
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
..
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
...
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
...
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
** Internal definitions for XJD1
*/
#ifndef _XJD1INT_H
#define _XJD1INT_H

#include "xjd1.h"
#include "parse.h"
#include "sqlite3.h"
#include <assert.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>

/* Marker for routines not intended for external use */
#define PRIVATE
................................................................................

/* A memory allocation pool */
struct Pool {
  PoolChunk *pChunk;                /* List of all memory allocations */
  char *pSpace;                     /* Space available for allocation */
  int nSpace;                       /* Bytes available in pSpace */
};

/* A variable length string */
struct String {
  Pool *pPool;                      /* Memory allocation pool or NULL */
  char *zBuf;                       /* String content */
  int nUsed;                        /* Slots used.  Not counting final 0 */
  int nAlloc;                       /* Space allocated */
};

/* Execution context */
struct xjd1_context {
  int nRef;                         /* Reference count */
  u8 isDying;                       /* True if has been deleted */
  int (*xLog)(const char*,void*);   /* Error logging function */
  void *pLogArg;                    /* 2nd argument to xLog() */
................................................................................

/* An open database connection */
struct xjd1 {
  xjd1_context *pContext;           /* Execution context */
  int nRef;                         /* Reference count */
  u8 isDying;                       /* True if has been closed */
  u8 parserTrace;                   /* True to enable parser tracing */
  u8 appendErr;                     /* append errMsg rather than overwrite */
  xjd1_stmt *pStmt;                 /* list of all prepared statements */
  sqlite3 *db;                      /* Storage engine */
  int errCode;                      /* Latest non-zero error code */
  String errMsg;                    /* Latest error message */
};

/* A prepared statement */
struct xjd1_stmt {
  xjd1 *pConn;                      /* Database connection */
  xjd1_stmt *pNext, *pPrev;         /* List of all statements */
  Pool sPool;                       /* Memory pool used for parsing */
................................................................................
  int nRef;                         /* Reference count */
  u8 isDying;                       /* True if has been closed */
  char *zCode;                      /* Text of the query */
  Command *pCmd;                    /* Parsed command */
  char *zErrMsg;                    /* Error message */
};









/* A token into to the parser */
struct Token {
  const char *z;                    /* Text of the token */
  int n;                            /* Number of characters */
};

/* A single element of an expression list */
................................................................................
    } func;
    Query *q;               /* Subqueries */
  } u;
};

/* Parsing context */
struct Parse {
  xjd1 *pConn;                    /* Connect for recording errors */
  Pool *pPool;                    /* Memory allocation pool */
  Command *pCmd;                  /* Results */
  Token sTok;                     /* Last token seen */
  int errCode;                    /* Error code */
  String errMsg;                  /* Error message string */
};

................................................................................
#define XJD1_STRUCT    6

/******************************** context.c **********************************/
void xjd1ContextUnref(xjd1_context*);

/******************************** conn.c *************************************/
void xjd1Unref(xjd1*);
void xjd1Error(xjd1*,int,const char*,...);

/******************************** json.c *************************************/
JsonNode *xjd1JsonParse(const char *zIn);
void xjd1JsonRender(String*, JsonNode*);
void xjd1JsonFree(JsonNode*);

/******************************** malloc.c ***********************************/