]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Remove the aFKey hash table, which was not being used. Simplify the
authordrh <drh@noemail.net>
Sat, 2 May 2009 13:29:37 +0000 (13:29 +0000)
committerdrh <drh@noemail.net>
Sat, 2 May 2009 13:29:37 +0000 (13:29 +0000)
FKey object.  Simplify the hash.c module since the copyKey parameter
formerly used only by aFKey is now no longer required. (CVS 6594)

FossilOrigin-Name: 80c43a355c6e482457abc2f9c3ad3a565cec55fb

manifest
manifest.uuid
src/build.c
src/callback.c
src/hash.c
src/hash.h
src/main.c
src/sqliteInt.h

index d1483fa29366b4779e0820904f9205a4b9cc2261..4de93f52a476392858c9d63d9060af5f383eb651 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Reduce\sthe\ssize\sof\san\sinteger\sliteral\sin\srowhash.tcl\sso\sthat\sthe\stest\nis\sable\sto\srun\swith\sthe\sdefault\sTCL\sinstallation\son\sMac\sOS\s10.5.\s(CVS\s6593)
-D 2009-05-02T12:02:02
+C Remove\sthe\saFKey\shash\stable,\swhich\swas\snot\sbeing\sused.\s\sSimplify\sthe\nFKey\sobject.\s\sSimplify\sthe\shash.c\smodule\ssince\sthe\scopyKey\sparameter\nformerly\sused\sonly\sby\saFKey\sis\snow\sno\slonger\srequired.\s(CVS\s6594)
+D 2009-05-02T13:29:38
 F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
 F Makefile.in 583e87706abc3026960ed759aff6371faf84c211
 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
@@ -109,8 +109,8 @@ F src/btmutex.c 9b899c0d8df3bd68f527b0afe03088321b696d3c
 F src/btree.c 64ad8841aefce2ba0cb3b138e5fe8669ce5fa6db
 F src/btree.h 99fcc7e8c4a1e35afe271bcb38de1a698dfc904e
 F src/btreeInt.h df64030d632f8c8ac217ed52e8b6b3eacacb33a5
-F src/build.c a079f965feea2d0b469b293e09cd0ac41be1272f
-F src/callback.c 73016376d6848ba987709e8c9048d4f0e0776036
+F src/build.c 9f00cc9cc0a3e7271dad30cd11915ea1f323174d
+F src/callback.c 3aff18ce7ede2baba7c7cad1f55f9d88fa0c323e
 F src/complete.c 5ad5c6cd4548211867c204c41a126d73a9fbcea0
 F src/date.c d327ec7bb2f64b08d32b1035de82b9ba8675de91
 F src/delete.c a0a0932eea77471ab243337026abbce444024c43
@@ -118,14 +118,14 @@ F src/expr.c 40b35167137c53777d15d3247d93615b4eefec2d
 F src/fault.c dc88c821842157460750d2d61a8a8b4197d047ff
 F src/func.c f667fe886309707c7178542073bb0ced00a9fae7
 F src/global.c 448419c44ce0701104c2121b0e06919b44514c0c
-F src/hash.c 0caea57f020226903cd8591125732e1e19f17f14
-F src/hash.h 457e230c3b2bd3c56742824d43b16618ff30d7c0
+F src/hash.c 7e90268f62662dc8ccb9da1e93090ea64481e4f8
+F src/hash.h 35b216c13343d0b4f87d9f21969ac55ad72174e1
 F src/hwtime.h 4a1d45f4cae1f402ea19686acf24acf4f0cb53cb
 F src/insert.c 0805018acaa97c5f5b83d4e058da821bc12fa0c6
 F src/journal.c e00df0c0da8413ab6e1bb7d7cab5665d4a9000d0
 F src/legacy.c 2ad5b52df322d0f132f66817095e0e79c8942611
 F src/loadext.c 3f96631089fc4f3871a67f02f2e4fc7ea4d51edc
-F src/main.c 96da66bcc2639d9ed3b0d223853ba79e34da7025
+F src/main.c 27a22ea98931594fcd476c87066a948a2faa53b6
 F src/malloc.c a1f0f8ae110abb8eb546e259ab0eaea7e0f9b588
 F src/mem0.c f2f84062d1f35814d6535c9f9e33de3bfb3b132c
 F src/mem1.c e6d5c23941288df8191b8a98c28e3f57771e2270
@@ -162,7 +162,7 @@ F src/select.c 84022ec5d41c321e98fa96e4f4d5e44de203a099
 F src/shell.c 0a11f831603f17fea20ca97133c0f64e716af4a7
 F src/sqlite.h.in 926985a312747e284c21ab32a8e8231a3bed9bd1
 F src/sqlite3ext.h 1db7d63ab5de4b3e6b83dd03d1a4e64fef6d2a17
-F src/sqliteInt.h 6ca6e40ee904ccdbbaaa3da82c0c92057459cf75
+F src/sqliteInt.h a734ac9d1c5f0d2b3b1ebc8581e237d1293ae6b7
 F src/sqliteLimit.h ffe93f5a0c4e7bd13e70cd7bf84cfb5c3465f45d
 F src/status.c 237b193efae0cf6ac3f0817a208de6c6c6ef6d76
 F src/table.c cc86ad3d6ad54df7c63a3e807b5783c90411a08d
@@ -727,7 +727,7 @@ F tool/speedtest16.c c8a9c793df96db7e4933f0852abb7a03d48f2e81
 F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
 F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
-P 9950c0a79c82eb7d8495b0b1a8fe117d566e2387
-R 6ae38c3439a7c80d21c4c447ba2af531
+P 2229accef308db9feac4e1de16b57e7f680dbb1a
+R 7adc2aa8ad28fd5fae72c98955166e30
 U drh
-Z a3a56a3572a73362a5dc6024fff3a217
+Z de5878a9bc4d8c7d1245568e36e5b246
index 188d3e024928ed0f9facdf10baa4fd72144cd045..4ecc7725c5687c7de7c90722969578ff741ad1dc 100644 (file)
@@ -1 +1 @@
-2229accef308db9feac4e1de16b57e7f680dbb1a
\ No newline at end of file
+80c43a355c6e482457abc2f9c3ad3a565cec55fb
\ No newline at end of file
index 01222593a124212eebfffd6a59db765c47952188..9dc63a440bcbf0c07bba2d6652f8dfd78fbe6221 100644 (file)
@@ -22,7 +22,7 @@
 **     COMMIT
 **     ROLLBACK
 **
-** $Id: build.c,v 1.533 2009/05/01 21:13:37 drh Exp $
+** $Id: build.c,v 1.534 2009/05/02 13:29:38 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -489,8 +489,7 @@ static void sqliteResetColumnNames(Table *pTable){
 ** Table.  No changes are made to disk by this routine.
 **
 ** This routine just deletes the data structure.  It does not unlink
-** the table data structure from the hash table.  Nor does it remove
-** foreign keys from the sqlite.aFKey hash table.  But it does destroy
+** the table data structure from the hash table.  But it does destroy
 ** memory structures of the indices and foreign keys associated with 
 ** the table.
 */
@@ -518,13 +517,9 @@ void sqlite3DeleteTable(Table *pTable){
   }
 
 #ifndef SQLITE_OMIT_FOREIGN_KEY
-  /* Delete all foreign keys associated with this table.  The keys
-  ** should have already been unlinked from the pSchema->aFKey hash table 
-  */
+  /* Delete all foreign keys associated with this table. */
   for(pFKey=pTable->pFKey; pFKey; pFKey=pNextFKey){
     pNextFKey = pFKey->pNextFrom;
-    assert( sqlite3HashFind(&pTable->pSchema->aFKey,
-                           pFKey->zTo, sqlite3Strlen30(pFKey->zTo))!=pFKey );
     sqlite3DbFree(db, pFKey);
   }
 #endif
@@ -548,7 +543,6 @@ void sqlite3DeleteTable(Table *pTable){
 */
 void sqlite3UnlinkAndDeleteTable(sqlite3 *db, int iDb, const char *zTabName){
   Table *p;
-  FKey *pF1, *pF2;
   Db *pDb;
 
   assert( db!=0 );
@@ -557,23 +551,7 @@ void sqlite3UnlinkAndDeleteTable(sqlite3 *db, int iDb, const char *zTabName){
   pDb = &db->aDb[iDb];
   p = sqlite3HashInsert(&pDb->pSchema->tblHash, zTabName,
                         sqlite3Strlen30(zTabName),0);
-  if( p ){
-#ifndef SQLITE_OMIT_FOREIGN_KEY
-    for(pF1=p->pFKey; pF1; pF1=pF1->pNextFrom){
-      int nTo = sqlite3Strlen30(pF1->zTo);
-      pF2 = sqlite3HashFind(&pDb->pSchema->aFKey, pF1->zTo, nTo);
-      if( pF2==pF1 ){
-        sqlite3HashInsert(&pDb->pSchema->aFKey, pF1->zTo, nTo, pF1->pNextTo);
-      }else{
-        while( pF2 && pF2->pNextTo!=pF1 ){ pF2=pF2->pNextTo; }
-        if( pF2 ){
-          pF2->pNextTo = pF1->pNextTo;
-        }
-      }
-    }
-#endif
-    sqlite3DeleteTable(p);
-  }
+  sqlite3DeleteTable(p);
   db->flags |= SQLITE_InternChanges;
 }
 
@@ -1688,7 +1666,6 @@ void sqlite3EndTable(
   */
   if( db->init.busy && pParse->nErr==0 ){
     Table *pOld;
-    FKey *pFKey; 
     Schema *pSchema = p->pSchema;
     pOld = sqlite3HashInsert(&pSchema->tblHash, p->zName,
                              sqlite3Strlen30(p->zName),p);
@@ -1697,17 +1674,6 @@ void sqlite3EndTable(
       db->mallocFailed = 1;
       return;
     }
-#ifndef SQLITE_OMIT_FOREIGN_KEY
-    for(pFKey=p->pFKey; pFKey; pFKey=pFKey->pNextFrom){
-      void *data;
-      int nTo = sqlite3Strlen30(pFKey->zTo);
-      pFKey->pNextTo = sqlite3HashFind(&pSchema->aFKey, pFKey->zTo, nTo);
-      data = sqlite3HashInsert(&pSchema->aFKey, pFKey->zTo, nTo, pFKey);
-      if( data==(void *)pFKey ){
-        db->mallocFailed = 1;
-      }
-    }
-#endif
     pParse->pNewTable = 0;
     db->nTable++;
     db->flags |= SQLITE_InternChanges;
@@ -2214,9 +2180,7 @@ exit_drop_table:
 ** in the ON DELETE, ON UPDATE and ON INSERT clauses.
 **
 ** An FKey structure is created and added to the table currently
-** under construction in the pParse->pNewTable field.  The new FKey
-** is not linked into db->aFKey at this point - that does not happen
-** until sqlite3EndTable().
+** under construction in the pParse->pNewTable field.
 **
 ** The foreign key is set for IMMEDIATE processing.  A subsequent call
 ** to sqlite3DeferForeignKey() might change this to DEFERRED.
@@ -2257,7 +2221,7 @@ void sqlite3CreateForeignKey(
   }else{
     nCol = pFromCol->nExpr;
   }
-  nByte = sizeof(*pFKey) + nCol*sizeof(pFKey->aCol[0]) + pTo->n + 1;
+  nByte = sizeof(*pFKey) + (nCol-1)*sizeof(pFKey->aCol[0]) + pTo->n + 1;
   if( pToCol ){
     for(i=0; i<pToCol->nExpr; i++){
       nByte += sqlite3Strlen30(pToCol->a[i].zName) + 1;
@@ -2269,15 +2233,12 @@ void sqlite3CreateForeignKey(
   }
   pFKey->pFrom = p;
   pFKey->pNextFrom = p->pFKey;
-  z = (char*)&pFKey[1];
-  pFKey->aCol = (struct sColMap*)z;
-  z += sizeof(struct sColMap)*nCol;
+  z = (char*)&pFKey->aCol[nCol];
   pFKey->zTo = z;
   memcpy(z, pTo->z, pTo->n);
   z[pTo->n] = 0;
   sqlite3Dequote(z);
   z += pTo->n+1;
-  pFKey->pNextTo = 0;
   pFKey->nCol = nCol;
   if( pFromCol==0 ){
     pFKey->aCol[0].iFrom = p->nCol-1;
index c4a5280d271af08c3b158c7cad6ef410ec81f10d..a95969b1b2f37c2153a7e4e00e7eb369ff64872b 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.37 2009/03/24 15:08:10 drh Exp $
+** $Id: callback.c,v 1.38 2009/05/02 13:29:38 drh Exp $
 */
 
 #include "sqliteInt.h"
@@ -413,14 +413,13 @@ void sqlite3SchemaFree(void *p){
 
   temp1 = pSchema->tblHash;
   temp2 = pSchema->trigHash;
-  sqlite3HashInit(&pSchema->trigHash, 0);
-  sqlite3HashClear(&pSchema->aFKey);
+  sqlite3HashInit(&pSchema->trigHash);
   sqlite3HashClear(&pSchema->idxHash);
   for(pElem=sqliteHashFirst(&temp2); pElem; pElem=sqliteHashNext(pElem)){
     sqlite3DeleteTrigger(0, (Trigger*)sqliteHashData(pElem));
   }
   sqlite3HashClear(&temp2);
-  sqlite3HashInit(&pSchema->tblHash, 0);
+  sqlite3HashInit(&pSchema->tblHash);
   for(pElem=sqliteHashFirst(&temp1); pElem; pElem=sqliteHashNext(pElem)){
     Table *pTab = sqliteHashData(pElem);
     assert( pTab->dbMem==0 );
@@ -445,10 +444,9 @@ Schema *sqlite3SchemaGet(sqlite3 *db, Btree *pBt){
   if( !p ){
     db->mallocFailed = 1;
   }else if ( 0==p->file_format ){
-    sqlite3HashInit(&p->tblHash, 0);
-    sqlite3HashInit(&p->idxHash, 0);
-    sqlite3HashInit(&p->trigHash, 0);
-    sqlite3HashInit(&p->aFKey, 1);
+    sqlite3HashInit(&p->tblHash);
+    sqlite3HashInit(&p->idxHash);
+    sqlite3HashInit(&p->trigHash);
     p->enc = SQLITE_UTF8;
   }
   return p;
index 8be6dab346383b3303efc4f29078ee131dcaf1f0..9c7b21c61a78d4f46d0411201f18980fbe11aa8d 100644 (file)
@@ -12,7 +12,7 @@
 ** This is the implementation of generic hash-tables
 ** used in SQLite.
 **
-** $Id: hash.c,v 1.36 2009/04/28 17:33:16 drh Exp $
+** $Id: hash.c,v 1.37 2009/05/02 13:29:38 drh Exp $
 */
 #include "sqliteInt.h"
 #include <assert.h>
 ** fields of the Hash structure.
 **
 ** "pNew" is a pointer to the hash table that is to be initialized.
-** "copyKey" is true if the hash table should make its own private
-** copy of keys and false if it should just use the supplied pointer.
 */
-void sqlite3HashInit(Hash *pNew, int copyKey){
+void sqlite3HashInit(Hash *pNew){
   assert( pNew!=0 );
-  pNew->copyKey = copyKey!=0;
   pNew->first = 0;
   pNew->count = 0;
   pNew->htsize = 0;
@@ -48,9 +45,6 @@ void sqlite3HashClear(Hash *pH){
   pH->htsize = 0;
   while( elem ){
     HashElem *next_elem = elem->next;
-    if( pH->copyKey ){
-      sqlite3_free(elem->pKey);
-    }
     sqlite3_free(elem);
     elem = next_elem;
   }
@@ -58,10 +52,9 @@ void sqlite3HashClear(Hash *pH){
 }
 
 /*
-** Hash and comparison functions when the mode is SQLITE_HASH_STRING
+** The hashing function.
 */
-static unsigned int strHash(const void *pKey, int nKey){
-  const char *z = (const char *)pKey;
+static unsigned int strHash(const char *z, int nKey){
   int h = 0;
   assert( nKey>=0 );
   while( nKey > 0  ){
@@ -70,10 +63,6 @@ static unsigned int strHash(const void *pKey, int nKey){
   }
   return h;
 }
-static int strCompare(const void *pKey1, int n1, const void *pKey2, int n2){
-  if( n1!=n2 ) return 1;
-  return sqlite3StrNICmp((const char*)pKey1,(const char*)pKey2,n1);
-}
 
 
 /* Link pNew element into the hash table pH.  If pEntry!=0 then also
@@ -151,7 +140,7 @@ static int rehash(Hash *pH, unsigned int new_size){
 */
 static HashElem *findElementGivenHash(
   const Hash *pH,     /* The pH to be searched */
-  const void *pKey,   /* The key we are searching for */
+  const char *pKey,   /* The key we are searching for */
   int nKey,           /* Bytes in key (not counting zero terminator) */
   unsigned int h      /* The hash for this key. */
 ){
@@ -167,7 +156,7 @@ static HashElem *findElementGivenHash(
     count = pH->count;
   }
   while( count-- && ALWAYS(elem) ){
-    if( strCompare(elem->pKey,elem->nKey,pKey,nKey)==0 ){ 
+    if( elem->nKey==nKey && sqlite3StrNICmp(elem->pKey,pKey,nKey)==0 ){ 
       return elem;
     }
     elem = elem->next;
@@ -200,9 +189,6 @@ static void removeElementGivenHash(
     pEntry->count--;
     assert( pEntry->count>=0 );
   }
-  if( pH->copyKey ){
-    sqlite3_free(elem->pKey);
-  }
   sqlite3_free( elem );
   pH->count--;
   if( pH->count<=0 ){
@@ -216,7 +202,7 @@ static void removeElementGivenHash(
 ** that matches pKey,nKey.  Return the data for this element if it is
 ** found, or NULL if there is no match.
 */
-void *sqlite3HashFind(const Hash *pH, const void *pKey, int nKey){
+void *sqlite3HashFind(const Hash *pH, const char *pKey, int nKey){
   HashElem *elem;    /* The element that matches key */
   unsigned int h;    /* A hash on key */
 
@@ -236,8 +222,7 @@ void *sqlite3HashFind(const Hash *pH, const void *pKey, int nKey){
 ** and the data is "data".
 **
 ** If no element exists with a matching key, then a new
-** element is created.  A copy of the key is made if the copyKey
-** flag is set.  NULL is returned.
+** element is created and NULL is returned.
 **
 ** If another element already exists with the same key, then the
 ** new data replaces the old data and the old data is returned.
@@ -247,7 +232,7 @@ void *sqlite3HashFind(const Hash *pH, const void *pKey, int nKey){
 ** If the "data" parameter to this function is NULL, then the
 ** element corresponding to "key" is removed from the hash table.
 */
-void *sqlite3HashInsert(Hash *pH, const void *pKey, int nKey, void *data){
+void *sqlite3HashInsert(Hash *pH, const char *pKey, int nKey, void *data){
   unsigned int h;       /* the hash of the key modulo hash table size */
   HashElem *elem;       /* Used to loop thru the element list */
   HashElem *new_elem;   /* New element added to the pH */
@@ -267,9 +252,7 @@ void *sqlite3HashInsert(Hash *pH, const void *pKey, int nKey, void *data){
       removeElementGivenHash(pH,elem,h);
     }else{
       elem->data = data;
-      if( !pH->copyKey ){
-        elem->pKey = (void *)pKey;
-      }
+      elem->pKey = pKey;
       assert(nKey==elem->nKey);
     }
     return old_data;
@@ -277,16 +260,7 @@ void *sqlite3HashInsert(Hash *pH, const void *pKey, int nKey, void *data){
   if( data==0 ) return 0;
   new_elem = (HashElem*)sqlite3Malloc( sizeof(HashElem) );
   if( new_elem==0 ) return data;
-  if( pH->copyKey ){
-    new_elem->pKey = sqlite3Malloc( nKey );
-    if( new_elem->pKey==0 ){
-      sqlite3_free(new_elem);
-      return data;
-    }
-    memcpy((void*)new_elem->pKey, pKey, nKey);
-  }else{
-    new_elem->pKey = (void*)pKey;
-  }
+  new_elem->pKey = pKey;
   new_elem->nKey = nKey;
   new_elem->data = data;
   pH->count++;
index b0ba3b1a5feab4a61a1215e14dabfa8d2c39badc..959f50964e1938e7511de8a74899fbbd889fe7c6 100644 (file)
@@ -12,7 +12,7 @@
 ** This is the header file for the generic hash-table implemenation
 ** used in SQLite.
 **
-** $Id: hash.h,v 1.14 2009/04/28 16:35:43 drh Exp $
+** $Id: hash.h,v 1.15 2009/05/02 13:29:38 drh Exp $
 */
 #ifndef _SQLITE_HASH_H_
 #define _SQLITE_HASH_H_
@@ -43,8 +43,7 @@ typedef struct HashElem HashElem;
 ** the hash table.
 */
 struct Hash {
-  unsigned int copyKey : 1; /* True if copy of key made on insert */
-  unsigned int htsize : 31; /* Number of buckets in the hash table */
+  unsigned int htsize;      /* Number of buckets in the hash table */
   unsigned int count;       /* Number of entries in this table */
   HashElem *first;          /* The first element of the array */
   struct _ht {              /* the hash table */
@@ -60,17 +59,17 @@ struct Hash {
 ** be opaque because it is used by macros.
 */
 struct HashElem {
-  HashElem *next, *prev;   /* Next and previous elements in the table */
-  void *data;              /* Data associated with this element */
-  void *pKey; int nKey;    /* Key associated with this element */
+  HashElem *next, *prev;       /* Next and previous elements in the table */
+  void *data;                  /* Data associated with this element */
+  const char *pKey; int nKey;  /* Key associated with this element */
 };
 
 /*
 ** Access routines.  To delete, insert a NULL pointer.
 */
-void sqlite3HashInit(Hash*, int copyKey);
-void *sqlite3HashInsert(Hash*, const void *pKey, int nKey, void *pData);
-void *sqlite3HashFind(const Hash*, const void *pKey, int nKey);
+void sqlite3HashInit(Hash*);
+void *sqlite3HashInsert(Hash*, const char *pKey, int nKey, void *pData);
+void *sqlite3HashFind(const Hash*, const char *pKey, int nKey);
 void sqlite3HashClear(Hash*);
 
 /*
index 37b63e6b21dca1bdf0bbf5a9f7031384d0348188..cc2a810575d09b063a5b6648e9794b34ef265889 100644 (file)
@@ -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.544 2009/04/30 12:25:10 drh Exp $
+** $Id: main.c,v 1.545 2009/05/02 13:29:38 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -1580,9 +1580,9 @@ static int openDatabase(
                  | SQLITE_LoadExtension
 #endif
       ;
-  sqlite3HashInit(&db->aCollSeq, 0);
+  sqlite3HashInit(&db->aCollSeq);
 #ifndef SQLITE_OMIT_VIRTUALTABLE
-  sqlite3HashInit(&db->aModule, 0);
+  sqlite3HashInit(&db->aModule);
 #endif
 
   db->pVfs = sqlite3_vfs_find(zVfs);
index 488a0686ec2dadc801f60684186bc4a857225298..52093c0923eea0a9c0577f3b441d0a588b033a1f 100644 (file)
@@ -11,7 +11,7 @@
 *************************************************************************
 ** Internal interface definitions for SQLite.
 **
-** @(#) $Id: sqliteInt.h,v 1.865 2009/05/01 21:13:37 drh Exp $
+** @(#) $Id: sqliteInt.h,v 1.866 2009/05/02 13:29:38 drh Exp $
 */
 #ifndef _SQLITEINT_H_
 #define _SQLITEINT_H_
@@ -639,7 +639,6 @@ struct Schema {
   Hash tblHash;        /* All tables indexed by name */
   Hash idxHash;        /* All (named) indices indexed by name */
   Hash trigHash;       /* All triggers indexed by name */
-  Hash aFKey;          /* Foreign keys indexed by to-table */
   Table *pSeqTab;      /* The sqlite_sequence table used by AUTOINCREMENT */
   u8 file_format;      /* Schema format version for this file */
   u8 enc;              /* Text encoding used by this database */
@@ -1195,28 +1194,21 @@ struct Table {
 **
 ** Each REFERENCES clause generates an instance of the following structure
 ** which is attached to the from-table.  The to-table need not exist when
-** the from-table is created.  The existence of the to-table is not checked
-** until an attempt is made to insert data into the from-table.
-**
-** The sqlite.aFKey hash table stores pointers to this structure
-** given the name of a to-table.  For each to-table, all foreign keys
-** associated with that table are on a linked list using the FKey.pNextTo
-** field.
+** the from-table is created.  The existence of the to-table is not checked.
 */
 struct FKey {
   Table *pFrom;     /* The table that contains the REFERENCES clause */
   FKey *pNextFrom;  /* Next foreign key in pFrom */
   char *zTo;        /* Name of table that the key points to */
-  FKey *pNextTo;    /* Next foreign key that points to zTo */
   int nCol;         /* Number of columns in this key */
-  struct sColMap {  /* Mapping of columns in pFrom to columns in zTo */
-    int iFrom;         /* Index of column in pFrom */
-    char *zCol;        /* Name of column in zTo.  If 0 use PRIMARY KEY */
-  } *aCol;          /* One entry for each of nCol column s */
   u8 isDeferred;    /* True if constraint checking is deferred till COMMIT */
   u8 updateConf;    /* How to resolve conflicts that occur on UPDATE */
   u8 deleteConf;    /* How to resolve conflicts that occur on DELETE */
   u8 insertConf;    /* How to resolve conflicts that occur on INSERT */
+  struct sColMap {  /* Mapping of columns in pFrom to columns in zTo */
+    int iFrom;         /* Index of column in pFrom */
+    char *zCol;        /* Name of column in zTo.  If 0 use PRIMARY KEY */
+  } aCol[1];        /* One entry for each of nCol column s */
 };
 
 /*