Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Progress toward fixing iproblems with compound selects. (CVS 1911) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
307478593d5d96b79386da222c7742ea |
User & Date: | drh 2004-08-29 01:31:05.000 |
Context
2004-08-29
| ||
16:25 | Corrections to transient table handling in compound select statments. Tickets #826 and #875. (CVS 1912) (check-in: 9cc765be46 user: drh tags: trunk) | |
01:31 | Progress toward fixing iproblems with compound selects. (CVS 1911) (check-in: 307478593d user: drh tags: trunk) | |
2004-08-28
| ||
18:21 | Add prototype in sqlite3.h for the sqlite3_libversion() function. (CVS 1910) (check-in: d50c47b499 user: drh tags: trunk) | |
Changes
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.204 2004/08/29 01:31:05 drh Exp $ */ #include "sqliteInt.h" /* ** Allocate a new Select structure and return a pointer to that ** structure. |
︙ | ︙ | |||
1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 | (char*)pKeyInfo, P3_KEYINFO_HANDOFF); if( keyAsData ){ sqlite3VdbeAddOp(v, OP_KeyAsData, iTab, 1); } return addr; } static int multiSelectOpenTempAddr(Select *p, int addr, IdList **ppOpenTemp){ if( !p->ppOpenTemp ){ *ppOpenTemp = sqlite3IdListAppend(0, 0); p->ppOpenTemp = ppOpenTemp; }else{ *p->ppOpenTemp = sqlite3IdListAppend(*p->ppOpenTemp, 0); } | > > > > > > > > > > > > > > > > > | > | > > > > > > > > | > > | | 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 | (char*)pKeyInfo, P3_KEYINFO_HANDOFF); if( keyAsData ){ sqlite3VdbeAddOp(v, OP_KeyAsData, iTab, 1); } return addr; } /* ** FIX ME: ** + Omit the ppOpenTemp parameter from multiSelectOpenTempAddr(). ** + Attach pOpenList to the right-most term always. ** + Make sure Select.ppOpenTemp is initialized to NULL */ /* ** Add the address "addr" to the set of all opcode addresses contained ** in the pOpenTemp list for the whole compound select. If no pOpenTemp ** list has been created yet, then create a new one and make *ppOpenTemp ** point to it. If the pOpenTemp list already exists, leave *ppOpenTemp ** unchanged and just add the new address to the existing list. */ static int multiSelectOpenTempAddr(Select *p, int addr, IdList **ppOpenTemp){ IdList *pList; if( !p->ppOpenTemp ){ /* Create a new list */ *ppOpenTemp = sqlite3IdListAppend(0, 0); p->ppOpenTemp = ppOpenTemp; }else{ /* Add a new element onto the end of the existing list */ *p->ppOpenTemp = sqlite3IdListAppend(*p->ppOpenTemp, 0); } pList = *p->ppOpenTemp; if( pList==0 ){ return SQLITE_NOMEM; } pList->a[pList->nId-1].idx = addr; return SQLITE_OK; } /* ** 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. ** ** The collating sequence for the compound select is taken from the ** left-most term of the select that has a collating sequence. */ static CollSeq *multiSelectCollSeq(Parse *pParse, Select *p, int iCol){ CollSeq *pRet; if( p->pPrior ){ pRet = multiSelectCollSeq(pParse, p->pPrior, iCol); }else{ pRet = 0; } if( pRet==0 ){ pRet = sqlite3ExprCollSeq(pParse, p->pEList->a[iCol].pExpr); } return pRet; } /* ** This routine is called to process a query that is really the union |
︙ | ︙ | |||
1331 1332 1333 1334 1335 1336 1337 | ** So if this routine is called with p equal to the t3 query, then ** pPrior will be the t2 query. p->op will be TK_UNION in this case. ** ** Notice that because of the way SQLite parses compound SELECTs, the ** individual selects always group from left to right. */ static int multiSelect( | | | | | | | | | | | | 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 | ** So if this routine is called with p equal to the t3 query, then ** pPrior will be the t2 query. p->op will be TK_UNION in this case. ** ** Notice that because of the way SQLite parses compound SELECTs, the ** individual selects always group from left to right. */ static int multiSelect( Parse *pParse, /* Parsing context */ Select *p, /* The right-most of SELECTs to be coded */ int eDest, /* \___ Store query results as specified */ int iParm, /* / by these two parameters. */ char *aff /* If eDest is SRT_Union, the affinity string */ ){ int rc = SQLITE_OK; /* Success code from a subroutine */ Select *pPrior; /* Another SELECT immediately to our left */ Vdbe *v; /* Generate code to this VDBE */ IdList *pOpenTemp = 0;/* OP_OpenTemp opcodes that need a KeyInfo */ /* Make sure there is no ORDER BY or LIMIT clause on prior SELECTs. Only ** the last (right-most) SELECT in the series may have an ORDER BY or LIMIT. */ if( p==0 || p->pPrior==0 ){ rc = 1; goto multi_select_end; } pPrior = p->pPrior; if( pPrior->pOrderBy ){ |
︙ | ︙ | |||
1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 | */ v = sqlite3GetVdbe(pParse); if( v==0 ){ rc = 1; goto multi_select_end; } /* Create the destination temporary table if necessary */ if( eDest==SRT_TempTable ){ assert( p->pEList ); sqlite3VdbeAddOp(v, OP_OpenTemp, iParm, 0); sqlite3VdbeAddOp(v, OP_SetNumColumns, iParm, p->pEList->nExpr); eDest = SRT_Table; } /* Generate code for the left and right SELECT statements. */ switch( p->op ){ case TK_ALL: { if( p->pOrderBy==0 ){ pPrior->nLimit = p->nLimit; pPrior->nOffset = p->nOffset; | > > > > > > > > > > > > > > > | | 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 | */ v = sqlite3GetVdbe(pParse); if( v==0 ){ rc = 1; goto multi_select_end; } /* PART OF FIX: */ if( p->ppOpenTemp==0 ){ p->ppOpenTemp = &pOpenTemp; } pPrior->ppOpenTemp = p->ppOpenTemp; /* Create the destination temporary table if necessary */ if( eDest==SRT_TempTable ){ assert( p->pEList ); sqlite3VdbeAddOp(v, OP_OpenTemp, iParm, 0); /* FIX ME: ** p->pEList->nExpr might contain a "*" and so might not be the ** correct number. Go ahead and code the SetNumColumns instruction ** here, but also record its address. Change the P2 value of the ** instruction to the number of columns after sqlite3Select() has ** been called to code the subquery and has modified pEList->nExpr ** to be the correct value. */ sqlite3VdbeAddOp(v, OP_SetNumColumns, iParm, p->pEList->nExpr); eDest = SRT_Table; } /* Generate code for the left and right SELECT statements. */ switch( p->op ){ case TK_ALL: { if( p->pOrderBy==0 ){ pPrior->nLimit = p->nLimit; pPrior->nOffset = p->nOffset; /* pPrior->ppOpenTemp = p->ppOpenTemp; // FIX */ rc = sqlite3Select(pParse, pPrior, eDest, iParm, 0, 0, 0, aff); if( rc ){ goto multi_select_end; } p->pPrior = 0; p->iLimit = pPrior->iLimit; p->iOffset = pPrior->iOffset; |
︙ | ︙ | |||
1444 1445 1446 1447 1448 1449 1450 | sqlite3VdbeAddOp(v, OP_KeyAsData, unionTab, 1); } assert( p->pEList ); } /* Code the SELECT statements to our left */ | | | 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 | sqlite3VdbeAddOp(v, OP_KeyAsData, unionTab, 1); } assert( p->pEList ); } /* Code the SELECT statements to our left */ /* pPrior->ppOpenTemp = p->ppOpenTemp; // FIX */ rc = sqlite3Select(pParse, pPrior, priorOp, unionTab, 0, 0, 0, aff); if( rc ){ goto multi_select_end; } if( p->op==TK_ALL ){ sqlite3VdbeAddOp(v, OP_SetNumColumns, unionTab, pPrior->pEList->nExpr); } |
︙ | ︙ | |||
1532 1533 1534 1535 1536 1537 1538 | goto multi_select_end; } sqlite3VdbeAddOp(v, OP_KeyAsData, tab1, 1); assert( p->pEList ); /* Code the SELECTs to our left into temporary table "tab1". */ | | | 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 | goto multi_select_end; } sqlite3VdbeAddOp(v, OP_KeyAsData, tab1, 1); assert( p->pEList ); /* Code the SELECTs to our left into temporary table "tab1". */ /* pPrior->ppOpenTemp = p->ppOpenTemp; // FIX */ rc = sqlite3Select(pParse, pPrior, SRT_Union, tab1, 0, 0, 0, aff); if( rc ){ goto multi_select_end; } /* Code the current SELECT into temporary table "tab2" */ |
︙ | ︙ | |||
1595 1596 1597 1598 1599 1600 1601 1602 | if( p->pEList->nExpr!=pPrior->pEList->nExpr ){ sqlite3ErrorMsg(pParse, "SELECTs to the left and right of %s" " do not have the same number of result columns", selectOpName(p->op)); rc = 1; goto multi_select_end; } if( p->pOrderBy || (pOpenTemp && pOpenTemp->nId>0) ){ | > > > > > | | > > | | 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 | if( p->pEList->nExpr!=pPrior->pEList->nExpr ){ sqlite3ErrorMsg(pParse, "SELECTs to the left and right of %s" " do not have the same number of result columns", selectOpName(p->op)); rc = 1; goto multi_select_end; } /* Compute collating sequences used by either the ORDER BY clause or ** by any temporary tables needed to implement the compound select. ** Attach the KeyInfo structure to all temporary tables. Invoke the ** ORDER BY processing if there is an ORDER BY clause. */ if( p->pOrderBy || (pOpenTemp && pOpenTemp->nId>0) ){ int nCol = p->pEList->nExpr; /* Number of columns in the result set */ int i; /* Loop counter */ KeyInfo *pKeyInfo; /* Collating sequence for the result set */ pKeyInfo = sqliteMalloc(sizeof(*pKeyInfo)+nCol*sizeof(CollSeq*)); if( !pKeyInfo ){ rc = SQLITE_NOMEM; goto multi_select_end; } pKeyInfo->enc = pParse->db->enc; pKeyInfo->nField = nCol; |
︙ | ︙ | |||
1621 1622 1623 1624 1625 1626 1627 | for(i=0; pOpenTemp && i<pOpenTemp->nId; i++){ int p3type = (i==0?P3_KEYINFO_HANDOFF:P3_KEYINFO); int addr = pOpenTemp->a[i].idx; sqlite3VdbeChangeP3(v, addr, (char *)pKeyInfo, p3type); } if( p->pOrderBy ){ | > | | | | 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 | for(i=0; pOpenTemp && i<pOpenTemp->nId; i++){ int p3type = (i==0?P3_KEYINFO_HANDOFF:P3_KEYINFO); int addr = pOpenTemp->a[i].idx; sqlite3VdbeChangeP3(v, addr, (char *)pKeyInfo, p3type); } if( p->pOrderBy ){ struct ExprList_item *pOrderByTerm = p->pOrderBy->a; for(i=0; i<p->pOrderBy->nExpr; i++, pOrderByTerm++){ Expr *pExpr = pOrderByTerm->pExpr; char *zName = pOrderByTerm->zName; assert( pExpr->op==TK_COLUMN && pExpr->iColumn<nCol ); assert( !pExpr->pColl ); if( zName ){ pExpr->pColl = sqlite3LocateCollSeq(pParse, zName, -1); }else{ pExpr->pColl = pKeyInfo->aColl[pExpr->iColumn]; } |
︙ | ︙ | |||
2314 2315 2316 2317 2318 2319 2320 | /* 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); } | < < | 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 | /* 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); } /* If the destination is SRT_Union, then set the number of columns in ** the records that will be inserted into the temporary table. The caller ** couldn't do this, in case the select statement is of the form ** "SELECT * FROM ....". ** ** We need to do this before we start inserting records into the ** temporary table (which has had OP_KeyAsData executed on it), because ** it is required by the key comparison function. So do it now, even ** though this means that OP_SetNumColumns may be executed on the same ** cursor more than once. */ if( eDest==SRT_Union ){ sqlite3VdbeAddOp(v, OP_SetNumColumns, iParm, pEList->nExpr); } /* Generate code for all sub-queries in the FROM clause */ for(i=0; i<pTabList->nSrc; i++){ const char *zSavedAuthContext = 0; int needRestoreContext; |
︙ | ︙ |