Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Rewrite the aggregate handling logic so that it runs in O(1) space. This is the first cut at the code. Many regression tests fail. (CVS 2662) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
17039ec3ff4396862beedf4a8af89654 |
User & Date: | drh 2005-09-07 21:22:46.000 |
Context
2005-09-07
| ||
22:09 | Bug fixes in aggregate processing. Fewer tests fail. (CVS 2663) (check-in: c3ac58592f user: drh tags: trunk) | |
21:22 | Rewrite the aggregate handling logic so that it runs in O(1) space. This is the first cut at the code. Many regression tests fail. (CVS 2662) (check-in: 17039ec3ff user: drh tags: trunk) | |
2005-09-06
| ||
21:40 | Changes to reduce the amount of stack space required. (CVS 2661) (check-in: b86bd70f30 user: drh tags: trunk) | |
Changes
Changes to src/build.c.
︙ | ︙ | |||
18 19 20 21 22 23 24 | ** CREATE INDEX ** DROP INDEX ** creating ID lists ** BEGIN TRANSACTION ** COMMIT ** ROLLBACK ** | | | 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | ** CREATE INDEX ** DROP INDEX ** creating ID lists ** BEGIN TRANSACTION ** COMMIT ** ROLLBACK ** ** $Id: build.c,v 1.345 2005/09/07 21:22:46 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> /* ** This routine is called when a new SQL statement is beginning to ** be parsed. Initialize the pParse structure as needed. |
︙ | ︙ | |||
99 100 101 102 103 104 105 | /* Get the VDBE program ready for execution */ if( v && pParse->nErr==0 ){ FILE *trace = (db->flags & SQLITE_VdbeTrace)!=0 ? stdout : 0; sqlite3VdbeTrace(v, trace); sqlite3VdbeMakeReady(v, pParse->nVar, pParse->nMem+3, | | | 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 | /* Get the VDBE program ready for execution */ if( v && pParse->nErr==0 ){ FILE *trace = (db->flags & SQLITE_VdbeTrace)!=0 ? stdout : 0; sqlite3VdbeTrace(v, trace); sqlite3VdbeMakeReady(v, pParse->nVar, pParse->nMem+3, pParse->nTab+3, pParse->explain); pParse->rc = SQLITE_DONE; pParse->colNamesSet = 0; }else if( pParse->rc==SQLITE_OK ){ pParse->rc = SQLITE_ERROR; } pParse->nTab = 0; pParse->nMem = 0; |
︙ | ︙ | |||
2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 | destroyRootPage(pParse, pIndex->tnum, iDb); sqlite3VdbeOp3(v, OP_DropIndex, iDb, 0, pIndex->zName, 0); } exit_drop_index: sqlite3SrcListDelete(pName); } /* ** Append a new element to the given IdList. Create a new IdList if ** need be. ** ** A new IdList is returned, or NULL if malloc() fails. */ IdList *sqlite3IdListAppend(IdList *pList, Token *pToken){ if( pList==0 ){ pList = sqliteMalloc( sizeof(IdList) ); if( pList==0 ) return 0; pList->nAlloc = 0; } | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > < < < | | | | | < < < | < | 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 | destroyRootPage(pParse, pIndex->tnum, iDb); sqlite3VdbeOp3(v, OP_DropIndex, iDb, 0, pIndex->zName, 0); } exit_drop_index: sqlite3SrcListDelete(pName); } /* ** ppArray points into a structure where there is an array pointer ** followed by two integers. The first integer is the ** number of elements in the structure array. The second integer ** is the number of allocated slots in the array. ** ** In other words, the structure looks something like this: ** ** struct Example1 { ** struct subElem *aEntry; ** int nEntry; ** int nAlloc; ** } ** ** The pnEntry parameter points to the equivalent of Example1.nEntry. ** ** This routine allocates a new slot in the array, zeros it out, ** and returns its index. If malloc fails a negative number is returned. ** ** szEntry is the sizeof of a single array entry. initSize is the ** number of array entries allocated on the initial allocation. */ int sqlite3ArrayAllocate(void **ppArray, int szEntry, int initSize){ char *p; int *an = (int*)&ppArray[1]; if( an[0]>=an[1] ){ void *pNew; an[1] = an[1]*2 + initSize; pNew = sqliteRealloc(*ppArray, an[1]*szEntry); if( pNew==0 ){ return -1; } *ppArray = pNew; } p = *ppArray; memset(&p[an[0]*szEntry], 0, szEntry); return an[0]++; } /* ** Append a new element to the given IdList. Create a new IdList if ** need be. ** ** A new IdList is returned, or NULL if malloc() fails. */ IdList *sqlite3IdListAppend(IdList *pList, Token *pToken){ int i; if( pList==0 ){ pList = sqliteMalloc( sizeof(IdList) ); if( pList==0 ) return 0; pList->nAlloc = 0; } i = sqlite3ArrayAllocate((void**)&pList->a, sizeof(pList->a[0]), 5); if( i<0 ){ sqlite3IdListDelete(pList); return 0; } pList->a[i].zName = sqlite3NameFromToken(pToken); return pList; } /* ** Delete an IdList. */ void sqlite3IdListDelete(IdList *pList){ |
︙ | ︙ |
Changes to src/expr.c.
︙ | ︙ | |||
8 9 10 11 12 13 14 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains routines used for analyzing expressions and ** for generating VDBE code that evaluates expressions in SQLite. ** | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains routines used for analyzing expressions and ** for generating VDBE code that evaluates expressions in SQLite. ** ** $Id: expr.c,v 1.225 2005/09/07 21:22:46 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> /* ** Return the 'affinity' of the expression pExpr if any. ** |
︙ | ︙ | |||
691 692 693 694 695 696 697 698 699 700 701 702 703 704 | case TK_FUNCTION: if( *((int*)pArg)==2 ) return 0; /* Fall through */ case TK_ID: case TK_COLUMN: case TK_DOT: case TK_AGG_FUNCTION: #ifndef SQLITE_OMIT_SUBQUERY case TK_SELECT: case TK_EXISTS: #endif *((int*)pArg) = 0; return 2; case TK_IN: | > | 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 | case TK_FUNCTION: if( *((int*)pArg)==2 ) return 0; /* Fall through */ case TK_ID: case TK_COLUMN: case TK_DOT: case TK_AGG_FUNCTION: case TK_AGG_COLUMN: #ifndef SQLITE_OMIT_SUBQUERY case TK_SELECT: case TK_EXISTS: #endif *((int*)pArg) = 0; return 2; case TK_IN: |
︙ | ︙ | |||
1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 | ** If the expression contains aggregate functions then set the EP_Agg ** property on the expression. */ int sqlite3ExprResolveNames( NameContext *pNC, /* Namespace to resolve expressions in. */ Expr *pExpr /* The expression to be analyzed. */ ){ if( pExpr==0 ) return 0; walkExprTree(pExpr, nameResolverStep, pNC); if( pNC->nErr>0 ){ ExprSetProperty(pExpr, EP_Error); } return ExprHasProperty(pExpr, EP_Error); } /* ** A pointer instance of this structure is used to pass information ** through walkExprTree into codeSubqueryStep(). | > > > > > > > > | 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 | ** If the expression contains aggregate functions then set the EP_Agg ** property on the expression. */ int sqlite3ExprResolveNames( NameContext *pNC, /* Namespace to resolve expressions in. */ Expr *pExpr /* The expression to be analyzed. */ ){ int savedHasAgg; if( pExpr==0 ) return 0; savedHasAgg = pNC->hasAgg; pNC->hasAgg = 0; walkExprTree(pExpr, nameResolverStep, pNC); if( pNC->nErr>0 ){ ExprSetProperty(pExpr, EP_Error); } if( pNC->hasAgg ){ ExprSetProperty(pExpr, EP_Agg); }else if( savedHasAgg ){ pNC->hasAgg = 1; } return ExprHasProperty(pExpr, EP_Error); } /* ** A pointer instance of this structure is used to pass information ** through walkExprTree into codeSubqueryStep(). |
︙ | ︙ | |||
1283 1284 1285 1286 1287 1288 1289 | sqlite3VdbeAddOp(v, OP_MemLoad, mem, 0); testAddr = sqlite3VdbeAddOp(v, OP_If, 0, 0); assert( testAddr>0 ); sqlite3VdbeAddOp(v, OP_Integer, 1, 0); sqlite3VdbeAddOp(v, OP_MemStore, mem, 1); } | < < < < | 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 | sqlite3VdbeAddOp(v, OP_MemLoad, mem, 0); testAddr = sqlite3VdbeAddOp(v, OP_If, 0, 0); assert( testAddr>0 ); sqlite3VdbeAddOp(v, OP_Integer, 1, 0); sqlite3VdbeAddOp(v, OP_MemStore, mem, 1); } switch( pExpr->op ){ case TK_IN: { char affinity; KeyInfo keyInfo; int addr; /* Address of OP_OpenVirtual instruction */ affinity = sqlite3ExprAffinity(pExpr->pLeft); |
︙ | ︙ | |||
1399 1400 1401 1402 1403 1404 1405 | sqlite3Expr(TK_INTEGER, 0, 0, &one), 0); } sqlite3Select(pParse, pSel, sop, pExpr->iColumn, 0, 0, 0, 0); break; } } | < < < | 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 | sqlite3Expr(TK_INTEGER, 0, 0, &one), 0); } sqlite3Select(pParse, pSel, sop, pExpr->iColumn, 0, 0, 0, 0); break; } } if( testAddr ){ sqlite3VdbeChangeP2(v, testAddr, sqlite3VdbeCurrentAddr(v)); } return; } #endif /* SQLITE_OMIT_SUBQUERY */ |
︙ | ︙ | |||
1444 1445 1446 1447 1448 1449 1450 | if( v==0 ) return; if( pExpr==0 ){ sqlite3VdbeAddOp(v, OP_Null, 0, 0); return; } op = pExpr->op; switch( op ){ | | > | > | > > > > > > > > > | | 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 | if( v==0 ) return; if( pExpr==0 ){ sqlite3VdbeAddOp(v, OP_Null, 0, 0); return; } op = pExpr->op; switch( op ){ case TK_AGG_COLUMN: { AggInfo *pAggInfo = pExpr->pAggInfo; struct AggInfo_col *pCol = &pAggInfo->aCol[pExpr->iAgg]; if( !pAggInfo->directMode ){ sqlite3VdbeAddOp(v, OP_MemLoad, pCol->iMem, 0); break; }else if( pAggInfo->useSortingIdx ){ sqlite3VdbeAddOp(v, OP_Column, pAggInfo->sortingIdx, pCol->iSorterColumn); break; } /* Otherwise, fall thru into the TK_COLUMN case */ } case TK_COLUMN: { if( pExpr->iColumn>=0 ){ sqlite3VdbeAddOp(v, OP_Column, pExpr->iTable, pExpr->iColumn); sqlite3ColumnDefault(v, pExpr->pTab, pExpr->iColumn); }else{ sqlite3VdbeAddOp(v, OP_Rowid, pExpr->iTable, 0); } break; } |
︙ | ︙ | |||
1596 1597 1598 1599 1600 1601 1602 | sqlite3ExprCode(pParse, pExpr->pLeft); dest = sqlite3VdbeCurrentAddr(v) + 2; sqlite3VdbeAddOp(v, op, 1, dest); sqlite3VdbeAddOp(v, OP_AddImm, -1, 0); break; } case TK_AGG_FUNCTION: { | > | | | | | 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 | sqlite3ExprCode(pParse, pExpr->pLeft); dest = sqlite3VdbeCurrentAddr(v) + 2; sqlite3VdbeAddOp(v, op, 1, dest); sqlite3VdbeAddOp(v, OP_AddImm, -1, 0); break; } case TK_AGG_FUNCTION: { AggInfo *pInfo = pExpr->pAggInfo; sqlite3VdbeAddOp(v, OP_MemLoad, pInfo->aFunc[pExpr->iAgg].iMem, 0); break; } case TK_CONST_FUNC: case TK_FUNCTION: { ExprList *pList = pExpr->pList; int nExpr = pList ? pList->nExpr : 0; FuncDef *pDef; int nId; const char *zId; int constMask = 0; int i; u8 enc = pParse->db->enc; CollSeq *pColl = 0; zId = pExpr->token.z; nId = pExpr->token.n; pDef = sqlite3FindFunction(pParse->db, zId, nId, nExpr, enc, 0); assert( pDef!=0 ); nExpr = sqlite3ExprCodeExprList(pParse, pList); for(i=0; i<nExpr && i<32; i++){ if( sqlite3ExprIsConstant(pList->a[i].pExpr) ){ constMask |= (1<<i); } if( pDef->needCollSeq && !pColl ){ pColl = sqlite3ExprCollSeq(pParse, pList->a[i].pExpr); } } if( pDef->needCollSeq ){ if( !pColl ) pColl = pParse->db->pDfltColl; sqlite3VdbeOp3(v, OP_CollSeq, 0, 0, (char *)pColl, P3_COLLSEQ); } sqlite3VdbeOp3(v, OP_Function, constMask, nExpr, (char*)pDef, P3_FUNCDEF); break; } #ifndef SQLITE_OMIT_SUBQUERY case TK_EXISTS: case TK_SELECT: { sqlite3CodeSubselect(pParse, pExpr); sqlite3VdbeAddOp(v, OP_MemLoad, pExpr->iColumn, 0); |
︙ | ︙ | |||
2043 2044 2045 2046 2047 2048 2049 2050 | if( pB->token.z==0 ) return 0; if( pB->token.n!=pA->token.n ) return 0; if( sqlite3StrNICmp(pA->token.z, pB->token.z, pB->token.n)!=0 ) return 0; } return 1; } /* | > | | < | < | | | | | < > | | > > > > > > > > > > | | < > > > > > > | > | > > > > > > | | | < < | | | | > > > > | | | > | > | > | > > > > | > > > > > > > > > > > | > | | < > > > > > > > | | < | | > > | | | < | > | | | | > > > > > > > > > | 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 | if( pB->token.z==0 ) return 0; if( pB->token.n!=pA->token.n ) return 0; if( sqlite3StrNICmp(pA->token.z, pB->token.z, pB->token.n)!=0 ) return 0; } return 1; } /* ** Add a new element to the pAggInfo->aCol[] array. Return the index of ** the new element. Return a negative number if malloc fails. */ static int addAggInfoColumn(AggInfo *pInfo){ int i; i = sqlite3ArrayAllocate((void**)&pInfo->aCol, sizeof(pInfo->aCol[0]), 3); if( i<0 ){ return -1; } return i; } /* ** Add a new element to the pAggInfo->aFunc[] array. Return the index of ** the new element. Return a negative number if malloc fails. */ static int addAggInfoFunc(AggInfo *pInfo){ int i; i = sqlite3ArrayAllocate((void**)&pInfo->aFunc, sizeof(pInfo->aFunc[0]), 2); if( i<0 ){ return -1; } return i; } /* ** This is an xFunc for walkExprTree() used to implement ** sqlite3ExprAnalyzeAggregates(). See sqlite3ExprAnalyzeAggregates ** for additional information. ** ** This routine analyzes the aggregate function at pExpr. */ static int analyzeAggregate(void *pArg, Expr *pExpr){ int i; NameContext *pNC = (NameContext *)pArg; Parse *pParse = pNC->pParse; SrcList *pSrcList = pNC->pSrcList; AggInfo *pAggInfo = pNC->pAggInfo; switch( pExpr->op ){ case TK_COLUMN: { /* Check to see if the column is in one of the tables in the FROM ** clause of the aggregate query */ if( pSrcList ){ struct SrcList_item *pItem = pSrcList->a; for(i=0; i<pSrcList->nSrc; i++, pItem++){ struct AggInfo_col *pCol; if( pExpr->iTable==pItem->iCursor ){ /* If we reach this point, it means that pExpr refers to a table ** that is in the FROM clause of the aggregate query. ** ** Make an entry for the column in pAggInfo->aCol[] if there ** is not an entry there already. */ pCol = pAggInfo->aCol; for(i=0; i<pAggInfo->nColumn; i++, pCol++){ if( pCol->iTable==pExpr->iTable && pCol->iColumn==pExpr->iColumn ){ break; } } if( i>=pAggInfo->nColumn && (i = addAggInfoColumn(pAggInfo))>=0 ){ pCol = &pAggInfo->aCol[i]; pCol->iTable = pExpr->iTable; pCol->iColumn = pExpr->iColumn; pCol->iMem = pParse->nMem++; pCol->iSorterColumn = -1; if( pAggInfo->pGroupBy ){ int j, n; ExprList *pGB = pAggInfo->pGroupBy; struct ExprList_item *pTerm = pGB->a; n = pGB->nExpr; for(j=0; j<n; j++, pTerm++){ Expr *pE = pTerm->pExpr; if( pE->op==TK_COLUMN && pE->iTable==pExpr->iTable && pE->iColumn==pExpr->iColumn ){ pCol->iSorterColumn = j; break; } } } if( pCol->iSorterColumn<0 ){ pCol->iSorterColumn = pAggInfo->nSortingColumn++; } } /* There is now an entry for pExpr in pAggInfo->aCol[] (either ** because it was there before or because we just created it). ** Convert the pExpr to be a TK_AGG_COLUMN referring to that ** pAggInfo->aCol[] entry. */ pExpr->pAggInfo = pAggInfo; pExpr->op = TK_AGG_COLUMN; pExpr->iAgg = i; break; } /* endif pExpr->iTable==pItem->iCursor */ } /* end loop over pSrcList */ } return 1; } case TK_AGG_FUNCTION: { /* The pNC->nDepth==0 test causes aggregate functions in subqueries ** to be ignored */ if( pNC->nDepth==0 ){ /* Check to see if pExpr is a duplicate of another aggregate ** function that is already in the pAggInfo structure */ struct AggInfo_func *pItem = pAggInfo->aFunc; for(i=0; i<pAggInfo->nFunc; i++, pItem++){ if( sqlite3ExprCompare(pItem->pExpr, pExpr) ){ break; } } if( i>=pAggInfo->nFunc ){ /* pExpr is original. Make a new entry in pAggInfo->aFunc[] */ u8 enc = pParse->db->enc; i = addAggInfoFunc(pAggInfo); if( i>=0 ){ pItem = &pAggInfo->aFunc[i]; pItem->pExpr = pExpr; pItem->iMem = pParse->nMem++; pItem->pFunc = sqlite3FindFunction(pParse->db, pExpr->token.z, pExpr->token.n, pExpr->pList ? pExpr->pList->nExpr : 0, enc, 0); } } /* Make pExpr point to the appropriate pAggInfo->aFunc[] entry */ pExpr->iAgg = i; pExpr->pAggInfo = pAggInfo; return 1; } } } /* Recursively walk subqueries looking for TK_COLUMN nodes that need ** to be changed to TK_AGG_COLUMN. But increment nDepth so that ** TK_AGG_FUNCTION nodes in subqueries will be unchanged. */ if( pExpr->pSelect ){ pNC->nDepth++; walkSelectExpr(pExpr->pSelect, analyzeAggregate, pNC); pNC->nDepth--; } return 0; } |
︙ | ︙ |
Changes to src/main.c.
︙ | ︙ | |||
10 11 12 13 14 15 16 | ** ************************************************************************* ** Main file for the SQLite library. The routines in this file ** implement the programmer interface to the library. Routines in ** other files are for internal use by SQLite and should not be ** accessed by users of the library. ** | | | 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | ** ************************************************************************* ** Main file for the SQLite library. The routines in this file ** implement the programmer interface to the library. Routines in ** other files are for internal use by SQLite and should not be ** accessed by users of the library. ** ** $Id: main.c,v 1.301 2005/09/07 21:22:46 drh Exp $ */ #include "sqliteInt.h" #include "os.h" #include <ctype.h> /* ** The following constant value is used by the SQLITE_BIGENDIAN and |
︙ | ︙ | |||
871 872 873 874 875 876 877 | */ int sqlite3_reset(sqlite3_stmt *pStmt){ int rc; if( pStmt==0 ){ rc = SQLITE_OK; }else{ rc = sqlite3VdbeReset((Vdbe*)pStmt); | | | 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 | */ int sqlite3_reset(sqlite3_stmt *pStmt){ int rc; if( pStmt==0 ){ rc = SQLITE_OK; }else{ rc = sqlite3VdbeReset((Vdbe*)pStmt); sqlite3VdbeMakeReady((Vdbe*)pStmt, -1, 0, 0, 0); } return rc; } /* ** Register a new collation sequence with the database handle db. */ |
︙ | ︙ |
Changes to src/parse.y.
︙ | ︙ | |||
10 11 12 13 14 15 16 | ** ************************************************************************* ** 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. ** | | | 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | ** ************************************************************************* ** 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.176 2005/09/07 21:22:46 drh Exp $ */ // All token codes are small integers with #defines that begin with "TK_" %token_prefix TK_ // The type of the data attached to each token is Token. This is also the // default type for non-terminals. |
︙ | ︙ | |||
89 90 91 92 93 94 95 | } // end %include // 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 parse.h output file. // %nonassoc END_OF_FILE ILLEGAL SPACE UNCLOSED_STRING COMMENT FUNCTION | | | 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 | } // end %include // 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 parse.h output file. // %nonassoc END_OF_FILE ILLEGAL SPACE UNCLOSED_STRING COMMENT FUNCTION COLUMN AGG_FUNCTION AGG_COLUMN CONST_FUNC. // Input is a single SQL command input ::= cmdlist. cmdlist ::= cmdlist ecmd. cmdlist ::= ecmd. cmdx ::= cmd. { sqlite3FinishCoding(pParse); } ecmd ::= SEMI. |
︙ | ︙ |
Changes to src/select.c.
︙ | ︙ | |||
8 9 10 11 12 13 14 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains C code routines that are called by the parser ** to handle SELECT statements in SQLite. ** | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains C code routines that are called by the parser ** to handle SELECT statements in SQLite. ** ** $Id: select.c,v 1.261 2005/09/07 21:22:47 drh Exp $ */ #include "sqliteInt.h" /* ** Allocate a new Select structure and return a pointer to that ** structure. |
︙ | ︙ | |||
342 343 344 345 346 347 348 | static void codeLimiter( Vdbe *v, /* Generate code into this VM */ Select *p, /* The SELECT statement being coded */ int iContinue, /* Jump here to skip the current record */ int iBreak, /* Jump here to end the loop */ int nPop /* Number of times to pop stack when jumping */ ){ | | | | 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 | static void codeLimiter( Vdbe *v, /* Generate code into this VM */ Select *p, /* The SELECT statement being coded */ int iContinue, /* Jump here to skip the current record */ int iBreak, /* Jump here to end the loop */ int nPop /* Number of times to pop stack when jumping */ ){ if( p->iOffset>=0 && iContinue!=0 ){ int addr = sqlite3VdbeCurrentAddr(v) + 3; if( nPop>0 ) addr++; sqlite3VdbeAddOp(v, OP_MemIncr, p->iOffset, 0); sqlite3VdbeAddOp(v, OP_IfMemPos, p->iOffset, addr); if( nPop>0 ){ sqlite3VdbeAddOp(v, OP_Pop, nPop, 0); } sqlite3VdbeAddOp(v, OP_Goto, 0, iContinue); VdbeComment((v, "# skip OFFSET records")); } if( p->iLimit>=0 && iBreak!=0 ){ sqlite3VdbeAddOp(v, OP_MemIncr, p->iLimit, iBreak); VdbeComment((v, "# exit when LIMIT reached")); } } /* ** This routine generates the code for the inside of the inner loop |
︙ | ︙ | |||
431 432 433 434 435 436 437 | sqlite3VdbeAddOp(v, OP_IdxInsert, distinct, 0); if( pOrderBy==0 ){ codeLimiter(v, p, iContinue, iBreak, nColumn); } } switch( eDest ){ | < > > | > | 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 | sqlite3VdbeAddOp(v, OP_IdxInsert, distinct, 0); if( pOrderBy==0 ){ codeLimiter(v, p, iContinue, iBreak, nColumn); } } switch( eDest ){ /* In this mode, write each query result to the key of the temporary ** table iParm. */ #ifndef SQLITE_OMIT_COMPOUND_SELECT case SRT_Union: { sqlite3VdbeAddOp(v, OP_MakeRecord, nColumn, NULL_ALWAYS_DISTINCT); if( aff ){ sqlite3VdbeChangeP3(v, -1, aff, P3_STATIC); } sqlite3VdbeAddOp(v, OP_IdxInsert, iParm, 0); break; } /* Construct a record from the query result, but instead of ** saving that record, use it as a key to delete elements from ** the temporary table iParm. |
︙ | ︙ | |||
1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 | pOrderBy->iTab = pParse->nTab++; addr = sqlite3VdbeAddOp(pParse->pVdbe, OP_OpenVirtual, pOrderBy->iTab, pOrderBy->nExpr+1); assert( p->addrOpenVirt[2] == -1 ); p->addrOpenVirt[2] = addr; } } #ifndef SQLITE_OMIT_COMPOUND_SELECT /* ** Return the appropriate collating sequence for the iCol-th column of ** the result set for the compound-select statement "p". Return NULL if ** the column has no default collating sequence. ** | > > > > > > > > > > > > > > | 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 | pOrderBy->iTab = pParse->nTab++; addr = sqlite3VdbeAddOp(pParse->pVdbe, OP_OpenVirtual, pOrderBy->iTab, pOrderBy->nExpr+1); assert( p->addrOpenVirt[2] == -1 ); p->addrOpenVirt[2] = addr; } } /* ** The opcode at addr is an OP_OpenVirtual that created a sorting ** index tha we ended up not needing. This routine changes that ** opcode to OP_Noop. */ static void uncreateSortingIndex(Parse *pParse, int addr){ Vdbe *v = pParse->pVdbe; VdbeOp *pOp = sqlite3VdbeGetOp(v, addr); sqlite3VdbeChangeP3(v, addr, 0, 0); pOp->opcode = OP_Noop; pOp->p1 = 0; pOp->p2 = 0; } #ifndef SQLITE_OMIT_COMPOUND_SELECT /* ** Return the appropriate collating sequence for the iCol-th column of ** the result set for the compound-select statement "p". Return NULL if ** the column has no default collating sequence. ** |
︙ | ︙ | |||
2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 | Parse *pParse, /* The parser context */ Select *p, /* The SELECT statement being coded. */ NameContext *pOuterNC /* The outer name context. May be NULL. */ ){ ExprList *pEList; /* Result set. */ int i; /* For-loop variable used in multiple places */ NameContext sNC; /* Local name-context */ /* If this routine has run before, return immediately. */ if( p->isResolved ){ assert( !pOuterNC ); return SQLITE_OK; } p->isResolved = 1; | > | 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 | Parse *pParse, /* The parser context */ Select *p, /* The SELECT statement being coded. */ NameContext *pOuterNC /* The outer name context. May be NULL. */ ){ ExprList *pEList; /* Result set. */ int i; /* For-loop variable used in multiple places */ NameContext sNC; /* Local name-context */ ExprList *pGroupBy; /* The group by clause */ /* If this routine has run before, return immediately. */ if( p->isResolved ){ assert( !pOuterNC ); return SQLITE_OK; } p->isResolved = 1; |
︙ | ︙ | |||
2315 2316 2317 2318 2319 2320 2321 | /* Set up the local name-context to pass to ExprResolveNames() to ** resolve the expression-list. */ sNC.allowAgg = 1; sNC.pSrcList = p->pSrc; sNC.pNext = pOuterNC; | < < < < < < < < < < < < > | | | > > > > > > > > > > > > > > < | < > | > > | | > | > > > > > | < > > | > | > > > | | | > > > > > > > > > | > > > | | > > > > | > > > > > | > > | | > > > > > > | < < < < < < > | > > > > > > > > > | > > > | | > | 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 | /* Set up the local name-context to pass to ExprResolveNames() to ** resolve the expression-list. */ sNC.allowAgg = 1; sNC.pSrcList = p->pSrc; sNC.pNext = pOuterNC; /* Resolve names in the result set. */ pEList = p->pEList; if( !pEList ) return SQLITE_ERROR; for(i=0; i<pEList->nExpr; i++){ Expr *pX = pEList->a[i].pExpr; if( sqlite3ExprResolveNames(&sNC, pX) ){ return SQLITE_ERROR; } } /* If there are no aggregate functions in the result-set, and no GROUP BY ** expression, do not allow aggregates in any of the other expressions. */ assert( !p->isAgg ); pGroupBy = p->pGroupBy; if( pGroupBy || sNC.hasAgg ){ p->isAgg = 1; }else{ sNC.allowAgg = 0; } /* If a HAVING clause is present, then there must be a GROUP BY clause. */ if( p->pHaving && !pGroupBy ){ sqlite3ErrorMsg(pParse, "a GROUP BY clause is required before HAVING"); return SQLITE_ERROR; } /* Add the expression list to the name-context before parsing the ** other expressions in the SELECT statement. This is so that ** expressions in the WHERE clause (etc.) can refer to expressions by ** aliases in the result set. ** ** Minor point: If this is the case, then the expression will be ** re-evaluated for each reference to it. */ sNC.pEList = p->pEList; if( sqlite3ExprResolveNames(&sNC, p->pWhere) || sqlite3ExprResolveNames(&sNC, p->pHaving) || processOrderGroupBy(&sNC, p->pOrderBy, "ORDER") || processOrderGroupBy(&sNC, pGroupBy, "GROUP") ){ return SQLITE_ERROR; } /* Make sure the GROUP BY clause does not contain aggregate functions. */ if( pGroupBy ){ struct ExprList_item *pItem; for(i=0, pItem=pGroupBy->a; i<pGroupBy->nExpr; i++, pItem++){ if( ExprHasProperty(pItem->pExpr, EP_Agg) ){ sqlite3ErrorMsg(pParse, "aggregate functions are not allowed in " "the GROUP BY clause"); return SQLITE_ERROR; } } } return SQLITE_OK; } /* ** Reset the aggregate accumulator. ** ** The aggregate accumulator is a set of memory cells that hold ** intermediate results while calculating an aggregate. This ** routine simply stores NULLs in all of those memory cells. */ static void resetAccumulator(Parse *pParse, AggInfo *pAggInfo){ Vdbe *v = pParse->pVdbe; int i; int addr; if( pAggInfo->nFunc+pAggInfo->nColumn==0 ){ return; } sqlite3VdbeAddOp(v, OP_Null, 0, 0); for(i=0; i<pAggInfo->nColumn; i++){ addr = sqlite3VdbeAddOp(v, OP_MemStore, pAggInfo->aCol[i].iMem, 0); } for(i=0; i<pAggInfo->nFunc; i++){ addr = sqlite3VdbeAddOp(v, OP_MemStore, pAggInfo->aFunc[i].iMem, 0); } sqlite3VdbeChangeP2(v, addr, 1); } /* ** Invoke the OP_AggFinalize opcode for every aggregate function ** in the AggInfo structure. */ static void finalizeAggFunctions(Parse *pParse, AggInfo *pAggInfo){ Vdbe *v = pParse->pVdbe; int i; struct AggInfo_func *pF; for(i=0, pF=pAggInfo->aFunc; i<pAggInfo->nFunc; i++, pF++){ sqlite3VdbeAddOp(v, OP_AggFinal, pF->iMem, 0); } } /* ** Update the accumulator memory cells for an aggregate based on ** the current cursor position. */ static void updateAccumulator(Parse *pParse, AggInfo *pAggInfo){ Vdbe *v = pParse->pVdbe; int i; struct AggInfo_func *pF; struct AggInfo_col *pC; Expr fauxExpr; pAggInfo->directMode = 1; for(i=0, pF=pAggInfo->aFunc; i<pAggInfo->nFunc; i++, pF++){ int nArg; ExprList *pList = pF->pExpr->pList; if( pList ){ nArg = pList->nExpr; sqlite3ExprCodeExprList(pParse, pList); }else{ nArg = 0; } if( pF->pFunc->needCollSeq ){ CollSeq *pColl = 0; struct ExprList_item *pItem; int j; for(j=0, pItem=pList->a; !pColl && j<pList->nExpr; j++, pItem++){ pColl = sqlite3ExprCollSeq(pParse, pItem->pExpr); } if( !pColl ){ pColl = pParse->db->pDfltColl; } sqlite3VdbeOp3(v, OP_CollSeq, 0, 0, (char *)pColl, P3_COLLSEQ); } sqlite3VdbeOp3(v, OP_AggStep, pF->iMem, nArg, (void*)pF->pFunc, P3_FUNCDEF); } memset(&fauxExpr, 0, sizeof(fauxExpr)); fauxExpr.op = TK_AGG_COLUMN; fauxExpr.pAggInfo = pAggInfo; for(i=0, pC=pAggInfo->aCol; i<pAggInfo->nAccumulator; i++, pC++){ fauxExpr.iAgg = i; sqlite3ExprCode(pParse, &fauxExpr); sqlite3VdbeAddOp(v, OP_MemStore, pC->iMem, 1); } pAggInfo->directMode = 0; } /* ** Generate code for the given SELECT statement. ** ** The results are distributed in various ways depending on the ** value of eDest and iParm. ** ** eDest Value Result |
︙ | ︙ | |||
2471 2472 2473 2474 2475 2476 2477 | int eDest, /* How to dispose of the results */ int iParm, /* A parameter used by the eDest disposal method */ Select *pParent, /* Another SELECT for which this is a sub-query */ int parentTab, /* Index in pParent->pSrc of this query */ int *pParentAgg, /* True if pParent uses aggregate functions */ char *aff /* If eDest is SRT_Union, the affinity string */ ){ | | | | | > < < > | 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 | int eDest, /* How to dispose of the results */ int iParm, /* A parameter used by the eDest disposal method */ Select *pParent, /* Another SELECT for which this is a sub-query */ int parentTab, /* Index in pParent->pSrc of this query */ int *pParentAgg, /* True if pParent uses aggregate functions */ char *aff /* If eDest is SRT_Union, the affinity string */ ){ int i, j; /* Loop counters */ WhereInfo *pWInfo; /* Return from sqlite3WhereBegin() */ Vdbe *v; /* The virtual machine under construction */ int isAgg; /* True for select lists like "count(*)" */ ExprList *pEList; /* List of columns to extract. */ SrcList *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 */ int rc = 1; /* Value to return from this function */ AggInfo sAggInfo; /* Information used by aggregate queries */ if( sqlite3_malloc_failed || pParse->nErr || p==0 ) return 1; if( sqlite3AuthCheck(pParse, SQLITE_SELECT, 0, 0, 0) ) return 1; memset(&sAggInfo, 0, sizeof(sAggInfo)); #ifndef SQLITE_OMIT_COMPOUND_SELECT /* If there is are a sequence of queries, do the earlier ones first. */ if( p->pPrior ){ if( p->pRightmost==0 ){ Select *pLoop; for(pLoop=p; pLoop; pLoop=pLoop->pPrior){ pLoop->pRightmost = p; } } return multiSelect(pParse, p, eDest, iParm, aff); } #endif pOrderBy = p->pOrderBy; if( IgnorableOrderby(eDest) ){ p->pOrderBy = 0; } if( sqlite3SelectResolve(pParse, p, 0) ){ goto select_end; } p->pOrderBy = pOrderBy; |
︙ | ︙ | |||
2544 2545 2546 2547 2548 2549 2550 | "a SELECT that is part of an expression"); goto select_end; } #endif /* ORDER BY is ignored for some destinations. */ | | < < < | < < < > | | | | | | | 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 | "a SELECT that is part of an expression"); goto select_end; } #endif /* ORDER BY is ignored for some destinations. */ if( IgnorableOrderby(eDest) ){ pOrderBy = 0; } /* Begin generating code. */ v = sqlite3GetVdbe(pParse); if( v==0 ) goto select_end; /* Identify column names if we will be using them in a callback. This ** step is skipped if the output is going to some other destination. */ if( eDest==SRT_Callback ){ generateColumnNames(pParse, pTabList, pEList); } /* Generate code for all sub-queries in the FROM clause */ #if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) for(i=0; i<pTabList->nSrc; i++){ const char *zSavedAuthContext = 0; int needRestoreContext; struct SrcList_item *pItem = &pTabList->a[i]; if( pItem->pSelect==0 ) continue; if( pItem->zName!=0 ){ zSavedAuthContext = pParse->zAuthContext; pParse->zAuthContext = pItem->zName; needRestoreContext = 1; }else{ needRestoreContext = 0; } sqlite3Select(pParse, pItem->pSelect, SRT_TempTable, pItem->iCursor, p, i, &isAgg, 0); if( needRestoreContext ){ pParse->zAuthContext = zSavedAuthContext; } pTabList = p->pSrc; pWhere = p->pWhere; if( !IgnorableOrderby(eDest) ){ pOrderBy = p->pOrderBy; } pGroupBy = p->pGroupBy; pHaving = p->pHaving; isDistinct = p->isDistinct; } #endif |
︙ | ︙ | |||
2648 2649 2650 2651 2652 2653 2654 | /* If the output is destined for a temporary table, open that table. */ if( eDest==SRT_TempTable ){ sqlite3VdbeAddOp(v, OP_OpenVirtual, iParm, pEList->nExpr); } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < > > > | | | < | | < | < | | < < | > | > | | | > > | < < | | < < | < < < < | > > > > > > | | | < < < | < < < < < < < < < < < < < < < | < | | < < < | < > > | > > > > > | > | < < < < | | < < < < < > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 | /* If the output is destined for a temporary table, open that table. */ if( eDest==SRT_TempTable ){ sqlite3VdbeAddOp(v, OP_OpenVirtual, iParm, pEList->nExpr); } /* Initialize the memory cell to NULL for SRT_Mem or 0 for SRT_Exists */ if( eDest==SRT_Mem || eDest==SRT_Exists ){ sqlite3VdbeAddOp(v, eDest==SRT_Mem ? OP_Null : OP_Integer, 0, 0); sqlite3VdbeAddOp(v, OP_MemStore, iParm, 1); } /* Open a virtual index to use for the distinct set. */ if( isDistinct ){ KeyInfo *pKeyInfo; distinct = pParse->nTab++; pKeyInfo = keyInfoFromExprList(pParse, p->pEList); sqlite3VdbeOp3(v, OP_OpenVirtual, distinct, 0, (char*)pKeyInfo, P3_KEYINFO_HANDOFF); }else{ distinct = -1; } /* Aggregate and non-aggregate queries are handled differently */ if( !isAgg && pGroupBy==0 ){ /* This case is for non-aggregate queries ** Begin the database scan */ pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pOrderBy); if( pWInfo==0 ) goto select_end; /* Use the standard inner loop */ if( selectInnerLoop(pParse, p, pEList, 0, 0, pOrderBy, distinct, eDest, iParm, pWInfo->iContinue, pWInfo->iBreak, aff) ){ goto select_end; } /* End the database scan loop. */ sqlite3WhereEnd(pWInfo); }else{ /* This is the processing for aggregate queries */ NameContext sNC; /* Name context for processing aggregate information */ int iAMem; /* First Mem address for storing current GROUP BY */ int iBMem; /* First Mem address for previous GROUP BY */ int iUseFlag; /* Mem address holding flag indicating that at least ** one row of the input to the aggregator has been ** processed */ int iAbortFlag; /* Mem address which causes query abort if positive */ int groupBySort; /* Rows come from source in GROUP BY order */ /* The following variables hold addresses or labels for parts of the ** virtual machine program we are putting together */ int addrOutputRow; /* Start of subroutine that outputs a result row */ int addrSetAbort; /* Set the abort flag and return */ int addrInitializeLoop; /* Start of code that initializes the input loop */ int addrTopOfLoop; /* Top of the input loop */ int addrGroupByChange; /* Code that runs when any GROUP BY term changes */ int addrProcessRow; /* Code to process a single input row */ int addrEnd; /* End of all processing */ int addrSortingIdx; /* The OP_OpenVirtual for the sorting index */ addrEnd = sqlite3VdbeMakeLabel(v); /* Convert TK_COLUMN nodes into TK_AGG_COLUMN and make entries in ** sAggInfo for all TK_AGG_FUNCTION nodes in expressions of the ** SELECT statement. */ memset(&sNC, 0, sizeof(sNC)); sNC.pParse = pParse; sNC.pSrcList = pTabList; sNC.pAggInfo = &sAggInfo; sAggInfo.nSortingColumn = pGroupBy ? pGroupBy->nExpr+1 : 0; if( sqlite3ExprAnalyzeAggList(&sNC, pEList) ){ goto select_end; } if( sqlite3ExprAnalyzeAggList(&sNC, pOrderBy) ){ goto select_end; } if( pHaving && sqlite3ExprAnalyzeAggregates(&sNC, pHaving) ){ goto select_end; } sAggInfo.nAccumulator = sAggInfo.nColumn; for(i=0; i<sAggInfo.nFunc; i++){ if( sqlite3ExprAnalyzeAggList(&sNC, sAggInfo.aFunc[i].pExpr->pList) ){ goto select_end; } } /* Processing for aggregates with GROUP BY is very different and ** much more complex tha aggregates without a GROUP BY. */ if( pGroupBy ){ KeyInfo *pKeyInfo; /* Keying information for the group by clause */ /* Create labels that we will be needing */ addrInitializeLoop = sqlite3VdbeMakeLabel(v); addrGroupByChange = sqlite3VdbeMakeLabel(v); addrProcessRow = sqlite3VdbeMakeLabel(v); /* If there is a GROUP BY clause we might need a sorting index to ** implement it. Allocate that sorting index now. If it turns out ** that we do not need it after all, the OpenVirtual instruction ** will be converted into a Noop. */ sAggInfo.sortingIdx = pParse->nTab++; pKeyInfo = keyInfoFromExprList(pParse, pGroupBy); addrSortingIdx = sqlite3VdbeOp3(v, OP_OpenVirtual, sAggInfo.sortingIdx, sAggInfo.nSortingColumn, (char*)pKeyInfo, P3_KEYINFO_HANDOFF); /* Initialize memory locations used by GROUP BY aggregate processing */ iUseFlag = pParse->nMem++; iAbortFlag = pParse->nMem++; iAMem = pParse->nMem; pParse->nMem += pGroupBy->nExpr; iBMem = pParse->nMem; pParse->nMem += pGroupBy->nExpr; sqlite3VdbeAddOp(v, OP_Integer, 0, 0); sqlite3VdbeAddOp(v, OP_MemStore, iAbortFlag, 0); sqlite3VdbeAddOp(v, OP_MemStore, iUseFlag, 1); sqlite3VdbeAddOp(v, OP_Null, 0, 0); sqlite3VdbeAddOp(v, OP_MemStore, iAMem, 1); sqlite3VdbeAddOp(v, OP_Goto, 0, addrInitializeLoop); /* Generate a subroutine that outputs a single row of the result ** set. This subroutine first looks at the iUseFlag. If iUseFlag ** is less than or equal to zero, the subroutine is a no-op. If ** the processing calls for the query to abort, this subroutine ** increments the iAbortFlag memory location before returning in ** order to signal the caller to abort. */ addrSetAbort = sqlite3VdbeCurrentAddr(v); sqlite3VdbeAddOp(v, OP_MemIncr, iAbortFlag, 0); sqlite3VdbeAddOp(v, OP_Return, 0, 0); addrOutputRow = sqlite3VdbeCurrentAddr(v); sqlite3VdbeAddOp(v, OP_IfMemPos, iUseFlag, addrOutputRow+2); sqlite3VdbeAddOp(v, OP_Return, 0, 0); finalizeAggFunctions(pParse, &sAggInfo); if( pHaving ){ sqlite3ExprIfFalse(pParse, pHaving, addrOutputRow+1, 1); } rc = selectInnerLoop(pParse, p, p->pEList, 0, 0, pOrderBy, distinct, eDest, iParm, addrOutputRow+1, addrSetAbort, aff); if( rc ){ goto select_end; } sqlite3VdbeAddOp(v, OP_Return, 0, 0); /* Begin a loop that will extract all source rows in GROUP BY order. ** This might involve two separate loops with an OP_Sort in between, or ** it might be a single loop that uses an index to extract information ** in the right order to begin with. */ sqlite3VdbeResolveLabel(v, addrInitializeLoop); pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pGroupBy); if( pGroupBy==0 ){ /* The optimizer is able to deliver rows in group by order so ** we do not have to sort. The OP_OpenVirtual table will be ** cancelled later because we still need to use the pKeyInfo */ pGroupBy = p->pGroupBy; groupBySort = 0; }else{ /* Rows are coming out in undetermined order. We have to push ** each row into a sorting index, terminate the first loop, ** then loop over the sorting index in order to get the output ** in sorted order */ groupBySort = 1; sqlite3ExprCodeExprList(pParse, pGroupBy); sqlite3VdbeAddOp(v, OP_Sequence, sAggInfo.sortingIdx, 0); j = pGroupBy->nExpr+1; for(i=0; i<sAggInfo.nColumn; i++){ struct AggInfo_col *pCol = &sAggInfo.aCol[i]; if( pCol->iSorterColumn<j ) continue; if( pCol->iColumn<0 ){ sqlite3VdbeAddOp(v, OP_Rowid, pCol->iTable, 0); }else{ sqlite3VdbeAddOp(v, OP_Column, pCol->iTable, pCol->iColumn); } j++; } sqlite3VdbeAddOp(v, OP_MakeRecord, j, 0); sqlite3VdbeAddOp(v, OP_IdxInsert, sAggInfo.sortingIdx, 0); sqlite3WhereEnd(pWInfo); sqlite3VdbeAddOp(v, OP_Sort, sAggInfo.sortingIdx, 0); sAggInfo.useSortingIdx = 1; } /* Evaluate the current GROUP BY terms and store in b0, b1, b2... ** (b0 is memory location iBMem+0, b1 is iBMem+1, and so forth) ** Then compare the current GROUP BY terms against the GROUP BY terms ** from the previous row currently stored in a0, a1, a2... */ addrTopOfLoop = sqlite3VdbeCurrentAddr(v); for(j=0; j<pGroupBy->nExpr; j++){ if( groupBySort ){ sqlite3VdbeAddOp(v, OP_Column, sAggInfo.sortingIdx, j); }else{ sAggInfo.directMode = 1; sqlite3ExprCode(pParse, pGroupBy->a[j].pExpr); } sqlite3VdbeAddOp(v, OP_MemStore, iBMem+j, j<pGroupBy->nExpr-1); } for(j=pGroupBy->nExpr-1; j>=0; j--){ if( j<pGroupBy->nExpr-1 ){ sqlite3VdbeAddOp(v, OP_MemLoad, iBMem+j, 0); } sqlite3VdbeAddOp(v, OP_MemLoad, iAMem+j, 0); if( j==0 ){ sqlite3VdbeAddOp(v, OP_Eq, 0, addrProcessRow); }else{ sqlite3VdbeAddOp(v, OP_Ne, 0x100, addrGroupByChange); } sqlite3VdbeChangeP3(v, -1, (void*)pKeyInfo->aColl[j], P3_COLLSEQ); } /* Generate code that runs whenever the GROUP BY changes. ** Change in the GROUP BY are detected by the previous code ** block. If there were no changes, this block is skipped. ** ** This code copies current group by terms in b0,b1,b2,... ** over to a0,a1,a2. It then calls the output subroutine ** and resets the aggregate accumulator registers in preparation ** for the next GROUP BY batch. */ sqlite3VdbeResolveLabel(v, addrGroupByChange); for(j=0; j<pGroupBy->nExpr; j++){ sqlite3VdbeAddOp(v, OP_MemLoad, iBMem+j, 0); sqlite3VdbeAddOp(v, OP_MemStore, iAMem+j, 1); } sqlite3VdbeAddOp(v, OP_Gosub, 0, addrOutputRow); sqlite3VdbeAddOp(v, OP_IfMemPos, iAbortFlag, addrEnd); resetAccumulator(pParse, &sAggInfo); /* Update the aggregate accumulators based on the content of ** the current row */ sqlite3VdbeResolveLabel(v, addrProcessRow); updateAccumulator(pParse, &sAggInfo); sqlite3VdbeAddOp(v, OP_MemIncr, iUseFlag, 0); /* End of the loop */ if( groupBySort ){ sqlite3VdbeAddOp(v, OP_Next, sAggInfo.sortingIdx, addrTopOfLoop); }else{ sqlite3WhereEnd(pWInfo); uncreateSortingIndex(pParse, addrSortingIdx); } /* Output the final row of result */ sqlite3VdbeAddOp(v, OP_Gosub, 0, addrOutputRow); } /* endif pGroupBy */ else { /* This case runs if the aggregate has no GROUP BY clause. The ** processing is much simpler since there is only a single row ** of output. */ resetAccumulator(pParse, &sAggInfo); pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0); updateAccumulator(pParse, &sAggInfo); sqlite3WhereEnd(pWInfo); finalizeAggFunctions(pParse, &sAggInfo); pOrderBy = 0; selectInnerLoop(pParse, p, p->pEList, 0, 0, 0, -1, eDest, iParm, addrEnd, addrEnd, aff); } sqlite3VdbeResolveLabel(v, addrEnd); } /* endif aggregate query */ /* 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 ){ generateSortTail(pParse, p, v, pEList->nExpr, eDest, iParm); } |
︙ | ︙ | |||
2836 2837 2838 2839 2840 2841 2842 | */ rc = 0; /* Control jumps to here if an error is encountered above, or upon ** successful coding of the SELECT. */ select_end: | | > | 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 | */ rc = 0; /* Control jumps to here if an error is encountered above, or upon ** successful coding of the SELECT. */ select_end: sqliteFree(sAggInfo.aCol); sqliteFree(sAggInfo.aFunc); return rc; } |
Changes to src/sqliteInt.h.
1 2 3 4 5 6 7 8 9 10 11 12 13 | /* ** 2001 September 15 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** Internal interface definitions for SQLite. ** | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | /* ** 2001 September 15 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** Internal interface definitions for SQLite. ** ** @(#) $Id: sqliteInt.h,v 1.408 2005/09/07 21:22:47 drh Exp $ */ #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ /* ** These #defines should enable >2GB file support on Posix if the ** underlying operating system supports it. If the OS lacks |
︙ | ︙ | |||
294 295 296 297 298 299 300 | ** an array. */ #define ArraySize(X) (sizeof(X)/sizeof(X[0])) /* ** Forward references to structures */ | | | 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 | ** an array. */ #define ArraySize(X) (sizeof(X)/sizeof(X[0])) /* ** Forward references to structures */ typedef struct AggInfo AggInfo; typedef struct AuthContext AuthContext; typedef struct CollSeq CollSeq; typedef struct Column Column; typedef struct Db Db; typedef struct Expr Expr; typedef struct ExprList ExprList; typedef struct FKey FKey; |
︙ | ︙ | |||
784 785 786 787 788 789 790 791 792 793 794 795 796 797 | */ struct Token { const unsigned char *z; /* Text of the token. Not NULL-terminated! */ unsigned dyn : 1; /* True for malloced memory, false for static */ unsigned n : 31; /* Number of characters in this token */ }; /* ** Each node of an expression in the parse tree is an instance ** of this structure. ** ** Expr.op is the opcode. The integer parser token codes are reused ** as opcodes here. For example, the parser defines TK_GE to be an integer ** code representing the ">=" operator. This same integer code is reused | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 | */ struct Token { const unsigned char *z; /* Text of the token. Not NULL-terminated! */ unsigned dyn : 1; /* True for malloced memory, false for static */ unsigned n : 31; /* Number of characters in this token */ }; /* ** An instance of this structure contains information needed to generate ** code for a SELECT that contains aggregate functions. ** ** If Expr.op==TK_AGG_COLUMN or TK_AGG_FUNCTION then Expr.pAggInfo is a ** pointer to this structure. The Expr.iColumn field is the index in ** AggInfo.aCol[] or AggInfo.aFunc[] of information needed to generate ** code for that node. ** ** AggInfo.pGroupBy and AggInfo.aFunc.pExpr point to fields within the ** original Select structure that describes the SELECT statement. These ** fields do not need to be freed when deallocating the AggInfo structure. */ struct AggInfo { u8 directMode; /* Direct rendering mode means take data directly ** from source tables rather than from accumulators */ u8 useSortingIdx; /* In direct mode, reference the sorting index rather ** than the source table */ int sortingIdx; /* Cursor number of the sorting index */ ExprList *pGroupBy; /* The group by clause */ int nSortingColumn; /* Number of columns in the sorting index */ struct AggInfo_col { /* For each column used in source tables */ int iTable; /* Cursor number of the source table */ int iColumn; /* Column number within the source table */ int iSorterColumn; /* Column number in the sorting index */ int iMem; /* Memory location that acts as accumulator */ } *aCol; int nColumn; /* Number of used entries in aCol[] */ int nColumnAlloc; /* Number of slots allocated for aCol[] */ int nAccumulator; /* Number of columns that show through to the output. ** Additional columns are used only as parameters to ** aggregate functions */ struct AggInfo_func { /* For each aggregate function */ Expr *pExpr; /* Expression encoding the function */ FuncDef *pFunc; /* The aggregate function implementation */ int iMem; /* Memory location that acts as accumulator */ } *aFunc; int nFunc; /* Number of entries in aFunc[] */ int nFuncAlloc; /* Number of slots allocated for aFunc[] */ }; /* ** Each node of an expression in the parse tree is an instance ** of this structure. ** ** Expr.op is the opcode. The integer parser token codes are reused ** as opcodes here. For example, the parser defines TK_GE to be an integer ** code representing the ">=" operator. This same integer code is reused |
︙ | ︙ | |||
843 844 845 846 847 848 849 | Expr *pLeft, *pRight; /* Left and right subnodes */ ExprList *pList; /* A list of expressions used as function arguments ** or in "<expr> IN (<expr-list)" */ Token token; /* An operand token */ Token span; /* Complete text of the expression */ int iTable, iColumn; /* When op==TK_COLUMN, then this expr node means the ** iColumn-th field of the iTable-th table. */ | > | < < | 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 | Expr *pLeft, *pRight; /* Left and right subnodes */ ExprList *pList; /* A list of expressions used as function arguments ** or in "<expr> IN (<expr-list)" */ Token token; /* An operand token */ Token span; /* Complete text of the expression */ int iTable, iColumn; /* When op==TK_COLUMN, then this expr node means the ** iColumn-th field of the iTable-th table. */ AggInfo *pAggInfo; /* Used by TK_AGG_COLUMN and TK_AGG_FUNCTION */ int iAgg; /* Which entry in pAggInfo->aCol[] or ->aFunc[] */ Select *pSelect; /* When the expression is a sub-select. Also the ** right side of "<expr> IN (<select>)" */ Table *pTab; /* Table for OP_Column expressions. */ }; /* ** The following are the meanings of bits in the Expr.flags field. |
︙ | ︙ | |||
908 909 910 911 912 913 914 | ** column names after a table name in an INSERT statement. In the statement ** ** INSERT INTO t(a,b,c) ... ** ** If "a" is the k-th column of table "t", then IdList.a[0].idx==k. */ struct IdList { | < < > > | 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 | ** column names after a table name in an INSERT statement. In the statement ** ** INSERT INTO t(a,b,c) ... ** ** If "a" is the k-th column of table "t", then IdList.a[0].idx==k. */ struct IdList { struct IdList_item { char *zName; /* Name of the identifier */ int idx; /* Index in some Table.aCol[] of a column named zName */ } *a; int nId; /* Number of identifiers on the list */ int nAlloc; /* Number of entries allocated for a[] below */ }; /* ** The bitmask datatype defined below is used for various optimizations. */ typedef unsigned int Bitmask; |
︙ | ︙ | |||
1027 1028 1029 1030 1031 1032 1033 | struct NameContext { Parse *pParse; /* The parser */ SrcList *pSrcList; /* One or more tables used to resolve names */ ExprList *pEList; /* Optional list of named expressions */ int nRef; /* Number of names resolved by this context */ int nErr; /* Number of errors encountered while resolving names */ u8 allowAgg; /* Aggregate functions allowed here */ | | > | 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 | struct NameContext { Parse *pParse; /* The parser */ SrcList *pSrcList; /* One or more tables used to resolve names */ ExprList *pEList; /* Optional list of named expressions */ int nRef; /* Number of names resolved by this context */ int nErr; /* Number of errors encountered while resolving names */ u8 allowAgg; /* Aggregate functions allowed here */ u8 hasAgg; /* True if aggregates are seen */ int nDepth; /* Depth of subquery recursion. 1 for no recursion */ AggInfo *pAggInfo; /* Information about aggregates at this level */ NameContext *pNext; /* Next outer name context. NULL for outermost */ }; /* ** An instance of the following structure contains all information ** needed to generate code for a single SELECT statement. ** |
︙ | ︙ | |||
1075 1076 1077 1078 1079 1080 1081 | int iLimit, iOffset; /* Memory registers holding LIMIT & OFFSET counters */ int addrOpenVirt[3]; /* OP_OpenVirtual opcodes related to this select */ }; /* ** The results of a select can be distributed in several ways. */ | > > > > > > > | | | < < | < | | | < < < < < < < < < < < < < < < < < < < < < < < < < < | 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 | int iLimit, iOffset; /* Memory registers holding LIMIT & OFFSET counters */ int addrOpenVirt[3]; /* OP_OpenVirtual opcodes related to this select */ }; /* ** The results of a select can be distributed in several ways. */ #define SRT_Union 1 /* Store result as keys in an index */ #define SRT_Except 2 /* Remove result from a UNION index */ #define SRT_Discard 3 /* Do not save the results anywhere */ /* The ORDER BY clause is ignored for all of the above */ #define IgnorableOrderby(X) (X<=SRT_Discard) #define SRT_Callback 4 /* Invoke a callback with each row of result */ #define SRT_Mem 5 /* Store result in a memory cell */ #define SRT_Set 6 /* Store non-null results as keys in an index */ #define SRT_Table 7 /* Store result as data and add automatic rowid */ #define SRT_TempTable 8 /* Store result in a trasient table */ #define SRT_Sorter 9 /* Store results in the sorter NOT USED */ #define SRT_Subroutine 10 /* Call a subroutine to handle results */ #define SRT_Exists 11 /* Put 0 or 1 in a memory cell */ /* ** An SQL parser context. A copy of this structure is passed through ** the parser and down into all the parser action routine in order to ** carry around information that is global to the entire parse. ** ** The structure is divided into two parts. When the parser and code ** generate call themselves recursively, the first part of the structure ** is constant but the second part is reset at the beginning and end of ** each recursion. */ struct Parse { sqlite3 *db; /* The main database structure */ int rc; /* Return code from execution */ char *zErrMsg; /* An error message */ Vdbe *pVdbe; /* An engine for executing database bytecode */ u8 colNamesSet; /* TRUE after OP_ColumnName has been issued to pVdbe */ u8 nameClash; /* A permanent table name clashes with temp table name */ u8 checkSchema; /* Causes schema cookie check after an error */ u8 nested; /* Number of nested calls to the parser/code generator */ int nErr; /* Number of errors seen */ int nTab; /* Number of previously allocated VDBE cursors */ int nMem; /* Number of memory cells used so far */ int nSet; /* Number of sets used so far */ u32 writeMask; /* Start a write transaction on these databases */ u32 cookieMask; /* Bitmask of schema verified databases */ int cookieGoto; /* Address of OP_Goto to cookie verifier subroutine */ |
︙ | ︙ | |||
1158 1159 1160 1161 1162 1163 1164 | Token sLastToken; /* The last token parsed */ const char *zSql; /* All SQL text */ const char *zTail; /* All SQL text past the last semicolon parsed */ Table *pNewTable; /* A table being constructed by CREATE TABLE */ Trigger *pNewTrigger; /* Trigger under construct by a CREATE TRIGGER */ TriggerStack *trigStack; /* Trigger actions being coded */ const char *zAuthContext; /* The 6th parameter to db->xAuth callbacks */ | < < < | 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 | Token sLastToken; /* The last token parsed */ const char *zSql; /* All SQL text */ const char *zTail; /* All SQL text past the last semicolon parsed */ Table *pNewTable; /* A table being constructed by CREATE TABLE */ Trigger *pNewTrigger; /* Trigger under construct by a CREATE TRIGGER */ TriggerStack *trigStack; /* Trigger actions being coded */ const char *zAuthContext; /* The 6th parameter to db->xAuth callbacks */ }; /* ** An instance of the following structure can be declared on a stack and used ** to save the Parse.zAuthContext value so that it can be restored later. */ struct AuthContext { |
︙ | ︙ | |||
1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 | #else # define sqlite3ViewGetColumnNames(A,B) 0 #endif void sqlite3DropTable(Parse*, SrcList*, int); void sqlite3DeleteTable(sqlite3*, Table*); void sqlite3Insert(Parse*, SrcList*, ExprList*, Select*, IdList*, int); IdList *sqlite3IdListAppend(IdList*, Token*); int sqlite3IdListIndex(IdList*,const char*); SrcList *sqlite3SrcListAppend(SrcList*, Token*, Token*); void sqlite3SrcListAddAlias(SrcList*, Token*); void sqlite3SrcListAssignCursors(Parse*, SrcList*); void sqlite3IdListDelete(IdList*); void sqlite3SrcListDelete(SrcList*); | > | 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 | #else # define sqlite3ViewGetColumnNames(A,B) 0 #endif void sqlite3DropTable(Parse*, SrcList*, int); void sqlite3DeleteTable(sqlite3*, Table*); void sqlite3Insert(Parse*, SrcList*, ExprList*, Select*, IdList*, int); int sqlite3ArrayAllocate(void**,int,int); IdList *sqlite3IdListAppend(IdList*, Token*); int sqlite3IdListIndex(IdList*,const char*); SrcList *sqlite3SrcListAppend(SrcList*, Token*, Token*); void sqlite3SrcListAddAlias(SrcList*, Token*); void sqlite3SrcListAssignCursors(Parse*, SrcList*); void sqlite3IdListDelete(IdList*); void sqlite3SrcListDelete(SrcList*); |
︙ | ︙ |
Changes to src/vdbe.c.
︙ | ︙ | |||
39 40 41 42 43 44 45 | ** ** Various scripts scan this source file in order to generate HTML ** documentation, headers files, or other derived files. The formatting ** of the code in this file is, therefore, important. See other comments ** in this file for details. If in doubt, do not deviate from existing ** commenting and indentation practices when changing or adding code. ** | | | 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | ** ** Various scripts scan this source file in order to generate HTML ** documentation, headers files, or other derived files. The formatting ** of the code in this file is, therefore, important. See other comments ** in this file for details. If in doubt, do not deviate from existing ** commenting and indentation practices when changing or adding code. ** ** $Id: vdbe.c,v 1.482 2005/09/07 21:22:47 drh Exp $ */ #include "sqliteInt.h" #include "os.h" #include <ctype.h> #include "vdbeInt.h" /* |
︙ | ︙ | |||
156 157 158 159 160 161 162 | else if( flags & MEM_Str ){ pMem->type = SQLITE_TEXT; }else{ pMem->type = SQLITE_BLOB; } } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 156 157 158 159 160 161 162 163 164 165 166 167 168 169 | else if( flags & MEM_Str ){ pMem->type = SQLITE_TEXT; }else{ pMem->type = SQLITE_BLOB; } } /* ** Pop the stack N times. */ static void popStack(Mem **ppTos, int N){ Mem *pTos = *ppTos; while( N>0 ){ N--; |
︙ | ︙ | |||
1127 1128 1129 1130 1131 1132 1133 | assert( pOp->p3type==P3_COLLSEQ ); break; } /* Opcode: Function P1 P2 P3 ** ** Invoke a user function (P3 is a pointer to a Function structure that | | | | | | < | 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 | assert( pOp->p3type==P3_COLLSEQ ); break; } /* Opcode: Function P1 P2 P3 ** ** Invoke a user function (P3 is a pointer to a Function structure that ** defines the function) with P2 arguments taken from the stack. Pop all ** arguments from the stack and push back the result. ** ** P1 is a 32-bit bitmask indicating whether or not each argument to the ** function was determined to be constant at compile time. If the first ** argument was constant then bit 0 of P1 is set. This is used to determine ** whether meta data associated with a user function argument using the ** sqlite3_set_auxdata() API may be safely retained until the next ** invocation of this opcode. ** ** See also: AggStep and AggFinal */ case OP_Function: { int i; Mem *pArg; sqlite3_context ctx; sqlite3_value **apVal; int n = pOp->p2; apVal = p->apArg; assert( apVal || n==0 ); pArg = &pTos[1-n]; for(i=0; i<n; i++, pArg++){ apVal[i] = pArg; storeTypeInfo(pArg, db->enc); |
︙ | ︙ | |||
1185 1186 1187 1188 1189 1190 1191 | if( sqlite3_malloc_failed ) goto no_mem; popStack(&pTos, n); /* If any auxilary data functions have been called by this user function, ** immediately call the destructor for any non-static values. */ if( ctx.pVdbeFunc ){ | | | 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 | if( sqlite3_malloc_failed ) goto no_mem; popStack(&pTos, n); /* If any auxilary data functions have been called by this user function, ** immediately call the destructor for any non-static values. */ if( ctx.pVdbeFunc ){ sqlite3VdbeDeleteAuxData(ctx.pVdbeFunc, pOp->p1); pOp->p3 = (char *)ctx.pVdbeFunc; pOp->p3type = P3_VDBEFUNC; } /* Copy the result of the function to the top of the stack */ sqlite3VdbeChangeEncoding(&ctx.s, db->enc); pTos++; |
︙ | ︙ | |||
4024 4025 4026 4027 4028 4029 4030 | pTos++; pTos->i = v; pTos->flags = MEM_Int; } break; } | < < < < < < < < < < < < < < < < < < < < < < < < < | 3991 3992 3993 3994 3995 3996 3997 3998 3999 4000 4001 4002 4003 4004 | pTos++; pTos->i = v; pTos->flags = MEM_Int; } break; } #ifndef SQLITE_OMIT_TRIGGER /* Opcode: ContextPush * * * ** ** Save the current Vdbe context such that it can be restored by a ContextPop ** opcode. The context stores the last insert row id, the last statement change ** count, and the current statement change count. */ |
︙ | ︙ | |||
4195 4196 4197 4198 4199 4200 4201 | assert( pMem->flags==MEM_Int ); if( pMem->i>0 ){ pc = pOp->p2 - 1; } break; } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | > < < < | | < | < < < < > | | | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | < < < < < < < < < < < < < < < < | < < < < < < < < < < < | | < < | < < < < < < < < < < < < < < < < < | < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 4137 4138 4139 4140 4141 4142 4143 4144 4145 4146 4147 4148 4149 4150 4151 4152 4153 4154 4155 4156 4157 4158 4159 4160 4161 4162 4163 4164 4165 4166 4167 4168 4169 4170 4171 4172 4173 4174 4175 4176 4177 4178 4179 4180 4181 4182 4183 4184 4185 4186 4187 4188 4189 4190 4191 4192 4193 4194 4195 4196 4197 4198 4199 4200 4201 4202 4203 4204 4205 4206 4207 4208 | assert( pMem->flags==MEM_Int ); if( pMem->i>0 ){ pc = pOp->p2 - 1; } break; } /* Opcode: AggStep P1 P2 P3 ** ** Execute the step function for an aggregate. The ** function has P2 arguments. P3 is a pointer to the FuncDef ** structure that specifies the function. Use memory location ** P1 as the accumulator. ** ** The P2 arguments are popped from the stack. */ case OP_AggStep: { /* no-push */ int n = pOp->p2; int i; Mem *pMem, *pRec; sqlite3_context ctx; sqlite3_value **apVal; assert( n>=0 ); pRec = &pTos[1-n]; assert( pRec>=p->aStack ); apVal = p->apArg; assert( apVal || n==0 ); for(i=0; i<n; i++, pRec++){ apVal[i] = pRec; storeTypeInfo(pRec, db->enc); } ctx.pFunc = (FuncDef*)pOp->p3; assert( pOp->p1>=0 && pOp->p1<p->nMem ); ctx.pMem = pMem = &p->aMem[pOp->p1]; pMem->n++; ctx.isError = 0; ctx.pColl = 0; if( ctx.pFunc->needCollSeq ){ assert( pOp>p->aOp ); assert( pOp[-1].p3type==P3_COLLSEQ ); assert( pOp[-1].opcode==OP_CollSeq ); ctx.pColl = (CollSeq *)pOp[-1].p3; } (ctx.pFunc->xStep)(&ctx, n, apVal); popStack(&pTos, n); if( ctx.isError ){ rc = SQLITE_ERROR; } break; } /* Opcode: AggFinal P1 * * ** ** Execute the finalizer function for an aggregate. P1 is ** the memory location that is the accumulator for the aggregate. */ case OP_AggFinal: { /* no-push */ Mem *pMem; assert( pOp->p1>=0 && pOp->p1<p->nMem ); pMem = &p->aMem[pOp->p1]; sqlite3VdbeMemFinalize(pMem); break; } /* Opcode: Vacuum * * * ** ** Vacuum the entire database. This opcode will cause other virtual ** machines to be created and run. It may not be called from within ** a transaction. */ |
︙ | ︙ |
Changes to src/vdbe.h.
︙ | ︙ | |||
11 12 13 14 15 16 17 | ************************************************************************* ** Header file for the Virtual DataBase Engine (VDBE) ** ** This header defines the interface to the virtual database engine ** or VDBE. The VDBE implements an abstract machine that runs a ** simple program to access and modify the underlying database. ** | | | 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | ************************************************************************* ** Header file for the Virtual DataBase Engine (VDBE) ** ** This header defines the interface to the virtual database engine ** or VDBE. The VDBE implements an abstract machine that runs a ** simple program to access and modify the underlying database. ** ** $Id: vdbe.h,v 1.98 2005/09/07 21:22:47 drh Exp $ */ #ifndef _SQLITE_VDBE_H_ #define _SQLITE_VDBE_H_ #include <stdio.h> /* ** A single VDBE is an opaque structure named "Vdbe". Only routines |
︙ | ︙ | |||
104 105 106 107 108 109 110 | int sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp); void sqlite3VdbeChangeP1(Vdbe*, int addr, int P1); void sqlite3VdbeChangeP2(Vdbe*, int addr, int P2); void sqlite3VdbeChangeP3(Vdbe*, int addr, const char *zP1, int N); VdbeOp *sqlite3VdbeGetOp(Vdbe*, int); int sqlite3VdbeMakeLabel(Vdbe*); void sqlite3VdbeDelete(Vdbe*); | | | 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 | int sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp); void sqlite3VdbeChangeP1(Vdbe*, int addr, int P1); void sqlite3VdbeChangeP2(Vdbe*, int addr, int P2); void sqlite3VdbeChangeP3(Vdbe*, int addr, const char *zP1, int N); VdbeOp *sqlite3VdbeGetOp(Vdbe*, int); int sqlite3VdbeMakeLabel(Vdbe*); void sqlite3VdbeDelete(Vdbe*); void sqlite3VdbeMakeReady(Vdbe*,int,int,int,int); int sqlite3VdbeFinalize(Vdbe*); void sqlite3VdbeResolveLabel(Vdbe*, int); int sqlite3VdbeCurrentAddr(Vdbe*); void sqlite3VdbeTrace(Vdbe*,FILE*); int sqlite3VdbeReset(Vdbe*); int sqliteVdbeSetVariables(Vdbe*,int,const char**); void sqlite3VdbeSetNumCols(Vdbe*,int); |
︙ | ︙ |
Changes to src/vdbeInt.h.
︙ | ︙ | |||
197 198 199 200 201 202 203 | VdbeFunc *pVdbeFunc; /* Auxilary data, if created. */ Mem s; /* The return value is stored here */ Mem *pMem; /* Memory cell used to store aggregate context */ u8 isError; /* Set to true for an error */ CollSeq *pColl; /* Collating sequence */ }; | < < < < < < < < < < < < < < < < < < < < < < < < | 197 198 199 200 201 202 203 204 205 206 207 208 209 210 | VdbeFunc *pVdbeFunc; /* Auxilary data, if created. */ Mem s; /* The return value is stored here */ Mem *pMem; /* Memory cell used to store aggregate context */ u8 isError; /* Set to true for an error */ CollSeq *pColl; /* Collating sequence */ }; /* ** A Set structure is used for quick testing to see if a value ** is part of a small set. Sets are used to implement code like ** this: ** x.y IN ('hi','hoo','hum') */ typedef struct Set Set; |
︙ | ︙ | |||
305 306 307 308 309 310 311 | int nVar; /* Number of entries in aVar[] */ Mem *aVar; /* Values for the OP_Variable opcode. */ char **azVar; /* Name of variables */ int okVar; /* True if azVar[] has been initialized */ int magic; /* Magic number for sanity checking */ int nMem; /* Number of memory locations currently allocated */ Mem *aMem; /* The memory locations */ | < < < | 281 282 283 284 285 286 287 288 289 290 291 292 293 294 | int nVar; /* Number of entries in aVar[] */ Mem *aVar; /* Values for the OP_Variable opcode. */ char **azVar; /* Name of variables */ int okVar; /* True if azVar[] has been initialized */ int magic; /* Magic number for sanity checking */ int nMem; /* Number of memory locations currently allocated */ Mem *aMem; /* The memory locations */ int nCallback; /* Number of callbacks invoked so far */ Fifo sFifo; /* A list of ROWIDs */ int contextStackTop; /* Index of top element in the context stack */ int contextStackDepth; /* The size of the "context" stack */ Context *contextStack; /* Stack used by opcodes ContextPush & ContextPop*/ int pc; /* The program counter */ int rc; /* Value to return */ |
︙ | ︙ | |||
345 346 347 348 349 350 351 | #define VDBE_MAGIC_HALT 0x519c2973 /* VDBE has completed execution */ #define VDBE_MAGIC_DEAD 0xb606c3c8 /* The VDBE has been deallocated */ /* ** Function prototypes */ void sqlite3VdbeFreeCursor(Cursor*); | < | 318 319 320 321 322 323 324 325 326 327 328 329 330 331 | #define VDBE_MAGIC_HALT 0x519c2973 /* VDBE has completed execution */ #define VDBE_MAGIC_DEAD 0xb606c3c8 /* The VDBE has been deallocated */ /* ** Function prototypes */ void sqlite3VdbeFreeCursor(Cursor*); void sqliteVdbePopStack(Vdbe*,int); int sqlite3VdbeCursorMoveto(Cursor*); #if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE) void sqlite3VdbePrintOp(FILE*, int, Op*); #endif #ifdef SQLITE_DEBUG void sqlite3VdbePrintSql(Vdbe*); |
︙ | ︙ | |||
387 388 389 390 391 392 393 | int sqlite3VdbeMemStringify(Mem*, int); i64 sqlite3VdbeIntValue(Mem*); int sqlite3VdbeMemIntegerify(Mem*); double sqlite3VdbeRealValue(Mem*); int sqlite3VdbeMemRealify(Mem*); int sqlite3VdbeMemFromBtree(BtCursor*,int,int,int,Mem*); void sqlite3VdbeMemRelease(Mem *p); | | | 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 | int sqlite3VdbeMemStringify(Mem*, int); i64 sqlite3VdbeIntValue(Mem*); int sqlite3VdbeMemIntegerify(Mem*); double sqlite3VdbeRealValue(Mem*); int sqlite3VdbeMemRealify(Mem*); int sqlite3VdbeMemFromBtree(BtCursor*,int,int,int,Mem*); void sqlite3VdbeMemRelease(Mem *p); void sqlite3VdbeMemFinalize(Mem*); #ifndef NDEBUG void sqlite3VdbeMemSanity(Mem*, u8); int sqlite3VdbeOpcodeNoPush(u8); #endif int sqlite3VdbeMemTranslate(Mem*, u8); void sqlite3VdbeMemPrettyPrint(Mem *pMem, char *zBuf, int nBuf); int sqlite3VdbeMemHandleBom(Mem *pMem); void sqlite3VdbeFifoInit(Fifo*); int sqlite3VdbeFifoPush(Fifo*, i64); int sqlite3VdbeFifoPop(Fifo*, i64*); void sqlite3VdbeFifoClear(Fifo*); |
Changes to src/vdbeaux.c.
︙ | ︙ | |||
211 212 213 214 215 216 217 | /* ** Loop through the program looking for P2 values that are negative. ** Each such value is a label. Resolve the label by setting the P2 ** value to its correct non-zero value. ** ** This routine is called once after all opcodes have been inserted. ** | | | | 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 | /* ** Loop through the program looking for P2 values that are negative. ** Each such value is a label. Resolve the label by setting the P2 ** value to its correct non-zero value. ** ** This routine is called once after all opcodes have been inserted. ** ** Variable *pMaxFuncArgs is set to the maximum value of any P2 argument ** to an OP_Function or OP_AggStep opcode. This is used by ** sqlite3VdbeMakeReady() to size the Vdbe.apArg[] array. ** ** The integer *pMaxStack is set to the maximum number of vdbe stack ** entries that static analysis reveals this program might need. ** ** This routine also does the following optimization: It scans for ** Halt instructions where P1==SQLITE_CONSTRAINT or P2==OE_Abort or for |
︙ | ︙ | |||
235 236 237 238 239 240 241 | Op *pOp; int *aLabel = p->aLabel; int doesStatementRollback = 0; int hasStatementBegin = 0; for(pOp=p->aOp, i=p->nOp-1; i>=0; i--, pOp++){ u8 opcode = pOp->opcode; | < < < | < < | 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 | Op *pOp; int *aLabel = p->aLabel; int doesStatementRollback = 0; int hasStatementBegin = 0; for(pOp=p->aOp, i=p->nOp-1; i>=0; i--, pOp++){ u8 opcode = pOp->opcode; if( opcode==OP_Function || opcode==OP_AggStep ){ if( pOp->p2>nMaxArgs ) nMaxArgs = pOp->p2; }else if( opcode==OP_Halt ){ if( pOp->p1==SQLITE_CONSTRAINT && pOp->p2==OE_Abort ){ doesStatementRollback = 1; } }else if( opcode==OP_IdxInsert ){ if( pOp->p2 ){ |
︙ | ︙ | |||
659 660 661 662 663 664 665 | ** VDBE_MAGIC_RUN. */ void sqlite3VdbeMakeReady( Vdbe *p, /* The VDBE */ int nVar, /* Number of '?' see in the SQL statement */ int nMem, /* Number of memory cells to allocate */ int nCursor, /* Number of cursors to allocate */ | < | 654 655 656 657 658 659 660 661 662 663 664 665 666 667 | ** VDBE_MAGIC_RUN. */ void sqlite3VdbeMakeReady( Vdbe *p, /* The VDBE */ int nVar, /* Number of '?' see in the SQL statement */ int nMem, /* Number of memory cells to allocate */ int nCursor, /* Number of cursors to allocate */ int isExplain /* True if the EXPLAIN keywords is present */ ){ int n; assert( p!=0 ); assert( p->magic==VDBE_MAGIC_INIT ); |
︙ | ︙ | |||
702 703 704 705 706 707 708 | p->aStack = sqliteMalloc( nStack*sizeof(p->aStack[0]) /* aStack */ + nArg*sizeof(Mem*) /* apArg */ + nVar*sizeof(Mem) /* aVar */ + nVar*sizeof(char*) /* azVar */ + nMem*sizeof(Mem) /* aMem */ + nCursor*sizeof(Cursor*) /* apCsr */ | < < < < < < | 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 | p->aStack = sqliteMalloc( nStack*sizeof(p->aStack[0]) /* aStack */ + nArg*sizeof(Mem*) /* apArg */ + nVar*sizeof(Mem) /* aVar */ + nVar*sizeof(char*) /* azVar */ + nMem*sizeof(Mem) /* aMem */ + nCursor*sizeof(Cursor*) /* apCsr */ ); if( !sqlite3_malloc_failed ){ p->aMem = &p->aStack[nStack]; p->nMem = nMem; p->aVar = &p->aMem[nMem]; p->nVar = nVar; p->okVar = 0; p->apArg = (Mem**)&p->aVar[nVar]; p->azVar = (char**)&p->apArg[nArg]; p->apCsr = (Cursor**)&p->azVar[nVar]; p->nCursor = nCursor; for(n=0; n<nVar; n++){ p->aVar[n].flags = MEM_Null; } } } for(n=0; n<p->nMem; n++){ p->aMem[n].flags = MEM_Null; } #ifdef SQLITE_DEBUG if( (p->db->flags & SQLITE_VdbeListing)!=0 || sqlite3OsFileExists("vdbe_explain") |
︙ | ︙ | |||
764 765 766 767 768 769 770 | p->aOp[i].cnt = 0; p->aOp[i].cycles = 0; } } #endif } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 752 753 754 755 756 757 758 759 760 761 762 763 764 765 | p->aOp[i].cnt = 0; p->aOp[i].cycles = 0; } } #endif } /* ** Close a cursor and release all the resources that cursor happens ** to hold. */ void sqlite3VdbeFreeCursor(Cursor *pCx){ if( pCx==0 ){ return; |
︙ | ︙ | |||
940 941 942 943 944 945 946 | sqlite3VdbeFifoClear(&p->sFifo); if( p->contextStack ){ for(i=0; i<p->contextStackTop; i++){ sqlite3VdbeFifoClear(&p->contextStack[i].sFifo); } sqliteFree(p->contextStack); } | < < < | 805 806 807 808 809 810 811 812 813 814 815 816 817 818 | sqlite3VdbeFifoClear(&p->sFifo); if( p->contextStack ){ for(i=0; i<p->contextStackTop; i++){ sqlite3VdbeFifoClear(&p->contextStack[i].sFifo); } sqliteFree(p->contextStack); } p->contextStack = 0; p->contextStackDepth = 0; p->contextStackTop = 0; sqliteFree(p->zErrMsg); p->zErrMsg = 0; } |
︙ | ︙ |
Changes to src/vdbemem.c.
︙ | ︙ | |||
188 189 190 191 192 193 194 | } /* ** Memory cell pMem contains the context of an aggregate function. ** This routine calls the finalize method for that function. The ** result of the aggregate is stored back into pMem. */ | | > > | | | | | | | | | | | | | > | | 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 | } /* ** Memory cell pMem contains the context of an aggregate function. ** This routine calls the finalize method for that function. The ** result of the aggregate is stored back into pMem. */ void sqlite3VdbeMemFinalize(Mem *pMem){ if( pMem->flags & MEM_Agg ){ FuncDef *pFunc = *(FuncDef**)&pMem->i; if( pFunc && pFunc->xFinalize ){ sqlite3_context ctx; ctx.s.flags = MEM_Null; ctx.s.z = pMem->zShort; ctx.pMem = pMem; ctx.pFunc = pFunc; pFunc->xFinalize(&ctx); if( pMem->z && pMem->z!=pMem->zShort ){ sqliteFree( pMem->z ); } *pMem = ctx.s; if( pMem->flags & MEM_Short ){ pMem->z = pMem->zShort; } } } } /* ** Release any memory held by the Mem. This may leave the Mem in an ** inconsistent state, for example with (Mem.z==0) and ** (Mem.type==SQLITE_TEXT). */ void sqlite3VdbeMemRelease(Mem *p){ if( p->flags & (MEM_Dyn|MEM_Agg) ){ if( p->xDel ){ if( p->flags & MEM_Agg ){ sqlite3VdbeMemFinalize(p); assert( (p->flags & MEM_Agg)==0 ); sqlite3VdbeMemRelease(p); }else{ p->xDel((void *)p->z); } }else{ sqliteFree(p->z); |
︙ | ︙ |
Changes to test/misc4.test.
︙ | ︙ | |||
9 10 11 12 13 14 15 | # #*********************************************************************** # This file implements regression tests for SQLite library. # # This file implements tests for miscellanous features that were # left out of other test files. # | | | 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | # #*********************************************************************** # This file implements regression tests for SQLite library. # # This file implements tests for miscellanous features that were # left out of other test files. # # $Id: misc4.test,v 1.17 2005/09/07 21:22:47 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl # Prepare a statement that will create a temporary table. Then do # a rollback. Then try to execute the prepared statement. # |
︙ | ︙ | |||
92 93 94 95 96 97 98 | execsql { CREATE TABLE Table1(ID integer primary key, Value TEXT); INSERT INTO Table1 VALUES(1, 'x'); CREATE TABLE Table2(ID integer NOT NULL, Value TEXT); INSERT INTO Table2 VALUES(1, 'z'); INSERT INTO Table2 VALUES (1, 'a'); SELECT ID, Value FROM Table1 | | | 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 | execsql { CREATE TABLE Table1(ID integer primary key, Value TEXT); INSERT INTO Table1 VALUES(1, 'x'); CREATE TABLE Table2(ID integer NOT NULL, Value TEXT); INSERT INTO Table2 VALUES(1, 'z'); INSERT INTO Table2 VALUES (1, 'a'); SELECT ID, Value FROM Table1 UNION SELECT ID, max(Value) FROM Table2 GROUP BY 1 ORDER BY 1, 2; } } {{} {} 1 x 1 z} } ;# ifcapable compound # Ticket #1047. Make sure column types are preserved in subqueries. # |
︙ | ︙ | |||
173 174 175 176 177 178 179 | do_test misc4-6.2 { execsql { SELECT a FROM abc LEFT JOIN def ON (abc.a=def.d); } } {1} finish_test | < | 173 174 175 176 177 178 179 | do_test misc4-6.2 { execsql { SELECT a FROM abc LEFT JOIN def ON (abc.a=def.d); } } {1} finish_test |