From 50c44200300f77e5415e8fe8c3475d53830a9ff2 Mon Sep 17 00:00:00 2001 From: drh <> Date: Sat, 18 Jan 2025 21:00:19 +0000 Subject: [PATCH 1/2] Add support for automatic query-time indexes on WITHOUT ROWID tables. FossilOrigin-Name: 89c4cbd9529081941d7283a401c4a8d71b241f4577ebf6d3eb2ebe5a1cf92f2e --- manifest | 17 ++++++++++------- manifest.uuid | 2 +- src/where.c | 23 +++++++++++++++++++---- 3 files changed, 30 insertions(+), 12 deletions(-) diff --git a/manifest b/manifest index e7d438afbf..dbd4e38927 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C When\srunning\smake\sinstall,\savoid\sthe\s-s\s(strip)\sflag\swhen\scross-compiling,\sas\sit\sonly\sworks\sfor\sthe\sbuild\splatform.\sReported\sin\s[forum:9a67df63eda9925c|forum\spost\s9a67df63eda9925c]. -D 2025-01-18T13:51:01.877 +C Add\ssupport\sfor\sautomatic\squery-time\sindexes\son\sWITHOUT\sROWID\stables. +D 2025-01-18T21:00:19.369 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md e108e1e69ae8e8a59e93c455654b8ac9356a11720d3345df2a4743e9590fb20d @@ -862,7 +862,7 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/wal.c 4e6181d8780ab0af2e1388d0754cbe6f2f04593d2b1ab6c41699a89942fd8997 F src/wal.h ba252daaa94f889f4b2c17c027e823d9be47ce39da1d3799886bbd51f0490452 F src/walker.c d5006d6b005e4ea7302ad390957a8d41ed83faa177e412f89bc5600a7462a014 -F src/where.c 7aa91f806d19d254d47763564e355cca50d1787d93fc0a62c7d5361d8dfbce70 +F src/where.c b09334881ab87dfdb1d2dbc71a8cf97f345834d36509344207a133f0e6b86161 F src/whereInt.h 2b0804f300c7f65de4046a1d81c65f01b208d6c08950ccd1fa6b8c16162a8af7 F src/wherecode.c 0c3d3199a2b769a5e2bb70feb5003dc85b3d86842ecaf903a47f2b4205ca5dab F src/whereexpr.c 0f93a29cabd3a338d09a1f5c6770620a1ac51ec1157f3229502a7e7767c60b6f @@ -2207,8 +2207,11 @@ F tool/version-info.c 3b36468a90faf1bbd59c65fd0eb66522d9f941eedd364fabccd7227350 F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee87c1b31a7 F tool/warnings.sh 49a486c5069de041aedcbde4de178293e0463ae9918ecad7539eedf0ec77a139 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 0852c57ee2768224af79910e6f26e70a4962651dae0f8b45cbfc847e6707d7bb -R ed0f0a3d6dea2dbb296ffb05bcf1dd67 -U stephan -Z b7991c6ad22e45c5f184f51dda631f10 +P 230e49c10e3aa6fe9c487a1e026016a8bf97f7e736e7477d5976d987da5e83cf +R 1eb7d22a051c22dd4afc1e0246916027 +T *branch * without-rowid-autoidx +T *sym-without-rowid-autoidx * +T -sym-trunk * +U drh +Z eca129c2aba163fe6547f234a58ed149 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index dbbf089777..d320276785 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -230e49c10e3aa6fe9c487a1e026016a8bf97f7e736e7477d5976d987da5e83cf +89c4cbd9529081941d7283a401c4a8d71b241f4577ebf6d3eb2ebe5a1cf92f2e diff --git a/src/where.c b/src/where.c index b3f177fb40..8af00b96a3 100644 --- a/src/where.c +++ b/src/where.c @@ -1080,6 +1080,19 @@ static SQLITE_NOINLINE void constructAutomaticIndex( }else{ extraCols = pSrc->colUsed & (~idxCols | MASKBIT(BMS-1)); } + if( !HasRowid(pTable) ){ + /* For WITHOUT ROWID tables, ensure that all PRIMARY KEY columns are + ** either in the idxCols mask or in the extraCols mask */ + for(i=0; inCol; i++){ + if( (pTable->aCol[i].colFlags & COLFLAG_PRIMKEY)==0 ) continue; + if( i>=BMS-1 ){ + extraCols |= MASKBIT(BMS-1); + break; + } + if( idxCols & MASKBIT(i) ) continue; + extraCols |= MASKBIT(i); + } + } mxBitCol = MIN(BMS-1,pTable->nCol); testcase( pTable->nCol==BMS-1 ); testcase( pTable->nCol==BMS-2 ); @@ -1091,7 +1104,8 @@ static SQLITE_NOINLINE void constructAutomaticIndex( } /* Construct the Index object to describe this index */ - pIdx = sqlite3AllocateIndexObject(pParse->db, nKeyCol+1, 0, &zNotUsed); + pIdx = sqlite3AllocateIndexObject(pParse->db, nKeyCol+HasRowid(pTable), + 0, &zNotUsed); if( pIdx==0 ) goto end_auto_index_create; pLoop->u.btree.pIndex = pIdx; pIdx->zName = "auto-index"; @@ -1147,8 +1161,10 @@ static SQLITE_NOINLINE void constructAutomaticIndex( } } assert( n==nKeyCol ); - pIdx->aiColumn[n] = XN_ROWID; - pIdx->azColl[n] = sqlite3StrBINARY; + if( HasRowid(pTable) ){ + pIdx->aiColumn[n] = XN_ROWID; + pIdx->azColl[n] = sqlite3StrBINARY; + } /* Create the automatic index */ explainAutomaticIndex(pParse, pIdx, pPartial!=0, &addrExp); @@ -3923,7 +3939,6 @@ static int whereLoopAddBtree( && (pWInfo->pParse->db->flags & SQLITE_AutoIndex)!=0 && !pSrc->fg.isIndexedBy /* Has no INDEXED BY clause */ && !pSrc->fg.notIndexed /* Has no NOT INDEXED clause */ - && HasRowid(pTab) /* Not WITHOUT ROWID table. (FIXME: Why not?) */ && !pSrc->fg.isCorrelated /* Not a correlated subquery */ && !pSrc->fg.isRecursive /* Not a recursive common table expression. */ && (pSrc->fg.jointype & JT_RIGHT)==0 /* Not the right tab of a RIGHT JOIN */ From 0f4de9bf9deabc2246fc9f076c22e83322a339b0 Mon Sep 17 00:00:00 2001 From: drh <> Date: Sat, 18 Jan 2025 21:19:02 +0000 Subject: [PATCH 2/2] Add a simple test case (many more are coming soon to TH3). Fix an obsolete assert(). FossilOrigin-Name: aa829a131a3431791083cf60d9cf00e7b3c0fafdd39a23e761b629a2287ab875 --- manifest | 17 +++++++---------- manifest.uuid | 2 +- src/where.c | 2 +- test/autoindex1.test | 28 ++++++++++++++++++++++++++++ 4 files changed, 37 insertions(+), 12 deletions(-) diff --git a/manifest b/manifest index dbd4e38927..acd3f5611e 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\ssupport\sfor\sautomatic\squery-time\sindexes\son\sWITHOUT\sROWID\stables. -D 2025-01-18T21:00:19.369 +C Add\sa\ssimple\stest\scase\s(many\smore\sare\scoming\ssoon\sto\sTH3).\s\sFix\san\sobsolete\nassert(). +D 2025-01-18T21:19:02.129 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md e108e1e69ae8e8a59e93c455654b8ac9356a11720d3345df2a4743e9590fb20d @@ -862,7 +862,7 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/wal.c 4e6181d8780ab0af2e1388d0754cbe6f2f04593d2b1ab6c41699a89942fd8997 F src/wal.h ba252daaa94f889f4b2c17c027e823d9be47ce39da1d3799886bbd51f0490452 F src/walker.c d5006d6b005e4ea7302ad390957a8d41ed83faa177e412f89bc5600a7462a014 -F src/where.c b09334881ab87dfdb1d2dbc71a8cf97f345834d36509344207a133f0e6b86161 +F src/where.c 521472bb0c7cfdd65a9b5b92d44f921e3e0a26a1996cc0416cf53e25301820d2 F src/whereInt.h 2b0804f300c7f65de4046a1d81c65f01b208d6c08950ccd1fa6b8c16162a8af7 F src/wherecode.c 0c3d3199a2b769a5e2bb70feb5003dc85b3d86842ecaf903a47f2b4205ca5dab F src/whereexpr.c 0f93a29cabd3a338d09a1f5c6770620a1ac51ec1157f3229502a7e7767c60b6f @@ -925,7 +925,7 @@ F test/auth2.test 9eb7fce9f34bf1f50d3f366fb3e606be5a2000a1 F test/auth3.test 76d20a7fa136d63bcfcf8bcb65c0b1455ed71078d81f22bcd0550d3eb18594ab F test/autoanalyze1.test b9cc3f32a990fa56669b668d237c6d53e983554ae80c0604992e18869a0b2dec F test/autoinc.test 997d6f185f138229dc4251583a1d04816423dddc2fc034871a01aeb1d728cb39 -F test/autoindex1.test 714cac6e60beeb5a26ed346dd46505ba60b5a5597e9122c9ed3a55f89a922aa4 +F test/autoindex1.test 65931519206bbec71948b11e125af0656435a0937973fe5fed70d776a712911f F test/autoindex2.test 12ef578928102baaa0dc23ad397601a2f4ecb0df F test/autoindex3.test ca502c8050166ac6107a7b4fe4e951f4d3270a23a958af02b14f1b962b83c4b6 F test/autoindex4.test 3c2105e9172920e26f950ba3c5823e4972190e022c1e6f260ba476b0af24c593 @@ -2207,11 +2207,8 @@ F tool/version-info.c 3b36468a90faf1bbd59c65fd0eb66522d9f941eedd364fabccd7227350 F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee87c1b31a7 F tool/warnings.sh 49a486c5069de041aedcbde4de178293e0463ae9918ecad7539eedf0ec77a139 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 230e49c10e3aa6fe9c487a1e026016a8bf97f7e736e7477d5976d987da5e83cf -R 1eb7d22a051c22dd4afc1e0246916027 -T *branch * without-rowid-autoidx -T *sym-without-rowid-autoidx * -T -sym-trunk * +P 89c4cbd9529081941d7283a401c4a8d71b241f4577ebf6d3eb2ebe5a1cf92f2e +R 060bc82586424a9cc221e972d5251271 U drh -Z eca129c2aba163fe6547f234a58ed149 +Z 18819fcf6e705c7a88ab29e3c059c242 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index d320276785..1691c3d936 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -89c4cbd9529081941d7283a401c4a8d71b241f4577ebf6d3eb2ebe5a1cf92f2e +aa829a131a3431791083cf60d9cf00e7b3c0fafdd39a23e761b629a2287ab875 diff --git a/src/where.c b/src/where.c index 8af00b96a3..b867e615f7 100644 --- a/src/where.c +++ b/src/where.c @@ -949,7 +949,7 @@ static void explainAutomaticIndex( sqlite3_str *pStr = sqlite3_str_new(pParse->db); sqlite3_str_appendf(pStr,"CREATE AUTOMATIC INDEX ON %s(", pTab->zName); assert( pIdx->nColumn>1 ); - assert( pIdx->aiColumn[pIdx->nColumn-1]==XN_ROWID ); + assert( pIdx->aiColumn[pIdx->nColumn-1]==XN_ROWID || !HasRowid(pTab) ); for(ii=0; ii<(pIdx->nColumn-1); ii++){ const char *zName = 0; int iCol = pIdx->aiColumn[ii]; diff --git a/test/autoindex1.test b/test/autoindex1.test index b294a2721f..1c8ce007f0 100644 --- a/test/autoindex1.test +++ b/test/autoindex1.test @@ -563,4 +563,32 @@ do_execsql_test autoindex-1120 { SELECT * FROM t1 LEFT JOIN t2 ON (t2.c=+t1.a) LEFT JOIN t3 ON (t2.d IS NULL); } {1 1 1 2 {} {}} +# 2025-01-18 +# Added support for automatic indexes on WITHOUT ROWID tables. +# +reset_db +do_execsql_test autoindex-1200 { + CREATE TABLE t1(a INT, b INT, x INT, PRIMARY KEY(a,b)) WITHOUT ROWID; + INSERT INTO t1 VALUES(1,2,90),(1,3,91),(1,4,92); + CREATE TABLE t2a(c INTEGER PRIMARY KEY, i1 INT); + CREATE TABLE t2b(i1 INTEGER PRIMARY KEY, d INT); + CREATE VIEW t2(c,d) AS SELECT c, d FROM t2a NATURAL JOIN t2b; + INSERT INTO t2a VALUES(3,93),(4,94),(5,95),(6,96),(7,97); + INSERT INTO t2b VALUES(91,11),(92,22),(93,33),(94,44),(95,55); + CREATE TABLE dual(dummy TEXT); + INSERT INTO dual(dummy) VALUES('x'); +} +db null NULL +do_execsql_test autoindex-1210 { + SELECT t1.*, t2.* FROM t2 LEFT OUTER JOIN t1 ON b=c ORDER BY +b; +} { + NULL NULL NULL 5 55 + 1 3 91 3 33 + 1 4 92 4 44 +} +do_execsql_test autoindex-1211 { + EXPLAIN QUERY PLAN + SELECT t1.*, t2.* FROM t2 LEFT OUTER JOIN t1 ON b=c ORDER BY +b; +} {/SEARCH t1 USING AUTOMATIC COVERING INDEX/} + finish_test