DBD-SQLite2

 view release on metacpan or  search on metacpan

Changes  view on Meta::CPAN

    - Fix SEGV when fetchrow() is called again after it has returned an
      empty list ie. the query has completed. [cpan #16451]
    - Add testcases for [cpan #26775] and [cpan #28448]
    - Fixed [cpan #26775]: Remove () in names with DISTINCT(t.name)
    - Honor -g in $Config{optimize}
    - Add META and POD tests, and META info for EUMM

0.34 2013-04-01 rurban
    - Fix SEGV in t/ak-dbd.t with asan, concurrent _sqlite2_fetch_row  [cpan #55636]
    - Add return value for dbd_bind_ph() - bind_param with handle
    - Add declaration for sqlite2_busy_timeout()
    - Fix clang -Wparentheses and -Wint-conversion warnings

0.33
    - Set HAVE_USLEEP appropriately. This massively improves
      concurrent access to your SQLite DB.

0.32
    - Renamed to DBD::SQLite2 to allow backwards compatibility
    - Implemented busy_timeout API
    - Add internal line number to error reporting

0.31
    - Fixed a free() bug on Win32
    - Silence warnings in test suite
    - Updated to sqlite 2.8.12

0.30
    - Updated to sqlite 2.8.11
    - A few minor bugs fixed

SQLite2.xs  view on Meta::CPAN

    SV *dbh
    char *name
    int argc
    SV *aggr
    CODE:
    {
        sqlite2_db_create_aggregate( dbh, name, argc, aggr );
    }

int 
busy_timeout(dbh, timeout=0)
  SV *dbh
  int timeout
  CODE:
    RETVAL = sqlite2_busy_timeout( dbh, timeout );
  OUTPUT:
    RETVAL

MODULE = DBD::SQLite2          PACKAGE = DBD::SQLite2::st

PROTOTYPES: DISABLE

MODULE = DBD::SQLite2          PACKAGE = DBD::SQLite2

INCLUDE: SQLite2.xsi

SQLiteXS.h  view on Meta::CPAN


/************************************************************************
    DBI Specific Stuff - Added by Matt Sergeant
 ************************************************************************/
#define NEED_DBIXS_VERSION 93
#include <DBIXS.h>
#include "dbdimp.h"
#include <dbd_xsh.h>

#include "sqlite.h"
int sqlite2_busy_timeout( SV *dbh, int timeout );

#endif

auth.c  view on Meta::CPAN

int sqliteAuthCheck(
  Parse *pParse,
  int code,
  const char *zArg1,
  const char *zArg2,
  const char *zArg3
){
  sqlite *db = pParse->db;
  int rc;

  if( db->init.busy || db->xAuth==0 ){
    return SQLITE_OK;
  }
  rc = db->xAuth(db->pAuthArg, code, zArg1, zArg2, zArg3, pParse->zAuthContext);
  if( rc==SQLITE_DENY ){
    sqliteErrorMsg(pParse, "not authorized");
    pParse->rc = SQLITE_AUTH;
  }else if( rc!=SQLITE_OK && rc!=SQLITE_IGNORE ){
    rc = SQLITE_DENY;
    sqliteAuthBadReturnCode(pParse, rc);
  }

build.c  view on Meta::CPAN

/*
** This routine is called when a new SQL statement is beginning to
** be parsed.  Check to see if the schema for the database needs
** to be read from the SQLITE_MASTER and SQLITE_TEMP_MASTER tables.
** If it does, then read it.
*/
void sqliteBeginParse(Parse *pParse, int explainFlag){
  sqlite *db = pParse->db;
  int i;
  pParse->explain = explainFlag;
  if((db->flags & SQLITE_Initialized)==0 && db->init.busy==0 ){
    int rc = sqliteInit(db, &pParse->zErrMsg);
    if( rc!=SQLITE_OK ){
      pParse->rc = rc;
      pParse->nErr++;
    }
  }
  for(i=0; i<db->nDb; i++){
    DbClearProperty(db, i, DB_Locked);
    if( !db->aDb[i].inTrans ){
      DbClearProperty(db, i, DB_Cookie);

build.c  view on Meta::CPAN


  /* Make sure the new table name does not collide with an existing
  ** index or table name.  Issue an error message if it does.
  **
  ** If we are re-reading the sqlite_master table because of a schema
  ** change and a new permanent table is found whose name collides with
  ** an existing temporary table, that is not an error.
  */
  pTable = sqliteFindTable(db, zName, 0);
  iDb = isTemp ? 1 : db->init.iDb;
  if( pTable!=0 && (pTable->iDb==iDb || !db->init.busy) ){
    sqliteErrorMsg(pParse, "table %T already exists", pName);
    sqliteFree(zName);
    return;
  }
  if( (pIdx = sqliteFindIndex(db, zName, 0))!=0 &&
          (pIdx->iDb==0 || !db->init.busy) ){
    sqliteErrorMsg(pParse, "there is already an index named %s", zName);
    sqliteFree(zName);
    return;
  }
  pTable = sqliteMalloc( sizeof(Table) );
  if( pTable==0 ){
    sqliteFree(zName);
    return;
  }
  pTable->zName = zName;

build.c  view on Meta::CPAN

  pParse->pNewTable = pTable;

  /* Begin generating the code that will insert the table record into
  ** the SQLITE_MASTER table.  Note in particular that we must go ahead
  ** and allocate the record number for the table entry now.  Before any
  ** PRIMARY KEY or UNIQUE keywords are parsed.  Those keywords will cause
  ** indices to be created and the table record must come before the 
  ** indices.  Hence, the record number for the table must be allocated
  ** now.
  */
  if( !db->init.busy && (v = sqliteGetVdbe(pParse))!=0 ){
    sqliteBeginWriteOperation(pParse, 0, isTemp);
    if( !isTemp ){
      sqliteVdbeAddOp(v, OP_Integer, db->file_format, 0);
      sqliteVdbeAddOp(v, OP_SetCookie, 0, 1);
    }
    sqliteOpenMasterTable(v, isTemp);
    sqliteVdbeAddOp(v, OP_NewRecno, 0, 0);
    sqliteVdbeAddOp(v, OP_Dup, 0, 0);
    sqliteVdbeAddOp(v, OP_String, 0, 0);
    sqliteVdbeAddOp(v, OP_PutIntKey, 0, 0);

build.c  view on Meta::CPAN


/*
** This routine is called to report the final ")" that terminates
** a CREATE TABLE statement.
**
** The table structure that other action routines have been building
** is added to the internal hash tables, assuming no errors have
** occurred.
**
** An entry for the table is made in the master table on disk, unless
** this is a temporary table or db->init.busy==1.  When db->init.busy==1
** it means we are reading the sqlite_master table because we just
** connected to the database or because the sqlite_master table has
** recently changes, so the entry for this table already exists in
** the sqlite_master table.  We do not want to create it again.
**
** If the pSelect argument is not NULL, it means that this routine
** was called to create a table generated from a 
** "CREATE TABLE ... AS SELECT ..." statement.  The column names of
** the new table will match the result set of the SELECT.
*/

build.c  view on Meta::CPAN

    Table *pSelTab = sqliteResultSetOfSelect(pParse, 0, pSelect);
    if( pSelTab==0 ) return;
    assert( p->aCol==0 );
    p->nCol = pSelTab->nCol;
    p->aCol = pSelTab->aCol;
    pSelTab->nCol = 0;
    pSelTab->aCol = 0;
    sqliteDeleteTable(0, pSelTab);
  }

  /* If the db->init.busy is 1 it means we are reading the SQL off the
  ** "sqlite_master" or "sqlite_temp_master" table on the disk.
  ** So do not write to the disk again.  Extract the root page number
  ** for the table from the db->init.newTnum field.  (The page number
  ** should have been put there by the sqliteOpenCb routine.)
  */
  if( db->init.busy ){
    p->tnum = db->init.newTnum;
  }

  /* If not initializing, then create a record for the new table
  ** in the SQLITE_MASTER table of the database.  The record number
  ** for the new table entry should already be on the stack.
  **
  ** If this is a TEMPORARY table, write the entry into the auxiliary
  ** file instead of into the main database file.
  */
  if( !db->init.busy ){
    int n;
    Vdbe *v;

    v = sqliteGetVdbe(pParse);
    if( v==0 ) return;
    if( p->pSelect==0 ){
      /* A regular table */
      sqliteVdbeOp3(v, OP_CreateTable, 0, p->iDb, (char*)&p->tnum, P3_POINTER);
    }else{
      /* A view */

build.c  view on Meta::CPAN

    return;
  }

  /* Make a copy of the entire SELECT statement that defines the view.
  ** This will force all the Expr.token.z values to be dynamically
  ** allocated rather than point to the input string - which means that
  ** they will persist after the current sqlite_exec() call returns.
  */
  p->pSelect = sqliteSelectDup(pSelect);
  sqliteSelectDelete(pSelect);
  if( !pParse->db->init.busy ){
    sqliteViewGetColumnNames(pParse, p);
  }

  /* Locate the end of the CREATE VIEW statement.  Make sEnd point to
  ** the end.
  */
  sEnd = pParse->sLastToken;
  if( sEnd.z[0]!=0 && sEnd.z[0]!=';' ){
    sEnd.z += sEnd.n;
  }

build.c  view on Meta::CPAN

  Table *pTab;     /* Table to be indexed */
  Index *pIndex;   /* The index to be created */
  char *zName = 0;
  int i, j;
  Token nullId;    /* Fake token for an empty ID list */
  DbFixer sFix;    /* For assigning database names to pTable */
  int isTemp;      /* True for a temporary index */
  sqlite *db = pParse->db;

  if( pParse->nErr || sqlite_malloc_failed ) goto exit_create_index;
  if( db->init.busy 
     && sqliteFixInit(&sFix, pParse, db->init.iDb, "index", pName)
     && sqliteFixSrcList(&sFix, pTable)
  ){
    goto exit_create_index;
  }

  /*
  ** Find the table that is to be indexed.  Return early if not found.
  */
  if( pTable!=0 ){

build.c  view on Meta::CPAN

    pTab =  sqliteSrcListLookup(pParse, pTable);
  }else{
    assert( pName==0 );
    pTab =  pParse->pNewTable;
  }
  if( pTab==0 || pParse->nErr ) goto exit_create_index;
  if( pTab->readOnly ){
    sqliteErrorMsg(pParse, "table %s may not be indexed", pTab->zName);
    goto exit_create_index;
  }
  if( pTab->iDb>=2 && db->init.busy==0 ){
    sqliteErrorMsg(pParse, "table %s may not have indices added", pTab->zName);
    goto exit_create_index;
  }
  if( pTab->pSelect ){
    sqliteErrorMsg(pParse, "views may not be indexed");
    goto exit_create_index;
  }
  isTemp = pTab->iDb==1;

  /*

build.c  view on Meta::CPAN

  **
  ** Exception:  If we are reading the names of permanent indices from the
  ** sqlite_master table (because some other process changed the schema) and
  ** one of the index names collides with the name of a temporary table or
  ** index, then we will continue to process this index.
  **
  ** If pName==0 it means that we are
  ** dealing with a primary key or UNIQUE constraint.  We have to invent our
  ** own name.
  */
  if( pName && !db->init.busy ){
    Index *pISameName;    /* Another index with the same name */
    Table *pTSameName;    /* A table with same name as the index */
    zName = sqliteTableNameFromToken(pName);
    if( zName==0 ) goto exit_create_index;
    if( (pISameName = sqliteFindIndex(db, zName, 0))!=0 ){
      sqliteErrorMsg(pParse, "index %s already exists", zName);
      goto exit_create_index;
    }
    if( (pTSameName = sqliteFindTable(db, zName, 0))!=0 ){
      sqliteErrorMsg(pParse, "there is already a table named %s", zName);

build.c  view on Meta::CPAN

    pTab->pIndex = pIndex;
  }else{
    Index *pOther = pTab->pIndex;
    while( pOther->pNext && pOther->pNext->onError!=OE_Replace ){
      pOther = pOther->pNext;
    }
    pIndex->pNext = pOther->pNext;
    pOther->pNext = pIndex;
  }

  /* If the db->init.busy is 1 it means we are reading the SQL off the
  ** "sqlite_master" table on the disk.  So do not write to the disk
  ** again.  Extract the table number from the db->init.newTnum field.
  */
  if( db->init.busy && pTable!=0 ){
    pIndex->tnum = db->init.newTnum;
  }

  /* If the db->init.busy is 0 then create the index on disk.  This
  ** involves writing the index into the master table and filling in the
  ** index with the current table contents.
  **
  ** The db->init.busy is 0 when the user first enters a CREATE INDEX 
  ** command.  db->init.busy is 1 when a database is opened and 
  ** CREATE INDEX statements are read out of the master table.  In
  ** the latter case the index already exists on disk, which is why
  ** we don't want to recreate it.
  **
  ** If pTable==0 it means this index is generated as a primary key
  ** or UNIQUE constraint of a CREATE TABLE statement.  Since the table
  ** has just been created, it contains no data and the index initialization
  ** step can be skipped.
  */
  else if( db->init.busy==0 ){
    int n;
    Vdbe *v;
    int lbl1, lbl2;
    int i;
    int addr;

    v = sqliteGetVdbe(pParse);
    if( v==0 ) goto exit_create_index;
    if( pTable!=0 ){
      sqliteBeginWriteOperation(pParse, 0, isTemp);

dbdimp.c  view on Meta::CPAN

    DBIc_IMPSET_on(imp_dbh);

    imp_dbh->in_tran = FALSE;
    imp_dbh->no_utf8_flag = FALSE;
    imp_dbh->functions = newAV();
    imp_dbh->aggregates = newAV();
    imp_dbh->timeout = SQL_TIMEOUT;
    
    imp_dbh->handle_binary_nulls = FALSE;

    sqlite_busy_timeout(imp_dbh->db, SQL_TIMEOUT);

    if ((retval = sqlite_exec(imp_dbh->db, "PRAGMA empty_result_callbacks = ON",
        NULL, NULL, &errmsg)
	 != SQLITE_OK))
    {
        /*  warn("failed to set pragma: %s\n", errmsg); */
	    sqlite2_error(dbh, (imp_xxh_t*)imp_dbh, retval, errmsg);
        sqlite_freemem(errmsg);
        return FALSE;
    }

dbdimp.c  view on Meta::CPAN

        sqlite_freemem(errmsg);
        return FALSE;
    }

    DBIc_ACTIVE_on(imp_dbh);

    return TRUE;
}

int
sqlite2_busy_timeout ( SV *dbh, int timeout )
{
  D_imp_dbh(dbh);
  if (timeout) {
    imp_dbh->timeout = timeout;
    sqlite_busy_timeout(imp_dbh->db, timeout);
  }
  return imp_dbh->timeout;
}

int
sqlite2_db_disconnect (SV *dbh, imp_dbh_t *imp_dbh)
{
    dTHR;
    DBIc_ACTIVE_off(imp_dbh);

dbdimp.c  view on Meta::CPAN


int
_sqlite2_fetch_row (imp_sth_t *imp_sth)
{
    while (1)
    {
        if (imp_sth->vm)
          imp_sth->retval = sqlite_step(imp_sth->vm,
            &(imp_sth->ncols), (const char ***)&(imp_sth->results), (const char ***)&(imp_sth->coldata));
        if (imp_sth->retval == SQLITE_BUSY) {
            break; /* We should never get "busy" here because we set sqlite_timeout, so assume error */
        }
        break;
    }
    /* warn("step got: %d\nCol1: %s\n", imp_sth->retval, imp_sth->coldata[0]); */
    return imp_sth->retval;
}

int
sqlite2_st_execute (SV *sth, imp_sth_t *imp_sth)
{

main.c  view on Meta::CPAN

    case 'v':
    case 'i':
    case 't': {  /* CREATE TABLE, CREATE INDEX, or CREATE VIEW statements */
      sqlite *db = pData->db;
      if( argv[2]==0 || argv[4]==0 ){
        corruptSchema(pData, 0);
        return 1;
      }
      if( argv[3] && argv[3][0] ){
        /* Call the parser to process a CREATE TABLE, INDEX or VIEW.
        ** But because db->init.busy is set to 1, no VDBE code is generated
        ** or executed.  All the parser does is build the internal data
        ** structures that describe the table, index, or view.
        */
        char *zErr;
        assert( db->init.busy );
        db->init.iDb = atoi(argv[4]);
        assert( db->init.iDb>=0 && db->init.iDb<db->nDb );
        db->init.newTnum = atoi(argv[2]);
        if( sqlite_exec(db, argv[3], 0, 0, &zErr) ){
          corruptSchema(pData, zErr);
          sqlite_freemem(zErr);
        }
        db->init.iDb = 0;
      }else{
        /* If the SQL column is blank it means this is an index that

main.c  view on Meta::CPAN

    }
    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.

main.c  view on Meta::CPAN

** 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) || i==1 ) continue;
    rc = sqliteInitOne(db, i, pzErrMsg);
    if( rc ){
      sqliteResetInternalSchema(db, i);
    }
  }

  /* Once all the other databases have been initialised, load the schema
  ** for the TEMP database. This is loaded last, as the TEMP database
  ** schema may contain references to objects in other databases.
  */
  if( rc==SQLITE_OK && db->nDb>1 && !DbHasProperty(db, 1, DB_SchemaLoaded) ){
    rc = sqliteInitOne(db, 1, pzErrMsg);
    if( rc ){
      sqliteResetInternalSchema(db, 1);
    }
  }

  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.
  */

main.c  view on Meta::CPAN

  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;
      }

main.c  view on Meta::CPAN

        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);

main.c  view on Meta::CPAN

    case SQLITE_AUTH:       z = "authorization denied";                  break;
    case SQLITE_FORMAT:     z = "auxiliary database format error";       break;
    case SQLITE_RANGE:      z = "bind index out of range";               break;
    case SQLITE_NOTADB:     z = "file is encrypted or is not a database";break;
    default:                z = "unknown error";                         break;
  }
  return z;
}

/*
** This routine implements a busy callback that sleeps and tries
** again until a timeout value is reached.  The timeout value is
** an integer number of milliseconds passed in as the first
** argument.
*/
static int sqliteDefaultBusyCallback(
 void *Timeout,           /* Maximum amount of time to wait */
 const char *NotUsed,     /* The name of the table that is busy */
 int count                /* Number of times table has been busy */
){
#if SQLITE_MIN_SLEEP_MS==1
  static const char delays[] =
     { 1, 2, 5, 10, 15, 20, 25, 25,  25,  50,  50,  50, 100};
  static const short int totals[] =
     { 0, 1, 3,  8, 18, 33, 53, 78, 103, 128, 178, 228, 287};
# define NDELAY (sizeof(delays)/sizeof(delays[0]))
  int timeout = (int)(long)Timeout;
  int delay, prior;

main.c  view on Meta::CPAN

  int timeout = (int)(long)Timeout;
  if( (count+1)*1000 > timeout ){
    return 0;
  }
  sqliteOsSleep(1000);
  return 1;
#endif
}

/*
** This routine sets the busy callback for an Sqlite database to the
** given callback function with the given argument.
*/
void sqlite_busy_handler(
  sqlite *db,
  int (*xBusy)(void*,const char*,int),
  void *pArg
){
  db->xBusyCallback = xBusy;
  db->pBusyArg = pArg;
}

#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
/*

main.c  view on Meta::CPAN

  }else{
    db->xProgress = 0;
    db->nProgressOps = 0;
    db->pProgressArg = 0;
  }
}
#endif


/*
** This routine installs a default busy handler that waits for the
** specified number of milliseconds before returning 0.
*/
void sqlite_busy_timeout(sqlite *db, int ms){
  if( ms>0 ){
    sqlite_busy_handler(db, sqliteDefaultBusyCallback, (void*)(long)ms);
  }else{
    sqlite_busy_handler(db, 0, 0);
  }
}

/*
** Cause any pending operation to stop at its earliest opportunity.
*/
void sqlite_interrupt(sqlite *db){
  db->flags |= SQLITE_Interrupt;
}

sqlite.h  view on Meta::CPAN

** *errmsg is made to point to that message.  The calling function
** is responsible for freeing the memory that holds the error
** message.   Use sqlite_freemem() for this.  If errmsg==NULL,
** then no error message is ever written.
**
** The return value is is SQLITE_OK if there are no errors and
** some other return code if there is an error.  The particular
** return value depends on the type of error. 
**
** If the query could not be executed because a database file is
** locked or busy, then this function returns SQLITE_BUSY.  (This
** behavior can be modified somewhat using the sqlite_busy_handler()
** and sqlite_busy_timeout() functions below.)
*/
int sqlite_exec(
  sqlite*,                      /* An open database */
  const char *sql,              /* SQL to be executed */
  sqlite_callback,              /* Callback function */
  void *,                       /* 1st argument to callback function */
  char **errmsg                 /* Error msg written here */
);

/*

sqlite.h  view on Meta::CPAN

**
** The algorithm is simple.  If the last token other than spaces
** and comments is a semicolon, then return true.  otherwise return
** false.
*/
int sqlite_complete(const char *sql);

/*
** This routine identifies a callback function that is invoked
** whenever an attempt is made to open a database table that is
** currently locked by another process or thread.  If the busy callback
** is NULL, then sqlite_exec() returns SQLITE_BUSY immediately if
** it finds a locked table.  If the busy callback is not NULL, then
** sqlite_exec() invokes the callback with three arguments.  The
** second argument is the name of the locked table and the third
** argument is the number of times the table has been busy.  If the
** busy callback returns 0, then sqlite_exec() immediately returns
** SQLITE_BUSY.  If the callback returns non-zero, then sqlite_exec()
** tries to open the table again and the cycle repeats.
**
** The default busy callback is NULL.
**
** Sqlite is re-entrant, so the busy handler may start a new query. 
** (It is not clear why anyone would every want to do this, but it
** is allowed, in theory.)  But the busy handler may not close the
** database.  Closing the database from a busy handler will delete 
** data structures out from under the executing query and will 
** probably result in a coredump.
*/
void sqlite_busy_handler(sqlite*, int(*)(void*,const char*,int), void*);

/*
** This routine sets a busy handler that sleeps for a while when a
** table is locked.  The handler will sleep multiple times until 
** at least "ms" milleseconds of sleeping have been done.  After
** "ms" milleseconds of sleeping, the handler returns 0 which
** causes sqlite_exec() to return SQLITE_BUSY.
**
** Calling this routine with an argument less than or equal to zero
** turns off all busy handlers.
*/
void sqlite_busy_timeout(sqlite*, int ms);

/*
** This next routine is really just a wrapper around sqlite_exec().
** Instead of invoking a user-supplied callback for each row of the
** result, this routine remembers each row of the result in memory
** obtained from malloc(), then returns all of the result after the
** query has finished. 
**
** As an example, suppose the query result where this table:
**

sqlite.h  view on Meta::CPAN

**
** SQLITE_ERROR means that the virtual machine encountered a run-time
** error.  sqlite_step() should not be called again for the same
** virtual machine.  *pN is set to 0 and *pazColName and *pazValue are set
** to NULL.  Use sqlite_finalize() to obtain the specific error code
** and the error message text for the error.
**
** SQLITE_BUSY means that an attempt to open the database failed because
** another thread or process is holding a lock.  The calling routine
** can try again to open the database by calling sqlite_step() again.
** The return code will only be SQLITE_BUSY if no busy handler is registered
** using the sqlite_busy_handler() or sqlite_busy_timeout() routines.  If
** a busy handler callback has been registered but returns 0, then this
** routine will return SQLITE_ERROR and sqltie_finalize() will return
** SQLITE_BUSY when it is called.
**
** SQLITE_ROW means that a single row of the result is now available.
** The data is contained in *pazValue.  The value of the i-th column is
** (*azValue)[i].  *pN and *pazColName are set as described in SQLITE_DONE.
** Invoke sqlite_step() again to advance to the next row.
**
** SQLITE_MISUSE is returned if sqlite_step() is called incorrectly.
** For example, if you call sqlite_step() after the virtual machine

sqliteInt.h  view on Meta::CPAN

  Db aDbStatic[2];              /* Static space for the 2 default backends */
  int flags;                    /* Miscellanous flags. See below */
  u8 file_format;               /* What file format version is this database? */
  u8 safety_level;              /* How aggressive at synching data to disk */
  u8 want_to_close;             /* Close after all VDBEs are deallocated */
  u8 temp_store;                /* 1=file, 2=memory, 0=compile-time default */
  u8 onError;                   /* Default conflict algorithm */
  int next_cookie;              /* Next value of aDb[0].schema_cookie */
  int cache_size;               /* Number of pages to use in the cache */
  int nTable;                   /* Number of tables in the database */
  void *pBusyArg;               /* 1st Argument to the busy callback */
  int (*xBusyCallback)(void *,const char*,int);  /* The busy callback */
  void *pCommitArg;             /* Argument to xCommitCallback() */   
  int (*xCommitCallback)(void*);/* Invoked at every commit. */
  Hash aFunc;                   /* All functions that can be in SQL exprs */
  int lastRowid;                /* ROWID of most recent insert (see above) */
  int priorNewRowid;            /* Last randomly generated ROWID */
  int magic;                    /* Magic number for detect library misuse */
  int nChange;                  /* Number of rows changed (see above) */
  int lsChange;                 /* Last statement change count (see above) */
  int csChange;                 /* Current statement change count (see above) */
  struct sqliteInitInfo {       /* Information used during initialization */
    int iDb;                       /* When back is being initialized */
    int newTnum;                   /* Rootpage of table being initialized */
    u8 busy;                       /* TRUE if currently initializing */
  } init;
  struct Vdbe *pVdbe;           /* List of active virtual machines */
  void (*xTrace)(void*,const char*);     /* Trace function */
  void *pTraceArg;                       /* Argument to the trace function */
#ifndef SQLITE_OMIT_AUTHORIZATION
  int (*xAuth)(void*,int,const char*,const char*,const char*,const char*);
                                /* Access authorization function */
  void *pAuthArg;               /* 1st argument to the access auth function */
#endif
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK

trigger.c  view on Meta::CPAN


  /* Check that: 
  ** 1. the trigger name does not already exist.
  ** 2. the table (or view) does exist in the same database as the trigger.
  ** 3. that we are not trying to create a trigger on the sqlite_master table
  ** 4. That we are not trying to create an INSTEAD OF trigger on a table.
  ** 5. That we are not trying to create a BEFORE or AFTER trigger on a view.
  */
  if( sqlite_malloc_failed ) goto trigger_cleanup;
  assert( pTableName->nSrc==1 );
  if( db->init.busy
   && sqliteFixInit(&sFix, pParse, db->init.iDb, "trigger", pName)
   && sqliteFixSrcList(&sFix, pTableName)
  ){
    goto trigger_cleanup;
  }
  tab = sqliteSrcListLookup(pParse, pTableName);
  if( !tab ){
    goto trigger_cleanup;
  }
  iDb = isTemp ? 1 : tab->iDb;
  if( iDb>=2 && !db->init.busy ){
    sqliteErrorMsg(pParse, "triggers may not be added to auxiliary "
       "database %s", db->aDb[tab->iDb].zName);
    goto trigger_cleanup;
  }

  zName = sqliteStrNDup(pName->z, pName->n);
  sqliteDequote(zName);
  if( sqliteHashFind(&(db->aDb[iDb].trigHash), zName,pName->n+1) ){
    sqliteErrorMsg(pParse, "trigger %T already exists", pName);
    goto trigger_cleanup;

trigger.c  view on Meta::CPAN

    pStepList = pStepList->pNext;
  }
  if( sqliteFixInit(&sFix, pParse, nt->iDb, "trigger", &nt->nameToken) 
          && sqliteFixTriggerStep(&sFix, nt->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 VdbeOpList insertTrig[] = {
      { OP_NewRecno,   0, 0,  0          },
      { OP_String,     0, 0,  "trigger"  },
      { OP_String,     0, 0,  0          },  /* 2: trigger name */
      { OP_String,     0, 0,  0          },  /* 3: table name */
      { OP_Integer,    0, 0,  0          },
      { OP_String,     0, 0,  0          },  /* 5: SQL */
      { OP_MakeRecord, 5, 0,  0          },
      { OP_PutIntKey,  0, 0,  0          },
    };

vdbe.c  view on Meta::CPAN

*/
int sqlite_interrupt_count = 0;

/*
** Advance the virtual machine to the next output row.
**
** The return vale will be either SQLITE_BUSY, SQLITE_DONE, 
** SQLITE_ROW, SQLITE_ERROR, or SQLITE_MISUSE.
**
** SQLITE_BUSY means that the virtual machine attempted to open
** a locked database and there is no busy callback registered.
** Call sqlite_step() again to retry the open.  *pN is set to 0
** and *pazColName and *pazValue are both set to NULL.
**
** SQLITE_DONE means that the virtual machine has finished
** executing.  sqlite_step() should not be called again on this
** virtual machine.  *pN and *pazColName are set appropriately
** but *pazValue is set to NULL.
**
** SQLITE_ROW means that the virtual machine has generated another
** row of the result set.  *pN is set to the number of columns in

vdbe.c  view on Meta::CPAN

**
** sqliteVdbeMakeReady() must be called before this routine in order to
** close the program with a final OP_Halt and to set up the callbacks
** and the error message pointer.
**
** Whenever a row or result data is available, this routine will either
** invoke the result callback (if there is one) or return with
** SQLITE_ROW.
**
** If an attempt is made to open a locked database, then this routine
** will either invoke the busy callback (if there is one) or it will
** return SQLITE_BUSY.
**
** If an error occurs, an error message is written to memory obtained
** from sqliteMalloc() and p->zErrMsg is made to point to that memory.
** The error code is stored in p->rc and this routine returns SQLITE_ERROR.
**
** If the callback ever returns non-zero, then the program exits
** immediately.  There will be no error message but the p->rc field is
** set to SQLITE_ABORT and this routine will return SQLITE_ERROR.
**

vdbe.c  view on Meta::CPAN

** started.  Index 0 is the main database file and index 1 is the
** file used for temporary tables.
**
** A write lock is obtained on the database file when a transaction is
** started.  No other process can read or write the file while the
** transaction is underway.  Starting a transaction also creates a
** rollback journal.  A transaction must be started before any changes
** can be made to the database.
*/
case OP_Transaction: {
  int busy = 1;
  int i = pOp->p1;
  assert( i>=0 && i<db->nDb );
  if( db->aDb[i].inTrans ) break;
  while( db->aDb[i].pBt!=0 && busy ){
    rc = sqliteBtreeBeginTrans(db->aDb[i].pBt);
    switch( rc ){
      case SQLITE_BUSY: {
        if( db->xBusyCallback==0 ){
          p->pc = pc;
          p->undoTransOnError = 1;
          p->rc = SQLITE_BUSY;
          p->pTos = pTos;
          return SQLITE_BUSY;
        }else if( (*db->xBusyCallback)(db->pBusyArg, "", busy++)==0 ){
          sqliteSetString(&p->zErrMsg, sqlite_error_string(rc), (char*)0);
          busy = 0;
        }
        break;
      }
      case SQLITE_READONLY: {
        rc = SQLITE_OK;
        /* Fall thru into the next case */
      }
      case SQLITE_OK: {
        p->inTempTrans = 0;
        busy = 0;
        break;
      }
      default: {
        goto abort_due_to_error;
      }
    }
  }
  db->aDb[i].inTrans = 1;
  p->undoTransOnError = 1;
  break;

vdbe.c  view on Meta::CPAN

** table name into P3 to make the code easier to read.
**
** This instruction works just like OpenRead except that it opens the cursor
** in read/write mode.  For a given table, there can be one or more read-only
** cursors or a single read/write cursor but not both.
**
** See also OpenRead.
*/
case OP_OpenRead:
case OP_OpenWrite: {
  int busy = 0;
  int i = pOp->p1;
  int p2 = pOp->p2;
  int wrFlag;
  Btree *pX;
  int iDb;
  
  assert( pTos>=p->aStack );
  Integerify(pTos);
  iDb = pTos->i;
  pTos--;

vdbe.c  view on Meta::CPAN

  if( pX==0 ) break;
  do{
    rc = sqliteBtreeCursor(pX, p2, wrFlag, &p->aCsr[i].pCursor);
    switch( rc ){
      case SQLITE_BUSY: {
        if( db->xBusyCallback==0 ){
          p->pc = pc;
          p->rc = SQLITE_BUSY;
          p->pTos = &pTos[1 + (pOp->p2<=0)]; /* Operands must remain on stack */
          return SQLITE_BUSY;
        }else if( (*db->xBusyCallback)(db->pBusyArg, pOp->p3, ++busy)==0 ){
          sqliteSetString(&p->zErrMsg, sqlite_error_string(rc), (char*)0);
          busy = 0;
        }
        break;
      }
      case SQLITE_OK: {
        busy = 0;
        break;
      }
      default: {
        goto abort_due_to_error;
      }
    }
  }while( busy );
  break;
}

/* Opcode: OpenTemp P1 P2 *
**
** Open a new cursor to a transient table.
** The transient cursor is always opened read/write even if 
** the main database is read-only.  The transient table is deleted
** automatically when the cursor is closed.
**



( run in 0.519 second using v1.01-cache-2.11-cpan-87723dcf8b7 )