From: drh <> Date: Fri, 1 Oct 2021 00:25:06 +0000 (+0000) Subject: Fixes to the version of "varsep" group_concat so that (1) it builds under X-Git-Tag: version-3.37.0~179^2~2 X-Git-Url: http://git.ipfire.org/gitweb/gitweb.cgi?a=commitdiff_plain;h=f06db3e8929e36f7686ccc8f9f138359c6b12e80;p=thirdparty%2Fsqlite.git Fixes to the version of "varsep" group_concat so that (1) it builds under separate compilation and (2) omits tabs in source code and (3) runs faster than trunk. This variant of the group_concat_varsep branch might be preferred over the tip because it preserves (undocumented) legacy behavior about the position of separators relative to terms. FossilOrigin-Name: 04399cf9645e04b171090ff8a3c27752929c10d2cd8778e26f8f3337aa902ab6 --- diff --git a/manifest b/manifest index 6f2d72cf83..4057ec873a 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Sync\sw/trunk -D 2021-09-29T16:35:14.868 +C Fixes\sto\sthe\sversion\sof\s"varsep"\sgroup_concat\sso\sthat\s(1)\sit\sbuilds\sunder\nseparate\scompilation\sand\s(2)\somits\stabs\sin\ssource\scode\sand\s(3)\sruns\sfaster\nthan\strunk.\s\sThis\svariant\sof\sthe\sgroup_concat_varsep\sbranch\smight\sbe\spreferred\nover\sthe\stip\sbecause\sit\spreserves\s(undocumented)\slegacy\sbehavior\sabout\sthe\nposition\sof\sseparators\srelative\sto\sterms. +D 2021-10-01T00:25:06.629 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -502,7 +502,7 @@ F src/delete.c 3ce6af6b64c8b476de51ccc32da0cb3142d42e65754e1d8118addf65b8bcba15 F src/expr.c f2e0f5dd07d1b202f700f26b0851f2ea485e36ec8f335b05aec2cd91cd08853f F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007 F src/fkey.c 1905af1821b88321e1bb9d6a69e704495b6844a9b6c29398d40117cc251e893c -F src/func.c c852d68d0a984263f969e3b84d602c6d821147a32905fecca65b1d86098367b4 +F src/func.c 35e0beafdbd8e9d7050577668ab3f515b86d8aff18bb81603d961d9152955b16 F src/global.c 612ea60c9acbcb45754c2ed659b4a56936a06814718e969636fedc7e3b889808 F src/hash.c 8d7dda241d0ebdafb6ffdeda3149a412d7df75102cecfc1021c98d6219823b19 F src/hash.h 9d56a9079d523b648774c1784b74b89bd93fac7b365210157482e4319a468f38 @@ -543,7 +543,7 @@ F src/pcache1.c 54881292a9a5db202b2c0ac541c5e3ef9a5e8c4f1c1383adb2601d5499a60e65 F src/pragma.c 4a473feae3646063996ce3bfae78032009fa950765908d97424f7578b202813c F src/pragma.h b33c7a542ae7965c471f0d3c0565ce4d340c3f32cc162f44133539b6b0edb927 F src/prepare.c 8f07616db04337057b8498b72d051ee90f73c54615c2e908c05404cef1e060b7 -F src/printf.c 78fabb49b9ac9a12dd1c89d744abdc9b67fd3205e62967e158f78b965a29ec4b +F src/printf.c 1ce574bf02b503b0e031a70d3453324a9f4a0eb1ad379f3324ced73b918ed20b F src/random.c 097dc8b31b8fba5a9aca1697aeb9fd82078ec91be734c16bffda620ced7ab83c F src/resolve.c b9e60afa56d0484ee573aba54d9e73603736236df33d2ae3421b4cd0367d907d F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92 @@ -552,7 +552,7 @@ F src/shell.c.in 9df263dc0949698a8728ecc5bb826666ca8ced75201d5440a161b629455cd46 F src/sqlite.h.in 4e977a5e2ed1a9e8987ff65a2cab5f99a4298ebf040ea5ff636e1753339ff45a F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h e97f4e9b509408fea4c4e9bef5a41608dfac343b4d3c7a990dedde1e19af9510 -F src/sqliteInt.h 06a8f97a644388b28c0a9428a6b2cdf40e8b51b1cf38064f41baba5fd810be49 +F src/sqliteInt.h 90aabdfc427a6356f0ff1ed77c886f823d10e08f100e992816dec1033c225079 F src/sqliteLimit.h d7323ffea5208c6af2734574bae933ca8ed2ab728083caa117c9738581a31657 F src/status.c 4b8bc2a6905163a38b739854a35b826c737333fab5b1f8e03fa7eb9a4799c4c1 F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1 @@ -1927,7 +1927,10 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 3d148615f9d9c6a3d63d8eb015f3d70f453a66de49b28e665831254387c700b9 df0d7e36dbf98ab5405d8366ce92fb85176d4388b47a57b0ca1aa1ba6ae5212e -R 4764117e20f212be49211212953ddad0 -U larrybr -Z 559da611469829addf62248db5ff3864 +P a4c18b2f0ce4a0f4d0c4f4c25dc69fbed4cb4876d2b69e3e5e0e756410892d74 +R 247138f3b5e489fa491f98b9cd97dbe7 +T *branch * group_concat-fix-legacy +T *sym-group_concat-fix-legacy * +T -sym-group_concat_varsep * +U drh +Z 89839e6f88669e9a8e94fe2639f687c4 diff --git a/manifest.uuid b/manifest.uuid index 43f8a3d717..fede5e072e 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -a4c18b2f0ce4a0f4d0c4f4c25dc69fbed4cb4876d2b69e3e5e0e756410892d74 \ No newline at end of file +04399cf9645e04b171090ff8a3c27752929c10d2cd8778e26f8f3337aa902ab6 \ No newline at end of file diff --git a/src/func.c b/src/func.c index d348aa6574..860466bc10 100644 --- a/src/func.c +++ b/src/func.c @@ -1715,17 +1715,23 @@ static void minMaxFinalize(sqlite3_context *context){ /* ** group_concat(EXPR, ?SEPARATOR?) +** +** The SEPARATOR goes before the EXPR string. This is tragic. The +** groupConcatInverse() implementation would have been easier if the +** SEPARATOR were appended after EXPR. And the order is undocumented, +** so we could change it, in theory. But the old behavior has been +** around for so long that we dare not, for fear of breaking something. */ typedef struct { StrAccum str; /* The accumulated concatenation */ #ifndef SQLITE_OMIT_WINDOWFUNC int nAccum; /* Number of strings presently concatenated */ - int nFirstSepLength; /* Used to detect separator length change */ + int nFirstSepLength; /* Used to detect separator length change */ /* If pnSepLengths!=0, refs an array of inter-string separator lengths, - * stored as actually incorporated into presently accumulated result. - * (Hence, its slots in use number nAccum-1 between method calls.) - * If pnSepLengths==0, nFirstSepLength is the length used throughout. - */ + ** stored as actually incorporated into presently accumulated result. + ** (Hence, its slots in use number nAccum-1 between method calls.) + ** If pnSepLengths==0, nFirstSepLength is the length used throughout. + */ int *pnSepLengths; #endif } GroupConcatCtx; @@ -1746,38 +1752,45 @@ static void groupConcatStep( sqlite3 *db = sqlite3_context_db_handle(context); int firstTerm = pGCC->str.mxAlloc==0; pGCC->str.mxAlloc = db->aLimit[SQLITE_LIMIT_LENGTH]; - if( !firstTerm ){ - if( argc==2 ){ - zSep = (char*)sqlite3_value_text(argv[1]); - nSep = sqlite3_value_bytes(argv[1]); - }else{ - zSep = ","; - nSep = 1; + if( argc==1 ){ + if( !firstTerm ){ + sqlite3_str_appendchar(&pGCC->str, 1, ','); + } +#ifndef SQLITE_OMIT_WINDOWFUNC + else{ + pGCC->nFirstSepLength = 1; + } +#endif + }else if( !firstTerm ){ + zSep = (char*)sqlite3_value_text(argv[1]); + nSep = sqlite3_value_bytes(argv[1]); + if( zSep ){ + sqlite3_str_append(&pGCC->str, zSep, nSep); } - if( zSep ) - sqlite3_str_append(&pGCC->str, zSep, nSep); #ifndef SQLITE_OMIT_WINDOWFUNC - else - nSep = 0; + else{ + nSep = 0; + } if( nSep != pGCC->nFirstSepLength || pGCC->pnSepLengths != 0 ){ - int * pnsl = pGCC->pnSepLengths; - if( pnsl == 0 ){ - /* First separator length variation seen, start tracking them. */ - pnsl = (int*)sqlite3_malloc64((pGCC->nAccum+1) * sizeof(int)); - if( pnsl!=0 ){ - int i = 0, nA = pGCC->nAccum-1; - while( inFirstSepLength; - } - }else{ - pnsl = (int*)sqlite3_realloc64(pnsl, pGCC->nAccum * sizeof(int)); - } - if( pnsl!=0 ){ - if( pGCC->nAccum>0 ) - pnsl[pGCC->nAccum-1] = nSep; - pGCC->pnSepLengths = pnsl; - }else{ - setStrAccumError(&pGCC->str, SQLITE_NOMEM); - } + int *pnsl = pGCC->pnSepLengths; + if( pnsl == 0 ){ + /* First separator length variation seen, start tracking them. */ + pnsl = (int*)sqlite3_malloc64((pGCC->nAccum+1) * sizeof(int)); + if( pnsl!=0 ){ + int i = 0, nA = pGCC->nAccum-1; + while( inFirstSepLength; + } + }else{ + pnsl = (int*)sqlite3_realloc64(pnsl, pGCC->nAccum * sizeof(int)); + } + if( pnsl!=0 ){ + if( pGCC->nAccum>0 ){ + pnsl[pGCC->nAccum-1] = nSep; + } + pGCC->pnSepLengths = pnsl; + }else{ + sqlite3StrAccumSetError(&pGCC->str, SQLITE_NOMEM); + } } #endif } @@ -1811,9 +1824,9 @@ static void groupConcatInverse( if( pGCC->pnSepLengths!=0 ){ assert(pGCC->nAccum >= 0); if( pGCC->nAccum>0 ){ - nVS += *pGCC->pnSepLengths; - memmove(pGCC->pnSepLengths, pGCC->pnSepLengths+1, - (pGCC->nAccum-1)*sizeof(int)); + nVS += *pGCC->pnSepLengths; + memmove(pGCC->pnSepLengths, pGCC->pnSepLengths+1, + (pGCC->nAccum-1)*sizeof(int)); } }else{ /* If removing single accumulated string, harmlessly over-do. */ @@ -1844,8 +1857,9 @@ static void groupConcatFinalize(sqlite3_context *context){ sqlite3_result_error_toobig(context); }else if( pAccum->accError==SQLITE_NOMEM ){ sqlite3_result_error_nomem(context); - }else{ - sqlite3_result_text(context, sqlite3StrAccumFinish(pAccum), -1, + }else{ + int n = pAccum->nChar; + sqlite3_result_text(context, sqlite3StrAccumFinish(pAccum), n, sqlite3_free); } #ifndef SQLITE_OMIT_WINDOWFUNC @@ -1865,7 +1879,7 @@ static void groupConcatValue(sqlite3_context *context){ sqlite3_result_error_nomem(context); }else{ const char *zText = sqlite3_str_value(pAccum); - sqlite3_result_text(context, zText, -1, SQLITE_TRANSIENT); + sqlite3_result_text(context, zText, pAccum->nChar, SQLITE_TRANSIENT); } } } diff --git a/src/printf.c b/src/printf.c index f663e1b1ed..eb06e1a23d 100644 --- a/src/printf.c +++ b/src/printf.c @@ -145,7 +145,7 @@ static char et_getdigit(LONGDOUBLE_TYPE *val, int *cnt){ /* ** Set the StrAccum object to an error mode. */ -static void setStrAccumError(StrAccum *p, u8 eError){ +void sqlite3StrAccumSetError(StrAccum *p, u8 eError){ assert( eError==SQLITE_NOMEM || eError==SQLITE_TOOBIG ); p->accError = eError; if( p->mxAlloc ) sqlite3_str_reset(p); @@ -181,12 +181,12 @@ static char *printfTempBuf(sqlite3_str *pAccum, sqlite3_int64 n){ char *z; if( pAccum->accError ) return 0; if( n>pAccum->nAlloc && n>pAccum->mxAlloc ){ - setStrAccumError(pAccum, SQLITE_TOOBIG); + sqlite3StrAccumSetError(pAccum, SQLITE_TOOBIG); return 0; } z = sqlite3DbMallocRaw(pAccum->db, n); if( z==0 ){ - setStrAccumError(pAccum, SQLITE_NOMEM); + sqlite3StrAccumSetError(pAccum, SQLITE_NOMEM); } return z; } @@ -925,7 +925,7 @@ static int sqlite3StrAccumEnlarge(StrAccum *p, int N){ return 0; } if( p->mxAlloc==0 ){ - setStrAccumError(p, SQLITE_TOOBIG); + sqlite3StrAccumSetError(p, SQLITE_TOOBIG); return p->nAlloc - p->nChar - 1; }else{ char *zOld = isMalloced(p) ? p->zText : 0; @@ -938,7 +938,7 @@ static int sqlite3StrAccumEnlarge(StrAccum *p, int N){ } if( szNew > p->mxAlloc ){ sqlite3_str_reset(p); - setStrAccumError(p, SQLITE_TOOBIG); + sqlite3StrAccumSetError(p, SQLITE_TOOBIG); return 0; }else{ p->nAlloc = (int)szNew; @@ -956,7 +956,7 @@ static int sqlite3StrAccumEnlarge(StrAccum *p, int N){ p->printfFlags |= SQLITE_PRINTF_MALLOCED; }else{ sqlite3_str_reset(p); - setStrAccumError(p, SQLITE_NOMEM); + sqlite3StrAccumSetError(p, SQLITE_NOMEM); return 0; } } @@ -1029,7 +1029,7 @@ static SQLITE_NOINLINE char *strAccumFinishRealloc(StrAccum *p){ memcpy(zText, p->zText, p->nChar+1); p->printfFlags |= SQLITE_PRINTF_MALLOCED; }else{ - setStrAccumError(p, SQLITE_NOMEM); + sqlite3StrAccumSetError(p, SQLITE_NOMEM); } p->zText = zText; return zText; diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 21682fa113..c0f8455f6e 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -4933,6 +4933,7 @@ int sqlite3OpenTempDatabase(Parse *); void sqlite3StrAccumInit(StrAccum*, sqlite3*, char*, int, int); char *sqlite3StrAccumFinish(StrAccum*); +void sqlite3StrAccumSetError(StrAccum*, u8); void sqlite3SelectDestInit(SelectDest*,int,int); Expr *sqlite3CreateColumnExpr(sqlite3 *, SrcList *, int, int);