/ Check-in [d2fb2bb5]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Changes to the "sqlite" structure that allow simultaneous operations on multiple database files. Many regession tests pass - but not all of them. Do not use this version except for debugging SQLite itself. (CVS 883)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: d2fb2bb50cf1e13feb90995079f291384abd6ba9
User & Date: drh 2003-03-27 12:51:24
Context
2003-03-27
12:51
Changes to the "sqlite" structure that allow simultaneous operations on multiple database files. Many regession tests pass - but not all of them. Do not use this version except for debugging SQLite itself. (CVS 1731) check-in: 9ac71c32 user: drh tags: trunk
12:51
Changes to the "sqlite" structure that allow simultaneous operations on multiple database files. Many regession tests pass - but not all of them. Do not use this version except for debugging SQLite itself. (CVS 883) check-in: d2fb2bb5 user: drh tags: trunk
2003-03-24
09:42
Re-generated. (CVS 882) check-in: f0c5bcf7 user: a.rottmann tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/build.c.

    21     21   **     COPY
    22     22   **     VACUUM
    23     23   **     BEGIN TRANSACTION
    24     24   **     COMMIT
    25     25   **     ROLLBACK
    26     26   **     PRAGMA
    27     27   **
    28         -** $Id: build.c,v 1.133 2003/03/20 01:16:58 drh Exp $
           28  +** $Id: build.c,v 1.134 2003/03/27 12:51:24 drh Exp $
    29     29   */
    30     30   #include "sqliteInt.h"
    31     31   #include <ctype.h>
    32     32   
    33     33   /*
    34     34   ** This routine is called when a new SQL statement is beginning to
    35     35   ** be parsed.  Check to see if the schema for the database needs
................................................................................
   109    109   }
   110    110   
   111    111   /*
   112    112   ** Locate the in-memory structure that describes 
   113    113   ** a particular database table given the name
   114    114   ** of that table.  Return NULL if not found.
   115    115   */
   116         -Table *sqliteFindTable(sqlite *db, const char *zName){
   117         -  Table *p;
   118         -  p = sqliteHashFind(&db->tblHash, zName, strlen(zName)+1);
          116  +Table *sqliteFindTable(sqlite *db, const char *zName, const char *zDatabase){
          117  +  Table *p = 0;
          118  +  int i;
          119  +  for(i=0; i<db->nDb; i++){
          120  +    if( zDatabase!=0 && sqliteStrICmp(zDatabase, db->aDb[i].zName) ) continue;
          121  +    p = sqliteHashFind(&db->aDb[i].tblHash, zName, strlen(zName)+1);
          122  +    if( p ) break;
          123  +  }
   119    124     return p;
   120    125   }
   121    126   
   122    127   /*
   123    128   ** Locate the in-memory structure that describes 
   124    129   ** a particular index given the name of that index.
   125    130   ** Return NULL if not found.
   126    131   */
   127         -Index *sqliteFindIndex(sqlite *db, const char *zName){
   128         -  Index *p;
   129         -  p = sqliteHashFind(&db->idxHash, zName, strlen(zName)+1);
          132  +Index *sqliteFindIndex(sqlite *db, const char *zName, const char *zDb){
          133  +  Index *p = 0;
          134  +  int i;
          135  +  for(i=0; i<db->nDb; i++){
          136  +    if( zDb && sqliteStrICmp(zDb, db->aDb[i].zName) ) continue;
          137  +    p = sqliteHashFind(&db->aDb[i].idxHash, zName, strlen(zName)+1);
          138  +    if( p ) break;
          139  +  }
   130    140     return p;
   131    141   }
   132    142   
   133    143   /*
   134    144   ** Remove the given index from the index hash table, and free
   135    145   ** its memory structures.
   136    146   **
   137    147   ** The index is removed from the database hash tables but
   138    148   ** it is not unlinked from the Table that it indexes.
   139    149   ** Unlinking from the Table must be done by the calling function.
   140    150   */
   141    151   static void sqliteDeleteIndex(sqlite *db, Index *p){
   142    152     Index *pOld;
          153  +
   143    154     assert( db!=0 && p->zName!=0 );
   144         -  pOld = sqliteHashInsert(&db->idxHash, p->zName, strlen(p->zName)+1, 0);
          155  +  pOld = sqliteHashInsert(&db->aDb[p->iDb].idxHash, p->zName,
          156  +                          strlen(p->zName)+1, 0);
   145    157     if( pOld!=0 && pOld!=p ){
   146         -    sqliteHashInsert(&db->idxHash, pOld->zName, strlen(pOld->zName)+1, pOld);
          158  +    sqliteHashInsert(&db->aDb[p->iDb].idxHash, pOld->zName,
          159  +                     strlen(pOld->zName)+1, pOld);
   147    160     }
   148    161     sqliteFree(p);
   149    162   }
   150    163   
   151    164   /*
   152    165   ** Unlink the given index from its table, then remove
   153    166   ** the index from the index hash table and free its memory
................................................................................
   172    185   ** before the connection closes.  It is also called during a rollback
   173    186   ** if there were schema changes during the transaction.
   174    187   */
   175    188   void sqliteResetInternalSchema(sqlite *db){
   176    189     HashElem *pElem;
   177    190     Hash temp1;
   178    191     Hash temp2;
          192  +  int i;
   179    193   
   180         -  sqliteHashClear(&db->aFKey);
   181         -  temp1 = db->tblHash;
   182         -  temp2 = db->trigHash;
   183         -  sqliteHashInit(&db->trigHash, SQLITE_HASH_STRING, 0);
   184         -  sqliteHashClear(&db->idxHash);
   185         -  for(pElem=sqliteHashFirst(&temp2); pElem; pElem=sqliteHashNext(pElem)){
   186         -    Trigger *pTrigger = sqliteHashData(pElem);
   187         -    sqliteDeleteTrigger(pTrigger);
          194  +  for(i=0; i<db->nDb; i++){
          195  +    Db *pDb = &db->aDb[i];
          196  +    temp1 = pDb->tblHash;
          197  +    temp2 = pDb->trigHash;
          198  +    sqliteHashInit(&pDb->trigHash, SQLITE_HASH_STRING, 0);
          199  +    sqliteHashClear(&pDb->aFKey);
          200  +    sqliteHashClear(&pDb->idxHash);
          201  +    for(pElem=sqliteHashFirst(&temp2); pElem; pElem=sqliteHashNext(pElem)){
          202  +      Trigger *pTrigger = sqliteHashData(pElem);
          203  +      sqliteDeleteTrigger(pTrigger);
          204  +    }
          205  +    sqliteHashClear(&temp2);
          206  +    sqliteHashInit(&pDb->tblHash, SQLITE_HASH_STRING, 0);
          207  +    for(pElem=sqliteHashFirst(&temp1); pElem; pElem=sqliteHashNext(pElem)){
          208  +      Table *pTab = sqliteHashData(pElem);
          209  +      sqliteDeleteTable(db, pTab);
          210  +    }
          211  +    sqliteHashClear(&temp1);
   188    212     }
   189         -  sqliteHashClear(&temp2);
   190         -  sqliteHashInit(&db->tblHash, SQLITE_HASH_STRING, 0);
   191         -  for(pElem=sqliteHashFirst(&temp1); pElem; pElem=sqliteHashNext(pElem)){
   192         -    Table *pTab = sqliteHashData(pElem);
   193         -    sqliteDeleteTable(db, pTab);
   194         -  }
   195         -  sqliteHashClear(&temp1);
   196    213     db->flags &= ~(SQLITE_Initialized|SQLITE_InternChanges);
   197    214   }
   198    215   
   199    216   /*
   200    217   ** This routine is called whenever a rollback occurs.  If there were
   201    218   ** schema changes during the transaction, then we have to reset the
   202    219   ** internal hash tables and reload them from disk.
................................................................................
   237    254   
   238    255     if( pTable==0 ) return;
   239    256   
   240    257     /* Delete all indices associated with this table
   241    258     */
   242    259     for(pIndex = pTable->pIndex; pIndex; pIndex=pNext){
   243    260       pNext = pIndex->pNext;
          261  +    assert( pIndex->iDb==pTable->iDb || (pTable->iDb==0 && pIndex->iDb==1) );
   244    262       sqliteDeleteIndex(db, pIndex);
   245    263     }
   246    264   
   247    265     /* Delete all foreign keys associated with this table.  The keys
   248    266     ** should have already been unlinked from the db->aFKey hash table 
   249    267     */
   250    268     for(pFKey=pTable->pFKey; pFKey; pFKey=pNextFKey){
   251    269       pNextFKey = pFKey->pNextFrom;
   252         -    assert( sqliteHashFind(&db->aFKey,pFKey->zTo,strlen(pFKey->zTo)+1)!=pFKey );
          270  +    assert( pTable->iDb<db->nDb );
          271  +    assert( sqliteHashFind(&db->aDb[pTable->iDb].aFKey,
          272  +                           pFKey->zTo, strlen(pFKey->zTo)+1)!=pFKey );
   253    273       sqliteFree(pFKey);
   254    274     }
   255    275   
   256    276     /* Delete the Table structure itself.
   257    277     */
   258    278     for(i=0; i<pTable->nCol; i++){
   259    279       sqliteFree(pTable->aCol[i].zName);
................................................................................
   269    289   /*
   270    290   ** Unlink the given table from the hash tables and the delete the
   271    291   ** table structure with all its indices and foreign keys.
   272    292   */
   273    293   static void sqliteUnlinkAndDeleteTable(sqlite *db, Table *p){
   274    294     Table *pOld;
   275    295     FKey *pF1, *pF2;
          296  +  int i = p->iDb;
   276    297     assert( db!=0 );
   277         -  pOld = sqliteHashInsert(&db->tblHash, p->zName, strlen(p->zName)+1, 0);
          298  +  pOld = sqliteHashInsert(&db->aDb[i].tblHash, p->zName, strlen(p->zName)+1, 0);
   278    299     assert( pOld==0 || pOld==p );
   279    300     for(pF1=p->pFKey; pF1; pF1=pF1->pNextFrom){
   280    301       int nTo = strlen(pF1->zTo) + 1;
   281         -    pF2 = sqliteHashFind(&db->aFKey, pF1->zTo, nTo);
          302  +    pF2 = sqliteHashFind(&db->aDb[i].aFKey, pF1->zTo, nTo);
   282    303       if( pF2==pF1 ){
   283         -      sqliteHashInsert(&db->aFKey, pF1->zTo, nTo, pF1->pNextTo);
          304  +      sqliteHashInsert(&db->aDb[i].aFKey, pF1->zTo, nTo, pF1->pNextTo);
   284    305       }else{
   285    306         while( pF2 && pF2->pNextTo!=pF1 ){ pF2=pF2->pNextTo; }
   286    307         if( pF2 ){
   287    308           pF2->pNextTo = pF1->pNextTo;
   288    309         }
   289    310       }
   290    311     }
................................................................................
   343    364     char *zName;
   344    365     sqlite *db = pParse->db;
   345    366     Vdbe *v;
   346    367   
   347    368     pParse->sFirstToken = *pStart;
   348    369     zName = sqliteTableNameFromToken(pName);
   349    370     if( zName==0 ) return;
          371  +  if( pParse->iDb==1 ) isTemp = 1;
   350    372   #ifndef SQLITE_OMIT_AUTHORIZATION
          373  +  assert( (isTemp & 1)==isTemp );
   351    374     if( sqliteAuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(isTemp), 0) ){
   352    375       sqliteFree(zName);
   353    376       return;
   354    377     }
   355    378     {
   356    379       int code;
   357    380       if( isView ){
................................................................................
   374    397     }
   375    398   #endif
   376    399    
   377    400   
   378    401     /* Before trying to create a temporary table, make sure the Btree for
   379    402     ** holding temporary tables is open.
   380    403     */
   381         -  if( isTemp && db->aDb[1].pBt==0 ){
          404  +  if( isTemp && db->aDb[1].pBt==0 && !pParse->explain ){
   382    405       int rc = sqliteBtreeOpen(0, 0, MAX_PAGES, &db->aDb[1].pBt);
   383    406       if( rc!=SQLITE_OK ){
   384    407         sqliteSetString(&pParse->zErrMsg, "unable to open a temporary database "
   385    408           "file for storing temporary tables", 0);
   386    409         pParse->nErr++;
   387    410         return;
   388    411       }
................................................................................
   398    421     }
   399    422   
   400    423     /* Make sure the new table name does not collide with an existing
   401    424     ** index or table name.  Issue an error message if it does.
   402    425     **
   403    426     ** If we are re-reading the sqlite_master table because of a schema
   404    427     ** change and a new permanent table is found whose name collides with
   405         -  ** an existing temporary table, then ignore the new permanent table.
   406         -  ** We will continue parsing, but the pParse->nameClash flag will be set
   407         -  ** so we will know to discard the table record once parsing has finished.
          428  +  ** an existing temporary table, that is not an error.
   408    429     */
   409         -  pTable = sqliteFindTable(db, zName);
   410         -  if( pTable!=0 ){
   411         -    if( pTable->isTemp && pParse->initFlag ){
   412         -      pParse->nameClash = 1;
   413         -    }else{
   414         -      sqliteSetNString(&pParse->zErrMsg, "table ", 0, pName->z, pName->n,
   415         -          " already exists", 0, 0);
   416         -      sqliteFree(zName);
   417         -      pParse->nErr++;
   418         -      return;
   419         -    }
   420         -  }else{
   421         -    pParse->nameClash = 0;
          430  +  pTable = sqliteFindTable(db, zName, 0);
          431  +  if( pTable!=0 && (pTable->iDb==isTemp || !pParse->initFlag) ){
          432  +    sqliteSetNString(&pParse->zErrMsg, "table ", 0, pName->z, pName->n,
          433  +        " already exists", 0, 0);
          434  +    sqliteFree(zName);
          435  +    pParse->nErr++;
          436  +    return;
   422    437     }
   423         -  if( (pIdx = sqliteFindIndex(db, zName))!=0 &&
   424         -          (!pIdx->pTable->isTemp || !pParse->initFlag) ){
          438  +  if( (pIdx = sqliteFindIndex(db, zName, 0))!=0 &&
          439  +          (pIdx->iDb==0 || !pParse->initFlag) ){
   425    440       sqliteSetString(&pParse->zErrMsg, "there is already an index named ", 
   426    441          zName, 0);
   427    442       sqliteFree(zName);
   428    443       pParse->nErr++;
   429    444       return;
   430    445     }
   431    446     pTable = sqliteMalloc( sizeof(Table) );
................................................................................
   434    449       return;
   435    450     }
   436    451     pTable->zName = zName;
   437    452     pTable->nCol = 0;
   438    453     pTable->aCol = 0;
   439    454     pTable->iPKey = -1;
   440    455     pTable->pIndex = 0;
   441         -  pTable->isTemp = isTemp;
          456  +  pTable->iDb = isTemp ? 1 : pParse->iDb;
   442    457     if( pParse->pNewTable ) sqliteDeleteTable(db, pParse->pNewTable);
   443    458     pParse->pNewTable = pTable;
   444    459   
   445    460     /* Begin generating the code that will insert the table record into
   446    461     ** the SQLITE_MASTER table.  Note in particular that we must go ahead
   447    462     ** and allocate the record number for the table entry now.  Before any
   448    463     ** PRIMARY KEY or UNIQUE keywords are parsed.  Those keywords will cause
................................................................................
   620    635       zType = pTab->aCol[iCol].zType;
   621    636     }
   622    637     if( pParse->db->file_format>=1 && 
   623    638              zType && sqliteStrICmp(zType, "INTEGER")==0 ){
   624    639       pTab->iPKey = iCol;
   625    640       pTab->keyConf = onError;
   626    641     }else{
   627         -    sqliteCreateIndex(pParse, 0, 0, pList, onError, 0, 0);
          642  +    sqliteCreateIndex(pParse, 0, 0, pList, onError, 0, 0, 0);
   628    643       pList = 0;
   629    644     }
   630    645   
   631    646   primary_key_exit:
   632    647     sqliteIdListDelete(pList);
   633    648     return;
   634    649   }
................................................................................
   774    789       zSep = "\n  ";
   775    790       zSep2 = ",\n  ";
   776    791       zEnd = "\n)";
   777    792     }
   778    793     n += 35 + 6*p->nCol;
   779    794     zStmt = sqliteMallocRaw( n );
   780    795     if( zStmt==0 ) return 0;
   781         -  strcpy(zStmt, p->isTemp ? "CREATE TEMP TABLE " : "CREATE TABLE ");
          796  +  strcpy(zStmt, p->iDb==1 ? "CREATE TEMP TABLE " : "CREATE TABLE ");
   782    797     k = strlen(zStmt);
   783    798     identPut(zStmt, &k, p->zName);
   784    799     zStmt[k++] = '(';
   785    800     for(i=0; i<p->nCol; i++){
   786    801       strcpy(&zStmt[k], zSep);
   787    802       k += strlen(&zStmt[k]);
   788    803       zSep = zSep2;
................................................................................
   855    870       int n;
   856    871       Vdbe *v;
   857    872   
   858    873       v = sqliteGetVdbe(pParse);
   859    874       if( v==0 ) return;
   860    875       if( p->pSelect==0 ){
   861    876         /* A regular table */
   862         -      sqliteVdbeAddOp(v, OP_CreateTable, 0, p->isTemp);
          877  +      sqliteVdbeAddOp(v, OP_CreateTable, 0, p->iDb);
   863    878         sqliteVdbeChangeP3(v, -1, (char *)&p->tnum, P3_POINTER);
   864    879       }else{
   865    880         /* A view */
   866    881         sqliteVdbeAddOp(v, OP_Integer, 0, 0);
   867    882       }
   868    883       p->tnum = 0;
   869    884       sqliteVdbeAddOp(v, OP_Pull, 1, 0);
................................................................................
   887    902       }else{
   888    903         assert( pEnd!=0 );
   889    904         n = Addr(pEnd->z) - Addr(pParse->sFirstToken.z) + 1;
   890    905         sqliteVdbeChangeP3(v, -1, pParse->sFirstToken.z, n);
   891    906       }
   892    907       sqliteVdbeAddOp(v, OP_MakeRecord, 5, 0);
   893    908       sqliteVdbeAddOp(v, OP_PutIntKey, 0, 0);
   894         -    if( !p->isTemp ){
          909  +    if( !p->iDb ){
   895    910         sqliteChangeCookie(db, v);
   896    911       }
   897    912       sqliteVdbeAddOp(v, OP_Close, 0, 0);
   898    913       if( pSelect ){
   899         -      sqliteVdbeAddOp(v, OP_Integer, p->isTemp, 0);
          914  +      sqliteVdbeAddOp(v, OP_Integer, p->iDb, 0);
   900    915         sqliteVdbeAddOp(v, OP_OpenWrite, 1, 0);
   901    916         pParse->nTab = 2;
   902    917         sqliteSelect(pParse, pSelect, SRT_Table, 1, 0, 0, 0);
   903    918       }
   904    919       sqliteEndWriteOperation(pParse);
   905    920     }
   906    921   
   907    922     /* Add the table to the in-memory representation of the database.
   908    923     */
   909         -  assert( pParse->nameClash==0 || pParse->initFlag==1 );
   910         -  if( pParse->explain==0 && pParse->nameClash==0 && pParse->nErr==0 ){
          924  +  if( pParse->explain==0 && pParse->nErr==0 ){
   911    925       Table *pOld;
   912    926       FKey *pFKey;
   913         -    pOld = sqliteHashInsert(&db->tblHash, p->zName, strlen(p->zName)+1, p);
          927  +    pOld = sqliteHashInsert(&db->aDb[p->iDb].tblHash, 
          928  +                            p->zName, strlen(p->zName)+1, p);
   914    929       if( pOld ){
   915    930         assert( p==pOld );  /* Malloc must have failed inside HashInsert() */
   916    931         return;
   917    932       }
   918    933       for(pFKey=p->pFKey; pFKey; pFKey=pFKey->pNextFrom){
   919    934         int nTo = strlen(pFKey->zTo) + 1;
   920         -      pFKey->pNextTo = sqliteHashFind(&db->aFKey, pFKey->zTo, nTo);
   921         -      sqliteHashInsert(&db->aFKey, pFKey->zTo, nTo, pFKey);
          935  +      pFKey->pNextTo = sqliteHashFind(&db->aDb[p->iDb].aFKey, pFKey->zTo, nTo);
          936  +      sqliteHashInsert(&db->aDb[p->iDb].aFKey, pFKey->zTo, nTo, pFKey);
   922    937       }
   923    938       pParse->pNewTable = 0;
   924    939       db->nTable++;
   925    940       db->flags |= SQLITE_InternChanges;
   926    941     }
   927    942   }
   928    943   
................................................................................
  1034   1049     if( pSelTab ){
  1035   1050       assert( pTable->aCol==0 );
  1036   1051       pTable->nCol = pSelTab->nCol;
  1037   1052       pTable->aCol = pSelTab->aCol;
  1038   1053       pSelTab->nCol = 0;
  1039   1054       pSelTab->aCol = 0;
  1040   1055       sqliteDeleteTable(0, pSelTab);
  1041         -    pParse->db->flags |= SQLITE_UnresetViews;
         1056  +    pParse->db->aDb[pTable->iDb].flags |= SQLITE_UnresetViews;
  1042   1057     }else{
  1043   1058       pTable->nCol = 0;
  1044   1059       nErr++;
  1045   1060     }
  1046   1061     sqliteSelectUnbind(pSel);
  1047   1062     sqliteExprListDelete(pSel->pEList);
  1048   1063     pSel->pEList = pEList;
................................................................................
  1070   1085     pTable->aCol = 0;
  1071   1086     pTable->nCol = 0;
  1072   1087   }
  1073   1088   
  1074   1089   /*
  1075   1090   ** Clear the column names from every VIEW.
  1076   1091   */
  1077         -void sqliteViewResetAll(sqlite *db){
         1092  +static void sqliteViewResetAll(sqlite *db, int idx){
  1078   1093     HashElem *i;
  1079         -  if( (db->flags & SQLITE_UnresetViews)==0 ) return;
  1080         -  for(i=sqliteHashFirst(&db->tblHash); i; i=sqliteHashNext(i)){
         1094  +  if( (db->aDb[idx].flags & SQLITE_UnresetViews)==0 ) return;
         1095  +  for(i=sqliteHashFirst(&db->aDb[idx].tblHash); i; i=sqliteHashNext(i)){
  1081   1096       Table *pTab = sqliteHashData(i);
  1082   1097       if( pTab->pSelect ){
  1083   1098         sqliteViewResetColumnNames(pTab);
  1084   1099       }
  1085   1100     }
  1086         -  db->flags &= ~SQLITE_UnresetViews;
         1101  +  db->aDb[idx].flags &= ~SQLITE_UnresetViews;
  1087   1102   }
  1088   1103   
  1089   1104   /*
  1090   1105   ** Given a token, look up a table with that name.  If not found, leave
  1091   1106   ** an error for the parser to find and return NULL.
  1092   1107   */
  1093   1108   Table *sqliteTableFromToken(Parse *pParse, Token *pTok){
  1094   1109     char *zName;
  1095   1110     Table *pTab;
  1096   1111     zName = sqliteTableNameFromToken(pTok);
  1097   1112     if( zName==0 ) return 0;
  1098         -  pTab = sqliteFindTable(pParse->db, zName);
         1113  +  pTab = sqliteFindTable(pParse->db, zName, 0);
  1099   1114     sqliteFree(zName);
  1100   1115     if( pTab==0 ){
  1101   1116       sqliteSetNString(&pParse->zErrMsg, "no such table: ", 0, 
  1102   1117           pTok->z, pTok->n, 0);
  1103   1118       pParse->nErr++;
  1104   1119     }
  1105   1120     return pTab;
................................................................................
  1110   1125   ** pName is the name of the table to be dropped.
  1111   1126   */
  1112   1127   void sqliteDropTable(Parse *pParse, Token *pName, int isView){
  1113   1128     Table *pTable;
  1114   1129     Vdbe *v;
  1115   1130     int base;
  1116   1131     sqlite *db = pParse->db;
         1132  +  int iDb;
  1117   1133   
  1118   1134     if( pParse->nErr || sqlite_malloc_failed ) return;
  1119   1135     pTable = sqliteTableFromToken(pParse, pName);
  1120   1136     if( pTable==0 ) return;
         1137  +  iDb = pTable->iDb;
  1121   1138   #ifndef SQLITE_OMIT_AUTHORIZATION
  1122         -  if( sqliteAuthCheck(pParse, SQLITE_DELETE, SCHEMA_TABLE(pTable->isTemp),0)){
         1139  +  if( sqliteAuthCheck(pParse, SQLITE_DELETE, SCHEMA_TABLE(pTable->iDb),0)){
  1123   1140       return;
  1124   1141     }
  1125   1142     {
  1126   1143       int code;
  1127   1144       if( isView ){
  1128         -      if( pTable->isTemp ){
         1145  +      if( iDb==1 ){
  1129   1146           code = SQLITE_DROP_TEMP_VIEW;
  1130   1147         }else{
  1131   1148           code = SQLITE_DROP_VIEW;
  1132   1149         }
  1133   1150       }else{
  1134         -      if( pTable->isTemp ){
         1151  +      if( iDb==1 ){
  1135   1152           code = SQLITE_DROP_TEMP_TABLE;
  1136   1153         }else{
  1137   1154           code = SQLITE_DROP_TABLE;
  1138   1155         }
  1139   1156       }
  1140   1157       if( sqliteAuthCheck(pParse, code, pTable->zName, 0) ){
  1141   1158         return;
................................................................................
  1177   1194         { OP_Column,     0, 2,        0},
  1178   1195         { OP_Ne,         0, ADDR(7),  0},
  1179   1196         { OP_Delete,     0, 0,        0},
  1180   1197         { OP_Next,       0, ADDR(3),  0}, /* 7 */
  1181   1198       };
  1182   1199       Index *pIdx;
  1183   1200       Trigger *pTrigger;
  1184         -    sqliteBeginWriteOperation(pParse, 0, pTable->isTemp);
  1185         -    sqliteOpenMasterTable(v, pTable->isTemp);
         1201  +    sqliteBeginWriteOperation(pParse, 0, pTable->iDb);
         1202  +    sqliteOpenMasterTable(v, pTable->iDb);
  1186   1203       /* Drop all triggers associated with the table being dropped */
  1187   1204       pTrigger = pTable->pTrigger;
  1188   1205       while( pTrigger ){
  1189         -      Token tt;
  1190         -      tt.z = pTable->pTrigger->name;
  1191         -      tt.n = strlen(pTable->pTrigger->name);
  1192         -      sqliteDropTrigger(pParse, &tt, 1);
         1206  +      SrcList *pNm;
         1207  +      assert( pTrigger->iDb==pTable->iDb );
         1208  +      pNm = sqliteSrcListAppend(0, 0, 0);
         1209  +      pNm->a[0].zName = sqliteStrDup(pTrigger->name);
         1210  +      pNm->a[0].zDatabase = sqliteStrDup(db->aDb[pTable->iDb].zName);
         1211  +      sqliteDropTrigger(pParse, pNm, 1);
  1193   1212         if( pParse->explain ){
  1194   1213           pTrigger = pTrigger->pNext;
  1195   1214         }else{
  1196   1215           pTrigger = pTable->pTrigger;
  1197   1216         }
  1198   1217       }
  1199   1218       base = sqliteVdbeAddOpList(v, ArraySize(dropTable), dropTable);
  1200   1219       sqliteVdbeChangeP3(v, base+1, pTable->zName, 0);
  1201         -    if( !pTable->isTemp ){
         1220  +    if( !pTable->iDb ){
  1202   1221         sqliteChangeCookie(db, v);
  1203   1222       }
  1204   1223       sqliteVdbeAddOp(v, OP_Close, 0, 0);
  1205   1224       if( !isView ){
  1206         -      sqliteVdbeAddOp(v, OP_Destroy, pTable->tnum, pTable->isTemp);
         1225  +      sqliteVdbeAddOp(v, OP_Destroy, pTable->tnum, pTable->iDb);
  1207   1226         for(pIdx=pTable->pIndex; pIdx; pIdx=pIdx->pNext){
  1208         -        sqliteVdbeAddOp(v, OP_Destroy, pIdx->tnum, pTable->isTemp);
         1227  +        sqliteVdbeAddOp(v, OP_Destroy, pIdx->tnum, pTable->iDb);
  1209   1228         }
  1210   1229       }
  1211   1230       sqliteEndWriteOperation(pParse);
  1212   1231     }
  1213   1232   
  1214   1233     /* Delete the in-memory description of the table.
  1215   1234     **
................................................................................
  1216   1235     ** Exception: if the SQL statement began with the EXPLAIN keyword,
  1217   1236     ** then no changes should be made.
  1218   1237     */
  1219   1238     if( !pParse->explain ){
  1220   1239       sqliteUnlinkAndDeleteTable(db, pTable);
  1221   1240       db->flags |= SQLITE_InternChanges;
  1222   1241     }
  1223         -  sqliteViewResetAll(db);
         1242  +  sqliteViewResetAll(db, iDb);
  1224   1243   }
  1225   1244   
  1226   1245   /*
  1227   1246   ** This routine constructs a P3 string suitable for an OP_MakeIdxKey
  1228   1247   ** opcode and adds that P3 string to the most recently inserted instruction
  1229   1248   ** in the virtual machine.  The P3 string consists of a single character
  1230   1249   ** for each column in the index pIdx of table pTab.  If the column uses
................................................................................
  1399   1418   ** pList is a list of columns to be indexed.  pList will be NULL if this
  1400   1419   ** is a primary key or unique-constraint on the most recent column added
  1401   1420   ** to the table currently under construction.  
  1402   1421   */
  1403   1422   void sqliteCreateIndex(
  1404   1423     Parse *pParse,   /* All information about this parse */
  1405   1424     Token *pName,    /* Name of the index.  May be NULL */
  1406         -  Token *pTable,   /* Name of the table to index.  Use pParse->pNewTable if 0 */
         1425  +  SrcList *pTable, /* Name of the table to index.  Use pParse->pNewTable if 0 */
  1407   1426     IdList *pList,   /* A list of columns to be indexed */
  1408   1427     int onError,     /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */
         1428  +  int isTemp,      /* True if this is a temporary index */
  1409   1429     Token *pStart,   /* The CREATE token that begins a CREATE TABLE statement */
  1410   1430     Token *pEnd      /* The ")" that closes the CREATE INDEX statement */
  1411   1431   ){
  1412   1432     Table *pTab;     /* Table to be indexed */
  1413   1433     Index *pIndex;   /* The index to be created */
  1414   1434     char *zName = 0;
  1415   1435     int i, j;
  1416   1436     Token nullId;             /* Fake token for an empty ID list */
  1417   1437     sqlite *db = pParse->db;
  1418         -  int hideName = 0;         /* Do not put table name in the hash table */
  1419   1438   
  1420   1439     if( pParse->nErr || sqlite_malloc_failed ) goto exit_create_index;
  1421   1440   
  1422   1441     /*
  1423   1442     ** Find the table that is to be indexed.  Return early if not found.
  1424   1443     */
  1425   1444     if( pTable!=0 ){
  1426   1445       assert( pName!=0 );
  1427         -    pTab =  sqliteTableFromToken(pParse, pTable);
         1446  +    assert( pTable->nSrc==1 );
         1447  +    pTab =  sqliteTableNameToTable(pParse, 
         1448  +                 pTable->a[0].zName, pTable->a[0].zDatabase);
  1428   1449     }else{
  1429   1450       assert( pName==0 );
  1430   1451       pTab =  pParse->pNewTable;
  1431   1452     }
  1432   1453     if( pTab==0 || pParse->nErr ) goto exit_create_index;
  1433         -  if( pTab->readOnly ){
         1454  +  if( !isTemp && (pTab->readOnly || pTab->iDb>=2) ){
  1434   1455       sqliteSetString(&pParse->zErrMsg, "table ", pTab->zName, 
  1435         -      " may not have new indices added", 0);
         1456  +      " may not have non-temporary indices added", 0);
  1436   1457       pParse->nErr++;
  1437   1458       goto exit_create_index;
  1438   1459     }
  1439   1460     if( pTab->pSelect ){
  1440   1461       sqliteSetString(&pParse->zErrMsg, "views may not be indexed", 0);
  1441   1462       pParse->nErr++;
  1442   1463       goto exit_create_index;
  1443   1464     }
         1465  +  if( pTab->iDb==1 ){
         1466  +    isTemp = 1;
         1467  +  }
  1444   1468   
         1469  +
         1470  +#if 0
  1445   1471     /* If this index is created while re-reading the schema from sqlite_master
  1446   1472     ** but the table associated with this index is a temporary table, it can
  1447   1473     ** only mean that the table that this index is really associated with is
  1448   1474     ** one whose name is hidden behind a temporary table with the same name.
  1449   1475     ** Since its table has been suppressed, we need to also suppress the
  1450   1476     ** index.
  1451   1477     */
  1452         -  if( pParse->initFlag && !pParse->isTemp && pTab->isTemp ){
         1478  +  if( pParse->initFlag && !pParse->isTemp && pTab->iDb ){
  1453   1479       goto exit_create_index;
  1454   1480     }
         1481  +#endif
  1455   1482   
  1456   1483     /*
  1457   1484     ** Find the name of the index.  Make sure there is not already another
  1458   1485     ** index or table with the same name.  
  1459   1486     **
  1460   1487     ** Exception:  If we are reading the names of permanent indices from the
  1461   1488     ** sqlite_master table (because some other process changed the schema) and
  1462   1489     ** one of the index names collides with the name of a temporary table or
  1463         -  ** index, then we will continue to process this index, but we will not
  1464         -  ** store its name in the hash table.  Set the hideName flag to accomplish
  1465         -  ** this.
         1490  +  ** index, then we will continue to process this index.
  1466   1491     **
  1467   1492     ** If pName==0 it means that we are
  1468   1493     ** dealing with a primary key or UNIQUE constraint.  We have to invent our
  1469   1494     ** own name.
  1470   1495     */
  1471         -  if( pName ){
         1496  +  if( pName && !pParse->initFlag ){
  1472   1497       Index *pISameName;    /* Another index with the same name */
  1473   1498       Table *pTSameName;    /* A table with same name as the index */
  1474         -    zName = sqliteTableNameFromToken(pName);
         1499  +    zName = sqliteStrNDup(pName->z, pName->n);
  1475   1500       if( zName==0 ) goto exit_create_index;
  1476         -    if( (pISameName = sqliteFindIndex(db, zName))!=0 ){
  1477         -      if( pISameName->pTable->isTemp && pParse->initFlag ){
  1478         -        hideName = 1;
  1479         -      }else{
  1480         -        sqliteSetString(&pParse->zErrMsg, "index ", zName, 
  1481         -           " already exists", 0);
  1482         -        pParse->nErr++;
  1483         -        goto exit_create_index;
  1484         -      }
         1501  +    if( (pISameName = sqliteFindIndex(db, zName, 0))!=0 ){
         1502  +      sqliteSetString(&pParse->zErrMsg, "index ", zName, 
         1503  +         " already exists", 0);
         1504  +      pParse->nErr++;
         1505  +      goto exit_create_index;
  1485   1506       }
  1486         -    if( (pTSameName = sqliteFindTable(db, zName))!=0 ){
  1487         -      if( pTSameName->isTemp && pParse->initFlag ){
  1488         -        hideName = 1;
  1489         -      }else{
  1490         -        sqliteSetString(&pParse->zErrMsg, "there is already a table named ",
  1491         -           zName, 0);
  1492         -        pParse->nErr++;
  1493         -        goto exit_create_index;
  1494         -      }
         1507  +    if( (pTSameName = sqliteFindTable(db, zName, 0))!=0 ){
         1508  +      sqliteSetString(&pParse->zErrMsg, "there is already a table named ",
         1509  +         zName, 0);
         1510  +      pParse->nErr++;
         1511  +      goto exit_create_index;
  1495   1512       }
  1496         -  }else{
         1513  +  }else if( pName==0 ){
  1497   1514       char zBuf[30];
  1498   1515       int n;
  1499   1516       Index *pLoop;
  1500   1517       for(pLoop=pTab->pIndex, n=1; pLoop; pLoop=pLoop->pNext, n++){}
  1501   1518       sprintf(zBuf,"%d)",n);
  1502   1519       zName = 0;
  1503   1520       sqliteSetString(&zName, "(", pTab->zName, " autoindex ", zBuf, 0);
  1504   1521       if( zName==0 ) goto exit_create_index;
  1505         -    hideName = sqliteFindIndex(db, zName)!=0;
         1522  +  }else{
         1523  +    zName = sqliteStrNDup(pName->z, pName->n);
  1506   1524     }
  1507   1525   
  1508   1526     /* Check for authorization to create an index.
  1509   1527     */
  1510   1528   #ifndef SQLITE_OMIT_AUTHORIZATION
  1511         -  if( sqliteAuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(pTab->isTemp), 0) ){
         1529  +  assert( isTemp==0 || isTemp==1 );
         1530  +  assert( pTab->iDb==pParse->iDb || isTemp==1 );
         1531  +  if( sqliteAuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(isTemp), 0) ){
  1512   1532       goto exit_create_index;
  1513   1533     }
  1514   1534     i = SQLITE_CREATE_INDEX;
  1515         -  if( pTab->isTemp ) i = SQLITE_CREATE_TEMP_INDEX;
         1535  +  if( isTemp ) i = SQLITE_CREATE_TEMP_INDEX;
  1516   1536     if( sqliteAuthCheck(pParse, i, zName, pTab->zName) ){
  1517   1537       goto exit_create_index;
  1518   1538     }
  1519   1539   #endif
  1520   1540   
  1521   1541     /* If pList==0, it means this routine was called to make a primary
  1522   1542     ** key out of the last column added to the table under construction.
................................................................................
  1538   1558     pIndex->aiColumn = (int*)&pIndex[1];
  1539   1559     pIndex->zName = (char*)&pIndex->aiColumn[pList->nId];
  1540   1560     strcpy(pIndex->zName, zName);
  1541   1561     pIndex->pTable = pTab;
  1542   1562     pIndex->nColumn = pList->nId;
  1543   1563     pIndex->onError = pIndex->isUnique = onError;
  1544   1564     pIndex->autoIndex = pName==0;
         1565  +  pIndex->iDb = isTemp ? 1 : pParse->iDb;
  1545   1566   
  1546   1567     /* Scan the names of the columns of the table to be indexed and
  1547   1568     ** load the column indices into the Index structure.  Report an error
  1548   1569     ** if any column is not found.
  1549   1570     */
  1550   1571     for(i=0; i<pList->nId; i++){
  1551   1572       for(j=0; j<pTab->nCol; j++){
................................................................................
  1560   1581       }
  1561   1582       pIndex->aiColumn[i] = j;
  1562   1583     }
  1563   1584   
  1564   1585     /* Link the new Index structure to its table and to the other
  1565   1586     ** in-memory database structures. 
  1566   1587     */
  1567         -  if( !pParse->explain && !hideName ){
         1588  +  if( !pParse->explain ){
  1568   1589       Index *p;
  1569         -    p = sqliteHashInsert(&db->idxHash, pIndex->zName, strlen(zName)+1, pIndex);
         1590  +    p = sqliteHashInsert(&db->aDb[isTemp].idxHash, 
         1591  +                         pIndex->zName, strlen(zName)+1, pIndex);
  1570   1592       if( p ){
  1571   1593         assert( p==pIndex );  /* Malloc must have failed */
  1572   1594         sqliteFree(pIndex);
  1573   1595         goto exit_create_index;
  1574   1596       }
  1575   1597       db->flags |= SQLITE_InternChanges;
  1576   1598     }
................................................................................
  1618   1640     */
  1619   1641     else if( pParse->initFlag==0 ){
  1620   1642       int n;
  1621   1643       Vdbe *v;
  1622   1644       int lbl1, lbl2;
  1623   1645       int i;
  1624   1646       int addr;
  1625         -    int isTemp = pTab->isTemp;
  1626   1647   
  1627   1648       v = sqliteGetVdbe(pParse);
  1628   1649       if( v==0 ) goto exit_create_index;
  1629   1650       if( pTable!=0 ){
  1630   1651         sqliteBeginWriteOperation(pParse, 0, isTemp);
  1631   1652         sqliteOpenMasterTable(v, isTemp);
  1632   1653       }
................................................................................
  1649   1670       if( pStart && pEnd ){
  1650   1671         n = Addr(pEnd->z) - Addr(pStart->z) + 1;
  1651   1672         sqliteVdbeChangeP3(v, addr, pStart->z, n);
  1652   1673       }
  1653   1674       sqliteVdbeAddOp(v, OP_MakeRecord, 5, 0);
  1654   1675       sqliteVdbeAddOp(v, OP_PutIntKey, 0, 0);
  1655   1676       if( pTable ){
  1656         -      sqliteVdbeAddOp(v, OP_Integer, isTemp, 0);
         1677  +      sqliteVdbeAddOp(v, OP_Integer, pTab->iDb, 0);
  1657   1678         sqliteVdbeAddOp(v, OP_OpenRead, 2, pTab->tnum);
  1658   1679         sqliteVdbeChangeP3(v, -1, pTab->zName, P3_STATIC);
  1659   1680         lbl2 = sqliteVdbeMakeLabel(v);
  1660   1681         sqliteVdbeAddOp(v, OP_Rewind, 2, lbl2);
  1661   1682         lbl1 = sqliteVdbeAddOp(v, OP_Recno, 2, 0);
  1662   1683         for(i=0; i<pIndex->nColumn; i++){
  1663   1684           sqliteVdbeAddOp(v, OP_Column, 2, pIndex->aiColumn[i]);
................................................................................
  1679   1700         sqliteEndWriteOperation(pParse);
  1680   1701       }
  1681   1702     }
  1682   1703   
  1683   1704     /* Clean up before exiting */
  1684   1705   exit_create_index:
  1685   1706     sqliteIdListDelete(pList);
         1707  +  sqliteSrcListDelete(pTable);
  1686   1708     sqliteFree(zName);
  1687   1709     return;
  1688   1710   }
  1689   1711   
  1690   1712   /*
  1691   1713   ** This routine will drop an existing named index.  This routine
  1692   1714   ** implements the DROP INDEX statement.
  1693   1715   */
  1694         -void sqliteDropIndex(Parse *pParse, Token *pName){
         1716  +void sqliteDropIndex(Parse *pParse, SrcList *pName){
  1695   1717     Index *pIndex;
  1696         -  char *zName;
  1697   1718     Vdbe *v;
  1698   1719     sqlite *db = pParse->db;
  1699   1720   
  1700   1721     if( pParse->nErr || sqlite_malloc_failed ) return;
  1701         -  zName = sqliteTableNameFromToken(pName);
  1702         -  if( zName==0 ) return;
  1703         -  pIndex = sqliteFindIndex(db, zName);
  1704         -  sqliteFree(zName);
         1722  +  assert( pName->nSrc==1 );
         1723  +  pIndex = sqliteFindIndex(db, pName->a[0].zName, pName->a[0].zDatabase);
  1705   1724     if( pIndex==0 ){
  1706         -    sqliteSetNString(&pParse->zErrMsg, "no such index: ", 0, 
  1707         -        pName->z, pName->n, 0);
         1725  +    sqliteSetString(&pParse->zErrMsg, "no such index: ", pName->a[0].zName, 0);
  1708   1726       pParse->nErr++;
  1709         -    return;
         1727  +    goto exit_drop_index;
  1710   1728     }
  1711   1729     if( pIndex->autoIndex ){
  1712   1730       sqliteSetString(&pParse->zErrMsg, "index associated with UNIQUE "
  1713   1731         "or PRIMARY KEY constraint cannot be dropped", 0);
  1714   1732       pParse->nErr++;
  1715         -    return;
         1733  +    goto exit_drop_index;
         1734  +  }
         1735  +  if( pIndex->iDb>1 ){
         1736  +    sqliteSetString(&pParse->zErrMsg, "cannot alter schema of attached "
         1737  +       "databases", 0);
         1738  +    pParse->nErr++;
         1739  +    goto exit_drop_index;
  1716   1740     }
  1717   1741   #ifndef SQLITE_OMIT_AUTHORIZATION
  1718   1742     {
  1719   1743       int code = SQLITE_DROP_INDEX;
  1720   1744       Table *pTab = pIndex->pTable;
  1721         -    if( sqliteAuthCheck(pParse, SQLITE_DELETE, SCHEMA_TABLE(pTab->isTemp), 0) ){
  1722         -      return;
         1745  +    if( sqliteAuthCheck(pParse, SQLITE_DELETE, SCHEMA_TABLE(pIndex->iDb), 0) ){
         1746  +      goto exit_drop_index;
  1723   1747       }
  1724         -    if( pTab->isTemp ) code = SQLITE_DROP_TEMP_INDEX;
         1748  +    if( pIndex->iDb ) code = SQLITE_DROP_TEMP_INDEX;
  1725   1749       if( sqliteAuthCheck(pParse, code, pIndex->zName, pTab->zName) ){
  1726         -      return;
         1750  +      goto exit_drop_index;
  1727   1751       }
  1728   1752     }
  1729   1753   #endif
  1730   1754   
  1731   1755     /* Generate code to remove the index and from the master table */
  1732   1756     v = sqliteGetVdbe(pParse);
  1733   1757     if( v ){
................................................................................
  1739   1763         { OP_Column,     0, 1,       0},
  1740   1764         { OP_Eq,         0, ADDR(8), 0},
  1741   1765         { OP_Next,       0, ADDR(3), 0},
  1742   1766         { OP_Goto,       0, ADDR(9), 0},
  1743   1767         { OP_Delete,     0, 0,       0}, /* 8 */
  1744   1768       };
  1745   1769       int base;
  1746         -    Table *pTab = pIndex->pTable;
  1747   1770   
  1748         -    sqliteBeginWriteOperation(pParse, 0, pTab->isTemp);
  1749         -    sqliteOpenMasterTable(v, pTab->isTemp);
         1771  +    sqliteBeginWriteOperation(pParse, 0, pIndex->iDb);
         1772  +    sqliteOpenMasterTable(v, pIndex->iDb);
  1750   1773       base = sqliteVdbeAddOpList(v, ArraySize(dropIndex), dropIndex);
  1751   1774       sqliteVdbeChangeP3(v, base+1, pIndex->zName, 0);
  1752         -    if( !pTab->isTemp ){
         1775  +    if( pIndex->iDb==0 ){
  1753   1776         sqliteChangeCookie(db, v);
  1754   1777       }
  1755   1778       sqliteVdbeAddOp(v, OP_Close, 0, 0);
  1756         -    sqliteVdbeAddOp(v, OP_Destroy, pIndex->tnum, pTab->isTemp);
         1779  +    sqliteVdbeAddOp(v, OP_Destroy, pIndex->tnum, pIndex->iDb);
  1757   1780       sqliteEndWriteOperation(pParse);
  1758   1781     }
  1759   1782   
  1760   1783     /* Delete the in-memory description of this index.
  1761   1784     */
  1762   1785     if( !pParse->explain ){
  1763   1786       sqliteUnlinkAndDeleteIndex(db, pIndex);
  1764   1787       db->flags |= SQLITE_InternChanges;
  1765   1788     }
         1789  +
         1790  +exit_drop_index:
         1791  +  sqliteSrcListDelete(pName);
  1766   1792   }
  1767   1793   
  1768   1794   /*
  1769   1795   ** Append a new element to the given IdList.  Create a new IdList if
  1770   1796   ** need be.
  1771   1797   **
  1772   1798   ** A new IdList is returned, or NULL if malloc() fails.
................................................................................
  1939   1965   **
  1940   1966   ** "table" is an existing table name.  We will read lines of code from
  1941   1967   ** file to fill this table with data.  File might be "stdin".  The optional
  1942   1968   ** delimiter string identifies the field separators.  The default is a tab.
  1943   1969   */
  1944   1970   void sqliteCopy(
  1945   1971     Parse *pParse,       /* The parser context */
  1946         -  Token *pTableName,   /* The name of the table into which we will insert */
         1972  +  SrcList *pTableName, /* The name of the table into which we will insert */
  1947   1973     Token *pFilename,    /* The file from which to obtain information */
  1948   1974     Token *pDelimiter,   /* Use this as the field delimiter */
  1949   1975     int onError          /* What to do if a constraint fails */
  1950   1976   ){
  1951   1977     Table *pTab;
  1952         -  char *zTab;
  1953   1978     int i;
  1954   1979     Vdbe *v;
  1955   1980     int addr, end;
  1956   1981     Index *pIdx;
  1957   1982     char *zFile = 0;
  1958   1983     sqlite *db = pParse->db;
  1959   1984   
  1960   1985   
  1961         -  zTab = sqliteTableNameFromToken(pTableName);
  1962         -  if( sqlite_malloc_failed || zTab==0 ) goto copy_cleanup;
  1963         -  pTab = sqliteTableNameToTable(pParse, zTab);
  1964         -  sqliteFree(zTab);
         1986  +  if( sqlite_malloc_failed  ) goto copy_cleanup;
         1987  +  assert( pTableName->nSrc==1 );
         1988  +  pTab = sqliteTableNameToTable(pParse, pTableName->a[0].zName,
         1989  +                                pTableName->a[0].zDatabase);
  1965   1990     if( pTab==0 ) goto copy_cleanup;
  1966   1991     zFile = sqliteStrNDup(pFilename->z, pFilename->n);
  1967   1992     sqliteDequote(zFile);
  1968   1993     if( sqliteAuthCheck(pParse, SQLITE_INSERT, pTab->zName, zFile)
  1969   1994         || sqliteAuthCheck(pParse, SQLITE_COPY, pTab->zName, zFile) ){
  1970   1995       goto copy_cleanup;
  1971   1996     }
  1972   1997     v = sqliteGetVdbe(pParse);
  1973   1998     if( v ){
  1974         -    sqliteBeginWriteOperation(pParse, 1, pTab->isTemp);
         1999  +    sqliteBeginWriteOperation(pParse, 1, pTab->iDb==1);
  1975   2000       addr = sqliteVdbeAddOp(v, OP_FileOpen, 0, 0);
  1976   2001       sqliteVdbeChangeP3(v, addr, pFilename->z, pFilename->n);
  1977   2002       sqliteVdbeDequoteP3(v, addr);
  1978         -    sqliteVdbeAddOp(v, OP_Integer, pTab->isTemp, 0);
         2003  +    sqliteVdbeAddOp(v, OP_Integer, pTab->iDb, 0);
  1979   2004       sqliteVdbeAddOp(v, OP_OpenWrite, 0, pTab->tnum);
  1980   2005       sqliteVdbeChangeP3(v, -1, pTab->zName, P3_STATIC);
  1981   2006       for(i=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
  1982         -      sqliteVdbeAddOp(v, OP_Integer, pTab->isTemp, 0);
         2007  +      assert( pIdx->iDb==1 || pIdx->iDb==pTab->iDb );
         2008  +      sqliteVdbeAddOp(v, OP_Integer, pIdx->iDb, 0);
  1983   2009         sqliteVdbeAddOp(v, OP_OpenWrite, i, pIdx->tnum);
  1984   2010         sqliteVdbeChangeP3(v, -1, pIdx->zName, P3_STATIC);
  1985   2011       }
  1986   2012       if( db->flags & SQLITE_CountRows ){
  1987   2013         sqliteVdbeAddOp(v, OP_Integer, 0, 0);  /* Initialize the row count */
  1988   2014       }
  1989   2015       end = sqliteVdbeMakeLabel(v);
................................................................................
  2022   2048         sqliteVdbeAddOp(v, OP_ColumnName, 0, 0);
  2023   2049         sqliteVdbeChangeP3(v, -1, "rows inserted", P3_STATIC);
  2024   2050         sqliteVdbeAddOp(v, OP_Callback, 1, 0);
  2025   2051       }
  2026   2052     }
  2027   2053     
  2028   2054   copy_cleanup:
         2055  +  sqliteSrcListDelete(pTableName);
  2029   2056     sqliteFree(zFile);
  2030   2057     return;
  2031   2058   }
  2032   2059   
  2033   2060   /*
  2034   2061   ** The non-standard VACUUM command is used to clean up the database,
  2035   2062   ** collapse free space, etc.  It is modelled after the VACUUM command
................................................................................
  2483   2510       }else{
  2484   2511         db->flags &= ~SQLITE_NullCallback;
  2485   2512       }
  2486   2513     }else
  2487   2514   
  2488   2515     if( sqliteStrICmp(zLeft, "table_info")==0 ){
  2489   2516       Table *pTab;
  2490         -    pTab = sqliteFindTable(db, zRight);
         2517  +    pTab = sqliteFindTable(db, zRight, 0);
  2491   2518       if( pTab ){
  2492   2519         static VdbeOp tableInfoPreface[] = {
  2493   2520           { OP_ColumnName,  0, 0,       "cid"},
  2494   2521           { OP_ColumnName,  1, 0,       "name"},
  2495   2522           { OP_ColumnName,  2, 0,       "type"},
  2496   2523           { OP_ColumnName,  3, 0,       "notnull"},
  2497   2524           { OP_ColumnName,  4, 0,       "dflt_value"},
................................................................................
  2513   2540         }
  2514   2541       }
  2515   2542     }else
  2516   2543   
  2517   2544     if( sqliteStrICmp(zLeft, "index_info")==0 ){
  2518   2545       Index *pIdx;
  2519   2546       Table *pTab;
  2520         -    pIdx = sqliteFindIndex(db, zRight);
         2547  +    pIdx = sqliteFindIndex(db, zRight, 0);
  2521   2548       if( pIdx ){
  2522   2549         static VdbeOp tableInfoPreface[] = {
  2523   2550           { OP_ColumnName,  0, 0,       "seqno"},
  2524   2551           { OP_ColumnName,  1, 0,       "cid"},
  2525   2552           { OP_ColumnName,  2, 0,       "name"},
  2526   2553         };
  2527   2554         int i;
................................................................................
  2538   2565         }
  2539   2566       }
  2540   2567     }else
  2541   2568   
  2542   2569     if( sqliteStrICmp(zLeft, "index_list")==0 ){
  2543   2570       Index *pIdx;
  2544   2571       Table *pTab;
  2545         -    pTab = sqliteFindTable(db, zRight);
         2572  +    pTab = sqliteFindTable(db, zRight, 0);
  2546   2573       if( pTab ){
  2547   2574         v = sqliteGetVdbe(pParse);
  2548   2575         pIdx = pTab->pIndex;
  2549   2576       }
  2550   2577       if( pTab && pIdx ){
  2551   2578         int i = 0; 
  2552   2579         static VdbeOp indexListPreface[] = {

Changes to src/delete.c.

     8      8   **    May you find forgiveness for yourself and forgive others.
     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12     12   ** This file contains C code routines that are called by the parser
    13     13   ** to handle DELETE FROM statements.
    14     14   **
    15         -** $Id: delete.c,v 1.47 2003/03/20 01:16:59 drh Exp $
           15  +** $Id: delete.c,v 1.48 2003/03/27 12:51:24 drh Exp $
    16     16   */
    17     17   #include "sqliteInt.h"
    18     18   
    19     19   
    20     20   /*
    21     21   ** Given a table name, find the corresponding table and make sure the
    22     22   ** table is writeable.  Generate an error and return NULL if not.  If
    23     23   ** everything checks out, return a pointer to the Table structure.
    24     24   */
    25         -Table *sqliteTableNameToTable(Parse *pParse, const char *zTab){
           25  +Table *sqliteTableNameToTable(Parse *pParse, const char *zTab, const char *zDb){
    26     26     Table *pTab;
    27         -  pTab = sqliteFindTable(pParse->db, zTab);
           27  +  pTab = sqliteFindTable(pParse->db, zTab, zDb);
    28     28     if( pTab==0 ){
    29         -    sqliteSetString(&pParse->zErrMsg, "no such table: ", zTab, 0);
           29  +    if( zDb==0 || zDb[0]==0 ){
           30  +      sqliteSetString(&pParse->zErrMsg, "no such table: ", zTab, 0);
           31  +    }else{
           32  +      sqliteSetString(&pParse->zErrMsg, "no such table: ", zDb, ".", zTab, 0);
           33  +    }
    30     34       pParse->nErr++;
    31     35       return 0;
    32     36     }
    33     37     if( pTab->readOnly || pTab->pSelect ){
    34     38       sqliteSetString(&pParse->zErrMsg, 
    35     39         pTab->pSelect ? "view " : "table ",
    36     40         zTab,
................................................................................
    48     52     Parse *pParse,         /* The parser context */
    49     53     SrcList *pTabList,     /* The table from which we should delete things */
    50     54     Expr *pWhere           /* The WHERE clause.  May be null */
    51     55   ){
    52     56     Vdbe *v;               /* The virtual database engine */
    53     57     Table *pTab;           /* The table from which records will be deleted */
    54     58     char *zTab;            /* Name of the table from which we are deleting */
           59  +  char *zDb;             /* Name of database containing table zTab */
    55     60     int end, addr;         /* A couple addresses of generated code */
    56     61     int i;                 /* Loop counter */
    57     62     WhereInfo *pWInfo;     /* Information about the WHERE clause */
    58     63     Index *pIdx;           /* For looping over indices of the table */
    59     64     int base;              /* Index of the first available table cursor */
    60     65     sqlite *db;            /* Main database structure */
    61     66   
................................................................................
    69     74     db = pParse->db;
    70     75     assert( pTabList->nSrc==1 );
    71     76   
    72     77     /* Check for the special case of a VIEW with one or more ON DELETE triggers 
    73     78     ** defined 
    74     79     */
    75     80     zTab = pTabList->a[0].zName;
           81  +  zDb = pTabList->a[0].zDatabase;
    76     82     if( zTab != 0 ){
    77         -    pTab = sqliteFindTable(pParse->db, zTab);
           83  +    pTab = sqliteFindTable(pParse->db, zTab, zDb);
    78     84       if( pTab ){
    79     85         row_triggers_exist = 
    80     86           sqliteTriggersExist(pParse, pTab->pTrigger, 
    81     87               TK_DELETE, TK_BEFORE, TK_ROW, 0) ||
    82     88           sqliteTriggersExist(pParse, pTab->pTrigger, 
    83     89               TK_DELETE, TK_AFTER, TK_ROW, 0);
    84     90       }
................................................................................
    91     97     }
    92     98   
    93     99     /* Locate the table which we want to delete.  This table has to be
    94    100     ** put in an SrcList structure because some of the subroutines we
    95    101     ** will be calling are designed to work with multiple tables and expect
    96    102     ** an SrcList* parameter instead of just a Table* parameter.
    97    103     */
    98         -  pTab = pTabList->a[0].pTab = sqliteTableNameToTable(pParse, zTab);
          104  +  pTab = pTabList->a[0].pTab = sqliteTableNameToTable(pParse, zTab, zDb);
    99    105     if( pTab==0 ){
   100    106       goto delete_from_cleanup;
   101    107     }
   102    108     assert( pTab->pSelect==0 );  /* This table is not a view */
   103    109     if( sqliteAuthCheck(pParse, SQLITE_DELETE, pTab->zName, 0) ){
   104    110       goto delete_from_cleanup;
   105    111     }
................................................................................
   125    131     /* Begin generating code.
   126    132     */
   127    133     v = sqliteGetVdbe(pParse);
   128    134     if( v==0 ){
   129    135       goto delete_from_cleanup;
   130    136     }
   131    137     sqliteBeginWriteOperation(pParse, row_triggers_exist,
   132         -       !row_triggers_exist && pTab->isTemp);
          138  +       !row_triggers_exist && pTab->iDb==1);
   133    139   
   134    140     /* Initialize the counter of the number of rows deleted, if
   135    141     ** we are counting rows.
   136    142     */
   137    143     if( db->flags & SQLITE_CountRows ){
   138    144       sqliteVdbeAddOp(v, OP_Integer, 0, 0);
   139    145     }
................................................................................
   144    150     */
   145    151     if( pWhere==0 && !row_triggers_exist ){
   146    152       if( db->flags & SQLITE_CountRows ){
   147    153         /* If counting rows deleted, just count the total number of
   148    154         ** entries in the table. */
   149    155         int endOfLoop = sqliteVdbeMakeLabel(v);
   150    156         int addr;
   151         -      sqliteVdbeAddOp(v, OP_Integer, pTab->isTemp, 0);
          157  +      sqliteVdbeAddOp(v, OP_Integer, pTab->iDb, 0);
   152    158         sqliteVdbeAddOp(v, OP_OpenRead, base, pTab->tnum);
   153    159         sqliteVdbeAddOp(v, OP_Rewind, base, sqliteVdbeCurrentAddr(v)+2);
   154    160         addr = sqliteVdbeAddOp(v, OP_AddImm, 1, 0);
   155    161         sqliteVdbeAddOp(v, OP_Next, base, addr);
   156    162         sqliteVdbeResolveLabel(v, endOfLoop);
   157    163         sqliteVdbeAddOp(v, OP_Close, base, 0);
   158    164       }
   159         -    sqliteVdbeAddOp(v, OP_Clear, pTab->tnum, pTab->isTemp);
          165  +    sqliteVdbeAddOp(v, OP_Clear, pTab->tnum, pTab->iDb);
   160    166       for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
   161         -      sqliteVdbeAddOp(v, OP_Clear, pIdx->tnum, pTab->isTemp);
          167  +      sqliteVdbeAddOp(v, OP_Clear, pIdx->tnum, pIdx->iDb);
   162    168       }
   163    169     }
   164    170   
   165    171     /* The usual case: There is a WHERE clause so we have to scan through
   166    172     ** the table an pick which records to delete.
   167    173     */
   168    174     else{
................................................................................
   191    197   
   192    198       /* This is the beginning of the delete loop when there are
   193    199       ** row triggers.
   194    200       */
   195    201       if( row_triggers_exist ){
   196    202         addr = sqliteVdbeAddOp(v, OP_ListRead, 0, end);
   197    203         sqliteVdbeAddOp(v, OP_Dup, 0, 0);
   198         -      sqliteVdbeAddOp(v, OP_Integer, pTab->isTemp, 0);
          204  +      sqliteVdbeAddOp(v, OP_Integer, pTab->iDb, 0);
   199    205         sqliteVdbeAddOp(v, OP_OpenRead, base, pTab->tnum);
   200    206         sqliteVdbeAddOp(v, OP_MoveTo, base, 0);
   201    207         sqliteVdbeAddOp(v, OP_OpenTemp, oldIdx, 0);
   202    208   
   203    209         sqliteVdbeAddOp(v, OP_Integer, 13, 0);
   204    210         for(i = 0; i<pTab->nCol; i++){
   205    211           if( i==pTab->iPKey ){ 
................................................................................
   221    227       /* Open cursors for the table we are deleting from and all its
   222    228       ** indices.  If there are row triggers, this happens inside the
   223    229       ** OP_ListRead loop because the cursor have to all be closed
   224    230       ** before the trigger fires.  If there are no row triggers, the
   225    231       ** cursors are opened only once on the outside the loop.
   226    232       */
   227    233       pParse->nTab = base + 1;
   228         -    sqliteVdbeAddOp(v, OP_Integer, pTab->isTemp, 0);
          234  +    sqliteVdbeAddOp(v, OP_Integer, pTab->iDb, 0);
   229    235       sqliteVdbeAddOp(v, OP_OpenWrite, base, pTab->tnum);
   230    236       for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
   231         -      sqliteVdbeAddOp(v, OP_Integer, pTab->isTemp, 0);
          237  +      sqliteVdbeAddOp(v, OP_Integer, pIdx->iDb, 0);
   232    238         sqliteVdbeAddOp(v, OP_OpenWrite, pParse->nTab++, pIdx->tnum);
   233    239       }
   234    240   
   235    241       /* This is the beginning of the delete loop when there are no
   236    242       ** row triggers */
   237    243       if( !row_triggers_exist ){ 
   238    244         addr = sqliteVdbeAddOp(v, OP_ListRead, 0, end);

Changes to src/expr.c.

     8      8   **    May you find forgiveness for yourself and forgive others.
     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12     12   ** This file contains routines used for analyzing expressions and
    13     13   ** for generating VDBE code that evaluates expressions in SQLite.
    14     14   **
    15         -** $Id: expr.c,v 1.89 2003/03/20 01:16:59 drh Exp $
           15  +** $Id: expr.c,v 1.90 2003/03/27 12:51:25 drh Exp $
    16     16   */
    17     17   #include "sqliteInt.h"
    18     18   #include <ctype.h>
    19     19   
    20     20   /*
    21     21   ** Construct a new expression node and return a pointer to it.  Memory
    22     22   ** for this node is obtained from sqliteMalloc().  The calling function
................................................................................
   489    489         }
   490    490         if( pExpr->op==TK_COLUMN ){
   491    491           sqliteAuthRead(pParse, pExpr, pTabList, base);
   492    492         }
   493    493         break; 
   494    494       }
   495    495     
   496         -    /* A table name and column name:  ID.ID */
          496  +    /* A table name and column name:     ID.ID
          497  +    ** Or a database, table and column:  ID.ID.ID
          498  +    */
   497    499       case TK_DOT: {
   498    500         int cnt = 0;             /* Number of matches */
   499    501         int cntTab = 0;          /* Number of matching tables */
   500    502         int i;                   /* Loop counter */
   501    503         Expr *pLeft, *pRight;    /* Left and right subbranches of the expr */
   502    504         char *zLeft, *zRight;    /* Text of an identifier */
          505  +      char *zDb;               /* Name of database holding table */
          506  +      sqlite *db = pParse->db;
   503    507   
   504         -      pLeft = pExpr->pLeft;
   505    508         pRight = pExpr->pRight;
          509  +      if( pRight->op==TK_ID ){
          510  +        pLeft = pExpr->pLeft;
          511  +        zDb = 0;
          512  +      }else{
          513  +        Expr *pDb = pExpr->pLeft;
          514  +        assert( pDb && pDb->op==TK_ID && pDb->token.z );
          515  +        zDb = sqliteStrNDup(pDb->token.z, pDb->token.n);
          516  +        pLeft = pRight->pLeft;
          517  +        pRight = pRight->pRight;
          518  +      }
   506    519         assert( pLeft && pLeft->op==TK_ID && pLeft->token.z );
   507    520         assert( pRight && pRight->op==TK_ID && pRight->token.z );
   508    521         zLeft = sqliteStrNDup(pLeft->token.z, pLeft->token.n);
   509    522         zRight = sqliteStrNDup(pRight->token.z, pRight->token.n);
   510    523         if( zLeft==0 || zRight==0 ){
   511    524           sqliteFree(zLeft);
   512    525           sqliteFree(zRight);
          526  +        sqliteFree(zDb);
   513    527           return 1;
   514    528         }
          529  +      sqliteDequote(zDb);
   515    530         sqliteDequote(zLeft);
   516    531         sqliteDequote(zRight);
   517    532         pExpr->iTable = -1;
   518    533         for(i=0; i<pTabList->nSrc; i++){
   519    534           int j;
   520    535           char *zTab;
   521    536           Table *pTab = pTabList->a[i].pTab;
   522    537           if( pTab==0 ) continue;
   523    538           assert( pTab->nCol>0 );
   524    539           if( pTabList->a[i].zAlias ){
   525    540             zTab = pTabList->a[i].zAlias;
          541  +          if( sqliteStrICmp(zTab, zLeft)!=0 ) continue;
   526    542           }else{
   527    543             zTab = pTab->zName;
          544  +          if( zTab==0 || sqliteStrICmp(zTab, zLeft)!=0 ) continue;
          545  +          if( zDb!=0 && sqliteStrICmp(db->aDb[pTab->iDb].zName, zDb)!=0 ){
          546  +            continue;
          547  +          }
   528    548           }
   529         -        if( zTab==0 || sqliteStrICmp(zTab, zLeft)!=0 ) continue;
   530    549           if( 0==(cntTab++) ) pExpr->iTable = i + base;
   531    550           for(j=0; j<pTab->nCol; j++){
   532    551             if( sqliteStrICmp(pTab->aCol[j].zName, zRight)==0 ){
   533    552               cnt++;
   534    553               pExpr->iTable = i + base;
   535    554               if( j==pTab->iPKey ){
   536    555                 /* Substitute the record number for the INTEGER PRIMARY KEY */
................................................................................
   573    592         }
   574    593   
   575    594         if( cnt==0 && cntTab==1 && sqliteIsRowid(zRight) ){
   576    595           cnt = 1;
   577    596           pExpr->iColumn = -1;
   578    597           pExpr->dataType = SQLITE_SO_NUM;
   579    598         }
          599  +      sqliteFree(zDb);
   580    600         sqliteFree(zLeft);
   581    601         sqliteFree(zRight);
   582    602         if( cnt==0 ){
   583    603           sqliteSetNString(&pParse->zErrMsg, "no such column: ", -1,  
   584    604             pLeft->token.z, pLeft->token.n, ".", 1, 
   585    605             pRight->token.z, pRight->token.n, 0);
   586    606           pParse->nErr++;
................................................................................
   588    608         }else if( cnt>1 ){
   589    609           sqliteSetNString(&pParse->zErrMsg, "ambiguous column name: ", -1,  
   590    610             pLeft->token.z, pLeft->token.n, ".", 1,
   591    611             pRight->token.z, pRight->token.n, 0);
   592    612           pParse->nErr++;
   593    613           return 1;
   594    614         }
   595         -      sqliteExprDelete(pLeft);
          615  +      sqliteExprDelete(pExpr->pLeft);
   596    616         pExpr->pLeft = 0;
   597         -      sqliteExprDelete(pRight);
          617  +      sqliteExprDelete(pExpr->pRight);
   598    618         pExpr->pRight = 0;
   599    619         pExpr->op = TK_COLUMN;
   600    620         sqliteAuthRead(pParse, pExpr, pTabList, base);
   601    621         break;
   602    622       }
   603    623   
   604    624       case TK_IN: {

Changes to src/func.c.

    12     12   ** This file contains the C functions that implement various SQL
    13     13   ** functions of SQLite.  
    14     14   **
    15     15   ** There is only one exported symbol in this file - the function
    16     16   ** sqliteRegisterBuildinFunctions() found at the bottom of the file.
    17     17   ** All other code has file scope.
    18     18   **
    19         -** $Id: func.c,v 1.23 2002/11/04 19:32:25 drh Exp $
           19  +** $Id: func.c,v 1.24 2003/03/27 12:51:25 drh Exp $
    20     20   */
    21     21   #include <ctype.h>
    22     22   #include <math.h>
    23     23   #include <stdlib.h>
    24     24   #include <assert.h>
    25     25   #include "sqliteInt.h"
    26     26   
................................................................................
   250    250   /*
   251    251   ** Implementation of the VERSION(*) function.  The result is the version
   252    252   ** of the SQLite library that is running.
   253    253   */
   254    254   static void versionFunc(sqlite_func *context, int argc, const char **argv){
   255    255     sqlite_set_result_string(context, sqlite_version, -1);
   256    256   }
          257  +
          258  +#ifdef SQLITE_SOUNDEX
          259  +/*
          260  +** Compute the soundex encoding of a word.
          261  +*/
          262  +static void soundexFunc(sqlite_func *context, int argc, const char **argv){
          263  +  char zResult[8];
          264  +  const char *zIn;
          265  +  int i, j;
          266  +  static const unsigned char iCode[] = {
          267  +    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
          268  +    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
          269  +    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
          270  +    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
          271  +    0, 0, 1, 2, 3, 0, 1, 2, 0, 0, 2, 2, 4, 5, 5, 0,
          272  +    1, 2, 6, 2, 3, 0, 1, 0, 2, 0, 2, 0, 0, 0, 0, 0,
          273  +    0, 0, 1, 2, 3, 0, 1, 2, 0, 0, 2, 2, 4, 5, 5, 0,
          274  +    1, 2, 6, 2, 3, 0, 1, 0, 2, 0, 2, 0, 0, 0, 0, 0,
          275  +  };
          276  +  assert( argc==1 );
          277  +  zIn = argv[0];
          278  +  for(i=0; zIn[i] && !isalpha(zIn[i]); i++){}
          279  +  if( zIn[i] ){
          280  +    zResult[0] = toupper(zIn[i]);
          281  +    for(j=1; j<4 && zIn[i]; i++){
          282  +      int code = iCode[zIn[i]&0x7f];
          283  +      if( code>0 ){
          284  +        zResult[j++] = code + '0';
          285  +      }
          286  +    }
          287  +    while( j<4 ){
          288  +      zResult[j++] = '0';
          289  +    }
          290  +    zResult[j] = 0;
          291  +    sqlite_set_result_string(context, zResult, 4);
          292  +  }else{
          293  +    sqlite_set_result_string(context, zResult, "?000", 4);
          294  +  }
          295  +}
          296  +#endif
   257    297   
   258    298   #ifdef SQLITE_TEST
   259    299   /*
   260    300   ** This function generates a string of random characters.  Used for
   261    301   ** generating test data.
   262    302   */
   263    303   static void randStr(sqlite_func *context, int argc, const char **argv){
................................................................................
   486    526       { "coalesce",   1, 0,              0          },
   487    527       { "ifnull",     2, SQLITE_ARGS,    ifnullFunc },
   488    528       { "random",    -1, SQLITE_NUMERIC, randomFunc },
   489    529       { "like",       2, SQLITE_NUMERIC, likeFunc   },
   490    530       { "glob",       2, SQLITE_NUMERIC, globFunc   },
   491    531       { "nullif",     2, SQLITE_ARGS,    nullifFunc },
   492    532       { "sqlite_version",0,SQLITE_TEXT,  versionFunc},
          533  +#ifdef SQLITE_SOUNDEX
          534  +    { "soundex",    1, SQLITE_TEXT,    soundexFunc},
          535  +#endif
   493    536   #ifdef SQLITE_TEST
   494    537       { "randstr",    2, SQLITE_TEXT,    randStr    },
   495    538   #endif
   496    539     };
   497    540     static struct {
   498    541       char *zName;
   499    542       int nArg;

Changes to src/insert.c.

     8      8   **    May you find forgiveness for yourself and forgive others.
     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12     12   ** This file contains C code routines that are called by the parser
    13     13   ** to handle INSERT statements in SQLite.
    14     14   **
    15         -** $Id: insert.c,v 1.74 2003/03/20 01:16:59 drh Exp $
           15  +** $Id: insert.c,v 1.75 2003/03/27 12:51:25 drh Exp $
    16     16   */
    17     17   #include "sqliteInt.h"
    18     18   
    19     19   /*
    20     20   ** This routine is call to handle SQL of the following forms:
    21     21   **
    22     22   **    insert into TABLE (IDLIST) values(EXPRLIST)
................................................................................
    89     89     ExprList *pList,      /* List of values to be inserted */
    90     90     Select *pSelect,      /* A SELECT statement to use as the data source */
    91     91     IdList *pColumn,      /* Column names corresponding to IDLIST. */
    92     92     int onError           /* How to handle constraint errors */
    93     93   ){
    94     94     Table *pTab;          /* The table to insert into */
    95     95     char *zTab;           /* Name of the table into which we are inserting */
           96  +  char *zDb;            /* Name of the database holding zTab */
    96     97     int i, j, idx;        /* Loop counters */
    97     98     Vdbe *v;              /* Generate code into this virtual machine */
    98     99     Index *pIdx;          /* For looping over indices of the table */
    99    100     int nColumn;          /* Number of columns in the data */
   100    101     int base;             /* First available cursor */
   101    102     int iCont, iBreak;    /* Beginning and end of the loop over srcTab */
   102    103     sqlite *db;           /* The main database structure */
................................................................................
   116    117     db = pParse->db;
   117    118   
   118    119     /* Locate the table into which we will be inserting new information.
   119    120     */
   120    121     assert( pTabList->nSrc==1 );
   121    122     zTab = pTabList->a[0].zName;
   122    123     if( zTab==0 ) goto insert_cleanup;
   123         -  pTab = sqliteFindTable(pParse->db, zTab);
          124  +  zDb = pTabList->a[0].zDatabase;
          125  +  pTab = sqliteTableNameToTable(pParse, zTab, zDb);
   124    126     if( pTab==0 ){
   125         -    sqliteSetString(&pParse->zErrMsg, "no such table: ", zTab, 0);
   126         -    pParse->nErr++;
   127    127       goto insert_cleanup;
   128    128     }
   129    129     if( sqliteAuthCheck(pParse, SQLITE_INSERT, pTab->zName, 0) ){
   130    130       goto insert_cleanup;
   131    131     }
   132    132   
   133    133     /* Ensure that:
................................................................................
   158    158     }
   159    159   
   160    160     /* Allocate a VDBE
   161    161     */
   162    162     v = sqliteGetVdbe(pParse);
   163    163     if( v==0 ) goto insert_cleanup;
   164    164     sqliteBeginWriteOperation(pParse, pSelect || row_triggers_exist,
   165         -         !row_triggers_exist && pTab->isTemp);
          165  +         !row_triggers_exist && pTab->iDb==1);
   166    166   
   167    167     /* if there are row triggers, allocate a temp table for new.* references. */
   168    168     if( row_triggers_exist ){
   169    169       newIdx = pParse->nTab++;
   170    170     }
   171    171   
   172    172     /* Figure out how many columns of data are supplied.  If the data
................................................................................
   192    192       assert( pSelect->pEList );
   193    193       nColumn = pSelect->pEList->nExpr;
   194    194   
   195    195       /* Set useTempTable to TRUE if the result of the SELECT statement
   196    196       ** should be written into a temporary table.  Set to FALSE if each
   197    197       ** row of the SELECT can be written directly into the result table.
   198    198       */
   199         -    opCode = pTab->isTemp ? OP_OpenTemp : OP_OpenRead;
          199  +    opCode = pTab->iDb==1 ? OP_OpenTemp : OP_OpenRead;
   200    200       useTempTable = row_triggers_exist || sqliteVdbeFindOp(v,opCode,pTab->tnum);
   201    201   
   202    202       if( useTempTable ){
   203    203         /* Generate the subroutine that SELECT calls to process each row of
   204    204         ** the result.  Store the result in a temporary table
   205    205         */
   206    206         srcTab = pParse->nTab++;
................................................................................
   323    323       sqliteVdbeAddOp(v, OP_Integer, 0, 0);
   324    324       sqliteVdbeAddOp(v, OP_MemStore, iCntMem, 1);
   325    325     }
   326    326   
   327    327     /* Open tables and indices if there are no row triggers */
   328    328     if( !row_triggers_exist ){
   329    329       base = pParse->nTab;
   330         -    sqliteVdbeAddOp(v, OP_Integer, pTab->isTemp, 0);
          330  +    sqliteVdbeAddOp(v, OP_Integer, pTab->iDb, 0);
   331    331       sqliteVdbeAddOp(v, OP_OpenWrite, base, pTab->tnum);
   332    332       sqliteVdbeChangeP3(v, -1, pTab->zName, P3_STATIC);
   333    333       for(idx=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, idx++){
   334         -      sqliteVdbeAddOp(v, OP_Integer, pTab->isTemp, 0);
          334  +      sqliteVdbeAddOp(v, OP_Integer, pIdx->iDb, 0);
   335    335         sqliteVdbeAddOp(v, OP_OpenWrite, idx+base, pIdx->tnum);
   336    336         sqliteVdbeChangeP3(v, -1, pIdx->zName, P3_STATIC);
   337    337       }
   338    338       pParse->nTab += idx;
   339    339     }
   340    340   
   341    341     /* If the data source is a temporary table, then we have to create
................................................................................
   385    385           onError, endOfLoop) ){
   386    386         goto insert_cleanup;
   387    387       }
   388    388   
   389    389       /* Open the tables and indices for the INSERT */
   390    390       if( !pTab->pSelect ){
   391    391         base = pParse->nTab;
   392         -      sqliteVdbeAddOp(v, OP_Integer, pTab->isTemp, 0);
          392  +      sqliteVdbeAddOp(v, OP_Integer, pTab->iDb, 0);
   393    393         sqliteVdbeAddOp(v, OP_OpenWrite, base, pTab->tnum);
   394    394         sqliteVdbeChangeP3(v, -1, pTab->zName, P3_STATIC);
   395    395         for(idx=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, idx++){
   396         -        sqliteVdbeAddOp(v, OP_Integer, pTab->isTemp, 0);
          396  +        sqliteVdbeAddOp(v, OP_Integer, pIdx->iDb, 0);
   397    397           sqliteVdbeAddOp(v, OP_OpenWrite, idx+base, pIdx->tnum);
   398    398           sqliteVdbeChangeP3(v, -1, pIdx->zName, P3_STATIC);
   399    399         }
   400    400         pParse->nTab += idx;
   401    401       }
   402    402     }
   403    403   

Changes to src/main.c.

    10     10   **
    11     11   *************************************************************************
    12     12   ** Main file for the SQLite library.  The routines in this file
    13     13   ** implement the programmer interface to the library.  Routines in
    14     14   ** other files are for internal use by SQLite and should not be
    15     15   ** accessed by users of the library.
    16     16   **
    17         -** $Id: main.c,v 1.116 2003/03/20 01:16:59 drh Exp $
           17  +** $Id: main.c,v 1.117 2003/03/27 12:51:25 drh Exp $
    18     18   */
    19     19   #include "sqliteInt.h"
    20     20   #include "os.h"
    21     21   #include <ctype.h>
    22     22   
    23     23   /*
    24     24   ** A pointer to this structure is used to communicate information
................................................................................
    63     63           ** But because sParse.initFlag is set to 1, no VDBE code is generated
    64     64           ** or executed.  All the parser does is build the internal data
    65     65           ** structures that describe the table, index, or view.
    66     66           */
    67     67           memset(&sParse, 0, sizeof(sParse));
    68     68           sParse.db = pData->db;
    69     69           sParse.initFlag = 1;
    70         -        sParse.isTemp = argv[4][0] - '0';
           70  +        sParse.iDb = atoi(argv[4]);
    71     71           sParse.newTnum = atoi(argv[2]);
    72     72           sParse.useCallback = 1;
    73     73           sqliteRunParser(&sParse, argv[3], pData->pzErrMsg);
    74     74         }else{
    75     75           /* If the SQL column is blank it means this is an index that
    76     76           ** was created to be the PRIMARY KEY or to fulfill a UNIQUE
    77     77           ** constraint for a CREATE TABLE.  The index should have already
    78     78           ** been created when we processed the CREATE TABLE.  All we have
    79     79           ** to do here is record the root page number for that index.
    80     80           */
    81         -        Index *pIndex = sqliteFindIndex(pData->db, argv[1]);
           81  +        int iDb;
           82  +        Index *pIndex;
           83  +
           84  +        iDb = atoi(argv[4]);
           85  +        assert( iDb>=0 && iDb<pData->db->nDb );
           86  +        pIndex = sqliteFindIndex(pData->db, argv[1], pData->db->aDb[iDb].zName);
    82     87           if( pIndex==0 || pIndex->tnum!=0 ){
    83     88             /* This can occur if there exists an index on a TEMP table which
    84     89             ** has the same name as another index on a permanent index.  Since
    85     90             ** the permanent table is hidden by the TEMP table, we can also
    86     91             ** safely ignore the index on the permanent table.
    87     92             */
    88     93             /* Do Nothing */;
................................................................................
   114    119   int upgrade_3_callback(void *pInit, int argc, char **argv, char **NotUsed){
   115    120     InitData *pData = (InitData*)pInit;
   116    121     int rc;
   117    122     Table *pTab;
   118    123     Trigger *pTrig;
   119    124     char *zErr = 0;
   120    125   
   121         -  pTab = sqliteFindTable(pData->db, argv[0]);
          126  +  pTab = sqliteFindTable(pData->db, argv[0], 0);
   122    127     assert( pTab!=0 );
   123    128     assert( sqliteStrICmp(pTab->zName, argv[0])==0 );
   124    129     if( pTab ){
   125    130       pTrig = pTab->pTrigger;
   126    131       pTab->pTrigger = 0;  /* Disable all triggers before rebuilding the table */
   127    132     }
   128    133     rc = sqlite_exec_printf(pData->db,
................................................................................
   137    142     }
   138    143   
   139    144     /* If an error occurred in the SQL above, then the transaction will
   140    145     ** rollback which will delete the internal symbol tables.  This will
   141    146     ** cause the structure that pTab points to be deleted.  In case that
   142    147     ** happened, we need to refetch pTab.
   143    148     */
   144         -  pTab = sqliteFindTable(pData->db, argv[0]);
          149  +  pTab = sqliteFindTable(pData->db, argv[0], 0);
   145    150     if( pTab ){
   146    151       assert( sqliteStrICmp(pTab->zName, argv[0])==0 );
   147    152       pTab->pTrigger = pTrig;  /* Re-enable triggers */
   148    153     }
   149    154     return rc!=SQLITE_OK;
   150    155   }
   151    156   
................................................................................
   230    235     azArg[2] = "2";
   231    236     azArg[3] = master_schema;
   232    237     azArg[4] = "0";
   233    238     azArg[5] = 0;
   234    239     initData.db = db;
   235    240     initData.pzErrMsg = pzErrMsg;
   236    241     sqliteInitCallback(&initData, 5, azArg, 0);
   237         -  pTab = sqliteFindTable(db, MASTER_NAME);
          242  +  pTab = sqliteFindTable(db, MASTER_NAME, "main");
   238    243     if( pTab ){
   239    244       pTab->readOnly = 1;
   240    245     }
   241    246     azArg[1] = TEMP_MASTER_NAME;
   242    247     azArg[3] = temp_master_schema;
   243    248     azArg[4] = "1";
   244    249     sqliteInitCallback(&initData, 5, azArg, 0);
   245         -  pTab = sqliteFindTable(db, TEMP_MASTER_NAME);
          250  +  pTab = sqliteFindTable(db, TEMP_MASTER_NAME, "temp");
   246    251     if( pTab ){
   247    252       pTab->readOnly = 1;
   248    253     }
   249    254   
   250    255     /* Create a cursor to hold the database open
   251    256     */
   252    257     if( db->aDb[0].pBt==0 ) return SQLITE_OK;
................................................................................
   343    348   ** An attempt is made to initialize the in-memory data structures that
   344    349   ** hold the database schema.  But if this fails (because the schema file
   345    350   ** is locked) then that step is deferred until the first call to
   346    351   ** sqlite_exec().
   347    352   */
   348    353   sqlite *sqlite_open(const char *zFilename, int mode, char **pzErrMsg){
   349    354     sqlite *db;
   350         -  int rc;
          355  +  int rc, i;
   351    356   
   352    357     /* Allocate the sqlite data structure */
   353    358     db = sqliteMalloc( sizeof(sqlite) );
   354    359     if( pzErrMsg ) *pzErrMsg = 0;
   355    360     if( db==0 ) goto no_mem_on_open;
   356         -  sqliteHashInit(&db->tblHash, SQLITE_HASH_STRING, 0);
   357         -  sqliteHashInit(&db->idxHash, SQLITE_HASH_STRING, 0);
   358         -  sqliteHashInit(&db->trigHash, SQLITE_HASH_STRING, 0);
   359         -  sqliteHashInit(&db->aFunc, SQLITE_HASH_STRING, 1);
   360         -  sqliteHashInit(&db->aFKey, SQLITE_HASH_STRING, 1);
   361    361     db->onError = OE_Default;
   362    362     db->priorNewRowid = 0;
   363    363     db->magic = SQLITE_MAGIC_BUSY;
   364    364     db->nDb = 2;
   365    365     db->aDb = db->aDbStatic;
          366  +  sqliteHashInit(&db->aFunc, SQLITE_HASH_STRING, 1);
          367  +  for(i=0; i<db->nDb; i++){
          368  +    sqliteHashInit(&db->aDb[i].tblHash, SQLITE_HASH_STRING, 0);
          369  +    sqliteHashInit(&db->aDb[i].idxHash, SQLITE_HASH_STRING, 0);
          370  +    sqliteHashInit(&db->aDb[i].trigHash, SQLITE_HASH_STRING, 0);
          371  +    sqliteHashInit(&db->aDb[i].aFKey, SQLITE_HASH_STRING, 1);
          372  +  }
   366    373     
   367    374     /* Open the backend database driver */
   368    375     rc = sqliteBtreeOpen(zFilename, 0, MAX_PAGES, &db->aDb[0].pBt);
   369    376     if( rc!=SQLITE_OK ){
   370    377       switch( rc ){
   371    378         default: {
   372    379           sqliteSetString(pzErrMsg, "unable to open database: ", zFilename, 0);
................................................................................
   482    489       FuncDef *pFunc, *pNext;
   483    490       for(pFunc = (FuncDef*)sqliteHashData(i); pFunc; pFunc=pNext){
   484    491         pNext = pFunc->pNext;
   485    492         sqliteFree(pFunc);
   486    493       }
   487    494     }
   488    495     sqliteHashClear(&db->aFunc);
   489         -  sqliteHashClear(&db->aFKey);
   490    496     sqliteFree(db);
   491    497   }
   492    498   
   493    499   /*
   494    500   ** Return TRUE if the given SQL string ends in a semicolon.
   495    501   **
   496    502   ** Special handling is require for CREATE TRIGGER statements.

Changes to src/parse.y.

    10     10   **
    11     11   *************************************************************************
    12     12   ** This file contains SQLite's grammar for SQL.  Process this file
    13     13   ** using the lemon parser generator to generate C code that runs
    14     14   ** the parser.  Lemon will also generate a header file containing
    15     15   ** numeric codes for all of the tokens.
    16     16   **
    17         -** @(#) $Id: parse.y,v 1.92 2003/03/20 01:16:59 drh Exp $
           17  +** @(#) $Id: parse.y,v 1.93 2003/03/27 12:51:25 drh Exp $
    18     18   */
    19     19   %token_prefix TK_
    20     20   %token_type {Token}
    21     21   %default_type {Token}
    22     22   %extra_argument {Parse *pParse}
    23     23   %syntax_error {
    24     24     if( pParse->zErrMsg==0 ){
................................................................................
    92     92   ///////////////////// The CREATE TABLE statement ////////////////////////////
    93     93   //
    94     94   cmd ::= create_table create_table_args.
    95     95   create_table ::= CREATE(X) temp(T) TABLE nm(Y). {
    96     96      sqliteStartTable(pParse,&X,&Y,T,0);
    97     97   }
    98     98   %type temp {int}
    99         -temp(A) ::= TEMP.  {A = pParse->isTemp || !pParse->initFlag;}
   100         -temp(A) ::= .      {A = pParse->isTemp;}
           99  +temp(A) ::= TEMP.  {A = 1;}
          100  +temp(A) ::= .      {A = 0;}
   101    101   create_table_args ::= LP columnlist conslist_opt RP(X). {
   102    102     sqliteEndTable(pParse,&X,0);
   103    103   }
   104    104   create_table_args ::= AS select(S). {
   105    105     sqliteEndTable(pParse,0,S);
   106    106     sqliteSelectDelete(S);
   107    107   }
................................................................................
   172    172   
   173    173   // In addition to the type name, we also care about the primary key and
   174    174   // UNIQUE constraints.
   175    175   //
   176    176   ccons ::= NULL onconf.
   177    177   ccons ::= NOT NULL onconf(R).               {sqliteAddNotNull(pParse, R);}
   178    178   ccons ::= PRIMARY KEY sortorder onconf(R).  {sqliteAddPrimaryKey(pParse,0,R);}
   179         -ccons ::= UNIQUE onconf(R).            {sqliteCreateIndex(pParse,0,0,0,R,0,0);}
          179  +ccons ::= UNIQUE onconf(R).           {sqliteCreateIndex(pParse,0,0,0,R,0,0,0);}
   180    180   ccons ::= CHECK LP expr RP onconf.
   181    181   ccons ::= REFERENCES nm(T) idxlist_opt(TA) refargs(R).
   182    182                                   {sqliteCreateForeignKey(pParse,0,&T,TA,R);}
   183    183   ccons ::= defer_subclause(D).   {sqliteDeferForeignKey(pParse,D);}
   184    184   ccons ::= COLLATE id(C).  {
   185    185      sqliteAddCollateType(pParse, sqliteCollateType(C.z, C.n));
   186    186   }
................................................................................
   219    219   conslist ::= conslist COMMA tcons.
   220    220   conslist ::= conslist tcons.
   221    221   conslist ::= tcons.
   222    222   tcons ::= CONSTRAINT nm.
   223    223   tcons ::= PRIMARY KEY LP idxlist(X) RP onconf(R).
   224    224                                                {sqliteAddPrimaryKey(pParse,X,R);}
   225    225   tcons ::= UNIQUE LP idxlist(X) RP onconf(R).
   226         -                                       {sqliteCreateIndex(pParse,0,0,X,R,0,0);}
          226  +                                     {sqliteCreateIndex(pParse,0,0,X,R,0,0,0);}
   227    227   tcons ::= CHECK expr onconf.
   228    228   tcons ::= FOREIGN KEY LP idxlist(FA) RP
   229    229             REFERENCES nm(T) idxlist_opt(TA) refargs(R) defer_subclause_opt(D). {
   230    230       sqliteCreateForeignKey(pParse, FA, &T, TA, R);
   231    231       sqliteDeferForeignKey(pParse, D);
   232    232   }
   233    233   %type defer_subclause_opt {int}
................................................................................
   524    524   expr(A) ::= ID(X).               {A = sqliteExpr(TK_ID, 0, 0, &X);}
   525    525   expr(A) ::= JOIN_KW(X).          {A = sqliteExpr(TK_ID, 0, 0, &X);}
   526    526   expr(A) ::= nm(X) DOT nm(Y). {
   527    527     Expr *temp1 = sqliteExpr(TK_ID, 0, 0, &X);
   528    528     Expr *temp2 = sqliteExpr(TK_ID, 0, 0, &Y);
   529    529     A = sqliteExpr(TK_DOT, temp1, temp2, 0);
   530    530   }
          531  +expr(A) ::= nm(X) DOT nm(Y) DOT nm(Z). {
          532  +  Expr *temp1 = sqliteExpr(TK_ID, 0, 0, &X);
          533  +  Expr *temp2 = sqliteExpr(TK_ID, 0, 0, &Y);
          534  +  Expr *temp3 = sqliteExpr(TK_ID, 0, 0, &Z);
          535  +  Expr *temp4 = sqliteExpr(TK_DOT, temp2, temp3, 0);
          536  +  A = sqliteExpr(TK_DOT, temp1, temp4, 0);
          537  +}
   531    538   expr(A) ::= expr(B) ORACLE_OUTER_JOIN. 
   532    539                                {A = B; ExprSetProperty(A,EP_Oracle8Join);}
   533    540   expr(A) ::= INTEGER(X).      {A = sqliteExpr(TK_INTEGER, 0, 0, &X);}
   534    541   expr(A) ::= FLOAT(X).        {A = sqliteExpr(TK_FLOAT, 0, 0, &X);}
   535    542   expr(A) ::= STRING(X).       {A = sqliteExpr(TK_STRING, 0, 0, &X);}
   536    543   expr(A) ::= ID(X) LP exprlist(Y) RP(E). {
   537    544     A = sqliteExprFunction(Y, &X);
................................................................................
   688    695      {A = sqliteExprListAppend(X,Y,0);}
   689    696   exprlist(A) ::= expritem(X).            {A = sqliteExprListAppend(0,X,0);}
   690    697   expritem(A) ::= expr(X).                {A = X;}
   691    698   expritem(A) ::= .                       {A = 0;}
   692    699   
   693    700   ///////////////////////////// The CREATE INDEX command ///////////////////////
   694    701   //
   695         -cmd ::= CREATE(S) uniqueflag(U) INDEX nm(X)
   696         -        ON nm(Y) LP idxlist(Z) RP(E) onconf(R). {
          702  +cmd ::= CREATE(S) temp(T) uniqueflag(U) INDEX nm(X)
          703  +        ON nm(Y) dbnm(D) LP idxlist(Z) RP(E) onconf(R). {
          704  +  SrcList *pSrc = sqliteSrcListAppend(0, &Y, &D);
   697    705     if( U!=OE_None ) U = R;
   698    706     if( U==OE_Default) U = OE_Abort;
   699         -  sqliteCreateIndex(pParse, &X, &Y, Z, U, &S, &E);
          707  +  sqliteCreateIndex(pParse, &X, pSrc, Z, U, T, &S, &E);
   700    708   }
   701    709   
   702    710   %type uniqueflag {int}
   703    711   uniqueflag(A) ::= UNIQUE.  { A = OE_Abort; }
   704    712   uniqueflag(A) ::= .        { A = OE_None; }
   705    713   
   706    714   %type idxlist {IdList*}
................................................................................
   714    722   idxlist(A) ::= idxlist(X) COMMA idxitem(Y).  {A = sqliteIdListAppend(X,&Y);}
   715    723   idxlist(A) ::= idxitem(Y).                   {A = sqliteIdListAppend(0,&Y);}
   716    724   idxitem(A) ::= nm(X).                        {A = X;}
   717    725   
   718    726   ///////////////////////////// The DROP INDEX command /////////////////////////
   719    727   //
   720    728   
   721         -cmd ::= DROP INDEX nm(X).      {sqliteDropIndex(pParse, &X);}
          729  +cmd ::= DROP INDEX nm(X) dbnm(Y).   {
          730  +  sqliteDropIndex(pParse, sqliteSrcListAppend(0,&X,&Y));
          731  +}
   722    732   
   723    733   
   724    734   ///////////////////////////// The COPY command ///////////////////////////////
   725    735   //
   726         -cmd ::= COPY orconf(R) nm(X) FROM nm(Y) USING DELIMITERS STRING(Z).
   727         -    {sqliteCopy(pParse,&X,&Y,&Z,R);}
   728         -cmd ::= COPY orconf(R) nm(X) FROM nm(Y).
   729         -    {sqliteCopy(pParse,&X,&Y,0,R);}
          736  +cmd ::= COPY orconf(R) nm(X) dbnm(D) FROM nm(Y) USING DELIMITERS STRING(Z).
          737  +    {sqliteCopy(pParse,sqliteSrcListAppend(0,&X,&D),&Y,&Z,R);}
          738  +cmd ::= COPY orconf(R) nm(X) dbnm(D) FROM nm(Y).
          739  +    {sqliteCopy(pParse,sqliteSrcListAppend(0,&X,&D),&Y,0,R);}
   730    740   
   731    741   ///////////////////////////// The VACUUM command /////////////////////////////
   732    742   //
   733    743   cmd ::= VACUUM.                {sqliteVacuum(pParse,0);}
   734    744   cmd ::= VACUUM nm(X).         {sqliteVacuum(pParse,&X);}
   735    745   
   736    746   ///////////////////////////// The PRAGMA command /////////////////////////////
................................................................................
   745    755   minus_num(A) ::= MINUS number(X).     {A = X;}
   746    756   number(A) ::= INTEGER(X).  {A = X;}
   747    757   number(A) ::= FLOAT(X).    {A = X;}
   748    758   plus_opt ::= PLUS.
   749    759   plus_opt ::= .
   750    760   
   751    761   //////////////////////////// The CREATE TRIGGER command /////////////////////
   752         -cmd ::= CREATE(A) TRIGGER nm(B) trigger_time(C) trigger_event(D) ON nm(E) 
          762  +cmd ::= CREATE(A) TRIGGER nm(B) trigger_time(C) trigger_event(D) 
          763  +                  ON nm(E) dbnm(DB)
   753    764                     foreach_clause(F) when_clause(G)
   754    765                     BEGIN trigger_cmd_list(S) END(Z). {
          766  +  SrcList *pTab = sqliteSrcListAppend(0, &E, &DB);
   755    767     Token all;
   756    768     all.z = A.z;
   757    769     all.n = (Z.z - A.z) + Z.n;
   758         -  sqliteCreateTrigger(pParse, &B, C, D.a, D.b, &E, F, G, S, &all);
          770  +  sqliteCreateTrigger(pParse, &B, C, D.a, D.b, pTab, F, G, S, &all);
   759    771   }
   760    772   
   761    773   %type trigger_time  {int}
   762    774   trigger_time(A) ::= BEFORE.      { A = TK_BEFORE; }
   763    775   trigger_time(A) ::= AFTER.       { A = TK_AFTER;  }
   764    776   trigger_time(A) ::= INSTEAD OF.  { A = TK_INSTEAD;}
   765    777   trigger_time(A) ::= .            { A = TK_BEFORE; }
................................................................................
   824    836   expr(A) ::= RAISE(X) LP FAIL COMMA nm(Z) RP(Y).  {
   825    837     A = sqliteExpr(TK_RAISE, 0, 0, &Z); 
   826    838     A->iColumn = OE_Fail;
   827    839     sqliteExprSpan(A, &X, &Y);
   828    840   }
   829    841   
   830    842   ////////////////////////  DROP TRIGGER statement //////////////////////////////
   831         -cmd ::= DROP TRIGGER nm(X). {
   832         -    sqliteDropTrigger(pParse,&X,0);
          843  +cmd ::= DROP TRIGGER nm(X) dbnm(D). {
          844  +    sqliteDropTrigger(pParse,sqliteSrcListAppend(0,&X,&D),0);
   833    845   }
   834    846   
   835    847   //////////////////////// ATTACH DATABASE file AS name /////////////////////////
   836    848   cmd ::= ATTACH database_kw_opt ids AS nm.
   837    849   
   838    850   database_kw_opt ::= DATABASE.
   839    851   database_kw_opt ::= .
   840    852   
   841    853   //////////////////////// DETACH DATABASE name /////////////////////////////////
   842    854   cmd ::= DETACH database_kw_opt nm.

Changes to src/select.c.

     8      8   **    May you find forgiveness for yourself and forgive others.
     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12     12   ** This file contains C code routines that are called by the parser
    13     13   ** to handle SELECT statements in SQLite.
    14     14   **
    15         -** $Id: select.c,v 1.127 2003/03/19 03:14:02 drh Exp $
           15  +** $Id: select.c,v 1.128 2003/03/27 12:51:25 drh Exp $
    16     16   */
    17     17   #include "sqliteInt.h"
    18     18   
    19     19   
    20     20   /*
    21     21   ** Allocate a new Select structure and return a pointer to that
    22     22   ** structure.
................................................................................
   908    908         if( pTab==0 ){
   909    909           return 1;
   910    910         }
   911    911         pTab->isTransient = 1;
   912    912       }else{
   913    913         /* An ordinary table or view name in the FROM clause */
   914    914         pTabList->a[i].pTab = pTab = 
   915         -        sqliteFindTable(pParse->db, pTabList->a[i].zName);
          915  +        sqliteFindTable(pParse->db, pTabList->a[i].zName,
          916  +                                    pTabList->a[i].zDatabase);
   916    917         if( pTab==0 ){
   917    918           sqliteSetString(&pParse->zErrMsg, "no such table: ", 
   918    919              pTabList->a[i].zName, 0);
   919    920           pParse->nErr++;
   920    921           return 1;
   921    922         }
   922    923         if( pTab->pSelect ){
................................................................................
  1826   1827     ** the min() or max() is on the INTEGER PRIMARY KEY, then find the first
  1827   1828     ** or last entry in the main table.
  1828   1829     */
  1829   1830     if( !pParse->schemaVerified && (pParse->db->flags & SQLITE_InTrans)==0 ){
  1830   1831       sqliteCodeVerifySchema(pParse);
  1831   1832     }
  1832   1833     base = p->base;
  1833         -  sqliteVdbeAddOp(v, OP_Integer, pTab->isTemp, 0);
         1834  +  sqliteVdbeAddOp(v, OP_Integer, pTab->iDb, 0);
  1834   1835     sqliteVdbeAddOp(v, OP_OpenRead, base, pTab->tnum);
  1835   1836     sqliteVdbeChangeP3(v, -1, pTab->zName, P3_STATIC);
  1836   1837     if( pIdx==0 ){
  1837   1838       sqliteVdbeAddOp(v, seekOp, base, 0);
  1838   1839     }else{
  1839         -    sqliteVdbeAddOp(v, OP_Integer, pTab->isTemp, 0);
         1840  +    sqliteVdbeAddOp(v, OP_Integer, pIdx->iDb, 0);
  1840   1841       sqliteVdbeAddOp(v, OP_OpenRead, base+1, pIdx->tnum);
  1841   1842       sqliteVdbeChangeP3(v, -1, pIdx->zName, P3_STATIC);
  1842   1843       sqliteVdbeAddOp(v, seekOp, base+1, 0);
  1843   1844       sqliteVdbeAddOp(v, OP_IdxRecno, base+1, 0);
  1844   1845       sqliteVdbeAddOp(v, OP_Close, base+1, 0);
  1845   1846       sqliteVdbeAddOp(v, OP_MoveTo, base, 0);
  1846   1847     }

Changes to src/sqliteInt.h.

     7      7   **    May you do good and not evil.
     8      8   **    May you find forgiveness for yourself and forgive others.
     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12     12   ** Internal interface definitions for SQLite.
    13     13   **
    14         -** @(#) $Id: sqliteInt.h,v 1.164 2003/03/20 01:16:59 drh Exp $
           14  +** @(#) $Id: sqliteInt.h,v 1.165 2003/03/27 12:51:25 drh Exp $
    15     15   */
    16     16   #include "config.h"
    17     17   #include "sqlite.h"
    18     18   #include "hash.h"
    19     19   #include "vdbe.h"
    20     20   #include "parse.h"
    21     21   #include "btree.h"
................................................................................
   196    196   ** aDb[1] is the database file used to hold temporary tables.  But
   197    197   ** additional databases may be attached to the engine.
   198    198   */
   199    199   struct Db {
   200    200     char *zName;         /* Name of this database */
   201    201     Btree *pBt;          /* The B*Tree structure for this database file */
   202    202     int schema_cookie;   /* Database schema version number for this file */
          203  +  Hash tblHash;        /* All tables indexed by name */
          204  +  Hash idxHash;        /* All (named) indices indexed by name */
          205  +  Hash trigHash;       /* All triggers indexed by name */
          206  +  Hash aFKey;          /* Foreign keys indexed by to-table */
   203    207     u8 inTrans;          /* True if a transaction is underway for this backend */
          208  +  u16 flags;           /* Flags associated with this database */
   204    209   };
   205    210   
   206    211   /*
   207    212   ** Each database is an instance of the following structure.
   208    213   **
   209    214   ** The sqlite.file_format is initialized by the database file
   210    215   ** and helps determines how the data in the database file is
................................................................................
   227    232     u8 safety_level;              /* How aggressive at synching data to disk */
   228    233     u8 want_to_close;             /* Close after all VDBEs are deallocated */
   229    234     int next_cookie;              /* Next value of aDb[0].schema_cookie */
   230    235     int cache_size;               /* Number of pages to use in the cache */
   231    236     int nTable;                   /* Number of tables in the database */
   232    237     void *pBusyArg;               /* 1st Argument to the busy callback */
   233    238     int (*xBusyCallback)(void *,const char*,int);  /* The busy callback */
   234         -  Hash tblHash;                 /* All tables indexed by name */
   235         -  Hash idxHash;                 /* All (named) indices indexed by name */
   236         -  Hash trigHash;                /* All triggers indexed by name */
   237    239     Hash aFunc;                   /* All functions that can be in SQL exprs */
   238         -  Hash aFKey;                   /* Foreign keys indexed by to-table */
   239    240     int lastRowid;                /* ROWID of most recent insert */
   240    241     int priorNewRowid;            /* Last randomly generated ROWID */
   241    242     int onError;                  /* Default conflict algorithm */
   242    243     int magic;                    /* Magic number for detect library misuse */
   243    244     int nChange;                  /* Number of rows changed */
   244    245     struct Vdbe *pVdbe;           /* List of active virtual machines */
   245    246   #ifndef SQLITE_OMIT_TRACE
................................................................................
   325    326   #define SQLITE_SO_DESC      1  /* Sort in descending order */
   326    327   #define SQLITE_SO_DIRMASK   1  /* Mask to extract the sort direction */
   327    328   
   328    329   /*
   329    330   ** Each SQL table is represented in memory by an instance of the
   330    331   ** following structure.
   331    332   **
   332         -** Expr.zName is the name of the table.  The case of the original
          333  +** Table.zName is the name of the table.  The case of the original
   333    334   ** CREATE TABLE statement is stored, but case is not significant for
   334    335   ** comparisons.
   335    336   **
   336         -** Expr.nCol is the number of columns in this table.  Expr.aCol is a
          337  +** Table.nCol is the number of columns in this table.  Table.aCol is a
   337    338   ** pointer to an array of Column structures, one for each column.
   338    339   **
   339         -** If the table has an INTEGER PRIMARY KEY, then Expr.iPKey is the index of
   340         -** the column that is that key.   Otherwise Expr.iPKey is negative.  Note
          340  +** If the table has an INTEGER PRIMARY KEY, then Table.iPKey is the index of
          341  +** the column that is that key.   Otherwise Table.iPKey is negative.  Note
   341    342   ** that the datatype of the PRIMARY KEY must be INTEGER for this field to
   342    343   ** be set.  An INTEGER PRIMARY KEY is used as the rowid for each row of
   343    344   ** the table.  If a table has no INTEGER PRIMARY KEY, then a random rowid
   344         -** is generated for each row of the table.  Expr.hasPrimKey is true if
          345  +** is generated for each row of the table.  Table.hasPrimKey is true if
   345    346   ** the table has any PRIMARY KEY, INTEGER or otherwise.
   346    347   **
   347         -** Expr.tnum is the page number for the root BTree page of the table in the
   348         -** database file.  If Expr.isTemp is true, then this page occurs in the
   349         -** auxiliary database file, not the main database file.  If Expr.isTransient
          348  +** Table.tnum is the page number for the root BTree page of the table in the
          349  +** database file.  If Table.iDb is the index of the database table backend
          350  +** in sqlite.aDb[].  0 is for the main database and 1 is for the file that
          351  +** holds temporary tables and indices.  If Table.isTransient
   350    352   ** is true, then the table is stored in a file that is automatically deleted
   351         -** when the VDBE cursor to the table is closed.  In this case Expr.tnum 
          353  +** when the VDBE cursor to the table is closed.  In this case Table.tnum 
   352    354   ** refers VDBE cursor number that holds the table open, not to the root
   353    355   ** page number.  Transient tables are used to hold the results of a
   354    356   ** sub-query that appears instead of a real table name in the FROM clause 
   355    357   ** of a SELECT statement.
   356    358   */
   357    359   struct Table {
   358    360     char *zName;     /* Name of the table */
................................................................................
   359    361     int nCol;        /* Number of columns in this table */
   360    362     Column *aCol;    /* Information about each column */
   361    363     int iPKey;       /* If not less then 0, use aCol[iPKey] as the primary key */
   362    364     Index *pIndex;   /* List of SQL indexes on this table. */
   363    365     int tnum;        /* Root BTree node for this table (see note above) */
   364    366     Select *pSelect; /* NULL for tables.  Points to definition if a view. */
   365    367     u8 readOnly;     /* True if this table should not be written by the user */
   366         -  u8 isTemp;       /* Index into sqlite.aDb[] of the backend for this table */
          368  +  u8 iDb;          /* Index into sqlite.aDb[] of the backend for this table */
   367    369     u8 isTransient;  /* True if automatically deleted when VDBE finishes */
   368    370     u8 hasPrimKey;   /* True if there exists a primary key */
   369    371     u8 keyConf;      /* What to do in case of uniqueness conflict on iPKey */
   370    372     Trigger *pTrigger; /* List of SQL triggers on this table */
   371    373     FKey *pFKey;       /* Linked list of all foreign keys in this table */
   372    374   };
   373    375   
................................................................................
   475    477     int nColumn;     /* Number of columns in the table used by this index */
   476    478     int *aiColumn;   /* Which columns are used by this index.  1st is 0 */
   477    479     Table *pTable;   /* The SQL table being indexed */
   478    480     int tnum;        /* Page containing root of this index in database file */
   479    481     u8 isUnique;     /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */
   480    482     u8 onError;      /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */
   481    483     u8 autoIndex;    /* True if is automatically created (ex: by UNIQUE) */
          484  +  u8 iDb;          /* Index in sqlite.aDb[] of where this index is stored */
   482    485     Index *pNext;    /* The next index associated with the same table */
   483    486   };
   484    487   
   485    488   /*
   486    489   ** Each token coming out of the lexer is an instance of
   487    490   ** this structure.  Tokens are also used as part of an expression.
   488    491   */
................................................................................
   600    603     } *a;
   601    604   };
   602    605   
   603    606   /*
   604    607   ** The following structure describes the FROM clause of a SELECT statement.
   605    608   ** Each table or subquery in the FROM clause is a separate element of
   606    609   ** the SrcList.a[] array.
          610  +**
          611  +** With the addition of multiple database support, the following structure
          612  +** can also be used to describe a particular table such as the table that
          613  +** is modified by an INSERT, DELETE, or UPDATE statement.  In standard SQL,
          614  +** such a table must be a simple name: ID.  But in SQLite, the table can
          615  +** now be identified by a database name, a dot, then the table name: ID.ID.
   607    616   */
   608    617   struct SrcList {
   609    618     int nSrc;        /* Number of tables or subqueries in the FROM clause */
   610    619     struct SrcList_item {
   611    620       char *zDatabase;  /* Name of database holding this table */
   612    621       char *zName;      /* Name of the table */
   613    622       char *zAlias;     /* The "B" part of a "A AS B" phrase.  zName is the "A" */
................................................................................
   761    770     u8 explain;          /* True if the EXPLAIN flag is found on the query */
   762    771     u8 initFlag;         /* True if reparsing CREATE TABLEs */
   763    772     u8 nameClash;        /* A permanent table name clashes with temp table name */
   764    773     u8 useAgg;           /* If true, extract field values from the aggregator
   765    774                          ** while generating expressions.  Normally false */
   766    775     u8 schemaVerified;   /* True if an OP_VerifySchema has been coded someplace
   767    776                          ** other than after an OP_Transaction */
   768         -  u8 isTemp;           /* True if parsing temporary tables */
          777  +  u8 iDb;              /* Index of database whose schema is being parsed */
   769    778     u8 useCallback;      /* True if callbacks should be used to report results */
   770    779     int newTnum;         /* Table number to use when reparsing CREATE TABLEs */
   771    780     int nErr;            /* Number of errors seen */
   772    781     int nTab;            /* Number of previously allocated VDBE cursors */
   773    782     int nMem;            /* Number of memory cells used so far */
   774    783     int nSet;            /* Number of sets used so far */
   775    784     int nAgg;            /* Number of aggregate expressions */
................................................................................
   803    812    * If the transaction is rolled back, the trigger is re-added into the trigHash
   804    813    * hash table (and hence the database schema). If the transaction is commited,
   805    814    * then the Trigger structure is deleted permanently.
   806    815    */
   807    816   struct Trigger {
   808    817     char *name;             /* The name of the trigger                        */
   809    818     char *table;            /* The table or view to which the trigger applies */
          819  +  int iDb;                /* Database containing this trigger               */
   810    820     int op;                 /* One of TK_DELETE, TK_UPDATE, TK_INSERT         */
   811    821     int tr_tm;              /* One of TK_BEFORE, TK_AFTER */
   812    822     Expr *pWhen;            /* The WHEN clause of the expresion (may be NULL) */
   813    823     IdList *pColumns;       /* If this is an UPDATE OF <column-list> trigger,
   814    824                                the <column-list> is stored here */
   815    825     int foreach;            /* One of TK_ROW or TK_STATEMENT */
   816    826   
................................................................................
   969    979   void sqliteAddColumnType(Parse*,Token*,Token*);
   970    980   void sqliteAddDefaultValue(Parse*,Token*,int);
   971    981   int sqliteCollateType(const char*, int);
   972    982   void sqliteAddCollateType(Parse*, int);
   973    983   void sqliteEndTable(Parse*,Token*,Select*);
   974    984   void sqliteCreateView(Parse*,Token*,Token*,Select*,int);
   975    985   int sqliteViewGetColumnNames(Parse*,Table*);
   976         -void sqliteViewResetAll(sqlite*);
   977    986   void sqliteDropTable(Parse*, Token*, int);
   978    987   void sqliteDeleteTable(sqlite*, Table*);
   979    988   void sqliteInsert(Parse*, SrcList*, ExprList*, Select*, IdList*, int);
   980    989   IdList *sqliteIdListAppend(IdList*, Token*);
   981    990   int sqliteIdListIndex(IdList*,const char*);
   982    991   SrcList *sqliteSrcListAppend(SrcList*, Token*, Token*);
   983    992   void sqliteSrcListAddAlias(SrcList*, Token*);
   984    993   void sqliteIdListDelete(IdList*);
   985    994   void sqliteSrcListDelete(SrcList*);
   986         -void sqliteCreateIndex(Parse*, Token*, Token*, IdList*, int, Token*, Token*);
   987         -void sqliteDropIndex(Parse*, Token*);
          995  +void sqliteCreateIndex(Parse*,Token*,SrcList*,IdList*,int,int,Token*,Token*);
          996  +void sqliteDropIndex(Parse*, SrcList*);
   988    997   void sqliteAddKeyType(Vdbe*, ExprList*);
   989    998   void sqliteAddIdxKeyType(Vdbe*, Index*);
   990    999   int sqliteSelect(Parse*, Select*, int, int, Select*, int, int*);
   991   1000   Select *sqliteSelectNew(ExprList*,SrcList*,Expr*,ExprList*,Expr*,ExprList*,
   992   1001                           int,int,int);
   993   1002   void sqliteSelectDelete(Select*);
   994   1003   void sqliteSelectUnbind(Select*);
   995         -Table *sqliteTableNameToTable(Parse*, const char*);
         1004  +Table *sqliteTableNameToTable(Parse*, const char*, const char*);
   996   1005   void sqliteDeleteFrom(Parse*, SrcList*, Expr*);
   997   1006   void sqliteUpdate(Parse*, SrcList*, ExprList*, Expr*, int);
   998   1007   WhereInfo *sqliteWhereBegin(Parse*, int, SrcList*, Expr*, int, ExprList**);
   999   1008   void sqliteWhereEnd(WhereInfo*);
  1000   1009   void sqliteExprCode(Parse*, Expr*);
  1001   1010   void sqliteExprIfTrue(Parse*, Expr*, int, int);
  1002   1011   void sqliteExprIfFalse(Parse*, Expr*, int, int);
  1003         -Table *sqliteFindTable(sqlite*,const char*);
  1004         -Index *sqliteFindIndex(sqlite*,const char*);
         1012  +Table *sqliteFindTable(sqlite*,const char*, const char*);
         1013  +Index *sqliteFindIndex(sqlite*,const char*, const char*);
  1005   1014   void sqliteUnlinkAndDeleteIndex(sqlite*,Index*);
  1006         -void sqliteCopy(Parse*, Token*, Token*, Token*, int);
         1015  +void sqliteCopy(Parse*, SrcList*, Token*, Token*, int);
  1007   1016   void sqliteVacuum(Parse*, Token*);
  1008   1017   int sqliteGlobCompare(const unsigned char*,const unsigned char*);
  1009   1018   int sqliteLikeCompare(const unsigned char*,const unsigned char*);
  1010   1019   char *sqliteTableNameFromToken(Token*);
  1011   1020   int sqliteExprCheck(Parse*, Expr*, int, int*);
  1012   1021   int sqliteExprType(Expr*);
  1013   1022   int sqliteExprCompare(Expr*, Expr*);
................................................................................
  1039   1048   Select *sqliteSelectDup(Select*);
  1040   1049   FuncDef *sqliteFindFunction(sqlite*,const char*,int,int,int);
  1041   1050   void sqliteRegisterBuiltinFunctions(sqlite*);
  1042   1051   int sqliteSafetyOn(sqlite*);
  1043   1052   int sqliteSafetyOff(sqlite*);
  1044   1053   int sqliteSafetyCheck(sqlite*);
  1045   1054   void sqliteChangeCookie(sqlite*, Vdbe*);
  1046         -void sqliteCreateTrigger(Parse*, Token*, int, int, IdList*, Token*, 
         1055  +void sqliteCreateTrigger(Parse*, Token*, int, int, IdList*, SrcList*, 
  1047   1056                            int, Expr*, TriggerStep*, Token*);
  1048         -void sqliteDropTrigger(Parse*, Token*, int);
         1057  +void sqliteDropTrigger(Parse*, SrcList*, int);
  1049   1058   int sqliteTriggersExist(Parse* , Trigger* , int , int , int, ExprList*);
  1050   1059   int sqliteCodeRowTrigger(Parse*, int, ExprList*, int, Table *, int, int, 
  1051   1060                            int, int);
  1052   1061   void sqliteViewTriggers(Parse*, Table*, Expr*, int, ExprList*);
  1053   1062   TriggerStep *sqliteTriggerSelectStep(Select*);
  1054   1063   TriggerStep *sqliteTriggerInsertStep(Token*, IdList*, ExprList*, Select*, int);
  1055   1064   TriggerStep *sqliteTriggerUpdateStep(Token*, ExprList*, Expr*, int);

Changes to src/trigger.c.

    37     37   */
    38     38   void sqliteCreateTrigger(
    39     39     Parse *pParse,      /* The parse context of the CREATE TRIGGER statement */
    40     40     Token *pName,       /* The name of the trigger */
    41     41     int tr_tm,          /* One of TK_BEFORE, TK_AFTER , TK_INSTEAD */
    42     42     int op,             /* One of TK_INSERT, TK_UPDATE, TK_DELETE */
    43     43     IdList *pColumns,   /* column list if this is an UPDATE OF trigger */
    44         -  Token *pTableName,  /* The name of the table/view the trigger applies to */
           44  +  SrcList *pTableName,/* The name of the table/view the trigger applies to */
    45     45     int foreach,        /* One of TK_ROW or TK_STATEMENT */
    46     46     Expr *pWhen,        /* WHEN clause */
    47     47     TriggerStep *pStepList, /* The triggered program */
    48     48     Token *pAll             /* Token that describes the complete CREATE TRIGGER */
    49     49   ){
    50     50     Trigger *nt;
    51     51     Table   *tab;
    52     52     char *zName = 0;    /* Name of the trigger */
           53  +  sqlite *db = pParse->db;
    53     54   
    54     55     /* Check that: 
    55     56     ** 1. the trigger name does not already exist.
    56     57     ** 2. the table (or view) does exist.
    57     58     ** 3. that we are not trying to create a trigger on the sqlite_master table
    58     59     ** 4. That we are not trying to create an INSTEAD OF trigger on a table.
    59     60     ** 5. That we are not trying to create a BEFORE or AFTER trigger on a view.
    60     61     */
           62  +  if( sqlite_malloc_failed ) goto trigger_cleanup;
           63  +  assert( pTableName->nSrc==1 );
           64  +  tab = sqliteTableNameToTable(pParse, pTableName->a[0].zName,
           65  +                                pTableName->a[0].zDatabase);
           66  +  if( !tab ){
           67  +    goto trigger_cleanup;
           68  +  }
           69  +  if( tab->iDb>=2 ){
           70  +    sqliteSetString(&pParse->zErrMsg, "triggers may not be added to "
           71  +       "auxiliary database \"", db->aDb[tab->iDb].zName, "\"", 0);
           72  +    pParse->nErr++;
           73  +    goto trigger_cleanup;
           74  +  }
           75  +
    61     76     zName = sqliteStrNDup(pName->z, pName->n);
    62         -  if( sqliteHashFind(&(pParse->db->trigHash), zName, pName->n + 1) ){
           77  +  if( sqliteHashFind(&(db->aDb[tab->iDb].trigHash), zName,pName->n+1) ){
    63     78       sqliteSetNString(&pParse->zErrMsg, "trigger ", -1,
    64     79           pName->z, pName->n, " already exists", -1, 0);
    65     80       pParse->nErr++;
    66     81       goto trigger_cleanup;
    67     82     }
           83  +  if( sqliteStrNICmp(tab->zName, "sqlite_", 7)==0 ){
           84  +    sqliteSetString(&pParse->zErrMsg,"cannot create trigger on system table",0);
           85  +    pParse->nErr++;
           86  +    goto trigger_cleanup;
           87  +  }
           88  +  if( tab->pSelect && tr_tm != TK_INSTEAD ){
           89  +    sqliteSetNString(&pParse->zErrMsg, "cannot create ", 
           90  +        (tr_tm == TK_BEFORE)?"BEFORE":"AFTER", " trigger on view: ",
           91  +        pTableName->a[0].zName, 0);
           92  +    goto trigger_cleanup;
           93  +  }
           94  +  if( !tab->pSelect && tr_tm == TK_INSTEAD ){
           95  +    sqliteSetNString(&pParse->zErrMsg, "cannot create INSTEAD OF", 
           96  +        " trigger on table: ", pTableName->a[0].zName);
           97  +    goto trigger_cleanup;
           98  +  }
           99  +#ifndef SQLITE_OMIT_AUTHORIZATION
    68    100     {
    69         -    char *tmp_str = sqliteStrNDup(pTableName->z, pTableName->n);
    70         -    if( tmp_str==0 ) goto trigger_cleanup;
    71         -    tab = sqliteFindTable(pParse->db, tmp_str);
    72         -    sqliteFree(tmp_str);
    73         -    if( !tab ){
    74         -      sqliteSetNString(&pParse->zErrMsg, "no such table: ", -1,
    75         -          pTableName->z, pTableName->n, 0);
    76         -      pParse->nErr++;
          101  +    int code = SQLITE_CREATE_TRIGGER;
          102  +    if( tab->iDb==1 ) code = SQLITE_CREATE_TEMP_TRIGGER;
          103  +    if( sqliteAuthCheck(pParse, code, zName, tab->zName) ){
    77    104         goto trigger_cleanup;
    78    105       }
    79         -    if( sqliteStrICmp(tab->zName, MASTER_NAME)==0 ){
    80         -      sqliteSetString(&pParse->zErrMsg, "cannot create trigger on system "
    81         -         "table: " MASTER_NAME, 0);
    82         -      pParse->nErr++;
    83         -      goto trigger_cleanup;
    84         -    }
    85         -    if( sqliteStrICmp(tab->zName, TEMP_MASTER_NAME)==0 ){
    86         -      sqliteSetString(&pParse->zErrMsg, "cannot create trigger on system "
    87         -         "table: " TEMP_MASTER_NAME, 0);
    88         -      pParse->nErr++;
          106  +    if( sqliteAuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(tab->iDb), 0)){
    89    107         goto trigger_cleanup;
    90    108       }
    91         -    if( tab->pSelect && tr_tm != TK_INSTEAD ){
    92         -      sqliteSetNString(&pParse->zErrMsg, "cannot create ", -1,
    93         -	  (tr_tm == TK_BEFORE)?"BEFORE":"AFTER", -1, " trigger on view: ", -1
    94         -          , pTableName->z, pTableName->n, 0);
    95         -      goto trigger_cleanup;
    96         -    }
    97         -    if( !tab->pSelect && tr_tm == TK_INSTEAD ){
    98         -      sqliteSetNString(&pParse->zErrMsg, "cannot create INSTEAD OF", -1, 
    99         -	  " trigger on table: ", -1, pTableName->z, pTableName->n, 0);
   100         -      goto trigger_cleanup;
   101         -    }
   102         -#ifndef SQLITE_OMIT_AUTHORIZATION
   103         -    {
   104         -      int code = SQLITE_CREATE_TRIGGER;
   105         -      if( tab->isTemp ) code = SQLITE_CREATE_TEMP_TRIGGER;
   106         -      if( sqliteAuthCheck(pParse, code, zName, tab->zName) ){
   107         -        goto trigger_cleanup;
   108         -      }
   109         -      if( sqliteAuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(tab->isTemp), 0)){
   110         -        goto trigger_cleanup;
   111         -      }
   112         -    }
          109  +  }
   113    110   #endif
   114         -  }
   115    111   
   116    112     if (tr_tm == TK_INSTEAD){
   117    113       tr_tm = TK_BEFORE;
   118    114     }
   119    115   
   120    116     /* Build the Trigger object */
   121    117     nt = (Trigger*)sqliteMalloc(sizeof(Trigger));
   122    118     if( nt==0 ) goto trigger_cleanup;
   123    119     nt->name = zName;
   124    120     zName = 0;
   125         -  nt->table = sqliteStrNDup(pTableName->z, pTableName->n);
          121  +  nt->table = sqliteStrDup(pTableName->a[0].zName);
   126    122     if( sqlite_malloc_failed ) goto trigger_cleanup;
          123  +  nt->iDb = tab->iDb;
   127    124     nt->op = op;
   128    125     nt->tr_tm = tr_tm;
   129    126     nt->pWhen = sqliteExprDup(pWhen);
   130    127     sqliteExprDelete(pWhen);
   131    128     nt->pColumns = sqliteIdListDup(pColumns);
   132    129     sqliteIdListDelete(pColumns);
   133    130     nt->foreach = foreach;
................................................................................
   150    147       int addr;
   151    148       Vdbe *v;
   152    149   
   153    150       /* Make an entry in the sqlite_master table */
   154    151       v = sqliteGetVdbe(pParse);
   155    152       if( v==0 ) goto trigger_cleanup;
   156    153       sqliteBeginWriteOperation(pParse, 0, 0);
   157         -    sqliteOpenMasterTable(v, tab->isTemp);
          154  +    sqliteOpenMasterTable(v, tab->iDb);
   158    155       addr = sqliteVdbeAddOpList(v, ArraySize(insertTrig), insertTrig);
   159         -    sqliteVdbeChangeP3(v, addr, tab->isTemp ? TEMP_MASTER_NAME : MASTER_NAME,
          156  +    sqliteVdbeChangeP3(v, addr, tab->iDb ? TEMP_MASTER_NAME : MASTER_NAME,
   160    157                          P3_STATIC);
   161    158       sqliteVdbeChangeP3(v, addr+2, nt->name, 0); 
   162    159       sqliteVdbeChangeP3(v, addr+3, nt->table, 0); 
   163    160       sqliteVdbeChangeP3(v, addr+5, pAll->z, pAll->n);
   164         -    if( !tab->isTemp ){
   165         -      sqliteChangeCookie(pParse->db, v);
          161  +    if( tab->iDb==0 ){
          162  +      sqliteChangeCookie(db, v);
   166    163       }
   167    164       sqliteVdbeAddOp(v, OP_Close, 0, 0);
   168    165       sqliteEndWriteOperation(pParse);
   169    166     }
   170    167   
   171    168     if( !pParse->explain ){
   172    169       /* Stick it in the hash-table */
   173         -    sqliteHashInsert(&(pParse->db->trigHash), nt->name, pName->n + 1, nt);
          170  +    sqliteHashInsert(&(db->aDb[nt->iDb].trigHash), nt->name, pName->n + 1, nt);
   174    171   
   175    172       /* Attach it to the table object */
   176    173       nt->pNext = tab->pTrigger;
   177    174       tab->pTrigger = nt;
   178    175       return;
   179    176     }else{
   180    177       sqliteFree(nt->name);
................................................................................
   181    178       sqliteFree(nt->table);
   182    179       sqliteFree(nt);
   183    180     }
   184    181   
   185    182   trigger_cleanup:
   186    183   
   187    184     sqliteFree(zName);
          185  +  sqliteSrcListDelete(pTableName);
   188    186     sqliteIdListDelete(pColumns);
   189    187     sqliteExprDelete(pWhen);
   190    188     sqliteDeleteTriggerStep(pStepList);
   191    189   }
   192    190   
   193    191   /*
   194    192   ** Make a copy of all components of the given trigger step.  This has
................................................................................
   338    336    * sqliteDropTable(). In the latter case the "nested" argument is true.
   339    337    *
   340    338    * Note that this function does not delete the trigger entirely. Instead it
   341    339    * removes it from the internal schema and places it in the trigDrop hash 
   342    340    * table. This is so that the trigger can be restored into the database schema
   343    341    * if the transaction is rolled back.
   344    342    */
   345         -void sqliteDropTrigger(Parse *pParse, Token *pName, int nested){
   346         -  char *zName;
          343  +void sqliteDropTrigger(Parse *pParse, SrcList *pName, int nested){
   347    344     Trigger *pTrigger;
   348    345     Table   *pTable;
   349    346     Vdbe *v;
          347  +  int i;
          348  +  const char *zDb;
          349  +  const char *zName;
          350  +  int nName;
          351  +  sqlite *db = pParse->db;
   350    352   
   351         -  zName = sqliteStrNDup(pName->z, pName->n);
   352         -
   353         -  /* ensure that the trigger being dropped exists */
   354         -  pTrigger = sqliteHashFind(&(pParse->db->trigHash), zName, pName->n + 1); 
          353  +  if( sqlite_malloc_failed ) goto drop_trigger_cleanup;
          354  +  assert( pName->nSrc==1 );
          355  +  zDb = pName->a[0].zDatabase;
          356  +  zName = pName->a[0].zName;
          357  +  nName = strlen(zName);
          358  +  for(i=0; i<db->nDb; i++){
          359  +    if( zDb && sqliteStrICmp(db->aDb[i].zName, zDb) ) continue;
          360  +    pTrigger = sqliteHashFind(&(db->aDb[i].trigHash), zName, nName+1);
          361  +    if( pTrigger ) break;
          362  +  }
   355    363     if( !pTrigger ){
   356         -    sqliteSetNString(&pParse->zErrMsg, "no such trigger: ", -1,
   357         -        zName, -1, 0);
   358         -    sqliteFree(zName);
   359         -    return;
          364  +    sqliteSetString(&pParse->zErrMsg, "no such trigger: ", zName, 0);
          365  +    goto drop_trigger_cleanup;
   360    366     }
   361         -  pTable = sqliteFindTable(pParse->db, pTrigger->table);
          367  +  assert( pTrigger->iDb>=0 && pTrigger->iDb<db->nDb );
          368  +  if( pTrigger->iDb>=2 ){
          369  +    sqliteSetString(&pParse->zErrMsg, "triggers may not be removed from "
          370  +       "auxiliary database \"", db->aDb[pTrigger->iDb].zName, "\"", 0);
          371  +    pParse->nErr++;
          372  +    goto drop_trigger_cleanup;
          373  +  }
          374  +  pTable = sqliteFindTable(db, pTrigger->table, db->aDb[pTrigger->iDb].zName);
   362    375     assert(pTable);
          376  +  assert( pTable->iDb==pTrigger->iDb );
   363    377   #ifndef SQLITE_OMIT_AUTHORIZATION
   364    378     {
   365    379       int code = SQLITE_DROP_TRIGGER;
   366         -    if( pTable->isTemp ) code = SQLITE_DROP_TEMP_TRIGGER;
          380  +    if( pTable->iDb ) code = SQLITE_DROP_TEMP_TRIGGER;
   367    381       if( sqliteAuthCheck(pParse, code, pTrigger->name, pTable->zName) ||
   368         -      sqliteAuthCheck(pParse, SQLITE_DELETE, SCHEMA_TABLE(pTable->isTemp),0) ){
   369         -      sqliteFree(zName);
          382  +      sqliteAuthCheck(pParse, SQLITE_DELETE, SCHEMA_TABLE(pTable->iDb),0) ){
   370    383         return;
   371    384       }
   372    385     }
   373    386   #endif
   374    387   
   375    388     /*
   376    389      * If this is not an "explain", then delete the trigger structure.
................................................................................
   385    398             cc->pNext = cc->pNext->pNext;
   386    399             break;
   387    400           }
   388    401           cc = cc->pNext;
   389    402         }
   390    403         assert(cc);
   391    404       }
   392         -    sqliteHashInsert(&(pParse->db->trigHash), zName, pName->n + 1, NULL);
          405  +    sqliteHashInsert(&(db->aDb[pTrigger->iDb].trigHash), zName, nName+1, 0);
   393    406       sqliteDeleteTrigger(pTrigger);
   394    407     }
   395    408   
   396    409     /* Generate code to destroy the database record of the trigger.
   397    410     */
   398    411     if( pTable!=0 && !nested && (v = sqliteGetVdbe(pParse))!=0 ){
   399    412       int base;
................................................................................
   405    418         { OP_Column,     0, 1,        0},
   406    419         { OP_Ne,         0, ADDR(7),  0},
   407    420         { OP_Delete,     0, 0,        0},
   408    421         { OP_Next,       0, ADDR(3),  0}, /* 7 */
   409    422       };
   410    423   
   411    424       sqliteBeginWriteOperation(pParse, 0, 0);
   412         -    sqliteOpenMasterTable(v, pTable->isTemp);
          425  +    sqliteOpenMasterTable(v, pTable->iDb);
   413    426       base = sqliteVdbeAddOpList(v,  ArraySize(dropTrigger), dropTrigger);
   414    427       sqliteVdbeChangeP3(v, base+1, zName, 0);
   415         -    if( !pTable->isTemp ){
   416         -      sqliteChangeCookie(pParse->db, v);
          428  +    if( pTable->iDb==0 ){
          429  +      sqliteChangeCookie(db, v);
   417    430       }
   418    431       sqliteVdbeAddOp(v, OP_Close, 0, 0);
   419    432       sqliteEndWriteOperation(pParse);
   420    433     }
   421    434   
   422         -  sqliteFree(zName);
          435  +drop_trigger_cleanup:
          436  +  sqliteSrcListDelete(pName);
   423    437   }
   424    438   
   425    439   /*
   426    440   ** pEList is the SET clause of an UPDATE statement.  Each entry
   427    441   ** in pEList is of the format <id>=<expr>.  If any of the entries
   428    442   ** in pEList have an <id> which matches an identifier in pIdList,
   429    443   ** then return TRUE.  If pIdList==NULL, then it is considered a

Changes to src/update.c.

     8      8   **    May you find forgiveness for yourself and forgive others.
     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12     12   ** This file contains C code routines that are called by the parser
    13     13   ** to handle UPDATE statements.
    14     14   **
    15         -** $Id: update.c,v 1.55 2003/03/20 01:16:59 drh Exp $
           15  +** $Id: update.c,v 1.56 2003/03/27 12:51:25 drh Exp $
    16     16   */
    17     17   #include "sqliteInt.h"
    18     18   
    19     19   /*
    20     20   ** Process an UPDATE statement.
    21     21   */
    22     22   void sqliteUpdate(
................................................................................
    24     24     SrcList *pTabList,     /* The table in which we should change things */
    25     25     ExprList *pChanges,    /* Things to be changed */
    26     26     Expr *pWhere,          /* The WHERE clause.  May be null */
    27     27     int onError            /* How to handle constraint errors */
    28     28   ){
    29     29     int i, j;              /* Loop counters */
    30     30     char *zTab;            /* Name of the table to be updated */
           31  +  char *zDb;             /* Name of the database holding zTab */
    31     32     Table *pTab;           /* The table to be updated */
    32     33     int addr;              /* VDBE instruction address of the start of the loop */
    33     34     WhereInfo *pWInfo;     /* Information about the WHERE clause */
    34     35     Vdbe *v;               /* The virtual database engine */
    35     36     Index *pIdx;           /* For looping over indices */
    36     37     int nIdx;              /* Number of indices that need updating */
    37     38     int nIdxTotal;         /* Total number of indices */
................................................................................
    55     56     db = pParse->db;
    56     57     assert( pTabList->nSrc==1 );
    57     58   
    58     59     /* Check for the special case of a VIEW with one or more ON UPDATE triggers 
    59     60      * defined 
    60     61      */
    61     62     zTab = pTabList->a[0].zName;
           63  +  zDb = pTabList->a[0].zDatabase;
    62     64     if( zTab != 0 ){
    63         -    pTab = sqliteFindTable(pParse->db, zTab);
           65  +    pTab = sqliteFindTable(pParse->db, zTab, zDb);
    64     66       if( pTab ){
    65     67         row_triggers_exist = 
    66     68           sqliteTriggersExist(pParse, pTab->pTrigger, 
    67     69               TK_UPDATE, TK_BEFORE, TK_ROW, pChanges) ||
    68     70           sqliteTriggersExist(pParse, pTab->pTrigger, 
    69     71               TK_UPDATE, TK_AFTER, TK_ROW, pChanges);
    70     72       }
................................................................................
    78     80     }
    79     81   
    80     82     /* Locate the table which we want to update.  This table has to be
    81     83     ** put in an SrcList structure because some of the subroutines we
    82     84     ** will be calling are designed to work with multiple tables and expect
    83     85     ** an SrcList* parameter instead of just a Table* parameter.
    84     86     */
    85         -  pTab = pTabList->a[0].pTab = sqliteTableNameToTable(pParse, zTab);
           87  +  pTab = pTabList->a[0].pTab = sqliteTableNameToTable(pParse, zTab, zDb);
    86     88     if( pTab==0 ) goto update_cleanup;
    87     89     assert( pTab->pSelect==0 );  /* This table is not a VIEW */
    88     90     aXRef = sqliteMalloc( sizeof(int) * pTab->nCol );
    89     91     if( aXRef==0 ) goto update_cleanup;
    90     92     for(i=0; i<pTab->nCol; i++) aXRef[i] = -1;
    91     93   
    92     94     /* If there are FOR EACH ROW triggers, allocate temp tables */
................................................................................
   193    195       }
   194    196     }
   195    197   
   196    198     /* Begin generating code.
   197    199     */
   198    200     v = sqliteGetVdbe(pParse);
   199    201     if( v==0 ) goto update_cleanup;
   200         -  sqliteBeginWriteOperation(pParse, 1, !row_triggers_exist && pTab->isTemp);
          202  +  sqliteBeginWriteOperation(pParse, 1, !row_triggers_exist && pTab->iDb==1);
   201    203   
   202    204     /* Begin the database scan
   203    205     */
   204    206     pWInfo = sqliteWhereBegin(pParse, base, pTabList, pWhere, 1, 0);
   205    207     if( pWInfo==0 ) goto update_cleanup;
   206    208   
   207    209     /* Remember the index of every item to be updated.
................................................................................
   225    227       sqliteVdbeAddOp(v, OP_OpenTemp, newIdx, 0);
   226    228   
   227    229       sqliteVdbeAddOp(v, OP_ListRewind, 0, 0);
   228    230       addr = sqliteVdbeAddOp(v, OP_ListRead, 0, 0);
   229    231       sqliteVdbeAddOp(v, OP_Dup, 0, 0);
   230    232   
   231    233       sqliteVdbeAddOp(v, OP_Dup, 0, 0);
   232         -    sqliteVdbeAddOp(v, OP_Integer, pTab->isTemp, 0);
          234  +    sqliteVdbeAddOp(v, OP_Integer, pTab->iDb, 0);
   233    235       sqliteVdbeAddOp(v, OP_OpenRead, base, pTab->tnum);
   234    236       sqliteVdbeAddOp(v, OP_MoveTo, base, 0);
   235    237   
   236    238       sqliteVdbeAddOp(v, OP_Integer, 13, 0);
   237    239       for(ii = 0; ii < pTab->nCol; ii++){
   238    240         if( ii == pTab->iPKey ){
   239    241   	sqliteVdbeAddOp(v, OP_Recno, base, 0);
................................................................................
   271    273   
   272    274     /* Rewind the list of records that need to be updated and
   273    275     ** open every index that needs updating.  Note that if any
   274    276     ** index could potentially invoke a REPLACE conflict resolution 
   275    277     ** action, then we need to open all indices because we might need
   276    278     ** to be deleting some records.
   277    279     */
   278         -  sqliteVdbeAddOp(v, OP_Integer, pTab->isTemp, 0);
          280  +  sqliteVdbeAddOp(v, OP_Integer, pTab->iDb, 0);
   279    281     sqliteVdbeAddOp(v, OP_OpenWrite, base, pTab->tnum);
   280    282     if( onError==OE_Replace ){
   281    283       openAll = 1;
   282    284     }else{
   283    285       openAll = 0;
   284    286       for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
   285    287         if( pIdx->onError==OE_Replace ){
................................................................................
   286    288           openAll = 1;
   287    289           break;
   288    290         }
   289    291       }
   290    292     }
   291    293     for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
   292    294       if( openAll || aIdxUsed[i] ){
   293         -      sqliteVdbeAddOp(v, OP_Integer, pTab->isTemp, 0);
          295  +      sqliteVdbeAddOp(v, OP_Integer, pIdx->iDb, 0);
   294    296         sqliteVdbeAddOp(v, OP_OpenWrite, base+i+1, pIdx->tnum);
   295    297         assert( pParse->nTab>base+i+1 );
   296    298       }
   297    299     }
   298    300   
   299    301     /* Loop over every record that needs updating.  We have to load
   300    302     ** the old data for each record to be updated because some columns

Changes to src/where.c.

     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12     12   ** This module contains C code that generates VDBE code used to process
    13     13   ** the WHERE clause of SQL statements.  Also found here are subroutines
    14     14   ** to generate VDBE code to evaluate expressions.
    15     15   **
    16         -** $Id: where.c,v 1.73 2003/03/19 03:14:03 drh Exp $
           16  +** $Id: where.c,v 1.74 2003/03/27 12:51:26 drh Exp $
    17     17   */
    18     18   #include "sqliteInt.h"
    19     19   
    20     20   /*
    21     21   ** The query generator uses an array of instances of this structure to
    22     22   ** help it analyze the subexpressions of the WHERE clause.  Each WHERE
    23     23   ** clause subexpression is separated from the others by an AND operator.
................................................................................
   636    636     /* Open all tables in the pTabList and all indices used by those tables.
   637    637     */
   638    638     for(i=0; i<pTabList->nSrc; i++){
   639    639       Table *pTab;
   640    640   
   641    641       pTab = pTabList->a[i].pTab;
   642    642       if( pTab->isTransient || pTab->pSelect ) continue;
   643         -    sqliteVdbeAddOp(v, OP_Integer, pTab->isTemp, 0);
          643  +    sqliteVdbeAddOp(v, OP_Integer, pTab->iDb, 0);
   644    644       sqliteVdbeAddOp(v, OP_OpenRead, base+i, pTab->tnum);
   645    645       sqliteVdbeChangeP3(v, -1, pTab->zName, P3_STATIC);
   646    646       if( i==0 && !pParse->schemaVerified &&
   647    647             (pParse->db->flags & SQLITE_InTrans)==0 ){
   648    648         sqliteCodeVerifySchema(pParse);
   649    649       }
   650    650       if( pWInfo->a[i].pIdx!=0 ){
   651         -      sqliteVdbeAddOp(v, OP_Integer, pTab->isTemp, 0);
          651  +      sqliteVdbeAddOp(v, OP_Integer, pWInfo->a[i].pIdx->iDb, 0);
   652    652         sqliteVdbeAddOp(v, OP_OpenRead,
   653    653                         pWInfo->a[i].iCur, pWInfo->a[i].pIdx->tnum);
   654    654         sqliteVdbeChangeP3(v, -1, pWInfo->a[i].pIdx->zName, P3_STATIC);
   655    655       }
   656    656     }
   657    657   
   658    658     /* Generate the code to do the search