When the sqlite3WindowRewrite() routine detects and error, have it convert

the SELECT statement into just "SELECT null" so that it does not leave the
parse tree in a goofy state that can cause problems with subsequent code
before the stack has a chance to unwind and report the error.
Ticket [d87336c81c7d0873]

FossilOrigin-Name: fa58aad48a788802b13a819e49f9b8787f713bbe395c46c7295e821c52c81738
This commit is contained in:
drh 2019-12-25 23:54:21 +00:00
parent b44fec68a5
commit a9ebfe2030
7 changed files with 60 additions and 22 deletions

View File

@ -1,5 +1,5 @@
C Fix\sa\sminor\sperformance\sregression\sfrom\scheck-in\s[401c9d30e06191d9]
D 2019-12-24T21:42:22.593
C When\sthe\ssqlite3WindowRewrite()\sroutine\sdetects\sand\serror,\shave\sit\sconvert\nthe\sSELECT\sstatement\sinto\sjust\s"SELECT\snull"\sso\sthat\sit\sdoes\snot\sleave\sthe\nparse\stree\sin\sa\sgoofy\sstate\sthat\scan\scause\sproblems\swith\ssubsequent\scode\nbefore\sthe\sstack\shas\sa\schance\sto\sunwind\sand\sreport\sthe\serror.\nTicket\s[d87336c81c7d0873]
D 2019-12-25T23:54:21.640
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@ -479,7 +479,7 @@ F src/date.c e1d8ac7102f3f283e63e13867acb0efa33861cf34f0faf4cdbaf9fa7a1eb7041
F src/dbpage.c 135eb3b5e74f9ef74bde5cec2571192c90c86984fa534c88bf4a055076fa19b7
F src/dbstat.c 6c407e549406c10fde9ac3987f6d734459205239ad370369bc5fcd683084a4fa
F src/delete.c a5c59b9c0251cf7682bc52af0d64f09b1aefc6781a63592c8f1136f7b73c66e4
F src/expr.c 518e46716bcf072b41e3e88209965e2495f4c7888f2f698ff00b3e415738912d
F src/expr.c 3a27de3630d2dec266423505f1ad38484096df4b6d80cf5c90076340d6b2b810
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
F src/fkey.c 92a248ec0fa4ed8ab60c98d9b188ce173aaf218f32e7737ba77deb2a684f9847
F src/func.c ed33e38cd642058182a31a3f518f2e34f4bbe53aa483335705c153c4d3e50b12
@ -527,12 +527,12 @@ F src/printf.c 9be6945837c839ba57837b4bc3af349eba630920fa5532aa518816defe42a7d4
F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384
F src/resolve.c 86a7773d2892227ba9ad1721c41bb03c501830f1bf6de5f78dd0062b82e10c9d
F src/rowset.c d977b011993aaea002cab3e0bb2ce50cf346000dff94e944d547b989f4b1fe93
F src/select.c b895d809b93596c828c4cd79f4da96d48bf1969414877bb4313770000ea736cc
F src/select.c 338c1e7e2d88f1ecc47b3f0b1af73522baffe5b6461d86510bec80b70d9eb63f
F src/shell.c.in 4a3a9e1c11847b1904f2b01d087af1c052f660902755abab457cab1756817ded
F src/sqlite.h.in 2a23e8161775253d9cf383c2c6aa559005dc787d350dcb0be67a6c4cc3bd1d19
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h 72af51aa4e912e14cd495fb6e7fac65f0940db80ed950d90911aff292cc47ce2
F src/sqliteInt.h eada1e78b6b950670eb4cc093ce6eb96a7df8bc548cabd7bc6127fa4fbce8ba5
F src/sqliteInt.h 3e235c7a406630bff9fe7183d9af5d4ce21a9b7acb77bf1b82a0caa130a5f687
F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b
F src/status.c 46e7aec11f79dad50965a5ca5fa9de009f7d6bde08be2156f1538a0a296d4d0e
F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34
@ -617,7 +617,7 @@ F src/where.c 58653781a4b31fa16b95b953591fdc1f1ed5ff77574e59b90a27da3819b60a46
F src/whereInt.h 4a296fd4fa79fdcbc2b5e8c1b898901617655811223e1082b899c23ecb092217
F src/wherecode.c bb58d5e6e7f583db5b74e0fd35f1d65fdee67d20553b55cd6098fc3f8148053a
F src/whereexpr.c 4b34be1434183e7bb8a05d4bf42bd53ea53021b0b060936fbd12062b4ff6b396
F src/window.c da010455914c81037dcb5b0c6f4273f8a32c94567865c46a60060b937b018a96
F src/window.c a5b69ea3cd22555d390582771173a68c1b798a0847aef3bd9eb51792bc6fcacb
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
F test/affinity2.test ce1aafc86e110685b324e9a763eab4f2a73f737842ec3b687bd965867de90627
F test/affinity3.test 6a101af2fc945ce2912f6fe54dd646018551710d
@ -1713,7 +1713,7 @@ F test/win32heap.test 10fd891266bd00af68671e702317726375e5407561d859be1aa04696f2
F test/win32lock.test fbf107c91d8f5512be5a5b87c4c42ab9fdd54972
F test/win32longpath.test 169c75a3b2e43481f4a62122510210c67b08f26d
F test/win32nolock.test ac4f08811a562e45a5755e661f45ca85892bdbbc
F test/window1.test 790c9f12bc4c6f789216fb2c38bd1fbf5e191bed8b9a3712326e4af1a50222c0
F test/window1.test 7968f1baa13e4f4399a65a21ae9c324a073c28c684adcda2ddf1ea25741d1faa
F test/window2.tcl 114b217d4ffff891142023cc5f3131b0dae3ad149ac4b45a6ed9e2ad943f8ce2
F test/window2.test dea2ffecb7182a385143ea0eb368b6241ee43c5f971f4ad1c4337029cb1fc10a
F test/window3.tcl acea6e86a4324a210fd608d06741010ca83ded9fde438341cb978c49928faf03
@ -1852,7 +1852,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P ddb10f0374e66886d0681937b14cf0b4f100f03d3955b45b6c508dc6d9e36976
R 5b1079c8a384ce37450b3fecba55c04d
P 76f54ee86777cbf530654323c953388ef64d0608516722d2522be6c859fa1382
R c46405001dbbf37c4a4da195980c58c5
U drh
Z b050346f80259aa216b8caa58ba47eb4
Z 7b421b0b8aa6e2e1e8fb7d8227a85505

View File

@ -1 +1 @@
76f54ee86777cbf530654323c953388ef64d0608516722d2522be6c859fa1382
fa58aad48a788802b13a819e49f9b8787f713bbe395c46c7295e821c52c81738

View File

@ -594,6 +594,7 @@ static void codeVectorCompare(
int addrDone = sqlite3VdbeMakeLabel(pParse);
int isCommuted = ExprHasProperty(pExpr,EP_Commuted);
if( pParse->nErr ) return;
if( nLeft!=sqlite3ExprVectorSize(pRight) ){
sqlite3ErrorMsg(pParse, "row value misused");
return;
@ -2686,8 +2687,10 @@ static char *exprINAffinity(Parse *pParse, Expr *pExpr){
** "sub-select returns N columns - expected M"
*/
void sqlite3SubselectError(Parse *pParse, int nActual, int nExpect){
const char *zFmt = "sub-select returns %d columns - expected %d";
sqlite3ErrorMsg(pParse, zFmt, nActual, nExpect);
if( pParse->nErr==0 ){
const char *zFmt = "sub-select returns %d columns - expected %d";
sqlite3ErrorMsg(pParse, zFmt, nActual, nExpect);
}
}
#endif

View File

@ -84,7 +84,10 @@ struct SortCtx {
/*
** Delete all the content of a Select structure. Deallocate the structure
** itself only if bFree is true.
** itself depending on the value of bFree
**
** If bFree==1, call sqlite3DbFree() on the p object.
** If bFree==0, Leave the first Select object unfreed
*/
static void clearSelect(sqlite3 *db, Select *p, int bFree){
while( p ){
@ -188,6 +191,20 @@ void sqlite3SelectDelete(sqlite3 *db, Select *p){
if( OK_IF_ALWAYS_TRUE(p) ) clearSelect(db, p, 1);
}
/*
** Delete all the substructure for p, but keep p allocated. Redefine
** p to be a single SELECT where every column of the result set has a
** value of NULL.
*/
void sqlite3SelectReset(Parse *pParse, Select *p){
if( ALWAYS(p) ){
clearSelect(pParse->db, p, 0);
memset(&p->iLimit, 0, sizeof(Select) - offsetof(Select,iLimit));
p->pEList = sqlite3ExprListAppend(pParse, 0,
sqlite3ExprAlloc(pParse->db,TK_NULL,0,0));
}
}
/*
** Return a pointer to the right-most SELECT statement in a compound.
*/
@ -2711,9 +2728,9 @@ static int multiSelect(
** it is that we currently need.
*/
assert( unionTab==dest.iSDParm || dest.eDest!=priorOp );
if( dest.eDest!=priorOp ){
assert( p->pEList || db->mallocFailed );
if( dest.eDest!=priorOp && db->mallocFailed==0 ){
int iCont, iBreak, iStart;
assert( p->pEList );
iBreak = sqlite3VdbeMakeLabel(pParse);
iCont = sqlite3VdbeMakeLabel(pParse);
computeLimitRegisters(pParse, p, iBreak);
@ -5738,7 +5755,9 @@ int sqlite3Select(
}
#ifndef SQLITE_OMIT_WINDOWFUNC
if( sqlite3WindowRewrite(pParse, p) ){
rc = sqlite3WindowRewrite(pParse, p);
if( rc ){
assert( pParse->nErr>0 );
goto select_end;
}
#if SELECTTRACE_ENABLED

View File

@ -2918,13 +2918,13 @@ struct Upsert {
** sequences for the ORDER BY clause.
*/
struct Select {
ExprList *pEList; /* The fields of the result */
u8 op; /* One of: TK_UNION TK_ALL TK_INTERSECT TK_EXCEPT */
LogEst nSelectRow; /* Estimated number of result rows */
u32 selFlags; /* Various SF_* values */
int iLimit, iOffset; /* Memory registers holding LIMIT & OFFSET counters */
u32 selId; /* Unique identifier number for this SELECT */
int addrOpenEphm[2]; /* OP_OpenEphem opcodes related to this select */
ExprList *pEList; /* The fields of the result */
SrcList *pSrc; /* The FROM clause */
Expr *pWhere; /* The WHERE clause */
ExprList *pGroupBy; /* The GROUP BY clause */
@ -4092,6 +4092,7 @@ int sqlite3Select(Parse*, Select*, SelectDest*);
Select *sqlite3SelectNew(Parse*,ExprList*,SrcList*,Expr*,ExprList*,
Expr*,ExprList*,u32,Expr*);
void sqlite3SelectDelete(sqlite3*, Select*);
void sqlite3SelectReset(Parse*, Select*);
Table *sqlite3SrcListLookup(Parse*, SrcList*);
int sqlite3IsReadOnly(Parse*, Table*, int);
void sqlite3OpenTable(Parse*, int iCur, int iDb, Table*, int);

View File

@ -1021,6 +1021,9 @@ int sqlite3WindowRewrite(Parse *pParse, Select *p){
pSub->selFlags |= SF_Expanded;
pTab2 = sqlite3ResultSetOfSelect(pParse, pSub, SQLITE_AFF_NONE);
if( pTab2==0 ){
/* Might actually be some other kind of error, but in that case
** pParse->nErr will be set, so if SQLITE_NOMEM is set, we will get
** the correct error message regardless. */
rc = SQLITE_NOMEM;
}else{
memcpy(pTab, pTab2, sizeof(Table));
@ -1039,9 +1042,12 @@ int sqlite3WindowRewrite(Parse *pParse, Select *p){
sqlite3DbFree(db, pTab);
}
if( rc && pParse->nErr==0 ){
assert( pParse->db->mallocFailed );
return sqlite3ErrorToParser(pParse->db, SQLITE_NOMEM);
if( rc ){
if( pParse->nErr==0 ){
assert( pParse->db->mallocFailed );
sqlite3ErrorToParser(pParse->db, SQLITE_NOMEM);
}
sqlite3SelectReset(pParse, p);
}
return rc;
}

View File

@ -1329,7 +1329,7 @@ do_execsql_test 37.20 {
SELECT c FROM v0 WHERE c BETWEEN -10 AND 20;
} {}
# 2019-20-20 mrigger reported problem with a FILTER clause on an aggregate
# 2019-12-20 mrigger reported problem with a FILTER clause on an aggregate
# in a join.
#
reset_db
@ -1361,5 +1361,14 @@ do_execsql_test 39.4 {
SELECT * FROM t0 WHERE (t0.c0, 1) IN(SELECT NTILE(1) OVER(), 0 FROM t0);
}
# 2019-12-25 ticket d87336c81c7d0873
#
reset_db
do_catchsql_test 40.1 {
CREATE VIRTUAL TABLE t0 USING rtree(c0, c1, c2);
SELECT * FROM t0
WHERE ((0,0) IN (SELECT COUNT(*),LAG(5)OVER(PARTITION BY 0) FROM t0),0)<=(c1,0);
} {1 {1st ORDER BY term out of range - should be between 1 and 3}}
finish_test