From 8b4c40d8ac254b7e0e7da0e72959dc71a12b648d Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 1 Feb 2007 23:02:45 +0000 Subject: [PATCH] First cut at adding the COLLATE operator. Regression tests pass (or at least the quick set does) and a few new tests have been added. But many more tests are needed. Rules for combining collations need to be worked out. (CVS 3624) FossilOrigin-Name: 85cca7cd252d46ba71d302a89bc67c56146ec552 --- manifest | 24 +++++++------- manifest.uuid | 2 +- src/expr.c | 25 ++++++++++++-- src/parse.y | 15 +++++---- src/select.c | 27 +++++++-------- src/sqliteInt.h | 4 ++- test/collate1.test | 82 ++++++++++++++++++++++++++++++++++++++++++++-- test/collate2.test | 53 +++++++++++++++++++++++++++++- www/lang.tcl | 12 +++++-- 9 files changed, 200 insertions(+), 44 deletions(-) diff --git a/manifest b/manifest index 7b38cf5a93..06cd220878 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\sbug\sin\sthe\scopy\smethod\sof\sthe\sTCL\sinterface.\s\sTicket\s#2201.\s(CVS\s3623) -D 2007-02-01T01:53:44 +C First\scut\sat\sadding\sthe\sCOLLATE\soperator.\s\sRegression\stests\spass\s(or\sat\sleast\nthe\squick\sset\sdoes)\sand\sa\sfew\snew\stests\shave\sbeen\sadded.\s\sBut\smany\smore\ntests\sare\sneeded.\s\sRules\sfor\scombining\scollations\sneed\sto\sbe\sworked\sout.\s(CVS\s3624) +D 2007-02-01T23:02:45 F Makefile.in 7fa74bf4359aa899da5586e394d17735f221315f F Makefile.linux-gcc 2d8574d1ba75f129aba2019f0b959db380a90935 F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028 @@ -65,7 +65,7 @@ F src/complete.c 7d1a44be8f37de125fcafd3d3a018690b3799675 F src/date.c 393c73fc027597e008dcd81454544659e978b05c F src/delete.c 804384761144fe1a5035b99f4bd7d706976831bd F src/experimental.c 1b2d1a6cd62ecc39610e97670332ca073c50792b -F src/expr.c ec0b5d9dd6f69425302c255d88475511f5d8b5c9 +F src/expr.c 4ece4d575fa8686535877bbfb2e9d74093a4aa94 F src/func.c b7e1e220a6795ecae7649815145ea5f8644dfa5f F src/hash.c 449f3d6620193aa557f5d86cbc5cc6b87702b185 F src/hash.h 1b3f7e2609141fd571f62199fc38687d262e9564 @@ -87,17 +87,17 @@ F src/os_win.c 8736cf3a49fd651a6538857480f302807d57814c F src/os_win.h 41a946bea10f61c158ce8645e7646b29d44f122b F src/pager.c d6ad66eb119602cb2e6a097f8f635372ba677d23 F src/pager.h 2e6d42f4ae004ae748a037b8468112b851c447a7 -F src/parse.y 31ea08df1305100abd5bcee61b4a01c4e43cbd35 +F src/parse.y ebf4253e3710452953cd1ba8171beb86f47f7f57 F src/pragma.c 5091300911670ddaa552bfa12c45cbca1bb7e7d6 F src/prepare.c 484389c6811415b8f23d259ac9c029613e1c72c3 F src/printf.c aade23a789d7cc88b397ec0d33a0a01a33a7a9c1 F src/random.c 6119474a6f6917f708c1dee25b9a8e519a620e88 -F src/select.c 628f49827d5a94ed9b6246efb8dc9f5c24e413f1 +F src/select.c 63b2163f35fd2570a02dab5759979644c4405f1c F src/server.c 087b92a39d883e3fa113cae259d64e4c7438bc96 F src/shell.c d13ca007cd18192c07a668aeddcdd6a9fe639be9 F src/sqlite.h.in 6b7383baf76070214f6381f603328ca9b22a7fae F src/sqlite3ext.h 011c75fd6459a61454514af07c7a4f1f5c767f27 -F src/sqliteInt.h f6053066ba92ed66507661fe6a78c31ca856b6f8 +F src/sqliteInt.h 650d05a8c530ee3c28ad8b19684d70f889458e60 F src/table.c 6d0da66dde26ee75614ed8f584a1996467088d06 F src/tclsqlite.c cd2b3b86ab07c0e0779f6c6e71e72c6c7dc1e704 F src/test1.c 053f5224697efaefff1f4c647fd90fdea9346cc5 @@ -172,8 +172,8 @@ F test/capi3b.test 5f0bc94b104e11086b1103b20277e1910f59c7f4 F test/capi3c.test 5961df13666c994890ffd44f0143cf92897d18dc F test/cast.test f88e7b6946e9a467cf4bb142d92bb65a83747fc2 F test/check.test e5ea0c1a06c10e81e3434ca029e2c4a562f2b673 -F test/collate1.test add9454cef160677bb8b34148b8f277ce7f9f1c4 -F test/collate2.test 224a632ba04907c049804b08162efd234aa7871f +F test/collate1.test e3eaa48c21e150814be1a7b852d2a8af24458d04 +F test/collate2.test 701d9651c5707024fd86a20649af9ea55e2c0eb8 F test/collate3.test 947a77f5b8227e037a7094d0e338a5504f155cc4 F test/collate4.test daf498e294dcd596b961d425c3f2dda117e4717e F test/collate5.test 8fb4e7e0241839356bd8710f437c32efb47bfff8 @@ -406,7 +406,7 @@ F www/fullscanb.gif f7c94cb227f060511f8909e10f570157263e9a25 F www/index-ex1-x-b.gif f9b1d85c3fa2435cf38b15970c7e3aa1edae23a3 F www/index.tcl 7f67d421e4c1f48083c178bee460a27220f4fcc1 F www/indirect1b1.gif adfca361d2df59e34f9c5cac52a670c2bfc303a1 -F www/lang.tcl aa6d599679cbd5612d7fd7b1ae733ac1221c2a76 +F www/lang.tcl 65d0aa787aa55619dd7a8497306ea539f1201bf3 F www/lockingv3.tcl f59b19d6c8920a931f096699d6faaf61c05db55f F www/mingw.tcl d96b451568c5d28545fefe0c80bee3431c73f69c F www/nulls.tcl ec35193f92485b87b90a994a01d0171b58823fcf @@ -428,7 +428,7 @@ F www/tclsqlite.tcl bb0d1357328a42b1993d78573e587c6dcbc964b9 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0 F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b F www/whentouse.tcl 97e2b5cd296f7d8057e11f44427dea8a4c2db513 -P 505dce8f4e8717341e04f49f6f382719c3c704f1 -R 4143445bb3574091269b3a2a42f03d6f +P 936263966ea70792e8abb712730f78cafa1fdbad +R 2d8d95cad338f4e2489cbc3239cd084f U drh -Z 96cc038466dba8dfd6f53c6f8d4f749d +Z f3d08231d49c025fe236a57faf179faf diff --git a/manifest.uuid b/manifest.uuid index d694ed0637..628e774c7d 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -936263966ea70792e8abb712730f78cafa1fdbad \ No newline at end of file +85cca7cd252d46ba71d302a89bc67c56146ec552 \ No newline at end of file diff --git a/src/expr.c b/src/expr.c index a20e1541cc..7b34352c94 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 @@ -49,6 +49,21 @@ char sqlite3ExprAffinity(Expr *pExpr){ return pExpr->affinity; } +/* +** 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( inSrc-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 1ca6f56da0..ea64d96c37 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 49fa9b8221..57194b9c74 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; ipExpr; - char *zName = pOTerm->zName; - assert( pExpr->op==TK_COLUMN && pExpr->iColumnflags & 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; inExpr; 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 bd14300241..541d9f28af 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 *); diff --git a/test/collate1.test b/test/collate1.test index 2f769e86a9..ac2c75be38 100644 --- a/test/collate1.test +++ b/test/collate1.test @@ -12,7 +12,7 @@ # This file implements regression tests for SQLite library. The # focus of this script is page cache subsystem. # -# $Id: collate1.test,v 1.4 2005/11/01 15:48:25 drh Exp $ +# $Id: collate1.test,v 1.5 2007/02/01 23:02:46 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl @@ -90,6 +90,21 @@ do_test collate1-1.4 { } } {{} 0x2D 0x119} do_test collate1-1.5 { + execsql { + SELECT c2 COLLATE hex FROM collate1t1 ORDER BY 1 + } +} {{} 0x2D 0x119} +do_test collate1-1.6 { + execsql { + SELECT c2 COLLATE hex FROM collate1t1 ORDER BY 1 ASC + } +} {{} 0x2D 0x119} +do_test collate1-1.7 { + execsql { + SELECT c2 COLLATE hex FROM collate1t1 ORDER BY 1 DESC + } +} {0x119 0x2D {}} +do_test collate1-1.99 { execsql { DROP TABLE collate1t1; } @@ -133,7 +148,59 @@ do_test collate1-2.6 { ORDER BY 1 COLLATE binary ASC, 2 COLLATE hex ASC; } } {{} {} 11 0x11 11 0x101 5 0xA 5 0x11 7 0xA} -do_test collate1-2.7 { +do_test collate1-2.12.1 { + execsql { + SELECT c1 COLLATE numeric, c2 FROM collate1t1 + ORDER BY 1, 2 COLLATE hex; + } +} {{} {} 5 0xA 5 0x11 7 0xA 11 0x11 11 0x101} +do_test collate1-2.12.2 { + execsql { + SELECT c1 COLLATE hex, c2 FROM collate1t1 + ORDER BY 1 COLLATE numeric, 2 COLLATE hex; + } +} {{} {} 5 0xA 5 0x11 7 0xA 11 0x11 11 0x101} +do_test collate1-2.12.3 { + execsql { + SELECT c1, c2 COLLATE hex FROM collate1t1 + ORDER BY 1 COLLATE numeric, 2; + } +} {{} {} 5 0xA 5 0x11 7 0xA 11 0x11 11 0x101} +do_test collate1-2.12.4 { + execsql { + SELECT c1 COLLATE numeric, c2 COLLATE hex + FROM collate1t1 + ORDER BY 1, 2; + } +} {{} {} 5 0xA 5 0x11 7 0xA 11 0x11 11 0x101} +do_test collate1-2.13 { + execsql { + SELECT c1 COLLATE binary, c2 COLLATE hex + FROM collate1t1 + ORDER BY 1, 2; + } +} {{} {} 11 0x11 11 0x101 5 0xA 5 0x11 7 0xA} +do_test collate1-2.14 { + execsql { + SELECT c1, c2 + FROM collate1t1 ORDER BY 1 COLLATE binary DESC, 2 COLLATE hex; + } +} {7 0xA 5 0xA 5 0x11 11 0x11 11 0x101 {} {}} +do_test collate1-2.15 { + execsql { + SELECT c1 COLLATE binary, c2 COLLATE hex + FROM collate1t1 + ORDER BY 1 DESC, 2 DESC; + } +} {7 0xA 5 0x11 5 0xA 11 0x101 11 0x11 {} {}} +do_test collate1-2.16 { + execsql { + SELECT c1 COLLATE hex, c2 COLLATE binary + FROM collate1t1 + ORDER BY 1 COLLATE binary ASC, 2 COLLATE hex ASC; + } +} {{} {} 11 0x11 11 0x101 5 0xA 5 0x11 7 0xA} +do_test collate1-2.99 { execsql { DROP TABLE collate1t1; } @@ -180,6 +247,12 @@ do_test collate1-3.5 { SELECT a as c1, b as c2 FROM collate1t1 ORDER BY c1 COLLATE binary; } } {{} {} 0x45 69 0x5 5 1 1} +do_test collate1-3.5.1 { + execsql { + SELECT a COLLATE binary as c1, b as c2 + FROM collate1t1 ORDER BY c1; + } +} {{} {} 0x45 69 0x5 5 1 1} do_test collate1-3.6 { execsql { DROP TABLE collate1t1; @@ -220,6 +293,11 @@ do_test collate1-4.4 { SELECT c1||'' FROM collate1t1 ORDER BY 1; } } {{} 1 101 12} +do_test collate1-4.4.1 { + execsql { + SELECT (c1||'') COLLATE numeric FROM collate1t1 ORDER BY 1; + } +} {{} 1 12 101} do_test collate1-4.5 { execsql { DROP TABLE collate1t1; diff --git a/test/collate2.test b/test/collate2.test index 7c4093b9a8..28f4a913ee 100644 --- a/test/collate2.test +++ b/test/collate2.test @@ -12,7 +12,7 @@ # This file implements regression tests for SQLite library. The # focus of this script is page cache subsystem. # -# $Id: collate2.test,v 1.4 2005/01/21 03:12:16 danielk1977 Exp $ +# $Id: collate2.test,v 1.5 2007/02/01 23:02:46 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl @@ -98,16 +98,67 @@ do_test collate2-1.1 { SELECT a FROM collate2t1 WHERE a > 'aa' ORDER BY 1; } } {ab bA bB ba bb} +do_test collate2-1.1.1 { + execsql { + SELECT a FROM collate2t1 WHERE a COLLATE binary > 'aa' ORDER BY 1; + } +} {ab bA bB ba bb} +do_test collate2-1.1.2 { + execsql { + SELECT a FROM collate2t1 WHERE b COLLATE binary > 'aa' ORDER BY 1; + } +} {ab bA bB ba bb} +do_test collate2-1.1.3 { + execsql { + SELECT a FROM collate2t1 WHERE c COLLATE binary > 'aa' ORDER BY 1; + } +} {ab bA bB ba bb} do_test collate2-1.2 { execsql { SELECT b FROM collate2t1 WHERE b > 'aa' ORDER BY 1, oid; } } {ab aB Ab AB ba bA Ba BA bb bB Bb BB} +do_test collate2-1.2.1 { + execsql { + SELECT b FROM collate2t1 WHERE a COLLATE nocase > 'aa' + ORDER BY 1, oid; + } +} {ab aB Ab AB ba bA Ba BA bb bB Bb BB} +do_test collate2-1.2.2 { + execsql { + SELECT b FROM collate2t1 WHERE b COLLATE nocase > 'aa' + ORDER BY 1, oid; + } +} {ab aB Ab AB ba bA Ba BA bb bB Bb BB} +do_test collate2-1.2.3 { + execsql { + SELECT b FROM collate2t1 WHERE c COLLATE nocase > 'aa' + ORDER BY 1, oid; + } +} {ab aB Ab AB ba bA Ba BA bb bB Bb BB} do_test collate2-1.3 { execsql { SELECT c FROM collate2t1 WHERE c > 'aa' ORDER BY 1; } } {ba Ab Bb ab bb} +do_test collate2-1.3.1 { + execsql { + SELECT c FROM collate2t1 WHERE a COLLATE backwards > 'aa' + ORDER BY 1; + } +} {ba Ab Bb ab bb} +do_test collate2-1.3.2 { + execsql { + SELECT c FROM collate2t1 WHERE b COLLATE backwards > 'aa' + ORDER BY 1; + } +} {ba Ab Bb ab bb} +do_test collate2-1.3.3 { + execsql { + SELECT c FROM collate2t1 WHERE c COLLATE backwards > 'aa' + ORDER BY 1; + } +} {ba Ab Bb ab bb} do_test collate2-1.4 { execsql { SELECT a FROM collate2t1 WHERE a < 'aa' ORDER BY 1; diff --git a/www/lang.tcl b/www/lang.tcl index f51fd0d7bf..83c6d062f0 100644 --- a/www/lang.tcl +++ b/www/lang.tcl @@ -1,7 +1,7 @@ # # Run this Tcl script to generate the lang-*.html files. # -set rcsid {$Id: lang.tcl,v 1.120 2007/01/29 17:58:28 drh Exp $} +set rcsid {$Id: lang.tcl,v 1.121 2007/02/01 23:02:46 drh Exp $} source common.tcl if {[llength $argv]>0} { @@ -1007,7 +1007,8 @@ Syntax {expr} { [NOT] IN [ .] | [EXISTS] ( ) | CASE [] LP WHEN THEN RPPLUS [ELSE ] END | -CAST ( AS ) +CAST ( AS ) | + COLLATE } {like-op} { LIKE | GLOB | REGEXP | MATCH } @@ -1032,12 +1033,17 @@ AND OR -

Supported unary operators are these:

+

Supported unary prefix operators are these:

 -    +    !    ~    NOT
 
+

The COLLATE operator can be thought of as a unary postfix +operator. The COLLATE operator has the highest precedence. +It always binds more tightly than any prefix unary operator or +any binary operator.

+

The unary operator [Operator +] is a no-op. It can be applied to strings, numbers, or blobs and it always gives as its result the value of the operand.

-- 2.47.2