DBD-SQLite2
view release on metacpan or search on metacpan
- 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
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
/************************************************************************
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
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);
}
/*
** 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);
/* 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;
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);
/*
** 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.
*/
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 */
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;
}
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 ){
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;
/*
**
** 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);
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);
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;
}
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);
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)
{
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
}
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.
** 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.
*/
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;
}
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);
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;
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
/*
}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;
}
** *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 */
);
/*
**
** 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_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
/* 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;
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 },
};
*/
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
**
** 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.
**
** 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;
** 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--;
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 )