xref: /illumos-gate/usr/src/lib/libsqlite/src/attach.c (revision 1da57d55)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate ** 2003 April 6
37c478bd9Sstevel@tonic-gate **
47c478bd9Sstevel@tonic-gate ** The author disclaims copyright to this source code.  In place of
57c478bd9Sstevel@tonic-gate ** a legal notice, here is a blessing:
67c478bd9Sstevel@tonic-gate **
77c478bd9Sstevel@tonic-gate **    May you do good and not evil.
87c478bd9Sstevel@tonic-gate **    May you find forgiveness for yourself and forgive others.
97c478bd9Sstevel@tonic-gate **    May you share freely, never taking more than you give.
107c478bd9Sstevel@tonic-gate **
117c478bd9Sstevel@tonic-gate *************************************************************************
127c478bd9Sstevel@tonic-gate ** This file contains code used to implement the ATTACH and DETACH commands.
137c478bd9Sstevel@tonic-gate **
147c478bd9Sstevel@tonic-gate ** $Id: attach.c,v 1.10.2.1 2004/05/07 01:46:01 drh Exp $
157c478bd9Sstevel@tonic-gate */
167c478bd9Sstevel@tonic-gate #include "sqliteInt.h"
177c478bd9Sstevel@tonic-gate 
187c478bd9Sstevel@tonic-gate /*
197c478bd9Sstevel@tonic-gate ** This routine is called by the parser to process an ATTACH statement:
207c478bd9Sstevel@tonic-gate **
217c478bd9Sstevel@tonic-gate **     ATTACH DATABASE filename AS dbname
227c478bd9Sstevel@tonic-gate **
237c478bd9Sstevel@tonic-gate ** The pFilename and pDbname arguments are the tokens that define the
247c478bd9Sstevel@tonic-gate ** filename and dbname in the ATTACH statement.
257c478bd9Sstevel@tonic-gate */
sqliteAttach(Parse * pParse,Token * pFilename,Token * pDbname,Token * pKey)267c478bd9Sstevel@tonic-gate void sqliteAttach(Parse *pParse, Token *pFilename, Token *pDbname, Token *pKey){
277c478bd9Sstevel@tonic-gate   Db *aNew;
287c478bd9Sstevel@tonic-gate   int rc, i;
297c478bd9Sstevel@tonic-gate   char *zFile, *zName;
307c478bd9Sstevel@tonic-gate   sqlite *db;
317c478bd9Sstevel@tonic-gate   Vdbe *v;
327c478bd9Sstevel@tonic-gate 
337c478bd9Sstevel@tonic-gate   v = sqliteGetVdbe(pParse);
347c478bd9Sstevel@tonic-gate   sqliteVdbeAddOp(v, OP_Halt, 0, 0);
357c478bd9Sstevel@tonic-gate   if( pParse->explain ) return;
367c478bd9Sstevel@tonic-gate   db = pParse->db;
377c478bd9Sstevel@tonic-gate   if( db->file_format<4 ){
387c478bd9Sstevel@tonic-gate     sqliteErrorMsg(pParse, "cannot attach auxiliary databases to an "
397c478bd9Sstevel@tonic-gate        "older format master database", 0);
407c478bd9Sstevel@tonic-gate     pParse->rc = SQLITE_ERROR;
417c478bd9Sstevel@tonic-gate     return;
427c478bd9Sstevel@tonic-gate   }
437c478bd9Sstevel@tonic-gate   if( db->nDb>=MAX_ATTACHED+2 ){
44*1da57d55SToomas Soome     sqliteErrorMsg(pParse, "too many attached databases - max %d",
457c478bd9Sstevel@tonic-gate        MAX_ATTACHED);
467c478bd9Sstevel@tonic-gate     pParse->rc = SQLITE_ERROR;
477c478bd9Sstevel@tonic-gate     return;
487c478bd9Sstevel@tonic-gate   }
497c478bd9Sstevel@tonic-gate 
507c478bd9Sstevel@tonic-gate   zFile = 0;
517c478bd9Sstevel@tonic-gate   sqliteSetNString(&zFile, pFilename->z, pFilename->n, 0);
527c478bd9Sstevel@tonic-gate   if( zFile==0 ) return;
537c478bd9Sstevel@tonic-gate   sqliteDequote(zFile);
547c478bd9Sstevel@tonic-gate #ifndef SQLITE_OMIT_AUTHORIZATION
557c478bd9Sstevel@tonic-gate   if( sqliteAuthCheck(pParse, SQLITE_ATTACH, zFile, 0, 0)!=SQLITE_OK ){
567c478bd9Sstevel@tonic-gate     sqliteFree(zFile);
577c478bd9Sstevel@tonic-gate     return;
587c478bd9Sstevel@tonic-gate   }
597c478bd9Sstevel@tonic-gate #endif /* SQLITE_OMIT_AUTHORIZATION */
607c478bd9Sstevel@tonic-gate 
617c478bd9Sstevel@tonic-gate   zName = 0;
627c478bd9Sstevel@tonic-gate   sqliteSetNString(&zName, pDbname->z, pDbname->n, 0);
637c478bd9Sstevel@tonic-gate   if( zName==0 ) return;
647c478bd9Sstevel@tonic-gate   sqliteDequote(zName);
657c478bd9Sstevel@tonic-gate   for(i=0; i<db->nDb; i++){
667c478bd9Sstevel@tonic-gate     if( db->aDb[i].zName && sqliteStrICmp(db->aDb[i].zName, zName)==0 ){
677c478bd9Sstevel@tonic-gate       sqliteErrorMsg(pParse, "database %z is already in use", zName);
687c478bd9Sstevel@tonic-gate       pParse->rc = SQLITE_ERROR;
697c478bd9Sstevel@tonic-gate       sqliteFree(zFile);
707c478bd9Sstevel@tonic-gate       return;
717c478bd9Sstevel@tonic-gate     }
727c478bd9Sstevel@tonic-gate   }
737c478bd9Sstevel@tonic-gate 
747c478bd9Sstevel@tonic-gate   if( db->aDb==db->aDbStatic ){
757c478bd9Sstevel@tonic-gate     aNew = sqliteMalloc( sizeof(db->aDb[0])*3 );
767c478bd9Sstevel@tonic-gate     if( aNew==0 ) return;
777c478bd9Sstevel@tonic-gate     memcpy(aNew, db->aDb, sizeof(db->aDb[0])*2);
787c478bd9Sstevel@tonic-gate   }else{
797c478bd9Sstevel@tonic-gate     aNew = sqliteRealloc(db->aDb, sizeof(db->aDb[0])*(db->nDb+1) );
807c478bd9Sstevel@tonic-gate     if( aNew==0 ) return;
817c478bd9Sstevel@tonic-gate   }
827c478bd9Sstevel@tonic-gate   db->aDb = aNew;
837c478bd9Sstevel@tonic-gate   aNew = &db->aDb[db->nDb++];
847c478bd9Sstevel@tonic-gate   memset(aNew, 0, sizeof(*aNew));
857c478bd9Sstevel@tonic-gate   sqliteHashInit(&aNew->tblHash, SQLITE_HASH_STRING, 0);
867c478bd9Sstevel@tonic-gate   sqliteHashInit(&aNew->idxHash, SQLITE_HASH_STRING, 0);
877c478bd9Sstevel@tonic-gate   sqliteHashInit(&aNew->trigHash, SQLITE_HASH_STRING, 0);
887c478bd9Sstevel@tonic-gate   sqliteHashInit(&aNew->aFKey, SQLITE_HASH_STRING, 1);
897c478bd9Sstevel@tonic-gate   aNew->zName = zName;
907c478bd9Sstevel@tonic-gate   rc = sqliteBtreeFactory(db, zFile, 0, MAX_PAGES, &aNew->pBt);
917c478bd9Sstevel@tonic-gate   if( rc ){
927c478bd9Sstevel@tonic-gate     sqliteErrorMsg(pParse, "unable to open database: %s", zFile);
937c478bd9Sstevel@tonic-gate   }
947c478bd9Sstevel@tonic-gate #if SQLITE_HAS_CODEC
957c478bd9Sstevel@tonic-gate   {
967c478bd9Sstevel@tonic-gate     extern int sqliteCodecAttach(sqlite*, int, void*, int);
977c478bd9Sstevel@tonic-gate     char *zKey = 0;
987c478bd9Sstevel@tonic-gate     int nKey;
997c478bd9Sstevel@tonic-gate     if( pKey && pKey->z && pKey->n ){
1007c478bd9Sstevel@tonic-gate       sqliteSetNString(&zKey, pKey->z, pKey->n, 0);
1017c478bd9Sstevel@tonic-gate       sqliteDequote(zKey);
1027c478bd9Sstevel@tonic-gate       nKey = strlen(zKey);
1037c478bd9Sstevel@tonic-gate     }else{
1047c478bd9Sstevel@tonic-gate       zKey = 0;
1057c478bd9Sstevel@tonic-gate       nKey = 0;
1067c478bd9Sstevel@tonic-gate     }
1077c478bd9Sstevel@tonic-gate     sqliteCodecAttach(db, db->nDb-1, zKey, nKey);
1087c478bd9Sstevel@tonic-gate   }
1097c478bd9Sstevel@tonic-gate #endif
1107c478bd9Sstevel@tonic-gate   sqliteFree(zFile);
1117c478bd9Sstevel@tonic-gate   db->flags &= ~SQLITE_Initialized;
1127c478bd9Sstevel@tonic-gate   if( pParse->nErr ) return;
1137c478bd9Sstevel@tonic-gate   if( rc==SQLITE_OK ){
1147c478bd9Sstevel@tonic-gate     rc = sqliteInit(pParse->db, &pParse->zErrMsg);
1157c478bd9Sstevel@tonic-gate   }
1167c478bd9Sstevel@tonic-gate   if( rc ){
1177c478bd9Sstevel@tonic-gate     int i = db->nDb - 1;
1187c478bd9Sstevel@tonic-gate     assert( i>=2 );
1197c478bd9Sstevel@tonic-gate     if( db->aDb[i].pBt ){
1207c478bd9Sstevel@tonic-gate       sqliteBtreeClose(db->aDb[i].pBt);
1217c478bd9Sstevel@tonic-gate       db->aDb[i].pBt = 0;
1227c478bd9Sstevel@tonic-gate     }
1237c478bd9Sstevel@tonic-gate     sqliteResetInternalSchema(db, 0);
1247c478bd9Sstevel@tonic-gate     pParse->nErr++;
1257c478bd9Sstevel@tonic-gate     pParse->rc = SQLITE_ERROR;
1267c478bd9Sstevel@tonic-gate   }
1277c478bd9Sstevel@tonic-gate }
1287c478bd9Sstevel@tonic-gate 
1297c478bd9Sstevel@tonic-gate /*
1307c478bd9Sstevel@tonic-gate ** This routine is called by the parser to process a DETACH statement:
1317c478bd9Sstevel@tonic-gate **
1327c478bd9Sstevel@tonic-gate **    DETACH DATABASE dbname
1337c478bd9Sstevel@tonic-gate **
1347c478bd9Sstevel@tonic-gate ** The pDbname argument is the name of the database in the DETACH statement.
1357c478bd9Sstevel@tonic-gate */
sqliteDetach(Parse * pParse,Token * pDbname)1367c478bd9Sstevel@tonic-gate void sqliteDetach(Parse *pParse, Token *pDbname){
1377c478bd9Sstevel@tonic-gate   int i;
1387c478bd9Sstevel@tonic-gate   sqlite *db;
1397c478bd9Sstevel@tonic-gate   Vdbe *v;
1407c478bd9Sstevel@tonic-gate   Db *pDb;
1417c478bd9Sstevel@tonic-gate 
1427c478bd9Sstevel@tonic-gate   v = sqliteGetVdbe(pParse);
1437c478bd9Sstevel@tonic-gate   sqliteVdbeAddOp(v, OP_Halt, 0, 0);
1447c478bd9Sstevel@tonic-gate   if( pParse->explain ) return;
1457c478bd9Sstevel@tonic-gate   db = pParse->db;
1467c478bd9Sstevel@tonic-gate   for(i=0; i<db->nDb; i++){
1477c478bd9Sstevel@tonic-gate     pDb = &db->aDb[i];
1487c478bd9Sstevel@tonic-gate     if( pDb->pBt==0 || pDb->zName==0 ) continue;
1497c478bd9Sstevel@tonic-gate     if( strlen(pDb->zName)!=pDbname->n ) continue;
1507c478bd9Sstevel@tonic-gate     if( sqliteStrNICmp(pDb->zName, pDbname->z, pDbname->n)==0 ) break;
1517c478bd9Sstevel@tonic-gate   }
1527c478bd9Sstevel@tonic-gate   if( i>=db->nDb ){
1537c478bd9Sstevel@tonic-gate     sqliteErrorMsg(pParse, "no such database: %T", pDbname);
1547c478bd9Sstevel@tonic-gate     return;
1557c478bd9Sstevel@tonic-gate   }
1567c478bd9Sstevel@tonic-gate   if( i<2 ){
1577c478bd9Sstevel@tonic-gate     sqliteErrorMsg(pParse, "cannot detach database %T", pDbname);
1587c478bd9Sstevel@tonic-gate     return;
1597c478bd9Sstevel@tonic-gate   }
1607c478bd9Sstevel@tonic-gate #ifndef SQLITE_OMIT_AUTHORIZATION
1617c478bd9Sstevel@tonic-gate   if( sqliteAuthCheck(pParse,SQLITE_DETACH,db->aDb[i].zName,0,0)!=SQLITE_OK ){
1627c478bd9Sstevel@tonic-gate     return;
1637c478bd9Sstevel@tonic-gate   }
1647c478bd9Sstevel@tonic-gate #endif /* SQLITE_OMIT_AUTHORIZATION */
1657c478bd9Sstevel@tonic-gate   sqliteBtreeClose(pDb->pBt);
1667c478bd9Sstevel@tonic-gate   pDb->pBt = 0;
1677c478bd9Sstevel@tonic-gate   sqliteFree(pDb->zName);
1687c478bd9Sstevel@tonic-gate   sqliteResetInternalSchema(db, i);
1697c478bd9Sstevel@tonic-gate   if( pDb->pAux && pDb->xFreeAux ) pDb->xFreeAux(pDb->pAux);
1707c478bd9Sstevel@tonic-gate   db->nDb--;
1717c478bd9Sstevel@tonic-gate   if( i<db->nDb ){
1727c478bd9Sstevel@tonic-gate     db->aDb[i] = db->aDb[db->nDb];
1737c478bd9Sstevel@tonic-gate     memset(&db->aDb[db->nDb], 0, sizeof(db->aDb[0]));
1747c478bd9Sstevel@tonic-gate     sqliteResetInternalSchema(db, i);
1757c478bd9Sstevel@tonic-gate   }
1767c478bd9Sstevel@tonic-gate }
1777c478bd9Sstevel@tonic-gate 
1787c478bd9Sstevel@tonic-gate /*
1797c478bd9Sstevel@tonic-gate ** Initialize a DbFixer structure.  This routine must be called prior
1807c478bd9Sstevel@tonic-gate ** to passing the structure to one of the sqliteFixAAAA() routines below.
1817c478bd9Sstevel@tonic-gate **
1827c478bd9Sstevel@tonic-gate ** The return value indicates whether or not fixation is required.  TRUE
1837c478bd9Sstevel@tonic-gate ** means we do need to fix the database references, FALSE means we do not.
1847c478bd9Sstevel@tonic-gate */
sqliteFixInit(DbFixer * pFix,Parse * pParse,int iDb,const char * zType,const Token * pName)1857c478bd9Sstevel@tonic-gate int sqliteFixInit(
1867c478bd9Sstevel@tonic-gate   DbFixer *pFix,      /* The fixer to be initialized */
1877c478bd9Sstevel@tonic-gate   Parse *pParse,      /* Error messages will be written here */
1887c478bd9Sstevel@tonic-gate   int iDb,            /* This is the database that must must be used */
1897c478bd9Sstevel@tonic-gate   const char *zType,  /* "view", "trigger", or "index" */
1907c478bd9Sstevel@tonic-gate   const Token *pName  /* Name of the view, trigger, or index */
1917c478bd9Sstevel@tonic-gate ){
1927c478bd9Sstevel@tonic-gate   sqlite *db;
1937c478bd9Sstevel@tonic-gate 
1947c478bd9Sstevel@tonic-gate   if( iDb<0 || iDb==1 ) return 0;
1957c478bd9Sstevel@tonic-gate   db = pParse->db;
1967c478bd9Sstevel@tonic-gate   assert( db->nDb>iDb );
1977c478bd9Sstevel@tonic-gate   pFix->pParse = pParse;
1987c478bd9Sstevel@tonic-gate   pFix->zDb = db->aDb[iDb].zName;
1997c478bd9Sstevel@tonic-gate   pFix->zType = zType;
2007c478bd9Sstevel@tonic-gate   pFix->pName = pName;
2017c478bd9Sstevel@tonic-gate   return 1;
2027c478bd9Sstevel@tonic-gate }
2037c478bd9Sstevel@tonic-gate 
2047c478bd9Sstevel@tonic-gate /*
2057c478bd9Sstevel@tonic-gate ** The following set of routines walk through the parse tree and assign
2067c478bd9Sstevel@tonic-gate ** a specific database to all table references where the database name
2077c478bd9Sstevel@tonic-gate ** was left unspecified in the original SQL statement.  The pFix structure
2087c478bd9Sstevel@tonic-gate ** must have been initialized by a prior call to sqliteFixInit().
2097c478bd9Sstevel@tonic-gate **
2107c478bd9Sstevel@tonic-gate ** These routines are used to make sure that an index, trigger, or
2117c478bd9Sstevel@tonic-gate ** view in one database does not refer to objects in a different database.
2127c478bd9Sstevel@tonic-gate ** (Exception: indices, triggers, and views in the TEMP database are
2137c478bd9Sstevel@tonic-gate ** allowed to refer to anything.)  If a reference is explicitly made
2147c478bd9Sstevel@tonic-gate ** to an object in a different database, an error message is added to
2157c478bd9Sstevel@tonic-gate ** pParse->zErrMsg and these routines return non-zero.  If everything
2167c478bd9Sstevel@tonic-gate ** checks out, these routines return 0.
2177c478bd9Sstevel@tonic-gate */
sqliteFixSrcList(DbFixer * pFix,SrcList * pList)2187c478bd9Sstevel@tonic-gate int sqliteFixSrcList(
2197c478bd9Sstevel@tonic-gate   DbFixer *pFix,       /* Context of the fixation */
2207c478bd9Sstevel@tonic-gate   SrcList *pList       /* The Source list to check and modify */
2217c478bd9Sstevel@tonic-gate ){
2227c478bd9Sstevel@tonic-gate   int i;
2237c478bd9Sstevel@tonic-gate   const char *zDb;
2247c478bd9Sstevel@tonic-gate 
2257c478bd9Sstevel@tonic-gate   if( pList==0 ) return 0;
2267c478bd9Sstevel@tonic-gate   zDb = pFix->zDb;
2277c478bd9Sstevel@tonic-gate   for(i=0; i<pList->nSrc; i++){
2287c478bd9Sstevel@tonic-gate     if( pList->a[i].zDatabase==0 ){
2297c478bd9Sstevel@tonic-gate       pList->a[i].zDatabase = sqliteStrDup(zDb);
2307c478bd9Sstevel@tonic-gate     }else if( sqliteStrICmp(pList->a[i].zDatabase,zDb)!=0 ){
2317c478bd9Sstevel@tonic-gate       sqliteErrorMsg(pFix->pParse,
2327c478bd9Sstevel@tonic-gate          "%s %z cannot reference objects in database %s",
2337c478bd9Sstevel@tonic-gate          pFix->zType, sqliteStrNDup(pFix->pName->z, pFix->pName->n),
2347c478bd9Sstevel@tonic-gate          pList->a[i].zDatabase);
2357c478bd9Sstevel@tonic-gate       return 1;
2367c478bd9Sstevel@tonic-gate     }
2377c478bd9Sstevel@tonic-gate     if( sqliteFixSelect(pFix, pList->a[i].pSelect) ) return 1;
2387c478bd9Sstevel@tonic-gate     if( sqliteFixExpr(pFix, pList->a[i].pOn) ) return 1;
2397c478bd9Sstevel@tonic-gate   }
2407c478bd9Sstevel@tonic-gate   return 0;
2417c478bd9Sstevel@tonic-gate }
sqliteFixSelect(DbFixer * pFix,Select * pSelect)2427c478bd9Sstevel@tonic-gate int sqliteFixSelect(
2437c478bd9Sstevel@tonic-gate   DbFixer *pFix,       /* Context of the fixation */
2447c478bd9Sstevel@tonic-gate   Select *pSelect      /* The SELECT statement to be fixed to one database */
2457c478bd9Sstevel@tonic-gate ){
2467c478bd9Sstevel@tonic-gate   while( pSelect ){
2477c478bd9Sstevel@tonic-gate     if( sqliteFixExprList(pFix, pSelect->pEList) ){
2487c478bd9Sstevel@tonic-gate       return 1;
2497c478bd9Sstevel@tonic-gate     }
2507c478bd9Sstevel@tonic-gate     if( sqliteFixSrcList(pFix, pSelect->pSrc) ){
2517c478bd9Sstevel@tonic-gate       return 1;
2527c478bd9Sstevel@tonic-gate     }
2537c478bd9Sstevel@tonic-gate     if( sqliteFixExpr(pFix, pSelect->pWhere) ){
2547c478bd9Sstevel@tonic-gate       return 1;
2557c478bd9Sstevel@tonic-gate     }
2567c478bd9Sstevel@tonic-gate     if( sqliteFixExpr(pFix, pSelect->pHaving) ){
2577c478bd9Sstevel@tonic-gate       return 1;
2587c478bd9Sstevel@tonic-gate     }
2597c478bd9Sstevel@tonic-gate     pSelect = pSelect->pPrior;
2607c478bd9Sstevel@tonic-gate   }
2617c478bd9Sstevel@tonic-gate   return 0;
2627c478bd9Sstevel@tonic-gate }
sqliteFixExpr(DbFixer * pFix,Expr * pExpr)2637c478bd9Sstevel@tonic-gate int sqliteFixExpr(
2647c478bd9Sstevel@tonic-gate   DbFixer *pFix,     /* Context of the fixation */
2657c478bd9Sstevel@tonic-gate   Expr *pExpr        /* The expression to be fixed to one database */
2667c478bd9Sstevel@tonic-gate ){
2677c478bd9Sstevel@tonic-gate   while( pExpr ){
2687c478bd9Sstevel@tonic-gate     if( sqliteFixSelect(pFix, pExpr->pSelect) ){
2697c478bd9Sstevel@tonic-gate       return 1;
2707c478bd9Sstevel@tonic-gate     }
2717c478bd9Sstevel@tonic-gate     if( sqliteFixExprList(pFix, pExpr->pList) ){
2727c478bd9Sstevel@tonic-gate       return 1;
2737c478bd9Sstevel@tonic-gate     }
2747c478bd9Sstevel@tonic-gate     if( sqliteFixExpr(pFix, pExpr->pRight) ){
2757c478bd9Sstevel@tonic-gate       return 1;
2767c478bd9Sstevel@tonic-gate     }
2777c478bd9Sstevel@tonic-gate     pExpr = pExpr->pLeft;
2787c478bd9Sstevel@tonic-gate   }
2797c478bd9Sstevel@tonic-gate   return 0;
2807c478bd9Sstevel@tonic-gate }
sqliteFixExprList(DbFixer * pFix,ExprList * pList)2817c478bd9Sstevel@tonic-gate int sqliteFixExprList(
2827c478bd9Sstevel@tonic-gate   DbFixer *pFix,     /* Context of the fixation */
2837c478bd9Sstevel@tonic-gate   ExprList *pList    /* The expression to be fixed to one database */
2847c478bd9Sstevel@tonic-gate ){
2857c478bd9Sstevel@tonic-gate   int i;
2867c478bd9Sstevel@tonic-gate   if( pList==0 ) return 0;
2877c478bd9Sstevel@tonic-gate   for(i=0; i<pList->nExpr; i++){
2887c478bd9Sstevel@tonic-gate     if( sqliteFixExpr(pFix, pList->a[i].pExpr) ){
2897c478bd9Sstevel@tonic-gate       return 1;
2907c478bd9Sstevel@tonic-gate     }
2917c478bd9Sstevel@tonic-gate   }
2927c478bd9Sstevel@tonic-gate   return 0;
2937c478bd9Sstevel@tonic-gate }
sqliteFixTriggerStep(DbFixer * pFix,TriggerStep * pStep)2947c478bd9Sstevel@tonic-gate int sqliteFixTriggerStep(
2957c478bd9Sstevel@tonic-gate   DbFixer *pFix,     /* Context of the fixation */
2967c478bd9Sstevel@tonic-gate   TriggerStep *pStep /* The trigger step be fixed to one database */
2977c478bd9Sstevel@tonic-gate ){
2987c478bd9Sstevel@tonic-gate   while( pStep ){
2997c478bd9Sstevel@tonic-gate     if( sqliteFixSelect(pFix, pStep->pSelect) ){
3007c478bd9Sstevel@tonic-gate       return 1;
3017c478bd9Sstevel@tonic-gate     }
3027c478bd9Sstevel@tonic-gate     if( sqliteFixExpr(pFix, pStep->pWhere) ){
3037c478bd9Sstevel@tonic-gate       return 1;
3047c478bd9Sstevel@tonic-gate     }
3057c478bd9Sstevel@tonic-gate     if( sqliteFixExprList(pFix, pStep->pExprList) ){
3067c478bd9Sstevel@tonic-gate       return 1;
3077c478bd9Sstevel@tonic-gate     }
3087c478bd9Sstevel@tonic-gate     pStep = pStep->pNext;
3097c478bd9Sstevel@tonic-gate   }
3107c478bd9Sstevel@tonic-gate   return 0;
3117c478bd9Sstevel@tonic-gate }
312