UnQL

Check-in [f4d26bb1e0]
Login

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

Overview
Comment:Get DELETE statements working.
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: f4d26bb1e0d01a674f5e04a951c45c77b947e61f
User & Date: drh 2011-06-30 00:09:07
Context
2011-06-30
15:51
Added preliminary UPSERT syntax. Added some simple UPDATE test cases, but since the UPDATE code is not in place, those test cases are currently failing. check-in: c0f72777e2 user: drh tags: trunk
00:09
Get DELETE statements working. check-in: f4d26bb1e0 user: drh tags: trunk
2011-06-29
23:08
Basic WHERE clauses working on simple SELECT statements. check-in: 0f90d3efaf 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
52
53
54
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 

# Generated source code files







|







>







33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
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 delete.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
LIBOBJ+= update.o

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

# Generated source code files

Added src/delete.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/
**
*************************************************************************
** Code to evaluate a DELETE command.
*/
#include "xjd1Int.h"

/*
** Evaluate a pragma.
**
** Unknown pragmas are silently ignored.
*/
int xjd1DeleteStep(xjd1_stmt *pStmt){
  Command *pCmd = pStmt->pCmd;
  int rc = XJD1_OK;
  sqlite3 *db;
  sqlite3_stmt *pQuery = 0;
  sqlite3_stmt *pIns = 0;
  char *zSql;
  
  assert( pCmd!=0 );
  assert( pCmd->eCmdType==TK_DELETE );
  db = pStmt->pConn->db;
  if( pCmd->u.del.pWhere==0 ){
    zSql = sqlite3_mprintf("DELETE FROM \"%w\"", pCmd->u.del.zName);
    sqlite3_exec(db, zSql, 0, 0, 0);
    sqlite3_free(zSql);
    return XJD1_OK;
  }
  sqlite3_exec(db, "BEGIN; CREATE TEMP TABLE _t1(x INTEGER PRIMARY KEY)",
               0, 0, 0);
  zSql = sqlite3_mprintf("SELECT rowid, x FROM \"%w\"", pCmd->u.del.zName);
  sqlite3_prepare_v2(db, zSql, -1, &pQuery, 0);
  sqlite3_prepare_v2(db, "INSERT INTO _t1(x) VALUES(?)", -1, &pIns, 0);
  if( pQuery ){
    while( SQLITE_ROW==sqlite3_step(pQuery) ){
      const char *zJson = (const char*)sqlite3_column_text(pQuery, 1);
      pStmt->pDoc = xjd1JsonParse(zJson, -1);
      if( xjd1ExprTrue(pCmd->u.del.pWhere) ){
        sqlite3_bind_int64(pIns, 0, sqlite3_column_int64(pQuery, 0));
        sqlite3_step(pIns);
        sqlite3_reset(pIns);
      }
      xjd1JsonFree(pStmt->pDoc);
      pStmt->pDoc = 0;
    }
  }
  sqlite3_finalize(pQuery);
  sqlite3_finalize(pIns);
  sqlite3_free(zSql);
  zSql = sqlite3_mprintf(
            "DELETE FROM \"%w\" WHERE rowid IN _t1;"
            "DROP TABLE _t1; COMMIT", pCmd->u.del.zName);
  sqlite3_exec(db, zSql, 0, 0, 0);
  sqlite3_free(zSql);
  return rc;
}

Changes to src/expr.c.

161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
int xjd1ExprListClose(ExprList *p){
  WalkAction sAction;
  memset(&sAction, 0, sizeof(sAction));
  sAction.xQueryAction = walkCloseQueryCallback;
  return walkExprList(p,&sAction);
}

/*
** Compute a real value from an expression
*/
static double realFromExpr(Expr *p){
  double r = 0.0;
  JsonNode *pNode;
  if( p==0 ) return 0.0;
  if( p->eType==TK_JVALUE ){
    pNode = p->u.json.p;
  }else{
    pNode = xjd1ExprEval(p);
  }
  xjd1JsonToReal(pNode, &r);
  if( p->eType!=TK_JVALUE ){
    xjd1JsonFree(pNode);
  }
  return r;
}

/*
** Return true if the JSON object is a string
*/
static int isStr(const JsonNode *p){
  if( p==0 ) return 0;
  switch( p->eJType ){
    case XJD1_TRUE:







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







161
162
163
164
165
166
167



















168
169
170
171
172
173
174
int xjd1ExprListClose(ExprList *p){
  WalkAction sAction;
  memset(&sAction, 0, sizeof(sAction));
  sAction.xQueryAction = walkCloseQueryCallback;
  return walkExprList(p,&sAction);
}




















/*
** Return true if the JSON object is a string
*/
static int isStr(const JsonNode *p){
  if( p==0 ) return 0;
  switch( p->eJType ){
    case XJD1_TRUE:

Changes to src/json.c.

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
      *pRes = 1.0;
      return 0;
    }
    case XJD1_REAL: {
      *pRes = p->u.r;
      return 0;
    }
    case XJD1_NULL: {
      return 1;
    }
    case XJD1_STRING: {
      char *zEnd;
      if( isspace(p->u.z[0]) ){
        return 1;
      }else{
        *pRes = strtod(p->u.z, &zEnd);
        if( zEnd[0]!=0 ){
          return 1;
        }
        return 0;
      }
    }
    case XJD1_ARRAY: {
      return 1;
    }
    case XJD1_STRUCT: {
      return 1;
    }
  }
}

/*
** Attempt to convert a JSON object into a string.  Return 0
** if successful and 1 if there is an error.
*/
int xjd1JsonToString(const JsonNode *p, String *pOut){







<
<
<












<
<
|
<
|
<
<







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
      *pRes = 1.0;
      return 0;
    }
    case XJD1_REAL: {
      *pRes = p->u.r;
      return 0;
    }



    case XJD1_STRING: {
      char *zEnd;
      if( isspace(p->u.z[0]) ){
        return 1;
      }else{
        *pRes = strtod(p->u.z, &zEnd);
        if( zEnd[0]!=0 ){
          return 1;
        }
        return 0;
      }
    }


  }

  return 1;


}

/*
** Attempt to convert a JSON object into a string.  Return 0
** if successful and 1 if there is an error.
*/
int xjd1JsonToString(const JsonNode *p, String *pOut){

Changes to src/stmt.c.

46
47
48
49
50
51
52









53
54
55
56
57
58
59
..
77
78
79
80
81
82
83









84
85
86
87
88
89
90
...
182
183
184
185
186
187
188








189
190
191
192
193
194
195
...
253
254
255
256
257
258
259




260
261
262
263
        xjd1QueryInit(pCmd->u.q.pQuery, p, 0);
        break;
      }
      case TK_INSERT: {
        xjd1QueryInit(pCmd->u.ins.pQuery, p, 0);
        break;
      }









    }
  }
  return rc;
}

/*
** Configure a prepared statement.
................................................................................
      case TK_SELECT: {
        xjd1QueryClose(pCmd->u.q.pQuery);
        break;
      }
      case TK_INSERT: {
        xjd1QueryClose(pCmd->u.ins.pQuery);
        break;









      }
    }
  }

  if( pStmt->pPrev ){
    pStmt->pPrev->pNext = pStmt->pNext;
  }else{
................................................................................
        xjd1JsonRender(&pStmt->retValue, pValue);
        xjd1JsonFree(pValue);
        pStmt->okValue = 1;
      }else{
        pStmt->okValue = 0;
      }
      break;








    }
    case TK_PRAGMA: {
      rc = xjd1PragmaStep(pStmt);
      break;
    }
  }
  return rc;
................................................................................
  if( pStmt==0 ) return 0;
  pCmd = pStmt->pCmd;
  if( pCmd==0 ) return 0;
  switch( pCmd->eCmdType ){
    case TK_SELECT: {
      pRes = xjd1QueryDoc(pCmd->u.q.pQuery, zDocName);
      break;




    }
  }
  return pRes;
}







>
>
>
>
>
>
>
>
>







 







>
>
>
>
>
>
>
>
>







 







>
>
>
>
>
>
>
>







 







>
>
>
>




46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
..
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
...
200
201
202
203
204
205
206
207
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
        xjd1QueryInit(pCmd->u.q.pQuery, p, 0);
        break;
      }
      case TK_INSERT: {
        xjd1QueryInit(pCmd->u.ins.pQuery, p, 0);
        break;
      }
      case TK_DELETE: {
        xjd1ExprInit(pCmd->u.del.pWhere, p, 0);
        break;
      }
      case TK_UPDATE: {
        xjd1ExprInit(pCmd->u.update.pWhere, p, 0);
        xjd1ExprListInit(pCmd->u.update.pChng, p, 0);
        break;
      }
    }
  }
  return rc;
}

/*
** Configure a prepared statement.
................................................................................
      case TK_SELECT: {
        xjd1QueryClose(pCmd->u.q.pQuery);
        break;
      }
      case TK_INSERT: {
        xjd1QueryClose(pCmd->u.ins.pQuery);
        break;
      }
      case TK_DELETE: {
        xjd1ExprClose(pCmd->u.del.pWhere);
        break;
      }
      case TK_UPDATE: {
        xjd1ExprClose(pCmd->u.update.pWhere);
        xjd1ExprListClose(pCmd->u.update.pChng);
        break;
      }
    }
  }

  if( pStmt->pPrev ){
    pStmt->pPrev->pNext = pStmt->pNext;
  }else{
................................................................................
        xjd1JsonRender(&pStmt->retValue, pValue);
        xjd1JsonFree(pValue);
        pStmt->okValue = 1;
      }else{
        pStmt->okValue = 0;
      }
      break;
    }
    case TK_DELETE: {
      rc = xjd1DeleteStep(pStmt);
      break;
    }
    case TK_UPDATE: {
      rc = xjd1UpdateStep(pStmt);
      break;
    }
    case TK_PRAGMA: {
      rc = xjd1PragmaStep(pStmt);
      break;
    }
  }
  return rc;
................................................................................
  if( pStmt==0 ) return 0;
  pCmd = pStmt->pCmd;
  if( pCmd==0 ) return 0;
  switch( pCmd->eCmdType ){
    case TK_SELECT: {
      pRes = xjd1QueryDoc(pCmd->u.q.pQuery, zDocName);
      break;
    }
    case TK_DELETE: {
      pRes = xjd1JsonRef(pStmt->pDoc);
      break;
    }
  }
  return pRes;
}

Added src/update.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
/*
** 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/
**
*************************************************************************
** Code to evaluate an UPDATE statement
*/
#include "xjd1Int.h"

/*
** Evaluate an UPDATE.
*/
int xjd1UpdateStep(xjd1_stmt *pStmt){
  Command *pCmd = pStmt->pCmd;
  int rc = XJD1_OK;
  assert( pCmd!=0 );
  assert( pCmd->eCmdType==TK_UPDATE );
  return rc;
}

Changes to src/xjd1Int.h.

106
107
108
109
110
111
112

113
114
115
116
117
118
119
...
316
317
318
319
320
321
322



323
324
325
326
327
328
329
...
392
393
394
395
396
397
398
399




400
  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 */

  int okValue;                      /* True if retValue is valid */
  String retValue;                  /* String rendering of return value */
  char *zErrMsg;                    /* Error message */
};

/* A token into to the parser */
struct Token {
................................................................................
/******************************** datasrc.c **********************************/
int xjd1DataSrcInit(DataSrc*,Query*);
int xjd1DataSrcRewind(DataSrc*);
int xjd1DataSrcStep(DataSrc*);
int xjd1DataSrcEOF(DataSrc*);
int xjd1DataSrcClose(DataSrc*);
JsonNode *xjd1DataSrcDoc(DataSrc*, const char*);




/******************************** expr.c *************************************/
int xjd1ExprInit(Expr*, xjd1_stmt*, Query*);
int xjd1ExprListInit(ExprList*, xjd1_stmt*, Query*);
JsonNode *xjd1ExprEval(Expr*);
int xjd1ExprTrue(Expr*);
int xjd1ExprClose(Expr*);
................................................................................
/******************************** trace.c ************************************/
const char *xjd1TokenName(int);
void xjd1TraceCommand(String*,int,const Command*);
void xjd1TraceQuery(String*,int,const Query*);
void xjd1TraceDataSrc(String*,int,const DataSrc*);
void xjd1TraceExpr(String*,const Expr*);
void xjd1TraceExprList(String*,int, const ExprList*);





#endif /* _XJD1INT_H */







>







 







>
>
>







 








>
>
>
>

106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
...
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
...
396
397
398
399
400
401
402
403
404
405
406
407
408
  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 */
  JsonNode *pDoc;                   /* Current document */
  int okValue;                      /* True if retValue is valid */
  String retValue;                  /* String rendering of return value */
  char *zErrMsg;                    /* Error message */
};

/* A token into to the parser */
struct Token {
................................................................................
/******************************** datasrc.c **********************************/
int xjd1DataSrcInit(DataSrc*,Query*);
int xjd1DataSrcRewind(DataSrc*);
int xjd1DataSrcStep(DataSrc*);
int xjd1DataSrcEOF(DataSrc*);
int xjd1DataSrcClose(DataSrc*);
JsonNode *xjd1DataSrcDoc(DataSrc*, const char*);

/******************************** delete.c ***********************************/
int xjd1DeleteStep(xjd1_stmt*);

/******************************** expr.c *************************************/
int xjd1ExprInit(Expr*, xjd1_stmt*, Query*);
int xjd1ExprListInit(ExprList*, xjd1_stmt*, Query*);
JsonNode *xjd1ExprEval(Expr*);
int xjd1ExprTrue(Expr*);
int xjd1ExprClose(Expr*);
................................................................................
/******************************** trace.c ************************************/
const char *xjd1TokenName(int);
void xjd1TraceCommand(String*,int,const Command*);
void xjd1TraceQuery(String*,int,const Query*);
void xjd1TraceDataSrc(String*,int,const DataSrc*);
void xjd1TraceExpr(String*,const Expr*);
void xjd1TraceExprList(String*,int, const ExprList*);

/******************************** update.c ***********************************/
int xjd1UpdateStep(xjd1_stmt*);


#endif /* _XJD1INT_H */

Changes to test/base01.test.

35
36
37
38
39
40
41










.testcase 150
SELECT FROM abc WHERE abc.name=="abc";
.result {"name":"abc"}
.testcase 151
SELECT FROM abc WHERE abc.name=="xyz";
.result
















>
>
>
>
>
>
>
>
>
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50

.testcase 150
SELECT FROM abc WHERE abc.name=="abc";
.result {"name":"abc"}
.testcase 151
SELECT FROM abc WHERE abc.name=="xyz";
.result

.testcase 160
DELETE FROM abc WHERE abc.name=="xyz";
SELECT FROM abc;
.result {"name":"abc"}
.testcase 161
DELETE FROM abc WHERE abc.name=="abc";
SELECT FROM abc;
.result