-C Multiplying\sNULL\sby\szero\sgives\sNULL,\snot\szero.\s\sI\smisread\sthe\stest\sdata\nand\scoded\sit\swrong.\s\sThis\scheck-in\sfixes\sthe\sproblem.\s(CVS\s601)
-D 2002-06-01T21:41:10
+C Enhance\sthe\sORDER\sBY\sclause\sso\sthat\san\sinteger\sterm\smeans\sto\ssort\sby\sthe\ncorresponding\scolumn.\s(CVS\s602)
+D 2002-06-02T16:09:02
F Makefile.in 6291a33b87d2a395aafd7646ee1ed562c6f2c28c
F Makefile.template 4e11752e0b5c7a043ca50af4296ec562857ba495
F README a4c0ba11354ef6ba0776b400d057c59da47a4cc0
F src/build.c 36e42718a7a94f554ea39508993378482f5335c7
F src/delete.c a2b098cbbf518e6b641847e26de85827793bc523
F src/encode.c 346b12b46148506c32038524b95c4631ab46d760
-F src/expr.c 6bb74762c3d86b1665b32a6a388a70eeaaca93f8
+F src/expr.c 4ee07b536119e7ee4f572e1ca83ad86c1aef0058
F src/func.c 061a520a122da7e4f9dcac15697bb996aac7d5df
F src/hash.c 6a6236b89c8c060c65dabd300a1c8ce7c10edb72
F src/hash.h dca065dda89d4575f3176e75e9a3dc0f4b4fb8b9
F src/parse.y c681da701bf142967325b8791f22418e2d81552d
F src/printf.c d8032ee18b860c812eeff596c9bebfdacb7930fd
F src/random.c 19e8e00fe0df32a742f115773f57651be327cabe
-F src/select.c 9a9f76d7d647284f41616bc120003961bea403ef
+F src/select.c ad9061b4735ccd79fc073415979882cd5c424c71
F src/shell.c 1d22fe870ee852cfb975fd000dbe3973713d0a15
F src/shell.tcl 27ecbd63dd88396ad16d81ab44f73e6c0ea9d20e
F src/sqlite.h.in 0038faa6d642de06b91143ee65a131bd831d020b
-F src/sqliteInt.h 55824b7c87dcead71801354f90e4f1b1481f1d1e
+F src/sqliteInt.h 8ec47ae045cf8525c2bcc1a650853d814ca7675c
F src/table.c eed2098c9b577aa17f8abe89313a9c4413f57d63
F src/tclsqlite.c 9300c9606a38bc0c75d6c0bc8a6197ab979353d1
F src/test1.c 09d95048b66ce6dcd2bae90f443589043d7d631e
F test/quick.test 6f023c7a73fc413e6d65b7a1879c79764038dc05
F test/quote.test 08f23385c685d3dc7914ec760d492cacea7f6e3d
F test/rowid.test 4c55943300cddf73dd0f88d40a268cab14c83274
-F test/select1.test a19a8026b5c2c5bdf5384d761f3d446954b7ebf9
+F test/select1.test 0d708cec567104653ec9aa49fecf3444a2e7d150
F test/select2.test aceea74fd895b9d007512f72499db589735bd8e4
F test/select3.test 9469c332250a75a0ef1771fb5da62dc04ec77f18
-F test/select4.test 32018b97fde7202dcb906748836fcd79410604d3
+F test/select4.test 9b5c87b7a372172d65928cf860bcd5a54694c775
F test/select5.test c2a6c4a003316ee42cbbd689eebef8fdce0db2ac
F test/select6.test efb8d0c07a440441db87db2c4ade6904e1407e85
F test/sort.test 3b996ce7ca385f9cd559944ac0f4027a23aa546b
F www/sqlite.tcl 8b5884354cb615049aed83039f8dfe1552a44279
F www/tclsqlite.tcl 1db15abeb446aad0caf0b95b8b9579720e4ea331
F www/vdbe.tcl 2013852c27a02a091d39a766bc87cff329f21218
-P da61aa1d238539dff9c43fd9f464d311e28d669f
-R f5c3f541431552f938b5386e692916f8
+P df9cc852ad02dbec5558d3915a0303f7e7b79b2b
+R d820e9b413015f44b726f7ec86a28058
U drh
-Z 64d47e65013a776dcf32882cb49edbc6
+Z 52b5b2062ca7af0b018c152f36b11673
-df9cc852ad02dbec5558d3915a0303f7e7b79b2b
\ No newline at end of file
+7acbf84b492202d8b5a05276a95b475027eb5f58
\ No newline at end of file
** This file contains routines used for analyzing expressions and
** for generating VDBE code that evaluates expressions in SQLite.
**
-** $Id: expr.c,v 1.66 2002/05/31 15:51:25 drh Exp $
+** $Id: expr.c,v 1.67 2002/06/02 16:09:02 drh Exp $
*/
#include "sqliteInt.h"
return 0;
}
+/*
+** If the given expression codes a constant integer, return 1 and put
+** the value of the integer in *pValue. If the expression is not an
+** integer, return 0 and leave *pValue unchanged.
+*/
+int sqliteExprIsInteger(Expr *p, int *pValue){
+ switch( p->op ){
+ case TK_INTEGER: {
+ *pValue = atoi(p->token.z);
+ return 1;
+ }
+ case TK_STRING: {
+ char *z = p->token.z;
+ int n = p->token.n;
+ if( n>0 && z=='-' ){ z++; n--; }
+ while( n>0 && *z && isdigit(*z) ){ z++; n--; }
+ if( n==0 ){
+ *pValue = atoi(p->token.z);
+ return 1;
+ }
+ break;
+ }
+ case TK_UMINUS: {
+ int v;
+ if( sqliteExprIsInteger(p->pLeft, &v) ){
+ *pValue = -v;
+ return 1;
+ }
+ break;
+ }
+ default: break;
+ }
+ return 0;
+}
+
/*
** Return TRUE if the given string is a row-id column name.
*/
** This file contains C code routines that are called by the parser
** to handle SELECT statements in SQLite.
**
-** $Id: select.c,v 1.89 2002/05/31 15:51:25 drh Exp $
+** $Id: select.c,v 1.90 2002/06/02 16:09:02 drh Exp $
*/
#include "sqliteInt.h"
Parse *pParse, /* A place to leave error messages */
Select *pSelect, /* Match to result columns of this SELECT */
ExprList *pOrderBy, /* The ORDER BY values to match against columns */
- int iTable, /* Insert this this value in iTable */
+ int iTable, /* Insert this value in iTable */
int mustComplete /* If TRUE all ORDER BYs must match */
){
int nErr = 0;
pEList = pSelect->pEList;
for(i=0; i<pOrderBy->nExpr; i++){
Expr *pE = pOrderBy->a[i].pExpr;
- int match = 0;
+ int iCol = -1;
if( pOrderBy->a[i].done ) continue;
- for(j=0; j<pEList->nExpr; j++){
+ if( sqliteExprIsInteger(pE, &iCol) ){
+ if( iCol<=0 || iCol>pEList->nExpr ){
+ char zBuf[200];
+ sprintf(zBuf,"ORDER BY position %d should be between 1 and %d",
+ iCol, pEList->nExpr);
+ sqliteSetString(&pParse->zErrMsg, zBuf, 0);
+ pParse->nErr++;
+ nErr++;
+ break;
+ }
+ iCol--;
+ }
+ for(j=0; iCol<0 && j<pEList->nExpr; j++){
if( pEList->a[j].zName && (pE->op==TK_ID || pE->op==TK_STRING) ){
char *zName, *zLabel;
zName = pEList->a[j].zName;
zLabel = sqliteStrNDup(pE->token.z, pE->token.n);
sqliteDequote(zLabel);
if( sqliteStrICmp(zName, zLabel)==0 ){
- match = 1;
+ iCol = j;
}
sqliteFree(zLabel);
}
- if( match==0 && sqliteExprCompare(pE, pEList->a[j].pExpr) ){
- match = 1;
- }
- if( match ){
- pE->op = TK_COLUMN;
- pE->iColumn = j;
- pE->iTable = iTable;
- pOrderBy->a[i].done = 1;
- break;
+ if( iCol<0 && sqliteExprCompare(pE, pEList->a[j].pExpr) ){
+ iCol = j;
}
}
- if( !match && mustComplete ){
+ if( iCol>=0 ){
+ pE->op = TK_COLUMN;
+ pE->iColumn = iCol;
+ pE->iTable = iTable;
+ pOrderBy->a[i].done = 1;
+ }
+ if( iCol<0 && mustComplete ){
char zBuf[30];
sprintf(zBuf,"%d",i+1);
sqliteSetString(&pParse->zErrMsg, "ORDER BY term number ", zBuf,
for(i=0; i<pOrderBy->nExpr; i++){
Expr *pE = pOrderBy->a[i].pExpr;
if( sqliteExprIsConstant(pE) ){
- sqliteSetString(&pParse->zErrMsg,
- "ORDER BY expressions should not be constant", 0);
- pParse->nErr++;
- goto select_end;
+ int iCol;
+ if( sqliteExprIsInteger(pE, &iCol)==0 ){
+ sqliteSetString(&pParse->zErrMsg,
+ "ORDER BY terms must not be non-integer constants", 0);
+ pParse->nErr++;
+ goto select_end;
+ }else if( iCol<=0 || iCol>pEList->nExpr ){
+ char zBuf[2000];
+ sprintf(zBuf,"ORDER BY column number %d out of range - should be "
+ "between 1 and %d", iCol, pEList->nExpr);
+ sqliteSetString(&pParse->zErrMsg, zBuf, 0);
+ pParse->nErr++;
+ goto select_end;
+ }
+ sqliteExprDelete(pE);
+ pE = pOrderBy->a[i].pExpr = sqliteExprDup(pEList->a[iCol-1].pExpr);
}
if( sqliteExprResolveIds(pParse, base, pTabList, pEList, pE) ){
goto select_end;
*************************************************************************
** Internal interface definitions for SQLite.
**
-** @(#) $Id: sqliteInt.h,v 1.118 2002/05/27 12:24:49 drh Exp $
+** @(#) $Id: sqliteInt.h,v 1.119 2002/06/02 16:09:02 drh Exp $
*/
#include "sqlite.h"
#include "hash.h"
void sqliteRollbackTransaction(Parse*);
char *sqlite_mprintf(const char *, ...);
int sqliteExprIsConstant(Expr*);
+int sqliteExprIsInteger(Expr*, int*);
void sqliteGenerateRowDelete(Vdbe*, Table*, int, int);
void sqliteGenerateRowIndexDelete(Vdbe*, Table*, int, char*);
void sqliteGenerateConstraintChecks(Parse*,Table*,int,char*,int,int,int,int);
# This file implements regression tests for SQLite library. The
# focus of this file is testing the SELECT statement.
#
-# $Id: select1.test,v 1.29 2002/05/29 23:22:23 drh Exp $
+# $Id: select1.test,v 1.30 2002/06/02 16:09:03 drh Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
catchsql {
SELECT f1 FROM test1 ORDER BY 8.4;
}
-} {1 {ORDER BY expressions should not be constant}}
+} {1 {ORDER BY terms must not be non-integer constants}}
+do_test select1-4.6 {
+ catchsql {
+ SELECT f1 FROM test1 ORDER BY '8.4';
+ }
+} {1 {ORDER BY terms must not be non-integer constants}}
+do_test select1-4.7 {
+ catchsql {
+ SELECT f1 FROM test1 ORDER BY 'xyz';
+ }
+} {1 {ORDER BY terms must not be non-integer constants}}
+do_test select1-4.8 {
+ execsql {
+ CREATE TABLE t5(a,b);
+ INSERT INTO t5 VALUES(1,10);
+ INSERT INTO t5 VALUES(2,9);
+ SELECT * FROM t5 ORDER BY 1;
+ }
+} {1 10 2 9}
+do_test select1-4.9 {
+ execsql {
+ SELECT * FROM t5 ORDER BY 2;
+ }
+} {2 9 1 10}
+do_test select1-4.10 {
+ catchsql {
+ SELECT * FROM t5 ORDER BY 3;
+ }
+} {1 {ORDER BY column number 3 out of range - should be between 1 and 2}}
+do_test select1-4.11 {
+ execsql {
+ INSERT INTO t5 VALUES(3,10);
+ SELECT * FROM t5 ORDER BY 2, 1 DESC;
+ }
+} {2 9 3 10 1 10}
+do_test select1-4.12 {
+ execsql {
+ SELECT * FROM t5 ORDER BY 1 DESC, b;
+ }
+} {3 10 2 9 1 10}
+do_test select1-4.13 {
+ execsql {
+ SELECT * FROM t5 ORDER BY b DESC, 1;
+ }
+} {1 10 3 10 2 9}
+
# ORDER BY ignored on an aggregate query
#
# focus of this file is testing UNION, INTERSECT and EXCEPT operators
# in SELECT statements.
#
-# $Id: select4.test,v 1.9 2002/05/31 15:51:26 drh Exp $
+# $Id: select4.test,v 1.10 2002/06/02 16:09:03 drh Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
}} msg]
lappend v $msg
} {0 {0 1 2 3 4 5 5 6 7 8}}
+do_test select4-5.2f {
+ catchsql {
+ SELECT DISTINCT log FROM t1
+ UNION ALL
+ SELECT n FROM t1 WHERE log=3
+ ORDER BY log;
+ }
+} {0 {0 1 2 3 4 5 5 6 7 8}}
+do_test select4-5.2g {
+ catchsql {
+ SELECT DISTINCT log FROM t1
+ UNION ALL
+ SELECT n FROM t1 WHERE log=3
+ ORDER BY 1;
+ }
+} {0 {0 1 2 3 4 5 5 6 7 8}}
+do_test select4-5.2h {
+ catchsql {
+ SELECT DISTINCT log FROM t1
+ UNION ALL
+ SELECT n FROM t1 WHERE log=3
+ ORDER BY 2;
+ }
+} {1 {ORDER BY position 2 should be between 1 and 1}}
+do_test select4-5.2i {
+ catchsql {
+ SELECT DISTINCT 1, log FROM t1
+ UNION ALL
+ SELECT 2, n FROM t1 WHERE log=3
+ ORDER BY 2, 1;
+ }
+} {0 {1 0 1 1 1 2 1 3 1 4 1 5 2 5 2 6 2 7 2 8}}
+do_test select4-5.2j {
+ catchsql {
+ SELECT DISTINCT 1, log FROM t1
+ UNION ALL
+ SELECT 2, n FROM t1 WHERE log=3
+ ORDER BY 1, 2 DESC;
+ }
+} {0 {1 5 1 4 1 3 1 2 1 1 1 0 2 8 2 7 2 6 2 5}}
+do_test select4-5.2k {
+ catchsql {
+ SELECT DISTINCT 1, log FROM t1
+ UNION ALL
+ SELECT 2, n FROM t1 WHERE log=3
+ ORDER BY n, 1;
+ }
+} {0 {1 0 1 1 1 2 1 3 1 4 1 5 2 5 2 6 2 7 2 8}}
do_test select4-5.3 {
set v [catch {execsql {
SELECT DISTINCT log, n FROM t1