1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-11-22 20:22:44 +03:00

Add the two-size lookaside memory allocator. Also, reduce the per-entry

size of the ExprList object.

FossilOrigin-Name: 51665bf0f975fb248964a4be205a4f3285d3f3f8cc697977d264efefbbe20dd8
This commit is contained in:
drh
2020-01-02 22:28:47 +00:00
16 changed files with 290 additions and 113 deletions

View File

@@ -1,5 +1,5 @@
C Do\snot\sallow\sthe\szipfile\svirtual\stable\sto\sstart\sa\stransaction\sif\sno\nfilename\shas\sbeen\sspecified.
D 2020-01-02T21:30:13.891
C Add\sthe\stwo-size\slookaside\smemory\sallocator.\s\sAlso,\sreduce\sthe\sper-entry\nsize\sof\sthe\sExprList\sobject.
D 2020-01-02T22:28:47.433
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -462,7 +462,7 @@ F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca
F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
F src/alter.c bc3e4089d5a708be4f1a8018737f64c2d11cc7ef0abf2e7b5a7f160e566e9d2f
F src/alter.c f48a4423c8f198d7f1ae4940f74b606707d05384ac79fb219be8e3323af2a2de
F src/analyze.c b3ceec3fc052df8a96ca8a8c858d455dc5029ba681b4be98bb5c5a9162cfa58c
F src/attach.c b30c44333d55a68c0a12920b5b9d40b254cbd3d4509bda77417209eeed8b3d80
F src/auth.c a3d5bfdba83d25abed1013a8c7a5f204e2e29b0c25242a56bc02bb0c07bf1e06
@@ -472,7 +472,7 @@ F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6
F src/btree.c f191aa4d99597a1ad77cb15a9473f1183f2a12a7f1650a7705eaac9085e493bb
F src/btree.h 6111552f19ed7a40f029cf4b33badc6fef9880314fffd80a945f0b7f43ab7471
F src/btreeInt.h 6794084fad08c9750b45145743c0e3e5c27c94dee89f26dd8df7073314934fd2
F src/build.c e63db6c6ceee67aa2dc7fe1b515f013a579bdecae22057d24ba2ec225920ce63
F src/build.c 9b7153d93308783c801c5c36d9b4b3189ab4f00cd9ad6bf4d6c9750378a56be9
F src/callback.c 88615dfc0a82167b65b452b4b305dbf86be77200b3343c6ffc6d03e92a01d181
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
F src/ctime.c 1b0724e66f95f33b160b1af85caaf9cceb325d22abf39bd24df4f54a73982251
@@ -480,20 +480,20 @@ F src/date.c e1d8ac7102f3f283e63e13867acb0efa33861cf34f0faf4cdbaf9fa7a1eb7041
F src/dbpage.c 135eb3b5e74f9ef74bde5cec2571192c90c86984fa534c88bf4a055076fa19b7
F src/dbstat.c 6c407e549406c10fde9ac3987f6d734459205239ad370369bc5fcd683084a4fa
F src/delete.c a5c59b9c0251cf7682bc52af0d64f09b1aefc6781a63592c8f1136f7b73c66e4
F src/expr.c d74209d6abec71609a64329726df5d003b6fb2897f5bbde77c35882e5d482e7c
F src/expr.c bef2f4c18a90fec59575dba1e32cc7d120af4120105bf503b843507f03f1d378
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
F src/fkey.c 92a248ec0fa4ed8ab60c98d9b188ce173aaf218f32e7737ba77deb2a684f9847
F src/func.c 259496e4856bd0a3215d16804992f3339f3e8db29f129a5a7285c341488bbe9c
F src/global.c bdd582ba2be6f29ffa5b9b91635c0dbea98101a25c92da15d1caca5ac999c7bb
F src/global.c b1ae842e22899ba071f90d7bcfac4052ef8d81691bc7bd804835dee55d91175f
F src/hash.c 8d7dda241d0ebdafb6ffdeda3149a412d7df75102cecfc1021c98d6219823b19
F src/hash.h 9d56a9079d523b648774c1784b74b89bd93fac7b365210157482e4319a468f38
F src/hwtime.h cb1d7e3e1ed94b7aa6fde95ae2c2daccc3df826be26fc9ed7fd90d1750ae6144
F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
F src/insert.c 7bbb7dec1d69f961f21d75bd83ed00ceee48d5aa71c794b1cce3205470c8a48f
F src/insert.c 5ba8fd376f539240939ae76b5bc9fa7ad9a0d86e9914ecd11eb7002204138c11
F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
F src/loadext.c d74f5e7bd51f3c9d283442473eb65aef359664efd6513591c03f01881c4ae2da
F src/main.c 7b06af0c38abf9720d9a5c49660bff8b7137427bbd513fa069baf8afa15da4d7
F src/malloc.c 550021fcae36f0ffe9f8563d83e6385f9df307a854d55d7d0abb7241ee8dbcc6
F src/main.c 07b5259e712bc479f0d7b51feaceab6ae3a4e08019a7ddad004562d56c317701
F src/malloc.c eaa4dc9602ce28b077f7de2eb275db2be270c5cc56d7fec5466301bd9b80e2f5
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de
F src/mem2.c f1940d9e91948dd6a908fbb9ce3835c36b5d83c3
@@ -526,16 +526,16 @@ F src/pragma.h ec3b31eac9b1df040f1cc8cb3d89bc06605c3b4cb3d76f833de8d6d6c3f77f04
F src/prepare.c 6049beb71385f017af6fc320d2c75a4e50b75e280c54232442b785fbb83df057
F src/printf.c 9be6945837c839ba57837b4bc3af349eba630920fa5532aa518816defe42a7d4
F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384
F src/resolve.c 17c74d7c180b50c703c404c1be7b80769536d9a1913fee4fc176cd95e445966b
F src/resolve.c 938295261d556dc173e7c4b85c921b565b25c38656b924bdf03c3ff8f37e24ab
F src/rowset.c d977b011993aaea002cab3e0bb2ce50cf346000dff94e944d547b989f4b1fe93
F src/select.c ba1af88f0dc93a03c0d5c379aab518109912cf87f92f1196de52812174e6fc9f
F src/select.c 8791103f21df458fdaba16c7d6452f92b00363f222f0f242661654f12455ea0a
F src/shell.c.in 90b002bf0054399cbbfac62dd752a9b05770427ba141bcba75eefbb0098f4280
F src/sqlite.h.in 51f69c62ba3e980aca1e39badcaf9ad13f008774fe1bb8e7f57e3e456c656670
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h 72af51aa4e912e14cd495fb6e7fac65f0940db80ed950d90911aff292cc47ce2
F src/sqliteInt.h 52a9d124cf7bc902eeaee8b744f928f38a8ca343f9555a922f3800bbca35533c
F src/sqliteInt.h 7f028954dc3602b5505064b1028ac671965bfd9905316767cb3298f945478ac0
F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b
F src/status.c 46e7aec11f79dad50965a5ca5fa9de009f7d6bde08be2156f1538a0a296d4d0e
F src/status.c 9ff2210207c6c3b4d9631a8241a7d45ab1b26a0e9c84cb07a9b5ce2de9a3b278
F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34
F src/tclsqlite.c 8cd2600e8de23dff6cdf84d39f46ca57139b061b28f6f80b166bace17d52ab1c
F src/test1.c 4d0ab2f67053a4fff87d1d3586ecc0e5322a1fc45dd4119ab11dc96de44f17a1
@@ -593,9 +593,9 @@ F src/test_window.c cdae419fdcea5bad6dcd9368c685abdad6deb59e9fc8b84b153de513d394
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c
F src/tokenize.c 7b17f6e2f20f6cbcb0b215025a86b7457c38451fc7622f705e553d7a488c572d
F src/treeview.c 7a8097cff1584acd0a228817103513bf1d1bf5ba91ff142b99c83e406c0968f3
F src/trigger.c 681ccdb910a87243940d63f99b26190d9c5d2534c2ded3c0825b7c0e315a342e
F src/update.c fae1082d3e28a13a4d4ed7ac35eaeb2f746d736882e46dd653671ab64396d86b
F src/treeview.c 74d4fb2b6a2eaced4c0a6e22a9caf6e4a975577774456575065c5c921bdb3381
F src/trigger.c a40d50e88bd3355f1d2a73f0a3b2d6b42eae26ca4219001b82ef0d064439badc
F src/update.c 9ad19af96aff95dc02a923a99f97c1bc0b909009a29a2914b796f786b9ac0c60
F src/upsert.c 2920de71b20f04fe25eb00b655d086f0ba60ea133c59d7fa3325c49838818e78
F src/utf.c 2f0fac345c7660d5c5bd3df9e9d8d33d4c27f366bcfb09e07443064d751a0507
F src/util.c 2c92bc706bbdb1c45a25180291e7e05a56e297aa5dd7b2bcd2b1c47e8bb05b17
@@ -1853,7 +1853,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 28900e5cab73f9edb9383d64a37e14fed0602966cb704ddffa60c0281698fd52
R 03baaef710a83490f407e9d1a4367e2e
P 7405e982257611803792617f5d8142c54f9831b4a030f4de8607888c525e6289 34b877742ef78e9bb3f16815180f4ad9cd722beb1d610f713400a3b25d68aa9b
R 896a86b40586a93b7de7ff4de391d81d
T +closed 34b877742ef78e9bb3f16815180f4ad9cd722beb1d610f713400a3b25d68aa9b
U drh
Z 36e9c165e34c3938dc7f6f92537f7688
Z 486c5971cb86c4301cea954c124cc71f

View File

@@ -1 +1 @@
7405e982257611803792617f5d8142c54f9831b4a030f4de8607888c525e6289
51665bf0f975fb248964a4be205a4f3285d3f3f8cc697977d264efefbbe20dd8

View File

@@ -766,8 +766,8 @@ static int renameUnmapSelectCb(Walker *pWalker, Select *p){
if( ALWAYS(p->pEList) ){
ExprList *pList = p->pEList;
for(i=0; i<pList->nExpr; i++){
if( pList->a[i].zName ){
sqlite3RenameTokenRemap(pParse, 0, (void*)pList->a[i].zName);
if( pList->a[i].zEName && pList->a[i].eEName==ENAME_NAME ){
sqlite3RenameTokenRemap(pParse, 0, (void*)pList->a[i].zEName);
}
}
}
@@ -811,7 +811,9 @@ void sqlite3RenameExprlistUnmap(Parse *pParse, ExprList *pEList){
sWalker.xExprCallback = renameUnmapExprCb;
sqlite3WalkExprList(&sWalker, pEList);
for(i=0; i<pEList->nExpr; i++){
sqlite3RenameTokenRemap(pParse, 0, (void*)pEList->a[i].zName);
if( ALWAYS(pEList->a[i].eEName==ENAME_NAME) ){
sqlite3RenameTokenRemap(pParse, 0, (void*)pEList->a[i].zEName);
}
}
}
}
@@ -949,8 +951,11 @@ static void renameColumnElistNames(
if( pEList ){
int i;
for(i=0; i<pEList->nExpr; i++){
char *zName = pEList->a[i].zName;
if( 0==sqlite3_stricmp(zName, zOld) ){
char *zName = pEList->a[i].zEName;
if( ALWAYS(pEList->a[i].eEName==ENAME_NAME)
&& ALWAYS(zName!=0)
&& 0==sqlite3_stricmp(zName, zOld)
){
renameTokenFind(pParse, pCtx, (void*)zName);
}
}

View File

@@ -3107,7 +3107,7 @@ void sqlite3CreateForeignKey(
nByte = sizeof(*pFKey) + (nCol-1)*sizeof(pFKey->aCol[0]) + pTo->n + 1;
if( pToCol ){
for(i=0; i<pToCol->nExpr; i++){
nByte += sqlite3Strlen30(pToCol->a[i].zName) + 1;
nByte += sqlite3Strlen30(pToCol->a[i].zEName) + 1;
}
}
pFKey = sqlite3DbMallocZero(db, nByte );
@@ -3132,7 +3132,7 @@ void sqlite3CreateForeignKey(
for(i=0; i<nCol; i++){
int j;
for(j=0; j<p->nCol; j++){
if( sqlite3StrICmp(p->aCol[j].zName, pFromCol->a[i].zName)==0 ){
if( sqlite3StrICmp(p->aCol[j].zName, pFromCol->a[i].zEName)==0 ){
pFKey->aCol[i].iFrom = j;
break;
}
@@ -3140,22 +3140,22 @@ void sqlite3CreateForeignKey(
if( j>=p->nCol ){
sqlite3ErrorMsg(pParse,
"unknown column \"%s\" in foreign key definition",
pFromCol->a[i].zName);
pFromCol->a[i].zEName);
goto fk_end;
}
if( IN_RENAME_OBJECT ){
sqlite3RenameTokenRemap(pParse, &pFKey->aCol[i], pFromCol->a[i].zName);
sqlite3RenameTokenRemap(pParse, &pFKey->aCol[i], pFromCol->a[i].zEName);
}
}
}
if( pToCol ){
for(i=0; i<nCol; i++){
int n = sqlite3Strlen30(pToCol->a[i].zName);
int n = sqlite3Strlen30(pToCol->a[i].zEName);
pFKey->aCol[i].zCol = z;
if( IN_RENAME_OBJECT ){
sqlite3RenameTokenRemap(pParse, z, pToCol->a[i].zName);
sqlite3RenameTokenRemap(pParse, z, pToCol->a[i].zEName);
}
memcpy(z, pToCol->a[i].zName, n);
memcpy(z, pToCol->a[i].zEName, n);
z[n] = 0;
z += n+1;
}

View File

@@ -1440,12 +1440,11 @@ ExprList *sqlite3ExprListDup(sqlite3 *db, ExprList *p, int flags){
pNewExpr->pLeft = pPriorSelectCol;
}
}
pItem->zName = sqlite3DbStrDup(db, pOldItem->zName);
pItem->zSpan = sqlite3DbStrDup(db, pOldItem->zSpan);
pItem->zEName = sqlite3DbStrDup(db, pOldItem->zEName);
pItem->sortFlags = pOldItem->sortFlags;
pItem->eEName = pOldItem->eEName;
pItem->done = 0;
pItem->bNulls = pOldItem->bNulls;
pItem->bSpanIsTab = pOldItem->bSpanIsTab;
pItem->bSorterRef = pOldItem->bSorterRef;
pItem->u = pOldItem->u;
}
@@ -1612,9 +1611,9 @@ ExprList *sqlite3ExprListAppend(
pList = pNew;
}
pItem = &pList->a[pList->nExpr++];
assert( offsetof(struct ExprList_item,zName)==sizeof(pItem->pExpr) );
assert( offsetof(struct ExprList_item,zEName)==sizeof(pItem->pExpr) );
assert( offsetof(struct ExprList_item,pExpr)==0 );
memset(&pItem->zName,0,sizeof(*pItem)-offsetof(struct ExprList_item,zName));
memset(&pItem->zEName,0,sizeof(*pItem)-offsetof(struct ExprList_item,zEName));
pItem->pExpr = pExpr;
return pList;
@@ -1671,7 +1670,7 @@ ExprList *sqlite3ExprListAppendVector(
pList = sqlite3ExprListAppend(pParse, pList, pSubExpr);
if( pList ){
assert( pList->nExpr==iFirst+i+1 );
pList->a[pList->nExpr-1].zName = pColumns->a[i].zName;
pList->a[pList->nExpr-1].zEName = pColumns->a[i].zName;
pColumns->a[i].zName = 0;
}
}
@@ -1731,7 +1730,7 @@ void sqlite3ExprListSetSortOrder(ExprList *p, int iSortOrder, int eNulls){
}
/*
** Set the ExprList.a[].zName element of the most recently added item
** Set the ExprList.a[].zEName element of the most recently added item
** on the expression list.
**
** pList might be NULL following an OOM error. But pName should never be
@@ -1749,11 +1748,12 @@ void sqlite3ExprListSetName(
struct ExprList_item *pItem;
assert( pList->nExpr>0 );
pItem = &pList->a[pList->nExpr-1];
assert( pItem->zName==0 );
pItem->zName = sqlite3DbStrNDup(pParse->db, pName->z, pName->n);
if( dequote ) sqlite3Dequote(pItem->zName);
assert( pItem->zEName==0 );
assert( pItem->eEName==ENAME_NAME );
pItem->zEName = sqlite3DbStrNDup(pParse->db, pName->z, pName->n);
if( dequote ) sqlite3Dequote(pItem->zEName);
if( IN_RENAME_OBJECT ){
sqlite3RenameTokenMap(pParse, (void*)pItem->zName, pName);
sqlite3RenameTokenMap(pParse, (void*)pItem->zEName, pName);
}
}
}
@@ -1777,8 +1777,10 @@ void sqlite3ExprListSetSpan(
if( pList ){
struct ExprList_item *pItem = &pList->a[pList->nExpr-1];
assert( pList->nExpr>0 );
sqlite3DbFree(db, pItem->zSpan);
pItem->zSpan = sqlite3DbSpanDup(db, zStart, zEnd);
if( pItem->zEName==0 ){
pItem->zEName = sqlite3DbSpanDup(db, zStart, zEnd);
pItem->eEName = ENAME_SPAN;
}
}
}
@@ -1808,8 +1810,7 @@ static SQLITE_NOINLINE void exprListDeleteNN(sqlite3 *db, ExprList *pList){
assert( pList->nExpr>0 );
do{
sqlite3ExprDelete(db, pItem->pExpr);
sqlite3DbFree(db, pItem->zName);
sqlite3DbFree(db, pItem->zSpan);
sqlite3DbFree(db, pItem->zEName);
pItem++;
}while( --i>0 );
sqlite3DbFreeNN(db, pList);

View File

@@ -190,9 +190,18 @@ const unsigned char sqlite3CtypeMap[256] = {
** changed as start-time using sqlite3_config(SQLITE_CONFIG_LOOKASIDE)
** or at run-time for an individual database connection using
** sqlite3_db_config(db, SQLITE_DBCONFIG_LOOKASIDE);
**
** With the two-size-lookaside enhancement, less lookaside is required.
** The default configuration of 1200,40 actually provides 30 1200-byte slots
** and 93 128-byte slots, which is more lookaside than is available
** using the older 1200,100 configuration without two-size-lookaside.
*/
#ifndef SQLITE_DEFAULT_LOOKASIDE
# define SQLITE_DEFAULT_LOOKASIDE 1200,100
# ifdef SQLITE_OMIT_TWOSIZE_LOOKASIDE
# define SQLITE_DEFAULT_LOOKASIDE 1200,100 /* 120KB of memory */
# else
# define SQLITE_DEFAULT_LOOKASIDE 1200,40 /* 48KB of memory */
# endif
#endif

View File

@@ -1673,7 +1673,7 @@ void sqlite3GenerateConstraintChecks(
if( onError==OE_Ignore ){
sqlite3VdbeGoto(v, ignoreDest);
}else{
char *zName = pCheck->a[i].zName;
char *zName = pCheck->a[i].zEName;
if( zName==0 ) zName = pTab->zName;
if( onError==OE_Replace ) onError = OE_Abort; /* IMP: R-26383-51744 */
sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_CHECK,

View File

@@ -683,6 +683,9 @@ int sqlite3_config(int op, ...){
static int setupLookaside(sqlite3 *db, void *pBuf, int sz, int cnt){
#ifndef SQLITE_OMIT_LOOKASIDE
void *pStart;
sqlite3_int64 szAlloc = sz*(sqlite3_int64)cnt;
int nBig; /* Number of full-size slots */
int nSm; /* Number smaller LOOKASIDE_SMALL-byte slots */
if( sqlite3LookasideUsed(db,0)>0 ){
return SQLITE_BUSY;
@@ -705,12 +708,27 @@ static int setupLookaside(sqlite3 *db, void *pBuf, int sz, int cnt){
pStart = 0;
}else if( pBuf==0 ){
sqlite3BeginBenignMalloc();
pStart = sqlite3Malloc( sz*(sqlite3_int64)cnt ); /* IMP: R-61949-35727 */
pStart = sqlite3Malloc( szAlloc ); /* IMP: R-61949-35727 */
sqlite3EndBenignMalloc();
if( pStart ) cnt = sqlite3MallocSize(pStart)/sz;
if( pStart ) szAlloc = sqlite3MallocSize(pStart);
}else{
pStart = pBuf;
}
#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE
if( sz>=LOOKASIDE_SMALL*3 ){
nBig = szAlloc/(3*LOOKASIDE_SMALL+sz);
nSm = (szAlloc - sz*nBig)/LOOKASIDE_SMALL;
}else if( sz>=LOOKASIDE_SMALL*2 ){
nBig = szAlloc/(LOOKASIDE_SMALL+sz);
nSm = (szAlloc - sz*nBig)/LOOKASIDE_SMALL;
}else
#endif /* SQLITE_OMIT_TWOSIZE_LOOKASIDE */
if( sz>0 ){
nBig = szAlloc/sz;
nSm = 0;
}else{
nBig = nSm = 0;
}
db->lookaside.pStart = pStart;
db->lookaside.pInit = 0;
db->lookaside.pFree = 0;
@@ -720,24 +738,41 @@ static int setupLookaside(sqlite3 *db, void *pBuf, int sz, int cnt){
int i;
LookasideSlot *p;
assert( sz > (int)sizeof(LookasideSlot*) );
db->lookaside.nSlot = cnt;
p = (LookasideSlot*)pStart;
for(i=cnt-1; i>=0; i--){
for(i=0; i<nBig; i++){
p->pNext = db->lookaside.pInit;
db->lookaside.pInit = p;
p = (LookasideSlot*)&((u8*)p)[sz];
}
#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE
db->lookaside.pSmallInit = 0;
db->lookaside.pSmallFree = 0;
db->lookaside.pMiddle = p;
for(i=0; i<nSm; i++){
p->pNext = db->lookaside.pSmallInit;
db->lookaside.pSmallInit = p;
p = (LookasideSlot*)&((u8*)p)[LOOKASIDE_SMALL];
}
#endif /* SQLITE_OMIT_TWOSIZE_LOOKASIDE */
assert( ((uptr)p)<=szAlloc + (uptr)pStart );
db->lookaside.pEnd = p;
db->lookaside.bDisable = 0;
db->lookaside.bMalloced = pBuf==0 ?1:0;
db->lookaside.nSlot = nBig+nSm;
}else{
db->lookaside.pStart = db;
#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE
db->lookaside.pSmallInit = 0;
db->lookaside.pSmallFree = 0;
db->lookaside.pMiddle = db;
#endif /* SQLITE_OMIT_TWOSIZE_LOOKASIDE */
db->lookaside.pEnd = db;
db->lookaside.bDisable = 1;
db->lookaside.sz = 0;
db->lookaside.bMalloced = 0;
db->lookaside.nSlot = 0;
}
assert( sqlite3LookasideUsed(db,0)==0 );
#endif /* SQLITE_OMIT_LOOKASIDE */
return SQLITE_OK;
}

View File

@@ -332,10 +332,17 @@ int sqlite3MallocSize(void *p){
assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) );
return sqlite3GlobalConfig.m.xSize(p);
}
static int lookasideMallocSize(sqlite3 *db, void *p){
#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE
return p<db->lookaside.pMiddle ? db->lookaside.szTrue : LOOKASIDE_SMALL;
#else
return db->lookaside.szTrue;
#endif
}
int sqlite3DbMallocSize(sqlite3 *db, void *p){
assert( p!=0 );
if( db==0 || !isLookaside(db,p) ){
#ifdef SQLITE_DEBUG
if( db==0 || !isLookaside(db,p) ){
if( db==0 ){
assert( sqlite3MemdebugNoType(p, (u8)~MEMTYPE_HEAP) );
assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) );
@@ -343,12 +350,23 @@ int sqlite3DbMallocSize(sqlite3 *db, void *p){
assert( sqlite3MemdebugHasType(p, (MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
assert( sqlite3MemdebugNoType(p, (u8)~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
}
#endif
return sqlite3GlobalConfig.m.xSize(p);
}else{
assert( sqlite3_mutex_held(db->mutex) );
return db->lookaside.szTrue;
}
#endif
if( db ){
if( ((uptr)p)<(uptr)(db->lookaside.pEnd) ){
#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE
if( ((uptr)p)>=(uptr)(db->lookaside.pMiddle) ){
assert( sqlite3_mutex_held(db->mutex) );
return LOOKASIDE_SMALL;
}
#endif
if( ((uptr)p)>=(uptr)(db->lookaside.pStart) ){
assert( sqlite3_mutex_held(db->mutex) );
return db->lookaside.szTrue;
}
}
}
return sqlite3GlobalConfig.m.xSize(p);
}
sqlite3_uint64 sqlite3_msize(void *p){
assert( sqlite3MemdebugNoType(p, (u8)~MEMTYPE_HEAP) );
@@ -395,15 +413,27 @@ void sqlite3DbFreeNN(sqlite3 *db, void *p){
measureAllocationSize(db, p);
return;
}
if( isLookaside(db, p) ){
LookasideSlot *pBuf = (LookasideSlot*)p;
if( ((uptr)p)<(uptr)(db->lookaside.pEnd) ){
#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE
if( ((uptr)p)>=(uptr)(db->lookaside.pMiddle) ){
LookasideSlot *pBuf = (LookasideSlot*)p;
#ifdef SQLITE_DEBUG
/* Trash all content in the buffer being freed */
memset(p, 0xaa, db->lookaside.szTrue);
memset(p, 0xaa, LOOKASIDE_SMALL); /* Trash freed content */
#endif
pBuf->pNext = db->lookaside.pFree;
db->lookaside.pFree = pBuf;
return;
pBuf->pNext = db->lookaside.pSmallFree;
db->lookaside.pSmallFree = pBuf;
return;
}
#endif /* SQLITE_OMIT_TWOSIZE_LOOKASIDE */
if( ((uptr)p)>=(uptr)(db->lookaside.pStart) ){
LookasideSlot *pBuf = (LookasideSlot*)p;
#ifdef SQLITE_DEBUG
memset(p, 0xaa, db->lookaside.szTrue); /* Trash freed content */
#endif
pBuf->pNext = db->lookaside.pFree;
db->lookaside.pFree = pBuf;
return;
}
}
}
assert( sqlite3MemdebugHasType(p, (MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
@@ -560,11 +590,27 @@ void *sqlite3DbMallocRawNN(sqlite3 *db, u64 n){
assert( sqlite3_mutex_held(db->mutex) );
assert( db->pnBytesFreed==0 );
if( n>db->lookaside.sz ){
if( db->lookaside.bDisable ){
return db->mallocFailed ? 0 : dbMallocRawFinish(db, n);
if( !db->lookaside.bDisable ){
db->lookaside.anStat[1]++;
}else if( db->mallocFailed ){
return 0;
}
db->lookaside.anStat[1]++;
}else if( (pBuf = db->lookaside.pFree)!=0 ){
return dbMallocRawFinish(db, n);
}
#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE
if( n<=LOOKASIDE_SMALL ){
if( (pBuf = db->lookaside.pSmallFree)!=0 ){
db->lookaside.pSmallFree = pBuf->pNext;
db->lookaside.anStat[0]++;
return (void*)pBuf;
}else if( (pBuf = db->lookaside.pSmallInit)!=0 ){
db->lookaside.pSmallInit = pBuf->pNext;
db->lookaside.anStat[0]++;
return (void*)pBuf;
}
}
#endif
if( (pBuf = db->lookaside.pFree)!=0 ){
db->lookaside.pFree = pBuf->pNext;
db->lookaside.anStat[0]++;
return (void*)pBuf;
@@ -597,7 +643,16 @@ void *sqlite3DbRealloc(sqlite3 *db, void *p, u64 n){
assert( db!=0 );
if( p==0 ) return sqlite3DbMallocRawNN(db, n);
assert( sqlite3_mutex_held(db->mutex) );
if( isLookaside(db,p) && n<=db->lookaside.szTrue ) return p;
if( ((uptr)p)<(uptr)db->lookaside.pEnd ){
#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE
if( ((uptr)p)>=(uptr)db->lookaside.pMiddle ){
if( n<=LOOKASIDE_SMALL ) return p;
}else
#endif
if( ((uptr)p)>=(uptr)db->lookaside.pStart ){
if( n<=db->lookaside.szTrue ) return p;
}
}
return dbReallocFinish(db, p, n);
}
static SQLITE_NOINLINE void *dbReallocFinish(sqlite3 *db, void *p, u64 n){
@@ -608,7 +663,7 @@ static SQLITE_NOINLINE void *dbReallocFinish(sqlite3 *db, void *p, u64 n){
if( isLookaside(db, p) ){
pNew = sqlite3DbMallocRawNN(db, n);
if( pNew ){
memcpy(pNew, p, db->lookaside.szTrue);
memcpy(pNew, p, lookasideMallocSize(db, p));
sqlite3DbFree(db, p);
}
}else{

View File

@@ -132,13 +132,16 @@ static int nameInUsingClause(IdList *pUsing, const char *zCol){
** and zCol. If any of zDb, zTab, and zCol are NULL then those fields will
** match anything.
*/
int sqlite3MatchSpanName(
const char *zSpan,
int sqlite3MatchEName(
const struct ExprList_item *pItem,
const char *zCol,
const char *zTab,
const char *zDb
){
int n;
const char *zSpan;
if( NEVER(pItem->eEName!=ENAME_TAB) ) return 0;
zSpan = pItem->zEName;
for(n=0; ALWAYS(zSpan[n]) && zSpan[n]!='.'; n++){}
if( zDb && (sqlite3StrNICmp(zSpan, zDb, n)!=0 || zDb[n]!=0) ){
return 0;
@@ -267,7 +270,7 @@ static int lookupName(
int hit = 0;
pEList = pItem->pSelect->pEList;
for(j=0; j<pEList->nExpr; j++){
if( sqlite3MatchSpanName(pEList->a[j].zSpan, zCol, zTab, zDb) ){
if( sqlite3MatchEName(&pEList->a[j], zCol, zTab, zDb) ){
cnt++;
cntTab = 2;
pMatch = pItem;
@@ -448,8 +451,11 @@ static int lookupName(
pEList = pNC->uNC.pEList;
assert( pEList!=0 );
for(j=0; j<pEList->nExpr; j++){
char *zAs = pEList->a[j].zName;
if( zAs!=0 && sqlite3StrICmp(zAs, zCol)==0 ){
char *zAs = pEList->a[j].zEName;
if( pEList->a[j].eEName==ENAME_NAME
&& ALWAYS(zAs!=0)
&& sqlite3StrICmp(zAs, zCol)==0
){
Expr *pOrig;
assert( pExpr->pLeft==0 && pExpr->pRight==0 );
assert( pExpr->x.pList==0 );
@@ -1117,8 +1123,11 @@ static int resolveAsName(
if( pE->op==TK_ID ){
char *zCol = pE->u.zToken;
for(i=0; i<pEList->nExpr; i++){
char *zAs = pEList->a[i].zName;
if( zAs!=0 && sqlite3StrICmp(zAs, zCol)==0 ){
char *zAs = pEList->a[i].zEName;
if( pEList->a[i].eEName==ENAME_NAME
&& ALWAYS(zAs!=0)
&& sqlite3StrICmp(zAs, zCol)==0
){
return i+1;
}
}

View File

@@ -939,7 +939,7 @@ static void selectInnerLoop(
if( srcTab>=0 ){
for(i=0; i<nResultCol; i++){
sqlite3VdbeAddOp3(v, OP_Column, srcTab, i, regResult+i);
VdbeComment((v, "%s", p->pEList->a[i].zName));
VdbeComment((v, "%s", p->pEList->a[i].zEName));
}
}else if( eDest!=SRT_Exists ){
#ifdef SQLITE_ENABLE_SORTER_REFERENCES
@@ -1560,7 +1560,7 @@ static void generateSortTail(
iRead = iCol--;
}
sqlite3VdbeAddOp3(v, OP_Column, iSortTab, iRead, regRow+i);
VdbeComment((v, "%s", aOutEx[i].zName?aOutEx[i].zName : aOutEx[i].zSpan));
VdbeComment((v, "%s", aOutEx[i].zEName));
}
}
switch( eDest ){
@@ -1894,9 +1894,9 @@ static void generateColumnNames(
assert( p!=0 );
assert( p->op!=TK_AGG_COLUMN ); /* Agg processing has not run yet */
assert( p->op!=TK_COLUMN || p->y.pTab!=0 ); /* Covering idx not yet coded */
if( pEList->a[i].zName ){
if( pEList->a[i].zEName && pEList->a[i].eEName==ENAME_NAME ){
/* An AS clause always takes first priority */
char *zName = pEList->a[i].zName;
char *zName = pEList->a[i].zEName;
sqlite3VdbeSetColName(v, i, COLNAME_NAME, zName, SQLITE_TRANSIENT);
}else if( srcName && p->op==TK_COLUMN ){
char *zCol;
@@ -1918,7 +1918,7 @@ static void generateColumnNames(
sqlite3VdbeSetColName(v, i, COLNAME_NAME, zCol, SQLITE_TRANSIENT);
}
}else{
const char *z = pEList->a[i].zSpan;
const char *z = pEList->a[i].zEName;
z = z==0 ? sqlite3MPrintf(db, "column%d", i+1) : sqlite3DbStrDup(db, z);
sqlite3VdbeSetColName(v, i, COLNAME_NAME, z, SQLITE_DYNAMIC);
}
@@ -1980,7 +1980,7 @@ int sqlite3ColumnsFromExprList(
for(i=0, pCol=aCol; i<nCol && !db->mallocFailed; i++, pCol++){
/* Get an appropriate name for the column
*/
if( (zName = pEList->a[i].zName)!=0 ){
if( (zName = pEList->a[i].zEName)!=0 && pEList->a[i].eEName==ENAME_NAME ){
/* If the column contains an "AS <name>" phrase, use <name> as the name */
}else{
Expr *pColExpr = sqlite3ExprSkipCollateAndLikely(pEList->a[i].pExpr);
@@ -2000,7 +2000,7 @@ int sqlite3ColumnsFromExprList(
zName = pColExpr->u.zToken;
}else{
/* Use the original text of the column expression as its name */
zName = pEList->a[i].zSpan;
zName = pEList->a[i].zEName;
}
}
if( zName ){
@@ -5031,10 +5031,9 @@ static int selectExpander(Walker *pWalker, Select *p){
*/
pNew = sqlite3ExprListAppend(pParse, pNew, a[k].pExpr);
if( pNew ){
pNew->a[pNew->nExpr-1].zName = a[k].zName;
pNew->a[pNew->nExpr-1].zSpan = a[k].zSpan;
a[k].zName = 0;
a[k].zSpan = 0;
pNew->a[pNew->nExpr-1].zEName = a[k].zEName;
pNew->a[pNew->nExpr-1].eEName = a[k].eEName;
a[k].zEName = 0;
}
a[k].pExpr = 0;
}else{
@@ -5073,7 +5072,7 @@ static int selectExpander(Walker *pWalker, Select *p){
assert( zName );
if( zTName && pSub
&& sqlite3MatchSpanName(pSub->pEList->a[j].zSpan, 0, zTName, 0)==0
&& sqlite3MatchEName(&pSub->pEList->a[j], 0, zTName, 0)==0
){
continue;
}
@@ -5126,15 +5125,16 @@ static int selectExpander(Walker *pWalker, Select *p){
sqlite3ExprListSetName(pParse, pNew, &sColname, 0);
if( pNew && (p->selFlags & SF_NestedFrom)!=0 ){
struct ExprList_item *pX = &pNew->a[pNew->nExpr-1];
sqlite3DbFree(db, pX->zEName);
if( pSub ){
pX->zSpan = sqlite3DbStrDup(db, pSub->pEList->a[j].zSpan);
testcase( pX->zSpan==0 );
pX->zEName = sqlite3DbStrDup(db, pSub->pEList->a[j].zEName);
testcase( pX->zEName==0 );
}else{
pX->zSpan = sqlite3MPrintf(db, "%s.%s.%s",
pX->zEName = sqlite3MPrintf(db, "%s.%s.%s",
zSchemaName, zTabName, zColname);
testcase( pX->zSpan==0 );
testcase( pX->zEName==0 );
}
pX->bSpanIsTab = 1;
pX->eEName = ENAME_TAB;
}
sqlite3DbFree(db, zToFree);
}

View File

@@ -1297,6 +1297,25 @@ struct Schema {
** disables lookaside without adding a new test for the bDisable flag
** in a performance-critical path. sz should be set by to szTrue whenever
** bDisable changes back to zero.
**
** Lookaside buffers are initially held on the pInit list. As they are
** used and freed, they are added back to the pFree list. New allocations
** come off of pFree first, then pInit as a fallback. This dual-list
** allows use to compute a high-water mark - the maximum number of allocations
** outstanding at any point in the past - by subtracting the number of
** allocations on the pInit list from the total number of allocations.
**
** Enhancement on 2019-12-12: Two-size-lookaside
** The default lookaside configuration is 100 slots of 1200 bytes each.
** The larger slot sizes are important for performance, but they waste
** a lot of space, as most lookaside allocations are less than 128 bytes.
** The two-size-lookaside enhancement breaks up the lookaside allocation
** into two pools: One of 128-byte slots and the other of the default size
** (1200-byte) slots. Allocations are filled from the small-pool first,
** failing over to the full-size pool if that does not work. Thus more
** lookaside slots are available while also using less memory.
** This enhancement can be omitted by compiling with
** SQLITE_OMIT_TWOSIZE_LOOKASIDE.
*/
struct Lookaside {
u32 bDisable; /* Only operate the lookaside when zero */
@@ -1307,6 +1326,12 @@ struct Lookaside {
u32 anStat[3]; /* 0: hits. 1: size misses. 2: full misses */
LookasideSlot *pInit; /* List of buffers not previously used */
LookasideSlot *pFree; /* List of available buffers */
#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE
LookasideSlot *pSmallInit; /* List of small buffers not prediously used */
LookasideSlot *pSmallFree; /* List of available small buffers */
void *pMiddle; /* First byte past end of full-size buffers and
** the first byte of LOOKASIDE_SMALL buffers */
#endif /* SQLITE_OMIT_TWOSIZE_LOOKASIDE */
void *pStart; /* First byte of available memory space */
void *pEnd; /* First byte past end of available space */
};
@@ -1318,6 +1343,13 @@ struct LookasideSlot {
#define EnableLookaside db->lookaside.bDisable--;\
db->lookaside.sz=db->lookaside.bDisable?0:db->lookaside.szTrue
/* Size of the smaller allocations in two-size lookside */
#ifdef SQLITE_OMIT_TWOSIZE_LOOKASIDE
# define LOOKASIDE_SMALL 0
#else
# define LOOKASIDE_SMALL 128
#endif
/*
** A hash table for built-in function definitions. (Application-defined
** functions use a regular table table from hash.h.)
@@ -2692,23 +2724,28 @@ struct Expr {
** also be used as the argument to a function, in which case the a.zName
** field is not used.
**
** By default the Expr.zSpan field holds a human-readable description of
** the expression that is used in the generation of error messages and
** column labels. In this case, Expr.zSpan is typically the text of a
** column expression as it exists in a SELECT statement. However, if
** the bSpanIsTab flag is set, then zSpan is overloaded to mean the name
** of the result column in the form: DATABASE.TABLE.COLUMN. This later
** form is used for name resolution with nested FROM clauses.
** In order to try to keep memory usage down, the Expr.a.zEName field
** is used for multiple purposes:
**
** eEName Usage
** ---------- -------------------------
** ENAME_NAME (1) the AS of result set column
** (2) COLUMN= of an UPDATE
**
** ENAME_TAB DB.TABLE.NAME used to resolve names
** of subqueries
**
** ENAME_SPAN Text of the original result set
** expression.
*/
struct ExprList {
int nExpr; /* Number of expressions on the list */
struct ExprList_item { /* For each expression in the list */
Expr *pExpr; /* The parse tree for this expression */
char *zName; /* Token associated with this expression */
char *zSpan; /* Original text of the expression */
char *zEName; /* Token associated with this expression */
u8 sortFlags; /* Mask of KEYINFO_ORDER_* flags */
unsigned eEName :2; /* Meaning of zEName */
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" */
@@ -2722,6 +2759,13 @@ struct ExprList {
} a[1]; /* One slot for each expression in the list */
};
/*
** Allowed values for Expr.a.eEName
*/
#define ENAME_NAME 0 /* The AS clause of a result set */
#define ENAME_SPAN 1 /* Complete text of the result set expression */
#define ENAME_TAB 2 /* "DB.TABLE.NAME" for the result set */
/*
** An instance of this structure can hold a simple list of identifiers,
** such as the list "a,b,c" in the following statements:
@@ -4461,7 +4505,12 @@ void sqlite3CodeRhsOfIN(Parse*, Expr*, int);
int sqlite3CodeSubselect(Parse*, Expr*);
void sqlite3SelectPrep(Parse*, Select*, NameContext*);
void sqlite3SelectWrongNumTermsError(Parse *pParse, Select *p);
int sqlite3MatchSpanName(const char*, const char*, const char*, const char*);
int sqlite3MatchEName(
const struct ExprList_item*,
const char*,
const char*,
const char*
);
int sqlite3ResolveExprNames(NameContext*, Expr*);
int sqlite3ResolveExprListNames(NameContext*, ExprList*);
void sqlite3ResolveSelectNames(Parse*, Select*, NameContext*);

View File

@@ -188,6 +188,10 @@ static u32 countLookasideSlots(LookasideSlot *p){
int sqlite3LookasideUsed(sqlite3 *db, int *pHighwater){
u32 nInit = countLookasideSlots(db->lookaside.pInit);
u32 nFree = countLookasideSlots(db->lookaside.pFree);
#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE
nInit += countLookasideSlots(db->lookaside.pSmallInit);
nFree += countLookasideSlots(db->lookaside.pSmallFree);
#endif /* SQLITE_OMIT_TWOSIZE_LOOKASIDE */
if( pHighwater ) *pHighwater = db->lookaside.nSlot - nInit;
return db->lookaside.nSlot - (nInit+nFree);
}
@@ -220,6 +224,15 @@ int sqlite3_db_status(
db->lookaside.pInit = db->lookaside.pFree;
db->lookaside.pFree = 0;
}
#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE
p = db->lookaside.pSmallFree;
if( p ){
while( p->pNext ) p = p->pNext;
p->pNext = db->lookaside.pSmallInit;
db->lookaside.pSmallInit = db->lookaside.pSmallFree;
db->lookaside.pSmallFree = 0;
}
#endif
}
break;
}

View File

@@ -106,7 +106,7 @@ void sqlite3TreeViewWith(TreeView *pView, const With *pWith, u8 moreToFollow){
char cSep = '(';
int j;
for(j=0; j<pCte->pCols->nExpr; j++){
sqlite3_str_appendf(&x, "%c%s", cSep, pCte->pCols->a[j].zName);
sqlite3_str_appendf(&x, "%c%s", cSep, pCte->pCols->a[j].zEName);
cSep = ',';
}
sqlite3_str_appendf(&x, ")");
@@ -728,7 +728,7 @@ void sqlite3TreeViewBareExprList(
sqlite3TreeViewLine(pView, "%s", zLabel);
for(i=0; i<pList->nExpr; i++){
int j = pList->a[i].u.x.iOrderByCol;
char *zName = pList->a[i].zName;
char *zName = pList->a[i].zEName;
int moreToFollow = i<pList->nExpr - 1;
if( j || zName ){
sqlite3TreeViewPush(pView, moreToFollow);

View File

@@ -688,7 +688,7 @@ static int checkColumnOverlap(IdList *pIdList, ExprList *pEList){
int e;
if( pIdList==0 || NEVER(pEList==0) ) return 1;
for(e=0; e<pEList->nExpr; e++){
if( sqlite3IdListIndex(pIdList, pEList->a[e].zName)>=0 ) return 1;
if( sqlite3IdListIndex(pIdList, pEList->a[e].zEName)>=0 ) return 1;
}
return 0;
}

View File

@@ -306,7 +306,7 @@ void sqlite3Update(
goto update_cleanup;
}
for(j=0; j<pTab->nCol; j++){
if( sqlite3StrICmp(pTab->aCol[j].zName, pChanges->a[i].zName)==0 ){
if( sqlite3StrICmp(pTab->aCol[j].zName, pChanges->a[i].zEName)==0 ){
if( j==pTab->iPKey ){
chngRowid = 1;
pRowidExpr = pChanges->a[i].pExpr;
@@ -328,12 +328,12 @@ void sqlite3Update(
}
}
if( j>=pTab->nCol ){
if( pPk==0 && sqlite3IsRowid(pChanges->a[i].zName) ){
if( pPk==0 && sqlite3IsRowid(pChanges->a[i].zEName) ){
j = -1;
chngRowid = 1;
pRowidExpr = pChanges->a[i].pExpr;
}else{
sqlite3ErrorMsg(pParse, "no such column: %s", pChanges->a[i].zName);
sqlite3ErrorMsg(pParse, "no such column: %s", pChanges->a[i].zEName);
pParse->checkSchema = 1;
goto update_cleanup;
}