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
This commit is contained in:
+9
-10
@@ -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 @@ void sqlite3RegisterBuiltinFunctions(sqlite3 *db){
|
||||
/*
|
||||
** 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 @@ void sqlite3RegisterLikeFunctions(sqlite3 *db, int caseSensitive){
|
||||
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 @@ void sqlite3RegisterLikeFunctions(sqlite3 *db, int caseSensitive){
|
||||
** 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 @@ int sqlite3IsLikeFunction(sqlite3 *db, Expr *pExpr, char *aWc){
|
||||
}
|
||||
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 @@ int sqlite3IsLikeFunction(sqlite3 *db, Expr *pExpr, char *aWc){
|
||||
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;
|
||||
}
|
||||
|
||||
+10
-2
@@ -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 @@ static int openDatabase(
|
||||
){
|
||||
sqlite3 *db;
|
||||
int rc, i;
|
||||
CollSeq *pColl;
|
||||
|
||||
/* Allocate the sqlite data structure */
|
||||
db = sqliteMalloc( sizeof(sqlite3) );
|
||||
@@ -730,6 +731,13 @@ static int openDatabase(
|
||||
/* 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 @@ int sqlite3_create_collation(
|
||||
|
||||
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;
|
||||
|
||||
+13
-3
@@ -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 @@ struct FuncDef {
|
||||
/*
|
||||
** 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,10 +552,19 @@ struct Column {
|
||||
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.
|
||||
*/
|
||||
@@ -1583,7 +1593,7 @@ int sqlite3FindDb(sqlite3*, Token*);
|
||||
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"
|
||||
|
||||
+13
-2
@@ -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 @@ static int isLikeOrGlob(
|
||||
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 @@ static int isLikeOrGlob(
|
||||
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++){}
|
||||
|
||||
Reference in New Issue
Block a user