Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | GROUP BY and HAVING installed (CVS 58) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
db88a0c2d4b5c5cd05e0172f061fc337 |
User & Date: | drh 2000-06-06 17:27:05.000 |
Context
2000-06-06
| ||
18:00 | :-) (CVS 59) (check-in: a8fa6719d5 user: drh tags: trunk) | |
17:27 | GROUP BY and HAVING installed (CVS 58) (check-in: db88a0c2d4 user: drh tags: trunk) | |
13:54 | added IN and BETWEEN operators (CVS 57) (check-in: 54d198189b user: drh tags: trunk) | |
Changes
Changes to src/expr.c.
︙ | ︙ | |||
19 20 21 22 23 24 25 | ** Author contact information: ** drh@hwaci.com ** http://www.hwaci.com/drh/ ** ************************************************************************* ** This file contains C code routines used for processing expressions ** | | | 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | ** 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. */ |
︙ | ︙ | |||
322 323 324 325 326 327 328 329 330 331 332 333 334 335 | 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; } | > | 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 | 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; } |
︙ | ︙ | |||
345 346 347 348 349 350 351 | ** ** 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; | < > > | 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 | ** ** 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; too_many_args = n>1; is_agg = 1; break; } 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; } |
︙ | ︙ | |||
397 398 399 400 401 402 403 404 405 406 407 408 409 410 | 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 ){ | > | | > | | 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 | 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; } |
︙ | ︙ | |||
452 453 454 455 456 457 458 | 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: { | > > > | > | 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 | 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; } |
︙ | ︙ | |||
518 519 520 521 522 523 524 525 526 | 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: { | > > > > > > > > > | | 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 | 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 ){ |
︙ | ︙ | |||
740 741 742 743 744 745 746 | sqliteExprCode(pParse, pExpr); sqliteVdbeAddOp(v, OP_Not, 0, 0, 0, 0); sqliteVdbeAddOp(v, OP_If, 0, dest, 0, 0); break; } } } | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 | 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 | ** ************************************************************************* ** 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. ** | | | 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | ** ************************************************************************* ** 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); |
︙ | ︙ | |||
47 48 49 50 51 52 53 | 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 | | | 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | 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);} |
︙ | ︙ | |||
137 138 139 140 141 142 143 | sqliteSelectDelete(X); } %type select {Select*} %destructor select {sqliteSelectDelete($$);} select(A) ::= SELECT distinct(D) selcollist(W) from(X) where_opt(Y) | | | | 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 | 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;} |
︙ | ︙ | |||
208 209 210 211 212 213 214 215 216 217 218 219 220 221 | %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;} | > > > > > > > > > > | 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 | %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 | ** drh@hwaci.com ** http://www.hwaci.com/drh/ ** ************************************************************************* ** This file contains C code routines that are called by the parser ** to handle SELECT statements. ** | | < | 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | ** 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, |
︙ | ︙ | |||
63 64 65 66 67 68 69 70 71 72 73 74 75 76 | 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. ** | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 | 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. ** |
︙ | ︙ | |||
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 | 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 | > > > > > | > > > > | > > > > > | > > > > > > > > > > | < < < < < < < < < < < > | | > > > > > | < < > > > > > | | > > > > | > > | > > > > | > | < > > > > > > > > > > > > > > > | | 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 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 | 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++){ Table *pTab = pTabList->a[i].pTab; for(j=0; j<pTab->nCol; j++){ Expr *pExpr = sqliteExpr(TK_FIELD, 0, 0, 0); pExpr->iTable = i + pParse->nTab; pExpr->iField = j; pEList = sqliteExprListAppend(pEList, pExpr, 0); } } } /* If writing to memory or generating a set ** only a single column may be output. */ 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); } if( v==0 ){ sqliteSetString(&pParse->zErrMsg, "out of memory", 0); 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 ){ |
︙ | ︙ | |||
275 276 277 278 279 280 281 | char *zName = pTab->aCol[p->iField].zName; sqliteVdbeAddOp(v, OP_ColumnName, i, 0, zName, 0); } } } } | | < < < < < | < < < < < < < < > | < | > > < > | > > | < | < < < | < | < < < < < < < | < | > > | < | > > | < < > > | > > | | > | > > > > > > > | < | > > | | > > | | | < | | | | | | > < < < < < < < < < < < < < > > > > > > > > > > > > > > > > > > > > > < < < < < < < < < < < < < < < < < < < | 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 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 | 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); } /* Begin the database scan */ 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 | ** Author contact information: ** drh@hwaci.com ** http://www.hwaci.com/drh/ ** ************************************************************************* ** Internal interface definitions for SQLite. ** | | | 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | ** 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> |
︙ | ︙ | |||
84 85 86 87 88 89 90 91 92 93 94 95 96 97 | 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 */ | > | 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 | 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 */ |
︙ | ︙ | |||
157 158 159 160 161 162 163 | */ 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 | | > > > | 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 | */ 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 |
︙ | ︙ | |||
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 | ** 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 */ char *zErrMsg; /* An error message */ Token sErrToken; /* The token at which the error occurred */ Token sFirstToken; /* The first token parsed */ Token sLastToken; /* The last token parsed */ Table *pNewTable; /* A table being constructed by CREATE TABLE */ 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); | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 | ** 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 */ char *zErrMsg; /* An error message */ Token sErrToken; /* The token at which the error occurred */ Token sFirstToken; /* The first token parsed */ Token sLastToken; /* The last token parsed */ Table *pNewTable; /* A table being constructed by CREATE TABLE */ 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); |
︙ | ︙ | |||
311 312 313 314 315 316 317 | 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*); | > > | 344 345 346 347 348 349 350 351 352 | 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 | ************************************************************************* ** 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. ** | | | 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | ************************************************************************* ** 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 |
︙ | ︙ | |||
64 65 66 67 68 69 70 71 72 73 74 75 76 77 | { "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 }, | > > | 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 | { "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 }, |
︙ | ︙ | |||
294 295 296 297 298 299 300 301 302 303 304 305 306 307 | 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 ){ | > | 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 | 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 ){ |
︙ | ︙ | |||
378 379 380 381 382 383 384 385 386 | sqliteVdbeDelete(pParse->pVdbe); pParse->pVdbe = 0; } if( pParse->pNewTable ){ sqliteDeleteTable(pParse->db, pParse->pNewTable); pParse->pNewTable = 0; } return nErr; } | > | 381 382 383 384 385 386 387 388 389 390 | 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 | ** 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. ** | | | 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | ** 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 |
︙ | ︙ | |||
419 420 421 422 423 424 425 | /* ** 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; | > | > > > | | 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 | /* ** 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 */ |
︙ | ︙ | |||
1141 1142 1143 1144 1145 1146 1147 | /* 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() | | < | < < < < | < < < < > > > > > > | 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 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 | /* 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; if( nos<0 ) goto not_enough_stack; if( (p->aStack[tos].flags & p->aStack[nos].flags & STK_Int)==STK_Int ){ int a, b; 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; p->aStack[nos].flags = STK_Int; }else{ double a, b; Realify(p, tos); Realify(p, nos); 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. */ |
︙ | ︙ | |||
1244 1245 1246 1247 1248 1249 1250 | break; } /* Opcode: Min * * * ** ** Pop the top two elements from the stack then push back the ** smaller of the two. | < < < | < | | | 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 | 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{ |
︙ | ︙ | |||
2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 | } 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. | > | 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 | } 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 | # 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. # | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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 |