Merge recent trunk changes into the STAT4 branch.
FossilOrigin-Name: c69b512af276a438399747af22659415af3a5d4d
This commit is contained in:
commit
d94f512f58
26
manifest
26
manifest
@ -1,5 +1,5 @@
|
||||
C Fix\sa\scrash\sthat\scan\soccur\sif\sthe\ssqlite_stat3\sor\ssqlite_stat4\stable\sis\scorrupt.
|
||||
D 2013-08-15T19:56:32.997
|
||||
C Merge\srecent\strunk\schanges\sinto\sthe\sSTAT4\sbranch.
|
||||
D 2013-08-16T12:26:33.317
|
||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||
F Makefile.in 5e41da95d92656a5004b03d3576e8b226858a28e
|
||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||
@ -185,13 +185,13 @@ F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d
|
||||
F src/legacy.c 0df0b1550b9cc1f58229644735e317ac89131f12
|
||||
F src/lempar.c cdf0a000315332fc9b50b62f3b5e22e080a0952b
|
||||
F src/loadext.c 867c7b330b740c6c917af9956b13b81d0a048303
|
||||
F src/main.c b2592b4119f9b34d20861d1a73a44f07d061508c
|
||||
F src/main.c 4e4cd5c2ee09db496c0dde79b507bba6b8bcbdcb
|
||||
F src/malloc.c fe085aa851b666b7c375c1ff957643dc20a04bf6
|
||||
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
|
||||
F src/mem1.c 437c7c4af964895d4650f29881df63535caaa1fa
|
||||
F src/mem2.c e307323e86b5da1853d7111b68fd6b84ad6f09cf
|
||||
F src/mem3.c 61c9d47b792908c532ca3a62b999cf21795c6534
|
||||
F src/mem5.c c2c63b7067570b00bf33d751c39af24182316f7f
|
||||
F src/mem5.c 0025308a93838022bd5696cf9627ff4e40b19918
|
||||
F src/memjournal.c 0683aac6cab6ec2b5374c0db37c0deb2436a3785
|
||||
F src/mutex.c d3b66a569368015e0fcb1ac15f81c119f504d3bc
|
||||
F src/mutex.h 5bc526e19dccc412b7ff04642f6fdad3fdfdabea
|
||||
@ -214,18 +214,18 @@ F src/pragma.c 590c75750d93ec5a1f903e4bb0dc6d2a0845bf8b
|
||||
F src/prepare.c fa6988589f39af8504a61731614cd4f6ae71554f
|
||||
F src/printf.c 41c49dac366a3a411190001a8ab495fa8887974e
|
||||
F src/random.c cd4a67b3953b88019f8cd4ccd81394a8ddfaba50
|
||||
F src/resolve.c 17e670996729ac41aadf6a31f57b4e6f29b3d819
|
||||
F src/resolve.c 9d53899cc6e1f4ec0b4632d07e97d57827bf63b9
|
||||
F src/rowset.c 64655f1a627c9c212d9ab497899e7424a34222e0
|
||||
F src/select.c 8b148eb851f384412aea57091659d14b369918ca
|
||||
F src/shell.c 128eb16ccec68509a4a2f1948f2483819bf63425
|
||||
F src/sqlite.h.in bd1451ba1ab681022a53bccc3c39580ba094a3ff
|
||||
F src/sqlite3.rc fea433eb0a59f4c9393c8e6d76a6e2596b1fe0c0
|
||||
F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc
|
||||
F src/sqliteInt.h 35ee14455ae3cb21b166fea7777867a42c60d0d5
|
||||
F src/sqliteInt.h 85cc797544e30cf585507b2127b4a3f60478c849
|
||||
F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
|
||||
F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158
|
||||
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
|
||||
F src/tclsqlite.c b8835978e853a89bf58de88acc943a5ca94d752e
|
||||
F src/tclsqlite.c 659dad8ef30b54831306a244b43e37af4725a444
|
||||
F src/test1.c 870fc648a48cb6d6808393174f7ebe82b8c840fa
|
||||
F src/test2.c 7355101c085304b90024f2261e056cdff13c6c35
|
||||
F src/test3.c 1c0e5d6f080b8e33c1ce8b3078e7013fdbcd560c
|
||||
@ -735,7 +735,7 @@ F test/regexp1.test 497ea812f264d12b6198d6e50a76be4a1973a9d8
|
||||
F test/reindex.test 44edd3966b474468b823d481eafef0c305022254
|
||||
F test/releasetest.mk 2eced2f9ae701fd0a29e714a241760503ccba25a
|
||||
F test/releasetest.tcl 06d289d8255794073a58d2850742f627924545ce
|
||||
F test/resolver01.test d1b487fc567bdb70b5dd09ccaaa877ddc61a233e
|
||||
F test/resolver01.test 33abf37ff8335e6bf98f2b45a0af3e06996ccd9a
|
||||
F test/rollback.test a1b4784b864331eae8b2a98c189efa2a8b11ff07
|
||||
F test/rowhash.test 0bc1d31415e4575d10cacf31e1a66b5cc0f8be81
|
||||
F test/rowid.test f777404492adb0e00868fd706a3721328fd3af48
|
||||
@ -908,7 +908,7 @@ F test/tkt2686.test 6ee01c9b9e9c48f6d3a1fdd553b1cc4258f903d6
|
||||
F test/tkt2767.test 569000d842678f9cf2db7e0d1b27cbc9011381b0
|
||||
F test/tkt2817.test f31839e01f4243cff7399ef654d3af3558cb8d8d
|
||||
F test/tkt2820.test 39940276b3436d125deb7d8ebeee053e4cf13213
|
||||
F test/tkt2822.test c3589494fba643e039bcf0bfde7554ff6028406d
|
||||
F test/tkt2822.test f391776423a7c0d0949edfce375708bfb0f3141e
|
||||
F test/tkt2832.test a9b0b74a02dca166a04d9e37739c414b10929caa
|
||||
F test/tkt2854.test e432965db29e27e16f539b2ba7f502eb2ccc49af
|
||||
F test/tkt2920.test a8737380e4ae6424e00c0273dc12775704efbebf
|
||||
@ -1107,7 +1107,7 @@ F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
||||
F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381
|
||||
F tool/wherecosttest.c f407dc4c79786982a475261866a161cd007947ae
|
||||
F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac
|
||||
P 9f80b2687012ab7c4d6d654fe19f40878bd78bd8
|
||||
R abb1a9d20998265ab3bcabc4adb13b2c
|
||||
U dan
|
||||
Z 4cffc531446b09bd876c8b206583a719
|
||||
P d51df8a8fcc31c37f6e1c9612204af5738ed865e f2d175f975cd0be63425424ec322a98fb650019e
|
||||
R a01801631ed4ae55018a7d07c406419f
|
||||
U drh
|
||||
Z 2e42de2ef767503ad01b3c8e93c6139b
|
||||
|
@ -1 +1 @@
|
||||
d51df8a8fcc31c37f6e1c9612204af5738ed865e
|
||||
c69b512af276a438399747af22659415af3a5d4d
|
20
src/main.c
20
src/main.c
@ -117,6 +117,9 @@ char *sqlite3_data_directory = 0;
|
||||
int sqlite3_initialize(void){
|
||||
MUTEX_LOGIC( sqlite3_mutex *pMaster; ) /* The main static mutex */
|
||||
int rc; /* Result code */
|
||||
#ifdef SQLITE_EXTRA_INIT
|
||||
int bRunExtraInit = 0; /* Extra initialization needed */
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE_OMIT_WSD
|
||||
rc = sqlite3_wsd_init(4096, 24);
|
||||
@ -214,6 +217,9 @@ int sqlite3_initialize(void){
|
||||
sqlite3PCacheBufferSetup( sqlite3GlobalConfig.pPage,
|
||||
sqlite3GlobalConfig.szPage, sqlite3GlobalConfig.nPage);
|
||||
sqlite3GlobalConfig.isInit = 1;
|
||||
#ifdef SQLITE_EXTRA_INIT
|
||||
bRunExtraInit = 1;
|
||||
#endif
|
||||
}
|
||||
sqlite3GlobalConfig.inProgress = 0;
|
||||
}
|
||||
@ -254,7 +260,7 @@ int sqlite3_initialize(void){
|
||||
** compile-time option.
|
||||
*/
|
||||
#ifdef SQLITE_EXTRA_INIT
|
||||
if( rc==SQLITE_OK && sqlite3GlobalConfig.isInit ){
|
||||
if( bRunExtraInit ){
|
||||
int SQLITE_EXTRA_INIT(const char*);
|
||||
rc = SQLITE_EXTRA_INIT(0);
|
||||
}
|
||||
@ -442,8 +448,8 @@ int sqlite3_config(int op, ...){
|
||||
memset(&sqlite3GlobalConfig.m, 0, sizeof(sqlite3GlobalConfig.m));
|
||||
}else{
|
||||
/* The heap pointer is not NULL, then install one of the
|
||||
** mem5.c/mem3.c methods. If neither ENABLE_MEMSYS3 nor
|
||||
** ENABLE_MEMSYS5 is defined, return an error.
|
||||
** mem5.c/mem3.c methods. The enclosing #if guarantees at
|
||||
** least one of these methods is currently enabled.
|
||||
*/
|
||||
#ifdef SQLITE_ENABLE_MEMSYS3
|
||||
sqlite3GlobalConfig.m = *sqlite3MemGetMemsys3();
|
||||
@ -462,7 +468,7 @@ int sqlite3_config(int op, ...){
|
||||
break;
|
||||
}
|
||||
|
||||
/* Record a pointer to the logger funcction and its first argument.
|
||||
/* Record a pointer to the logger function and its first argument.
|
||||
** The default is NULL. Logging is disabled if the function pointer is
|
||||
** NULL.
|
||||
*/
|
||||
@ -2178,20 +2184,20 @@ int sqlite3ParseUri(
|
||||
zFile = sqlite3_malloc(nByte);
|
||||
if( !zFile ) return SQLITE_NOMEM;
|
||||
|
||||
iIn = 5;
|
||||
#ifndef SQLITE_ALLOW_URI_AUTHORITY
|
||||
/* Discard the scheme and authority segments of the URI. */
|
||||
if( zUri[5]=='/' && zUri[6]=='/' ){
|
||||
iIn = 7;
|
||||
while( zUri[iIn] && zUri[iIn]!='/' ) iIn++;
|
||||
|
||||
if( iIn!=7 && (iIn!=16 || memcmp("localhost", &zUri[7], 9)) ){
|
||||
*pzErrMsg = sqlite3_mprintf("invalid uri authority: %.*s",
|
||||
iIn-7, &zUri[7]);
|
||||
rc = SQLITE_ERROR;
|
||||
goto parse_uri_out;
|
||||
}
|
||||
}else{
|
||||
iIn = 5;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Copy the filename and any query parameters into the zFile buffer.
|
||||
** Decode %HH escape codes along the way.
|
||||
|
@ -130,13 +130,13 @@ static SQLITE_WSD struct Mem5Global {
|
||||
} mem5;
|
||||
|
||||
/*
|
||||
** Access the static variable through a macro for SQLITE_OMIT_WSD
|
||||
** Access the static variable through a macro for SQLITE_OMIT_WSD.
|
||||
*/
|
||||
#define mem5 GLOBAL(struct Mem5Global, mem5)
|
||||
|
||||
/*
|
||||
** Assuming mem5.zPool is divided up into an array of Mem5Link
|
||||
** structures, return a pointer to the idx-th such lik.
|
||||
** structures, return a pointer to the idx-th such link.
|
||||
*/
|
||||
#define MEM5LINK(idx) ((Mem5Link *)(&mem5.zPool[(idx)*mem5.szAtom]))
|
||||
|
||||
@ -232,7 +232,7 @@ static int memsys5UnlinkFirst(int iLogsize){
|
||||
** Return a block of memory of at least nBytes in size.
|
||||
** Return NULL if unable. Return NULL if nBytes==0.
|
||||
**
|
||||
** The caller guarantees that nByte positive.
|
||||
** The caller guarantees that nByte is positive.
|
||||
**
|
||||
** The caller has obtained a mutex prior to invoking this
|
||||
** routine so there is never any chance that two or more
|
||||
@ -354,7 +354,7 @@ static void memsys5FreeUnsafe(void *pOld){
|
||||
}
|
||||
|
||||
/*
|
||||
** Allocate nBytes of memory
|
||||
** Allocate nBytes of memory.
|
||||
*/
|
||||
static void *memsys5Malloc(int nBytes){
|
||||
sqlite3_int64 *p = 0;
|
||||
|
@ -55,7 +55,7 @@ static void incrAggFunctionDepth(Expr *pExpr, int N){
|
||||
** column reference is so that the column reference will be recognized as
|
||||
** usable by indices within the WHERE clause processing logic.
|
||||
**
|
||||
** Hack: The TK_AS operator is inhibited if zType[0]=='G'. This means
|
||||
** The TK_AS operator is inhibited if zType[0]=='G'. This means
|
||||
** that in a GROUP BY clause, the expression is evaluated twice. Hence:
|
||||
**
|
||||
** SELECT random()%5 AS x, count(*) FROM tab GROUP BY x
|
||||
@ -65,8 +65,9 @@ static void incrAggFunctionDepth(Expr *pExpr, int N){
|
||||
** SELECT random()%5 AS x, count(*) FROM tab GROUP BY random()%5
|
||||
**
|
||||
** The result of random()%5 in the GROUP BY clause is probably different
|
||||
** from the result in the result-set. We might fix this someday. Or
|
||||
** then again, we might not...
|
||||
** from the result in the result-set. On the other hand Standard SQL does
|
||||
** not allow the GROUP BY clause to contain references to result-set columns.
|
||||
** So this should never come up in well-formed queries.
|
||||
**
|
||||
** If the reference is followed by a COLLATE operator, then make sure
|
||||
** the COLLATE operator is preserved. For example:
|
||||
@ -396,10 +397,16 @@ static int lookupName(
|
||||
** forms the result set entry ("a+b" in the example) and return immediately.
|
||||
** Note that the expression in the result set should have already been
|
||||
** resolved by the time the WHERE clause is resolved.
|
||||
**
|
||||
** The ability to use an output result-set column in the WHERE, GROUP BY,
|
||||
** or HAVING clauses, or as part of a larger expression in the ORDRE BY
|
||||
** clause is not standard SQL. This is a (goofy) SQLite extension, that
|
||||
** is supported for backwards compatibility only. TO DO: Issue a warning
|
||||
** on sqlite3_log() whenever the capability is used.
|
||||
*/
|
||||
if( (pEList = pNC->pEList)!=0
|
||||
&& zTab==0
|
||||
&& ((pNC->ncFlags & NC_AsMaybe)==0 || cnt==0)
|
||||
&& cnt==0
|
||||
){
|
||||
for(j=0; j<pEList->nExpr; j++){
|
||||
char *zAs = pEList->a[j].zName;
|
||||
@ -961,7 +968,7 @@ static int resolveCompoundOrderBy(
|
||||
/*
|
||||
** Check every term in the ORDER BY or GROUP BY clause pOrderBy of
|
||||
** the SELECT statement pSelect. If any term is reference to a
|
||||
** result set expression (as determined by the ExprList.a.iCol field)
|
||||
** result set expression (as determined by the ExprList.a.iOrderByCol field)
|
||||
** then convert that term into a copy of the corresponding result set
|
||||
** column.
|
||||
**
|
||||
@ -1009,7 +1016,7 @@ int sqlite3ResolveOrderGroupBy(
|
||||
** If the order-by term is an integer I between 1 and N (where N is the
|
||||
** number of columns in the result set of the SELECT) then the expression
|
||||
** in the resolution is a copy of the I-th result-set expression. If
|
||||
** the order-by term is an identify that corresponds to the AS-name of
|
||||
** the order-by term is an identifier that corresponds to the AS-name of
|
||||
** a result-set expression, then the term resolves to a copy of the
|
||||
** result-set expression. Otherwise, the expression is resolved in
|
||||
** the usual way - using sqlite3ResolveExprNames().
|
||||
@ -1035,16 +1042,19 @@ static int resolveOrderGroupBy(
|
||||
pParse = pNC->pParse;
|
||||
for(i=0, pItem=pOrderBy->a; i<pOrderBy->nExpr; i++, pItem++){
|
||||
Expr *pE = pItem->pExpr;
|
||||
iCol = resolveAsName(pParse, pSelect->pEList, pE);
|
||||
if( iCol>0 ){
|
||||
/* If an AS-name match is found, mark this ORDER BY column as being
|
||||
** a copy of the iCol-th result-set column. The subsequent call to
|
||||
** sqlite3ResolveOrderGroupBy() will convert the expression to a
|
||||
** copy of the iCol-th result-set expression. */
|
||||
pItem->iOrderByCol = (u16)iCol;
|
||||
continue;
|
||||
Expr *pE2 = sqlite3ExprSkipCollate(pE);
|
||||
if( zType[0]!='G' ){
|
||||
iCol = resolveAsName(pParse, pSelect->pEList, pE2);
|
||||
if( iCol>0 ){
|
||||
/* If an AS-name match is found, mark this ORDER BY column as being
|
||||
** a copy of the iCol-th result-set column. The subsequent call to
|
||||
** sqlite3ResolveOrderGroupBy() will convert the expression to a
|
||||
** copy of the iCol-th result-set expression. */
|
||||
pItem->iOrderByCol = (u16)iCol;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if( sqlite3ExprIsInteger(sqlite3ExprSkipCollate(pE), &iCol) ){
|
||||
if( sqlite3ExprIsInteger(pE2, &iCol) ){
|
||||
/* The ORDER BY term is an integer constant. Again, set the column
|
||||
** number so that sqlite3ResolveOrderGroupBy() will convert the
|
||||
** order-by term to a copy of the result-set expression */
|
||||
@ -1187,7 +1197,7 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
|
||||
return WRC_Abort;
|
||||
}
|
||||
|
||||
/* Add the expression list to the name-context before parsing the
|
||||
/* Add the output column 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.
|
||||
@ -1196,10 +1206,8 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
|
||||
** re-evaluated for each reference to it.
|
||||
*/
|
||||
sNC.pEList = p->pEList;
|
||||
sNC.ncFlags |= NC_AsMaybe;
|
||||
if( sqlite3ResolveExprNames(&sNC, p->pHaving) ) return WRC_Abort;
|
||||
if( sqlite3ResolveExprNames(&sNC, p->pWhere) ) return WRC_Abort;
|
||||
sNC.ncFlags &= ~NC_AsMaybe;
|
||||
|
||||
/* The ORDER BY and GROUP BY clauses may not refer to terms in
|
||||
** outer queries
|
||||
|
@ -2002,7 +2002,7 @@ struct SrcList {
|
||||
struct NameContext {
|
||||
Parse *pParse; /* The parser */
|
||||
SrcList *pSrcList; /* One or more tables used to resolve names */
|
||||
ExprList *pEList; /* Optional list of named expressions */
|
||||
ExprList *pEList; /* Optional list of result-set columns */
|
||||
AggInfo *pAggInfo; /* Information about aggregates at this level */
|
||||
NameContext *pNext; /* Next outer name context. NULL for outermost */
|
||||
int nRef; /* Number of names resolved by this context */
|
||||
@ -2017,9 +2017,7 @@ struct NameContext {
|
||||
#define NC_HasAgg 0x02 /* One or more aggregate functions seen */
|
||||
#define NC_IsCheck 0x04 /* True if resolving names in a CHECK constraint */
|
||||
#define NC_InAggFunc 0x08 /* True if analyzing arguments to an agg func */
|
||||
#define NC_AsMaybe 0x10 /* Resolve to AS terms of the result set only
|
||||
** if no other resolution is available */
|
||||
#define NC_PartIdx 0x20 /* True if resolving a partial index WHERE */
|
||||
#define NC_PartIdx 0x10 /* True if resolving a partial index WHERE */
|
||||
|
||||
/*
|
||||
** An instance of the following structure contains all information
|
||||
|
@ -41,6 +41,18 @@
|
||||
#endif
|
||||
#include <ctype.h>
|
||||
|
||||
/* Used to get the current process ID */
|
||||
#if !defined(_WIN32)
|
||||
# include <unistd.h>
|
||||
# define GETPID getpid
|
||||
#elif !defined(_WIN32_WCE)
|
||||
# ifndef SQLITE_AMALGAMATION
|
||||
# define WIN32_LEAN_AND_MEAN
|
||||
# include <windows.h>
|
||||
# endif
|
||||
# define GETPID (int)GetCurrentProcessId
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Windows needs to know which symbols to export. Unix does not.
|
||||
* BUILD_sqlite should be undefined for Unix.
|
||||
@ -3746,7 +3758,16 @@ static void init_all(Tcl_Interp *interp){
|
||||
#define TCLSH_MAIN main /* Needed to fake out mktclapp */
|
||||
int TCLSH_MAIN(int argc, char **argv){
|
||||
Tcl_Interp *interp;
|
||||
|
||||
|
||||
#if !defined(_WIN32_WCE)
|
||||
if( getenv("BREAK") ){
|
||||
fprintf(stderr,
|
||||
"attach debugger to process %d and press any key to continue.\n",
|
||||
GETPID());
|
||||
fgetc(stdin);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Call sqlite3_shutdown() once before doing anything else. This is to
|
||||
** test that sqlite3_shutdown() can be safely called by a process before
|
||||
** sqlite3_initialize() is. */
|
||||
|
@ -13,10 +13,18 @@
|
||||
# figures out what identifiers in the SQL statement refer to) that
|
||||
# were fixed by ticket [2500cdb9be]
|
||||
#
|
||||
# See also tickets [1c69be2daf] and [f617ea3125] from 2013-08-14.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
|
||||
# "ORDER BY y" binds to the output result-set column named "y"
|
||||
# if available. If no output column is named "y", then try to
|
||||
# bind against an input column named "y".
|
||||
#
|
||||
# This is classical SQL92 behavior.
|
||||
#
|
||||
do_test resolver01-1.1 {
|
||||
catchsql {
|
||||
CREATE TABLE t1(x, y); INSERT INTO t1 VALUES(11,22);
|
||||
@ -25,15 +33,176 @@ do_test resolver01-1.1 {
|
||||
}
|
||||
} {0 1}
|
||||
do_test resolver01-1.2 {
|
||||
catchsql {
|
||||
SELECT 1 AS yy FROM t1, t2 ORDER BY y;
|
||||
}
|
||||
} {1 {ambiguous column name: y}}
|
||||
do_test resolver01-1.3 {
|
||||
catchsql {
|
||||
CREATE TABLE t3(x,y); INSERT INTO t3 VALUES(11,44),(33,22);
|
||||
SELECT x AS y FROM t3 ORDER BY y;
|
||||
}
|
||||
} {0 {11 33}}
|
||||
do_test resolver01-1.4 {
|
||||
catchsql {
|
||||
SELECT x AS yy FROM t3 ORDER BY y;
|
||||
}
|
||||
} {0 {33 11}}
|
||||
|
||||
# SQLite allows the WHERE clause to reference output columns if there is
|
||||
# no other way to resolve the name.
|
||||
#
|
||||
do_test resolver01-1.5 {
|
||||
catchsql {
|
||||
SELECT x AS yy FROM t3 ORDER BY yy;
|
||||
}
|
||||
} {0 {11 33}}
|
||||
do_test resolver01-1.6 {
|
||||
catchsql {
|
||||
SELECT x AS yy FROM t3 ORDER BY 1;
|
||||
}
|
||||
} {0 {11 33}}
|
||||
|
||||
# The "ORDER BY y COLLATE nocase" form works the same as "ORDER BY y".
|
||||
# The "y" binds more tightly to output columns than to input columns.
|
||||
#
|
||||
# This is for compatibility with SQL92 and with historical SQLite behavior.
|
||||
# Note that PostgreSQL considers "y COLLATE nocase" to be an expression
|
||||
# and thus PostgreSQL treats this case as if it where the 3.x case below.
|
||||
#
|
||||
do_test resolver01-2.1 {
|
||||
catchsql {
|
||||
SELECT 2 AS y FROM t1, t2 ORDER BY y COLLATE nocase;
|
||||
}
|
||||
} {0 2}
|
||||
do_test resolver01-1.3 {
|
||||
do_test resolver01-2.2 {
|
||||
catchsql {
|
||||
SELECT 2 AS yy FROM t1, t2 ORDER BY y COLLATE nocase;
|
||||
}
|
||||
} {1 {ambiguous column name: y}}
|
||||
do_test resolver01-2.3 {
|
||||
catchsql {
|
||||
SELECT x AS y FROM t3 ORDER BY y COLLATE nocase;
|
||||
}
|
||||
} {0 {11 33}}
|
||||
do_test resolver01-2.4 {
|
||||
catchsql {
|
||||
SELECT x AS yy FROM t3 ORDER BY y COLLATE nocase;
|
||||
}
|
||||
} {0 {33 11}}
|
||||
do_test resolver01-2.5 {
|
||||
catchsql {
|
||||
SELECT x AS yy FROM t3 ORDER BY yy COLLATE nocase;
|
||||
}
|
||||
} {0 {11 33}}
|
||||
do_test resolver01-2.6 {
|
||||
catchsql {
|
||||
SELECT x AS yy FROM t3 ORDER BY 1 COLLATE nocase;
|
||||
}
|
||||
} {0 {11 33}}
|
||||
|
||||
# But if the form is "ORDER BY expr" then bind more tightly to the
|
||||
# the input column names and only use the output column names if no
|
||||
# input column name matches.
|
||||
#
|
||||
# This is SQL99 behavior, as implemented by PostgreSQL and MS-SQL.
|
||||
# Note that Oracle works differently.
|
||||
#
|
||||
do_test resolver01-3.1 {
|
||||
catchsql {
|
||||
SELECT 3 AS y FROM t1, t2 ORDER BY +y;
|
||||
}
|
||||
} {0 3}
|
||||
} {1 {ambiguous column name: y}}
|
||||
do_test resolver01-3.2 {
|
||||
catchsql {
|
||||
SELECT 2 AS yy FROM t1, t2 ORDER BY +y;
|
||||
}
|
||||
} {1 {ambiguous column name: y}}
|
||||
do_test resolver01-3.3 {
|
||||
catchsql {
|
||||
SELECT x AS y FROM t3 ORDER BY +y;
|
||||
}
|
||||
} {0 {33 11}}
|
||||
do_test resolver01-3.4 {
|
||||
catchsql {
|
||||
SELECT x AS yy FROM t3 ORDER BY +y;
|
||||
}
|
||||
} {0 {33 11}}
|
||||
do_test resolver01-3.5 {
|
||||
catchsql {
|
||||
SELECT x AS yy FROM t3 ORDER BY +yy
|
||||
}
|
||||
} {0 {11 33}}
|
||||
|
||||
# This is the test case given in ticket [f617ea3125e9] (with table name
|
||||
# changed from "t1" to "t4". The behavior of (1) and (3) match with
|
||||
# PostgreSQL, but we intentionally break with PostgreSQL to provide
|
||||
# SQL92 behavior for case (2).
|
||||
#
|
||||
do_execsql_test resolver01-4.1 {
|
||||
CREATE TABLE t4(m CHAR(2));
|
||||
INSERT INTO t4 VALUES('az');
|
||||
INSERT INTO t4 VALUES('by');
|
||||
INSERT INTO t4 VALUES('cx');
|
||||
SELECT '1', substr(m,2) AS m FROM t4 ORDER BY m;
|
||||
SELECT '2', substr(m,2) AS m FROM t4 ORDER BY m COLLATE binary;
|
||||
SELECT '3', substr(m,2) AS m FROM t4 ORDER BY lower(m);
|
||||
} {1 x 1 y 1 z 2 x 2 y 2 z 3 z 3 y 3 x}
|
||||
|
||||
##########################################################################
|
||||
# Test cases for ticket [1c69be2dafc28]: Make sure the GROUP BY binds
|
||||
# more tightly to the input tables in all cases.
|
||||
#
|
||||
# This first case case has been wrong in SQLite for time out of mind.
|
||||
# For SQLite version 3.7.17 the answer was two rows, which is wrong.
|
||||
#
|
||||
do_execsql_test resolver01-5.1 {
|
||||
CREATE TABLE t5(m CHAR(2));
|
||||
INSERT INTO t5 VALUES('ax');
|
||||
INSERT INTO t5 VALUES('bx');
|
||||
INSERT INTO t5 VALUES('cy');
|
||||
SELECT count(*), substr(m,2,1) AS m FROM t5 GROUP BY m ORDER BY 1, 2;
|
||||
} {1 x 1 x 1 y}
|
||||
|
||||
# This case is unambiguous and has always been correct.
|
||||
#
|
||||
do_execsql_test resolver01-5.2 {
|
||||
SELECT count(*), substr(m,2,1) AS mx FROM t5 GROUP BY m ORDER BY 1, 2;
|
||||
} {1 x 1 x 1 y}
|
||||
|
||||
# This case is not allowed in standard SQL, but SQLite allows and does
|
||||
# the sensible thing.
|
||||
#
|
||||
do_execsql_test resolver01-5.3 {
|
||||
SELECT count(*), substr(m,2,1) AS mx FROM t5 GROUP BY mx ORDER BY 1, 2;
|
||||
} {1 y 2 x}
|
||||
do_execsql_test resolver01-5.4 {
|
||||
SELECT count(*), substr(m,2,1) AS mx FROM t5
|
||||
GROUP BY substr(m,2,1) ORDER BY 1, 2;
|
||||
} {1 y 2 x}
|
||||
|
||||
# These test case weere provided in the 2013-08-14 email from Rob Golsteijn
|
||||
# that originally reported the problem of ticket [1c69be2dafc28].
|
||||
#
|
||||
do_execsql_test resolver01-6.1 {
|
||||
CREATE TABLE t61(name);
|
||||
SELECT min(name) FROM t61 GROUP BY lower(name);
|
||||
} {}
|
||||
do_execsql_test resolver01-6.2 {
|
||||
SELECT min(name) AS name FROM t61 GROUP BY lower(name);
|
||||
} {}
|
||||
do_execsql_test resolver01-6.3 {
|
||||
CREATE TABLE t63(name);
|
||||
INSERT INTO t63 VALUES (NULL);
|
||||
INSERT INTO t63 VALUES ('abc');
|
||||
SELECT count(),
|
||||
NULLIF(name,'abc') AS name
|
||||
FROM t63
|
||||
GROUP BY lower(name);
|
||||
} {1 {} 1 {}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
finish_test
|
||||
|
@ -208,15 +208,12 @@ do_test tkt2822-5.4 {
|
||||
|
||||
# In "ORDER BY +b" the term is now an expression rather than
|
||||
# a label. It therefore matches by rule (3) instead of rule (2).
|
||||
#
|
||||
# 2013-04-13: This is busted. Changed to conform to PostgreSQL and
|
||||
# MySQL and Oracle behavior.
|
||||
#
|
||||
do_test tkt2822-5.5 {
|
||||
execsql {
|
||||
SELECT a AS b FROM t3 ORDER BY +b;
|
||||
}
|
||||
} {1 9}
|
||||
} {9 1}
|
||||
|
||||
# Tests for rule 2 in compound queries
|
||||
#
|
||||
|
Loading…
Reference in New Issue
Block a user