The LIKE optimization does the right thing when collating sequences are
present.  LIKE expressions where the left-hand side has COLLATE NOCASE
are optimized in the default case. (CVS 2637)

FossilOrigin-Name: ef84ff795c85e9d28f1cac84ff42d8d4ef84cfc4
diff --git a/src/func.c b/src/func.c
index c7baaa0..919b3a8 100644
--- a/src/func.c
+++ b/src/func.c
@@ -16,7 +16,7 @@
 ** sqliteRegisterBuildinFunctions() found at the bottom of the file.
 ** All other code has file scope.
 **
-** $Id: func.c,v 1.105 2005/08/27 13:16:33 drh Exp $
+** $Id: func.c,v 1.106 2005/08/28 17:00:23 drh Exp $
 */
 #include "sqliteInt.h"
 #include <ctype.h>
@@ -1041,11 +1041,11 @@
 /*
 ** Set the LIKEOPT flag on the 2-argument function with the given name.
 */
-static void setLikeOptFlag(sqlite3 *db, const char *zName){
+static void setLikeOptFlag(sqlite3 *db, const char *zName, int flagVal){
   FuncDef *pDef;
   pDef = sqlite3FindFunction(db, zName, strlen(zName), 2, SQLITE_UTF8, 0);
   if( pDef ){
-    pDef->flags = SQLITE_FUNC_LIKEOPT;
+    pDef->flags = flagVal;
   }
 }
 
@@ -1065,10 +1065,9 @@
   sqlite3_create_function(db, "like", 3, SQLITE_UTF8, pInfo, likeFunc, 0, 0);
   sqlite3_create_function(db, "glob", 2, SQLITE_UTF8, 
       (struct compareInfo*)&globInfo, likeFunc, 0,0);
-  setLikeOptFlag(db, "glob");
-  if( caseSensitive ){
-    setLikeOptFlag(db, "like");
-  }
+  setLikeOptFlag(db, "glob", SQLITE_FUNC_LIKE | SQLITE_FUNC_CASE);
+  setLikeOptFlag(db, "like", 
+      caseSensitive ? (SQLITE_FUNC_LIKE | SQLITE_FUNC_CASE) : SQLITE_FUNC_LIKE);
 }
 
 /*
@@ -1078,7 +1077,7 @@
 ** return TRUE.  If the function is not a LIKE-style function then
 ** return FALSE.
 */
-int sqlite3IsLikeFunction(sqlite3 *db, Expr *pExpr, char *aWc){
+int sqlite3IsLikeFunction(sqlite3 *db, Expr *pExpr, int *pIsNocase, char *aWc){
   FuncDef *pDef;
   if( pExpr->op!=TK_FUNCTION ){
     return 0;
@@ -1088,7 +1087,7 @@
   }
   pDef = sqlite3FindFunction(db, pExpr->token.z, pExpr->token.n, 2,
                              SQLITE_UTF8, 0);
-  if( pDef==0 || (pDef->flags & SQLITE_FUNC_LIKEOPT)==0 ){
+  if( pDef==0 || (pDef->flags & SQLITE_FUNC_LIKE)==0 ){
     return 0;
   }
 
@@ -1100,6 +1099,6 @@
   assert( (char*)&likeInfoAlt == (char*)&likeInfoAlt.matchAll );
   assert( &((char*)&likeInfoAlt)[1] == (char*)&likeInfoAlt.matchOne );
   assert( &((char*)&likeInfoAlt)[2] == (char*)&likeInfoAlt.matchSet );
-
+  *pIsNocase = (pDef->flags & SQLITE_FUNC_CASE)==0;
   return 1;
 }
diff --git a/src/main.c b/src/main.c
index a84f94f..41d1045 100644
--- a/src/main.c
+++ b/src/main.c
@@ -14,7 +14,7 @@
 ** other files are for internal use by SQLite and should not be
 ** accessed by users of the library.
 **
-** $Id: main.c,v 1.298 2005/08/14 01:20:39 drh Exp $
+** $Id: main.c,v 1.299 2005/08/28 17:00:23 drh Exp $
 */
 #include "sqliteInt.h"
 #include "os.h"
@@ -694,6 +694,7 @@
 ){
   sqlite3 *db;
   int rc, i;
+  CollSeq *pColl;
 
   /* Allocate the sqlite data structure */
   db = sqliteMalloc( sizeof(sqlite3) );
@@ -730,6 +731,13 @@
   /* Also add a UTF-8 case-insensitive collation sequence. */
   sqlite3_create_collation(db, "NOCASE", SQLITE_UTF8, 0, nocaseCollatingFunc);
 
+  /* Set flags on the built-in collating sequences */
+  db->pDfltColl->type = SQLITE_COLL_BINARY;
+  pColl = sqlite3FindCollSeq(db, SQLITE_UTF8, "NOCASE", 6, 0);
+  if( pColl ){
+    pColl->type = SQLITE_COLL_NOCASE;
+  }
+
   /* Open the backend database driver */
   rc = sqlite3BtreeFactory(db, zFilename, 0, MAX_PAGES, &db->aDb[0].pBt);
   if( rc!=SQLITE_OK ){
@@ -901,7 +909,7 @@
 
   pColl = sqlite3FindCollSeq(db, (u8)enc, zName, strlen(zName), 1);
   if( 0==pColl ){
-   rc = SQLITE_NOMEM;
+    rc = SQLITE_NOMEM;
   }else{
     pColl->xCmp = xCompare;
     pColl->pUser = pCtx;
diff --git a/src/sqliteInt.h b/src/sqliteInt.h
index 180c0e2..dba03e1 100644
--- a/src/sqliteInt.h
+++ b/src/sqliteInt.h
@@ -11,7 +11,7 @@
 *************************************************************************
 ** Internal interface definitions for SQLite.
 **
-** @(#) $Id: sqliteInt.h,v 1.403 2005/08/19 00:14:42 drh Exp $
+** @(#) $Id: sqliteInt.h,v 1.404 2005/08/28 17:00:23 drh Exp $
 */
 #ifndef _SQLITEINT_H_
 #define _SQLITEINT_H_
@@ -511,7 +511,8 @@
 /*
 ** Possible values for FuncDef.flags
 */
-#define SQLITE_FUNC_LIKEOPT  0x01    /* Candidate for the LIKE optimization */
+#define SQLITE_FUNC_LIKE   0x01  /* Candidate for the LIKE optimization */
+#define SQLITE_FUNC_CASE   0x02  /* Case-sensitive LIKE-type function */
 
 /*
 ** information about each column of an SQL table is held in an instance
@@ -551,11 +552,20 @@
 struct CollSeq {
   char *zName;         /* Name of the collating sequence, UTF-8 encoded */
   u8 enc;              /* Text encoding handled by xCmp() */
+  u8 type;             /* One of the SQLITE_COLL_... values below */
   void *pUser;         /* First argument to xCmp() */
   int (*xCmp)(void*,int, const void*, int, const void*);
 };
 
 /*
+** Allowed values of CollSeq flags:
+*/
+#define SQLITE_COLL_BINARY  1  /* The default memcmp() collating sequence */
+#define SQLITE_COLL_NOCASE  2  /* The built-in NOCASE collating sequence */
+#define SQLITE_COLL_REVERSE 3  /* The built-in REVERSE collating sequence */
+#define SQLITE_COLL_USER    0  /* Any other user-defined collating sequence */
+
+/*
 ** A sort order can be either ASC or DESC.
 */
 #define SQLITE_SO_ASC       0  /* Sort in ascending order */
@@ -1583,7 +1593,7 @@
 void sqlite3AnalysisLoad(sqlite3*,int iDB);
 void sqlite3DefaultRowEst(Index*);
 void sqlite3RegisterLikeFunctions(sqlite3*, int);
-int sqlite3IsLikeFunction(sqlite3*,Expr*,char*);
+int sqlite3IsLikeFunction(sqlite3*,Expr*,int*,char*);
 
 #ifdef SQLITE_SSE
 #include "sseInt.h"
diff --git a/src/where.c b/src/where.c
index 4e355e8..3e59338 100644
--- a/src/where.c
+++ b/src/where.c
@@ -16,7 +16,7 @@
 ** so is applicable.  Because this module is responsible for selecting
 ** indices, you might also think of this module as the "query optimizer".
 **
-** $Id: where.c,v 1.165 2005/08/24 03:52:19 drh Exp $
+** $Id: where.c,v 1.166 2005/08/28 17:00:25 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -479,8 +479,11 @@
   Expr *pRight, *pLeft;
   ExprList *pList;
   int c, cnt;
+  int noCase;
   char wc[3];
-  if( !sqlite3IsLikeFunction(db, pExpr, wc) ){
+  CollSeq *pColl;
+
+  if( !sqlite3IsLikeFunction(db, pExpr, &noCase, wc) ){
     return 0;
   }
   pList = pExpr->pList;
@@ -492,6 +495,14 @@
   if( pLeft->op!=TK_COLUMN ){
     return 0;
   }
+  pColl = pLeft->pColl;
+  if( pColl==0 ){
+    pColl = db->pDfltColl;
+  }
+  if( (pColl->type!=SQLITE_COLL_BINARY || noCase) &&
+      (pColl->type!=SQLITE_COLL_NOCASE || !noCase) ){
+    return 0;
+  }
   sqlite3DequoteExpr(pRight);
   z = pRight->token.z;
   for(cnt=0; (c=z[cnt])!=0 && c!=wc[0] && c!=wc[1] && c!=wc[2]; cnt++){}