Patch level : 2.2

Files correlati     : sqlite
Ricompilazione Demo : [ ]
Commento            :
Passaggio da Sqlite 2 a Sqlite 3.3.5


git-svn-id: svn://10.65.10.50/trunk@13902 c028cbd2-c16b-5b4b-a496-9718f37d4682
This commit is contained in:
guy 2006-04-13 12:44:29 +00:00
parent 32422b92b9
commit e883f21fe8
59 changed files with 42398 additions and 24156 deletions

562
sqlite/alter.c Executable file
View File

@ -0,0 +1,562 @@
/*
** 2005 February 15
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that used to generate VDBE code
** that implements the ALTER TABLE command.
**
** $Id: alter.c,v 1.1 2006-04-13 12:44:29 guy Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
/*
** The code in this file only exists if we are not omitting the
** ALTER TABLE logic from the build.
*/
#ifndef SQLITE_OMIT_ALTERTABLE
/*
** This function is used by SQL generated to implement the
** ALTER TABLE command. The first argument is the text of a CREATE TABLE or
** CREATE INDEX command. The second is a table name. The table name in
** the CREATE TABLE or CREATE INDEX statement is replaced with the second
** argument and the result returned. Examples:
**
** sqlite_rename_table('CREATE TABLE abc(a, b, c)', 'def')
** -> 'CREATE TABLE def(a, b, c)'
**
** sqlite_rename_table('CREATE INDEX i ON abc(a)', 'def')
** -> 'CREATE INDEX i ON def(a, b, c)'
*/
static void renameTableFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
unsigned char const *zSql = sqlite3_value_text(argv[0]);
unsigned char const *zTableName = sqlite3_value_text(argv[1]);
int token;
Token tname;
unsigned char const *zCsr = zSql;
int len = 0;
char *zRet;
/* The principle used to locate the table name in the CREATE TABLE
** statement is that the table name is the first token that is immediatedly
** followed by a left parenthesis - TK_LP.
*/
if( zSql ){
do {
/* Store the token that zCsr points to in tname. */
tname.z = zCsr;
tname.n = len;
/* Advance zCsr to the next token. Store that token type in 'token',
** and it's length in 'len' (to be used next iteration of this loop).
*/
do {
zCsr += len;
len = sqlite3GetToken(zCsr, &token);
} while( token==TK_SPACE );
assert( len>0 );
} while( token!=TK_LP );
zRet = sqlite3MPrintf("%.*s%Q%s", tname.z - zSql, zSql,
zTableName, tname.z+tname.n);
sqlite3_result_text(context, zRet, -1, sqlite3FreeX);
}
}
#ifndef SQLITE_OMIT_TRIGGER
/* This function is used by SQL generated to implement the ALTER TABLE
** ALTER TABLE command. The first argument is the text of a CREATE TRIGGER
** statement. The second is a table name. The table name in the CREATE
** TRIGGER statement is replaced with the second argument and the result
** returned. This is analagous to renameTableFunc() above, except for CREATE
** TRIGGER, not CREATE INDEX and CREATE TABLE.
*/
static void renameTriggerFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
unsigned char const *zSql = sqlite3_value_text(argv[0]);
unsigned char const *zTableName = sqlite3_value_text(argv[1]);
int token;
Token tname;
int dist = 3;
unsigned char const *zCsr = zSql;
int len = 0;
char *zRet;
/* The principle used to locate the table name in the CREATE TRIGGER
** statement is that the table name is the first token that is immediatedly
** preceded by either TK_ON or TK_DOT and immediatedly followed by one
** of TK_WHEN, TK_BEGIN or TK_FOR.
*/
if( zSql ){
do {
/* Store the token that zCsr points to in tname. */
tname.z = zCsr;
tname.n = len;
/* Advance zCsr to the next token. Store that token type in 'token',
** and it's length in 'len' (to be used next iteration of this loop).
*/
do {
zCsr += len;
len = sqlite3GetToken(zCsr, &token);
}while( token==TK_SPACE );
assert( len>0 );
/* Variable 'dist' stores the number of tokens read since the most
** recent TK_DOT or TK_ON. This means that when a WHEN, FOR or BEGIN
** token is read and 'dist' equals 2, the condition stated above
** to be met.
**
** Note that ON cannot be a database, table or column name, so
** there is no need to worry about syntax like
** "CREATE TRIGGER ... ON ON.ON BEGIN ..." etc.
*/
dist++;
if( token==TK_DOT || token==TK_ON ){
dist = 0;
}
} while( dist!=2 || (token!=TK_WHEN && token!=TK_FOR && token!=TK_BEGIN) );
/* Variable tname now contains the token that is the old table-name
** in the CREATE TRIGGER statement.
*/
zRet = sqlite3MPrintf("%.*s%Q%s", tname.z - zSql, zSql,
zTableName, tname.z+tname.n);
sqlite3_result_text(context, zRet, -1, sqlite3FreeX);
}
}
#endif /* !SQLITE_OMIT_TRIGGER */
/*
** Register built-in functions used to help implement ALTER TABLE
*/
void sqlite3AlterFunctions(sqlite3 *db){
static const struct {
char *zName;
signed char nArg;
void (*xFunc)(sqlite3_context*,int,sqlite3_value **);
} aFuncs[] = {
{ "sqlite_rename_table", 2, renameTableFunc},
#ifndef SQLITE_OMIT_TRIGGER
{ "sqlite_rename_trigger", 2, renameTriggerFunc},
#endif
};
int i;
for(i=0; i<sizeof(aFuncs)/sizeof(aFuncs[0]); i++){
sqlite3CreateFunc(db, aFuncs[i].zName, aFuncs[i].nArg,
SQLITE_UTF8, 0, aFuncs[i].xFunc, 0, 0);
}
}
/*
** Generate the text of a WHERE expression which can be used to select all
** temporary triggers on table pTab from the sqlite_temp_master table. If
** table pTab has no temporary triggers, or is itself stored in the
** temporary database, NULL is returned.
*/
static char *whereTempTriggers(Parse *pParse, Table *pTab){
Trigger *pTrig;
char *zWhere = 0;
char *tmp = 0;
const Schema *pTempSchema = pParse->db->aDb[1].pSchema; /* Temp db schema */
/* If the table is not located in the temp-db (in which case NULL is
** returned, loop through the tables list of triggers. For each trigger
** that is not part of the temp-db schema, add a clause to the WHERE
** expression being built up in zWhere.
*/
if( pTab->pSchema!=pTempSchema ){
for( pTrig=pTab->pTrigger; pTrig; pTrig=pTrig->pNext ){
if( pTrig->pSchema==pTempSchema ){
if( !zWhere ){
zWhere = sqlite3MPrintf("name=%Q", pTrig->name);
}else{
tmp = zWhere;
zWhere = sqlite3MPrintf("%s OR name=%Q", zWhere, pTrig->name);
sqliteFree(tmp);
}
}
}
}
return zWhere;
}
/*
** Generate code to drop and reload the internal representation of table
** pTab from the database, including triggers and temporary triggers.
** Argument zName is the name of the table in the database schema at
** the time the generated code is executed. This can be different from
** pTab->zName if this function is being called to code part of an
** "ALTER TABLE RENAME TO" statement.
*/
static void reloadTableSchema(Parse *pParse, Table *pTab, const char *zName){
Vdbe *v;
char *zWhere;
int iDb; /* Index of database containing pTab */
#ifndef SQLITE_OMIT_TRIGGER
Trigger *pTrig;
#endif
v = sqlite3GetVdbe(pParse);
if( !v ) return;
iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
assert( iDb>=0 );
#ifndef SQLITE_OMIT_TRIGGER
/* Drop any table triggers from the internal schema. */
for(pTrig=pTab->pTrigger; pTrig; pTrig=pTrig->pNext){
int iTrigDb = sqlite3SchemaToIndex(pParse->db, pTrig->pSchema);
assert( iTrigDb==iDb || iTrigDb==1 );
sqlite3VdbeOp3(v, OP_DropTrigger, iTrigDb, 0, pTrig->name, 0);
}
#endif
/* Drop the table and index from the internal schema */
sqlite3VdbeOp3(v, OP_DropTable, iDb, 0, pTab->zName, 0);
/* Reload the table, index and permanent trigger schemas. */
zWhere = sqlite3MPrintf("tbl_name=%Q", zName);
if( !zWhere ) return;
sqlite3VdbeOp3(v, OP_ParseSchema, iDb, 0, zWhere, P3_DYNAMIC);
#ifndef SQLITE_OMIT_TRIGGER
/* Now, if the table is not stored in the temp database, reload any temp
** triggers. Don't use IN(...) in case SQLITE_OMIT_SUBQUERY is defined.
*/
if( (zWhere=whereTempTriggers(pParse, pTab))!=0 ){
sqlite3VdbeOp3(v, OP_ParseSchema, 1, 0, zWhere, P3_DYNAMIC);
}
#endif
}
/*
** Generate code to implement the "ALTER TABLE xxx RENAME TO yyy"
** command.
*/
void sqlite3AlterRenameTable(
Parse *pParse, /* Parser context. */
SrcList *pSrc, /* The table to rename. */
Token *pName /* The new table name. */
){
int iDb; /* Database that contains the table */
char *zDb; /* Name of database iDb */
Table *pTab; /* Table being renamed */
char *zName = 0; /* NULL-terminated version of pName */
sqlite3 *db = pParse->db; /* Database connection */
Vdbe *v;
#ifndef SQLITE_OMIT_TRIGGER
char *zWhere = 0; /* Where clause to locate temp triggers */
#endif
if( sqlite3MallocFailed() ) goto exit_rename_table;
assert( pSrc->nSrc==1 );
pTab = sqlite3LocateTable(pParse, pSrc->a[0].zName, pSrc->a[0].zDatabase);
if( !pTab ) goto exit_rename_table;
iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
zDb = db->aDb[iDb].zName;
/* Get a NULL terminated version of the new table name. */
zName = sqlite3NameFromToken(pName);
if( !zName ) goto exit_rename_table;
/* Check that a table or index named 'zName' does not already exist
** in database iDb. If so, this is an error.
*/
if( sqlite3FindTable(db, zName, zDb) || sqlite3FindIndex(db, zName, zDb) ){
sqlite3ErrorMsg(pParse,
"there is already another table or index with this name: %s", zName);
goto exit_rename_table;
}
/* Make sure it is not a system table being altered, or a reserved name
** that the table is being renamed to.
*/
if( strlen(pTab->zName)>6 && 0==sqlite3StrNICmp(pTab->zName, "sqlite_", 7) ){
sqlite3ErrorMsg(pParse, "table %s may not be altered", pTab->zName);
goto exit_rename_table;
}
if( SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){
goto exit_rename_table;
}
#ifndef SQLITE_OMIT_AUTHORIZATION
/* Invoke the authorization callback. */
if( sqlite3AuthCheck(pParse, SQLITE_ALTER_TABLE, zDb, pTab->zName, 0) ){
goto exit_rename_table;
}
#endif
/* Begin a transaction and code the VerifyCookie for database iDb.
** Then modify the schema cookie (since the ALTER TABLE modifies the
** schema).
*/
v = sqlite3GetVdbe(pParse);
if( v==0 ){
goto exit_rename_table;
}
sqlite3BeginWriteOperation(pParse, 0, iDb);
sqlite3ChangeCookie(db, v, iDb);
/* Modify the sqlite_master table to use the new table name. */
sqlite3NestedParse(pParse,
"UPDATE %Q.%s SET "
#ifdef SQLITE_OMIT_TRIGGER
"sql = sqlite_rename_table(sql, %Q), "
#else
"sql = CASE "
"WHEN type = 'trigger' THEN sqlite_rename_trigger(sql, %Q)"
"ELSE sqlite_rename_table(sql, %Q) END, "
#endif
"tbl_name = %Q, "
"name = CASE "
"WHEN type='table' THEN %Q "
"WHEN name LIKE 'sqlite_autoindex%%' AND type='index' THEN "
"'sqlite_autoindex_' || %Q || substr(name, %d+18,10) "
"ELSE name END "
"WHERE tbl_name=%Q AND "
"(type='table' OR type='index' OR type='trigger');",
zDb, SCHEMA_TABLE(iDb), zName, zName, zName,
#ifndef SQLITE_OMIT_TRIGGER
zName,
#endif
zName, strlen(pTab->zName), pTab->zName
);
#ifndef SQLITE_OMIT_AUTOINCREMENT
/* If the sqlite_sequence table exists in this database, then update
** it with the new table name.
*/
if( sqlite3FindTable(db, "sqlite_sequence", zDb) ){
sqlite3NestedParse(pParse,
"UPDATE %Q.sqlite_sequence set name = %Q WHERE name = %Q",
zDb, zName, pTab->zName);
}
#endif
#ifndef SQLITE_OMIT_TRIGGER
/* If there are TEMP triggers on this table, modify the sqlite_temp_master
** table. Don't do this if the table being ALTERed is itself located in
** the temp database.
*/
if( (zWhere=whereTempTriggers(pParse, pTab))!=0 ){
sqlite3NestedParse(pParse,
"UPDATE sqlite_temp_master SET "
"sql = sqlite_rename_trigger(sql, %Q), "
"tbl_name = %Q "
"WHERE %s;", zName, zName, zWhere);
sqliteFree(zWhere);
}
#endif
/* Drop and reload the internal table schema. */
reloadTableSchema(pParse, pTab, zName);
exit_rename_table:
sqlite3SrcListDelete(pSrc);
sqliteFree(zName);
}
/*
** This function is called after an "ALTER TABLE ... ADD" statement
** has been parsed. Argument pColDef contains the text of the new
** column definition.
**
** The Table structure pParse->pNewTable was extended to include
** the new column during parsing.
*/
void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){
Table *pNew; /* Copy of pParse->pNewTable */
Table *pTab; /* Table being altered */
int iDb; /* Database number */
const char *zDb; /* Database name */
const char *zTab; /* Table name */
char *zCol; /* Null-terminated column definition */
Column *pCol; /* The new column */
Expr *pDflt; /* Default value for the new column */
if( pParse->nErr ) return;
pNew = pParse->pNewTable;
assert( pNew );
iDb = sqlite3SchemaToIndex(pParse->db, pNew->pSchema);
zDb = pParse->db->aDb[iDb].zName;
zTab = pNew->zName;
pCol = &pNew->aCol[pNew->nCol-1];
pDflt = pCol->pDflt;
pTab = sqlite3FindTable(pParse->db, zTab, zDb);
assert( pTab );
#ifndef SQLITE_OMIT_AUTHORIZATION
/* Invoke the authorization callback. */
if( sqlite3AuthCheck(pParse, SQLITE_ALTER_TABLE, zDb, pTab->zName, 0) ){
return;
}
#endif
/* If the default value for the new column was specified with a
** literal NULL, then set pDflt to 0. This simplifies checking
** for an SQL NULL default below.
*/
if( pDflt && pDflt->op==TK_NULL ){
pDflt = 0;
}
/* Check that the new column is not specified as PRIMARY KEY or UNIQUE.
** If there is a NOT NULL constraint, then the default value for the
** column must not be NULL.
*/
if( pCol->isPrimKey ){
sqlite3ErrorMsg(pParse, "Cannot add a PRIMARY KEY column");
return;
}
if( pNew->pIndex ){
sqlite3ErrorMsg(pParse, "Cannot add a UNIQUE column");
return;
}
if( pCol->notNull && !pDflt ){
sqlite3ErrorMsg(pParse,
"Cannot add a NOT NULL column with default value NULL");
return;
}
/* Ensure the default expression is something that sqlite3ValueFromExpr()
** can handle (i.e. not CURRENT_TIME etc.)
*/
if( pDflt ){
sqlite3_value *pVal;
if( sqlite3ValueFromExpr(pDflt, SQLITE_UTF8, SQLITE_AFF_NONE, &pVal) ){
/* malloc() has failed */
return;
}
if( !pVal ){
sqlite3ErrorMsg(pParse, "Cannot add a column with non-constant default");
return;
}
sqlite3ValueFree(pVal);
}
/* Modify the CREATE TABLE statement. */
zCol = sqliteStrNDup((char*)pColDef->z, pColDef->n);
if( zCol ){
char *zEnd = &zCol[pColDef->n-1];
while( (zEnd>zCol && *zEnd==';') || isspace(*(unsigned char *)zEnd) ){
*zEnd-- = '\0';
}
sqlite3NestedParse(pParse,
"UPDATE %Q.%s SET "
"sql = substr(sql,1,%d) || ', ' || %Q || substr(sql,%d,length(sql)) "
"WHERE type = 'table' AND name = %Q",
zDb, SCHEMA_TABLE(iDb), pNew->addColOffset, zCol, pNew->addColOffset+1,
zTab
);
sqliteFree(zCol);
}
/* If the default value of the new column is NULL, then set the file
** format to 2. If the default value of the new column is not NULL,
** the file format becomes 3.
*/
sqlite3MinimumFileFormat(pParse, iDb, pDflt ? 3 : 2);
/* Reload the schema of the modified table. */
reloadTableSchema(pParse, pTab, pTab->zName);
}
/*
** This function is called by the parser after the table-name in
** an "ALTER TABLE <table-name> ADD" statement is parsed. Argument
** pSrc is the full-name of the table being altered.
**
** This routine makes a (partial) copy of the Table structure
** for the table being altered and sets Parse.pNewTable to point
** to it. Routines called by the parser as the column definition
** is parsed (i.e. sqlite3AddColumn()) add the new Column data to
** the copy. The copy of the Table structure is deleted by tokenize.c
** after parsing is finished.
**
** Routine sqlite3AlterFinishAddColumn() will be called to complete
** coding the "ALTER TABLE ... ADD" statement.
*/
void sqlite3AlterBeginAddColumn(Parse *pParse, SrcList *pSrc){
Table *pNew;
Table *pTab;
Vdbe *v;
int iDb;
int i;
int nAlloc;
/* Look up the table being altered. */
assert( pParse->pNewTable==0 );
if( sqlite3MallocFailed() ) goto exit_begin_add_column;
pTab = sqlite3LocateTable(pParse, pSrc->a[0].zName, pSrc->a[0].zDatabase);
if( !pTab ) goto exit_begin_add_column;
/* Make sure this is not an attempt to ALTER a view. */
if( pTab->pSelect ){
sqlite3ErrorMsg(pParse, "Cannot add a column to a view");
goto exit_begin_add_column;
}
assert( pTab->addColOffset>0 );
iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
/* Put a copy of the Table struct in Parse.pNewTable for the
** sqlite3AddColumn() function and friends to modify.
*/
pNew = (Table *)sqliteMalloc(sizeof(Table));
if( !pNew ) goto exit_begin_add_column;
pParse->pNewTable = pNew;
pNew->nRef = 1;
pNew->nCol = pTab->nCol;
assert( pNew->nCol>0 );
nAlloc = (((pNew->nCol-1)/8)*8)+8;
assert( nAlloc>=pNew->nCol && nAlloc%8==0 && nAlloc-pNew->nCol<8 );
pNew->aCol = (Column *)sqliteMalloc(sizeof(Column)*nAlloc);
pNew->zName = sqliteStrDup(pTab->zName);
if( !pNew->aCol || !pNew->zName ){
goto exit_begin_add_column;
}
memcpy(pNew->aCol, pTab->aCol, sizeof(Column)*pNew->nCol);
for(i=0; i<pNew->nCol; i++){
Column *pCol = &pNew->aCol[i];
pCol->zName = sqliteStrDup(pCol->zName);
pCol->zColl = 0;
pCol->zType = 0;
pCol->pDflt = 0;
}
pNew->pSchema = pParse->db->aDb[iDb].pSchema;
pNew->addColOffset = pTab->addColOffset;
pNew->nRef = 1;
/* Begin a transaction and increment the schema cookie. */
sqlite3BeginWriteOperation(pParse, 0, iDb);
v = sqlite3GetVdbe(pParse);
if( !v ) goto exit_begin_add_column;
sqlite3ChangeCookie(pParse->db, v, iDb);
exit_begin_add_column:
sqlite3SrcListDelete(pSrc);
return;
}
#endif /* SQLITE_ALTER_TABLE */

403
sqlite/analyze.c Executable file
View File

@ -0,0 +1,403 @@
/*
** 2005 July 8
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains code associated with the ANALYZE command.
**
** @(#) $Id: analyze.c,v 1.1 2006-04-13 12:44:29 guy Exp $
*/
#ifndef SQLITE_OMIT_ANALYZE
#include "sqliteInt.h"
/*
** This routine generates code that opens the sqlite_stat1 table on cursor
** iStatCur.
**
** If the sqlite_stat1 tables does not previously exist, it is created.
** If it does previously exist, all entires associated with table zWhere
** are removed. If zWhere==0 then all entries are removed.
*/
static void openStatTable(
Parse *pParse, /* Parsing context */
int iDb, /* The database we are looking in */
int iStatCur, /* Open the sqlite_stat1 table on this cursor */
const char *zWhere /* Delete entries associated with this table */
){
sqlite3 *db = pParse->db;
Db *pDb;
int iRootPage;
Table *pStat;
Vdbe *v = sqlite3GetVdbe(pParse);
pDb = &db->aDb[iDb];
if( (pStat = sqlite3FindTable(db, "sqlite_stat1", pDb->zName))==0 ){
/* The sqlite_stat1 tables does not exist. Create it.
** Note that a side-effect of the CREATE TABLE statement is to leave
** the rootpage of the new table on the top of the stack. This is
** important because the OpenWrite opcode below will be needing it. */
sqlite3NestedParse(pParse,
"CREATE TABLE %Q.sqlite_stat1(tbl,idx,stat)",
pDb->zName
);
iRootPage = 0; /* Cause rootpage to be taken from top of stack */
}else if( zWhere ){
/* The sqlite_stat1 table exists. Delete all entries associated with
** the table zWhere. */
sqlite3NestedParse(pParse,
"DELETE FROM %Q.sqlite_stat1 WHERE tbl=%Q",
pDb->zName, zWhere
);
iRootPage = pStat->tnum;
}else{
/* The sqlite_stat1 table already exists. Delete all rows. */
iRootPage = pStat->tnum;
sqlite3VdbeAddOp(v, OP_Clear, pStat->tnum, iDb);
}
/* Open the sqlite_stat1 table for writing. Unless it was created
** by this vdbe program, lock it for writing at the shared-cache level.
** If this vdbe did create the sqlite_stat1 table, then it must have
** already obtained a schema-lock, making the write-lock redundant.
*/
if( iRootPage>0 ){
sqlite3TableLock(pParse, iDb, iRootPage, 1, "sqlite_stat1");
}
sqlite3VdbeAddOp(v, OP_Integer, iDb, 0);
sqlite3VdbeAddOp(v, OP_OpenWrite, iStatCur, iRootPage);
sqlite3VdbeAddOp(v, OP_SetNumColumns, iStatCur, 3);
}
/*
** Generate code to do an analysis of all indices associated with
** a single table.
*/
static void analyzeOneTable(
Parse *pParse, /* Parser context */
Table *pTab, /* Table whose indices are to be analyzed */
int iStatCur, /* Cursor that writes to the sqlite_stat1 table */
int iMem /* Available memory locations begin here */
){
Index *pIdx; /* An index to being analyzed */
int iIdxCur; /* Cursor number for index being analyzed */
int nCol; /* Number of columns in the index */
Vdbe *v; /* The virtual machine being built up */
int i; /* Loop counter */
int topOfLoop; /* The top of the loop */
int endOfLoop; /* The end of the loop */
int addr; /* The address of an instruction */
int iDb; /* Index of database containing pTab */
v = sqlite3GetVdbe(pParse);
if( pTab==0 || pTab->pIndex==0 ){
/* Do no analysis for tables that have no indices */
return;
}
iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
assert( iDb>=0 );
#ifndef SQLITE_OMIT_AUTHORIZATION
if( sqlite3AuthCheck(pParse, SQLITE_ANALYZE, pTab->zName, 0,
pParse->db->aDb[iDb].zName ) ){
return;
}
#endif
/* Establish a read-lock on the table at the shared-cache level. */
sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName);
iIdxCur = pParse->nTab;
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIdx);
/* Open a cursor to the index to be analyzed
*/
assert( iDb==sqlite3SchemaToIndex(pParse->db, pIdx->pSchema) );
sqlite3VdbeAddOp(v, OP_Integer, iDb, 0);
VdbeComment((v, "# %s", pIdx->zName));
sqlite3VdbeOp3(v, OP_OpenRead, iIdxCur, pIdx->tnum,
(char *)pKey, P3_KEYINFO_HANDOFF);
nCol = pIdx->nColumn;
if( iMem+nCol*2>=pParse->nMem ){
pParse->nMem = iMem+nCol*2+1;
}
sqlite3VdbeAddOp(v, OP_SetNumColumns, iIdxCur, nCol+1);
/* Memory cells are used as follows:
**
** mem[iMem]: The total number of rows in the table.
** mem[iMem+1]: Number of distinct values in column 1
** ...
** mem[iMem+nCol]: Number of distinct values in column N
** mem[iMem+nCol+1] Last observed value of column 1
** ...
** mem[iMem+nCol+nCol]: Last observed value of column N
**
** Cells iMem through iMem+nCol are initialized to 0. The others
** are initialized to NULL.
*/
for(i=0; i<=nCol; i++){
sqlite3VdbeAddOp(v, OP_MemInt, 0, iMem+i);
}
for(i=0; i<nCol; i++){
sqlite3VdbeAddOp(v, OP_MemNull, iMem+nCol+i+1, 0);
}
/* Do the analysis.
*/
endOfLoop = sqlite3VdbeMakeLabel(v);
sqlite3VdbeAddOp(v, OP_Rewind, iIdxCur, endOfLoop);
topOfLoop = sqlite3VdbeCurrentAddr(v);
sqlite3VdbeAddOp(v, OP_MemIncr, 1, iMem);
for(i=0; i<nCol; i++){
sqlite3VdbeAddOp(v, OP_Column, iIdxCur, i);
sqlite3VdbeAddOp(v, OP_MemLoad, iMem+nCol+i+1, 0);
sqlite3VdbeAddOp(v, OP_Ne, 0x100, 0);
}
sqlite3VdbeAddOp(v, OP_Goto, 0, endOfLoop);
for(i=0; i<nCol; i++){
addr = sqlite3VdbeAddOp(v, OP_MemIncr, 1, iMem+i+1);
sqlite3VdbeChangeP2(v, topOfLoop + 3*i + 3, addr);
sqlite3VdbeAddOp(v, OP_Column, iIdxCur, i);
sqlite3VdbeAddOp(v, OP_MemStore, iMem+nCol+i+1, 1);
}
sqlite3VdbeResolveLabel(v, endOfLoop);
sqlite3VdbeAddOp(v, OP_Next, iIdxCur, topOfLoop);
sqlite3VdbeAddOp(v, OP_Close, iIdxCur, 0);
/* Store the results.
**
** The result is a single row of the sqlite_stmt1 table. The first
** two columns are the names of the table and index. The third column
** is a string composed of a list of integer statistics about the
** index. The first integer in the list is the total number of entires
** in the index. There is one additional integer in the list for each
** column of the table. This additional integer is a guess of how many
** rows of the table the index will select. If D is the count of distinct
** values and K is the total number of rows, then the integer is computed
** as:
**
** I = (K+D-1)/D
**
** If K==0 then no entry is made into the sqlite_stat1 table.
** If K>0 then it is always the case the D>0 so division by zero
** is never possible.
*/
sqlite3VdbeAddOp(v, OP_MemLoad, iMem, 0);
addr = sqlite3VdbeAddOp(v, OP_IfNot, 0, 0);
sqlite3VdbeAddOp(v, OP_NewRowid, iStatCur, 0);
sqlite3VdbeOp3(v, OP_String8, 0, 0, pTab->zName, 0);
sqlite3VdbeOp3(v, OP_String8, 0, 0, pIdx->zName, 0);
sqlite3VdbeAddOp(v, OP_MemLoad, iMem, 0);
sqlite3VdbeOp3(v, OP_String8, 0, 0, " ", 0);
for(i=0; i<nCol; i++){
sqlite3VdbeAddOp(v, OP_MemLoad, iMem, 0);
sqlite3VdbeAddOp(v, OP_MemLoad, iMem+i+1, 0);
sqlite3VdbeAddOp(v, OP_Add, 0, 0);
sqlite3VdbeAddOp(v, OP_AddImm, -1, 0);
sqlite3VdbeAddOp(v, OP_MemLoad, iMem+i+1, 0);
sqlite3VdbeAddOp(v, OP_Divide, 0, 0);
sqlite3VdbeAddOp(v, OP_ToInt, 0, 0);
if( i==nCol-1 ){
sqlite3VdbeAddOp(v, OP_Concat, nCol*2-1, 0);
}else{
sqlite3VdbeAddOp(v, OP_Dup, 1, 0);
}
}
sqlite3VdbeOp3(v, OP_MakeRecord, 3, 0, "aaa", 0);
sqlite3VdbeAddOp(v, OP_Insert, iStatCur, 0);
sqlite3VdbeJumpHere(v, addr);
}
}
/*
** Generate code that will cause the most recent index analysis to
** be laoded into internal hash tables where is can be used.
*/
static void loadAnalysis(Parse *pParse, int iDb){
Vdbe *v = sqlite3GetVdbe(pParse);
sqlite3VdbeAddOp(v, OP_LoadAnalysis, iDb, 0);
}
/*
** Generate code that will do an analysis of an entire database
*/
static void analyzeDatabase(Parse *pParse, int iDb){
sqlite3 *db = pParse->db;
Schema *pSchema = db->aDb[iDb].pSchema; /* Schema of database iDb */
HashElem *k;
int iStatCur;
int iMem;
sqlite3BeginWriteOperation(pParse, 0, iDb);
iStatCur = pParse->nTab++;
openStatTable(pParse, iDb, iStatCur, 0);
iMem = pParse->nMem;
for(k=sqliteHashFirst(&pSchema->tblHash); k; k=sqliteHashNext(k)){
Table *pTab = (Table*)sqliteHashData(k);
analyzeOneTable(pParse, pTab, iStatCur, iMem);
}
loadAnalysis(pParse, iDb);
}
/*
** Generate code that will do an analysis of a single table in
** a database.
*/
static void analyzeTable(Parse *pParse, Table *pTab){
int iDb;
int iStatCur;
assert( pTab!=0 );
iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
sqlite3BeginWriteOperation(pParse, 0, iDb);
iStatCur = pParse->nTab++;
openStatTable(pParse, iDb, iStatCur, pTab->zName);
analyzeOneTable(pParse, pTab, iStatCur, pParse->nMem);
loadAnalysis(pParse, iDb);
}
/*
** Generate code for the ANALYZE command. The parser calls this routine
** when it recognizes an ANALYZE command.
**
** ANALYZE -- 1
** ANALYZE <database> -- 2
** ANALYZE ?<database>.?<tablename> -- 3
**
** Form 1 causes all indices in all attached databases to be analyzed.
** Form 2 analyzes all indices the single database named.
** Form 3 analyzes all indices associated with the named table.
*/
void sqlite3Analyze(Parse *pParse, Token *pName1, Token *pName2){
sqlite3 *db = pParse->db;
int iDb;
int i;
char *z, *zDb;
Table *pTab;
Token *pTableName;
/* Read the database schema. If an error occurs, leave an error message
** and code in pParse and return NULL. */
if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){
return;
}
if( pName1==0 ){
/* Form 1: Analyze everything */
for(i=0; i<db->nDb; i++){
if( i==1 ) continue; /* Do not analyze the TEMP database */
analyzeDatabase(pParse, i);
}
}else if( pName2==0 || pName2->n==0 ){
/* Form 2: Analyze the database or table named */
iDb = sqlite3FindDb(db, pName1);
if( iDb>=0 ){
analyzeDatabase(pParse, iDb);
}else{
z = sqlite3NameFromToken(pName1);
pTab = sqlite3LocateTable(pParse, z, 0);
sqliteFree(z);
if( pTab ){
analyzeTable(pParse, pTab);
}
}
}else{
/* Form 3: Analyze the fully qualified table name */
iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pTableName);
if( iDb>=0 ){
zDb = db->aDb[iDb].zName;
z = sqlite3NameFromToken(pTableName);
pTab = sqlite3LocateTable(pParse, z, zDb);
sqliteFree(z);
if( pTab ){
analyzeTable(pParse, pTab);
}
}
}
}
/*
** Used to pass information from the analyzer reader through to the
** callback routine.
*/
typedef struct analysisInfo analysisInfo;
struct analysisInfo {
sqlite3 *db;
const char *zDatabase;
};
/*
** This callback is invoked once for each index when reading the
** sqlite_stat1 table.
**
** argv[0] = name of the index
** argv[1] = results of analysis - on integer for each column
*/
static int analysisLoader(void *pData, int argc, char **argv, char **azNotUsed){
analysisInfo *pInfo = (analysisInfo*)pData;
Index *pIndex;
int i, c;
unsigned int v;
const char *z;
assert( argc==2 );
if( argv==0 || argv[0]==0 || argv[1]==0 ){
return 0;
}
pIndex = sqlite3FindIndex(pInfo->db, argv[0], pInfo->zDatabase);
if( pIndex==0 ){
return 0;
}
z = argv[1];
for(i=0; *z && i<=pIndex->nColumn; i++){
v = 0;
while( (c=z[0])>='0' && c<='9' ){
v = v*10 + c - '0';
z++;
}
pIndex->aiRowEst[i] = v;
if( *z==' ' ) z++;
}
return 0;
}
/*
** Load the content of the sqlite_stat1 table into the index hash tables.
*/
void sqlite3AnalysisLoad(sqlite3 *db, int iDb){
analysisInfo sInfo;
HashElem *i;
char *zSql;
/* Clear any prior statistics */
for(i=sqliteHashFirst(&db->aDb[iDb].pSchema->idxHash);i;i=sqliteHashNext(i)){
Index *pIdx = sqliteHashData(i);
sqlite3DefaultRowEst(pIdx);
}
/* Check to make sure the sqlite_stat1 table existss */
sInfo.db = db;
sInfo.zDatabase = db->aDb[iDb].zName;
if( sqlite3FindTable(db, "sqlite_stat1", sInfo.zDatabase)==0 ){
return;
}
/* Load new statistics out of the sqlite_stat1 table */
zSql = sqlite3MPrintf("SELECT idx, stat FROM %Q.sqlite_stat1",
sInfo.zDatabase);
sqlite3SafetyOff(db);
sqlite3_exec(db, zSql, analysisLoader, &sInfo, 0);
sqlite3SafetyOn(db);
sqliteFree(zSql);
}
#endif /* SQLITE_OMIT_ANALYZE */

View File

@ -11,165 +11,347 @@
*************************************************************************
** This file contains code used to implement the ATTACH and DETACH commands.
**
** $Id: attach.c,v 1.1.1.1 2004-03-11 22:22:22 alex Exp $
** $Id: attach.c,v 1.2 2006-04-13 12:44:29 guy Exp $
*/
#include "sqliteInt.h"
/*
** This routine is called by the parser to process an ATTACH statement:
** Resolve an expression that was part of an ATTACH or DETACH statement. This
** is slightly different from resolving a normal SQL expression, because simple
** identifiers are treated as strings, not possible column names or aliases.
**
** ATTACH DATABASE filename AS dbname
** i.e. if the parser sees:
**
** The pFilename and pDbname arguments are the tokens that define the
** filename and dbname in the ATTACH statement.
** ATTACH DATABASE abc AS def
**
** it treats the two expressions as literal strings 'abc' and 'def' instead of
** looking for columns of the same name.
**
** This only applies to the root node of pExpr, so the statement:
**
** ATTACH DATABASE abc||def AS 'db2'
**
** will fail because neither abc or def can be resolved.
*/
void sqliteAttach(Parse *pParse, Token *pFilename, Token *pDbname, Token *pKey){
static int resolveAttachExpr(NameContext *pName, Expr *pExpr)
{
int rc = SQLITE_OK;
if( pExpr ){
if( pExpr->op!=TK_ID ){
rc = sqlite3ExprResolveNames(pName, pExpr);
}else{
pExpr->op = TK_STRING;
}
}
return rc;
}
/*
** An SQL user-function registered to do the work of an ATTACH statement. The
** three arguments to the function come directly from an attach statement:
**
** ATTACH DATABASE x AS y KEY z
**
** SELECT sqlite_attach(x, y, z)
**
** If the optional "KEY z" syntax is omitted, an SQL NULL is passed as the
** third argument.
*/
static void attachFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
int i;
int rc = 0;
sqlite3 *db = sqlite3_user_data(context);
const char *zName;
const char *zFile;
Db *aNew;
int rc, i;
char *zFile, *zName;
sqlite *db;
Vdbe *v;
char zErr[128];
char *zErrDyn = 0;
v = sqliteGetVdbe(pParse);
sqliteVdbeAddOp(v, OP_Halt, 0, 0);
if( pParse->explain ) return;
db = pParse->db;
if( db->file_format<4 ){
sqliteErrorMsg(pParse, "cannot attach auxiliary databases to an "
"older format master database", 0);
pParse->rc = SQLITE_ERROR;
return;
}
zFile = (const char *)sqlite3_value_text(argv[0]);
zName = (const char *)sqlite3_value_text(argv[1]);
/* Check for the following errors:
**
** * Too many attached databases,
** * Transaction currently open
** * Specified database name already being used.
*/
if( db->nDb>=MAX_ATTACHED+2 ){
sqliteErrorMsg(pParse, "too many attached databases - max %d",
MAX_ATTACHED);
pParse->rc = SQLITE_ERROR;
return;
sqlite3_snprintf(
127, zErr, "too many attached databases - max %d", MAX_ATTACHED
);
goto attach_error;
}
zFile = 0;
sqliteSetNString(&zFile, pFilename->z, pFilename->n, 0);
if( zFile==0 ) return;
sqliteDequote(zFile);
#ifndef SQLITE_OMIT_AUTHORIZATION
if( sqliteAuthCheck(pParse, SQLITE_ATTACH, zFile, 0, 0)!=SQLITE_OK ){
sqliteFree(zFile);
return;
if( !db->autoCommit ){
strcpy(zErr, "cannot ATTACH database within transaction");
goto attach_error;
}
#endif /* SQLITE_OMIT_AUTHORIZATION */
zName = 0;
sqliteSetNString(&zName, pDbname->z, pDbname->n, 0);
if( zName==0 ) return;
sqliteDequote(zName);
for(i=0; i<db->nDb; i++){
if( db->aDb[i].zName && sqliteStrICmp(db->aDb[i].zName, zName)==0 ){
sqliteErrorMsg(pParse, "database %z is already in use", zName);
pParse->rc = SQLITE_ERROR;
sqliteFree(zFile);
return;
char *z = db->aDb[i].zName;
if( z && sqlite3StrICmp(z, zName)==0 ){
sqlite3_snprintf(127, zErr, "database %s is already in use", zName);
goto attach_error;
}
}
/* Allocate the new entry in the db->aDb[] array and initialise the schema
** hash tables.
*/
if( db->aDb==db->aDbStatic ){
aNew = sqliteMalloc( sizeof(db->aDb[0])*3 );
if( aNew==0 ) return;
if( aNew==0 ){
return;
}
memcpy(aNew, db->aDb, sizeof(db->aDb[0])*2);
}else{
aNew = sqliteRealloc(db->aDb, sizeof(db->aDb[0])*(db->nDb+1) );
if( aNew==0 ) return;
if( aNew==0 ){
return;
}
}
db->aDb = aNew;
aNew = &db->aDb[db->nDb++];
memset(aNew, 0, sizeof(*aNew));
sqliteHashInit(&aNew->tblHash, SQLITE_HASH_STRING, 0);
sqliteHashInit(&aNew->idxHash, SQLITE_HASH_STRING, 0);
sqliteHashInit(&aNew->trigHash, SQLITE_HASH_STRING, 0);
sqliteHashInit(&aNew->aFKey, SQLITE_HASH_STRING, 1);
aNew->zName = zName;
rc = sqliteBtreeFactory(db, zFile, 0, MAX_PAGES, &aNew->pBt);
if( rc ){
sqliteErrorMsg(pParse, "unable to open database: %s", zFile);
/* Open the database file. If the btree is successfully opened, use
** it to obtain the database schema. At this point the schema may
** or may not be initialised.
*/
rc = sqlite3BtreeFactory(db, zFile, 0, MAX_PAGES, &aNew->pBt);
if( rc==SQLITE_OK ){
aNew->pSchema = sqlite3SchemaGet(aNew->pBt);
if( !aNew->pSchema ){
rc = SQLITE_NOMEM;
}else if( aNew->pSchema->file_format && aNew->pSchema->enc!=ENC(db) ){
strcpy(zErr,
"attached databases must use the same text encoding as main database");
goto attach_error;
}
}
aNew->zName = sqliteStrDup(zName);
aNew->safety_level = 3;
#if SQLITE_HAS_CODEC
{
extern int sqliteCodecAttach(sqlite*, int, void*, int);
char *zKey = 0;
extern int sqlite3CodecAttach(sqlite3*, int, void*, int);
extern void sqlite3CodecGetKey(sqlite3*, int, void**, int*);
int nKey;
if( pKey && pKey->z && pKey->n ){
sqliteSetNString(&zKey, pKey->z, pKey->n, 0);
sqliteDequote(zKey);
nKey = strlen(zKey);
}else{
zKey = 0;
nKey = 0;
char *zKey;
int t = sqlite3_value_type(argv[2]);
switch( t ){
case SQLITE_INTEGER:
case SQLITE_FLOAT:
zErrDyn = sqliteStrDup("Invalid key value");
rc = SQLITE_ERROR;
break;
case SQLITE_TEXT:
case SQLITE_BLOB:
nKey = sqlite3_value_bytes(argv[2]);
zKey = (char *)sqlite3_value_blob(argv[2]);
sqlite3CodecAttach(db, db->nDb-1, zKey, nKey);
break;
case SQLITE_NULL:
/* No key specified. Use the key from the main database */
sqlite3CodecGetKey(db, 0, (void**)&zKey, &nKey);
sqlite3CodecAttach(db, db->nDb-1, zKey, nKey);
break;
}
sqliteCodecAttach(db, db->nDb-1, zKey, nKey);
}
#endif
sqliteFree(zFile);
db->flags &= ~SQLITE_Initialized;
if( pParse->nErr ) return;
/* If the file was opened successfully, read the schema for the new database.
** If this fails, or if opening the file failed, then close the file and
** remove the entry from the db->aDb[] array. i.e. put everything back the way
** we found it.
*/
if( rc==SQLITE_OK ){
rc = sqliteInit(pParse->db, &pParse->zErrMsg);
sqlite3SafetyOn(db);
rc = sqlite3Init(db, &zErrDyn);
sqlite3SafetyOff(db);
}
if( rc ){
int i = db->nDb - 1;
assert( i>=2 );
if( db->aDb[i].pBt ){
sqliteBtreeClose(db->aDb[i].pBt);
db->aDb[i].pBt = 0;
int iDb = db->nDb - 1;
assert( iDb>=2 );
if( db->aDb[iDb].pBt ){
sqlite3BtreeClose(db->aDb[iDb].pBt);
db->aDb[iDb].pBt = 0;
db->aDb[iDb].pSchema = 0;
}
sqliteResetInternalSchema(db, 0);
pParse->nErr++;
pParse->rc = SQLITE_ERROR;
sqlite3ResetInternalSchema(db, 0);
db->nDb = iDb;
if( rc==SQLITE_NOMEM ){
sqlite3MallocFailed();
sqlite3_snprintf(127, zErr, "out of memory");
}else{
sqlite3_snprintf(127, zErr, "unable to open database: %s", zFile);
}
goto attach_error;
}
return;
attach_error:
/* Return an error if we get here */
if( zErrDyn ){
sqlite3_result_error(context, zErrDyn, -1);
sqliteFree(zErrDyn);
}else{
zErr[sizeof(zErr)-1] = 0;
sqlite3_result_error(context, zErr, -1);
}
}
/*
** This routine is called by the parser to process a DETACH statement:
** An SQL user-function registered to do the work of an DETACH statement. The
** three arguments to the function come directly from a detach statement:
**
** DETACH DATABASE dbname
** DETACH DATABASE x
**
** The pDbname argument is the name of the database in the DETACH statement.
** SELECT sqlite_detach(x)
*/
void sqliteDetach(Parse *pParse, Token *pDbname){
static void detachFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
const char *zName = (const char *)sqlite3_value_text(argv[0]);
sqlite3 *db = sqlite3_user_data(context);
int i;
sqlite *db;
Vdbe *v;
Db *pDb = 0;
char zErr[128];
v = sqliteGetVdbe(pParse);
sqliteVdbeAddOp(v, OP_Halt, 0, 0);
if( pParse->explain ) return;
db = pParse->db;
assert(zName);
for(i=0; i<db->nDb; i++){
if( db->aDb[i].pBt==0 || db->aDb[i].zName==0 ) continue;
if( strlen(db->aDb[i].zName)!=pDbname->n ) continue;
if( sqliteStrNICmp(db->aDb[i].zName, pDbname->z, pDbname->n)==0 ) break;
pDb = &db->aDb[i];
if( pDb->pBt==0 ) continue;
if( sqlite3StrICmp(pDb->zName, zName)==0 ) break;
}
if( i>=db->nDb ){
sqliteErrorMsg(pParse, "no such database: %T", pDbname);
return;
sqlite3_snprintf(sizeof(zErr), zErr, "no such database: %s", zName);
goto detach_error;
}
if( i<2 ){
sqliteErrorMsg(pParse, "cannot detach database %T", pDbname);
return;
sqlite3_snprintf(sizeof(zErr), zErr, "cannot detach database %s", zName);
goto detach_error;
}
if( !db->autoCommit ){
strcpy(zErr, "cannot DETACH database within transaction");
goto detach_error;
}
sqlite3BtreeClose(pDb->pBt);
pDb->pBt = 0;
pDb->pSchema = 0;
sqlite3ResetInternalSchema(db, 0);
return;
detach_error:
sqlite3_result_error(context, zErr, -1);
}
/*
** 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
if( sqliteAuthCheck(pParse,SQLITE_DETACH,db->aDb[i].zName,0,0)!=SQLITE_OK ){
return;
assert( sqlite3MallocFailed() || 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 */
sqliteBtreeClose(db->aDb[i].pBt);
db->aDb[i].pBt = 0;
sqliteFree(db->aDb[i].zName);
sqliteResetInternalSchema(db, i);
db->nDb--;
if( i<db->nDb ){
db->aDb[i] = db->aDb[db->nDb];
memset(&db->aDb[db->nDb], 0, sizeof(db->aDb[0]));
sqliteResetInternalSchema(db, i);
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 || sqlite3MallocFailed() );
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);
}
/*
** Called by the parser to compile a DETACH statement.
**
** DETACH pDbname
*/
void sqlite3Detach(Parse *pParse, Expr *pDbname){
codeAttach(pParse, SQLITE_DETACH, "sqlite_detach", 1, pDbname, 0, 0, pDbname);
}
/*
** Called by the parser to compile an ATTACH statement.
**
** ATTACH p AS pDbname KEY pKey
*/
void sqlite3Attach(Parse *pParse, Expr *p, Expr *pDbname, Expr *pKey){
codeAttach(pParse, SQLITE_ATTACH, "sqlite_attach", 3, p, p, pDbname, pKey);
}
/*
** Register the functions sqlite_attach and sqlite_detach.
*/
void sqlite3AttachFunctions(sqlite3 *db){
static const int enc = SQLITE_UTF8;
sqlite3CreateFunc(db, "sqlite_attach", 3, enc, db, attachFunc, 0, 0);
sqlite3CreateFunc(db, "sqlite_detach", 1, enc, db, detachFunc, 0, 0);
}
/*
@ -179,14 +361,14 @@ void sqliteDetach(Parse *pParse, Token *pDbname){
** The return value indicates whether or not fixation is required. TRUE
** means we do need to fix the database references, FALSE means we do not.
*/
int sqliteFixInit(
int sqlite3FixInit(
DbFixer *pFix, /* The fixer to be initialized */
Parse *pParse, /* Error messages will be written here */
int iDb, /* This is the database that must must be used */
int iDb, /* This is the database that must be used */
const char *zType, /* "view", "trigger", or "index" */
const Token *pName /* Name of the view, trigger, or index */
){
sqlite *db;
sqlite3 *db;
if( iDb<0 || iDb==1 ) return 0;
db = pParse->db;
@ -202,7 +384,7 @@ int sqliteFixInit(
** The following set of routines walk through the parse tree and assign
** a specific database to all table references where the database name
** was left unspecified in the original SQL statement. The pFix structure
** must have been initialized by a prior call to sqliteFixInit().
** must have been initialized by a prior call to sqlite3FixInit().
**
** These routines are used to make sure that an index, trigger, or
** view in one database does not refer to objects in a different database.
@ -212,97 +394,105 @@ int sqliteFixInit(
** pParse->zErrMsg and these routines return non-zero. If everything
** checks out, these routines return 0.
*/
int sqliteFixSrcList(
int sqlite3FixSrcList(
DbFixer *pFix, /* Context of the fixation */
SrcList *pList /* The Source list to check and modify */
){
int i;
const char *zDb;
struct SrcList_item *pItem;
if( pList==0 ) return 0;
zDb = pFix->zDb;
for(i=0; i<pList->nSrc; i++){
if( pList->a[i].zDatabase==0 ){
pList->a[i].zDatabase = sqliteStrDup(zDb);
}else if( sqliteStrICmp(pList->a[i].zDatabase,zDb)!=0 ){
sqliteErrorMsg(pFix->pParse,
"%s %z cannot reference objects in database %s",
pFix->zType, sqliteStrNDup(pFix->pName->z, pFix->pName->n),
pList->a[i].zDatabase);
for(i=0, pItem=pList->a; i<pList->nSrc; i++, pItem++){
if( pItem->zDatabase==0 ){
pItem->zDatabase = sqliteStrDup(zDb);
}else if( sqlite3StrICmp(pItem->zDatabase,zDb)!=0 ){
sqlite3ErrorMsg(pFix->pParse,
"%s %T cannot reference objects in database %s",
pFix->zType, pFix->pName, pItem->zDatabase);
return 1;
}
if( sqliteFixSelect(pFix, pList->a[i].pSelect) ) return 1;
if( sqliteFixExpr(pFix, pList->a[i].pOn) ) return 1;
#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER)
if( sqlite3FixSelect(pFix, pItem->pSelect) ) return 1;
if( sqlite3FixExpr(pFix, pItem->pOn) ) return 1;
#endif
}
return 0;
}
int sqliteFixSelect(
#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER)
int sqlite3FixSelect(
DbFixer *pFix, /* Context of the fixation */
Select *pSelect /* The SELECT statement to be fixed to one database */
){
while( pSelect ){
if( sqliteFixExprList(pFix, pSelect->pEList) ){
if( sqlite3FixExprList(pFix, pSelect->pEList) ){
return 1;
}
if( sqliteFixSrcList(pFix, pSelect->pSrc) ){
if( sqlite3FixSrcList(pFix, pSelect->pSrc) ){
return 1;
}
if( sqliteFixExpr(pFix, pSelect->pWhere) ){
if( sqlite3FixExpr(pFix, pSelect->pWhere) ){
return 1;
}
if( sqliteFixExpr(pFix, pSelect->pHaving) ){
if( sqlite3FixExpr(pFix, pSelect->pHaving) ){
return 1;
}
pSelect = pSelect->pPrior;
}
return 0;
}
int sqliteFixExpr(
int sqlite3FixExpr(
DbFixer *pFix, /* Context of the fixation */
Expr *pExpr /* The expression to be fixed to one database */
){
while( pExpr ){
if( sqliteFixSelect(pFix, pExpr->pSelect) ){
if( sqlite3FixSelect(pFix, pExpr->pSelect) ){
return 1;
}
if( sqliteFixExprList(pFix, pExpr->pList) ){
if( sqlite3FixExprList(pFix, pExpr->pList) ){
return 1;
}
if( sqliteFixExpr(pFix, pExpr->pRight) ){
if( sqlite3FixExpr(pFix, pExpr->pRight) ){
return 1;
}
pExpr = pExpr->pLeft;
}
return 0;
}
int sqliteFixExprList(
int sqlite3FixExprList(
DbFixer *pFix, /* Context of the fixation */
ExprList *pList /* The expression to be fixed to one database */
){
int i;
struct ExprList_item *pItem;
if( pList==0 ) return 0;
for(i=0; i<pList->nExpr; i++){
if( sqliteFixExpr(pFix, pList->a[i].pExpr) ){
for(i=0, pItem=pList->a; i<pList->nExpr; i++, pItem++){
if( sqlite3FixExpr(pFix, pItem->pExpr) ){
return 1;
}
}
return 0;
}
int sqliteFixTriggerStep(
#endif
#ifndef SQLITE_OMIT_TRIGGER
int sqlite3FixTriggerStep(
DbFixer *pFix, /* Context of the fixation */
TriggerStep *pStep /* The trigger step be fixed to one database */
){
while( pStep ){
if( sqliteFixSelect(pFix, pStep->pSelect) ){
if( sqlite3FixSelect(pFix, pStep->pSelect) ){
return 1;
}
if( sqliteFixExpr(pFix, pStep->pWhere) ){
if( sqlite3FixExpr(pFix, pStep->pWhere) ){
return 1;
}
if( sqliteFixExprList(pFix, pStep->pExprList) ){
if( sqlite3FixExprList(pFix, pStep->pExprList) ){
return 1;
}
pStep = pStep->pNext;
}
return 0;
}
#endif

View File

@ -9,12 +9,12 @@
** May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains code used to implement the sqlite_set_authorizer()
** This file contains code used to implement the sqlite3_set_authorizer()
** API. This facility is an optional feature of the library. Embedded
** systems that do not need this facility may omit it by recompiling
** the library with -DSQLITE_OMIT_AUTHORIZATION=1
**
** $Id: auth.c,v 1.1.1.1 2004-03-11 22:22:23 alex Exp $
** $Id: auth.c,v 1.2 2006-04-13 12:44:29 guy Exp $
*/
#include "sqliteInt.h"
@ -33,7 +33,6 @@
** is a copy of the 3rd argument to this routine. The second argument
** to the auth function is one of these constants:
**
** SQLITE_COPY
** SQLITE_CREATE_INDEX
** SQLITE_CREATE_TABLE
** SQLITE_CREATE_TEMP_INDEX
@ -62,7 +61,7 @@
** the table and the column that are being accessed. The auth function
** should return either SQLITE_OK, SQLITE_DENY, or SQLITE_IGNORE. If
** SQLITE_OK is returned, it means that access is allowed. SQLITE_DENY
** means that the SQL statement will never-run - the sqlite_exec() call
** means that the SQL statement will never-run - the sqlite3_exec() call
** will return with an error. SQLITE_IGNORE means that the SQL statement
** should run but attempts to read the specified column will return NULL
** and attempts to write the column will be ignored.
@ -70,13 +69,14 @@
** Setting the auth function to NULL disables this hook. The default
** setting of the auth function is NULL.
*/
int sqlite_set_authorizer(
sqlite *db,
int sqlite3_set_authorizer(
sqlite3 *db,
int (*xAuth)(void*,int,const char*,const char*,const char*,const char*),
void *pArg
){
db->xAuth = xAuth;
db->pAuthArg = pArg;
sqlite3ExpirePreparedStatements(db);
return SQLITE_OK;
}
@ -85,10 +85,10 @@ int sqlite_set_authorizer(
** user-supplied authorization function returned an illegal value.
*/
static void sqliteAuthBadReturnCode(Parse *pParse, int rc){
sqliteErrorMsg(pParse, "illegal return value (%d) from the "
sqlite3ErrorMsg(pParse, "illegal return value (%d) from the "
"authorization function - should be SQLITE_OK, SQLITE_IGNORE, "
"or SQLITE_DENY", rc);
pParse->rc = SQLITE_MISUSE;
pParse->rc = SQLITE_ERROR;
}
/*
@ -100,34 +100,42 @@ static void sqliteAuthBadReturnCode(Parse *pParse, int rc){
** instruction into a TK_NULL. If the auth function returns SQLITE_DENY,
** then generate an error.
*/
void sqliteAuthRead(
void sqlite3AuthRead(
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;
sqlite3 *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 */
TriggerStack *pStack; /* The stack of current triggers */
int iDb; /* The index of the database the expression refers to */
if( db->xAuth==0 ) return;
if( pExpr->op==TK_AS ) return;
assert( pExpr->op==TK_COLUMN );
for(iSrc=0; iSrc<pTabList->nSrc; iSrc++){
iDb = sqlite3SchemaToIndex(pParse->db, pExpr->pSchema);
if( iDb<0 ){
/* An attempt to read a column out of a subquery or other
** temporary table. */
return;
}
for(iSrc=0; pTabList && iSrc<pTabList->nSrc; iSrc++){
if( pExpr->iTable==pTabList->a[iSrc].iCursor ) break;
}
if( iSrc>=0 && iSrc<pTabList->nSrc ){
if( iSrc>=0 && pTabList && iSrc<pTabList->nSrc ){
pTab = pTabList->a[iSrc].pTab;
}else{
}else if( (pStack = pParse->trigStack)!=0 ){
/* 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;
}else{
return;
}
if( pTab==0 ) return;
if( pExpr->iColumn>=0 ){
@ -139,18 +147,18 @@ void sqliteAuthRead(
}else{
zCol = "ROWID";
}
assert( pExpr->iDb<db->nDb );
zDBase = db->aDb[pExpr->iDb].zName;
assert( iDb>=0 && iDb<db->nDb );
zDBase = db->aDb[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 ){
sqliteErrorMsg(pParse, "access to %s.%s.%s is prohibited",
if( db->nDb>2 || iDb!=0 ){
sqlite3ErrorMsg(pParse, "access to %s.%s.%s is prohibited",
zDBase, pTab->zName, zCol);
}else{
sqliteErrorMsg(pParse, "access to %s.%s is prohibited", pTab->zName,zCol);
sqlite3ErrorMsg(pParse, "access to %s.%s is prohibited",pTab->zName,zCol);
}
pParse->rc = SQLITE_AUTH;
}else if( rc!=SQLITE_OK ){
@ -164,22 +172,27 @@ void sqliteAuthRead(
** is returned, then the error count and error message in pParse are
** modified appropriately.
*/
int sqliteAuthCheck(
int sqlite3AuthCheck(
Parse *pParse,
int code,
const char *zArg1,
const char *zArg2,
const char *zArg3
){
sqlite *db = pParse->db;
sqlite3 *db = pParse->db;
int rc;
/* Don't do any authorization checks if the database is initialising. */
if( db->init.busy ){
return SQLITE_OK;
}
if( 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");
sqlite3ErrorMsg(pParse, "not authorized");
pParse->rc = SQLITE_AUTH;
}else if( rc!=SQLITE_OK && rc!=SQLITE_IGNORE ){
rc = SQLITE_DENY;
@ -193,7 +206,7 @@ int sqliteAuthCheck(
** zArg3 argument to authorization callbacks will be zContext until
** popped. Or if pParse==0, this routine is a no-op.
*/
void sqliteAuthContextPush(
void sqlite3AuthContextPush(
Parse *pParse,
AuthContext *pContext,
const char *zContext
@ -207,9 +220,9 @@ void sqliteAuthContextPush(
/*
** Pop an authorization context that was previously pushed
** by sqliteAuthContextPush
** by sqlite3AuthContextPush
*/
void sqliteAuthContextPop(AuthContext *pContext){
void sqlite3AuthContextPop(AuthContext *pContext){
if( pContext->pParse ){
pContext->pParse->zAuthContext = pContext->zAuthContext;
pContext->pParse = 0;

File diff suppressed because it is too large Load Diff

View File

@ -13,144 +13,136 @@
** subsystem. See comments in the source code for a detailed description
** of what each interface routine does.
**
** @(#) $Id: btree.h,v 1.1.1.1 2004-03-11 22:22:24 alex Exp $
** @(#) $Id: btree.h,v 1.2 2006-04-13 12:44:29 guy Exp $
*/
#ifndef _BTREE_H_
#define _BTREE_H_
/* TODO: This definition is just included so other modules compile. It
** needs to be revisited.
*/
#define SQLITE_N_BTREE_META 10
/*
** If defined as non-zero, auto-vacuum is enabled by default. Otherwise
** it must be turned on for each database using "PRAGMA auto_vacuum = 1".
*/
#ifndef SQLITE_DEFAULT_AUTOVACUUM
#define SQLITE_DEFAULT_AUTOVACUUM 0
#endif
/*
** Forward declarations of structure
*/
typedef struct Btree Btree;
typedef struct BtCursor BtCursor;
typedef struct BtOps BtOps;
typedef struct BtCursorOps BtCursorOps;
typedef struct BtShared BtShared;
/*
** An instance of the following structure contains pointers to all
** methods against an open BTree. Alternative BTree implementations
** (examples: file based versus in-memory) can be created by substituting
** different methods. Users of the BTree cannot tell the difference.
int sqlite3BtreeOpen(
const char *zFilename, /* Name of database file to open */
sqlite3 *db, /* Associated database connection */
Btree **, /* Return open Btree* here */
int flags /* Flags */
);
/* The flags parameter to sqlite3BtreeOpen can be the bitwise or of the
** following values.
**
** In C++ we could do this by defining a virtual base class and then
** creating subclasses for each different implementation. But this is
** C not C++ so we have to be a little more explicit.
** NOTE: These values must match the corresponding PAGER_ values in
** pager.h.
*/
struct BtOps {
int (*Close)(Btree*);
int (*SetCacheSize)(Btree*, int);
int (*SetSafetyLevel)(Btree*, int);
int (*BeginTrans)(Btree*);
int (*Commit)(Btree*);
int (*Rollback)(Btree*);
int (*BeginCkpt)(Btree*);
int (*CommitCkpt)(Btree*);
int (*RollbackCkpt)(Btree*);
int (*CreateTable)(Btree*, int*);
int (*CreateIndex)(Btree*, int*);
int (*DropTable)(Btree*, int);
int (*ClearTable)(Btree*, int);
int (*Cursor)(Btree*, int iTable, int wrFlag, BtCursor **ppCur);
int (*GetMeta)(Btree*, int*);
int (*UpdateMeta)(Btree*, int*);
char *(*IntegrityCheck)(Btree*, int*, int);
const char *(*GetFilename)(Btree*);
int (*Copyfile)(Btree*,Btree*);
struct Pager *(*Pager)(Btree*);
#define BTREE_OMIT_JOURNAL 1 /* Do not use journal. No argument */
#define BTREE_NO_READLOCK 2 /* Omit readlocks on readonly files */
#define BTREE_MEMORY 4 /* In-memory DB. No argument */
int sqlite3BtreeClose(Btree*);
int sqlite3BtreeSetBusyHandler(Btree*,BusyHandler*);
int sqlite3BtreeSetCacheSize(Btree*,int);
int sqlite3BtreeSetSafetyLevel(Btree*,int,int);
int sqlite3BtreeSyncDisabled(Btree*);
int sqlite3BtreeSetPageSize(Btree*,int,int);
int sqlite3BtreeGetPageSize(Btree*);
int sqlite3BtreeGetReserve(Btree*);
int sqlite3BtreeSetAutoVacuum(Btree *, int);
int sqlite3BtreeGetAutoVacuum(Btree *);
int sqlite3BtreeBeginTrans(Btree*,int);
int sqlite3BtreeCommit(Btree*);
int sqlite3BtreeRollback(Btree*);
int sqlite3BtreeBeginStmt(Btree*);
int sqlite3BtreeCommitStmt(Btree*);
int sqlite3BtreeRollbackStmt(Btree*);
int sqlite3BtreeCreateTable(Btree*, int*, int flags);
int sqlite3BtreeIsInTrans(Btree*);
int sqlite3BtreeIsInStmt(Btree*);
int sqlite3BtreeSync(Btree*, const char *zMaster);
void *sqlite3BtreeSchema(Btree *, int, void(*)(void *));
int sqlite3BtreeSchemaLocked(Btree *);
int sqlite3BtreeLockTable(Btree *, int, u8);
const char *sqlite3BtreeGetFilename(Btree *);
const char *sqlite3BtreeGetDirname(Btree *);
const char *sqlite3BtreeGetJournalname(Btree *);
int sqlite3BtreeCopyFile(Btree *, Btree *);
/* The flags parameter to sqlite3BtreeCreateTable can be the bitwise OR
** of the following flags:
*/
#define BTREE_INTKEY 1 /* Table has only 64-bit signed integer keys */
#define BTREE_ZERODATA 2 /* Table has keys only - no data */
#define BTREE_LEAFDATA 4 /* Data stored in leaves only. Implies INTKEY */
int sqlite3BtreeDropTable(Btree*, int, int*);
int sqlite3BtreeClearTable(Btree*, int);
int sqlite3BtreeGetMeta(Btree*, int idx, u32 *pValue);
int sqlite3BtreeUpdateMeta(Btree*, int idx, u32 value);
int sqlite3BtreeCursor(
Btree*, /* BTree containing table to open */
int iTable, /* Index of root page */
int wrFlag, /* 1 for writing. 0 for read-only */
int(*)(void*,int,const void*,int,const void*), /* Key comparison function */
void*, /* First argument to compare function */
BtCursor **ppCursor /* Returned cursor */
);
void sqlite3BtreeSetCompare(
BtCursor *,
int(*)(void*,int,const void*,int,const void*),
void*
);
int sqlite3BtreeCloseCursor(BtCursor*);
int sqlite3BtreeMoveto(BtCursor*, const void *pKey, i64 nKey, int *pRes);
int sqlite3BtreeDelete(BtCursor*);
int sqlite3BtreeInsert(BtCursor*, const void *pKey, i64 nKey,
const void *pData, int nData);
int sqlite3BtreeFirst(BtCursor*, int *pRes);
int sqlite3BtreeLast(BtCursor*, int *pRes);
int sqlite3BtreeNext(BtCursor*, int *pRes);
int sqlite3BtreeEof(BtCursor*);
int sqlite3BtreeFlags(BtCursor*);
int sqlite3BtreePrevious(BtCursor*, int *pRes);
int sqlite3BtreeKeySize(BtCursor*, i64 *pSize);
int sqlite3BtreeKey(BtCursor*, u32 offset, u32 amt, void*);
const void *sqlite3BtreeKeyFetch(BtCursor*, int *pAmt);
const void *sqlite3BtreeDataFetch(BtCursor*, int *pAmt);
int sqlite3BtreeDataSize(BtCursor*, u32 *pSize);
int sqlite3BtreeData(BtCursor*, u32 offset, u32 amt, void*);
char *sqlite3BtreeIntegrityCheck(Btree*, int *aRoot, int nRoot);
struct Pager *sqlite3BtreePager(Btree*);
#ifdef SQLITE_TEST
int (*PageDump)(Btree*, int, int);
int sqlite3BtreeCursorInfo(BtCursor*, int*, int);
void sqlite3BtreeCursorList(Btree*);
#endif
};
/*
** An instance of this structure defines all of the methods that can
** be executed against a cursor.
*/
struct BtCursorOps {
int (*Moveto)(BtCursor*, const void *pKey, int nKey, int *pRes);
int (*Delete)(BtCursor*);
int (*Insert)(BtCursor*, const void *pKey, int nKey,
const void *pData, int nData);
int (*First)(BtCursor*, int *pRes);
int (*Last)(BtCursor*, int *pRes);
int (*Next)(BtCursor*, int *pRes);
int (*Previous)(BtCursor*, int *pRes);
int (*KeySize)(BtCursor*, int *pSize);
int (*Key)(BtCursor*, int offset, int amt, char *zBuf);
int (*KeyCompare)(BtCursor*, const void *pKey, int nKey,
int nIgnore, int *pRes);
int (*DataSize)(BtCursor*, int *pSize);
int (*Data)(BtCursor*, int offset, int amt, char *zBuf);
int (*CloseCursor)(BtCursor*);
#ifdef SQLITE_TEST
int (*CursorDump)(BtCursor*, int*);
#ifdef SQLITE_DEBUG
int sqlite3BtreePageDump(Btree*, int, int recursive);
#else
#define sqlite3BtreePageDump(X,Y,Z) SQLITE_OK
#endif
};
/*
** The number of 4-byte "meta" values contained on the first page of each
** database file.
*/
#define SQLITE_N_BTREE_META 10
int sqliteBtreeOpen(const char *zFilename, int mode, int nPg, Btree **ppBtree);
int sqliteRbtreeOpen(const char *zFilename, int mode, int nPg, Btree **ppBtree);
#define btOps(pBt) (*((BtOps **)(pBt)))
#define btCOps(pCur) (*((BtCursorOps **)(pCur)))
#define sqliteBtreeClose(pBt) (btOps(pBt)->Close(pBt))
#define sqliteBtreeSetCacheSize(pBt, sz) (btOps(pBt)->SetCacheSize(pBt, sz))
#define sqliteBtreeSetSafetyLevel(pBt, sl) (btOps(pBt)->SetSafetyLevel(pBt, sl))
#define sqliteBtreeBeginTrans(pBt) (btOps(pBt)->BeginTrans(pBt))
#define sqliteBtreeCommit(pBt) (btOps(pBt)->Commit(pBt))
#define sqliteBtreeRollback(pBt) (btOps(pBt)->Rollback(pBt))
#define sqliteBtreeBeginCkpt(pBt) (btOps(pBt)->BeginCkpt(pBt))
#define sqliteBtreeCommitCkpt(pBt) (btOps(pBt)->CommitCkpt(pBt))
#define sqliteBtreeRollbackCkpt(pBt) (btOps(pBt)->RollbackCkpt(pBt))
#define sqliteBtreeCreateTable(pBt,piTable)\
(btOps(pBt)->CreateTable(pBt,piTable))
#define sqliteBtreeCreateIndex(pBt, piIndex)\
(btOps(pBt)->CreateIndex(pBt, piIndex))
#define sqliteBtreeDropTable(pBt, iTable) (btOps(pBt)->DropTable(pBt, iTable))
#define sqliteBtreeClearTable(pBt, iTable)\
(btOps(pBt)->ClearTable(pBt, iTable))
#define sqliteBtreeCursor(pBt, iTable, wrFlag, ppCur)\
(btOps(pBt)->Cursor(pBt, iTable, wrFlag, ppCur))
#define sqliteBtreeMoveto(pCur, pKey, nKey, pRes)\
(btCOps(pCur)->Moveto(pCur, pKey, nKey, pRes))
#define sqliteBtreeDelete(pCur) (btCOps(pCur)->Delete(pCur))
#define sqliteBtreeInsert(pCur, pKey, nKey, pData, nData) \
(btCOps(pCur)->Insert(pCur, pKey, nKey, pData, nData))
#define sqliteBtreeFirst(pCur, pRes) (btCOps(pCur)->First(pCur, pRes))
#define sqliteBtreeLast(pCur, pRes) (btCOps(pCur)->Last(pCur, pRes))
#define sqliteBtreeNext(pCur, pRes) (btCOps(pCur)->Next(pCur, pRes))
#define sqliteBtreePrevious(pCur, pRes) (btCOps(pCur)->Previous(pCur, pRes))
#define sqliteBtreeKeySize(pCur, pSize) (btCOps(pCur)->KeySize(pCur, pSize) )
#define sqliteBtreeKey(pCur, offset, amt, zBuf)\
(btCOps(pCur)->Key(pCur, offset, amt, zBuf))
#define sqliteBtreeKeyCompare(pCur, pKey, nKey, nIgnore, pRes)\
(btCOps(pCur)->KeyCompare(pCur, pKey, nKey, nIgnore, pRes))
#define sqliteBtreeDataSize(pCur, pSize) (btCOps(pCur)->DataSize(pCur, pSize))
#define sqliteBtreeData(pCur, offset, amt, zBuf)\
(btCOps(pCur)->Data(pCur, offset, amt, zBuf))
#define sqliteBtreeCloseCursor(pCur) (btCOps(pCur)->CloseCursor(pCur))
#define sqliteBtreeGetMeta(pBt, aMeta) (btOps(pBt)->GetMeta(pBt, aMeta))
#define sqliteBtreeUpdateMeta(pBt, aMeta) (btOps(pBt)->UpdateMeta(pBt, aMeta))
#define sqliteBtreeIntegrityCheck(pBt, aRoot, nRoot)\
(btOps(pBt)->IntegrityCheck(pBt, aRoot, nRoot))
#define sqliteBtreeGetFilename(pBt) (btOps(pBt)->GetFilename(pBt))
#define sqliteBtreeCopyFile(pBt1, pBt2) (btOps(pBt1)->Copyfile(pBt1, pBt2))
#define sqliteBtreePager(pBt) (btOps(pBt)->Pager(pBt))
#ifdef SQLITE_TEST
#define sqliteBtreePageDump(pBt, pgno, recursive)\
(btOps(pBt)->PageDump(pBt, pgno, recursive))
#define sqliteBtreeCursorDump(pCur, aResult)\
(btCOps(pCur)->CursorDump(pCur, aResult))
int btree_native_byte_order;
#endif /* SQLITE_TEST */
#endif /* _BTREE_H_ */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

367
sqlite/callback.c Executable file
View File

@ -0,0 +1,367 @@
/*
** 2005 May 23
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
**
** This file contains functions used to access the internal hash tables
** of user defined functions and collation sequences.
**
** $Id: callback.c,v 1.1 2006-04-13 12:44:29 guy Exp $
*/
#include "sqliteInt.h"
/*
** Invoke the 'collation needed' callback to request a collation sequence
** in the database text encoding of name zName, length nName.
** If the collation sequence
*/
static void callCollNeeded(sqlite3 *db, const char *zName, int nName){
assert( !db->xCollNeeded || !db->xCollNeeded16 );
if( nName<0 ) nName = strlen(zName);
if( db->xCollNeeded ){
char *zExternal = sqliteStrNDup(zName, nName);
if( !zExternal ) return;
db->xCollNeeded(db->pCollNeededArg, db, (int)ENC(db), zExternal);
sqliteFree(zExternal);
}
#ifndef SQLITE_OMIT_UTF16
if( db->xCollNeeded16 ){
char const *zExternal;
sqlite3_value *pTmp = sqlite3ValueNew();
sqlite3ValueSetStr(pTmp, nName, zName, SQLITE_UTF8, SQLITE_STATIC);
zExternal = sqlite3ValueText(pTmp, SQLITE_UTF16NATIVE);
if( zExternal ){
db->xCollNeeded16(db->pCollNeededArg, db, (int)ENC(db), zExternal);
}
sqlite3ValueFree(pTmp);
}
#endif
}
/*
** This routine is called if the collation factory fails to deliver a
** collation function in the best encoding but there may be other versions
** of this collation function (for other text encodings) available. Use one
** of these instead if they exist. Avoid a UTF-8 <-> UTF-16 conversion if
** possible.
*/
static int synthCollSeq(sqlite3 *db, CollSeq *pColl){
CollSeq *pColl2;
char *z = pColl->zName;
int n = strlen(z);
int i;
static const u8 aEnc[] = { SQLITE_UTF16BE, SQLITE_UTF16LE, SQLITE_UTF8 };
for(i=0; i<3; i++){
pColl2 = sqlite3FindCollSeq(db, aEnc[i], z, n, 0);
if( pColl2->xCmp!=0 ){
memcpy(pColl, pColl2, sizeof(CollSeq));
return SQLITE_OK;
}
}
return SQLITE_ERROR;
}
/*
** This function is responsible for invoking the collation factory callback
** or substituting a collation sequence of a different encoding when the
** requested collation sequence is not available in the database native
** encoding.
**
** If it is not NULL, then pColl must point to the database native encoding
** collation sequence with name zName, length nName.
**
** The return value is either the collation sequence to be used in database
** db for collation type name zName, length nName, or NULL, if no collation
** sequence can be found.
*/
CollSeq *sqlite3GetCollSeq(
sqlite3* db,
CollSeq *pColl,
const char *zName,
int nName
){
CollSeq *p;
p = pColl;
if( !p ){
p = sqlite3FindCollSeq(db, ENC(db), zName, nName, 0);
}
if( !p || !p->xCmp ){
/* No collation sequence of this type for this encoding is registered.
** Call the collation factory to see if it can supply us with one.
*/
callCollNeeded(db, zName, nName);
p = sqlite3FindCollSeq(db, ENC(db), zName, nName, 0);
}
if( p && !p->xCmp && synthCollSeq(db, p) ){
p = 0;
}
assert( !p || p->xCmp );
return p;
}
/*
** This routine is called on a collation sequence before it is used to
** check that it is defined. An undefined collation sequence exists when
** a database is loaded that contains references to collation sequences
** that have not been defined by sqlite3_create_collation() etc.
**
** If required, this routine calls the 'collation needed' callback to
** request a definition of the collating sequence. If this doesn't work,
** an equivalent collating sequence that uses a text encoding different
** from the main database is substituted, if one is available.
*/
int sqlite3CheckCollSeq(Parse *pParse, CollSeq *pColl){
if( pColl ){
const char *zName = pColl->zName;
CollSeq *p = sqlite3GetCollSeq(pParse->db, pColl, zName, -1);
if( !p ){
if( pParse->nErr==0 ){
sqlite3ErrorMsg(pParse, "no such collation sequence: %s", zName);
}
pParse->nErr++;
return SQLITE_ERROR;
}
assert( p==pColl );
}
return SQLITE_OK;
}
/*
** 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 || (sqlite3MallocFailed() && pDel==pColl) );
if( pDel ){
sqliteFree(pDel);
pColl = 0;
}
}
}
return pColl;
}
/*
** Parameter zName points to a UTF-8 encoded string nName bytes long.
** Return the CollSeq* pointer for the collation sequence named zName
** for the encoding 'enc' from the database 'db'.
**
** If the entry specified is not found and 'create' is true, then create a
** new entry. Otherwise return NULL.
*/
CollSeq *sqlite3FindCollSeq(
sqlite3 *db,
u8 enc,
const char *zName,
int nName,
int create
){
CollSeq *pColl;
if( zName ){
pColl = findCollSeqEntry(db, zName, nName, create);
}else{
pColl = db->pDfltColl;
}
assert( SQLITE_UTF8==1 && SQLITE_UTF16LE==2 && SQLITE_UTF16BE==3 );
assert( enc>=SQLITE_UTF8 && enc<=SQLITE_UTF16BE );
if( pColl ) pColl += enc-1;
return pColl;
}
/*
** Locate a user function given a name, a number of arguments and a flag
** indicating whether the function prefers UTF-16 over UTF-8. Return a
** pointer to the FuncDef structure that defines that function, or return
** NULL if the function does not exist.
**
** If the createFlag argument is true, then a new (blank) FuncDef
** structure is created and liked into the "db" structure if a
** no matching function previously existed. When createFlag is true
** and the nArg parameter is -1, then only a function that accepts
** any number of arguments will be returned.
**
** If createFlag is false and nArg is -1, then the first valid
** function found is returned. A function is valid if either xFunc
** or xStep is non-zero.
**
** If createFlag is false, then a function with the required name and
** number of arguments may be returned even if the eTextRep flag does not
** match that requested.
*/
FuncDef *sqlite3FindFunction(
sqlite3 *db, /* An open database */
const char *zName, /* Name of the function. Not null-terminated */
int nName, /* Number of characters in the name */
int nArg, /* Number of arguments. -1 means any number */
u8 enc, /* Preferred text encoding */
int createFlag /* Create new entry if true and does not otherwise exist */
){
FuncDef *p; /* Iterator variable */
FuncDef *pFirst; /* First function with this name */
FuncDef *pBest = 0; /* Best match found so far */
int bestmatch = 0;
assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE );
if( nArg<-1 ) nArg = -1;
pFirst = (FuncDef*)sqlite3HashFind(&db->aFunc, zName, nName);
for(p=pFirst; p; p=p->pNext){
/* During the search for the best function definition, bestmatch is set
** as follows to indicate the quality of the match with the definition
** pointed to by pBest:
**
** 0: pBest is NULL. No match has been found.
** 1: A variable arguments function that prefers UTF-8 when a UTF-16
** encoding is requested, or vice versa.
** 2: A variable arguments function that uses UTF-16BE when UTF-16LE is
** requested, or vice versa.
** 3: A variable arguments function using the same text encoding.
** 4: A function with the exact number of arguments requested that
** prefers UTF-8 when a UTF-16 encoding is requested, or vice versa.
** 5: A function with the exact number of arguments requested that
** prefers UTF-16LE when UTF-16BE is requested, or vice versa.
** 6: An exact match.
**
** A larger value of 'matchqual' indicates a more desirable match.
*/
if( p->nArg==-1 || p->nArg==nArg || nArg==-1 ){
int match = 1; /* Quality of this match */
if( p->nArg==nArg || nArg==-1 ){
match = 4;
}
if( enc==p->iPrefEnc ){
match += 2;
}
else if( (enc==SQLITE_UTF16LE && p->iPrefEnc==SQLITE_UTF16BE) ||
(enc==SQLITE_UTF16BE && p->iPrefEnc==SQLITE_UTF16LE) ){
match += 1;
}
if( match>bestmatch ){
pBest = p;
bestmatch = match;
}
}
}
/* If the createFlag parameter is true, and the seach did not reveal an
** exact match for the name, number of arguments and encoding, then add a
** new entry to the hash table and return it.
*/
if( createFlag && bestmatch<6 &&
(pBest = sqliteMalloc(sizeof(*pBest)+nName))!=0 ){
pBest->nArg = nArg;
pBest->pNext = pFirst;
pBest->iPrefEnc = enc;
memcpy(pBest->zName, zName, nName);
pBest->zName[nName] = 0;
if( pBest==sqlite3HashInsert(&db->aFunc,pBest->zName,nName,(void*)pBest) ){
sqliteFree(pBest);
return 0;
}
}
if( pBest && (pBest->xStep || pBest->xFunc || createFlag) ){
return pBest;
}
return 0;
}
/*
** Free all resources held by the schema structure. The void* argument points
** at a Schema struct. This function does not call sqliteFree() on the
** pointer itself, it just cleans up subsiduary resources (i.e. the contents
** of the schema hash tables).
*/
void sqlite3SchemaFree(void *p){
Hash temp1;
Hash temp2;
HashElem *pElem;
Schema *pSchema = (Schema *)p;
temp1 = pSchema->tblHash;
temp2 = pSchema->trigHash;
sqlite3HashInit(&pSchema->trigHash, SQLITE_HASH_STRING, 0);
sqlite3HashClear(&pSchema->aFKey);
sqlite3HashClear(&pSchema->idxHash);
for(pElem=sqliteHashFirst(&temp2); pElem; pElem=sqliteHashNext(pElem)){
sqlite3DeleteTrigger((Trigger*)sqliteHashData(pElem));
}
sqlite3HashClear(&temp2);
sqlite3HashInit(&pSchema->tblHash, SQLITE_HASH_STRING, 0);
for(pElem=sqliteHashFirst(&temp1); pElem; pElem=sqliteHashNext(pElem)){
Table *pTab = sqliteHashData(pElem);
sqlite3DeleteTable(0, pTab);
}
sqlite3HashClear(&temp1);
pSchema->pSeqTab = 0;
pSchema->flags &= ~DB_SchemaLoaded;
}
/*
** Find and return the schema associated with a BTree. Create
** a new one if necessary.
*/
Schema *sqlite3SchemaGet(Btree *pBt){
Schema * p;
if( pBt ){
p = (Schema *)sqlite3BtreeSchema(pBt,sizeof(Schema),sqlite3SchemaFree);
}else{
p = (Schema *)sqliteMalloc(sizeof(Schema));
}
if( p && 0==p->file_format ){
sqlite3HashInit(&p->tblHash, SQLITE_HASH_STRING, 0);
sqlite3HashInit(&p->idxHash, SQLITE_HASH_STRING, 0);
sqlite3HashInit(&p->trigHash, SQLITE_HASH_STRING, 0);
sqlite3HashInit(&p->aFKey, SQLITE_HASH_STRING, 1);
}
return p;
}

263
sqlite/complete.c Executable file
View File

@ -0,0 +1,263 @@
/*
** 2001 September 15
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
** An tokenizer for SQL
**
** This file contains C code that implements the sqlite3_complete() API.
** This code used to be part of the tokenizer.c source file. But by
** separating it out, the code will be automatically omitted from
** static links that do not use it.
**
** $Id: complete.c,v 1.1 2006-04-13 12:44:29 guy Exp $
*/
#include "sqliteInt.h"
#ifndef SQLITE_OMIT_COMPLETE
/*
** This is defined in tokenize.c. We just have to import the definition.
*/
extern const char sqlite3IsIdChar[];
#define IdChar(C) (((c=C)&0x80)!=0 || (c>0x1f && sqlite3IsIdChar[c-0x20]))
/*
** Token types used by the sqlite3_complete() routine. See the header
** comments on that procedure for additional information.
*/
#define tkSEMI 0
#define tkWS 1
#define tkOTHER 2
#define tkEXPLAIN 3
#define tkCREATE 4
#define tkTEMP 5
#define tkTRIGGER 6
#define tkEND 7
/*
** Return TRUE if the given SQL string ends in a semicolon.
**
** Special handling is require for CREATE TRIGGER statements.
** Whenever the CREATE TRIGGER keywords are seen, the statement
** must end with ";END;".
**
** This implementation uses a state machine with 7 states:
**
** (0) START At the beginning or end of an SQL statement. This routine
** returns 1 if it ends in the START state and 0 if it ends
** in any other state.
**
** (1) NORMAL We are in the middle of statement which ends with a single
** semicolon.
**
** (2) EXPLAIN The keyword EXPLAIN has been seen at the beginning of
** a statement.
**
** (3) CREATE The keyword CREATE has been seen at the beginning of a
** statement, possibly preceeded by EXPLAIN and/or followed by
** TEMP or TEMPORARY
**
** (4) TRIGGER We are in the middle of a trigger definition that must be
** ended by a semicolon, the keyword END, and another semicolon.
**
** (5) SEMI We've seen the first semicolon in the ";END;" that occurs at
** the end of a trigger definition.
**
** (6) END We've seen the ";END" of the ";END;" that occurs at the end
** of a trigger difinition.
**
** Transitions between states above are determined by tokens extracted
** from the input. The following tokens are significant:
**
** (0) tkSEMI A semicolon.
** (1) tkWS Whitespace
** (2) tkOTHER Any other SQL token.
** (3) tkEXPLAIN The "explain" keyword.
** (4) tkCREATE The "create" keyword.
** (5) tkTEMP The "temp" or "temporary" keyword.
** (6) tkTRIGGER The "trigger" keyword.
** (7) tkEND The "end" keyword.
**
** Whitespace never causes a state transition and is always ignored.
**
** If we compile with SQLITE_OMIT_TRIGGER, all of the computation needed
** to recognize the end of a trigger can be omitted. All we have to do
** is look for a semicolon that is not part of an string or comment.
*/
int sqlite3_complete(const char *zSql){
u8 state = 0; /* Current state, using numbers defined in header comment */
u8 token; /* Value of the next token */
#ifndef SQLITE_OMIT_TRIGGER
/* A complex statement machine used to detect the end of a CREATE TRIGGER
** statement. This is the normal case.
*/
static const u8 trans[7][8] = {
/* Token: */
/* State: ** SEMI WS OTHER EXPLAIN CREATE TEMP TRIGGER END */
/* 0 START: */ { 0, 0, 1, 2, 3, 1, 1, 1, },
/* 1 NORMAL: */ { 0, 1, 1, 1, 1, 1, 1, 1, },
/* 2 EXPLAIN: */ { 0, 2, 1, 1, 3, 1, 1, 1, },
/* 3 CREATE: */ { 0, 3, 1, 1, 1, 3, 4, 1, },
/* 4 TRIGGER: */ { 5, 4, 4, 4, 4, 4, 4, 4, },
/* 5 SEMI: */ { 5, 5, 4, 4, 4, 4, 4, 6, },
/* 6 END: */ { 0, 6, 4, 4, 4, 4, 4, 4, },
};
#else
/* If triggers are not suppored by this compile then the statement machine
** used to detect the end of a statement is much simplier
*/
static const u8 trans[2][3] = {
/* Token: */
/* State: ** SEMI WS OTHER */
/* 0 START: */ { 0, 0, 1, },
/* 1 NORMAL: */ { 0, 1, 1, },
};
#endif /* SQLITE_OMIT_TRIGGER */
while( *zSql ){
switch( *zSql ){
case ';': { /* A semicolon */
token = tkSEMI;
break;
}
case ' ':
case '\r':
case '\t':
case '\n':
case '\f': { /* White space is ignored */
token = tkWS;
break;
}
case '/': { /* C-style comments */
if( zSql[1]!='*' ){
token = tkOTHER;
break;
}
zSql += 2;
while( zSql[0] && (zSql[0]!='*' || zSql[1]!='/') ){ zSql++; }
if( zSql[0]==0 ) return 0;
zSql++;
token = tkWS;
break;
}
case '-': { /* SQL-style comments from "--" to end of line */
if( zSql[1]!='-' ){
token = tkOTHER;
break;
}
while( *zSql && *zSql!='\n' ){ zSql++; }
if( *zSql==0 ) return state==0;
token = tkWS;
break;
}
case '[': { /* Microsoft-style identifiers in [...] */
zSql++;
while( *zSql && *zSql!=']' ){ zSql++; }
if( *zSql==0 ) return 0;
token = tkOTHER;
break;
}
case '`': /* Grave-accent quoted symbols used by MySQL */
case '"': /* single- and double-quoted strings */
case '\'': {
int c = *zSql;
zSql++;
while( *zSql && *zSql!=c ){ zSql++; }
if( *zSql==0 ) return 0;
token = tkOTHER;
break;
}
default: {
int c;
if( IdChar((u8)*zSql) ){
/* Keywords and unquoted identifiers */
int nId;
for(nId=1; IdChar(zSql[nId]); nId++){}
#ifdef SQLITE_OMIT_TRIGGER
token = tkOTHER;
#else
switch( *zSql ){
case 'c': case 'C': {
if( nId==6 && sqlite3StrNICmp(zSql, "create", 6)==0 ){
token = tkCREATE;
}else{
token = tkOTHER;
}
break;
}
case 't': case 'T': {
if( nId==7 && sqlite3StrNICmp(zSql, "trigger", 7)==0 ){
token = tkTRIGGER;
}else if( nId==4 && sqlite3StrNICmp(zSql, "temp", 4)==0 ){
token = tkTEMP;
}else if( nId==9 && sqlite3StrNICmp(zSql, "temporary", 9)==0 ){
token = tkTEMP;
}else{
token = tkOTHER;
}
break;
}
case 'e': case 'E': {
if( nId==3 && sqlite3StrNICmp(zSql, "end", 3)==0 ){
token = tkEND;
}else
#ifndef SQLITE_OMIT_EXPLAIN
if( nId==7 && sqlite3StrNICmp(zSql, "explain", 7)==0 ){
token = tkEXPLAIN;
}else
#endif
{
token = tkOTHER;
}
break;
}
default: {
token = tkOTHER;
break;
}
}
#endif /* SQLITE_OMIT_TRIGGER */
zSql += nId-1;
}else{
/* Operators and special symbols */
token = tkOTHER;
}
break;
}
}
state = trans[state][token];
zSql++;
}
return state==0;
}
#ifndef SQLITE_OMIT_UTF16
/*
** This routine is the same as the sqlite3_complete() routine described
** above, except that the parameter is required to be UTF-16 encoded, not
** UTF-8.
*/
int sqlite3_complete16(const void *zSql){
sqlite3_value *pVal;
char const *zSql8;
int rc = 0;
pVal = sqlite3ValueNew();
sqlite3ValueSetStr(pVal, -1, zSql, SQLITE_UTF16NATIVE, SQLITE_STATIC);
zSql8 = sqlite3ValueText(pVal, SQLITE_UTF8);
if( zSql8 ){
rc = sqlite3_complete(zSql8);
}
sqlite3ValueFree(pVal);
return sqlite3ApiExit(0, rc);
}
#endif /* SQLITE_OMIT_UTF16 */
#endif /* SQLITE_OMIT_COMPLETE */

View File

@ -1 +0,0 @@
#define SQLITE_PTR_SZ 4

View File

@ -1,110 +0,0 @@
/*
** 2003 April 6
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains code used to implement the COPY command.
**
** $Id: copy.c,v 1.1.1.1 2004-03-11 22:22:23 alex Exp $
*/
#include "sqliteInt.h"
/*
** The COPY command is for compatibility with PostgreSQL and specificially
** for the ability to read the output of pg_dump. The format is as
** follows:
**
** COPY table FROM file [USING DELIMITERS string]
**
** "table" is an existing table name. We will read lines of code from
** file to fill this table with data. File might be "stdin". The optional
** delimiter string identifies the field separators. The default is a tab.
*/
void sqliteCopy(
Parse *pParse, /* The parser context */
SrcList *pTableName, /* The name of the table into which we will insert */
Token *pFilename, /* The file from which to obtain information */
Token *pDelimiter, /* Use this as the field delimiter */
int onError /* What to do if a constraint fails */
){
Table *pTab;
int i;
Vdbe *v;
int addr, end;
char *zFile = 0;
const char *zDb;
sqlite *db = pParse->db;
if( sqlite_malloc_failed ) goto copy_cleanup;
assert( pTableName->nSrc==1 );
pTab = sqliteSrcListLookup(pParse, pTableName);
if( pTab==0 || sqliteIsReadOnly(pParse, pTab, 0) ) goto copy_cleanup;
zFile = sqliteStrNDup(pFilename->z, pFilename->n);
sqliteDequote(zFile);
assert( pTab->iDb<db->nDb );
zDb = db->aDb[pTab->iDb].zName;
if( sqliteAuthCheck(pParse, SQLITE_INSERT, pTab->zName, 0, zDb)
|| sqliteAuthCheck(pParse, SQLITE_COPY, pTab->zName, zFile, zDb) ){
goto copy_cleanup;
}
v = sqliteGetVdbe(pParse);
if( v ){
sqliteBeginWriteOperation(pParse, 1, pTab->iDb);
addr = sqliteVdbeOp3(v, OP_FileOpen, 0, 0, pFilename->z, pFilename->n);
sqliteVdbeDequoteP3(v, addr);
sqliteOpenTableAndIndices(pParse, pTab, 0);
if( db->flags & SQLITE_CountRows ){
sqliteVdbeAddOp(v, OP_Integer, 0, 0); /* Initialize the row count */
}
end = sqliteVdbeMakeLabel(v);
addr = sqliteVdbeAddOp(v, OP_FileRead, pTab->nCol, end);
if( pDelimiter ){
sqliteVdbeChangeP3(v, addr, pDelimiter->z, pDelimiter->n);
sqliteVdbeDequoteP3(v, addr);
}else{
sqliteVdbeChangeP3(v, addr, "\t", 1);
}
if( pTab->iPKey>=0 ){
sqliteVdbeAddOp(v, OP_FileColumn, pTab->iPKey, 0);
sqliteVdbeAddOp(v, OP_MustBeInt, 0, 0);
}else{
sqliteVdbeAddOp(v, OP_NewRecno, 0, 0);
}
for(i=0; i<pTab->nCol; i++){
if( i==pTab->iPKey ){
/* The integer primary key column is filled with NULL since its
** value is always pulled from the record number */
sqliteVdbeAddOp(v, OP_String, 0, 0);
}else{
sqliteVdbeAddOp(v, OP_FileColumn, i, 0);
}
}
sqliteGenerateConstraintChecks(pParse, pTab, 0, 0, pTab->iPKey>=0,
0, onError, addr);
sqliteCompleteInsertion(pParse, pTab, 0, 0, 0, 0, -1);
if( (db->flags & SQLITE_CountRows)!=0 ){
sqliteVdbeAddOp(v, OP_AddImm, 1, 0); /* Increment row count */
}
sqliteVdbeAddOp(v, OP_Goto, 0, addr);
sqliteVdbeResolveLabel(v, end);
sqliteVdbeAddOp(v, OP_Noop, 0, 0);
sqliteEndWriteOperation(pParse);
if( db->flags & SQLITE_CountRows ){
sqliteVdbeAddOp(v, OP_ColumnName, 0, 1);
sqliteVdbeChangeP3(v, -1, "rows inserted", P3_STATIC);
sqliteVdbeAddOp(v, OP_Callback, 1, 0);
}
}
copy_cleanup:
sqliteSrcListDelete(pTableName);
sqliteFree(zFile);
return;
}

View File

@ -13,10 +13,10 @@
** functions for SQLite.
**
** There is only one exported symbol in this file - the function
** sqliteRegisterDateTimeFunctions() found at the bottom of the file.
** sqlite3RegisterDateTimeFunctions() found at the bottom of the file.
** All other code has file scope.
**
** $Id: date.c,v 1.1.1.1 2004-03-11 22:22:23 alex Exp $
** $Id: date.c,v 1.2 2006-04-13 12:44:29 guy Exp $
**
** NOTES:
**
@ -47,8 +47,8 @@
** Willmann-Bell, Inc
** Richmond, Virginia (USA)
*/
#include "os.h"
#include "sqliteInt.h"
#include "os.h"
#include <ctype.h>
#include <stdlib.h>
#include <assert.h>
@ -104,19 +104,21 @@ static int getDigits(const char *zDate, ...){
pVal = va_arg(ap, int*);
val = 0;
while( N-- ){
if( !isdigit(*zDate) ){
return cnt;
if( !isdigit(*(u8*)zDate) ){
goto end_getDigits;
}
val = val*10 + *zDate - '0';
zDate++;
}
if( val<min || val>max || (nextC!=0 && nextC!=*zDate) ){
return cnt;
goto end_getDigits;
}
*pVal = val;
zDate++;
cnt++;
}while( nextC );
end_getDigits:
va_end(ap);
return cnt;
}
@ -124,11 +126,7 @@ static int getDigits(const char *zDate, ...){
** Read text from z[] and convert into a floating point number. Return
** the number of digits converted.
*/
static int getValue(const char *z, double *pR){
const char *zEnd;
*pR = sqliteAtoF(z, &zEnd);
return zEnd - z;
}
#define getValue sqlite3AtoF
/*
** Parse a timezone extension on the end of a date-time.
@ -145,7 +143,7 @@ static int getValue(const char *z, double *pR){
static int parseTimezone(const char *zDate, DateTime *p){
int sgn = 0;
int nHr, nMn;
while( isspace(*zDate) ){ zDate++; }
while( isspace(*(u8*)zDate) ){ zDate++; }
p->tz = 0;
if( *zDate=='-' ){
sgn = -1;
@ -160,7 +158,7 @@ static int parseTimezone(const char *zDate, DateTime *p){
}
zDate += 5;
p->tz = sgn*(nMn + nHr*60);
while( isspace(*zDate) ){ zDate++; }
while( isspace(*(u8*)zDate) ){ zDate++; }
return *zDate!=0;
}
@ -184,10 +182,10 @@ static int parseHhMmSs(const char *zDate, DateTime *p){
return 1;
}
zDate += 2;
if( *zDate=='.' && isdigit(zDate[1]) ){
if( *zDate=='.' && isdigit((u8)zDate[1]) ){
double rScale = 1.0;
zDate++;
while( isdigit(*zDate) ){
while( isdigit(*(u8*)zDate) ){
ms = ms*10.0 + *zDate - '0';
rScale *= 10.0;
zDate++;
@ -240,7 +238,7 @@ static void computeJD(DateTime *p){
if( p->validHMS ){
p->rJD += (p->h*3600.0 + p->m*60.0 + p->s)/86400.0;
if( p->validTZ ){
p->rJD += p->tz*60/86400.0;
p->rJD -= p->tz*60/86400.0;
p->validHMS = 0;
p->validTZ = 0;
}
@ -272,7 +270,7 @@ static int parseYyyyMmDd(const char *zDate, DateTime *p){
return 1;
}
zDate += 10;
while( isspace(*zDate) ){ zDate++; }
while( isspace(*(u8*)zDate) || 'T'==*(u8*)zDate ){ zDate++; }
if( parseHhMmSs(zDate, p)==0 ){
/* We got the time */
}else if( *zDate==0 ){
@ -313,16 +311,14 @@ static int parseDateOrTime(const char *zDate, DateTime *p){
return 0;
}else if( parseHhMmSs(zDate, p)==0 ){
return 0;
}else if( sqliteStrICmp(zDate,"now")==0){
}else if( sqlite3StrICmp(zDate,"now")==0){
double r;
if( sqliteOsCurrentTime(&r)==0 ){
p->rJD = r;
p->validJD = 1;
return 0;
}
return 1;
}else if( sqliteIsNumber(zDate) ){
p->rJD = sqliteAtoF(zDate, 0);
sqlite3OsCurrentTime(&r);
p->rJD = r;
p->validJD = 1;
return 0;
}else if( sqlite3IsNumber(zDate, 0, SQLITE_UTF8) ){
getValue(zDate, &p->rJD);
p->validJD = 1;
return 0;
}
@ -415,7 +411,7 @@ static double localtimeOffset(DateTime *p){
x.validJD = 0;
computeJD(&x);
t = (x.rJD-2440587.5)*86400.0 + 0.5;
sqliteOsEnterMutex();
sqlite3OsEnterMutex();
pTm = localtime(&t);
y.Y = pTm->tm_year + 1900;
y.M = pTm->tm_mon + 1;
@ -423,7 +419,7 @@ static double localtimeOffset(DateTime *p){
y.h = pTm->tm_hour;
y.m = pTm->tm_min;
y.s = pTm->tm_sec;
sqliteOsLeaveMutex();
sqlite3OsLeaveMutex();
y.validYMD = 1;
y.validHMS = 1;
y.validJD = 0;
@ -504,7 +500,7 @@ static int parseModifier(const char *zMod, DateTime *p){
/*
** weekday N
**
** Move the date to the same time on the next occurrance of
** Move the date to the same time on the next occurrence of
** weekday N where 0==Sunday, 1==Monday, and so forth. If the
** date is already on the appropriate weekday, this is a no-op.
*/
@ -575,7 +571,7 @@ static int parseModifier(const char *zMod, DateTime *p){
const char *z2 = z;
DateTime tx;
int day;
if( !isdigit(*z2) ) z2++;
if( !isdigit(*(u8*)z2) ) z2++;
memset(&tx, 0, sizeof(tx));
if( parseHhMmSs(z2, &tx) ) break;
computeJD(&tx);
@ -590,7 +586,7 @@ static int parseModifier(const char *zMod, DateTime *p){
break;
}
z += n;
while( isspace(z[0]) ) z++;
while( isspace(*(u8*)z) ) z++;
n = strlen(z);
if( n>10 || n<3 ) break;
if( z[n-1]=='s' ){ z[n-1] = 0; n--; }
@ -641,12 +637,14 @@ static int parseModifier(const char *zMod, DateTime *p){
** the resulting time into the DateTime structure p. Return 0
** on success and 1 if there are any errors.
*/
static int isDate(int argc, const char **argv, DateTime *p){
static int isDate(int argc, sqlite3_value **argv, DateTime *p){
int i;
if( argc==0 ) return 1;
if( argv[0]==0 || parseDateOrTime(argv[0], p) ) return 1;
if( SQLITE_NULL==sqlite3_value_type(argv[0]) ||
parseDateOrTime((char*)sqlite3_value_text(argv[0]), p) ) return 1;
for(i=1; i<argc; i++){
if( argv[i]==0 || parseModifier(argv[i], p) ) return 1;
if( SQLITE_NULL==sqlite3_value_type(argv[i]) ||
parseModifier((char*)sqlite3_value_text(argv[i]), p) ) return 1;
}
return 0;
}
@ -662,11 +660,15 @@ static int isDate(int argc, const char **argv, DateTime *p){
**
** Return the julian day number of the date specified in the arguments
*/
static void juliandayFunc(sqlite_func *context, int argc, const char **argv){
static void juliandayFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
DateTime x;
if( isDate(argc, argv, &x)==0 ){
computeJD(&x);
sqlite_set_result_double(context, x.rJD);
sqlite3_result_double(context, x.rJD);
}
}
@ -675,14 +677,18 @@ static void juliandayFunc(sqlite_func *context, int argc, const char **argv){
**
** Return YYYY-MM-DD HH:MM:SS
*/
static void datetimeFunc(sqlite_func *context, int argc, const char **argv){
static void datetimeFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
DateTime x;
if( isDate(argc, argv, &x)==0 ){
char zBuf[100];
computeYMD_HMS(&x);
sprintf(zBuf, "%04d-%02d-%02d %02d:%02d:%02d",x.Y, x.M, x.D, x.h, x.m,
(int)(x.s));
sqlite_set_result_string(context, zBuf, -1);
sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
}
}
@ -691,13 +697,17 @@ static void datetimeFunc(sqlite_func *context, int argc, const char **argv){
**
** Return HH:MM:SS
*/
static void timeFunc(sqlite_func *context, int argc, const char **argv){
static void timeFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
DateTime x;
if( isDate(argc, argv, &x)==0 ){
char zBuf[100];
computeHMS(&x);
sprintf(zBuf, "%02d:%02d:%02d", x.h, x.m, (int)x.s);
sqlite_set_result_string(context, zBuf, -1);
sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
}
}
@ -706,13 +716,17 @@ static void timeFunc(sqlite_func *context, int argc, const char **argv){
**
** Return YYYY-MM-DD
*/
static void dateFunc(sqlite_func *context, int argc, const char **argv){
static void dateFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
DateTime x;
if( isDate(argc, argv, &x)==0 ){
char zBuf[100];
computeYMD(&x);
sprintf(zBuf, "%04d-%02d-%02d", x.Y, x.M, x.D);
sqlite_set_result_string(context, zBuf, -1);
sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
}
}
@ -735,13 +749,17 @@ static void dateFunc(sqlite_func *context, int argc, const char **argv){
** %Y year 0000-9999
** %% %
*/
static void strftimeFunc(sqlite_func *context, int argc, const char **argv){
static void strftimeFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
DateTime x;
int n, i, j;
char *z;
const char *zFmt = argv[0];
const char *zFmt = (const char*)sqlite3_value_text(argv[0]);
char zBuf[100];
if( argv[0]==0 || isDate(argc-1, argv+1, &x) ) return;
if( zFmt==0 || isDate(argc-1, argv+1, &x) ) return;
for(i=0, n=1; zFmt[i]; i++, n++){
if( zFmt[i]=='%' ){
switch( zFmt[i+1] ){
@ -800,18 +818,20 @@ static void strftimeFunc(sqlite_func *context, int argc, const char **argv){
case 'H': sprintf(&z[j],"%02d",x.h); j+=2; break;
case 'W': /* Fall thru */
case 'j': {
int n;
int nDay; /* Number of days since 1st day of year */
DateTime y = x;
y.validJD = 0;
y.M = 1;
y.D = 1;
computeJD(&y);
n = x.rJD - y.rJD + 1;
nDay = x.rJD - y.rJD;
if( zFmt[i]=='W' ){
sprintf(&z[j],"%02d",(n+6)/7);
int wd; /* 0=Monday, 1=Tuesday, ... 6=Sunday */
wd = ((int)(x.rJD+0.5)) % 7;
sprintf(&z[j],"%02d",(nDay+7-wd)/7);
j += 2;
}else{
sprintf(&z[j],"%03d",n);
sprintf(&z[j],"%03d",nDay+1);
j += 3;
}
break;
@ -832,42 +852,147 @@ static void strftimeFunc(sqlite_func *context, int argc, const char **argv){
}
}
z[j] = 0;
sqlite_set_result_string(context, z, -1);
sqlite3_result_text(context, z, -1, SQLITE_TRANSIENT);
if( z!=zBuf ){
sqliteFree(z);
}
}
/*
** current_time()
**
** This function returns the same value as time('now').
*/
static void ctimeFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
sqlite3_value *pVal = sqlite3ValueNew();
if( pVal ){
sqlite3ValueSetStr(pVal, -1, "now", SQLITE_UTF8, SQLITE_STATIC);
timeFunc(context, 1, &pVal);
sqlite3ValueFree(pVal);
}
}
/*
** current_date()
**
** This function returns the same value as date('now').
*/
static void cdateFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
sqlite3_value *pVal = sqlite3ValueNew();
if( pVal ){
sqlite3ValueSetStr(pVal, -1, "now", SQLITE_UTF8, SQLITE_STATIC);
dateFunc(context, 1, &pVal);
sqlite3ValueFree(pVal);
}
}
/*
** current_timestamp()
**
** This function returns the same value as datetime('now').
*/
static void ctimestampFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
sqlite3_value *pVal = sqlite3ValueNew();
if( pVal ){
sqlite3ValueSetStr(pVal, -1, "now", SQLITE_UTF8, SQLITE_STATIC);
datetimeFunc(context, 1, &pVal);
sqlite3ValueFree(pVal);
}
}
#endif /* !defined(SQLITE_OMIT_DATETIME_FUNCS) */
#ifdef SQLITE_OMIT_DATETIME_FUNCS
/*
** If the library is compiled to omit the full-scale date and time
** handling (to get a smaller binary), the following minimal version
** of the functions current_time(), current_date() and current_timestamp()
** are included instead. This is to support column declarations that
** include "DEFAULT CURRENT_TIME" etc.
**
** This function uses the C-library functions time(), gmtime()
** and strftime(). The format string to pass to strftime() is supplied
** as the user-data for the function.
*/
static void currentTimeFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
time_t t;
char *zFormat = (char *)sqlite3_user_data(context);
char zBuf[20];
time(&t);
#ifdef SQLITE_TEST
{
extern int sqlite3_current_time; /* See os_XXX.c */
if( sqlite3_current_time ){
t = sqlite3_current_time;
}
}
#endif
sqlite3OsEnterMutex();
strftime(zBuf, 20, zFormat, gmtime(&t));
sqlite3OsLeaveMutex();
sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
}
#endif
/*
** This function registered all of the above C functions as SQL
** functions. This should be the only routine in this file with
** external linkage.
*/
void sqliteRegisterDateTimeFunctions(sqlite *db){
static struct {
void sqlite3RegisterDateTimeFunctions(sqlite3 *db){
#ifndef SQLITE_OMIT_DATETIME_FUNCS
static const struct {
char *zName;
int nArg;
int dataType;
void (*xFunc)(sqlite_func*,int,const char**);
void (*xFunc)(sqlite3_context*,int,sqlite3_value**);
} aFuncs[] = {
#ifndef SQLITE_OMIT_DATETIME_FUNCS
{ "julianday", -1, SQLITE_NUMERIC, juliandayFunc },
{ "date", -1, SQLITE_TEXT, dateFunc },
{ "time", -1, SQLITE_TEXT, timeFunc },
{ "datetime", -1, SQLITE_TEXT, datetimeFunc },
{ "strftime", -1, SQLITE_TEXT, strftimeFunc },
#endif
{ "julianday", -1, juliandayFunc },
{ "date", -1, dateFunc },
{ "time", -1, timeFunc },
{ "datetime", -1, datetimeFunc },
{ "strftime", -1, strftimeFunc },
{ "current_time", 0, ctimeFunc },
{ "current_timestamp", 0, ctimestampFunc },
{ "current_date", 0, cdateFunc },
};
int i;
for(i=0; i<sizeof(aFuncs)/sizeof(aFuncs[0]); i++){
sqlite_create_function(db, aFuncs[i].zName,
aFuncs[i].nArg, aFuncs[i].xFunc, 0);
if( aFuncs[i].xFunc ){
sqlite_function_type(db, aFuncs[i].zName, aFuncs[i].dataType);
}
sqlite3CreateFunc(db, aFuncs[i].zName, aFuncs[i].nArg,
SQLITE_UTF8, 0, aFuncs[i].xFunc, 0, 0);
}
#else
static const struct {
char *zName;
char *zFormat;
} aFuncs[] = {
{ "current_time", "%H:%M:%S" },
{ "current_date", "%Y-%m-%d" },
{ "current_timestamp", "%Y-%m-%d %H:%M:%S" }
};
int i;
for(i=0; i<sizeof(aFuncs)/sizeof(aFuncs[0]); i++){
sqlite3CreateFunc(db, aFuncs[i].zName, 0, SQLITE_UTF8,
aFuncs[i].zFormat, currentTimeFunc, 0, 0);
}
#endif
}

View File

@ -10,9 +10,9 @@
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle DELETE FROM statements.
** in order to generate code for DELETE FROM statements.
**
** $Id: delete.c,v 1.1.1.1 2004-03-11 22:22:23 alex Exp $
** $Id: delete.c,v 1.2 2006-04-13 12:44:29 guy Exp $
*/
#include "sqliteInt.h"
@ -21,14 +21,17 @@
** add an error message to pParse->zErrMsg and return NULL. If all tables
** are found, return a pointer to the last table.
*/
Table *sqliteSrcListLookup(Parse *pParse, SrcList *pSrc){
Table *sqlite3SrcListLookup(Parse *pParse, SrcList *pSrc){
Table *pTab = 0;
int i;
for(i=0; i<pSrc->nSrc; i++){
const char *zTab = pSrc->a[i].zName;
const char *zDb = pSrc->a[i].zDatabase;
pTab = sqliteLocateTable(pParse, zTab, zDb);
pSrc->a[i].pTab = pTab;
struct SrcList_item *pItem;
for(i=0, pItem=pSrc->a; i<pSrc->nSrc; i++, pItem++){
pTab = sqlite3LocateTable(pParse, pItem->zName, pItem->zDatabase);
sqlite3DeleteTable(pParse->db, pItem->pTab);
pItem->pTab = pTab;
if( pTab ){
pTab->nRef++;
}
}
return pTab;
}
@ -38,22 +41,49 @@ Table *sqliteSrcListLookup(Parse *pParse, SrcList *pSrc){
** writable, generate an error message and return 1. If it is
** writable return 0;
*/
int sqliteIsReadOnly(Parse *pParse, Table *pTab, int viewOk){
if( pTab->readOnly ){
sqliteErrorMsg(pParse, "table %s may not be modified", pTab->zName);
int sqlite3IsReadOnly(Parse *pParse, Table *pTab, int viewOk){
if( pTab->readOnly && (pParse->db->flags & SQLITE_WriteSchema)==0
&& pParse->nested==0 ){
sqlite3ErrorMsg(pParse, "table %s may not be modified", pTab->zName);
return 1;
}
#ifndef SQLITE_OMIT_VIEW
if( !viewOk && pTab->pSelect ){
sqliteErrorMsg(pParse, "cannot modify %s because it is a view",pTab->zName);
sqlite3ErrorMsg(pParse,"cannot modify %s because it is a view",pTab->zName);
return 1;
}
#endif
return 0;
}
/*
** Process a DELETE FROM statement.
** Generate code that will open a table for reading.
*/
void sqliteDeleteFrom(
void sqlite3OpenTable(
Parse *p, /* Generate code into this VDBE */
int iCur, /* The cursor number of the table */
int iDb, /* The database index in sqlite3.aDb[] */
Table *pTab, /* The table to be opened */
int opcode /* OP_OpenRead or OP_OpenWrite */
){
Vdbe *v = sqlite3GetVdbe(p);
assert( opcode==OP_OpenWrite || opcode==OP_OpenRead );
sqlite3TableLock(p, iDb, pTab->tnum, (opcode==OP_OpenWrite), pTab->zName);
sqlite3VdbeAddOp(v, OP_Integer, iDb, 0);
VdbeComment((v, "# %s", pTab->zName));
sqlite3VdbeAddOp(v, opcode, iCur, pTab->tnum);
sqlite3VdbeAddOp(v, OP_SetNumColumns, iCur, pTab->nCol);
}
/*
** Generate code for a DELETE FROM statement.
**
** DELETE FROM table_wxyz WHERE a<5 AND b NOT NULL;
** \________/ \________________/
** pTabList pWhere
*/
void sqlite3DeleteFrom(
Parse *pParse, /* The parser context */
SrcList *pTabList, /* The table from which we should delete things */
Expr *pWhere /* The WHERE clause. May be null */
@ -61,23 +91,24 @@ void sqliteDeleteFrom(
Vdbe *v; /* The virtual database engine */
Table *pTab; /* The table from which records will be deleted */
const char *zDb; /* Name of database holding pTab */
int end, addr; /* A couple addresses of generated code */
int end, addr = 0; /* A couple addresses of generated code */
int i; /* Loop counter */
WhereInfo *pWInfo; /* Information about the WHERE clause */
Index *pIdx; /* For looping over indices of the table */
int iCur; /* VDBE Cursor number for pTab */
sqlite *db; /* Main database structure */
int isView; /* True if attempting to delete from a view */
sqlite3 *db; /* Main database structure */
AuthContext sContext; /* Authorization context */
int oldIdx = -1; /* Cursor for the OLD table of AFTER triggers */
NameContext sNC; /* Name context to resolve expressions in */
int iDb;
int row_triggers_exist = 0; /* True if any triggers exist */
int before_triggers; /* True if there are BEFORE triggers */
int after_triggers; /* True if there are AFTER triggers */
int oldIdx = -1; /* Cursor for the OLD table of AFTER triggers */
#ifndef SQLITE_OMIT_TRIGGER
int isView; /* True if attempting to delete from a view */
int triggers_exist = 0; /* True if any triggers exist */
#endif
sContext.pParse = 0;
if( pParse->nErr || sqlite_malloc_failed ){
pTabList = 0;
if( pParse->nErr || sqlite3MallocFailed() ){
goto delete_from_cleanup;
}
db = pParse->db;
@ -88,102 +119,115 @@ void sqliteDeleteFrom(
** will be calling are designed to work with multiple tables and expect
** an SrcList* parameter instead of just a Table* parameter.
*/
pTab = sqliteSrcListLookup(pParse, pTabList);
pTab = sqlite3SrcListLookup(pParse, pTabList);
if( pTab==0 ) goto delete_from_cleanup;
before_triggers = sqliteTriggersExist(pParse, pTab->pTrigger,
TK_DELETE, TK_BEFORE, TK_ROW, 0);
after_triggers = sqliteTriggersExist(pParse, pTab->pTrigger,
TK_DELETE, TK_AFTER, TK_ROW, 0);
row_triggers_exist = before_triggers || after_triggers;
/* Figure out if we have any triggers and if the table being
** deleted from is a view
*/
#ifndef SQLITE_OMIT_TRIGGER
triggers_exist = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0);
isView = pTab->pSelect!=0;
if( sqliteIsReadOnly(pParse, pTab, before_triggers) ){
#else
# define triggers_exist 0
# define isView 0
#endif
#ifdef SQLITE_OMIT_VIEW
# undef isView
# define isView 0
#endif
if( sqlite3IsReadOnly(pParse, pTab, triggers_exist) ){
goto delete_from_cleanup;
}
assert( pTab->iDb<db->nDb );
zDb = db->aDb[pTab->iDb].zName;
if( sqliteAuthCheck(pParse, SQLITE_DELETE, pTab->zName, 0, zDb) ){
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
assert( iDb<db->nDb );
zDb = db->aDb[iDb].zName;
if( sqlite3AuthCheck(pParse, SQLITE_DELETE, pTab->zName, 0, zDb) ){
goto delete_from_cleanup;
}
/* If pTab is really a view, make sure it has been initialized.
*/
if( isView && sqliteViewGetColumnNames(pParse, pTab) ){
if( isView && sqlite3ViewGetColumnNames(pParse, pTab) ){
goto delete_from_cleanup;
}
/* Allocate a cursor used to store the old.* data for a trigger.
*/
if( row_triggers_exist ){
if( triggers_exist ){
oldIdx = pParse->nTab++;
}
/* Resolve the column names in all the expressions.
/* Resolve the column names in the WHERE clause.
*/
assert( pTabList->nSrc==1 );
iCur = pTabList->a[0].iCursor = pParse->nTab++;
if( pWhere ){
if( sqliteExprResolveIds(pParse, pTabList, 0, pWhere) ){
goto delete_from_cleanup;
}
if( sqliteExprCheck(pParse, pWhere, 0, 0) ){
goto delete_from_cleanup;
}
memset(&sNC, 0, sizeof(sNC));
sNC.pParse = pParse;
sNC.pSrcList = pTabList;
if( sqlite3ExprResolveNames(&sNC, pWhere) ){
goto delete_from_cleanup;
}
/* Start the view context
*/
if( isView ){
sqliteAuthContextPush(pParse, &sContext, pTab->zName);
sqlite3AuthContextPush(pParse, &sContext, pTab->zName);
}
/* Begin generating code.
*/
v = sqliteGetVdbe(pParse);
v = sqlite3GetVdbe(pParse);
if( v==0 ){
goto delete_from_cleanup;
}
sqliteBeginWriteOperation(pParse, row_triggers_exist, pTab->iDb);
if( pParse->nested==0 ) sqlite3VdbeCountChanges(v);
sqlite3BeginWriteOperation(pParse, triggers_exist, iDb);
/* If we are trying to delete from a view, construct that view into
** a temporary table.
/* If we are trying to delete from a view, realize that view into
** a ephemeral table.
*/
if( isView ){
Select *pView = sqliteSelectDup(pTab->pSelect);
sqliteSelect(pParse, pView, SRT_TempTable, iCur, 0, 0, 0);
sqliteSelectDelete(pView);
Select *pView = sqlite3SelectDup(pTab->pSelect);
sqlite3Select(pParse, pView, SRT_VirtualTab, iCur, 0, 0, 0, 0);
sqlite3SelectDelete(pView);
}
/* Initialize the counter of the number of rows deleted, if
** we are counting rows.
*/
if( db->flags & SQLITE_CountRows ){
sqliteVdbeAddOp(v, OP_Integer, 0, 0);
sqlite3VdbeAddOp(v, OP_Integer, 0, 0);
}
/* Special case: A DELETE without a WHERE clause deletes everything.
** It is easier just to erase the whole table. Note, however, that
** this means that the row change count will be incorrect.
*/
if( pWhere==0 && !row_triggers_exist ){
if( pWhere==0 && !triggers_exist ){
if( db->flags & SQLITE_CountRows ){
/* If counting rows deleted, just count the total number of
** entries in the table. */
int endOfLoop = sqliteVdbeMakeLabel(v);
int addr;
int endOfLoop = sqlite3VdbeMakeLabel(v);
int addr2;
if( !isView ){
sqliteVdbeAddOp(v, OP_Integer, pTab->iDb, 0);
sqliteVdbeAddOp(v, OP_OpenRead, iCur, pTab->tnum);
sqlite3OpenTable(pParse, iCur, iDb, pTab, OP_OpenRead);
}
sqliteVdbeAddOp(v, OP_Rewind, iCur, sqliteVdbeCurrentAddr(v)+2);
addr = sqliteVdbeAddOp(v, OP_AddImm, 1, 0);
sqliteVdbeAddOp(v, OP_Next, iCur, addr);
sqliteVdbeResolveLabel(v, endOfLoop);
sqliteVdbeAddOp(v, OP_Close, iCur, 0);
sqlite3VdbeAddOp(v, OP_Rewind, iCur, sqlite3VdbeCurrentAddr(v)+2);
addr2 = sqlite3VdbeAddOp(v, OP_AddImm, 1, 0);
sqlite3VdbeAddOp(v, OP_Next, iCur, addr2);
sqlite3VdbeResolveLabel(v, endOfLoop);
sqlite3VdbeAddOp(v, OP_Close, iCur, 0);
}
if( !isView ){
sqliteVdbeAddOp(v, OP_Clear, pTab->tnum, pTab->iDb);
sqlite3VdbeAddOp(v, OP_Clear, pTab->tnum, iDb);
if( !pParse->nested ){
sqlite3VdbeChangeP3(v, -1, pTab->zName, P3_STATIC);
}
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
sqliteVdbeAddOp(v, OP_Clear, pIdx->tnum, pIdx->iDb);
assert( pIdx->pSchema==pTab->pSchema );
sqlite3VdbeAddOp(v, OP_Clear, pIdx->tnum, iDb);
}
}
}
@ -194,122 +238,118 @@ void sqliteDeleteFrom(
else{
/* Begin the database scan
*/
pWInfo = sqliteWhereBegin(pParse, pTabList, pWhere, 1, 0);
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0);
if( pWInfo==0 ) goto delete_from_cleanup;
/* Remember the key of every item to be deleted.
/* Remember the rowid of every item to be deleted.
*/
sqliteVdbeAddOp(v, OP_ListWrite, 0, 0);
sqlite3VdbeAddOp(v, OP_Rowid, iCur, 0);
sqlite3VdbeAddOp(v, OP_FifoWrite, 0, 0);
if( db->flags & SQLITE_CountRows ){
sqliteVdbeAddOp(v, OP_AddImm, 1, 0);
sqlite3VdbeAddOp(v, OP_AddImm, 1, 0);
}
/* End the database scan loop.
*/
sqliteWhereEnd(pWInfo);
sqlite3WhereEnd(pWInfo);
/* Open the pseudo-table used to store OLD if there are triggers.
*/
if( row_triggers_exist ){
sqliteVdbeAddOp(v, OP_OpenPseudo, oldIdx, 0);
if( triggers_exist ){
sqlite3VdbeAddOp(v, OP_OpenPseudo, oldIdx, 0);
sqlite3VdbeAddOp(v, OP_SetNumColumns, oldIdx, pTab->nCol);
}
/* Delete every item whose key was written to the list during the
** database scan. We have to delete items after the scan is complete
** because deleting an item can change the scan order.
*/
sqliteVdbeAddOp(v, OP_ListRewind, 0, 0);
end = sqliteVdbeMakeLabel(v);
end = sqlite3VdbeMakeLabel(v);
/* This is the beginning of the delete loop when there are
** row triggers.
*/
if( row_triggers_exist ){
addr = sqliteVdbeAddOp(v, OP_ListRead, 0, end);
sqliteVdbeAddOp(v, OP_Dup, 0, 0);
if( triggers_exist ){
addr = sqlite3VdbeAddOp(v, OP_FifoRead, 0, end);
if( !isView ){
sqliteVdbeAddOp(v, OP_Integer, pTab->iDb, 0);
sqliteVdbeAddOp(v, OP_OpenRead, iCur, pTab->tnum);
sqlite3VdbeAddOp(v, OP_Dup, 0, 0);
sqlite3OpenTable(pParse, iCur, iDb, pTab, OP_OpenRead);
}
sqliteVdbeAddOp(v, OP_MoveTo, iCur, 0);
sqliteVdbeAddOp(v, OP_Recno, iCur, 0);
sqliteVdbeAddOp(v, OP_RowData, iCur, 0);
sqliteVdbeAddOp(v, OP_PutIntKey, oldIdx, 0);
sqlite3VdbeAddOp(v, OP_MoveGe, iCur, 0);
sqlite3VdbeAddOp(v, OP_Rowid, iCur, 0);
sqlite3VdbeAddOp(v, OP_RowData, iCur, 0);
sqlite3VdbeAddOp(v, OP_Insert, oldIdx, 0);
if( !isView ){
sqliteVdbeAddOp(v, OP_Close, iCur, 0);
sqlite3VdbeAddOp(v, OP_Close, iCur, 0);
}
sqliteCodeRowTrigger(pParse, TK_DELETE, 0, TK_BEFORE, pTab, -1,
oldIdx, (pParse->trigStack)?pParse->trigStack->orconf:OE_Default,
addr);
(void)sqlite3CodeRowTrigger(pParse, TK_DELETE, 0, TRIGGER_BEFORE, pTab,
-1, oldIdx, (pParse->trigStack)?pParse->trigStack->orconf:OE_Default,
addr);
}
if( !isView ){
/* Open cursors for the table we are deleting from and all its
** indices. If there are row triggers, this happens inside the
** OP_ListRead loop because the cursor have to all be closed
** OP_FifoRead loop because the cursor have to all be closed
** before the trigger fires. If there are no row triggers, the
** cursors are opened only once on the outside the loop.
*/
pParse->nTab = iCur + 1;
sqliteOpenTableAndIndices(pParse, pTab, iCur);
sqlite3OpenTableAndIndices(pParse, pTab, iCur, OP_OpenWrite);
/* This is the beginning of the delete loop when there are no
** row triggers */
if( !row_triggers_exist ){
addr = sqliteVdbeAddOp(v, OP_ListRead, 0, end);
if( !triggers_exist ){
addr = sqlite3VdbeAddOp(v, OP_FifoRead, 0, end);
}
/* Delete the row */
sqliteGenerateRowDelete(db, v, pTab, iCur, pParse->trigStack==0);
sqlite3GenerateRowDelete(db, v, pTab, iCur, pParse->nested==0);
}
/* If there are row triggers, close all cursors then invoke
** the AFTER triggers
*/
if( row_triggers_exist ){
if( triggers_exist ){
if( !isView ){
for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
sqliteVdbeAddOp(v, OP_Close, iCur + i, pIdx->tnum);
sqlite3VdbeAddOp(v, OP_Close, iCur + i, pIdx->tnum);
}
sqliteVdbeAddOp(v, OP_Close, iCur, 0);
sqlite3VdbeAddOp(v, OP_Close, iCur, 0);
}
sqliteCodeRowTrigger(pParse, TK_DELETE, 0, TK_AFTER, pTab, -1,
(void)sqlite3CodeRowTrigger(pParse, TK_DELETE, 0, TRIGGER_AFTER, pTab, -1,
oldIdx, (pParse->trigStack)?pParse->trigStack->orconf:OE_Default,
addr);
addr);
}
/* End of the delete loop */
sqliteVdbeAddOp(v, OP_Goto, 0, addr);
sqliteVdbeResolveLabel(v, end);
sqliteVdbeAddOp(v, OP_ListReset, 0, 0);
sqlite3VdbeAddOp(v, OP_Goto, 0, addr);
sqlite3VdbeResolveLabel(v, end);
/* Close the cursors after the loop if there are no row triggers */
if( !row_triggers_exist ){
if( !triggers_exist ){
for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
sqliteVdbeAddOp(v, OP_Close, iCur + i, pIdx->tnum);
sqlite3VdbeAddOp(v, OP_Close, iCur + i, pIdx->tnum);
}
sqliteVdbeAddOp(v, OP_Close, iCur, 0);
pParse->nTab = iCur;
sqlite3VdbeAddOp(v, OP_Close, iCur, 0);
}
}
sqliteVdbeAddOp(v, OP_SetCounts, 0, 0);
sqliteEndWriteOperation(pParse);
/*
** Return the number of rows that were deleted.
** Return the number of rows that were deleted. If this routine is
** generating code because of a call to sqlite3NestedParse(), do not
** invoke the callback function.
*/
if( db->flags & SQLITE_CountRows ){
sqliteVdbeAddOp(v, OP_ColumnName, 0, 1);
sqliteVdbeChangeP3(v, -1, "rows deleted", P3_STATIC);
sqliteVdbeAddOp(v, OP_Callback, 1, 0);
if( db->flags & SQLITE_CountRows && pParse->nested==0 && !pParse->trigStack ){
sqlite3VdbeAddOp(v, OP_Callback, 1, 0);
sqlite3VdbeSetNumCols(v, 1);
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows deleted", P3_STATIC);
}
delete_from_cleanup:
sqliteAuthContextPop(&sContext);
sqliteSrcListDelete(pTabList);
sqliteExprDelete(pWhere);
sqlite3AuthContextPop(&sContext);
sqlite3SrcListDelete(pTabList);
sqlite3ExprDelete(pWhere);
return;
}
@ -333,19 +373,21 @@ delete_from_cleanup:
** and then generates code to remove both the table record and all index
** entries that point to that record.
*/
void sqliteGenerateRowDelete(
sqlite *db, /* The database containing the index */
void sqlite3GenerateRowDelete(
sqlite3 *db, /* The database containing the index */
Vdbe *v, /* Generate code into this VDBE */
Table *pTab, /* Table containing the row to be deleted */
int iCur, /* Cursor number for the table */
int count /* Increment the row change counter */
){
int addr;
addr = sqliteVdbeAddOp(v, OP_NotExists, iCur, 0);
sqliteGenerateRowIndexDelete(db, v, pTab, iCur, 0);
sqliteVdbeAddOp(v, OP_Delete, iCur,
(count?OPFLAG_NCHANGE:0) | OPFLAG_CSCHANGE);
sqliteVdbeChangeP2(v, addr, sqliteVdbeCurrentAddr(v));
addr = sqlite3VdbeAddOp(v, OP_NotExists, iCur, 0);
sqlite3GenerateRowIndexDelete(v, pTab, iCur, 0);
sqlite3VdbeAddOp(v, OP_Delete, iCur, (count?OPFLAG_NCHANGE:0));
if( count ){
sqlite3VdbeChangeP3(v, -1, pTab->zName, P3_STATIC);
}
sqlite3VdbeJumpHere(v, addr);
}
/*
@ -364,8 +406,7 @@ void sqliteGenerateRowDelete(
** 3. The "iCur" cursor must be pointing to the row that is to be
** deleted.
*/
void sqliteGenerateRowIndexDelete(
sqlite *db, /* The database containing the index */
void sqlite3GenerateRowIndexDelete(
Vdbe *v, /* Generate code into this VDBE */
Table *pTab, /* Table containing the row to be deleted */
int iCur, /* Cursor number for the table */
@ -375,19 +416,36 @@ void sqliteGenerateRowIndexDelete(
Index *pIdx;
for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
int j;
if( aIdxUsed!=0 && aIdxUsed[i-1]==0 ) continue;
sqliteVdbeAddOp(v, OP_Recno, iCur, 0);
for(j=0; j<pIdx->nColumn; j++){
int idx = pIdx->aiColumn[j];
if( idx==pTab->iPKey ){
sqliteVdbeAddOp(v, OP_Dup, j, 0);
}else{
sqliteVdbeAddOp(v, OP_Column, iCur, idx);
}
}
sqliteVdbeAddOp(v, OP_MakeIdxKey, pIdx->nColumn, 0);
if( db->file_format>=4 ) sqliteAddIdxKeyType(v, pIdx);
sqliteVdbeAddOp(v, OP_IdxDelete, iCur+i, 0);
sqlite3GenerateIndexKey(v, pIdx, iCur);
sqlite3VdbeAddOp(v, OP_IdxDelete, iCur+i, 0);
}
}
/*
** Generate code that will assemble an index key and put it on the top
** of the tack. The key with be for index pIdx which is an index on pTab.
** iCur is the index of a cursor open on the pTab table and pointing to
** the entry that needs indexing.
*/
void sqlite3GenerateIndexKey(
Vdbe *v, /* Generate code into this VDBE */
Index *pIdx, /* The index for which to generate a key */
int iCur /* Cursor number for the pIdx->pTable table */
){
int j;
Table *pTab = pIdx->pTable;
sqlite3VdbeAddOp(v, OP_Rowid, iCur, 0);
for(j=0; j<pIdx->nColumn; j++){
int idx = pIdx->aiColumn[j];
if( idx==pTab->iPKey ){
sqlite3VdbeAddOp(v, OP_Dup, j, 0);
}else{
sqlite3VdbeAddOp(v, OP_Column, iCur, idx);
sqlite3ColumnDefault(v, pTab, idx);
}
}
sqlite3VdbeAddOp(v, OP_MakeIdxRec, pIdx->nColumn, 0);
sqlite3IndexAffinityStr(v, pIdx);
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -12,7 +12,7 @@
** This is the implementation of generic hash-tables
** used in SQLite.
**
** $Id: hash.c,v 1.1.1.1 2004-03-11 22:22:23 alex Exp $
** $Id: hash.c,v 1.2 2006-04-13 12:44:29 guy Exp $
*/
#include "sqliteInt.h"
#include <assert.h>
@ -20,7 +20,7 @@
/* Turn bulk memory into a hash table object by initializing the
** fields of the Hash structure.
**
** "new" is a pointer to the hash table that is to be initialized.
** "pNew" is a pointer to the hash table that is to be initialized.
** keyClass is one of the constants SQLITE_HASH_INT, SQLITE_HASH_POINTER,
** SQLITE_HASH_BINARY, or SQLITE_HASH_STRING. The value of keyClass
** determines what kind of key the hash table will use. "copyKey" is
@ -29,42 +29,47 @@
** sense for SQLITE_HASH_STRING and SQLITE_HASH_BINARY and is ignored
** for other key classes.
*/
void sqliteHashInit(Hash *new, int keyClass, int copyKey){
assert( new!=0 );
assert( keyClass>=SQLITE_HASH_INT && keyClass<=SQLITE_HASH_BINARY );
new->keyClass = keyClass;
new->copyKey = copyKey &&
(keyClass==SQLITE_HASH_STRING || keyClass==SQLITE_HASH_BINARY);
new->first = 0;
new->count = 0;
new->htsize = 0;
new->ht = 0;
void sqlite3HashInit(Hash *pNew, int keyClass, int copyKey){
assert( pNew!=0 );
assert( keyClass>=SQLITE_HASH_STRING && keyClass<=SQLITE_HASH_BINARY );
pNew->keyClass = keyClass;
#if 0
if( keyClass==SQLITE_HASH_POINTER || keyClass==SQLITE_HASH_INT ) copyKey = 0;
#endif
pNew->copyKey = copyKey;
pNew->first = 0;
pNew->count = 0;
pNew->htsize = 0;
pNew->ht = 0;
pNew->xMalloc = sqlite3MallocX;
pNew->xFree = sqlite3FreeX;
}
/* Remove all entries from a hash table. Reclaim all memory.
** Call this routine to delete a hash table or to reset a hash table
** to the empty state.
*/
void sqliteHashClear(Hash *pH){
void sqlite3HashClear(Hash *pH){
HashElem *elem; /* For looping over all elements of the table */
assert( pH!=0 );
elem = pH->first;
pH->first = 0;
if( pH->ht ) sqliteFree(pH->ht);
if( pH->ht ) pH->xFree(pH->ht);
pH->ht = 0;
pH->htsize = 0;
while( elem ){
HashElem *next_elem = elem->next;
if( pH->copyKey && elem->pKey ){
sqliteFree(elem->pKey);
pH->xFree(elem->pKey);
}
sqliteFree(elem);
pH->xFree(elem);
elem = next_elem;
}
pH->count = 0;
}
#if 0 /* NOT USED */
/*
** Hash and comparison functions when the mode is SQLITE_HASH_INT
*/
@ -74,6 +79,7 @@ static int intHash(const void *pKey, int nKey){
static int intCompare(const void *pKey1, int n1, const void *pKey2, int n2){
return n2 - n1;
}
#endif
#if 0 /* NOT USED */
/*
@ -94,11 +100,18 @@ static int ptrCompare(const void *pKey1, int n1, const void *pKey2, int n2){
** Hash and comparison functions when the mode is SQLITE_HASH_STRING
*/
static int strHash(const void *pKey, int nKey){
return sqliteHashNoCase((const char*)pKey, nKey);
const char *z = (const char *)pKey;
int h = 0;
if( nKey<=0 ) nKey = strlen(z);
while( nKey > 0 ){
h = (h<<3) ^ h ^ sqlite3UpperToLower[(unsigned char)*z++];
nKey--;
}
return h & 0x7fffffff;
}
static int strCompare(const void *pKey1, int n1, const void *pKey2, int n2){
if( n1!=n2 ) return n2-n1;
return sqliteStrNICmp((const char*)pKey1,(const char*)pKey2,n1);
if( n1!=n2 ) return 1;
return sqlite3StrNICmp((const char*)pKey1,(const char*)pKey2,n1);
}
/*
@ -113,7 +126,7 @@ static int binHash(const void *pKey, int nKey){
return h & 0x7fffffff;
}
static int binCompare(const void *pKey1, int n1, const void *pKey2, int n2){
if( n1!=n2 ) return n2-n1;
if( n1!=n2 ) return 1;
return memcmp(pKey1,pKey2,n1);
}
@ -130,14 +143,23 @@ static int binCompare(const void *pKey1, int n1, const void *pKey2, int n2){
** with types "const void*" and "int" and returns an "int".
*/
static int (*hashFunction(int keyClass))(const void*,int){
#if 0 /* HASH_INT and HASH_POINTER are never used */
switch( keyClass ){
case SQLITE_HASH_INT: return &intHash;
/* case SQLITE_HASH_POINTER: return &ptrHash; // NOT USED */
case SQLITE_HASH_POINTER: return &ptrHash;
case SQLITE_HASH_STRING: return &strHash;
case SQLITE_HASH_BINARY: return &binHash;;
default: break;
}
return 0;
#else
if( keyClass==SQLITE_HASH_STRING ){
return &strHash;
}else{
assert( keyClass==SQLITE_HASH_BINARY );
return &binHash;
}
#endif
}
/*
@ -147,14 +169,48 @@ static int (*hashFunction(int keyClass))(const void*,int){
** see the header comment on the previous function.
*/
static int (*compareFunction(int keyClass))(const void*,int,const void*,int){
#if 0 /* HASH_INT and HASH_POINTER are never used */
switch( keyClass ){
case SQLITE_HASH_INT: return &intCompare;
/* case SQLITE_HASH_POINTER: return &ptrCompare; // NOT USED */
case SQLITE_HASH_POINTER: return &ptrCompare;
case SQLITE_HASH_STRING: return &strCompare;
case SQLITE_HASH_BINARY: return &binCompare;
default: break;
}
return 0;
#else
if( keyClass==SQLITE_HASH_STRING ){
return &strCompare;
}else{
assert( keyClass==SQLITE_HASH_BINARY );
return &binCompare;
}
#endif
}
/* Link an element into the hash table
*/
static void insertElement(
Hash *pH, /* The complete hash table */
struct _ht *pEntry, /* The entry into which pNew is inserted */
HashElem *pNew /* The element to be inserted */
){
HashElem *pHead; /* First element already in pEntry */
pHead = pEntry->chain;
if( pHead ){
pNew->next = pHead;
pNew->prev = pHead->prev;
if( pHead->prev ){ pHead->prev->next = pNew; }
else { pH->first = pNew; }
pHead->prev = pNew;
}else{
pNew->next = pH->first;
if( pH->first ){ pH->first->prev = pNew; }
pNew->prev = 0;
pH->first = pNew;
}
pEntry->count++;
pEntry->chain = pNew;
}
@ -165,34 +221,19 @@ static int (*compareFunction(int keyClass))(const void*,int,const void*,int){
static void rehash(Hash *pH, int new_size){
struct _ht *new_ht; /* The new hash table */
HashElem *elem, *next_elem; /* For looping over existing elements */
HashElem *x; /* Element being copied to new hash table */
int (*xHash)(const void*,int); /* The hash function */
assert( (new_size & (new_size-1))==0 );
new_ht = (struct _ht *)sqliteMalloc( new_size*sizeof(struct _ht) );
new_ht = (struct _ht *)pH->xMalloc( new_size*sizeof(struct _ht) );
if( new_ht==0 ) return;
if( pH->ht ) sqliteFree(pH->ht);
if( pH->ht ) pH->xFree(pH->ht);
pH->ht = new_ht;
pH->htsize = new_size;
xHash = hashFunction(pH->keyClass);
for(elem=pH->first, pH->first=0; elem; elem = next_elem){
int h = (*xHash)(elem->pKey, elem->nKey) & (new_size-1);
next_elem = elem->next;
x = new_ht[h].chain;
if( x ){
elem->next = x;
elem->prev = x->prev;
if( x->prev ) x->prev->next = elem;
else pH->first = elem;
x->prev = elem;
}else{
elem->next = pH->first;
if( pH->first ) pH->first->prev = elem;
elem->prev = 0;
pH->first = elem;
}
new_ht[h].chain = elem;
new_ht[h].count++;
insertElement(pH, &new_ht[h], elem);
}
}
@ -211,8 +252,9 @@ static HashElem *findElementGivenHash(
int (*xCompare)(const void*,int,const void*,int); /* comparison function */
if( pH->ht ){
elem = pH->ht[h].chain;
count = pH->ht[h].count;
struct _ht *pEntry = &pH->ht[h];
elem = pEntry->chain;
count = pEntry->count;
xCompare = compareFunction(pH->keyClass);
while( count-- && elem ){
if( (*xCompare)(elem->pKey,elem->nKey,pKey,nKey)==0 ){
@ -232,6 +274,7 @@ static void removeElementGivenHash(
HashElem* elem, /* The element to be removed from the pH */
int h /* Hash value for the element */
){
struct _ht *pEntry;
if( elem->prev ){
elem->prev->next = elem->next;
}else{
@ -240,25 +283,31 @@ static void removeElementGivenHash(
if( elem->next ){
elem->next->prev = elem->prev;
}
if( pH->ht[h].chain==elem ){
pH->ht[h].chain = elem->next;
pEntry = &pH->ht[h];
if( pEntry->chain==elem ){
pEntry->chain = elem->next;
}
pH->ht[h].count--;
if( pH->ht[h].count<=0 ){
pH->ht[h].chain = 0;
pEntry->count--;
if( pEntry->count<=0 ){
pEntry->chain = 0;
}
if( pH->copyKey && elem->pKey ){
sqliteFree(elem->pKey);
pH->xFree(elem->pKey);
}
sqliteFree( elem );
pH->xFree( elem );
pH->count--;
if( pH->count<=0 ){
assert( pH->first==0 );
assert( pH->count==0 );
sqlite3HashClear(pH);
}
}
/* Attempt to locate an element of the hash table pH with a key
** that matches pKey,nKey. Return the data for this element if it is
** found, or NULL if there is no match.
*/
void *sqliteHashFind(const Hash *pH, const void *pKey, int nKey){
void *sqlite3HashFind(const Hash *pH, const void *pKey, int nKey){
int h; /* A hash on key */
HashElem *elem; /* The element that matches key */
int (*xHash)(const void*,int); /* The hash function */
@ -287,7 +336,7 @@ void *sqliteHashFind(const Hash *pH, const void *pKey, int nKey){
** If the "data" parameter to this function is NULL, then the
** element corresponding to "key" is removed from the hash table.
*/
void *sqliteHashInsert(Hash *pH, const void *pKey, int nKey, void *data){
void *sqlite3HashInsert(Hash *pH, const void *pKey, int nKey, void *data){
int hraw; /* Raw hash value of the key */
int h; /* the hash of the key modulo hash table size */
HashElem *elem; /* Used to loop thru the element list */
@ -311,12 +360,12 @@ void *sqliteHashInsert(Hash *pH, const void *pKey, int nKey, void *data){
return old_data;
}
if( data==0 ) return 0;
new_elem = (HashElem*)sqliteMalloc( sizeof(HashElem) );
new_elem = (HashElem*)pH->xMalloc( sizeof(HashElem) );
if( new_elem==0 ) return data;
if( pH->copyKey && pKey!=0 ){
new_elem->pKey = sqliteMallocRaw( nKey );
new_elem->pKey = pH->xMalloc( nKey );
if( new_elem->pKey==0 ){
sqliteFree(new_elem);
pH->xFree(new_elem);
return data;
}
memcpy((void*)new_elem->pKey, pKey, nKey);
@ -325,32 +374,21 @@ void *sqliteHashInsert(Hash *pH, const void *pKey, int nKey, void *data){
}
new_elem->nKey = nKey;
pH->count++;
if( pH->htsize==0 ) rehash(pH,8);
if( pH->htsize==0 ){
pH->count = 0;
sqliteFree(new_elem);
return data;
rehash(pH,8);
if( pH->htsize==0 ){
pH->count = 0;
pH->xFree(new_elem);
return data;
}
}
if( pH->count > pH->htsize ){
rehash(pH,pH->htsize*2);
}
assert( pH->htsize>0 );
assert( (pH->htsize & (pH->htsize-1))==0 );
h = hraw & (pH->htsize-1);
elem = pH->ht[h].chain;
if( elem ){
new_elem->next = elem;
new_elem->prev = elem->prev;
if( elem->prev ){ elem->prev->next = new_elem; }
else { pH->first = new_elem; }
elem->prev = new_elem;
}else{
new_elem->next = pH->first;
new_elem->prev = 0;
if( pH->first ){ pH->first->prev = new_elem; }
pH->first = new_elem;
}
pH->ht[h].count++;
pH->ht[h].chain = new_elem;
insertElement(pH, &pH->ht[h], new_elem);
new_elem->data = data;
return 0;
}

View File

@ -12,7 +12,7 @@
** This is the header file for the generic hash-table implemenation
** used in SQLite.
**
** $Id: hash.h,v 1.1.1.1 2004-03-11 22:22:23 alex Exp $
** $Id: hash.h,v 1.2 2006-04-13 12:44:29 guy Exp $
*/
#ifndef _SQLITE_HASH_H_
#define _SQLITE_HASH_H_
@ -34,6 +34,8 @@ struct Hash {
char copyKey; /* True if copy of key made on insert */
int count; /* Number of entries in this table */
HashElem *first; /* The first element of the array */
void *(*xMalloc)(int); /* malloc() function to use */
void (*xFree)(void *); /* free() function to use */
int htsize; /* Number of buckets in the hash table */
struct _ht { /* the hash table */
int count; /* Number of entries with this hash */
@ -70,7 +72,7 @@ struct HashElem {
** A copy of the key is made for SQLITE_HASH_STRING and SQLITE_HASH_BINARY
** if the copyKey parameter to HashInit is 1.
*/
#define SQLITE_HASH_INT 1
/* #define SQLITE_HASH_INT 1 // NOT USED */
/* #define SQLITE_HASH_POINTER 2 // NOT USED */
#define SQLITE_HASH_STRING 3
#define SQLITE_HASH_BINARY 4
@ -78,10 +80,10 @@ struct HashElem {
/*
** Access routines. To delete, insert a NULL pointer.
*/
void sqliteHashInit(Hash*, int keytype, int copyKey);
void *sqliteHashInsert(Hash*, const void *pKey, int nKey, void *pData);
void *sqliteHashFind(const Hash*, const void *pKey, int nKey);
void sqliteHashClear(Hash*);
void sqlite3HashInit(Hash*, int keytype, int copyKey);
void *sqlite3HashInsert(Hash*, const void *pKey, int nKey, void *pData);
void *sqlite3HashFind(const Hash*, const void *pKey, int nKey);
void sqlite3HashClear(Hash*);
/*
** Macros for looping over all elements of a hash table. The idiom is

File diff suppressed because it is too large Load Diff

98
sqlite/keywordhash.h Executable file
View File

@ -0,0 +1,98 @@
/* Hash score: 159 */
static int keywordCode(const char *z, int n){
static const char zText[537] =
"ABORTABLEFTEMPORARYADDATABASELECTHENDEFAULTRANSACTIONATURALTER"
"AISEACHECKEYAFTEREFERENCESCAPELSEXCEPTRIGGEREGEXPLAINITIALLYANALYZE"
"XCLUSIVEXISTSTATEMENTANDEFERRABLEATTACHAVINGLOBEFOREIGNOREINDEX"
"AUTOINCREMENTBEGINNERENAMEBETWEENOTNULLIKEBYCASCADEFERREDELETE"
"CASECASTCOLLATECOLUMNCOMMITCONFLICTCONSTRAINTERSECTCREATECROSS"
"CURRENT_DATECURRENT_TIMESTAMPLANDESCDETACHDISTINCTDROPRAGMATCH"
"FAILIMITFROMFULLGROUPDATEIFIMMEDIATEINSERTINSTEADINTOFFSETISNULL"
"JOINORDEREPLACEOUTERESTRICTPRIMARYQUERYRIGHTROLLBACKROWHENUNION"
"UNIQUEUSINGVACUUMVALUESVIEWHERE";
static const unsigned char aHash[127] = {
92, 80, 107, 91, 0, 4, 0, 0, 114, 0, 83, 0, 0,
95, 44, 76, 93, 0, 106, 109, 97, 90, 0, 10, 0, 0,
113, 0, 110, 103, 0, 28, 48, 0, 41, 0, 0, 65, 71,
0, 63, 19, 0, 105, 36, 104, 0, 108, 74, 0, 0, 33,
0, 61, 37, 0, 8, 0, 115, 38, 12, 0, 77, 40, 25,
66, 0, 0, 31, 81, 53, 30, 50, 20, 88, 0, 34, 0,
75, 26, 0, 72, 0, 0, 0, 64, 47, 67, 22, 87, 29,
69, 86, 0, 1, 0, 9, 101, 58, 18, 0, 112, 82, 99,
54, 6, 85, 0, 0, 49, 94, 0, 102, 0, 70, 0, 0,
15, 0, 116, 51, 56, 0, 2, 55, 0, 111,
};
static const unsigned char aNext[116] = {
0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0,
0, 11, 0, 0, 0, 0, 5, 13, 0, 7, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 43, 0, 0, 0, 0, 0,
0, 0, 16, 0, 23, 52, 0, 0, 0, 0, 45, 0, 59,
0, 0, 0, 0, 0, 0, 0, 0, 73, 42, 0, 24, 60,
21, 0, 79, 0, 0, 68, 0, 0, 84, 46, 0, 0, 0,
0, 0, 0, 0, 0, 39, 96, 98, 0, 0, 100, 0, 32,
0, 14, 27, 78, 0, 57, 89, 0, 35, 0, 62, 0,
};
static const unsigned char aLen[116] = {
5, 5, 4, 4, 9, 2, 3, 8, 2, 6, 4, 3, 7,
11, 2, 7, 5, 5, 4, 5, 3, 5, 10, 6, 4, 6,
7, 6, 7, 9, 3, 7, 9, 6, 9, 3, 10, 6, 6,
4, 6, 3, 7, 6, 7, 5, 13, 2, 2, 5, 5, 6,
7, 3, 7, 4, 4, 2, 7, 3, 8, 6, 4, 4, 7,
6, 6, 8, 10, 9, 6, 5, 12, 12, 17, 4, 4, 6,
8, 2, 4, 6, 5, 4, 5, 4, 4, 5, 6, 2, 9,
6, 7, 4, 2, 6, 3, 6, 4, 5, 7, 5, 8, 7,
5, 5, 8, 3, 4, 5, 6, 5, 6, 6, 4, 5,
};
static const unsigned short int aOffset[116] = {
0, 4, 7, 10, 10, 14, 19, 21, 26, 27, 32, 34, 36,
42, 51, 52, 57, 61, 65, 67, 71, 74, 78, 86, 91, 94,
99, 105, 108, 113, 118, 122, 128, 136, 141, 150, 152, 162, 167,
172, 175, 177, 177, 181, 185, 187, 192, 194, 196, 205, 208, 212,
218, 224, 224, 227, 230, 234, 236, 237, 241, 248, 254, 258, 262,
269, 275, 281, 289, 296, 305, 311, 316, 328, 328, 344, 348, 352,
358, 359, 366, 369, 373, 378, 381, 386, 390, 394, 397, 403, 405,
414, 420, 427, 430, 430, 433, 436, 442, 446, 450, 457, 461, 469,
476, 481, 486, 494, 496, 500, 505, 511, 516, 522, 528, 531,
};
static const unsigned char aCode[116] = {
TK_ABORT, TK_TABLE, TK_JOIN_KW, TK_TEMP, TK_TEMP,
TK_OR, TK_ADD, TK_DATABASE, TK_AS, TK_SELECT,
TK_THEN, TK_END, TK_DEFAULT, TK_TRANSACTION,TK_ON,
TK_JOIN_KW, TK_ALTER, TK_RAISE, TK_EACH, TK_CHECK,
TK_KEY, TK_AFTER, TK_REFERENCES, TK_ESCAPE, TK_ELSE,
TK_EXCEPT, TK_TRIGGER, TK_LIKE_KW, TK_EXPLAIN, TK_INITIALLY,
TK_ALL, TK_ANALYZE, TK_EXCLUSIVE, TK_EXISTS, TK_STATEMENT,
TK_AND, TK_DEFERRABLE, TK_ATTACH, TK_HAVING, TK_LIKE_KW,
TK_BEFORE, TK_FOR, TK_FOREIGN, TK_IGNORE, TK_REINDEX,
TK_INDEX, TK_AUTOINCR, TK_TO, TK_IN, TK_BEGIN,
TK_JOIN_KW, TK_RENAME, TK_BETWEEN, TK_NOT, TK_NOTNULL,
TK_NULL, TK_LIKE_KW, TK_BY, TK_CASCADE, TK_ASC,
TK_DEFERRED, TK_DELETE, TK_CASE, TK_CAST, TK_COLLATE,
TK_COLUMNKW, TK_COMMIT, TK_CONFLICT, TK_CONSTRAINT, TK_INTERSECT,
TK_CREATE, TK_JOIN_KW, TK_CTIME_KW, TK_CTIME_KW, TK_CTIME_KW,
TK_PLAN, TK_DESC, TK_DETACH, TK_DISTINCT, TK_IS,
TK_DROP, TK_PRAGMA, TK_MATCH, TK_FAIL, TK_LIMIT,
TK_FROM, TK_JOIN_KW, TK_GROUP, TK_UPDATE, TK_IF,
TK_IMMEDIATE, TK_INSERT, TK_INSTEAD, TK_INTO, TK_OF,
TK_OFFSET, TK_SET, TK_ISNULL, TK_JOIN, TK_ORDER,
TK_REPLACE, TK_JOIN_KW, TK_RESTRICT, TK_PRIMARY, TK_QUERY,
TK_JOIN_KW, TK_ROLLBACK, TK_ROW, TK_WHEN, TK_UNION,
TK_UNIQUE, TK_USING, TK_VACUUM, TK_VALUES, TK_VIEW,
TK_WHERE,
};
int h, i;
if( n<2 ) return TK_ID;
h = ((charMap(z[0])*4) ^
(charMap(z[n-1])*3) ^
n) % 127;
for(i=((int)aHash[h])-1; i>=0; i=((int)aNext[i])-1){
if( aLen[i]==n && sqlite3StrNICmp(&zText[aOffset[i]],z,n)==0 ){
return aCode[i];
}
}
return TK_ID;
}
int sqlite3KeywordCode(const unsigned char *z, int n){
return keywordCode((char*)z, n);
}

135
sqlite/legacy.c Executable file
View File

@ -0,0 +1,135 @@
/*
** 2001 September 15
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
** Main file for the SQLite library. The routines in this file
** implement the programmer interface to the library. Routines in
** other files are for internal use by SQLite and should not be
** accessed by users of the library.
**
** $Id: legacy.c,v 1.1 2006-04-13 12:44:29 guy Exp $
*/
#include "sqliteInt.h"
#include "os.h"
#include <ctype.h>
/*
** 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);
assert( rc==SQLITE_OK || pStmt==0 );
if( rc!=SQLITE_OK ){
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 *) + 1);
if( azCols==0 ){
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);
rc = sqlite3ApiExit(0, rc);
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;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,138 +1,147 @@
/* Automatically generated file. Do not edit */
char *sqliteOpcodeNames[] = { "???",
"Goto",
"Gosub",
"Return",
"Halt",
"Integer",
"String",
"Variable",
"Pop",
"Dup",
"Pull",
"Push",
"ColumnName",
"Callback",
"Concat",
"Add",
"Subtract",
"Multiply",
"Divide",
"Remainder",
"Function",
"BitAnd",
"BitOr",
"ShiftLeft",
"ShiftRight",
"AddImm",
"ForceInt",
"MustBeInt",
"Eq",
"Ne",
"Lt",
"Le",
"Gt",
"Ge",
"StrEq",
"StrNe",
"StrLt",
"StrLe",
"StrGt",
"StrGe",
"And",
"Or",
"Negative",
"AbsValue",
"Not",
"BitNot",
"Noop",
"If",
"IfNot",
"IsNull",
"NotNull",
"MakeRecord",
"MakeIdxKey",
"MakeKey",
"IncrKey",
"Checkpoint",
"Transaction",
"Commit",
"Rollback",
"ReadCookie",
"SetCookie",
"VerifyCookie",
"OpenRead",
"OpenWrite",
"OpenTemp",
"OpenPseudo",
"Close",
"MoveLt",
"MoveTo",
"Distinct",
"NotFound",
"Found",
"IsUnique",
"NotExists",
"NewRecno",
"PutIntKey",
"PutStrKey",
"Delete",
"SetCounts",
"KeyAsData",
"RowKey",
"RowData",
"Column",
"Recno",
"FullKey",
"NullRow",
"Last",
"Rewind",
"Prev",
"Next",
"IdxPut",
"IdxDelete",
"IdxRecno",
"IdxLT",
"IdxGT",
"IdxGE",
"IdxIsNull",
"Destroy",
"Clear",
"CreateIndex",
"CreateTable",
"IntegrityCk",
"ListWrite",
"ListRewind",
"ListRead",
"ListReset",
"ListPush",
"ListPop",
"ContextPush",
"ContextPop",
"SortPut",
"SortMakeRec",
"SortMakeKey",
"Sort",
"SortNext",
"SortCallback",
"SortReset",
"FileOpen",
"FileRead",
"FileColumn",
"MemStore",
"MemLoad",
"MemIncr",
"AggReset",
"AggInit",
"AggFunc",
"AggFocus",
"AggSet",
"AggGet",
"AggNext",
"SetInsert",
"SetFound",
"SetNotFound",
"SetFirst",
"SetNext",
"Vacuum",
/* Automatically generated. Do not edit */
/* See the mkopcodec.awk script for details. */
#if !defined(SQLITE_OMIT_EXPLAIN) || !defined(NDEBUG) || defined(VDBE_PROFILE) || defined(SQLITE_DEBUG)
const char *const sqlite3OpcodeNames[] = { "?",
/* 1 */ "MemLoad",
/* 2 */ "Column",
/* 3 */ "SetCookie",
/* 4 */ "IfMemPos",
/* 5 */ "Sequence",
/* 6 */ "MoveGt",
/* 7 */ "RowKey",
/* 8 */ "OpenWrite",
/* 9 */ "If",
/* 10 */ "Pop",
/* 11 */ "CollSeq",
/* 12 */ "OpenRead",
/* 13 */ "Expire",
/* 14 */ "AutoCommit",
/* 15 */ "IntegrityCk",
/* 16 */ "Not",
/* 17 */ "Sort",
/* 18 */ "Function",
/* 19 */ "Noop",
/* 20 */ "Return",
/* 21 */ "NewRowid",
/* 22 */ "IfMemNeg",
/* 23 */ "Variable",
/* 24 */ "String",
/* 25 */ "RealAffinity",
/* 26 */ "ParseSchema",
/* 27 */ "Close",
/* 28 */ "CreateIndex",
/* 29 */ "IsUnique",
/* 30 */ "IdxIsNull",
/* 31 */ "NotFound",
/* 32 */ "Int64",
/* 33 */ "MustBeInt",
/* 34 */ "Halt",
/* 35 */ "Rowid",
/* 36 */ "IdxLT",
/* 37 */ "AddImm",
/* 38 */ "Statement",
/* 39 */ "RowData",
/* 40 */ "MemMax",
/* 41 */ "Push",
/* 42 */ "NotExists",
/* 43 */ "MemIncr",
/* 44 */ "Gosub",
/* 45 */ "Integer",
/* 46 */ "MemInt",
/* 47 */ "Prev",
/* 48 */ "CreateTable",
/* 49 */ "Last",
/* 50 */ "IdxRowid",
/* 51 */ "MakeIdxRec",
/* 52 */ "ResetCount",
/* 53 */ "FifoWrite",
/* 54 */ "Callback",
/* 55 */ "ContextPush",
/* 56 */ "DropTrigger",
/* 57 */ "DropIndex",
/* 58 */ "IdxGE",
/* 59 */ "Or",
/* 60 */ "And",
/* 61 */ "IdxDelete",
/* 62 */ "Vacuum",
/* 63 */ "MoveLe",
/* 64 */ "IsNull",
/* 65 */ "NotNull",
/* 66 */ "Ne",
/* 67 */ "Eq",
/* 68 */ "Gt",
/* 69 */ "Le",
/* 70 */ "Lt",
/* 71 */ "Ge",
/* 72 */ "IfNot",
/* 73 */ "BitAnd",
/* 74 */ "BitOr",
/* 75 */ "ShiftLeft",
/* 76 */ "ShiftRight",
/* 77 */ "Add",
/* 78 */ "Subtract",
/* 79 */ "Multiply",
/* 80 */ "Divide",
/* 81 */ "Remainder",
/* 82 */ "Concat",
/* 83 */ "Negative",
/* 84 */ "DropTable",
/* 85 */ "BitNot",
/* 86 */ "String8",
/* 87 */ "MakeRecord",
/* 88 */ "Delete",
/* 89 */ "AggFinal",
/* 90 */ "Dup",
/* 91 */ "Goto",
/* 92 */ "TableLock",
/* 93 */ "FifoRead",
/* 94 */ "Clear",
/* 95 */ "IdxGT",
/* 96 */ "MoveLt",
/* 97 */ "VerifyCookie",
/* 98 */ "AggStep",
/* 99 */ "Pull",
/* 100 */ "SetNumColumns",
/* 101 */ "AbsValue",
/* 102 */ "Transaction",
/* 103 */ "ContextPop",
/* 104 */ "Next",
/* 105 */ "IdxInsert",
/* 106 */ "Distinct",
/* 107 */ "Insert",
/* 108 */ "Destroy",
/* 109 */ "ReadCookie",
/* 110 */ "ForceInt",
/* 111 */ "LoadAnalysis",
/* 112 */ "OpenVirtual",
/* 113 */ "Explain",
/* 114 */ "IfMemZero",
/* 115 */ "OpenPseudo",
/* 116 */ "Null",
/* 117 */ "Blob",
/* 118 */ "MemStore",
/* 119 */ "Rewind",
/* 120 */ "MoveGe",
/* 121 */ "MemMove",
/* 122 */ "MemNull",
/* 123 */ "Found",
/* 124 */ "Real",
/* 125 */ "HexBlob",
/* 126 */ "NullRow",
/* 127 */ "NotUsed_127",
/* 128 */ "NotUsed_128",
/* 129 */ "NotUsed_129",
/* 130 */ "NotUsed_130",
/* 131 */ "NotUsed_131",
/* 132 */ "NotUsed_132",
/* 133 */ "NotUsed_133",
/* 134 */ "NotUsed_134",
/* 135 */ "NotUsed_135",
/* 136 */ "NotUsed_136",
/* 137 */ "ToText",
/* 138 */ "ToBlob",
/* 139 */ "ToNumeric",
/* 140 */ "ToInt",
/* 141 */ "ToReal",
};
#endif

View File

@ -1,136 +1,159 @@
/* Automatically generated file. Do not edit */
#define OP_Goto 1
#define OP_Gosub 2
#define OP_Return 3
#define OP_Halt 4
#define OP_Integer 5
#define OP_String 6
#define OP_Variable 7
#define OP_Pop 8
#define OP_Dup 9
#define OP_Pull 10
#define OP_Push 11
#define OP_ColumnName 12
#define OP_Callback 13
#define OP_Concat 14
#define OP_Add 15
#define OP_Subtract 16
#define OP_Multiply 17
#define OP_Divide 18
#define OP_Remainder 19
#define OP_Function 20
#define OP_BitAnd 21
#define OP_BitOr 22
#define OP_ShiftLeft 23
#define OP_ShiftRight 24
#define OP_AddImm 25
#define OP_ForceInt 26
#define OP_MustBeInt 27
#define OP_Eq 28
#define OP_Ne 29
#define OP_Lt 30
#define OP_Le 31
#define OP_Gt 32
#define OP_Ge 33
#define OP_StrEq 34
#define OP_StrNe 35
#define OP_StrLt 36
#define OP_StrLe 37
#define OP_StrGt 38
#define OP_StrGe 39
#define OP_And 40
#define OP_Or 41
#define OP_Negative 42
#define OP_AbsValue 43
#define OP_Not 44
#define OP_BitNot 45
#define OP_Noop 46
#define OP_If 47
#define OP_IfNot 48
#define OP_IsNull 49
#define OP_NotNull 50
#define OP_MakeRecord 51
#define OP_MakeIdxKey 52
#define OP_MakeKey 53
#define OP_IncrKey 54
#define OP_Checkpoint 55
#define OP_Transaction 56
#define OP_Commit 57
#define OP_Rollback 58
#define OP_ReadCookie 59
#define OP_SetCookie 60
#define OP_VerifyCookie 61
#define OP_OpenRead 62
#define OP_OpenWrite 63
#define OP_OpenTemp 64
#define OP_OpenPseudo 65
#define OP_Close 66
#define OP_MoveLt 67
#define OP_MoveTo 68
#define OP_Distinct 69
#define OP_NotFound 70
#define OP_Found 71
#define OP_IsUnique 72
#define OP_NotExists 73
#define OP_NewRecno 74
#define OP_PutIntKey 75
#define OP_PutStrKey 76
#define OP_Delete 77
#define OP_SetCounts 78
#define OP_KeyAsData 79
#define OP_RowKey 80
#define OP_RowData 81
#define OP_Column 82
#define OP_Recno 83
#define OP_FullKey 84
#define OP_NullRow 85
#define OP_Last 86
#define OP_Rewind 87
#define OP_Prev 88
#define OP_Next 89
#define OP_IdxPut 90
#define OP_IdxDelete 91
#define OP_IdxRecno 92
#define OP_IdxLT 93
#define OP_IdxGT 94
#define OP_IdxGE 95
#define OP_IdxIsNull 96
#define OP_Destroy 97
#define OP_Clear 98
#define OP_CreateIndex 99
#define OP_CreateTable 100
#define OP_IntegrityCk 101
#define OP_ListWrite 102
#define OP_ListRewind 103
#define OP_ListRead 104
#define OP_ListReset 105
#define OP_ListPush 106
#define OP_ListPop 107
#define OP_ContextPush 108
#define OP_ContextPop 109
#define OP_SortPut 110
#define OP_SortMakeRec 111
#define OP_SortMakeKey 112
#define OP_Sort 113
#define OP_SortNext 114
#define OP_SortCallback 115
#define OP_SortReset 116
#define OP_FileOpen 117
#define OP_FileRead 118
#define OP_FileColumn 119
#define OP_MemStore 120
#define OP_MemLoad 121
#define OP_MemIncr 122
#define OP_AggReset 123
#define OP_AggInit 124
#define OP_AggFunc 125
#define OP_AggFocus 126
#define OP_AggSet 127
#define OP_AggGet 128
#define OP_AggNext 129
#define OP_SetInsert 130
#define OP_SetFound 131
#define OP_SetNotFound 132
#define OP_SetFirst 133
#define OP_SetNext 134
#define OP_Vacuum 135
/* Automatically generated. Do not edit */
/* See the mkopcodeh.awk script for details */
#define OP_MemLoad 1
#define OP_HexBlob 125 /* same as TK_BLOB */
#define OP_Column 2
#define OP_SetCookie 3
#define OP_IfMemPos 4
#define OP_Real 124 /* same as TK_FLOAT */
#define OP_Sequence 5
#define OP_MoveGt 6
#define OP_Ge 71 /* same as TK_GE */
#define OP_RowKey 7
#define OP_Eq 67 /* same as TK_EQ */
#define OP_OpenWrite 8
#define OP_NotNull 65 /* same as TK_NOTNULL */
#define OP_If 9
#define OP_ToInt 140 /* same as TK_TO_INT */
#define OP_String8 86 /* same as TK_STRING */
#define OP_Pop 10
#define OP_CollSeq 11
#define OP_OpenRead 12
#define OP_Expire 13
#define OP_AutoCommit 14
#define OP_Gt 68 /* same as TK_GT */
#define OP_IntegrityCk 15
#define OP_Sort 17
#define OP_Function 18
#define OP_And 60 /* same as TK_AND */
#define OP_Subtract 78 /* same as TK_MINUS */
#define OP_Noop 19
#define OP_Return 20
#define OP_Remainder 81 /* same as TK_REM */
#define OP_NewRowid 21
#define OP_Multiply 79 /* same as TK_STAR */
#define OP_IfMemNeg 22
#define OP_Variable 23
#define OP_String 24
#define OP_RealAffinity 25
#define OP_ParseSchema 26
#define OP_Close 27
#define OP_CreateIndex 28
#define OP_IsUnique 29
#define OP_IdxIsNull 30
#define OP_NotFound 31
#define OP_Int64 32
#define OP_MustBeInt 33
#define OP_Halt 34
#define OP_Rowid 35
#define OP_IdxLT 36
#define OP_AddImm 37
#define OP_Statement 38
#define OP_RowData 39
#define OP_MemMax 40
#define OP_Push 41
#define OP_Or 59 /* same as TK_OR */
#define OP_NotExists 42
#define OP_MemIncr 43
#define OP_Gosub 44
#define OP_Divide 80 /* same as TK_SLASH */
#define OP_Integer 45
#define OP_ToNumeric 139 /* same as TK_TO_NUMERIC*/
#define OP_MemInt 46
#define OP_Prev 47
#define OP_Concat 82 /* same as TK_CONCAT */
#define OP_BitAnd 73 /* same as TK_BITAND */
#define OP_CreateTable 48
#define OP_Last 49
#define OP_IsNull 64 /* same as TK_ISNULL */
#define OP_IdxRowid 50
#define OP_MakeIdxRec 51
#define OP_ShiftRight 76 /* same as TK_RSHIFT */
#define OP_ResetCount 52
#define OP_FifoWrite 53
#define OP_Callback 54
#define OP_ContextPush 55
#define OP_DropTrigger 56
#define OP_DropIndex 57
#define OP_IdxGE 58
#define OP_IdxDelete 61
#define OP_Vacuum 62
#define OP_MoveLe 63
#define OP_IfNot 72
#define OP_DropTable 84
#define OP_MakeRecord 87
#define OP_ToBlob 138 /* same as TK_TO_BLOB */
#define OP_Delete 88
#define OP_AggFinal 89
#define OP_ShiftLeft 75 /* same as TK_LSHIFT */
#define OP_Dup 90
#define OP_Goto 91
#define OP_TableLock 92
#define OP_FifoRead 93
#define OP_Clear 94
#define OP_IdxGT 95
#define OP_MoveLt 96
#define OP_Le 69 /* same as TK_LE */
#define OP_VerifyCookie 97
#define OP_AggStep 98
#define OP_Pull 99
#define OP_ToText 137 /* same as TK_TO_TEXT */
#define OP_Not 16 /* same as TK_NOT */
#define OP_ToReal 141 /* same as TK_TO_REAL */
#define OP_SetNumColumns 100
#define OP_AbsValue 101
#define OP_Transaction 102
#define OP_Negative 83 /* same as TK_UMINUS */
#define OP_Ne 66 /* same as TK_NE */
#define OP_ContextPop 103
#define OP_BitOr 74 /* same as TK_BITOR */
#define OP_Next 104
#define OP_IdxInsert 105
#define OP_Distinct 106
#define OP_Lt 70 /* same as TK_LT */
#define OP_Insert 107
#define OP_Destroy 108
#define OP_ReadCookie 109
#define OP_ForceInt 110
#define OP_LoadAnalysis 111
#define OP_OpenVirtual 112
#define OP_Explain 113
#define OP_IfMemZero 114
#define OP_OpenPseudo 115
#define OP_Null 116
#define OP_Blob 117
#define OP_Add 77 /* same as TK_PLUS */
#define OP_MemStore 118
#define OP_Rewind 119
#define OP_MoveGe 120
#define OP_BitNot 85 /* same as TK_BITNOT */
#define OP_MemMove 121
#define OP_MemNull 122
#define OP_Found 123
#define OP_NullRow 126
/* The following opcode values are never used */
#define OP_NotUsed_127 127
#define OP_NotUsed_128 128
#define OP_NotUsed_129 129
#define OP_NotUsed_130 130
#define OP_NotUsed_131 131
#define OP_NotUsed_132 132
#define OP_NotUsed_133 133
#define OP_NotUsed_134 134
#define OP_NotUsed_135 135
#define OP_NotUsed_136 136
/* Opcodes that are guaranteed to never push a value onto the stack
** contain a 1 their corresponding position of the following mask
** set. See the opcodeNoPush() function in vdbeaux.c */
#define NOPUSH_MASK_0 0x7f58
#define NOPUSH_MASK_1 0xee5b
#define NOPUSH_MASK_2 0x9f76
#define NOPUSH_MASK_3 0xfff2
#define NOPUSH_MASK_4 0xffff
#define NOPUSH_MASK_5 0xdb3b
#define NOPUSH_MASK_6 0xcfdf
#define NOPUSH_MASK_7 0x49cd
#define NOPUSH_MASK_8 0x3e00
#define NOPUSH_MASK_9 0x0000

File diff suppressed because it is too large Load Diff

View File

@ -18,31 +18,44 @@
#define _SQLITE_OS_H_
/*
** Helpful hint: To get this to compile on HP/UX, add -D_INCLUDE_POSIX_SOURCE
** to the compiler command line.
** Figure out if we are dealing with Unix, Windows, or some other
** operating system.
*/
#if !defined(OS_UNIX) && !defined(OS_OTHER)
# define OS_OTHER 0
# ifndef OS_WIN
# if defined(_WIN32) || defined(WIN32) || defined(__CYGWIN__) || defined(__MINGW32__) || defined(__BORLANDC__)
# define OS_WIN 1
# define OS_UNIX 0
# else
# define OS_WIN 0
# define OS_UNIX 1
# endif
# else
# define OS_UNIX 0
# endif
#else
# ifndef OS_WIN
# define OS_WIN 0
# endif
#endif
/*
** These #defines should enable >2GB file support on Posix if the
** underlying operating system supports it. If the OS lacks
** large file support, or if the OS is windows, these should be no-ops.
**
** Large file support can be disabled using the -DSQLITE_DISABLE_LFS switch
** on the compiler command line. This is necessary if you are compiling
** on a recent machine (ex: RedHat 7.2) but you want your code to work
** on an older machine (ex: RedHat 6.0). If you compile on RedHat 7.2
** without this option, LFS is enable. But LFS does not exist in the kernel
** in RedHat 6.0, so the code won't work. Hence, for maximum binary
** portability you should omit LFS.
**
** Similar is true for MacOS. LFS is only supported on MacOS 9 and later.
** Define the maximum size of a temporary filename
*/
#ifndef SQLITE_DISABLE_LFS
# define _LARGE_FILE 1
# ifndef _FILE_OFFSET_BITS
# define _FILE_OFFSET_BITS 64
# endif
# define _LARGEFILE_SOURCE 1
#if OS_WIN
# include <windows.h>
# define SQLITE_TEMPNAME_SIZE (MAX_PATH+50)
#else
# define SQLITE_TEMPNAME_SIZE 200
#endif
/* If the SET_FULLSYNC macro is not defined above, then make it
** a no-op
*/
#ifndef SET_FULLSYNC
# define SET_FULLSYNC(x,y)
#endif
/*
@ -59,133 +72,369 @@
#endif
/*
** Figure out if we are dealing with Unix, Windows or MacOS.
**
** N.B. MacOS means Mac Classic (or Carbon). Treat Darwin (OS X) as Unix.
** The MacOS build is designed to use CodeWarrior (tested with v8)
** Define the interfaces for Unix and for Windows.
*/
#ifndef OS_UNIX
# ifndef OS_WIN
# ifndef OS_MAC
# if defined(__MACOS__)
# define OS_MAC 1
# define OS_WIN 0
# define OS_UNIX 0
# elif defined(_WIN32) || defined(WIN32) || defined(__CYGWIN__) || defined(__MINGW32__) || defined(__BORLANDC__)
# define OS_MAC 0
# define OS_WIN 1
# define OS_UNIX 0
# else
# define OS_MAC 0
# define OS_WIN 0
# define OS_UNIX 1
# endif
# else
# define OS_WIN 0
# define OS_UNIX 0
# endif
# else
# define OS_MAC 0
# define OS_UNIX 0
# endif
#else
# define OS_MAC 0
# ifndef OS_WIN
# define OS_WIN 0
# endif
#if OS_UNIX
#define sqlite3OsOpenReadWrite sqlite3UnixOpenReadWrite
#define sqlite3OsOpenExclusive sqlite3UnixOpenExclusive
#define sqlite3OsOpenReadOnly sqlite3UnixOpenReadOnly
#define sqlite3OsDelete sqlite3UnixDelete
#define sqlite3OsFileExists sqlite3UnixFileExists
#define sqlite3OsFullPathname sqlite3UnixFullPathname
#define sqlite3OsIsDirWritable sqlite3UnixIsDirWritable
#define sqlite3OsSyncDirectory sqlite3UnixSyncDirectory
#define sqlite3OsTempFileName sqlite3UnixTempFileName
#define sqlite3OsRandomSeed sqlite3UnixRandomSeed
#define sqlite3OsSleep sqlite3UnixSleep
#define sqlite3OsCurrentTime sqlite3UnixCurrentTime
#define sqlite3OsEnterMutex sqlite3UnixEnterMutex
#define sqlite3OsLeaveMutex sqlite3UnixLeaveMutex
#define sqlite3OsInMutex sqlite3UnixInMutex
#define sqlite3OsThreadSpecificData sqlite3UnixThreadSpecificData
#define sqlite3OsMalloc sqlite3GenericMalloc
#define sqlite3OsRealloc sqlite3GenericRealloc
#define sqlite3OsFree sqlite3GenericFree
#define sqlite3OsAllocationSize sqlite3GenericAllocationSize
#endif
#if OS_WIN
#define sqlite3OsOpenReadWrite sqlite3WinOpenReadWrite
#define sqlite3OsOpenExclusive sqlite3WinOpenExclusive
#define sqlite3OsOpenReadOnly sqlite3WinOpenReadOnly
#define sqlite3OsDelete sqlite3WinDelete
#define sqlite3OsFileExists sqlite3WinFileExists
#define sqlite3OsFullPathname sqlite3WinFullPathname
#define sqlite3OsIsDirWritable sqlite3WinIsDirWritable
#define sqlite3OsSyncDirectory sqlite3WinSyncDirectory
#define sqlite3OsTempFileName sqlite3WinTempFileName
#define sqlite3OsRandomSeed sqlite3WinRandomSeed
#define sqlite3OsSleep sqlite3WinSleep
#define sqlite3OsCurrentTime sqlite3WinCurrentTime
#define sqlite3OsEnterMutex sqlite3WinEnterMutex
#define sqlite3OsLeaveMutex sqlite3WinLeaveMutex
#define sqlite3OsInMutex sqlite3WinInMutex
#define sqlite3OsThreadSpecificData sqlite3WinThreadSpecificData
#define sqlite3OsMalloc sqlite3GenericMalloc
#define sqlite3OsRealloc sqlite3GenericRealloc
#define sqlite3OsFree sqlite3GenericFree
#define sqlite3OsAllocationSize sqlite3GenericAllocationSize
#endif
/*
** A handle for an open file is stored in an OsFile object.
** If using an alternative OS interface, then we must have an "os_other.h"
** header file available for that interface. Presumably the "os_other.h"
** header file contains #defines similar to those above.
*/
#if OS_UNIX
# include <sys/types.h>
# include <sys/stat.h>
# include <fcntl.h>
# include <unistd.h>
typedef struct OsFile OsFile;
struct OsFile {
struct openCnt *pOpen; /* Info about all open fd's on this inode */
struct lockInfo *pLock; /* Info about locks on this inode */
int fd; /* The file descriptor */
int locked; /* True if this instance holds the lock */
int dirfd; /* File descriptor for the directory */
};
# define SQLITE_TEMPNAME_SIZE 200
# if defined(HAVE_USLEEP) && HAVE_USLEEP
# define SQLITE_MIN_SLEEP_MS 1
# else
# define SQLITE_MIN_SLEEP_MS 1000
# endif
#if OS_OTHER
# include "os_other.h"
#endif
#if OS_WIN
#include <windows.h>
#include <winbase.h>
typedef struct OsFile OsFile;
struct OsFile {
HANDLE h; /* Handle for accessing the file */
int locked; /* 0: unlocked, <0: write lock, >0: read lock */
};
# if defined(_MSC_VER) || defined(__BORLANDC__)
typedef __int64 off_t;
# else
# if !defined(_CYGWIN_TYPES_H)
typedef long long off_t;
# if defined(__MINGW32__)
# define _OFF_T_
# endif
# endif
# endif
# define SQLITE_TEMPNAME_SIZE (MAX_PATH+50)
# define SQLITE_MIN_SLEEP_MS 1
/*
** Forward declarations
*/
typedef struct OsFile OsFile;
typedef struct IoMethod IoMethod;
/*
** An instance of the following structure contains pointers to all
** methods on an OsFile object.
*/
struct IoMethod {
int (*xClose)(OsFile**);
int (*xOpenDirectory)(OsFile*, const char*);
int (*xRead)(OsFile*, void*, int amt);
int (*xWrite)(OsFile*, const void*, int amt);
int (*xSeek)(OsFile*, i64 offset);
int (*xTruncate)(OsFile*, i64 size);
int (*xSync)(OsFile*, int);
void (*xSetFullSync)(OsFile *id, int setting);
int (*xFileHandle)(OsFile *id);
int (*xFileSize)(OsFile*, i64 *pSize);
int (*xLock)(OsFile*, int);
int (*xUnlock)(OsFile*, int);
int (*xLockState)(OsFile *id);
int (*xCheckReservedLock)(OsFile *id);
};
/*
** The OsFile object describes an open disk file in an OS-dependent way.
** The version of OsFile defined here is a generic version. Each OS
** implementation defines its own subclass of this structure that contains
** additional information needed to handle file I/O. But the pMethod
** entry (pointing to the virtual function table) always occurs first
** so that we can always find the appropriate methods.
*/
struct OsFile {
IoMethod const *pMethod;
};
/*
** The following values may be passed as the second argument to
** sqlite3OsLock(). The various locks exhibit the following semantics:
**
** SHARED: Any number of processes may hold a SHARED lock simultaneously.
** RESERVED: A single process may hold a RESERVED lock on a file at
** any time. Other processes may hold and obtain new SHARED locks.
** PENDING: A single process may hold a PENDING lock on a file at
** any one time. Existing SHARED locks may persist, but no new
** SHARED locks may be obtained by other processes.
** EXCLUSIVE: An EXCLUSIVE lock precludes all other locks.
**
** PENDING_LOCK may not be passed directly to sqlite3OsLock(). Instead, a
** process that requests an EXCLUSIVE lock may actually obtain a PENDING
** lock. This can be upgraded to an EXCLUSIVE lock by a subsequent call to
** sqlite3OsLock().
*/
#define NO_LOCK 0
#define SHARED_LOCK 1
#define RESERVED_LOCK 2
#define PENDING_LOCK 3
#define EXCLUSIVE_LOCK 4
/*
** File Locking Notes: (Mostly about windows but also some info for Unix)
**
** We cannot use LockFileEx() or UnlockFileEx() on Win95/98/ME because
** those functions are not available. So we use only LockFile() and
** UnlockFile().
**
** LockFile() prevents not just writing but also reading by other processes.
** A SHARED_LOCK is obtained by locking a single randomly-chosen
** byte out of a specific range of bytes. The lock byte is obtained at
** random so two separate readers can probably access the file at the
** same time, unless they are unlucky and choose the same lock byte.
** An EXCLUSIVE_LOCK is obtained by locking all bytes in the range.
** There can only be one writer. A RESERVED_LOCK is obtained by locking
** a single byte of the file that is designated as the reserved lock byte.
** A PENDING_LOCK is obtained by locking a designated byte different from
** the RESERVED_LOCK byte.
**
** On WinNT/2K/XP systems, LockFileEx() and UnlockFileEx() are available,
** which means we can use reader/writer locks. When reader/writer locks
** are used, the lock is placed on the same range of bytes that is used
** for probabilistic locking in Win95/98/ME. Hence, the locking scheme
** will support two or more Win95 readers or two or more WinNT readers.
** But a single Win95 reader will lock out all WinNT readers and a single
** WinNT reader will lock out all other Win95 readers.
**
** The following #defines specify the range of bytes used for locking.
** SHARED_SIZE is the number of bytes available in the pool from which
** a random byte is selected for a shared lock. The pool of bytes for
** shared locks begins at SHARED_FIRST.
**
** These #defines are available in sqlite_aux.h so that adaptors for
** connecting SQLite to other operating systems can use the same byte
** ranges for locking. In particular, the same locking strategy and
** byte ranges are used for Unix. This leaves open the possiblity of having
** clients on win95, winNT, and unix all talking to the same shared file
** and all locking correctly. To do so would require that samba (or whatever
** tool is being used for file sharing) implements locks correctly between
** windows and unix. I'm guessing that isn't likely to happen, but by
** using the same locking range we are at least open to the possibility.
**
** Locking in windows is manditory. For this reason, we cannot store
** actual data in the bytes used for locking. The pager never allocates
** the pages involved in locking therefore. SHARED_SIZE is selected so
** that all locks will fit on a single page even at the minimum page size.
** PENDING_BYTE defines the beginning of the locks. By default PENDING_BYTE
** is set high so that we don't have to allocate an unused page except
** for very large databases. But one should test the page skipping logic
** by setting PENDING_BYTE low and running the entire regression suite.
**
** Changing the value of PENDING_BYTE results in a subtly incompatible
** file format. Depending on how it is changed, you might not notice
** the incompatibility right away, even running a full regression test.
** The default location of PENDING_BYTE is the first byte past the
** 1GB boundary.
**
*/
#ifndef SQLITE_TEST
#define PENDING_BYTE 0x40000000 /* First byte past the 1GB boundary */
#else
extern unsigned int sqlite3_pending_byte;
#define PENDING_BYTE sqlite3_pending_byte
#endif
#if OS_MAC
# include <unistd.h>
# include <Files.h>
typedef struct OsFile OsFile;
struct OsFile {
SInt16 refNum; /* Data fork/file reference number */
SInt16 refNumRF; /* Resource fork reference number (for locking) */
int locked; /* 0: unlocked, <0: write lock, >0: read lock */
int delOnClose; /* True if file is to be deleted on close */
char *pathToDel; /* Name of file to delete on close */
};
# ifdef _LARGE_FILE
typedef SInt64 off_t;
# else
typedef SInt32 off_t;
# endif
# define SQLITE_TEMPNAME_SIZE _MAX_PATH
# define SQLITE_MIN_SLEEP_MS 17
#define RESERVED_BYTE (PENDING_BYTE+1)
#define SHARED_FIRST (PENDING_BYTE+2)
#define SHARED_SIZE 510
/*
** Prototypes for operating system interface routines.
*/
int sqlite3OsClose(OsFile**);
int sqlite3OsOpenDirectory(OsFile*, const char*);
int sqlite3OsRead(OsFile*, void*, int amt);
int sqlite3OsWrite(OsFile*, const void*, int amt);
int sqlite3OsSeek(OsFile*, i64 offset);
int sqlite3OsTruncate(OsFile*, i64 size);
int sqlite3OsSync(OsFile*, int);
void sqlite3OsSetFullSync(OsFile *id, int setting);
int sqlite3OsFileHandle(OsFile *id);
int sqlite3OsFileSize(OsFile*, i64 *pSize);
int sqlite3OsLock(OsFile*, int);
int sqlite3OsUnlock(OsFile*, int);
int sqlite3OsLockState(OsFile *id);
int sqlite3OsCheckReservedLock(OsFile *id);
int sqlite3OsOpenReadWrite(const char*, OsFile**, int*);
int sqlite3OsOpenExclusive(const char*, OsFile**, int);
int sqlite3OsOpenReadOnly(const char*, OsFile**);
int sqlite3OsDelete(const char*);
int sqlite3OsFileExists(const char*);
char *sqlite3OsFullPathname(const char*);
int sqlite3OsIsDirWritable(char*);
int sqlite3OsSyncDirectory(const char*);
int sqlite3OsTempFileName(char*);
int sqlite3OsRandomSeed(char*);
int sqlite3OsSleep(int ms);
int sqlite3OsCurrentTime(double*);
void sqlite3OsEnterMutex(void);
void sqlite3OsLeaveMutex(void);
int sqlite3OsInMutex(int);
ThreadData *sqlite3OsThreadSpecificData(int);
void *sqlite3OsMalloc(int);
void *sqlite3OsRealloc(void *, int);
void sqlite3OsFree(void *);
int sqlite3OsAllocationSize(void *);
/*
** If the SQLITE_ENABLE_REDEF_IO macro is defined, then the OS-layer
** interface routines are not called directly but are invoked using
** pointers to functions. This allows the implementation of various
** OS-layer interface routines to be modified at run-time. There are
** obscure but legitimate reasons for wanting to do this. But for
** most users, a direct call to the underlying interface is preferable
** so the the redefinable I/O interface is turned off by default.
*/
#ifdef SQLITE_ENABLE_REDEF_IO
/*
** When redefinable I/O is enabled, a single global instance of the
** following structure holds pointers to the routines that SQLite
** uses to talk with the underlying operating system. Modify this
** structure (before using any SQLite API!) to accomodate perculiar
** operating system interfaces or behaviors.
*/
struct sqlite3OsVtbl {
int (*xOpenReadWrite)(const char*, OsFile**, int*);
int (*xOpenExclusive)(const char*, OsFile**, int);
int (*xOpenReadOnly)(const char*, OsFile**);
int (*xDelete)(const char*);
int (*xFileExists)(const char*);
char *(*xFullPathname)(const char*);
int (*xIsDirWritable)(char*);
int (*xSyncDirectory)(const char*);
int (*xTempFileName)(char*);
int (*xRandomSeed)(char*);
int (*xSleep)(int ms);
int (*xCurrentTime)(double*);
void (*xEnterMutex)(void);
void (*xLeaveMutex)(void);
int (*xInMutex)(int);
ThreadData *(*xThreadSpecificData)(int);
void *(*xMalloc)(int);
void *(*xRealloc)(void *, int);
void (*xFree)(void *);
int (*xAllocationSize)(void *);
};
/* Macro used to comment out routines that do not exists when there is
** no disk I/O
*/
#ifdef SQLITE_OMIT_DISKIO
# define IF_DISKIO(X) 0
#else
# define IF_DISKIO(X) X
#endif
int sqliteOsDelete(const char*);
int sqliteOsFileExists(const char*);
int sqliteOsFileRename(const char*, const char*);
int sqliteOsOpenReadWrite(const char*, OsFile*, int*);
int sqliteOsOpenExclusive(const char*, OsFile*, int);
int sqliteOsOpenReadOnly(const char*, OsFile*);
int sqliteOsOpenDirectory(const char*, OsFile*);
int sqliteOsTempFileName(char*);
int sqliteOsClose(OsFile*);
int sqliteOsRead(OsFile*, void*, int amt);
int sqliteOsWrite(OsFile*, const void*, int amt);
int sqliteOsSeek(OsFile*, off_t offset);
int sqliteOsSync(OsFile*);
int sqliteOsTruncate(OsFile*, off_t size);
int sqliteOsFileSize(OsFile*, off_t *pSize);
int sqliteOsReadLock(OsFile*);
int sqliteOsWriteLock(OsFile*);
int sqliteOsUnlock(OsFile*);
int sqliteOsRandomSeed(char*);
int sqliteOsSleep(int ms);
int sqliteOsCurrentTime(double*);
void sqliteOsEnterMutex(void);
void sqliteOsLeaveMutex(void);
char *sqliteOsFullPathname(const char*);
#ifdef _SQLITE_OS_C_
/*
** The os.c file implements the global virtual function table.
*/
struct sqlite3OsVtbl sqlite3Os = {
IF_DISKIO( sqlite3OsOpenReadWrite ),
IF_DISKIO( sqlite3OsOpenExclusive ),
IF_DISKIO( sqlite3OsOpenReadOnly ),
IF_DISKIO( sqlite3OsDelete ),
IF_DISKIO( sqlite3OsFileExists ),
IF_DISKIO( sqlite3OsFullPathname ),
IF_DISKIO( sqlite3OsIsDirWritable ),
IF_DISKIO( sqlite3OsSyncDirectory ),
IF_DISKIO( sqlite3OsTempFileName ),
sqlite3OsRandomSeed,
sqlite3OsSleep,
sqlite3OsCurrentTime,
sqlite3OsEnterMutex,
sqlite3OsLeaveMutex,
sqlite3OsInMutex,
sqlite3OsThreadSpecificData,
sqlite3OsMalloc,
sqlite3OsRealloc,
sqlite3OsFree,
sqlite3OsAllocationSize
};
#else
/*
** Files other than os.c just reference the global virtual function table.
*/
extern struct sqlite3OsVtbl sqlite3Os;
#endif /* _SQLITE_OS_C_ */
/* This additional API routine is available with redefinable I/O */
struct sqlite3OsVtbl *sqlite3_os_switch(void);
/*
** Redefine the OS interface to go through the virtual function table
** rather than calling routines directly.
*/
#undef sqlite3OsOpenReadWrite
#undef sqlite3OsOpenExclusive
#undef sqlite3OsOpenReadOnly
#undef sqlite3OsDelete
#undef sqlite3OsFileExists
#undef sqlite3OsFullPathname
#undef sqlite3OsIsDirWritable
#undef sqlite3OsSyncDirectory
#undef sqlite3OsTempFileName
#undef sqlite3OsRandomSeed
#undef sqlite3OsSleep
#undef sqlite3OsCurrentTime
#undef sqlite3OsEnterMutex
#undef sqlite3OsLeaveMutex
#undef sqlite3OsInMutex
#undef sqlite3OsThreadSpecificData
#undef sqlite3OsMalloc
#undef sqlite3OsRealloc
#undef sqlite3OsFree
#undef sqlite3OsAllocationSize
#define sqlite3OsOpenReadWrite sqlite3Os.xOpenReadWrite
#define sqlite3OsOpenExclusive sqlite3Os.xOpenExclusive
#define sqlite3OsOpenReadOnly sqlite3Os.xOpenReadOnly
#define sqlite3OsDelete sqlite3Os.xDelete
#define sqlite3OsFileExists sqlite3Os.xFileExists
#define sqlite3OsFullPathname sqlite3Os.xFullPathname
#define sqlite3OsIsDirWritable sqlite3Os.xIsDirWritable
#define sqlite3OsSyncDirectory sqlite3Os.xSyncDirectory
#define sqlite3OsTempFileName sqlite3Os.xTempFileName
#define sqlite3OsRandomSeed sqlite3Os.xRandomSeed
#define sqlite3OsSleep sqlite3Os.xSleep
#define sqlite3OsCurrentTime sqlite3Os.xCurrentTime
#define sqlite3OsEnterMutex sqlite3Os.xEnterMutex
#define sqlite3OsLeaveMutex sqlite3Os.xLeaveMutex
#define sqlite3OsInMutex sqlite3Os.xInMutex
#define sqlite3OsThreadSpecificData sqlite3Os.xThreadSpecificData
#define sqlite3OsMalloc sqlite3Os.xMalloc
#define sqlite3OsRealloc sqlite3Os.xRealloc
#define sqlite3OsFree sqlite3Os.xFree
#define sqlite3OsAllocationSize sqlite3Os.xAllocationSize
#endif /* SQLITE_ENABLE_REDEF_IO */
#endif /* _SQLITE_OS_H_ */

188
sqlite/os_common.h Executable file
View File

@ -0,0 +1,188 @@
/*
** 2004 May 22
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
******************************************************************************
**
** This file contains macros and a little bit of code that is common to
** all of the platform-specific files (os_*.c) and is #included into those
** files.
**
** This file should be #included by the os_*.c files only. It is not a
** general purpose header file.
*/
/*
** At least two bugs have slipped in because we changed the MEMORY_DEBUG
** macro to SQLITE_DEBUG and some older makefiles have not yet made the
** switch. The following code should catch this problem at compile-time.
*/
#ifdef MEMORY_DEBUG
# error "The MEMORY_DEBUG macro is obsolete. Use SQLITE_DEBUG instead."
#endif
/*
* When testing, this global variable stores the location of the
* pending-byte in the database file.
*/
#ifdef SQLITE_TEST
unsigned int sqlite3_pending_byte = 0x40000000;
#endif
int sqlite3_os_trace = 0;
#ifdef SQLITE_DEBUG
static int last_page = 0;
#define SEEK(X) last_page=(X)
#define TRACE1(X) if( sqlite3_os_trace ) sqlite3DebugPrintf(X)
#define TRACE2(X,Y) if( sqlite3_os_trace ) sqlite3DebugPrintf(X,Y)
#define TRACE3(X,Y,Z) if( sqlite3_os_trace ) sqlite3DebugPrintf(X,Y,Z)
#define TRACE4(X,Y,Z,A) if( sqlite3_os_trace ) sqlite3DebugPrintf(X,Y,Z,A)
#define TRACE5(X,Y,Z,A,B) if( sqlite3_os_trace ) sqlite3DebugPrintf(X,Y,Z,A,B)
#define TRACE6(X,Y,Z,A,B,C) if(sqlite3_os_trace) sqlite3DebugPrintf(X,Y,Z,A,B,C)
#define TRACE7(X,Y,Z,A,B,C,D) \
if(sqlite3_os_trace) sqlite3DebugPrintf(X,Y,Z,A,B,C,D)
#else
#define SEEK(X)
#define TRACE1(X)
#define TRACE2(X,Y)
#define TRACE3(X,Y,Z)
#define TRACE4(X,Y,Z,A)
#define TRACE5(X,Y,Z,A,B)
#define TRACE6(X,Y,Z,A,B,C)
#define TRACE7(X,Y,Z,A,B,C,D)
#endif
/*
** Macros for performance tracing. Normally turned off. Only works
** on i486 hardware.
*/
#ifdef SQLITE_PERFORMANCE_TRACE
__inline__ unsigned long long int hwtime(void){
unsigned long long int x;
__asm__("rdtsc\n\t"
"mov %%edx, %%ecx\n\t"
:"=A" (x));
return x;
}
static unsigned long long int g_start;
static unsigned int elapse;
#define TIMER_START g_start=hwtime()
#define TIMER_END elapse=hwtime()-g_start
#define TIMER_ELAPSED elapse
#else
#define TIMER_START
#define TIMER_END
#define TIMER_ELAPSED 0
#endif
/*
** If we compile with the SQLITE_TEST macro set, then the following block
** of code will give us the ability to simulate a disk I/O error. This
** is used for testing the I/O recovery logic.
*/
#ifdef SQLITE_TEST
int sqlite3_io_error_hit = 0;
int sqlite3_io_error_pending = 0;
int sqlite3_diskfull_pending = 0;
int sqlite3_diskfull = 0;
#define SimulateIOError(A) \
if( sqlite3_io_error_pending ) \
if( sqlite3_io_error_pending-- == 1 ){ local_ioerr(); return A; }
static void local_ioerr(){
sqlite3_io_error_hit = 1; /* Really just a place to set a breakpoint */
}
#define SimulateDiskfullError \
if( sqlite3_diskfull_pending ){ \
if( sqlite3_diskfull_pending == 1 ){ \
local_ioerr(); \
sqlite3_diskfull = 1; \
return SQLITE_FULL; \
}else{ \
sqlite3_diskfull_pending--; \
} \
}
#else
#define SimulateIOError(A)
#define SimulateDiskfullError
#endif
/*
** When testing, keep a count of the number of open files.
*/
#ifdef SQLITE_TEST
int sqlite3_open_file_count = 0;
#define OpenCounter(X) sqlite3_open_file_count+=(X)
#else
#define OpenCounter(X)
#endif
/*
** sqlite3GenericMalloc
** sqlite3GenericRealloc
** sqlite3GenericOsFree
** sqlite3GenericAllocationSize
**
** Implementation of the os level dynamic memory allocation interface in terms
** of the standard malloc(), realloc() and free() found in many operating
** systems. No rocket science here.
**
** There are two versions of these four functions here. The version
** implemented here is only used if memory-management or memory-debugging is
** enabled. This version allocates an extra 8-bytes at the beginning of each
** block and stores the size of the allocation there.
**
** If neither memory-management or debugging is enabled, the second
** set of implementations is used instead.
*/
#if defined(SQLITE_ENABLE_MEMORY_MANAGEMENT) || defined (SQLITE_MEMDEBUG)
void *sqlite3GenericMalloc(int n){
char *p = (char *)malloc(n+8);
assert(n>0);
assert(sizeof(int)<=8);
if( p ){
*(int *)p = n;
p += 8;
}
return (void *)p;
}
void *sqlite3GenericRealloc(void *p, int n){
char *p2 = ((char *)p - 8);
assert(n>0);
p2 = (char*)realloc(p2, n+8);
if( p2 ){
*(int *)p2 = n;
p2 += 8;
}
return (void *)p2;
}
void sqlite3GenericFree(void *p){
assert(p);
free((void *)((char *)p - 8));
}
int sqlite3GenericAllocationSize(void *p){
return p ? *(int *)((char *)p - 8) : 0;
}
#else
void *sqlite3GenericMalloc(int n){
char *p = (char *)malloc(n);
return (void *)p;
}
void *sqlite3GenericRealloc(void *p, int n){
assert(n>0);
p = realloc(p, n);
return p;
}
void sqlite3GenericFree(void *p){
assert(p);
free(p);
}
/* Never actually used, but needed for the linker */
int sqlite3GenericAllocationSize(void *p){ return 0; }
#endif

1995
sqlite/os_unix.c Executable file

File diff suppressed because it is too large Load Diff

1516
sqlite/os_win.c Executable file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -13,45 +13,35 @@
** subsystem. The page cache subsystem reads and writes a file a page
** at a time and provides a journal for rollback.
**
** @(#) $Id: pager.h,v 1.1.1.1 2004-03-11 22:22:23 alex Exp $
** @(#) $Id: pager.h,v 1.2 2006-04-13 12:44:29 guy Exp $
*/
#ifndef _PAGER_H_
#define _PAGER_H_
/*
** The size of one page
**
** You can change this value to another (reasonable) value you want.
** It need not be a power of two, though the interface to the disk
** will likely be faster if it is.
**
** Experiments show that a page size of 1024 gives the best speed
** for common usages. The speed differences for different sizes
** such as 512, 2048, 4096, an so forth, is minimal. Note, however,
** that changing the page size results in a completely imcompatible
** file format.
** The default size of a database page.
*/
#ifndef SQLITE_PAGE_SIZE
#define SQLITE_PAGE_SIZE 1024
#ifndef SQLITE_DEFAULT_PAGE_SIZE
# define SQLITE_DEFAULT_PAGE_SIZE 1024
#endif
/* Maximum page size. The upper bound on this value is 32768. This a limit
** imposed by necessity of storing the value in a 2-byte unsigned integer
** and the fact that the page size must be a power of 2.
**
** This value is used to initialize certain arrays on the stack at
** various places in the code. On embedded machines where stack space
** is limited and the flexibility of having large pages is not needed,
** it makes good sense to reduce the maximum page size to something more
** reasonable, like 1024.
*/
#ifndef SQLITE_MAX_PAGE_SIZE
# define SQLITE_MAX_PAGE_SIZE 32768
#endif
/*
** Number of extra bytes of data allocated at the end of each page and
** stored on disk but not used by the higher level btree layer. Changing
** this value results in a completely incompatible file format.
*/
#ifndef SQLITE_PAGE_RESERVE
#define SQLITE_PAGE_RESERVE 0
#endif
/*
** The total number of usable bytes stored on disk for each page.
** The usable bytes come at the beginning of the page and the reserve
** bytes come at the end.
*/
#define SQLITE_USABLE_SIZE (SQLITE_PAGE_SIZE-SQLITE_PAGE_RESERVE)
/*
** Maximum number of pages in one database. (This is a limitation of
** imposed by 4GB files size limits.)
** Maximum number of pages in one database.
*/
#define SQLITE_MAX_PAGE 1073741823
@ -66,42 +56,67 @@ typedef unsigned int Pgno;
*/
typedef struct Pager Pager;
/*
** Allowed values for the flags parameter to sqlite3pager_open().
**
** NOTE: This values must match the corresponding BTREE_ values in btree.h.
*/
#define PAGER_OMIT_JOURNAL 0x0001 /* Do not use a rollback journal */
#define PAGER_NO_READLOCK 0x0002 /* Omit readlocks on readonly files */
/*
** See source code comments for a detailed description of the following
** routines:
*/
int sqlitepager_open(Pager **ppPager, const char *zFilename,
int nPage, int nExtra, int useJournal);
void sqlitepager_set_destructor(Pager*, void(*)(void*));
void sqlitepager_set_cachesize(Pager*, int);
int sqlitepager_close(Pager *pPager);
int sqlitepager_get(Pager *pPager, Pgno pgno, void **ppPage);
void *sqlitepager_lookup(Pager *pPager, Pgno pgno);
int sqlitepager_ref(void*);
int sqlitepager_unref(void*);
Pgno sqlitepager_pagenumber(void*);
int sqlitepager_write(void*);
int sqlitepager_iswriteable(void*);
int sqlitepager_overwrite(Pager *pPager, Pgno pgno, void*);
int sqlitepager_pagecount(Pager*);
int sqlitepager_truncate(Pager*,Pgno);
int sqlitepager_begin(void*);
int sqlitepager_commit(Pager*);
int sqlitepager_rollback(Pager*);
int sqlitepager_isreadonly(Pager*);
int sqlitepager_ckpt_begin(Pager*);
int sqlitepager_ckpt_commit(Pager*);
int sqlitepager_ckpt_rollback(Pager*);
void sqlitepager_dont_rollback(void*);
void sqlitepager_dont_write(Pager*, Pgno);
int *sqlitepager_stats(Pager*);
void sqlitepager_set_safety_level(Pager*,int);
const char *sqlitepager_filename(Pager*);
int sqlitepager_rename(Pager*, const char *zNewName);
void sqlitepager_set_codec(Pager*,void(*)(void*,void*,Pgno,int),void*);
int sqlite3pager_open(Pager **ppPager, const char *zFilename,
int nExtra, int flags);
void sqlite3pager_set_busyhandler(Pager*, BusyHandler *pBusyHandler);
void sqlite3pager_set_destructor(Pager*, void(*)(void*,int));
void sqlite3pager_set_reiniter(Pager*, void(*)(void*,int));
int sqlite3pager_set_pagesize(Pager*, int);
void sqlite3pager_read_fileheader(Pager*, int, unsigned char*);
void sqlite3pager_set_cachesize(Pager*, int);
int sqlite3pager_close(Pager *pPager);
int sqlite3pager_get(Pager *pPager, Pgno pgno, void **ppPage);
void *sqlite3pager_lookup(Pager *pPager, Pgno pgno);
int sqlite3pager_ref(void*);
int sqlite3pager_unref(void*);
Pgno sqlite3pager_pagenumber(void*);
int sqlite3pager_write(void*);
int sqlite3pager_iswriteable(void*);
int sqlite3pager_overwrite(Pager *pPager, Pgno pgno, void*);
int sqlite3pager_pagecount(Pager*);
int sqlite3pager_truncate(Pager*,Pgno);
int sqlite3pager_begin(void*, int exFlag);
int sqlite3pager_commit(Pager*);
int sqlite3pager_sync(Pager*,const char *zMaster, Pgno);
int sqlite3pager_rollback(Pager*);
int sqlite3pager_isreadonly(Pager*);
int sqlite3pager_stmt_begin(Pager*);
int sqlite3pager_stmt_commit(Pager*);
int sqlite3pager_stmt_rollback(Pager*);
void sqlite3pager_dont_rollback(void*);
void sqlite3pager_dont_write(Pager*, Pgno);
int *sqlite3pager_stats(Pager*);
void sqlite3pager_set_safety_level(Pager*,int,int);
const char *sqlite3pager_filename(Pager*);
const char *sqlite3pager_dirname(Pager*);
const char *sqlite3pager_journalname(Pager*);
int sqlite3pager_nosync(Pager*);
int sqlite3pager_rename(Pager*, const char *zNewName);
void sqlite3pager_set_codec(Pager*,void*(*)(void*,void*,Pgno,int),void*);
int sqlite3pager_movepage(Pager*,void*,Pgno);
int sqlite3pager_reset(Pager*);
int sqlite3pager_release_memory(int);
#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
int sqlite3pager_lockstate(Pager*);
#endif
#ifdef SQLITE_TEST
void sqlitepager_refdump(Pager*);
int pager_refinfo_enable;
int journal_format;
void sqlite3pager_refdump(Pager*);
int pager3_refinfo_enable;
#endif
#endif /* _PAGER_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -1,20 +1,20 @@
#define TK_END_OF_FILE 1
#define TK_ILLEGAL 2
#define TK_SPACE 3
#define TK_UNCLOSED_STRING 4
#define TK_COMMENT 5
#define TK_FUNCTION 6
#define TK_COLUMN 7
#define TK_AGG_FUNCTION 8
#define TK_SEMI 9
#define TK_EXPLAIN 10
#define TK_BEGIN 11
#define TK_TRANSACTION 12
#define TK_COMMIT 13
#define TK_END 14
#define TK_ROLLBACK 15
#define TK_CREATE 16
#define TK_TABLE 17
#define TK_SEMI 1
#define TK_EXPLAIN 2
#define TK_QUERY 3
#define TK_PLAN 4
#define TK_BEGIN 5
#define TK_TRANSACTION 6
#define TK_DEFERRED 7
#define TK_IMMEDIATE 8
#define TK_EXCLUSIVE 9
#define TK_COMMIT 10
#define TK_END 11
#define TK_ROLLBACK 12
#define TK_CREATE 13
#define TK_TABLE 14
#define TK_IF 15
#define TK_NOT 16
#define TK_EXISTS 17
#define TK_TEMP 18
#define TK_LP 19
#define TK_RP 20
@ -23,108 +23,129 @@
#define TK_ID 23
#define TK_ABORT 24
#define TK_AFTER 25
#define TK_ASC 26
#define TK_ATTACH 27
#define TK_BEFORE 28
#define TK_CASCADE 29
#define TK_CLUSTER 30
#define TK_CONFLICT 31
#define TK_COPY 32
#define TK_ANALYZE 26
#define TK_ASC 27
#define TK_ATTACH 28
#define TK_BEFORE 29
#define TK_CASCADE 30
#define TK_CAST 31
#define TK_CONFLICT 32
#define TK_DATABASE 33
#define TK_DEFERRED 34
#define TK_DELIMITERS 35
#define TK_DESC 36
#define TK_DETACH 37
#define TK_EACH 38
#define TK_FAIL 39
#define TK_FOR 40
#define TK_GLOB 41
#define TK_IGNORE 42
#define TK_IMMEDIATE 43
#define TK_INITIALLY 44
#define TK_INSTEAD 45
#define TK_LIKE 46
#define TK_MATCH 47
#define TK_KEY 48
#define TK_OF 49
#define TK_OFFSET 50
#define TK_PRAGMA 51
#define TK_RAISE 52
#define TK_REPLACE 53
#define TK_RESTRICT 54
#define TK_ROW 55
#define TK_STATEMENT 56
#define TK_TRIGGER 57
#define TK_VACUUM 58
#define TK_VIEW 59
#define TK_OR 60
#define TK_AND 61
#define TK_NOT 62
#define TK_EQ 63
#define TK_NE 64
#define TK_ISNULL 65
#define TK_NOTNULL 66
#define TK_IS 67
#define TK_BETWEEN 68
#define TK_IN 69
#define TK_GT 70
#define TK_DESC 34
#define TK_DETACH 35
#define TK_EACH 36
#define TK_FAIL 37
#define TK_FOR 38
#define TK_IGNORE 39
#define TK_INITIALLY 40
#define TK_INSTEAD 41
#define TK_LIKE_KW 42
#define TK_MATCH 43
#define TK_KEY 44
#define TK_OF 45
#define TK_OFFSET 46
#define TK_PRAGMA 47
#define TK_RAISE 48
#define TK_REPLACE 49
#define TK_RESTRICT 50
#define TK_ROW 51
#define TK_STATEMENT 52
#define TK_TRIGGER 53
#define TK_VACUUM 54
#define TK_VIEW 55
#define TK_REINDEX 56
#define TK_RENAME 57
#define TK_CTIME_KW 58
#define TK_OR 59
#define TK_AND 60
#define TK_IS 61
#define TK_BETWEEN 62
#define TK_IN 63
#define TK_ISNULL 64
#define TK_NOTNULL 65
#define TK_NE 66
#define TK_EQ 67
#define TK_GT 68
#define TK_LE 69
#define TK_LT 70
#define TK_GE 71
#define TK_LT 72
#define TK_LE 73
#define TK_BITAND 74
#define TK_BITOR 75
#define TK_LSHIFT 76
#define TK_RSHIFT 77
#define TK_PLUS 78
#define TK_MINUS 79
#define TK_STAR 80
#define TK_SLASH 81
#define TK_REM 82
#define TK_CONCAT 83
#define TK_UMINUS 84
#define TK_UPLUS 85
#define TK_BITNOT 86
#define TK_STRING 87
#define TK_JOIN_KW 88
#define TK_INTEGER 89
#define TK_CONSTRAINT 90
#define TK_DEFAULT 91
#define TK_FLOAT 92
#define TK_NULL 93
#define TK_PRIMARY 94
#define TK_UNIQUE 95
#define TK_CHECK 96
#define TK_REFERENCES 97
#define TK_COLLATE 98
#define TK_ON 99
#define TK_DELETE 100
#define TK_UPDATE 101
#define TK_INSERT 102
#define TK_SET 103
#define TK_DEFERRABLE 104
#define TK_FOREIGN 105
#define TK_DROP 106
#define TK_UNION 107
#define TK_ALL 108
#define TK_INTERSECT 109
#define TK_EXCEPT 110
#define TK_SELECT 111
#define TK_DISTINCT 112
#define TK_DOT 113
#define TK_FROM 114
#define TK_JOIN 115
#define TK_USING 116
#define TK_ORDER 117
#define TK_BY 118
#define TK_GROUP 119
#define TK_HAVING 120
#define TK_LIMIT 121
#define TK_WHERE 122
#define TK_INTO 123
#define TK_VALUES 124
#define TK_VARIABLE 125
#define TK_CASE 126
#define TK_WHEN 127
#define TK_THEN 128
#define TK_ELSE 129
#define TK_INDEX 130
#define TK_ESCAPE 72
#define TK_BITAND 73
#define TK_BITOR 74
#define TK_LSHIFT 75
#define TK_RSHIFT 76
#define TK_PLUS 77
#define TK_MINUS 78
#define TK_STAR 79
#define TK_SLASH 80
#define TK_REM 81
#define TK_CONCAT 82
#define TK_UMINUS 83
#define TK_UPLUS 84
#define TK_BITNOT 85
#define TK_STRING 86
#define TK_JOIN_KW 87
#define TK_CONSTRAINT 88
#define TK_DEFAULT 89
#define TK_NULL 90
#define TK_PRIMARY 91
#define TK_UNIQUE 92
#define TK_CHECK 93
#define TK_REFERENCES 94
#define TK_COLLATE 95
#define TK_AUTOINCR 96
#define TK_ON 97
#define TK_DELETE 98
#define TK_UPDATE 99
#define TK_INSERT 100
#define TK_SET 101
#define TK_DEFERRABLE 102
#define TK_FOREIGN 103
#define TK_DROP 104
#define TK_UNION 105
#define TK_ALL 106
#define TK_EXCEPT 107
#define TK_INTERSECT 108
#define TK_SELECT 109
#define TK_DISTINCT 110
#define TK_DOT 111
#define TK_FROM 112
#define TK_JOIN 113
#define TK_USING 114
#define TK_ORDER 115
#define TK_BY 116
#define TK_GROUP 117
#define TK_HAVING 118
#define TK_LIMIT 119
#define TK_WHERE 120
#define TK_INTO 121
#define TK_VALUES 122
#define TK_INTEGER 123
#define TK_FLOAT 124
#define TK_BLOB 125
#define TK_REGISTER 126
#define TK_VARIABLE 127
#define TK_CASE 128
#define TK_WHEN 129
#define TK_THEN 130
#define TK_ELSE 131
#define TK_INDEX 132
#define TK_ALTER 133
#define TK_TO 134
#define TK_ADD 135
#define TK_COLUMNKW 136
#define TK_TO_TEXT 137
#define TK_TO_BLOB 138
#define TK_TO_NUMERIC 139
#define TK_TO_INT 140
#define TK_TO_REAL 141
#define TK_END_OF_FILE 142
#define TK_ILLEGAL 143
#define TK_SPACE 144
#define TK_UNCLOSED_STRING 145
#define TK_COMMENT 146
#define TK_FUNCTION 147
#define TK_COLUMN 148
#define TK_AGG_FUNCTION 149
#define TK_AGG_COLUMN 150
#define TK_CONST_FUNC 151

File diff suppressed because it is too large Load Diff

583
sqlite/prepare.c Executable file
View File

@ -0,0 +1,583 @@
/*
** 2005 May 25
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains the implementation of the sqlite3_prepare()
** interface, and routines that contribute to loading the database schema
** from disk.
**
** $Id: prepare.c,v 1.1 2006-04-13 12:44:29 guy Exp $
*/
#include "sqliteInt.h"
#include "os.h"
#include <ctype.h>
/*
** Fill the InitData structure with an error message that indicates
** that the database is corrupt.
*/
static void corruptSchema(InitData *pData, const char *zExtra){
if( !sqlite3MallocFailed() ){
sqlite3SetString(pData->pzErrMsg, "malformed database schema",
zExtra!=0 && zExtra[0]!=0 ? " - " : (char*)0, zExtra, (char*)0);
}
}
/*
** This is the callback routine for the code that initializes the
** database. See sqlite3Init() below for additional information.
** This routine is also called from the OP_ParseSchema opcode of the VDBE.
**
** Each callback contains the following information:
**
** argv[0] = name of thing being created
** argv[1] = root page number for table or index. NULL for trigger or view.
** argv[2] = SQL text for the CREATE statement.
** argv[3] = "1" for temporary files, "0" for main database, "2" or more
** for auxiliary database files.
**
*/
int sqlite3InitCallback(void *pInit, int argc, char **argv, char **azColName){
InitData *pData = (InitData*)pInit;
sqlite3 *db = pData->db;
int iDb;
if( sqlite3MallocFailed() ){
return SQLITE_NOMEM;
}
assert( argc==4 );
if( argv==0 ) return 0; /* Might happen if EMPTY_RESULT_CALLBACKS are on */
if( argv[1]==0 || argv[3]==0 ){
corruptSchema(pData, 0);
return 1;
}
iDb = atoi(argv[3]);
assert( iDb>=0 && iDb<db->nDb );
if( argv[2] && argv[2][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;
int rc;
assert( db->init.busy );
db->init.iDb = iDb;
db->init.newTnum = atoi(argv[1]);
rc = sqlite3_exec(db, argv[2], 0, 0, &zErr);
db->init.iDb = 0;
assert( rc!=SQLITE_OK || zErr==0 );
if( SQLITE_OK!=rc ){
if( rc==SQLITE_NOMEM ){
sqlite3FailedMalloc();
}else{
corruptSchema(pData, zErr);
}
sqlite3_free(zErr);
return rc;
}
}else{
/* If the SQL column is blank it means this is an index that
** was created to be the PRIMARY KEY or to fulfill a UNIQUE
** constraint for a CREATE TABLE. The index should have already
** been created when we processed the CREATE TABLE. All we have
** to do here is record the root page number for that index.
*/
Index *pIndex;
pIndex = sqlite3FindIndex(db, argv[0], db->aDb[iDb].zName);
if( pIndex==0 || pIndex->tnum!=0 ){
/* This can occur if there exists an index on a TEMP table which
** has the same name as another index on a permanent index. Since
** the permanent table is hidden by the TEMP table, we can also
** safely ignore the index on the permanent table.
*/
/* Do Nothing */;
}else{
pIndex->tnum = atoi(argv[1]);
}
}
return 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 sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
int rc;
BtCursor *curMain;
int size;
Table *pTab;
Db *pDb;
char const *azArg[5];
char zDbNum[30];
int meta[10];
InitData initData;
char const *zMasterSchema;
char const *zMasterName = SCHEMA_TABLE(iDb);
/*
** The master database table has a structure like this
*/
static const char master_schema[] =
"CREATE TABLE sqlite_master(\n"
" type text,\n"
" name text,\n"
" tbl_name text,\n"
" rootpage integer,\n"
" sql text\n"
")"
;
#ifndef SQLITE_OMIT_TEMPDB
static const 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"
")"
;
#else
#define temp_master_schema 0
#endif
assert( iDb>=0 && iDb<db->nDb );
assert( db->aDb[iDb].pSchema );
/* 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( !OMIT_TEMPDB && iDb==1 ){
zMasterSchema = temp_master_schema;
}else{
zMasterSchema = master_schema;
}
zMasterName = SCHEMA_TABLE(iDb);
/* Construct the schema tables. */
sqlite3SafetyOff(db);
azArg[0] = zMasterName;
azArg[1] = "1";
azArg[2] = zMasterSchema;
sprintf(zDbNum, "%d", iDb);
azArg[3] = zDbNum;
azArg[4] = 0;
initData.db = db;
initData.pzErrMsg = pzErrMsg;
rc = sqlite3InitCallback(&initData, 4, (char **)azArg, 0);
if( rc!=SQLITE_OK ){
sqlite3SafetyOn(db);
return rc;
}
pTab = sqlite3FindTable(db, zMasterName, db->aDb[iDb].zName);
if( pTab ){
pTab->readOnly = 1;
}
sqlite3SafetyOn(db);
/* Create a cursor to hold the database open
*/
pDb = &db->aDb[iDb];
if( pDb->pBt==0 ){
if( !OMIT_TEMPDB && iDb==1 ){
DbSetProperty(db, 1, DB_SchemaLoaded);
}
return SQLITE_OK;
}
rc = sqlite3BtreeCursor(pDb->pBt, MASTER_ROOT, 0, 0, 0, &curMain);
if( rc!=SQLITE_OK && rc!=SQLITE_EMPTY ){
sqlite3SetString(pzErrMsg, sqlite3ErrStr(rc), (char*)0);
return rc;
}
/* Get the database meta information.
**
** Meta values are as follows:
** meta[0] Schema cookie. Changes with each schema change.
** meta[1] File format of schema layer.
** meta[2] Size of the page cache.
** meta[3] Use freelist if 0. Autovacuum if greater than zero.
** meta[4] Db text encoding. 1:UTF-8 3:UTF-16 LE 4:UTF-16 BE
** meta[5] The user cookie. Used by the application.
** meta[6]
** meta[7]
** meta[8]
** meta[9]
**
** Note: The #defined SQLITE_UTF* symbols in sqliteInt.h correspond to
** the possible values of meta[4].
*/
if( rc==SQLITE_OK ){
int i;
for(i=0; rc==SQLITE_OK && i<sizeof(meta)/sizeof(meta[0]); i++){
rc = sqlite3BtreeGetMeta(pDb->pBt, i+1, (u32 *)&meta[i]);
}
if( rc ){
sqlite3SetString(pzErrMsg, sqlite3ErrStr(rc), (char*)0);
sqlite3BtreeCloseCursor(curMain);
return rc;
}
}else{
memset(meta, 0, sizeof(meta));
}
pDb->pSchema->schema_cookie = meta[0];
/* If opening a non-empty database, check the text encoding. For the
** main database, set sqlite3.enc to the encoding of the main database.
** For an attached db, it is an error if the encoding is not the same
** as sqlite3.enc.
*/
if( meta[4] ){ /* text encoding */
if( iDb==0 ){
/* If opening the main database, set ENC(db). */
ENC(db) = (u8)meta[4];
db->pDfltColl = sqlite3FindCollSeq(db, SQLITE_UTF8, "BINARY", 6, 0);
}else{
/* If opening an attached database, the encoding much match ENC(db) */
if( meta[4]!=ENC(db) ){
sqlite3BtreeCloseCursor(curMain);
sqlite3SetString(pzErrMsg, "attached databases must use the same"
" text encoding as main database", (char*)0);
return SQLITE_ERROR;
}
}
}else{
DbSetProperty(db, iDb, DB_Empty);
}
pDb->pSchema->enc = ENC(db);
size = meta[2];
if( size==0 ){ size = MAX_PAGES; }
pDb->pSchema->cache_size = size;
sqlite3BtreeSetCacheSize(pDb->pBt, pDb->pSchema->cache_size);
/*
** file_format==1 Version 3.0.0.
** file_format==2 Version 3.1.3. // ALTER TABLE ADD COLUMN
** file_format==3 Version 3.1.4. // ditto but with non-NULL defaults
** file_format==4 Version 3.3.0. // DESC indices. Boolean constants
*/
pDb->pSchema->file_format = meta[1];
if( pDb->pSchema->file_format==0 ){
pDb->pSchema->file_format = 1;
}
if( pDb->pSchema->file_format>SQLITE_MAX_FILE_FORMAT ){
sqlite3BtreeCloseCursor(curMain);
sqlite3SetString(pzErrMsg, "unsupported file format", (char*)0);
return SQLITE_ERROR;
}
/* Read the schema information out of the schema tables
*/
assert( db->init.busy );
if( rc==SQLITE_EMPTY ){
/* For an empty database, there is nothing to read */
rc = SQLITE_OK;
}else{
char *zSql;
zSql = sqlite3MPrintf(
"SELECT name, rootpage, sql, '%s' FROM '%q'.%s",
zDbNum, db->aDb[iDb].zName, zMasterName);
sqlite3SafetyOff(db);
rc = sqlite3_exec(db, zSql, sqlite3InitCallback, &initData, 0);
sqlite3SafetyOn(db);
sqliteFree(zSql);
#ifndef SQLITE_OMIT_ANALYZE
if( rc==SQLITE_OK ){
sqlite3AnalysisLoad(db, iDb);
}
#endif
sqlite3BtreeCloseCursor(curMain);
}
if( sqlite3MallocFailed() ){
/* sqlite3SetString(pzErrMsg, "out of memory", (char*)0); */
rc = SQLITE_NOMEM;
sqlite3ResetInternalSchema(db, 0);
}
if( rc==SQLITE_OK ){
DbSetProperty(db, iDb, DB_SchemaLoaded);
}else{
sqlite3ResetInternalSchema(db, iDb);
}
return rc;
}
/*
** 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 a database is initialized, the DB_SchemaLoaded bit is set
** bit is set in the flags field of the Db structure. If the database
** file was of zero-length, then the DB_Empty flag is also set.
*/
int sqlite3Init(sqlite3 *db, char **pzErrMsg){
int i, rc;
int called_initone = 0;
if( db->init.busy ) return SQLITE_OK;
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 = sqlite3InitOne(db, i, pzErrMsg);
if( rc ){
sqlite3ResetInternalSchema(db, i);
}
called_initone = 1;
}
/* 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.
*/
#ifndef SQLITE_OMIT_TEMPDB
if( rc==SQLITE_OK && db->nDb>1 && !DbHasProperty(db, 1, DB_SchemaLoaded) ){
rc = sqlite3InitOne(db, 1, pzErrMsg);
if( rc ){
sqlite3ResetInternalSchema(db, 1);
}
called_initone = 1;
}
#endif
db->init.busy = 0;
if( rc==SQLITE_OK && called_initone ){
sqlite3CommitInternalChanges(db);
}
return rc;
}
/*
** This routine is a no-op if the database schema is already initialised.
** Otherwise, the schema is loaded. An error code is returned.
*/
int sqlite3ReadSchema(Parse *pParse){
int rc = SQLITE_OK;
sqlite3 *db = pParse->db;
if( !db->init.busy ){
rc = sqlite3Init(db, &pParse->zErrMsg);
}
if( rc!=SQLITE_OK ){
pParse->rc = rc;
pParse->nErr++;
}
return rc;
}
/*
** Check schema cookies in all databases. If any cookie is out
** of date, return 0. If all schema cookies are current, return 1.
*/
static int schemaIsValid(sqlite3 *db){
int iDb;
int rc;
BtCursor *curTemp;
int cookie;
int allOk = 1;
for(iDb=0; allOk && iDb<db->nDb; iDb++){
Btree *pBt;
pBt = db->aDb[iDb].pBt;
if( pBt==0 ) continue;
rc = sqlite3BtreeCursor(pBt, MASTER_ROOT, 0, 0, 0, &curTemp);
if( rc==SQLITE_OK ){
rc = sqlite3BtreeGetMeta(pBt, 1, (u32 *)&cookie);
if( rc==SQLITE_OK && cookie!=db->aDb[iDb].pSchema->schema_cookie ){
allOk = 0;
}
sqlite3BtreeCloseCursor(curTemp);
}
}
return allOk;
}
/*
** Convert a schema pointer into the iDb index that indicates
** which database file in db->aDb[] the schema refers to.
**
** If the same database is attached more than once, the first
** attached database is returned.
*/
int sqlite3SchemaToIndex(sqlite3 *db, Schema *pSchema){
int i = -1000000;
/* If pSchema is NULL, then return -1000000. This happens when code in
** expr.c is trying to resolve a reference to a transient table (i.e. one
** created by a sub-select). In this case the return value of this
** function should never be used.
**
** We return -1000000 instead of the more usual -1 simply because using
** -1000000 as incorrectly using -1000000 index into db->aDb[] is much
** more likely to cause a segfault than -1 (of course there are assert()
** statements too, but it never hurts to play the odds).
*/
if( pSchema ){
for(i=0; i<db->nDb; i++){
if( db->aDb[i].pSchema==pSchema ){
break;
}
}
assert( i>=0 &&i>=0 && i<db->nDb );
}
return i;
}
/*
** Compile the UTF-8 encoded SQL statement zSql into a statement handle.
*/
int sqlite3_prepare(
sqlite3 *db, /* Database handle. */
const char *zSql, /* UTF-8 encoded SQL statement. */
int nBytes, /* Length of zSql in bytes. */
sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */
const char** pzTail /* OUT: End of parsed string */
){
Parse sParse;
char *zErrMsg = 0;
int rc = SQLITE_OK;
int i;
/* Assert that malloc() has not failed */
assert( !sqlite3MallocFailed() );
assert( ppStmt );
*ppStmt = 0;
if( sqlite3SafetyOn(db) ){
return SQLITE_MISUSE;
}
/* If any attached database schemas are locked, do not proceed with
** compilation. Instead return SQLITE_LOCKED immediately.
*/
for(i=0; i<db->nDb; i++) {
Btree *pBt = db->aDb[i].pBt;
if( pBt && sqlite3BtreeSchemaLocked(pBt) ){
const char *zDb = db->aDb[i].zName;
sqlite3Error(db, SQLITE_LOCKED, "database schema is locked: %s", zDb);
sqlite3SafetyOff(db);
return SQLITE_LOCKED;
}
}
memset(&sParse, 0, sizeof(sParse));
sParse.db = db;
if( nBytes>=0 && zSql[nBytes]!=0 ){
char *zSqlCopy = sqlite3StrNDup(zSql, nBytes);
sqlite3RunParser(&sParse, zSqlCopy, &zErrMsg);
sParse.zTail += zSql - zSqlCopy;
sqliteFree(zSqlCopy);
}else{
sqlite3RunParser(&sParse, zSql, &zErrMsg);
}
if( sqlite3MallocFailed() ){
sParse.rc = SQLITE_NOMEM;
}
if( sParse.rc==SQLITE_DONE ) sParse.rc = SQLITE_OK;
if( sParse.checkSchema && !schemaIsValid(db) ){
sParse.rc = SQLITE_SCHEMA;
}
if( sParse.rc==SQLITE_SCHEMA ){
sqlite3ResetInternalSchema(db, 0);
}
if( pzTail ) *pzTail = sParse.zTail;
rc = sParse.rc;
#ifndef SQLITE_OMIT_EXPLAIN
if( rc==SQLITE_OK && sParse.pVdbe && sParse.explain ){
if( sParse.explain==2 ){
sqlite3VdbeSetNumCols(sParse.pVdbe, 3);
sqlite3VdbeSetColName(sParse.pVdbe, 0, COLNAME_NAME, "order", P3_STATIC);
sqlite3VdbeSetColName(sParse.pVdbe, 1, COLNAME_NAME, "from", P3_STATIC);
sqlite3VdbeSetColName(sParse.pVdbe, 2, COLNAME_NAME, "detail", P3_STATIC);
}else{
sqlite3VdbeSetNumCols(sParse.pVdbe, 5);
sqlite3VdbeSetColName(sParse.pVdbe, 0, COLNAME_NAME, "addr", P3_STATIC);
sqlite3VdbeSetColName(sParse.pVdbe, 1, COLNAME_NAME, "opcode", P3_STATIC);
sqlite3VdbeSetColName(sParse.pVdbe, 2, COLNAME_NAME, "p1", P3_STATIC);
sqlite3VdbeSetColName(sParse.pVdbe, 3, COLNAME_NAME, "p2", P3_STATIC);
sqlite3VdbeSetColName(sParse.pVdbe, 4, COLNAME_NAME, "p3", P3_STATIC);
}
}
#endif
if( sqlite3SafetyOff(db) ){
rc = SQLITE_MISUSE;
}
if( rc==SQLITE_OK ){
*ppStmt = (sqlite3_stmt*)sParse.pVdbe;
}else if( sParse.pVdbe ){
sqlite3_finalize((sqlite3_stmt*)sParse.pVdbe);
}
if( zErrMsg ){
sqlite3Error(db, rc, "%s", zErrMsg);
sqliteFree(zErrMsg);
}else{
sqlite3Error(db, rc, 0);
}
rc = sqlite3ApiExit(db, rc);
sqlite3ReleaseThreadData();
return rc;
}
#ifndef SQLITE_OMIT_UTF16
/*
** Compile the UTF-16 encoded SQL statement zSql into a statement handle.
*/
int sqlite3_prepare16(
sqlite3 *db, /* Database handle. */
const void *zSql, /* UTF-8 encoded SQL statement. */
int nBytes, /* Length of zSql in bytes. */
sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */
const void **pzTail /* OUT: End of parsed string */
){
/* This function currently works by first transforming the UTF-16
** encoded string to UTF-8, then invoking sqlite3_prepare(). The
** tricky bit is figuring out the pointer to return in *pzTail.
*/
char *zSql8;
const char *zTail8 = 0;
int rc = SQLITE_OK;
if( sqlite3SafetyCheck(db) ){
return SQLITE_MISUSE;
}
zSql8 = sqlite3utf16to8(zSql, nBytes);
if( zSql8 ){
rc = sqlite3_prepare(db, zSql8, -1, ppStmt, &zTail8);
}
if( zTail8 && pzTail ){
/* If sqlite3_prepare returns a tail pointer, we calculate the
** equivalent pointer into the UTF-16 string by counting the unicode
** characters between zSql8 and zTail8, and then returning a pointer
** the same number of characters into the UTF-16 string.
*/
int chars_parsed = sqlite3utf8CharLen(zSql8, zTail8-zSql8);
*pzTail = (u8 *)zSql + sqlite3utf16ByteLen(zSql, chars_parsed);
}
sqliteFree(zSql8);
return sqlite3ApiExit(db, rc);
}
#endif /* SQLITE_OMIT_UTF16 */

View File

@ -65,14 +65,14 @@
#define etDYNSTRING 7 /* Dynamically allocated strings. %z */
#define etPERCENT 8 /* Percent symbol. %% */
#define etCHARX 9 /* Characters. %c */
#define etERROR 10 /* Used to indicate no such conversion type */
/* The rest are extensions, not normally found in printf() */
#define etCHARLIT 11 /* Literal characters. %' */
#define etSQLESCAPE 12 /* Strings with '\'' doubled. %q */
#define etSQLESCAPE2 13 /* Strings with '\'' doubled and enclosed in '',
#define etCHARLIT 10 /* Literal characters. %' */
#define etSQLESCAPE 11 /* Strings with '\'' doubled. %q */
#define etSQLESCAPE2 12 /* Strings with '\'' doubled and enclosed in '',
NULL pointers replaced by SQL NULL. %Q */
#define etTOKEN 14 /* a pointer to a Token structure */
#define etSRCLIST 15 /* a pointer to a SrcList */
#define etTOKEN 13 /* a pointer to a Token structure */
#define etSRCLIST 14 /* a pointer to a SrcList */
#define etPOINTER 15 /* The %p conversion */
/*
@ -89,8 +89,8 @@ typedef struct et_info { /* Information about each format field */
etByte base; /* The base for radix conversion */
etByte flags; /* One or more of FLAG_ constants below */
etByte type; /* Conversion paradigm */
char *charset; /* The character set for conversion */
char *prefix; /* Prefix on non-zero values in alt format */
etByte charset; /* Offset into aDigits[] of the digits string */
etByte prefix; /* Offset into aPrefix[] of the prefix string */
} et_info;
/*
@ -98,42 +98,47 @@ typedef struct et_info { /* Information about each format field */
*/
#define FLAG_SIGNED 1 /* True if the value to convert is signed */
#define FLAG_INTERN 2 /* True if for internal use only */
#define FLAG_STRING 4 /* Allow infinity precision */
/*
** The following table is searched linearly, so it is good to put the
** most frequently used conversion types first.
*/
static et_info fmtinfo[] = {
{ 'd', 10, 1, etRADIX, "0123456789", 0 },
{ 's', 0, 0, etSTRING, 0, 0 },
{ 'z', 0, 2, etDYNSTRING, 0, 0 },
{ 'q', 0, 0, etSQLESCAPE, 0, 0 },
{ 'Q', 0, 0, etSQLESCAPE2, 0, 0 },
{ 'c', 0, 0, etCHARX, 0, 0 },
{ 'o', 8, 0, etRADIX, "01234567", "0" },
{ 'u', 10, 0, etRADIX, "0123456789", 0 },
{ 'x', 16, 0, etRADIX, "0123456789abcdef", "x0" },
{ 'X', 16, 0, etRADIX, "0123456789ABCDEF", "X0" },
{ 'f', 0, 1, etFLOAT, 0, 0 },
{ 'e', 0, 1, etEXP, "e", 0 },
{ 'E', 0, 1, etEXP, "E", 0 },
{ 'g', 0, 1, etGENERIC, "e", 0 },
{ 'G', 0, 1, etGENERIC, "E", 0 },
{ 'i', 10, 1, etRADIX, "0123456789", 0 },
{ 'n', 0, 0, etSIZE, 0, 0 },
{ '%', 0, 0, etPERCENT, 0, 0 },
{ 'p', 10, 0, etRADIX, "0123456789", 0 },
{ 'T', 0, 2, etTOKEN, 0, 0 },
{ 'S', 0, 2, etSRCLIST, 0, 0 },
static const char aDigits[] = "0123456789ABCDEF0123456789abcdef";
static const char aPrefix[] = "-x0\000X0";
static const et_info fmtinfo[] = {
{ 'd', 10, 1, etRADIX, 0, 0 },
{ 's', 0, 4, etSTRING, 0, 0 },
{ 'g', 0, 1, etGENERIC, 30, 0 },
{ 'z', 0, 6, etDYNSTRING, 0, 0 },
{ 'q', 0, 4, etSQLESCAPE, 0, 0 },
{ 'Q', 0, 4, etSQLESCAPE2, 0, 0 },
{ 'c', 0, 0, etCHARX, 0, 0 },
{ 'o', 8, 0, etRADIX, 0, 2 },
{ 'u', 10, 0, etRADIX, 0, 0 },
{ 'x', 16, 0, etRADIX, 16, 1 },
{ 'X', 16, 0, etRADIX, 0, 4 },
#ifndef SQLITE_OMIT_FLOATING_POINT
{ 'f', 0, 1, etFLOAT, 0, 0 },
{ 'e', 0, 1, etEXP, 30, 0 },
{ 'E', 0, 1, etEXP, 14, 0 },
{ 'G', 0, 1, etGENERIC, 14, 0 },
#endif
{ 'i', 10, 1, etRADIX, 0, 0 },
{ 'n', 0, 0, etSIZE, 0, 0 },
{ '%', 0, 0, etPERCENT, 0, 0 },
{ 'p', 16, 0, etPOINTER, 0, 1 },
{ 'T', 0, 2, etTOKEN, 0, 0 },
{ 'S', 0, 2, etSRCLIST, 0, 0 },
};
#define etNINFO (sizeof(fmtinfo)/sizeof(fmtinfo[0]))
/*
** If NOFLOATINGPOINT is defined, then none of the floating point
** If SQLITE_OMIT_FLOATING_POINT is defined, then none of the floating point
** conversions will work.
*/
#ifndef etNOFLOATINGPOINT
#ifndef SQLITE_OMIT_FLOATING_POINT
/*
** "*val" is a double such that 0.1 <= *val < 10.0
** Return the ascii code for the leading digit of *val, then
@ -157,9 +162,17 @@ static int et_getdigit(LONGDOUBLE_TYPE *val, int *cnt){
*val = (*val - d)*10.0;
return digit;
}
#endif
#endif /* SQLITE_OMIT_FLOATING_POINT */
#define etBUFSIZE 1000 /* Size of the output buffer */
/*
** On machines with a small stack size, you can redefine the
** SQLITE_PRINT_BUF_SIZE to be less than 350. But beware - for
** smaller values some %f conversions may go into an infinite loop.
*/
#ifndef SQLITE_PRINT_BUF_SIZE
# define SQLITE_PRINT_BUF_SIZE 350
#endif
#define etBUFSIZE SQLITE_PRINT_BUF_SIZE /* Size of the output buffer */
/*
** The root program. All variations call this core.
@ -206,20 +219,24 @@ static int vxprintf(
etByte flag_plussign; /* True if "+" flag is present */
etByte flag_blanksign; /* True if " " flag is present */
etByte flag_alternateform; /* True if "#" flag is present */
etByte flag_altform2; /* True if "!" flag is present */
etByte flag_zeropad; /* True if field width constant starts with zero */
etByte flag_long; /* True if "l" flag is present */
unsigned long longvalue; /* Value for integer types */
etByte flag_longlong; /* True if the "ll" flag is present */
etByte done; /* Loop termination flag */
sqlite_uint64 longvalue; /* Value for integer types */
LONGDOUBLE_TYPE realvalue; /* Value for real types */
et_info *infop; /* Pointer to the appropriate info structure */
const et_info *infop; /* Pointer to the appropriate info structure */
char buf[etBUFSIZE]; /* Conversion buffer */
char prefix; /* Prefix character. "+" or "-" or " " or '\0'. */
etByte errorflag = 0; /* True if an error is encountered */
etByte xtype; /* Conversion paradigm */
char *zExtra; /* Extra memory used for etTCLESCAPE conversions */
static char spaces[] = " ";
static const char spaces[] =
" ";
#define etSPACESIZE (sizeof(spaces)-1)
#ifndef etNOFLOATINGPOINT
int exp; /* exponent of real numbers */
#ifndef SQLITE_OMIT_FLOATING_POINT
int exp, e2; /* exponent of real numbers */
double rounder; /* Used for rounding floating point values */
etByte flag_dp; /* True if decimal point should be shown */
etByte flag_rtz; /* True if trailing zeros should be removed */
@ -227,6 +244,7 @@ static int vxprintf(
int nsd; /* Number of significant digits returned */
#endif
func(arg,"",0);
count = length = 0;
bufpt = 0;
for(; (c=(*fmt))!=0; ++fmt){
@ -247,17 +265,19 @@ static int vxprintf(
}
/* Find out what flags are present */
flag_leftjustify = flag_plussign = flag_blanksign =
flag_alternateform = flag_zeropad = 0;
flag_alternateform = flag_altform2 = flag_zeropad = 0;
done = 0;
do{
switch( c ){
case '-': flag_leftjustify = 1; c = 0; break;
case '+': flag_plussign = 1; c = 0; break;
case ' ': flag_blanksign = 1; c = 0; break;
case '#': flag_alternateform = 1; c = 0; break;
case '0': flag_zeropad = 1; c = 0; break;
default: break;
case '-': flag_leftjustify = 1; break;
case '+': flag_plussign = 1; break;
case ' ': flag_blanksign = 1; break;
case '#': flag_alternateform = 1; break;
case '!': flag_altform2 = 1; break;
case '0': flag_zeropad = 1; break;
default: done = 1; break;
}
}while( c==0 && (c=(*++fmt))!=0 );
}while( !done && (c=(*++fmt))!=0 );
/* Get the field width */
width = 0;
if( c=='*' ){
@ -290,8 +310,6 @@ static int vxprintf(
c = *++fmt;
}
}
/* Limit the precision to prevent overflowing buf[] during conversion */
if( precision>etBUFSIZE-40 ) precision = etBUFSIZE-40;
}else{
precision = -1;
}
@ -299,12 +317,17 @@ static int vxprintf(
if( c=='l' ){
flag_long = 1;
c = *++fmt;
if( c=='l' ){
flag_longlong = 1;
c = *++fmt;
}else{
flag_longlong = 0;
}
}else{
flag_long = 0;
flag_long = flag_longlong = 0;
}
/* Fetch the info entry for the field */
infop = 0;
xtype = etERROR;
for(idx=0; idx<etNINFO; idx++){
if( c==fmtinfo[idx].fmttype ){
infop = &fmtinfo[idx];
@ -315,17 +338,29 @@ static int vxprintf(
}
}
zExtra = 0;
if( infop==0 ){
return -1;
}
/* Limit the precision to prevent overflowing buf[] during conversion */
if( precision>etBUFSIZE-40 && (infop->flags & FLAG_STRING)==0 ){
precision = etBUFSIZE-40;
}
/*
** At this point, variables are initialized as follows:
**
** flag_alternateform TRUE if a '#' is present.
** flag_altform2 TRUE if a '!' is present.
** flag_plussign TRUE if a '+' is present.
** flag_leftjustify TRUE if a '-' is present or if the
** field width was negative.
** flag_zeropad TRUE if the width began with 0.
** flag_long TRUE if the letter 'l' (ell) prefixed
** the conversion character.
** flag_longlong TRUE if the letter 'll' (ell ell) prefixed
** the conversion character.
** flag_blanksign TRUE if a ' ' is present.
** width The specified field width. This is
** always non-negative. Zero is the default.
@ -335,34 +370,40 @@ static int vxprintf(
** infop Pointer to the appropriate info struct.
*/
switch( xtype ){
case etPOINTER:
flag_longlong = sizeof(char*)==sizeof(i64);
flag_long = sizeof(char*)==sizeof(long int);
/* Fall through into the next case */
case etRADIX:
if( flag_long ) longvalue = va_arg(ap,long);
else longvalue = va_arg(ap,int);
#if 1
/* For the format %#x, the value zero is printed "0" not "0x0".
** I think this is stupid. */
if( longvalue==0 ) flag_alternateform = 0;
#else
/* More sensible: turn off the prefix for octal (to prevent "00"),
** but leave the prefix for hex. */
if( longvalue==0 && infop->base==8 ) flag_alternateform = 0;
#endif
if( infop->flags & FLAG_SIGNED ){
if( *(long*)&longvalue<0 ){
longvalue = -*(long*)&longvalue;
i64 v;
if( flag_longlong ) v = va_arg(ap,i64);
else if( flag_long ) v = va_arg(ap,long int);
else v = va_arg(ap,int);
if( v<0 ){
longvalue = -v;
prefix = '-';
}else if( flag_plussign ) prefix = '+';
else if( flag_blanksign ) prefix = ' ';
else prefix = 0;
}else prefix = 0;
}else{
longvalue = v;
if( flag_plussign ) prefix = '+';
else if( flag_blanksign ) prefix = ' ';
else prefix = 0;
}
}else{
if( flag_longlong ) longvalue = va_arg(ap,u64);
else if( flag_long ) longvalue = va_arg(ap,unsigned long int);
else longvalue = va_arg(ap,unsigned int);
prefix = 0;
}
if( longvalue==0 ) flag_alternateform = 0;
if( flag_zeropad && precision<width-(prefix!=0) ){
precision = width-(prefix!=0);
}
bufpt = &buf[etBUFSIZE-1];
{
register char *cset; /* Use registers for speed */
register const char *cset; /* Use registers for speed */
register int base;
cset = infop->charset;
cset = &aDigits[infop->charset];
base = infop->base;
do{ /* Convert to ascii */
*(--bufpt) = cset[longvalue%base];
@ -375,10 +416,11 @@ static int vxprintf(
}
if( prefix ) *(--bufpt) = prefix; /* Add sign */
if( flag_alternateform && infop->prefix ){ /* Add "0" or "0x" */
char *pre, x;
pre = infop->prefix;
const char *pre;
char x;
pre = &aPrefix[infop->prefix];
if( *bufpt!=pre[0] ){
for(pre=infop->prefix; (x=(*pre))!=0; pre++) *(--bufpt) = x;
for(; (x=(*pre))!=0; pre++) *(--bufpt) = x;
}
}
length = &buf[etBUFSIZE-1]-bufpt;
@ -387,9 +429,9 @@ static int vxprintf(
case etEXP:
case etGENERIC:
realvalue = va_arg(ap,double);
#ifndef etNOFLOATINGPOINT
#ifndef SQLITE_OMIT_FLOATING_POINT
if( precision<0 ) precision = 6; /* Set default precision */
if( precision>etBUFSIZE-10 ) precision = etBUFSIZE-10;
if( precision>etBUFSIZE/2-10 ) precision = etBUFSIZE/2-10;
if( realvalue<0.0 ){
realvalue = -realvalue;
prefix = '-';
@ -398,19 +440,19 @@ static int vxprintf(
else if( flag_blanksign ) prefix = ' ';
else prefix = 0;
}
if( infop->type==etGENERIC && precision>0 ) precision--;
rounder = 0.0;
if( xtype==etGENERIC && precision>0 ) precision--;
#if 0
/* Rounding works like BSD when the constant 0.4999 is used. Wierd! */
for(idx=precision, rounder=0.4999; idx>0; idx--, rounder*=0.1);
#else
/* It makes more sense to use 0.5 */
for(idx=precision, rounder=0.5; idx>0; idx--, rounder*=0.1);
for(idx=precision, rounder=0.5; idx>0; idx--, rounder*=0.1){}
#endif
if( infop->type==etFLOAT ) realvalue += rounder;
if( xtype==etFLOAT ) realvalue += rounder;
/* Normalize realvalue to within 10.0 > realvalue >= 1.0 */
exp = 0;
if( realvalue>0.0 ){
while( realvalue>=1e32 && exp<=350 ){ realvalue *= 1e-32; exp+=32; }
while( realvalue>=1e8 && exp<=350 ){ realvalue *= 1e-8; exp+=8; }
while( realvalue>=10.0 && exp<=350 ){ realvalue *= 0.1; exp++; }
while( realvalue<1e-8 && exp>=-350 ){ realvalue *= 1e8; exp-=8; }
@ -442,51 +484,67 @@ static int vxprintf(
}else{
flag_rtz = 0;
}
/*
** The "exp+precision" test causes output to be of type etEXP if
** the precision is too large to fit in buf[].
*/
if( xtype==etEXP ){
e2 = 0;
}else{
e2 = exp;
}
nsd = 0;
if( xtype==etFLOAT && exp+precision<etBUFSIZE-30 ){
flag_dp = (precision>0 || flag_alternateform);
if( prefix ) *(bufpt++) = prefix; /* Sign */
if( exp<0 ) *(bufpt++) = '0'; /* Digits before "." */
else for(; exp>=0; exp--) *(bufpt++) = et_getdigit(&realvalue,&nsd);
if( flag_dp ) *(bufpt++) = '.'; /* The decimal point */
for(exp++; exp<0 && precision>0; precision--, exp++){
*(bufpt++) = '0';
}
while( (precision--)>0 ) *(bufpt++) = et_getdigit(&realvalue,&nsd);
*(bufpt--) = 0; /* Null terminate */
if( flag_rtz && flag_dp ){ /* Remove trailing zeros and "." */
while( bufpt>=buf && *bufpt=='0' ) *(bufpt--) = 0;
if( bufpt>=buf && *bufpt=='.' ) *(bufpt--) = 0;
}
bufpt++; /* point to next free slot */
}else{ /* etEXP or etGENERIC */
flag_dp = (precision>0 || flag_alternateform);
if( prefix ) *(bufpt++) = prefix; /* Sign */
*(bufpt++) = et_getdigit(&realvalue,&nsd); /* First digit */
if( flag_dp ) *(bufpt++) = '.'; /* Decimal point */
while( (precision--)>0 ) *(bufpt++) = et_getdigit(&realvalue,&nsd);
bufpt--; /* point to last digit */
if( flag_rtz && flag_dp ){ /* Remove tail zeros */
while( bufpt>=buf && *bufpt=='0' ) *(bufpt--) = 0;
if( bufpt>=buf && *bufpt=='.' ) *(bufpt--) = 0;
}
bufpt++; /* point to next free slot */
if( exp || flag_exp ){
*(bufpt++) = infop->charset[0];
if( exp<0 ){ *(bufpt++) = '-'; exp = -exp; } /* sign of exp */
else { *(bufpt++) = '+'; }
if( exp>=100 ){
*(bufpt++) = (exp/100)+'0'; /* 100's digit */
exp %= 100;
}
*(bufpt++) = exp/10+'0'; /* 10's digit */
*(bufpt++) = exp%10+'0'; /* 1's digit */
flag_dp = (precision>0) | flag_alternateform | flag_altform2;
/* The sign in front of the number */
if( prefix ){
*(bufpt++) = prefix;
}
/* Digits prior to the decimal point */
if( e2<0 ){
*(bufpt++) = '0';
}else{
for(; e2>=0; e2--){
*(bufpt++) = et_getdigit(&realvalue,&nsd);
}
}
/* The decimal point */
if( flag_dp ){
*(bufpt++) = '.';
}
/* "0" digits after the decimal point but before the first
** significant digit of the number */
for(e2++; e2<0 && precision>0; precision--, e2++){
*(bufpt++) = '0';
}
/* Significant digits after the decimal point */
while( (precision--)>0 ){
*(bufpt++) = et_getdigit(&realvalue,&nsd);
}
/* Remove trailing zeros and the "." if no digits follow the "." */
if( flag_rtz && flag_dp ){
while( bufpt[-1]=='0' ) *(--bufpt) = 0;
assert( bufpt>buf );
if( bufpt[-1]=='.' ){
if( flag_altform2 ){
*(bufpt++) = '0';
}else{
*(--bufpt) = 0;
}
}
}
/* Add the "eNNN" suffix */
if( flag_exp || (xtype==etEXP && exp) ){
*(bufpt++) = aDigits[infop->charset];
if( exp<0 ){
*(bufpt++) = '-'; exp = -exp;
}else{
*(bufpt++) = '+';
}
if( exp>=100 ){
*(bufpt++) = (exp/100)+'0'; /* 100's digit */
exp %= 100;
}
*(bufpt++) = exp/10+'0'; /* 10's digit */
*(bufpt++) = exp%10+'0'; /* 1's digit */
}
*bufpt = 0;
/* The converted number is in buf[] and zero terminated. Output it.
** Note that the number is in the usual order, not reversed as with
** integer conversions. */
@ -539,37 +597,41 @@ static int vxprintf(
if( precision>=0 && precision<length ) length = precision;
break;
case etSQLESCAPE:
case etSQLESCAPE2:
{
int i, j, n, c, isnull;
char *arg = va_arg(ap,char*);
isnull = arg==0;
if( isnull ) arg = (xtype==etSQLESCAPE2 ? "NULL" : "(NULL)");
for(i=n=0; (c=arg[i])!=0; i++){
if( c=='\'' ) n++;
}
n += i + 1 + ((!isnull && xtype==etSQLESCAPE2) ? 2 : 0);
if( n>etBUFSIZE ){
bufpt = zExtra = sqliteMalloc( n );
if( bufpt==0 ) return -1;
}else{
bufpt = buf;
}
j = 0;
if( !isnull && xtype==etSQLESCAPE2 ) bufpt[j++] = '\'';
for(i=0; (c=arg[i])!=0; i++){
bufpt[j++] = c;
if( c=='\'' ) bufpt[j++] = c;
}
if( !isnull && xtype==etSQLESCAPE2 ) bufpt[j++] = '\'';
bufpt[j] = 0;
length = j;
if( precision>=0 && precision<length ) length = precision;
case etSQLESCAPE2: {
int i, j, n, ch, isnull;
int needQuote;
char *escarg = va_arg(ap,char*);
isnull = escarg==0;
if( isnull ) escarg = (xtype==etSQLESCAPE2 ? "NULL" : "(NULL)");
for(i=n=0; (ch=escarg[i])!=0; i++){
if( ch=='\'' ) n++;
}
needQuote = !isnull && xtype==etSQLESCAPE2;
n += i + 1 + needQuote*2;
if( n>etBUFSIZE ){
bufpt = zExtra = sqliteMalloc( n );
if( bufpt==0 ) return -1;
}else{
bufpt = buf;
}
j = 0;
if( needQuote ) bufpt[j++] = '\'';
for(i=0; (ch=escarg[i])!=0; i++){
bufpt[j++] = ch;
if( ch=='\'' ) bufpt[j++] = ch;
}
if( needQuote ) bufpt[j++] = '\'';
bufpt[j] = 0;
length = j;
/* The precision is ignored on %q and %Q */
/* if( precision>=0 && precision<length ) length = precision; */
break;
}
case etTOKEN: {
Token *pToken = va_arg(ap, Token*);
(*func)(arg, pToken->z, pToken->n);
if( pToken && pToken->z ){
(*func)(arg, (char*)pToken->z, pToken->n);
}
length = width = 0;
break;
}
@ -586,15 +648,6 @@ static int vxprintf(
length = width = 0;
break;
}
case etERROR:
buf[0] = '%';
buf[1] = c;
errorflag = 0;
idx = 1+(c!=0);
(*func)(arg,"%",idx);
count += idx;
if( c==0 ) fmt--;
break;
}/* End switch over the format type */
/*
** The text of the conversion is pointed to by "bufpt" and is
@ -669,13 +722,19 @@ static void mout(void *arg, const char *zNewText, int nNewChar){
memcpy(pM->zText, pM->zBase, pM->nChar);
}
}else{
pM->zText = pM->xRealloc(pM->zText, pM->nAlloc);
char *zNew;
zNew = pM->xRealloc(pM->zText, pM->nAlloc);
if( zNew ){
pM->zText = zNew;
}
}
}
}
if( pM->zText && nNewChar>0 ){
memcpy(&pM->zText[pM->nChar], zNewText, nNewChar);
pM->nChar += nNewChar;
if( pM->zText ){
if( nNewChar>0 ){
memcpy(&pM->zText[pM->nChar], zNewText, nNewChar);
pM->nChar += nNewChar;
}
pM->zText[pM->nChar] = 0;
}
}
@ -701,9 +760,14 @@ static char *base_vprintf(
if( xRealloc ){
if( sM.zText==sM.zBase ){
sM.zText = xRealloc(0, sM.nChar+1);
memcpy(sM.zText, sM.zBase, sM.nChar+1);
if( sM.zText ){
memcpy(sM.zText, sM.zBase, sM.nChar+1);
}
}else if( sM.nAlloc>sM.nChar+10 ){
sM.zText = xRealloc(sM.zText, sM.nChar+1);
char *zNew = xRealloc(sM.zText, sM.nChar+1);
if( zNew ){
sM.zText = zNew;
}
}
}
return sM.zText;
@ -720,8 +784,8 @@ static void *printf_realloc(void *old, int size){
** Print into memory obtained from sqliteMalloc(). Use the internal
** %-conversion extensions.
*/
char *sqliteVMPrintf(const char *zFormat, va_list ap){
char zBase[1000];
char *sqlite3VMPrintf(const char *zFormat, va_list ap){
char zBase[SQLITE_PRINT_BUF_SIZE];
return base_vprintf(printf_realloc, 1, zBase, sizeof(zBase), zFormat, ap);
}
@ -729,10 +793,10 @@ char *sqliteVMPrintf(const char *zFormat, va_list ap){
** Print into memory obtained from sqliteMalloc(). Use the internal
** %-conversion extensions.
*/
char *sqliteMPrintf(const char *zFormat, ...){
char *sqlite3MPrintf(const char *zFormat, ...){
va_list ap;
char *z;
char zBase[1000];
char zBase[SQLITE_PRINT_BUF_SIZE];
va_start(ap, zFormat);
z = base_vprintf(printf_realloc, 1, zBase, sizeof(zBase), zFormat, ap);
va_end(ap);
@ -743,7 +807,7 @@ char *sqliteMPrintf(const char *zFormat, ...){
** Print into memory obtained from malloc(). Do not use the internal
** %-conversion extensions. This routine is for use by external users.
*/
char *sqlite_mprintf(const char *zFormat, ...){
char *sqlite3_mprintf(const char *zFormat, ...){
va_list ap;
char *z;
char zBuf[200];
@ -755,21 +819,21 @@ char *sqlite_mprintf(const char *zFormat, ...){
return z;
}
/* This is the varargs version of sqlite_mprintf.
/* This is the varargs version of sqlite3_mprintf.
*/
char *sqlite_vmprintf(const char *zFormat, va_list ap){
char *sqlite3_vmprintf(const char *zFormat, va_list ap){
char zBuf[200];
return base_vprintf((void*(*)(void*,int))realloc, 0,
zBuf, sizeof(zBuf), zFormat, ap);
}
/*
** sqlite_snprintf() works like snprintf() except that it ignores the
** sqlite3_snprintf() works like snprintf() except that it ignores the
** current locale settings. This is important for SQLite because we
** are not able to use a "," as the decimal point in place of "." as
** specified by some locales.
*/
char *sqlite_snprintf(int n, char *zBuf, const char *zFormat, ...){
char *sqlite3_snprintf(int n, char *zBuf, const char *zFormat, ...){
char *z;
va_list ap;
@ -779,77 +843,20 @@ char *sqlite_snprintf(int n, char *zBuf, const char *zFormat, ...){
return z;
}
#if defined(SQLITE_TEST) || defined(SQLITE_DEBUG)
/*
** The following four routines implement the varargs versions of the
** sqlite_exec() and sqlite_get_table() interfaces. See the sqlite.h
** header files for a more detailed description of how these interfaces
** work.
**
** These routines are all just simple wrappers.
** A version of printf() that understands %lld. Used for debugging.
** The printf() built into some versions of windows does not understand %lld
** and segfaults if you give it a long long int.
*/
int sqlite_exec_printf(
sqlite *db, /* An open database */
const char *sqlFormat, /* printf-style format string for the SQL */
sqlite_callback xCallback, /* Callback function */
void *pArg, /* 1st argument to callback function */
char **errmsg, /* Error msg written here */
... /* Arguments to the format string. */
){
void sqlite3DebugPrintf(const char *zFormat, ...){
extern int getpid(void);
va_list ap;
int rc;
va_start(ap, errmsg);
rc = sqlite_exec_vprintf(db, sqlFormat, xCallback, pArg, errmsg, ap);
char zBuf[500];
va_start(ap, zFormat);
base_vprintf(0, 0, zBuf, sizeof(zBuf), zFormat, ap);
va_end(ap);
return rc;
}
int sqlite_exec_vprintf(
sqlite *db, /* An open database */
const char *sqlFormat, /* printf-style format string for the SQL */
sqlite_callback xCallback, /* Callback function */
void *pArg, /* 1st argument to callback function */
char **errmsg, /* Error msg written here */
va_list ap /* Arguments to the format string. */
){
char *zSql;
int rc;
zSql = sqlite_vmprintf(sqlFormat, ap);
rc = sqlite_exec(db, zSql, xCallback, pArg, errmsg);
free(zSql);
return rc;
}
int sqlite_get_table_printf(
sqlite *db, /* An open database */
const char *sqlFormat, /* printf-style format string for the SQL */
char ***resultp, /* Result written to a char *[] that this points to */
int *nrow, /* Number of result rows written here */
int *ncol, /* Number of result columns written here */
char **errmsg, /* Error msg written here */
... /* Arguments to the format string */
){
va_list ap;
int rc;
va_start(ap, errmsg);
rc = sqlite_get_table_vprintf(db, sqlFormat, resultp, nrow, ncol, errmsg, ap);
va_end(ap);
return rc;
}
int sqlite_get_table_vprintf(
sqlite *db, /* An open database */
const char *sqlFormat, /* printf-style format string for the SQL */
char ***resultp, /* Result written to a char *[] that this points to */
int *nrow, /* Number of result rows written here */
int *ncolumn, /* Number of result columns written here */
char **errmsg, /* Error msg written here */
va_list ap /* Arguments to the format string */
){
char *zSql;
int rc;
zSql = sqlite_vmprintf(sqlFormat, ap);
rc = sqlite_get_table(db, zSql, resultp, nrow, ncolumn, errmsg);
free(zSql);
return rc;
fprintf(stdout,"%d: %s", getpid(), zBuf);
fflush(stdout);
}
#endif

View File

@ -15,7 +15,7 @@
** Random numbers are used by some of the database backends in order
** to generate random integer keys for tables or random filenames.
**
** $Id: random.c,v 1.1.1.1 2004-03-11 22:22:23 alex Exp $
** $Id: random.c,v 1.2 2006-04-13 12:44:29 guy Exp $
*/
#include "sqliteInt.h"
#include "os.h"
@ -26,13 +26,16 @@
** must be held while executing this routine.
**
** Why not just use a library random generator like lrand48() for this?
** Because the OP_NewRecno opcode in the VDBE depends on having a very
** Because the OP_NewRowid opcode in the VDBE depends on having a very
** good source of random numbers. The lrand48() library function may
** well be good enough. But maybe not. Or maybe lrand48() has some
** subtle problems on some systems that could cause problems. It is hard
** to know. To minimize the risk of problems due to bad lrand48()
** implementations, SQLite uses this random number generator based
** on RC4, which we know works very well.
**
** (Later): Actually, OP_NewRowid does not depend on a good source of
** randomness any more. But we will leave this code in all the same.
*/
static int randomByte(){
unsigned char t;
@ -60,7 +63,7 @@ static int randomByte(){
char k[256];
prng.j = 0;
prng.i = 0;
sqliteOsRandomSeed(k);
sqlite3OsRandomSeed(k);
for(i=0; i<256; i++){
prng.s[i] = i;
}
@ -87,11 +90,11 @@ static int randomByte(){
/*
** Return N random bytes.
*/
void sqliteRandomness(int N, void *pBuf){
void sqlite3Randomness(int N, void *pBuf){
unsigned char *zBuf = pBuf;
sqliteOsEnterMutex();
sqlite3OsEnterMutex();
while( N-- ){
*(zBuf++) = randomByte();
}
sqliteOsLeaveMutex();
sqlite3OsLeaveMutex();
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,849 +0,0 @@
/*
** 2001 September 15
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
** This header file defines the interface that the SQLite library
** presents to client programs.
**
** @(#) $Id: sqlite.h,v 1.2 2004-03-29 09:48:53 luca Exp $
*/
#ifndef _SQLITE_H_
#define _SQLITE_H_
#include <stdarg.h> /* Needed for the definition of va_list */
#ifdef WIN32
#ifdef SQLITE_EXPORTS
#define SQLITE_EXPORT __declspec(dllexport)
#else
#define SQLITE_EXPORT __declspec(dllimport)
#endif
#else
#define SQLITE_EXPORT
#endif // WIN32
/*
** Make sure we can call this stuff from C++.
*/
#ifdef __cplusplus
extern "C" {
#endif
/*
** The version of the SQLite library.
*/
#define SQLITE_VERSION "2.8.13"
/*
** The version string is also compiled into the library so that a program
** can check to make sure that the lib*.a file and the *.h file are from
** the same version.
*/
extern const char sqlite_version[];
/*
** The SQLITE_UTF8 macro is defined if the library expects to see
** UTF-8 encoded data. The SQLITE_ISO8859 macro is defined if the
** iso8859 encoded should be used.
*/
#define SQLITE_ISO8859 1
/*
** The following constant holds one of two strings, "UTF-8" or "iso8859",
** depending on which character encoding the SQLite library expects to
** see. The character encoding makes a difference for the LIKE and GLOB
** operators and for the LENGTH() and SUBSTR() functions.
*/
extern const char sqlite_encoding[];
/*
** Each open sqlite database is represented by an instance of the
** following opaque structure.
*/
typedef struct sqlite sqlite;
/*
** A function to open a new sqlite database.
**
** If the database does not exist and mode indicates write
** permission, then a new database is created. If the database
** does not exist and mode does not indicate write permission,
** then the open fails, an error message generated (if errmsg!=0)
** and the function returns 0.
**
** If mode does not indicates user write permission, then the
** database is opened read-only.
**
** The Truth: As currently implemented, all databases are opened
** for writing all the time. Maybe someday we will provide the
** ability to open a database readonly. The mode parameters is
** provided in anticipation of that enhancement.
*/
SQLITE_EXPORT sqlite *sqlite_open(const char *filename, int mode, char **errmsg);
/*
** A function to close the database.
**
** Call this function with a pointer to a structure that was previously
** returned from sqlite_open() and the corresponding database will by closed.
*/
SQLITE_EXPORT void sqlite_close(sqlite *);
/*
** The type for a callback function.
*/
typedef int (*sqlite_callback)(void*,int,char**, char**);
/*
** A function to executes one or more statements of SQL.
**
** If one or more of the SQL statements are queries, then
** the callback function specified by the 3rd parameter is
** invoked once for each row of the query result. This callback
** should normally return 0. If the callback returns a non-zero
** value then the query is aborted, all subsequent SQL statements
** are skipped and the sqlite_exec() function returns the SQLITE_ABORT.
**
** The 4th parameter is an arbitrary pointer that is passed
** to the callback function as its first parameter.
**
** The 2nd parameter to the callback function is the number of
** columns in the query result. The 3rd parameter to the callback
** is an array of strings holding the values for each column.
** The 4th parameter to the callback is an array of strings holding
** the names of each column.
**
** The callback function may be NULL, even for queries. A NULL
** callback is not an error. It just means that no callback
** will be invoked.
**
** If an error occurs while parsing or evaluating the SQL (but
** not while executing the callback) then an appropriate error
** message is written into memory obtained from malloc() and
** *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.)
*/
SQLITE_EXPORT 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 */
);
/*
** Return values for sqlite_exec() and sqlite_step()
*/
#define SQLITE_OK 0 /* Successful result */
#define SQLITE_ERROR 1 /* SQL error or missing database */
#define SQLITE_INTERNAL 2 /* An internal logic error in SQLite */
#define SQLITE_PERM 3 /* Access permission denied */
#define SQLITE_ABORT 4 /* Callback routine requested an abort */
#define SQLITE_BUSY 5 /* The database file is locked */
#define SQLITE_LOCKED 6 /* A table in the database is locked */
#define SQLITE_NOMEM 7 /* A malloc() failed */
#define SQLITE_READONLY 8 /* Attempt to write a readonly database */
#define SQLITE_INTERRUPT 9 /* Operation terminated by sqlite_interrupt() */
#define SQLITE_IOERR 10 /* Some kind of disk I/O error occurred */
#define SQLITE_CORRUPT 11 /* The database disk image is malformed */
#define SQLITE_NOTFOUND 12 /* (Internal Only) Table or record not found */
#define SQLITE_FULL 13 /* Insertion failed because database is full */
#define SQLITE_CANTOPEN 14 /* Unable to open the database file */
#define SQLITE_PROTOCOL 15 /* Database lock protocol error */
#define SQLITE_EMPTY 16 /* (Internal Only) Database table is empty */
#define SQLITE_SCHEMA 17 /* The database schema changed */
#define SQLITE_TOOBIG 18 /* Too much data for one row of a table */
#define SQLITE_CONSTRAINT 19 /* Abort due to contraint violation */
#define SQLITE_MISMATCH 20 /* Data type mismatch */
#define SQLITE_MISUSE 21 /* Library used incorrectly */
#define SQLITE_NOLFS 22 /* Uses OS features not supported on host */
#define SQLITE_AUTH 23 /* Authorization denied */
#define SQLITE_FORMAT 24 /* Auxiliary database format error */
#define SQLITE_RANGE 25 /* 2nd parameter to sqlite_bind out of range */
#define SQLITE_NOTADB 26 /* File opened that is not a database file */
#define SQLITE_ROW 100 /* sqlite_step() has another row ready */
#define SQLITE_DONE 101 /* sqlite_step() has finished executing */
/*
** Each entry in an SQLite table has a unique integer key. (The key is
** the value of the INTEGER PRIMARY KEY column if there is such a column,
** otherwise the key is generated at random. The unique key is always
** available as the ROWID, OID, or _ROWID_ column.) The following routine
** returns the integer key of the most recent insert in the database.
**
** This function is similar to the mysql_insert_id() function from MySQL.
*/
int sqlite_last_insert_rowid(sqlite*);
/*
** This function returns the number of database rows that were changed
** (or inserted or deleted) by the most recent called sqlite_exec().
**
** All changes are counted, even if they were later undone by a
** ROLLBACK or ABORT. Except, changes associated with creating and
** dropping tables are not counted.
**
** If a callback invokes sqlite_exec() recursively, then the changes
** in the inner, recursive call are counted together with the changes
** in the outer call.
**
** SQLite implements the command "DELETE FROM table" without a WHERE clause
** by dropping and recreating the table. (This is much faster than going
** through and deleting individual elements form the table.) Because of
** this optimization, the change count for "DELETE FROM table" will be
** zero regardless of the number of elements that were originally in the
** table. To get an accurate count of the number of rows deleted, use
** "DELETE FROM table WHERE 1" instead.
*/
int sqlite_changes(sqlite*);
/*
** This function returns the number of database rows that were changed
** by the last INSERT, UPDATE, or DELETE statment executed by sqlite_exec(),
** or by the last VM to run to completion. The change count is not updated
** by SQL statements other than INSERT, UPDATE or DELETE.
**
** Changes are counted, even if they are later undone by a ROLLBACK or
** ABORT. Changes associated with trigger programs that execute as a
** result of the INSERT, UPDATE, or DELETE statement are not counted.
**
** If a callback invokes sqlite_exec() recursively, then the changes
** in the inner, recursive call are counted together with the changes
** in the outer call.
**
** SQLite implements the command "DELETE FROM table" without a WHERE clause
** by dropping and recreating the table. (This is much faster than going
** through and deleting individual elements form the table.) Because of
** this optimization, the change count for "DELETE FROM table" will be
** zero regardless of the number of elements that were originally in the
** table. To get an accurate count of the number of rows deleted, use
** "DELETE FROM table WHERE 1" instead.
**
******* THIS IS AN EXPERIMENTAL API AND IS SUBJECT TO CHANGE ******
*/
int sqlite_last_statement_changes(sqlite*);
/* If the parameter to this routine is one of the return value constants
** defined above, then this routine returns a constant text string which
** descripts (in English) the meaning of the return value.
*/
const char *sqlite_error_string(int);
#define sqliteErrStr sqlite_error_string /* Legacy. Do not use in new code. */
/* This function causes any pending database operation to abort and
** return at its earliest opportunity. This routine is typically
** called in response to a user action such as pressing "Cancel"
** or Ctrl-C where the user wants a long query operation to halt
** immediately.
*/
void sqlite_interrupt(sqlite*);
/* This function returns true if the given input string comprises
** one or more complete SQL statements.
**
** 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:
**
** Name | Age
** -----------------------
** Alice | 43
** Bob | 28
** Cindy | 21
**
** If the 3rd argument were &azResult then after the function returns
** azResult will contain the following data:
**
** azResult[0] = "Name";
** azResult[1] = "Age";
** azResult[2] = "Alice";
** azResult[3] = "43";
** azResult[4] = "Bob";
** azResult[5] = "28";
** azResult[6] = "Cindy";
** azResult[7] = "21";
**
** Notice that there is an extra row of data containing the column
** headers. But the *nrow return value is still 3. *ncolumn is
** set to 2. In general, the number of values inserted into azResult
** will be ((*nrow) + 1)*(*ncolumn).
**
** After the calling function has finished using the result, it should
** pass the result data pointer to sqlite_free_table() in order to
** release the memory that was malloc-ed. Because of the way the
** malloc() happens, the calling function must not try to call
** malloc() directly. Only sqlite_free_table() is able to release
** the memory properly and safely.
**
** The return value of this routine is the same as from sqlite_exec().
*/
int sqlite_get_table(
sqlite*, /* An open database */
const char *sql, /* SQL to be executed */
char ***resultp, /* Result written to a char *[] that this points to */
int *nrow, /* Number of result rows written here */
int *ncolumn, /* Number of result columns written here */
char **errmsg /* Error msg written here */
);
/*
** Call this routine to free the memory that sqlite_get_table() allocated.
*/
void sqlite_free_table(char **result);
/*
** The following routines are wrappers around sqlite_exec() and
** sqlite_get_table(). The only difference between the routines that
** follow and the originals is that the second argument to the
** routines that follow is really a printf()-style format
** string describing the SQL to be executed. Arguments to the format
** string appear at the end of the argument list.
**
** All of the usual printf formatting options apply. In addition, there
** is a "%q" option. %q works like %s in that it substitutes a null-terminated
** string from the argument list. But %q also doubles every '\'' character.
** %q is designed for use inside a string literal. By doubling each '\''
** character it escapes that character and allows it to be inserted into
** the string.
**
** For example, so some string variable contains text as follows:
**
** char *zText = "It's a happy day!";
**
** We can use this text in an SQL statement as follows:
**
** sqlite_exec_printf(db, "INSERT INTO table VALUES('%q')",
** callback1, 0, 0, zText);
**
** Because the %q format string is used, the '\'' character in zText
** is escaped and the SQL generated is as follows:
**
** INSERT INTO table1 VALUES('It''s a happy day!')
**
** This is correct. Had we used %s instead of %q, the generated SQL
** would have looked like this:
**
** INSERT INTO table1 VALUES('It's a happy day!');
**
** This second example is an SQL syntax error. As a general rule you
** should always use %q instead of %s when inserting text into a string
** literal.
*/
int sqlite_exec_printf(
sqlite*, /* An open database */
const char *sqlFormat, /* printf-style format string for the SQL */
sqlite_callback, /* Callback function */
void *, /* 1st argument to callback function */
char **errmsg, /* Error msg written here */
... /* Arguments to the format string. */
);
int sqlite_exec_vprintf(
sqlite*, /* An open database */
const char *sqlFormat, /* printf-style format string for the SQL */
sqlite_callback, /* Callback function */
void *, /* 1st argument to callback function */
char **errmsg, /* Error msg written here */
va_list ap /* Arguments to the format string. */
);
int sqlite_get_table_printf(
sqlite*, /* An open database */
const char *sqlFormat, /* printf-style format string for the SQL */
char ***resultp, /* Result written to a char *[] that this points to */
int *nrow, /* Number of result rows written here */
int *ncolumn, /* Number of result columns written here */
char **errmsg, /* Error msg written here */
... /* Arguments to the format string */
);
int sqlite_get_table_vprintf(
sqlite*, /* An open database */
const char *sqlFormat, /* printf-style format string for the SQL */
char ***resultp, /* Result written to a char *[] that this points to */
int *nrow, /* Number of result rows written here */
int *ncolumn, /* Number of result columns written here */
char **errmsg, /* Error msg written here */
va_list ap /* Arguments to the format string */
);
char *sqlite_mprintf(const char*,...);
char *sqlite_vmprintf(const char*, va_list);
/*
** Windows systems should call this routine to free memory that
** is returned in the in the errmsg parameter of sqlite_open() when
** SQLite is a DLL. For some reason, it does not work to call free()
** directly.
*/
SQLITE_EXPORT void sqlite_freemem(void *p);
/*
** Windows systems need functions to call to return the sqlite_version
** and sqlite_encoding strings.
*/
const char *sqlite_libversion(void);
const char *sqlite_libencoding(void);
/*
** A pointer to the following structure is used to communicate with
** the implementations of user-defined functions.
*/
typedef struct sqlite_func sqlite_func;
/*
** Use the following routines to create new user-defined functions. See
** the documentation for details.
*/
int sqlite_create_function(
sqlite*, /* Database where the new function is registered */
const char *zName, /* Name of the new function */
int nArg, /* Number of arguments. -1 means any number */
void (*xFunc)(sqlite_func*,int,const char**), /* C code to implement */
void *pUserData /* Available via the sqlite_user_data() call */
);
int sqlite_create_aggregate(
sqlite*, /* Database where the new function is registered */
const char *zName, /* Name of the function */
int nArg, /* Number of arguments */
void (*xStep)(sqlite_func*,int,const char**), /* Called for each row */
void (*xFinalize)(sqlite_func*), /* Called once to get final result */
void *pUserData /* Available via the sqlite_user_data() call */
);
/*
** Use the following routine to define the datatype returned by a
** user-defined function. The second argument can be one of the
** constants SQLITE_NUMERIC, SQLITE_TEXT, or SQLITE_ARGS or it
** can be an integer greater than or equal to zero. When the datatype
** parameter is non-negative, the type of the result will be the
** same as the datatype-th argument. If datatype==SQLITE_NUMERIC
** then the result is always numeric. If datatype==SQLITE_TEXT then
** the result is always text. If datatype==SQLITE_ARGS then the result
** is numeric if any argument is numeric and is text otherwise.
*/
int sqlite_function_type(
sqlite *db, /* The database there the function is registered */
const char *zName, /* Name of the function */
int datatype /* The datatype for this function */
);
#define SQLITE_NUMERIC (-1)
#define SQLITE_TEXT (-2)
#define SQLITE_ARGS (-3)
/*
** The user function implementations call one of the following four routines
** in order to return their results. The first parameter to each of these
** routines is a copy of the first argument to xFunc() or xFinialize().
** The second parameter to these routines is the result to be returned.
** A NULL can be passed as the second parameter to sqlite_set_result_string()
** in order to return a NULL result.
**
** The 3rd argument to _string and _error is the number of characters to
** take from the string. If this argument is negative, then all characters
** up to and including the first '\000' are used.
**
** The sqlite_set_result_string() function allocates a buffer to hold the
** result and returns a pointer to this buffer. The calling routine
** (that is, the implmentation of a user function) can alter the content
** of this buffer if desired.
*/
char *sqlite_set_result_string(sqlite_func*,const char*,int);
void sqlite_set_result_int(sqlite_func*,int);
void sqlite_set_result_double(sqlite_func*,double);
void sqlite_set_result_error(sqlite_func*,const char*,int);
/*
** The pUserData parameter to the sqlite_create_function() and
** sqlite_create_aggregate() routines used to register user functions
** is available to the implementation of the function using this
** call.
*/
void *sqlite_user_data(sqlite_func*);
/*
** Aggregate functions use the following routine to allocate
** a structure for storing their state. The first time this routine
** is called for a particular aggregate, a new structure of size nBytes
** is allocated, zeroed, and returned. On subsequent calls (for the
** same aggregate instance) the same buffer is returned. The implementation
** of the aggregate can use the returned buffer to accumulate data.
**
** The buffer allocated is freed automatically be SQLite.
*/
void *sqlite_aggregate_context(sqlite_func*, int nBytes);
/*
** The next routine returns the number of calls to xStep for a particular
** aggregate function instance. The current call to xStep counts so this
** routine always returns at least 1.
*/
int sqlite_aggregate_count(sqlite_func*);
/*
** This routine registers a callback with the SQLite library. The
** callback is invoked (at compile-time, not at run-time) for each
** attempt to access a column of a table in the database. The callback
** returns SQLITE_OK if access is allowed, SQLITE_DENY if the entire
** SQL statement should be aborted with an error and SQLITE_IGNORE
** if the column should be treated as a NULL value.
*/
int sqlite_set_authorizer(
sqlite*,
int (*xAuth)(void*,int,const char*,const char*,const char*,const char*),
void *pUserData
);
/*
** The second parameter to the access authorization function above will
** be one of the values below. These values signify what kind of operation
** is to be authorized. The 3rd and 4th parameters to the authorization
** function will be parameters or NULL depending on which of the following
** codes is used as the second parameter. The 5th parameter is the name
** of the database ("main", "temp", etc.) if applicable. The 6th parameter
** is the name of the inner-most trigger or view that is responsible for
** the access attempt or NULL if this access attempt is directly from
** input SQL code.
**
** Arg-3 Arg-4
*/
#define SQLITE_COPY 0 /* Table Name File Name */
#define SQLITE_CREATE_INDEX 1 /* Index Name Table Name */
#define SQLITE_CREATE_TABLE 2 /* Table Name NULL */
#define SQLITE_CREATE_TEMP_INDEX 3 /* Index Name Table Name */
#define SQLITE_CREATE_TEMP_TABLE 4 /* Table Name NULL */
#define SQLITE_CREATE_TEMP_TRIGGER 5 /* Trigger Name Table Name */
#define SQLITE_CREATE_TEMP_VIEW 6 /* View Name NULL */
#define SQLITE_CREATE_TRIGGER 7 /* Trigger Name Table Name */
#define SQLITE_CREATE_VIEW 8 /* View Name NULL */
#define SQLITE_DELETE 9 /* Table Name NULL */
#define SQLITE_DROP_INDEX 10 /* Index Name Table Name */
#define SQLITE_DROP_TABLE 11 /* Table Name NULL */
#define SQLITE_DROP_TEMP_INDEX 12 /* Index Name Table Name */
#define SQLITE_DROP_TEMP_TABLE 13 /* Table Name NULL */
#define SQLITE_DROP_TEMP_TRIGGER 14 /* Trigger Name Table Name */
#define SQLITE_DROP_TEMP_VIEW 15 /* View Name NULL */
#define SQLITE_DROP_TRIGGER 16 /* Trigger Name Table Name */
#define SQLITE_DROP_VIEW 17 /* View Name NULL */
#define SQLITE_INSERT 18 /* Table Name NULL */
#define SQLITE_PRAGMA 19 /* Pragma Name 1st arg or NULL */
#define SQLITE_READ 20 /* Table Name Column Name */
#define SQLITE_SELECT 21 /* NULL NULL */
#define SQLITE_TRANSACTION 22 /* NULL NULL */
#define SQLITE_UPDATE 23 /* Table Name Column Name */
#define SQLITE_ATTACH 24 /* Filename NULL */
#define SQLITE_DETACH 25 /* Database Name NULL */
/*
** The return value of the authorization function should be one of the
** following constants:
*/
/* #define SQLITE_OK 0 // Allow access (This is actually defined above) */
#define SQLITE_DENY 1 /* Abort the SQL statement with an error */
#define SQLITE_IGNORE 2 /* Don't allow access, but don't generate an error */
/*
** Register a function that is called at every invocation of sqlite_exec()
** or sqlite_compile(). This function can be used (for example) to generate
** a log file of all SQL executed against a database.
*/
void *sqlite_trace(sqlite*, void(*xTrace)(void*,const char*), void*);
/*** The Callback-Free API
**
** The following routines implement a new way to access SQLite that does not
** involve the use of callbacks.
**
** An sqlite_vm is an opaque object that represents a single SQL statement
** that is ready to be executed.
*/
typedef struct sqlite_vm sqlite_vm;
/*
** To execute an SQLite query without the use of callbacks, you first have
** to compile the SQL using this routine. The 1st parameter "db" is a pointer
** to an sqlite object obtained from sqlite_open(). The 2nd parameter
** "zSql" is the text of the SQL to be compiled. The remaining parameters
** are all outputs.
**
** *pzTail is made to point to the first character past the end of the first
** SQL statement in zSql. This routine only compiles the first statement
** in zSql, so *pzTail is left pointing to what remains uncompiled.
**
** *ppVm is left pointing to a "virtual machine" that can be used to execute
** the compiled statement. Or if there is an error, *ppVm may be set to NULL.
** If the input text contained no SQL (if the input is and empty string or
** a comment) then *ppVm is set to NULL.
**
** If any errors are detected during compilation, an error message is written
** into space obtained from malloc() and *pzErrMsg is made to point to that
** error message. The calling routine is responsible for freeing the text
** of this message when it has finished with it. Use sqlite_freemem() to
** free the message. pzErrMsg may be NULL in which case no error message
** will be generated.
**
** On success, SQLITE_OK is returned. Otherwise and error code is returned.
*/
int sqlite_compile(
sqlite *db, /* The open database */
const char *zSql, /* SQL statement to be compiled */
const char **pzTail, /* OUT: uncompiled tail of zSql */
sqlite_vm **ppVm, /* OUT: the virtual machine to execute zSql */
char **pzErrmsg /* OUT: Error message. */
);
/*
** After an SQL statement has been compiled, it is handed to this routine
** to be executed. This routine executes the statement as far as it can
** go then returns. The return value will be one of SQLITE_DONE,
** SQLITE_ERROR, SQLITE_BUSY, SQLITE_ROW, or SQLITE_MISUSE.
**
** SQLITE_DONE means that the execute of the SQL statement is complete
** an no errors have occurred. sqlite_step() should not be called again
** for the same virtual machine. *pN is set to the number of columns in
** the result set and *pazColName is set to an array of strings that
** describe the column names and datatypes. The name of the i-th column
** is (*pazColName)[i] and the datatype of the i-th column is
** (*pazColName)[i+*pN]. *pazValue is set to NULL.
**
** 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
** has halted (after a prior call to sqlite_step() has returned SQLITE_DONE)
** or if you call sqlite_step() with an incorrectly initialized virtual
** machine or a virtual machine that has been deleted or that is associated
** with an sqlite structure that has been closed.
*/
int sqlite_step(
sqlite_vm *pVm, /* The virtual machine to execute */
int *pN, /* OUT: Number of columns in result */
const char ***pazValue, /* OUT: Column data */
const char ***pazColName /* OUT: Column names and datatypes */
);
/*
** This routine is called to delete a virtual machine after it has finished
** executing. The return value is the result code. SQLITE_OK is returned
** if the statement executed successfully and some other value is returned if
** there was any kind of error. If an error occurred and pzErrMsg is not
** NULL, then an error message is written into memory obtained from malloc()
** and *pzErrMsg is made to point to that error message. The calling routine
** should use sqlite_freemem() to delete this message when it has finished
** with it.
**
** This routine can be called at any point during the execution of the
** virtual machine. If the virtual machine has not completed execution
** when this routine is called, that is like encountering an error or
** an interrupt. (See sqlite_interrupt().) Incomplete updates may be
** rolled back and transactions cancelled, depending on the circumstances,
** and the result code returned will be SQLITE_ABORT.
*/
int sqlite_finalize(sqlite_vm*, char **pzErrMsg);
/*
** This routine deletes the virtual machine, writes any error message to
** *pzErrMsg and returns an SQLite return code in the same way as the
** sqlite_finalize() function.
**
** Additionally, if ppVm is not NULL, *ppVm is left pointing to a new virtual
** machine loaded with the compiled version of the original query ready for
** execution.
**
** If sqlite_reset() returns SQLITE_SCHEMA, then *ppVm is set to NULL.
**
******* THIS IS AN EXPERIMENTAL API AND IS SUBJECT TO CHANGE ******
*/
int sqlite_reset(sqlite_vm*, char **pzErrMsg);
/*
** If the SQL that was handed to sqlite_compile contains variables that
** are represeted in the SQL text by a question mark ('?'). This routine
** is used to assign values to those variables.
**
** The first parameter is a virtual machine obtained from sqlite_compile().
** The 2nd "idx" parameter determines which variable in the SQL statement
** to bind the value to. The left most '?' is 1. The 3rd parameter is
** the value to assign to that variable. The 4th parameter is the number
** of bytes in the value, including the terminating \000 for strings.
** Finally, the 5th "copy" parameter is TRUE if SQLite should make its
** own private copy of this value, or false if the space that the 3rd
** parameter points to will be unchanging and can be used directly by
** SQLite.
**
** Unbound variables are treated as having a value of NULL. To explicitly
** set a variable to NULL, call this routine with the 3rd parameter as a
** NULL pointer.
**
** If the 4th "len" parameter is -1, then strlen() is used to find the
** length.
**
** This routine can only be called immediately after sqlite_compile()
** or sqlite_reset() and before any calls to sqlite_step().
**
******* THIS IS AN EXPERIMENTAL API AND IS SUBJECT TO CHANGE ******
*/
int sqlite_bind(sqlite_vm*, int idx, const char *value, int len, int copy);
/*
** This routine configures a callback function - the progress callback - that
** is invoked periodically during long running calls to sqlite_exec(),
** sqlite_step() and sqlite_get_table(). An example use for this API is to keep
** a GUI updated during a large query.
**
** The progress callback is invoked once for every N virtual machine opcodes,
** where N is the second argument to this function. The progress callback
** itself is identified by the third argument to this function. The fourth
** argument to this function is a void pointer passed to the progress callback
** function each time it is invoked.
**
** If a call to sqlite_exec(), sqlite_step() or sqlite_get_table() results
** in less than N opcodes being executed, then the progress callback is not
** invoked.
**
** Calling this routine overwrites any previously installed progress callback.
** To remove the progress callback altogether, pass NULL as the third
** argument to this function.
**
** If the progress callback returns a result other than 0, then the current
** query is immediately terminated and any database changes rolled back. If the
** query was part of a larger transaction, then the transaction is not rolled
** back and remains active. The sqlite_exec() call returns SQLITE_ABORT.
**
******* THIS IS AN EXPERIMENTAL API AND IS SUBJECT TO CHANGE ******
*/
void sqlite_progress_handler(sqlite*, int, int(*)(void*), void*);
/*
** Register a callback function to be invoked whenever a new transaction
** is committed. The pArg argument is passed through to the callback.
** callback. If the callback function returns non-zero, then the commit
** is converted into a rollback.
**
** If another function was previously registered, its pArg value is returned.
** Otherwise NULL is returned.
**
** Registering a NULL function disables the callback.
**
******* THIS IS AN EXPERIMENTAL API AND IS SUBJECT TO CHANGE ******
*/
void *sqlite_commit_hook(sqlite*, int(*)(void*), void*);
/*
** Open an encrypted SQLite database. If pKey==0 or nKey==0, this routine
** is the same as sqlite_open().
**
** The code to implement this API is not available in the public release
** of SQLite.
*/
sqlite *sqlite_open_encrypted(
const char *zFilename, /* Name of the encrypted database */
const void *pKey, /* Pointer to the key */
int nKey, /* Number of bytes in the key */
int *pErrcode, /* Write error code here */
char **pzErrmsg /* Write error message here */
);
/*
** Change the key on an open database. If the current database is not
** encrypted, this routine will encrypt it. If pNew==0 or nNew==0, the
** database is decrypted.
**
** The code to implement this API is not available in the public release
** of SQLite.
*/
int sqlite_rekey(
sqlite *db, /* Database to be rekeyed */
const void *pKey, int nKey /* The new key */
);
#ifdef __cplusplus
} /* End of the 'extern "C"' block */
#endif
#endif /* _SQLITE_H_ */

101
sqlite/sqlite3.def Executable file
View File

@ -0,0 +1,101 @@
EXPORTS
sqlite3_aggregate_context
sqlite3_aggregate_count
sqlite3_bind_blob
sqlite3_bind_double
sqlite3_bind_int
sqlite3_bind_int64
sqlite3_bind_null
sqlite3_bind_parameter_count
sqlite3_bind_parameter_index
sqlite3_bind_parameter_name
sqlite3_bind_text
sqlite3_bind_text16
sqlite3_busy_handler
sqlite3_busy_timeout
sqlite3_changes
sqlite3_close
sqlite3_collation_needed
sqlite3_collation_needed16
sqlite3_column_blob
sqlite3_column_bytes
sqlite3_column_bytes16
sqlite3_column_count
sqlite3_column_decltype
sqlite3_column_decltype16
sqlite3_column_double
sqlite3_column_int
sqlite3_column_int64
sqlite3_column_name
sqlite3_column_name16
sqlite3_column_text
sqlite3_column_text16
sqlite3_column_type
sqlite3_commit_hook
sqlite3_complete
sqlite3_complete16
sqlite3_create_collation
sqlite3_create_collation16
sqlite3_create_function
sqlite3_create_function16
sqlite3_data_count
sqlite3_db_handle
sqlite3_enable_shared_cache
sqlite3_errcode
sqlite3_errmsg
sqlite3_errmsg16
sqlite3_exec
sqlite3_expired
sqlite3_finalize
sqlite3_free
sqlite3_free_table
sqlite3_get_autocommit
sqlite3_get_auxdata
sqlite3_get_table
sqlite3_global_recover
sqlite3_interrupt
sqlite3_last_insert_rowid
sqlite3_libversion
sqlite3_libversion_number
sqlite3_mprintf
sqlite3_open
sqlite3_open16
sqlite3_prepare
sqlite3_prepare16
sqlite3_progress_handler
sqlite3_reset
sqlite3_result_blob
sqlite3_result_double
sqlite3_result_error
sqlite3_result_error16
sqlite3_result_int
sqlite3_result_int64
sqlite3_result_null
sqlite3_result_text
sqlite3_result_text16
sqlite3_result_text16be
sqlite3_result_text16le
sqlite3_result_value
sqlite3_rollback_hook
sqlite3_set_authorizer
sqlite3_set_auxdata
sqlite3_snprintf
sqlite3_step
sqlite3_thread_cleanup
sqlite3_total_changes
sqlite3_trace
sqlite3_transfer_bindings
sqlite3_update_hook
sqlite3_user_data
sqlite3_value_blob
sqlite3_value_bytes
sqlite3_value_bytes16
sqlite3_value_double
sqlite3_value_int
sqlite3_value_int64
sqlite3_value_text
sqlite3_value_text16
sqlite3_value_text16be
sqlite3_value_text16le
sqlite3_value_type
sqlite3_vmprintf

1482
sqlite/sqlite3.h Executable file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -9,19 +9,21 @@
** May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains the sqlite_get_table() and sqlite_free_table()
** This file contains the sqlite3_get_table() and sqlite3_free_table()
** interface routines. These are just wrappers around the main
** interface routine of sqlite_exec().
** interface routine of sqlite3_exec().
**
** These routines are in a separate files so that they will not be linked
** if they are not used.
*/
#include "sqliteInt.h"
#include <stdlib.h>
#include <string.h>
#include "sqliteInt.h"
#ifndef SQLITE_OMIT_GET_TABLE
/*
** This structure is used to pass data from sqlite_get_table() through
** This structure is used to pass data from sqlite3_get_table() through
** to the callback function is uses to build the result.
*/
typedef struct TabResult {
@ -40,7 +42,7 @@ typedef struct TabResult {
** is to fill in the TabResult structure appropriately, allocating new
** memory as necessary.
*/
static int sqlite_get_table_cb(void *pArg, int nCol, char **argv, char **colv){
static int sqlite3_get_table_cb(void *pArg, int nCol, char **argv, char **colv){
TabResult *p = (TabResult*)pArg;
int need;
int i;
@ -58,10 +60,7 @@ static int sqlite_get_table_cb(void *pArg, int nCol, char **argv, char **colv){
char **azNew;
p->nAlloc = p->nAlloc*2 + need + 1;
azNew = realloc( p->azResult, sizeof(char*)*p->nAlloc );
if( azNew==0 ){
p->rc = SQLITE_NOMEM;
return 1;
}
if( azNew==0 ) goto malloc_failed;
p->azResult = azNew;
}
@ -75,17 +74,14 @@ static int sqlite_get_table_cb(void *pArg, int nCol, char **argv, char **colv){
z = 0;
}else{
z = malloc( strlen(colv[i])+1 );
if( z==0 ){
p->rc = SQLITE_NOMEM;
return 1;
}
if( z==0 ) goto malloc_failed;
strcpy(z, colv[i]);
}
p->azResult[p->nData++] = z;
}
}else if( p->nColumn!=nCol ){
sqliteSetString(&p->zErrMsg,
"sqlite_get_table() called with two or more incompatible queries",
sqlite3SetString(&p->zErrMsg,
"sqlite3_get_table() called with two or more incompatible queries",
(char*)0);
p->rc = SQLITE_ERROR;
return 1;
@ -99,10 +95,7 @@ static int sqlite_get_table_cb(void *pArg, int nCol, char **argv, char **colv){
z = 0;
}else{
z = malloc( strlen(argv[i])+1 );
if( z==0 ){
p->rc = SQLITE_NOMEM;
return 1;
}
if( z==0 ) goto malloc_failed;
strcpy(z, argv[i]);
}
p->azResult[p->nData++] = z;
@ -110,6 +103,10 @@ static int sqlite_get_table_cb(void *pArg, int nCol, char **argv, char **colv){
p->nRow++;
}
return 0;
malloc_failed:
p->rc = SQLITE_NOMEM;
return 1;
}
/*
@ -119,11 +116,11 @@ static int sqlite_get_table_cb(void *pArg, int nCol, char **argv, char **colv){
**
** The result that is written to ***pazResult is held in memory obtained
** from malloc(). But the caller cannot free this memory directly.
** Instead, the entire table should be passed to sqlite_free_table() when
** Instead, the entire table should be passed to sqlite3_free_table() when
** the calling procedure is finished using it.
*/
int sqlite_get_table(
sqlite *db, /* The database on which the SQL executes */
int sqlite3_get_table(
sqlite3 *db, /* The database on which the SQL executes */
const char *zSql, /* The SQL to be executed */
char ***pazResult, /* Write the result table here */
int *pnRow, /* Write the number of rows in the result here */
@ -144,37 +141,35 @@ int sqlite_get_table(
res.nAlloc = 20;
res.rc = SQLITE_OK;
res.azResult = malloc( sizeof(char*)*res.nAlloc );
if( res.azResult==0 ){
return SQLITE_NOMEM;
}
if( res.azResult==0 ) return SQLITE_NOMEM;
res.azResult[0] = 0;
rc = sqlite_exec(db, zSql, sqlite_get_table_cb, &res, pzErrMsg);
rc = sqlite3_exec(db, zSql, sqlite3_get_table_cb, &res, pzErrMsg);
if( res.azResult ){
assert( sizeof(res.azResult[0])>= sizeof(res.nData) );
res.azResult[0] = (char*)res.nData;
}
if( rc==SQLITE_ABORT ){
sqlite_free_table(&res.azResult[1]);
sqlite3_free_table(&res.azResult[1]);
if( res.zErrMsg ){
if( pzErrMsg ){
free(*pzErrMsg);
*pzErrMsg = res.zErrMsg;
sqliteStrRealloc(pzErrMsg);
}else{
sqliteFree(res.zErrMsg);
*pzErrMsg = sqlite3_mprintf("%s",res.zErrMsg);
}
sqliteFree(res.zErrMsg);
}
db->errCode = res.rc;
return res.rc;
}
sqliteFree(res.zErrMsg);
if( rc!=SQLITE_OK ){
sqlite_free_table(&res.azResult[1]);
sqlite3_free_table(&res.azResult[1]);
return rc;
}
if( res.nAlloc>res.nData ){
char **azNew;
azNew = realloc( res.azResult, sizeof(char*)*(res.nData+1) );
if( azNew==0 ){
sqlite_free_table(&res.azResult[1]);
sqlite3_free_table(&res.azResult[1]);
return SQLITE_NOMEM;
}
res.nAlloc = res.nData+1;
@ -187,10 +182,10 @@ int sqlite_get_table(
}
/*
** This routine frees the space the sqlite_get_table() malloced.
** This routine frees the space the sqlite3_get_table() malloced.
*/
void sqlite_free_table(
char **azResult /* Result returned from from sqlite_get_table() */
void sqlite3_free_table(
char **azResult /* Result returned from from sqlite3_get_table() */
){
if( azResult ){
int i, n;
@ -201,3 +196,5 @@ void sqlite_free_table(
free(azResult);
}
}
#endif /* SQLITE_OMIT_GET_TABLE */

File diff suppressed because it is too large Load Diff

View File

@ -15,7 +15,7 @@
** individual tokens and sends those tokens one-by-one over to the
** parser for analysis.
**
** $Id: tokenize.c,v 1.1.1.1 2004-03-11 22:22:24 alex Exp $
** $Id: tokenize.c,v 1.2 2006-04-13 12:44:29 guy Exp $
*/
#include "sqliteInt.h"
#include "os.h"
@ -23,200 +23,106 @@
#include <stdlib.h>
/*
** All the keywords of the SQL language are stored as in a hash
** table composed of instances of the following structure.
** The charMap() macro maps alphabetic characters into their
** lower-case ASCII equivalent. On ASCII machines, this is just
** an upper-to-lower case map. On EBCDIC machines we also need
** to adjust the encoding. Only alphabetic characters and underscores
** need to be translated.
*/
typedef struct Keyword Keyword;
struct Keyword {
char *zName; /* The keyword name */
u8 tokenType; /* Token value for this keyword */
u8 len; /* Length of this keyword */
u8 iNext; /* Index in aKeywordTable[] of next with same hash */
#ifdef SQLITE_ASCII
# define charMap(X) sqlite3UpperToLower[(unsigned char)X]
#endif
#ifdef SQLITE_EBCDIC
# define charMap(X) ebcdicToAscii[(unsigned char)X]
const unsigned char ebcdicToAscii[] = {
/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1x */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 2x */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 3x */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 4x */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 5x */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 95, 0, 0, /* 6x */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 7x */
0, 97, 98, 99,100,101,102,103,104,105, 0, 0, 0, 0, 0, 0, /* 8x */
0,106,107,108,109,110,111,112,113,114, 0, 0, 0, 0, 0, 0, /* 9x */
0, 0,115,116,117,118,119,120,121,122, 0, 0, 0, 0, 0, 0, /* Ax */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Bx */
0, 97, 98, 99,100,101,102,103,104,105, 0, 0, 0, 0, 0, 0, /* Cx */
0,106,107,108,109,110,111,112,113,114, 0, 0, 0, 0, 0, 0, /* Dx */
0, 0,115,116,117,118,119,120,121,122, 0, 0, 0, 0, 0, 0, /* Ex */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Fx */
};
#endif
/*
** These are the keywords
*/
static Keyword aKeywordTable[] = {
{ "ABORT", TK_ABORT, },
{ "AFTER", TK_AFTER, },
{ "ALL", TK_ALL, },
{ "AND", TK_AND, },
{ "AS", TK_AS, },
{ "ASC", TK_ASC, },
{ "ATTACH", TK_ATTACH, },
{ "BEFORE", TK_BEFORE, },
{ "BEGIN", TK_BEGIN, },
{ "BETWEEN", TK_BETWEEN, },
{ "BY", TK_BY, },
{ "CASCADE", TK_CASCADE, },
{ "CASE", TK_CASE, },
{ "CHECK", TK_CHECK, },
{ "CLUSTER", TK_CLUSTER, },
{ "COLLATE", TK_COLLATE, },
{ "COMMIT", TK_COMMIT, },
{ "CONFLICT", TK_CONFLICT, },
{ "CONSTRAINT", TK_CONSTRAINT, },
{ "COPY", TK_COPY, },
{ "CREATE", TK_CREATE, },
{ "CROSS", TK_JOIN_KW, },
{ "DATABASE", TK_DATABASE, },
{ "DEFAULT", TK_DEFAULT, },
{ "DEFERRED", TK_DEFERRED, },
{ "DEFERRABLE", TK_DEFERRABLE, },
{ "DELETE", TK_DELETE, },
{ "DELIMITERS", TK_DELIMITERS, },
{ "DESC", TK_DESC, },
{ "DETACH", TK_DETACH, },
{ "DISTINCT", TK_DISTINCT, },
{ "DROP", TK_DROP, },
{ "END", TK_END, },
{ "EACH", TK_EACH, },
{ "ELSE", TK_ELSE, },
{ "EXCEPT", TK_EXCEPT, },
{ "EXPLAIN", TK_EXPLAIN, },
{ "FAIL", TK_FAIL, },
{ "FOR", TK_FOR, },
{ "FOREIGN", TK_FOREIGN, },
{ "FROM", TK_FROM, },
{ "FULL", TK_JOIN_KW, },
{ "GLOB", TK_GLOB, },
{ "GROUP", TK_GROUP, },
{ "HAVING", TK_HAVING, },
{ "IGNORE", TK_IGNORE, },
{ "IMMEDIATE", TK_IMMEDIATE, },
{ "IN", TK_IN, },
{ "INDEX", TK_INDEX, },
{ "INITIALLY", TK_INITIALLY, },
{ "INNER", TK_JOIN_KW, },
{ "INSERT", TK_INSERT, },
{ "INSTEAD", TK_INSTEAD, },
{ "INTERSECT", TK_INTERSECT, },
{ "INTO", TK_INTO, },
{ "IS", TK_IS, },
{ "ISNULL", TK_ISNULL, },
{ "JOIN", TK_JOIN, },
{ "KEY", TK_KEY, },
{ "LEFT", TK_JOIN_KW, },
{ "LIKE", TK_LIKE, },
{ "LIMIT", TK_LIMIT, },
{ "MATCH", TK_MATCH, },
{ "NATURAL", TK_JOIN_KW, },
{ "NOT", TK_NOT, },
{ "NOTNULL", TK_NOTNULL, },
{ "NULL", TK_NULL, },
{ "OF", TK_OF, },
{ "OFFSET", TK_OFFSET, },
{ "ON", TK_ON, },
{ "OR", TK_OR, },
{ "ORDER", TK_ORDER, },
{ "OUTER", TK_JOIN_KW, },
{ "PRAGMA", TK_PRAGMA, },
{ "PRIMARY", TK_PRIMARY, },
{ "RAISE", TK_RAISE, },
{ "REFERENCES", TK_REFERENCES, },
{ "REPLACE", TK_REPLACE, },
{ "RESTRICT", TK_RESTRICT, },
{ "RIGHT", TK_JOIN_KW, },
{ "ROLLBACK", TK_ROLLBACK, },
{ "ROW", TK_ROW, },
{ "SELECT", TK_SELECT, },
{ "SET", TK_SET, },
{ "STATEMENT", TK_STATEMENT, },
{ "TABLE", TK_TABLE, },
{ "TEMP", TK_TEMP, },
{ "TEMPORARY", TK_TEMP, },
{ "THEN", TK_THEN, },
{ "TRANSACTION", TK_TRANSACTION, },
{ "TRIGGER", TK_TRIGGER, },
{ "UNION", TK_UNION, },
{ "UNIQUE", TK_UNIQUE, },
{ "UPDATE", TK_UPDATE, },
{ "USING", TK_USING, },
{ "VACUUM", TK_VACUUM, },
{ "VALUES", TK_VALUES, },
{ "VIEW", TK_VIEW, },
{ "WHEN", TK_WHEN, },
{ "WHERE", TK_WHERE, },
};
/*
** This is the hash table
*/
#define KEY_HASH_SIZE 101
static u8 aiHashTable[KEY_HASH_SIZE];
/*
** This function looks up an identifier to determine if it is a
** keyword. If it is a keyword, the token code of that keyword is
** The sqlite3KeywordCode function looks up an identifier to determine if
** it is a keyword. If it is a keyword, the token code of that keyword is
** returned. If the input is not a keyword, TK_ID is returned.
**
** The implementation of this routine was generated by a program,
** mkkeywordhash.h, located in the tool subdirectory of the distribution.
** The output of the mkkeywordhash.c program is written into a file
** named keywordhash.h and then included into this source file by
** the #include below.
*/
int sqliteKeywordCode(const char *z, int n){
int h, i;
Keyword *p;
static char needInit = 1;
if( needInit ){
/* Initialize the keyword hash table */
sqliteOsEnterMutex();
if( needInit ){
int nk;
nk = sizeof(aKeywordTable)/sizeof(aKeywordTable[0]);
for(i=0; i<nk; i++){
aKeywordTable[i].len = strlen(aKeywordTable[i].zName);
h = sqliteHashNoCase(aKeywordTable[i].zName, aKeywordTable[i].len);
h %= KEY_HASH_SIZE;
aKeywordTable[i].iNext = aiHashTable[h];
aiHashTable[h] = i+1;
}
needInit = 0;
}
sqliteOsLeaveMutex();
}
h = sqliteHashNoCase(z, n) % KEY_HASH_SIZE;
for(i=aiHashTable[h]; i; i=p->iNext){
p = &aKeywordTable[i-1];
if( p->len==n && sqliteStrNICmp(p->zName, z, n)==0 ){
return p->tokenType;
}
}
return TK_ID;
}
#include "keywordhash.h"
/*
** If X is a character that can be used in an identifier and
** X&0x80==0 then isIdChar[X] will be 1. If X&0x80==0x80 then
** X is always an identifier character. (Hence all UTF-8
** characters can be part of an identifier). isIdChar[X] will
** be 0 for every character in the lower 128 ASCII characters
** that cannot be used as part of an identifier.
** If X is a character that can be used in an identifier then
** IdChar(X) will be true. Otherwise it is false.
**
** In this implementation, an identifier can be a string of
** alphabetic characters, digits, and "_" plus any character
** with the high-order bit set. The latter rule means that
** any sequence of UTF-8 characters or characters taken from
** an extended ISO8859 character set can form an identifier.
** For ASCII, any character with the high-order bit set is
** allowed in an identifier. For 7-bit characters,
** sqlite3IsIdChar[X] must be 1.
**
** For EBCDIC, the rules are more complex but have the same
** end result.
**
** Ticket #1066. the SQL standard does not allow '$' in the
** middle of identfiers. But many SQL implementations do.
** SQLite will allow '$' in identifiers for compatibility.
** But the feature is undocumented.
*/
static const char isIdChar[] = {
#ifdef SQLITE_ASCII
const char sqlite3IsIdChar[] = {
/* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1x */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 2x */
0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 2x */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 3x */
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 4x */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* 5x */
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 6x */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 7x */
};
#define IdChar(C) (((c=C)&0x80)!=0 || (c>0x1f && sqlite3IsIdChar[c-0x20]))
#endif
#ifdef SQLITE_EBCDIC
const char sqlite3IsIdChar[] = {
/* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */
0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 4x */
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, /* 5x */
0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, /* 6x */
0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, /* 7x */
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, /* 8x */
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, /* 9x */
1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, /* Ax */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Bx */
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, /* Cx */
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, /* Dx */
0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, /* Ex */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, /* Fx */
};
#define IdChar(C) (((c=C)>=0x42 && sqlite3IsIdChar[c-0x40]))
#endif
/*
** Return the length of the token that begins at z[0].
** Store the token type in *tokenType before returning.
*/
static int sqliteGetToken(const unsigned char *z, int *tokenType){
int i;
static int getToken(const unsigned char *z, int *tokenType){
int i, c;
switch( *z ){
case ' ': case '\t': case '\n': case '\f': case '\r': {
for(i=1; isspace(z[i]); i++){}
@ -225,7 +131,7 @@ static int sqliteGetToken(const unsigned char *z, int *tokenType){
}
case '-': {
if( z[1]=='-' ){
for(i=2; z[i] && z[i]!='\n'; i++){}
for(i=2; (c=z[i])!=0 && c!='\n'; i++){}
*tokenType = TK_COMMENT;
return i;
}
@ -257,8 +163,8 @@ static int sqliteGetToken(const unsigned char *z, int *tokenType){
*tokenType = TK_SLASH;
return 1;
}
for(i=3; z[i] && (z[i]!='/' || z[i-1]!='*'); i++){}
if( z[i] ) i++;
for(i=3, c=z[2]; (c!='*' || z[i]!='/') && (c=z[i])!=0; i++){}
if( c ) i++;
*tokenType = TK_COMMENT;
return i;
}
@ -271,13 +177,13 @@ static int sqliteGetToken(const unsigned char *z, int *tokenType){
return 1 + (z[1]=='=');
}
case '<': {
if( z[1]=='=' ){
if( (c=z[1])=='=' ){
*tokenType = TK_LE;
return 2;
}else if( z[1]=='>' ){
}else if( c=='>' ){
*tokenType = TK_NE;
return 2;
}else if( z[1]=='<' ){
}else if( c=='<' ){
*tokenType = TK_LSHIFT;
return 2;
}else{
@ -286,10 +192,10 @@ static int sqliteGetToken(const unsigned char *z, int *tokenType){
}
}
case '>': {
if( z[1]=='=' ){
if( (c=z[1])=='=' ){
*tokenType = TK_GE;
return 2;
}else if( z[1]=='>' ){
}else if( c=='>' ){
*tokenType = TK_RSHIFT;
return 2;
}else{
@ -327,10 +233,12 @@ static int sqliteGetToken(const unsigned char *z, int *tokenType){
*tokenType = TK_BITNOT;
return 1;
}
case '\'': case '"': {
case '`':
case '\'':
case '"': {
int delim = z[0];
for(i=1; z[i]; i++){
if( z[i]==delim ){
for(i=1; (c=z[i])!=0; i++){
if( c==delim ){
if( z[i+1]==delim ){
i++;
}else{
@ -338,20 +246,32 @@ static int sqliteGetToken(const unsigned char *z, int *tokenType){
}
}
}
if( z[i] ) i++;
*tokenType = TK_STRING;
return i;
if( c ){
*tokenType = TK_STRING;
return i+1;
}else{
*tokenType = TK_ILLEGAL;
return i;
}
}
case '.': {
*tokenType = TK_DOT;
return 1;
#ifndef SQLITE_OMIT_FLOATING_POINT
if( !isdigit(z[1]) )
#endif
{
*tokenType = TK_DOT;
return 1;
}
/* If the next character is a digit, this is a floating point
** number that begins with ".". Fall thru into the next case */
}
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9': {
*tokenType = TK_INTEGER;
for(i=1; isdigit(z[i]); i++){}
if( z[i]=='.' && isdigit(z[i+1]) ){
i += 2;
for(i=0; isdigit(z[i]); i++){}
#ifndef SQLITE_OMIT_FLOATING_POINT
if( z[i]=='.' ){
i++;
while( isdigit(z[i]) ){ i++; }
*tokenType = TK_FLOAT;
}
@ -364,29 +284,97 @@ static int sqliteGetToken(const unsigned char *z, int *tokenType){
while( isdigit(z[i]) ){ i++; }
*tokenType = TK_FLOAT;
}
#endif
return i;
}
case '[': {
for(i=1; z[i] && z[i-1]!=']'; i++){}
for(i=1, c=z[0]; c!=']' && (c=z[i])!=0; i++){}
*tokenType = TK_ID;
return i;
}
case '?': {
*tokenType = TK_VARIABLE;
return 1;
for(i=1; isdigit(z[i]); i++){}
return i;
}
case '#': {
for(i=1; isdigit(z[i]); i++){}
if( i>1 ){
/* Parameters of the form #NNN (where NNN is a number) are used
** internally by sqlite3NestedParse. */
*tokenType = TK_REGISTER;
return i;
}
/* Fall through into the next case if the '#' is not followed by
** a digit. Try to match #AAAA where AAAA is a parameter name. */
}
#ifndef SQLITE_OMIT_TCL_VARIABLE
case '$':
#endif
case '@': /* For compatibility with MS SQL Server */
case ':': {
int n = 0;
*tokenType = TK_VARIABLE;
for(i=1; (c=z[i])!=0; i++){
if( IdChar(c) ){
n++;
#ifndef SQLITE_OMIT_TCL_VARIABLE
}else if( c=='(' && n>0 ){
do{
i++;
}while( (c=z[i])!=0 && !isspace(c) && c!=')' );
if( c==')' ){
i++;
}else{
*tokenType = TK_ILLEGAL;
}
break;
}else if( c==':' && z[i+1]==':' ){
i++;
#endif
}else{
break;
}
}
if( n==0 ) *tokenType = TK_ILLEGAL;
return i;
}
#ifndef SQLITE_OMIT_BLOB_LITERAL
case 'x': case 'X': {
if( (c=z[1])=='\'' || c=='"' ){
int delim = c;
*tokenType = TK_BLOB;
for(i=2; (c=z[i])!=0; i++){
if( c==delim ){
if( i%2 ) *tokenType = TK_ILLEGAL;
break;
}
if( !isxdigit(c) ){
*tokenType = TK_ILLEGAL;
return i;
}
}
if( c ) i++;
return i;
}
/* Otherwise fall through to the next case */
}
#endif
default: {
if( (*z&0x80)==0 && !isIdChar[*z] ){
if( !IdChar(*z) ){
break;
}
for(i=1; (z[i]&0x80)!=0 || isIdChar[z[i]]; i++){}
*tokenType = sqliteKeywordCode((char*)z, i);
for(i=1; IdChar(z[i]); i++){}
*tokenType = keywordCode((char*)z, i);
return i;
}
}
*tokenType = TK_ILLEGAL;
return 1;
}
int sqlite3GetToken(const unsigned char *z, int *tokenType){
return getToken(z, tokenType);
}
/*
** Run the parser on the given SQL string. The parser structure is
@ -395,46 +383,54 @@ static int sqliteGetToken(const unsigned char *z, int *tokenType){
** 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 sqlite3RunParser(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*);
sqlite3 *db = pParse->db;
extern void *sqlite3ParserAlloc(void*(*)(int));
extern void sqlite3ParserFree(void*, void(*)(void*));
extern int sqlite3Parser(void*, int, Token, Parse*);
db->flags &= ~SQLITE_Interrupt;
pParse->rc = SQLITE_OK;
i = 0;
pEngine = sqliteParserAlloc((void*(*)(int))malloc);
pEngine = sqlite3ParserAlloc((void*(*)(int))sqlite3MallocX);
if( pEngine==0 ){
sqliteSetString(pzErrMsg, "out of memory", (char*)0);
return 1;
return SQLITE_NOMEM;
}
pParse->sLastToken.dyn = 0;
pParse->zTail = zSql;
while( sqlite_malloc_failed==0 && zSql[i]!=0 ){
assert( pParse->sLastToken.dyn==0 );
assert( pParse->pNewTable==0 );
assert( pParse->pNewTrigger==0 );
assert( pParse->nVar==0 );
assert( pParse->nVarExpr==0 );
assert( pParse->nVarExprAlloc==0 );
assert( pParse->apVarExpr==0 );
pParse->zTail = pParse->zSql = zSql;
while( !sqlite3MallocFailed() && zSql[i]!=0 ){
assert( i>=0 );
pParse->sLastToken.z = &zSql[i];
pParse->sLastToken.z = (u8*)&zSql[i];
assert( pParse->sLastToken.dyn==0 );
pParse->sLastToken.n = sqliteGetToken((unsigned char*)&zSql[i], &tokenType);
pParse->sLastToken.n = getToken((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);
sqlite3SetString(pzErrMsg, "interrupt", (char*)0);
goto abort_parse;
}
break;
}
case TK_ILLEGAL: {
sqliteSetNString(pzErrMsg, "unrecognized token: \"", -1,
pParse->sLastToken.z, pParse->sLastToken.n, "\"", 1, 0);
if( pzErrMsg ){
sqliteFree(*pzErrMsg);
*pzErrMsg = sqlite3MPrintf("unrecognized token: \"%T\"",
&pParse->sLastToken);
}
nErr++;
goto abort_parse;
}
@ -443,7 +439,7 @@ int sqliteRunParser(Parse *pParse, const char *zSql, char **pzErrMsg){
/* Fall thru into the default case */
}
default: {
sqliteParser(pEngine, tokenType, pParse->sLastToken, pParse);
sqlite3Parser(pEngine, tokenType, pParse->sLastToken, pParse);
lastTokenParsed = tokenType;
if( pParse->rc!=SQLITE_OK ){
goto abort_parse;
@ -455,15 +451,17 @@ int sqliteRunParser(Parse *pParse, const char *zSql, char **pzErrMsg){
abort_parse:
if( zSql[i]==0 && nErr==0 && pParse->rc==SQLITE_OK ){
if( lastTokenParsed!=TK_SEMI ){
sqliteParser(pEngine, TK_SEMI, pParse->sLastToken, pParse);
sqlite3Parser(pEngine, TK_SEMI, pParse->sLastToken, pParse);
pParse->zTail = &zSql[i];
}
sqliteParser(pEngine, 0, pParse->sLastToken, pParse);
sqlite3Parser(pEngine, 0, pParse->sLastToken, pParse);
}
sqlite3ParserFree(pEngine, sqlite3FreeX);
if( sqlite3MallocFailed() ){
pParse->rc = SQLITE_NOMEM;
}
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);
sqlite3SetString(&pParse->zErrMsg, sqlite3ErrStr(pParse->rc), (char*)0);
}
if( pParse->zErrMsg ){
if( pzErrMsg && *pzErrMsg==0 ){
@ -474,206 +472,22 @@ abort_parse:
pParse->zErrMsg = 0;
if( !nErr ) nErr++;
}
if( pParse->pVdbe && pParse->nErr>0 ){
sqliteVdbeDelete(pParse->pVdbe);
if( pParse->pVdbe && pParse->nErr>0 && pParse->nested==0 ){
sqlite3VdbeDelete(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;
#ifndef SQLITE_OMIT_SHARED_CACHE
if( pParse->nested==0 ){
sqliteFree(pParse->aTableLock);
pParse->aTableLock = 0;
pParse->nTableLock = 0;
}
#endif
sqlite3DeleteTable(pParse->db, pParse->pNewTable);
sqlite3DeleteTrigger(pParse->pNewTrigger);
sqliteFree(pParse->apVarExpr);
if( nErr>0 && (pParse->rc==SQLITE_OK || pParse->rc==SQLITE_DONE) ){
pParse->rc = SQLITE_ERROR;
}
return nErr;
}
/*
** Token types used by the sqlite_complete() routine. See the header
** comments on that procedure for additional information.
*/
#define tkEXPLAIN 0
#define tkCREATE 1
#define tkTEMP 2
#define tkTRIGGER 3
#define tkEND 4
#define tkSEMI 5
#define tkWS 6
#define tkOTHER 7
/*
** Return TRUE if the given SQL string ends in a semicolon.
**
** Special handling is require for CREATE TRIGGER statements.
** Whenever the CREATE TRIGGER keywords are seen, the statement
** must end with ";END;".
**
** This implementation uses a state machine with 7 states:
**
** (0) START At the beginning or end of an SQL statement. This routine
** returns 1 if it ends in the START state and 0 if it ends
** in any other state.
**
** (1) EXPLAIN The keyword EXPLAIN has been seen at the beginning of
** a statement.
**
** (2) CREATE The keyword CREATE has been seen at the beginning of a
** statement, possibly preceeded by EXPLAIN and/or followed by
** TEMP or TEMPORARY
**
** (3) NORMAL We are in the middle of statement which ends with a single
** semicolon.
**
** (4) TRIGGER We are in the middle of a trigger definition that must be
** ended by a semicolon, the keyword END, and another semicolon.
**
** (5) SEMI We've seen the first semicolon in the ";END;" that occurs at
** the end of a trigger definition.
**
** (6) END We've seen the ";END" of the ";END;" that occurs at the end
** of a trigger difinition.
**
** Transitions between states above are determined by tokens extracted
** from the input. The following tokens are significant:
**
** (0) tkEXPLAIN The "explain" keyword.
** (1) tkCREATE The "create" keyword.
** (2) tkTEMP The "temp" or "temporary" keyword.
** (3) tkTRIGGER The "trigger" keyword.
** (4) tkEND The "end" keyword.
** (5) tkSEMI A semicolon.
** (6) tkWS Whitespace
** (7) tkOTHER Any other SQL token.
**
** Whitespace never causes a state transition and is always ignored.
*/
int sqlite_complete(const char *zSql){
u8 state = 0; /* Current state, using numbers defined in header comment */
u8 token; /* Value of the next token */
/* The following matrix defines the transition from one state to another
** according to what token is seen. trans[state][token] returns the
** next state.
*/
static const u8 trans[7][8] = {
/* Token: */
/* State: ** EXPLAIN CREATE TEMP TRIGGER END SEMI WS OTHER */
/* 0 START: */ { 1, 2, 3, 3, 3, 0, 0, 3, },
/* 1 EXPLAIN: */ { 3, 2, 3, 3, 3, 0, 1, 3, },
/* 2 CREATE: */ { 3, 3, 2, 4, 3, 0, 2, 3, },
/* 3 NORMAL: */ { 3, 3, 3, 3, 3, 0, 3, 3, },
/* 4 TRIGGER: */ { 4, 4, 4, 4, 4, 5, 4, 4, },
/* 5 SEMI: */ { 4, 4, 4, 4, 6, 5, 5, 4, },
/* 6 END: */ { 4, 4, 4, 4, 4, 0, 6, 4, },
};
while( *zSql ){
switch( *zSql ){
case ';': { /* A semicolon */
token = tkSEMI;
break;
}
case ' ':
case '\r':
case '\t':
case '\n':
case '\f': { /* White space is ignored */
token = tkWS;
break;
}
case '/': { /* C-style comments */
if( zSql[1]!='*' ){
token = tkOTHER;
break;
}
zSql += 2;
while( zSql[0] && (zSql[0]!='*' || zSql[1]!='/') ){ zSql++; }
if( zSql[0]==0 ) return 0;
zSql++;
token = tkWS;
break;
}
case '-': { /* SQL-style comments from "--" to end of line */
if( zSql[1]!='-' ){
token = tkOTHER;
break;
}
while( *zSql && *zSql!='\n' ){ zSql++; }
if( *zSql==0 ) return state==0;
token = tkWS;
break;
}
case '[': { /* Microsoft-style identifiers in [...] */
zSql++;
while( *zSql && *zSql!=']' ){ zSql++; }
if( *zSql==0 ) return 0;
token = tkOTHER;
break;
}
case '"': /* single- and double-quoted strings */
case '\'': {
int c = *zSql;
zSql++;
while( *zSql && *zSql!=c ){ zSql++; }
if( *zSql==0 ) return 0;
token = tkOTHER;
break;
}
default: {
if( isIdChar[(u8)*zSql] ){
/* Keywords and unquoted identifiers */
int nId;
for(nId=1; isIdChar[(u8)zSql[nId]]; nId++){}
switch( *zSql ){
case 'c': case 'C': {
if( nId==6 && sqliteStrNICmp(zSql, "create", 6)==0 ){
token = tkCREATE;
}else{
token = tkOTHER;
}
break;
}
case 't': case 'T': {
if( nId==7 && sqliteStrNICmp(zSql, "trigger", 7)==0 ){
token = tkTRIGGER;
}else if( nId==4 && sqliteStrNICmp(zSql, "temp", 4)==0 ){
token = tkTEMP;
}else if( nId==9 && sqliteStrNICmp(zSql, "temporary", 9)==0 ){
token = tkTEMP;
}else{
token = tkOTHER;
}
break;
}
case 'e': case 'E': {
if( nId==3 && sqliteStrNICmp(zSql, "end", 3)==0 ){
token = tkEND;
}else if( nId==7 && sqliteStrNICmp(zSql, "explain", 7)==0 ){
token = tkEXPLAIN;
}else{
token = tkOTHER;
}
break;
}
default: {
token = tkOTHER;
break;
}
}
zSql += nId-1;
}else{
/* Operators and special symbols */
token = tkOTHER;
}
break;
}
}
state = trans[state][token];
zSql++;
}
return state==0;
}

View File

@ -12,19 +12,20 @@
*/
#include "sqliteInt.h"
#ifndef SQLITE_OMIT_TRIGGER
/*
** Delete a linked list of TriggerStep structures.
*/
void sqliteDeleteTriggerStep(TriggerStep *pTriggerStep){
void sqlite3DeleteTriggerStep(TriggerStep *pTriggerStep){
while( pTriggerStep ){
TriggerStep * pTmp = pTriggerStep;
pTriggerStep = pTriggerStep->pNext;
if( pTmp->target.dyn ) sqliteFree((char*)pTmp->target.z);
sqliteExprDelete(pTmp->pWhere);
sqliteExprListDelete(pTmp->pExprList);
sqliteSelectDelete(pTmp->pSelect);
sqliteIdListDelete(pTmp->pIdList);
sqlite3ExprDelete(pTmp->pWhere);
sqlite3ExprListDelete(pTmp->pExprList);
sqlite3SelectDelete(pTmp->pSelect);
sqlite3IdListDelete(pTmp->pIdList);
sqliteFree(pTmp);
}
@ -35,12 +36,13 @@ void sqliteDeleteTriggerStep(TriggerStep *pTriggerStep){
** 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
** sqliteFinishTrigger() function is called to complete the trigger
** sqlite3FinishTrigger() function is called to complete the trigger
** construction process.
*/
void sqliteBeginTrigger(
void sqlite3BeginTrigger(
Parse *pParse, /* The parse context of the CREATE TRIGGER statement */
Token *pName, /* The name of the trigger */
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 */
@ -49,76 +51,108 @@ void sqliteBeginTrigger(
Expr *pWhen, /* WHEN clause */
int isTemp /* True if the TEMPORARY keyword is present */
){
Trigger *nt;
Table *tab;
Trigger *pTrigger = 0;
Table *pTab;
char *zName = 0; /* Name of the trigger */
sqlite *db = pParse->db;
int iDb; /* When database to store the trigger in */
sqlite3 *db = pParse->db;
int iDb; /* The database to store the trigger in */
Token *pName; /* The unqualified db name */
DbFixer sFix;
int iTabDb;
/* 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.
assert( pName1!=0 ); /* pName1->z might be NULL, but not pName1 itself */
assert( pName2!=0 );
if( isTemp ){
/* If TEMP was specified, then the trigger name may not be qualified. */
if( 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( sqlite_malloc_failed ) goto trigger_cleanup;
if( !pTableName || sqlite3MallocFailed() ){
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( sqlite3MallocFailed() ) goto trigger_cleanup;
assert( pTableName->nSrc==1 );
if( db->init.busy
&& sqliteFixInit(&sFix, pParse, db->init.iDb, "trigger", pName)
&& sqliteFixSrcList(&sFix, pTableName)
){
if( sqlite3FixInit(&sFix, pParse, iDb, "trigger", pName) &&
sqlite3FixSrcList(&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);
pTab = sqlite3SrcListLookup(pParse, pTableName);
if( !pTab ){
/* The table does not exist. */
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);
/* 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( sqliteStrNICmp(tab->zName, "sqlite_", 7)==0 ){
sqliteErrorMsg(pParse, "cannot create trigger on system table");
if( sqlite3HashFind(&(db->aDb[iDb].pSchema->trigHash), zName,strlen(zName)) ){
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;
}
if( tab->pSelect && tr_tm != TK_INSTEAD ){
sqliteErrorMsg(pParse, "cannot create %s trigger on view: %S",
/* 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( !tab->pSelect && tr_tm == TK_INSTEAD ){
sqliteErrorMsg(pParse, "cannot create INSTEAD OF"
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[tab->iDb].zName;
const char *zDb = db->aDb[iTabDb].zName;
const char *zDbTrig = isTemp ? db->aDb[1].zName : zDb;
if( tab->iDb==1 || isTemp ) code = SQLITE_CREATE_TEMP_TRIGGER;
if( sqliteAuthCheck(pParse, code, zName, tab->zName, zDbTrig) ){
if( iTabDb==1 || isTemp ) code = SQLITE_CREATE_TEMP_TRIGGER;
if( sqlite3AuthCheck(pParse, code, zName, pTab->zName, zDbTrig) ){
goto trigger_cleanup;
}
if( sqliteAuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(tab->iDb), 0, zDb)){
if( sqlite3AuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(iTabDb),0,zDb)){
goto trigger_cleanup;
}
}
#endif
/* INSTEAD OF triggers can only appear on views and BEGIN triggers
/* 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.
@ -128,53 +162,59 @@ void sqliteBeginTrigger(
}
/* Build the Trigger object */
nt = (Trigger*)sqliteMalloc(sizeof(Trigger));
if( nt==0 ) goto trigger_cleanup;
nt->name = zName;
pTrigger = (Trigger*)sqliteMalloc(sizeof(Trigger));
if( pTrigger==0 ) goto trigger_cleanup;
pTrigger->name = zName;
zName = 0;
nt->table = sqliteStrDup(pTableName->a[0].zName);
if( sqlite_malloc_failed ) goto trigger_cleanup;
nt->iDb = iDb;
nt->iTabDb = tab->iDb;
nt->op = op;
nt->tr_tm = tr_tm;
nt->pWhen = sqliteExprDup(pWhen);
nt->pColumns = sqliteIdListDup(pColumns);
nt->foreach = foreach;
sqliteTokenCopy(&nt->nameToken,pName);
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 = nt;
pParse->pNewTrigger = pTrigger;
trigger_cleanup:
sqliteFree(zName);
sqliteSrcListDelete(pTableName);
sqliteIdListDelete(pColumns);
sqliteExprDelete(pWhen);
sqlite3SrcListDelete(pTableName);
sqlite3IdListDelete(pColumns);
sqlite3ExprDelete(pWhen);
if( !pParse->pNewTrigger ){
sqlite3DeleteTrigger(pTrigger);
}else{
assert( pParse->pNewTrigger==pTrigger );
}
}
/*
** This routine is called after all of the trigger actions have been parsed
** in order to complete the process of building the trigger.
*/
void sqliteFinishTrigger(
void sqlite3FinishTrigger(
Parse *pParse, /* Parser context */
TriggerStep *pStepList, /* The triggered program */
Token *pAll /* Token that describes the complete CREATE TRIGGER */
){
Trigger *nt = 0; /* The trigger whose construction is finishing up */
sqlite *db = pParse->db; /* The database */
Trigger *pTrig = 0; /* The trigger whose construction is finishing up */
sqlite3 *db = pParse->db; /* The database */
DbFixer sFix;
int iDb; /* Database containing the trigger */
if( pParse->nErr || pParse->pNewTrigger==0 ) goto triggerfinish_cleanup;
nt = pParse->pNewTrigger;
pTrig = pParse->pNewTrigger;
pParse->pNewTrigger = 0;
nt->step_list = pStepList;
if( pParse->nErr || !pTrig ) goto triggerfinish_cleanup;
iDb = sqlite3SchemaToIndex(pParse->db, pTrig->pSchema);
pTrig->step_list = pStepList;
while( pStepList ){
pStepList->pTrig = nt;
pStepList->pTrig = pTrig;
pStepList = pStepList->pNext;
}
if( sqliteFixInit(&sFix, pParse, nt->iDb, "trigger", &nt->nameToken)
&& sqliteFixTriggerStep(&sFix, nt->step_list) ){
if( sqlite3FixInit(&sFix, pParse, iDb, "trigger", &pTrig->nameToken)
&& sqlite3FixTriggerStep(&sFix, pTrig->step_list) ){
goto triggerfinish_cleanup;
}
@ -182,51 +222,58 @@ void sqliteFinishTrigger(
** 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 */
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_String, 0, 0, 0 }, /* 5: SQL */
{ OP_MakeRecord, 5, 0, 0 },
{ OP_PutIntKey, 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 = sqliteGetVdbe(pParse);
v = sqlite3GetVdbe(pParse);
if( v==0 ) goto triggerfinish_cleanup;
sqliteBeginWriteOperation(pParse, 0, 0);
sqliteOpenMasterTable(v, nt->iDb);
addr = sqliteVdbeAddOpList(v, ArraySize(insertTrig), insertTrig);
sqliteVdbeChangeP3(v, addr+2, nt->name, 0);
sqliteVdbeChangeP3(v, addr+3, nt->table, 0);
sqliteVdbeChangeP3(v, addr+5, pAll->z, pAll->n);
if( nt->iDb==0 ){
sqliteChangeCookie(db, v);
}
sqliteVdbeAddOp(v, OP_Close, 0, 0);
sqliteEndWriteOperation(pParse);
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( !pParse->explain ){
if( db->init.busy ){
int n;
Table *pTab;
sqliteHashInsert(&db->aDb[nt->iDb].trigHash,
nt->name, strlen(nt->name)+1, nt);
pTab = sqliteLocateTable(pParse, nt->table, db->aDb[nt->iTabDb].zName);
Trigger *pDel;
pDel = sqlite3HashInsert(&db->aDb[iDb].pSchema->trigHash,
pTrig->name, strlen(pTrig->name), pTrig);
if( pDel ){
assert( sqlite3MallocFailed() && pDel==pTrig );
goto triggerfinish_cleanup;
}
n = strlen(pTrig->table) + 1;
pTab = sqlite3HashFind(&pTrig->pTabSchema->tblHash, pTrig->table, n);
assert( pTab!=0 );
nt->pNext = pTab->pTrigger;
pTab->pTrigger = nt;
nt = 0;
pTrig->pNext = pTab->pTrigger;
pTab->pTrigger = pTrig;
pTrig = 0;
}
triggerfinish_cleanup:
sqliteDeleteTrigger(nt);
sqliteDeleteTrigger(pParse->pNewTrigger);
pParse->pNewTrigger = 0;
sqliteDeleteTriggerStep(pStepList);
sqlite3DeleteTrigger(pTrig);
assert( !pParse->pNewTrigger );
sqlite3DeleteTriggerStep(pStepList);
}
/*
@ -234,34 +281,34 @@ triggerfinish_cleanup:
** the effect of copying all Expr.token.z values into memory obtained
** from sqliteMalloc(). As initially created, the Expr.token.z values
** all point to the input string that was fed to the parser. But that
** string is ephemeral - it will go away as soon as the sqlite_exec()
** string is ephemeral - it will go away as soon as the sqlite3_exec()
** call that started the parser exits. This routine makes a persistent
** copy of all the Expr.token.z strings so that the TriggerStep structure
** will be valid even after the sqlite_exec() call returns.
** will be valid even after the sqlite3_exec() call returns.
*/
static void sqlitePersistTriggerStep(TriggerStep *p){
if( p->target.z ){
p->target.z = sqliteStrNDup(p->target.z, p->target.n);
p->target.z = (u8*)sqliteStrNDup((char*)p->target.z, p->target.n);
p->target.dyn = 1;
}
if( p->pSelect ){
Select *pNew = sqliteSelectDup(p->pSelect);
sqliteSelectDelete(p->pSelect);
Select *pNew = sqlite3SelectDup(p->pSelect);
sqlite3SelectDelete(p->pSelect);
p->pSelect = pNew;
}
if( p->pWhere ){
Expr *pNew = sqliteExprDup(p->pWhere);
sqliteExprDelete(p->pWhere);
Expr *pNew = sqlite3ExprDup(p->pWhere);
sqlite3ExprDelete(p->pWhere);
p->pWhere = pNew;
}
if( p->pExprList ){
ExprList *pNew = sqliteExprListDup(p->pExprList);
sqliteExprListDelete(p->pExprList);
ExprList *pNew = sqlite3ExprListDup(p->pExprList);
sqlite3ExprListDelete(p->pExprList);
p->pExprList = pNew;
}
if( p->pIdList ){
IdList *pNew = sqliteIdListDup(p->pIdList);
sqliteIdListDelete(p->pIdList);
IdList *pNew = sqlite3IdListDup(p->pIdList);
sqlite3IdListDelete(p->pIdList);
p->pIdList = pNew;
}
}
@ -273,9 +320,12 @@ static void sqlitePersistTriggerStep(TriggerStep *p){
** The parser calls this routine when it finds a SELECT statement in
** body of a TRIGGER.
*/
TriggerStep *sqliteTriggerSelectStep(Select *pSelect){
TriggerStep *sqlite3TriggerSelectStep(Select *pSelect){
TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep));
if( pTriggerStep==0 ) return 0;
if( pTriggerStep==0 ) {
sqlite3SelectDelete(pSelect);
return 0;
}
pTriggerStep->op = TK_SELECT;
pTriggerStep->pSelect = pSelect;
@ -292,7 +342,7 @@ TriggerStep *sqliteTriggerSelectStep(Select *pSelect){
** The parser calls this routine when it sees an INSERT inside the
** body of a trigger.
*/
TriggerStep *sqliteTriggerInsertStep(
TriggerStep *sqlite3TriggerInsertStep(
Token *pTableName, /* Name of the table into which we insert */
IdList *pColumn, /* List of columns in pTableName to insert into */
ExprList *pEList, /* The VALUE clause: a list of values to be inserted */
@ -300,18 +350,23 @@ TriggerStep *sqliteTriggerInsertStep(
int orconf /* The conflict algorithm (OE_Abort, OE_Replace, etc.) */
){
TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep));
if( pTriggerStep==0 ) return 0;
assert(pEList == 0 || pSelect == 0);
assert(pEList != 0 || pSelect != 0);
pTriggerStep->op = TK_INSERT;
pTriggerStep->pSelect = pSelect;
pTriggerStep->target = *pTableName;
pTriggerStep->pIdList = pColumn;
pTriggerStep->pExprList = pEList;
pTriggerStep->orconf = orconf;
sqlitePersistTriggerStep(pTriggerStep);
if( pTriggerStep ){
pTriggerStep->op = TK_INSERT;
pTriggerStep->pSelect = pSelect;
pTriggerStep->target = *pTableName;
pTriggerStep->pIdList = pColumn;
pTriggerStep->pExprList = pEList;
pTriggerStep->orconf = orconf;
sqlitePersistTriggerStep(pTriggerStep);
}else{
sqlite3IdListDelete(pColumn);
sqlite3ExprListDelete(pEList);
sqlite3SelectDup(pSelect);
}
return pTriggerStep;
}
@ -321,7 +376,7 @@ TriggerStep *sqliteTriggerInsertStep(
** a pointer to that trigger step. The parser calls this routine when it
** sees an UPDATE statement inside the body of a CREATE TRIGGER.
*/
TriggerStep *sqliteTriggerUpdateStep(
TriggerStep *sqlite3TriggerUpdateStep(
Token *pTableName, /* Name of the table to be updated */
ExprList *pEList, /* The SET clause: list of column and new values */
Expr *pWhere, /* The WHERE clause */
@ -345,7 +400,7 @@ TriggerStep *sqliteTriggerUpdateStep(
** a pointer to that trigger step. The parser calls this routine when it
** sees a DELETE statement inside the body of a CREATE TRIGGER.
*/
TriggerStep *sqliteTriggerDeleteStep(Token *pTableName, Expr *pWhere){
TriggerStep *sqlite3TriggerDeleteStep(Token *pTableName, Expr *pWhere){
TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep));
if( pTriggerStep==0 ) return 0;
@ -361,86 +416,90 @@ TriggerStep *sqliteTriggerDeleteStep(Token *pTableName, Expr *pWhere){
/*
** Recursively delete a Trigger structure
*/
void sqliteDeleteTrigger(Trigger *pTrigger){
void sqlite3DeleteTrigger(Trigger *pTrigger){
if( pTrigger==0 ) return;
sqliteDeleteTriggerStep(pTrigger->step_list);
sqlite3DeleteTriggerStep(pTrigger->step_list);
sqliteFree(pTrigger->name);
sqliteFree(pTrigger->table);
sqliteExprDelete(pTrigger->pWhen);
sqliteIdListDelete(pTrigger->pColumns);
sqlite3ExprDelete(pTrigger->pWhen);
sqlite3IdListDelete(pTrigger->pColumns);
if( pTrigger->nameToken.dyn ) sqliteFree((char*)pTrigger->nameToken.z);
sqliteFree(pTrigger);
}
/*
* 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 sqliteDropTriggerPtr() routine does the
* same job as this routine except it take a spointer to the trigger
* instead of the trigger name.
*
* Note that this function does not delete the trigger entirely. Instead it
* removes it from the internal schema and places it in the trigDrop hash
* table. This is so that the trigger can be restored into the database schema
* if the transaction is rolled back.
*/
void sqliteDropTrigger(Parse *pParse, SrcList *pName){
Trigger *pTrigger;
** 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;
sqlite *db = pParse->db;
sqlite3 *db = pParse->db;
if( sqlite3MallocFailed() ) goto drop_trigger_cleanup;
if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){
goto drop_trigger_cleanup;
}
if( sqlite_malloc_failed ) goto drop_trigger_cleanup;
assert( pName->nSrc==1 );
zDb = pName->a[0].zDatabase;
zName = pName->a[0].zName;
nName = strlen(zName);
for(i=0; i<db->nDb; i++){
for(i=OMIT_TEMPDB; i<db->nDb; i++){
int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */
if( zDb && sqliteStrICmp(db->aDb[j].zName, zDb) ) continue;
pTrigger = sqliteHashFind(&(db->aDb[j].trigHash), zName, nName+1);
if( zDb && sqlite3StrICmp(db->aDb[j].zName, zDb) ) continue;
pTrigger = sqlite3HashFind(&(db->aDb[j].pSchema->trigHash), zName, nName);
if( pTrigger ) break;
}
if( !pTrigger ){
sqliteErrorMsg(pParse, "no such trigger: %S", pName, 0);
sqlite3ErrorMsg(pParse, "no such trigger: %S", pName, 0);
goto drop_trigger_cleanup;
}
sqliteDropTriggerPtr(pParse, pTrigger, 0);
sqlite3DropTriggerPtr(pParse, pTrigger);
drop_trigger_cleanup:
sqliteSrcListDelete(pName);
sqlite3SrcListDelete(pName);
}
/*
** Drop a trigger given a pointer to that trigger. If nested is false,
** then also generate code to remove the trigger from the SQLITE_MASTER
** table.
** Return a pointer to the Table structure for the table that a trigger
** is set on.
*/
void sqliteDropTriggerPtr(Parse *pParse, Trigger *pTrigger, int nested){
static Table *tableOfTrigger(Trigger *pTrigger){
int n = strlen(pTrigger->table) + 1;
return sqlite3HashFind(&pTrigger->pTabSchema->tblHash, pTrigger->table, n);
}
/*
** Drop a trigger given a pointer to that trigger.
*/
void sqlite3DropTriggerPtr(Parse *pParse, Trigger *pTrigger){
Table *pTable;
Vdbe *v;
sqlite *db = pParse->db;
sqlite3 *db = pParse->db;
int iDb;
assert( pTrigger->iDb<db->nDb );
if( pTrigger->iDb>=2 ){
sqliteErrorMsg(pParse, "triggers may not be removed from "
"auxiliary database %s", db->aDb[pTrigger->iDb].zName);
return;
}
pTable = sqliteFindTable(db, pTrigger->table,db->aDb[pTrigger->iTabDb].zName);
assert(pTable);
assert( pTable->iDb==pTrigger->iDb || pTrigger->iDb==1 );
iDb = sqlite3SchemaToIndex(pParse->db, pTrigger->pSchema);
assert( iDb>=0 && iDb<db->nDb );
pTable = tableOfTrigger(pTrigger);
assert( pTable );
assert( pTable->pSchema==pTrigger->pSchema || iDb==1 );
#ifndef SQLITE_OMIT_AUTHORIZATION
{
int code = SQLITE_DROP_TRIGGER;
const char *zDb = db->aDb[pTrigger->iDb].zName;
const char *zTab = SCHEMA_TABLE(pTrigger->iDb);
if( pTrigger->iDb ) code = SQLITE_DROP_TEMP_TRIGGER;
if( sqliteAuthCheck(pParse, code, pTrigger->name, pTable->zName, zDb) ||
sqliteAuthCheck(pParse, SQLITE_DELETE, zTab, 0, zDb) ){
const char *zDb = db->aDb[iDb].zName;
const char *zTab = SCHEMA_TABLE(iDb);
if( iDb==1 ) code = SQLITE_DROP_TEMP_TRIGGER;
if( sqlite3AuthCheck(pParse, code, pTrigger->name, pTable->zName, zDb) ||
sqlite3AuthCheck(pParse, SQLITE_DELETE, zTab, 0, zDb) ){
return;
}
}
@ -448,37 +507,42 @@ void sqliteDropTriggerPtr(Parse *pParse, Trigger *pTrigger, int nested){
/* Generate code to destroy the database record of the trigger.
*/
if( pTable!=0 && !nested && (v = sqliteGetVdbe(pParse))!=0 ){
assert( pTable!=0 );
if( (v = sqlite3GetVdbe(pParse))!=0 ){
int base;
static VdbeOpList dropTrigger[] = {
static const VdbeOpList dropTrigger[] = {
{ OP_Rewind, 0, ADDR(9), 0},
{ OP_String, 0, 0, 0}, /* 1 */
{ OP_String8, 0, 0, 0}, /* 1 */
{ OP_Column, 0, 1, 0},
{ OP_Ne, 0, ADDR(8), 0},
{ OP_String, 0, 0, "trigger"},
{ OP_String8, 0, 0, "trigger"},
{ OP_Column, 0, 0, 0},
{ OP_Ne, 0, ADDR(8), 0},
{ OP_Delete, 0, 0, 0},
{ OP_Next, 0, ADDR(1), 0}, /* 8 */
};
sqliteBeginWriteOperation(pParse, 0, 0);
sqliteOpenMasterTable(v, pTrigger->iDb);
base = sqliteVdbeAddOpList(v, ArraySize(dropTrigger), dropTrigger);
sqliteVdbeChangeP3(v, base+1, pTrigger->name, 0);
if( pTrigger->iDb==0 ){
sqliteChangeCookie(db, v);
}
sqliteVdbeAddOp(v, OP_Close, 0, 0);
sqliteEndWriteOperation(pParse);
sqlite3BeginWriteOperation(pParse, 0, iDb);
sqlite3OpenMasterTable(pParse, iDb);
base = sqlite3VdbeAddOpList(v, ArraySize(dropTrigger), dropTrigger);
sqlite3VdbeChangeP3(v, base+1, pTrigger->name, 0);
sqlite3ChangeCookie(db, v, iDb);
sqlite3VdbeAddOp(v, OP_Close, 0, 0);
sqlite3VdbeOp3(v, OP_DropTrigger, iDb, 0, pTrigger->name, 0);
}
}
/*
* If this is not an "explain", then delete the trigger structure.
*/
if( !pParse->explain ){
const char *zName = pTrigger->name;
int nName = strlen(zName);
/*
** Remove a trigger from the hash tables of the sqlite* pointer.
*/
void sqlite3UnlinkAndDeleteTrigger(sqlite3 *db, int iDb, const char *zName){
Trigger *pTrigger;
int nName = strlen(zName);
pTrigger = sqlite3HashInsert(&(db->aDb[iDb].pSchema->trigHash),
zName, nName, 0);
if( pTrigger ){
Table *pTable = tableOfTrigger(pTrigger);
assert( pTable!=0 );
if( pTable->pTrigger == pTrigger ){
pTable->pTrigger = pTrigger->pNext;
}else{
@ -492,8 +556,8 @@ void sqliteDropTriggerPtr(Parse *pParse, Trigger *pTrigger, int nested){
}
assert(cc);
}
sqliteHashInsert(&(db->aDb[pTrigger->iDb].trigHash), zName, nName+1, 0);
sqliteDeleteTrigger(pTrigger);
sqlite3DeleteTrigger(pTrigger);
db->flags |= SQLITE_InternChanges;
}
}
@ -510,57 +574,36 @@ static int checkColumnOverLap(IdList *pIdList, ExprList *pEList){
int e;
if( !pIdList || !pEList ) return 1;
for(e=0; e<pEList->nExpr; e++){
if( sqliteIdListIndex(pIdList, pEList->a[e].zName)>=0 ) return 1;
if( sqlite3IdListIndex(pIdList, pEList->a[e].zName)>=0 ) return 1;
}
return 0;
}
/* A global variable that is TRUE if we should always set up temp tables for
* for triggers, even if there are no triggers to code. This is used to test
* how much overhead the triggers algorithm is causing.
*
* This flag can be set or cleared using the "trigger_overhead_test" pragma.
* The pragma is not documented since it is not really part of the interface
* to SQLite, just the test procedure.
*/
int always_code_trigger_setup = 0;
/*
* Returns true if a trigger matching op, tr_tm and foreach that is NOT already
* on the Parse objects trigger-stack (to prevent recursive trigger firing) is
* found in the list specified as pTrigger.
*/
int sqliteTriggersExist(
** Return a bit vector to indicate what kind of triggers exist for operation
** "op" on table pTab. If pChanges is not NULL then it is a list of columns
** that are being updated. Triggers only match if the ON clause of the
** trigger definition overlaps the set of columns being updated.
**
** The returned bit vector is some combination of TRIGGER_BEFORE and
** TRIGGER_AFTER.
*/
int sqlite3TriggersExist(
Parse *pParse, /* Used to check for recursive triggers */
Trigger *pTrigger, /* A list of triggers associated with a table */
Table *pTab, /* The table the contains the triggers */
int op, /* one of TK_DELETE, TK_INSERT, TK_UPDATE */
int tr_tm, /* one of TK_BEFORE, TK_AFTER */
int foreach, /* one of TK_ROW or TK_STATEMENT */
ExprList *pChanges /* Columns that change in an UPDATE statement */
){
Trigger * pTriggerCursor;
Trigger *pTrigger = pTab->pTrigger;
int mask = 0;
if( always_code_trigger_setup ){
return 1;
}
pTriggerCursor = pTrigger;
while( pTriggerCursor ){
if( pTriggerCursor->op == op &&
pTriggerCursor->tr_tm == tr_tm &&
pTriggerCursor->foreach == foreach &&
checkColumnOverLap(pTriggerCursor->pColumns, pChanges) ){
TriggerStack * ss;
ss = pParse->trigStack;
while( ss && ss->pTrigger != pTrigger ){
ss = ss->pNext;
}
if( !ss )return 1;
while( pTrigger ){
if( pTrigger->op==op && checkColumnOverLap(pTrigger->pColumns, pChanges) ){
mask |= pTrigger->tr_tm;
}
pTriggerCursor = pTriggerCursor->pNext;
pTrigger = pTrigger->pNext;
}
return 0;
return mask;
}
/*
@ -581,14 +624,14 @@ static SrcList *targetSrcList(
int iDb; /* Index of the database to use */
SrcList *pSrc; /* SrcList to be returned */
iDb = pStep->pTrig->iDb;
iDb = sqlite3SchemaToIndex(pParse->db, pStep->pTrig->pSchema);
if( iDb==0 || iDb>=2 ){
assert( iDb<pParse->db->nDb );
sDb.z = pParse->db->aDb[iDb].zName;
sDb.n = strlen(sDb.z);
pSrc = sqliteSrcListAppend(0, &sDb, &pStep->target);
sDb.z = (u8*)pParse->db->aDb[iDb].zName;
sDb.n = strlen((char*)sDb.z);
pSrc = sqlite3SrcListAppend(0, &sDb, &pStep->target);
} else {
pSrc = sqliteSrcListAppend(0, &pStep->target, 0);
pSrc = sqlite3SrcListAppend(0, &pStep->target, 0);
}
return pSrc;
}
@ -604,54 +647,61 @@ static int codeTriggerProgram(
){
TriggerStep * pTriggerStep = pStepList;
int orconf;
Vdbe *v = pParse->pVdbe;
assert( pTriggerStep!=0 );
assert( v!=0 );
sqlite3VdbeAddOp(v, OP_ContextPush, 0, 0);
VdbeComment((v, "# begin trigger %s", pStepList->pTrig->name));
while( pTriggerStep ){
int saveNTab = pParse->nTab;
orconf = (orconfin == OE_Default)?pTriggerStep->orconf:orconfin;
pParse->trigStack->orconf = orconf;
switch( pTriggerStep->op ){
case TK_SELECT: {
Select * ss = sqliteSelectDup(pTriggerStep->pSelect);
Select * ss = sqlite3SelectDup(pTriggerStep->pSelect);
assert(ss);
assert(ss->pSrc);
sqliteSelect(pParse, ss, SRT_Discard, 0, 0, 0, 0);
sqliteSelectDelete(ss);
sqlite3SelectResolve(pParse, ss, 0);
sqlite3Select(pParse, ss, SRT_Discard, 0, 0, 0, 0, 0);
sqlite3SelectDelete(ss);
break;
}
case TK_UPDATE: {
SrcList *pSrc;
pSrc = targetSrcList(pParse, pTriggerStep);
sqliteVdbeAddOp(pParse->pVdbe, OP_ListPush, 0, 0);
sqliteUpdate(pParse, pSrc,
sqliteExprListDup(pTriggerStep->pExprList),
sqliteExprDup(pTriggerStep->pWhere), orconf);
sqliteVdbeAddOp(pParse->pVdbe, OP_ListPop, 0, 0);
sqlite3VdbeAddOp(v, OP_ResetCount, 0, 0);
sqlite3Update(pParse, pSrc,
sqlite3ExprListDup(pTriggerStep->pExprList),
sqlite3ExprDup(pTriggerStep->pWhere), orconf);
sqlite3VdbeAddOp(v, OP_ResetCount, 1, 0);
break;
}
case TK_INSERT: {
SrcList *pSrc;
pSrc = targetSrcList(pParse, pTriggerStep);
sqliteInsert(pParse, pSrc,
sqliteExprListDup(pTriggerStep->pExprList),
sqliteSelectDup(pTriggerStep->pSelect),
sqliteIdListDup(pTriggerStep->pIdList), orconf);
sqlite3VdbeAddOp(v, OP_ResetCount, 0, 0);
sqlite3Insert(pParse, pSrc,
sqlite3ExprListDup(pTriggerStep->pExprList),
sqlite3SelectDup(pTriggerStep->pSelect),
sqlite3IdListDup(pTriggerStep->pIdList), orconf);
sqlite3VdbeAddOp(v, OP_ResetCount, 1, 0);
break;
}
case TK_DELETE: {
SrcList *pSrc;
sqliteVdbeAddOp(pParse->pVdbe, OP_ListPush, 0, 0);
sqlite3VdbeAddOp(v, OP_ResetCount, 0, 0);
pSrc = targetSrcList(pParse, pTriggerStep);
sqliteDeleteFrom(pParse, pSrc, sqliteExprDup(pTriggerStep->pWhere));
sqliteVdbeAddOp(pParse->pVdbe, OP_ListPop, 0, 0);
sqlite3DeleteFrom(pParse, pSrc, sqlite3ExprDup(pTriggerStep->pWhere));
sqlite3VdbeAddOp(v, OP_ResetCount, 1, 0);
break;
}
default:
assert(0);
}
pParse->nTab = saveNTab;
pTriggerStep = pTriggerStep->pNext;
}
sqlite3VdbeAddOp(v, OP_ContextPop, 0, 0);
VdbeComment((v, "# end trigger %s", pStepList->pTrig->name));
return 0;
}
@ -676,89 +726,88 @@ static int codeTriggerProgram(
** trigger program(s).
**
*/
int sqliteCodeRowTrigger(
int sqlite3CodeRowTrigger(
Parse *pParse, /* Parse context */
int op, /* One of TK_UPDATE, TK_INSERT, TK_DELETE */
ExprList *pChanges, /* Changes list for any UPDATE OF triggers */
int tr_tm, /* One of TK_BEFORE, TK_AFTER */
int tr_tm, /* One of TRIGGER_BEFORE, TRIGGER_AFTER */
Table *pTab, /* The table to code triggers from */
int newIdx, /* The indice of the "new" row to access */
int oldIdx, /* The indice of the "old" row to access */
int orconf, /* ON CONFLICT policy */
int ignoreJump /* Instruction to jump to for RAISE(IGNORE) */
){
Trigger * pTrigger;
TriggerStack * pTriggerStack;
Trigger *p;
TriggerStack trigStackEntry;
assert(op == TK_UPDATE || op == TK_INSERT || op == TK_DELETE);
assert(tr_tm == TK_BEFORE || tr_tm == TK_AFTER );
assert(tr_tm == TRIGGER_BEFORE || tr_tm == TRIGGER_AFTER );
assert(newIdx != -1 || oldIdx != -1);
pTrigger = pTab->pTrigger;
while( pTrigger ){
for(p=pTab->pTrigger; p; p=p->pNext){
int fire_this = 0;
/* determine whether we should code this trigger */
if( pTrigger->op == op && pTrigger->tr_tm == tr_tm &&
pTrigger->foreach == TK_ROW ){
fire_this = 1;
pTriggerStack = pParse->trigStack;
while( pTriggerStack ){
if( pTriggerStack->pTrigger == pTrigger ){
fire_this = 0;
}
pTriggerStack = pTriggerStack->pNext;
/* Determine whether we should code this trigger */
if(
p->op==op &&
p->tr_tm==tr_tm &&
(p->pSchema==p->pTabSchema || p->pSchema==pParse->db->aDb[1].pSchema) &&
(op!=TK_UPDATE||!p->pColumns||checkColumnOverLap(p->pColumns,pChanges))
){
TriggerStack *pS; /* Pointer to trigger-stack entry */
for(pS=pParse->trigStack; pS && p!=pS->pTrigger; pS=pS->pNext){}
if( !pS ){
fire_this = 1;
}
if( op == TK_UPDATE && pTrigger->pColumns &&
!checkColumnOverLap(pTrigger->pColumns, pChanges) ){
fire_this = 0;
#if 0 /* Give no warning for recursive triggers. Just do not do them */
else{
sqlite3ErrorMsg(pParse, "recursive triggers not supported (%s)",
p->name);
return SQLITE_ERROR;
}
#endif
}
if( fire_this && (pTriggerStack = sqliteMalloc(sizeof(TriggerStack)))!=0 ){
if( fire_this ){
int endTrigger;
SrcList dummyTablist;
Expr * whenExpr;
AuthContext sContext;
NameContext sNC;
dummyTablist.nSrc = 0;
memset(&sNC, 0, sizeof(sNC));
sNC.pParse = pParse;
/* Push an entry on to the trigger stack */
pTriggerStack->pTrigger = pTrigger;
pTriggerStack->newIdx = newIdx;
pTriggerStack->oldIdx = oldIdx;
pTriggerStack->pTab = pTab;
pTriggerStack->pNext = pParse->trigStack;
pTriggerStack->ignoreJump = ignoreJump;
pParse->trigStack = pTriggerStack;
sqliteAuthContextPush(pParse, &sContext, pTrigger->name);
trigStackEntry.pTrigger = p;
trigStackEntry.newIdx = newIdx;
trigStackEntry.oldIdx = oldIdx;
trigStackEntry.pTab = pTab;
trigStackEntry.pNext = pParse->trigStack;
trigStackEntry.ignoreJump = ignoreJump;
pParse->trigStack = &trigStackEntry;
sqlite3AuthContextPush(pParse, &sContext, p->name);
/* code the WHEN clause */
endTrigger = sqliteVdbeMakeLabel(pParse->pVdbe);
whenExpr = sqliteExprDup(pTrigger->pWhen);
if( sqliteExprResolveIds(pParse, &dummyTablist, 0, whenExpr) ){
pParse->trigStack = pParse->trigStack->pNext;
sqliteFree(pTriggerStack);
sqliteExprDelete(whenExpr);
endTrigger = sqlite3VdbeMakeLabel(pParse->pVdbe);
whenExpr = sqlite3ExprDup(p->pWhen);
if( sqlite3ExprResolveNames(&sNC, whenExpr) ){
pParse->trigStack = trigStackEntry.pNext;
sqlite3ExprDelete(whenExpr);
return 1;
}
sqliteExprIfFalse(pParse, whenExpr, endTrigger, 1);
sqliteExprDelete(whenExpr);
sqlite3ExprIfFalse(pParse, whenExpr, endTrigger, 1);
sqlite3ExprDelete(whenExpr);
sqliteVdbeAddOp(pParse->pVdbe, OP_ContextPush, 0, 0);
codeTriggerProgram(pParse, pTrigger->step_list, orconf);
sqliteVdbeAddOp(pParse->pVdbe, OP_ContextPop, 0, 0);
codeTriggerProgram(pParse, p->step_list, orconf);
/* Pop the entry off the trigger stack */
pParse->trigStack = pParse->trigStack->pNext;
sqliteAuthContextPop(&sContext);
sqliteFree(pTriggerStack);
pParse->trigStack = trigStackEntry.pNext;
sqlite3AuthContextPop(&sContext);
sqliteVdbeResolveLabel(pParse->pVdbe, endTrigger);
sqlite3VdbeResolveLabel(pParse->pVdbe, endTrigger);
}
pTrigger = pTrigger->pNext;
}
return 0;
}
#endif /* !defined(SQLITE_OMIT_TRIGGER) */

View File

@ -12,10 +12,49 @@
** This file contains C code routines that are called by the parser
** to handle UPDATE statements.
**
** $Id: update.c,v 1.1.1.1 2004-03-11 22:22:22 alex Exp $
** $Id: update.c,v 1.2 2006-04-13 12:44:29 guy Exp $
*/
#include "sqliteInt.h"
/*
** The most recently coded instruction was an OP_Column to retrieve the
** i-th column of table pTab. This routine sets the P3 parameter of the
** OP_Column to the default value, if any.
**
** The default value of a column is specified by a DEFAULT clause in the
** column definition. This was either supplied by the user when the table
** was created, or added later to the table definition by an ALTER TABLE
** command. If the latter, then the row-records in the table btree on disk
** may not contain a value for the column and the default value, taken
** from the P3 parameter of the OP_Column instruction, is returned instead.
** If the former, then all row-records are guaranteed to include a value
** for the column and the P3 value is not required.
**
** Column definitions created by an ALTER TABLE command may only have
** literal default values specified: a number, null or a string. (If a more
** complicated default expression value was provided, it is evaluated
** when the ALTER TABLE is executed and one of the literal values written
** into the sqlite_master table.)
**
** Therefore, the P3 parameter is only required if the default value for
** the column is a literal number, string or null. The sqlite3ValueFromExpr()
** function is capable of transforming these types of expressions into
** sqlite3_value objects.
*/
void sqlite3ColumnDefault(Vdbe *v, Table *pTab, int i){
if( pTab && !pTab->pSelect ){
sqlite3_value *pValue;
u8 enc = ENC(sqlite3VdbeDb(v));
Column *pCol = &pTab->aCol[i];
sqlite3ValueFromExpr(pCol->pDflt, enc, pCol->affinity, &pValue);
if( pValue ){
sqlite3VdbeChangeP3(v, -1, (const char *)pValue, P3_MEM);
}else{
VdbeComment((v, "# %s.%s", pTab->zName, pCol->zName));
}
}
}
/*
** Process an UPDATE statement.
**
@ -23,7 +62,7 @@
** \_______/ \________/ \______/ \________________/
* onError pTabList pChanges pWhere
*/
void sqliteUpdate(
void sqlite3Update(
Parse *pParse, /* The parser context */
SrcList *pTabList, /* The table in which we should change things */
ExprList *pChanges, /* Things to be changed */
@ -32,63 +71,78 @@ void sqliteUpdate(
){
int i, j; /* Loop counters */
Table *pTab; /* The table to be updated */
int addr; /* VDBE instruction address of the start of the loop */
int addr = 0; /* VDBE instruction address of the start of the loop */
WhereInfo *pWInfo; /* Information about the WHERE clause */
Vdbe *v; /* The virtual database engine */
Index *pIdx; /* For looping over indices */
int nIdx; /* Number of indices that need updating */
int nIdxTotal; /* Total number of indices */
int iCur; /* VDBE Cursor number of pTab */
sqlite *db; /* The database structure */
sqlite3 *db; /* The database structure */
Index **apIdx = 0; /* An array of indices that need updating too */
char *aIdxUsed = 0; /* aIdxUsed[i]==1 if the i-th index is used */
int *aXRef = 0; /* aXRef[i] is the index in pChanges->a[] of the
** an expression for the i-th column of the table.
** aXRef[i]==-1 if the i-th column is not changed. */
int chngRecno; /* True if the record number is being changed */
Expr *pRecnoExpr; /* Expression defining the new record number */
int openAll; /* True if all indices need to be opened */
int isView; /* Trying to update a view */
int chngRowid; /* True if the record number is being changed */
Expr *pRowidExpr = 0; /* Expression defining the new record number */
int openAll = 0; /* True if all indices need to be opened */
AuthContext sContext; /* The authorization context */
NameContext sNC; /* The name-context to resolve expressions in */
int iDb; /* Database containing the table being updated */
int before_triggers; /* True if there are any BEFORE triggers */
int after_triggers; /* True if there are any AFTER triggers */
int row_triggers_exist = 0; /* True if any row triggers exist */
#ifndef SQLITE_OMIT_TRIGGER
int isView; /* Trying to update a view */
int triggers_exist = 0; /* True if any row triggers exist */
#endif
int newIdx = -1; /* index of trigger "new" temp table */
int oldIdx = -1; /* index of trigger "old" temp table */
sContext.pParse = 0;
if( pParse->nErr || sqlite_malloc_failed ) goto update_cleanup;
if( pParse->nErr || sqlite3MallocFailed() ){
goto update_cleanup;
}
db = pParse->db;
assert( pTabList->nSrc==1 );
/* Locate the table which we want to update.
*/
pTab = sqliteSrcListLookup(pParse, pTabList);
pTab = sqlite3SrcListLookup(pParse, pTabList);
if( pTab==0 ) goto update_cleanup;
before_triggers = sqliteTriggersExist(pParse, pTab->pTrigger,
TK_UPDATE, TK_BEFORE, TK_ROW, pChanges);
after_triggers = sqliteTriggersExist(pParse, pTab->pTrigger,
TK_UPDATE, TK_AFTER, TK_ROW, pChanges);
row_triggers_exist = before_triggers || after_triggers;
iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
/* Figure out if we have any triggers and if the table being
** updated is a view
*/
#ifndef SQLITE_OMIT_TRIGGER
triggers_exist = sqlite3TriggersExist(pParse, pTab, TK_UPDATE, pChanges);
isView = pTab->pSelect!=0;
if( sqliteIsReadOnly(pParse, pTab, before_triggers) ){
#else
# define triggers_exist 0
# define isView 0
#endif
#ifdef SQLITE_OMIT_VIEW
# undef isView
# define isView 0
#endif
if( sqlite3IsReadOnly(pParse, pTab, triggers_exist) ){
goto update_cleanup;
}
if( isView ){
if( sqliteViewGetColumnNames(pParse, pTab) ){
if( sqlite3ViewGetColumnNames(pParse, pTab) ){
goto update_cleanup;
}
}
aXRef = sqliteMalloc( sizeof(int) * pTab->nCol );
aXRef = sqliteMallocRaw( sizeof(int) * pTab->nCol );
if( aXRef==0 ) goto update_cleanup;
for(i=0; i<pTab->nCol; i++) aXRef[i] = -1;
/* If there are FOR EACH ROW triggers, allocate cursors for the
** special OLD and NEW tables
*/
if( row_triggers_exist ){
if( triggers_exist ){
newIdx = pParse->nTab++;
oldIdx = pParse->nTab++;
}
@ -103,44 +157,46 @@ void sqliteUpdate(
pParse->nTab++;
}
/* Initialize the name-context */
memset(&sNC, 0, sizeof(sNC));
sNC.pParse = pParse;
sNC.pSrcList = pTabList;
/* Resolve the column names in all the expressions of the
** of the UPDATE statement. Also find the column index
** for each column to be updated in the pChanges array. For each
** column to be updated, make sure we have authorization to change
** that column.
*/
chngRecno = 0;
chngRowid = 0;
for(i=0; i<pChanges->nExpr; i++){
if( sqliteExprResolveIds(pParse, pTabList, 0, pChanges->a[i].pExpr) ){
goto update_cleanup;
}
if( sqliteExprCheck(pParse, pChanges->a[i].pExpr, 0, 0) ){
if( sqlite3ExprResolveNames(&sNC, pChanges->a[i].pExpr) ){
goto update_cleanup;
}
for(j=0; j<pTab->nCol; j++){
if( sqliteStrICmp(pTab->aCol[j].zName, pChanges->a[i].zName)==0 ){
if( sqlite3StrICmp(pTab->aCol[j].zName, pChanges->a[i].zName)==0 ){
if( j==pTab->iPKey ){
chngRecno = 1;
pRecnoExpr = pChanges->a[i].pExpr;
chngRowid = 1;
pRowidExpr = pChanges->a[i].pExpr;
}
aXRef[j] = i;
break;
}
}
if( j>=pTab->nCol ){
if( sqliteIsRowid(pChanges->a[i].zName) ){
chngRecno = 1;
pRecnoExpr = pChanges->a[i].pExpr;
if( sqlite3IsRowid(pChanges->a[i].zName) ){
chngRowid = 1;
pRowidExpr = pChanges->a[i].pExpr;
}else{
sqliteErrorMsg(pParse, "no such column: %s", pChanges->a[i].zName);
sqlite3ErrorMsg(pParse, "no such column: %s", pChanges->a[i].zName);
goto update_cleanup;
}
}
#ifndef SQLITE_OMIT_AUTHORIZATION
{
int rc;
rc = sqliteAuthCheck(pParse, SQLITE_UPDATE, pTab->zName,
pTab->aCol[j].zName, db->aDb[pTab->iDb].zName);
rc = sqlite3AuthCheck(pParse, SQLITE_UPDATE, pTab->zName,
pTab->aCol[j].zName, db->aDb[iDb].zName);
if( rc==SQLITE_DENY ){
goto update_cleanup;
}else if( rc==SQLITE_IGNORE ){
@ -156,7 +212,7 @@ void sqliteUpdate(
** number of the original table entry is changing.
*/
for(nIdx=nIdxTotal=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdxTotal++){
if( chngRecno ){
if( chngRowid ){
i = 0;
}else {
for(i=0; i<pIdx->nColumn; i++){
@ -166,12 +222,12 @@ void sqliteUpdate(
if( i<pIdx->nColumn ) nIdx++;
}
if( nIdxTotal>0 ){
apIdx = sqliteMalloc( sizeof(Index*) * nIdx + nIdxTotal );
apIdx = sqliteMallocRaw( sizeof(Index*) * nIdx + nIdxTotal );
if( apIdx==0 ) goto update_cleanup;
aIdxUsed = (char*)&apIdx[nIdx];
}
for(nIdx=j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
if( chngRecno ){
if( chngRowid ){
i = 0;
}else{
for(i=0; i<pIdx->nColumn; i++){
@ -189,112 +245,114 @@ void sqliteUpdate(
/* Resolve the column names in all the expressions in the
** WHERE clause.
*/
if( pWhere ){
if( sqliteExprResolveIds(pParse, pTabList, 0, pWhere) ){
goto update_cleanup;
}
if( sqliteExprCheck(pParse, pWhere, 0, 0) ){
goto update_cleanup;
}
if( sqlite3ExprResolveNames(&sNC, pWhere) ){
goto update_cleanup;
}
/* Start the view context
*/
if( isView ){
sqliteAuthContextPush(pParse, &sContext, pTab->zName);
sqlite3AuthContextPush(pParse, &sContext, pTab->zName);
}
/* Begin generating code.
*/
v = sqliteGetVdbe(pParse);
v = sqlite3GetVdbe(pParse);
if( v==0 ) goto update_cleanup;
sqliteBeginWriteOperation(pParse, 1, pTab->iDb);
if( pParse->nested==0 ) sqlite3VdbeCountChanges(v);
sqlite3BeginWriteOperation(pParse, 1, iDb);
/* If we are trying to update a view, construct that view into
** a temporary table.
/* If we are trying to update a view, realize that view into
** a ephemeral table.
*/
if( isView ){
Select *pView;
pView = sqliteSelectDup(pTab->pSelect);
sqliteSelect(pParse, pView, SRT_TempTable, iCur, 0, 0, 0);
sqliteSelectDelete(pView);
pView = sqlite3SelectDup(pTab->pSelect);
sqlite3Select(pParse, pView, SRT_VirtualTab, iCur, 0, 0, 0, 0);
sqlite3SelectDelete(pView);
}
/* Begin the database scan
*/
pWInfo = sqliteWhereBegin(pParse, pTabList, pWhere, 1, 0);
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0);
if( pWInfo==0 ) goto update_cleanup;
/* Remember the index of every item to be updated.
*/
sqliteVdbeAddOp(v, OP_ListWrite, 0, 0);
sqlite3VdbeAddOp(v, OP_Rowid, iCur, 0);
sqlite3VdbeAddOp(v, OP_FifoWrite, 0, 0);
/* End the database scan loop.
*/
sqliteWhereEnd(pWInfo);
sqlite3WhereEnd(pWInfo);
/* Initialize the count of updated rows
*/
if( db->flags & SQLITE_CountRows && !pParse->trigStack ){
sqliteVdbeAddOp(v, OP_Integer, 0, 0);
sqlite3VdbeAddOp(v, OP_Integer, 0, 0);
}
if( row_triggers_exist ){
if( triggers_exist ){
/* Create pseudo-tables for NEW and OLD
*/
sqliteVdbeAddOp(v, OP_OpenPseudo, oldIdx, 0);
sqliteVdbeAddOp(v, OP_OpenPseudo, newIdx, 0);
sqlite3VdbeAddOp(v, OP_OpenPseudo, oldIdx, 0);
sqlite3VdbeAddOp(v, OP_SetNumColumns, oldIdx, pTab->nCol);
sqlite3VdbeAddOp(v, OP_OpenPseudo, newIdx, 0);
sqlite3VdbeAddOp(v, OP_SetNumColumns, newIdx, pTab->nCol);
/* The top of the update loop for when there are triggers.
*/
sqliteVdbeAddOp(v, OP_ListRewind, 0, 0);
addr = sqliteVdbeAddOp(v, OP_ListRead, 0, 0);
sqliteVdbeAddOp(v, OP_Dup, 0, 0);
addr = sqlite3VdbeAddOp(v, OP_FifoRead, 0, 0);
/* Open a cursor and make it point to the record that is
** being updated.
*/
sqliteVdbeAddOp(v, OP_Dup, 0, 0);
if( !isView ){
sqliteVdbeAddOp(v, OP_Integer, pTab->iDb, 0);
sqliteVdbeAddOp(v, OP_OpenRead, iCur, pTab->tnum);
sqlite3VdbeAddOp(v, OP_Dup, 0, 0);
sqlite3VdbeAddOp(v, OP_Dup, 0, 0);
/* Open a cursor and make it point to the record that is
** being updated.
*/
sqlite3OpenTable(pParse, iCur, iDb, pTab, OP_OpenRead);
}
sqliteVdbeAddOp(v, OP_MoveTo, iCur, 0);
sqlite3VdbeAddOp(v, OP_MoveGe, iCur, 0);
/* Generate the OLD table
*/
sqliteVdbeAddOp(v, OP_Recno, iCur, 0);
sqliteVdbeAddOp(v, OP_RowData, iCur, 0);
sqliteVdbeAddOp(v, OP_PutIntKey, oldIdx, 0);
sqlite3VdbeAddOp(v, OP_Rowid, iCur, 0);
sqlite3VdbeAddOp(v, OP_RowData, iCur, 0);
sqlite3VdbeAddOp(v, OP_Insert, oldIdx, 0);
/* Generate the NEW table
*/
if( chngRecno ){
sqliteExprCode(pParse, pRecnoExpr);
if( chngRowid ){
sqlite3ExprCodeAndCache(pParse, pRowidExpr);
}else{
sqliteVdbeAddOp(v, OP_Recno, iCur, 0);
sqlite3VdbeAddOp(v, OP_Rowid, iCur, 0);
}
for(i=0; i<pTab->nCol; i++){
if( i==pTab->iPKey ){
sqliteVdbeAddOp(v, OP_String, 0, 0);
sqlite3VdbeAddOp(v, OP_Null, 0, 0);
continue;
}
j = aXRef[i];
if( j<0 ){
sqliteVdbeAddOp(v, OP_Column, iCur, i);
sqlite3VdbeAddOp(v, OP_Column, iCur, i);
sqlite3ColumnDefault(v, pTab, i);
}else{
sqliteExprCode(pParse, pChanges->a[j].pExpr);
sqlite3ExprCodeAndCache(pParse, pChanges->a[j].pExpr);
}
}
sqliteVdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0);
sqliteVdbeAddOp(v, OP_PutIntKey, newIdx, 0);
sqlite3VdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0);
if( !isView ){
sqliteVdbeAddOp(v, OP_Close, iCur, 0);
sqlite3TableAffinityStr(v, pTab);
}
if( pParse->nErr ) goto update_cleanup;
sqlite3VdbeAddOp(v, OP_Insert, newIdx, 0);
if( !isView ){
sqlite3VdbeAddOp(v, OP_Close, iCur, 0);
}
/* Fire the BEFORE and INSTEAD OF triggers
*/
if( sqliteCodeRowTrigger(pParse, TK_UPDATE, pChanges, TK_BEFORE, pTab,
if( sqlite3CodeRowTrigger(pParse, TK_UPDATE, pChanges, TRIGGER_BEFORE, pTab,
newIdx, oldIdx, onError, addr) ){
goto update_cleanup;
}
@ -307,8 +365,7 @@ void sqliteUpdate(
** action, then we need to open all indices because we might need
** to be deleting some records.
*/
sqliteVdbeAddOp(v, OP_Integer, pTab->iDb, 0);
sqliteVdbeAddOp(v, OP_OpenWrite, iCur, pTab->tnum);
sqlite3OpenTable(pParse, iCur, iDb, pTab, OP_OpenWrite);
if( onError==OE_Replace ){
openAll = 1;
}else{
@ -322,8 +379,10 @@ void sqliteUpdate(
}
for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
if( openAll || aIdxUsed[i] ){
sqliteVdbeAddOp(v, OP_Integer, pIdx->iDb, 0);
sqliteVdbeAddOp(v, OP_OpenWrite, iCur+i+1, pIdx->tnum);
KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIdx);
sqlite3VdbeAddOp(v, OP_Integer, iDb, 0);
sqlite3VdbeOp3(v, OP_OpenWrite, iCur+i+1, pIdx->tnum,
(char*)pKey, P3_KEYINFO_HANDOFF);
assert( pParse->nTab>iCur+i+1 );
}
}
@ -334,76 +393,75 @@ void sqliteUpdate(
** Also, the old data is needed to delete the old index entires.
** So make the cursor point at the old record.
*/
if( !row_triggers_exist ){
sqliteVdbeAddOp(v, OP_ListRewind, 0, 0);
addr = sqliteVdbeAddOp(v, OP_ListRead, 0, 0);
sqliteVdbeAddOp(v, OP_Dup, 0, 0);
if( !triggers_exist ){
addr = sqlite3VdbeAddOp(v, OP_FifoRead, 0, 0);
sqlite3VdbeAddOp(v, OP_Dup, 0, 0);
}
sqliteVdbeAddOp(v, OP_NotExists, iCur, addr);
sqlite3VdbeAddOp(v, OP_NotExists, iCur, addr);
/* If the record number will change, push the record number as it
** will be after the update. (The old record number is currently
** on top of the stack.)
*/
if( chngRecno ){
sqliteExprCode(pParse, pRecnoExpr);
sqliteVdbeAddOp(v, OP_MustBeInt, 0, 0);
if( chngRowid ){
sqlite3ExprCode(pParse, pRowidExpr);
sqlite3VdbeAddOp(v, OP_MustBeInt, 0, 0);
}
/* Compute new data for this record.
*/
for(i=0; i<pTab->nCol; i++){
if( i==pTab->iPKey ){
sqliteVdbeAddOp(v, OP_String, 0, 0);
sqlite3VdbeAddOp(v, OP_Null, 0, 0);
continue;
}
j = aXRef[i];
if( j<0 ){
sqliteVdbeAddOp(v, OP_Column, iCur, i);
sqlite3VdbeAddOp(v, OP_Column, iCur, i);
sqlite3ColumnDefault(v, pTab, i);
}else{
sqliteExprCode(pParse, pChanges->a[j].pExpr);
sqlite3ExprCode(pParse, pChanges->a[j].pExpr);
}
}
/* Do constraint checks
*/
sqliteGenerateConstraintChecks(pParse, pTab, iCur, aIdxUsed, chngRecno, 1,
sqlite3GenerateConstraintChecks(pParse, pTab, iCur, aIdxUsed, chngRowid, 1,
onError, addr);
/* Delete the old indices for the current record.
*/
sqliteGenerateRowIndexDelete(db, v, pTab, iCur, aIdxUsed);
sqlite3GenerateRowIndexDelete(v, pTab, iCur, aIdxUsed);
/* If changing the record number, delete the old record.
*/
if( chngRecno ){
sqliteVdbeAddOp(v, OP_Delete, iCur, 0);
if( chngRowid ){
sqlite3VdbeAddOp(v, OP_Delete, iCur, 0);
}
/* Create the new index entries and the new record.
*/
sqliteCompleteInsertion(pParse, pTab, iCur, aIdxUsed, chngRecno, 1, -1);
sqlite3CompleteInsertion(pParse, pTab, iCur, aIdxUsed, chngRowid, 1, -1);
}
/* Increment the row counter
*/
if( db->flags & SQLITE_CountRows && !pParse->trigStack){
sqliteVdbeAddOp(v, OP_AddImm, 1, 0);
sqlite3VdbeAddOp(v, OP_AddImm, 1, 0);
}
/* If there are triggers, close all the cursors after each iteration
** through the loop. The fire the after triggers.
*/
if( row_triggers_exist ){
if( triggers_exist ){
if( !isView ){
for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
if( openAll || aIdxUsed[i] )
sqliteVdbeAddOp(v, OP_Close, iCur+i+1, 0);
sqlite3VdbeAddOp(v, OP_Close, iCur+i+1, 0);
}
sqliteVdbeAddOp(v, OP_Close, iCur, 0);
pParse->nTab = iCur;
sqlite3VdbeAddOp(v, OP_Close, iCur, 0);
}
if( sqliteCodeRowTrigger(pParse, TK_UPDATE, pChanges, TK_AFTER, pTab,
if( sqlite3CodeRowTrigger(pParse, TK_UPDATE, pChanges, TRIGGER_AFTER, pTab,
newIdx, oldIdx, onError, addr) ){
goto update_cleanup;
}
@ -412,41 +470,39 @@ void sqliteUpdate(
/* Repeat the above with the next record to be updated, until
** all record selected by the WHERE clause have been updated.
*/
sqliteVdbeAddOp(v, OP_Goto, 0, addr);
sqliteVdbeChangeP2(v, addr, sqliteVdbeCurrentAddr(v));
sqliteVdbeAddOp(v, OP_ListReset, 0, 0);
sqlite3VdbeAddOp(v, OP_Goto, 0, addr);
sqlite3VdbeJumpHere(v, addr);
/* Close all tables if there were no FOR EACH ROW triggers */
if( !row_triggers_exist ){
if( !triggers_exist ){
for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
if( openAll || aIdxUsed[i] ){
sqliteVdbeAddOp(v, OP_Close, iCur+i+1, 0);
sqlite3VdbeAddOp(v, OP_Close, iCur+i+1, 0);
}
}
sqliteVdbeAddOp(v, OP_Close, iCur, 0);
pParse->nTab = iCur;
sqlite3VdbeAddOp(v, OP_Close, iCur, 0);
}else{
sqliteVdbeAddOp(v, OP_Close, newIdx, 0);
sqliteVdbeAddOp(v, OP_Close, oldIdx, 0);
sqlite3VdbeAddOp(v, OP_Close, newIdx, 0);
sqlite3VdbeAddOp(v, OP_Close, oldIdx, 0);
}
sqliteVdbeAddOp(v, OP_SetCounts, 0, 0);
sqliteEndWriteOperation(pParse);
/*
** Return the number of rows that were changed.
** Return the number of rows that were changed. If this routine is
** generating code because of a call to sqlite3NestedParse(), do not
** invoke the callback function.
*/
if( db->flags & SQLITE_CountRows && !pParse->trigStack ){
sqliteVdbeOp3(v, OP_ColumnName, 0, 1, "rows updated", P3_STATIC);
sqliteVdbeAddOp(v, OP_Callback, 1, 0);
if( db->flags & SQLITE_CountRows && !pParse->trigStack && pParse->nested==0 ){
sqlite3VdbeAddOp(v, OP_Callback, 1, 0);
sqlite3VdbeSetNumCols(v, 1);
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows updated", P3_STATIC);
}
update_cleanup:
sqliteAuthContextPop(&sContext);
sqlite3AuthContextPop(&sContext);
sqliteFree(apIdx);
sqliteFree(aXRef);
sqliteSrcListDelete(pTabList);
sqliteExprListDelete(pChanges);
sqliteExprDelete(pWhere);
sqlite3SrcListDelete(pTabList);
sqlite3ExprListDelete(pChanges);
sqlite3ExprDelete(pWhere);
return;
}

596
sqlite/utf.c Executable file
View File

@ -0,0 +1,596 @@
/*
** 2004 April 13
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains routines used to translate between UTF-8,
** UTF-16, UTF-16BE, and UTF-16LE.
**
** $Id: utf.c,v 1.1 2006-04-13 12:44:29 guy Exp $
**
** Notes on UTF-8:
**
** Byte-0 Byte-1 Byte-2 Byte-3 Value
** 0xxxxxxx 00000000 00000000 0xxxxxxx
** 110yyyyy 10xxxxxx 00000000 00000yyy yyxxxxxx
** 1110zzzz 10yyyyyy 10xxxxxx 00000000 zzzzyyyy yyxxxxxx
** 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx 000uuuuu zzzzyyyy yyxxxxxx
**
**
** Notes on UTF-16: (with wwww+1==uuuuu)
**
** Word-0 Word-1 Value
** 110110ww wwzzzzyy 110111yy yyxxxxxx 000uuuuu zzzzyyyy yyxxxxxx
** zzzzyyyy yyxxxxxx 00000000 zzzzyyyy yyxxxxxx
**
**
** BOM or Byte Order Mark:
** 0xff 0xfe little-endian utf-16 follows
** 0xfe 0xff big-endian utf-16 follows
**
**
** Handling of malformed strings:
**
** SQLite accepts and processes malformed strings without an error wherever
** possible. However this is not possible when converting between UTF-8 and
** UTF-16.
**
** When converting malformed UTF-8 strings to UTF-16, one instance of the
** replacement character U+FFFD for each byte that cannot be interpeted as
** part of a valid unicode character.
**
** When converting malformed UTF-16 strings to UTF-8, one instance of the
** replacement character U+FFFD for each pair of bytes that cannot be
** interpeted as part of a valid unicode character.
**
** This file contains the following public routines:
**
** sqlite3VdbeMemTranslate() - Translate the encoding used by a Mem* string.
** sqlite3VdbeMemHandleBom() - Handle byte-order-marks in UTF16 Mem* strings.
** sqlite3utf16ByteLen() - Calculate byte-length of a void* UTF16 string.
** sqlite3utf8CharLen() - Calculate char-length of a char* UTF8 string.
** sqlite3utf8LikeCompare() - Do a LIKE match given two UTF8 char* strings.
**
*/
#include "sqliteInt.h"
#include <assert.h>
#include "vdbeInt.h"
/*
** This table maps from the first byte of a UTF-8 character to the number
** of trailing bytes expected. A value '255' indicates that the table key
** is not a legal first byte for a UTF-8 character.
*/
static const u8 xtra_utf8_bytes[256] = {
/* 0xxxxxxx */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 10wwwwww */
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
/* 110yyyyy */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
/* 1110zzzz */
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
/* 11110yyy */
3, 3, 3, 3, 3, 3, 3, 3, 255, 255, 255, 255, 255, 255, 255, 255,
};
/*
** This table maps from the number of trailing bytes in a UTF-8 character
** to an integer constant that is effectively calculated for each character
** read by a naive implementation of a UTF-8 character reader. The code
** in the READ_UTF8 macro explains things best.
*/
static const int xtra_utf8_bits[4] = {
0,
12416, /* (0xC0 << 6) + (0x80) */
925824, /* (0xE0 << 12) + (0x80 << 6) + (0x80) */
63447168 /* (0xF0 << 18) + (0x80 << 12) + (0x80 << 6) + 0x80 */
};
#define READ_UTF8(zIn, c) { \
int xtra; \
c = *(zIn)++; \
xtra = xtra_utf8_bytes[c]; \
switch( xtra ){ \
case 255: c = (int)0xFFFD; break; \
case 3: c = (c<<6) + *(zIn)++; \
case 2: c = (c<<6) + *(zIn)++; \
case 1: c = (c<<6) + *(zIn)++; \
c -= xtra_utf8_bits[xtra]; \
} \
}
int sqlite3ReadUtf8(const unsigned char *z){
int c;
READ_UTF8(z, c);
return c;
}
#define SKIP_UTF8(zIn) { \
zIn += (xtra_utf8_bytes[*(u8 *)zIn] + 1); \
}
#define WRITE_UTF8(zOut, c) { \
if( c<0x00080 ){ \
*zOut++ = (c&0xFF); \
} \
else if( c<0x00800 ){ \
*zOut++ = 0xC0 + ((c>>6)&0x1F); \
*zOut++ = 0x80 + (c & 0x3F); \
} \
else if( c<0x10000 ){ \
*zOut++ = 0xE0 + ((c>>12)&0x0F); \
*zOut++ = 0x80 + ((c>>6) & 0x3F); \
*zOut++ = 0x80 + (c & 0x3F); \
}else{ \
*zOut++ = 0xF0 + ((c>>18) & 0x07); \
*zOut++ = 0x80 + ((c>>12) & 0x3F); \
*zOut++ = 0x80 + ((c>>6) & 0x3F); \
*zOut++ = 0x80 + (c & 0x3F); \
} \
}
#define WRITE_UTF16LE(zOut, c) { \
if( c<=0xFFFF ){ \
*zOut++ = (c&0x00FF); \
*zOut++ = ((c>>8)&0x00FF); \
}else{ \
*zOut++ = (((c>>10)&0x003F) + (((c-0x10000)>>10)&0x00C0)); \
*zOut++ = (0x00D8 + (((c-0x10000)>>18)&0x03)); \
*zOut++ = (c&0x00FF); \
*zOut++ = (0x00DC + ((c>>8)&0x03)); \
} \
}
#define WRITE_UTF16BE(zOut, c) { \
if( c<=0xFFFF ){ \
*zOut++ = ((c>>8)&0x00FF); \
*zOut++ = (c&0x00FF); \
}else{ \
*zOut++ = (0x00D8 + (((c-0x10000)>>18)&0x03)); \
*zOut++ = (((c>>10)&0x003F) + (((c-0x10000)>>10)&0x00C0)); \
*zOut++ = (0x00DC + ((c>>8)&0x03)); \
*zOut++ = (c&0x00FF); \
} \
}
#define READ_UTF16LE(zIn, c){ \
c = (*zIn++); \
c += ((*zIn++)<<8); \
if( c>=0xD800 && c<=0xE000 ){ \
int c2 = (*zIn++); \
c2 += ((*zIn++)<<8); \
c = (c2&0x03FF) + ((c&0x003F)<<10) + (((c&0x03C0)+0x0040)<<10); \
} \
}
#define READ_UTF16BE(zIn, c){ \
c = ((*zIn++)<<8); \
c += (*zIn++); \
if( c>=0xD800 && c<=0xE000 ){ \
int c2 = ((*zIn++)<<8); \
c2 += (*zIn++); \
c = (c2&0x03FF) + ((c&0x003F)<<10) + (((c&0x03C0)+0x0040)<<10); \
} \
}
#define SKIP_UTF16BE(zIn){ \
if( *zIn>=0xD8 && (*zIn<0xE0 || (*zIn==0xE0 && *(zIn+1)==0x00)) ){ \
zIn += 4; \
}else{ \
zIn += 2; \
} \
}
#define SKIP_UTF16LE(zIn){ \
zIn++; \
if( *zIn>=0xD8 && (*zIn<0xE0 || (*zIn==0xE0 && *(zIn-1)==0x00)) ){ \
zIn += 3; \
}else{ \
zIn += 1; \
} \
}
#define RSKIP_UTF16LE(zIn){ \
if( *zIn>=0xD8 && (*zIn<0xE0 || (*zIn==0xE0 && *(zIn-1)==0x00)) ){ \
zIn -= 4; \
}else{ \
zIn -= 2; \
} \
}
#define RSKIP_UTF16BE(zIn){ \
zIn--; \
if( *zIn>=0xD8 && (*zIn<0xE0 || (*zIn==0xE0 && *(zIn+1)==0x00)) ){ \
zIn -= 3; \
}else{ \
zIn -= 1; \
} \
}
/*
** If the TRANSLATE_TRACE macro is defined, the value of each Mem is
** printed on stderr on the way into and out of sqlite3VdbeMemTranslate().
*/
/* #define TRANSLATE_TRACE 1 */
#ifndef SQLITE_OMIT_UTF16
/*
** This routine transforms the internal text encoding used by pMem to
** desiredEnc. It is an error if the string is already of the desired
** encoding, or if *pMem does not contain a string value.
*/
int sqlite3VdbeMemTranslate(Mem *pMem, u8 desiredEnc){
unsigned char zShort[NBFS]; /* Temporary short output buffer */
int len; /* Maximum length of output string in bytes */
unsigned char *zOut; /* Output buffer */
unsigned char *zIn; /* Input iterator */
unsigned char *zTerm; /* End of input */
unsigned char *z; /* Output iterator */
int c;
assert( pMem->flags&MEM_Str );
assert( pMem->enc!=desiredEnc );
assert( pMem->enc!=0 );
assert( pMem->n>=0 );
#if defined(TRANSLATE_TRACE) && defined(SQLITE_DEBUG)
{
char zBuf[100];
sqlite3VdbeMemPrettyPrint(pMem, zBuf);
fprintf(stderr, "INPUT: %s\n", zBuf);
}
#endif
/* If the translation is between UTF-16 little and big endian, then
** all that is required is to swap the byte order. This case is handled
** differently from the others.
*/
if( pMem->enc!=SQLITE_UTF8 && desiredEnc!=SQLITE_UTF8 ){
u8 temp;
int rc;
rc = sqlite3VdbeMemMakeWriteable(pMem);
if( rc!=SQLITE_OK ){
assert( rc==SQLITE_NOMEM );
return SQLITE_NOMEM;
}
zIn = (u8*)pMem->z;
zTerm = &zIn[pMem->n];
while( zIn<zTerm ){
temp = *zIn;
*zIn = *(zIn+1);
zIn++;
*zIn++ = temp;
}
pMem->enc = desiredEnc;
goto translate_out;
}
/* Set len to the maximum number of bytes required in the output buffer. */
if( desiredEnc==SQLITE_UTF8 ){
/* When converting from UTF-16, the maximum growth results from
** translating a 2-byte character to a 3-byte UTF-8 character (i.e.
** code-point 0xFFFC). A single byte is required for the output string
** nul-terminator.
*/
len = (pMem->n/2) * 3 + 1;
}else{
/* When converting from UTF-8 to UTF-16 the maximum growth is caused
** when a 1-byte UTF-8 character is translated into a 2-byte UTF-16
** character. Two bytes are required in the output buffer for the
** nul-terminator.
*/
len = pMem->n * 2 + 2;
}
/* Set zIn to point at the start of the input buffer and zTerm to point 1
** byte past the end.
**
** Variable zOut is set to point at the output buffer. This may be space
** obtained from malloc(), or Mem.zShort, if it large enough and not in
** use, or the zShort array on the stack (see above).
*/
zIn = (u8*)pMem->z;
zTerm = &zIn[pMem->n];
if( len>NBFS ){
zOut = sqliteMallocRaw(len);
if( !zOut ) return SQLITE_NOMEM;
}else{
zOut = zShort;
}
z = zOut;
if( pMem->enc==SQLITE_UTF8 ){
if( desiredEnc==SQLITE_UTF16LE ){
/* UTF-8 -> UTF-16 Little-endian */
while( zIn<zTerm ){
READ_UTF8(zIn, c);
WRITE_UTF16LE(z, c);
}
}else{
assert( desiredEnc==SQLITE_UTF16BE );
/* UTF-8 -> UTF-16 Big-endian */
while( zIn<zTerm ){
READ_UTF8(zIn, c);
WRITE_UTF16BE(z, c);
}
}
pMem->n = z - zOut;
*z++ = 0;
}else{
assert( desiredEnc==SQLITE_UTF8 );
if( pMem->enc==SQLITE_UTF16LE ){
/* UTF-16 Little-endian -> UTF-8 */
while( zIn<zTerm ){
READ_UTF16LE(zIn, c);
WRITE_UTF8(z, c);
}
}else{
/* UTF-16 Little-endian -> UTF-8 */
while( zIn<zTerm ){
READ_UTF16BE(zIn, c);
WRITE_UTF8(z, c);
}
}
pMem->n = z - zOut;
}
*z = 0;
assert( (pMem->n+(desiredEnc==SQLITE_UTF8?1:2))<=len );
sqlite3VdbeMemRelease(pMem);
pMem->flags &= ~(MEM_Static|MEM_Dyn|MEM_Ephem|MEM_Short);
pMem->enc = desiredEnc;
if( zOut==zShort ){
memcpy(pMem->zShort, zOut, len);
zOut = (u8*)pMem->zShort;
pMem->flags |= (MEM_Term|MEM_Short);
}else{
pMem->flags |= (MEM_Term|MEM_Dyn);
}
pMem->z = (char*)zOut;
translate_out:
#if defined(TRANSLATE_TRACE) && defined(SQLITE_DEBUG)
{
char zBuf[100];
sqlite3VdbeMemPrettyPrint(pMem, zBuf);
fprintf(stderr, "OUTPUT: %s\n", zBuf);
}
#endif
return SQLITE_OK;
}
/*
** This routine checks for a byte-order mark at the beginning of the
** UTF-16 string stored in *pMem. If one is present, it is removed and
** the encoding of the Mem adjusted. This routine does not do any
** byte-swapping, it just sets Mem.enc appropriately.
**
** The allocation (static, dynamic etc.) and encoding of the Mem may be
** changed by this function.
*/
int sqlite3VdbeMemHandleBom(Mem *pMem){
int rc = SQLITE_OK;
u8 bom = 0;
if( pMem->n<0 || pMem->n>1 ){
u8 b1 = *(u8 *)pMem->z;
u8 b2 = *(((u8 *)pMem->z) + 1);
if( b1==0xFE && b2==0xFF ){
bom = SQLITE_UTF16BE;
}
if( b1==0xFF && b2==0xFE ){
bom = SQLITE_UTF16LE;
}
}
if( bom ){
/* This function is called as soon as a string is stored in a Mem*,
** from within sqlite3VdbeMemSetStr(). At that point it is not possible
** for the string to be stored in Mem.zShort, or for it to be stored
** in dynamic memory with no destructor.
*/
assert( !(pMem->flags&MEM_Short) );
assert( !(pMem->flags&MEM_Dyn) || pMem->xDel );
if( pMem->flags & MEM_Dyn ){
void (*xDel)(void*) = pMem->xDel;
char *z = pMem->z;
pMem->z = 0;
pMem->xDel = 0;
rc = sqlite3VdbeMemSetStr(pMem, &z[2], pMem->n-2, bom, SQLITE_TRANSIENT);
xDel(z);
}else{
rc = sqlite3VdbeMemSetStr(pMem, &pMem->z[2], pMem->n-2, bom,
SQLITE_TRANSIENT);
}
}
return rc;
}
#endif /* SQLITE_OMIT_UTF16 */
/*
** pZ is a UTF-8 encoded unicode string. If nByte is less than zero,
** return the number of unicode characters in pZ up to (but not including)
** the first 0x00 byte. If nByte is not less than zero, return the
** number of unicode characters in the first nByte of pZ (or up to
** the first 0x00, whichever comes first).
*/
int sqlite3utf8CharLen(const char *z, int nByte){
int r = 0;
const char *zTerm;
if( nByte>=0 ){
zTerm = &z[nByte];
}else{
zTerm = (const char *)(-1);
}
assert( z<=zTerm );
while( *z!=0 && z<zTerm ){
SKIP_UTF8(z);
r++;
}
return r;
}
#ifndef SQLITE_OMIT_UTF16
/*
** Convert a UTF-16 string in the native encoding into a UTF-8 string.
** Memory to hold the UTF-8 string is obtained from malloc and must be
** freed by the calling function.
**
** NULL is returned if there is an allocation error.
*/
char *sqlite3utf16to8(const void *z, int nByte){
Mem m;
memset(&m, 0, sizeof(m));
sqlite3VdbeMemSetStr(&m, z, nByte, SQLITE_UTF16NATIVE, SQLITE_STATIC);
sqlite3VdbeChangeEncoding(&m, SQLITE_UTF8);
assert( m.flags & MEM_Term );
assert( m.flags & MEM_Str );
return (m.flags & MEM_Dyn)!=0 ? m.z : sqliteStrDup(m.z);
}
/*
** pZ is a UTF-16 encoded unicode string. If nChar is less than zero,
** return the number of bytes up to (but not including), the first pair
** of consecutive 0x00 bytes in pZ. If nChar is not less than zero,
** then return the number of bytes in the first nChar unicode characters
** in pZ (or up until the first pair of 0x00 bytes, whichever comes first).
*/
int sqlite3utf16ByteLen(const void *zIn, int nChar){
int c = 1;
char const *z = zIn;
int n = 0;
if( SQLITE_UTF16NATIVE==SQLITE_UTF16BE ){
/* Using an "if (SQLITE_UTF16NATIVE==SQLITE_UTF16BE)" construct here
** and in other parts of this file means that at one branch will
** not be covered by coverage testing on any single host. But coverage
** will be complete if the tests are run on both a little-endian and
** big-endian host. Because both the UTF16NATIVE and SQLITE_UTF16BE
** macros are constant at compile time the compiler can determine
** which branch will be followed. It is therefore assumed that no runtime
** penalty is paid for this "if" statement.
*/
while( c && ((nChar<0) || n<nChar) ){
READ_UTF16BE(z, c);
n++;
}
}else{
while( c && ((nChar<0) || n<nChar) ){
READ_UTF16LE(z, c);
n++;
}
}
return (z-(char const *)zIn)-((c==0)?2:0);
}
/*
** UTF-16 implementation of the substr()
*/
void sqlite3utf16Substr(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
int y, z;
unsigned char const *zStr;
unsigned char const *zStrEnd;
unsigned char const *zStart;
unsigned char const *zEnd;
int i;
zStr = (unsigned char const *)sqlite3_value_text16(argv[0]);
zStrEnd = &zStr[sqlite3_value_bytes16(argv[0])];
y = sqlite3_value_int(argv[1]);
z = sqlite3_value_int(argv[2]);
if( y>0 ){
y = y-1;
zStart = zStr;
if( SQLITE_UTF16BE==SQLITE_UTF16NATIVE ){
for(i=0; i<y && zStart<zStrEnd; i++) SKIP_UTF16BE(zStart);
}else{
for(i=0; i<y && zStart<zStrEnd; i++) SKIP_UTF16LE(zStart);
}
}else{
zStart = zStrEnd;
if( SQLITE_UTF16BE==SQLITE_UTF16NATIVE ){
for(i=y; i<0 && zStart>zStr; i++) RSKIP_UTF16BE(zStart);
}else{
for(i=y; i<0 && zStart>zStr; i++) RSKIP_UTF16LE(zStart);
}
for(; i<0; i++) z -= 1;
}
zEnd = zStart;
if( SQLITE_UTF16BE==SQLITE_UTF16NATIVE ){
for(i=0; i<z && zEnd<zStrEnd; i++) SKIP_UTF16BE(zEnd);
}else{
for(i=0; i<z && zEnd<zStrEnd; i++) SKIP_UTF16LE(zEnd);
}
sqlite3_result_text16(context, zStart, zEnd-zStart, SQLITE_TRANSIENT);
}
#if defined(SQLITE_TEST)
/*
** This routine is called from the TCL test function "translate_selftest".
** It checks that the primitives for serializing and deserializing
** characters in each encoding are inverses of each other.
*/
void sqlite3utfSelfTest(){
int i;
unsigned char zBuf[20];
unsigned char *z;
int n;
int c;
for(i=0; i<0x00110000; i++){
z = zBuf;
WRITE_UTF8(z, i);
n = z-zBuf;
z = zBuf;
READ_UTF8(z, c);
assert( c==i );
assert( (z-zBuf)==n );
}
for(i=0; i<0x00110000; i++){
if( i>=0xD800 && i<=0xE000 ) continue;
z = zBuf;
WRITE_UTF16LE(z, i);
n = z-zBuf;
z = zBuf;
READ_UTF16LE(z, c);
assert( c==i );
assert( (z-zBuf)==n );
}
for(i=0; i<0x00110000; i++){
if( i>=0xD800 && i<=0xE000 ) continue;
z = zBuf;
WRITE_UTF16BE(z, i);
n = z-zBuf;
z = zBuf;
READ_UTF16BE(z, c);
assert( c==i );
assert( (z-zBuf)==n );
}
}
#endif /* SQLITE_TEST */
#endif /* SQLITE_OMIT_UTF16 */

File diff suppressed because it is too large Load Diff

View File

@ -14,173 +14,13 @@
** Most of the code in this file may be omitted by defining the
** SQLITE_OMIT_VACUUM macro.
**
** $Id: vacuum.c,v 1.1.1.1 2004-03-11 22:22:23 alex Exp $
** $Id: vacuum.c,v 1.2 2006-04-13 12:44:29 guy Exp $
*/
#include "sqliteInt.h"
#include "vdbeInt.h"
#include "os.h"
/*
** A structure for holding a dynamic string - a string that can grow
** without bound.
*/
typedef struct dynStr dynStr;
struct dynStr {
char *z; /* Text of the string in space obtained from sqliteMalloc() */
int nAlloc; /* Amount of space allocated to z[] */
int nUsed; /* Next unused slot in z[] */
};
/*
** A structure that holds the vacuum context
*/
typedef struct vacuumStruct vacuumStruct;
struct vacuumStruct {
sqlite *dbOld; /* Original database */
sqlite *dbNew; /* New database */
char **pzErrMsg; /* Write errors here */
int rc; /* Set to non-zero on an error */
const char *zTable; /* Name of a table being copied */
const char *zPragma; /* Pragma to execute with results */
dynStr s1, s2; /* Two dynamic strings */
};
#if !defined(SQLITE_OMIT_VACUUM) || SQLITE_OMIT_VACUUM
/*
** Append text to a dynamic string
*/
static void appendText(dynStr *p, const char *zText, int nText){
if( nText<0 ) nText = strlen(zText);
if( p->z==0 || p->nUsed + nText + 1 >= p->nAlloc ){
char *zNew;
p->nAlloc = p->nUsed + nText + 1000;
zNew = sqliteRealloc(p->z, p->nAlloc);
if( zNew==0 ){
sqliteFree(p->z);
memset(p, 0, sizeof(*p));
return;
}
p->z = zNew;
}
memcpy(&p->z[p->nUsed], zText, nText+1);
p->nUsed += nText;
}
/*
** Append text to a dynamic string, having first put the text in quotes.
*/
static void appendQuoted(dynStr *p, const char *zText){
int i, j;
appendText(p, "'", 1);
for(i=j=0; zText[i]; i++){
if( zText[i]=='\'' ){
appendText(p, &zText[j], i-j+1);
j = i + 1;
appendText(p, "'", 1);
}
}
if( j<i ){
appendText(p, &zText[j], i-j);
}
appendText(p, "'", 1);
}
/*
** Execute statements of SQL. If an error occurs, write the error
** message into *pzErrMsg and return non-zero.
*/
static int execsql(char **pzErrMsg, sqlite *db, const char *zSql){
char *zErrMsg = 0;
int rc;
/* printf("***** executing *****\n%s\n", zSql); */
rc = sqlite_exec(db, zSql, 0, 0, &zErrMsg);
if( zErrMsg ){
sqliteSetString(pzErrMsg, zErrMsg, (char*)0);
sqlite_freemem(zErrMsg);
}
return rc;
}
/*
** This is the second stage callback. Each invocation contains all the
** data for a single row of a single table in the original database. This
** routine must write that information into the new database.
*/
static int vacuumCallback2(void *pArg, int argc, char **argv, char **NotUsed){
vacuumStruct *p = (vacuumStruct*)pArg;
const char *zSep = "(";
int i;
if( argv==0 ) return 0;
p->s2.nUsed = 0;
appendText(&p->s2, "INSERT INTO ", -1);
appendQuoted(&p->s2, p->zTable);
appendText(&p->s2, " VALUES", -1);
for(i=0; i<argc; i++){
appendText(&p->s2, zSep, 1);
zSep = ",";
if( argv[i]==0 ){
appendText(&p->s2, "NULL", 4);
}else{
appendQuoted(&p->s2, argv[i]);
}
}
appendText(&p->s2,")", 1);
p->rc = execsql(p->pzErrMsg, p->dbNew, p->s2.z);
return p->rc;
}
/*
** This is the first stage callback. Each invocation contains three
** arguments where are taken from the SQLITE_MASTER table of the original
** database: (1) the entry type, (2) the entry name, and (3) the SQL for
** the entry. In all cases, execute the SQL of the third argument.
** For tables, run a query to select all entries in that table and
** transfer them to the second-stage callback.
*/
static int vacuumCallback1(void *pArg, int argc, char **argv, char **NotUsed){
vacuumStruct *p = (vacuumStruct*)pArg;
int rc = 0;
assert( argc==3 );
if( argv==0 ) return 0;
assert( argv[0]!=0 );
assert( argv[1]!=0 );
assert( argv[2]!=0 );
rc = execsql(p->pzErrMsg, p->dbNew, argv[2]);
if( rc==SQLITE_OK && strcmp(argv[0],"table")==0 ){
char *zErrMsg = 0;
p->s1.nUsed = 0;
appendText(&p->s1, "SELECT * FROM ", -1);
appendQuoted(&p->s1, argv[1]);
p->zTable = argv[1];
rc = sqlite_exec(p->dbOld, p->s1.z, vacuumCallback2, p, &zErrMsg);
if( zErrMsg ){
sqliteSetString(p->pzErrMsg, zErrMsg, (char*)0);
sqlite_freemem(zErrMsg);
}
}
if( rc!=SQLITE_ABORT ) p->rc = rc;
return rc;
}
/*
** This callback is used to transfer PRAGMA settings from one database
** to the other. The value in argv[0] should be passed to a pragma
** identified by ((vacuumStruct*)pArg)->zPragma.
*/
static int vacuumCallback3(void *pArg, int argc, char **argv, char **NotUsed){
vacuumStruct *p = (vacuumStruct*)pArg;
char zBuf[200];
assert( argc==1 );
if( argv==0 ) return 0;
assert( argv[0]!=0 );
assert( strlen(p->zPragma)<100 );
assert( strlen(argv[0])<30 );
sprintf(zBuf,"PRAGMA %s=%s;", p->zPragma, argv[0]);
p->rc = execsql(p->pzErrMsg, p->dbNew, zBuf);
return p->rc;
}
#ifndef SQLITE_OMIT_VACUUM
/*
** Generate a random name of 20 character in length.
*/
@ -189,11 +29,46 @@ static void randomName(unsigned char *zBuf){
"abcdefghijklmnopqrstuvwxyz"
"0123456789";
int i;
sqliteRandomness(20, zBuf);
sqlite3Randomness(20, zBuf);
for(i=0; i<20; i++){
zBuf[i] = zChars[ zBuf[i]%(sizeof(zChars)-1) ];
}
}
/*
** Execute zSql on database db. Return an error code.
*/
static int execSql(sqlite3 *db, const char *zSql){
sqlite3_stmt *pStmt;
if( SQLITE_OK!=sqlite3_prepare(db, zSql, -1, &pStmt, 0) ){
return sqlite3_errcode(db);
}
while( SQLITE_ROW==sqlite3_step(pStmt) ){}
return sqlite3_finalize(pStmt);
}
/*
** Execute zSql on database db. The statement returns exactly
** one column. Execute this as SQL on the same database.
*/
static int execExecSql(sqlite3 *db, const char *zSql){
sqlite3_stmt *pStmt;
int rc;
rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0);
if( rc!=SQLITE_OK ) return rc;
while( SQLITE_ROW==sqlite3_step(pStmt) ){
rc = execSql(db, (char*)sqlite3_column_text(pStmt, 0));
if( rc!=SQLITE_OK ){
sqlite3_finalize(pStmt);
return rc;
}
}
return sqlite3_finalize(pStmt);
}
#endif
/*
@ -206,115 +81,249 @@ static void randomName(unsigned char *zBuf){
** with 2.0.0, SQLite no longer uses GDBM so this command has
** become a no-op.
*/
void sqliteVacuum(Parse *pParse, Token *pTableName){
Vdbe *v = sqliteGetVdbe(pParse);
sqliteVdbeAddOp(v, OP_Vacuum, 0, 0);
void sqlite3Vacuum(Parse *pParse){
Vdbe *v = sqlite3GetVdbe(pParse);
if( v ){
sqlite3VdbeAddOp(v, OP_Vacuum, 0, 0);
}
return;
}
/*
** This routine implements the OP_Vacuum opcode of the VDBE.
*/
int sqliteRunVacuum(char **pzErrMsg, sqlite *db){
#if !defined(SQLITE_OMIT_VACUUM) || SQLITE_OMIT_VACUUM
int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){
int rc = SQLITE_OK; /* Return code from service routines */
#ifndef SQLITE_OMIT_VACUUM
const char *zFilename; /* full pathname of the database file */
int nFilename; /* number of characters in zFilename[] */
char *zTemp = 0; /* a temporary file in same directory as zFilename */
sqlite *dbNew = 0; /* The new vacuumed database */
int rc = SQLITE_OK; /* Return code from service routines */
int i; /* Loop counter */
char *zErrMsg; /* Error message */
vacuumStruct sVac; /* Information passed to callbacks */
Btree *pMain; /* The database being vacuumed */
Btree *pTemp;
char *zSql = 0;
int saved_flags; /* Saved value of the db->flags */
Db *pDb = 0; /* Database to detach at end of vacuum */
/* These are all of the pragmas that need to be transferred over
** to the new database */
static const char *zPragma[] = {
"default_synchronous",
"default_cache_size",
/* "default_temp_store", */
};
/* Save the current value of the write-schema flag before setting it. */
saved_flags = db->flags;
db->flags |= SQLITE_WriteSchema | SQLITE_IgnoreChecks;
if( db->flags & SQLITE_InTrans ){
sqliteSetString(pzErrMsg, "cannot VACUUM from within a transaction",
if( !db->autoCommit ){
sqlite3SetString(pzErrMsg, "cannot VACUUM from within a transaction",
(char*)0);
return SQLITE_ERROR;
rc = SQLITE_ERROR;
goto end_of_vacuum;
}
memset(&sVac, 0, sizeof(sVac));
/* Get the full pathname of the database file and create two
** temporary filenames in the same directory as the original file.
/* Get the full pathname of the database file and create a
** temporary filename in the same directory as the original file.
*/
zFilename = sqliteBtreeGetFilename(db->aDb[0].pBt);
if( zFilename==0 ){
/* This only happens with the in-memory database. VACUUM is a no-op
** there, so just return */
pMain = db->aDb[0].pBt;
zFilename = sqlite3BtreeGetFilename(pMain);
assert( zFilename );
if( zFilename[0]=='\0' ){
/* The in-memory database. Do nothing. Return directly to avoid causing
** an error trying to DETACH the vacuum_db (which never got attached)
** in the exit-handler.
*/
return SQLITE_OK;
}
nFilename = strlen(zFilename);
zTemp = sqliteMalloc( nFilename+100 );
if( zTemp==0 ) return SQLITE_NOMEM;
strcpy(zTemp, zFilename);
for(i=0; i<10; i++){
zTemp[nFilename] = '-';
randomName(&zTemp[nFilename+1]);
if( !sqliteOsFileExists(zTemp) ) break;
if( zTemp==0 ){
rc = SQLITE_NOMEM;
goto end_of_vacuum;
}
if( i>=10 ){
sqliteSetString(pzErrMsg, "unable to create a temporary database file "
"in the same directory as the original database", (char*)0);
strcpy(zTemp, zFilename);
/* The randomName() procedure in the following loop uses an excellent
** source of randomness to generate a name from a space of 1.3e+31
** possibilities. So unless the directory already contains on the order
** of 1.3e+31 files, the probability that the following loop will
** run more than once or twice is vanishingly small. We are certain
** enough that this loop will always terminate (and terminate quickly)
** that we don't even bother to set a maximum loop count.
*/
do {
zTemp[nFilename] = '-';
randomName((unsigned char*)&zTemp[nFilename+1]);
} while( sqlite3OsFileExists(zTemp) );
/* Attach the temporary database as 'vacuum_db'. The synchronous pragma
** can be set to 'off' for this file, as it is not recovered if a crash
** occurs anyway. The integrity of the database is maintained by a
** (possibly synchronous) transaction opened on the main database before
** sqlite3BtreeCopyFile() is called.
**
** An optimisation would be to use a non-journaled pager.
*/
zSql = sqlite3MPrintf("ATTACH '%q' AS vacuum_db;", zTemp);
if( !zSql ){
rc = SQLITE_NOMEM;
goto end_of_vacuum;
}
rc = execSql(db, zSql);
sqliteFree(zSql);
zSql = 0;
if( rc!=SQLITE_OK ) goto end_of_vacuum;
pDb = &db->aDb[db->nDb-1];
assert( strcmp(db->aDb[db->nDb-1].zName,"vacuum_db")==0 );
pTemp = db->aDb[db->nDb-1].pBt;
sqlite3BtreeSetPageSize(pTemp, sqlite3BtreeGetPageSize(pMain),
sqlite3BtreeGetReserve(pMain));
assert( sqlite3BtreeGetPageSize(pTemp)==sqlite3BtreeGetPageSize(pMain) );
rc = execSql(db, "PRAGMA vacuum_db.synchronous=OFF");
if( rc!=SQLITE_OK ){
goto end_of_vacuum;
}
dbNew = sqlite_open(zTemp, 0, &zErrMsg);
if( dbNew==0 ){
sqliteSetString(pzErrMsg, "unable to open a temporary database at ",
zTemp, " - ", zErrMsg, (char*)0);
goto end_of_vacuum;
}
if( (rc = execsql(pzErrMsg, db, "BEGIN"))!=0 ) goto end_of_vacuum;
if( (rc = execsql(pzErrMsg, dbNew, "PRAGMA synchronous=off; BEGIN"))!=0 ){
goto end_of_vacuum;
}
sVac.dbOld = db;
sVac.dbNew = dbNew;
sVac.pzErrMsg = pzErrMsg;
for(i=0; rc==SQLITE_OK && i<sizeof(zPragma)/sizeof(zPragma[0]); i++){
char zBuf[200];
assert( strlen(zPragma[i])<100 );
sprintf(zBuf, "PRAGMA %s;", zPragma[i]);
sVac.zPragma = zPragma[i];
rc = sqlite_exec(db, zBuf, vacuumCallback3, &sVac, &zErrMsg);
}
#ifndef SQLITE_OMIT_AUTOVACUUM
sqlite3BtreeSetAutoVacuum(pTemp, sqlite3BtreeGetAutoVacuum(pMain));
#endif
/* Begin a transaction */
rc = execSql(db, "BEGIN EXCLUSIVE;");
if( rc!=SQLITE_OK ) goto end_of_vacuum;
/* Query the schema of the main database. Create a mirror schema
** in the temporary database.
*/
rc = execExecSql(db,
"SELECT 'CREATE TABLE vacuum_db.' || substr(sql,14,100000000) "
" FROM sqlite_master WHERE type='table' AND name!='sqlite_sequence'");
if( rc!=SQLITE_OK ) goto end_of_vacuum;
rc = execExecSql(db,
"SELECT 'CREATE INDEX vacuum_db.' || substr(sql,14,100000000)"
" FROM sqlite_master WHERE sql LIKE 'CREATE INDEX %' ");
if( rc!=SQLITE_OK ) goto end_of_vacuum;
rc = execExecSql(db,
"SELECT 'CREATE UNIQUE INDEX vacuum_db.' || substr(sql,21,100000000) "
" FROM sqlite_master WHERE sql LIKE 'CREATE UNIQUE INDEX %'");
if( rc!=SQLITE_OK ) goto end_of_vacuum;
rc = execExecSql(db,
"SELECT 'CREATE VIEW vacuum_db.' || substr(sql,13,100000000) "
" FROM sqlite_master WHERE type='view'"
);
if( rc!=SQLITE_OK ) goto end_of_vacuum;
/* Loop through the tables in the main database. For each, do
** an "INSERT INTO vacuum_db.xxx SELECT * FROM xxx;" to copy
** the contents to the temporary database.
*/
rc = execExecSql(db,
"SELECT 'INSERT INTO vacuum_db.' || quote(name) "
"|| ' SELECT * FROM ' || quote(name) || ';'"
"FROM sqlite_master "
"WHERE type = 'table' AND name!='sqlite_sequence';"
);
if( rc!=SQLITE_OK ) goto end_of_vacuum;
/* Copy over the sequence table
*/
rc = execExecSql(db,
"SELECT 'DELETE FROM vacuum_db.' || quote(name) || ';' "
"FROM vacuum_db.sqlite_master WHERE name='sqlite_sequence' "
);
if( rc!=SQLITE_OK ) goto end_of_vacuum;
rc = execExecSql(db,
"SELECT 'INSERT INTO vacuum_db.' || quote(name) "
"|| ' SELECT * FROM ' || quote(name) || ';' "
"FROM vacuum_db.sqlite_master WHERE name=='sqlite_sequence';"
);
if( rc!=SQLITE_OK ) goto end_of_vacuum;
/* Copy the triggers from the main database to the temporary database.
** This was deferred before in case the triggers interfered with copying
** the data. It's possible the indices should be deferred until this
** point also.
*/
rc = execExecSql(db,
"SELECT 'CREATE TRIGGER vacuum_db.' || substr(sql, 16, 1000000) "
"FROM sqlite_master WHERE type='trigger'"
);
if( rc!=SQLITE_OK ) goto end_of_vacuum;
/* At this point, unless the main db was completely empty, there is now a
** transaction open on the vacuum database, but not on the main database.
** Open a btree level transaction on the main database. This allows a
** call to sqlite3BtreeCopyFile(). The main database btree level
** transaction is then committed, so the SQL level never knows it was
** opened for writing. This way, the SQL transaction used to create the
** temporary database never needs to be committed.
*/
if( rc==SQLITE_OK ){
rc = sqlite_exec(db,
"SELECT type, name, sql FROM sqlite_master "
"WHERE sql NOT NULL AND type!='view' "
"UNION ALL "
"SELECT type, name, sql FROM sqlite_master "
"WHERE sql NOT NULL AND type=='view'",
vacuumCallback1, &sVac, &zErrMsg);
}
if( rc==SQLITE_OK ){
rc = sqliteBtreeCopyFile(db->aDb[0].pBt, dbNew->aDb[0].pBt);
sqlite_exec(db, "COMMIT", 0, 0, 0);
sqliteResetInternalSchema(db, 0);
u32 meta;
int i;
/* This array determines which meta meta values are preserved in the
** vacuum. Even entries are the meta value number and odd entries
** are an increment to apply to the meta value after the vacuum.
** The increment is used to increase the schema cookie so that other
** connections to the same database will know to reread the schema.
*/
static const unsigned char aCopy[] = {
1, 1, /* Add one to the old schema cookie */
3, 0, /* Preserve the default page cache size */
5, 0, /* Preserve the default text encoding */
6, 0, /* Preserve the user version */
};
assert( 1==sqlite3BtreeIsInTrans(pTemp) );
assert( 1==sqlite3BtreeIsInTrans(pMain) );
/* Copy Btree meta values */
for(i=0; i<sizeof(aCopy)/sizeof(aCopy[0]); i+=2){
rc = sqlite3BtreeGetMeta(pMain, aCopy[i], &meta);
if( rc!=SQLITE_OK ) goto end_of_vacuum;
rc = sqlite3BtreeUpdateMeta(pTemp, aCopy[i], meta+aCopy[i+1]);
if( rc!=SQLITE_OK ) goto end_of_vacuum;
}
rc = sqlite3BtreeCopyFile(pMain, pTemp);
if( rc!=SQLITE_OK ) goto end_of_vacuum;
rc = sqlite3BtreeCommit(pTemp);
if( rc!=SQLITE_OK ) goto end_of_vacuum;
rc = sqlite3BtreeCommit(pMain);
}
end_of_vacuum:
if( rc && zErrMsg!=0 ){
sqliteSetString(pzErrMsg, "unable to vacuum database - ",
zErrMsg, (char*)0);
/* Restore the original value of db->flags */
db->flags = saved_flags;
/* Currently there is an SQL level transaction open on the vacuum
** database. No locks are held on any other files (since the main file
** was committed at the btree level). So it safe to end the transaction
** by manually setting the autoCommit flag to true and detaching the
** vacuum database. The vacuum_db journal file is deleted when the pager
** is closed by the DETACH.
*/
db->autoCommit = 1;
if( pDb ){
sqlite3MallocDisallow();
sqlite3BtreeClose(pDb->pBt);
sqlite3MallocAllow();
pDb->pBt = 0;
pDb->pSchema = 0;
}
sqlite_exec(db, "ROLLBACK", 0, 0, 0);
if( dbNew ) sqlite_close(dbNew);
sqliteOsDelete(zTemp);
sqliteFree(zTemp);
sqliteFree(sVac.s1.z);
sqliteFree(sVac.s2.z);
if( zErrMsg ) sqlite_freemem(zErrMsg);
if( rc==SQLITE_ABORT ) sVac.rc = SQLITE_ERROR;
return sVac.rc;
/* If one of the execSql() calls above returned SQLITE_NOMEM, then the
** mallocFailed flag will be clear (because execSql() calls sqlite3_exec()).
** Fix this so the flag and return code match.
*/
if( rc==SQLITE_NOMEM ){
sqlite3MallocFailed();
}
if( zTemp ){
sqlite3OsDelete(zTemp);
sqliteFree(zTemp);
}
sqliteFree( zSql );
sqlite3ResetInternalSchema(db, 0);
#endif
return rc;
}

File diff suppressed because it is too large Load Diff

View File

@ -15,7 +15,7 @@
** or VDBE. The VDBE implements an abstract machine that runs a
** simple program to access and modify the underlying database.
**
** $Id: vdbe.h,v 1.1.1.1 2004-03-11 22:22:23 alex Exp $
** $Id: vdbe.h,v 1.2 2006-04-13 12:44:29 guy Exp $
*/
#ifndef _SQLITE_VDBE_H_
#define _SQLITE_VDBE_H_
@ -38,7 +38,7 @@ struct VdbeOp {
int p1; /* First operand */
int p2; /* Second parameter (often the jump destination) */
char *p3; /* Third parameter */
int p3type; /* P3_STATIC, P3_DYNAMIC or P3_POINTER */
int p3type; /* One of the P3_xxx constants defined below */
#ifdef VDBE_PROFILE
int cnt; /* Number of times this instruction was executed */
long long cycles; /* Total time spend executing this instruction */
@ -64,12 +64,37 @@ typedef struct VdbeOpList VdbeOpList;
#define P3_NOTUSED 0 /* The P3 parameter is not used */
#define P3_DYNAMIC (-1) /* Pointer to a string obtained from sqliteMalloc() */
#define P3_STATIC (-2) /* Pointer to a static string */
#define P3_POINTER (-3) /* P3 is a pointer to some structure or object */
#define P3_COLLSEQ (-4) /* P3 is a pointer to a CollSeq structure */
#define P3_FUNCDEF (-5) /* P3 is a pointer to a FuncDef structure */
#define P3_KEYINFO (-6) /* P3 is a pointer to a KeyInfo structure */
#define P3_VDBEFUNC (-7) /* P3 is a pointer to a VdbeFunc structure */
#define P3_MEM (-8) /* P3 is a pointer to a Mem* structure */
#define P3_TRANSIENT (-9) /* P3 is a pointer to a transient string */
/* When adding a P3 argument using P3_KEYINFO, a copy of the KeyInfo structure
** is made. That copy is freed when the Vdbe is finalized. But if the
** argument is P3_KEYINFO_HANDOFF, the passed in pointer is used. It still
** gets freed when the Vdbe is finalized so it still should be obtained
** from a single sqliteMalloc(). But no copy is made and the calling
** function should *not* try to free the KeyInfo.
*/
#define P3_KEYINFO_HANDOFF (-9)
/*
** The Vdbe.aColName array contains 5n Mem structures, where n is the
** number of columns of data returned by the statement.
*/
#define COLNAME_NAME 0
#define COLNAME_DECLTYPE 1
#define COLNAME_DATABASE 2
#define COLNAME_TABLE 3
#define COLNAME_COLUMN 4
#define COLNAME_N 5 /* Number of COLNAME_xxx symbols */
/*
** The following macro converts a relative address in the p2 field
** of a VdbeOp structure into a negative number so that
** sqliteVdbeAddOpList() knows that the address is relative. Calling
** sqlite3VdbeAddOpList() knows that the address is relative. Calling
** the macro again restores the address.
*/
#define ADDR(X) (-1-(X))
@ -84,29 +109,36 @@ typedef struct VdbeOpList VdbeOpList;
** Prototypes for the VDBE interface. See comments on the implementation
** for a description of what each of these routines does.
*/
Vdbe *sqliteVdbeCreate(sqlite*);
void sqliteVdbeCreateCallback(Vdbe*, int*);
int sqliteVdbeAddOp(Vdbe*,int,int,int);
int sqliteVdbeOp3(Vdbe*,int,int,int,const char *zP3,int);
int sqliteVdbeCode(Vdbe*,...);
int sqliteVdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp);
void sqliteVdbeChangeP1(Vdbe*, int addr, int P1);
void sqliteVdbeChangeP2(Vdbe*, int addr, int P2);
void sqliteVdbeChangeP3(Vdbe*, int addr, const char *zP1, int N);
void sqliteVdbeDequoteP3(Vdbe*, int addr);
int sqliteVdbeFindOp(Vdbe*, int, int);
VdbeOp *sqliteVdbeGetOp(Vdbe*, int);
int sqliteVdbeMakeLabel(Vdbe*);
void sqliteVdbeDelete(Vdbe*);
void sqliteVdbeMakeReady(Vdbe*,int,int);
int sqliteVdbeExec(Vdbe*);
int sqliteVdbeList(Vdbe*);
int sqliteVdbeFinalize(Vdbe*,char**);
void sqliteVdbeResolveLabel(Vdbe*, int);
int sqliteVdbeCurrentAddr(Vdbe*);
void sqliteVdbeTrace(Vdbe*,FILE*);
void sqliteVdbeCompressSpace(Vdbe*,int);
int sqliteVdbeReset(Vdbe*,char **);
Vdbe *sqlite3VdbeCreate(sqlite3*);
void sqlite3VdbeCreateCallback(Vdbe*, int*);
int sqlite3VdbeAddOp(Vdbe*,int,int,int);
int sqlite3VdbeOp3(Vdbe*,int,int,int,const char *zP3,int);
int sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp);
void sqlite3VdbeChangeP1(Vdbe*, int addr, int P1);
void sqlite3VdbeChangeP2(Vdbe*, int addr, int P2);
void sqlite3VdbeJumpHere(Vdbe*, int addr);
void sqlite3VdbeChangeToNoop(Vdbe*, int addr, int N);
void sqlite3VdbeChangeP3(Vdbe*, int addr, const char *zP1, int N);
VdbeOp *sqlite3VdbeGetOp(Vdbe*, int);
int sqlite3VdbeMakeLabel(Vdbe*);
void sqlite3VdbeDelete(Vdbe*);
void sqlite3VdbeMakeReady(Vdbe*,int,int,int,int);
int sqlite3VdbeFinalize(Vdbe*);
void sqlite3VdbeResolveLabel(Vdbe*, int);
int sqlite3VdbeCurrentAddr(Vdbe*);
void sqlite3VdbeTrace(Vdbe*,FILE*);
int sqlite3VdbeReset(Vdbe*);
int sqliteVdbeSetVariables(Vdbe*,int,const char**);
void sqlite3VdbeSetNumCols(Vdbe*,int);
int sqlite3VdbeSetColName(Vdbe*, int, int, const char *, int);
void sqlite3VdbeCountChanges(Vdbe*);
sqlite3 *sqlite3VdbeDb(Vdbe*);
#ifndef NDEBUG
void sqlite3VdbeComment(Vdbe*, const char*, ...);
# define VdbeComment(X) sqlite3VdbeComment X
#else
# define VdbeComment(X)
#endif
#endif

View File

@ -17,21 +17,19 @@
*/
/*
** When converting from the native format to the key format and back
** again, in addition to changing the byte order we invert the high-order
** bit of the most significant byte. This causes negative numbers to
** sort before positive numbers in the memcmp() function.
** intToKey() and keyToInt() used to transform the rowid. But with
** the latest versions of the design they are no-ops.
*/
#define keyToInt(X) (sqliteVdbeByteSwap(X) ^ 0x80000000)
#define intToKey(X) (sqliteVdbeByteSwap((X) ^ 0x80000000))
#define keyToInt(X) (X)
#define intToKey(X) (X)
/*
** The makefile scans this source file and creates the following
** array of string constants which are the names of all VDBE opcodes.
** This array is defined in a separate source code file named opcode.c
** which is automatically generated by the makefile.
** The makefile scans the vdbe.c source file and creates the following
** array of string constants which are the names of all VDBE opcodes. This
** array is defined in a separate source code file named opcode.c which is
** automatically generated by the makefile.
*/
extern char *sqliteOpcodeNames[];
extern char *sqlite3OpcodeNames[];
/*
** SQL is translated into a sequence of instructions to be
@ -62,42 +60,43 @@ typedef unsigned char Bool;
*/
struct Cursor {
BtCursor *pCursor; /* The cursor structure of the backend */
int lastRecno; /* Last recno from a Next or NextIdx operation */
int nextRowid; /* Next rowid returned by OP_NewRowid */
Bool recnoIsValid; /* True if lastRecno is valid */
Bool keyAsData; /* The OP_Column command works on key instead of data */
int iDb; /* Index of cursor database in db->aDb[] (or -1) */
i64 lastRowid; /* Last rowid from a Next or NextIdx operation */
i64 nextRowid; /* Next rowid returned by OP_NewRowid */
Bool zeroed; /* True if zeroed out and ready for reuse */
Bool rowidIsValid; /* True if lastRowid is valid */
Bool atFirst; /* True if pointing to first entry */
Bool useRandomRowid; /* Generate new record numbers semi-randomly */
Bool nullRow; /* True if pointing to a row with no data */
Bool nextRowidValid; /* True if the nextRowid field is valid */
Bool pseudoTable; /* This is a NEW or OLD pseudo-tables of a trigger */
Bool deferredMoveto; /* A call to sqliteBtreeMoveto() is needed */
int movetoTarget; /* Argument to the deferred sqliteBtreeMoveto() */
Bool deferredMoveto; /* A call to sqlite3BtreeMoveto() is needed */
Bool isTable; /* True if a table requiring integer keys */
Bool isIndex; /* True if an index containing keys only - no data */
u8 bogusIncrKey; /* Something for pIncrKey to point to if pKeyInfo==0 */
i64 movetoTarget; /* Argument to the deferred sqlite3BtreeMoveto() */
Btree *pBt; /* Separate file holding temporary table */
int nData; /* Number of bytes in pData */
char *pData; /* Data for a NEW or OLD pseudo-table */
int iKey; /* Key for the NEW or OLD pseudo-table row */
i64 iKey; /* Key for the NEW or OLD pseudo-table row */
u8 *pIncrKey; /* Pointer to pKeyInfo->incrKey */
KeyInfo *pKeyInfo; /* Info about index keys needed by index cursors */
int nField; /* Number of fields in the header */
i64 seqCount; /* Sequence counter */
/* Cached information about the header for the data record that the
** cursor is currently pointing to. Only valid if cacheValid is true.
** aRow might point to (ephemeral) data for the current row, or it might
** be NULL.
*/
int cacheStatus; /* Cache is valid if this matches Vdbe.cacheCtr */
int payloadSize; /* Total number of bytes in the record */
u32 *aType; /* Type values for all entries in the record */
u32 *aOffset; /* Cached offsets to the start of each columns data */
u8 *aRow; /* Data for the current row, if all on one page */
};
typedef struct Cursor Cursor;
/*
** A sorter builds a list of elements to be sorted. Each element of
** the list is an instance of the following structure.
*/
typedef struct Sorter Sorter;
struct Sorter {
int nKey; /* Number of bytes in the key */
char *zKey; /* The key by which we will sort */
int nData; /* Number of bytes in the data */
char *pData; /* The data associated with this key */
Sorter *pNext; /* Next in the list */
};
/*
** Number of buckets used for merge-sort.
*/
#define NSORT 30
/*
** Number of bytes of string storage space available to each stack
** layer without having to malloc. NBFS is short for Number of Bytes
@ -106,36 +105,86 @@ struct Sorter {
#define NBFS 32
/*
** A single level of the stack or a single memory cell
** is an instance of the following structure.
** A value for Cursor.cacheValid that means the cache is always invalid.
*/
#define CACHE_STALE 0
/*
** Internally, the vdbe manipulates nearly all SQL values as Mem
** structures. Each Mem struct may cache multiple representations (string,
** integer etc.) of the same value. A value (and therefore Mem structure)
** has the following properties:
**
** Each value has a manifest type. The manifest type of the value stored
** in a Mem struct is returned by the MemType(Mem*) macro. The type is
** one of SQLITE_NULL, SQLITE_INTEGER, SQLITE_REAL, SQLITE_TEXT or
** SQLITE_BLOB.
*/
struct Mem {
int i; /* Integer value */
int n; /* Number of characters in string value, including '\0' */
int flags; /* Some combination of MEM_Null, MEM_Str, MEM_Dyn, etc. */
i64 i; /* Integer value. Or FuncDef* when flags==MEM_Agg */
double r; /* Real value */
char *z; /* String value */
char *z; /* String or BLOB value */
int n; /* Number of characters in string value, including '\0' */
u16 flags; /* Some combination of MEM_Null, MEM_Str, MEM_Dyn, etc. */
u8 type; /* One of MEM_Null, MEM_Str, etc. */
u8 enc; /* TEXT_Utf8, TEXT_Utf16le, or TEXT_Utf16be */
void (*xDel)(void *); /* If not null, call this function to delete Mem.z */
char zShort[NBFS]; /* Space for short strings */
};
typedef struct Mem Mem;
/*
** Allowed values for Mem.flags
/* One or more of the following flags are set to indicate the validOK
** representations of the value stored in the Mem struct.
**
** If the MEM_Null flag is set, then the value is an SQL NULL value.
** No other flags may be set in this case.
**
** If the MEM_Str flag is set then Mem.z points at a string representation.
** Usually this is encoded in the same unicode encoding as the main
** database (see below for exceptions). If the MEM_Term flag is also
** set, then the string is nul terminated. The MEM_Int and MEM_Real
** flags may coexist with the MEM_Str flag.
**
** Multiple of these values can appear in Mem.flags. But only one
** at a time can appear in Mem.type.
*/
#define MEM_Null 0x0001 /* Value is NULL */
#define MEM_Str 0x0002 /* Value is a string */
#define MEM_Int 0x0004 /* Value is an integer */
#define MEM_Real 0x0008 /* Value is a real number */
#define MEM_Dyn 0x0010 /* Need to call sqliteFree() on Mem.z */
#define MEM_Static 0x0020 /* Mem.z points to a static string */
#define MEM_Ephem 0x0040 /* Mem.z points to an ephemeral string */
#define MEM_Short 0x0080 /* Mem.z points to Mem.zShort */
#define MEM_Blob 0x0010 /* Value is a BLOB */
/* The following MEM_ value appears only in AggElem.aMem.s.flag fields.
** It indicates that the corresponding AggElem.aMem.z points to a
** aggregate function context that needs to be finalized.
/* Whenever Mem contains a valid string or blob representation, one of
** the following flags must be set to determine the memory management
** policy for Mem.z. The MEM_Term flag tells us whether or not the
** string is \000 or \u0000 terminated
*/
#define MEM_AggCtx 0x0100 /* Mem.z points to an agg function context */
#define MEM_Term 0x0020 /* String rep is nul terminated */
#define MEM_Dyn 0x0040 /* Need to call sqliteFree() on Mem.z */
#define MEM_Static 0x0080 /* Mem.z points to a static string */
#define MEM_Ephem 0x0100 /* Mem.z points to an ephemeral string */
#define MEM_Short 0x0200 /* Mem.z points to Mem.zShort */
#define MEM_Agg 0x0400 /* Mem.z points to an agg function context */
/* A VdbeFunc is just a FuncDef (defined in sqliteInt.h) that contains
** additional information about auxiliary information bound to arguments
** of the function. This is used to implement the sqlite3_get_auxdata()
** and sqlite3_set_auxdata() APIs. The "auxdata" is some auxiliary data
** that can be associated with a constant argument to a function. This
** allows functions such as "regexp" to compile their constant regular
** expression argument once and reused the compiled code for multiple
** invocations.
*/
struct VdbeFunc {
FuncDef *pFunc; /* The definition of the function */
int nAux; /* Number of entries allocated for apAux[] */
struct AuxData {
void *pAux; /* Aux data for the i-th argument */
void (*xDelete)(void *); /* Destructor for the aux data */
} apAux[1]; /* One slot for each function argument */
};
typedef struct VdbeFunc VdbeFunc;
/*
** The "context" argument for a installable function. A pointer to an
@ -147,38 +196,16 @@ typedef struct Mem Mem;
** But this file is the only place where the internal details of this
** structure are known.
**
** This structure is defined inside of vdbe.c because it uses substructures
** This structure is defined inside of vdbeInt.h because it uses substructures
** (Mem) which are only defined there.
*/
struct sqlite_func {
FuncDef *pFunc; /* Pointer to function information. MUST BE FIRST */
Mem s; /* The return value is stored here */
void *pAgg; /* Aggregate context */
u8 isError; /* Set to true for an error */
u8 isStep; /* Current in the step function */
int cnt; /* Number of times that the step function has been called */
};
/*
** An Agg structure describes an Aggregator. Each Agg consists of
** zero or more Aggregator elements (AggElem). Each AggElem contains
** a key and one or more values. The values are used in processing
** aggregate functions in a SELECT. The key is used to implement
** the GROUP BY clause of a select.
*/
typedef struct Agg Agg;
typedef struct AggElem AggElem;
struct Agg {
int nMem; /* Number of values stored in each AggElem */
AggElem *pCurrent; /* The AggElem currently in focus */
HashElem *pSearch; /* The hash element for pCurrent */
Hash hash; /* Hash table of all aggregate elements */
FuncDef **apFunc; /* Information about aggregate functions */
};
struct AggElem {
char *zKey; /* The key to this AggElem */
int nKey; /* Number of bytes in the key, including '\0' at end */
Mem aMem[1]; /* The values for this AggElem */
struct sqlite3_context {
FuncDef *pFunc; /* Pointer to function information. MUST BE FIRST */
VdbeFunc *pVdbeFunc; /* Auxilary data, if created. */
Mem s; /* The return value is stored here */
Mem *pMem; /* Memory cell used to store aggregate context */
u8 isError; /* Set to true for an error */
CollSeq *pColl; /* Collating sequence */
};
/*
@ -194,41 +221,56 @@ struct Set {
};
/*
** A Keylist is a bunch of keys into a table. The keylist can
** grow without bound. The keylist stores the ROWIDs of database
** records that need to be deleted or updated.
** A FifoPage structure holds a single page of valves. Pages are arranged
** in a list.
*/
typedef struct Keylist Keylist;
struct Keylist {
int nKey; /* Number of slots in aKey[] */
int nUsed; /* Next unwritten slot in aKey[] */
int nRead; /* Next unread slot in aKey[] */
Keylist *pNext; /* Next block of keys */
int aKey[1]; /* One or more keys. Extra space allocated as needed */
typedef struct FifoPage FifoPage;
struct FifoPage {
int nSlot; /* Number of entries aSlot[] */
int iWrite; /* Push the next value into this entry in aSlot[] */
int iRead; /* Read the next value from this entry in aSlot[] */
FifoPage *pNext; /* Next page in the fifo */
i64 aSlot[1]; /* One or more slots for rowid values */
};
/*
** The Fifo structure is typedef-ed in vdbeInt.h. But the implementation
** of that structure is private to this file.
**
** The Fifo structure describes the entire fifo.
*/
typedef struct Fifo Fifo;
struct Fifo {
int nEntry; /* Total number of entries */
FifoPage *pFirst; /* First page on the list */
FifoPage *pLast; /* Last page on the list */
};
/*
** A Context stores the last insert rowid, the last statement change count,
** and the current statement change count (i.e. changes since last statement).
** The current keylist is also stored in the context.
** Elements of Context structure type make up the ContextStack, which is
** updated by the ContextPush and ContextPop opcodes (used by triggers)
** updated by the ContextPush and ContextPop opcodes (used by triggers).
** The context is pushed before executing a trigger a popped when the
** trigger finishes.
*/
typedef struct Context Context;
struct Context {
int lastRowid; /* Last insert rowid (from db->lastRowid) */
int lsChange; /* Last statement change count (from db->lsChange) */
int csChange; /* Current statement change count (from db->csChange) */
i64 lastRowid; /* Last insert rowid (sqlite3.lastRowid) */
int nChange; /* Statement changes (Vdbe.nChanges) */
Fifo sFifo; /* Records that will participate in a DELETE or UPDATE */
};
/*
** An instance of the virtual machine. This structure contains the complete
** state of the virtual machine.
**
** The "sqlite_vm" structure pointer that is returned by sqlite_compile()
** The "sqlite3_stmt" structure pointer that is returned by sqlite3_compile()
** is really a pointer to an instance of this structure.
*/
struct Vdbe {
sqlite *db; /* The whole database */
sqlite3 *db; /* The whole database */
Vdbe *pPrev,*pNext; /* Linked list of VDBEs with the same Vdbe.db */
FILE *trace; /* Write an execution trace here, if not NULL */
int nOp; /* Number of instructions in the program */
@ -239,37 +281,27 @@ struct Vdbe {
int *aLabel; /* Space to hold the labels */
Mem *aStack; /* The operand stack, except string values */
Mem *pTos; /* Top entry in the operand stack */
char **zArgv; /* Text values used by the callback */
char **azColName; /* Becomes the 4th parameter to callbacks */
int nCursor; /* Number of slots in aCsr[] */
Cursor *aCsr; /* One element of this array for each open cursor */
Sorter *pSort; /* A linked list of objects to be sorted */
FILE *pFile; /* At most one open file handler */
int nField; /* Number of file fields */
char **azField; /* Data for each file field */
int nVar; /* Number of entries in azVariable[] */
char **azVar; /* Values for the OP_Variable opcode */
int *anVar; /* Length of each value in azVariable[] */
u8 *abVar; /* TRUE if azVariable[i] needs to be sqliteFree()ed */
char *zLine; /* A single line from the input file */
int nLineAlloc; /* Number of spaces allocated for zLine */
Mem **apArg; /* Arguments to currently executing user function */
Mem *aColName; /* Column names to return */
int nCursor; /* Number of slots in apCsr[] */
Cursor **apCsr; /* One element of this array for each open cursor */
int nVar; /* Number of entries in aVar[] */
Mem *aVar; /* Values for the OP_Variable opcode. */
char **azVar; /* Name of variables */
int okVar; /* True if azVar[] has been initialized */
int magic; /* Magic number for sanity checking */
int nMem; /* Number of memory locations currently allocated */
Mem *aMem; /* The memory locations */
Agg agg; /* Aggregate information */
int nSet; /* Number of sets allocated */
Set *aSet; /* An array of sets */
int nCallback; /* Number of callbacks invoked so far */
Keylist *pList; /* A list of ROWIDs */
int keylistStackDepth; /* The size of the "keylist" stack */
Keylist **keylistStack; /* The stack used by opcodes ListPush & ListPop */
int cacheCtr; /* Cursor row cache generation counter */
Fifo sFifo; /* A list of ROWIDs */
int contextStackTop; /* Index of top element in the context stack */
int contextStackDepth; /* The size of the "context" stack */
Context *contextStack; /* Stack used by opcodes ContextPush & ContextPop*/
int pc; /* The program counter */
int rc; /* Value to return */
unsigned uniqueCnt; /* Used by OP_MakeRecord when P2!=0 */
int errorAction; /* Recovery action to do in case of an error */
int undoTransOnError; /* If error, either ROLLBACK or COMMIT */
int inTempTrans; /* True if temp database is transactioned */
int returnStack[100]; /* Return address stack for OP_Gosub & OP_Return */
int returnDepth; /* Next unused element in returnStack[] */
@ -277,7 +309,18 @@ struct Vdbe {
char **azResColumn; /* Values for one row of result */
int popStack; /* Pop the stack this much on entry to VdbeExec() */
char *zErrMsg; /* Error message written here */
u8 resOnStack; /* True if there are result values on the stack */
u8 explain; /* True if EXPLAIN present on SQL command */
u8 changeCntOn; /* True to update the change-counter */
u8 aborted; /* True if ROLLBACK in another VM causes an abort */
u8 expired; /* True if the VM needs to be recompiled */
u8 minWriteFileFormat; /* Minimum file format for writable database files */
int nChange; /* Number of db changes made since last reset */
i64 startTime; /* Time when query started - used for profiling */
#ifdef SQLITE_SSE
int fetchId; /* Statement number used by sqlite3_fetch_statement */
int lru; /* Counter used for LRU cache replacement */
#endif
};
/*
@ -291,13 +334,59 @@ struct Vdbe {
/*
** Function prototypes
*/
void sqliteVdbeCleanupCursor(Cursor*);
void sqliteVdbeSorterReset(Vdbe*);
void sqliteVdbeAggReset(Agg*);
void sqliteVdbeKeylistFree(Keylist*);
void sqlite3VdbeFreeCursor(Cursor*);
void sqliteVdbePopStack(Vdbe*,int);
int sqliteVdbeCursorMoveto(Cursor*);
int sqliteVdbeByteSwap(int);
#if !defined(NDEBUG) || defined(VDBE_PROFILE)
void sqliteVdbePrintOp(FILE*, int, Op*);
int sqlite3VdbeCursorMoveto(Cursor*);
#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE)
void sqlite3VdbePrintOp(FILE*, int, Op*);
#endif
#ifdef SQLITE_DEBUG
void sqlite3VdbePrintSql(Vdbe*);
#endif
int sqlite3VdbeSerialTypeLen(u32);
u32 sqlite3VdbeSerialType(Mem*, int);
int sqlite3VdbeSerialPut(unsigned char*, Mem*, int);
int sqlite3VdbeSerialGet(const unsigned char*, u32, Mem*);
void sqlite3VdbeDeleteAuxData(VdbeFunc*, int);
int sqlite2BtreeKeyCompare(BtCursor *, const void *, int, int, int *);
int sqlite3VdbeIdxKeyCompare(Cursor*, int , const unsigned char*, int*);
int sqlite3VdbeIdxRowid(BtCursor *, i64 *);
int sqlite3MemCompare(const Mem*, const Mem*, const CollSeq*);
int sqlite3VdbeRecordCompare(void*,int,const void*,int, const void*);
int sqlite3VdbeIdxRowidLen(const u8*);
int sqlite3VdbeExec(Vdbe*);
int sqlite3VdbeList(Vdbe*);
int sqlite3VdbeHalt(Vdbe*);
int sqlite3VdbeChangeEncoding(Mem *, int);
int sqlite3VdbeMemCopy(Mem*, const Mem*);
void sqlite3VdbeMemShallowCopy(Mem*, const Mem*, int);
int sqlite3VdbeMemMove(Mem*, Mem*);
int sqlite3VdbeMemNulTerminate(Mem*);
int sqlite3VdbeMemSetStr(Mem*, const char*, int, u8, void(*)(void*));
void sqlite3VdbeMemSetInt64(Mem*, i64);
void sqlite3VdbeMemSetDouble(Mem*, double);
void sqlite3VdbeMemSetNull(Mem*);
int sqlite3VdbeMemMakeWriteable(Mem*);
int sqlite3VdbeMemDynamicify(Mem*);
int sqlite3VdbeMemStringify(Mem*, int);
i64 sqlite3VdbeIntValue(Mem*);
int sqlite3VdbeMemIntegerify(Mem*);
double sqlite3VdbeRealValue(Mem*);
void sqlite3VdbeIntegerAffinity(Mem*);
int sqlite3VdbeMemRealify(Mem*);
int sqlite3VdbeMemNumerify(Mem*);
int sqlite3VdbeMemFromBtree(BtCursor*,int,int,int,Mem*);
void sqlite3VdbeMemRelease(Mem *p);
int sqlite3VdbeMemFinalize(Mem*, FuncDef*);
#ifndef NDEBUG
void sqlite3VdbeMemSanity(Mem*);
int sqlite3VdbeOpcodeNoPush(u8);
#endif
int sqlite3VdbeMemTranslate(Mem*, u8);
void sqlite3VdbeMemPrettyPrint(Mem *pMem, char *zBuf);
int sqlite3VdbeMemHandleBom(Mem *pMem);
void sqlite3VdbeFifoInit(Fifo*);
int sqlite3VdbeFifoPush(Fifo*, i64);
int sqlite3VdbeFifoPop(Fifo*, i64*);
void sqlite3VdbeFifoClear(Fifo*);

815
sqlite/vdbeapi.c Executable file
View File

@ -0,0 +1,815 @@
/*
** 2004 May 26
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
**
** This file contains code use to implement APIs that are part of the
** VDBE.
*/
#include "sqliteInt.h"
#include "vdbeInt.h"
#include "os.h"
/*
** Return TRUE (non-zero) of the statement supplied as an argument needs
** to be recompiled. A statement needs to be recompiled whenever the
** execution environment changes in a way that would alter the program
** that sqlite3_prepare() generates. For example, if new functions or
** collating sequences are registered or if an authorizer function is
** added or changed.
*/
int sqlite3_expired(sqlite3_stmt *pStmt){
Vdbe *p = (Vdbe*)pStmt;
return p==0 || p->expired;
}
/**************************** sqlite3_value_ *******************************
** The following routines extract information from a Mem or sqlite3_value
** structure.
*/
const void *sqlite3_value_blob(sqlite3_value *pVal){
Mem *p = (Mem*)pVal;
if( p->flags & (MEM_Blob|MEM_Str) ){
return p->z;
}else{
return sqlite3_value_text(pVal);
}
}
int sqlite3_value_bytes(sqlite3_value *pVal){
return sqlite3ValueBytes(pVal, SQLITE_UTF8);
}
int sqlite3_value_bytes16(sqlite3_value *pVal){
return sqlite3ValueBytes(pVal, SQLITE_UTF16NATIVE);
}
double sqlite3_value_double(sqlite3_value *pVal){
return sqlite3VdbeRealValue((Mem*)pVal);
}
int sqlite3_value_int(sqlite3_value *pVal){
return sqlite3VdbeIntValue((Mem*)pVal);
}
sqlite_int64 sqlite3_value_int64(sqlite3_value *pVal){
return sqlite3VdbeIntValue((Mem*)pVal);
}
const unsigned char *sqlite3_value_text(sqlite3_value *pVal){
return (const unsigned char *)sqlite3ValueText(pVal, SQLITE_UTF8);
}
#ifndef SQLITE_OMIT_UTF16
const void *sqlite3_value_text16(sqlite3_value* pVal){
return sqlite3ValueText(pVal, SQLITE_UTF16NATIVE);
}
const void *sqlite3_value_text16be(sqlite3_value *pVal){
return sqlite3ValueText(pVal, SQLITE_UTF16BE);
}
const void *sqlite3_value_text16le(sqlite3_value *pVal){
return sqlite3ValueText(pVal, SQLITE_UTF16LE);
}
#endif /* SQLITE_OMIT_UTF16 */
int sqlite3_value_type(sqlite3_value* pVal){
return pVal->type;
}
/* sqlite3_value_numeric_type() defined in vdbe.c */
/**************************** sqlite3_result_ *******************************
** The following routines are used by user-defined functions to specify
** the function result.
*/
void sqlite3_result_blob(
sqlite3_context *pCtx,
const void *z,
int n,
void (*xDel)(void *)
){
assert( n>=0 );
sqlite3VdbeMemSetStr(&pCtx->s, z, n, 0, xDel);
}
void sqlite3_result_double(sqlite3_context *pCtx, double rVal){
sqlite3VdbeMemSetDouble(&pCtx->s, rVal);
}
void sqlite3_result_error(sqlite3_context *pCtx, const char *z, int n){
pCtx->isError = 1;
sqlite3VdbeMemSetStr(&pCtx->s, z, n, SQLITE_UTF8, SQLITE_TRANSIENT);
}
#ifndef SQLITE_OMIT_UTF16
void sqlite3_result_error16(sqlite3_context *pCtx, const void *z, int n){
pCtx->isError = 1;
sqlite3VdbeMemSetStr(&pCtx->s, z, n, SQLITE_UTF16NATIVE, SQLITE_TRANSIENT);
}
#endif
void sqlite3_result_int(sqlite3_context *pCtx, int iVal){
sqlite3VdbeMemSetInt64(&pCtx->s, (i64)iVal);
}
void sqlite3_result_int64(sqlite3_context *pCtx, i64 iVal){
sqlite3VdbeMemSetInt64(&pCtx->s, iVal);
}
void sqlite3_result_null(sqlite3_context *pCtx){
sqlite3VdbeMemSetNull(&pCtx->s);
}
void sqlite3_result_text(
sqlite3_context *pCtx,
const char *z,
int n,
void (*xDel)(void *)
){
sqlite3VdbeMemSetStr(&pCtx->s, z, n, SQLITE_UTF8, xDel);
}
#ifndef SQLITE_OMIT_UTF16
void sqlite3_result_text16(
sqlite3_context *pCtx,
const void *z,
int n,
void (*xDel)(void *)
){
sqlite3VdbeMemSetStr(&pCtx->s, z, n, SQLITE_UTF16NATIVE, xDel);
}
void sqlite3_result_text16be(
sqlite3_context *pCtx,
const void *z,
int n,
void (*xDel)(void *)
){
sqlite3VdbeMemSetStr(&pCtx->s, z, n, SQLITE_UTF16BE, xDel);
}
void sqlite3_result_text16le(
sqlite3_context *pCtx,
const void *z,
int n,
void (*xDel)(void *)
){
sqlite3VdbeMemSetStr(&pCtx->s, z, n, SQLITE_UTF16LE, xDel);
}
#endif /* SQLITE_OMIT_UTF16 */
void sqlite3_result_value(sqlite3_context *pCtx, sqlite3_value *pValue){
sqlite3VdbeMemCopy(&pCtx->s, pValue);
}
/*
** Execute the statement pStmt, either until a row of data is ready, the
** statement is completely executed or an error occurs.
*/
int sqlite3_step(sqlite3_stmt *pStmt){
Vdbe *p = (Vdbe*)pStmt;
sqlite3 *db;
int rc;
/* Assert that malloc() has not failed */
assert( !sqlite3MallocFailed() );
if( p==0 || p->magic!=VDBE_MAGIC_RUN ){
return SQLITE_MISUSE;
}
if( p->aborted ){
return SQLITE_ABORT;
}
if( p->pc<=0 && p->expired ){
if( p->rc==SQLITE_OK ){
p->rc = SQLITE_SCHEMA;
}
return SQLITE_ERROR;
}
db = p->db;
if( sqlite3SafetyOn(db) ){
p->rc = SQLITE_MISUSE;
return SQLITE_MISUSE;
}
if( p->pc<0 ){
#ifndef SQLITE_OMIT_TRACE
/* Invoke the trace callback if there is one
*/
if( db->xTrace && !db->init.busy ){
assert( p->nOp>0 );
assert( p->aOp[p->nOp-1].opcode==OP_Noop );
assert( p->aOp[p->nOp-1].p3!=0 );
assert( p->aOp[p->nOp-1].p3type==P3_DYNAMIC );
sqlite3SafetyOff(db);
db->xTrace(db->pTraceArg, p->aOp[p->nOp-1].p3);
if( sqlite3SafetyOn(db) ){
p->rc = SQLITE_MISUSE;
return SQLITE_MISUSE;
}
}
if( db->xProfile && !db->init.busy ){
double rNow;
sqlite3OsCurrentTime(&rNow);
p->startTime = (rNow - (int)rNow)*3600.0*24.0*1000000000.0;
}
#endif
/* Print a copy of SQL as it is executed if the SQL_TRACE pragma is turned
** on in debugging mode.
*/
#ifdef SQLITE_DEBUG
if( (db->flags & SQLITE_SqlTrace)!=0 ){
sqlite3DebugPrintf("SQL-trace: %s\n", p->aOp[p->nOp-1].p3);
}
#endif /* SQLITE_DEBUG */
db->activeVdbeCnt++;
p->pc = 0;
}
#ifndef SQLITE_OMIT_EXPLAIN
if( p->explain ){
rc = sqlite3VdbeList(p);
}else
#endif /* SQLITE_OMIT_EXPLAIN */
{
rc = sqlite3VdbeExec(p);
}
if( sqlite3SafetyOff(db) ){
rc = SQLITE_MISUSE;
}
#ifndef SQLITE_OMIT_TRACE
/* Invoke the profile callback if there is one
*/
if( rc!=SQLITE_ROW && db->xProfile && !db->init.busy ){
double rNow;
u64 elapseTime;
sqlite3OsCurrentTime(&rNow);
elapseTime = (rNow - (int)rNow)*3600.0*24.0*1000000000.0 - p->startTime;
assert( p->nOp>0 );
assert( p->aOp[p->nOp-1].opcode==OP_Noop );
assert( p->aOp[p->nOp-1].p3!=0 );
assert( p->aOp[p->nOp-1].p3type==P3_DYNAMIC );
db->xProfile(db->pProfileArg, p->aOp[p->nOp-1].p3, elapseTime);
}
#endif
sqlite3Error(p->db, rc, 0);
p->rc = sqlite3ApiExit(p->db, p->rc);
return rc;
}
/*
** Extract the user data from a sqlite3_context structure and return a
** pointer to it.
*/
void *sqlite3_user_data(sqlite3_context *p){
assert( p && p->pFunc );
return p->pFunc->pUserData;
}
/*
** Allocate or return the aggregate context for a user function. A new
** context is allocated on the first call. Subsequent calls return the
** same context that was returned on prior calls.
*/
void *sqlite3_aggregate_context(sqlite3_context *p, int nByte){
Mem *pMem = p->pMem;
assert( p && p->pFunc && p->pFunc->xStep );
if( (pMem->flags & MEM_Agg)==0 ){
if( nByte==0 ){
assert( pMem->flags==MEM_Null );
pMem->z = 0;
}else{
pMem->flags = MEM_Agg;
pMem->xDel = sqlite3FreeX;
*(FuncDef**)&pMem->i = p->pFunc;
if( nByte<=NBFS ){
pMem->z = pMem->zShort;
memset(pMem->z, 0, nByte);
}else{
pMem->z = sqliteMalloc( nByte );
}
}
}
return (void*)pMem->z;
}
/*
** Return the auxilary data pointer, if any, for the iArg'th argument to
** the user-function defined by pCtx.
*/
void *sqlite3_get_auxdata(sqlite3_context *pCtx, int iArg){
VdbeFunc *pVdbeFunc = pCtx->pVdbeFunc;
if( !pVdbeFunc || iArg>=pVdbeFunc->nAux || iArg<0 ){
return 0;
}
return pVdbeFunc->apAux[iArg].pAux;
}
/*
** Set the auxilary data pointer and delete function, for the iArg'th
** argument to the user-function defined by pCtx. Any previous value is
** deleted by calling the delete function specified when it was set.
*/
void sqlite3_set_auxdata(
sqlite3_context *pCtx,
int iArg,
void *pAux,
void (*xDelete)(void*)
){
struct AuxData *pAuxData;
VdbeFunc *pVdbeFunc;
if( iArg<0 ) return;
pVdbeFunc = pCtx->pVdbeFunc;
if( !pVdbeFunc || pVdbeFunc->nAux<=iArg ){
int nMalloc = sizeof(VdbeFunc) + sizeof(struct AuxData)*iArg;
pVdbeFunc = sqliteRealloc(pVdbeFunc, nMalloc);
if( !pVdbeFunc ) return;
pCtx->pVdbeFunc = pVdbeFunc;
memset(&pVdbeFunc->apAux[pVdbeFunc->nAux], 0,
sizeof(struct AuxData)*(iArg+1-pVdbeFunc->nAux));
pVdbeFunc->nAux = iArg+1;
pVdbeFunc->pFunc = pCtx->pFunc;
}
pAuxData = &pVdbeFunc->apAux[iArg];
if( pAuxData->pAux && pAuxData->xDelete ){
pAuxData->xDelete(pAuxData->pAux);
}
pAuxData->pAux = pAux;
pAuxData->xDelete = xDelete;
}
/*
** Return the number of times the Step function of a aggregate has been
** called.
**
** This function is deprecated. Do not use it for new code. It is
** provide only to avoid breaking legacy code. New aggregate function
** implementations should keep their own counts within their aggregate
** context.
*/
int sqlite3_aggregate_count(sqlite3_context *p){
assert( p && p->pFunc && p->pFunc->xStep );
return p->pMem->n;
}
/*
** Return the number of columns in the result set for the statement pStmt.
*/
int sqlite3_column_count(sqlite3_stmt *pStmt){
Vdbe *pVm = (Vdbe *)pStmt;
return pVm ? pVm->nResColumn : 0;
}
/*
** Return the number of values available from the current row of the
** currently executing statement pStmt.
*/
int sqlite3_data_count(sqlite3_stmt *pStmt){
Vdbe *pVm = (Vdbe *)pStmt;
if( pVm==0 || !pVm->resOnStack ) return 0;
return pVm->nResColumn;
}
/*
** Check to see if column iCol of the given statement is valid. If
** it is, return a pointer to the Mem for the value of that column.
** If iCol is not valid, return a pointer to a Mem which has a value
** of NULL.
*/
static Mem *columnMem(sqlite3_stmt *pStmt, int i){
Vdbe *pVm = (Vdbe *)pStmt;
int vals = sqlite3_data_count(pStmt);
if( i>=vals || i<0 ){
static Mem nullMem;
if( nullMem.flags==0 ){ nullMem.flags = MEM_Null; }
sqlite3Error(pVm->db, SQLITE_RANGE, 0);
return &nullMem;
}
return &pVm->pTos[(1-vals)+i];
}
/*
** This function is called after invoking an sqlite3_value_XXX function on a
** column value (i.e. a value returned by evaluating an SQL expression in the
** select list of a SELECT statement) that may cause a malloc() failure. If
** malloc() has failed, the threads mallocFailed flag is cleared and the result
** code of statement pStmt set to SQLITE_NOMEM.
**
** Specificly, this is called from within:
**
** sqlite3_column_int()
** sqlite3_column_int64()
** sqlite3_column_text()
** sqlite3_column_text16()
** sqlite3_column_real()
** sqlite3_column_bytes()
** sqlite3_column_bytes16()
**
** But not for sqlite3_column_blob(), which never calls malloc().
*/
static void columnMallocFailure(sqlite3_stmt *pStmt)
{
/* If malloc() failed during an encoding conversion within an
** sqlite3_column_XXX API, then set the return code of the statement to
** SQLITE_NOMEM. The next call to _step() (if any) will return SQLITE_ERROR
** and _finalize() will return NOMEM.
*/
Vdbe *p = (Vdbe *)pStmt;
p->rc = sqlite3ApiExit(0, p->rc);
}
/**************************** sqlite3_column_ *******************************
** The following routines are used to access elements of the current row
** in the result set.
*/
const void *sqlite3_column_blob(sqlite3_stmt *pStmt, int i){
const void *val;
sqlite3MallocDisallow();
val = sqlite3_value_blob( columnMem(pStmt,i) );
sqlite3MallocAllow();
return val;
}
int sqlite3_column_bytes(sqlite3_stmt *pStmt, int i){
int val = sqlite3_value_bytes( columnMem(pStmt,i) );
columnMallocFailure(pStmt);
return val;
}
int sqlite3_column_bytes16(sqlite3_stmt *pStmt, int i){
int val = sqlite3_value_bytes16( columnMem(pStmt,i) );
columnMallocFailure(pStmt);
return val;
}
double sqlite3_column_double(sqlite3_stmt *pStmt, int i){
double val = sqlite3_value_double( columnMem(pStmt,i) );
columnMallocFailure(pStmt);
return val;
}
int sqlite3_column_int(sqlite3_stmt *pStmt, int i){
int val = sqlite3_value_int( columnMem(pStmt,i) );
columnMallocFailure(pStmt);
return val;
}
sqlite_int64 sqlite3_column_int64(sqlite3_stmt *pStmt, int i){
sqlite_int64 val = sqlite3_value_int64( columnMem(pStmt,i) );
columnMallocFailure(pStmt);
return val;
}
const unsigned char *sqlite3_column_text(sqlite3_stmt *pStmt, int i){
const unsigned char *val = sqlite3_value_text( columnMem(pStmt,i) );
columnMallocFailure(pStmt);
return val;
}
#if 0
sqlite3_value *sqlite3_column_value(sqlite3_stmt *pStmt, int i){
return columnMem(pStmt, i);
}
#endif
#ifndef SQLITE_OMIT_UTF16
const void *sqlite3_column_text16(sqlite3_stmt *pStmt, int i){
const void *val = sqlite3_value_text16( columnMem(pStmt,i) );
columnMallocFailure(pStmt);
return val;
}
#endif /* SQLITE_OMIT_UTF16 */
int sqlite3_column_type(sqlite3_stmt *pStmt, int i){
return sqlite3_value_type( columnMem(pStmt,i) );
}
/* The following function is experimental and subject to change or
** removal */
/*int sqlite3_column_numeric_type(sqlite3_stmt *pStmt, int i){
** return sqlite3_value_numeric_type( columnMem(pStmt,i) );
**}
*/
/*
** Convert the N-th element of pStmt->pColName[] into a string using
** xFunc() then return that string. If N is out of range, return 0.
**
** There are up to 5 names for each column. useType determines which
** name is returned. Here are the names:
**
** 0 The column name as it should be displayed for output
** 1 The datatype name for the column
** 2 The name of the database that the column derives from
** 3 The name of the table that the column derives from
** 4 The name of the table column that the result column derives from
**
** If the result is not a simple column reference (if it is an expression
** or a constant) then useTypes 2, 3, and 4 return NULL.
*/
static const void *columnName(
sqlite3_stmt *pStmt,
int N,
const void *(*xFunc)(Mem*),
int useType
){
const void *ret;
Vdbe *p = (Vdbe *)pStmt;
int n = sqlite3_column_count(pStmt);
if( p==0 || N>=n || N<0 ){
return 0;
}
N += useType*n;
ret = xFunc(&p->aColName[N]);
/* A malloc may have failed inside of the xFunc() call. If this is the case,
** clear the mallocFailed flag and return NULL.
*/
sqlite3ApiExit(0, 0);
return ret;
}
/*
** Return the name of the Nth column of the result set returned by SQL
** statement pStmt.
*/
const char *sqlite3_column_name(sqlite3_stmt *pStmt, int N){
return columnName(
pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, COLNAME_NAME);
}
#ifndef SQLITE_OMIT_UTF16
const void *sqlite3_column_name16(sqlite3_stmt *pStmt, int N){
return columnName(
pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, COLNAME_NAME);
}
#endif
/*
** Return the column declaration type (if applicable) of the 'i'th column
** of the result set of SQL statement pStmt.
*/
const char *sqlite3_column_decltype(sqlite3_stmt *pStmt, int N){
return columnName(
pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, COLNAME_DECLTYPE);
}
#ifndef SQLITE_OMIT_UTF16
const void *sqlite3_column_decltype16(sqlite3_stmt *pStmt, int N){
return columnName(
pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, COLNAME_DECLTYPE);
}
#endif /* SQLITE_OMIT_UTF16 */
#ifdef SQLITE_ENABLE_COLUMN_METADATA
/*
** Return the name of the database from which a result column derives.
** NULL is returned if the result column is an expression or constant or
** anything else which is not an unabiguous reference to a database column.
*/
const char *sqlite3_column_database_name(sqlite3_stmt *pStmt, int N){
return columnName(
pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, COLNAME_DATABASE);
}
#ifndef SQLITE_OMIT_UTF16
const void *sqlite3_column_database_name16(sqlite3_stmt *pStmt, int N){
return columnName(
pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, COLNAME_DATABASE);
}
#endif /* SQLITE_OMIT_UTF16 */
/*
** Return the name of the table from which a result column derives.
** NULL is returned if the result column is an expression or constant or
** anything else which is not an unabiguous reference to a database column.
*/
const char *sqlite3_column_table_name(sqlite3_stmt *pStmt, int N){
return columnName(
pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, COLNAME_TABLE);
}
#ifndef SQLITE_OMIT_UTF16
const void *sqlite3_column_table_name16(sqlite3_stmt *pStmt, int N){
return columnName(
pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, COLNAME_TABLE);
}
#endif /* SQLITE_OMIT_UTF16 */
/*
** Return the name of the table column from which a result column derives.
** NULL is returned if the result column is an expression or constant or
** anything else which is not an unabiguous reference to a database column.
*/
const char *sqlite3_column_origin_name(sqlite3_stmt *pStmt, int N){
return columnName(
pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, COLNAME_COLUMN);
}
#ifndef SQLITE_OMIT_UTF16
const void *sqlite3_column_origin_name16(sqlite3_stmt *pStmt, int N){
return columnName(
pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, COLNAME_COLUMN);
}
#endif /* SQLITE_OMIT_UTF16 */
#endif /* SQLITE_ENABLE_COLUMN_METADATA */
/******************************* sqlite3_bind_ ***************************
**
** Routines used to attach values to wildcards in a compiled SQL statement.
*/
/*
** Unbind the value bound to variable i in virtual machine p. This is the
** the same as binding a NULL value to the column. If the "i" parameter is
** out of range, then SQLITE_RANGE is returned. Othewise SQLITE_OK.
**
** The error code stored in database p->db is overwritten with the return
** value in any case.
*/
static int vdbeUnbind(Vdbe *p, int i){
Mem *pVar;
if( p==0 || p->magic!=VDBE_MAGIC_RUN || p->pc>=0 ){
if( p ) sqlite3Error(p->db, SQLITE_MISUSE, 0);
return SQLITE_MISUSE;
}
if( i<1 || i>p->nVar ){
sqlite3Error(p->db, SQLITE_RANGE, 0);
return SQLITE_RANGE;
}
i--;
pVar = &p->aVar[i];
sqlite3VdbeMemRelease(pVar);
pVar->flags = MEM_Null;
sqlite3Error(p->db, SQLITE_OK, 0);
return SQLITE_OK;
}
/*
** Bind a text or BLOB value.
*/
static int bindText(
sqlite3_stmt *pStmt,
int i,
const void *zData,
int nData,
void (*xDel)(void*),
int encoding
){
Vdbe *p = (Vdbe *)pStmt;
Mem *pVar;
int rc;
rc = vdbeUnbind(p, i);
if( rc || zData==0 ){
return rc;
}
pVar = &p->aVar[i-1];
rc = sqlite3VdbeMemSetStr(pVar, zData, nData, encoding, xDel);
if( rc==SQLITE_OK && encoding!=0 ){
rc = sqlite3VdbeChangeEncoding(pVar, ENC(p->db));
}
sqlite3Error(((Vdbe *)pStmt)->db, rc, 0);
return sqlite3ApiExit(((Vdbe *)pStmt)->db, rc);
}
/*
** Bind a blob value to an SQL statement variable.
*/
int sqlite3_bind_blob(
sqlite3_stmt *pStmt,
int i,
const void *zData,
int nData,
void (*xDel)(void*)
){
return bindText(pStmt, i, zData, nData, xDel, 0);
}
int sqlite3_bind_double(sqlite3_stmt *pStmt, int i, double rValue){
int rc;
Vdbe *p = (Vdbe *)pStmt;
rc = vdbeUnbind(p, i);
if( rc==SQLITE_OK ){
sqlite3VdbeMemSetDouble(&p->aVar[i-1], rValue);
}
return rc;
}
int sqlite3_bind_int(sqlite3_stmt *p, int i, int iValue){
return sqlite3_bind_int64(p, i, (i64)iValue);
}
int sqlite3_bind_int64(sqlite3_stmt *pStmt, int i, sqlite_int64 iValue){
int rc;
Vdbe *p = (Vdbe *)pStmt;
rc = vdbeUnbind(p, i);
if( rc==SQLITE_OK ){
sqlite3VdbeMemSetInt64(&p->aVar[i-1], iValue);
}
return rc;
}
int sqlite3_bind_null(sqlite3_stmt* p, int i){
return vdbeUnbind((Vdbe *)p, i);
}
int sqlite3_bind_text(
sqlite3_stmt *pStmt,
int i,
const char *zData,
int nData,
void (*xDel)(void*)
){
return bindText(pStmt, i, zData, nData, xDel, SQLITE_UTF8);
}
#ifndef SQLITE_OMIT_UTF16
int sqlite3_bind_text16(
sqlite3_stmt *pStmt,
int i,
const void *zData,
int nData,
void (*xDel)(void*)
){
return bindText(pStmt, i, zData, nData, xDel, SQLITE_UTF16NATIVE);
}
#endif /* SQLITE_OMIT_UTF16 */
/*
** Return the number of wildcards that can be potentially bound to.
** This routine is added to support DBD::SQLite.
*/
int sqlite3_bind_parameter_count(sqlite3_stmt *pStmt){
Vdbe *p = (Vdbe*)pStmt;
return p ? p->nVar : 0;
}
/*
** Create a mapping from variable numbers to variable names
** in the Vdbe.azVar[] array, if such a mapping does not already
** exist.
*/
static void createVarMap(Vdbe *p){
if( !p->okVar ){
int j;
Op *pOp;
for(j=0, pOp=p->aOp; j<p->nOp; j++, pOp++){
if( pOp->opcode==OP_Variable ){
assert( pOp->p1>0 && pOp->p1<=p->nVar );
p->azVar[pOp->p1-1] = pOp->p3;
}
}
p->okVar = 1;
}
}
/*
** Return the name of a wildcard parameter. Return NULL if the index
** is out of range or if the wildcard is unnamed.
**
** The result is always UTF-8.
*/
const char *sqlite3_bind_parameter_name(sqlite3_stmt *pStmt, int i){
Vdbe *p = (Vdbe*)pStmt;
if( p==0 || i<1 || i>p->nVar ){
return 0;
}
createVarMap(p);
return p->azVar[i-1];
}
/*
** Given a wildcard parameter name, return the index of the variable
** with that name. If there is no variable with the given name,
** return 0.
*/
int sqlite3_bind_parameter_index(sqlite3_stmt *pStmt, const char *zName){
Vdbe *p = (Vdbe*)pStmt;
int i;
if( p==0 ){
return 0;
}
createVarMap(p);
if( zName ){
for(i=0; i<p->nVar; i++){
const char *z = p->azVar[i];
if( z && strcmp(z,zName)==0 ){
return i+1;
}
}
}
return 0;
}
/*
** Transfer all bindings from the first statement over to the second.
** If the two statements contain a different number of bindings, then
** an SQLITE_ERROR is returned.
*/
int sqlite3_transfer_bindings(sqlite3_stmt *pFromStmt, sqlite3_stmt *pToStmt){
Vdbe *pFrom = (Vdbe*)pFromStmt;
Vdbe *pTo = (Vdbe*)pToStmt;
int i, rc = SQLITE_OK;
if( (pFrom->magic!=VDBE_MAGIC_RUN && pFrom->magic!=VDBE_MAGIC_HALT)
|| (pTo->magic!=VDBE_MAGIC_RUN && pTo->magic!=VDBE_MAGIC_HALT) ){
return SQLITE_MISUSE;
}
if( pFrom->nVar!=pTo->nVar ){
return SQLITE_ERROR;
}
for(i=0; rc==SQLITE_OK && i<pFrom->nVar; i++){
sqlite3MallocDisallow();
rc = sqlite3VdbeMemMove(&pTo->aVar[i], &pFrom->aVar[i]);
sqlite3MallocAllow();
}
return rc;
}
/*
** Return the sqlite3* database handle to which the prepared statement given
** in the argument belongs. This is the same database handle that was
** the first argument to the sqlite3_prepare() that was used to create
** the statement in the first place.
*/
sqlite3 *sqlite3_db_handle(sqlite3_stmt *pStmt){
return pStmt ? ((Vdbe*)pStmt)->db : 0;
}

File diff suppressed because it is too large Load Diff

114
sqlite/vdbefifo.c Executable file
View File

@ -0,0 +1,114 @@
/*
** 2005 June 16
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
** This file implements a FIFO queue of rowids used for processing
** UPDATE and DELETE statements.
*/
#include "sqliteInt.h"
#include "vdbeInt.h"
/*
** Allocate a new FifoPage and return a pointer to it. Return NULL if
** we run out of memory. Leave space on the page for nEntry entries.
*/
static FifoPage *allocatePage(int nEntry){
FifoPage *pPage;
if( nEntry>32767 ){
nEntry = 32767;
}
pPage = sqliteMallocRaw( sizeof(FifoPage) + sizeof(i64)*(nEntry-1) );
if( pPage ){
pPage->nSlot = nEntry;
pPage->iWrite = 0;
pPage->iRead = 0;
pPage->pNext = 0;
}
return pPage;
}
/*
** Initialize a Fifo structure.
*/
void sqlite3VdbeFifoInit(Fifo *pFifo){
memset(pFifo, 0, sizeof(*pFifo));
}
/*
** Push a single 64-bit integer value into the Fifo. Return SQLITE_OK
** normally. SQLITE_NOMEM is returned if we are unable to allocate
** memory.
*/
int sqlite3VdbeFifoPush(Fifo *pFifo, i64 val){
FifoPage *pPage;
pPage = pFifo->pLast;
if( pPage==0 ){
pPage = pFifo->pLast = pFifo->pFirst = allocatePage(20);
if( pPage==0 ){
return SQLITE_NOMEM;
}
}else if( pPage->iWrite>=pPage->nSlot ){
pPage->pNext = allocatePage(pFifo->nEntry);
if( pPage->pNext==0 ){
return SQLITE_NOMEM;
}
pPage = pFifo->pLast = pPage->pNext;
}
pPage->aSlot[pPage->iWrite++] = val;
pFifo->nEntry++;
return SQLITE_OK;
}
/*
** Extract a single 64-bit integer value from the Fifo. The integer
** extracted is the one least recently inserted. If the Fifo is empty
** return SQLITE_DONE.
*/
int sqlite3VdbeFifoPop(Fifo *pFifo, i64 *pVal){
FifoPage *pPage;
if( pFifo->nEntry==0 ){
return SQLITE_DONE;
}
assert( pFifo->nEntry>0 );
pPage = pFifo->pFirst;
assert( pPage!=0 );
assert( pPage->iWrite>pPage->iRead );
assert( pPage->iWrite<=pPage->nSlot );
assert( pPage->iRead<pPage->nSlot );
assert( pPage->iRead>=0 );
*pVal = pPage->aSlot[pPage->iRead++];
pFifo->nEntry--;
if( pPage->iRead>=pPage->iWrite ){
pFifo->pFirst = pPage->pNext;
sqliteFree(pPage);
if( pFifo->nEntry==0 ){
assert( pFifo->pLast==pPage );
pFifo->pLast = 0;
}else{
assert( pFifo->pFirst!=0 );
}
}else{
assert( pFifo->nEntry>0 );
}
return SQLITE_OK;
}
/*
** Delete all information from a Fifo object. Free all memory held
** by the Fifo.
*/
void sqlite3VdbeFifoClear(Fifo *pFifo){
FifoPage *pPage, *pNextPage;
for(pPage=pFifo->pFirst; pPage; pPage=pNextPage){
pNextPage = pPage->pNext;
sqliteFree(pPage);
}
sqlite3VdbeFifoInit(pFifo);
}

907
sqlite/vdbemem.c Executable file
View File

@ -0,0 +1,907 @@
/*
** 2004 May 26
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
**
** This file contains code use to manipulate "Mem" structure. A "Mem"
** stores a single value in the VDBE. Mem is an opaque structure visible
** only within the VDBE. Interface routines refer to a Mem using the
** name sqlite_value
*/
#include "sqliteInt.h"
#include "os.h"
#include <ctype.h>
#include "vdbeInt.h"
/*
** If pMem is an object with a valid string representation, this routine
** ensures the internal encoding for the string representation is
** 'desiredEnc', one of SQLITE_UTF8, SQLITE_UTF16LE or SQLITE_UTF16BE.
**
** If pMem is not a string object, or the encoding of the string
** representation is already stored using the requested encoding, then this
** routine is a no-op.
**
** SQLITE_OK is returned if the conversion is successful (or not required).
** SQLITE_NOMEM may be returned if a malloc() fails during conversion
** between formats.
*/
int sqlite3VdbeChangeEncoding(Mem *pMem, int desiredEnc){
int rc;
if( !(pMem->flags&MEM_Str) || pMem->enc==desiredEnc ){
return SQLITE_OK;
}
#ifdef SQLITE_OMIT_UTF16
return SQLITE_ERROR;
#else
/* MemTranslate() may return SQLITE_OK or SQLITE_NOMEM. If NOMEM is returned,
** then the encoding of the value may not have changed.
*/
rc = sqlite3VdbeMemTranslate(pMem, desiredEnc);
assert(rc==SQLITE_OK || rc==SQLITE_NOMEM);
assert(rc==SQLITE_OK || pMem->enc!=desiredEnc);
assert(rc==SQLITE_NOMEM || pMem->enc==desiredEnc);
if( rc==SQLITE_NOMEM ){
/*
sqlite3VdbeMemRelease(pMem);
pMem->flags = MEM_Null;
pMem->z = 0;
*/
}
return rc;
#endif
}
/*
** Make the given Mem object MEM_Dyn.
**
** Return SQLITE_OK on success or SQLITE_NOMEM if malloc fails.
*/
int sqlite3VdbeMemDynamicify(Mem *pMem){
int n = pMem->n;
u8 *z;
if( (pMem->flags & (MEM_Ephem|MEM_Static|MEM_Short))==0 ){
return SQLITE_OK;
}
assert( (pMem->flags & MEM_Dyn)==0 );
assert( pMem->flags & (MEM_Str|MEM_Blob) );
z = sqliteMallocRaw( n+2 );
if( z==0 ){
return SQLITE_NOMEM;
}
pMem->flags |= MEM_Dyn|MEM_Term;
pMem->xDel = 0;
memcpy(z, pMem->z, n );
z[n] = 0;
z[n+1] = 0;
pMem->z = (char*)z;
pMem->flags &= ~(MEM_Ephem|MEM_Static|MEM_Short);
return SQLITE_OK;
}
/*
** Make the given Mem object either MEM_Short or MEM_Dyn so that bytes
** of the Mem.z[] array can be modified.
**
** Return SQLITE_OK on success or SQLITE_NOMEM if malloc fails.
*/
int sqlite3VdbeMemMakeWriteable(Mem *pMem){
int n;
u8 *z;
if( (pMem->flags & (MEM_Ephem|MEM_Static))==0 ){
return SQLITE_OK;
}
assert( (pMem->flags & MEM_Dyn)==0 );
assert( pMem->flags & (MEM_Str|MEM_Blob) );
if( (n = pMem->n)+2<sizeof(pMem->zShort) ){
z = (u8*)pMem->zShort;
pMem->flags |= MEM_Short|MEM_Term;
}else{
z = sqliteMallocRaw( n+2 );
if( z==0 ){
return SQLITE_NOMEM;
}
pMem->flags |= MEM_Dyn|MEM_Term;
pMem->xDel = 0;
}
memcpy(z, pMem->z, n );
z[n] = 0;
z[n+1] = 0;
pMem->z = (char*)z;
pMem->flags &= ~(MEM_Ephem|MEM_Static);
assert(0==(1&(int)pMem->z));
return SQLITE_OK;
}
/*
** Make sure the given Mem is \u0000 terminated.
*/
int sqlite3VdbeMemNulTerminate(Mem *pMem){
/* In SQLite, a string without a nul terminator occurs when a string
** is loaded from disk (in this case the memory management is ephemeral),
** or when it is supplied by the user as a bound variable or function
** return value. Therefore, the memory management of the string must be
** either ephemeral, static or controlled by a user-supplied destructor.
*/
assert(
!(pMem->flags&MEM_Str) || /* it's not a string, or */
(pMem->flags&MEM_Term) || /* it's nul term. already, or */
(pMem->flags&(MEM_Ephem|MEM_Static)) || /* it's static or ephem, or */
(pMem->flags&MEM_Dyn && pMem->xDel) /* external management */
);
if( (pMem->flags & MEM_Term)!=0 || (pMem->flags & MEM_Str)==0 ){
return SQLITE_OK; /* Nothing to do */
}
if( pMem->flags & (MEM_Static|MEM_Ephem) ){
return sqlite3VdbeMemMakeWriteable(pMem);
}else{
char *z = sqliteMalloc(pMem->n+2);
if( !z ) return SQLITE_NOMEM;
memcpy(z, pMem->z, pMem->n);
z[pMem->n] = 0;
z[pMem->n+1] = 0;
pMem->xDel(pMem->z);
pMem->xDel = 0;
pMem->z = z;
}
return SQLITE_OK;
}
/*
** Add MEM_Str to the set of representations for the given Mem. Numbers
** are converted using sqlite3_snprintf(). Converting a BLOB to a string
** is a no-op.
**
** Existing representations MEM_Int and MEM_Real are *not* invalidated.
**
** A MEM_Null value will never be passed to this function. This function is
** used for converting values to text for returning to the user (i.e. via
** sqlite3_value_text()), or for ensuring that values to be used as btree
** keys are strings. In the former case a NULL pointer is returned the
** user and the later is an internal programming error.
*/
int sqlite3VdbeMemStringify(Mem *pMem, int enc){
int rc = SQLITE_OK;
int fg = pMem->flags;
char *z = pMem->zShort;
assert( !(fg&(MEM_Str|MEM_Blob)) );
assert( fg&(MEM_Int|MEM_Real) );
/* For a Real or Integer, use sqlite3_snprintf() to produce the UTF-8
** string representation of the value. Then, if the required encoding
** is UTF-16le or UTF-16be do a translation.
**
** FIX ME: It would be better if sqlite3_snprintf() could do UTF-16.
*/
if( fg & MEM_Int ){
sqlite3_snprintf(NBFS, z, "%lld", pMem->i);
}else{
assert( fg & MEM_Real );
sqlite3_snprintf(NBFS, z, "%!.15g", pMem->r);
}
pMem->n = strlen(z);
pMem->z = z;
pMem->enc = SQLITE_UTF8;
pMem->flags |= MEM_Str | MEM_Short | MEM_Term;
sqlite3VdbeChangeEncoding(pMem, enc);
return rc;
}
/*
** Memory cell pMem contains the context of an aggregate function.
** This routine calls the finalize method for that function. The
** result of the aggregate is stored back into pMem.
**
** Return SQLITE_ERROR if the finalizer reports an error. SQLITE_OK
** otherwise.
*/
int sqlite3VdbeMemFinalize(Mem *pMem, FuncDef *pFunc){
int rc = SQLITE_OK;
if( pFunc && pFunc->xFinalize ){
sqlite3_context ctx;
assert( (pMem->flags & MEM_Null)!=0 || pFunc==*(FuncDef**)&pMem->i );
ctx.s.flags = MEM_Null;
ctx.s.z = pMem->zShort;
ctx.pMem = pMem;
ctx.pFunc = pFunc;
ctx.isError = 0;
pFunc->xFinalize(&ctx);
if( pMem->z && pMem->z!=pMem->zShort ){
sqliteFree( pMem->z );
}
*pMem = ctx.s;
if( pMem->flags & MEM_Short ){
pMem->z = pMem->zShort;
}
if( ctx.isError ){
rc = SQLITE_ERROR;
}
}
return rc;
}
/*
** Release any memory held by the Mem. This may leave the Mem in an
** inconsistent state, for example with (Mem.z==0) and
** (Mem.type==SQLITE_TEXT).
*/
void sqlite3VdbeMemRelease(Mem *p){
if( p->flags & (MEM_Dyn|MEM_Agg) ){
if( p->xDel ){
if( p->flags & MEM_Agg ){
sqlite3VdbeMemFinalize(p, *(FuncDef**)&p->i);
assert( (p->flags & MEM_Agg)==0 );
sqlite3VdbeMemRelease(p);
}else{
p->xDel((void *)p->z);
}
}else{
sqliteFree(p->z);
}
p->z = 0;
p->xDel = 0;
}
}
/*
** Return some kind of integer value which is the best we can do
** at representing the value that *pMem describes as an integer.
** If pMem is an integer, then the value is exact. If pMem is
** a floating-point then the value returned is the integer part.
** If pMem is a string or blob, then we make an attempt to convert
** it into a integer and return that. If pMem is NULL, return 0.
**
** If pMem is a string, its encoding might be changed.
*/
i64 sqlite3VdbeIntValue(Mem *pMem){
int flags = pMem->flags;
if( flags & MEM_Int ){
return pMem->i;
}else if( flags & MEM_Real ){
return (i64)pMem->r;
}else if( flags & (MEM_Str|MEM_Blob) ){
i64 value;
if( sqlite3VdbeChangeEncoding(pMem, SQLITE_UTF8)
|| sqlite3VdbeMemNulTerminate(pMem) ){
return 0;
}
assert( pMem->z );
sqlite3atoi64(pMem->z, &value);
return value;
}else{
return 0;
}
}
/*
** Return the best representation of pMem that we can get into a
** double. If pMem is already a double or an integer, return its
** value. If it is a string or blob, try to convert it to a double.
** If it is a NULL, return 0.0.
*/
double sqlite3VdbeRealValue(Mem *pMem){
if( pMem->flags & MEM_Real ){
return pMem->r;
}else if( pMem->flags & MEM_Int ){
return (double)pMem->i;
}else if( pMem->flags & (MEM_Str|MEM_Blob) ){
double val = 0.0;
if( sqlite3VdbeChangeEncoding(pMem, SQLITE_UTF8)
|| sqlite3VdbeMemNulTerminate(pMem) ){
return 0.0;
}
assert( pMem->z );
sqlite3AtoF(pMem->z, &val);
return val;
}else{
return 0.0;
}
}
/*
** The MEM structure is already a MEM_Real. Try to also make it a
** MEM_Int if we can.
*/
void sqlite3VdbeIntegerAffinity(Mem *pMem){
assert( pMem->flags & MEM_Real );
pMem->i = pMem->r;
if( ((double)pMem->i)==pMem->r ){
pMem->flags |= MEM_Int;
}
}
/*
** Convert pMem to type integer. Invalidate any prior representations.
*/
int sqlite3VdbeMemIntegerify(Mem *pMem){
pMem->i = sqlite3VdbeIntValue(pMem);
sqlite3VdbeMemRelease(pMem);
pMem->flags = MEM_Int;
return SQLITE_OK;
}
/*
** Convert pMem so that it is of type MEM_Real.
** Invalidate any prior representations.
*/
int sqlite3VdbeMemRealify(Mem *pMem){
pMem->r = sqlite3VdbeRealValue(pMem);
sqlite3VdbeMemRelease(pMem);
pMem->flags = MEM_Real;
return SQLITE_OK;
}
/*
** Convert pMem so that it has types MEM_Real or MEM_Int or both.
** Invalidate any prior representations.
*/
int sqlite3VdbeMemNumerify(Mem *pMem){
sqlite3VdbeMemRealify(pMem);
sqlite3VdbeIntegerAffinity(pMem);
return SQLITE_OK;
}
/*
** Delete any previous value and set the value stored in *pMem to NULL.
*/
void sqlite3VdbeMemSetNull(Mem *pMem){
sqlite3VdbeMemRelease(pMem);
pMem->flags = MEM_Null;
pMem->type = SQLITE_NULL;
pMem->n = 0;
}
/*
** Delete any previous value and set the value stored in *pMem to val,
** manifest type INTEGER.
*/
void sqlite3VdbeMemSetInt64(Mem *pMem, i64 val){
sqlite3VdbeMemRelease(pMem);
pMem->i = val;
pMem->flags = MEM_Int;
pMem->type = SQLITE_INTEGER;
}
/*
** Delete any previous value and set the value stored in *pMem to val,
** manifest type REAL.
*/
void sqlite3VdbeMemSetDouble(Mem *pMem, double val){
sqlite3VdbeMemRelease(pMem);
pMem->r = val;
pMem->flags = MEM_Real;
pMem->type = SQLITE_FLOAT;
}
/*
** Make an shallow copy of pFrom into pTo. Prior contents of
** pTo are overwritten. The pFrom->z field is not duplicated. If
** pFrom->z is used, then pTo->z points to the same thing as pFrom->z
** and flags gets srcType (either MEM_Ephem or MEM_Static).
*/
void sqlite3VdbeMemShallowCopy(Mem *pTo, const Mem *pFrom, int srcType){
memcpy(pTo, pFrom, sizeof(*pFrom)-sizeof(pFrom->zShort));
pTo->xDel = 0;
if( pTo->flags & (MEM_Str|MEM_Blob) ){
pTo->flags &= ~(MEM_Dyn|MEM_Static|MEM_Short|MEM_Ephem);
assert( srcType==MEM_Ephem || srcType==MEM_Static );
pTo->flags |= srcType;
}
}
/*
** Make a full copy of pFrom into pTo. Prior contents of pTo are
** freed before the copy is made.
*/
int sqlite3VdbeMemCopy(Mem *pTo, const Mem *pFrom){
int rc;
if( pTo->flags & MEM_Dyn ){
sqlite3VdbeMemRelease(pTo);
}
sqlite3VdbeMemShallowCopy(pTo, pFrom, MEM_Ephem);
if( pTo->flags & MEM_Ephem ){
rc = sqlite3VdbeMemMakeWriteable(pTo);
}else{
rc = SQLITE_OK;
}
return rc;
}
/*
** Transfer the contents of pFrom to pTo. Any existing value in pTo is
** freed. If pFrom contains ephemeral data, a copy is made.
**
** pFrom contains an SQL NULL when this routine returns. SQLITE_NOMEM
** might be returned if pFrom held ephemeral data and we were unable
** to allocate enough space to make a copy.
*/
int sqlite3VdbeMemMove(Mem *pTo, Mem *pFrom){
int rc;
if( pTo->flags & MEM_Dyn ){
sqlite3VdbeMemRelease(pTo);
}
memcpy(pTo, pFrom, sizeof(Mem));
if( pFrom->flags & MEM_Short ){
pTo->z = pTo->zShort;
}
pFrom->flags = MEM_Null;
pFrom->xDel = 0;
if( pTo->flags & MEM_Ephem ){
rc = sqlite3VdbeMemMakeWriteable(pTo);
}else{
rc = SQLITE_OK;
}
return rc;
}
/*
** Change the value of a Mem to be a string or a BLOB.
*/
int sqlite3VdbeMemSetStr(
Mem *pMem, /* Memory cell to set to string value */
const char *z, /* String pointer */
int n, /* Bytes in string, or negative */
u8 enc, /* Encoding of z. 0 for BLOBs */
void (*xDel)(void*) /* Destructor function */
){
sqlite3VdbeMemRelease(pMem);
if( !z ){
pMem->flags = MEM_Null;
pMem->type = SQLITE_NULL;
return SQLITE_OK;
}
pMem->z = (char *)z;
if( xDel==SQLITE_STATIC ){
pMem->flags = MEM_Static;
}else if( xDel==SQLITE_TRANSIENT ){
pMem->flags = MEM_Ephem;
}else{
pMem->flags = MEM_Dyn;
pMem->xDel = xDel;
}
pMem->enc = enc;
pMem->type = enc==0 ? SQLITE_BLOB : SQLITE_TEXT;
pMem->n = n;
assert( enc==0 || enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE
|| enc==SQLITE_UTF16BE );
switch( enc ){
case 0:
pMem->flags |= MEM_Blob;
pMem->enc = SQLITE_UTF8;
break;
case SQLITE_UTF8:
pMem->flags |= MEM_Str;
if( n<0 ){
pMem->n = strlen(z);
pMem->flags |= MEM_Term;
}
break;
#ifndef SQLITE_OMIT_UTF16
case SQLITE_UTF16LE:
case SQLITE_UTF16BE:
pMem->flags |= MEM_Str;
if( pMem->n<0 ){
pMem->n = sqlite3utf16ByteLen(pMem->z,-1);
pMem->flags |= MEM_Term;
}
if( sqlite3VdbeMemHandleBom(pMem) ){
return SQLITE_NOMEM;
}
#endif /* SQLITE_OMIT_UTF16 */
}
if( pMem->flags&MEM_Ephem ){
return sqlite3VdbeMemMakeWriteable(pMem);
}
return SQLITE_OK;
}
/*
** Compare the values contained by the two memory cells, returning
** negative, zero or positive if pMem1 is less than, equal to, or greater
** than pMem2. Sorting order is NULL's first, followed by numbers (integers
** and reals) sorted numerically, followed by text ordered by the collating
** sequence pColl and finally blob's ordered by memcmp().
**
** Two NULL values are considered equal by this function.
*/
int sqlite3MemCompare(const Mem *pMem1, const Mem *pMem2, const CollSeq *pColl){
int rc;
int f1, f2;
int combined_flags;
/* Interchange pMem1 and pMem2 if the collating sequence specifies
** DESC order.
*/
f1 = pMem1->flags;
f2 = pMem2->flags;
combined_flags = f1|f2;
/* If one value is NULL, it is less than the other. If both values
** are NULL, return 0.
*/
if( combined_flags&MEM_Null ){
return (f2&MEM_Null) - (f1&MEM_Null);
}
/* If one value is a number and the other is not, the number is less.
** If both are numbers, compare as reals if one is a real, or as integers
** if both values are integers.
*/
if( combined_flags&(MEM_Int|MEM_Real) ){
if( !(f1&(MEM_Int|MEM_Real)) ){
return 1;
}
if( !(f2&(MEM_Int|MEM_Real)) ){
return -1;
}
if( (f1 & f2 & MEM_Int)==0 ){
double r1, r2;
if( (f1&MEM_Real)==0 ){
r1 = pMem1->i;
}else{
r1 = pMem1->r;
}
if( (f2&MEM_Real)==0 ){
r2 = pMem2->i;
}else{
r2 = pMem2->r;
}
if( r1<r2 ) return -1;
if( r1>r2 ) return 1;
return 0;
}else{
assert( f1&MEM_Int );
assert( f2&MEM_Int );
if( pMem1->i < pMem2->i ) return -1;
if( pMem1->i > pMem2->i ) return 1;
return 0;
}
}
/* If one value is a string and the other is a blob, the string is less.
** If both are strings, compare using the collating functions.
*/
if( combined_flags&MEM_Str ){
if( (f1 & MEM_Str)==0 ){
return 1;
}
if( (f2 & MEM_Str)==0 ){
return -1;
}
assert( pMem1->enc==pMem2->enc );
assert( pMem1->enc==SQLITE_UTF8 ||
pMem1->enc==SQLITE_UTF16LE || pMem1->enc==SQLITE_UTF16BE );
/* The collation sequence must be defined at this point, even if
** the user deletes the collation sequence after the vdbe program is
** compiled (this was not always the case).
*/
assert( !pColl || pColl->xCmp );
if( pColl ){
if( pMem1->enc==pColl->enc ){
/* The strings are already in the correct encoding. Call the
** comparison function directly */
return pColl->xCmp(pColl->pUser,pMem1->n,pMem1->z,pMem2->n,pMem2->z);
}else{
u8 origEnc = pMem1->enc;
const void *v1, *v2;
int n1, n2;
/* Convert the strings into the encoding that the comparison
** function expects */
v1 = sqlite3ValueText((sqlite3_value*)pMem1, pColl->enc);
n1 = v1==0 ? 0 : pMem1->n;
assert( n1==sqlite3ValueBytes((sqlite3_value*)pMem1, pColl->enc) );
v2 = sqlite3ValueText((sqlite3_value*)pMem2, pColl->enc);
n2 = v2==0 ? 0 : pMem2->n;
assert( n2==sqlite3ValueBytes((sqlite3_value*)pMem2, pColl->enc) );
/* Do the comparison */
rc = pColl->xCmp(pColl->pUser, n1, v1, n2, v2);
/* Convert the strings back into the database encoding */
sqlite3ValueText((sqlite3_value*)pMem1, origEnc);
sqlite3ValueText((sqlite3_value*)pMem2, origEnc);
return rc;
}
}
/* If a NULL pointer was passed as the collate function, fall through
** to the blob case and use memcmp(). */
}
/* Both values must be blobs. Compare using memcmp(). */
rc = memcmp(pMem1->z, pMem2->z, (pMem1->n>pMem2->n)?pMem2->n:pMem1->n);
if( rc==0 ){
rc = pMem1->n - pMem2->n;
}
return rc;
}
/*
** Move data out of a btree key or data field and into a Mem structure.
** The data or key is taken from the entry that pCur is currently pointing
** to. offset and amt determine what portion of the data or key to retrieve.
** key is true to get the key or false to get data. The result is written
** into the pMem element.
**
** The pMem structure is assumed to be uninitialized. Any prior content
** is overwritten without being freed.
**
** If this routine fails for any reason (malloc returns NULL or unable
** to read from the disk) then the pMem is left in an inconsistent state.
*/
int sqlite3VdbeMemFromBtree(
BtCursor *pCur, /* Cursor pointing at record to retrieve. */
int offset, /* Offset from the start of data to return bytes from. */
int amt, /* Number of bytes to return. */
int key, /* If true, retrieve from the btree key, not data. */
Mem *pMem /* OUT: Return data in this Mem structure. */
){
char *zData; /* Data from the btree layer */
int available; /* Number of bytes available on the local btree page */
if( key ){
zData = (char *)sqlite3BtreeKeyFetch(pCur, &available);
}else{
zData = (char *)sqlite3BtreeDataFetch(pCur, &available);
}
pMem->n = amt;
if( offset+amt<=available ){
pMem->z = &zData[offset];
pMem->flags = MEM_Blob|MEM_Ephem;
}else{
int rc;
if( amt>NBFS-2 ){
zData = (char *)sqliteMallocRaw(amt+2);
if( !zData ){
return SQLITE_NOMEM;
}
pMem->flags = MEM_Blob|MEM_Dyn|MEM_Term;
pMem->xDel = 0;
}else{
zData = &(pMem->zShort[0]);
pMem->flags = MEM_Blob|MEM_Short|MEM_Term;
}
pMem->z = zData;
pMem->enc = 0;
pMem->type = SQLITE_BLOB;
if( key ){
rc = sqlite3BtreeKey(pCur, offset, amt, zData);
}else{
rc = sqlite3BtreeData(pCur, offset, amt, zData);
}
zData[amt] = 0;
zData[amt+1] = 0;
if( rc!=SQLITE_OK ){
if( amt>NBFS-2 ){
assert( zData!=pMem->zShort );
assert( pMem->flags & MEM_Dyn );
sqliteFree(zData);
} else {
assert( zData==pMem->zShort );
assert( pMem->flags & MEM_Short );
}
return rc;
}
}
return SQLITE_OK;
}
#ifndef NDEBUG
/*
** Perform various checks on the memory cell pMem. An assert() will
** fail if pMem is internally inconsistent.
*/
void sqlite3VdbeMemSanity(Mem *pMem){
int flags = pMem->flags;
assert( flags!=0 ); /* Must define some type */
if( pMem->flags & (MEM_Str|MEM_Blob) ){
int x = pMem->flags & (MEM_Static|MEM_Dyn|MEM_Ephem|MEM_Short);
assert( x!=0 ); /* Strings must define a string subtype */
assert( (x & (x-1))==0 ); /* Only one string subtype can be defined */
assert( pMem->z!=0 ); /* Strings must have a value */
/* Mem.z points to Mem.zShort iff the subtype is MEM_Short */
assert( (pMem->flags & MEM_Short)==0 || pMem->z==pMem->zShort );
assert( (pMem->flags & MEM_Short)!=0 || pMem->z!=pMem->zShort );
/* No destructor unless there is MEM_Dyn */
assert( pMem->xDel==0 || (pMem->flags & MEM_Dyn)!=0 );
if( (flags & MEM_Str) ){
assert( pMem->enc==SQLITE_UTF8 ||
pMem->enc==SQLITE_UTF16BE ||
pMem->enc==SQLITE_UTF16LE
);
/* If the string is UTF-8 encoded and nul terminated, then pMem->n
** must be the length of the string. (Later:) If the database file
** has been corrupted, '\000' characters might have been inserted
** into the middle of the string. In that case, the strlen() might
** be less.
*/
if( pMem->enc==SQLITE_UTF8 && (flags & MEM_Term) ){
assert( strlen(pMem->z)<=pMem->n );
assert( pMem->z[pMem->n]==0 );
}
}
}else{
/* Cannot define a string subtype for non-string objects */
assert( (pMem->flags & (MEM_Static|MEM_Dyn|MEM_Ephem|MEM_Short))==0 );
assert( pMem->xDel==0 );
}
/* MEM_Null excludes all other types */
assert( (pMem->flags&(MEM_Str|MEM_Int|MEM_Real|MEM_Blob))==0
|| (pMem->flags&MEM_Null)==0 );
/* If the MEM is both real and integer, the values are equal */
assert( (pMem->flags & (MEM_Int|MEM_Real))!=(MEM_Int|MEM_Real)
|| pMem->r==pMem->i );
}
#endif
/* This function is only available internally, it is not part of the
** external API. It works in a similar way to sqlite3_value_text(),
** except the data returned is in the encoding specified by the second
** parameter, which must be one of SQLITE_UTF16BE, SQLITE_UTF16LE or
** SQLITE_UTF8.
**
** (2006-02-16:) The enc value can be or-ed with SQLITE_UTF16_ALIGNED.
** If that is the case, then the result must be aligned on an even byte
** boundary.
*/
const void *sqlite3ValueText(sqlite3_value* pVal, u8 enc){
if( !pVal ) return 0;
assert( (enc&3)==(enc&~SQLITE_UTF16_ALIGNED) );
if( pVal->flags&MEM_Null ){
return 0;
}
assert( (MEM_Blob>>3) == MEM_Str );
pVal->flags |= (pVal->flags & MEM_Blob)>>3;
if( pVal->flags&MEM_Str ){
sqlite3VdbeChangeEncoding(pVal, enc & ~SQLITE_UTF16_ALIGNED);
if( (enc & SQLITE_UTF16_ALIGNED)!=0 && 1==(1&(int)pVal->z) ){
assert( (pVal->flags & (MEM_Ephem|MEM_Static))!=0 );
if( sqlite3VdbeMemMakeWriteable(pVal)!=SQLITE_OK ){
return 0;
}
}
}else if( !(pVal->flags&MEM_Blob) ){
sqlite3VdbeMemStringify(pVal, enc);
assert( 0==(1&(int)pVal->z) );
}
assert(pVal->enc==(enc & ~SQLITE_UTF16_ALIGNED) || sqlite3MallocFailed() );
if( pVal->enc==(enc & ~SQLITE_UTF16_ALIGNED) ){
return pVal->z;
}else{
return 0;
}
}
/*
** Create a new sqlite3_value object.
*/
sqlite3_value* sqlite3ValueNew(void){
Mem *p = sqliteMalloc(sizeof(*p));
if( p ){
p->flags = MEM_Null;
p->type = SQLITE_NULL;
}
return p;
}
/*
** Create a new sqlite3_value object, containing the value of pExpr.
**
** This only works for very simple expressions that consist of one constant
** token (i.e. "5", "5.1", "NULL", "'a string'"). If the expression can
** be converted directly into a value, then the value is allocated and
** a pointer written to *ppVal. The caller is responsible for deallocating
** the value by passing it to sqlite3ValueFree() later on. If the expression
** cannot be converted to a value, then *ppVal is set to NULL.
*/
int sqlite3ValueFromExpr(
Expr *pExpr,
u8 enc,
u8 affinity,
sqlite3_value **ppVal
){
int op;
char *zVal = 0;
sqlite3_value *pVal = 0;
if( !pExpr ){
*ppVal = 0;
return SQLITE_OK;
}
op = pExpr->op;
if( op==TK_STRING || op==TK_FLOAT || op==TK_INTEGER ){
zVal = sqliteStrNDup((char*)pExpr->token.z, pExpr->token.n);
pVal = sqlite3ValueNew();
if( !zVal || !pVal ) goto no_mem;
sqlite3Dequote(zVal);
sqlite3ValueSetStr(pVal, -1, zVal, SQLITE_UTF8, sqlite3FreeX);
if( (op==TK_INTEGER || op==TK_FLOAT ) && affinity==SQLITE_AFF_NONE ){
sqlite3ValueApplyAffinity(pVal, SQLITE_AFF_NUMERIC, enc);
}else{
sqlite3ValueApplyAffinity(pVal, affinity, enc);
}
}else if( op==TK_UMINUS ) {
if( SQLITE_OK==sqlite3ValueFromExpr(pExpr->pLeft, enc, affinity, &pVal) ){
pVal->i = -1 * pVal->i;
pVal->r = -1.0 * pVal->r;
}
}
#ifndef SQLITE_OMIT_BLOB_LITERAL
else if( op==TK_BLOB ){
int nVal;
pVal = sqlite3ValueNew();
zVal = sqliteStrNDup((char*)pExpr->token.z+1, pExpr->token.n-1);
if( !zVal || !pVal ) goto no_mem;
sqlite3Dequote(zVal);
nVal = strlen(zVal)/2;
sqlite3VdbeMemSetStr(pVal, sqlite3HexToBlob(zVal), nVal, 0, sqlite3FreeX);
sqliteFree(zVal);
}
#endif
*ppVal = pVal;
return SQLITE_OK;
no_mem:
sqliteFree(zVal);
sqlite3ValueFree(pVal);
*ppVal = 0;
return SQLITE_NOMEM;
}
/*
** Change the string value of an sqlite3_value object
*/
void sqlite3ValueSetStr(
sqlite3_value *v,
int n,
const void *z,
u8 enc,
void (*xDel)(void*)
){
if( v ) sqlite3VdbeMemSetStr((Mem *)v, z, n, enc, xDel);
}
/*
** Free an sqlite3_value object
*/
void sqlite3ValueFree(sqlite3_value *v){
if( !v ) return;
sqlite3ValueSetStr(v, 0, 0, SQLITE_UTF8, SQLITE_STATIC);
sqliteFree(v);
}
/*
** Return the number of bytes in the sqlite3_value object assuming
** that it uses the encoding "enc"
*/
int sqlite3ValueBytes(sqlite3_value *pVal, u8 enc){
Mem *p = (Mem*)pVal;
if( (p->flags & MEM_Blob)!=0 || sqlite3ValueText(pVal, enc) ){
return p->n;
}
return 0;
}

File diff suppressed because it is too large Load Diff