From ae80ddea9f4cf8505b5a27aeec3fa8b959218064 Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 6 Dec 2012 21:16:43 +0000 Subject: [PATCH] Remove the Expr.pColl field and compute the collating sequence as it is needed. This fixes the test script "shared9.test", though there is still a memory leak. And there are other problems. Consider this a work-in-progress. FossilOrigin-Name: fd011cb22f2d899d94ec7ce22641d7a8f5e19972 --- manifest | 27 +++++------ manifest.uuid | 2 +- src/build.c | 18 +++---- src/expr.c | 123 +++++++++++++++++++++++++----------------------- src/fkey.c | 2 +- src/resolve.c | 9 +--- src/select.c | 9 +--- src/sqliteInt.h | 4 +- src/where.c | 44 ++++++++++------- 9 files changed, 117 insertions(+), 121 deletions(-) diff --git a/manifest b/manifest index 36a1e81ed7..982c3dfca5 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sa\stest\scase\sthat\sdemonstrates\sticket\s[71e333e7d2e642]. -D 2012-12-06T15:15:15.819 +C Remove\sthe\sExpr.pColl\sfield\sand\scompute\sthe\scollating\ssequence\sas\sit\sis\sneeded.\nThis\sfixes\sthe\stest\sscript\s"shared9.test",\sthough\sthere\sis\sstill\sa\smemory\sleak.\nAnd\sthere\sare\sother\sproblems.\s\sConsider\sthis\sa\swork-in-progress. +D 2012-12-06T21:16:43.401 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 690d441a758cbffd13e814dc2724a721a6ebd400 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -124,15 +124,15 @@ F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7 F src/btree.c eccee944cb2221e919d7a855e5928d8643194b14 F src/btree.h 3ad7964d6c5b1c7bff569aab6adfa075f8bf06cd F src/btreeInt.h 4e5c2bd0f9b36b2a815a6d84f771a61a65830621 -F src/build.c f35dac52924a6e8e6346a90f0c195a84e28b6f21 +F src/build.c 9721f654f5dc84b3c85559d181346b701f8ea9a4 F src/callback.c d7e46f40c3cf53c43550b7da7a1d0479910b62cc F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac F src/ctime.c 72a70dcfda75d3a1f81041ce4573e7afddcd8e4e F src/date.c 067a81c9942c497aafd2c260e13add8a7d0c7dd4 F src/delete.c 9b8d308979114991e5dc7cee958316e07186941d -F src/expr.c 3b25a95f3d309403940ba4a3212f197b8b6251d5 +F src/expr.c 696c9e664a3d0405fb83ed206500809519f9c1a7 F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb -F src/fkey.c c82a04e7a92bb728f9ab972b76590403283be2af +F src/fkey.c ca70996e72b307d58718e4d1f11668ff76d5f2d4 F src/func.c 8147799b048065a1590805be464d05b4913e652c F src/global.c e59ecd2c553ad0d4bfbc84ca71231336f8993a7a F src/hash.c ac3470bbf1ca4ae4e306a8ecb0fdf1731810ffe4 @@ -172,14 +172,14 @@ F src/pragma.c 015723c48072781d2740e310ab04dc92956b76d1 F src/prepare.c 931ad0d852a0df48f79adcba6ce79ca5f475625c F src/printf.c 4a9f882f1c1787a8b494a2987765acf9d97ac21f F src/random.c cd4a67b3953b88019f8cd4ccd81394a8ddfaba50 -F src/resolve.c 7b986a715ac281643309c29257bb58cfae7aa810 +F src/resolve.c 6faf0f337ef89f7f9f6142d766793a87074612dc F src/rowset.c 64655f1a627c9c212d9ab497899e7424a34222e0 -F src/select.c 3a8baf4719f9723b4e0b43f2baa60692d0d921f8 +F src/select.c da1af4c2f1ff4d280aa68eb58b714e9b7d0fc1c3 F src/shell.c e392dd1ccbb77cc1d75a8367a89b473c24bea019 F src/sqlite.h.in 4e71a210f383b6d060bd3fdf81d850f0f8c4eca3 F src/sqlite3.rc fea433eb0a59f4c9393c8e6d76a6e2596b1fe0c0 F src/sqlite3ext.h 6904f4aadf976f95241311fbffb00823075d9477 -F src/sqliteInt.h 666935d603a7354d90e7ddfe040e3afdd1d8ee16 +F src/sqliteInt.h 9cec95011e6e6f14f74f855275e21bea79daee2e F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d F src/status.c bedc37ec1a6bb9399944024d63f4c769971955a9 F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e @@ -250,7 +250,7 @@ F src/vtab.c b05e5f1f4902461ba9f5fc49bb7eb7c3a0741a83 F src/wal.c f5c7b5027d0ed0e9bc9afeb4a3a8dfea762ec7d2 F src/wal.h 29c197540b19044e6cd73487017e5e47a1d3dac6 F src/walker.c 3d75ba73de15e0f8cd0737643badbeb0e002f07b -F src/where.c b5325975cbdd9b64f680fb88d7e727fc9368db68 +F src/where.c 1c7ff5ad06fe23d9d46008a23f9118926bb4fcb7 F test/8_3_names.test 631ea964a3edb091cf73c3b540f6bcfdb36ce823 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2 F test/aggnested.test 45c0201e28045ad38a530b5a144b73cd4aa2cfd6 @@ -1025,10 +1025,7 @@ F tool/vdbe-compress.tcl f12c884766bd14277f4fcedcae07078011717381 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac -P d507648d820cfea70e17f3d21c35c932a2d20367 -R c8862607377e39d862ea6493db661aac -T *branch * ticket-71e333e7 -T *sym-ticket-71e333e7 * -T -sym-trunk * +P cc6e0785df3c2342376351e19ba7dba7b8d2f6a3 +R a2a449d5f80e428bd0ee765a55dfac68 U drh -Z b40bafefd4b37344c158547788b014ab +Z 434d5050577e1426f5ec867bc43f759c diff --git a/manifest.uuid b/manifest.uuid index 317159043e..e5f7e5fe65 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -cc6e0785df3c2342376351e19ba7dba7b8d2f6a3 \ No newline at end of file +fd011cb22f2d899d94ec7ce22641d7a8f5e19972 \ No newline at end of file diff --git a/src/build.c b/src/build.c index 4c45a92727..c03e50295d 100644 --- a/src/build.c +++ b/src/build.c @@ -2690,10 +2690,8 @@ Index *sqlite3CreateIndex( for(i=0; inExpr; i++){ Expr *pExpr = pList->a[i].pExpr; if( pExpr ){ - CollSeq *pColl = pExpr->pColl; - /* Either pColl!=0 or there was an OOM failure. But if an OOM - ** failure we have quit before reaching this point. */ - if( ALWAYS(pColl) ){ + CollSeq *pColl = sqlite3ExprCollSeq(pParse, pExpr); + if( pColl ){ nExtra += (1 + sqlite3Strlen30(pColl->zName)); } } @@ -2756,6 +2754,7 @@ Index *sqlite3CreateIndex( const char *zColName = pListItem->zName; Column *pTabCol; int requestedSortOrder; + CollSeq *pColl; /* Collating sequence */ char *zColl; /* Collation sequence name */ for(j=0, pTabCol=pTab->aCol; jnCol; j++, pTabCol++){ @@ -2768,14 +2767,11 @@ Index *sqlite3CreateIndex( goto exit_create_index; } pIndex->aiColumn[i] = j; - /* Justification of the ALWAYS(pListItem->pExpr->pColl): Because of - ** the way the "idxlist" non-terminal is constructed by the parser, - ** if pListItem->pExpr is not null then either pListItem->pExpr->pColl - ** must exist or else there must have been an OOM error. But if there - ** was an OOM error, we would never reach this point. */ - if( pListItem->pExpr && ALWAYS(pListItem->pExpr->pColl) ){ + if( pListItem->pExpr + && (pColl = sqlite3ExprCollSeq(pParse, pListItem->pExpr))!=0 + ){ int nColl; - zColl = pListItem->pExpr->pColl->zName; + zColl = pColl->zName; nColl = sqlite3Strlen30(zColl) + 1; assert( nExtra>=nColl ); memcpy(zExtra, zColl, nColl); diff --git a/src/expr.c b/src/expr.c index ae828489a6..11feaa216a 100644 --- a/src/expr.c +++ b/src/expr.c @@ -55,67 +55,73 @@ char sqlite3ExprAffinity(Expr *pExpr){ return pExpr->affinity; } -/* -** Set the explicit collating sequence for an expression to the -** collating sequence supplied in the second argument. -*/ -Expr *sqlite3ExprSetColl(Expr *pExpr, CollSeq *pColl){ - if( pExpr && pColl ){ - pExpr->pColl = pColl; - pExpr->flags |= EP_ExpCollate; - } - return pExpr; -} - /* ** Set the collating sequence for expression pExpr to be the collating -** sequence named by pToken. Return a pointer to the revised expression. -** The collating sequence is marked as "explicit" using the EP_ExpCollate -** flag. An explicit collating sequence will override implicit -** collating sequences. +** sequence named by pToken. Return a pointer to a new Expr node that +** implements the COLLATE operator. */ Expr *sqlite3ExprSetCollByToken(Parse *pParse, Expr *pExpr, Token *pCollName){ - char *zColl = 0; /* Dequoted name of collation sequence */ - CollSeq *pColl; - sqlite3 *db = pParse->db; - zColl = sqlite3NameFromToken(db, pCollName); - pColl = sqlite3LocateCollSeq(pParse, zColl); - sqlite3ExprSetColl(pExpr, pColl); - sqlite3DbFree(db, zColl); - return pExpr; + Expr *pNew = sqlite3ExprAlloc(pParse->db, TK_COLLATE, pCollName, 1); + if( pNew ){ + pNew->pLeft = pExpr; + pNew->flags |= EP_Collate; + } + return pNew; } /* -** Return the default collation sequence for the expression pExpr. If -** there is no default collation type, return 0. +** Return the collation sequence for the expression pExpr. If +** there is no defined collating sequence, return NULL. +** +** The collating sequence might be determined by a COLLATE operator +** or by the presence of a column with a defined collating sequence. +** COLLATE operators take first precedence. Left operands take +** precedence over right operands. */ CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){ + sqlite3 *db = pParse->db; CollSeq *pColl = 0; Expr *p = pExpr; - while( p ){ - int op; - pColl = p->pColl; - if( pColl ) break; - op = p->op; - if( p->pTab!=0 && ( - op==TK_AGG_COLUMN || op==TK_COLUMN || op==TK_REGISTER || op==TK_TRIGGER - )){ + while( p && pColl==0 ){ + int op = p->op; + if( op==TK_CAST || op==TK_UPLUS ){ + p = p->pLeft; + continue; + } + if( op==TK_COLLATE ){ + pColl = sqlite3FindCollSeq(db, ENC(db), p->u.zToken, 0); + break; + } + if( p->pTab!=0 + && (op==TK_AGG_COLUMN || op==TK_COLUMN + || op==TK_REGISTER || op==TK_TRIGGER) + ){ /* op==TK_REGISTER && p->pTab!=0 happens when pExpr was originally ** a TK_COLUMN but was previously evaluated and cached in a register */ - const char *zColl; int j = p->iColumn; if( j>=0 ){ - sqlite3 *db = pParse->db; - zColl = p->pTab->aCol[j].zColl; + const char *zColl = p->pTab->aCol[j].zColl; pColl = sqlite3FindCollSeq(db, ENC(db), zColl, 0); - pExpr->pColl = pColl; } break; } - if( op!=TK_CAST && op!=TK_UPLUS ){ + if( p->flags & EP_Collate ){ + if( p->pLeft->flags & EP_Collate ){ + p = p->pLeft; + }else{ + p = p->pRight; + } + }else{ + break; + } +#if 0 + else if( p->flags & EP_TokenOnly ){ break; + }else{ + pColl = sqlite3ExprCollSeq(pParse, p->pLeft); + p = p->pRight; } - p = p->pLeft; +#endif } if( sqlite3CheckCollSeq(pParse, pColl) ){ pColl = 0; @@ -219,12 +225,10 @@ CollSeq *sqlite3BinaryCompareCollSeq( ){ CollSeq *pColl; assert( pLeft ); - if( pLeft->flags & EP_ExpCollate ){ - assert( pLeft->pColl ); - pColl = pLeft->pColl; - }else if( pRight && pRight->flags & EP_ExpCollate ){ - assert( pRight->pColl ); - pColl = pRight->pColl; + if( pLeft->flags & EP_Collate ){ + pColl = sqlite3ExprCollSeq(pParse, pLeft); + }else if( pRight && (pRight->flags & EP_Collate)!=0 ){ + pColl = sqlite3ExprCollSeq(pParse, pRight); }else{ pColl = sqlite3ExprCollSeq(pParse, pLeft); if( !pColl ){ @@ -454,17 +458,11 @@ void sqlite3ExprAttachSubtrees( }else{ if( pRight ){ pRoot->pRight = pRight; - if( pRight->flags & EP_ExpCollate ){ - pRoot->flags |= EP_ExpCollate; - pRoot->pColl = pRight->pColl; - } + pRoot->flags |= EP_Collate & pRight->flags; } if( pLeft ){ pRoot->pLeft = pLeft; - if( pLeft->flags & EP_ExpCollate ){ - pRoot->flags |= EP_ExpCollate; - pRoot->pColl = pLeft->pColl; - } + pRoot->flags |= EP_Collate & pLeft->flags; } exprSetHeight(pRoot); } @@ -722,7 +720,7 @@ static int dupedExprStructSize(Expr *p, int flags){ assert( !ExprHasProperty(p, EP_FromJoin) ); assert( (p->flags2 & EP2_MallocedToken)==0 ); assert( (p->flags2 & EP2_Irreducible)==0 ); - if( p->pLeft || p->pRight || p->pColl || p->x.pList ){ + if( p->pLeft || p->pRight || p->x.pList ){ nSize = EXPR_REDUCEDSIZE | EP_Reduced; }else{ nSize = EXPR_TOKENONLYSIZE | EP_TokenOnly; @@ -2746,6 +2744,7 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ sqlite3ReleaseTempReg(pParse, r4); break; } + case TK_COLLATE: case TK_UPLUS: { inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target); break; @@ -3773,7 +3772,15 @@ int sqlite3ExprCompare(Expr *pA, Expr *pB){ return 2; } if( (pA->flags & EP_Distinct)!=(pB->flags & EP_Distinct) ) return 2; - if( pA->op!=pB->op ) return 2; + if( pA->op!=pB->op ){ + if( pA->op==TK_COLLATE && sqlite3ExprCompare(pA->pLeft, pB)<2 ){ + return 1; + } + if( pB->op==TK_COLLATE && sqlite3ExprCompare(pA, pB->pLeft)<2 ){ + return 1; + } + return 2; + } if( sqlite3ExprCompare(pA->pLeft, pB->pLeft) ) return 2; if( sqlite3ExprCompare(pA->pRight, pB->pRight) ) return 2; if( sqlite3ExprListCompare(pA->x.pList, pB->x.pList) ) return 2; @@ -3785,11 +3792,9 @@ int sqlite3ExprCompare(Expr *pA, Expr *pB){ }else if( pA->op!=TK_COLUMN && ALWAYS(pA->op!=TK_AGG_COLUMN) && pA->u.zToken){ if( ExprHasProperty(pB, EP_IntValue) || NEVER(pB->u.zToken==0) ) return 2; if( strcmp(pA->u.zToken,pB->u.zToken)!=0 ){ - return 2; + return pA->op==TK_COLLATE ? 1 : 2; } } - if( (pA->flags & EP_ExpCollate)!=(pB->flags & EP_ExpCollate) ) return 1; - if( (pA->flags & EP_ExpCollate)!=0 && pA->pColl!=pB->pColl ) return 2; return 0; } diff --git a/src/fkey.c b/src/fkey.c index a3214a94da..a120b7b2b3 100644 --- a/src/fkey.c +++ b/src/fkey.c @@ -516,7 +516,7 @@ static void fkScanChildren( if( pTab->iPKey==iCol ) iCol = -1; pLeft->iTable = regData+iCol+1; pLeft->affinity = pCol->affinity; - pLeft->pColl = sqlite3LocateCollSeq(pParse, pCol->zColl); + // fix me. pLeft->pColl = sqlite3LocateCollSeq(pParse, pCol->zColl); }else{ pLeft->iTable = regData; pLeft->affinity = SQLITE_AFF_INTEGER; diff --git a/src/resolve.c b/src/resolve.c index 0ffc633558..c2b0523f08 100644 --- a/src/resolve.c +++ b/src/resolve.c @@ -114,10 +114,6 @@ static void resolveAlias( pDup->flags2 |= EP2_MallocedToken; pDup->u.zToken = sqlite3DbStrDup(db, zToken); } - if( pExpr->flags & EP_ExpCollate ){ - pDup->pColl = pExpr->pColl; - pDup->flags |= EP_ExpCollate; - } /* Before calling sqlite3ExprDelete(), set the EP_Static flag. This ** prevents ExprDelete() from deleting the Expr structure itself, @@ -830,13 +826,10 @@ static int resolveCompoundOrderBy( } } if( iCol>0 ){ - CollSeq *pColl = pE->pColl; - int flags = pE->flags & EP_ExpCollate; sqlite3ExprDelete(db, pE); pItem->pExpr = pE = sqlite3Expr(db, TK_INTEGER, 0); if( pE==0 ) return 1; - pE->pColl = pColl; - pE->flags |= EP_IntValue | flags; + pE->flags |= EP_IntValue; pE->u.iValue = iCol; pItem->iOrderByCol = (u16)iCol; pItem->done = 1; diff --git a/src/select.c b/src/select.c index cba766f99d..ee1755dbd8 100644 --- a/src/select.c +++ b/src/select.c @@ -2333,12 +2333,10 @@ static int multiSelectOrderBy( for(i=0; ia[i].pExpr; - if( pTerm->flags & EP_ExpCollate ){ - pColl = pTerm->pColl; + if( pTerm->flags & EP_Collate ){ + pColl = sqlite3ExprCollSeq(pParse, pTerm); }else{ pColl = multiSelectCollSeq(pParse, p, aPermute[i]); - pTerm->flags |= EP_ExpCollate; - pTerm->pColl = pColl; } pKeyMerge->aColl[i] = pColl; pKeyMerge->aSortOrder[i] = pOrderBy->a[i].sortOrder; @@ -2608,9 +2606,6 @@ static Expr *substExpr( assert( pEList!=0 && pExpr->iColumnnExpr ); assert( pExpr->pLeft==0 && pExpr->pRight==0 ); pNew = sqlite3ExprDup(db, pEList->a[pExpr->iColumn].pExpr, 0); - if( pNew && pExpr->pColl ){ - pNew->pColl = pExpr->pColl; - } sqlite3ExprDelete(db, pExpr); pExpr = pNew; } diff --git a/src/sqliteInt.h b/src/sqliteInt.h index b9b9e6c417..fc975bd3c3 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -1678,7 +1678,6 @@ struct Expr { ExprList *pList; /* Function arguments or in " IN ( IN (