Пример #1
0
/*
** The pExpr should be a TK_COLUMN expression.  The table referred to
** is in pTabList or else it is the NEW or OLD table of a trigger.  
** Check to see if it is OK to read this particular column.
**
** If the auth function returns SQLITE_IGNORE, change the TK_COLUMN 
** instruction into a TK_NULL.  If the auth function returns SQLITE_DENY,
** then generate an error.
*/
void sqliteAuthRead(
  Parse *pParse,        /* The parser context */
  Expr *pExpr,          /* The expression to check authorization on */
  SrcList *pTabList     /* All table that pExpr might refer to */
){
  sqlite *db = pParse->db;
  int rc;
  Table *pTab;          /* The table being read */
  const char *zCol;     /* Name of the column of the table */
  int iSrc;             /* Index in pTabList->a[] of table being read */
  const char *zDBase;   /* Name of database being accessed */

  if( db->xAuth==0 ) return;
  assert( pExpr->op==TK_COLUMN );
  for(iSrc=0; iSrc<pTabList->nSrc; iSrc++){
    if( pExpr->iTable==pTabList->a[iSrc].iCursor ) break;
  }
  if( iSrc>=0 && iSrc<pTabList->nSrc ){
    pTab = pTabList->a[iSrc].pTab;
  }else{
    /* This must be an attempt to read the NEW or OLD pseudo-tables
    ** of a trigger.
    */
    TriggerStack *pStack; /* The stack of current triggers */
    pStack = pParse->trigStack;
    assert( pStack!=0 );
    assert( pExpr->iTable==pStack->newIdx || pExpr->iTable==pStack->oldIdx );
    pTab = pStack->pTab;
  }
  if( pTab==0 ) return;
  if( pExpr->iColumn>=0 ){
    assert( pExpr->iColumn<pTab->nCol );
    zCol = pTab->aCol[pExpr->iColumn].zName;
  }else if( pTab->iPKey>=0 ){
    assert( pTab->iPKey<pTab->nCol );
    zCol = pTab->aCol[pTab->iPKey].zName;
  }else{
    zCol = "ROWID";
  }
  assert( pExpr->iDb<db->nDb );
  zDBase = db->aDb[pExpr->iDb].zName;
  rc = db->xAuth(db->pAuthArg, SQLITE_READ, pTab->zName, zCol, zDBase, 
                 pParse->zAuthContext);
  if( rc==SQLITE_IGNORE ){
    pExpr->op = TK_NULL;
  }else if( rc==SQLITE_DENY ){
    if( db->nDb>2 || pExpr->iDb!=0 ){
      sqliteSetString(&pParse->zErrMsg,"access to ", zDBase, ".",
          pTab->zName, ".", zCol, " is prohibited", 0);
    }else{
      sqliteSetString(&pParse->zErrMsg,"access to ", pTab->zName, ".",
                      zCol, " is prohibited", 0);
    }
    pParse->nErr++;
    pParse->rc = SQLITE_AUTH;
  }else if( rc!=SQLITE_OK ){
    sqliteAuthBadReturnCode(pParse, rc);
  }
}
Пример #2
0
/*
** Initialize all database files - the main database file, the file
** used to store temporary tables, and any additional database files
** created using ATTACH statements.  Return a success code.  If an
** error occurs, write an error message into *pzErrMsg.
**
** After the database is initialized, the SQLITE_Initialized
** bit is set in the flags field of the sqlite structure.  An
** attempt is made to initialize the database as soon as it
** is opened.  If that fails (perhaps because another process
** has the sqlite_master table locked) than another attempt
** is made the first time the database is accessed.
*/
int sqliteInit(sqlite *db, char **pzErrMsg){
  int i, rc;
  
  if( db->init.busy ) return SQLITE_OK;
  assert( (db->flags & SQLITE_Initialized)==0 );
  rc = SQLITE_OK;
  db->init.busy = 1;
  for(i=0; rc==SQLITE_OK && i<db->nDb; i++){
    if( DbHasProperty(db, i, DB_SchemaLoaded) ) continue;
    assert( i!=1 );  /* Should have been initialized together with 0 */
    rc = sqliteInitOne(db, i, pzErrMsg);
    if( rc ){
      sqliteResetInternalSchema(db, i);
    }
  }
  db->init.busy = 0;
  if( rc==SQLITE_OK ){
    db->flags |= SQLITE_Initialized;
    sqliteCommitInternalChanges(db);
  }

  /* If the database is in formats 1 or 2, then upgrade it to
  ** version 3.  This will reconstruct all indices.  If the
  ** upgrade fails for any reason (ex: out of disk space, database
  ** is read only, interrupt received, etc.) then fail the init.
  */
  if( rc==SQLITE_OK && db->file_format<3 ){
    char *zErr = 0;
    InitData initData;
    int meta[SQLITE_N_BTREE_META];

    db->magic = SQLITE_MAGIC_OPEN;
    initData.db = db;
    initData.pzErrMsg = &zErr;
    db->file_format = 3;
    rc = sqlite_exec(db,
      "BEGIN; SELECT name FROM sqlite_master WHERE type='table';",
      upgrade_3_callback,
      &initData,
      &zErr);
    if( rc==SQLITE_OK ){
      sqliteBtreeGetMeta(db->aDb[0].pBt, meta);
      meta[2] = 4;
      sqliteBtreeUpdateMeta(db->aDb[0].pBt, meta);
      sqlite_exec(db, "COMMIT", 0, 0, 0);
    }
    if( rc!=SQLITE_OK ){
      sqliteSetString(pzErrMsg, 
        "unable to upgrade database to the version 2.6 format",
        zErr ? ": " : 0, zErr, (char*)0);
    }
    sqlite_freemem(zErr);
  }

  if( rc!=SQLITE_OK ){
    db->flags &= ~SQLITE_Initialized;
  }
  return rc;
}
Пример #3
0
/*
** Write an error message into pParse->zErrMsg that explains that the
** user-supplied authorization function returned an illegal value.
*/
static void sqliteAuthBadReturnCode(Parse *pParse, int rc){
  char zBuf[20];
  sprintf(zBuf, "(%d)", rc);
  sqliteSetString(&pParse->zErrMsg, "illegal return value ", zBuf,
    " from the authorization function - should be SQLITE_OK, "
    "SQLITE_IGNORE, or SQLITE_DENY", 0);
  pParse->nErr++;
  pParse->rc = SQLITE_MISUSE;
}
Пример #4
0
/*
 * A string-manipulation helper function for check_redblack_tree(). If (orig ==
 * NULL) a copy of val is returned. If (orig != NULL) then a copy of the *
 * concatenation of orig and val is returned. The original orig is deleted
 * (using sqliteFree()).
 */
static char *append_val(char * orig, char const * val){
  char *z;
  if( !orig ){
    z = sqliteStrDup( val );
  } else{
    z = 0;
    sqliteSetString(&z, orig, val, (char*)0);
    sqliteFree( orig );
  }
  return z;
}
Пример #5
0
/*
** Give a listing of the program in the virtual machine.
**
** The interface is the same as sqliteVdbeExec().  But instead of
** running the code, it invokes the callback once for each instruction.
** This feature is used to implement "EXPLAIN".
*/
int sqliteVdbeList(
  Vdbe *p                   /* The VDBE */
){
  sqlite *db = p->db;
  int i;
  int rc = SQLITE_OK;
  static char *azColumnNames[] = {
     "addr", "opcode", "p1",  "p2",  "p3", 
     "int",  "text",   "int", "int", "text",
     0
  };

  assert( p->popStack==0 );
  assert( p->explain );
  p->azColName = azColumnNames;
  p->azResColumn = p->zArgv;
  for(i=0; i<5; i++) p->zArgv[i] = p->aStack[i].zShort;
  i = p->pc;
  if( i>=p->nOp ){
    p->rc = SQLITE_OK;
    rc = SQLITE_DONE;
  }else if( db->flags & SQLITE_Interrupt ){
    db->flags &= ~SQLITE_Interrupt;
    if( db->magic!=SQLITE_MAGIC_BUSY ){
      p->rc = SQLITE_MISUSE;
    }else{
      p->rc = SQLITE_INTERRUPT;
    }
    rc = SQLITE_ERROR;
    sqliteSetString(&p->zErrMsg, sqlite_error_string(p->rc), (char*)0);
  }else{
    sprintf(p->zArgv[0],"%d",i);
    sprintf(p->zArgv[2],"%d", p->aOp[i].p1);
    sprintf(p->zArgv[3],"%d", p->aOp[i].p2);
    if( p->aOp[i].p3type==P3_POINTER ){
      sprintf(p->aStack[4].zShort, "ptr(%#x)", (int)p->aOp[i].p3);
      p->zArgv[4] = p->aStack[4].zShort;
    }else{
      p->zArgv[4] = p->aOp[i].p3;
    }
    p->zArgv[1] = sqliteOpcodeNames[p->aOp[i].opcode];
    p->pc = i+1;
    p->azResColumn = p->zArgv;
    p->nResColumn = 5;
    p->rc = SQLITE_OK;
    rc = SQLITE_ROW;
  }
  return rc;
}
Пример #6
0
/*
** Clean up and delete a VDBE after execution.  Return an integer which is
** the result code.  Write any error message text into *pzErrMsg.
*/
int sqliteVdbeFinalize(Vdbe *p, char **pzErrMsg){
  int rc;
  sqlite *db;

  if( p->magic!=VDBE_MAGIC_RUN && p->magic!=VDBE_MAGIC_HALT ){
    sqliteSetString(pzErrMsg, sqlite_error_string(SQLITE_MISUSE), (char*)0);
    return SQLITE_MISUSE;
  }
  db = p->db;
  rc = sqliteVdbeReset(p, pzErrMsg);
  sqliteVdbeDelete(p);
  if( db->want_to_close && db->pVdbe==0 ){
    sqlite_close(db);
  }
  if( rc==SQLITE_SCHEMA ){
    sqliteResetInternalSchema(db, 0);
  }
  return rc;
}
Пример #7
0
/*
** Do an authorization check using the code and arguments given.  Return
** either SQLITE_OK (zero) or SQLITE_IGNORE or SQLITE_DENY.  If SQLITE_DENY
** is returned, then the error count and error message in pParse are
** modified appropriately.
*/
int sqliteAuthCheck(
  Parse *pParse,
  int code,
  const char *zArg1,
  const char *zArg2,
  const char *zArg3
){
  sqlite *db = pParse->db;
  int rc;

  if( db->xAuth==0 ){
    return SQLITE_OK;
  }
  rc = db->xAuth(db->pAuthArg, code, zArg1, zArg2, zArg3, pParse->zAuthContext);
  if( rc==SQLITE_DENY ){
    sqliteSetString(&pParse->zErrMsg, "not authorized", 0);
    pParse->rc = SQLITE_AUTH;
    pParse->nErr++;
  }else if( rc!=SQLITE_OK && rc!=SQLITE_IGNORE ){
    rc = SQLITE_DENY;
    sqliteAuthBadReturnCode(pParse, rc);
  }
  return rc;
}
Пример #8
0
/*
** Run the parser on the given SQL string.  The parser structure is
** passed in.  An SQLITE_ status code is returned.  If an error occurs
** and pzErrMsg!=NULL then an error message might be written into 
** memory obtained from malloc() and *pzErrMsg made to point to that
** error message.  Or maybe not.
*/
int sqliteRunParser(Parse *pParse, const char *zSql, char **pzErrMsg){
  int nErr = 0;
  int i;
  void *pEngine;
  int tokenType;
  int lastTokenParsed = -1;
  sqlite *db = pParse->db;
  extern void *sqliteParserAlloc(void*(*)(int));
  extern void sqliteParserFree(void*, void(*)(void*));
  extern int sqliteParser(void*, int, Token, Parse*);

  db->flags &= ~SQLITE_Interrupt;
  pParse->rc = SQLITE_OK;
  i = 0;
  pEngine = sqliteParserAlloc((void*(*)(int))malloc);
  if( pEngine==0 ){
    sqliteSetString(pzErrMsg, "out of memory", (char*)0);
    return 1;
  }
  pParse->sLastToken.dyn = 0;
  pParse->zTail = zSql;
  while( sqlite_malloc_failed==0 && zSql[i]!=0 ){
    assert( i>=0 );
    pParse->sLastToken.z = &zSql[i];
    assert( pParse->sLastToken.dyn==0 );
    pParse->sLastToken.n = sqliteGetToken((unsigned char*)&zSql[i], &tokenType);
    i += pParse->sLastToken.n;
    switch( tokenType ){
      case TK_SPACE:
      case TK_COMMENT: {
        if( (db->flags & SQLITE_Interrupt)!=0 ){
          pParse->rc = SQLITE_INTERRUPT;
          sqliteSetString(pzErrMsg, "interrupt", (char*)0);
          goto abort_parse;
        }
        break;
      }
      case TK_ILLEGAL: {
        sqliteSetNString(pzErrMsg, "unrecognized token: \"", -1, 
           pParse->sLastToken.z, pParse->sLastToken.n, "\"", 1, 0);
        nErr++;
        goto abort_parse;
      }
      case TK_SEMI: {
        pParse->zTail = &zSql[i];
        /* Fall thru into the default case */
      }
      default: {
        sqliteParser(pEngine, tokenType, pParse->sLastToken, pParse);
        lastTokenParsed = tokenType;
        if( pParse->rc!=SQLITE_OK ){
          goto abort_parse;
        }
        break;
      }
    }
  }
abort_parse:
  if( zSql[i]==0 && nErr==0 && pParse->rc==SQLITE_OK ){
    if( lastTokenParsed!=TK_SEMI ){
      sqliteParser(pEngine, TK_SEMI, pParse->sLastToken, pParse);
      pParse->zTail = &zSql[i];
    }
    sqliteParser(pEngine, 0, pParse->sLastToken, pParse);
  }
  sqliteParserFree(pEngine, free);
  if( pParse->rc!=SQLITE_OK && pParse->rc!=SQLITE_DONE && pParse->zErrMsg==0 ){
    sqliteSetString(&pParse->zErrMsg, sqlite_error_string(pParse->rc),
                    (char*)0);
  }
  if( pParse->zErrMsg ){
    if( pzErrMsg && *pzErrMsg==0 ){
      *pzErrMsg = pParse->zErrMsg;
    }else{
      sqliteFree(pParse->zErrMsg);
    }
    pParse->zErrMsg = 0;
    if( !nErr ) nErr++;
  }
  if( pParse->pVdbe && pParse->nErr>0 ){
    sqliteVdbeDelete(pParse->pVdbe);
    pParse->pVdbe = 0;
  }
  if( pParse->pNewTable ){
    sqliteDeleteTable(pParse->db, pParse->pNewTable);
    pParse->pNewTable = 0;
  }
  if( pParse->pNewTrigger ){
    sqliteDeleteTrigger(pParse->pNewTrigger);
    pParse->pNewTrigger = 0;
  }
  if( nErr>0 && (pParse->rc==SQLITE_OK || pParse->rc==SQLITE_DONE) ){
    pParse->rc = SQLITE_ERROR;
  }
  return nErr;
}
Пример #9
0
/*
** Compile a single statement of SQL into a virtual machine.  Return one
** of the SQLITE_ success/failure codes.  Also write an error message into
** memory obtained from malloc() and make *pzErrMsg point to that message.
*/
int sqlite_compile(
  sqlite *db,                 /* The database on which the SQL executes */
  const char *zSql,           /* The SQL to be executed */
  const char **pzTail,        /* OUT: Next statement after the first */
  sqlite_vm **ppVm,           /* OUT: The virtual machine */
  char **pzErrMsg             /* OUT: Write error messages here */
){
  Parse sParse;

  if( pzErrMsg ) *pzErrMsg = 0;
  if( sqliteSafetyOn(db) ) goto exec_misuse;
  if( !db->init.busy ){
    if( (db->flags & SQLITE_Initialized)==0 ){
      int rc, cnt = 1;
      while( (rc = sqliteInit(db, pzErrMsg))==SQLITE_BUSY
         && db->xBusyCallback
         && db->xBusyCallback(db->pBusyArg, "", cnt++)!=0 ){}
      if( rc!=SQLITE_OK ){
        sqliteStrRealloc(pzErrMsg);
        sqliteSafetyOff(db);
        return rc;
      }
      if( pzErrMsg ){
        sqliteFree(*pzErrMsg);
        *pzErrMsg = 0;
      }
    }
    if( db->file_format<3 ){
      sqliteSafetyOff(db);
      sqliteSetString(pzErrMsg, "obsolete database file format", (char*)0);
      return SQLITE_ERROR;
    }
  }
  assert( (db->flags & SQLITE_Initialized)!=0 || db->init.busy );
  if( db->pVdbe==0 ){ db->nChange = 0; }
  memset(&sParse, 0, sizeof(sParse));
  sParse.db = db;
  sqliteRunParser(&sParse, zSql, pzErrMsg);
  if( db->xTrace && !db->init.busy ){
    /* Trace only the statment that was compiled.
    ** Make a copy of that part of the SQL string since zSQL is const
    ** and we must pass a zero terminated string to the trace function
    ** The copy is unnecessary if the tail pointer is pointing at the
    ** beginnig or end of the SQL string.
    */
    if( sParse.zTail && sParse.zTail!=zSql && *sParse.zTail ){
      char *tmpSql = sqliteStrNDup(zSql, sParse.zTail - zSql);
      if( tmpSql ){
        db->xTrace(db->pTraceArg, tmpSql);
        free(tmpSql);
      }else{
        /* If a memory error occurred during the copy,
        ** trace entire SQL string and fall through to the
        ** sqlite_malloc_failed test to report the error.
        */
        db->xTrace(db->pTraceArg, zSql); 
      }
    }else{
      db->xTrace(db->pTraceArg, zSql); 
    }
  }
  if( sqlite_malloc_failed ){
    sqliteSetString(pzErrMsg, "out of memory", (char*)0);
    sParse.rc = SQLITE_NOMEM;
    sqliteRollbackAll(db);
    sqliteResetInternalSchema(db, 0);
    db->flags &= ~SQLITE_InTrans;
  }
  if( sParse.rc==SQLITE_DONE ) sParse.rc = SQLITE_OK;
  if( sParse.rc!=SQLITE_OK && pzErrMsg && *pzErrMsg==0 ){
    sqliteSetString(pzErrMsg, sqlite_error_string(sParse.rc), (char*)0);
  }
  sqliteStrRealloc(pzErrMsg);
  if( sParse.rc==SQLITE_SCHEMA ){
    sqliteResetInternalSchema(db, 0);
  }
  assert( ppVm );
  *ppVm = (sqlite_vm*)sParse.pVdbe;
  if( pzTail ) *pzTail = sParse.zTail;
  if( sqliteSafetyOff(db) ) goto exec_misuse;
  return sParse.rc;

exec_misuse:
  if( pzErrMsg ){
    *pzErrMsg = 0;
    sqliteSetString(pzErrMsg, sqlite_error_string(SQLITE_MISUSE), (char*)0);
    sqliteStrRealloc(pzErrMsg);
  }
  return SQLITE_MISUSE;
}
Пример #10
0
/*
** Open a new SQLite database.  Construct an "sqlite" structure to define
** the state of this database and return a pointer to that structure.
**
** An attempt is made to initialize the in-memory data structures that
** hold the database schema.  But if this fails (because the schema file
** is locked) then that step is deferred until the first call to
** sqlite_exec().
*/
sqlite *sqlite_open(const char *zFilename, int mode, char **pzErrMsg){
  sqlite *db;
  int rc, i;

  /* Allocate the sqlite data structure */
  db = sqliteMalloc( sizeof(sqlite) );
  if( pzErrMsg ) *pzErrMsg = 0;
  if( db==0 ) goto no_mem_on_open;
  db->onError = OE_Default;
  db->priorNewRowid = 0;
  db->magic = SQLITE_MAGIC_BUSY;
  db->nDb = 2;
  db->aDb = db->aDbStatic;
  /* db->flags |= SQLITE_ShortColNames; */
  sqliteHashInit(&db->aFunc, SQLITE_HASH_STRING, 1);
  for(i=0; i<db->nDb; i++){
    sqliteHashInit(&db->aDb[i].tblHash, SQLITE_HASH_STRING, 0);
    sqliteHashInit(&db->aDb[i].idxHash, SQLITE_HASH_STRING, 0);
    sqliteHashInit(&db->aDb[i].trigHash, SQLITE_HASH_STRING, 0);
    sqliteHashInit(&db->aDb[i].aFKey, SQLITE_HASH_STRING, 1);
  }
  
  /* Open the backend database driver */
  if( zFilename[0]==':' && strcmp(zFilename,":memory:")==0 ){
    db->temp_store = 2;
  }
  rc = sqliteBtreeFactory(db, zFilename, 0, MAX_PAGES, &db->aDb[0].pBt);
  if( rc!=SQLITE_OK ){
    switch( rc ){
      default: {
        sqliteSetString(pzErrMsg, "unable to open database: ",
           zFilename, (char*)0);
      }
    }
    sqliteFree(db);
    sqliteStrRealloc(pzErrMsg);
    return 0;
  }
  db->aDb[0].zName = "main";
  db->aDb[1].zName = "temp";

  /* Attempt to read the schema */
  sqliteRegisterBuiltinFunctions(db);
  rc = sqliteInit(db, pzErrMsg);
  db->magic = SQLITE_MAGIC_OPEN;
  if( sqlite_malloc_failed ){
    sqlite_close(db);
    goto no_mem_on_open;
  }else if( rc!=SQLITE_OK && rc!=SQLITE_BUSY ){
    sqlite_close(db);
    sqliteStrRealloc(pzErrMsg);
    return 0;
  }else if( pzErrMsg ){
    sqliteFree(*pzErrMsg);
    *pzErrMsg = 0;
  }

  /* Return a pointer to the newly opened database structure */
  return db;

no_mem_on_open:
  sqliteSetString(pzErrMsg, "out of memory", (char*)0);
  sqliteStrRealloc(pzErrMsg);
  return 0;
}
Пример #11
0
/*
** Fill the InitData structure with an error message that indicates
** that the database is corrupt.
*/
static void corruptSchema(InitData *pData, const char *zExtra){
  sqliteSetString(pData->pzErrMsg, "malformed database schema",
     zExtra!=0 && zExtra[0]!=0 ? " - " : (char*)0, zExtra, (char*)0);
}
Пример #12
0
/*
** Attempt to read the database schema and initialize internal
** data structures for a single database file.  The index of the
** database file is given by iDb.  iDb==0 is used for the main
** database.  iDb==1 should never be used.  iDb>=2 is used for
** auxiliary databases.  Return one of the SQLITE_ error codes to
** indicate success or failure.
*/
static int sqliteInitOne(sqlite *db, int iDb, char **pzErrMsg){
  int rc;
  BtCursor *curMain;
  int size;
  Table *pTab;
  char const *azArg[6];
  char zDbNum[30];
  int meta[SQLITE_N_BTREE_META];
  InitData initData;
  char const *zMasterSchema;
  char const *zMasterName;
  char *zSql = 0;

  /*
  ** The master database table has a structure like this
  */
  static char master_schema[] = 
     "CREATE TABLE sqlite_master(\n"
     "  type text,\n"
     "  name text,\n"
     "  tbl_name text,\n"
     "  rootpage integer,\n"
     "  sql text\n"
     ")"
  ;
  static char temp_master_schema[] = 
     "CREATE TEMP TABLE sqlite_temp_master(\n"
     "  type text,\n"
     "  name text,\n"
     "  tbl_name text,\n"
     "  rootpage integer,\n"
     "  sql text\n"
     ")"
  ;

  assert( iDb>=0 && iDb<db->nDb );

  /* zMasterSchema and zInitScript are set to point at the master schema
  ** and initialisation script appropriate for the database being
  ** initialised. zMasterName is the name of the master table.
  */
  if( iDb==1 ){
    zMasterSchema = temp_master_schema;
    zMasterName = TEMP_MASTER_NAME;
  }else{
    zMasterSchema = master_schema;
    zMasterName = MASTER_NAME;
  }

  /* Construct the schema table.
  */
  sqliteSafetyOff(db);
  azArg[0] = "table";
  azArg[1] = zMasterName;
  azArg[2] = "2";
  azArg[3] = zMasterSchema;
  sprintf(zDbNum, "%d", iDb);
  azArg[4] = zDbNum;
  azArg[5] = 0;
  initData.db = db;
  initData.pzErrMsg = pzErrMsg;
  sqliteInitCallback(&initData, 5, (char **)azArg, 0);
  pTab = sqliteFindTable(db, zMasterName, db->aDb[iDb].zName);
  if( pTab ){
    pTab->readOnly = 1;
  }else{
    return SQLITE_NOMEM;
  }
  sqliteSafetyOn(db);

  /* Create a cursor to hold the database open
  */
  if( db->aDb[iDb].pBt==0 ) return SQLITE_OK;
  rc = sqliteBtreeCursor(db->aDb[iDb].pBt, 2, 0, &curMain);
  if( rc ){
    sqliteSetString(pzErrMsg, sqlite_error_string(rc), (char*)0);
    return rc;
  }

  /* Get the database meta information
  */
  rc = sqliteBtreeGetMeta(db->aDb[iDb].pBt, meta);
  if( rc ){
    sqliteSetString(pzErrMsg, sqlite_error_string(rc), (char*)0);
    sqliteBtreeCloseCursor(curMain);
    return rc;
  }
  db->aDb[iDb].schema_cookie = meta[1];
  if( iDb==0 ){
    db->next_cookie = meta[1];
    db->file_format = meta[2];
    size = meta[3];
    if( size==0 ){ size = MAX_PAGES; }
    db->cache_size = size;
    db->safety_level = meta[4];
    if( meta[6]>0 && meta[6]<=2 && db->temp_store==0 ){
      db->temp_store = meta[6];
    }
    if( db->safety_level==0 ) db->safety_level = 2;

    /*
    **  file_format==1    Version 2.1.0.
    **  file_format==2    Version 2.2.0. Add support for INTEGER PRIMARY KEY.
    **  file_format==3    Version 2.6.0. Fix empty-string index bug.
    **  file_format==4    Version 2.7.0. Add support for separate numeric and
    **                    text datatypes.
    */
    if( db->file_format==0 ){
      /* This happens if the database was initially empty */
      db->file_format = 4;
    }else if( db->file_format>4 ){
      sqliteBtreeCloseCursor(curMain);
      sqliteSetString(pzErrMsg, "unsupported file format", (char*)0);
      return SQLITE_ERROR;
    }
  }else if( iDb!=1 && (db->file_format!=meta[2] || db->file_format<4) ){
    assert( db->file_format>=4 );
    if( meta[2]==0 ){
      sqliteSetString(pzErrMsg, "cannot attach empty database: ",
         db->aDb[iDb].zName, (char*)0);
    }else{
      sqliteSetString(pzErrMsg, "incompatible file format in auxiliary "
         "database: ", db->aDb[iDb].zName, (char*)0);
    }
    sqliteBtreeClose(db->aDb[iDb].pBt);
    db->aDb[iDb].pBt = 0;
    return SQLITE_FORMAT;
  }
  sqliteBtreeSetCacheSize(db->aDb[iDb].pBt, db->cache_size);
  sqliteBtreeSetSafetyLevel(db->aDb[iDb].pBt, meta[4]==0 ? 2 : meta[4]);

  /* Read the schema information out of the schema tables
  */
  assert( db->init.busy );
  sqliteSafetyOff(db);

  /* The following SQL will read the schema from the master tables.
  ** The first version works with SQLite file formats 2 or greater.
  ** The second version is for format 1 files.
  **
  ** Beginning with file format 2, the rowid for new table entries
  ** (including entries in sqlite_master) is an increasing integer.
  ** So for file format 2 and later, we can play back sqlite_master
  ** and all the CREATE statements will appear in the right order.
  ** But with file format 1, table entries were random and so we
  ** have to make sure the CREATE TABLEs occur before their corresponding
  ** CREATE INDEXs.  (We don't have to deal with CREATE VIEW or
  ** CREATE TRIGGER in file format 1 because those constructs did
  ** not exist then.) 
  */
  if( db->file_format>=2 ){
    sqliteSetString(&zSql, 
        "SELECT type, name, rootpage, sql, ", zDbNum, " FROM \"",
       db->aDb[iDb].zName, "\".", zMasterName, (char*)0);
  }else{
    sqliteSetString(&zSql, 
        "SELECT type, name, rootpage, sql, ", zDbNum, " FROM \"",
       db->aDb[iDb].zName, "\".", zMasterName, 
       " WHERE type IN ('table', 'index')"
       " ORDER BY CASE type WHEN 'table' THEN 0 ELSE 1 END", (char*)0);
  }
  rc = sqlite_exec(db, zSql, sqliteInitCallback, &initData, 0);

  sqliteFree(zSql);
  sqliteSafetyOn(db);
  sqliteBtreeCloseCursor(curMain);
  if( sqlite_malloc_failed ){
    sqliteSetString(pzErrMsg, "out of memory", (char*)0);
    rc = SQLITE_NOMEM;
    sqliteResetInternalSchema(db, 0);
  }
  if( rc==SQLITE_OK ){
    DbSetProperty(db, iDb, DB_SchemaLoaded);
  }else{
    sqliteResetInternalSchema(db, iDb);
  }
  return rc;
}
Пример #13
0
/*
** Clean up a VDBE after execution but do not delete the VDBE just yet.
** Write any error messages into *pzErrMsg.  Return the result code.
**
** After this routine is run, the VDBE should be ready to be executed
** again.
*/
int sqliteVdbeReset(Vdbe *p, char **pzErrMsg){
  sqlite *db = p->db;
  int i;

  if( p->magic!=VDBE_MAGIC_RUN && p->magic!=VDBE_MAGIC_HALT ){
    sqliteSetString(pzErrMsg, sqlite_error_string(SQLITE_MISUSE), (char*)0);
    return SQLITE_MISUSE;
  }
  if( p->zErrMsg ){
    if( pzErrMsg && *pzErrMsg==0 ){
      *pzErrMsg = p->zErrMsg;
    }else{
      sqliteFree(p->zErrMsg);
    }
    p->zErrMsg = 0;
  }else if( p->rc ){
    sqliteSetString(pzErrMsg, sqlite_error_string(p->rc), (char*)0);
  }
  Cleanup(p);
  if( p->rc!=SQLITE_OK ){
    switch( p->errorAction ){
      case OE_Abort: {
        if( !p->undoTransOnError ){
          for(i=0; i<db->nDb; i++){
            if( db->aDb[i].pBt ){
              sqliteBtreeRollbackCkpt(db->aDb[i].pBt);
            }
          }
          break;
        }
        /* Fall through to ROLLBACK */
      }
      case OE_Rollback: {
        sqliteRollbackAll(db);
        db->flags &= ~SQLITE_InTrans;
        db->onError = OE_Default;
        break;
      }
      default: {
        if( p->undoTransOnError ){
          sqliteRollbackAll(db);
          db->flags &= ~SQLITE_InTrans;
          db->onError = OE_Default;
        }
        break;
      }
    }
    sqliteRollbackInternalChanges(db);
  }
  for(i=0; i<db->nDb; i++){
    if( db->aDb[i].pBt && db->aDb[i].inTrans==2 ){
      sqliteBtreeCommitCkpt(db->aDb[i].pBt);
      db->aDb[i].inTrans = 1;
    }
  }
  assert( p->pTos<&p->aStack[p->pc] || sqlite_malloc_failed==1 );
#ifdef VDBE_PROFILE
  {
    FILE *out = fopen("vdbe_profile.out", "a");
    if( out ){
      int i;
      fprintf(out, "---- ");
      for(i=0; i<p->nOp; i++){
        fprintf(out, "%02x", p->aOp[i].opcode);
      }
      fprintf(out, "\n");
      for(i=0; i<p->nOp; i++){
        fprintf(out, "%6d %10lld %8lld ",
           p->aOp[i].cnt,
           p->aOp[i].cycles,
           p->aOp[i].cnt>0 ? p->aOp[i].cycles/p->aOp[i].cnt : 0
        );
        sqliteVdbePrintOp(out, i, &p->aOp[i]);
      }
      fclose(out);
    }
  }
#endif
  p->magic = VDBE_MAGIC_INIT;
  return p->rc;
}
Пример #14
0
/*
** Generate code to do a constraint check prior to an INSERT or an UPDATE.
**
** When this routine is called, the stack contains (from bottom to top)
** the following values:
**
**    1.  The recno of the row to be updated before the update.  This
**        value is omitted unless we are doing an UPDATE that involves a
**        change to the record number.
**
**    2.  The recno of the row after the update.
**
**    3.  The data in the first column of the entry after the update.
**
**    i.  Data from middle columns...
**
**    N.  The data in the last column of the entry after the update.
**
** The old recno shown as entry (1) above is omitted unless both isUpdate
** and recnoChng are 1.  isUpdate is true for UPDATEs and false for
** INSERTs and recnoChng is true if the record number is being changed.
**
** The code generated by this routine pushes additional entries onto
** the stack which are the keys for new index entries for the new record.
** The order of index keys is the same as the order of the indices on
** the pTable->pIndex list.  A key is only created for index i if 
** aIdxUsed!=0 and aIdxUsed[i]!=0.
**
** This routine also generates code to check constraints.  NOT NULL,
** CHECK, and UNIQUE constraints are all checked.  If a constraint fails,
** then the appropriate action is performed.  There are five possible
** actions: ROLLBACK, ABORT, FAIL, REPLACE, and IGNORE.
**
**  Constraint type  Action       What Happens
**  ---------------  ----------   ----------------------------------------
**  any              ROLLBACK     The current transaction is rolled back and
**                                sqlite_exec() returns immediately with a
**                                return code of SQLITE_CONSTRAINT.
**
**  any              ABORT        Back out changes from the current command
**                                only (do not do a complete rollback) then
**                                cause sqlite_exec() to return immediately
**                                with SQLITE_CONSTRAINT.
**
**  any              FAIL         Sqlite_exec() returns immediately with a
**                                return code of SQLITE_CONSTRAINT.  The
**                                transaction is not rolled back and any
**                                prior changes are retained.
**
**  any              IGNORE       The record number and data is popped from
**                                the stack and there is an immediate jump
**                                to label ignoreDest.
**
**  NOT NULL         REPLACE      The NULL value is replace by the default
**                                value for that column.  If the default value
**                                is NULL, the action is the same as ABORT.
**
**  UNIQUE           REPLACE      The other row that conflicts with the row
**                                being inserted is removed.
**
**  CHECK            REPLACE      Illegal.  The results in an exception.
**
** Which action to take is determined by the overrideError parameter.
** Or if overrideError==OE_Default, then the pParse->onError parameter
** is used.  Or if pParse->onError==OE_Default then the onError value
** for the constraint is used.
**
** The calling routine must open a read/write cursor for pTab with
** cursor number "base".  All indices of pTab must also have open
** read/write cursors with cursor number base+i for the i-th cursor.
** Except, if there is no possibility of a REPLACE action then
** cursors do not need to be open for indices where aIdxUsed[i]==0.
**
** If the isUpdate flag is true, it means that the "base" cursor is
** initially pointing to an entry that is being updated.  The isUpdate
** flag causes extra code to be generated so that the "base" cursor
** is still pointing at the same entry after the routine returns.
** Without the isUpdate flag, the "base" cursor might be moved.
*/
void sqliteGenerateConstraintChecks(
  Parse *pParse,      /* The parser context */
  Table *pTab,        /* the table into which we are inserting */
  int base,           /* Index of a read/write cursor pointing at pTab */
  char *aIdxUsed,     /* Which indices are used.  NULL means all are used */
  int recnoChng,      /* True if the record number will change */
  int isUpdate,       /* True for UPDATE, False for INSERT */
  int overrideError,  /* Override onError to this if not OE_Default */
  int ignoreDest      /* Jump to this label on an OE_Ignore resolution */
){
  int i;
  Vdbe *v;
  int nCol;
  int onError;
  int addr;
  int extra;
  int iCur;
  Index *pIdx;
  int seenReplace = 0;
  int jumpInst1, jumpInst2;
  int contAddr;
  int hasTwoRecnos = (isUpdate && recnoChng);

  v = sqliteGetVdbe(pParse);
  assert( v!=0 );
  assert( pTab->pSelect==0 );  /* This table is not a VIEW */
  nCol = pTab->nCol;

  /* Test all NOT NULL constraints.
  */
  for(i=0; i<nCol; i++){
    if( i==pTab->iPKey ){
      continue;
    }
    onError = pTab->aCol[i].notNull;
    if( onError==OE_None ) continue;
    if( overrideError!=OE_Default ){
      onError = overrideError;
    }else if( pParse->db->onError!=OE_Default ){
      onError = pParse->db->onError;
    }else if( onError==OE_Default ){
      onError = OE_Abort;
    }
    if( onError==OE_Replace && pTab->aCol[i].zDflt==0 ){
      onError = OE_Abort;
    }
    sqliteVdbeAddOp(v, OP_Dup, nCol-1-i, 1);
    addr = sqliteVdbeAddOp(v, OP_NotNull, 1, 0);
    switch( onError ){
      case OE_Rollback:
      case OE_Abort:
      case OE_Fail: {
        char *zMsg = 0;
        sqliteVdbeAddOp(v, OP_Halt, SQLITE_CONSTRAINT, onError);
        sqliteSetString(&zMsg, pTab->zName, ".", pTab->aCol[i].zName,
                        " may not be NULL", (char*)0);
        sqliteVdbeChangeP3(v, -1, zMsg, P3_DYNAMIC);
        break;
      }
      case OE_Ignore: {
        sqliteVdbeAddOp(v, OP_Pop, nCol+1+hasTwoRecnos, 0);
        sqliteVdbeAddOp(v, OP_Goto, 0, ignoreDest);
        break;
      }
      case OE_Replace: {
        sqliteVdbeOp3(v, OP_String, 0, 0, pTab->aCol[i].zDflt, P3_STATIC);
        sqliteVdbeAddOp(v, OP_Push, nCol-i, 0);
        break;
      }
      default: assert(0);
    }
    sqliteVdbeChangeP2(v, addr, sqliteVdbeCurrentAddr(v));
  }

  /* Test all CHECK constraints
  */
  /**** TBD ****/

  /* If we have an INTEGER PRIMARY KEY, make sure the primary key
  ** of the new record does not previously exist.  Except, if this
  ** is an UPDATE and the primary key is not changing, that is OK.
  */
  if( recnoChng ){
    onError = pTab->keyConf;
    if( overrideError!=OE_Default ){
      onError = overrideError;
    }else if( pParse->db->onError!=OE_Default ){
      onError = pParse->db->onError;
    }else if( onError==OE_Default ){
      onError = OE_Abort;
    }
    
    if( isUpdate ){
      sqliteVdbeAddOp(v, OP_Dup, nCol+1, 1);
      sqliteVdbeAddOp(v, OP_Dup, nCol+1, 1);
      jumpInst1 = sqliteVdbeAddOp(v, OP_Eq, 0, 0);
    }
    sqliteVdbeAddOp(v, OP_Dup, nCol, 1);
    jumpInst2 = sqliteVdbeAddOp(v, OP_NotExists, base, 0);
    switch( onError ){
      default: {
        onError = OE_Abort;
        /* Fall thru into the next case */
      }
      case OE_Rollback:
      case OE_Abort:
      case OE_Fail: {
        sqliteVdbeOp3(v, OP_Halt, SQLITE_CONSTRAINT, onError,
                         "PRIMARY KEY must be unique", P3_STATIC);
        break;
      }
      case OE_Replace: {
        sqliteGenerateRowIndexDelete(pParse->db, v, pTab, base, 0);
        if( isUpdate ){
          sqliteVdbeAddOp(v, OP_Dup, nCol+hasTwoRecnos, 1);
          sqliteVdbeAddOp(v, OP_MoveTo, base, 0);
        }
        seenReplace = 1;
        break;
      }
      case OE_Ignore: {
        assert( seenReplace==0 );
        sqliteVdbeAddOp(v, OP_Pop, nCol+1+hasTwoRecnos, 0);
        sqliteVdbeAddOp(v, OP_Goto, 0, ignoreDest);
        break;
      }
    }
    contAddr = sqliteVdbeCurrentAddr(v);
    sqliteVdbeChangeP2(v, jumpInst2, contAddr);
    if( isUpdate ){
      sqliteVdbeChangeP2(v, jumpInst1, contAddr);
      sqliteVdbeAddOp(v, OP_Dup, nCol+1, 1);
      sqliteVdbeAddOp(v, OP_MoveTo, base, 0);
    }
  }

  /* Test all UNIQUE constraints by creating entries for each UNIQUE
  ** index and making sure that duplicate entries do not already exist.
  ** Add the new records to the indices as we go.
  */
  extra = -1;
  for(iCur=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, iCur++){
    if( aIdxUsed && aIdxUsed[iCur]==0 ) continue;  /* Skip unused indices */
    extra++;

    /* Create a key for accessing the index entry */
    sqliteVdbeAddOp(v, OP_Dup, nCol+extra, 1);
    for(i=0; i<pIdx->nColumn; i++){
      int idx = pIdx->aiColumn[i];
      if( idx==pTab->iPKey ){
        sqliteVdbeAddOp(v, OP_Dup, i+extra+nCol+1, 1);
      }else{
        sqliteVdbeAddOp(v, OP_Dup, i+extra+nCol-idx, 1);
      }
    }
    jumpInst1 = sqliteVdbeAddOp(v, OP_MakeIdxKey, pIdx->nColumn, 0);
    if( pParse->db->file_format>=4 ) sqliteAddIdxKeyType(v, pIdx);

    /* Find out what action to take in case there is an indexing conflict */
    onError = pIdx->onError;
    if( onError==OE_None ) continue;  /* pIdx is not a UNIQUE index */
    if( overrideError!=OE_Default ){
      onError = overrideError;
    }else if( pParse->db->onError!=OE_Default ){
      onError = pParse->db->onError;
    }else if( onError==OE_Default ){
      onError = OE_Abort;
    }
    if( seenReplace ){
      if( onError==OE_Ignore ) onError = OE_Replace;
      else if( onError==OE_Fail ) onError = OE_Abort;
    }
    

    /* Check to see if the new index entry will be unique */
    sqliteVdbeAddOp(v, OP_Dup, extra+nCol+1+hasTwoRecnos, 1);
    jumpInst2 = sqliteVdbeAddOp(v, OP_IsUnique, base+iCur+1, 0);

    /* Generate code that executes if the new index entry is not unique */
    switch( onError ){
      case OE_Rollback:
      case OE_Abort:
      case OE_Fail: {
        int j, n1, n2;
        char zErrMsg[200];
        strcpy(zErrMsg, pIdx->nColumn>1 ? "columns " : "column ");
        n1 = strlen(zErrMsg);
        for(j=0; j<pIdx->nColumn && n1<sizeof(zErrMsg)-30; j++){
          char *zCol = pTab->aCol[pIdx->aiColumn[j]].zName;
          n2 = strlen(zCol);
          if( j>0 ){
            strcpy(&zErrMsg[n1], ", ");
            n1 += 2;
          }
          if( n1+n2>sizeof(zErrMsg)-30 ){
            strcpy(&zErrMsg[n1], "...");
            n1 += 3;
            break;
          }else{
            strcpy(&zErrMsg[n1], zCol);
            n1 += n2;
          }
        }
        strcpy(&zErrMsg[n1], 
            pIdx->nColumn>1 ? " are not unique" : " is not unique");
        sqliteVdbeOp3(v, OP_Halt, SQLITE_CONSTRAINT, onError, zErrMsg, 0);
        break;
      }
      case OE_Ignore: {
        assert( seenReplace==0 );
        sqliteVdbeAddOp(v, OP_Pop, nCol+extra+3+hasTwoRecnos, 0);
        sqliteVdbeAddOp(v, OP_Goto, 0, ignoreDest);
        break;
      }
      case OE_Replace: {
        sqliteGenerateRowDelete(pParse->db, v, pTab, base, 0);
        if( isUpdate ){
          sqliteVdbeAddOp(v, OP_Dup, nCol+extra+1+hasTwoRecnos, 1);
          sqliteVdbeAddOp(v, OP_MoveTo, base, 0);
        }
        seenReplace = 1;
        break;
      }
      default: assert(0);
    }
    contAddr = sqliteVdbeCurrentAddr(v);
#if NULL_DISTINCT_FOR_UNIQUE
    sqliteVdbeChangeP2(v, jumpInst1, contAddr);
#endif
    sqliteVdbeChangeP2(v, jumpInst2, contAddr);
  }
}
Пример #15
0
/*
** Generate the beginning of the loop used for WHERE clause processing.
** The return value is a pointer to an (opaque) structure that contains
** information needed to terminate the loop.  Later, the calling routine
** should invoke sqliteWhereEnd() with the return value of this function
** in order to complete the WHERE clause processing.
**
** If an error occurs, this routine returns NULL.
**
** The basic idea is to do a nested loop, one loop for each table in
** the FROM clause of a select.  (INSERT and UPDATE statements are the
** same as a SELECT with only a single table in the FROM clause.)  For
** example, if the SQL is this:
**
**       SELECT * FROM t1, t2, t3 WHERE ...;
**
** Then the code generated is conceptually like the following:
**
**      foreach row1 in t1 do       \    Code generated
**        foreach row2 in t2 do      |-- by sqliteWhereBegin()
**          foreach row3 in t3 do   /
**            ...
**          end                     \    Code generated
**        end                        |-- by sqliteWhereEnd()
**      end                         /
**
** There are Btree cursors associated with each table.  t1 uses cursor
** number pTabList->a[0].iCursor.  t2 uses the cursor pTabList->a[1].iCursor.
** And so forth.  This routine generates code to open those VDBE cursors
** and sqliteWhereEnd() generates the code to close them.
**
** If the WHERE clause is empty, the foreach loops must each scan their
** entire tables.  Thus a three-way join is an O(N^3) operation.  But if
** the tables have indices and there are terms in the WHERE clause that
** refer to those indices, a complete table scan can be avoided and the
** code will run much faster.  Most of the work of this routine is checking
** to see if there are indices that can be used to speed up the loop.
**
** Terms of the WHERE clause are also used to limit which rows actually
** make it to the "..." in the middle of the loop.  After each "foreach",
** terms of the WHERE clause that use only terms in that loop and outer
** loops are evaluated and if false a jump is made around all subsequent
** inner loops (or around the "..." if the test occurs within the inner-
** most loop)
**
** OUTER JOINS
**
** An outer join of tables t1 and t2 is conceptally coded as follows:
**
**    foreach row1 in t1 do
**      flag = 0
**      foreach row2 in t2 do
**        start:
**          ...
**          flag = 1
**      end
**      if flag==0 then
**        move the row2 cursor to a null row
**        goto start
**      fi
**    end
**
** ORDER BY CLAUSE PROCESSING
**
** *ppOrderBy is a pointer to the ORDER BY clause of a SELECT statement,
** if there is one.  If there is no ORDER BY clause or if this routine
** is called from an UPDATE or DELETE statement, then ppOrderBy is NULL.
**
** If an index can be used so that the natural output order of the table
** scan is correct for the ORDER BY clause, then that index is used and
** *ppOrderBy is set to NULL.  This is an optimization that prevents an
** unnecessary sort of the result set if an index appropriate for the
** ORDER BY clause already exists.
**
** If the where clause loops cannot be arranged to provide the correct
** output order, then the *ppOrderBy is unchanged.
*/
WhereInfo *sqliteWhereBegin(
    Parse *pParse,       /* The parser context */
    SrcList *pTabList,   /* A list of all tables to be scanned */
    Expr *pWhere,        /* The WHERE clause */
    int pushKey,         /* If TRUE, leave the table key on the stack */
    ExprList **ppOrderBy /* An ORDER BY clause, or NULL */
) {
    int i;                     /* Loop counter */
    WhereInfo *pWInfo;         /* Will become the return value of this function */
    Vdbe *v = pParse->pVdbe;   /* The virtual database engine */
    int brk, cont = 0;         /* Addresses used during code generation */
    int nExpr;           /* Number of subexpressions in the WHERE clause */
    int loopMask;        /* One bit set for each outer loop */
    int haveKey;         /* True if KEY is on the stack */
    ExprMaskSet maskSet; /* The expression mask set */
    int iDirectEq[32];   /* Term of the form ROWID==X for the N-th table */
    int iDirectLt[32];   /* Term of the form ROWID<X or ROWID<=X */
    int iDirectGt[32];   /* Term of the form ROWID>X or ROWID>=X */
    ExprInfo aExpr[101]; /* The WHERE clause is divided into these expressions */

    /* pushKey is only allowed if there is a single table (as in an INSERT or
    ** UPDATE statement)
    */
    assert( pushKey==0 || pTabList->nSrc==1 );

    /* Split the WHERE clause into separate subexpressions where each
    ** subexpression is separated by an AND operator.  If the aExpr[]
    ** array fills up, the last entry might point to an expression which
    ** contains additional unfactored AND operators.
    */
    initMaskSet(&maskSet);
    memset(aExpr, 0, sizeof(aExpr));
    nExpr = exprSplit(ARRAYSIZE(aExpr), aExpr, pWhere);
    if( nExpr==ARRAYSIZE(aExpr) ) {
        char zBuf[50];
        sprintf(zBuf, "%d", (int)ARRAYSIZE(aExpr)-1);
        sqliteSetString(&pParse->zErrMsg, "WHERE clause too complex - no more "
                        "than ", zBuf, " terms allowed", (char*)0);
        pParse->nErr++;
        return 0;
    }

    /* Allocate and initialize the WhereInfo structure that will become the
    ** return value.
    */
    pWInfo = sqliteMalloc( sizeof(WhereInfo) + pTabList->nSrc*sizeof(WhereLevel));
    if( sqlite_malloc_failed ) {
        sqliteFree(pWInfo);
        return 0;
    }
    pWInfo->pParse = pParse;
    pWInfo->pTabList = pTabList;
    pWInfo->peakNTab = pWInfo->savedNTab = pParse->nTab;
    pWInfo->iBreak = sqliteVdbeMakeLabel(v);

    /* Special case: a WHERE clause that is constant.  Evaluate the
    ** expression and either jump over all of the code or fall thru.
    */
    if( pWhere && (pTabList->nSrc==0 || sqliteExprIsConstant(pWhere)) ) {
        sqliteExprIfFalse(pParse, pWhere, pWInfo->iBreak, 1);
        pWhere = 0;
    }

    /* Analyze all of the subexpressions.
    */
    for(i=0; i<nExpr; i++) {
        exprAnalyze(&maskSet, &aExpr[i]);

        /* If we are executing a trigger body, remove all references to
        ** new.* and old.* tables from the prerequisite masks.
        */
        if( pParse->trigStack ) {
            int x;
            if( (x = pParse->trigStack->newIdx) >= 0 ) {
                int mask = ~getMask(&maskSet, x);
                aExpr[i].prereqRight &= mask;
                aExpr[i].prereqLeft &= mask;
                aExpr[i].prereqAll &= mask;
            }
            if( (x = pParse->trigStack->oldIdx) >= 0 ) {
                int mask = ~getMask(&maskSet, x);
                aExpr[i].prereqRight &= mask;
                aExpr[i].prereqLeft &= mask;
                aExpr[i].prereqAll &= mask;
            }
        }
    }

    /* Figure out what index to use (if any) for each nested loop.
    ** Make pWInfo->a[i].pIdx point to the index to use for the i-th nested
    ** loop where i==0 is the outer loop and i==pTabList->nSrc-1 is the inner
    ** loop.
    **
    ** If terms exist that use the ROWID of any table, then set the
    ** iDirectEq[], iDirectLt[], or iDirectGt[] elements for that table
    ** to the index of the term containing the ROWID.  We always prefer
    ** to use a ROWID which can directly access a table rather than an
    ** index which requires reading an index first to get the rowid then
    ** doing a second read of the actual database table.
    **
    ** Actually, if there are more than 32 tables in the join, only the
    ** first 32 tables are candidates for indices.  This is (again) due
    ** to the limit of 32 bits in an integer bitmask.
    */
    loopMask = 0;
    for(i=0; i<pTabList->nSrc && i<ARRAYSIZE(iDirectEq); i++) {
        int j;
        int iCur = pTabList->a[i].iCursor;    /* The cursor for this table */
        int mask = getMask(&maskSet, iCur);   /* Cursor mask for this table */
        Table *pTab = pTabList->a[i].pTab;
        Index *pIdx;
        Index *pBestIdx = 0;
        int bestScore = 0;

        /* Check to see if there is an expression that uses only the
        ** ROWID field of this table.  For terms of the form ROWID==expr
        ** set iDirectEq[i] to the index of the term.  For terms of the
        ** form ROWID<expr or ROWID<=expr set iDirectLt[i] to the term index.
        ** For terms like ROWID>expr or ROWID>=expr set iDirectGt[i].
        **
        ** (Added:) Treat ROWID IN expr like ROWID=expr.
        */
        pWInfo->a[i].iCur = -1;
        iDirectEq[i] = -1;
        iDirectLt[i] = -1;
        iDirectGt[i] = -1;
        for(j=0; j<nExpr; j++) {
            if( aExpr[j].idxLeft==iCur && aExpr[j].p->pLeft->iColumn<0
                    && (aExpr[j].prereqRight & loopMask)==aExpr[j].prereqRight ) {
                switch( aExpr[j].p->op ) {
                case TK_IN:
                case TK_EQ:
                    iDirectEq[i] = j;
                    break;
                case TK_LE:
                case TK_LT:
                    iDirectLt[i] = j;
                    break;
                case TK_GE:
                case TK_GT:
                    iDirectGt[i] = j;
                    break;
                }
            }
            if( aExpr[j].idxRight==iCur && aExpr[j].p->pRight->iColumn<0
                    && (aExpr[j].prereqLeft & loopMask)==aExpr[j].prereqLeft ) {
                switch( aExpr[j].p->op ) {
                case TK_EQ:
                    iDirectEq[i] = j;
                    break;
                case TK_LE:
                case TK_LT:
                    iDirectGt[i] = j;
                    break;
                case TK_GE:
                case TK_GT:
                    iDirectLt[i] = j;
                    break;
                }
            }
        }
        if( iDirectEq[i]>=0 ) {
            loopMask |= mask;
            pWInfo->a[i].pIdx = 0;
            continue;
        }

        /* Do a search for usable indices.  Leave pBestIdx pointing to
        ** the "best" index.  pBestIdx is left set to NULL if no indices
        ** are usable.
        **
        ** The best index is determined as follows.  For each of the
        ** left-most terms that is fixed by an equality operator, add
        ** 8 to the score.  The right-most term of the index may be
        ** constrained by an inequality.  Add 1 if for an "x<..." constraint
        ** and add 2 for an "x>..." constraint.  Chose the index that
        ** gives the best score.
        **
        ** This scoring system is designed so that the score can later be
        ** used to determine how the index is used.  If the score&7 is 0
        ** then all constraints are equalities.  If score&1 is not 0 then
        ** there is an inequality used as a termination key.  (ex: "x<...")
        ** If score&2 is not 0 then there is an inequality used as the
        ** start key.  (ex: "x>...").  A score or 4 is the special case
        ** of an IN operator constraint.  (ex:  "x IN ...").
        **
        ** The IN operator (as in "<expr> IN (...)") is treated the same as
        ** an equality comparison except that it can only be used on the
        ** left-most column of an index and other terms of the WHERE clause
        ** cannot be used in conjunction with the IN operator to help satisfy
        ** other columns of the index.
        */
        for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext) {
            int eqMask = 0;  /* Index columns covered by an x=... term */
            int ltMask = 0;  /* Index columns covered by an x<... term */
            int gtMask = 0;  /* Index columns covered by an x>... term */
            int inMask = 0;  /* Index columns covered by an x IN .. term */
            int nEq, m, score;

            if( pIdx->nColumn>32 ) continue;  /* Ignore indices too many columns */
            for(j=0; j<nExpr; j++) {
                if( aExpr[j].idxLeft==iCur
                        && (aExpr[j].prereqRight & loopMask)==aExpr[j].prereqRight ) {
                    int iColumn = aExpr[j].p->pLeft->iColumn;
                    int k;
                    for(k=0; k<pIdx->nColumn; k++) {
                        if( pIdx->aiColumn[k]==iColumn ) {
                            switch( aExpr[j].p->op ) {
                            case TK_IN: {
                                if( k==0 ) inMask |= 1;
                                break;
                            }
                            case TK_EQ: {
                                eqMask |= 1<<k;
                                break;
                            }
                            case TK_LE:
                            case TK_LT: {
                                ltMask |= 1<<k;
                                break;
                            }
                            case TK_GE:
                            case TK_GT: {
                                gtMask |= 1<<k;
                                break;
                            }
                            default: {
                                /* CANT_HAPPEN */
                                assert( 0 );
                                break;
                            }
                            }
                            break;
                        }
                    }
                }
                if( aExpr[j].idxRight==iCur
                        && (aExpr[j].prereqLeft & loopMask)==aExpr[j].prereqLeft ) {
                    int iColumn = aExpr[j].p->pRight->iColumn;
                    int k;
                    for(k=0; k<pIdx->nColumn; k++) {
                        if( pIdx->aiColumn[k]==iColumn ) {
                            switch( aExpr[j].p->op ) {
                            case TK_EQ: {
                                eqMask |= 1<<k;
                                break;
                            }
                            case TK_LE:
                            case TK_LT: {
                                gtMask |= 1<<k;
                                break;
                            }
                            case TK_GE:
                            case TK_GT: {
                                ltMask |= 1<<k;
                                break;
                            }
                            default: {
                                /* CANT_HAPPEN */
                                assert( 0 );
                                break;
                            }
                            }
                            break;
                        }
                    }
                }
            }

            /* The following loop ends with nEq set to the number of columns
            ** on the left of the index with == constraints.
            */
            for(nEq=0; nEq<pIdx->nColumn; nEq++) {
                m = (1<<(nEq+1))-1;
                if( (m & eqMask)!=m ) break;
            }
            score = nEq*8;   /* Base score is 8 times number of == constraints */
            m = 1<<nEq;
            if( m & ltMask ) score++;    /* Increase score for a < constraint */
            if( m & gtMask ) score+=2;   /* Increase score for a > constraint */
            if( score==0 && inMask ) score = 4;  /* Default score for IN constraint */
            if( score>bestScore ) {
                pBestIdx = pIdx;
                bestScore = score;
            }
        }
        pWInfo->a[i].pIdx = pBestIdx;
        pWInfo->a[i].score = bestScore;
        pWInfo->a[i].bRev = 0;
        loopMask |= mask;
        if( pBestIdx ) {
            pWInfo->a[i].iCur = pParse->nTab++;
            pWInfo->peakNTab = pParse->nTab;
        }
    }

    /* Check to see if the ORDER BY clause is or can be satisfied by the
    ** use of an index on the first table.
    */
    if( ppOrderBy && *ppOrderBy && pTabList->nSrc>0 ) {
        Index *pSortIdx;
        Index *pIdx;
        Table *pTab;
        int bRev = 0;

        pTab = pTabList->a[0].pTab;
        pIdx = pWInfo->a[0].pIdx;
        if( pIdx && pWInfo->a[0].score==4 ) {
            /* If there is already an IN index on the left-most table,
            ** it will not give the correct sort order.
            ** So, pretend that no suitable index is found.
            */
            pSortIdx = 0;
        } else if( iDirectEq[0]>=0 || iDirectLt[0]>=0 || iDirectGt[0]>=0 ) {
            /* If the left-most column is accessed using its ROWID, then do
            ** not try to sort by index.
            */
            pSortIdx = 0;
        } else {
            int nEqCol = (pWInfo->a[0].score+4)/8;
            pSortIdx = findSortingIndex(pTab, pTabList->a[0].iCursor,
                                        *ppOrderBy, pIdx, nEqCol, &bRev);
        }
        if( pSortIdx && (pIdx==0 || pIdx==pSortIdx) ) {
            if( pIdx==0 ) {
                pWInfo->a[0].pIdx = pSortIdx;
                pWInfo->a[0].iCur = pParse->nTab++;
                pWInfo->peakNTab = pParse->nTab;
            }
            pWInfo->a[0].bRev = bRev;
            *ppOrderBy = 0;
        }
    }

    /* Open all tables in the pTabList and all indices used by those tables.
    */
    for(i=0; i<pTabList->nSrc; i++) {
        Table *pTab;

        pTab = pTabList->a[i].pTab;
        if( pTab->isTransient || pTab->pSelect ) continue;
        sqliteVdbeAddOp(v, OP_Integer, pTab->iDb, 0);
        sqliteVdbeAddOp(v, OP_OpenRead, pTabList->a[i].iCursor, pTab->tnum);
        sqliteVdbeChangeP3(v, -1, pTab->zName, P3_STATIC);
        sqliteCodeVerifySchema(pParse, pTab->iDb);
        if( pWInfo->a[i].pIdx!=0 ) {
            sqliteVdbeAddOp(v, OP_Integer, pWInfo->a[i].pIdx->iDb, 0);
            sqliteVdbeAddOp(v, OP_OpenRead,
                            pWInfo->a[i].iCur, pWInfo->a[i].pIdx->tnum);
            sqliteVdbeChangeP3(v, -1, pWInfo->a[i].pIdx->zName, P3_STATIC);
        }
    }

    /* Generate the code to do the search
    */
    loopMask = 0;
    for(i=0; i<pTabList->nSrc; i++) {
        int j, k;
        int iCur = pTabList->a[i].iCursor;
        Index *pIdx;
        WhereLevel *pLevel = &pWInfo->a[i];

        /* If this is the right table of a LEFT OUTER JOIN, allocate and
        ** initialize a memory cell that records if this table matches any
        ** row of the left table of the join.
        */
        if( i>0 && (pTabList->a[i-1].jointype & JT_LEFT)!=0 ) {
            if( !pParse->nMem ) pParse->nMem++;
            pLevel->iLeftJoin = pParse->nMem++;
            sqliteVdbeAddOp(v, OP_String, 0, 0);
            sqliteVdbeAddOp(v, OP_MemStore, pLevel->iLeftJoin, 1);
        }

        pIdx = pLevel->pIdx;
        pLevel->inOp = OP_Noop;
        if( i<ARRAYSIZE(iDirectEq) && iDirectEq[i]>=0 ) {
            /* Case 1:  We can directly reference a single row using an
            **          equality comparison against the ROWID field.  Or
            **          we reference multiple rows using a "rowid IN (...)"
            **          construct.
            */
            k = iDirectEq[i];
            assert( k<nExpr );
            assert( aExpr[k].p!=0 );
            assert( aExpr[k].idxLeft==iCur || aExpr[k].idxRight==iCur );
            brk = pLevel->brk = sqliteVdbeMakeLabel(v);
            if( aExpr[k].idxLeft==iCur ) {
                Expr *pX = aExpr[k].p;
                if( pX->op!=TK_IN ) {
                    sqliteExprCode(pParse, aExpr[k].p->pRight);
                } else if( pX->pList ) {
                    sqliteVdbeAddOp(v, OP_SetFirst, pX->iTable, brk);
                    pLevel->inOp = OP_SetNext;
                    pLevel->inP1 = pX->iTable;
                    pLevel->inP2 = sqliteVdbeCurrentAddr(v);
                } else {
                    assert( pX->pSelect );
                    sqliteVdbeAddOp(v, OP_Rewind, pX->iTable, brk);
                    sqliteVdbeAddOp(v, OP_KeyAsData, pX->iTable, 1);
                    pLevel->inP2 = sqliteVdbeAddOp(v, OP_FullKey, pX->iTable, 0);
                    pLevel->inOp = OP_Next;
                    pLevel->inP1 = pX->iTable;
                }
            } else {
                sqliteExprCode(pParse, aExpr[k].p->pLeft);
            }
            aExpr[k].p = 0;
            cont = pLevel->cont = sqliteVdbeMakeLabel(v);
            sqliteVdbeAddOp(v, OP_MustBeInt, 1, brk);
            haveKey = 0;
            sqliteVdbeAddOp(v, OP_NotExists, iCur, brk);
            pLevel->op = OP_Noop;
        } else if( pIdx!=0 && pLevel->score>0 && pLevel->score%4==0 ) {
            /* Case 2:  There is an index and all terms of the WHERE clause that
            **          refer to the index use the "==" or "IN" operators.
            */
            int start;
            int testOp;
            int nColumn = (pLevel->score+4)/8;
            brk = pLevel->brk = sqliteVdbeMakeLabel(v);
            for(j=0; j<nColumn; j++) {
                for(k=0; k<nExpr; k++) {
                    Expr *pX = aExpr[k].p;
                    if( pX==0 ) continue;
                    if( aExpr[k].idxLeft==iCur
                            && (aExpr[k].prereqRight & loopMask)==aExpr[k].prereqRight
                            && pX->pLeft->iColumn==pIdx->aiColumn[j]
                      ) {
                        if( pX->op==TK_EQ ) {
                            sqliteExprCode(pParse, pX->pRight);
                            aExpr[k].p = 0;
                            break;
                        }
                        if( pX->op==TK_IN && nColumn==1 ) {
                            if( pX->pList ) {
                                sqliteVdbeAddOp(v, OP_SetFirst, pX->iTable, brk);
                                pLevel->inOp = OP_SetNext;
                                pLevel->inP1 = pX->iTable;
                                pLevel->inP2 = sqliteVdbeCurrentAddr(v);
                            } else {
                                assert( pX->pSelect );
                                sqliteVdbeAddOp(v, OP_Rewind, pX->iTable, brk);
                                sqliteVdbeAddOp(v, OP_KeyAsData, pX->iTable, 1);
                                pLevel->inP2 = sqliteVdbeAddOp(v, OP_FullKey, pX->iTable, 0);
                                pLevel->inOp = OP_Next;
                                pLevel->inP1 = pX->iTable;
                            }
                            aExpr[k].p = 0;
                            break;
                        }
                    }
                    if( aExpr[k].idxRight==iCur
                            && aExpr[k].p->op==TK_EQ
                            && (aExpr[k].prereqLeft & loopMask)==aExpr[k].prereqLeft
                            && aExpr[k].p->pRight->iColumn==pIdx->aiColumn[j]
                      ) {
                        sqliteExprCode(pParse, aExpr[k].p->pLeft);
                        aExpr[k].p = 0;
                        break;
                    }
                }
            }
            pLevel->iMem = pParse->nMem++;
            cont = pLevel->cont = sqliteVdbeMakeLabel(v);
            sqliteVdbeAddOp(v, OP_NotNull, -nColumn, sqliteVdbeCurrentAddr(v)+3);
            sqliteVdbeAddOp(v, OP_Pop, nColumn, 0);
            sqliteVdbeAddOp(v, OP_Goto, 0, brk);
            sqliteVdbeAddOp(v, OP_MakeKey, nColumn, 0);
            sqliteAddIdxKeyType(v, pIdx);
            if( nColumn==pIdx->nColumn || pLevel->bRev ) {
                sqliteVdbeAddOp(v, OP_MemStore, pLevel->iMem, 0);
                testOp = OP_IdxGT;
            } else {
                sqliteVdbeAddOp(v, OP_Dup, 0, 0);
                sqliteVdbeAddOp(v, OP_IncrKey, 0, 0);
                sqliteVdbeAddOp(v, OP_MemStore, pLevel->iMem, 1);
                testOp = OP_IdxGE;
            }
            if( pLevel->bRev ) {
                /* Scan in reverse order */
                sqliteVdbeAddOp(v, OP_IncrKey, 0, 0);
                sqliteVdbeAddOp(v, OP_MoveLt, pLevel->iCur, brk);
                start = sqliteVdbeAddOp(v, OP_MemLoad, pLevel->iMem, 0);
                sqliteVdbeAddOp(v, OP_IdxLT, pLevel->iCur, brk);
                pLevel->op = OP_Prev;
            } else {
                /* Scan in the forward order */
                sqliteVdbeAddOp(v, OP_MoveTo, pLevel->iCur, brk);
                start = sqliteVdbeAddOp(v, OP_MemLoad, pLevel->iMem, 0);
                sqliteVdbeAddOp(v, testOp, pLevel->iCur, brk);
                pLevel->op = OP_Next;
            }
            sqliteVdbeAddOp(v, OP_RowKey, pLevel->iCur, 0);
            sqliteVdbeAddOp(v, OP_IdxIsNull, nColumn, cont);
            sqliteVdbeAddOp(v, OP_IdxRecno, pLevel->iCur, 0);
            if( i==pTabList->nSrc-1 && pushKey ) {
                haveKey = 1;
            } else {
                sqliteVdbeAddOp(v, OP_MoveTo, iCur, 0);
                haveKey = 0;
            }
            pLevel->p1 = pLevel->iCur;
            pLevel->p2 = start;
        } else if( i<ARRAYSIZE(iDirectLt) && (iDirectLt[i]>=0 || iDirectGt[i]>=0) ) {
            /* Case 3:  We have an inequality comparison against the ROWID field.
            */
            int testOp = OP_Noop;
            int start;

            brk = pLevel->brk = sqliteVdbeMakeLabel(v);
            cont = pLevel->cont = sqliteVdbeMakeLabel(v);
            if( iDirectGt[i]>=0 ) {
                k = iDirectGt[i];
                assert( k<nExpr );
                assert( aExpr[k].p!=0 );
                assert( aExpr[k].idxLeft==iCur || aExpr[k].idxRight==iCur );
                if( aExpr[k].idxLeft==iCur ) {
                    sqliteExprCode(pParse, aExpr[k].p->pRight);
                } else {
                    sqliteExprCode(pParse, aExpr[k].p->pLeft);
                }
                sqliteVdbeAddOp(v, OP_ForceInt,
                                aExpr[k].p->op==TK_LT || aExpr[k].p->op==TK_GT, brk);
                sqliteVdbeAddOp(v, OP_MoveTo, iCur, brk);
                aExpr[k].p = 0;
            } else {
                sqliteVdbeAddOp(v, OP_Rewind, iCur, brk);
            }
            if( iDirectLt[i]>=0 ) {
                k = iDirectLt[i];
                assert( k<nExpr );
                assert( aExpr[k].p!=0 );
                assert( aExpr[k].idxLeft==iCur || aExpr[k].idxRight==iCur );
                if( aExpr[k].idxLeft==iCur ) {
                    sqliteExprCode(pParse, aExpr[k].p->pRight);
                } else {
                    sqliteExprCode(pParse, aExpr[k].p->pLeft);
                }
                /* sqliteVdbeAddOp(v, OP_MustBeInt, 0, sqliteVdbeCurrentAddr(v)+1); */
                pLevel->iMem = pParse->nMem++;
                sqliteVdbeAddOp(v, OP_MemStore, pLevel->iMem, 1);
                if( aExpr[k].p->op==TK_LT || aExpr[k].p->op==TK_GT ) {
                    testOp = OP_Ge;
                } else {
                    testOp = OP_Gt;
                }
                aExpr[k].p = 0;
            }
            start = sqliteVdbeCurrentAddr(v);
            pLevel->op = OP_Next;
            pLevel->p1 = iCur;
            pLevel->p2 = start;
            if( testOp!=OP_Noop ) {
                sqliteVdbeAddOp(v, OP_Recno, iCur, 0);
                sqliteVdbeAddOp(v, OP_MemLoad, pLevel->iMem, 0);
                sqliteVdbeAddOp(v, testOp, 0, brk);
            }
            haveKey = 0;
        } else if( pIdx==0 ) {
            /* Case 4:  There is no usable index.  We must do a complete
            **          scan of the entire database table.
            */
            int start;

            brk = pLevel->brk = sqliteVdbeMakeLabel(v);
            cont = pLevel->cont = sqliteVdbeMakeLabel(v);
            sqliteVdbeAddOp(v, OP_Rewind, iCur, brk);
            start = sqliteVdbeCurrentAddr(v);
            pLevel->op = OP_Next;
            pLevel->p1 = iCur;
            pLevel->p2 = start;
            haveKey = 0;
        } else {
            /* Case 5: The WHERE clause term that refers to the right-most
            **         column of the index is an inequality.  For example, if
            **         the index is on (x,y,z) and the WHERE clause is of the
            **         form "x=5 AND y<10" then this case is used.  Only the
            **         right-most column can be an inequality - the rest must
            **         use the "==" operator.
            **
            **         This case is also used when there are no WHERE clause
            **         constraints but an index is selected anyway, in order
            **         to force the output order to conform to an ORDER BY.
            */
            int score = pLevel->score;
            int nEqColumn = score/8;
            int start;
            int leFlag, geFlag;
            int testOp;

            /* Evaluate the equality constraints
            */
            for(j=0; j<nEqColumn; j++) {
                for(k=0; k<nExpr; k++) {
                    if( aExpr[k].p==0 ) continue;
                    if( aExpr[k].idxLeft==iCur
                            && aExpr[k].p->op==TK_EQ
                            && (aExpr[k].prereqRight & loopMask)==aExpr[k].prereqRight
                            && aExpr[k].p->pLeft->iColumn==pIdx->aiColumn[j]
                      ) {
                        sqliteExprCode(pParse, aExpr[k].p->pRight);
                        aExpr[k].p = 0;
                        break;
                    }
                    if( aExpr[k].idxRight==iCur
                            && aExpr[k].p->op==TK_EQ
                            && (aExpr[k].prereqLeft & loopMask)==aExpr[k].prereqLeft
                            && aExpr[k].p->pRight->iColumn==pIdx->aiColumn[j]
                      ) {
                        sqliteExprCode(pParse, aExpr[k].p->pLeft);
                        aExpr[k].p = 0;
                        break;
                    }
                }
            }

            /* Duplicate the equality term values because they will all be
            ** used twice: once to make the termination key and once to make the
            ** start key.
            */
            for(j=0; j<nEqColumn; j++) {
                sqliteVdbeAddOp(v, OP_Dup, nEqColumn-1, 0);
            }

            /* Labels for the beginning and end of the loop
            */
            cont = pLevel->cont = sqliteVdbeMakeLabel(v);
            brk = pLevel->brk = sqliteVdbeMakeLabel(v);

            /* Generate the termination key.  This is the key value that
            ** will end the search.  There is no termination key if there
            ** are no equality terms and no "X<..." term.
            **
            ** 2002-Dec-04: On a reverse-order scan, the so-called "termination"
            ** key computed here really ends up being the start key.
            */
            if( (score & 1)!=0 ) {
                for(k=0; k<nExpr; k++) {
                    Expr *pExpr = aExpr[k].p;
                    if( pExpr==0 ) continue;
                    if( aExpr[k].idxLeft==iCur
                            && (pExpr->op==TK_LT || pExpr->op==TK_LE)
                            && (aExpr[k].prereqRight & loopMask)==aExpr[k].prereqRight
                            && pExpr->pLeft->iColumn==pIdx->aiColumn[j]
                      ) {
                        sqliteExprCode(pParse, pExpr->pRight);
                        leFlag = pExpr->op==TK_LE;
                        aExpr[k].p = 0;
                        break;
                    }
                    if( aExpr[k].idxRight==iCur
                            && (pExpr->op==TK_GT || pExpr->op==TK_GE)
                            && (aExpr[k].prereqLeft & loopMask)==aExpr[k].prereqLeft
                            && pExpr->pRight->iColumn==pIdx->aiColumn[j]
                      ) {
                        sqliteExprCode(pParse, pExpr->pLeft);
                        leFlag = pExpr->op==TK_GE;
                        aExpr[k].p = 0;
                        break;
                    }
                }
                testOp = OP_IdxGE;
            } else {
                testOp = nEqColumn>0 ? OP_IdxGE : OP_Noop;
                leFlag = 1;
            }
            if( testOp!=OP_Noop ) {
                int nCol = nEqColumn + (score & 1);
                pLevel->iMem = pParse->nMem++;
                sqliteVdbeAddOp(v, OP_NotNull, -nCol, sqliteVdbeCurrentAddr(v)+3);
                sqliteVdbeAddOp(v, OP_Pop, nCol, 0);
                sqliteVdbeAddOp(v, OP_Goto, 0, brk);
                sqliteVdbeAddOp(v, OP_MakeKey, nCol, 0);
                sqliteAddIdxKeyType(v, pIdx);
                if( leFlag ) {
                    sqliteVdbeAddOp(v, OP_IncrKey, 0, 0);
                }
                if( pLevel->bRev ) {
                    sqliteVdbeAddOp(v, OP_MoveLt, pLevel->iCur, brk);
                } else {
                    sqliteVdbeAddOp(v, OP_MemStore, pLevel->iMem, 1);
                }
            } else if( pLevel->bRev ) {
                sqliteVdbeAddOp(v, OP_Last, pLevel->iCur, brk);
            }

            /* Generate the start key.  This is the key that defines the lower
            ** bound on the search.  There is no start key if there are no
            ** equality terms and if there is no "X>..." term.  In
            ** that case, generate a "Rewind" instruction in place of the
            ** start key search.
            **
            ** 2002-Dec-04: In the case of a reverse-order search, the so-called
            ** "start" key really ends up being used as the termination key.
            */
            if( (score & 2)!=0 ) {
                for(k=0; k<nExpr; k++) {
                    Expr *pExpr = aExpr[k].p;
                    if( pExpr==0 ) continue;
                    if( aExpr[k].idxLeft==iCur
                            && (pExpr->op==TK_GT || pExpr->op==TK_GE)
                            && (aExpr[k].prereqRight & loopMask)==aExpr[k].prereqRight
                            && pExpr->pLeft->iColumn==pIdx->aiColumn[j]
                      ) {
                        sqliteExprCode(pParse, pExpr->pRight);
                        geFlag = pExpr->op==TK_GE;
                        aExpr[k].p = 0;
                        break;
                    }
                    if( aExpr[k].idxRight==iCur
                            && (pExpr->op==TK_LT || pExpr->op==TK_LE)
                            && (aExpr[k].prereqLeft & loopMask)==aExpr[k].prereqLeft
                            && pExpr->pRight->iColumn==pIdx->aiColumn[j]
                      ) {
                        sqliteExprCode(pParse, pExpr->pLeft);
                        geFlag = pExpr->op==TK_LE;
                        aExpr[k].p = 0;
                        break;
                    }
                }
            } else {
                geFlag = 1;
            }
            if( nEqColumn>0 || (score&2)!=0 ) {
                int nCol = nEqColumn + ((score&2)!=0);
                sqliteVdbeAddOp(v, OP_NotNull, -nCol, sqliteVdbeCurrentAddr(v)+3);
                sqliteVdbeAddOp(v, OP_Pop, nCol, 0);
                sqliteVdbeAddOp(v, OP_Goto, 0, brk);
                sqliteVdbeAddOp(v, OP_MakeKey, nCol, 0);
                sqliteAddIdxKeyType(v, pIdx);
                if( !geFlag ) {
                    sqliteVdbeAddOp(v, OP_IncrKey, 0, 0);
                }
                if( pLevel->bRev ) {
                    pLevel->iMem = pParse->nMem++;
                    sqliteVdbeAddOp(v, OP_MemStore, pLevel->iMem, 1);
                    testOp = OP_IdxLT;
                } else {
                    sqliteVdbeAddOp(v, OP_MoveTo, pLevel->iCur, brk);
                }
            } else if( pLevel->bRev ) {
                testOp = OP_Noop;
            } else {
                sqliteVdbeAddOp(v, OP_Rewind, pLevel->iCur, brk);
            }

            /* Generate the the top of the loop.  If there is a termination
            ** key we have to test for that key and abort at the top of the
            ** loop.
            */
            start = sqliteVdbeCurrentAddr(v);
            if( testOp!=OP_Noop ) {
                sqliteVdbeAddOp(v, OP_MemLoad, pLevel->iMem, 0);
                sqliteVdbeAddOp(v, testOp, pLevel->iCur, brk);
            }
            sqliteVdbeAddOp(v, OP_RowKey, pLevel->iCur, 0);
            sqliteVdbeAddOp(v, OP_IdxIsNull, nEqColumn + (score & 1), cont);
            sqliteVdbeAddOp(v, OP_IdxRecno, pLevel->iCur, 0);
            if( i==pTabList->nSrc-1 && pushKey ) {
                haveKey = 1;
            } else {
                sqliteVdbeAddOp(v, OP_MoveTo, iCur, 0);
                haveKey = 0;
            }

            /* Record the instruction used to terminate the loop.
            */
            pLevel->op = pLevel->bRev ? OP_Prev : OP_Next;
            pLevel->p1 = pLevel->iCur;
            pLevel->p2 = start;
        }
        loopMask |= getMask(&maskSet, iCur);

        /* Insert code to test every subexpression that can be completely
        ** computed using the current set of tables.
        */
        for(j=0; j<nExpr; j++) {
            if( aExpr[j].p==0 ) continue;
            if( (aExpr[j].prereqAll & loopMask)!=aExpr[j].prereqAll ) continue;
            if( pLevel->iLeftJoin && !ExprHasProperty(aExpr[j].p,EP_FromJoin) ) {
                continue;
            }
            if( haveKey ) {
                haveKey = 0;
                sqliteVdbeAddOp(v, OP_MoveTo, iCur, 0);
            }
            sqliteExprIfFalse(pParse, aExpr[j].p, cont, 1);
            aExpr[j].p = 0;
        }
        brk = cont;

        /* For a LEFT OUTER JOIN, generate code that will record the fact that
        ** at least one row of the right table has matched the left table.
        */
        if( pLevel->iLeftJoin ) {
            pLevel->top = sqliteVdbeCurrentAddr(v);
            sqliteVdbeAddOp(v, OP_Integer, 1, 0);
            sqliteVdbeAddOp(v, OP_MemStore, pLevel->iLeftJoin, 1);
            for(j=0; j<nExpr; j++) {
                if( aExpr[j].p==0 ) continue;
                if( (aExpr[j].prereqAll & loopMask)!=aExpr[j].prereqAll ) continue;
                if( haveKey ) {
                    /* Cannot happen.  "haveKey" can only be true if pushKey is true
                    ** an pushKey can only be true for DELETE and UPDATE and there are
                    ** no outer joins with DELETE and UPDATE.
                    */
                    haveKey = 0;
                    sqliteVdbeAddOp(v, OP_MoveTo, iCur, 0);
                }
                sqliteExprIfFalse(pParse, aExpr[j].p, cont, 1);
                aExpr[j].p = 0;
            }
        }
    }
    pWInfo->iContinue = cont;
    if( pushKey && !haveKey ) {
        sqliteVdbeAddOp(v, OP_Recno, pTabList->a[0].iCursor, 0);
    }
    freeMaskSet(&maskSet);
    return pWInfo;
}
Пример #16
0
/*
** Given the name of a column of the form X.Y.Z or Y.Z or just Z, look up
** that name in the set of source tables in pSrcList and make the pExpr 
** expression node refer back to that source column.  The following changes
** are made to pExpr:
**
**    pExpr->iDb           Set the index in db->aDb[] of the database holding
**                         the table.
**    pExpr->iTable        Set to the cursor number for the table obtained
**                         from pSrcList.
**    pExpr->iColumn       Set to the column number within the table.
**    pExpr->dataType      Set to the appropriate data type for the column.
**    pExpr->op            Set to TK_COLUMN.
**    pExpr->pLeft         Any expression this points to is deleted
**    pExpr->pRight        Any expression this points to is deleted.
**
** The pDbToken is the name of the database (the "X").  This value may be
** NULL meaning that name is of the form Y.Z or Z.  Any available database
** can be used.  The pTableToken is the name of the table (the "Y").  This
** value can be NULL if pDbToken is also NULL.  If pTableToken is NULL it
** means that the form of the name is Z and that columns from any table
** can be used.
**
** If the name cannot be resolved unambiguously, leave an error message
** in pParse and return non-zero.  Return zero on success.
*/
static int lookupName(
  Parse *pParse,      /* The parsing context */
  Token *pDbToken,     /* Name of the database containing table, or NULL */
  Token *pTableToken,  /* Name of table containing column, or NULL */
  Token *pColumnToken, /* Name of the column. */
  SrcList *pSrcList,   /* List of tables used to resolve column names */
  ExprList *pEList,    /* List of expressions used to resolve "AS" */
  Expr *pExpr          /* Make this EXPR node point to the selected column */
){
  char *zDb = 0;       /* Name of the database.  The "X" in X.Y.Z */
  char *zTab = 0;      /* Name of the table.  The "Y" in X.Y.Z or Y.Z */
  char *zCol = 0;      /* Name of the column.  The "Z" */
  int i, j;            /* Loop counters */
  int cnt = 0;         /* Number of matching column names */
  int cntTab = 0;      /* Number of matching table names */
  sqlite *db = pParse->db;  /* The database */

  assert( pColumnToken && pColumnToken->z ); /* The Z in X.Y.Z cannot be NULL */
  if( pDbToken && pDbToken->z ){
    zDb = sqliteStrNDup(pDbToken->z, pDbToken->n);
    sqliteDequote(zDb);
  }else{
    zDb = 0;
  }
  if( pTableToken && pTableToken->z ){
    zTab = sqliteStrNDup(pTableToken->z, pTableToken->n);
    sqliteDequote(zTab);
  }else{
    assert( zDb==0 );
    zTab = 0;
  }
  zCol = sqliteStrNDup(pColumnToken->z, pColumnToken->n);
  sqliteDequote(zCol);
  if( sqlite_malloc_failed ){
    return 1;  /* Leak memory (zDb and zTab) if malloc fails */
  }
  assert( zTab==0 || pEList==0 );

  pExpr->iTable = -1;
  for(i=0; i<pSrcList->nSrc; i++){
    struct SrcList_item *pItem = &pSrcList->a[i];
    Table *pTab = pItem->pTab;
    Column *pCol;

    if( pTab==0 ) continue;
    assert( pTab->nCol>0 );
    if( zTab ){
      if( pItem->zAlias ){
        char *zTabName = pItem->zAlias;
        if( sqliteStrICmp(zTabName, zTab)!=0 ) continue;
      }else{
        char *zTabName = pTab->zName;
        if( zTabName==0 || sqliteStrICmp(zTabName, zTab)!=0 ) continue;
        if( zDb!=0 && sqliteStrICmp(db->aDb[pTab->iDb].zName, zDb)!=0 ){
          continue;
        }
      }
    }
    if( 0==(cntTab++) ){
      pExpr->iTable = pItem->iCursor;
      pExpr->iDb = pTab->iDb;
    }
    for(j=0, pCol=pTab->aCol; j<pTab->nCol; j++, pCol++){
      if( sqliteStrICmp(pCol->zName, zCol)==0 ){
        cnt++;
        pExpr->iTable = pItem->iCursor;
        pExpr->iDb = pTab->iDb;
        /* Substitute the rowid (column -1) for the INTEGER PRIMARY KEY */
        pExpr->iColumn = j==pTab->iPKey ? -1 : j;
        pExpr->dataType = pCol->sortOrder & SQLITE_SO_TYPEMASK;
        break;
      }
    }
  }

  /* If we have not already resolved the name, then maybe 
  ** it is a new.* or old.* trigger argument reference
  */
  if( zDb==0 && zTab!=0 && cnt==0 && pParse->trigStack!=0 ){
    TriggerStack *pTriggerStack = pParse->trigStack;
    Table *pTab = 0;
    if( pTriggerStack->newIdx != -1 && sqliteStrICmp("new", zTab) == 0 ){
      pExpr->iTable = pTriggerStack->newIdx;
      assert( pTriggerStack->pTab );
      pTab = pTriggerStack->pTab;
    }else if( pTriggerStack->oldIdx != -1 && sqliteStrICmp("old", zTab) == 0 ){
      pExpr->iTable = pTriggerStack->oldIdx;
      assert( pTriggerStack->pTab );
      pTab = pTriggerStack->pTab;
    }

    if( pTab ){ 
      int j;
      Column *pCol = pTab->aCol;
      
      pExpr->iDb = pTab->iDb;
      cntTab++;
      for(j=0; j < pTab->nCol; j++, pCol++) {
        if( sqliteStrICmp(pCol->zName, zCol)==0 ){
          cnt++;
          pExpr->iColumn = j==pTab->iPKey ? -1 : j;
          pExpr->dataType = pCol->sortOrder & SQLITE_SO_TYPEMASK;
          break;
        }
      }
    }
  }

  /*
  ** Perhaps the name is a reference to the ROWID
  */
  if( cnt==0 && cntTab==1 && sqliteIsRowid(zCol) ){
    cnt = 1;
    pExpr->iColumn = -1;
    pExpr->dataType = SQLITE_SO_NUM;
  }

  /*
  ** If the input is of the form Z (not Y.Z or X.Y.Z) then the name Z
  ** might refer to an result-set alias.  This happens, for example, when
  ** we are resolving names in the WHERE clause of the following command:
  **
  **     SELECT a+b AS x FROM table WHERE x<10;
  **
  ** In cases like this, replace pExpr with a copy of the expression that
  ** forms the result set entry ("a+b" in the example) and return immediately.
  ** Note that the expression in the result set should have already been
  ** resolved by the time the WHERE clause is resolved.
  */
  if( cnt==0 && pEList!=0 ){
    for(j=0; j<pEList->nExpr; j++){
      char *zAs = pEList->a[j].zName;
      if( zAs!=0 && sqliteStrICmp(zAs, zCol)==0 ){
        assert( pExpr->pLeft==0 && pExpr->pRight==0 );
        pExpr->op = TK_AS;
        pExpr->iColumn = j;
        pExpr->pLeft = sqliteExprDup(pEList->a[j].pExpr);
        sqliteFree(zCol);
        assert( zTab==0 && zDb==0 );
        return 0;
      }
    } 
  }

  /*
  ** If X and Y are NULL (in other words if only the column name Z is
  ** supplied) and the value of Z is enclosed in double-quotes, then
  ** Z is a string literal if it doesn't match any column names.  In that
  ** case, we need to return right away and not make any changes to
  ** pExpr.
  */
  if( cnt==0 && zTab==0 && pColumnToken->z[0]=='"' ){
    sqliteFree(zCol);
    return 0;
  }

  /*
  ** cnt==0 means there was not match.  cnt>1 means there were two or
  ** more matches.  Either way, we have an error.
  */
  if( cnt!=1 ){
    char *z = 0;
    char *zErr;
    zErr = cnt==0 ? "no such column: %s" : "ambiguous column name: %s";
    if( zDb ){
      sqliteSetString(&z, zDb, ".", zTab, ".", zCol, 0);
    }else if( zTab ){
      sqliteSetString(&z, zTab, ".", zCol, 0);
    }else{
      z = sqliteStrDup(zCol);
    }
    sqliteErrorMsg(pParse, zErr, z);
    sqliteFree(z);
  }

  /* Clean up and return
  */
  sqliteFree(zDb);
  sqliteFree(zTab);
  sqliteFree(zCol);
  sqliteExprDelete(pExpr->pLeft);
  pExpr->pLeft = 0;
  sqliteExprDelete(pExpr->pRight);
  pExpr->pRight = 0;
  pExpr->op = TK_COLUMN;
  sqliteAuthRead(pParse, pExpr, pSrcList);
  return cnt!=1;
}