From 81a23623d8790fca64f6e6551f59a2d4694dbf75 Mon Sep 17 00:00:00 2001 From: drh <> Date: Fri, 8 Apr 2022 15:11:10 +0000 Subject: [PATCH 1/4] Improved explanation and commentary on the sqlite3JoinType() routine. One of the error messages changes slightly, but besides that everything works the same. FossilOrigin-Name: 48f2e5a1fbaa8ceb32e08066766be74233b0c67ab430bbf7adfdff42cdb7b8ec --- manifest | 12 ++++----- manifest.uuid | 2 +- src/select.c | 75 +++++++++++++++++++++++++++++++++++++++++---------- 3 files changed, 68 insertions(+), 21 deletions(-) diff --git a/manifest b/manifest index 9e29deaa06..a2472f06dc 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\stwo\sunreachable\sbranches\sintroduced\sby\sthe\srecent\nsqlite3TriggersExist()\soptimization. -D 2022-04-07T20:45:38.697 +C Improved\sexplanation\sand\scommentary\son\sthe\ssqlite3JoinType()\sroutine.\s\sOne\nof\sthe\serror\smessages\schanges\sslightly,\sbut\sbesides\sthat\severything\sworks\nthe\ssame. +D 2022-04-08T15:11:10.072 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -552,7 +552,7 @@ F src/printf.c 05d8dfd2018bc4fc3ddb8b37eb97ccef7abf985643fa1caebdcf2916ca90fa32 F src/random.c 097dc8b31b8fba5a9aca1697aeb9fd82078ec91be734c16bffda620ced7ab83c F src/resolve.c 18d99e7146852d6064559561769fcca0743eb32b14a97da6dbed373a30ee0e76 F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92 -F src/select.c d6c04eb93395024af80f61a8c278a33c2a0333aeb7d57bb6aa737a6f1c4af4b8 +F src/select.c 7c106b3f36d483242b0a9c696614cd53d6f29e1ac81da6a3f0e9ea92f4211cc3 F src/shell.c.in 1a8fbf932ecd582b1a5f66c1e8294f92c30d954616f5c7cc54c9623fcdbb028d F src/sqlite.h.in 2a35f62185eb5e7ecc64a2f68442b538ce9be74f80f28a00abc24837edcf1c17 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 @@ -1945,8 +1945,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P c2965fea9df7076b235d3eadaf84f0a36242476d0329030b0e57557b66e2540c -R 07d0b0c26e9cd2798bbb00ddbafc6a3b +P 1b5475d212cf9de0bff69eee8c607b4fcd8e04bf4df72171429e7609c4153951 +R 931142dc24337bfedaa0369d45a2c00c U drh -Z 93237070ff101cf9292ceb1ee884c28a +Z 277112caa7eb0641987ae3d1eca17748 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 55edbcf9bb..b27079fd83 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -1b5475d212cf9de0bff69eee8c607b4fcd8e04bf4df72171429e7609c4153951 \ No newline at end of file +48f2e5a1fbaa8ceb32e08066766be74233b0c67ab430bbf7adfdff42cdb7b8ec \ No newline at end of file diff --git a/src/select.c b/src/select.c index 989446af61..7ac23bd388 100644 --- a/src/select.c +++ b/src/select.c @@ -204,6 +204,52 @@ static Select *findRightmost(Select *p){ ** ** If an illegal or unsupported join type is seen, then still return ** a join type, but put an error in the pParse structure. +** +** These are the valid join types: +** +** +** pA pB pC Return Value +** ------- ----- ----- ------------ +** CROSS - - JT_CROSS +** INNER - - JT_INNER +** LEFT - - JT_LEFT|JT_OUTER +** LEFT OUTER - JT_LEFT|JT_OUTER +** RIGHT - - JT_RIGHT|JT_OUTER +** RIGHT OUTER - JT_RIGHT|JT_OUTER +** FULL - - JT_LEFT|JT_RIGHT|JT_OUTER +** FULL OUTER - JT_LEFT|JT_RIGHT|JT_OUTER +** NATURAL INNER - JT_NATURAL|JT_INNER +** NATURAL LEFT - JT_NATURAL|JT_LEFT|JT_OUTER +** NATURAL LEFT OUTER JT_NATURAL|JT_LEFT|JT_OUTER +** NATURAL RIGHT - JT_NATURAL|JT_RIGHT|JT_OUTER +** NATURAL RIGHT OUTER JT_NATURAL|JT_RIGHT|JT_OUTER +** NATURAL FULL - JT_NATURAL|JT_LEFT|JT_RIGHT +** NATURAL FULL OUTER JT_NATRUAL|JT_LEFT|JT_RIGHT +** +** To preserve historical compatibly, SQLite also accepts a variety +** of other non-standard and in many cases non-sensical join types. +** This routine makes as much sense at it can from the nonsense join +** type and returns a result. Examples of accepted nonsense join types +** include but are not limited to: +** +** INNER CROSS JOIN -> same as JOIN +** NATURAL CROSS JOIN -> same as NATURAL JOIN +** OUTER LEFT JOIN -> same as LEFT JOIN +** LEFT NATURAL JOIN -> same as NATURAL LEFT JOIN +** LEFT RIGHT JOIN -> same as FULL JOIN +** RIGHT OUTER FULL JOIN -> same as FULL JOIN +** CROSS CROSS CROSS JOIN -> same as JOIN +** +** The only restrictions on the join type name are: +** +** * "INNER" cannot appear together with "OUTER", "LEFT", "RIGHT", +** or "FULL". +** +** * "CROSS" cannot appear together with "OUTER", "LEFT", "RIGHT, +** or "FULL". +** +** * If "OUTER" is present then there must also be one of +** "LEFT", "RIGHT", or "FULL" */ int sqlite3JoinType(Parse *pParse, Token *pA, Token *pB, Token *pC){ int jointype = 0; @@ -216,13 +262,13 @@ int sqlite3JoinType(Parse *pParse, Token *pA, Token *pB, Token *pC){ u8 nChar; /* Length of the keyword in characters */ u8 code; /* Join type mask */ } aKeyword[] = { - /* natural */ { 0, 7, JT_NATURAL }, - /* left */ { 6, 4, JT_LEFT|JT_OUTER }, - /* outer */ { 10, 5, JT_OUTER }, - /* right */ { 14, 5, JT_RIGHT|JT_OUTER }, - /* full */ { 19, 4, JT_LEFT|JT_RIGHT|JT_OUTER }, - /* inner */ { 23, 5, JT_INNER }, - /* cross */ { 28, 5, JT_INNER|JT_CROSS }, + /* (0) natural */ { 0, 7, JT_NATURAL }, + /* (1) left */ { 6, 4, JT_LEFT|JT_OUTER }, + /* (2) outer */ { 10, 5, JT_OUTER }, + /* (3) right */ { 14, 5, JT_RIGHT|JT_OUTER }, + /* (4) full */ { 19, 4, JT_LEFT|JT_RIGHT|JT_OUTER }, + /* (5) inner */ { 23, 5, JT_INNER }, + /* (6) cross */ { 28, 5, JT_INNER|JT_CROSS }, }; int i, j; apAll[0] = pA; @@ -245,16 +291,17 @@ int sqlite3JoinType(Parse *pParse, Token *pA, Token *pB, Token *pC){ } if( (jointype & (JT_INNER|JT_OUTER))==(JT_INNER|JT_OUTER) || - (jointype & JT_ERROR)!=0 + (jointype & JT_ERROR)!=0 || + (jointype & (JT_OUTER|JT_LEFT|JT_RIGHT))==JT_OUTER ){ - const char *zSp = " "; - assert( pB!=0 ); - if( pC==0 ){ zSp++; } + const char *zSp1 = " "; + const char *zSp2 = " "; + if( pB==0 ){ zSp1++; } + if( pC==0 ){ zSp2++; } sqlite3ErrorMsg(pParse, "unknown or unsupported join type: " - "%T %T%s%T", pA, pB, zSp, pC); + "%T%s%T%s%T", pA, zSp1, pB, zSp2, pC); jointype = JT_INNER; - }else if( (jointype & JT_OUTER)!=0 - && (jointype & (JT_LEFT|JT_RIGHT))!=JT_LEFT ){ + }else if( (jointype & JT_RIGHT)!=0 ){ sqlite3ErrorMsg(pParse, "RIGHT and FULL OUTER JOINs are not currently supported"); jointype = JT_INNER; From 7d0ae00361386f87d179916d5abc6c11d3c85330 Mon Sep 17 00:00:00 2001 From: drh <> Date: Fri, 8 Apr 2022 17:01:29 +0000 Subject: [PATCH 2/4] Enhance the sqlite_dbpage fix at [/info/642a0b4752743216|check-in 642a0b4752743] from about a month ago such that it still takes a transaction on all attached databases, but it only starts a read transaction for read-only operations, rather than starting a write transaction for everything. FossilOrigin-Name: 8efd61e8518594e3e9c84681fc35796a78fe8885a97ad4dd19f1573ee8065b18 --- manifest | 16 ++++++++-------- manifest.uuid | 2 +- src/dbpage.c | 2 +- src/sqliteInt.h | 2 +- src/where.c | 17 ++++++++++++++--- 5 files changed, 25 insertions(+), 14 deletions(-) diff --git a/manifest b/manifest index a2472f06dc..4dcfbdb9c9 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Improved\sexplanation\sand\scommentary\son\sthe\ssqlite3JoinType()\sroutine.\s\sOne\nof\sthe\serror\smessages\schanges\sslightly,\sbut\sbesides\sthat\severything\sworks\nthe\ssame. -D 2022-04-08T15:11:10.072 +C Enhance\sthe\ssqlite_dbpage\sfix\sat\s[/info/642a0b4752743216|check-in\s642a0b4752743]\nfrom\sabout\sa\smonth\sago\ssuch\sthat\sit\sstill\stakes\sa\stransaction\son\sall\sattached\ndatabases,\sbut\sit\sonly\sstarts\sa\sread\stransaction\sfor\sread-only\soperations,\nrather\sthan\sstarting\sa\swrite\stransaction\sfor\severything. +D 2022-04-08T17:01:29.519 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -500,7 +500,7 @@ F src/callback.c 4c19af69835787bfe790ac560f3071a824eb629f34e41f97b52ce5235c77de1 F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e F src/ctime.c 026dbdcdbd8c3cde98a88483ee88310ff43150ab164ad768f12cc700a11495ad F src/date.c 15082566229d4b1e5f24fdb490bf9bcc68824b911d70e3573ef075a1b9e2d26f -F src/dbpage.c a70be9a4879ac5392673a1050d526a72b8b2f9938df7049f65348566a2637db3 +F src/dbpage.c 90661a87e1db8bfbc8d2ebbdcd3749651ddb287c555c07a28fb17c7c591ffb68 F src/dbstat.c 861e08690fcb0f2ee1165eff0060ea8d4f3e2ea10f80dab7d32ad70443a6ff2d F src/delete.c a8e844af211a48b13b5b358be77a12c860c6a557c21990ad51a548e2536500ce F src/expr.c 5e247a8dfabb92e9fd10b78a675dc5d25430433dfd9e316471b4447b548635ba @@ -557,7 +557,7 @@ F src/shell.c.in 1a8fbf932ecd582b1a5f66c1e8294f92c30d954616f5c7cc54c9623fcdbb028 F src/sqlite.h.in 2a35f62185eb5e7ecc64a2f68442b538ce9be74f80f28a00abc24837edcf1c17 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h f49e28c25bd941e79794db5415fdf7b202deb3bc072ed6f1ed273d578703684e -F src/sqliteInt.h 8262a5a484ffc0c0899537c9d99fff381f2d76061e256592a342bc098860a6ec +F src/sqliteInt.h 364699d46b6cd2fbcaedfb907cedd42c8ed6e32a671f7f72edb257cad861c40b F src/sqliteLimit.h d7323ffea5208c6af2734574bae933ca8ed2ab728083caa117c9738581a31657 F src/status.c 4a3da6d77eeb3531cb0dbdf7047772a2a1b99f98c69e90ce009c75fe6328b2c0 F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1 @@ -639,7 +639,7 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/wal.c b9df133a705093da8977da5eb202eaadb844839f1c7297c08d33471f5491843d F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a F src/walker.c f890a3298418d7cba3b69b8803594fdc484ea241206a8dfa99db6dd36f8cbb3b -F src/where.c a2483d4fe7cde88638cd3140dd5d6ee3dc0c80d3b3fe20322a8d08dc451f97ae +F src/where.c a17d57807aa63dca4f3204d01db7a863bc0290bd7913928582236d65c9ad4212 F src/whereInt.h 15d2975c3b4c193c78c26674400a840da8647fe1777ae3b026e2d15937b38a03 F src/wherecode.c 6292d7bf2d751b1ce68139a70e5468dd6615a9a9dab5b5e61c0053836723bb7a F src/whereexpr.c 612f58f5f6e3e3bb94d10e2c56672ade8bbf94d4a928d3edb4e84e2ed3c00dca @@ -1945,8 +1945,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 1b5475d212cf9de0bff69eee8c607b4fcd8e04bf4df72171429e7609c4153951 -R 931142dc24337bfedaa0369d45a2c00c +P 48f2e5a1fbaa8ceb32e08066766be74233b0c67ab430bbf7adfdff42cdb7b8ec +R 20c6686a28e5cb126a28d0c27a5e917b U drh -Z 277112caa7eb0641987ae3d1eca17748 +Z 5fb2265312a791be3cfc50f876b63b0a # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index b27079fd83..081aaf7939 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -48f2e5a1fbaa8ceb32e08066766be74233b0c67ab430bbf7adfdff42cdb7b8ec \ No newline at end of file +8efd61e8518594e3e9c84681fc35796a78fe8885a97ad4dd19f1573ee8065b18 \ No newline at end of file diff --git a/src/dbpage.c b/src/dbpage.c index 8a997e2def..003997b95f 100644 --- a/src/dbpage.c +++ b/src/dbpage.c @@ -156,7 +156,7 @@ static int dbpageBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){ ){ pIdxInfo->orderByConsumed = 1; } - sqlite3VtabWriteAll(pIdxInfo); + sqlite3VtabUsesAllSchemas(pIdxInfo); return SQLITE_OK; } diff --git a/src/sqliteInt.h b/src/sqliteInt.h index a9f3121c7c..ead20c9a2f 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -5174,7 +5174,7 @@ int sqlite3VtabBegin(sqlite3 *, VTable *); FuncDef *sqlite3VtabOverloadFunction(sqlite3 *,FuncDef*, int nArg, Expr*); #if (defined(SQLITE_ENABLE_DBPAGE_VTAB) || defined(SQLITE_TEST)) \ && !defined(SQLITE_OMIT_VIRTUALTABLE) - void sqlite3VtabWriteAll(sqlite3_index_info*); + void sqlite3VtabUsesAllSchemas(sqlite3_index_info*); #endif sqlite3_int64 sqlite3StmtCurrentTime(sqlite3_context*); int sqlite3VdbeParameterIndex(Vdbe*, const char*, int); diff --git a/src/where.c b/src/where.c index f9f42d5285..f08c350b06 100644 --- a/src/where.c +++ b/src/where.c @@ -3788,15 +3788,26 @@ int sqlite3_vtab_distinct(sqlite3_index_info *pIdxInfo){ && !defined(SQLITE_OMIT_VIRTUALTABLE) /* ** Cause the prepared statement that is associated with a call to -** xBestIndex to open write transactions on all attached schemas. +** xBestIndex to potentiall use all schemas. If the statement being +** prepared is read-only, then just start read transactions on all +** schemas. But if this is a write operation, start writes on all +** schemas. +** ** This is used by the (built-in) sqlite_dbpage virtual table. */ -void sqlite3VtabWriteAll(sqlite3_index_info *pIdxInfo){ +void sqlite3VtabUsesAllSchemas(sqlite3_index_info *pIdxInfo){ HiddenIndexInfo *pHidden = (HiddenIndexInfo*)&pIdxInfo[1]; Parse *pParse = pHidden->pParse; int nDb = pParse->db->nDb; int i; - for(i=0; iwriteMask ){ + for(i=0; i Date: Sat, 9 Apr 2022 03:06:01 +0000 Subject: [PATCH 3/4] The sqlite3WhereMalloc() routine allocates memory that is automatically deleted when the corresponding WhereInfo object is destroyed. FossilOrigin-Name: f237e1d8cc41b937f34288daebfacf5f7b0990a807a805e0cb6b45bc730192d6 --- manifest | 18 +++++++++--------- manifest.uuid | 2 +- src/where.c | 37 +++++++++++++++++++++++++++++-------- src/whereInt.h | 13 +++++++++++++ src/wherecode.c | 5 +++-- src/whereexpr.c | 10 ++-------- 6 files changed, 57 insertions(+), 28 deletions(-) diff --git a/manifest b/manifest index 4dcfbdb9c9..bf8983c822 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Enhance\sthe\ssqlite_dbpage\sfix\sat\s[/info/642a0b4752743216|check-in\s642a0b4752743]\nfrom\sabout\sa\smonth\sago\ssuch\sthat\sit\sstill\stakes\sa\stransaction\son\sall\sattached\ndatabases,\sbut\sit\sonly\sstarts\sa\sread\stransaction\sfor\sread-only\soperations,\nrather\sthan\sstarting\sa\swrite\stransaction\sfor\severything. -D 2022-04-08T17:01:29.519 +C The\ssqlite3WhereMalloc()\sroutine\sallocates\smemory\sthat\sis\sautomatically\ndeleted\swhen\sthe\scorresponding\sWhereInfo\sobject\sis\sdestroyed. +D 2022-04-09T03:06:01.731 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -639,10 +639,10 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/wal.c b9df133a705093da8977da5eb202eaadb844839f1c7297c08d33471f5491843d F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a F src/walker.c f890a3298418d7cba3b69b8803594fdc484ea241206a8dfa99db6dd36f8cbb3b -F src/where.c a17d57807aa63dca4f3204d01db7a863bc0290bd7913928582236d65c9ad4212 -F src/whereInt.h 15d2975c3b4c193c78c26674400a840da8647fe1777ae3b026e2d15937b38a03 -F src/wherecode.c 6292d7bf2d751b1ce68139a70e5468dd6615a9a9dab5b5e61c0053836723bb7a -F src/whereexpr.c 612f58f5f6e3e3bb94d10e2c56672ade8bbf94d4a928d3edb4e84e2ed3c00dca +F src/where.c 929ac88a1b65bcdef7e05a0b87b13a0c55cd3d5d3bc27ec81a6f37eaca13e5fe +F src/whereInt.h 41ce0a8c0368372d8422e420e05a1e037624ce52fae139c3c19538ee491fb4c0 +F src/wherecode.c b7bc24b150d6a47c48844f89c3bf6d8f694780acb71768c83b9bec8a729e0d81 +F src/whereexpr.c 2ce4ff64b80fce0a0f7579f5ec2b953f10952a3410c441564e12b650ea8c2aba F src/window.c 42a71595263dbd8ef8248218e4fc7d4b5ddccece52146ad48e079342d93f6f8f F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/affinity2.test ce1aafc86e110685b324e9a763eab4f2a73f737842ec3b687bd965867de90627 @@ -1945,8 +1945,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 48f2e5a1fbaa8ceb32e08066766be74233b0c67ab430bbf7adfdff42cdb7b8ec -R 20c6686a28e5cb126a28d0c27a5e917b +P 8efd61e8518594e3e9c84681fc35796a78fe8885a97ad4dd19f1573ee8065b18 +R 48010733dae82cb9023efd9a61e0d9ba U drh -Z 5fb2265312a791be3cfc50f876b63b0a +Z a50ac2a16236eccfde93e32da194e6bb # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 081aaf7939..0f6e9d2f91 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -8efd61e8518594e3e9c84681fc35796a78fe8885a97ad4dd19f1573ee8065b18 \ No newline at end of file +f237e1d8cc41b937f34288daebfacf5f7b0990a807a805e0cb6b45bc730192d6 \ No newline at end of file diff --git a/src/where.c b/src/where.c index f08c350b06..4820a5c031 100644 --- a/src/where.c +++ b/src/where.c @@ -253,6 +253,30 @@ Bitmask sqlite3WhereGetMask(WhereMaskSet *pMaskSet, int iCursor){ return 0; } +/* Allocate memory that is automatically freed when pWInfo is freed. +*/ +void *sqlite3WhereMalloc(WhereInfo *pWInfo, u64 nByte){ + WhereMemBlock *pBlock; + pBlock = sqlite3DbMallocRawNN(pWInfo->pParse->db, nByte+sizeof(*pBlock)); + if( pBlock ){ + pBlock->pNext = pWInfo->pMemToFree; + pBlock->sz = nByte; + pWInfo->pMemToFree = pBlock; + pBlock++; + } + return (void*)pBlock; +} +void *sqlite3WhereRealloc(WhereInfo *pWInfo, void *pOld, u64 nByte){ + void *pNew = sqlite3WhereMalloc(pWInfo, nByte); + if( pNew && pOld ){ + WhereMemBlock *pOldBlk = (WhereMemBlock*)pOld; + pOldBlk--; + assert( pOldBlk->szsz); + } + return pNew; +} + /* ** Create a new mask for cursor iCursor. ** @@ -2216,15 +2240,7 @@ static void whereLoopDelete(sqlite3 *db, WhereLoop *p){ ** Free a WhereInfo structure */ static void whereInfoFree(sqlite3 *db, WhereInfo *pWInfo){ - int i; assert( pWInfo!=0 ); - for(i=0; inLevel; i++){ - WhereLevel *pLevel = &pWInfo->a[i]; - if( pLevel->pWLoop && (pLevel->pWLoop->wsFlags & WHERE_IN_ABLE)!=0 ){ - assert( (pLevel->pWLoop->wsFlags & WHERE_MULTI_OR)==0 ); - sqlite3DbFree(db, pLevel->u.in.aInLoop); - } - } sqlite3WhereClauseClear(&pWInfo->sWC); while( pWInfo->pLoops ){ WhereLoop *p = pWInfo->pLoops; @@ -2232,6 +2248,11 @@ static void whereInfoFree(sqlite3 *db, WhereInfo *pWInfo){ whereLoopDelete(db, p); } assert( pWInfo->pExprMods==0 ); + while( pWInfo->pMemToFree ){ + WhereMemBlock *pNext = pWInfo->pMemToFree->pNext; + sqlite3DbFreeNN(db, pWInfo->pMemToFree); + pWInfo->pMemToFree = pNext; + } sqlite3DbFreeNN(db, pWInfo); } diff --git a/src/whereInt.h b/src/whereInt.h index 3fc39f6b4a..e0f44d6bac 100644 --- a/src/whereInt.h +++ b/src/whereInt.h @@ -32,6 +32,16 @@ typedef struct WhereLoopBuilder WhereLoopBuilder; typedef struct WhereScan WhereScan; typedef struct WhereOrCost WhereOrCost; typedef struct WhereOrSet WhereOrSet; +typedef struct WhereMemBlock WhereMemBlock; + +/* +** This object is a header on a block of allocated memory that will be +** automatically freed when its WInfo oject is destructed. +*/ +struct WhereMemBlock { + WhereMemBlock *pNext; /* Next block in the chain */ + u8 sz; /* Bytes of space */ +}; /* ** This object contains information needed to implement a single nested @@ -478,6 +488,7 @@ struct WhereInfo { int iEndWhere; /* End of the WHERE clause itself */ WhereLoop *pLoops; /* List of all WhereLoop objects */ WhereExprMod *pExprMods; /* Expression modifications */ + WhereMemBlock *pMemToFree;/* Memory to free when this object destroyed */ Bitmask revMask; /* Mask of ORDER BY terms that need reversing */ WhereClause sWC; /* Decomposition of the WHERE clause */ WhereMaskSet sMaskSet; /* Map cursor numbers to bitmasks */ @@ -503,6 +514,8 @@ WhereTerm *sqlite3WhereFindTerm( u32 op, /* Mask of WO_xx values describing operator */ Index *pIdx /* Must be compatible with this index, if not NULL */ ); +void *sqlite3WhereMalloc(WhereInfo *pWInfo, u64 nByte); +void *sqlite3WhereRealloc(WhereInfo *pWInfo, void *pOld, u64 nByte); /* wherecode.c: */ #ifndef SQLITE_OMIT_EXPLAIN diff --git a/src/wherecode.c b/src/wherecode.c index bab514a693..561b34fc85 100644 --- a/src/wherecode.c +++ b/src/wherecode.c @@ -640,8 +640,9 @@ static int codeEqualityTerm( i = pLevel->u.in.nIn; pLevel->u.in.nIn += nEq; pLevel->u.in.aInLoop = - sqlite3DbReallocOrFree(pParse->db, pLevel->u.in.aInLoop, - sizeof(pLevel->u.in.aInLoop[0])*pLevel->u.in.nIn); + sqlite3WhereRealloc(pTerm->pWC->pWInfo, + pLevel->u.in.aInLoop, + sizeof(pLevel->u.in.aInLoop[0])*pLevel->u.in.nIn); pIn = pLevel->u.in.aInLoop; if( pIn ){ int iMap = 0; /* Index in aiMap[] */ diff --git a/src/whereexpr.c b/src/whereexpr.c index 26a521fffd..a3316db65b 100644 --- a/src/whereexpr.c +++ b/src/whereexpr.c @@ -64,7 +64,7 @@ static int whereClauseInsert(WhereClause *pWC, Expr *p, u16 wtFlags){ if( pWC->nTerm>=pWC->nSlot ){ WhereTerm *pOld = pWC->a; sqlite3 *db = pWC->pWInfo->pParse->db; - pWC->a = sqlite3DbMallocRawNN(db, sizeof(pWC->a[0])*pWC->nSlot*2 ); + pWC->a = sqlite3WhereMalloc(pWC->pWInfo, sizeof(pWC->a[0])*pWC->nSlot*2 ); if( pWC->a==0 ){ if( wtFlags & TERM_DYNAMIC ){ sqlite3ExprDelete(db, p); @@ -73,10 +73,7 @@ static int whereClauseInsert(WhereClause *pWC, Expr *p, u16 wtFlags){ return 0; } memcpy(pWC->a, pOld, sizeof(pWC->a[0])*pWC->nTerm); - if( pOld!=pWC->aStatic ){ - sqlite3DbFree(db, pOld); - } - pWC->nSlot = sqlite3DbMallocSize(db, pWC->a)/sizeof(pWC->a[0]); + pWC->nSlot = pWC->nSlot*2; } pTerm = &pWC->a[idx = pWC->nTerm++]; if( (wtFlags & TERM_VIRTUAL)==0 ) pWC->nBase = pWC->nTerm; @@ -1686,9 +1683,6 @@ void sqlite3WhereClauseClear(WhereClause *pWC){ a++; } } - if( pWC->a!=pWC->aStatic ){ - sqlite3DbFree(db, pWC->a); - } } From 039132be208664a241b831a8a6ade069a8bb8c4d Mon Sep 17 00:00:00 2001 From: larrybr Date: Sat, 9 Apr 2022 18:51:49 +0000 Subject: [PATCH 4/4] Fix .import bug reported at https://sqlite.org/forum/forumpost/14db09d7e765b819 . zAutoColumn made to deliver characters, not bytes. FossilOrigin-Name: 21e96600d90c1cda84777abe22a11058eba46c9faefeb05f8c31bc0e7fa84b19 --- manifest | 16 ++++++++-------- manifest.uuid | 2 +- src/shell.c.in | 4 ++-- test/shell5.test | 30 ++++++++++++++++++++++++++++++ 4 files changed, 41 insertions(+), 11 deletions(-) diff --git a/manifest b/manifest index bf8983c822..e767080f57 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C The\ssqlite3WhereMalloc()\sroutine\sallocates\smemory\sthat\sis\sautomatically\ndeleted\swhen\sthe\scorresponding\sWhereInfo\sobject\sis\sdestroyed. -D 2022-04-09T03:06:01.731 +C Fix\s.import\sbug\sreported\sat\shttps://sqlite.org/forum/forumpost/14db09d7e765b819\s.\szAutoColumn\smade\sto\sdeliver\scharacters,\snot\sbytes. +D 2022-04-09T18:51:49.784 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -553,7 +553,7 @@ F src/random.c 097dc8b31b8fba5a9aca1697aeb9fd82078ec91be734c16bffda620ced7ab83c F src/resolve.c 18d99e7146852d6064559561769fcca0743eb32b14a97da6dbed373a30ee0e76 F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92 F src/select.c 7c106b3f36d483242b0a9c696614cd53d6f29e1ac81da6a3f0e9ea92f4211cc3 -F src/shell.c.in 1a8fbf932ecd582b1a5f66c1e8294f92c30d954616f5c7cc54c9623fcdbb028d +F src/shell.c.in eb7f10d5e2c47bd014d92ec5db1def21fcc1ed56ffaaa4ee715b6c37c370b47f F src/sqlite.h.in 2a35f62185eb5e7ecc64a2f68442b538ce9be74f80f28a00abc24837edcf1c17 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h f49e28c25bd941e79794db5415fdf7b202deb3bc072ed6f1ed273d578703684e @@ -1393,7 +1393,7 @@ F test/shell1.test b224e0793c5f48aa3749e65d8c64b93a30731bd206f2e41e6c5f1bee1bdb1 F test/shell2.test 7a3a23a9f57b99453f1679b1fe8072cb30e382a622874c0c4d97695fadb0a787 F test/shell3.test a50628ab1d78d90889d9d3f32fb2c084ee15674771e96afe954aaa0accd1de3c F test/shell4.test 8f6c0fce4abed19a8a7f7262517149812a04caa905d01bdc8f5e92573504b759 -F test/shell5.test 0a9920d81fae28c45cd5dbd1deb809487a23c5f4b422a49f9d31c85f926d4a9c +F test/shell5.test 78a7a8516b1e7de560748881424f621321549023d3e5f7ed2e1c56497f64c06c F test/shell6.test 1ceb51b2678c472ba6cf1e5da96679ce8347889fe2c3bf93a0e0fa73f00b00d3 F test/shell7.test 115132f66d0463417f408562cc2cf534f6bbc6d83a6d50f0072a9eb171bae97f F test/shell8.test 388471d16e4de767333107e30653983f186232c0e863f4490bb230419e830aae @@ -1945,8 +1945,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 8efd61e8518594e3e9c84681fc35796a78fe8885a97ad4dd19f1573ee8065b18 -R 48010733dae82cb9023efd9a61e0d9ba -U drh -Z a50ac2a16236eccfde93e32da194e6bb +P f237e1d8cc41b937f34288daebfacf5f7b0990a807a805e0cb6b45bc730192d6 +R 32d747db1a8abc3115c9e0c3c720312e +U larrybr +Z 31d16ad9966991b7487e6e03ff8edde4 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 0f6e9d2f91..b96920f440 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -f237e1d8cc41b937f34288daebfacf5f7b0990a807a805e0cb6b45bc730192d6 \ No newline at end of file +21e96600d90c1cda84777abe22a11058eba46c9faefeb05f8c31bc0e7fa84b19 \ No newline at end of file diff --git a/src/shell.c.in b/src/shell.c.in index 452e8b9cb1..996a7f942b 100644 --- a/src/shell.c.in +++ b/src/shell.c.in @@ -7962,12 +7962,12 @@ SELECT\ ','||iif((cpos-1)%4>0, ' ', x'0a'||' '))\ ||')' AS ColsSpec \ FROM (\ - SELECT cpos, printf('\"%w\"',printf('%.*s%s', nlen-chop,name,suff)) AS cname \ + SELECT cpos, printf('\"%w\"',printf('%!.*s%s', nlen-chop,name,suff)) AS cname \ FROM ColNames ORDER BY cpos\ )"; static const char * const zRenamesDone = "SELECT group_concat(" - " printf('\"%w\" to \"%w\"',name,printf('%.*s%s', nlen-chop, name, suff))," + " printf('\"%w\" to \"%w\"',name,printf('%!.*s%s', nlen-chop, name, suff))," " ','||x'0a')" "FROM ColNames WHERE suff<>'' OR chop!=0" ; diff --git a/test/shell5.test b/test/shell5.test index d63a0a20d3..00d89f8d78 100644 --- a/test/shell5.test +++ b/test/shell5.test @@ -540,4 +540,34 @@ Columns renamed during .import shell5.csv due to duplicates: "CoW" to "CoW_3", "cOw" to "cOw_4"}} +#---------------------------------------------------------------------------- +# Tests for preserving utf-8 that is not also ASCII. +# + +do_test shell5-6.1 { + set out [open shell5.csv w] + fconfigure $out -translation lf + puts $out {あい,うえお} + puts $out {1,2} + close $out + forcedelete test.db + catchcmd test.db {.import -csv shell5.csv t1 +.mode line +SELECT * FROM t1;} +} {0 { あい = 1 +うえお = 2}} + +do_test shell5-6.2 { + set out [open shell5.csv w] + fconfigure $out -translation lf + puts $out {1,2} + puts $out {あい,うえお} + close $out + forcedelete test.db + catchcmd test.db {.import -csv shell5.csv t1 +.mode line +SELECT * FROM t1;} +} {0 { 1 = あい + 2 = うえお}} + finish_test