UnQL

Check-in [9d3d2f9226]
Login

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

Overview
Comment:Typing in more code.
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 9d3d2f9226b689180f680b1024f7e6f689b4a90f
User & Date: drh 2011-06-24 19:14:07
Context
2011-06-25
00:07
Very simply queries working. check-in: 4eda880431 user: drh tags: trunk
2011-06-24
19:14
Typing in more code. check-in: 9d3d2f9226 user: drh tags: trunk
2011-06-21
20:36
Improvisations directed toward implementing the query engine. check-in: 26fd1b039d user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to main.mk.

33
34
35
36
37
38
39


40
41
42
43
44
45
46
47
48
49
50
51
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 pragma.o
LIBOBJ+= query.o
LIBOBJ+= scan.o sqlite3.o stmt.o string.o
LIBOBJ+= tokenize.o trace.o

# All of the source code files.
#
SRC = \
  $(TOP)/src/parse.y 








>
>




|







33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
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+= datasrc.o
LIBOBJ+= expr.o
LIBOBJ+= json.o
LIBOBJ+= memory.o
LIBOBJ+= parse.o pragma.o
LIBOBJ+= query.o
LIBOBJ+= sqlite3.o stmt.o string.o
LIBOBJ+= tokenize.o trace.o

# All of the source code files.
#
SRC = \
  $(TOP)/src/parse.y 

Added src/datasrc.c.













































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
69
70
/*
** Copyright (c) 2011 D. Richard Hipp
**
** This program is free software; you can redistribute it and/or
** modify it under the terms of the Simplified BSD License (also
** known as the "2-Clause License" or "FreeBSD License".)
**
** This program is distributed in the hope that it will be useful,
** but without any warranty; without even the implied warranty of
** merchantability or fitness for a particular purpose.
**
** Author contact information:
**   drh@hwaci.com
**   http://www.hwaci.com/drh/
**
*************************************************************************
** This file contains code used to implement methods for the DataSrc object.
*/
#include "xjd1Int.h"

/*
** Called after statement parsing to initalize every DataSrc object.
*/
int xjd1DataSrcInit(DataSrc *p, Query *pQuery){
  p->pQuery = pQuery;
  switch( p->eDSType ){
    case TK_COMMA: {
      xjd1DataSrcInit(p->u.join.pLeft, pQuery);
      xjd1DataSrcInit(p->u.join.pRight, pQuery);
      break;
    }
    case TK_SELECT: {
      xjd1QueryInit(p->u.subq.q, pQuery->pStmt, pQuery);
      break;
    }
  }
  return XJD1_OK;
}

/*
** Rewind a data source so that it is pointing at the first row.
** Return XJD1_DONE if the data source is empty and XJD1_ROW if
** the rewind results in a row of content being available.
*/
int xjd1DataSrcRewind(DataSrc *p){
  return XJD1_DONE;
}

/*
** Advance a data source to the next row.
** Return XJD1_DONE if the data source is empty and XJD1_ROW if
** the step results in a row of content being available.
*/
int xjd1DataSrcStep(DataSrc *p){
  return XJD1_DONE;
}

/*
** Return true if the data source is at the end of file
*/
int xjd1DataSrcEOF(DataSrc *p){
  return 1;
}

/*
** The destructor for a Query object.
*/
int xjd1DataSrcClose(DataSrc *p){
  return XJD1_OK;
}

Added src/expr.c.













































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
/*
** Copyright (c) 2011 D. Richard Hipp
**
** This program is free software; you can redistribute it and/or
** modify it under the terms of the Simplified BSD License (also
** known as the "2-Clause License" or "FreeBSD License".)
**
** This program is distributed in the hope that it will be useful,
** but without any warranty; without even the implied warranty of
** merchantability or fitness for a particular purpose.
**
** Author contact information:
**   drh@hwaci.com
**   http://www.hwaci.com/drh/
**
*************************************************************************
** This file contains code used to evaluate expressions at run-time.
*/
#include "xjd1Int.h"


/*
** 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 
*/
static int walkExprList(ExprList *p, WalkAction *pAction){
  if( p ){
    int i;
    for(i=0; i<p->nEItem; i++){
      walkExpr(p->apEItem[i].pExpr, pAction);
    }
  }
  return XJD1_OK;
}

/*
** 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: {
      walkExpr(p->u.bi.pLeft, pAction);
      walkExpr(p->u.bi.pRight, pAction);
      break;
    }
    case XJD1_EXPR_TK: {
      /* Nothing to do */
      break;
    }
  }
  return rc;
}


/*
** Callback for query expressions
*/
static int initQueryCallback(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 = initQueryCallback;
  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 = initQueryCallback;
  sAction.pStmt = pStmt;
  sAction.pQuery = pQuery;
  return walkExprList(p, &sAction);
}

/*
** Return TRUE if the given expression evaluates to TRUE.
** An empty expression is considered to be TRUE.  A NULL value
** is not TRUE.
*/
int xjd1ExprTrue(Expr *p){
  return 1;
}



/* Walker callback for ExprClose() */
static int walkCloseQueryCallback(Expr *p, WalkAction *pAction){
  assert( p );
  assert( p->eType==TK_SELECT );
  return xjd1QueryClose(p->u.q);
}

/*
** Close all subqueries in an expression.
*/
int xjd1ExprClose(Expr *p){
  WalkAction sAction;
  memset(&sAction, 0, sizeof(sAction));
  sAction.xQueryAction = walkCloseQueryCallback;
  return walkExpr(p,&sAction);
}

/*
** Close all subqueries in an expression list.
*/
int xjd1ExprListClose(ExprList *p){
  WalkAction sAction;
  memset(&sAction, 0, sizeof(sAction));
  sAction.xQueryAction = walkCloseQueryCallback;
  return walkExprList(p,&sAction);
}

Changes to src/parse.y.

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

%include {
  /* Generate an Expr object from a token */
  static Expr *tokExpr(Parse *p, int eType, Token *pTok){
    Expr *pNew = xjd1PoolMallocZero(p->pPool, sizeof(*pNew));
    if( pNew ){
      pNew->eType = eType; 

      pNew->u.tk = *pTok;
    }
    return pNew;
  }

  /* Generate an Expr object that is a binary operator on two
  ** other Expr objects. */
  static Expr *biExpr(Parse *p, Expr *pLeft, int eOp, Expr *pRight){
    Expr *pNew = xjd1PoolMallocZero(p->pPool, sizeof(*pNew));
    if( pNew ){
      pNew->eType = eOp; 

      pNew->u.bi.pLeft = pLeft;
      pNew->u.bi.pRight = pRight;
    }
    return pNew;
  }

  /* Generate an Expr object that is a function call. */
  static Expr *funcExpr(Parse *p, Token *pFName, ExprList *pArgs){
    Expr *pNew = xjd1PoolMallocZero(p->pPool, sizeof(*pNew));
    if( pNew ){
      pNew->eType = TK_FUNCTION; 

      pNew->u.func.name = *pFName;
      pNew->u.func.args = pArgs;
    }
    return pNew;
  }

  /* Generate an Expr object that is a subquery. */
  static Expr *subqExpr(Parse *p, Query *pQuery){
    Expr *pNew = xjd1PoolMallocZero(p->pPool, sizeof(*pNew));
    if( pNew ){
      pNew->eType = TK_SELECT;

      pNew->u.q = pQuery;
    }
    return pNew;
  }

  /* Append a new expression to an expression list.  Allocate the
  ** expression list object if necessary. */







>











>











>











>







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

%include {
  /* Generate an Expr object from a token */
  static Expr *tokExpr(Parse *p, int eType, Token *pTok){
    Expr *pNew = xjd1PoolMallocZero(p->pPool, sizeof(*pNew));
    if( pNew ){
      pNew->eType = eType; 
      pNew->eClass = XJD1_EXPR_TK;
      pNew->u.tk = *pTok;
    }
    return pNew;
  }

  /* Generate an Expr object that is a binary operator on two
  ** other Expr objects. */
  static Expr *biExpr(Parse *p, Expr *pLeft, int eOp, Expr *pRight){
    Expr *pNew = xjd1PoolMallocZero(p->pPool, sizeof(*pNew));
    if( pNew ){
      pNew->eType = eOp; 
      pNew->eClass = XJD1_EXPR_BI;
      pNew->u.bi.pLeft = pLeft;
      pNew->u.bi.pRight = pRight;
    }
    return pNew;
  }

  /* Generate an Expr object that is a function call. */
  static Expr *funcExpr(Parse *p, Token *pFName, ExprList *pArgs){
    Expr *pNew = xjd1PoolMallocZero(p->pPool, sizeof(*pNew));
    if( pNew ){
      pNew->eType = TK_FUNCTION; 
      pNew->eClass = XJD1_EXPR_FUNC;
      pNew->u.func.name = *pFName;
      pNew->u.func.args = pArgs;
    }
    return pNew;
  }

  /* Generate an Expr object that is a subquery. */
  static Expr *subqExpr(Parse *p, Query *pQuery){
    Expr *pNew = xjd1PoolMallocZero(p->pPool, sizeof(*pNew));
    if( pNew ){
      pNew->eType = TK_SELECT;
      pNew->eClass = XJD1_EXPR_Q;
      pNew->u.q = pQuery;
    }
    return pNew;
  }

  /* Append a new expression to an expression list.  Allocate the
  ** expression list object if necessary. */

Changes to src/query.c.

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
69
70

71






72
73
74
75
76
77
*/
#include "xjd1Int.h"

/*
** Called after statement parsing to initalize every Query object
** within the statement.
*/
int xjd1QueryInit(xjd1_stmt *pStmt, Query *pQuery){
  if( pQuery==0 ) return XJD1_OK;
  pQuery->pStmt = pStmt;

  if( pQuery->eQType==TK_SELECT ){

    xjd1ScannerInit(pQuery, pQuery->u.simple.pFrom);






  }else{
    xjd1QueryInit(pStmt, pQuery->u.compound.pLeft);
    xjd1QueryInit(pStmt, pQuery->u.compound.pRight);
  }
  return XJD1_OK;
}

/*
** Rewind a query so that it is pointing at the first row.
*/
int xjd1QueryRewind(Query *pQuery){
  if( pQuery==0 ) return XJD1_OK;
  if( pQuery->eQType==TK_SELECT ){
    xjd1ScannerRewind(pQuery->u.simple.pFrom);
  }else{
    xjd1QueryRewind(pQuery->u.compound.pLeft);

    xjd1QueryRewind(pQuery->u.compound.pRight);
  }
  return XJD1_OK;
}

/*
** Advance a query to the next row.

*/
int xjd1QueryStep(Query *pQuery){

  if( pQuery==0 ) return XJD1_OK;
  if( pQuery->eQType==TK_SELECT ){
    /* TBD */






  }else{
    /* TBD */




  }




  return XJD1_OK;


















}

/*
** The destructor for a Query object.
*/
int xjd1QueryClose(Query *pQuery){
  int rc = XJD1_OK;
  if( pQuery==0 ) return rc;
  if( pQuery->eQType==TK_SELECT ){

    xjd1ScannerClose(pQuery->u.simple.pFrom);






  }else{
    xjd1QueryClose(pQuery->u.compound.pLeft);
    xjd1QueryClose(pQuery->u.compound.pRight);
  }
  return rc;
}







|


>

>
|
>
>
>
>
>
>

|
|







|
|
|
|

|
>
|





|
>

|
>
|
|
<
>
>
>
>
>
>

<
>
>
>
>
|
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>









>
|
>
>
>
>
>
>






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
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
*/
#include "xjd1Int.h"

/*
** Called after statement parsing to initalize every Query object
** within the statement.
*/
int xjd1QueryInit(Query *pQuery, xjd1_stmt *pStmt, Query *pOuter){
  if( pQuery==0 ) return XJD1_OK;
  pQuery->pStmt = pStmt;
  pQuery->pOuter = pOuter;
  if( pQuery->eQType==TK_SELECT ){
    xjd1ExprListInit(pQuery->u.simple.pCol, pStmt, pQuery);
    xjd1DataSrcInit(pQuery->u.simple.pFrom, pQuery);
    xjd1ExprInit(pQuery->u.simple.pWhere, pStmt, pQuery);
    xjd1ExprListInit(pQuery->u.simple.pGroupBy, pStmt, pQuery);
    xjd1ExprInit(pQuery->u.simple.pHaving, pStmt, pQuery);
    xjd1ExprListInit(pQuery->u.simple.pOrderBy, pStmt, pQuery);
    xjd1ExprInit(pQuery->u.simple.pLimit, pStmt, pQuery);
    xjd1ExprInit(pQuery->u.simple.pOffset, pStmt, pQuery);
  }else{
    xjd1QueryInit(pQuery->u.compound.pLeft, pStmt, pOuter);
    xjd1QueryInit(pQuery->u.compound.pRight, pStmt, pOuter);
  }
  return XJD1_OK;
}

/*
** Rewind a query so that it is pointing at the first row.
*/
int xjd1QueryRewind(Query *p){
  if( p==0 ) return XJD1_OK;
  if( p->eQType==TK_SELECT ){
    xjd1DataSrcRewind(p->u.simple.pFrom);
  }else{
    xjd1QueryRewind(p->u.compound.pLeft);
    p->u.compound.doneLeft = xjd1QueryEOF(p->u.compound.pLeft);
    xjd1QueryRewind(p->u.compound.pRight);
  }
  return XJD1_OK;
}

/*
** Advance a query to the next row.  Return XDJ1_DONE if there is no
** next row, or XJD1_ROW if the step was successful.
*/
int xjd1QueryStep(Query *p){
  int rc;
  if( p==0 ) return XJD1_DONE;
  if( p->eQType==TK_SELECT ){

    do{
      rc = xjd1DataSrcStep(p->u.simple.pFrom);
    }while(
         rc==XJD1_ROW
      && (p->u.simple.pWhere==0 || !xjd1ExprTrue(p->u.simple.pWhere))
    );
  }else{

    rc = XJD1_ROW;
    if( !p->u.compound.doneLeft ){
      rc = xjd1QueryStep(p->u.compound.pLeft);
      if( rc==XJD1_DONE ) p->u.compound.doneLeft = 1;
    }
    if( p->u.compound.doneLeft ){
      rc = xjd1QueryStep(p->u.compound.pRight);
    }
  }
  return rc;
}

/* Return true if there are no more rows available on this query */
int xjd1QueryEOF(Query *p){
  int rc;
  if( p->eQType==TK_SELECT ){
    rc = xjd1DataSrcEOF(p->u.simple.pFrom);
  }else{
    rc = 0;
    if( !p->u.compound.doneLeft ){
      rc = xjd1QueryEOF(p->u.compound.pLeft);
      if( rc ) p->u.compound.doneLeft = 1;
    }
    if( p->u.compound.doneLeft ){
      rc = xjd1QueryEOF(p->u.compound.pRight);
    }
  }
  return rc;
}

/*
** The destructor for a Query object.
*/
int xjd1QueryClose(Query *pQuery){
  int rc = XJD1_OK;
  if( pQuery==0 ) return rc;
  if( pQuery->eQType==TK_SELECT ){
    xjd1ExprListClose(pQuery->u.simple.pCol);
    xjd1DataSrcClose(pQuery->u.simple.pFrom);
    xjd1ExprClose(pQuery->u.simple.pWhere);
    xjd1ExprListClose(pQuery->u.simple.pGroupBy);
    xjd1ExprClose(pQuery->u.simple.pHaving);
    xjd1ExprListClose(pQuery->u.simple.pOrderBy);
    xjd1ExprClose(pQuery->u.simple.pLimit);
    xjd1ExprClose(pQuery->u.simple.pOffset);
  }else{
    xjd1QueryClose(pQuery->u.compound.pLeft);
    xjd1QueryClose(pQuery->u.compound.pRight);
  }
  return rc;
}

Deleted src/scan.c.

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
/*
** Copyright (c) 2011 D. Richard Hipp
**
** This program is free software; you can redistribute it and/or
** modify it under the terms of the Simplified BSD License (also
** known as the "2-Clause License" or "FreeBSD License".)
**
** This program is distributed in the hope that it will be useful,
** but without any warranty; without even the implied warranty of
** merchantability or fitness for a particular purpose.
**
** Author contact information:
**   drh@hwaci.com
**   http://www.hwaci.com/drh/
**
*************************************************************************
** This file contains code used to scan a data source during a query.
*/
#include "xjd1Int.h"

int xjd1ScannerInit(Query *pQuery, DataSrc *pDSrc){
  if( pDSrc==0 ) return XJD1_OK;
  pDSrc->pQuery = pQuery;
  return XJD1_OK;
}
int xjd1ScannerEOF(DataSrc *pDSrc){
  return 1;
}
int xjd1ScannerStep(DataSrc *pDSrc){
  return XJD1_DONE;
}
int xjd1ScannerRewind(DataSrc *pDSrc){
  return XJD1_OK;
}
int xjd1ScannerClose(DataSrc *pDSrc){
  return XJD1_OK;
}
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<










































































Changes to src/stmt.c.

39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
  p->zCode = xjd1PoolDup(&p->sPool, zStmt, -1);
  if( pN==0 ) pN = &dummy;
  rc = xjd1RunParser(pConn, p, p->zCode, pN);
  pCmd = p->pCmd;
  if( pCmd ){
    switch( pCmd->eCmdType ){
      case TK_SELECT: {
        xjd1QueryInit(p, pCmd->u.q.pQuery);
        break;
      }
      case TK_INSERT: {
        xjd1QueryInit(p, pCmd->u.ins.pQuery);
        break;
      }
    }
  }
  return rc;
}








|



|







39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
  p->zCode = xjd1PoolDup(&p->sPool, zStmt, -1);
  if( pN==0 ) pN = &dummy;
  rc = xjd1RunParser(pConn, p, p->zCode, pN);
  pCmd = p->pCmd;
  if( pCmd ){
    switch( pCmd->eCmdType ){
      case TK_SELECT: {
        xjd1QueryInit(pCmd->u.q.pQuery, p, 0);
        break;
      }
      case TK_INSERT: {
        xjd1QueryInit(pCmd->u.ins.pQuery, p, 0);
        break;
      }
    }
  }
  return rc;
}

Changes to src/xjd1Int.h.

38
39
40
41
42
43
44

45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
...
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
...
128
129
130
131
132
133
134
135

136
137
138
139
140
141
142
143
144
145
146
147
148




149
150
151
152
153
154
155
...
162
163
164
165
166
167
168

169
170
171
172
173
174
175
...
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
...
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
...
281
282
283
284
285
286
287














288
289
290
291
292
293
294
...
299
300
301
302
303
304
305
306
307
308

309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
#define TK_FUNCTION       100
#define TK_SPACE          101
#define TK_ILLEGAL        102
#define TK_CREATEDATASET  103
#define TK_DROPDATASET    104

typedef unsigned char u8;

typedef struct Command Command;
typedef struct DataSrc DataSrc;
typedef struct Expr Expr;
typedef struct ExprItem ExprItem;
typedef struct ExprList ExprList;
typedef struct JsonNode JsonNode;
typedef struct JsonStructElem JsonStructElem;
typedef struct Line Line;
typedef struct Parse Parse;
typedef struct PoolChunk PoolChunk;
typedef struct Pool Pool;
typedef struct Query Query;
typedef struct String String;
typedef struct Token Token;

................................................................................
  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 */
  Line *pLine;                      /* Active lines */
  char *zErrMsg;                    /* Error message */
};

/* A token into to the parser */
struct Token {
  const char *z;                    /* Text of the token */
  int n;                            /* Number of characters */
................................................................................
  int nEItem;               /* Number of items on the expression list */
  int nEAlloc;              /* Slots allocated in apEItem[] */
  ExprItem *apEItem;        /* The expression in the list */
};

/* A node of an expression */
struct Expr {
  int eType;                /* Expression node type */

  union {
    struct {                /* Binary and unary operators */
      Expr *pLeft;             /* Left operand.  Only operand for unary ops */
      Expr *pRight;            /* Right operand.  NULL for unary ops */
    } bi;
    Token tk;               /* Token values */
    struct {                /* Function calls */
      Token name;              /* Name of the function */
      ExprList *args;          /* List of argumnts */
    } 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 eQType;                   /* Query type */
  xjd1_stmt *pStmt;             /* Statement this query is part of */
  Query *pOuter;                /* Next outer query for a subquery */
  union {
    struct {                    /* For compound queries */
      Query *pLeft;               /* Left subquery */
      Query *pRight;              /* Righ subquery */

    } compound;
    struct {                    /* For simple queries */
      ExprList *pCol;             /* List of result columns */
      DataSrc *pFrom;             /* The FROM clause */
      Expr *pWhere;               /* The WHERE clause */
      ExprList *pGroupBy;         /* The GROUP BY clause */
      Expr *pHaving;              /* The HAVING clause */
................................................................................
};

/* A Data Source is a representation of a term out of the FROM clause. */
struct DataSrc {
  int eDSType;              /* Source type */
  Token asId;               /* The identifier after the AS keyword */
  Query *pQuery;            /* Query this data source services */
  Line *pOut;               /* Where output of this source is stored */
  int isOwner;              /* True if this DataSrc owns the pOut line */
  union {
    struct {                /* For a join.  eDSType==TK_COMMA */
      DataSrc *pLeft;          /* Data source on the left */
      DataSrc *pRight;         /* Data source on the right */
    } join;
    struct {                /* For a named table.  eDSType==TK_ID */
................................................................................
    } flatten;
    struct {                /* A subquery.  eDSType==TK_SELECT */
      Query *q;                /* The subquery */
    } subq;
  } u;
};

/* A line is analogous to a row in an SQL database */
struct Line {
  Line *pNext;              /* Next line in a list */
  Token name;               /* Name of this line */
  JsonNode *pValue;         /* JSON associated with this line */
};

/* Any command, including but not limited to a query */
struct Command {
  int eCmdType;             /* Type of command */
  union {
    struct {                /* Transaction control operations */
      Token id;                /* Transaction name */
    } trans;
................................................................................

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

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















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

/******************************** malloc.c ***********************************/
................................................................................
void *xjd1PoolMallocZero(Pool*, int);
char *xjd1PoolDup(Pool*, const char *, int);

/******************************** pragma.c ***********************************/
int xjd1PragmaStep(xjd1_stmt*);

/******************************** query.c ************************************/
int xjd1QueryInit(xjd1_stmt*,Query*);
int xjd1QueryRewind(Query*);
int xjd1QueryStep(Query*);

int xjd1QueryClose(Query*);

/******************************** scan.c *************************************/
int xjd1ScannerInit(Query*,DataSrc*);
int xjd1ScannerRewind(DataSrc*);
int xjd1ScannerEOF(DataSrc*);
int xjd1ScannerStep(DataSrc*);
int xjd1ScannerClose(DataSrc*);

/******************************** stmt.c *************************************/

/******************************** string.c ***********************************/
int xjd1Strlen30(const char *);
void xjd1StringInit(String*, Pool*, int);
String *xjd1StringNew(Pool*, int);
int xjd1StringAppend(String*, const char*, int);







>







<







 







<







 







|
>

|



|
|



|


>
>
>
>







 







>







 







|







 







<
<
<
<
<
<
<







 







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







 







|


>


<
<
<
<
<
<
<







38
39
40
41
42
43
44
45
46
47
48
49
50
51
52

53
54
55
56
57
58
59
...
103
104
105
106
107
108
109

110
111
112
113
114
115
116
...
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
152
153
154
155
156
157
158
159
...
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
...
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
...
208
209
210
211
212
213
214







215
216
217
218
219
220
221
...
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
...
311
312
313
314
315
316
317
318
319
320
321
322
323







324
325
326
327
328
329
330
#define TK_FUNCTION       100
#define TK_SPACE          101
#define TK_ILLEGAL        102
#define TK_CREATEDATASET  103
#define TK_DROPDATASET    104

typedef unsigned char u8;
typedef unsigned short int u16;
typedef struct Command Command;
typedef struct DataSrc DataSrc;
typedef struct Expr Expr;
typedef struct ExprItem ExprItem;
typedef struct ExprList ExprList;
typedef struct JsonNode JsonNode;
typedef struct JsonStructElem JsonStructElem;

typedef struct Parse Parse;
typedef struct PoolChunk PoolChunk;
typedef struct Pool Pool;
typedef struct Query Query;
typedef struct String String;
typedef struct Token Token;

................................................................................
  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 */
................................................................................
  int nEItem;               /* Number of items on the expression list */
  int nEAlloc;              /* Slots allocated in apEItem[] */
  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 */
      Token name;              /* Name of the function */
      ExprList *args;          /* List of argumnts */
    } func;
    Query *q;               /* Subqueries. eClass=EXPR_Q */
  } u;
};
#define XJD1_EXPR_BI      1
#define XJD1_EXPR_TK      2
#define XJD1_EXPR_FUNC    3
#define XJD1_EXPR_Q       4

/* Parsing context */
struct Parse {
  xjd1 *pConn;                    /* Connect for recording errors */
  Pool *pPool;                    /* Memory allocation pool */
  Command *pCmd;                  /* Results */
  Token sTok;                     /* Last token seen */
................................................................................
  int eQType;                   /* Query type */
  xjd1_stmt *pStmt;             /* Statement this query is part of */
  Query *pOuter;                /* Next outer query for a subquery */
  union {
    struct {                    /* For compound queries */
      Query *pLeft;               /* Left subquery */
      Query *pRight;              /* Righ subquery */
      int doneLeft;               /* True if left is run to completion */
    } compound;
    struct {                    /* For simple queries */
      ExprList *pCol;             /* List of result columns */
      DataSrc *pFrom;             /* The FROM clause */
      Expr *pWhere;               /* The WHERE clause */
      ExprList *pGroupBy;         /* The GROUP BY clause */
      Expr *pHaving;              /* The HAVING clause */
................................................................................
};

/* A Data Source is a representation of a term out of the FROM clause. */
struct DataSrc {
  int eDSType;              /* Source type */
  Token asId;               /* The identifier after the AS keyword */
  Query *pQuery;            /* Query this data source services */
  JsonNode *pValue;         /* Current value for this data source */
  int isOwner;              /* True if this DataSrc owns the pOut line */
  union {
    struct {                /* For a join.  eDSType==TK_COMMA */
      DataSrc *pLeft;          /* Data source on the left */
      DataSrc *pRight;         /* Data source on the right */
    } join;
    struct {                /* For a named table.  eDSType==TK_ID */
................................................................................
    } flatten;
    struct {                /* A subquery.  eDSType==TK_SELECT */
      Query *q;                /* The subquery */
    } subq;
  } u;
};








/* Any command, including but not limited to a query */
struct Command {
  int eCmdType;             /* Type of command */
  union {
    struct {                /* Transaction control operations */
      Token id;                /* Transaction name */
    } trans;
................................................................................

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

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

/******************************** datasrc.c **********************************/
int xjd1DataSrcInit(DataSrc*,Query*);
int xjd1DataSrcRewind(DataSrc*);
int xjd1DataSrcStep(DataSrc*);
int xjd1DataSrcEOF(DataSrc*);
int xjd1DataSrcClose(DataSrc*);

/******************************** expr.c *************************************/
int xjd1ExprInit(Expr*, xjd1_stmt*, Query*);
int xjd1ExprListInit(ExprList*, xjd1_stmt*, Query*);
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 ***********************************/
................................................................................
void *xjd1PoolMallocZero(Pool*, int);
char *xjd1PoolDup(Pool*, const char *, int);

/******************************** pragma.c ***********************************/
int xjd1PragmaStep(xjd1_stmt*);

/******************************** query.c ************************************/
int xjd1QueryInit(Query*,xjd1_stmt*,Query*);
int xjd1QueryRewind(Query*);
int xjd1QueryStep(Query*);
int xjd1QueryEOF(Query*);
int xjd1QueryClose(Query*);








/******************************** stmt.c *************************************/

/******************************** string.c ***********************************/
int xjd1Strlen30(const char *);
void xjd1StringInit(String*, Pool*, int);
String *xjd1StringNew(Pool*, int);
int xjd1StringAppend(String*, const char*, int);