diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/expr.c | 25 | ||||
-rw-r--r-- | src/parse.y | 15 | ||||
-rw-r--r-- | src/select.c | 27 | ||||
-rw-r--r-- | src/sqliteInt.h | 4 |
4 files changed, 46 insertions, 25 deletions
diff --git a/src/expr.c b/src/expr.c index a20e1541c..7b34352c9 100644 --- a/src/expr.c +++ b/src/expr.c @@ -12,7 +12,7 @@ ** This file contains routines used for analyzing expressions and ** for generating VDBE code that evaluates expressions in SQLite. ** -** $Id: expr.c,v 1.272 2007/02/01 01:40:44 drh Exp $ +** $Id: expr.c,v 1.273 2007/02/01 23:02:45 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> @@ -50,6 +50,21 @@ char sqlite3ExprAffinity(Expr *pExpr){ } /* +** Set the collating sequence for expression pExpr to be the collating +** sequence named by pToken. Return a pointer to the revised expression. +*/ +Expr *sqlite3ExprSetColl(Parse *pParse, Expr *pExpr, Token *pName){ + CollSeq *pColl; + if( pExpr==0 ) return 0; + pColl = sqlite3LocateCollSeq(pParse, (char*)pName->z, pName->n); + if( pColl ){ + pExpr->pColl = pColl; + pExpr->flags |= EP_ExpCollate; + } + return pExpr; +} + +/* ** Return the default collation sequence for the expression pExpr. If ** there is no default collation type, return 0. */ @@ -890,7 +905,9 @@ static int lookupName( /* Substitute the rowid (column -1) for the INTEGER PRIMARY KEY */ pExpr->iColumn = j==pTab->iPKey ? -1 : j; pExpr->affinity = pTab->aCol[j].affinity; - pExpr->pColl = sqlite3FindCollSeq(db, ENC(db), zColl,-1, 0); + if( (pExpr->flags & EP_ExpCollate)==0 ){ + pExpr->pColl = sqlite3FindCollSeq(db, ENC(db), zColl,-1, 0); + } if( i<pSrcList->nSrc-1 ){ if( pItem[1].jointype & JT_NATURAL ){ /* If this match occurred in the left table of a natural join, @@ -946,7 +963,9 @@ static int lookupName( cnt++; pExpr->iColumn = iCol==pTab->iPKey ? -1 : iCol; pExpr->affinity = pTab->aCol[iCol].affinity; - pExpr->pColl = sqlite3FindCollSeq(db, ENC(db), zColl,-1, 0); + if( (pExpr->flags & EP_ExpCollate)==0 ){ + pExpr->pColl = sqlite3FindCollSeq(db, ENC(db), zColl,-1, 0); + } pExpr->pTab = pTab; break; } diff --git a/src/parse.y b/src/parse.y index 1ca6f56da..ea64d96c3 100644 --- a/src/parse.y +++ b/src/parse.y @@ -14,7 +14,7 @@ ** the parser. Lemon will also generate a header file containing ** numeric codes for all of the tokens. ** -** @(#) $Id: parse.y,v 1.213 2007/01/27 02:38:30 drh Exp $ +** @(#) $Id: parse.y,v 1.214 2007/02/01 23:02:45 drh Exp $ */ // All token codes are small integers with #defines that begin with "TK_" @@ -204,7 +204,7 @@ id(A) ::= ID(X). {A = X;} %left BITAND BITOR LSHIFT RSHIFT. %left PLUS MINUS. %left STAR SLASH REM. -%left CONCAT. +%left CONCAT COLLATE. %right UMINUS UPLUS BITNOT. // And "ids" is an identifer-or-string. @@ -515,12 +515,12 @@ using_opt(U) ::= . {U = 0;} orderby_opt(A) ::= . {A = 0;} orderby_opt(A) ::= ORDER BY sortlist(X). {A = X;} -sortlist(A) ::= sortlist(X) COMMA sortitem(Y) collate(C) sortorder(Z). { - A = sqlite3ExprListAppend(X,Y,C.n>0?&C:0); +sortlist(A) ::= sortlist(X) COMMA sortitem(Y) sortorder(Z). { + A = sqlite3ExprListAppend(X,Y,0); if( A ) A->a[A->nExpr-1].sortOrder = Z; } -sortlist(A) ::= sortitem(Y) collate(C) sortorder(Z). { - A = sqlite3ExprListAppend(0,Y,C.n>0?&C:0); +sortlist(A) ::= sortitem(Y) sortorder(Z). { + A = sqlite3ExprListAppend(0,Y,0); if( A && A->a ) A->a[0].sortOrder = Z; } sortitem(A) ::= expr(X). {A = X;} @@ -642,6 +642,9 @@ expr(A) ::= VARIABLE(X). { Expr *pExpr = A = sqlite3Expr(TK_VARIABLE, 0, 0, pToken); sqlite3ExprAssignVarNumber(pParse, pExpr); } +expr(A) ::= expr(E) COLLATE id(C). { + A = sqlite3ExprSetColl(pParse, E, &C); +} %ifndef SQLITE_OMIT_CAST expr(A) ::= CAST(X) LP expr(E) AS typetoken(T) RP(Y). { A = sqlite3Expr(TK_CAST, E, 0, &T); diff --git a/src/select.c b/src/select.c index 49fa9b822..57194b9c7 100644 --- a/src/select.c +++ b/src/select.c @@ -12,7 +12,7 @@ ** This file contains C code routines that are called by the parser ** to handle SELECT statements in SQLite. ** -** $Id: select.c,v 1.325 2007/01/26 19:23:33 drh Exp $ +** $Id: select.c,v 1.326 2007/02/01 23:02:45 drh Exp $ */ #include "sqliteInt.h" @@ -1952,10 +1952,9 @@ static int multiSelect( apColl = pKeyInfo->aColl; for(i=0; i<nOrderByExpr; i++, pOTerm++, apColl++, pSortOrder++){ Expr *pExpr = pOTerm->pExpr; - char *zName = pOTerm->zName; - assert( pExpr->op==TK_COLUMN && pExpr->iColumn<nCol ); - if( zName ){ - *apColl = sqlite3LocateCollSeq(pParse, zName, -1); + if( (pExpr->flags & EP_ExpCollate) ){ + assert( pExpr->pColl!=0 ); + *apColl = pExpr->pColl; }else{ *apColl = aCopy[pExpr->iColumn]; } @@ -2478,8 +2477,14 @@ static int processOrderGroupBy( Expr *pE = pOrderBy->a[i].pExpr; if( sqlite3ExprIsInteger(pE, &iCol) ){ if( iCol>0 && iCol<=pEList->nExpr ){ + CollSeq *pColl = pE->pColl; + int flags = pE->flags & EP_ExpCollate; sqlite3ExprDelete(pE); pE = pOrderBy->a[i].pExpr = sqlite3ExprDup(pEList->a[iCol-1].pExpr); + if( pColl && flags ){ + pE->pColl = pColl; + pE->flags |= flags; + } }else{ sqlite3ErrorMsg(pParse, "%s BY column number %d out of range - should be " @@ -2914,23 +2919,15 @@ int sqlite3Select( } #endif - /* If there is an ORDER BY clause, resolve any collation sequences - ** names that have been explicitly specified and create a sorting index. - ** - ** This sorting index might end up being unused if the data can be + /* If there is an ORDER BY clause, then this sorting + ** index might end up being unused if the data can be ** extracted in pre-sorted order. If that is the case, then the ** OP_OpenEphemeral instruction will be changed to an OP_Noop once ** we figure out that the sorting index is not needed. The addrSortIndex ** variable is used to facilitate that change. */ if( pOrderBy ){ - struct ExprList_item *pTerm; KeyInfo *pKeyInfo; - for(i=0, pTerm=pOrderBy->a; i<pOrderBy->nExpr; i++, pTerm++){ - if( pTerm->zName ){ - pTerm->pExpr->pColl = sqlite3LocateCollSeq(pParse, pTerm->zName, -1); - } - } if( pParse->nErr ){ goto select_end; } diff --git a/src/sqliteInt.h b/src/sqliteInt.h index bd1430024..541d9f28a 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -11,7 +11,7 @@ ************************************************************************* ** Internal interface definitions for SQLite. ** -** @(#) $Id: sqliteInt.h,v 1.534 2007/02/01 01:40:44 drh Exp $ +** @(#) $Id: sqliteInt.h,v 1.535 2007/02/01 23:02:45 drh Exp $ */ #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ @@ -1021,6 +1021,7 @@ struct Expr { #define EP_VarSelect 0x20 /* pSelect is correlated, not constant */ #define EP_Dequoted 0x40 /* True if the string has been dequoted */ #define EP_InfixFunc 0x80 /* True for an infix function: LIKE, GLOB, etc */ +#define EP_ExpCollate 0x100 /* Collating sequence specified explicitly */ /* ** These macros can be used to test, set, or clear bits in the @@ -1777,6 +1778,7 @@ int sqlite3ReadSchema(Parse *pParse); CollSeq *sqlite3FindCollSeq(sqlite3*,u8 enc, const char *,int,int); CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char *zName, int nName); CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr); +Expr *sqlite3ExprSetColl(Parse *pParse, Expr *, Token *); int sqlite3CheckCollSeq(Parse *, CollSeq *); int sqlite3CheckIndexCollSeq(Parse *, Index *); int sqlite3CheckObjectName(Parse *, const char *); |