From: dan Date: Mon, 19 Aug 2019 17:26:32 +0000 (+0000) Subject: Prevent NULLS FIRST/LAST from being used in CREATE INDEX and other statements. X-Git-Tag: version-3.30.0~101^2~16 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=9105fd51893062a8503c8850e5d88ad49de28495;p=thirdparty%2Fsqlite.git Prevent NULLS FIRST/LAST from being used in CREATE INDEX and other statements. FossilOrigin-Name: bb9767a287097a615aeb4abdba689b10e1a1c36c016c8e55905b508075e62c86 --- diff --git a/manifest b/manifest index 2584ef1bad..b8cb71e76a 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\stests\sto\sensure\sthat\sthis\sbranch\sreally\sdoes\sfix\sticket\s[f8a7060ece]. -D 2019-08-17T18:16:59.747 +C Prevent\sNULLS\sFIRST/LAST\sfrom\sbeing\sused\sin\sCREATE\sINDEX\sand\sother\sstatements. +D 2019-08-19T17:26:32.202 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -467,7 +467,7 @@ F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6 F src/btree.c 5cf994516c1b74928b9d15971573a8bc8595e1afec129184099976da603402de F src/btree.h c11446f07ec0e9dc85af8041cb0855c52f5359c8b2a43e47e02a685282504d89 F src/btreeInt.h 6111c15868b90669f79081039d19e7ea8674013f907710baa3c814dc3f8bfd3f -F src/build.c 39f448776a17f202e0d205bda9e2b0bb80853503268ceb36a48ff6d0d963fd7b +F src/build.c da5d5d82eb53cb004e9120277cfe93a9c3dd294871eae3d728ebd0faee84d969 F src/callback.c 25dda5e1c2334a367b94a64077b1d06b2553369f616261ca6783c48bcb6bda73 F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e F src/ctime.c 1b0724e66f95f33b160b1af85caaf9cceb325d22abf39bd24df4f54a73982251 @@ -475,7 +475,7 @@ F src/date.c e1d8ac7102f3f283e63e13867acb0efa33861cf34f0faf4cdbaf9fa7a1eb7041 F src/dbpage.c 135eb3b5e74f9ef74bde5cec2571192c90c86984fa534c88bf4a055076fa19b7 F src/dbstat.c c12833de69cb655751487d2c5a59607e36be1c58ba1f4bd536609909ad47b319 F src/delete.c d08c9e01a2664afd12edcfa3a9c6578517e8ff8735f35509582693adbe0edeaf -F src/expr.c bef29885d12c1b7ec4353fc07f61f18d044430fc4f9c1476fd5098a5834d17bd +F src/expr.c 0a3442b0df31f1eca86b2aa3634f61bca5f1a6781f543ca9a0d87e29961f7f4f F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007 F src/fkey.c 6b79f4c2447691aa9ac86e2a6a774b65f3b3dd053d4220a4893051a0de20f82e F src/func.c 4ee36219698d50d672a28eca4adb0fd6b92e607a1883d318315e0d2fd5044467 @@ -484,7 +484,7 @@ F src/hash.c 8d7dda241d0ebdafb6ffdeda3149a412d7df75102cecfc1021c98d6219823b19 F src/hash.h 9d56a9079d523b648774c1784b74b89bd93fac7b365210157482e4319a468f38 F src/hwtime.h 747c1bbe9df21a92e9c50f3bbec1de841dc5e5da F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71 -F src/insert.c c2194dd2886337b870226fcb31c13e7df8c4b5e0ea85140e510a6f1daf1ad65b +F src/insert.c 81eec6acf4fbf0942bbab6804fe50df3e109acba40b8bbfb00fec9a14d0715a6 F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa F src/loadext.c 22afc33c3a61b4fd80a60a54f1882688371e6bc64685df2696b008fce65a999c F src/main.c 51c55eb579eac4180bfcc6242741084710911350d2cd0c3fdd0f9fde55442128 @@ -528,7 +528,7 @@ F src/shell.c.in d2465e7747a014bd48a75c1bcf648e8e6cb46832dcc6e1293c5f285bc5542e8 F src/sqlite.h.in 5445ee2844c15bf277ebb64e910b56b0e6fb9377f184a81cd9bd78f0946be8c8 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 9ecc93b8493bd20c0c07d52e2ac0ed8bab9b549c7f7955b59869597b650dd8b5 -F src/sqliteInt.h ed60d41dbb600515abdd5bbfd7f826f0238153d7d70fc3383f5e1179e131b3b8 +F src/sqliteInt.h 84d3b381b515acfd098152bb2c9a91fb3ea72b55e15dfc2b86c031da222a910c F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b F src/status.c 46e7aec11f79dad50965a5ca5fa9de009f7d6bde08be2156f1538a0a296d4d0e F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34 @@ -589,7 +589,7 @@ F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9 F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c F src/tokenize.c d3615f0cbe4db5949503bf5916f3cd4fa5de855d5b4ef560f3b6dd5629423a1e F src/treeview.c fc8c6c0a8a26afb3a97e3f844d65403dd27cf1450baf4415034fa4ccf00c4d7e -F src/trigger.c 2305271878e95addc1c01361e5e8e342e87cba5efefdd7d3032687e5d67e05d1 +F src/trigger.c d115eb6c1e2a22e116e0c6e34c35e5b2029238238e05b9708fe1567434da3230 F src/update.c 3cb9150d2cf661d938e2f1b1749945f3faa767f88febdb739ab1793bbf895ff2 F src/upsert.c 0dd81b40206841814d46942a7337786932475f085716042d0cb2fc7791bf8ca4 F src/utf.c 2f0fac345c7660d5c5bd3df9e9d8d33d4c27f366bcfb09e07443064d751a0507 @@ -1182,7 +1182,7 @@ F test/notify2.test 2ecabaa1305083856b7c39cf32816b612740c161 F test/notify3.test 10ff25cde502e72a92053a2f215d64bece4ef934 F test/notnull.test a37b663d5bb728d66fc182016613fb8e4a0a4bbf3d75b8876a7527f7d4ed3f18 F test/null.test 0dcce4f04284ec66108c503327ad6d224c0752b3 -F test/nulls1.test 522f0da68881b6ac616b1361fbd5a9897bd366597809495143968af743e3318c +F test/nulls1.test 6d226787ee0d479bc009e00b7fa812fb261fbb3eab764de18ecb988f4ec69f4a F test/numcast.test 5d126f7f581432e86a90d1e35cac625164aec4a1 F test/numindex1.test 20a5450d4b056e48cd5db30e659f13347a099823 F test/offset1.test f06b83657bcf26f9ce805e67450e189e282143b2 @@ -1837,7 +1837,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 b49df1fe9b7174ebc60023179e8da628c926e59df3dc01b15d4a28e17807bb97 -R 45771ddb0f2c68cf3dbfa90b9e4149c6 +P f892066425671a8a0ac923e3ad4744677f6434a66f97b91afa8141f11f179975 +R 453ca41ba88968d27d033b2c6ac5c131 U dan -Z 6452b2b9b9aca3f08bbef29f8e41e25a +Z d9760a7ecfe79d11a5b817a651ccacbf diff --git a/manifest.uuid b/manifest.uuid index b6a8464c5f..05637d33b1 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -f892066425671a8a0ac923e3ad4744677f6434a66f97b91afa8141f11f179975 \ No newline at end of file +bb9767a287097a615aeb4abdba689b10e1a1c36c016c8e55905b508075e62c86 \ No newline at end of file diff --git a/src/build.c b/src/build.c index 3f9ab0b975..106b995d31 100644 --- a/src/build.c +++ b/src/build.c @@ -3153,6 +3153,27 @@ Index *sqlite3AllocateIndexObject( return p; } +/* +** If expression list pList contains an expression that was parsed with +** an explicit "NULLS FIRST" or "NULLS LAST" clause, leave an error in +** pParse and return non-zero. Otherwise, return zero. +*/ +int sqlite3HasExplicitNulls(Parse *pParse, ExprList *pList){ + if( pList ){ + int i; + for(i=0; inExpr; i++){ + if( pList->a[i].bNulls ){ + u8 sf = pList->a[i].sortFlags; + sqlite3ErrorMsg(pParse, "unsupported use of NULLS %s", + (sf==0 || sf==3) ? "FIRST" : "LAST" + ); + return 1; + } + } + } + return 0; +} + /* ** Create a new index for an SQL table. pName1.pName2 is the name of the index ** and pTblList is the name of the table that is to be indexed. Both will @@ -3204,6 +3225,9 @@ void sqlite3CreateIndex( if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){ goto exit_create_index; } + if( sqlite3HasExplicitNulls(pParse, pList) ){ + goto exit_create_index; + } /* ** Find the table that is to be indexed. Return early if not found. diff --git a/src/expr.c b/src/expr.c index c5072aa615..6948c5a0fe 100644 --- a/src/expr.c +++ b/src/expr.c @@ -1653,6 +1653,7 @@ vector_append_error: ** Set the sort order for the last element on the given ExprList. */ void sqlite3ExprListSetSortOrder(ExprList *p, int iSortOrder, int eNulls){ + struct ExprList_item *pItem; if( p==0 ) return; assert( p->nExpr>0 ); @@ -1666,10 +1667,18 @@ void sqlite3ExprListSetSortOrder(ExprList *p, int iSortOrder, int eNulls){ || eNulls==SQLITE_SO_DESC ); - if( iSortOrder==SQLITE_SO_UNDEFINED ) iSortOrder = SQLITE_SO_ASC; - p->a[p->nExpr-1].sortFlags = (u8)iSortOrder; - if( eNulls!=SQLITE_SO_UNDEFINED && iSortOrder!=eNulls ){ - p->a[p->nExpr-1].sortFlags |= KEYINFO_ORDER_BIGNULL; + pItem = &p->a[p->nExpr-1]; + assert( pItem->bNulls==0 ); + if( iSortOrder==SQLITE_SO_UNDEFINED ){ + iSortOrder = SQLITE_SO_ASC; + } + pItem->sortFlags = (u8)iSortOrder; + + if( eNulls!=SQLITE_SO_UNDEFINED ){ + pItem->bNulls = 1; + if( iSortOrder!=eNulls ){ + pItem->sortFlags |= KEYINFO_ORDER_BIGNULL; + } } } diff --git a/src/insert.c b/src/insert.c index 53d7e89b2a..04d3d580f5 100644 --- a/src/insert.c +++ b/src/insert.c @@ -833,6 +833,9 @@ void sqlite3Insert( pTab->zName); goto insert_cleanup; } + if( sqlite3HasExplicitNulls(pParse, pUpsert->pUpsertTarget) ){ + goto insert_cleanup; + } pTabList->a[0].iCursor = iDataCur; pUpsert->pUpsertSrc = pTabList; pUpsert->regData = regData; diff --git a/src/sqliteInt.h b/src/sqliteInt.h index c47cc6ffc7..b777409179 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -2605,11 +2605,12 @@ struct ExprList { Expr *pExpr; /* The parse tree for this expression */ char *zName; /* Token associated with this expression */ char *zSpan; /* Original text of the expression */ - u8 sortFlags; /* 1 for DESC or 0 for ASC */ + u8 sortFlags; /* Mask of KEYINFO_ORDER_* flags */ unsigned done :1; /* A flag to indicate when processing is finished */ unsigned bSpanIsTab :1; /* zSpan holds DB.TABLE.COLUMN */ unsigned reusable :1; /* Constant expression is reusable */ unsigned bSorterRef :1; /* Defer evaluation until after sorting */ + unsigned bNulls: 1; /* True if explicit "NULLS FIRST/LAST" */ union { struct { u16 iOrderByCol; /* For ORDER BY, column number in result set */ @@ -4366,6 +4367,7 @@ void sqlite3KeyInfoUnref(KeyInfo*); KeyInfo *sqlite3KeyInfoRef(KeyInfo*); KeyInfo *sqlite3KeyInfoOfIndex(Parse*, Index*); KeyInfo *sqlite3KeyInfoFromExprList(Parse*, ExprList*, int, int); +int sqlite3HasExplicitNulls(Parse*, ExprList*); #ifdef SQLITE_DEBUG int sqlite3KeyInfoIsWriteable(KeyInfo*); diff --git a/src/trigger.c b/src/trigger.c index 989df9678a..84f80c23ee 100644 --- a/src/trigger.c +++ b/src/trigger.c @@ -463,6 +463,9 @@ TriggerStep *sqlite3TriggerInsertStep( pTriggerStep->pIdList = pColumn; pTriggerStep->pUpsert = pUpsert; pTriggerStep->orconf = orconf; + if( pUpsert ){ + sqlite3HasExplicitNulls(pParse, pUpsert->pUpsertTarget); + } }else{ testcase( pColumn ); sqlite3IdListDelete(db, pColumn); diff --git a/test/nulls1.test b/test/nulls1.test index 866ed2b296..dc7fb6e86b 100644 --- a/test/nulls1.test +++ b/test/nulls1.test @@ -83,5 +83,43 @@ do_execsql_test 2.2 { 1 1 1 } +#------------------------------------------------------------------------- +reset_db +do_execsql_test 3.0 { + CREATE TABLE t1(a, b, c, d, UNIQUE (b)); +} +foreach {tn sql err} { + 1 { CREATE INDEX i1 ON t1(a ASC NULLS LAST) } LAST + 2 { CREATE INDEX i1 ON t1(a ASC NULLS FIRST) } FIRST + 3 { CREATE INDEX i1 ON t1(a, b ASC NULLS LAST) } LAST + 4 { CREATE INDEX i1 ON t1(a, b ASC NULLS FIRST) } FIRST + 5 { CREATE INDEX i1 ON t1(a DESC NULLS LAST) } LAST + 6 { CREATE INDEX i1 ON t1(a DESC NULLS FIRST) } FIRST + 7 { CREATE INDEX i1 ON t1(a, b DESC NULLS LAST) } LAST + 8 { CREATE INDEX i1 ON t1(a, b DESC NULLS FIRST) } FIRST + 9 { CREATE TABLE t2(a, b, PRIMARY KEY(a DESC, b NULLS FIRST)) } FIRST + 10 { CREATE TABLE t2(a, b, UNIQUE(a DESC NULLS FIRST, b)) } FIRST + 11 { INSERT INTO t1 VALUES(1, 2, 3, 4) + ON CONFLICT (b DESC NULLS LAST) DO UPDATE SET a = a+1 } LAST + 12 { + CREATE TRIGGER tr1 AFTER INSERT ON t1 BEGIN + INSERT INTO t1 VALUES(1, 2, 3, 4) + ON CONFLICT (b DESC NULLS FIRST) DO UPDATE SET a = a+1; + END + } FIRST +} { + do_catchsql_test 3.1.$tn $sql "1 {unsupported use of NULLS $err}" +} + +do_execsql_test 3.2 { + CREATE TABLE first(nulls, last); + INSERT INTO first(last, nulls) VALUES(100,200), (300,400), (200,300); + SELECT * FROM first ORDER BY nulls; +} { + 200 100 + 300 200 + 400 300 +} + finish_test