/ Check-in [db88a0c2]
Login

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

Overview
Comment:GROUP BY and HAVING installed (CVS 58)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: db88a0c2d4b5c5cd05e0172f061fc33763fe3829
User & Date: drh 2000-06-06 17:27:05
Context
2000-06-06
18:00
:-) (CVS 59) check-in: a8fa6719 user: drh tags: trunk
17:27
GROUP BY and HAVING installed (CVS 58) check-in: db88a0c2 user: drh tags: trunk
13:54
added IN and BETWEEN operators (CVS 57) check-in: 54d19818 user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/expr.c.

19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
...
322
323
324
325
326
327
328

329
330
331
332
333
334
335
...
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361

362
363
364
365
366
367
368
...
372
373
374
375
376
377
378

379
380
381
382
383
384
385
...
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
...
452
453
454
455
456
457
458



459

460
461
462
463
464
465
466
...
518
519
520
521
522
523
524
525









526
527

528
529
530
531
532
533
534
...
740
741
742
743
744
745
746











































































































































** Author contact information:
**   drh@hwaci.com
**   http://www.hwaci.com/drh/
**
*************************************************************************
** This file contains C code routines used for processing expressions
**
** $Id: expr.c,v 1.9 2000/06/06 13:54:15 drh Exp $
*/
#include "sqliteInt.h"

/*
** Walk an expression tree.  Return 1 if the expression is constant
** and 0 if it involves variables.
*/
................................................................................
     int len;
     int id;
  } aFunc[] = {
     { "count",  5, FN_Count },
     { "min",    3, FN_Min   },
     { "max",    3, FN_Max   },
     { "sum",    3, FN_Sum   },

  };
  int i;
  for(i=0; i<ArraySize(aFunc); i++){
    if( aFunc[i].len==pToken->n 
     && sqliteStrNICmp(pToken->z, aFunc[i].zName, aFunc[i].len)==0 ){
       return aFunc[i].id;
    }
................................................................................
**
** if pIsAgg is not null and this expression is an aggregate function
** (like count(*) or max(value)) then write a 1 into *pIsAgg.
*/
int sqliteExprCheck(Parse *pParse, Expr *pExpr, int allowAgg, int *pIsAgg){
  int nErr = 0;
  if( pExpr==0 ) return 0;
  if( pIsAgg ) *pIsAgg = 0;
  switch( pExpr->op ){
    case TK_FUNCTION: {
      int id = sqliteFuncId(&pExpr->token);
      int n = pExpr->pList ? pExpr->pList->nExpr : 0;
      int no_such_func = 0;
      int too_many_args = 0;
      int too_few_args = 0;
      int is_agg = 0;
      int i;

      switch( id ){
        case FN_Unknown: { 
          no_such_func = 1;
          break;
        }
        case FN_Count: { 
          no_such_func = !allowAgg;
................................................................................
        }
        case FN_Max:
        case FN_Min: {
          too_few_args = allowAgg ? n<1 : n<2;
          is_agg = n==1;
          break;
        }

        case FN_Sum: {
          no_such_func = !allowAgg;
          too_many_args = n>1;
          too_few_args = n<1;
          is_agg = 1;
          break;
        }
................................................................................
        nErr++;
      }else if( too_few_args ){
        sqliteSetNString(&pParse->zErrMsg, "too few arguments to function ",-1,
           pExpr->token.z, pExpr->token.n, "()", 2, 0);
        pParse->nErr++;
        nErr++;
      }

      if( is_agg && pIsAgg ) *pIsAgg = 1;
      for(i=0; nErr==0 && i<n; i++){
        nErr = sqliteExprCheck(pParse, pExpr->pList->a[i].pExpr, 0, 0);
      }
    }
    default: {
      if( pExpr->pLeft ){
        nErr = sqliteExprCheck(pParse, pExpr->pLeft, 0, 0);
      }
      if( nErr==0 && pExpr->pRight ){
        nErr = sqliteExprCheck(pParse, pExpr->pRight, 0, 0);
      }
      if( nErr==0 && pExpr->pList ){
        int n = pExpr->pList->nExpr;
        int i;
        for(i=0; nErr==0 && i<n; i++){

          nErr = sqliteExprCheck(pParse, pExpr->pList->a[i].pExpr, 0, 0);
        }
      }
      break;
    }
  }
  return nErr;
}
................................................................................
    case TK_NOTNULL:  op = OP_NotNull;  break;
    case TK_NOT:      op = OP_Not;      break;
    case TK_UMINUS:   op = OP_Negative; break;
    default: break;
  }
  switch( pExpr->op ){
    case TK_FIELD: {



      sqliteVdbeAddOp(v, OP_Field, pExpr->iTable, pExpr->iField, 0, 0);

      break;
    }
    case TK_INTEGER: {
      int i = atoi(pExpr->token.z);
      sqliteVdbeAddOp(v, OP_Integer, i, 0, 0, 0);
      break;
    }
................................................................................
      int dest;
      sqliteVdbeAddOp(v, OP_Integer, 1, 0, 0, 0);
      sqliteExprCode(pParse, pExpr->pLeft);
      dest = sqliteVdbeCurrentAddr(v) + 2;
      sqliteVdbeAddOp(v, op, 0, dest, 0, 0);
      sqliteVdbeAddOp(v, OP_AddImm, -1, 0, 0, 0);
      break;
    }









    case TK_FUNCTION: {
      int id = sqliteFuncId(&pExpr->token);

      int op;
      int i;
      ExprList *pList = pExpr->pList;
      op = id==FN_Min ? OP_Min : OP_Max;
      for(i=0; i<pList->nExpr; i++){
        sqliteExprCode(pParse, pList->a[i].pExpr);
        if( i>0 ){
................................................................................
      sqliteExprCode(pParse, pExpr);
      sqliteVdbeAddOp(v, OP_Not, 0, 0, 0, 0);
      sqliteVdbeAddOp(v, OP_If, 0, dest, 0, 0);
      break;
    }
  }
}


















































































































































|







 







>







 







<









>







 







>







 







>







|


|





>
|







 







>
>
>
|
>







 








>
>
>
>
>
>
>
>
>

<
>







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
...
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
...
346
347
348
349
350
351
352

353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
...
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
...
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
...
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
...
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543

544
545
546
547
548
549
550
551
...
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
** Author contact information:
**   drh@hwaci.com
**   http://www.hwaci.com/drh/
**
*************************************************************************
** This file contains C code routines used for processing expressions
**
** $Id: expr.c,v 1.10 2000/06/06 17:27:05 drh Exp $
*/
#include "sqliteInt.h"

/*
** Walk an expression tree.  Return 1 if the expression is constant
** and 0 if it involves variables.
*/
................................................................................
     int len;
     int id;
  } aFunc[] = {
     { "count",  5, FN_Count },
     { "min",    3, FN_Min   },
     { "max",    3, FN_Max   },
     { "sum",    3, FN_Sum   },
     { "avg",    3, FN_Avg   },
  };
  int i;
  for(i=0; i<ArraySize(aFunc); i++){
    if( aFunc[i].len==pToken->n 
     && sqliteStrNICmp(pToken->z, aFunc[i].zName, aFunc[i].len)==0 ){
       return aFunc[i].id;
    }
................................................................................
**
** if pIsAgg is not null and this expression is an aggregate function
** (like count(*) or max(value)) then write a 1 into *pIsAgg.
*/
int sqliteExprCheck(Parse *pParse, Expr *pExpr, int allowAgg, int *pIsAgg){
  int nErr = 0;
  if( pExpr==0 ) return 0;

  switch( pExpr->op ){
    case TK_FUNCTION: {
      int id = sqliteFuncId(&pExpr->token);
      int n = pExpr->pList ? pExpr->pList->nExpr : 0;
      int no_such_func = 0;
      int too_many_args = 0;
      int too_few_args = 0;
      int is_agg = 0;
      int i;
      pExpr->iField = id;
      switch( id ){
        case FN_Unknown: { 
          no_such_func = 1;
          break;
        }
        case FN_Count: { 
          no_such_func = !allowAgg;
................................................................................
        }
        case FN_Max:
        case FN_Min: {
          too_few_args = allowAgg ? n<1 : n<2;
          is_agg = n==1;
          break;
        }
        case FN_Avg:
        case FN_Sum: {
          no_such_func = !allowAgg;
          too_many_args = n>1;
          too_few_args = n<1;
          is_agg = 1;
          break;
        }
................................................................................
        nErr++;
      }else if( too_few_args ){
        sqliteSetNString(&pParse->zErrMsg, "too few arguments to function ",-1,
           pExpr->token.z, pExpr->token.n, "()", 2, 0);
        pParse->nErr++;
        nErr++;
      }
      if( is_agg ) pExpr->op = TK_AGG_FUNCTION;
      if( is_agg && pIsAgg ) *pIsAgg = 1;
      for(i=0; nErr==0 && i<n; i++){
        nErr = sqliteExprCheck(pParse, pExpr->pList->a[i].pExpr, 0, 0);
      }
    }
    default: {
      if( pExpr->pLeft ){
        nErr = sqliteExprCheck(pParse, pExpr->pLeft, allowAgg, pIsAgg);
      }
      if( nErr==0 && pExpr->pRight ){
        nErr = sqliteExprCheck(pParse, pExpr->pRight, allowAgg, pIsAgg);
      }
      if( nErr==0 && pExpr->pList ){
        int n = pExpr->pList->nExpr;
        int i;
        for(i=0; nErr==0 && i<n; i++){
          Expr *pE2 = pExpr->pList->a[i].pExpr;
          nErr = sqliteExprCheck(pParse, pE2, allowAgg, pIsAgg);
        }
      }
      break;
    }
  }
  return nErr;
}
................................................................................
    case TK_NOTNULL:  op = OP_NotNull;  break;
    case TK_NOT:      op = OP_Not;      break;
    case TK_UMINUS:   op = OP_Negative; break;
    default: break;
  }
  switch( pExpr->op ){
    case TK_FIELD: {
      if( pParse->useAgg ){
        sqliteVdbeAddOp(v, OP_AggGet, 0, pExpr->iAgg, 0, 0);
      }else{
        sqliteVdbeAddOp(v, OP_Field, pExpr->iTable, pExpr->iField, 0, 0);
      }
      break;
    }
    case TK_INTEGER: {
      int i = atoi(pExpr->token.z);
      sqliteVdbeAddOp(v, OP_Integer, i, 0, 0, 0);
      break;
    }
................................................................................
      int dest;
      sqliteVdbeAddOp(v, OP_Integer, 1, 0, 0, 0);
      sqliteExprCode(pParse, pExpr->pLeft);
      dest = sqliteVdbeCurrentAddr(v) + 2;
      sqliteVdbeAddOp(v, op, 0, dest, 0, 0);
      sqliteVdbeAddOp(v, OP_AddImm, -1, 0, 0, 0);
      break;
    }
    case TK_AGG_FUNCTION: {
      sqliteVdbeAddOp(v, OP_AggGet, 0, pExpr->iAgg, 0, 0);
      if( pExpr->iField==FN_Avg ){
        assert( pParse->iAggCount>=0 && pParse->iAggCount<pParse->nAgg );
        sqliteVdbeAddOp(v, OP_AggGet, 0, pParse->iAggCount, 0, 0);
        sqliteVdbeAddOp(v, OP_Divide, 0, 0, 0, 0);
      }
      break;
    }
    case TK_FUNCTION: {

      int id = pExpr->iField;
      int op;
      int i;
      ExprList *pList = pExpr->pList;
      op = id==FN_Min ? OP_Min : OP_Max;
      for(i=0; i<pList->nExpr; i++){
        sqliteExprCode(pParse, pList->a[i].pExpr);
        if( i>0 ){
................................................................................
      sqliteExprCode(pParse, pExpr);
      sqliteVdbeAddOp(v, OP_Not, 0, 0, 0, 0);
      sqliteVdbeAddOp(v, OP_If, 0, dest, 0, 0);
      break;
    }
  }
}

/*
** Do a deep comparison of two expression trees.  Return TRUE (non-zero)
** if they are identical and return FALSE if they differ in any way.
*/
static int exprDeepCompare(Expr *pA, Expr *pB){
  int i;
  if( pA==0 ){
    return pB==0;
  }else if( pB==0 ){
    return 0;
  }
  if( pA->op!=pB->op ) return 0;
  if( !exprDeepCompare(pA->pLeft, pB->pLeft) ) return 0;
  if( !exprDeepCompare(pA->pRight, pB->pRight) ) return 0;
  if( pA->pList ){
    if( pB->pList==0 ) return 0;
    if( pA->pList->nExpr!=pB->pList->nExpr ) return 0;
    for(i=0; i<pA->pList->nExpr; i++){
      if( !exprDeepCompare(pA->pList->a[i].pExpr, pB->pList->a[i].pExpr) ){
        return 0;
      }
    }
  }else if( pB->pList ){
    return 0;
  }
  if( pA->pSelect || pB->pSelect ) return 0;
  if( pA->token.z ){
    if( pB->token.z==0 ) return 0;
    if( pB->token.n!=pA->token.n ) return 0;
    if( sqliteStrNICmp(pA->token.z, pB->token.z, pA->token.n)!=0 ) return 0;
  }
  return 1;
}

/*
** Add a new element to the pParse->aAgg[] array and return its index.
*/
static int appendAggInfo(Parse *pParse){
  if( (pParse->nAgg & 0x7)==0 ){
    int amt = pParse->nAgg + 8;
    pParse->aAgg = sqliteRealloc(pParse->aAgg, amt*sizeof(pParse->aAgg[0]));
    if( pParse->aAgg==0 ){
      sqliteSetString(&pParse->zErrMsg, "out of memory", 0);
      pParse->nErr++;
      return -1;
    }
  }
  memset(&pParse->aAgg[pParse->nAgg], 0, sizeof(pParse->aAgg[0]));
  return pParse->nAgg++;
}

/*
** Analyze the given expression looking for aggregate functions and
** for variables that need to be added to the pParse->aAgg[] array.
** Make additional entries to the pParse->aAgg[] array as necessary.
**
** This routine should only be called after the expression has been
** analyzed by sqliteExprResolveIds() and sqliteExprCheck().
**
** If errors are seen, leave an error message in zErrMsg and return
** the number of errors.
*/
int sqliteExprAnalyzeAggregates(Parse *pParse, Expr *pExpr){
  int i;
  AggExpr *aAgg;
  int nErr = 0;

  if( pExpr==0 ) return 0;
  switch( pExpr->op ){
    case TK_FIELD: {
      aAgg = pParse->aAgg;
      for(i=0; i<pParse->nAgg; i++){
        if( aAgg[i].isAgg ) continue;
        if( aAgg[i].pExpr->iTable==pExpr->iTable
         && aAgg[i].pExpr->iField==pExpr->iField ){
          pExpr->iAgg = i;
          break;
        }
      }
      if( i>=pParse->nAgg ){
        i = appendAggInfo(pParse);
        if( i<0 ) return 1;
        pParse->aAgg[i].isAgg = 0;
        pParse->aAgg[i].pExpr = pExpr;
      }
      break;
    }
    case TK_AGG_FUNCTION: {
      if( pExpr->iField==FN_Count || pExpr->iField==FN_Avg ){
        if( pParse->iAggCount>=0 ){
          i = pParse->iAggCount;
        }else{
          i = appendAggInfo(pParse);
          if( i<0 ) return 1;
          pParse->aAgg[i].isAgg = 1;
          pParse->aAgg[i].pExpr = 0;
          pParse->iAggCount = i;
        }
        if( pExpr->iField==FN_Count ){
          pExpr->iAgg = i;
          break;
        }
      }
      aAgg = pParse->aAgg;
      for(i=0; i<pParse->nAgg; i++){
        if( !aAgg[i].isAgg ) continue;
        if( exprDeepCompare(aAgg[i].pExpr, pExpr) ){
          break;
        }
      }
      if( i>=pParse->nAgg ){
        i = appendAggInfo(pParse);
        if( i<0 ) return 1;
        pParse->aAgg[i].isAgg = 1;
        pParse->aAgg[i].pExpr = pExpr;
      }
      pExpr->iAgg = i;
      break;
    }
    default: {
      if( pExpr->pLeft ){
        nErr = sqliteExprAnalyzeAggregates(pParse, pExpr->pLeft);
      }
      if( nErr==0 && pExpr->pRight ){
        nErr = sqliteExprAnalyzeAggregates(pParse, pExpr->pRight);
      }
      if( nErr==0 && pExpr->pList ){
        int n = pExpr->pList->nExpr;
        int i;
        for(i=0; nErr==0 && i<n; i++){
          nErr = sqliteExprAnalyzeAggregates(pParse, pExpr->pList->a[i].pExpr);
        }
      }
      break;
    }
  }
  return nErr;
}

Changes to src/parse.y.

22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
..
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
...
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
...
208
209
210
211
212
213
214










215
216
217
218
219
220
221
**
*************************************************************************
** 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.12 2000/06/06 13:54:15 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);
................................................................................
input ::= cmdlist.

// These are extra tokens used by the lexer but never seen by the
// parser.  We put them in a rule so that the parser generator will
// add them to the sqliteTokens.h output file.
//
input ::= END_OF_FILE ILLEGAL SPACE UNCLOSED_STRING COMMENT FUNCTION
          UMINUS FIELD.

// A list of commands is zero or more commands
//
cmdlist ::= ecmd.
cmdlist ::= cmdlist SEMI ecmd.
ecmd ::= explain cmd.  {sqliteExec(pParse);}
ecmd ::= cmd.          {sqliteExec(pParse);}
................................................................................
  sqliteSelectDelete(X);
}

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

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

// The "distinct" nonterminal is true (1) if the DISTINCT keyword is
// present and false (0) if it is not.
//
%type distinct {int}
distinct(A) ::= DISTINCT.   {A = 1;}
................................................................................

%type sortorder {int}

sortorder(A) ::= ASC.      {A = 0;}
sortorder(A) ::= DESC.     {A = 1;}
sortorder(A) ::= .         {A = 0;}











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

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

where_opt(A) ::= .                    {A = 0;}







|







 







|







 







|
|







 







>
>
>
>
>
>
>
>
>
>







22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
..
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
...
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
...
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
**
*************************************************************************
** 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);
................................................................................
input ::= cmdlist.

// These are extra tokens used by the lexer but never seen by the
// parser.  We put them in a rule so that the parser generator will
// add them to the sqliteTokens.h output file.
//
input ::= END_OF_FILE ILLEGAL SPACE UNCLOSED_STRING COMMENT FUNCTION
          UMINUS FIELD AGG_FUNCTION.

// A list of commands is zero or more commands
//
cmdlist ::= ecmd.
cmdlist ::= cmdlist SEMI ecmd.
ecmd ::= explain cmd.  {sqliteExec(pParse);}
ecmd ::= cmd.          {sqliteExec(pParse);}
................................................................................
  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.
//
%type distinct {int}
distinct(A) ::= DISTINCT.   {A = 1;}
................................................................................

%type sortorder {int}

sortorder(A) ::= ASC.      {A = 0;}
sortorder(A) ::= DESC.     {A = 1;}
sortorder(A) ::= .         {A = 0;}

%type groupby_opt {ExprList*}
%destructor groupby_opt {sqliteExprListDelete($$);}
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($$);}

where_opt(A) ::= .                    {A = 0;}

Changes to src/select.c.

20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
..
63
64
65
66
67
68
69



































































































70
71
72
73
74
75
76
...
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
...
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
...
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
...
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
...
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
353
354
355
356
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
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
**   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.10 2000/06/06 13:54:15 drh Exp $
*/
#include "sqliteInt.h"


/*
** Allocate a new Select structure and return a pointer to that
** structure.
*/
Select *sqliteSelectNew(
  ExprList *pEList,
................................................................................
  sqliteIdListDelete(p->pSrc);
  sqliteExprDelete(p->pWhere);
  sqliteExprListDelete(p->pGroupBy);
  sqliteExprDelete(p->pHaving);
  sqliteExprListDelete(p->pOrderBy);
  sqliteFree(p);
}




































































































/*
** Generate code for the given SELECT statement.
**
** The results are distributed in various ways depending on the
** value of eDest and iParm.
**
................................................................................
  WhereInfo *pWInfo;
  Vdbe *v;
  int isAgg = 0;         /* True for select lists like "count(*)" */
  ExprList *pEList;      /* List of fields to extract.  NULL means "*" */
  IdList *pTabList;      /* List of tables to select from */
  Expr *pWhere;          /* The WHERE clause.  May be NULL */
  ExprList *pOrderBy;    /* The ORDER BY 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;


  isDistinct = p->isDistinct;

  /* 
  ** Do not even attempt to generate any code if we have already seen
  ** errors before this routine starts.
  */
  if( pParse->nErr>0 ) return 0;


  /* Look up every table in the table list.
  */
  for(i=0; i<pTabList->nId; i++){
    pTabList->a[i].pTab = sqliteFindTable(pParse->db, pTabList->a[i].zName);
    if( pTabList->a[i].pTab==0 ){
      sqliteSetString(&pParse->zErrMsg, "no such table: ", 
................................................................................
         pTabList->a[i].zName, 0);
      pParse->nErr++;
      return 1;
    }
  }

  /* Allocate a temporary table to use for the DISTINCT set, if
  ** necessary.

  */
  if( isDistinct ){
    distinct = pParse->nTab++;


  }

  /* If the list of fields to retrieve is "*" then replace it with
  ** a list of all fields from all tables.
  */
  if( pEList==0 ){
    for(i=0; i<pTabList->nId; i++){
................................................................................
        pExpr->iTable = i + pParse->nTab;
        pExpr->iField = j;
        pEList = sqliteExprListAppend(pEList, pExpr, 0);
      }
    }
  }


  /* If writing to memory, only a single column may be output.
  */
  if( (eDest==SRT_Mem || eDest==SRT_Set) && pEList->nExpr>1 ){
    sqliteSetString(&pParse->zErrMsg, "only a single result allowed for "
       "a SELECT that is part of an expression", 0);
    pParse->nErr++;
    return 1;
  }

  /* Resolve the field names and do a semantics check on all the expressions.






  */
  for(i=0; i<pEList->nExpr; i++){
    sqliteExprResolveInSelect(pParse, pEList->a[i].pExpr);
  }
  if( pWhere ) sqliteExprResolveInSelect(pParse, pWhere);
  if( pOrderBy ){
    for(i=0; i<pOrderBy->nExpr; i++){
      sqliteExprResolveInSelect(pParse, pOrderBy->a[i].pExpr);
    }
  }









  for(i=0; i<pEList->nExpr; i++){
    if( sqliteExprResolveIds(pParse, pTabList, pEList->a[i].pExpr) ){
      return 1;
    }
    if( sqliteExprCheck(pParse, pEList->a[i].pExpr, 1, &pEList->a[i].isAgg) ){
      return 1;
    }
  }
  if( pEList->nExpr>0 ){
    isAgg = pEList->a[0].isAgg;
    for(i=1; i<pEList->nExpr; i++){
      if( pEList->a[i].isAgg!=isAgg ){
        sqliteSetString(&pParse->zErrMsg, "some selected items are aggregates "
          "and others are not", 0);
        pParse->nErr++;
        return 1;
      }
    }
  }
  if( pWhere ){
    if( sqliteExprResolveIds(pParse, pTabList, pWhere) ){
      return 1;
    }
    if( sqliteExprCheck(pParse, pWhere, 0, 0) ){
      return 1;
    }
  }
  if( pOrderBy ){
    for(i=0; i<pOrderBy->nExpr; i++){

      if( sqliteExprResolveIds(pParse, pTabList, pOrderBy->a[i].pExpr) ){
        return 1;
      }
      if( sqliteExprCheck(pParse, pOrderBy->a[i].pExpr, 0, 0) ){











        return 1;
      }
    }
  }







  /* ORDER BY is ignored if we are not invoking callbacks.
  */
  if( isAgg || eDest!=SRT_Callback ){
    pOrderBy = 0;


  }



  /* Turn off distinct if this is an aggregate or writing to memory.



  */
  if( isAgg || eDest==SRT_Mem ){
    isDistinct = 0;















  }

  /* Begin generating code.
  */
  v = pParse->pVdbe;
  if( v==0 ){
    v = pParse->pVdbe = sqliteVdbeCreate(pParse->db->pBe);
................................................................................
    pParse->nErr++;
    return 1;
  }
  if( pOrderBy ){
    sqliteVdbeAddOp(v, OP_SortOpen, 0, 0, 0, 0);
  }

  /* Identify column names if we will be using a 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 = pTab->aCol[p->iField].zName;
          sqliteVdbeAddOp(v, OP_ColumnName, i, 0, zName, 0);
        }
      }
    }
  }

  /* Initialize the stack to contain aggregate seed values
  */
  if( isAgg ){
    for(i=0; i<pEList->nExpr; i++){
      Expr *p = pEList->a[i].pExpr;
      switch( sqliteFuncId(&p->token) ){
        case FN_Min:
        case FN_Max: {
          sqliteVdbeAddOp(v, OP_Null, 0, 0, 0, 0);
          break;
        }
        default: {
          sqliteVdbeAddOp(v, OP_Integer, 0, 0, 0, 0);
          break;
        }
      }
    }
  }

  /* Initialize the memory cell to NULL
  */
  if( eDest==SRT_Mem ){
    sqliteVdbeAddOp(v, OP_Null, 0, 0, 0, 0);
    sqliteVdbeAddOp(v, OP_MemStore, iParm, 0, 0, 0);
................................................................................
  */
  if( isDistinct ){
    sqliteVdbeAddOp(v, OP_Open, distinct, 1, 0, 0);
  }
  pWInfo = sqliteWhereBegin(pParse, pTabList, pWhere, 0);
  if( pWInfo==0 ) return 1;

  /* Pull the requested fields.

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


    }
  }

  /* If the current result is not distinct, script the remainder
  ** of this processing.
  */
  if( isDistinct ){
    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, pWInfo->iContinue, 0, 0);
    sqliteVdbeAddOp(v, OP_String, 0, 0, "", lbl);
    sqliteVdbeAddOp(v, OP_Put, distinct, 0, 0, 0);
  }
  
  /* If there is no ORDER BY clause, then we can invoke the callback
  ** right away.  If there is an ORDER BY, then we need to put the
  ** data into an appropriate sorter record.
  */
  if( pOrderBy ){
    char *zSortOrder;
    sqliteVdbeAddOp(v, OP_SortMakeRec, pEList->nExpr, 0, 0, 0);
    zSortOrder = sqliteMalloc( pOrderBy->nExpr + 1 );
    if( zSortOrder==0 ) return 1;
    for(i=0; i<pOrderBy->nExpr; i++){
      zSortOrder[i] = pOrderBy->a[i].idx ? '-' : '+';
      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( isAgg ){
    int n = pEList->nExpr;
    for(i=0; i<n; i++){
      Expr *p = pEList->a[i].pExpr;
      int id = sqliteFuncId(&p->token);
      int op, p1;
      if( n>1 ){
        sqliteVdbeAddOp(v, OP_Pull, n-1, 0, 0, 0);
      }
      if( id!=FN_Count && p->pList && p->pList->nExpr>=1 ){
        sqliteExprCode(pParse, p->pList->a[0].pExpr);
        sqliteVdbeAddOp(v, OP_Concat, 1, 0, 0, 0);
      }
      switch( sqliteFuncId(&p->token) ){
        case FN_Count: op = OP_AddImm; p1 = 1; break;
        case FN_Sum:   op = OP_Add;    p1 = 0; break;
        case FN_Min:   op = OP_Min;    p1 = 1; break;
        case FN_Max:   op = OP_Max;    p1 = 0; break;
      }
      sqliteVdbeAddOp(v, op, p1, 0, 0, 0);
    }
  }else 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( eDest==SRT_Set ){
    sqliteVdbeAddOp(v, OP_String, 0, 0, "", 0);
    sqliteVdbeAddOp(v, OP_Put, iParm, 0, 0, 0);
  }else if( eDest==SRT_Mem ){
    sqliteVdbeAddOp(v, OP_MemStore, iParm, 0, 0, 0);
    sqliteVdbeAddOp(v, OP_Goto, 0, pWInfo->iBreak, 0, 0);
  }else{
    sqliteVdbeAddOp(v, OP_Callback, pEList->nExpr, 0, 0, 0);
  }

  /* End the database scan loop.
  */
  sqliteWhereEnd(pWInfo);





















  /* If there is an ORDER BY clause, then we need to sort the results
  ** and send them to the callback one by one.
  */
  if( pOrderBy ){
    int end = sqliteVdbeMakeLabel(v);
    int addr;
    sqliteVdbeAddOp(v, OP_Sort, 0, 0, 0, 0);
    addr = sqliteVdbeAddOp(v, OP_SortNext, 0, end, 0, 0);
    sqliteVdbeAddOp(v, OP_SortCallback, pEList->nExpr, 0, 0, 0);
    sqliteVdbeAddOp(v, OP_Goto, 0, addr, 0, 0);
    sqliteVdbeAddOp(v, OP_SortClose, 0, 0, 0, end);
  }

  /* If this is an aggregate, then we need to invoke the callback
  ** exactly once.
  */
  if( isAgg ){
    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( eDest==SRT_Set ){
      sqliteVdbeAddOp(v, OP_String, 0, 0, "", 0);
      sqliteVdbeAddOp(v, OP_Put, iParm, 0, 0, 0);
    }else if( eDest==SRT_Mem ){
      sqliteVdbeAddOp(v, OP_MemStore, iParm, 0, 0, 0);
    }else{
      sqliteVdbeAddOp(v, OP_Callback, pEList->nExpr, 0, 0, 0);
    }
  }
  return 0;
}







|


<







 







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







 







>
>







>
>







>







 







|
>



>
>







 







>
|








|
>
>
>
>
>
>










>
>
>
>
>
>
>
>
>




|



<
<
<
<
<
<
<
<
<
<
<










>
|


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




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

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







 







|







 







|


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







 







|
>


<
|
>
>



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




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













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


20
21
22
23
24
25
26
27
28
29

30
31
32
33
34
35
36
..
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
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
...
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
...
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
353
354

355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
...
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
...
420
421
422
423
424
425
426
427
428
429





430








431
432
433
434
435
436
437
...
441
442
443
444
445
446
447
448
449
450
451

452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514







515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551



















552
553
**   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.11 2000/06/06 17:27:05 drh Exp $
*/
#include "sqliteInt.h"


/*
** Allocate a new Select structure and return a pointer to that
** structure.
*/
Select *sqliteSelectNew(
  ExprList *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){
  sqliteFree(pParse->aAgg);
  pParse->aAgg = 0;
  pParse->nAgg = 0;
  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 );
    if( zSortOrder==0 ) return 1;
    for(i=0; i<pOrderBy->nExpr; i++){
      zSortOrder[i] = pOrderBy->a[i].idx ? '-' : '+';
      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.
**
** The results are distributed in various ways depending on the
** value of eDest and iParm.
**
................................................................................
  WhereInfo *pWInfo;
  Vdbe *v;
  int isAgg = 0;         /* True for select lists like "count(*)" */
  ExprList *pEList;      /* List of fields to extract.  NULL means "*" */
  IdList *pTabList;      /* List of tables to select from */
  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;

  /* 
  ** Do not even attempt to generate any code if we have already seen
  ** errors before this routine starts.
  */
  if( pParse->nErr>0 ) return 0;
  sqliteParseInfoReset(pParse);

  /* Look up every table in the table list.
  */
  for(i=0; i<pTabList->nId; i++){
    pTabList->a[i].pTab = sqliteFindTable(pParse->db, pTabList->a[i].zName);
    if( pTabList->a[i].pTab==0 ){
      sqliteSetString(&pParse->zErrMsg, "no such table: ", 
................................................................................
         pTabList->a[i].zName, 0);
      pParse->nErr++;
      return 1;
    }
  }

  /* Allocate a temporary table to use for the DISTINCT set, if
  ** necessary.  This must be done early to allocate the cursor before
  ** any calls to sqliteExprResolveIds().
  */
  if( isDistinct ){
    distinct = pParse->nTab++;
  }else{
    distinct = -1;
  }

  /* If the list of fields to retrieve is "*" then replace it with
  ** a list of all fields from all tables.
  */
  if( pEList==0 ){
    for(i=0; i<pTabList->nId; i++){
................................................................................
        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.
  */
  if( (eDest==SRT_Mem || eDest==SRT_Set) && pEList->nExpr>1 ){
    sqliteSetString(&pParse->zErrMsg, "only a single result allowed for "
       "a SELECT that is part of an expression", 0);
    pParse->nErr++;
    return 1;
  }

  /* ORDER BY is ignored if we are not sending the result to a callback.
  */
  if( eDest!=SRT_Callback ){
    pOrderBy = 0;
  }

  /* Allocate cursors for "expr IN (SELECT ...)" constructs.
  */
  for(i=0; i<pEList->nExpr; i++){
    sqliteExprResolveInSelect(pParse, pEList->a[i].pExpr);
  }
  if( pWhere ) sqliteExprResolveInSelect(pParse, pWhere);
  if( pOrderBy ){
    for(i=0; i<pOrderBy->nExpr; i++){
      sqliteExprResolveInSelect(pParse, pOrderBy->a[i].pExpr);
    }
  }
  if( pGroupBy ){
    for(i=0; i<pGroupBy->nExpr; i++){
      sqliteExprResolveInSelect(pParse, pGroupBy->a[i].pExpr);
    }
  }
  if( pHaving ) sqliteExprResolveInSelect(pParse, pHaving);

  /* Resolve the field names and do a semantics check on all the expressions.
  */
  for(i=0; i<pEList->nExpr; i++){
    if( sqliteExprResolveIds(pParse, pTabList, pEList->a[i].pExpr) ){
      return 1;
    }
    if( sqliteExprCheck(pParse, pEList->a[i].pExpr, 1, &isAgg) ){
      return 1;
    }
  }











  if( pWhere ){
    if( sqliteExprResolveIds(pParse, pTabList, pWhere) ){
      return 1;
    }
    if( sqliteExprCheck(pParse, pWhere, 0, 0) ){
      return 1;
    }
  }
  if( pOrderBy ){
    for(i=0; i<pOrderBy->nExpr; i++){
      Expr *pE = pOrderBy->a[i].pExpr;
      if( sqliteExprResolveIds(pParse, pTabList, pE) ){
        return 1;
      }
      if( sqliteExprCheck(pParse, pE, isAgg, 0) ){
        return 1;
      }
    }
  }
  if( pGroupBy ){
    for(i=0; i<pGroupBy->nExpr; i++){
      Expr *pE = pGroupBy->a[i].pExpr;
      if( sqliteExprResolveIds(pParse, pTabList, pE) ){
        return 1;
      }
      if( sqliteExprCheck(pParse, pE, isAgg, 0) ){
        return 1;
      }
    }
  }
  if( pHaving ){
    if( pGroupBy==0 ){
      sqliteSetString(&pParse->zErrMsg, "a GROUP BY clause is required to "
         "use HAVING", 0);
      pParse->nErr++;
      return 1;
    }




    if( sqliteExprResolveIds(pParse, pTabList, pHaving) ){
      return 1;
    }
    if( sqliteExprCheck(pParse, pHaving, 0, 0) ){
      return 1;
    }

  }

  /* Do an analysis of aggregate expressions.
  */
  if( isAgg ){

    for(i=0; i<pEList->nExpr; i++){
      if( sqliteExprAnalyzeAggregates(pParse, pEList->a[i].pExpr) ){
        return 1;
      }
    }
    if( pGroupBy ){
      for(i=0; i<pGroupBy->nExpr; i++){
        if( sqliteExprAnalyzeAggregates(pParse, pGroupBy->a[i].pExpr) ){
          return 1;
        }
      }
    }
    if( pHaving && sqliteExprAnalyzeAggregates(pParse, pHaving) ){
      return 1;
    }
  }

  /* Begin generating code.
  */
  v = pParse->pVdbe;
  if( v==0 ){
    v = pParse->pVdbe = sqliteVdbeCreate(pParse->db->pBe);
................................................................................
    pParse->nErr++;
    return 1;
  }
  if( pOrderBy ){
    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 = 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);








  }

  /* Initialize the memory cell to NULL
  */
  if( eDest==SRT_Mem ){
    sqliteVdbeAddOp(v, OP_Null, 0, 0, 0, 0);
    sqliteVdbeAddOp(v, OP_MemStore, iParm, 0, 0, 0);
................................................................................
  */
  if( isDistinct ){
    sqliteVdbeAddOp(v, OP_Open, distinct, 1, 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.  
  */
  else{
    int doFocus;
    if( pGroupBy ){
      for(i=0; i<pGroupBy->nExpr; i++){
        sqliteExprCode(pParse, pGroupBy->a[i].pExpr);
      }
      sqliteVdbeAddOp(v, OP_MakeKey, pGroupBy->nExpr, 0, 0, 0);
      doFocus = 1;
    }else{
      doFocus = 0;
      for(i=0; i<pParse->nAgg; i++){
        if( !pParse->aAgg[i].isAgg ){
          doFocus = 1;
          break;
        }
      }
      if( doFocus ){
        sqliteVdbeAddOp(v, OP_String, 0, 0, "", 0);
      }
    }
    if( doFocus ){
      int lbl1 = sqliteVdbeMakeLabel(v);
      sqliteVdbeAddOp(v, OP_AggFocus, 0, lbl1, 0, 0);
      for(i=0; i<pParse->nAgg; i++){
        if( pParse->aAgg[i].isAgg ) continue;
        sqliteExprCode(pParse, pParse->aAgg[i].pExpr);
        sqliteVdbeAddOp(v, OP_AggSet, 0, i, 0, 0);
      }
      sqliteVdbeResolveLabel(v, lbl1);
    }
    for(i=0; i<pParse->nAgg; i++){
      Expr *pE;
      int op;
      if( !pParse->aAgg[i].isAgg ) continue;
      pE = pParse->aAgg[i].pExpr;
      if( pE==0 ){
        sqliteVdbeAddOp(v, OP_AggIncr, 1, i, 0, 0);
        continue;
      }
      assert( pE->op==TK_AGG_FUNCTION );
      assert( pE->pList!=0 && pE->pList->nExpr==1 );
      sqliteExprCode(pParse, pE->pList->a[0].pExpr);
      sqliteVdbeAddOp(v, OP_AggGet, 0, i, 0, 0);
      switch( pE->iField ){
        case FN_Min:  op = OP_Min;   break;
        case FN_Max:  op = OP_Max;   break;
        case FN_Avg:  op = OP_Add;   break;
        case FN_Sum:  op = OP_Add;   break;
      }
      sqliteVdbeAddOp(v, op, 0, 0, 0, 0);
      sqliteVdbeAddOp(v, OP_AggSet, 0, i, 0, 0);
    }
  }









  /* End the database scan loop.
  */
  sqliteWhereEnd(pWInfo);

  /* If we are processing aggregates, we need to set up a second loop
  ** over all of the aggregate values and process them.
  */
  if( isAgg ){
    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;
  }

  /* If there is an ORDER BY clause, then we need to sort the results
  ** and send them to the callback one by one.
  */
  if( pOrderBy ){
    int end = sqliteVdbeMakeLabel(v);
    int addr;
    sqliteVdbeAddOp(v, OP_Sort, 0, 0, 0, 0);
    addr = sqliteVdbeAddOp(v, OP_SortNext, 0, end, 0, 0);
    sqliteVdbeAddOp(v, OP_SortCallback, pEList->nExpr, 0, 0, 0);
    sqliteVdbeAddOp(v, OP_Goto, 0, addr, 0, 0);
    sqliteVdbeAddOp(v, OP_SortClose, 0, 0, 0, end);
  }



















  return 0;
}

Changes to src/sqliteInt.h.

19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
..
84
85
86
87
88
89
90

91
92
93
94
95
96
97
...
157
158
159
160
161
162
163
164



165
166
167
168
169
170
171
...
230
231
232
233
234
235
236
























237
238
239
240
241
242
243
...
249
250
251
252
253
254
255





256
257
258
259
260
261
262
...
311
312
313
314
315
316
317


** Author contact information:
**   drh@hwaci.com
**   http://www.hwaci.com/drh/
**
*************************************************************************
** Internal interface definitions for SQLite.
**
** @(#) $Id: sqliteInt.h,v 1.17 2000/06/06 13:54:15 drh Exp $
*/
#include "sqlite.h"
#include "dbbe.h"
#include "vdbe.h"
#include "parse.h"
#include <gdbm.h>
#include <stdio.h>
................................................................................
typedef struct Expr Expr;
typedef struct ExprList ExprList;
typedef struct Parse Parse;
typedef struct Token Token;
typedef struct IdList IdList;
typedef struct WhereInfo WhereInfo;
typedef struct Select Select;


/*
** Each database is an instance of the following structure
*/
struct sqlite {
  Dbbe *pBe;                 /* The backend driver */
  int flags;                 /* Miscellanous flags */
................................................................................
*/
struct Expr {
  int op;                /* Operation performed by this node */
  Expr *pLeft, *pRight;  /* Left and right subnodes */
  ExprList *pList;       /* A list of expressions used as a function argument */
  Token token;           /* An operand token */
  int iTable, iField;    /* When op==TK_FIELD, then this node means the
                         ** iField-th field of the iTable-th table */



  Select *pSelect;       /* When the expression is a sub-select */
};

/*
** A list of expressions.  Each expression may optionally have a
** name.  An expr/name combination can be used in several ways, such
** as the list of "expr AS ID" fields following a "SELECT" or in the
................................................................................
** 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 */

























/*
** An SQL parser context
*/
struct Parse {
  sqlite *db;          /* The main database structure */
  sqlite_callback xCallback;  /* The callback function */
  void *pArg;          /* First argument to the callback function */
................................................................................
  Vdbe *pVdbe;         /* An engine for executing database bytecode */
  int explain;         /* True if the EXPLAIN flag is found on the query */
  int initFlag;        /* True if reparsing CREATE TABLEs */
  int nErr;            /* Number of errors seen */
  int nTab;            /* Number of previously allocated cursors */
  int nMem;            /* Number of memory cells used so far */
  int nSet;            /* Number of sets used so far */





};

/*
** Internal function prototypes
*/
int sqliteStrICmp(const char *, const char *);
int sqliteStrNICmp(const char *, const char *, int);
................................................................................
int sqliteGlobCompare(const char*,const char*);
int sqliteLikeCompare(const unsigned char*,const unsigned char*);
char *sqliteTableNameFromToken(Token*);
int sqliteExprCheck(Parse*, Expr*, int, int*);
int sqliteFuncId(Token*);
int sqliteExprResolveIds(Parse*, IdList*, Expr*);
void sqliteExprResolveInSelect(Parse*, Expr*);









|







 







>







 







|
>
>
>







 







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







 







>
>
>
>
>







 







>
>
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
..
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
...
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
...
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
...
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
...
344
345
346
347
348
349
350
351
352
** 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>
................................................................................
typedef struct Expr Expr;
typedef struct ExprList ExprList;
typedef struct Parse Parse;
typedef struct Token Token;
typedef struct IdList IdList;
typedef struct WhereInfo WhereInfo;
typedef struct Select Select;
typedef struct AggExpr AggExpr;

/*
** Each database is an instance of the following structure
*/
struct sqlite {
  Dbbe *pBe;                 /* The backend driver */
  int flags;                 /* Miscellanous flags */
................................................................................
*/
struct Expr {
  int op;                /* Operation performed by this node */
  Expr *pLeft, *pRight;  /* Left and right subnodes */
  ExprList *pList;       /* A list of expressions used as a function argument */
  Token token;           /* An operand token */
  int iTable, iField;    /* When op==TK_FIELD, then this node means the
                         ** iField-th field of the iTable-th table.  When
                         ** op==TK_FUNCTION, iField holds the function id */
  int iAgg;              /* When op==TK_FIELD and pParse->useAgg==TRUE, pull
                         ** value from these element of the aggregator */
  Select *pSelect;       /* When the expression is a sub-select */
};

/*
** A list of expressions.  Each expression may optionally have a
** name.  An expr/name combination can be used in several ways, such
** as the list of "expr AS ID" fields following a "SELECT" or in the
................................................................................
** 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
** expressions.
**
** Note that when analyzing a SELECT containing aggregates, both
** non-aggregate field variables and aggregate functions are stored
** in the AggExpr array of the Parser structure.
**
** The pExpr field points to an expression that is part of either the
** field list, the GROUP BY clause, the HAVING clause or the ORDER BY
** clause.  The expression will be freed when those clauses are cleaned
** up.  Do not try to delete the expression attached to AggExpr.pExpr.
**
** If AggExpr.pExpr==0, that means the expression is "count(*)".
*/
struct AggExpr {
  int isAgg;        /* if TRUE contains an aggregate function */
  Expr *pExpr;      /* The expression */
};

/*
** An SQL parser context
*/
struct Parse {
  sqlite *db;          /* The main database structure */
  sqlite_callback xCallback;  /* The callback function */
  void *pArg;          /* First argument to the callback function */
................................................................................
  Vdbe *pVdbe;         /* An engine for executing database bytecode */
  int explain;         /* True if the EXPLAIN flag is found on the query */
  int initFlag;        /* True if reparsing CREATE TABLEs */
  int nErr;            /* Number of errors seen */
  int nTab;            /* Number of previously allocated cursors */
  int nMem;            /* Number of memory cells used so far */
  int nSet;            /* Number of sets used so far */
  int nAgg;            /* Number of aggregate expressions */
  AggExpr *aAgg;       /* An array of aggregate expressions */
  int iAggCount;       /* Index of the count(*) aggregate in aAgg[] */
  int useAgg;          /* If true, extract field values from the aggregator
                       ** while generating expressions.  Normally false */
};

/*
** Internal function prototypes
*/
int sqliteStrICmp(const char *, const char *);
int sqliteStrNICmp(const char *, const char *, int);
................................................................................
int sqliteGlobCompare(const char*,const char*);
int sqliteLikeCompare(const unsigned char*,const unsigned char*);
char *sqliteTableNameFromToken(Token*);
int sqliteExprCheck(Parse*, Expr*, int, int*);
int sqliteFuncId(Token*);
int sqliteExprResolveIds(Parse*, IdList*, Expr*);
void sqliteExprResolveInSelect(Parse*, Expr*);
int sqliteExprAnalyzeAggregates(Parse*, Expr*);
void sqlitePArseInfoReset(Parse*);

Changes to src/tokenize.c.

23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
..
64
65
66
67
68
69
70


71
72
73
74
75
76
77
...
294
295
296
297
298
299
300

301
302
303
304
305
306
307
...
378
379
380
381
382
383
384

385
386
*************************************************************************
** 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.6 2000/06/06 01:50:43 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
#include <stdlib.h>

/*
** All the keywords of the SQL language are stored as in a hash
................................................................................
  { "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 },


  { "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 },
................................................................................
  static FILE *trace = 0;
  extern void *sqliteParserAlloc(void*(*)(int));
  extern void sqliteParserFree(void*, void(*)(void*));
  extern int sqliteParser(void*, int, ...);
  extern void sqliteParserTrace(FILE*, char *);

  i = 0;

  pEngine = sqliteParserAlloc((void*(*)(int))malloc);
  if( pEngine==0 ){
    sqliteSetString(pzErrMsg, "out of memory", 0);
    return 1;
  }
  sqliteParserTrace(trace, "parser: ");
  while( nErr==0 && i>=0 && zSql[i]!=0 ){
................................................................................
    sqliteVdbeDelete(pParse->pVdbe);
    pParse->pVdbe = 0;
  }
  if( pParse->pNewTable ){
    sqliteDeleteTable(pParse->db, pParse->pNewTable);
    pParse->pNewTable = 0;
  }

  return nErr;
}







|







 







>
>







 







>







 







>


23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
..
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
...
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
...
381
382
383
384
385
386
387
388
389
390
*************************************************************************
** 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
................................................................................
  { "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 },
................................................................................
  static FILE *trace = 0;
  extern void *sqliteParserAlloc(void*(*)(int));
  extern void sqliteParserFree(void*, void(*)(void*));
  extern int sqliteParser(void*, int, ...);
  extern void sqliteParserTrace(FILE*, char *);

  i = 0;
  sqliteParseInfoReset(pParse);
  pEngine = sqliteParserAlloc((void*(*)(int))malloc);
  if( pEngine==0 ){
    sqliteSetString(pzErrMsg, "out of memory", 0);
    return 1;
  }
  sqliteParserTrace(trace, "parser: ");
  while( nErr==0 && i>=0 && zSql[i]!=0 ){
................................................................................
    sqliteVdbeDelete(pParse->pVdbe);
    pParse->pVdbe = 0;
  }
  if( pParse->pNewTable ){
    sqliteDeleteTable(pParse->db, pParse->pNewTable);
    pParse->pNewTable = 0;
  }
  sqliteParseInfoReset(pParse);
  return nErr;
}

Changes to src/vdbe.c.

37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
...
419
420
421
422
423
424
425

426
427
428
429
430
431
432
433
434
435
436
437
438
439



440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
....
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
....
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
....
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205






1206
1207
1208
1209
1210
1211
1212
....
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
....
2724
2725
2726
2727
2728
2729
2730

2731
2732
2733
2734
2735
2736
2737
** 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.20 2000/06/06 13:54:16 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
................................................................................
/*
** Insert a new element and make it the current element.  
**
** Return 0 on success and 1 if memory is exhausted.
*/
static int AggInsert(Agg *p, char *zKey){
  AggElem *pElem;

  if( p->nHash < p->nElem*2 ){
    AggRehash(p, p->nElem*2 + 103);
  }
  if( p->nHash==0 ) return 1;
  pElem = sqliteMalloc( sizeof(AggElem) + strlen(zKey) + 1 +
                        (p->nMem-1)*sizeof(pElem->aMem[0]) );
  if( pElem==0 ) return 1;
  pElem->zKey = (char*)&pElem->aMem[p->nMem];
  strcpy(pElem->zKey, zKey);
  AggEnhash(p, pElem);
  pElem->pNext = p->pFirst;
  p->pFirst = pElem;
  p->nElem++;
  p->pCurrent = pElem;



  return 0;
}

/*
** Get the AggElem currently in focus
*/
#define AggInFocus(P)   ((P).pCurrent ? (P).pCurrent : _AggInFocus(&(P)))
static AggElem *_AggInFocus(Agg *p){
  AggElem *pFocus = p->pFirst;
  if( pFocus ){
    p->pCurrent = pFocus;
  }else{
    AggInsert(p,"");
    pFocus = p->pCurrent;
  }
  return pFocus;
}

/*
** Erase all information from a Set
*/
................................................................................
      /* Opcode: Divide * * *
      **
      ** Pop the top two elements from the stack, divide the
      ** first (what was on top of the stack) from the second (the
      ** next on stack)
      ** and push the result back onto the stack.  If either element
      ** is a string then it is converted to a double using the atof()
      ** function before the division.  Division by zero causes the
      ** program to abort with an error.
      */
      case OP_Add:
      case OP_Subtract:
      case OP_Multiply:
      case OP_Divide: {
        int tos = p->tos;
        int nos = tos - 1;
................................................................................
          a = p->aStack[tos].i;
          b = p->aStack[nos].i;
          switch( pOp->opcode ){
            case OP_Add:         b += a;       break;
            case OP_Subtract:    b -= a;       break;
            case OP_Multiply:    b *= a;       break;
            default: {
              if( a==0 ){ 
                sqliteSetString(pzErrMsg, "division by zero", 0);
                rc = SQLITE_ERROR;
                goto cleanup;
              }
              b /= a;
              break;
            }
          }
          PopStack(p, 2);
          p->tos = nos;
          p->aStack[nos].i = b;
................................................................................
          a = p->aStack[tos].r;
          b = p->aStack[nos].r;
          switch( pOp->opcode ){
            case OP_Add:         b += a;       break;
            case OP_Subtract:    b -= a;       break;
            case OP_Multiply:    b *= a;       break;
            default: {
              if( a==0.0 ){ 
                sqliteSetString(pzErrMsg, "division by zero", 0);
                rc = SQLITE_ERROR;
                goto cleanup;
              }
              b /= a;
              break;
            }
          }
          PopStack(p, 1);
          Release(p, nos);
          p->aStack[nos].r = b;
          p->aStack[nos].flags = STK_Real;
        }
        break;






      }

      /* Opcode: Max * * *
      **
      ** Pop the top two elements from the stack then push back the
      ** largest of the two.
      */
................................................................................
        break;
      }

      /* Opcode: Min * * *
      **
      ** Pop the top two elements from the stack then push back the
      ** smaller of the two. 
      **
      ** If P1==1, always choose TOS for the min and decrement P1.
      ** This is self-altering code...
      */
      case OP_Min: {
        int tos = p->tos;
        int nos = tos - 1;
        int ft, fn;
        int copy = 0;
        if( nos<0 ) goto not_enough_stack;
        ft = p->aStack[tos].flags;
        fn = p->aStack[nos].flags;
        if( pOp->p1 ){
          copy = 1;
          pOp->p1 = 0;
        }else if( fn & STK_Null ){
          copy = 1;
        }else if( (ft & fn & STK_Int)==STK_Int ){
          copy = p->aStack[nos].i>p->aStack[tos].i;
        }else if( ( (ft|fn) & (STK_Int|STK_Real) ) !=0 ){
          Realify(p, tos);
          Realify(p, nos);
          copy = p->aStack[tos].r<p->aStack[nos].r;
        }else{
................................................................................
        }
        if( pElem ){
          p->agg.pCurrent = pElem;
          pc = pOp->p2 - 1;
        }else{
          AggInsert(&p->agg, zKey);
        }

        break; 
      }

      /* Opcode: AggIncr P1 P2 *
      **
      ** Increment the P2-th field of the aggregate element current
      ** in focus by an amount P1.







|







 







>
|













>
>
>













|







 







|
<







 







|
<
<
<
<







 







|
<
<
<
<










>
>
>
>
>
>







 







<
<
<









|

<
|
|







 







>







37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
...
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
....
1145
1146
1147
1148
1149
1150
1151
1152

1153
1154
1155
1156
1157
1158
1159
....
1163
1164
1165
1166
1167
1168
1169
1170




1171
1172
1173
1174
1175
1176
1177
....
1183
1184
1185
1186
1187
1188
1189
1190




1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
....
1245
1246
1247
1248
1249
1250
1251



1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262

1263
1264
1265
1266
1267
1268
1269
1270
1271
....
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
** 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.21 2000/06/06 17:27:06 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
................................................................................
/*
** Insert a new element and make it the current element.  
**
** Return 0 on success and 1 if memory is exhausted.
*/
static int AggInsert(Agg *p, char *zKey){
  AggElem *pElem;
  int i;
  if( p->nHash <= p->nElem*2 ){
    AggRehash(p, p->nElem*2 + 103);
  }
  if( p->nHash==0 ) return 1;
  pElem = sqliteMalloc( sizeof(AggElem) + strlen(zKey) + 1 +
                        (p->nMem-1)*sizeof(pElem->aMem[0]) );
  if( pElem==0 ) return 1;
  pElem->zKey = (char*)&pElem->aMem[p->nMem];
  strcpy(pElem->zKey, zKey);
  AggEnhash(p, pElem);
  pElem->pNext = p->pFirst;
  p->pFirst = pElem;
  p->nElem++;
  p->pCurrent = pElem;
  for(i=0; i<p->nMem; i++){
    pElem->aMem[i].s.flags = STK_Null;
  }
  return 0;
}

/*
** Get the AggElem currently in focus
*/
#define AggInFocus(P)   ((P).pCurrent ? (P).pCurrent : _AggInFocus(&(P)))
static AggElem *_AggInFocus(Agg *p){
  AggElem *pFocus = p->pFirst;
  if( pFocus ){
    p->pCurrent = pFocus;
  }else{
    AggInsert(p,"");
    pFocus = p->pCurrent = p->pFirst;
  }
  return pFocus;
}

/*
** Erase all information from a Set
*/
................................................................................
      /* Opcode: Divide * * *
      **
      ** Pop the top two elements from the stack, divide the
      ** first (what was on top of the stack) from the second (the
      ** next on stack)
      ** and push the result back onto the stack.  If either element
      ** is a string then it is converted to a double using the atof()
      ** function before the division.  Division by zero returns NULL.

      */
      case OP_Add:
      case OP_Subtract:
      case OP_Multiply:
      case OP_Divide: {
        int tos = p->tos;
        int nos = tos - 1;
................................................................................
          a = p->aStack[tos].i;
          b = p->aStack[nos].i;
          switch( pOp->opcode ){
            case OP_Add:         b += a;       break;
            case OP_Subtract:    b -= a;       break;
            case OP_Multiply:    b *= a;       break;
            default: {
              if( a==0 ) goto divide_by_zero;




              b /= a;
              break;
            }
          }
          PopStack(p, 2);
          p->tos = nos;
          p->aStack[nos].i = b;
................................................................................
          a = p->aStack[tos].r;
          b = p->aStack[nos].r;
          switch( pOp->opcode ){
            case OP_Add:         b += a;       break;
            case OP_Subtract:    b -= a;       break;
            case OP_Multiply:    b *= a;       break;
            default: {
              if( a==0.0 ) goto divide_by_zero;




              b /= a;
              break;
            }
          }
          PopStack(p, 1);
          Release(p, nos);
          p->aStack[nos].r = b;
          p->aStack[nos].flags = STK_Real;
        }
        break;

      divide_by_zero:
        PopStack(p, 2);
        p->tos = nos;
        p->aStack[nos].flags = STK_Null;
        break;
      }

      /* Opcode: Max * * *
      **
      ** Pop the top two elements from the stack then push back the
      ** largest of the two.
      */
................................................................................
        break;
      }

      /* Opcode: Min * * *
      **
      ** Pop the top two elements from the stack then push back the
      ** smaller of the two. 



      */
      case OP_Min: {
        int tos = p->tos;
        int nos = tos - 1;
        int ft, fn;
        int copy = 0;
        if( nos<0 ) goto not_enough_stack;
        ft = p->aStack[tos].flags;
        fn = p->aStack[nos].flags;
        if( fn & STK_Null ){
          copy = 1;

        }else if( ft & STK_Null ){
          copy = 0;
        }else if( (ft & fn & STK_Int)==STK_Int ){
          copy = p->aStack[nos].i>p->aStack[tos].i;
        }else if( ( (ft|fn) & (STK_Int|STK_Real) ) !=0 ){
          Realify(p, tos);
          Realify(p, nos);
          copy = p->aStack[tos].r<p->aStack[nos].r;
        }else{
................................................................................
        }
        if( pElem ){
          p->agg.pCurrent = pElem;
          pc = pOp->p2 - 1;
        }else{
          AggInsert(&p->agg, zKey);
        }
        PopStack(p, 1);
        break; 
      }

      /* Opcode: AggIncr P1 P2 *
      **
      ** Increment the P2-th field of the aggregate element current
      ** in focus by an amount P1.

Changes to test/select1.test.

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
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
#   drh@hwaci.com
#   http://www.hwaci.com/drh/
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing the SELECT statement.
#
# $Id: select1.test,v 1.2 2000/05/31 18:20:14 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Try to select on a non-existant table.
#
do_test select-1.1 {
  set v [catch {execsql {SELECT * FROM test1}} msg]
  lappend v $msg
} {1 {no such table: test1}}

execsql {CREATE TABLE test1(f1 int, f2 int)}

do_test select-1.2 {
  set v [catch {execsql {SELECT * FROM test1, test2}} msg]
  lappend v $msg
} {1 {no such table: test2}}
do_test select-1.3 {
  set v [catch {execsql {SELECT * FROM test2, test1}} msg]
  lappend v $msg
} {1 {no such table: test2}}

execsql {INSERT INTO test1(f1,f2) VALUES(11,22)}


# Make sure the fields are extracted correctly.
#
do_test select-1.4 {
  execsql {SELECT f1 FROM test1}
} {11}
do_test select-1.5 {
  execsql {SELECT f2 FROM test1}
} {22}
do_test select-1.6 {
  execsql {SELECT f2, f1 FROM test1}
} {22 11}
do_test select-1.7 {
  execsql {SELECT f1, f2 FROM test1}
} {11 22}
do_test select-1.8 {
  execsql {SELECT * FROM test1}
} {11 22}

execsql {CREATE TABLE test2(r1 real, r2 real)}
execsql {INSERT INTO test2(r1,r2) VALUES(1.1,2.2)}

do_test select-1.9 {
  execsql {SELECT * FROM test1, test2}
} {11 22 1.1 2.2}
do_test select-1.10 {
  execsql {SELECT test1.f1, test2.r1 FROM test1, test2}
} {11 1.1}
do_test select-1.11 {
  execsql {SELECT test1.f1, test2.r1 FROM test2, test1}
} {11 1.1}
do_test select-1.12 {
  execsql {SELECT max(test1.f1,test2.r1), min(test1.f2,test2.r2)
           FROM test2, test1}
} {11 2.2}
do_test select-1.13 {
  execsql {SELECT min(test1.f1,test2.r1), max(test1.f2,test2.r2)
           FROM test1, test2}
} {1.1 22}

execsql {DROP TABLE test2}
execsql {DELETE FROM test1}
execsql {INSERT INTO test1 VALUES(11,22)}
execsql {INSERT INTO test1 VALUES(33,44)}

# Error messges from sqliteExprCheck
#
do_test select-2.1 {
  set v [catch {execsql {SELECT count(f1,f2) FROM test1}} msg]
  lappend v $msg
} {1 {too many arguments to function count()}}
do_test select-2.2 {
  set v [catch {execsql {SELECT count(f1) FROM test1}} msg]
  lappend v $msg
} {0 2}
do_test select-2.3 {
  set v [catch {execsql {SELECT Count() FROM test1}} msg]
  lappend v $msg
} {0 2}
do_test select-2.4 {
  set v [catch {execsql {SELECT COUNT(*) FROM test1}} msg]
  lappend v $msg
} {0 2}
do_test select-2.5 {
  set v [catch {execsql {SELECT COUNT(*)+1 FROM test1}} msg]
  lappend v $msg
} {1 {no such function: COUNT}}
do_test select-2.6 {
  set v [catch {execsql {SELECT min(*) FROM test1}} msg]
  lappend v $msg
} {1 {too few arguments to function min()}}
do_test select-2.7 {
  set v [catch {execsql {SELECT Min(f1) FROM test1}} msg]
  lappend v $msg
} {0 11}
do_test select-2.8 {
  set v [catch {execsql {SELECT MIN(f1,f2) FROM test1}} msg]
  lappend v [lsort $msg]
} {0 {11 33}}
do_test select-2.9 {
  set v [catch {execsql {SELECT MAX(*) FROM test1}} msg]
  lappend v $msg
} {1 {too few arguments to function MAX()}}
do_test select-2.10 {
  set v [catch {execsql {SELECT Max(f1) FROM test1}} msg]
  lappend v $msg
} {0 33}
do_test select-2.11 {
  set v [catch {execsql {SELECT max(f1,f2) FROM test1}} msg]
  lappend v [lsort $msg]
} {0 {22 44}}
do_test select-2.12 {
  set v [catch {execsql {SELECT MAX(f1,f2)+1 FROM test1}} msg]
  lappend v [lsort $msg]
} {0 {23 45}}
do_test select-2.13 {
  set v [catch {execsql {SELECT MAX(f1)+1 FROM test1}} msg]
  lappend v $msg
} {1 {too few arguments to function MAX()}}
do_test select-2.14 {
  set v [catch {execsql {SELECT SUM(*) FROM test1}} msg]
  lappend v $msg
} {1 {too few arguments to function SUM()}}
do_test select-2.15 {
  set v [catch {execsql {SELECT Sum(f1) FROM test1}} msg]
  lappend v $msg
} {0 44}
do_test select-2.16 {
  set v [catch {execsql {SELECT sum(f1,f2) FROM test1}} msg]
  lappend v $msg
} {1 {too many arguments to function sum()}}
do_test select-2.17 {
  set v [catch {execsql {SELECT SUM(f1)+1 FROM test1}} msg]
  lappend v $msg
} {1 {no such function: SUM}}
do_test select-2.18 {
  set v [catch {execsql {SELECT XYZZY(f1) FROM test1}} msg]
  lappend v $msg
} {1 {no such function: XYZZY}}
do_test select-2.19 {
  set v [catch {execsql {SELECT SUM(min(f1,f2)) FROM test1}} msg]
  lappend v $msg
} {0 44}
do_test select-2.20 {
  set v [catch {execsql {SELECT SUM(min(f1)) FROM test1}} msg]
  lappend v $msg
} {1 {too few arguments to function min()}}

# WHERE clause expressions
#
do_test select-3.1 {
  set v [catch {execsql {SELECT f1 FROM test1 WHERE f1<11}} msg]
  lappend v $msg
} {0 {}}
do_test select-3.2 {
  set v [catch {execsql {SELECT f1 FROM test1 WHERE f1<=11}} msg]
  lappend v $msg
} {0 11}
do_test select-3.3 {
  set v [catch {execsql {SELECT f1 FROM test1 WHERE f1=11}} msg]
  lappend v $msg
} {0 11}
do_test select-3.4 {
  set v [catch {execsql {SELECT f1 FROM test1 WHERE f1>=11}} msg]
  lappend v [lsort $msg]
} {0 {11 33}}
do_test select-3.5 {
  set v [catch {execsql {SELECT f1 FROM test1 WHERE f1>11}} msg]
  lappend v [lsort $msg]
} {0 33}
do_test select-3.6 {
  set v [catch {execsql {SELECT f1 FROM test1 WHERE f1!=11}} msg]
  lappend v [lsort $msg]
} {0 33}
do_test select-3.7 {
  set v [catch {execsql {SELECT f1 FROM test1 WHERE min(f1,f2)!=11}} msg]
  lappend v [lsort $msg]
} {0 33}
do_test select-3.8 {
  set v [catch {execsql {SELECT f1 FROM test1 WHERE max(f1,f2)!=11}} msg]
  lappend v [lsort $msg]
} {0 {11 33}}
do_test select-3.9 {
  set v [catch {execsql {SELECT f1 FROM test1 WHERE count(f1,f2)!=11}} msg]
  lappend v $msg
} {1 {no such function: count}}

# ORDER BY expressions
#
do_test select-4.1 {
  set v [catch {execsql {SELECT f1 FROM test1 ORDER BY f1}} msg]
  lappend v $msg
} {0 {11 33}}
do_test select-4.2 {
  set v [catch {execsql {SELECT f1 FROM test1 ORDER BY -f1}} msg]
  lappend v $msg
} {0 {33 11}}
do_test select-4.3 {
  set v [catch {execsql {SELECT f1 FROM test1 ORDER BY min(f1,f2)}} msg]
  lappend v $msg
} {0 {11 33}}
do_test select-4.4 {
  set v [catch {execsql {SELECT f1 FROM test1 ORDER BY min(f1)}} msg]
  lappend v $msg
} {1 {too few arguments to function min()}}

# ORDER BY ignored on an aggregate query
#
do_test select-5.1 {
  set v [catch {execsql {SELECT max(f1) FROM test1 ORDER BY f2}} msg]
  lappend v $msg
} {0 33}

execsql {CREATE TABLE test2(t1 test, t2 text)}
execsql {INSERT INTO test2 VALUES('abc','xyz')}

# Check for field naming
#
do_test select-6.1 {
  set v [catch {execsql2 {SELECT f1 FROM test1 ORDER BY f2}} msg]
  lappend v $msg
} {0 {f1 11 f1 33}}
do_test select-6.2 {
  set v [catch {execsql2 {SELECT f1 as xyzzy FROM test1 ORDER BY f2}} msg]
  lappend v $msg
} {0 {xyzzy 11 xyzzy 33}}
do_test select-6.3 {
  set v [catch {execsql2 {SELECT f1 as "xyzzy" FROM test1 ORDER BY f2}} msg]
  lappend v $msg
} {0 {xyzzy 11 xyzzy 33}}
do_test select-6.4 {
  set v [catch {execsql2 {SELECT f1+F2 as xyzzy FROM test1 ORDER BY f2}} msg]
  lappend v $msg
} {0 {xyzzy 33 xyzzy 77}}
do_test select-6.5 {
  set v [catch {execsql2 {SELECT test1.f1+F2 FROM test1 ORDER BY f2}} msg]
  lappend v $msg
} {0 {field1 33 field1 77}}
do_test select-6.6 {
  set v [catch {execsql2 {SELECT test1.f1+F2, t1 FROM test1, test2 
         ORDER BY f2}} msg]
  lappend v $msg
} {0 {field1 33 test2.t1 abc field1 77 test2.t1 abc}}
do_test select-6.7 {
  set v [catch {execsql2 {SELECT A.f1, t1 FROM test1 as A, test2 
         ORDER BY f2}} msg]
  lappend v $msg
} {0 {A.f1 11 test2.t1 abc A.f1 33 test2.t1 abc}}
do_test select-6.8 {
  set v [catch {execsql2 {SELECT A.f1, f1 FROM test1 as A, test1 as B 
         ORDER BY f2}} msg]
  lappend v $msg
} {1 {ambiguous field name: f1}}
do_test select-6.8 {
  set v [catch {execsql2 {SELECT A.f1, B.f1 FROM test1 as A, test1 as B 
         ORDER BY f2}} msg]
  lappend v $msg
} {1 {ambiguous field name: f2}}
do_test select-6.9 {
  set v [catch {execsql2 {SELECT A.f1, B.f1 FROM test1 as A, test1 as B 
         ORDER BY A.f1, B.f1}} msg]
  lappend v $msg
} {0 {A.f1 11 B.f1 11 A.f1 11 B.f1 33 A.f1 33 B.f1 11 A.f1 33 B.f1 33}}

finish_test







|






|






|



|









|


|


|


|


|






|


|


|


|



|











|



|



|



|



|


|
|



|



|



|



|



|



|



|


|
|



|



|



|


|
|



|



|






|



|



|



|



|



|



|



|



|






|



|



|



|






|









|



|



|



|



|



|




|




|




|




|






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
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
#   drh@hwaci.com
#   http://www.hwaci.com/drh/
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing the SELECT statement.
#
# $Id: select1.test,v 1.3 2000/06/06 17:27:06 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Try to select on a non-existant table.
#
do_test select1-1.1 {
  set v [catch {execsql {SELECT * FROM test1}} msg]
  lappend v $msg
} {1 {no such table: test1}}

execsql {CREATE TABLE test1(f1 int, f2 int)}

do_test select1-1.2 {
  set v [catch {execsql {SELECT * FROM test1, test2}} msg]
  lappend v $msg
} {1 {no such table: test2}}
do_test select1-1.3 {
  set v [catch {execsql {SELECT * FROM test2, test1}} msg]
  lappend v $msg
} {1 {no such table: test2}}

execsql {INSERT INTO test1(f1,f2) VALUES(11,22)}


# Make sure the fields are extracted correctly.
#
do_test select1-1.4 {
  execsql {SELECT f1 FROM test1}
} {11}
do_test select1-1.5 {
  execsql {SELECT f2 FROM test1}
} {22}
do_test select1-1.6 {
  execsql {SELECT f2, f1 FROM test1}
} {22 11}
do_test select1-1.7 {
  execsql {SELECT f1, f2 FROM test1}
} {11 22}
do_test select1-1.8 {
  execsql {SELECT * FROM test1}
} {11 22}

execsql {CREATE TABLE test2(r1 real, r2 real)}
execsql {INSERT INTO test2(r1,r2) VALUES(1.1,2.2)}

do_test select1-1.9 {
  execsql {SELECT * FROM test1, test2}
} {11 22 1.1 2.2}
do_test select1-1.10 {
  execsql {SELECT test1.f1, test2.r1 FROM test1, test2}
} {11 1.1}
do_test select1-1.11 {
  execsql {SELECT test1.f1, test2.r1 FROM test2, test1}
} {11 1.1}
do_test select1-1.12 {
  execsql {SELECT max(test1.f1,test2.r1), min(test1.f2,test2.r2)
           FROM test2, test1}
} {11 2.2}
do_test select1-1.13 {
  execsql {SELECT min(test1.f1,test2.r1), max(test1.f2,test2.r2)
           FROM test1, test2}
} {1.1 22}

execsql {DROP TABLE test2}
execsql {DELETE FROM test1}
execsql {INSERT INTO test1 VALUES(11,22)}
execsql {INSERT INTO test1 VALUES(33,44)}

# Error messges from sqliteExprCheck
#
do_test select1-2.1 {
  set v [catch {execsql {SELECT count(f1,f2) FROM test1}} msg]
  lappend v $msg
} {1 {too many arguments to function count()}}
do_test select1-2.2 {
  set v [catch {execsql {SELECT count(f1) FROM test1}} msg]
  lappend v $msg
} {0 2}
do_test select1-2.3 {
  set v [catch {execsql {SELECT Count() FROM test1}} msg]
  lappend v $msg
} {0 2}
do_test select1-2.4 {
  set v [catch {execsql {SELECT COUNT(*) FROM test1}} msg]
  lappend v $msg
} {0 2}
do_test select1-2.5 {
  set v [catch {execsql {SELECT COUNT(*)+1 FROM test1}} msg]
  lappend v $msg
} {0 3}
do_test select1-2.6 {
  set v [catch {execsql {SELECT min(*) FROM test1}} msg]
  lappend v $msg
} {1 {too few arguments to function min()}}
do_test select1-2.7 {
  set v [catch {execsql {SELECT Min(f1) FROM test1}} msg]
  lappend v $msg
} {0 11}
do_test select1-2.8 {
  set v [catch {execsql {SELECT MIN(f1,f2) FROM test1}} msg]
  lappend v [lsort $msg]
} {0 {11 33}}
do_test select1-2.9 {
  set v [catch {execsql {SELECT MAX(*) FROM test1}} msg]
  lappend v $msg
} {1 {too few arguments to function MAX()}}
do_test select1-2.10 {
  set v [catch {execsql {SELECT Max(f1) FROM test1}} msg]
  lappend v $msg
} {0 33}
do_test select1-2.11 {
  set v [catch {execsql {SELECT max(f1,f2) FROM test1}} msg]
  lappend v [lsort $msg]
} {0 {22 44}}
do_test select1-2.12 {
  set v [catch {execsql {SELECT MAX(f1,f2)+1 FROM test1}} msg]
  lappend v [lsort $msg]
} {0 {23 45}}
do_test select1-2.13 {
  set v [catch {execsql {SELECT MAX(f1)+1 FROM test1}} msg]
  lappend v $msg
} {0 34}
do_test select1-2.14 {
  set v [catch {execsql {SELECT SUM(*) FROM test1}} msg]
  lappend v $msg
} {1 {too few arguments to function SUM()}}
do_test select1-2.15 {
  set v [catch {execsql {SELECT Sum(f1) FROM test1}} msg]
  lappend v $msg
} {0 44}
do_test select1-2.16 {
  set v [catch {execsql {SELECT sum(f1,f2) FROM test1}} msg]
  lappend v $msg
} {1 {too many arguments to function sum()}}
do_test select1-2.17 {
  set v [catch {execsql {SELECT SUM(f1)+1 FROM test1}} msg]
  lappend v $msg
} {0 45}
do_test select1-2.18 {
  set v [catch {execsql {SELECT XYZZY(f1) FROM test1}} msg]
  lappend v $msg
} {1 {no such function: XYZZY}}
do_test select1-2.19 {
  set v [catch {execsql {SELECT SUM(min(f1,f2)) FROM test1}} msg]
  lappend v $msg
} {0 44}
do_test select1-2.20 {
  set v [catch {execsql {SELECT SUM(min(f1)) FROM test1}} msg]
  lappend v $msg
} {1 {too few arguments to function min()}}

# WHERE clause expressions
#
do_test select1-3.1 {
  set v [catch {execsql {SELECT f1 FROM test1 WHERE f1<11}} msg]
  lappend v $msg
} {0 {}}
do_test select1-3.2 {
  set v [catch {execsql {SELECT f1 FROM test1 WHERE f1<=11}} msg]
  lappend v $msg
} {0 11}
do_test select1-3.3 {
  set v [catch {execsql {SELECT f1 FROM test1 WHERE f1=11}} msg]
  lappend v $msg
} {0 11}
do_test select1-3.4 {
  set v [catch {execsql {SELECT f1 FROM test1 WHERE f1>=11}} msg]
  lappend v [lsort $msg]
} {0 {11 33}}
do_test select1-3.5 {
  set v [catch {execsql {SELECT f1 FROM test1 WHERE f1>11}} msg]
  lappend v [lsort $msg]
} {0 33}
do_test select1-3.6 {
  set v [catch {execsql {SELECT f1 FROM test1 WHERE f1!=11}} msg]
  lappend v [lsort $msg]
} {0 33}
do_test select1-3.7 {
  set v [catch {execsql {SELECT f1 FROM test1 WHERE min(f1,f2)!=11}} msg]
  lappend v [lsort $msg]
} {0 33}
do_test select1-3.8 {
  set v [catch {execsql {SELECT f1 FROM test1 WHERE max(f1,f2)!=11}} msg]
  lappend v [lsort $msg]
} {0 {11 33}}
do_test select1-3.9 {
  set v [catch {execsql {SELECT f1 FROM test1 WHERE count(f1,f2)!=11}} msg]
  lappend v $msg
} {1 {no such function: count}}

# ORDER BY expressions
#
do_test select1-4.1 {
  set v [catch {execsql {SELECT f1 FROM test1 ORDER BY f1}} msg]
  lappend v $msg
} {0 {11 33}}
do_test select1-4.2 {
  set v [catch {execsql {SELECT f1 FROM test1 ORDER BY -f1}} msg]
  lappend v $msg
} {0 {33 11}}
do_test select1-4.3 {
  set v [catch {execsql {SELECT f1 FROM test1 ORDER BY min(f1,f2)}} msg]
  lappend v $msg
} {0 {11 33}}
do_test select1-4.4 {
  set v [catch {execsql {SELECT f1 FROM test1 ORDER BY min(f1)}} msg]
  lappend v $msg
} {1 {too few arguments to function min()}}

# ORDER BY ignored on an aggregate query
#
do_test select1-5.1 {
  set v [catch {execsql {SELECT max(f1) FROM test1 ORDER BY f2}} msg]
  lappend v $msg
} {0 33}

execsql {CREATE TABLE test2(t1 test, t2 text)}
execsql {INSERT INTO test2 VALUES('abc','xyz')}

# Check for field naming
#
do_test select1-6.1 {
  set v [catch {execsql2 {SELECT f1 FROM test1 ORDER BY f2}} msg]
  lappend v $msg
} {0 {f1 11 f1 33}}
do_test select1-6.2 {
  set v [catch {execsql2 {SELECT f1 as xyzzy FROM test1 ORDER BY f2}} msg]
  lappend v $msg
} {0 {xyzzy 11 xyzzy 33}}
do_test select1-6.3 {
  set v [catch {execsql2 {SELECT f1 as "xyzzy" FROM test1 ORDER BY f2}} msg]
  lappend v $msg
} {0 {xyzzy 11 xyzzy 33}}
do_test select1-6.4 {
  set v [catch {execsql2 {SELECT f1+F2 as xyzzy FROM test1 ORDER BY f2}} msg]
  lappend v $msg
} {0 {xyzzy 33 xyzzy 77}}
do_test select1-6.5 {
  set v [catch {execsql2 {SELECT test1.f1+F2 FROM test1 ORDER BY f2}} msg]
  lappend v $msg
} {0 {field1 33 field1 77}}
do_test select1-6.6 {
  set v [catch {execsql2 {SELECT test1.f1+F2, t1 FROM test1, test2 
         ORDER BY f2}} msg]
  lappend v $msg
} {0 {field1 33 test2.t1 abc field1 77 test2.t1 abc}}
do_test select1-6.7 {
  set v [catch {execsql2 {SELECT A.f1, t1 FROM test1 as A, test2 
         ORDER BY f2}} msg]
  lappend v $msg
} {0 {A.f1 11 test2.t1 abc A.f1 33 test2.t1 abc}}
do_test select1-6.8 {
  set v [catch {execsql2 {SELECT A.f1, f1 FROM test1 as A, test1 as B 
         ORDER BY f2}} msg]
  lappend v $msg
} {1 {ambiguous field name: f1}}
do_test select1-6.8 {
  set v [catch {execsql2 {SELECT A.f1, B.f1 FROM test1 as A, test1 as B 
         ORDER BY f2}} msg]
  lappend v $msg
} {1 {ambiguous field name: f2}}
do_test select1-6.9 {
  set v [catch {execsql2 {SELECT A.f1, B.f1 FROM test1 as A, test1 as B 
         ORDER BY A.f1, B.f1}} msg]
  lappend v $msg
} {0 {A.f1 11 B.f1 11 A.f1 11 B.f1 33 A.f1 33 B.f1 11 A.f1 33 B.f1 33}}

finish_test