]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Store collation sequence names instead of pointers in sharable schema data structures...
authordanielk1977 <danielk1977@noemail.net>
Tue, 10 Jan 2006 17:58:23 +0000 (17:58 +0000)
committerdanielk1977 <danielk1977@noemail.net>
Tue, 10 Jan 2006 17:58:23 +0000 (17:58 +0000)
FossilOrigin-Name: 0f0213be4d064b3d24e31ff93ec16f6862003d26

15 files changed:
manifest
manifest.uuid
src/analyze.c
src/build.c
src/callback.c
src/delete.c
src/expr.c
src/insert.c
src/pragma.c
src/prepare.c
src/select.c
src/sqliteInt.h
src/update.c
src/vdbemem.c
src/where.c

index 681fed375a08f33836bfd074d26e133cda3b37e1..e4a6a1e151f41153f5ba934aa65571bf285cca20 100644 (file)
--- a/manifest
+++ b/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
index 367af7c8c5ffa46ee84a4e13bc2d5555ed47c15c..6dee7c9d149272dd90818f9c455970fdb1476544 100644 (file)
@@ -1 +1 @@
-bdd35e9fbb651fe7a1ed5042923c9529c3c5ab7c
\ No newline at end of file
+0f0213be4d064b3d24e31ff93ec16f6862003d26
\ No newline at end of file
index ba07b7bd2d2e30821abd92fab0bfd2d479681ac7..3d27134e4ac212d26677b59087967952a13f0e79 100644 (file)
@@ -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;
index 3fd4308f12ddd0c50e11fcc46ab118f21cd669a4..e7c1742e290ed0ca995395c01e6f2f7853674ffe 100644 (file)
@@ -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;
+}
+
index bd8e28eeb64ab927c66c45a01b6d296a523045c7..a1bf57789506c9f21f8482054b79343eab5c192b 100644 (file)
@@ -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;
index fd5065d54432754fb1fd586c5efeeb27317f8434..c1bc529986e4fa4cc9659fc5e9b1f8beceb74fbb 100644 (file)
@@ -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);
index d3c31f15889fbd23a3f9eabd0e81732866295a94..fa7be8c35df46e4f25c8456c6724f4ade3097c46 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.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;
           }
index b1191eb7d0ae7c03f8c284b2950e5f9dfa1612a9..3d4c460b65e3bd53f64342d4cf38d32716bcc226 100644 (file)
@@ -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;
index ff694146d3aad554d89d596cf3dccbd827c99a07..b9f510cd7a6a7551e98b70bfbecebd0fd8992f93 100644 (file)
@@ -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++;
         }
index 4efdf1fec5059c822de9cc317b92c57658733959..c59d7fc82ae2c61f486488ae56da8a722e7985f5 100644 (file)
@@ -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) ){
index 0b401b392dbbd348110e5e5df64d5a3ac2bc3aca..145f319b0856e65e424fbcc8726f1064310c6b30 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.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);
index f3a9227f7d323af3d723753b95cf0ca94802db32..5dc84f2decf68e6ba0e9cfd52dc3b51ca98b1cc5 100644 (file)
@@ -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 *);
index 3c8cb61a83e2e78e2498504d9c8945997b1327e6..c44e24e1eb5c8a3e430082de32262da08972c40c 100644 (file)
@@ -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 );
       }
     }
index e7b5b0d632f7cce4a17b4405cde0af3fe9b78f42..e3463352f844ae300d796de831747626dbb35937 100644 (file)
@@ -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 );
 
index 104a7892e61ac566ceeeadcf5d438159debc02f3..e427e62c124dcdff7362b284632a3be51310828a 100644 (file)
@@ -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{