]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
First cut at adding the COLLATE operator. Regression tests pass (or at least
authordrh <drh@noemail.net>
Thu, 1 Feb 2007 23:02:45 +0000 (23:02 +0000)
committerdrh <drh@noemail.net>
Thu, 1 Feb 2007 23:02:45 +0000 (23:02 +0000)
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
manifest.uuid
src/expr.c
src/parse.y
src/select.c
src/sqliteInt.h
test/collate1.test
test/collate2.test
www/lang.tcl

index 7b38cf5a93deb3ed75862fbfa56b9ebdfed088ac..06cd220878a11d673877d590a7d5cdd543d967f2 100644 (file)
--- 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
index d694ed063740fe7bcdfc4c0a611aa524d0eb6228..628e774c7d446d26dbbe41787659458560313038 100644 (file)
@@ -1 +1 @@
-936263966ea70792e8abb712730f78cafa1fdbad
\ No newline at end of file
+85cca7cd252d46ba71d302a89bc67c56146ec552
\ No newline at end of file
index a20e1541ccf3fb7408d5fc37d1078d819073d3c6..7b34352c944319bf673b1d80854e25237c3902d4 100644 (file)
@@ -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>
@@ -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( 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;
           }
index 1ca6f56da0da76af94bfce4ab217d4a7a9ed166e..ea64d96c378d3efd2d124d6b721e680759e25826 100644 (file)
@@ -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);
index 49fa9b8221c85e7011508774824e835a3afd800e..57194b9c7474059e6fde7da30e35e613ac723bb5 100644 (file)
@@ -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;
     }
index bd14300241ba0893f4eaac7bb14f3f6bcf6004fc..541d9f28af6301b3ff2a7dc8822fab938f1ae11e 100644 (file)
@@ -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 *);
index 2f769e86a96a81fbdccad062b0d626bbd790b5a4..ac2c75be388acaa3fc602a4c643bf05b9622eda8 100644 (file)
@@ -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;
index 7c4093b9a8083e7de1622388c54affd72831c899..28f4a913ee7f8ecf9d3638d1826ec1355970f7c2 100644 (file)
@@ -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;
index f51fd0d7bf6180999d63acd7f0708826a4416b0a..83c6d062f038765b65046a35b37e54f768b2a667 100644 (file)
@@ -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} {
 <expr> [NOT] IN [<database-name> .] <table-name> |
 [EXISTS] ( <select-statement> ) |
 CASE [<expr>] LP WHEN <expr> THEN <expr> RPPLUS [ELSE <expr>] END |
-CAST ( <expr> AS <type> )
+CAST ( <expr> AS <type> ) |
+<expr> COLLATE <collation-name>
 } {like-op} {
 LIKE | GLOB | REGEXP | MATCH
 }
@@ -1032,12 +1033,17 @@ AND
 OR</font>
 </pre></blockquote>
 
-<p>Supported unary operators are these:</p>
+<p>Supported unary prefix operators are these:</p>
 
 <blockquote><pre>
 <font color="#2c2cf0"><big>-    +    !    ~    NOT</big></font>
 </pre></blockquote>
 
+<p>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.</p>
+
 <p>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.</p>