Esempio n. 1
0
/*
** This function is called to drop a trigger from the database schema.
**
** This may be called directly from the parser and therefore identifies
** the trigger by name.  The sqlite3DropTriggerPtr() routine does the
** same job as this routine except it takes a pointer to the trigger
** instead of the trigger name.
**/
void sqlite3DropTrigger(Parse *pParse, SrcList *pName) {
    Trigger *pTrigger = 0;
    int i;
    const char *zDb;
    const char *zName;
    int nName;
    sqlite3 *db = pParse->db;

    if( sqlite3ThreadDataReadOnly()->mallocFailed ) goto drop_trigger_cleanup;
    if( SQLITE_OK!=sqlite3ReadSchema(pParse) ) {
        goto drop_trigger_cleanup;
    }

    assert( pName->nSrc==1 );
    zDb = pName->a[0].zDatabase;
    zName = pName->a[0].zName;
    nName = strlen(zName);
    for(i=OMIT_TEMPDB; i<db->nDb; i++) {
        int j = (i<2) ? i^1 : i;  /* Search TEMP before MAIN */
        if( zDb && sqlite3StrICmp(db->aDb[j].zName, zDb) ) continue;
        pTrigger = sqlite3HashFind(&(db->aDb[j].pSchema->trigHash), zName, nName+1);
        if( pTrigger ) break;
    }
    if( !pTrigger ) {
        sqlite3ErrorMsg(pParse, "no such trigger: %S", pName, 0);
        goto drop_trigger_cleanup;
    }
    sqlite3DropTriggerPtr(pParse, pTrigger, 0);

drop_trigger_cleanup:
    sqlite3SrcListDelete(pName);
}
Esempio n. 2
0
/*
** Locate and return an entry from the db.aCollSeq hash table. If the entry
** specified by zName and nName is not found and parameter 'create' is
** true, then create a new entry. Otherwise return NULL.
**
** Each pointer stored in the sqlite3.aCollSeq hash table contains an
** array of three CollSeq structures. The first is the collation sequence
** prefferred for UTF-8, the second UTF-16le, and the third UTF-16be.
**
** Stored immediately after the three collation sequences is a copy of
** the collation sequence name. A pointer to this string is stored in
** each collation sequence structure.
*/
static CollSeq *findCollSeqEntry(
  sqlite3 *db,
  const char *zName,
  int nName,
  int create
){
  CollSeq *pColl;
  if( nName<0 ) nName = strlen(zName);
  pColl = sqlite3HashFind(&db->aCollSeq, zName, nName);

  if( 0==pColl && create ){
    pColl = sqliteMalloc( 3*sizeof(*pColl) + nName + 1 );
    if( pColl ){
      CollSeq *pDel = 0;
      pColl[0].zName = (char*)&pColl[3];
      pColl[0].enc = SQLITE_UTF8;
      pColl[1].zName = (char*)&pColl[3];
      pColl[1].enc = SQLITE_UTF16LE;
      pColl[2].zName = (char*)&pColl[3];
      pColl[2].enc = SQLITE_UTF16BE;
      memcpy(pColl[0].zName, zName, nName);
      pColl[0].zName[nName] = 0;
      pDel = sqlite3HashInsert(&db->aCollSeq, pColl[0].zName, nName, pColl);

      /* If a malloc() failure occured in sqlite3HashInsert(), it will 
      ** return the pColl pointer to be deleted (because it wasn't added
      ** to the hash table).
      */
      assert( !pDel ||
              (sqlite3ThreadDataReadOnly()->mallocFailed && pDel==pColl) );
      sqliteFree(pDel);
    }
  }
  return pColl;
}
Esempio n. 3
0
/*
** This is the test layer's wrapper around sqlite3OsRealloc().
*/
static void * OSREALLOC(void *pRealloc, int n){
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
  sqlite3_nMaxAlloc = 
      MAX(sqlite3_nMaxAlloc, sqlite3ThreadDataReadOnly()->nAlloc);
#endif
  assert( !sqlite3_mallocDisallowed );
  if( !sqlite3TestMallocFail() ){
    u32 *p = (u32 *)getOsPointer(pRealloc);
    checkGuards(p);
    p = sqlite3OsRealloc(p, n + TESTALLOC_OVERHEAD);
    applyGuards(p);
    relinkAlloc(p);
    return (void *)(&p[TESTALLOC_NGUARD + 2*sizeof(void *)/sizeof(u32)]);
  }
  return 0;
}
Esempio n. 4
0
/*
** This is the test layer's wrapper around sqlite3OsMalloc().
*/
static void * OSMALLOC(int n){
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
  sqlite3_nMaxAlloc = 
      MAX(sqlite3_nMaxAlloc, sqlite3ThreadDataReadOnly()->nAlloc);
#endif
  assert( !sqlite3_mallocDisallowed );
  if( !sqlite3TestMallocFail() ){
    u32 *p;
    p = (u32 *)sqlite3OsMalloc(n + TESTALLOC_OVERHEAD);
    assert(p);
    sqlite3_nMalloc++;
    applyGuards(p);
    linkAlloc(p);
    return (void *)(&p[TESTALLOC_NGUARD + 2*sizeof(void *)/sizeof(u32)]);
  }
  return 0;
}
Esempio n. 5
0
/*
** The parser calls this routine when it first sees a CREATE VIRTUAL TABLE
** statement.  The module name has been parsed, but the optional list
** of parameters that follow the module name are still pending.
*/
void sqlite3VtabBeginParse(
  Parse *pParse,        /* Parsing context */
  Token *pName1,        /* Name of new table, or database name */
  Token *pName2,        /* Name of new table or NULL */
  Token *pModuleName    /* Name of the module for the virtual table */
){
  int iDb;              /* The database the table is being created in */
  Table *pTable;        /* The new virtual table */

#ifndef SQLITE_OMIT_SHARED_CACHE
  if( sqlite3ThreadDataReadOnly()->useSharedData ){
    sqlite3ErrorMsg(pParse, "Cannot use virtual tables in shared-cache mode");
    return;
  }
#endif

  sqlite3StartTable(pParse, pName1, pName2, 0, 0, 1, 0);
  pTable = pParse->pNewTable;
  if( pTable==0 || pParse->nErr ) return;
  assert( 0==pTable->pIndex );

  iDb = sqlite3SchemaToIndex(pParse->db, pTable->pSchema);
  assert( iDb>=0 );

  pTable->isVirtual = 1;
  pTable->nModuleArg = 0;
  addModuleArgument(pTable, sqlite3NameFromToken(pModuleName));
  addModuleArgument(pTable, sqlite3StrDup(pParse->db->aDb[iDb].zName));
  addModuleArgument(pTable, sqlite3StrDup(pTable->zName));
  pParse->sNameToken.n = pModuleName->z + pModuleName->n - pName1->z;

#ifndef SQLITE_OMIT_AUTHORIZATION
  /* Creating a virtual table invokes the authorization callback twice.
  ** The first invocation, to obtain permission to INSERT a row into the
  ** sqlite_master table, has already been made by sqlite3StartTable().
  ** The second call, to obtain permission to create the table, is made now.
  */
  if( pTable->azModuleArg ){
    sqlite3AuthCheck(pParse, SQLITE_CREATE_VTABLE, pTable->zName, 
            pTable->azModuleArg[0], pParse->db->aDb[iDb].zName);
  }
#endif
}
Esempio n. 6
0
/*
** Execute SQL code.  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.
**
** If the SQL is a query, then for each row in the query result
** the xCallback() function is called.  pArg becomes the first
** argument to xCallback().  If xCallback=NULL then no callback
** is invoked, even for queries.
*/
int sqlite3_exec(
  sqlite3 *db,                /* The database on which the SQL executes */
  const char *zSql,           /* The SQL to be executed */
  sqlite3_callback xCallback, /* Invoke this callback routine */
  void *pArg,                 /* First argument to xCallback() */
  char **pzErrMsg             /* Write error messages here */
){
  int rc = SQLITE_OK;
  const char *zLeftover;
  sqlite3_stmt *pStmt = 0;
  char **azCols = 0;

  int nRetry = 0;
  int nChange = 0;
  int nCallback;

  if( zSql==0 ) return SQLITE_OK;
  while( (rc==SQLITE_OK || (rc==SQLITE_SCHEMA && (++nRetry)<2)) && zSql[0] ){
    int nCol;
    char **azVals = 0;

    pStmt = 0;
    rc = sqlite3_prepare(db, zSql, -1, &pStmt, &zLeftover);
    if( rc!=SQLITE_OK ){
      if( pStmt ) sqlite3_finalize(pStmt);
      continue;
    }
    if( !pStmt ){
      /* this happens for a comment or white-space */
      zSql = zLeftover;
      continue;
    }

    db->nChange += nChange;
    nCallback = 0;

    nCol = sqlite3_column_count(pStmt);
    azCols = sqliteMalloc(2*nCol*sizeof(const char *));
    if( nCol && !azCols ){
      goto exec_out;
    }

    while( 1 ){
      int i;
      rc = sqlite3_step(pStmt);

      /* Invoke the callback function if required */
      if( xCallback && (SQLITE_ROW==rc || 
          (SQLITE_DONE==rc && !nCallback && db->flags&SQLITE_NullCallback)) ){
        if( 0==nCallback ){
          for(i=0; i<nCol; i++){
            azCols[i] = (char *)sqlite3_column_name(pStmt, i);
          }
          nCallback++;
        }
        if( rc==SQLITE_ROW ){
          azVals = &azCols[nCol];
          for(i=0; i<nCol; i++){
            azVals[i] = (char *)sqlite3_column_text(pStmt, i);
          }
        }
        if( xCallback(pArg, nCol, azVals, azCols) ){
          rc = SQLITE_ABORT;
          goto exec_out;
        }
      }

      if( rc!=SQLITE_ROW ){
        rc = sqlite3_finalize(pStmt);
        pStmt = 0;
        if( db->pVdbe==0 ){
          nChange = db->nChange;
        }
        if( rc!=SQLITE_SCHEMA ){
          nRetry = 0;
          zSql = zLeftover;
          while( isspace((unsigned char)zSql[0]) ) zSql++;
        }
        break;
      }
    }

    sqliteFree(azCols);
    azCols = 0;
  }

exec_out:
  if( pStmt ) sqlite3_finalize(pStmt);
  if( azCols ) sqliteFree(azCols);

  if( sqlite3ThreadDataReadOnly()->mallocFailed ){
    rc = SQLITE_NOMEM;
    sqlite3MallocClearFailed();
  }

  if( rc!=SQLITE_OK && rc==sqlite3_errcode(db) && pzErrMsg ){
    *pzErrMsg = malloc(1+strlen(sqlite3_errmsg(db)));
    if( *pzErrMsg ){
      strcpy(*pzErrMsg, sqlite3_errmsg(db));
    }
  }else if( pzErrMsg ){
    *pzErrMsg = 0;
  }

  return rc;
}
Esempio n. 7
0
/*
** This procedure generates VDBE code for a single invocation of either the
** sqlite_detach() or sqlite_attach() SQL user functions.
*/
static void codeAttach(
  Parse *pParse,       /* The parser context */
  int type,            /* Either SQLITE_ATTACH or SQLITE_DETACH */
  const char *zFunc,   /* Either "sqlite_attach" or "sqlite_detach */
  int nFunc,           /* Number of args to pass to zFunc */
  Expr *pAuthArg,      /* Expression to pass to authorization callback */
  Expr *pFilename,     /* Name of database file */
  Expr *pDbname,       /* Name of the database to use internally */
  Expr *pKey           /* Database key for encryption extension */
){
  int rc;
  NameContext sName;
  Vdbe *v;
  FuncDef *pFunc;
  sqlite3* db = pParse->db;

#ifndef SQLITE_OMIT_AUTHORIZATION
  assert( sqlite3ThreadDataReadOnly()->mallocFailed || pAuthArg );
  if( pAuthArg ){
    char *zAuthArg = sqlite3NameFromToken(&pAuthArg->span);
    if( !zAuthArg ){
      goto attach_end;
    }
    rc = sqlite3AuthCheck(pParse, type, zAuthArg, 0, 0);
    sqliteFree(zAuthArg);
    if(rc!=SQLITE_OK ){
      goto attach_end;
    }
  }
#endif /* SQLITE_OMIT_AUTHORIZATION */

  memset(&sName, 0, sizeof(NameContext));
  sName.pParse = pParse;

  if( 
      SQLITE_OK!=(rc = resolveAttachExpr(&sName, pFilename)) ||
      SQLITE_OK!=(rc = resolveAttachExpr(&sName, pDbname)) ||
      SQLITE_OK!=(rc = resolveAttachExpr(&sName, pKey))
  ){
    pParse->nErr++;
    goto attach_end;
  }

  v = sqlite3GetVdbe(pParse);
  sqlite3ExprCode(pParse, pFilename);
  sqlite3ExprCode(pParse, pDbname);
  sqlite3ExprCode(pParse, pKey);

  assert(v || sqlite3ThreadDataReadOnly()->mallocFailed);
  if( v ){
    sqlite3VdbeAddOp(v, OP_Function, 0, nFunc);
    pFunc = sqlite3FindFunction(db, zFunc, strlen(zFunc), nFunc, SQLITE_UTF8,0);
    sqlite3VdbeChangeP3(v, -1, (char *)pFunc, P3_FUNCDEF);

    /* Code an OP_Expire. For an ATTACH statement, set P1 to true (expire this
    ** statement only). For DETACH, set it to false (expire all existing
    ** statements).
    */
    sqlite3VdbeAddOp(v, OP_Expire, (type==SQLITE_ATTACH), 0);
  }
  
attach_end:
  sqlite3ExprDelete(pFilename);
  sqlite3ExprDelete(pDbname);
  sqlite3ExprDelete(pKey);
}
Esempio n. 8
0
/*
** This is called by the parser when it sees a CREATE TRIGGER statement
** up to the point of the BEGIN before the trigger actions.  A Trigger
** structure is generated based on the information available and stored
** in pParse->pNewTrigger.  After the trigger actions have been parsed, the
** sqlite3FinishTrigger() function is called to complete the trigger
** construction process.
*/
void sqlite3BeginTrigger(
    Parse *pParse,      /* The parse context of the CREATE TRIGGER statement */
    Token *pName1,      /* The name of the trigger */
    Token *pName2,      /* The name of the trigger */
    int tr_tm,          /* One of TK_BEFORE, TK_AFTER, TK_INSTEAD */
    int op,             /* One of TK_INSERT, TK_UPDATE, TK_DELETE */
    IdList *pColumns,   /* column list if this is an UPDATE OF trigger */
    SrcList *pTableName,/* The name of the table/view the trigger applies to */
    int foreach,        /* One of TK_ROW or TK_STATEMENT */
    Expr *pWhen,        /* WHEN clause */
    int isTemp          /* True if the TEMPORARY keyword is present */
) {
    Trigger *pTrigger = 0;
    Table *pTab;
    char *zName = 0;        /* Name of the trigger */
    sqlite3 *db = pParse->db;
    int iDb;                /* The database to store the trigger in */
    Token *pName;           /* The unqualified db name */
    DbFixer sFix;
    int iTabDb;

    if( isTemp ) {
        /* If TEMP was specified, then the trigger name may not be qualified. */
        if( pName2 && pName2->n>0 ) {
            sqlite3ErrorMsg(pParse, "temporary trigger may not have qualified name");
            goto trigger_cleanup;
        }
        iDb = 1;
        pName = pName1;
    } else {
        /* Figure out the db that the the trigger will be created in */
        iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pName);
        if( iDb<0 ) {
            goto trigger_cleanup;
        }
    }

    /* If the trigger name was unqualified, and the table is a temp table,
    ** then set iDb to 1 to create the trigger in the temporary database.
    ** If sqlite3SrcListLookup() returns 0, indicating the table does not
    ** exist, the error is caught by the block below.
    */
    if( !pTableName || sqlite3ThreadDataReadOnly()->mallocFailed ) {
        goto trigger_cleanup;
    }
    pTab = sqlite3SrcListLookup(pParse, pTableName);
    if( pName2->n==0 && pTab && pTab->pSchema==db->aDb[1].pSchema ) {
        iDb = 1;
    }

    /* Ensure the table name matches database name and that the table exists */
    if( sqlite3ThreadDataReadOnly()->mallocFailed ) goto trigger_cleanup;
    assert( pTableName->nSrc==1 );
    if( sqlite3FixInit(&sFix, pParse, iDb, "trigger", pName) &&
            sqlite3FixSrcList(&sFix, pTableName) ) {
        goto trigger_cleanup;
    }
    pTab = sqlite3SrcListLookup(pParse, pTableName);
    if( !pTab ) {
        /* The table does not exist. */
        goto trigger_cleanup;
    }

    /* Check that the trigger name is not reserved and that no trigger of the
    ** specified name exists */
    zName = sqlite3NameFromToken(pName);
    if( !zName || SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ) {
        goto trigger_cleanup;
    }
    if( sqlite3HashFind(&(db->aDb[iDb].pSchema->trigHash), zName,pName->n+1) ) {
        sqlite3ErrorMsg(pParse, "trigger %T already exists", pName);
        goto trigger_cleanup;
    }

    /* Do not create a trigger on a system table */
    if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0 ) {
        sqlite3ErrorMsg(pParse, "cannot create trigger on system table");
        pParse->nErr++;
        goto trigger_cleanup;
    }

    /* INSTEAD of triggers are only for views and views only support INSTEAD
    ** of triggers.
    */
    if( pTab->pSelect && tr_tm!=TK_INSTEAD ) {
        sqlite3ErrorMsg(pParse, "cannot create %s trigger on view: %S",
                        (tr_tm == TK_BEFORE)?"BEFORE":"AFTER", pTableName, 0);
        goto trigger_cleanup;
    }
    if( !pTab->pSelect && tr_tm==TK_INSTEAD ) {
        sqlite3ErrorMsg(pParse, "cannot create INSTEAD OF"
                        " trigger on table: %S", pTableName, 0);
        goto trigger_cleanup;
    }
    iTabDb = sqlite3SchemaToIndex(db, pTab->pSchema);

#ifndef SQLITE_OMIT_AUTHORIZATION
    {
        int code = SQLITE_CREATE_TRIGGER;
        const char *zDb = db->aDb[iTabDb].zName;
        const char *zDbTrig = isTemp ? db->aDb[1].zName : zDb;
        if( iTabDb==1 || isTemp ) code = SQLITE_CREATE_TEMP_TRIGGER;
        if( sqlite3AuthCheck(pParse, code, zName, pTab->zName, zDbTrig) ) {
            goto trigger_cleanup;
        }
        if( sqlite3AuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(iTabDb),0,zDb)) {
            goto trigger_cleanup;
        }
    }
#endif

    /* INSTEAD OF triggers can only appear on views and BEFORE triggers
    ** cannot appear on views.  So we might as well translate every
    ** INSTEAD OF trigger into a BEFORE trigger.  It simplifies code
    ** elsewhere.
    */
    if (tr_tm == TK_INSTEAD) {
        tr_tm = TK_BEFORE;
    }

    /* Build the Trigger object */
    pTrigger = (Trigger*)sqliteMalloc(sizeof(Trigger));
    if( pTrigger==0 ) goto trigger_cleanup;
    pTrigger->name = zName;
    zName = 0;
    pTrigger->table = sqliteStrDup(pTableName->a[0].zName);
    pTrigger->pSchema = db->aDb[iDb].pSchema;
    pTrigger->pTabSchema = pTab->pSchema;
    pTrigger->op = op;
    pTrigger->tr_tm = tr_tm==TK_BEFORE ? TRIGGER_BEFORE : TRIGGER_AFTER;
    pTrigger->pWhen = sqlite3ExprDup(pWhen);
    pTrigger->pColumns = sqlite3IdListDup(pColumns);
    pTrigger->foreach = foreach;
    sqlite3TokenCopy(&pTrigger->nameToken,pName);
    assert( pParse->pNewTrigger==0 );
    pParse->pNewTrigger = pTrigger;

trigger_cleanup:
    sqliteFree(zName);
    sqlite3SrcListDelete(pTableName);
    sqlite3IdListDelete(pColumns);
    sqlite3ExprDelete(pWhen);
    if( !pParse->pNewTrigger ) {
        sqlite3DeleteTrigger(pTrigger);
    } else {
        assert( pParse->pNewTrigger==pTrigger );
    }
}
Esempio n. 9
0
/*
** This routine is called after all of the trigger actions have been parsed
** in order to complete the process of building the trigger.
*/
void sqlite3FinishTrigger(
    Parse *pParse,          /* Parser context */
    TriggerStep *pStepList, /* The triggered program */
    Token *pAll             /* Token that describes the complete CREATE TRIGGER */
) {
    Trigger *pTrig = 0;     /* The trigger whose construction is finishing up */
    sqlite3 *db = pParse->db;  /* The database */
    DbFixer sFix;
    int iDb;                   /* Database containing the trigger */

    pTrig = pParse->pNewTrigger;
    pParse->pNewTrigger = 0;
    if( pParse->nErr || !pTrig ) goto triggerfinish_cleanup;
    iDb = sqlite3SchemaToIndex(pParse->db, pTrig->pSchema);
    pTrig->step_list = pStepList;
    while( pStepList ) {
        pStepList->pTrig = pTrig;
        pStepList = pStepList->pNext;
    }
    if( sqlite3FixInit(&sFix, pParse, iDb, "trigger", &pTrig->nameToken)
            && sqlite3FixTriggerStep(&sFix, pTrig->step_list) ) {
        goto triggerfinish_cleanup;
    }

    /* if we are not initializing, and this trigger is not on a TEMP table,
    ** build the sqlite_master entry
    */
    if( !db->init.busy ) {
        static const VdbeOpList insertTrig[] = {
            { OP_NewRowid,   0, 0,  0          },
            { OP_String8,    0, 0,  "trigger"  },
            { OP_String8,    0, 0,  0          },  /* 2: trigger name */
            { OP_String8,    0, 0,  0          },  /* 3: table name */
            { OP_Integer,    0, 0,  0          },
            { OP_String8,    0, 0,  "CREATE TRIGGER "},
            { OP_String8,    0, 0,  0          },  /* 6: SQL */
            { OP_Concat,     0, 0,  0          },
            { OP_MakeRecord, 5, 0,  "aaada"    },
            { OP_Insert,     0, 0,  0          },
        };
        int addr;
        Vdbe *v;

        /* Make an entry in the sqlite_master table */
        v = sqlite3GetVdbe(pParse);
        if( v==0 ) goto triggerfinish_cleanup;
        sqlite3BeginWriteOperation(pParse, 0, iDb);
        sqlite3OpenMasterTable(pParse, iDb);
        addr = sqlite3VdbeAddOpList(v, ArraySize(insertTrig), insertTrig);
        sqlite3VdbeChangeP3(v, addr+2, pTrig->name, 0);
        sqlite3VdbeChangeP3(v, addr+3, pTrig->table, 0);
        sqlite3VdbeChangeP3(v, addr+6, (char*)pAll->z, pAll->n);
        sqlite3ChangeCookie(db, v, iDb);
        sqlite3VdbeAddOp(v, OP_Close, 0, 0);
        sqlite3VdbeOp3(v, OP_ParseSchema, iDb, 0,
                       sqlite3MPrintf("type='trigger' AND name='%q'", pTrig->name), P3_DYNAMIC);
    }

    if( db->init.busy ) {
        int n;
        Table *pTab;
        Trigger *pDel;
        pDel = sqlite3HashInsert(&db->aDb[iDb].pSchema->trigHash,
                                 pTrig->name, strlen(pTrig->name)+1, pTrig);
        if( pDel ) {
            assert( sqlite3ThreadDataReadOnly()->mallocFailed && pDel==pTrig );
            goto triggerfinish_cleanup;
        }
        n = strlen(pTrig->table) + 1;
        pTab = sqlite3HashFind(&pTrig->pTabSchema->tblHash, pTrig->table, n);
        assert( pTab!=0 );
        pTrig->pNext = pTab->pTrigger;
        pTab->pTrigger = pTrig;
        pTrig = 0;
    }

triggerfinish_cleanup:
    sqlite3DeleteTrigger(pTrig);
    assert( !pParse->pNewTrigger );
    sqlite3DeleteTriggerStep(pStepList);
}