Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Match ORDER BY terms to columns using names in compound queries. Make sure this works for subqueries, especially in the right-hand side of an IN operator. Ticket #2296. (CVS 3842) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
cfc6f933dc60ca88ae848f7f0c402e82 |
User & Date: | drh 2007-04-13 16:06:33.000 |
Context
2007-04-14
| ||
12:04 | Update the whentouse.html document to mention that less bitmap memory is used for larger page sizes. (CVS 3843) (check-in: 2c8e2a5be3 user: drh tags: trunk) | |
2007-04-13
| ||
16:06 | Match ORDER BY terms to columns using names in compound queries. Make sure this works for subqueries, especially in the right-hand side of an IN operator. Ticket #2296. (CVS 3842) (check-in: cfc6f933dc user: drh tags: trunk) | |
04:01 | Fix a bug in autovacuum introduced by (3839). (CVS 3841) (check-in: e39efa195a user: drh tags: trunk) | |
Changes
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.284 2007/04/13 16:06:33 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> /* ** Return the 'affinity' of the expression pExpr if any. ** |
︙ | ︙ | |||
1416 1417 1418 1419 1420 1421 1422 | ** ** Generate code to write the results of the select into the temporary ** table allocated and opened above. */ int iParm = pExpr->iTable + (((int)affinity)<<16); ExprList *pEList; assert( (pExpr->iTable&0x0000FFFF)==pExpr->iTable ); | | > > | 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 | ** ** Generate code to write the results of the select into the temporary ** table allocated and opened above. */ int iParm = pExpr->iTable + (((int)affinity)<<16); ExprList *pEList; assert( (pExpr->iTable&0x0000FFFF)==pExpr->iTable ); if( sqlite3Select(pParse, pExpr->pSelect, SRT_Set, iParm, 0, 0, 0, 0) ){ return; } pEList = pExpr->pSelect->pEList; if( pEList && pEList->nExpr>0 ){ keyInfo.aColl[0] = binaryCompareCollSeq(pParse, pExpr->pLeft, pEList->a[0].pExpr); } }else if( pExpr->pList ){ /* Case 2: expr IN (exprlist) |
︙ | ︙ | |||
1487 1488 1489 1490 1491 1492 1493 | }else{ sop = SRT_Exists; sqlite3VdbeAddOp(v, OP_MemInt, 0, iMem); VdbeComment((v, "# Init EXISTS result")); } sqlite3ExprDelete(pSel->pLimit); pSel->pLimit = sqlite3Expr(TK_INTEGER, 0, 0, &one); | | > > | 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 | }else{ sop = SRT_Exists; sqlite3VdbeAddOp(v, OP_MemInt, 0, iMem); VdbeComment((v, "# Init EXISTS result")); } sqlite3ExprDelete(pSel->pLimit); pSel->pLimit = sqlite3Expr(TK_INTEGER, 0, 0, &one); if( sqlite3Select(pParse, pSel, sop, iMem, 0, 0, 0, 0) ){ return; } break; } } if( testAddr ){ sqlite3VdbeJumpHere(v, testAddr); } |
︙ | ︙ |
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.336 2007/04/13 16:06:33 drh Exp $ */ #include "sqliteInt.h" /* ** Delete all the content of a Select structure but do not deallocate ** the select structure itself. |
︙ | ︙ | |||
1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 | if( pSelect->pPrior ){ if( matchOrderbyToColumn(pParse, pSelect->pPrior, pOrderBy, iTable, 0) ){ return 1; } } pEList = pSelect->pEList; for(i=0; i<pOrderBy->nExpr; i++){ Expr *pE = pOrderBy->a[i].pExpr; int iCol = -1; if( pOrderBy->a[i].done ) continue; if( sqlite3ExprIsInteger(pE, &iCol) ){ if( iCol<=0 || iCol>pEList->nExpr ){ sqlite3ErrorMsg(pParse, "ORDER BY position %d should be between 1 and %d", iCol, pEList->nExpr); nErr++; break; } if( !mustComplete ) continue; iCol--; } | > > > > | < | | > > | < > | > | | < < < | | 1397 1398 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 1445 1446 1447 1448 1449 1450 | if( pSelect->pPrior ){ if( matchOrderbyToColumn(pParse, pSelect->pPrior, pOrderBy, iTable, 0) ){ return 1; } } pEList = pSelect->pEList; for(i=0; i<pOrderBy->nExpr; i++){ struct ExprList_item *pItem; Expr *pE = pOrderBy->a[i].pExpr; int iCol = -1; char *zLabel; if( pOrderBy->a[i].done ) continue; if( sqlite3ExprIsInteger(pE, &iCol) ){ if( iCol<=0 || iCol>pEList->nExpr ){ sqlite3ErrorMsg(pParse, "ORDER BY position %d should be between 1 and %d", iCol, pEList->nExpr); nErr++; break; } if( !mustComplete ) continue; iCol--; } if( iCol<0 && (zLabel = sqlite3NameFromToken(&pE->token))!=0 ){ for(j=0, pItem=pEList->a; j<pEList->nExpr; j++, pItem++){ char *zName; if( pItem->zName ){ zName = sqlite3StrDup(pItem->zName); }else{ zName = sqlite3NameFromToken(&pItem->pExpr->token); } if( zName && sqlite3StrICmp(zName, zLabel)==0 ){ iCol = j; break; } sqliteFree(zName); } sqliteFree(zLabel); } if( iCol>=0 ){ pE->op = TK_COLUMN; pE->iColumn = iCol; pE->iTable = iTable; pE->iAgg = -1; pOrderBy->a[i].done = 1; }else if( mustComplete ){ sqlite3ErrorMsg(pParse, "ORDER BY term number %d does not match any result column", i+1); nErr++; break; } } return nErr; |
︙ | ︙ |
Changes to test/select1.test.
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. # #*********************************************************************** # This file implements regression tests for SQLite library. The # focus of this file is testing the SELECT statement. # | | | 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. # #*********************************************************************** # This file implements regression tests for SQLite library. The # focus of this file is testing the SELECT statement. # # $Id: select1.test,v 1.53 2007/04/13 16:06:34 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl # Try to select on a non-existant table. # do_test select1-1.1 { |
︙ | ︙ | |||
491 492 493 494 495 496 497 | } {0 {f1 11 f1 22 f1 33 f1 44}} do_test select1-6.11 { set v [catch {execsql2 { SELECT f1 FROM test1 UNION SELECT f2+100 FROM test1 ORDER BY f2+100; }} msg] lappend v $msg | > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 | } {0 {f1 11 f1 22 f1 33 f1 44}} do_test select1-6.11 { set v [catch {execsql2 { SELECT f1 FROM test1 UNION SELECT f2+100 FROM test1 ORDER BY f2+100; }} msg] lappend v $msg } {1 {ORDER BY term number 1 does not match any result column}} # Ticket #2296 do_test select1-6.20 { execsql { CREATE TABLE t6(a TEXT, b TEXT); INSERT INTO t6 VALUES('a','0'); INSERT INTO t6 VALUES('b','1'); INSERT INTO t6 VALUES('c','2'); INSERT INTO t6 VALUES('d','3'); SELECT a FROM t6 WHERE b IN (SELECT b FROM t6 WHERE a<='b' UNION SELECT '3' AS x ORDER BY 1 LIMIT 1) } } {a} do_test select1-6.21 { execsql { SELECT a FROM t6 WHERE b IN (SELECT b FROM t6 WHERE a<='b' UNION SELECT '3' AS x ORDER BY 1 DESC LIMIT 1) } } {d} do_test select1-6.22 { execsql { SELECT a FROM t6 WHERE b IN (SELECT b FROM t6 WHERE a<='b' UNION SELECT '3' AS x ORDER BY b LIMIT 2) ORDER BY a; } } {a b} do_test select1-6.23 { execsql { SELECT a FROM t6 WHERE b IN (SELECT b FROM t6 WHERE a<='b' UNION SELECT '3' AS x ORDER BY x DESC LIMIT 2) ORDER BY a; } } {b d} } ;#ifcapable compound do_test select1-7.1 { set v [catch {execsql { SELECT f1 FROM test1 WHERE f2=; }} msg] lappend v $msg |
︙ | ︙ |