Enhance the ORDER BY clause so that an integer term means to sort by the
corresponding column. (CVS 602) FossilOrigin-Name: 7acbf84b492202d8b5a05276a95b475027eb5f58
This commit is contained in:
parent
1288c9561d
commit
e4de1feb3e
20
manifest
20
manifest
@ -1,5 +1,5 @@
|
||||
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
|
||||
@ -23,7 +23,7 @@ F src/btree.h 8abeabfe6e0b1a990b64fa457592a6482f6674f3
|
||||
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
|
||||
@ -37,11 +37,11 @@ F src/pager.h 6fddfddd3b73aa8abc081b973886320e3c614f0e
|
||||
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
|
||||
@ -87,10 +87,10 @@ F test/printf.test 3cb415073754cb8ff076f26173143c3cd293a9da
|
||||
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
|
||||
@ -136,7 +136,7 @@ F www/speed.tcl da8afcc1d3ccc5696cfb388a68982bc3d9f7f00f
|
||||
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
|
||||
|
@ -1 +1 @@
|
||||
df9cc852ad02dbec5558d3915a0303f7e7b79b2b
|
||||
7acbf84b492202d8b5a05276a95b475027eb5f58
|
37
src/expr.c
37
src/expr.c
@ -12,7 +12,7 @@
|
||||
** 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"
|
||||
|
||||
@ -335,6 +335,41 @@ int sqliteExprIsConstant(Expr *p){
|
||||
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.
|
||||
*/
|
||||
|
61
src/select.c
61
src/select.c
@ -12,7 +12,7 @@
|
||||
** 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"
|
||||
|
||||
@ -790,7 +790,7 @@ static int matchOrderbyToColumn(
|
||||
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;
|
||||
@ -812,9 +812,21 @@ static int matchOrderbyToColumn(
|
||||
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;
|
||||
@ -822,22 +834,21 @@ static int matchOrderbyToColumn(
|
||||
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,
|
||||
@ -1520,10 +1531,22 @@ int sqliteSelect(
|
||||
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;
|
||||
|
@ -11,7 +11,7 @@
|
||||
*************************************************************************
|
||||
** 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"
|
||||
@ -841,6 +841,7 @@ void sqliteCommitTransaction(Parse*);
|
||||
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);
|
||||
|
@ -11,7 +11,7 @@
|
||||
# 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
|
||||
@ -285,7 +285,52 @@ do_test select1-4.5 {
|
||||
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
|
||||
#
|
||||
|
@ -12,7 +12,7 @@
|
||||
# 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
|
||||
@ -209,6 +209,54 @@ do_test select4-5.2e {
|
||||
}} 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
|
||||
|
Loading…
Reference in New Issue
Block a user