Store collation sequence names instead of pointers in sharable schema data structures. (CVS 2904)
FossilOrigin-Name: 0f0213be4d064b3d24e31ff93ec16f6862003d26
This commit is contained in:
parent
d2d4a6b00d
commit
b3bf556ef6
38
manifest
38
manifest
@ -1,5 +1,5 @@
|
||||
C Updates\sto\sthe\sC-API\sdocumentation.\s\sChange\sthe\sparameter\stype\sof\nsqlite3_soft_heap_limit\sto\sinteger.\s(CVS\s2903)
|
||||
D 2006-01-10T15:18:28
|
||||
C Store\scollation\ssequence\snames\sinstead\sof\spointers\sin\ssharable\sschema\sdata\sstructures.\s(CVS\s2904)
|
||||
D 2006-01-10T17:58:23
|
||||
F Makefile.in ab3ffd8d469cef4477257169b82810030a6bb967
|
||||
F Makefile.linux-gcc aee18d8a05546dcf1888bd4547e442008a49a092
|
||||
F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028
|
||||
@ -31,22 +31,22 @@ F sqlite3.1 6be1ad09113570e1fc8dcaff84c9b0b337db5ffc
|
||||
F sqlite3.def c413e514217736884254739a105c8c942fdf0c2f
|
||||
F sqlite3.pc.in 985b9bf34192a549d7d370e0f0b6b34a4f61369a
|
||||
F src/alter.c d0dd079b9ef0d551ff4a4ce09ee270c07b307bbb
|
||||
F src/analyze.c ed87abad3f6f60e1bd5308ed6ff6e0fa396db52b
|
||||
F src/analyze.c 7d2b7ab9a9c2fd6e55700f69064dfdd3e36d7a8a
|
||||
F src/attach.c 8438a2808f89c01cfd472e676a27d771ac4405aa
|
||||
F src/auth.c cdec356a5cd8b217c346f816c5912221537fe87f
|
||||
F src/btree.c 874eaba6dec1660c7c917d5afc790f69de82cf2e
|
||||
F src/btree.h 5663c4f43e8521546ccebc8fc95acb013b8f3184
|
||||
F src/build.c 97997d435acfb9406f776f14931c16559bd534e5
|
||||
F src/callback.c 1c2b78a210fda18cdd4d0b604ed41bf0e1f5125c
|
||||
F src/build.c 59c4a6fc0e89590c7eec3154acb4cf6644674d7d
|
||||
F src/callback.c 51fe813309f7cf69d3d19a2e7be2103130186efd
|
||||
F src/complete.c df1681cef40dec33a286006981845f87b194e7a4
|
||||
F src/date.c a927bdbb51296ac398d2f667086a7072c099e5ab
|
||||
F src/delete.c 66199ba71a0f753033073b080baebb349157c960
|
||||
F src/delete.c b242a0d9462d2b7054e38c5250bdbe94d6772a8e
|
||||
F src/experimental.c 50c1e3b34f752f4ac10c36f287db095c2b61766d
|
||||
F src/expr.c 426717b11cf55cb538ccd3db8a3b22a0f956ce8d
|
||||
F src/expr.c b90fa835a2216edd6808b4bb5da6bbf3b8ee29b9
|
||||
F src/func.c e013c3b6c607c6a1654f5260eab59f5609a5ce4a
|
||||
F src/hash.c 8747cf51d12de46512880dfcf1b68b4e24072863
|
||||
F src/hash.h 1b0c445e1c89ff2aaad9b4605ba61375af001e84
|
||||
F src/insert.c 16610475976dc9b25d231338e283dd4b4362a430
|
||||
F src/insert.c 337785137430a012ff0f1c181d4a4d55d2a942d3
|
||||
F src/legacy.c f651ccd3700f99fa05766ac53506bf9a0694761b
|
||||
F src/main.c 3fe4b606db7d269d7a57c7b51ab3d9ff488e4b98
|
||||
F src/md5.c c5fdfa5c2593eaee2e32a5ce6c6927c986eaf217
|
||||
@ -62,15 +62,15 @@ F src/os_win.h 41a946bea10f61c158ce8645e7646b29d44f122b
|
||||
F src/pager.c f84488fa616f1279761aaf06b0acc42af345d3a5
|
||||
F src/pager.h e0acb095b3ad0bca48f2ab00c87346665643f64f
|
||||
F src/parse.y 83df51fea35f68f7e07384d75dce83d1ed30434c
|
||||
F src/pragma.c 05abacaa5a1817a44876d9dbb4790aa7c784427b
|
||||
F src/prepare.c 41d9a8563e2b988932922c9f96a7bb1271932564
|
||||
F src/pragma.c 711992e440ce78569322dd625d2cfe1cd696ccfb
|
||||
F src/prepare.c 3283bb65b4b217a092c9cbf65014774e6c3a142d
|
||||
F src/printf.c f47a2f4b5387cd2ebb12e9117a1a5d6bd9a2b812
|
||||
F src/random.c d40f8d356cecbd351ccfab6eaedd7ec1b54f5261
|
||||
F src/select.c acfeda959fe07eac04950d945ac7ec0518ef4b7d
|
||||
F src/select.c 579cfdd250c5598de7c867134f7d35a2099b1dcc
|
||||
F src/server.c 42a2bd02eec5018098a96e08f7a923f4965a2b1d
|
||||
F src/shell.c 66b073375efbdee19045e7e0cd38b85f9aff71da
|
||||
F src/sqlite.h.in 821b93f918d126c54d9a91fc928434945655edc3
|
||||
F src/sqliteInt.h f3fe5c8b7d3a7491d6f47f0605b7ed70f146c59f
|
||||
F src/sqliteInt.h d7584dc5b8e15f1732a195ece9e93049ccde35fa
|
||||
F src/table.c 486dcfce532685b53b5a2b5da8bba0ded6fb2316
|
||||
F src/tclsqlite.c d650bea0248fc0a310ddc2cb94273a3a5021fddf
|
||||
F src/test1.c 5f634ce9aa452dbcc362993c9612047df800216c
|
||||
@ -83,7 +83,7 @@ F src/test7.c bfe36c62cae189509660acfeeb891ffb9da8ef0c
|
||||
F src/test_async.c 9733deb7fefa18a3596e5234c1ef05b4685c6ad7
|
||||
F src/tokenize.c 196486012c871cdcad6cc84a820cc988603f1b9d
|
||||
F src/trigger.c 883b5f3b97137fbe417e3337c3fa20ac8e9c1ae5
|
||||
F src/update.c e09da54cb8e042f89f4177f4ef879b594d8ab946
|
||||
F src/update.c cd8ad5bb1a29f2056347481308fca4a59f2f4764
|
||||
F src/utf.c b7bffac4260177ae7f83c01d025fe0f5ed70ce71
|
||||
F src/util.c 5d5792d4a4dda20d70fdfb973ed8a5ed71fea98c
|
||||
F src/vacuum.c f5a068096b22fad438bf1f1cf69ccb7f9e8cc7fb
|
||||
@ -93,8 +93,8 @@ F src/vdbeInt.h 5451cf71f229e366ac543607c0a17f36e5737ea9
|
||||
F src/vdbeapi.c 6d20e92de62b90ae27aeea3a7b18653734b0b1cb
|
||||
F src/vdbeaux.c e4b8f492e41e3b8ecee8f66045e897dae92d1356
|
||||
F src/vdbefifo.c 9efb94c8c3f4c979ebd0028219483f88e57584f5
|
||||
F src/vdbemem.c d712dfd80d58011db688fa8234c1821262a57cae
|
||||
F src/where.c 18a7a16a5b050b2df6f8b03945313ec0f46dc30c
|
||||
F src/vdbemem.c 2ada7cae76da9c840cd0d3c01d2b3987d97141c6
|
||||
F src/where.c 4fecfccf8f35ec7b325d666f0cd2fb016a53da43
|
||||
F tclinstaller.tcl 046e3624671962dc50f0481d7c25b38ef803eb42
|
||||
F test/all.test 90cf64bb655e3d474b0dda04e63ece03e36b0ce2
|
||||
F test/alter.test b94b640063e725d062b2997bd2810ac39195c718
|
||||
@ -340,7 +340,7 @@ F www/tclsqlite.tcl bb0d1357328a42b1993d78573e587c6dcbc964b9
|
||||
F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
|
||||
F www/version3.tcl a99cf5f6d8bd4d5537584a2b342f0fb9fa601d8b
|
||||
F www/whentouse.tcl 97e2b5cd296f7d8057e11f44427dea8a4c2db513
|
||||
P 4f2ec95283f1ae0a28b2f9ce0afc5a7203de87fb
|
||||
R 6f27b31eddededb37a4ce53e31f18e64
|
||||
U drh
|
||||
Z abf90018e50b865b136d9f985b2b2657
|
||||
P bdd35e9fbb651fe7a1ed5042923c9529c3c5ab7c
|
||||
R 86f043f12b95a158f3793bd5117e0f9d
|
||||
U danielk1977
|
||||
Z 598f1f083965de59648a9c0d25b3df80
|
||||
|
@ -1 +1 @@
|
||||
bdd35e9fbb651fe7a1ed5042923c9529c3c5ab7c
|
||||
0f0213be4d064b3d24e31ff93ec16f6862003d26
|
@ -11,7 +11,7 @@
|
||||
*************************************************************************
|
||||
** This file contains code associated with the ANALYZE command.
|
||||
**
|
||||
** @(#) $Id: analyze.c,v 1.15 2006/01/09 06:29:48 danielk1977 Exp $
|
||||
** @(#) $Id: analyze.c,v 1.16 2006/01/10 17:58:23 danielk1977 Exp $
|
||||
*/
|
||||
#ifndef SQLITE_OMIT_ANALYZE
|
||||
#include "sqliteInt.h"
|
||||
@ -114,13 +114,15 @@ static void analyzeOneTable(
|
||||
|
||||
iIdxCur = pParse->nTab;
|
||||
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
|
||||
KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIdx);
|
||||
|
||||
/* Open a cursor to the index to be analyzed
|
||||
*/
|
||||
assert( iDb==sqlite3SchemaToIndex(pParse->db, pIdx->pSchema) );
|
||||
sqlite3VdbeAddOp(v, OP_Integer, iDb, 0);
|
||||
VdbeComment((v, "# %s", pIdx->zName));
|
||||
sqlite3VdbeOp3(v, OP_OpenRead, iIdxCur, pIdx->tnum,
|
||||
(char*)&pIdx->keyInfo, P3_KEYINFO);
|
||||
(char *)pKey, P3_KEYINFO_HANDOFF);
|
||||
nCol = pIdx->nColumn;
|
||||
if( iMem+nCol*2>=pParse->nMem ){
|
||||
pParse->nMem = iMem+nCol*2+1;
|
||||
|
184
src/build.c
184
src/build.c
@ -22,7 +22,7 @@
|
||||
** COMMIT
|
||||
** ROLLBACK
|
||||
**
|
||||
** $Id: build.c,v 1.374 2006/01/10 07:14:23 danielk1977 Exp $
|
||||
** $Id: build.c,v 1.375 2006/01/10 17:58:23 danielk1977 Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include <ctype.h>
|
||||
@ -468,6 +468,7 @@ static void sqliteResetColumnNames(Table *pTable){
|
||||
sqliteFree(pCol->zName);
|
||||
sqlite3ExprDelete(pCol->pDflt);
|
||||
sqliteFree(pCol->zType);
|
||||
sqliteFree(pCol->zColl);
|
||||
}
|
||||
sqliteFree(pTable->aCol);
|
||||
}
|
||||
@ -938,7 +939,6 @@ void sqlite3AddColumn(Parse *pParse, Token *pName){
|
||||
** be called next to set pCol->affinity correctly.
|
||||
*/
|
||||
pCol->affinity = SQLITE_AFF_NONE;
|
||||
pCol->pColl = pParse->db->pDfltColl;
|
||||
p->nCol++;
|
||||
}
|
||||
|
||||
@ -1167,41 +1167,26 @@ void sqlite3AddCheckConstraint(
|
||||
*/
|
||||
void sqlite3AddCollateType(Parse *pParse, const char *zType, int nType){
|
||||
Table *p;
|
||||
Index *pIdx;
|
||||
CollSeq *pColl;
|
||||
int i;
|
||||
|
||||
if( (p = pParse->pNewTable)==0 ) return;
|
||||
i = p->nCol-1;
|
||||
|
||||
pColl = sqlite3LocateCollSeq(pParse, zType, nType);
|
||||
p->aCol[i].pColl = pColl;
|
||||
|
||||
/* If the column is declared as "<name> PRIMARY KEY COLLATE <type>",
|
||||
** then an index may have been created on this column before the
|
||||
** collation type was added. Correct this if it is the case.
|
||||
*/
|
||||
for(pIdx = p->pIndex; pIdx; pIdx=pIdx->pNext){
|
||||
assert( pIdx->nColumn==1 );
|
||||
if( pIdx->aiColumn[0]==i ) pIdx->keyInfo.aColl[0] = pColl;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Call sqlite3CheckCollSeq() for all collating sequences in an index,
|
||||
** in order to verify that all the necessary collating sequences are
|
||||
** loaded.
|
||||
*/
|
||||
int sqlite3CheckIndexCollSeq(Parse *pParse, Index *pIdx){
|
||||
if( pIdx ){
|
||||
int i;
|
||||
for(i=0; i<pIdx->nColumn; i++){
|
||||
if( sqlite3CheckCollSeq(pParse, pIdx->keyInfo.aColl[i]) ){
|
||||
return SQLITE_ERROR;
|
||||
if( sqlite3LocateCollSeq(pParse, zType, nType) ){
|
||||
Index *pIdx;
|
||||
p->aCol[i].zColl = sqlite3StrNDup(zType, nType);
|
||||
|
||||
/* If the column is declared as "<name> PRIMARY KEY COLLATE <type>",
|
||||
** then an index may have been created on this column before the
|
||||
** collation type was added. Correct this if it is the case.
|
||||
*/
|
||||
for(pIdx=p->pIndex; pIdx; pIdx=pIdx->pNext){
|
||||
assert( pIdx->nColumn==1 );
|
||||
if( pIdx->aiColumn[0]==i ){
|
||||
pIdx->azColl[0] = p->aCol[i].zColl;
|
||||
}
|
||||
}
|
||||
}
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1222,8 +1207,9 @@ CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char *zName, int nName){
|
||||
sqlite3 *db = pParse->db;
|
||||
u8 enc = ENC(db);
|
||||
u8 initbusy = db->init.busy;
|
||||
CollSeq *pColl;
|
||||
|
||||
CollSeq *pColl = sqlite3FindCollSeq(db, enc, zName, nName, initbusy);
|
||||
pColl = sqlite3FindCollSeq(db, enc, zName, nName, initbusy);
|
||||
if( !initbusy && (!pColl || !pColl->xCmp) ){
|
||||
pColl = sqlite3GetCollSeq(db, pColl, zName, nName);
|
||||
if( !pColl ){
|
||||
@ -2131,6 +2117,7 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
|
||||
int addr1; /* Address of top of loop */
|
||||
int tnum; /* Root page of index */
|
||||
Vdbe *v; /* Generate code into this virtual machine */
|
||||
KeyInfo *pKey; /* KeyInfo for index */
|
||||
int iDb = sqlite3SchemaToIndex(pParse->db, pIndex->pSchema);
|
||||
|
||||
#ifndef SQLITE_OMIT_AUTHORIZATION
|
||||
@ -2140,14 +2127,6 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Ensure all the required collation sequences are available. This
|
||||
** routine will invoke the collation-needed callback if necessary (and
|
||||
** if one has been registered).
|
||||
*/
|
||||
if( sqlite3CheckIndexCollSeq(pParse, pIndex) ){
|
||||
return;
|
||||
}
|
||||
|
||||
/* Require a write-lock on the table to perform this operation */
|
||||
sqlite3TableLock(pParse, iDb, pTab->tnum, 1, pTab->zName);
|
||||
|
||||
@ -2161,8 +2140,8 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
|
||||
sqlite3VdbeAddOp(v, OP_Clear, tnum, iDb);
|
||||
}
|
||||
sqlite3VdbeAddOp(v, OP_Integer, iDb, 0);
|
||||
sqlite3VdbeOp3(v, OP_OpenWrite, iIdx, tnum,
|
||||
(char*)&pIndex->keyInfo, P3_KEYINFO);
|
||||
pKey = sqlite3IndexKeyinfo(pParse, pIndex);
|
||||
sqlite3VdbeOp3(v, OP_OpenWrite, iIdx, tnum, (char *)pKey, P3_KEYINFO_HANDOFF);
|
||||
sqlite3OpenTable(pParse, iTab, iDb, pTab, OP_OpenRead);
|
||||
addr1 = sqlite3VdbeAddOp(v, OP_Rewind, iTab, 0);
|
||||
sqlite3GenerateIndexKey(v, pIndex, iTab);
|
||||
@ -2221,6 +2200,9 @@ void sqlite3CreateIndex(
|
||||
int iDb; /* Index of the database that is being written */
|
||||
Token *pName = 0; /* Unqualified name of the index to create */
|
||||
struct ExprList_item *pListItem; /* For looping over pList */
|
||||
int nCol;
|
||||
int nExtra = 0;
|
||||
char *zExtra;
|
||||
|
||||
if( pParse->nErr || sqlite3ThreadData()->mallocFailed ){
|
||||
goto exit_create_index;
|
||||
@ -2352,17 +2334,37 @@ void sqlite3CreateIndex(
|
||||
pList->a[0].sortOrder = sortOrder;
|
||||
}
|
||||
|
||||
/* Figure out how many bytes of space are required to store explicitly
|
||||
** specified collation sequence names.
|
||||
*/
|
||||
for(i=0; i<pList->nExpr; i++){
|
||||
Expr *pExpr = pList->a[i].pExpr;
|
||||
if( pExpr ){
|
||||
nExtra += (1 + strlen(pExpr->pColl->zName));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Allocate the index structure.
|
||||
*/
|
||||
nName = strlen(zName);
|
||||
pIndex = sqliteMalloc( sizeof(Index) + nName + 2 + sizeof(int) +
|
||||
(sizeof(int)*2 + sizeof(CollSeq*) + 1)*pList->nExpr );
|
||||
nCol = pList->nExpr;
|
||||
pIndex = sqliteMalloc(
|
||||
sizeof(Index) + /* Index structure */
|
||||
sizeof(int)*nCol + /* Index.aiColumn */
|
||||
sizeof(int)*(nCol+1) + /* Index.aiRowEst */
|
||||
sizeof(char *)*nCol + /* Index.azColl */
|
||||
sizeof(u8)*nCol + /* Index.aSortOrder */
|
||||
nName + 1 + /* Index.zName */
|
||||
nExtra /* Collation sequence names */
|
||||
);
|
||||
if( sqlite3ThreadData()->mallocFailed ) goto exit_create_index;
|
||||
pIndex->aiColumn = (int*)&pIndex->keyInfo.aColl[pList->nExpr];
|
||||
pIndex->aiRowEst = (unsigned*)&pIndex->aiColumn[pList->nExpr];
|
||||
pIndex->zName = (char*)&pIndex->aiRowEst[pList->nExpr+1];
|
||||
pIndex->keyInfo.aSortOrder = &pIndex->zName[nName+1];
|
||||
pIndex->aiColumn = (int *)(&pIndex[1]);
|
||||
pIndex->aiRowEst = (int *)(&pIndex->aiColumn[nCol]);
|
||||
pIndex->azColl = (char **)(&pIndex->aiRowEst[nCol+1]);
|
||||
pIndex->aSortOrder = (u8 *)(&pIndex->azColl[nCol]);
|
||||
pIndex->zName = (char *)(&pIndex->aSortOrder[nCol]);
|
||||
zExtra = (char *)(&pIndex->zName[nName+1]);
|
||||
strcpy(pIndex->zName, zName);
|
||||
pIndex->pTable = pTab;
|
||||
pIndex->nColumn = pList->nExpr;
|
||||
@ -2386,6 +2388,8 @@ void sqlite3CreateIndex(
|
||||
const char *zColName = pListItem->zName;
|
||||
Column *pTabCol;
|
||||
int requestedSortOrder;
|
||||
char *zColl; /* Collation sequence */
|
||||
|
||||
for(j=0, pTabCol=pTab->aCol; j<pTab->nCol; j++, pTabCol++){
|
||||
if( sqlite3StrICmp(zColName, pTabCol->zName)==0 ) break;
|
||||
}
|
||||
@ -2397,20 +2401,22 @@ void sqlite3CreateIndex(
|
||||
pIndex->aiColumn[i] = j;
|
||||
if( pListItem->pExpr ){
|
||||
assert( pListItem->pExpr->pColl );
|
||||
pIndex->keyInfo.aColl[i] = pListItem->pExpr->pColl;
|
||||
zColl = zExtra;
|
||||
strcpy(zExtra, pListItem->pExpr->pColl->zName);
|
||||
zExtra += (strlen(zColl) + 1);
|
||||
}else{
|
||||
pIndex->keyInfo.aColl[i] = pTab->aCol[j].pColl;
|
||||
zColl = pTab->aCol[j].zColl;
|
||||
if( !zColl ){
|
||||
zColl = db->pDfltColl->zName;
|
||||
}
|
||||
}
|
||||
assert( pIndex->keyInfo.aColl[i] );
|
||||
if( !db->init.busy &&
|
||||
sqlite3CheckCollSeq(pParse, pIndex->keyInfo.aColl[i])
|
||||
){
|
||||
if( !db->init.busy && !sqlite3LocateCollSeq(pParse, zColl, -1) ){
|
||||
goto exit_create_index;
|
||||
}
|
||||
pIndex->azColl[i] = zColl;
|
||||
requestedSortOrder = pListItem->sortOrder & sortOrderMask;
|
||||
pIndex->keyInfo.aSortOrder[i] = requestedSortOrder;
|
||||
pIndex->aSortOrder[i] = requestedSortOrder;
|
||||
}
|
||||
pIndex->keyInfo.nField = pList->nExpr;
|
||||
sqlite3DefaultRowEst(pIndex);
|
||||
|
||||
if( pTab==pParse->pNewTable ){
|
||||
@ -2436,9 +2442,11 @@ void sqlite3CreateIndex(
|
||||
|
||||
if( pIdx->nColumn!=pIndex->nColumn ) continue;
|
||||
for(k=0; k<pIdx->nColumn; k++){
|
||||
const char *z1 = pIdx->azColl[k];
|
||||
const char *z2 = pIndex->azColl[k];
|
||||
if( pIdx->aiColumn[k]!=pIndex->aiColumn[k] ) break;
|
||||
if( pIdx->keyInfo.aColl[k]!=pIndex->keyInfo.aColl[k] ) break;
|
||||
if( pIdx->keyInfo.aSortOrder[k]!=pIndex->keyInfo.aSortOrder[k] ) break;
|
||||
if( pIdx->aSortOrder[k]!=pIndex->aSortOrder[k] ) break;
|
||||
if( z1!=z2 && sqlite3StrICmp(z1, z2) ) break;
|
||||
}
|
||||
if( k==pIdx->nColumn ){
|
||||
if( pIdx->onError!=pIndex->onError ){
|
||||
@ -3054,12 +3062,13 @@ void sqlite3BeginWriteOperation(Parse *pParse, int setStatement, int iDb){
|
||||
** true if it does and false if it does not.
|
||||
*/
|
||||
#ifndef SQLITE_OMIT_REINDEX
|
||||
static int collationMatch(CollSeq *pColl, Index *pIndex){
|
||||
int n = pIndex->keyInfo.nField;
|
||||
CollSeq **pp = pIndex->keyInfo.aColl;
|
||||
while( n-- ){
|
||||
if( *pp==pColl ) return 1;
|
||||
pp++;
|
||||
static int collationMatch(const char *zColl, Index *pIndex){
|
||||
int i;
|
||||
for(i=0; i<pIndex->nColumn; i++){
|
||||
const char *z = pIndex->azColl[i];
|
||||
if( z==zColl || (z && zColl && 0==sqlite3StrICmp(z, zColl)) ){
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -3070,11 +3079,11 @@ static int collationMatch(CollSeq *pColl, Index *pIndex){
|
||||
** If pColl==0 then recompute all indices of pTab.
|
||||
*/
|
||||
#ifndef SQLITE_OMIT_REINDEX
|
||||
static void reindexTable(Parse *pParse, Table *pTab, CollSeq *pColl){
|
||||
static void reindexTable(Parse *pParse, Table *pTab, char const *zColl){
|
||||
Index *pIndex; /* An index associated with pTab */
|
||||
|
||||
for(pIndex=pTab->pIndex; pIndex; pIndex=pIndex->pNext){
|
||||
if( pColl==0 || collationMatch(pColl,pIndex) ){
|
||||
if( zColl==0 || collationMatch(zColl, pIndex) ){
|
||||
int iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
|
||||
sqlite3BeginWriteOperation(pParse, 0, iDb);
|
||||
sqlite3RefillIndex(pParse, pIndex, -1);
|
||||
@ -3089,7 +3098,7 @@ static void reindexTable(Parse *pParse, Table *pTab, CollSeq *pColl){
|
||||
** all indices everywhere.
|
||||
*/
|
||||
#ifndef SQLITE_OMIT_REINDEX
|
||||
static void reindexDatabases(Parse *pParse, CollSeq *pColl){
|
||||
static void reindexDatabases(Parse *pParse, char const *zColl){
|
||||
Db *pDb; /* A single database */
|
||||
int iDb; /* The database index number */
|
||||
sqlite3 *db = pParse->db; /* The database connection */
|
||||
@ -3100,7 +3109,7 @@ static void reindexDatabases(Parse *pParse, CollSeq *pColl){
|
||||
if( pDb==0 ) continue;
|
||||
for(k=sqliteHashFirst(&pDb->pSchema->tblHash); k; k=sqliteHashNext(k)){
|
||||
pTab = (Table*)sqliteHashData(k);
|
||||
reindexTable(pParse, pTab, pColl);
|
||||
reindexTable(pParse, pTab, zColl);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3140,9 +3149,14 @@ void sqlite3Reindex(Parse *pParse, Token *pName1, Token *pName2){
|
||||
reindexDatabases(pParse, 0);
|
||||
return;
|
||||
}else if( pName2==0 || pName2->z==0 ){
|
||||
assert( pName1->z );
|
||||
pColl = sqlite3FindCollSeq(db, ENC(db), (char*)pName1->z, pName1->n, 0);
|
||||
if( pColl ){
|
||||
reindexDatabases(pParse, pColl);
|
||||
char *z = sqlite3StrNDup(pName1->z, pName1->n);
|
||||
if( z ){
|
||||
reindexDatabases(pParse, z);
|
||||
sqliteFree(z);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -3166,3 +3180,39 @@ void sqlite3Reindex(Parse *pParse, Token *pName1, Token *pName2){
|
||||
sqlite3ErrorMsg(pParse, "unable to identify the object to be reindexed");
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Return a dynamicly allocated KeyInfo structure that can be used
|
||||
** with OP_OpenRead or OP_OpenWrite to access database index pIdx.
|
||||
**
|
||||
** If successful, a pointer to the new structure is returned. In this case
|
||||
** the caller is responsible for calling sqliteFree() on the returned
|
||||
** pointer. If an error occurs (out of memory or missing collation
|
||||
** sequence), NULL is returned and the state of pParse updated to reflect
|
||||
** the error.
|
||||
*/
|
||||
KeyInfo *sqlite3IndexKeyinfo(Parse *pParse, Index *pIdx){
|
||||
int i;
|
||||
int nCol = pIdx->nColumn;
|
||||
int nBytes = sizeof(KeyInfo) + (nCol-1)*sizeof(CollSeq*) + nCol;
|
||||
KeyInfo *pKey = (KeyInfo *)sqliteMalloc(nBytes);
|
||||
|
||||
if( pKey ){
|
||||
pKey->aSortOrder = (u8 *)&(pKey->aColl[nCol]);
|
||||
assert( &pKey->aSortOrder[nCol]==&(((u8 *)pKey)[nBytes]) );
|
||||
for(i=0; i<nCol; i++){
|
||||
char *zColl = pIdx->azColl[i];
|
||||
assert( zColl );
|
||||
pKey->aColl[i] = sqlite3LocateCollSeq(pParse, zColl, -1);
|
||||
pKey->aSortOrder[i] = pIdx->aSortOrder[i];
|
||||
}
|
||||
pKey->nField = nCol;
|
||||
}
|
||||
|
||||
if( pParse->nErr ){
|
||||
sqliteFree(pKey);
|
||||
pKey = 0;
|
||||
}
|
||||
return pKey;
|
||||
}
|
||||
|
||||
|
@ -13,7 +13,7 @@
|
||||
** This file contains functions used to access the internal hash tables
|
||||
** of user defined functions and collation sequences.
|
||||
**
|
||||
** $Id: callback.c,v 1.9 2006/01/09 16:12:05 danielk1977 Exp $
|
||||
** $Id: callback.c,v 1.10 2006/01/10 17:58:23 danielk1977 Exp $
|
||||
*/
|
||||
|
||||
#include "sqliteInt.h"
|
||||
@ -130,6 +130,7 @@ int sqlite3CheckCollSeq(Parse *pParse, CollSeq *pColl){
|
||||
pParse->nErr++;
|
||||
return SQLITE_ERROR;
|
||||
}
|
||||
assert( p==pColl );
|
||||
}
|
||||
return SQLITE_OK;
|
||||
}
|
||||
@ -199,7 +200,12 @@ CollSeq *sqlite3FindCollSeq(
|
||||
int nName,
|
||||
int create
|
||||
){
|
||||
CollSeq *pColl = findCollSeqEntry(db, zName, nName, create);
|
||||
CollSeq *pColl;
|
||||
if( zName ){
|
||||
pColl = findCollSeqEntry(db, zName, nName, create);
|
||||
}else{
|
||||
pColl = db->pDfltColl;
|
||||
}
|
||||
assert( SQLITE_UTF8==1 && SQLITE_UTF16LE==2 && SQLITE_UTF16BE==3 );
|
||||
assert( enc>=SQLITE_UTF8 && enc<=SQLITE_UTF16BE );
|
||||
if( pColl ) pColl += enc-1;
|
||||
|
@ -12,7 +12,7 @@
|
||||
** This file contains C code routines that are called by the parser
|
||||
** in order to generate code for DELETE FROM statements.
|
||||
**
|
||||
** $Id: delete.c,v 1.116 2006/01/09 06:29:48 danielk1977 Exp $
|
||||
** $Id: delete.c,v 1.117 2006/01/10 17:58:23 danielk1977 Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
|
||||
@ -236,13 +236,6 @@ void sqlite3DeleteFrom(
|
||||
** the table and pick which records to delete.
|
||||
*/
|
||||
else{
|
||||
/* Ensure all required collation sequences are available. */
|
||||
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
|
||||
if( sqlite3CheckIndexCollSeq(pParse, pIdx) ){
|
||||
goto delete_from_cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
/* Begin the database scan
|
||||
*/
|
||||
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0);
|
||||
|
@ -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.246 2006/01/09 16:12:05 danielk1977 Exp $
|
||||
** $Id: expr.c,v 1.247 2006/01/10 17:58:23 danielk1977 Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include <ctype.h>
|
||||
@ -867,6 +867,7 @@ static int lookupName(
|
||||
}
|
||||
for(j=0, pCol=pTab->aCol; j<pTab->nCol; j++, pCol++){
|
||||
if( sqlite3StrICmp(pCol->zName, zCol)==0 ){
|
||||
const char *zColl = pTab->aCol[j].zColl;
|
||||
IdList *pUsing;
|
||||
cnt++;
|
||||
pExpr->iTable = pItem->iCursor;
|
||||
@ -875,7 +876,7 @@ 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 = pTab->aCol[j].pColl;
|
||||
pExpr->pColl = sqlite3FindCollSeq(db, ENC(db), zColl,-1, 0);
|
||||
if( pItem->jointype & JT_NATURAL ){
|
||||
/* If this match occurred in the left table of a natural join,
|
||||
** then skip the right table to avoid a duplicate match */
|
||||
@ -926,10 +927,11 @@ static int lookupName(
|
||||
cntTab++;
|
||||
for(j=0; j < pTab->nCol; j++, pCol++) {
|
||||
if( sqlite3StrICmp(pCol->zName, zCol)==0 ){
|
||||
const char *zColl = pTab->aCol[j].zColl;
|
||||
cnt++;
|
||||
pExpr->iColumn = j==pTab->iPKey ? -1 : j;
|
||||
pExpr->affinity = pTab->aCol[j].affinity;
|
||||
pExpr->pColl = pTab->aCol[j].pColl;
|
||||
pExpr->pColl = sqlite3FindCollSeq(db, ENC(db), zColl,-1, 0);
|
||||
pExpr->pTab = pTab;
|
||||
break;
|
||||
}
|
||||
|
13
src/insert.c
13
src/insert.c
@ -12,7 +12,7 @@
|
||||
** This file contains C code routines that are called by the parser
|
||||
** to handle INSERT statements in SQLite.
|
||||
**
|
||||
** $Id: insert.c,v 1.155 2006/01/09 06:29:48 danielk1977 Exp $
|
||||
** $Id: insert.c,v 1.156 2006/01/10 17:58:23 danielk1977 Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
|
||||
@ -275,13 +275,6 @@ void sqlite3Insert(
|
||||
goto insert_cleanup;
|
||||
}
|
||||
|
||||
/* Ensure all required collation sequences are available. */
|
||||
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
|
||||
if( sqlite3CheckIndexCollSeq(pParse, pIdx) ){
|
||||
goto insert_cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
/* Allocate a VDBE
|
||||
*/
|
||||
v = sqlite3GetVdbe(pParse);
|
||||
@ -1108,11 +1101,11 @@ void sqlite3OpenTableAndIndices(
|
||||
assert( v!=0 );
|
||||
sqlite3OpenTable(pParse, base, iDb, pTab, op);
|
||||
for(i=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
|
||||
KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIdx);
|
||||
assert( pIdx->pSchema==pTab->pSchema );
|
||||
sqlite3VdbeAddOp(v, OP_Integer, iDb, 0);
|
||||
VdbeComment((v, "# %s", pIdx->zName));
|
||||
sqlite3VdbeOp3(v, op, i+base, pIdx->tnum,
|
||||
(char*)&pIdx->keyInfo, P3_KEYINFO);
|
||||
sqlite3VdbeOp3(v, op, i+base, pIdx->tnum, (char*)pKey, P3_KEYINFO_HANDOFF);
|
||||
}
|
||||
if( pParse->nTab<=base+i ){
|
||||
pParse->nTab = base+i;
|
||||
|
@ -11,7 +11,7 @@
|
||||
*************************************************************************
|
||||
** This file contains code used to implement the PRAGMA command.
|
||||
**
|
||||
** $Id: pragma.c,v 1.111 2006/01/09 16:12:05 danielk1977 Exp $
|
||||
** $Id: pragma.c,v 1.112 2006/01/10 17:58:23 danielk1977 Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include "os.h"
|
||||
@ -670,7 +670,6 @@ void sqlite3Pragma(
|
||||
sqlite3VdbeAddOp(v, OP_Integer, pTab->tnum, 0);
|
||||
cnt++;
|
||||
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
|
||||
if( sqlite3CheckIndexCollSeq(pParse, pIdx) ) goto pragma_out;
|
||||
sqlite3VdbeAddOp(v, OP_Integer, pIdx->tnum, 0);
|
||||
cnt++;
|
||||
}
|
||||
|
@ -13,7 +13,7 @@
|
||||
** interface, and routines that contribute to loading the database schema
|
||||
** from disk.
|
||||
**
|
||||
** $Id: prepare.c,v 1.17 2006/01/09 16:12:05 danielk1977 Exp $
|
||||
** $Id: prepare.c,v 1.18 2006/01/10 17:58:23 danielk1977 Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include "os.h"
|
||||
@ -262,7 +262,7 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
|
||||
if( iDb==0 ){
|
||||
/* If opening the main database, set ENC(db). */
|
||||
ENC(db) = (u8)meta[4];
|
||||
db->pDfltColl = sqlite3FindCollSeq(db, ENC(db), "BINARY", 6, 0);
|
||||
db->pDfltColl = sqlite3FindCollSeq(db, SQLITE_UTF8, "BINARY", 6, 0);
|
||||
}else{
|
||||
/* If opening an attached database, the encoding much match ENC(db) */
|
||||
if( meta[4]!=ENC(db) ){
|
||||
|
19
src/select.c
19
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.291 2006/01/09 16:12:05 danielk1977 Exp $
|
||||
** $Id: select.c,v 1.292 2006/01/10 17:58:23 danielk1977 Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
|
||||
@ -978,6 +978,7 @@ Table *sqlite3ResultSetOfSelect(Parse *pParse, char *zTabName, Select *pSelect){
|
||||
char *zType;
|
||||
char *zName;
|
||||
char *zBasename;
|
||||
CollSeq *pColl;
|
||||
int cnt;
|
||||
NameContext sNC;
|
||||
|
||||
@ -1030,9 +1031,9 @@ Table *sqlite3ResultSetOfSelect(Parse *pParse, char *zTabName, Select *pSelect){
|
||||
zType = sqliteStrDup(columnType(&sNC, p));
|
||||
pCol->zType = zType;
|
||||
pCol->affinity = sqlite3ExprAffinity(p);
|
||||
pCol->pColl = sqlite3ExprCollSeq(pParse, p);
|
||||
if( !pCol->pColl ){
|
||||
pCol->pColl = pParse->db->pDfltColl;
|
||||
pColl = sqlite3ExprCollSeq(pParse, p);
|
||||
if( pColl ){
|
||||
pCol->zColl = sqlite3StrDup(pColl->zName);
|
||||
}
|
||||
}
|
||||
pTab->iPKey = -1;
|
||||
@ -2278,7 +2279,10 @@ static int simpleMinMaxQuery(Parse *pParse, Select *p, int eDest, int iParm){
|
||||
CollSeq *pColl = sqlite3ExprCollSeq(pParse, pExpr);
|
||||
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
|
||||
assert( pIdx->nColumn>=1 );
|
||||
if( pIdx->aiColumn[0]==iCol && pIdx->keyInfo.aColl[0]==pColl ) break;
|
||||
if( pIdx->aiColumn[0]==iCol &&
|
||||
0==sqlite3StrICmp(pIdx->azColl[0], pColl->zName) ){
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( pIdx==0 ) return 0;
|
||||
}
|
||||
@ -2321,11 +2325,12 @@ static int simpleMinMaxQuery(Parse *pParse, Select *p, int eDest, int iParm){
|
||||
** "INSERT INTO x SELECT max() FROM x".
|
||||
*/
|
||||
int iIdx;
|
||||
KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIdx);
|
||||
iIdx = pParse->nTab++;
|
||||
assert( pIdx->pSchema==pTab->pSchema );
|
||||
sqlite3VdbeAddOp(v, OP_Integer, iDb, 0);
|
||||
sqlite3VdbeOp3(v, OP_OpenRead, iIdx, pIdx->tnum,
|
||||
(char*)&pIdx->keyInfo, P3_KEYINFO);
|
||||
sqlite3VdbeOp3(v, OP_OpenRead, iIdx, pIdx->tnum,
|
||||
(char*)pKey, P3_KEYINFO_HANDOFF);
|
||||
if( seekOp==OP_Rewind ){
|
||||
sqlite3VdbeAddOp(v, OP_Null, 0, 0);
|
||||
sqlite3VdbeAddOp(v, OP_MakeRecord, 1, 0);
|
||||
|
@ -11,7 +11,7 @@
|
||||
*************************************************************************
|
||||
** Internal interface definitions for SQLite.
|
||||
**
|
||||
** @(#) $Id: sqliteInt.h,v 1.459 2006/01/10 15:18:28 drh Exp $
|
||||
** @(#) $Id: sqliteInt.h,v 1.460 2006/01/10 17:58:23 danielk1977 Exp $
|
||||
*/
|
||||
#ifndef _SQLITEINT_H_
|
||||
#define _SQLITEINT_H_
|
||||
@ -584,7 +584,7 @@ struct Column {
|
||||
char *zName; /* Name of this column */
|
||||
Expr *pDflt; /* Default value of this column */
|
||||
char *zType; /* Data type for this column */
|
||||
CollSeq *pColl; /* Collating sequence. If NULL, use the default */
|
||||
char *zColl; /* Collating sequence. If NULL, use the default */
|
||||
u8 notNull; /* True if there is a NOT NULL constraint */
|
||||
u8 isPrimKey; /* True if this column is part of the PRIMARY KEY */
|
||||
char affinity; /* One of the SQLITE_AFF_... values */
|
||||
@ -600,7 +600,7 @@ struct Column {
|
||||
** processes text encoded in UTF-16 (CollSeq.xCmp16), using the machine
|
||||
** native byte order. When a collation sequence is invoked, SQLite selects
|
||||
** the version that will require the least expensive encoding
|
||||
** transalations, if any.
|
||||
** translations, if any.
|
||||
**
|
||||
** The CollSeq.pUser member variable is an extra parameter that passed in
|
||||
** as the first argument to the UTF-8 comparison function, xCmp.
|
||||
@ -845,11 +845,11 @@ struct Index {
|
||||
int tnum; /* Page containing root of this index in database file */
|
||||
u8 onError; /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */
|
||||
u8 autoIndex; /* True if is automatically created (ex: by UNIQUE) */
|
||||
// u8 iDb; /* Index in sqlite.aDb[] of where this index is stored */
|
||||
char *zColAff; /* String defining the affinity of each column */
|
||||
Index *pNext; /* The next index associated with the same table */
|
||||
Schema *pSchema;
|
||||
KeyInfo keyInfo; /* Info on how to order keys. MUST BE LAST */
|
||||
Schema *pSchema; /* Schema containing this index */
|
||||
u8 *aSortOrder; /* Array of size Index.nColumn. True==DESC, False==ASC */
|
||||
char **azColl; /* Array of collation sequence names for index */
|
||||
};
|
||||
|
||||
/*
|
||||
@ -1736,6 +1736,7 @@ void sqlite3MinimumFileFormat(Parse*, int, int);
|
||||
void sqlite3SchemaFree(void *);
|
||||
Schema *sqlite3SchemaGet(Btree *);
|
||||
int sqlite3SchemaToIndex(sqlite3 *db, Schema *);
|
||||
KeyInfo *sqlite3IndexKeyinfo(Parse *, Index *);
|
||||
|
||||
#ifndef SQLITE_OMIT_SHARED_CACHE
|
||||
void sqlite3TableLock(Parse *, int, int, u8, const char *);
|
||||
|
@ -12,7 +12,7 @@
|
||||
** This file contains C code routines that are called by the parser
|
||||
** to handle UPDATE statements.
|
||||
**
|
||||
** $Id: update.c,v 1.118 2006/01/09 16:12:05 danielk1977 Exp $
|
||||
** $Id: update.c,v 1.119 2006/01/10 17:58:23 danielk1977 Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
|
||||
@ -233,7 +233,6 @@ void sqlite3Update(
|
||||
}
|
||||
}
|
||||
if( i<pIdx->nColumn ){
|
||||
if( sqlite3CheckIndexCollSeq(pParse, pIdx) ) goto update_cleanup;
|
||||
apIdx[nIdx++] = pIdx;
|
||||
aIdxUsed[j] = 1;
|
||||
}else{
|
||||
@ -378,9 +377,10 @@ void sqlite3Update(
|
||||
}
|
||||
for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
|
||||
if( openAll || aIdxUsed[i] ){
|
||||
KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIdx);
|
||||
sqlite3VdbeAddOp(v, OP_Integer, iDb, 0);
|
||||
sqlite3VdbeOp3(v, OP_OpenWrite, iCur+i+1, pIdx->tnum,
|
||||
(char*)&pIdx->keyInfo, P3_KEYINFO);
|
||||
(char*)pKey, P3_KEYINFO_HANDOFF);
|
||||
assert( pParse->nTab>iCur+i+1 );
|
||||
}
|
||||
}
|
||||
|
@ -579,9 +579,9 @@ int sqlite3MemCompare(const Mem *pMem1, const Mem *pMem2, const CollSeq *pColl){
|
||||
assert( pMem1->enc==SQLITE_UTF8 ||
|
||||
pMem1->enc==SQLITE_UTF16LE || pMem1->enc==SQLITE_UTF16BE );
|
||||
|
||||
/* This assert may fail if the collation sequence is deleted after this
|
||||
** vdbe program is compiled. The documentation defines this as an
|
||||
** undefined condition. A crash is usual result.
|
||||
/* The collation sequence must be defined at this point, even if
|
||||
** the user deletes the collation sequence after the vdbe program is
|
||||
** compiled (this was not always the case).
|
||||
*/
|
||||
assert( !pColl || pColl->xCmp );
|
||||
|
||||
|
18
src/where.c
18
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.192 2006/01/09 06:29:49 danielk1977 Exp $
|
||||
** $Id: where.c,v 1.193 2006/01/10 17:58:23 danielk1977 Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
|
||||
@ -450,7 +450,7 @@ static WhereTerm *findTerm(
|
||||
}
|
||||
for(k=0; k<pIdx->nColumn && pIdx->aiColumn[k]!=iColumn; k++){}
|
||||
assert( k<pIdx->nColumn );
|
||||
if( pColl!=pIdx->keyInfo.aColl[k] ) continue;
|
||||
if( sqlite3StrICmp(pColl->zName, pIdx->azColl[k]) ) continue;
|
||||
}
|
||||
return pTerm;
|
||||
}
|
||||
@ -810,7 +810,8 @@ static int isSortingIndex(
|
||||
}
|
||||
pColl = sqlite3ExprCollSeq(pParse, pExpr);
|
||||
if( !pColl ) pColl = db->pDfltColl;
|
||||
if( pExpr->iColumn!=pIdx->aiColumn[i] || pColl!=pIdx->keyInfo.aColl[i] ){
|
||||
if( pExpr->iColumn!=pIdx->aiColumn[i] ||
|
||||
sqlite3StrICmp(pColl->zName, pIdx->azColl[i]) ){
|
||||
/* Term j of the ORDER BY clause does not match column i of the index */
|
||||
if( i<nEqCol ){
|
||||
/* If an index column that is constrained by == fails to match an
|
||||
@ -824,10 +825,10 @@ static int isSortingIndex(
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
assert( pIdx->keyInfo.aSortOrder!=0 );
|
||||
assert( pIdx->aSortOrder!=0 );
|
||||
assert( pTerm->sortOrder==0 || pTerm->sortOrder==1 );
|
||||
assert( pIdx->keyInfo.aSortOrder[i]==0 || pIdx->keyInfo.aSortOrder[i]==1 );
|
||||
termSortOrder = pIdx->keyInfo.aSortOrder[i] ^ pTerm->sortOrder;
|
||||
assert( pIdx->aSortOrder[i]==0 || pIdx->aSortOrder[i]==1 );
|
||||
termSortOrder = pIdx->aSortOrder[i] ^ pTerm->sortOrder;
|
||||
if( i>nEqCol ){
|
||||
if( termSortOrder!=sortOrder ){
|
||||
/* Indices can only be used if all ORDER BY terms past the
|
||||
@ -1586,11 +1587,12 @@ WhereInfo *sqlite3WhereBegin(
|
||||
}
|
||||
pLevel->iTabCur = pTabItem->iCursor;
|
||||
if( (pIx = pLevel->pIdx)!=0 ){
|
||||
KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIx);
|
||||
assert( pIx->pSchema==pTab->pSchema );
|
||||
sqlite3VdbeAddOp(v, OP_Integer, iDb, 0);
|
||||
VdbeComment((v, "# %s", pIx->zName));
|
||||
sqlite3VdbeOp3(v, OP_OpenRead, iIdxCur, pIx->tnum,
|
||||
(char*)&pIx->keyInfo, P3_KEYINFO);
|
||||
(char*)pKey, P3_KEYINFO_HANDOFF);
|
||||
}
|
||||
if( (pLevel->flags & WHERE_IDX_ONLY)!=0 ){
|
||||
sqlite3VdbeAddOp(v, OP_SetNumColumns, iIdxCur, pIx->nColumn+1);
|
||||
@ -1747,7 +1749,7 @@ WhereInfo *sqlite3WhereBegin(
|
||||
** index the operators are reversed.
|
||||
*/
|
||||
nNotNull = nEq + topLimit;
|
||||
if( pIdx->keyInfo.aSortOrder[nEq]==SQLITE_SO_ASC ){
|
||||
if( pIdx->aSortOrder[nEq]==SQLITE_SO_ASC ){
|
||||
topOp = WO_LT|WO_LE;
|
||||
btmOp = WO_GT|WO_GE;
|
||||
}else{
|
||||
|
Loading…
Reference in New Issue
Block a user