diff options
author | Ilia Alshanetsky <iliaa@php.net> | 2005-06-30 20:58:36 +0000 |
---|---|---|
committer | Ilia Alshanetsky <iliaa@php.net> | 2005-06-30 20:58:36 +0000 |
commit | 7d02c9dcb2e9e06aef2e74068abedb929198c4c5 (patch) | |
tree | d4aa4b9ee9c45ef44c51d06710917b81fc022667 /ext/pdo_sqlite/sqlite/src/expr.c | |
parent | efc6ccaa01caba362c59e1708261076e25a28efe (diff) | |
download | php-git-7d02c9dcb2e9e06aef2e74068abedb929198c4c5.tar.gz |
Upgraded bundled sqlite lib to 3.2.2
Diffstat (limited to 'ext/pdo_sqlite/sqlite/src/expr.c')
-rw-r--r-- | ext/pdo_sqlite/sqlite/src/expr.c | 286 |
1 files changed, 92 insertions, 194 deletions
diff --git a/ext/pdo_sqlite/sqlite/src/expr.c b/ext/pdo_sqlite/sqlite/src/expr.c index c4943b1f83..70bdd8692f 100644 --- a/ext/pdo_sqlite/sqlite/src/expr.c +++ b/ext/pdo_sqlite/sqlite/src/expr.c @@ -138,7 +138,7 @@ int sqlite3IndexAffinityOk(Expr *pExpr, char idx_affinity){ */ static int binaryCompareP1(Expr *pExpr1, Expr *pExpr2, int jumpIfNull){ char aff = sqlite3ExprAffinity(pExpr2); - return (((int)sqlite3CompareAffinity(pExpr1, aff))<<8)+(jumpIfNull?1:0); + return ((int)sqlite3CompareAffinity(pExpr1, aff))+(jumpIfNull?0x100:0); } /* @@ -183,7 +183,12 @@ Expr *sqlite3Expr(int op, Expr *pLeft, Expr *pRight, const Token *pToken){ Expr *pNew; pNew = sqliteMalloc( sizeof(Expr) ); if( pNew==0 ){ - /* When malloc fails, we leak memory from pLeft and pRight */ + /* When malloc fails, delete pLeft and pRight. Expressions passed to + ** this function must always be allocated with sqlite3Expr() for this + ** reason. + */ + sqlite3ExprDelete(pLeft); + sqlite3ExprDelete(pRight); return 0; } pNew->op = op; @@ -260,7 +265,7 @@ void sqlite3ExprSpan(Expr *pExpr, Token *pLeft, Token *pRight){ assert( pLeft->dyn==0 || pLeft->z[pLeft->n]==0 ); if( pLeft->dyn==0 && pRight->dyn==0 ){ pExpr->span.z = pLeft->z; - pExpr->span.n = pRight->n + Addr(pRight->z) - Addr(pLeft->z); + pExpr->span.n = pRight->n + (pRight->z - pLeft->z); }else{ pExpr->span.z = 0; } @@ -275,7 +280,7 @@ Expr *sqlite3ExprFunction(ExprList *pList, Token *pToken){ Expr *pNew; pNew = sqliteMalloc( sizeof(Expr) ); if( pNew==0 ){ - /* sqlite3ExprListDelete(pList); // Leak pList when malloc fails */ + sqlite3ExprListDelete(pList); /* Avoid leaking memory when malloc fails */ return 0; } pNew->op = TK_FUNCTION; @@ -403,6 +408,7 @@ Expr *sqlite3ExprDup(Expr *p){ pNew->pRight = sqlite3ExprDup(p->pRight); pNew->pList = sqlite3ExprListDup(p->pList); pNew->pSelect = sqlite3SelectDup(p->pSelect); + pNew->pTab = p->pTab; return pNew; } void sqlite3TokenCopy(Token *pTo, Token *pFrom){ @@ -468,14 +474,15 @@ SrcList *sqlite3SrcListDup(SrcList *p){ for(i=0; i<p->nSrc; i++){ struct SrcList_item *pNewItem = &pNew->a[i]; struct SrcList_item *pOldItem = &p->a[i]; + Table *pTab; pNewItem->zDatabase = sqliteStrDup(pOldItem->zDatabase); pNewItem->zName = sqliteStrDup(pOldItem->zName); pNewItem->zAlias = sqliteStrDup(pOldItem->zAlias); pNewItem->jointype = pOldItem->jointype; pNewItem->iCursor = pOldItem->iCursor; - pNewItem->pTab = pOldItem->pTab; - if( pNewItem->pTab ){ - pNewItem->pTab->isTransient = 0; + pTab = pNewItem->pTab = pOldItem->pTab; + if( pTab ){ + pTab->nRef++; } pNewItem->pSelect = sqlite3SelectDup(pOldItem->pSelect); pNewItem->pOn = sqlite3ExprDup(pOldItem->pOn); @@ -492,7 +499,10 @@ IdList *sqlite3IdListDup(IdList *p){ if( pNew==0 ) return 0; pNew->nId = pNew->nAlloc = p->nId; pNew->a = sqliteMallocRaw( p->nId*sizeof(p->a[0]) ); - if( pNew->a==0 ) return 0; + if( pNew->a==0 ){ + sqliteFree(pNew); + return 0; + } for(i=0; i<p->nId; i++){ struct IdList_item *pNewItem = &pNew->a[i]; struct IdList_item *pOldItem = &p->a[i]; @@ -520,7 +530,6 @@ Select *sqlite3SelectDup(Select *p){ pNew->iLimit = -1; pNew->iOffset = -1; pNew->ppOpenTemp = 0; - pNew->pFetch = 0; pNew->isResolved = p->isResolved; pNew->isAgg = p->isAgg; return pNew; @@ -541,28 +550,34 @@ ExprList *sqlite3ExprListAppend(ExprList *pList, Expr *pExpr, Token *pName){ if( pList==0 ){ pList = sqliteMalloc( sizeof(ExprList) ); if( pList==0 ){ - /* sqlite3ExprDelete(pExpr); // Leak memory if malloc fails */ - return 0; + goto no_mem; } assert( pList->nAlloc==0 ); } if( pList->nAlloc<=pList->nExpr ){ - pList->nAlloc = pList->nAlloc*2 + 4; - pList->a = sqliteRealloc(pList->a, pList->nAlloc*sizeof(pList->a[0])); - if( pList->a==0 ){ - /* sqlite3ExprDelete(pExpr); // Leak memory if malloc fails */ - pList->nExpr = pList->nAlloc = 0; - return pList; - } + struct ExprList_item *a; + int n = pList->nAlloc*2 + 4; + a = sqliteRealloc(pList->a, n*sizeof(pList->a[0])); + if( a==0 ){ + goto no_mem; + } + pList->a = a; + pList->nAlloc = n; } assert( pList->a!=0 ); if( pExpr || pName ){ struct ExprList_item *pItem = &pList->a[pList->nExpr++]; memset(pItem, 0, sizeof(*pItem)); - pItem->pExpr = pExpr; pItem->zName = sqlite3NameFromToken(pName); + pItem->pExpr = pExpr; } return pList; + +no_mem: + /* Avoid leaking memory if malloc has failed. */ + sqlite3ExprDelete(pExpr); + sqlite3ExprListDelete(pList); + return 0; } /* @@ -768,7 +783,7 @@ static int lookupName( zTab = sqlite3NameFromToken(pTableToken); zCol = sqlite3NameFromToken(pColumnToken); if( sqlite3_malloc_failed ){ - return 1; /* Leak memory (zDb and zTab) if malloc fails */ + goto lookupname_end; } pExpr->iTable = -1; @@ -776,7 +791,6 @@ static int lookupName( SrcList *pSrcList = pNC->pSrcList; ExprList *pEList = pNC->pEList; - pNC->nRef++; /* assert( zTab==0 || pEList==0 ); */ if( pSrcList ){ for(i=0, pItem=pSrcList->a; i<pSrcList->nSrc; i++, pItem++){ @@ -804,6 +818,7 @@ static int lookupName( } for(j=0, pCol=pTab->aCol; j<pTab->nCol; j++, pCol++){ if( sqlite3StrICmp(pCol->zName, zCol)==0 ){ + IdList *pUsing; cnt++; pExpr->iTable = pItem->iCursor; pMatch = pItem; @@ -812,6 +827,25 @@ static int lookupName( pExpr->iColumn = j==pTab->iPKey ? -1 : j; pExpr->affinity = pTab->aCol[j].affinity; pExpr->pColl = pTab->aCol[j].pColl; + if( pItem->jointype & JT_NATURAL ){ + /* If this match occurred in the left table of a natural join, + ** then skip the right table to avoid a duplicate match */ + pItem++; + i++; + } + if( (pUsing = pItem->pUsing)!=0 ){ + /* If this match occurs on a column that is in the USING clause + ** of a join, skip the search of the right table of the join + ** to avoid a duplicate match there. */ + int k; + for(k=0; k<pUsing->nId; k++){ + if( sqlite3StrICmp(pUsing->a[k].zName, zCol)==0 ){ + pItem++; + i++; + break; + } + } + } break; } } @@ -847,6 +881,7 @@ static int lookupName( pExpr->iColumn = j==pTab->iPKey ? -1 : j; pExpr->affinity = pTab->aCol[j].affinity; pExpr->pColl = pTab->aCol[j].pColl; + pExpr->pTab = pTab; break; } } @@ -883,9 +918,9 @@ static int lookupName( pExpr->op = TK_AS; pExpr->iColumn = j; pExpr->pLeft = sqlite3ExprDup(pEList->a[j].pExpr); - sqliteFree(zCol); + cnt = 1; assert( zTab==0 && zDb==0 ); - return 0; + goto lookupname_end_2; } } } @@ -904,6 +939,9 @@ static int lookupName( ** Z is a string literal if it doesn't match any column names. In that ** case, we need to return right away and not make any changes to ** pExpr. + ** + ** Because no reference was made to outer contexts, the pNC->nRef + ** fields are not changed in any context. */ if( cnt==0 && zTab==0 && pColumnToken->z[0]=='"' ){ sqliteFree(zCol); @@ -945,63 +983,35 @@ static int lookupName( pMatch->colUsed |= 1<<n; } +lookupname_end: /* Clean up and return */ sqliteFree(zDb); sqliteFree(zTab); - sqliteFree(zCol); sqlite3ExprDelete(pExpr->pLeft); pExpr->pLeft = 0; sqlite3ExprDelete(pExpr->pRight); pExpr->pRight = 0; pExpr->op = TK_COLUMN; +lookupname_end_2: + sqliteFree(zCol); if( cnt==1 ){ assert( pNC!=0 ); sqlite3AuthRead(pParse, pExpr, pNC->pSrcList); - } - return cnt!=1; -} - -/* -** pExpr is a node that defines a function of some kind. It might -** be a syntactic function like "count(x)" or it might be a function -** that implements an operator, like "a LIKE b". -** -** This routine makes *pzName point to the name of the function and -** *pnName hold the number of characters in the function name. -*/ -static void getFunctionName(Expr *pExpr, const char **pzName, int *pnName){ - switch( pExpr->op ){ - case TK_FUNCTION: { - *pzName = pExpr->token.z; - *pnName = pExpr->token.n; - break; - } - case TK_LIKE: { - *pzName = "like"; - *pnName = 4; - break; - } - case TK_GLOB: { - *pzName = "glob"; - *pnName = 4; - break; + if( pMatch && !pMatch->pSelect ){ + pExpr->pTab = pMatch->pTab; } - case TK_CTIME: { - *pzName = "current_time"; - *pnName = 12; - break; - } - case TK_CDATE: { - *pzName = "current_date"; - *pnName = 12; - break; - } - case TK_CTIMESTAMP: { - *pzName = "current_timestamp"; - *pnName = 17; - break; + /* Increment the nRef value on all name contexts from TopNC up to + ** the point where the name matched. */ + for(;;){ + assert( pTopNC!=0 ); + pTopNC->nRef++; + if( pTopNC==pNC ) break; + pTopNC = pTopNC->pNext; } + return 0; + } else { + return 1; } } @@ -1079,11 +1089,7 @@ static int nameResolverStep(void *pArg, Expr *pExpr){ /* Resolve function names */ - case TK_CTIME: - case TK_CTIMESTAMP: - case TK_CDATE: - case TK_GLOB: - case TK_LIKE: + case TK_CONST_FUNC: case TK_FUNCTION: { ExprList *pList = pExpr->pList; /* The argument list */ int n = pList ? pList->nExpr : 0; /* Number of arguments */ @@ -1096,7 +1102,8 @@ static int nameResolverStep(void *pArg, Expr *pExpr){ FuncDef *pDef; /* Information about the function */ int enc = pParse->db->enc; /* The database encoding */ - getFunctionName(pExpr, &zId, &nId); + zId = pExpr->token.z; + nId = pExpr->token.n; pDef = sqlite3FindFunction(pParse->db, zId, nId, n, enc, 0); if( pDef==0 ){ pDef = sqlite3FindFunction(pParse->db, zId, nId, -1, enc, 0); @@ -1302,8 +1309,7 @@ void sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){ /* Evaluate the expression and insert it into the temp table */ sqlite3ExprCode(pParse, pE2); sqlite3VdbeOp3(v, OP_MakeRecord, 1, 0, &affinity, 1); - sqlite3VdbeAddOp(v, OP_String8, 0, 0); - sqlite3VdbeAddOp(v, OP_PutStrKey, pExpr->iTable, 0); + sqlite3VdbeAddOp(v, OP_IdxInsert, pExpr->iTable, 0); } } sqlite3VdbeChangeP3(v, addr, (void *)&keyInfo, P3_KEYINFO); @@ -1375,7 +1381,7 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){ int op; if( v==0 ) return; if( pExpr==0 ){ - sqlite3VdbeAddOp(v, OP_String8, 0, 0); /* Empty expression evals to NULL */ + sqlite3VdbeAddOp(v, OP_Null, 0, 0); return; } op = pExpr->op; @@ -1385,13 +1391,9 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){ sqlite3VdbeAddOp(v, OP_AggGet, pExpr->iAggCtx, pExpr->iAgg); }else if( pExpr->iColumn>=0 ){ sqlite3VdbeAddOp(v, OP_Column, pExpr->iTable, pExpr->iColumn); -#ifndef NDEBUG - if( pExpr->span.z && pExpr->span.n>0 && pExpr->span.n<100 ){ - VdbeComment((v, "# %T", &pExpr->span)); - } -#endif + sqlite3ColumnDefault(v, pExpr->pTab, pExpr->iColumn); }else{ - sqlite3VdbeAddOp(v, OP_Recno, pExpr->iTable, 0); + sqlite3VdbeAddOp(v, OP_Rowid, pExpr->iTable, 0); } break; } @@ -1407,6 +1409,10 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){ sqlite3VdbeDequoteP3(v, -1); break; } + case TK_NULL: { + sqlite3VdbeAddOp(v, OP_Null, 0, 0); + break; + } #ifndef SQLITE_OMIT_BLOB_LITERAL case TK_BLOB: { assert( TK_BLOB==OP_HexBlob ); @@ -1415,10 +1421,6 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){ break; } #endif - case TK_NULL: { - sqlite3VdbeAddOp(v, OP_String8, 0, 0); - break; - } case TK_VARIABLE: { sqlite3VdbeAddOp(v, OP_Variable, pExpr->iTable, 0); if( pExpr->token.n>1 ){ @@ -1516,11 +1518,7 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){ sqlite3VdbeAddOp(v, OP_AggGet, 0, pExpr->iAgg); break; } - case TK_CDATE: - case TK_CTIME: - case TK_CTIMESTAMP: - case TK_GLOB: - case TK_LIKE: + case TK_CONST_FUNC: case TK_FUNCTION: { ExprList *pList = pExpr->pList; int nExpr = pList ? pList->nExpr : 0; @@ -1531,7 +1529,8 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){ int i; u8 enc = pParse->db->enc; CollSeq *pColl = 0; - getFunctionName(pExpr, &zId, &nId); + zId = pExpr->token.z; + nId = pExpr->token.n; pDef = sqlite3FindFunction(pParse->db, zId, nId, nExpr, enc, 0); assert( pDef!=0 ); nExpr = sqlite3ExprCodeExprList(pParse, pList); @@ -1578,7 +1577,7 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){ addr = sqlite3VdbeCurrentAddr(v); sqlite3VdbeAddOp(v, OP_NotNull, -1, addr+4); /* addr + 0 */ sqlite3VdbeAddOp(v, OP_Pop, 2, 0); - sqlite3VdbeAddOp(v, OP_String8, 0, 0); + sqlite3VdbeAddOp(v, OP_Null, 0, 0); sqlite3VdbeAddOp(v, OP_Goto, 0, addr+7); sqlite3VdbeOp3(v, OP_MakeRecord, 1, 0, &affinity, 1); /* addr + 4 */ sqlite3VdbeAddOp(v, OP_Found, pExpr->iTable, addr+7); @@ -1648,7 +1647,7 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){ if( pExpr->pRight ){ sqlite3ExprCode(pParse, pExpr->pRight); }else{ - sqlite3VdbeAddOp(v, OP_String8, 0, 0); + sqlite3VdbeAddOp(v, OP_Null, 0, 0); } sqlite3VdbeResolveLabel(v, expr_end_label); break; @@ -2070,104 +2069,3 @@ int sqlite3ExprAnalyzeAggregates(NameContext *pNC, Expr *pExpr){ walkExprTree(pExpr, analyzeAggregate, pNC); return pNC->pParse->nErr - nErr; } - -/* -** Locate a user function given a name, a number of arguments and a flag -** indicating whether the function prefers UTF-16 over UTF-8. Return a -** pointer to the FuncDef structure that defines that function, or return -** NULL if the function does not exist. -** -** If the createFlag argument is true, then a new (blank) FuncDef -** structure is created and liked into the "db" structure if a -** no matching function previously existed. When createFlag is true -** and the nArg parameter is -1, then only a function that accepts -** any number of arguments will be returned. -** -** If createFlag is false and nArg is -1, then the first valid -** function found is returned. A function is valid if either xFunc -** or xStep is non-zero. -** -** If createFlag is false, then a function with the required name and -** number of arguments may be returned even if the eTextRep flag does not -** match that requested. -*/ -FuncDef *sqlite3FindFunction( - sqlite3 *db, /* An open database */ - const char *zName, /* Name of the function. Not null-terminated */ - int nName, /* Number of characters in the name */ - int nArg, /* Number of arguments. -1 means any number */ - u8 enc, /* Preferred text encoding */ - int createFlag /* Create new entry if true and does not otherwise exist */ -){ - FuncDef *p; /* Iterator variable */ - FuncDef *pFirst; /* First function with this name */ - FuncDef *pBest = 0; /* Best match found so far */ - int bestmatch = 0; - - - assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE ); - if( nArg<-1 ) nArg = -1; - - pFirst = (FuncDef*)sqlite3HashFind(&db->aFunc, zName, nName); - for(p=pFirst; p; p=p->pNext){ - /* During the search for the best function definition, bestmatch is set - ** as follows to indicate the quality of the match with the definition - ** pointed to by pBest: - ** - ** 0: pBest is NULL. No match has been found. - ** 1: A variable arguments function that prefers UTF-8 when a UTF-16 - ** encoding is requested, or vice versa. - ** 2: A variable arguments function that uses UTF-16BE when UTF-16LE is - ** requested, or vice versa. - ** 3: A variable arguments function using the same text encoding. - ** 4: A function with the exact number of arguments requested that - ** prefers UTF-8 when a UTF-16 encoding is requested, or vice versa. - ** 5: A function with the exact number of arguments requested that - ** prefers UTF-16LE when UTF-16BE is requested, or vice versa. - ** 6: An exact match. - ** - ** A larger value of 'matchqual' indicates a more desirable match. - */ - if( p->nArg==-1 || p->nArg==nArg || nArg==-1 ){ - int match = 1; /* Quality of this match */ - if( p->nArg==nArg || nArg==-1 ){ - match = 4; - } - if( enc==p->iPrefEnc ){ - match += 2; - } - else if( (enc==SQLITE_UTF16LE && p->iPrefEnc==SQLITE_UTF16BE) || - (enc==SQLITE_UTF16BE && p->iPrefEnc==SQLITE_UTF16LE) ){ - match += 1; - } - - if( match>bestmatch ){ - pBest = p; - bestmatch = match; - } - } - } - - /* If the createFlag parameter is true, and the seach did not reveal an - ** exact match for the name, number of arguments and encoding, then add a - ** new entry to the hash table and return it. - */ - if( createFlag && bestmatch<6 && - (pBest = sqliteMalloc(sizeof(*pBest)+nName+1)) ){ - pBest->nArg = nArg; - pBest->pNext = pFirst; - pBest->zName = (char*)&pBest[1]; - pBest->iPrefEnc = enc; - memcpy(pBest->zName, zName, nName); - pBest->zName[nName] = 0; - if( pBest==sqlite3HashInsert(&db->aFunc,pBest->zName,nName,(void*)pBest) ){ - sqliteFree(pBest); - return 0; - } - } - - if( pBest && (pBest->xStep || pBest->xFunc || createFlag) ){ - return pBest; - } - return 0; -} |