/ Check-in [f4d9089c]
Login

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

Overview
Comment::-) (CVS 62)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: f4d9089c5d69b16fee5feb49b02e524499e6328d
User & Date: drh 2000-06-06 21:56:08
Context
2000-06-06
22:13
:-) (CVS 63) check-in: 65d2100d user: drh tags: trunk
21:56
:-) (CVS 62) check-in: f4d9089c user: drh tags: trunk
19:18
:-) (CVS 61) check-in: 25984b4d user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Show Whitespace Changes Patch

Changes to src/parse.y.

22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
...
135
136
137
138
139
140
141


142











143
144
145
146
147
148
149
150
...
217
218
219
220
221
222
223

224
225
226
227
228
229
230
**
*************************************************************************
** This file contains SQLite's grammar for SQL.  Process this file
** using the lemon parser generator to generate C code that runs
** the parser.  Lemon will also generate a header file containing
** numeric codes for all of the tokens.
**
** @(#) $Id: parse.y,v 1.13 2000/06/06 17:27:05 drh Exp $
*/
%token_prefix TK_
%token_type {Token}
%extra_argument {Parse *pParse}
%syntax_error {
  sqliteSetNString(&pParse->zErrMsg,"syntax error near \"",0,TOKEN.z,TOKEN.n,
                   "\"", 1, 0);
................................................................................
cmd ::= select(X).  {
  sqliteSelect(pParse, X, SRT_Callback, 0);
  sqliteSelectDelete(X);
}

%type select {Select*}
%destructor select {sqliteSelectDelete($$);}














select(A) ::= SELECT distinct(D) selcollist(W) from(X) where_opt(Y)
              groupby_opt(P) having_opt(Q) orderby_opt(Z). {
  A = sqliteSelectNew(W,X,Y,P,Q,Z,D);
}

// The "distinct" nonterminal is true (1) if the DISTINCT keyword is
// present and false (0) if it is not.
//
................................................................................
groupby_opt(A) ::= .     {A = 0;}
groupby_opt(A) ::= GROUP BY exprlist(X).  {A = X;}

%type having_opt {Expr*}
%destructor having_opt {sqliteExprDelete($$);}
having_opt(A) ::= .      {A = 0;}
having_opt(A) ::= HAVING expr(X).  {A = X;}


cmd ::= DELETE FROM ID(X) where_opt(Y).
    {sqliteDeleteFrom(pParse, &X, Y);}

%type where_opt {Expr*}
%destructor where_opt {sqliteExprDelete($$);}








|







 







>
>

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







 







>







22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
...
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
160
161
162
163
...
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
**
*************************************************************************
** This file contains SQLite's grammar for SQL.  Process this file
** using the lemon parser generator to generate C code that runs
** the parser.  Lemon will also generate a header file containing
** numeric codes for all of the tokens.
**
** @(#) $Id: parse.y,v 1.14 2000/06/06 21:56:08 drh Exp $
*/
%token_prefix TK_
%token_type {Token}
%extra_argument {Parse *pParse}
%syntax_error {
  sqliteSetNString(&pParse->zErrMsg,"syntax error near \"",0,TOKEN.z,TOKEN.n,
                   "\"", 1, 0);
................................................................................
cmd ::= select(X).  {
  sqliteSelect(pParse, X, SRT_Callback, 0);
  sqliteSelectDelete(X);
}

%type select {Select*}
%destructor select {sqliteSelectDelete($$);}
%type oneselect {Select*}
%destructor oneselect {sqliteSelectDelete($$);}

select(A) ::= oneselect(X).                      {A = X;}
select(A) ::= select(X) joinop(Y) oneselect(Z).  {
    Z->op = Y;
    Z->pPrior = X;
    A = Z;
}
%type joinop {int}
joinop(A) ::= UNION.      {A = TK_UNION;}
joinop(A) ::= UNION ALL.  {A = TK_ALL;}
joinop(A) ::= INTERSECT.  {A = TK_INTERSECT;}
joinop(A) ::= EXCEPT.     {A = TK_EXCEPT;}
oneselect(A) ::= SELECT distinct(D) selcollist(W) from(X) where_opt(Y)
                 groupby_opt(P) having_opt(Q) orderby_opt(Z). {
  A = sqliteSelectNew(W,X,Y,P,Q,Z,D);
}

// The "distinct" nonterminal is true (1) if the DISTINCT keyword is
// present and false (0) if it is not.
//
................................................................................
groupby_opt(A) ::= .     {A = 0;}
groupby_opt(A) ::= GROUP BY exprlist(X).  {A = X;}

%type having_opt {Expr*}
%destructor having_opt {sqliteExprDelete($$);}
having_opt(A) ::= .      {A = 0;}
having_opt(A) ::= HAVING expr(X).  {A = X;}


cmd ::= DELETE FROM ID(X) where_opt(Y).
    {sqliteDeleteFrom(pParse, &X, Y);}

%type where_opt {Expr*}
%destructor where_opt {sqliteExprDelete($$);}

Changes to src/select.c.

20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
..
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
..
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
...
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
151

152
153
154
155
156
157
158
159
160
161
162
163
164

























































































































































165
166
167
168
169
170
171
...
176
177
178
179
180
181
182
183


184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
...
204
205
206
207
208
209
210








211
212
213
214
215
216
217
...
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
...
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
...
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
...
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
**   drh@hwaci.com
**   http://www.hwaci.com/drh/
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle SELECT statements.
**
** $Id: select.c,v 1.12 2000/06/06 18:00:16 drh Exp $
*/
#include "sqliteInt.h"

/*
** Allocate a new Select structure and return a pointer to that
** structure.
*/
................................................................................
  pNew->pEList = pEList;
  pNew->pSrc = pSrc;
  pNew->pWhere = pWhere;
  pNew->pGroupBy = pGroupBy;
  pNew->pHaving = pHaving;
  pNew->pOrderBy = pOrderBy;
  pNew->isDistinct = isDistinct;

  return pNew;
}

/*
** Delete the given Select structure and all of its substructures.
*/
void sqliteSelectDelete(Select *p){

  sqliteExprListDelete(p->pEList);
  sqliteIdListDelete(p->pSrc);
  sqliteExprDelete(p->pWhere);
  sqliteExprListDelete(p->pGroupBy);
  sqliteExprDelete(p->pHaving);
  sqliteExprListDelete(p->pOrderBy);

  sqliteFree(p);
}

/*
** Delete the aggregate information from the parse structure.
*/
void sqliteParseInfoReset(Parse *pParse){
................................................................................
  pParse->iAggCount = -1;
  pParse->useAgg = 0;
}

/*
** This routine generates the code for the inside of the inner loop
** of a SELECT.




*/
static int selectInnerLoop(
  Parse *pParse,          /* The parser context */
  ExprList *pEList,       /* List of values being extracted */


  ExprList *pOrderBy,     /* If not NULL, sort results using this key */
  int distinct,           /* If >=0, make sure results are distinct */
  int eDest,              /* How to dispose of the results */
  int iParm,              /* An argument to the disposal method */
  int iContinue,          /* Jump here to continue with next row */
  int iBreak              /* Jump here to break out of the inner loop */
){
  Vdbe *v = pParse->pVdbe;
  int i;

  /* Pull the requested fields.
  */

  for(i=0; i<pEList->nExpr; i++){
    sqliteExprCode(pParse, pEList->a[i].pExpr);






  }

  /* If the current result is not distinct, skip the rest
  ** of the processing for the current row.
  */
  if( distinct>=0 ){
    int lbl = sqliteVdbeMakeLabel(v);
................................................................................
    sqliteVdbeAddOp(v, OP_MakeKey, pEList->nExpr, 1, 0, 0);
    sqliteVdbeAddOp(v, OP_Distinct, distinct, lbl, 0, 0);
    sqliteVdbeAddOp(v, OP_Pop, pEList->nExpr+1, 0, 0, 0);
    sqliteVdbeAddOp(v, OP_Goto, 0, iContinue, 0, 0);
    sqliteVdbeAddOp(v, OP_String, 0, 0, "", lbl);
    sqliteVdbeAddOp(v, OP_Put, distinct, 0, 0, 0);
  }

  /* If there is an ORDER BY clause, then store the results
  ** in a sorter.
  */
  if( pOrderBy ){
    char *zSortOrder;
    sqliteVdbeAddOp(v, OP_SortMakeRec, pEList->nExpr, 0, 0, 0);
    zSortOrder = sqliteMalloc( pOrderBy->nExpr + 1 );
................................................................................
      sqliteExprCode(pParse, pOrderBy->a[i].pExpr);
    }
    zSortOrder[pOrderBy->nExpr] = 0;
    sqliteVdbeAddOp(v, OP_SortMakeKey, pOrderBy->nExpr, 0, zSortOrder, 0);
    sqliteVdbeAddOp(v, OP_SortPut, 0, 0, 0, 0);
  }else 

  /* If we are writing to a table, then write the results to the table.

  */
  if( eDest==SRT_Table ){
    sqliteVdbeAddOp(v, OP_MakeRecord, pEList->nExpr, 0, 0, 0);
    sqliteVdbeAddOp(v, OP_New, iParm, 0, 0, 0);
    sqliteVdbeAddOp(v, OP_Pull, 1, 0, 0, 0);









    sqliteVdbeAddOp(v, OP_Put, iParm, 0, 0, 0);
  }else 

  /* If we are creating a set for an "expr IN (SELECT ...)" construct,
  ** then there should be a single item on the stack.  Write this
  ** item into the set table with bogus data.
  */
  if( eDest==SRT_Set ){
    assert( pEList->nExpr==1 );
    sqliteVdbeAddOp(v, OP_String, 0, 0, "", 0);
    sqliteVdbeAddOp(v, OP_Put, iParm, 0, 0, 0);
  }else 


  /* If this is a scalar select that is part of an expression, then
  ** store the results in the appropriate memory cell and break out
  ** of the scan loop.
  */
  if( eDest==SRT_Mem ){
    sqliteVdbeAddOp(v, OP_MemStore, iParm, 0, 0, 0);
    sqliteVdbeAddOp(v, OP_Goto, 0, iBreak, 0, 0);
  }else

  /* If none of the above, send the data to the callback function.
  */
  {
    sqliteVdbeAddOp(v, OP_Callback, pEList->nExpr, 0, 0, 0);

























































































































































  }
  return 0;
}

/*
** Generate code for the given SELECT statement.
**
................................................................................
**     ------------    -------------------------------------------
**     SRT_Callback    Invoke the callback for each row of the result.
**
**     SRT_Mem         Store first result in memory cell iParm
**
**     SRT_Set         Store results as keys of a table with cursor iParm
**
**     SRT_Table       Store results in a regular table with cursor iParm


**
** This routine returns the number of errors.  If any errors are
** encountered, then an appropriate error message is left in
** pParse->zErrMsg.
**
** This routine does NOT free the Select structure passed in.  The
** calling function needs to do that.
*/
int sqliteSelect(
  Parse *pParse,         /* The parser context */
  Select *p,             /* The SELECT statement being coded. */
  int eDest,             /* One of SRT_Callback, SRT_Mem, SRT_Set, SRT_Table */
  int iParm              /* Save result in this memory location, if >=0 */
){
  int i, j;
  WhereInfo *pWInfo;
  Vdbe *v;
  int isAgg = 0;         /* True for select lists like "count(*)" */
  ExprList *pEList;      /* List of fields to extract.  NULL means "*" */
................................................................................
  Expr *pWhere;          /* The WHERE clause.  May be NULL */
  ExprList *pOrderBy;    /* The ORDER BY clause.  May be NULL */
  ExprList *pGroupBy;    /* The GROUP BY clause.  May be NULL */
  Expr *pHaving;         /* The HAVING clause.  May be NULL */
  int isDistinct;        /* True if the DISTINCT keyword is present */
  int distinct;          /* Table to use for the distinct set */









  pEList = p->pEList;
  pTabList = p->pSrc;
  pWhere = p->pWhere;
  pOrderBy = p->pOrderBy;
  pGroupBy = p->pGroupBy;
  pHaving = p->pHaving;
  isDistinct = p->isDistinct;
................................................................................
  if( pEList==0 ){
    for(i=0; i<pTabList->nId; i++){
      Table *pTab = pTabList->a[i].pTab;
      for(j=0; j<pTab->nCol; j++){
        Expr *pExpr = sqliteExpr(TK_FIELD, 0, 0, 0);
        pExpr->iTable = i + pParse->nTab;
        pExpr->iField = j;
        pEList = sqliteExprListAppend(pEList, pExpr, 0);
      }
    }
  }

  /* If writing to memory or generating a set
  ** only a single column may be output.
  */
................................................................................
    sqliteVdbeAddOp(v, OP_SortOpen, 0, 0, 0, 0);
  }

  /* Identify column names if we will be using in the callback.  This
  ** step is skipped if the output is going to a table or a memory cell.
  */
  if( eDest==SRT_Callback ){
    sqliteVdbeAddOp(v, OP_ColumnCount, pEList->nExpr, 0, 0, 0);
    for(i=0; i<pEList->nExpr; i++){
      Expr *p;
      if( pEList->a[i].zName ){
        char *zName = pEList->a[i].zName;
        int addr = sqliteVdbeAddOp(v, OP_ColumnName, i, 0, zName, 0);
        if( zName[0]=='\'' || zName[0]=='"' ){
          sqliteVdbeDequoteP3(v, addr);
        }
        continue;
      }
      p = pEList->a[i].pExpr;
      if( p->op!=TK_FIELD ){
        char zName[30];
        sprintf(zName, "field%d", i+1);
        sqliteVdbeAddOp(v, OP_ColumnName, i, 0, zName, 0);
      }else{
        if( pTabList->nId>1 ){
          char *zName = 0;
          Table *pTab = pTabList->a[p->iTable].pTab;
          char *zTab;
  
          zTab = pTabList->a[p->iTable].zAlias;
          if( zTab==0 ) zTab = pTab->zName;
          sqliteSetString(&zName, zTab, ".", pTab->aCol[p->iField].zName, 0);
          sqliteVdbeAddOp(v, OP_ColumnName, i, 0, zName, 0);
          sqliteFree(zName);
        }else{
          Table *pTab = pTabList->a[0].pTab;
          char *zName = pTab->aCol[p->iField].zName;
          sqliteVdbeAddOp(v, OP_ColumnName, i, 0, zName, 0);
        }
      }
    }
  }

  /* Reset the aggregator
  */
  if( isAgg ){
    sqliteVdbeAddOp(v, OP_AggReset, 0, pParse->nAgg, 0, 0);
  }
................................................................................
  pWInfo = sqliteWhereBegin(pParse, pTabList, pWhere, 0);
  if( pWInfo==0 ) return 1;

  /* Use the standard inner loop if we are not dealing with
  ** aggregates
  */
  if( !isAgg ){
    if( selectInnerLoop(pParse, pEList, pOrderBy, distinct, eDest, iParm,
                    pWInfo->iContinue, pWInfo->iBreak) ){
       return 1;
    }
  }

  /* If we are dealing with aggregates, then to the special aggregate
  ** processing.  
................................................................................
    int endagg = sqliteVdbeMakeLabel(v);
    int startagg;
    startagg = sqliteVdbeAddOp(v, OP_AggNext, 0, endagg, 0, 0);
    pParse->useAgg = 1;
    if( pHaving ){
      sqliteExprIfFalse(pParse, pHaving, startagg);
    }
    if( selectInnerLoop(pParse, pEList, pOrderBy, distinct, eDest, iParm,
                    startagg, endagg) ){
      return 1;
    }
    sqliteVdbeAddOp(v, OP_Goto, 0, startagg, 0, 0);
    sqliteVdbeAddOp(v, OP_Noop, 0, 0, 0, endagg);
    pParse->useAgg = 0;
  }







|







 







>







>






>







 







>
>
>
>




>
>












>
|
|
>
>
>
>
>
>







 







>







 







|
>

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













>












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







 







|
>
>











|







 







>
>
>
>
>
>
>
>







 







|







 







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







 







|







 







|







20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
..
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
..
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
...
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
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
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
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
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
...
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
...
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
...
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
...
575
576
577
578
579
580
581
582

































583
584
585
586
587
588
589
...
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
...
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
**   drh@hwaci.com
**   http://www.hwaci.com/drh/
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle SELECT statements.
**
** $Id: select.c,v 1.13 2000/06/06 21:56:08 drh Exp $
*/
#include "sqliteInt.h"

/*
** Allocate a new Select structure and return a pointer to that
** structure.
*/
................................................................................
  pNew->pEList = pEList;
  pNew->pSrc = pSrc;
  pNew->pWhere = pWhere;
  pNew->pGroupBy = pGroupBy;
  pNew->pHaving = pHaving;
  pNew->pOrderBy = pOrderBy;
  pNew->isDistinct = isDistinct;
  pNew->op = TK_SELECT;
  return pNew;
}

/*
** Delete the given Select structure and all of its substructures.
*/
void sqliteSelectDelete(Select *p){
  if( p==0 ) return;
  sqliteExprListDelete(p->pEList);
  sqliteIdListDelete(p->pSrc);
  sqliteExprDelete(p->pWhere);
  sqliteExprListDelete(p->pGroupBy);
  sqliteExprDelete(p->pHaving);
  sqliteExprListDelete(p->pOrderBy);
  sqliteSelectDelete(p->pPrior);
  sqliteFree(p);
}

/*
** Delete the aggregate information from the parse structure.
*/
void sqliteParseInfoReset(Parse *pParse){
................................................................................
  pParse->iAggCount = -1;
  pParse->useAgg = 0;
}

/*
** This routine generates the code for the inside of the inner loop
** of a SELECT.
**
** The pEList is used to determine the values for each column in the
** result row.  Except  if pEList==NULL, then we just read nField
** elements from the srcTab table.
*/
static int selectInnerLoop(
  Parse *pParse,          /* The parser context */
  ExprList *pEList,       /* List of values being extracted */
  int srcTab,             /* Pull data from this table */
  int nField,             /* Number of fields in the source table */
  ExprList *pOrderBy,     /* If not NULL, sort results using this key */
  int distinct,           /* If >=0, make sure results are distinct */
  int eDest,              /* How to dispose of the results */
  int iParm,              /* An argument to the disposal method */
  int iContinue,          /* Jump here to continue with next row */
  int iBreak              /* Jump here to break out of the inner loop */
){
  Vdbe *v = pParse->pVdbe;
  int i;

  /* Pull the requested fields.
  */
  if( pEList ){
    for(i=0; i<pEList->nExpr; i++){
      sqliteExprCode(pParse, pEList->a[i].pExpr);
    }
    nField = pEList->nExpr;
  }else{
    for(i=0; i<nField; i++){
      sqliteVdbeAddOp(v, OP_Field, srcTab, i, 0, 0);
    }
  }

  /* If the current result is not distinct, skip the rest
  ** of the processing for the current row.
  */
  if( distinct>=0 ){
    int lbl = sqliteVdbeMakeLabel(v);
................................................................................
    sqliteVdbeAddOp(v, OP_MakeKey, pEList->nExpr, 1, 0, 0);
    sqliteVdbeAddOp(v, OP_Distinct, distinct, lbl, 0, 0);
    sqliteVdbeAddOp(v, OP_Pop, pEList->nExpr+1, 0, 0, 0);
    sqliteVdbeAddOp(v, OP_Goto, 0, iContinue, 0, 0);
    sqliteVdbeAddOp(v, OP_String, 0, 0, "", lbl);
    sqliteVdbeAddOp(v, OP_Put, distinct, 0, 0, 0);
  }

  /* If there is an ORDER BY clause, then store the results
  ** in a sorter.
  */
  if( pOrderBy ){
    char *zSortOrder;
    sqliteVdbeAddOp(v, OP_SortMakeRec, pEList->nExpr, 0, 0, 0);
    zSortOrder = sqliteMalloc( pOrderBy->nExpr + 1 );
................................................................................
      sqliteExprCode(pParse, pOrderBy->a[i].pExpr);
    }
    zSortOrder[pOrderBy->nExpr] = 0;
    sqliteVdbeAddOp(v, OP_SortMakeKey, pOrderBy->nExpr, 0, zSortOrder, 0);
    sqliteVdbeAddOp(v, OP_SortPut, 0, 0, 0, 0);
  }else 

  /* In this mode, write each query result to the key of the temporary
  ** table iParm.
  */
  if( eDest==SRT_Union ){
    sqliteVdbeAddOp(v, OP_MakeRecord, nField, 0, 0, 0);
    sqliteVdbeAddOp(v, OP_String, iParm, 0, "", 0);
    sqliteVdbeAddOp(v, OP_Put, iParm, 0, 0, 0);
  }else 

  /* Construct a record from the query result, but instead of
  ** saving that record, use it as a key to delete elements from
  ** the temporary table iParm.
  */
  if( eDest==SRT_Except ){
    assert( pEList->nExpr==1 );
    sqliteVdbeAddOp(v, OP_String, 0, 0, "", 0);
    sqliteVdbeAddOp(v, OP_Put, iParm, 0, 0, 0);
  }else 

  /* If we are creating a set for an "expr IN (SELECT ...)" construct,
  ** then there should be a single item on the stack.  Write this
  ** item into the set table with bogus data.
  */
  if( eDest==SRT_Set ){
    assert( pEList->nExpr==1 );
    sqliteVdbeAddOp(v, OP_String, 0, 0, "", 0);
    sqliteVdbeAddOp(v, OP_Put, iParm, 0, 0, 0);
  }else 


  /* If this is a scalar select that is part of an expression, then
  ** store the results in the appropriate memory cell and break out
  ** of the scan loop.
  */
  if( eDest==SRT_Mem ){
    sqliteVdbeAddOp(v, OP_MemStore, iParm, 0, 0, 0);
    sqliteVdbeAddOp(v, OP_Goto, 0, iBreak, 0, 0);
  }else

  /* If none of the above, send the data to the callback function.
  */
  {
    sqliteVdbeAddOp(v, OP_Callback, nField, 0, 0, 0);
  }
  return 0;
}

/*
** Generate code that will tell the VDBE how many columns there
** are in the result and the name for each column.  This information
** is used to provide "argc" and "azCol[]" values in the callback.
*/
static void generateColumnNames(Vdbe *v, IdList *pTabList, ExprList *pEList){
  int i;
  sqliteVdbeAddOp(v, OP_ColumnCount, pEList->nExpr, 0, 0, 0);
  for(i=0; i<pEList->nExpr; i++){
    Expr *p;
    if( pEList->a[i].zName ){
      char *zName = pEList->a[i].zName;
      int addr = sqliteVdbeAddOp(v, OP_ColumnName, i, 0, zName, 0);
      if( zName[0]=='\'' || zName[0]=='"' ){
        sqliteVdbeDequoteP3(v, addr);
      }
      continue;
    }
    p = pEList->a[i].pExpr;
    if( p->op!=TK_FIELD || pTabList==0 ){
      char zName[30];
      sprintf(zName, "field%d", i+1);
      sqliteVdbeAddOp(v, OP_ColumnName, i, 0, zName, 0);
    }else{
      if( pTabList->nId>1 ){
        char *zName = 0;
        Table *pTab = pTabList->a[p->iTable].pTab;
        char *zTab;
 
        zTab = pTabList->a[p->iTable].zAlias;
        if( zTab==0 ) zTab = pTab->zName;
        sqliteSetString(&zName, zTab, ".", pTab->aCol[p->iField].zName, 0);
        sqliteVdbeAddOp(v, OP_ColumnName, i, 0, zName, 0);
        sqliteFree(zName);
      }else{
        Table *pTab = pTabList->a[0].pTab;
        char *zName = pTab->aCol[p->iField].zName;
        sqliteVdbeAddOp(v, OP_ColumnName, i, 0, zName, 0);
      }
    }
  }
}

/*
** This routine is called to process a query that is really the union
** or intersection of two or more separate queries.
*/
static int multiSelect(Parse *pParse, Select *p, int eDest, int iParm){
  int rc;
  Select *pPrior;
  Vdbe *v;
  int i;

  /* Make sure we have a valid query engine.  If not, create a new one.
  */
  v = pParse->pVdbe;
  if( v==0 ){
    v = pParse->pVdbe = sqliteVdbeCreate(pParse->db->pBe);
  }
  if( v==0 ){
    sqliteSetString(&pParse->zErrMsg, "out of memory", 0);
    pParse->nErr++;
    return 1;
  }

  assert( p->pPrior!=0 );
  pPrior = p->pPrior;
  switch( p->op ){
    case TK_ALL: {
      rc = sqliteSelect(pParse, pPrior, eDest, iParm);
      if( rc ) return rc;
      p->pPrior = 0;
      rc = sqliteSelect(pParse, p, eDest, iParm);
      p->pPrior = pPrior;
      break;
    }
    case TK_EXCEPT:
    case TK_UNION: {
      int unionTab;
      int op;

      if( eDest==SRT_Union ){
        unionTab = iParm;
      }else{
        unionTab = pParse->nTab++;          
        sqliteVdbeAddOp(v, OP_Open, unionTab, 1, 0, 0);
        sqliteVdbeAddOp(v, OP_KeyAsData, unionTab, 1, 0, 0);
      }
      rc = sqliteSelect(pParse, pPrior, SRT_Union, unionTab);
      if( rc ) return rc;
      op = p->op==TK_EXCEPT ? SRT_Except : SRT_Union;
      p->pPrior = 0;
      rc = sqliteSelect(pParse, p, op, unionTab);
      p->pPrior = pPrior;
      if( rc ) return rc;
      if( eDest!=SRT_Union ){
        int iCont, iBreak;
        assert( p->pEList );
        generateColumnNames(v, 0, p->pEList);
        iBreak = sqliteVdbeMakeLabel(v);
        iCont = sqliteVdbeAddOp(v, OP_Next, unionTab, iBreak, 0, 0);
        rc = selectInnerLoop(pParse, 0, unionTab, p->pEList->nExpr,
                             0, -1, eDest, iParm, 
                             iCont, iBreak);
        if( rc ) return 1;
        sqliteVdbeAddOp(v, OP_Goto, 0, iCont, 0, 0);
        sqliteVdbeAddOp(v, OP_Close, unionTab, 0, 0, iBreak);
      }
      break;
    }
    case TK_INTERSECT: {
      int tab1, tab2;
      Select *pPrior;
      int iCont, iBreak;

      tab1 = pParse->nTab++;
      tab2 = pParse->nTab++;
      sqliteVdbeAddOp(v, OP_Open, tab1, 1, 0, 0);
      sqliteVdbeAddOp(v, OP_KeyAsData, tab1, 1, 0, 0);
      rc = sqliteSelect(pParse, pPrior, SRT_Union, tab1);
      if( rc ) return rc;
      sqliteVdbeAddOp(v, OP_Open, tab2, 1, 0, 0);
      sqliteVdbeAddOp(v, OP_KeyAsData, tab2, 1, 0, 0);
      p->pPrior = 0;
      rc = sqliteSelect(pParse, p, SRT_Union, tab2);
      p->pPrior = pPrior;
      if( rc ) return rc;
      assert( p->pEList );
      generateColumnNames(v, 0, p->pEList);
      iBreak = sqliteVdbeMakeLabel(v);
      iCont = sqliteVdbeAddOp(v, OP_Next, tab1, iBreak, 0, 0);
      sqliteVdbeAddOp(v, OP_Key, tab1, 0, 0, 0);
      sqliteVdbeAddOp(v, OP_NotFound, tab2, iCont, 0, 0);
      rc = selectInnerLoop(pParse, 0, tab1, p->pEList->nExpr,
                             0, -1, eDest, iParm, 
                             iCont, iBreak);
      if( rc ) return 1;
      sqliteVdbeAddOp(v, OP_Goto, 0, iCont, 0, 0);
      sqliteVdbeAddOp(v, OP_Close, tab2, 0, 0, iBreak);
      sqliteVdbeAddOp(v, OP_Close, tab1, 0, 0, 0);
      break;
    }
  }
  assert( p->pEList && pPrior->pEList );
  if( p->pEList->nExpr!=pPrior->pEList->nExpr ){
    sqliteSetString(&pParse->zErrMsg, "SELECTs have different numbers "
       "of columns and therefore cannot be joined", 0);
    pParse->nErr++;
    return 1;
  }
  return 0;
}

/*
** Generate code for the given SELECT statement.
**
................................................................................
**     ------------    -------------------------------------------
**     SRT_Callback    Invoke the callback for each row of the result.
**
**     SRT_Mem         Store first result in memory cell iParm
**
**     SRT_Set         Store results as keys of a table with cursor iParm
**
**     SRT_Union       Store results as a key in a temporary table iParm
**
**     SRT_Except      Remove results form the temporary talbe iParm.
**
** This routine returns the number of errors.  If any errors are
** encountered, then an appropriate error message is left in
** pParse->zErrMsg.
**
** This routine does NOT free the Select structure passed in.  The
** calling function needs to do that.
*/
int sqliteSelect(
  Parse *pParse,         /* The parser context */
  Select *p,             /* The SELECT statement being coded. */
  int eDest,             /* One of: SRT_Callback Mem Set Union Except */
  int iParm              /* Save result in this memory location, if >=0 */
){
  int i, j;
  WhereInfo *pWInfo;
  Vdbe *v;
  int isAgg = 0;         /* True for select lists like "count(*)" */
  ExprList *pEList;      /* List of fields to extract.  NULL means "*" */
................................................................................
  Expr *pWhere;          /* The WHERE clause.  May be NULL */
  ExprList *pOrderBy;    /* The ORDER BY clause.  May be NULL */
  ExprList *pGroupBy;    /* The GROUP BY clause.  May be NULL */
  Expr *pHaving;         /* The HAVING clause.  May be NULL */
  int isDistinct;        /* True if the DISTINCT keyword is present */
  int distinct;          /* Table to use for the distinct set */

  /* If there is are a sequence of queries, do the earlier ones first.
  */
  if( p->pPrior ){
    return multiSelect(pParse, p, eDest, iParm);
  }

  /* Make local copies of the parameters for this query.
  */
  pEList = p->pEList;
  pTabList = p->pSrc;
  pWhere = p->pWhere;
  pOrderBy = p->pOrderBy;
  pGroupBy = p->pGroupBy;
  pHaving = p->pHaving;
  isDistinct = p->isDistinct;
................................................................................
  if( pEList==0 ){
    for(i=0; i<pTabList->nId; i++){
      Table *pTab = pTabList->a[i].pTab;
      for(j=0; j<pTab->nCol; j++){
        Expr *pExpr = sqliteExpr(TK_FIELD, 0, 0, 0);
        pExpr->iTable = i + pParse->nTab;
        pExpr->iField = j;
        p->pEList = pEList = sqliteExprListAppend(pEList, pExpr, 0);
      }
    }
  }

  /* If writing to memory or generating a set
  ** only a single column may be output.
  */
................................................................................
    sqliteVdbeAddOp(v, OP_SortOpen, 0, 0, 0, 0);
  }

  /* Identify column names if we will be using in the callback.  This
  ** step is skipped if the output is going to a table or a memory cell.
  */
  if( eDest==SRT_Callback ){
    generateColumnNames(v, pTabList, pEList);

































  }

  /* Reset the aggregator
  */
  if( isAgg ){
    sqliteVdbeAddOp(v, OP_AggReset, 0, pParse->nAgg, 0, 0);
  }
................................................................................
  pWInfo = sqliteWhereBegin(pParse, pTabList, pWhere, 0);
  if( pWInfo==0 ) return 1;

  /* Use the standard inner loop if we are not dealing with
  ** aggregates
  */
  if( !isAgg ){
    if( selectInnerLoop(pParse, pEList, 0, 0, pOrderBy, distinct, eDest, iParm,
                    pWInfo->iContinue, pWInfo->iBreak) ){
       return 1;
    }
  }

  /* If we are dealing with aggregates, then to the special aggregate
  ** processing.  
................................................................................
    int endagg = sqliteVdbeMakeLabel(v);
    int startagg;
    startagg = sqliteVdbeAddOp(v, OP_AggNext, 0, endagg, 0, 0);
    pParse->useAgg = 1;
    if( pHaving ){
      sqliteExprIfFalse(pParse, pHaving, startagg);
    }
    if( selectInnerLoop(pParse, pEList, 0, 0, pOrderBy, distinct, eDest, iParm,
                    startagg, endagg) ){
      return 1;
    }
    sqliteVdbeAddOp(v, OP_Goto, 0, startagg, 0, 0);
    sqliteVdbeAddOp(v, OP_Noop, 0, 0, 0, endagg);
    pParse->useAgg = 0;
  }

Changes to src/sqliteInt.h.

19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
...
224
225
226
227
228
229
230


231
232
233
234
235
236
237
238
239

240
241
242
243
244
245
246
** Author contact information:
**   drh@hwaci.com
**   http://www.hwaci.com/drh/
**
*************************************************************************
** Internal interface definitions for SQLite.
**
** @(#) $Id: sqliteInt.h,v 1.18 2000/06/06 17:27:05 drh Exp $
*/
#include "sqlite.h"
#include "dbbe.h"
#include "vdbe.h"
#include "parse.h"
#include <gdbm.h>
#include <stdio.h>
................................................................................
  int isDistinct;        /* True if the DISTINCT keyword is present */
  ExprList *pEList;      /* The fields of the result */
  IdList *pSrc;          /* The FROM clause */
  Expr *pWhere;          /* The WHERE clause */
  ExprList *pGroupBy;    /* The GROUP BY clause */
  Expr *pHaving;         /* The HAVING clause */
  ExprList *pOrderBy;    /* The ORDER BY clause */


};

/*
** The results of a select can be distributed in several ways.
*/
#define SRT_Callback     1  /* Invoke a callback with each row of result */
#define SRT_Mem          2  /* Store result in a memory cell */
#define SRT_Set          3  /* Store result in a table for use with "IN" */
#define SRT_Table        4  /* Store result in a regular table */


/*
** When a SELECT uses aggregate functions (like "count(*)" or "avg(f1)")
** we have to do some additional analysis of expressions.  An instance
** of the following structure holds information about a single subexpression
** somewhere in the SELECT statement.  An array of these structures holds
** all the information we need to generate code for aggregate







|







 







>
>







|
|
>







19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
...
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
** Author contact information:
**   drh@hwaci.com
**   http://www.hwaci.com/drh/
**
*************************************************************************
** Internal interface definitions for SQLite.
**
** @(#) $Id: sqliteInt.h,v 1.19 2000/06/06 21:56:08 drh Exp $
*/
#include "sqlite.h"
#include "dbbe.h"
#include "vdbe.h"
#include "parse.h"
#include <gdbm.h>
#include <stdio.h>
................................................................................
  int isDistinct;        /* True if the DISTINCT keyword is present */
  ExprList *pEList;      /* The fields of the result */
  IdList *pSrc;          /* The FROM clause */
  Expr *pWhere;          /* The WHERE clause */
  ExprList *pGroupBy;    /* The GROUP BY clause */
  Expr *pHaving;         /* The HAVING clause */
  ExprList *pOrderBy;    /* The ORDER BY clause */
  int op;                /* One of: TK_UNION TK_ALL TK_INTERSECT TK_EXCEPT */
  Select *pPrior;        /* Prior select to which this one joins */
};

/*
** The results of a select can be distributed in several ways.
*/
#define SRT_Callback     1  /* Invoke a callback with each row of result */
#define SRT_Mem          2  /* Store result in a memory cell */
#define SRT_Set          3  /* Store result as unique keys in a table */
#define SRT_Union        5  /* Store result as keys in a table */
#define SRT_Except       6  /* Remove result from a UNION table */

/*
** When a SELECT uses aggregate functions (like "count(*)" or "avg(f1)")
** we have to do some additional analysis of expressions.  An instance
** of the following structure holds information about a single subexpression
** somewhere in the SELECT statement.  An array of these structures holds
** all the information we need to generate code for aggregate

Changes to src/tokenize.c.

23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
..
61
62
63
64
65
66
67

68
69
70
71
72
73
74
75

76
77
78
79
80
81
82
..
84
85
86
87
88
89
90

91
92
93
94
95
96
97
*************************************************************************
** An tokenizer for SQL
**
** This file contains C code that splits an SQL input string up into
** individual tokens and sends those tokens one-by-one over to the
** parser for analysis.
**
** $Id: tokenize.c,v 1.7 2000/06/06 17:27:06 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
#include <stdlib.h>

/*
** All the keywords of the SQL language are stored as in a hash
................................................................................
  { "CREATE",            0, TK_CREATE,           0 },
  { "DEFAULT",           0, TK_DEFAULT,          0 },
  { "DELETE",            0, TK_DELETE,           0 },
  { "DELIMITERS",        0, TK_DELIMITERS,       0 },
  { "DESC",              0, TK_DESC,             0 },
  { "DISTINCT",          0, TK_DISTINCT,         0 },
  { "DROP",              0, TK_DROP,             0 },

  { "EXPLAIN",           0, TK_EXPLAIN,          0 },
  { "FROM",              0, TK_FROM,             0 },
  { "GLOB",              0, TK_GLOB,             0 },
  { "GROUP",             0, TK_GROUP,            0 },
  { "HAVING",            0, TK_HAVING,           0 },
  { "IN",                0, TK_IN,               0 },
  { "INDEX",             0, TK_INDEX,            0 },
  { "INSERT",            0, TK_INSERT,           0 },

  { "INTO",              0, TK_INTO,             0 },
  { "IS",                0, TK_IS,               0 },
  { "ISNULL",            0, TK_ISNULL,           0 },
  { "KEY",               0, TK_KEY,              0 },
  { "LIKE",              0, TK_LIKE,             0 },
  { "NOT",               0, TK_NOT,              0 },
  { "NOTNULL",           0, TK_NOTNULL,          0 },
................................................................................
  { "ON",                0, TK_ON,               0 },
  { "OR",                0, TK_OR,               0 },
  { "ORDER",             0, TK_ORDER,            0 },
  { "PRIMARY",           0, TK_PRIMARY,          0 },
  { "SELECT",            0, TK_SELECT,           0 },
  { "SET",               0, TK_SET,              0 },
  { "TABLE",             0, TK_TABLE,            0 },

  { "UNIQUE",            0, TK_UNIQUE,           0 },
  { "UPDATE",            0, TK_UPDATE,           0 },
  { "USING",             0, TK_USING,            0 },
  { "VACUUM",            0, TK_VACUUM,           0 },
  { "VALUES",            0, TK_VALUES,           0 },
  { "WHERE",             0, TK_WHERE,            0 },
};







|







 







>








>







 







>







23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
..
61
62
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
*************************************************************************
** An tokenizer for SQL
**
** This file contains C code that splits an SQL input string up into
** individual tokens and sends those tokens one-by-one over to the
** parser for analysis.
**
** $Id: tokenize.c,v 1.8 2000/06/06 21:56:08 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
#include <stdlib.h>

/*
** All the keywords of the SQL language are stored as in a hash
................................................................................
  { "CREATE",            0, TK_CREATE,           0 },
  { "DEFAULT",           0, TK_DEFAULT,          0 },
  { "DELETE",            0, TK_DELETE,           0 },
  { "DELIMITERS",        0, TK_DELIMITERS,       0 },
  { "DESC",              0, TK_DESC,             0 },
  { "DISTINCT",          0, TK_DISTINCT,         0 },
  { "DROP",              0, TK_DROP,             0 },
  { "EXCEPT",            0, TK_EXCEPT,           0 },
  { "EXPLAIN",           0, TK_EXPLAIN,          0 },
  { "FROM",              0, TK_FROM,             0 },
  { "GLOB",              0, TK_GLOB,             0 },
  { "GROUP",             0, TK_GROUP,            0 },
  { "HAVING",            0, TK_HAVING,           0 },
  { "IN",                0, TK_IN,               0 },
  { "INDEX",             0, TK_INDEX,            0 },
  { "INSERT",            0, TK_INSERT,           0 },
  { "INTERSECT",         0, TK_INTERSECT,        0 },
  { "INTO",              0, TK_INTO,             0 },
  { "IS",                0, TK_IS,               0 },
  { "ISNULL",            0, TK_ISNULL,           0 },
  { "KEY",               0, TK_KEY,              0 },
  { "LIKE",              0, TK_LIKE,             0 },
  { "NOT",               0, TK_NOT,              0 },
  { "NOTNULL",           0, TK_NOTNULL,          0 },
................................................................................
  { "ON",                0, TK_ON,               0 },
  { "OR",                0, TK_OR,               0 },
  { "ORDER",             0, TK_ORDER,            0 },
  { "PRIMARY",           0, TK_PRIMARY,          0 },
  { "SELECT",            0, TK_SELECT,           0 },
  { "SET",               0, TK_SET,              0 },
  { "TABLE",             0, TK_TABLE,            0 },
  { "UNION",             0, TK_UNION,            0 },
  { "UNIQUE",            0, TK_UNIQUE,           0 },
  { "UPDATE",            0, TK_UPDATE,           0 },
  { "USING",             0, TK_USING,            0 },
  { "VACUUM",            0, TK_VACUUM,           0 },
  { "VALUES",            0, TK_VALUES,           0 },
  { "WHERE",             0, TK_WHERE,            0 },
};

Changes to src/vdbe.c.

37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
..
56
57
58
59
60
61
62

63
64
65
66
67
68
69
...
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
....
1877
1878
1879
1880
1881
1882
1883
















1884
1885
1886
1887
1888
1889
1890
....
1899
1900
1901
1902
1903
1904
1905













1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916


1917
1918
1919
1920
1921
1922
1923
** inplicit conversion from one type to the other occurs as necessary.
** 
** Most of the code in this file is taken up by the sqliteVdbeExec()
** function which does the work of interpreting a VDBE program.
** But other routines are also provided to help in building up
** a program instruction by instruction.
**
** $Id: vdbe.c,v 1.22 2000/06/06 19:18:24 drh Exp $
*/
#include "sqliteInt.h"
#include <unistd.h>

/*
** SQL is translated into a sequence of instructions to be
** executed by a virtual machine.  Each instruction is an instance
................................................................................
/*
** Every table that the virtual machine has open is represented by an
** instance of the following structure.
*/
struct VdbeTable {
  DbbeTable *pTable;    /* The table structure of the backend */
  int index;            /* The next index to extract */

};
typedef struct VdbeTable VdbeTable;

/*
** A sorter builds a list of elements to be sorted.  Each element of
** the list is an instance of the following structure.
*/
................................................................................
** change, be sure to change this array to match.  You can use the
** "opNames.awk" awk script which is part of the source tree to regenerate
** this array, then copy and paste it into this file, if you want.
*/
static char *zOpName[] = { 0,
  "Open",           "Close",          "Fetch",          "New",
  "Put",            "Distinct",       "Found",          "NotFound",
  "Delete",         "Field",          "Key",            "Rewind",
  "Next",           "Destroy",        "Reorganize",     "ResetIdx",
  "NextIdx",        "PutIdx",         "DeleteIdx",      "MemLoad",
  "MemStore",       "ListOpen",       "ListWrite",      "ListRewind",
  "ListRead",       "ListClose",      "SortOpen",       "SortPut",
  "SortMakeRec",    "SortMakeKey",    "Sort",           "SortNext",
  "SortKey",        "SortCallback",   "SortClose",      "FileOpen",
  "FileRead",       "FileField",      "FileClose",      "AggReset",
  "AggFocus",       "AggIncr",        "AggNext",        "AggSet",
  "AggGet",         "SetInsert",      "SetFound",       "SetNotFound",
  "SetClear",       "MakeRecord",     "MakeKey",        "Goto",
  "If",             "Halt",           "ColumnCount",    "ColumnName",
  "Callback",       "Integer",        "String",         "Null",
  "Pop",            "Dup",            "Pull",           "Add",
  "AddImm",         "Subtract",       "Multiply",       "Divide",
  "Min",            "Max",            "Like",           "Glob",
  "Eq",             "Ne",             "Lt",             "Le",
  "Gt",             "Ge",             "IsNull",         "NotNull",
  "Negative",       "And",            "Or",             "Not",
  "Concat",         "Noop",         
};

/*
** Given the name of an opcode, return its number.  Return 0 if
** there is no match.
**
** This routine is used for testing and debugging.
................................................................................
            zKey = p->zStack[tos];
          }
          sqliteDbbeDelete(p->aTab[i].pTable, nKey, zKey);
        }
        PopStack(p, 1);
        break;
      }

















      /* Opcode: Field P1 P2 *
      **
      ** Push onto the stack the value of the P2-th field from the
      ** most recent Fetch from table P1.
      ** 
      ** The value pushed is just a pointer to the data in the cursor.
................................................................................
        int p2 = pOp->p2;
        int tos = ++p->tos;
        DbbeTable *pTab;
        char *z;

        if( NeedStack(p, tos) ) goto no_mem;
        if( i>=0 && i<p->nTable && (pTab = p->aTab[i].pTable)!=0 ){













          amt = sqliteDbbeDataLength(pTab);
          if( amt<=sizeof(int)*(p2+1) ){
            p->aStack[tos].flags = STK_Null;
            break;
          }
          pAddr = (int*)sqliteDbbeReadData(pTab, sizeof(int)*p2);
          if( *pAddr==0 ){
            p->aStack[tos].flags = STK_Null;
            break;
          }
          p->zStack[tos] = z = sqliteDbbeReadData(pTab, *pAddr);


          p->aStack[tos].n = strlen(z) + 1;
          p->aStack[tos].flags = STK_Str;
        }
        break;
      }

      /* Opcode: Key P1 * *







|







 







>







 







|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|







 







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







 







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










|
>
>







37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
..
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
...
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
....
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
....
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
** inplicit conversion from one type to the other occurs as necessary.
** 
** Most of the code in this file is taken up by the sqliteVdbeExec()
** function which does the work of interpreting a VDBE program.
** But other routines are also provided to help in building up
** a program instruction by instruction.
**
** $Id: vdbe.c,v 1.23 2000/06/06 21:56:08 drh Exp $
*/
#include "sqliteInt.h"
#include <unistd.h>

/*
** SQL is translated into a sequence of instructions to be
** executed by a virtual machine.  Each instruction is an instance
................................................................................
/*
** Every table that the virtual machine has open is represented by an
** instance of the following structure.
*/
struct VdbeTable {
  DbbeTable *pTable;    /* The table structure of the backend */
  int index;            /* The next index to extract */
  int keyAsData;        /* The OP_Field command works on key instead of data */
};
typedef struct VdbeTable VdbeTable;

/*
** A sorter builds a list of elements to be sorted.  Each element of
** the list is an instance of the following structure.
*/
................................................................................
** change, be sure to change this array to match.  You can use the
** "opNames.awk" awk script which is part of the source tree to regenerate
** this array, then copy and paste it into this file, if you want.
*/
static char *zOpName[] = { 0,
  "Open",           "Close",          "Fetch",          "New",
  "Put",            "Distinct",       "Found",          "NotFound",
  "Delete",         "Field",          "KeyAsData",      "Key",
  "Rewind",         "Next",           "Destroy",        "Reorganize",
  "ResetIdx",       "NextIdx",        "PutIdx",         "DeleteIdx",
  "MemLoad",        "MemStore",       "ListOpen",       "ListWrite",
  "ListRewind",     "ListRead",       "ListClose",      "SortOpen",
  "SortPut",        "SortMakeRec",    "SortMakeKey",    "Sort",
  "SortNext",       "SortKey",        "SortCallback",   "SortClose",
  "FileOpen",       "FileRead",       "FileField",      "FileClose",
  "AggReset",       "AggFocus",       "AggIncr",        "AggNext",
  "AggSet",         "AggGet",         "SetInsert",      "SetFound",
  "SetNotFound",    "SetClear",       "MakeRecord",     "MakeKey",
  "Goto",           "If",             "Halt",           "ColumnCount",
  "ColumnName",     "Callback",       "Integer",        "String",
  "Null",           "Pop",            "Dup",            "Pull",
  "Add",            "AddImm",         "Subtract",       "Multiply",
  "Divide",         "Min",            "Max",            "Like",
  "Glob",           "Eq",             "Ne",             "Lt",
  "Le",             "Gt",             "Ge",             "IsNull",
  "NotNull",        "Negative",       "And",            "Or",
  "Not",            "Concat",         "Noop",         
};

/*
** Given the name of an opcode, return its number.  Return 0 if
** there is no match.
**
** This routine is used for testing and debugging.
................................................................................
            zKey = p->zStack[tos];
          }
          sqliteDbbeDelete(p->aTab[i].pTable, nKey, zKey);
        }
        PopStack(p, 1);
        break;
      }

      /* Opcode: KeyAsData P1 P2 *
      **
      ** Turn the key-as-data mode for cursor P1 either on (if P2==1) or
      ** off (if P2==0).  In key-as-data mode, the OP_Fetch opcode pulls
      ** data off of the key rather than the data.  This is useful for
      ** outer joins and stuff...
      */
      case OP_KeyAsData: {
        int i = pOp->p1;
        VdbeTable *pTab;
        if( i>=0 && i<p->nTable && p->aTab[i].pTable!=0 ){
          p->aTab[i].keyAsData = pOp->p2;
        }
        break;
      }

      /* Opcode: Field P1 P2 *
      **
      ** Push onto the stack the value of the P2-th field from the
      ** most recent Fetch from table P1.
      ** 
      ** The value pushed is just a pointer to the data in the cursor.
................................................................................
        int p2 = pOp->p2;
        int tos = ++p->tos;
        DbbeTable *pTab;
        char *z;

        if( NeedStack(p, tos) ) goto no_mem;
        if( i>=0 && i<p->nTable && (pTab = p->aTab[i].pTable)!=0 ){
          if( p->aTab[i].keyAsData ){
            amt = sqliteDbbeKeyLength(pTab);
            if( amt<=sizeof(int)*(p2+1) ){
              p->aStack[tos].flags = STK_Null;
              break;
            }
            pAddr = (int*)sqliteDbbeReadKey(pTab, sizeof(int)*p2);
            if( *pAddr==0 ){
              p->aStack[tos].flags = STK_Null;
              break;
            }
            z = sqliteDbbeReadKey(pTab, *pAddr);
          }else{
            amt = sqliteDbbeDataLength(pTab);
            if( amt<=sizeof(int)*(p2+1) ){
              p->aStack[tos].flags = STK_Null;
              break;
            }
            pAddr = (int*)sqliteDbbeReadData(pTab, sizeof(int)*p2);
            if( *pAddr==0 ){
              p->aStack[tos].flags = STK_Null;
              break;
            }
            z = sqliteDbbeReadData(pTab, *pAddr);
          }
          p->zStack[tos] = z;
          p->aStack[tos].n = strlen(z) + 1;
          p->aStack[tos].flags = STK_Str;
        }
        break;
      }

      /* Opcode: Key P1 * *

Changes to src/vdbe.h.

23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
..
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
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
*************************************************************************
** Header file for the Virtual DataBase Engine (VDBE)
**
** This header defines the interface to the virtual database engine
** or VDBE.  The VDBE implements an abstract machine that runs a
** simple program to access and modify the underlying database.
**
** $Id: vdbe.h,v 1.8 2000/06/06 01:50:44 drh Exp $
*/
#ifndef _SQLITE_VDBE_H_
#define _SQLITE_VDBE_H_
#include <stdio.h>

/*
** A single VDBE is an opaque structure named "Vdbe".  Only routines
................................................................................
#define OP_New                 4
#define OP_Put                 5
#define OP_Distinct            6
#define OP_Found               7
#define OP_NotFound            8
#define OP_Delete              9
#define OP_Field              10

#define OP_Key                11
#define OP_Rewind             12
#define OP_Next               13

#define OP_Destroy            14
#define OP_Reorganize         15

#define OP_ResetIdx           16
#define OP_NextIdx            17
#define OP_PutIdx             18
#define OP_DeleteIdx          19

#define OP_MemLoad            20
#define OP_MemStore           21

#define OP_ListOpen           22
#define OP_ListWrite          23
#define OP_ListRewind         24
#define OP_ListRead           25
#define OP_ListClose          26

#define OP_SortOpen           27
#define OP_SortPut            28
#define OP_SortMakeRec        29
#define OP_SortMakeKey        30
#define OP_Sort               31
#define OP_SortNext           32
#define OP_SortKey            33
#define OP_SortCallback       34
#define OP_SortClose          35

#define OP_FileOpen           36
#define OP_FileRead           37
#define OP_FileField          38
#define OP_FileClose          39

#define OP_AggReset           40
#define OP_AggFocus           41
#define OP_AggIncr            42
#define OP_AggNext            43
#define OP_AggSet             44
#define OP_AggGet             45

#define OP_SetInsert          46
#define OP_SetFound           47
#define OP_SetNotFound        48
#define OP_SetClear           49

#define OP_MakeRecord         50
#define OP_MakeKey            51

#define OP_Goto               52
#define OP_If                 53
#define OP_Halt               54

#define OP_ColumnCount        55
#define OP_ColumnName         56
#define OP_Callback           57

#define OP_Integer            58
#define OP_String             59
#define OP_Null               60
#define OP_Pop                61
#define OP_Dup                62
#define OP_Pull               63

#define OP_Add                64
#define OP_AddImm             65
#define OP_Subtract           66
#define OP_Multiply           67
#define OP_Divide             68
#define OP_Min                69
#define OP_Max                70
#define OP_Like               71
#define OP_Glob               72
#define OP_Eq                 73
#define OP_Ne                 74
#define OP_Lt                 75
#define OP_Le                 76
#define OP_Gt                 77
#define OP_Ge                 78
#define OP_IsNull             79
#define OP_NotNull            80
#define OP_Negative           81
#define OP_And                82
#define OP_Or                 83
#define OP_Not                84
#define OP_Concat             85
#define OP_Noop               86

#define OP_MAX                86

/*
** Prototypes for the VDBE interface.  See comments on the implementation
** for a description of what each of these routines does.
*/
Vdbe *sqliteVdbeCreate(Dbbe*);
int sqliteVdbeAddOp(Vdbe*,int,int,int,const char*,int);







|







 







>
|
|
|

|
|

|
|
|
|

|
|

|
|
|
|
|

|
|
|
|
|
|
|
|
|

|
|
|
|

|
|
|
|
|
|

|
|
|
|

|
|

|
|
|

|
|
|

|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

|







23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
..
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
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
*************************************************************************
** Header file for the Virtual DataBase Engine (VDBE)
**
** This header defines the interface to the virtual database engine
** or VDBE.  The VDBE implements an abstract machine that runs a
** simple program to access and modify the underlying database.
**
** $Id: vdbe.h,v 1.9 2000/06/06 21:56:08 drh Exp $
*/
#ifndef _SQLITE_VDBE_H_
#define _SQLITE_VDBE_H_
#include <stdio.h>

/*
** A single VDBE is an opaque structure named "Vdbe".  Only routines
................................................................................
#define OP_New                 4
#define OP_Put                 5
#define OP_Distinct            6
#define OP_Found               7
#define OP_NotFound            8
#define OP_Delete              9
#define OP_Field              10
#define OP_KeyAsData          11
#define OP_Key                12
#define OP_Rewind             13
#define OP_Next               14

#define OP_Destroy            15
#define OP_Reorganize         16

#define OP_ResetIdx           17
#define OP_NextIdx            18
#define OP_PutIdx             19
#define OP_DeleteIdx          20

#define OP_MemLoad            21
#define OP_MemStore           22

#define OP_ListOpen           23
#define OP_ListWrite          24
#define OP_ListRewind         25
#define OP_ListRead           26
#define OP_ListClose          27

#define OP_SortOpen           28
#define OP_SortPut            29
#define OP_SortMakeRec        30
#define OP_SortMakeKey        31
#define OP_Sort               32
#define OP_SortNext           33
#define OP_SortKey            34
#define OP_SortCallback       35
#define OP_SortClose          36

#define OP_FileOpen           37
#define OP_FileRead           38
#define OP_FileField          39
#define OP_FileClose          40

#define OP_AggReset           41
#define OP_AggFocus           42
#define OP_AggIncr            43
#define OP_AggNext            44
#define OP_AggSet             45
#define OP_AggGet             46

#define OP_SetInsert          47
#define OP_SetFound           48
#define OP_SetNotFound        49
#define OP_SetClear           50

#define OP_MakeRecord         51
#define OP_MakeKey            52

#define OP_Goto               53
#define OP_If                 54
#define OP_Halt               55

#define OP_ColumnCount        56
#define OP_ColumnName         57
#define OP_Callback           58

#define OP_Integer            59
#define OP_String             60
#define OP_Null               61
#define OP_Pop                62
#define OP_Dup                63
#define OP_Pull               64

#define OP_Add                65
#define OP_AddImm             66
#define OP_Subtract           67
#define OP_Multiply           68
#define OP_Divide             69
#define OP_Min                70
#define OP_Max                71
#define OP_Like               72
#define OP_Glob               73
#define OP_Eq                 74
#define OP_Ne                 75
#define OP_Lt                 76
#define OP_Le                 77
#define OP_Gt                 78
#define OP_Ge                 79
#define OP_IsNull             80
#define OP_NotNull            81
#define OP_Negative           82
#define OP_And                83
#define OP_Or                 84
#define OP_Not                85
#define OP_Concat             86
#define OP_Noop               87

#define OP_MAX                87

/*
** Prototypes for the VDBE interface.  See comments on the implementation
** for a description of what each of these routines does.
*/
Vdbe *sqliteVdbeCreate(Dbbe*);
int sqliteVdbeAddOp(Vdbe*,int,int,int,const char*,int);