summaryrefslogtreecommitdiff
path: root/ext/pdo_sqlite/sqlite/src/expr.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext/pdo_sqlite/sqlite/src/expr.c')
-rw-r--r--ext/pdo_sqlite/sqlite/src/expr.c286
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;
-}