attach.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578
  1. /*
  2. ** 2003 April 6
  3. **
  4. ** The author disclaims copyright to this source code. In place of
  5. ** a legal notice, here is a blessing:
  6. **
  7. ** May you do good and not evil.
  8. ** May you find forgiveness for yourself and forgive others.
  9. ** May you share freely, never taking more than you give.
  10. **
  11. *************************************************************************
  12. ** This file contains code used to implement the ATTACH and DETACH commands.
  13. */
  14. #include "sqliteInt.h"
  15. #ifndef SQLITE_OMIT_ATTACH
  16. /*
  17. ** Resolve an expression that was part of an ATTACH or DETACH statement. This
  18. ** is slightly different from resolving a normal SQL expression, because simple
  19. ** identifiers are treated as strings, not possible column names or aliases.
  20. **
  21. ** i.e. if the parser sees:
  22. **
  23. ** ATTACH DATABASE abc AS def
  24. **
  25. ** it treats the two expressions as literal strings 'abc' and 'def' instead of
  26. ** looking for columns of the same name.
  27. **
  28. ** This only applies to the root node of pExpr, so the statement:
  29. **
  30. ** ATTACH DATABASE abc||def AS 'db2'
  31. **
  32. ** will fail because neither abc or def can be resolved.
  33. */
  34. static int resolveAttachExpr(NameContext *pName, Expr *pExpr)
  35. {
  36. int rc = SQLITE_OK;
  37. if( pExpr ){
  38. if( pExpr->op!=TK_ID ){
  39. rc = sqlite3ResolveExprNames(pName, pExpr);
  40. if( rc==SQLITE_OK && !sqlite3ExprIsConstant(pExpr) ){
  41. sqlite3ErrorMsg(pName->pParse, "invalid name: \"%s\"", pExpr->u.zToken);
  42. return SQLITE_ERROR;
  43. }
  44. }else{
  45. pExpr->op = TK_STRING;
  46. }
  47. }
  48. return rc;
  49. }
  50. /*
  51. ** An SQL user-function registered to do the work of an ATTACH statement. The
  52. ** three arguments to the function come directly from an attach statement:
  53. **
  54. ** ATTACH DATABASE x AS y KEY z
  55. **
  56. ** SELECT sqlite_attach(x, y, z)
  57. **
  58. ** If the optional "KEY z" syntax is omitted, an SQL NULL is passed as the
  59. ** third argument.
  60. */
  61. static void attachFunc(
  62. sqlite3_context *context,
  63. int NotUsed,
  64. sqlite3_value **argv
  65. ){
  66. int i;
  67. int rc = 0;
  68. sqlite3 *db = sqlite3_context_db_handle(context);
  69. const char *zName;
  70. const char *zFile;
  71. char *zPath = 0;
  72. char *zErr = 0;
  73. unsigned int flags;
  74. Db *aNew;
  75. char *zErrDyn = 0;
  76. sqlite3_vfs *pVfs;
  77. UNUSED_PARAMETER(NotUsed);
  78. zFile = (const char *)sqlite3_value_text(argv[0]);
  79. zName = (const char *)sqlite3_value_text(argv[1]);
  80. if( zFile==0 ) zFile = "";
  81. if( zName==0 ) zName = "";
  82. /* Check for the following errors:
  83. **
  84. ** * Too many attached databases,
  85. ** * Transaction currently open
  86. ** * Specified database name already being used.
  87. */
  88. if( db->nDb>=db->aLimit[SQLITE_LIMIT_ATTACHED]+2 ){
  89. zErrDyn = sqlite3MPrintf(db, "too many attached databases - max %d",
  90. db->aLimit[SQLITE_LIMIT_ATTACHED]
  91. );
  92. goto attach_error;
  93. }
  94. if( !db->autoCommit ){
  95. zErrDyn = sqlite3MPrintf(db, "cannot ATTACH database within transaction");
  96. goto attach_error;
  97. }
  98. for(i=0; i<db->nDb; i++){
  99. char *z = db->aDb[i].zName;
  100. assert( z && zName );
  101. if( sqlite3StrICmp(z, zName)==0 ){
  102. zErrDyn = sqlite3MPrintf(db, "database %s is already in use", zName);
  103. goto attach_error;
  104. }
  105. }
  106. /* Allocate the new entry in the db->aDb[] array and initialize the schema
  107. ** hash tables.
  108. */
  109. if( db->aDb==db->aDbStatic ){
  110. aNew = sqlite3DbMallocRaw(db, sizeof(db->aDb[0])*3 );
  111. if( aNew==0 ) return;
  112. memcpy(aNew, db->aDb, sizeof(db->aDb[0])*2);
  113. }else{
  114. aNew = sqlite3DbRealloc(db, db->aDb, sizeof(db->aDb[0])*(db->nDb+1) );
  115. if( aNew==0 ) return;
  116. }
  117. db->aDb = aNew;
  118. aNew = &db->aDb[db->nDb];
  119. memset(aNew, 0, sizeof(*aNew));
  120. /* Open the database file. If the btree is successfully opened, use
  121. ** it to obtain the database schema. At this point the schema may
  122. ** or may not be initialized.
  123. */
  124. flags = db->openFlags;
  125. rc = sqlite3ParseUri(db->pVfs->zName, zFile, &flags, &pVfs, &zPath, &zErr);
  126. if( rc!=SQLITE_OK ){
  127. if( rc==SQLITE_NOMEM ) db->mallocFailed = 1;
  128. sqlite3_result_error(context, zErr, -1);
  129. sqlite3_free(zErr);
  130. return;
  131. }
  132. assert( pVfs );
  133. flags |= SQLITE_OPEN_MAIN_DB;
  134. rc = sqlite3BtreeOpen(pVfs, zPath, db, &aNew->pBt, 0, flags);
  135. sqlite3_free( zPath );
  136. db->nDb++;
  137. if( rc==SQLITE_CONSTRAINT ){
  138. rc = SQLITE_ERROR;
  139. zErrDyn = sqlite3MPrintf(db, "database is already attached");
  140. }else if( rc==SQLITE_OK ){
  141. Pager *pPager;
  142. aNew->pSchema = sqlite3SchemaGet(db, aNew->pBt);
  143. if( !aNew->pSchema ){
  144. rc = SQLITE_NOMEM;
  145. }else if( aNew->pSchema->file_format && aNew->pSchema->enc!=ENC(db) ){
  146. zErrDyn = sqlite3MPrintf(db,
  147. "attached databases must use the same text encoding as main database");
  148. rc = SQLITE_ERROR;
  149. }
  150. pPager = sqlite3BtreePager(aNew->pBt);
  151. sqlite3PagerLockingMode(pPager, db->dfltLockMode);
  152. sqlite3BtreeSecureDelete(aNew->pBt,
  153. sqlite3BtreeSecureDelete(db->aDb[0].pBt,-1) );
  154. #ifndef SQLITE_OMIT_PAGER_PRAGMAS
  155. sqlite3BtreeSetPagerFlags(aNew->pBt, 3 | (db->flags & PAGER_FLAGS_MASK));
  156. #endif
  157. }
  158. aNew->safety_level = 3;
  159. aNew->zName = sqlite3DbStrDup(db, zName);
  160. if( rc==SQLITE_OK && aNew->zName==0 ){
  161. rc = SQLITE_NOMEM;
  162. }
  163. #ifdef SQLITE_HAS_CODEC
  164. if( rc==SQLITE_OK ){
  165. extern int sqlite3CodecAttach(sqlite3*, int, const void*, int);
  166. extern void sqlite3CodecGetKey(sqlite3*, int, void**, int*);
  167. int nKey;
  168. char *zKey;
  169. int t = sqlite3_value_type(argv[2]);
  170. switch( t ){
  171. case SQLITE_INTEGER:
  172. case SQLITE_FLOAT:
  173. zErrDyn = sqlite3DbStrDup(db, "Invalid key value");
  174. rc = SQLITE_ERROR;
  175. break;
  176. case SQLITE_TEXT:
  177. case SQLITE_BLOB:
  178. nKey = sqlite3_value_bytes(argv[2]);
  179. zKey = (char *)sqlite3_value_blob(argv[2]);
  180. rc = sqlite3CodecAttach(db, db->nDb-1, zKey, nKey);
  181. break;
  182. case SQLITE_NULL:
  183. /* No key specified. Use the key from the main database */
  184. sqlite3CodecGetKey(db, 0, (void**)&zKey, &nKey);
  185. if( nKey>0 || sqlite3BtreeGetReserve(db->aDb[0].pBt)>0 ){
  186. rc = sqlite3CodecAttach(db, db->nDb-1, zKey, nKey);
  187. }
  188. break;
  189. }
  190. }
  191. #endif
  192. /* If the file was opened successfully, read the schema for the new database.
  193. ** If this fails, or if opening the file failed, then close the file and
  194. ** remove the entry from the db->aDb[] array. i.e. put everything back the way
  195. ** we found it.
  196. */
  197. if( rc==SQLITE_OK ){
  198. sqlite3BtreeEnterAll(db);
  199. rc = sqlite3Init(db, &zErrDyn);
  200. sqlite3BtreeLeaveAll(db);
  201. }
  202. if( rc ){
  203. int iDb = db->nDb - 1;
  204. assert( iDb>=2 );
  205. if( db->aDb[iDb].pBt ){
  206. sqlite3BtreeClose(db->aDb[iDb].pBt);
  207. db->aDb[iDb].pBt = 0;
  208. db->aDb[iDb].pSchema = 0;
  209. }
  210. sqlite3ResetAllSchemasOfConnection(db);
  211. db->nDb = iDb;
  212. if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){
  213. db->mallocFailed = 1;
  214. sqlite3DbFree(db, zErrDyn);
  215. zErrDyn = sqlite3MPrintf(db, "out of memory");
  216. }else if( zErrDyn==0 ){
  217. zErrDyn = sqlite3MPrintf(db, "unable to open database: %s", zFile);
  218. }
  219. goto attach_error;
  220. }
  221. return;
  222. attach_error:
  223. /* Return an error if we get here */
  224. if( zErrDyn ){
  225. sqlite3_result_error(context, zErrDyn, -1);
  226. sqlite3DbFree(db, zErrDyn);
  227. }
  228. if( rc ) sqlite3_result_error_code(context, rc);
  229. }
  230. /*
  231. ** An SQL user-function registered to do the work of an DETACH statement. The
  232. ** three arguments to the function come directly from a detach statement:
  233. **
  234. ** DETACH DATABASE x
  235. **
  236. ** SELECT sqlite_detach(x)
  237. */
  238. static void detachFunc(
  239. sqlite3_context *context,
  240. int NotUsed,
  241. sqlite3_value **argv
  242. ){
  243. const char *zName = (const char *)sqlite3_value_text(argv[0]);
  244. sqlite3 *db = sqlite3_context_db_handle(context);
  245. int i;
  246. Db *pDb = 0;
  247. char zErr[128];
  248. UNUSED_PARAMETER(NotUsed);
  249. if( zName==0 ) zName = "";
  250. for(i=0; i<db->nDb; i++){
  251. pDb = &db->aDb[i];
  252. if( pDb->pBt==0 ) continue;
  253. if( sqlite3StrICmp(pDb->zName, zName)==0 ) break;
  254. }
  255. if( i>=db->nDb ){
  256. sqlite3_snprintf(sizeof(zErr),zErr, "no such database: %s", zName);
  257. goto detach_error;
  258. }
  259. if( i<2 ){
  260. sqlite3_snprintf(sizeof(zErr),zErr, "cannot detach database %s", zName);
  261. goto detach_error;
  262. }
  263. if( !db->autoCommit ){
  264. sqlite3_snprintf(sizeof(zErr), zErr,
  265. "cannot DETACH database within transaction");
  266. goto detach_error;
  267. }
  268. if( sqlite3BtreeIsInReadTrans(pDb->pBt) || sqlite3BtreeIsInBackup(pDb->pBt) ){
  269. sqlite3_snprintf(sizeof(zErr),zErr, "database %s is locked", zName);
  270. goto detach_error;
  271. }
  272. sqlite3BtreeClose(pDb->pBt);
  273. pDb->pBt = 0;
  274. pDb->pSchema = 0;
  275. sqlite3ResetAllSchemasOfConnection(db);
  276. return;
  277. detach_error:
  278. sqlite3_result_error(context, zErr, -1);
  279. }
  280. /*
  281. ** This procedure generates VDBE code for a single invocation of either the
  282. ** sqlite_detach() or sqlite_attach() SQL user functions.
  283. */
  284. static void codeAttach(
  285. Parse *pParse, /* The parser context */
  286. int type, /* Either SQLITE_ATTACH or SQLITE_DETACH */
  287. FuncDef const *pFunc,/* FuncDef wrapper for detachFunc() or attachFunc() */
  288. Expr *pAuthArg, /* Expression to pass to authorization callback */
  289. Expr *pFilename, /* Name of database file */
  290. Expr *pDbname, /* Name of the database to use internally */
  291. Expr *pKey /* Database key for encryption extension */
  292. ){
  293. int rc;
  294. NameContext sName;
  295. Vdbe *v;
  296. sqlite3* db = pParse->db;
  297. int regArgs;
  298. memset(&sName, 0, sizeof(NameContext));
  299. sName.pParse = pParse;
  300. if(
  301. SQLITE_OK!=(rc = resolveAttachExpr(&sName, pFilename)) ||
  302. SQLITE_OK!=(rc = resolveAttachExpr(&sName, pDbname)) ||
  303. SQLITE_OK!=(rc = resolveAttachExpr(&sName, pKey))
  304. ){
  305. pParse->nErr++;
  306. goto attach_end;
  307. }
  308. #ifndef SQLITE_OMIT_AUTHORIZATION
  309. if( pAuthArg ){
  310. char *zAuthArg;
  311. if( pAuthArg->op==TK_STRING ){
  312. zAuthArg = pAuthArg->u.zToken;
  313. }else{
  314. zAuthArg = 0;
  315. }
  316. rc = sqlite3AuthCheck(pParse, type, zAuthArg, 0, 0);
  317. if(rc!=SQLITE_OK ){
  318. goto attach_end;
  319. }
  320. }
  321. #endif /* SQLITE_OMIT_AUTHORIZATION */
  322. v = sqlite3GetVdbe(pParse);
  323. regArgs = sqlite3GetTempRange(pParse, 4);
  324. sqlite3ExprCode(pParse, pFilename, regArgs);
  325. sqlite3ExprCode(pParse, pDbname, regArgs+1);
  326. sqlite3ExprCode(pParse, pKey, regArgs+2);
  327. assert( v || db->mallocFailed );
  328. if( v ){
  329. sqlite3VdbeAddOp3(v, OP_Function, 0, regArgs+3-pFunc->nArg, regArgs+3);
  330. assert( pFunc->nArg==-1 || (pFunc->nArg&0xff)==pFunc->nArg );
  331. sqlite3VdbeChangeP5(v, (u8)(pFunc->nArg));
  332. sqlite3VdbeChangeP4(v, -1, (char *)pFunc, P4_FUNCDEF);
  333. /* Code an OP_Expire. For an ATTACH statement, set P1 to true (expire this
  334. ** statement only). For DETACH, set it to false (expire all existing
  335. ** statements).
  336. */
  337. sqlite3VdbeAddOp1(v, OP_Expire, (type==SQLITE_ATTACH));
  338. }
  339. attach_end:
  340. sqlite3ExprDelete(db, pFilename);
  341. sqlite3ExprDelete(db, pDbname);
  342. sqlite3ExprDelete(db, pKey);
  343. }
  344. /*
  345. ** Called by the parser to compile a DETACH statement.
  346. **
  347. ** DETACH pDbname
  348. */
  349. void sqlite3Detach(Parse *pParse, Expr *pDbname){
  350. static const FuncDef detach_func = {
  351. 1, /* nArg */
  352. SQLITE_UTF8, /* funcFlags */
  353. 0, /* pUserData */
  354. 0, /* pNext */
  355. detachFunc, /* xFunc */
  356. 0, /* xStep */
  357. 0, /* xFinalize */
  358. "sqlite_detach", /* zName */
  359. 0, /* pHash */
  360. 0 /* pDestructor */
  361. };
  362. codeAttach(pParse, SQLITE_DETACH, &detach_func, pDbname, 0, 0, pDbname);
  363. }
  364. /*
  365. ** Called by the parser to compile an ATTACH statement.
  366. **
  367. ** ATTACH p AS pDbname KEY pKey
  368. */
  369. void sqlite3Attach(Parse *pParse, Expr *p, Expr *pDbname, Expr *pKey){
  370. static const FuncDef attach_func = {
  371. 3, /* nArg */
  372. SQLITE_UTF8, /* funcFlags */
  373. 0, /* pUserData */
  374. 0, /* pNext */
  375. attachFunc, /* xFunc */
  376. 0, /* xStep */
  377. 0, /* xFinalize */
  378. "sqlite_attach", /* zName */
  379. 0, /* pHash */
  380. 0 /* pDestructor */
  381. };
  382. codeAttach(pParse, SQLITE_ATTACH, &attach_func, p, p, pDbname, pKey);
  383. }
  384. #endif /* SQLITE_OMIT_ATTACH */
  385. /*
  386. ** Initialize a DbFixer structure. This routine must be called prior
  387. ** to passing the structure to one of the sqliteFixAAAA() routines below.
  388. */
  389. void sqlite3FixInit(
  390. DbFixer *pFix, /* The fixer to be initialized */
  391. Parse *pParse, /* Error messages will be written here */
  392. int iDb, /* This is the database that must be used */
  393. const char *zType, /* "view", "trigger", or "index" */
  394. const Token *pName /* Name of the view, trigger, or index */
  395. ){
  396. sqlite3 *db;
  397. db = pParse->db;
  398. assert( db->nDb>iDb );
  399. pFix->pParse = pParse;
  400. pFix->zDb = db->aDb[iDb].zName;
  401. pFix->pSchema = db->aDb[iDb].pSchema;
  402. pFix->zType = zType;
  403. pFix->pName = pName;
  404. pFix->bVarOnly = (iDb==1);
  405. }
  406. /*
  407. ** The following set of routines walk through the parse tree and assign
  408. ** a specific database to all table references where the database name
  409. ** was left unspecified in the original SQL statement. The pFix structure
  410. ** must have been initialized by a prior call to sqlite3FixInit().
  411. **
  412. ** These routines are used to make sure that an index, trigger, or
  413. ** view in one database does not refer to objects in a different database.
  414. ** (Exception: indices, triggers, and views in the TEMP database are
  415. ** allowed to refer to anything.) If a reference is explicitly made
  416. ** to an object in a different database, an error message is added to
  417. ** pParse->zErrMsg and these routines return non-zero. If everything
  418. ** checks out, these routines return 0.
  419. */
  420. int sqlite3FixSrcList(
  421. DbFixer *pFix, /* Context of the fixation */
  422. SrcList *pList /* The Source list to check and modify */
  423. ){
  424. int i;
  425. const char *zDb;
  426. struct SrcList_item *pItem;
  427. if( NEVER(pList==0) ) return 0;
  428. zDb = pFix->zDb;
  429. for(i=0, pItem=pList->a; i<pList->nSrc; i++, pItem++){
  430. if( pFix->bVarOnly==0 ){
  431. if( pItem->zDatabase && sqlite3StrICmp(pItem->zDatabase, zDb) ){
  432. sqlite3ErrorMsg(pFix->pParse,
  433. "%s %T cannot reference objects in database %s",
  434. pFix->zType, pFix->pName, pItem->zDatabase);
  435. return 1;
  436. }
  437. sqlite3DbFree(pFix->pParse->db, pItem->zDatabase);
  438. pItem->zDatabase = 0;
  439. pItem->pSchema = pFix->pSchema;
  440. }
  441. #if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER)
  442. if( sqlite3FixSelect(pFix, pItem->pSelect) ) return 1;
  443. if( sqlite3FixExpr(pFix, pItem->pOn) ) return 1;
  444. #endif
  445. }
  446. return 0;
  447. }
  448. #if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER)
  449. int sqlite3FixSelect(
  450. DbFixer *pFix, /* Context of the fixation */
  451. Select *pSelect /* The SELECT statement to be fixed to one database */
  452. ){
  453. while( pSelect ){
  454. if( sqlite3FixExprList(pFix, pSelect->pEList) ){
  455. return 1;
  456. }
  457. if( sqlite3FixSrcList(pFix, pSelect->pSrc) ){
  458. return 1;
  459. }
  460. if( sqlite3FixExpr(pFix, pSelect->pWhere) ){
  461. return 1;
  462. }
  463. if( sqlite3FixExprList(pFix, pSelect->pGroupBy) ){
  464. return 1;
  465. }
  466. if( sqlite3FixExpr(pFix, pSelect->pHaving) ){
  467. return 1;
  468. }
  469. if( sqlite3FixExprList(pFix, pSelect->pOrderBy) ){
  470. return 1;
  471. }
  472. if( sqlite3FixExpr(pFix, pSelect->pLimit) ){
  473. return 1;
  474. }
  475. if( sqlite3FixExpr(pFix, pSelect->pOffset) ){
  476. return 1;
  477. }
  478. pSelect = pSelect->pPrior;
  479. }
  480. return 0;
  481. }
  482. int sqlite3FixExpr(
  483. DbFixer *pFix, /* Context of the fixation */
  484. Expr *pExpr /* The expression to be fixed to one database */
  485. ){
  486. while( pExpr ){
  487. if( pExpr->op==TK_VARIABLE ){
  488. if( pFix->pParse->db->init.busy ){
  489. pExpr->op = TK_NULL;
  490. }else{
  491. sqlite3ErrorMsg(pFix->pParse, "%s cannot use variables", pFix->zType);
  492. return 1;
  493. }
  494. }
  495. if( ExprHasProperty(pExpr, EP_TokenOnly) ) break;
  496. if( ExprHasProperty(pExpr, EP_xIsSelect) ){
  497. if( sqlite3FixSelect(pFix, pExpr->x.pSelect) ) return 1;
  498. }else{
  499. if( sqlite3FixExprList(pFix, pExpr->x.pList) ) return 1;
  500. }
  501. if( sqlite3FixExpr(pFix, pExpr->pRight) ){
  502. return 1;
  503. }
  504. pExpr = pExpr->pLeft;
  505. }
  506. return 0;
  507. }
  508. int sqlite3FixExprList(
  509. DbFixer *pFix, /* Context of the fixation */
  510. ExprList *pList /* The expression to be fixed to one database */
  511. ){
  512. int i;
  513. struct ExprList_item *pItem;
  514. if( pList==0 ) return 0;
  515. for(i=0, pItem=pList->a; i<pList->nExpr; i++, pItem++){
  516. if( sqlite3FixExpr(pFix, pItem->pExpr) ){
  517. return 1;
  518. }
  519. }
  520. return 0;
  521. }
  522. #endif
  523. #ifndef SQLITE_OMIT_TRIGGER
  524. int sqlite3FixTriggerStep(
  525. DbFixer *pFix, /* Context of the fixation */
  526. TriggerStep *pStep /* The trigger step be fixed to one database */
  527. ){
  528. while( pStep ){
  529. if( sqlite3FixSelect(pFix, pStep->pSelect) ){
  530. return 1;
  531. }
  532. if( sqlite3FixExpr(pFix, pStep->pWhere) ){
  533. return 1;
  534. }
  535. if( sqlite3FixExprList(pFix, pStep->pExprList) ){
  536. return 1;
  537. }
  538. pStep = pStep->pNext;
  539. }
  540. return 0;
  541. }
  542. #endif