зеркало из https://github.com/mozilla/pjs.git
Bug 341137 - Upgrade to latest version of sqlite. r=vladimir
This commit is contained in:
Родитель
312a19f6b6
Коммит
13ecb97542
|
@ -21,6 +21,7 @@
|
|||
#
|
||||
# Contributor(s):
|
||||
# Vladimir Vukicevic <vladimir.vukicevic@oracle.com>
|
||||
# Shawn Wilsher <me@shawnwilsher.com>
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
|
@ -48,52 +49,22 @@ LIBRARY_NAME = sqlite3_s
|
|||
MODULE_NAME = sqlite3
|
||||
FORCE_STATIC_LIB = 1
|
||||
|
||||
ifdef GNU_CC
|
||||
MODULE_OPTIMIZE_FLAGS = -O3
|
||||
else
|
||||
ifeq ($(OS_ARCH),SunOS)
|
||||
MODULE_OPTIMIZE_FLAGS = -fast
|
||||
endif
|
||||
ifeq ($(OS_ARCH),WINNT)
|
||||
MODULE_OPTIMIZE_FLAGS = -Ox
|
||||
endif
|
||||
endif
|
||||
|
||||
|
||||
EXPORTS = sqlite3.h sqlite3file.h
|
||||
|
||||
CSRCS = \
|
||||
alter.c \
|
||||
analyze.c \
|
||||
attach.c \
|
||||
auth.c \
|
||||
btree.c \
|
||||
build.c \
|
||||
callback.c \
|
||||
complete.c \
|
||||
date.c \
|
||||
delete.c \
|
||||
experimental.c \
|
||||
expr.c \
|
||||
func.c \
|
||||
hash.c \
|
||||
insert.c \
|
||||
legacy.c \
|
||||
main.c \
|
||||
opcodes.c \
|
||||
os.c \
|
||||
os_unix.c \
|
||||
os_win.c \
|
||||
os_os2.c \
|
||||
os_beos.c \
|
||||
pager.c \
|
||||
parse.c \
|
||||
pragma.c \
|
||||
prepare.c \
|
||||
printf.c \
|
||||
random.c \
|
||||
select.c \
|
||||
table.c \
|
||||
tokenize.c \
|
||||
trigger.c \
|
||||
update.c \
|
||||
utf.c \
|
||||
util.c \
|
||||
vacuum.c \
|
||||
vdbe.c \
|
||||
vdbeapi.c \
|
||||
vdbeaux.c \
|
||||
vdbefifo.c \
|
||||
vdbemem.c \
|
||||
where.c \
|
||||
sqlite3.c \
|
||||
$(NULL)
|
||||
|
||||
# REFEF_IO allows us to override IO functions, which is used in the AsyncIO
|
||||
|
|
|
@ -1,562 +0,0 @@
|
|||
/*
|
||||
** 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.7 2006-05-22 17:48:14 brettw%gmail.com 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 */
|
|
@ -1,403 +0,0 @@
|
|||
/*
|
||||
** 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.4 2006-05-22 17:48:14 brettw%gmail.com 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 */
|
|
@ -1,367 +0,0 @@
|
|||
/*
|
||||
** 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.5 2006-05-22 17:48:14 brettw%gmail.com 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;
|
||||
}
|
|
@ -1,263 +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.
|
||||
**
|
||||
*************************************************************************
|
||||
** 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.4 2006-05-22 17:48:14 brettw%gmail.com 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 */
|
|
@ -1,37 +0,0 @@
|
|||
/*
|
||||
** 2005 January 20
|
||||
**
|
||||
** 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 are not a part of the official
|
||||
** SQLite API. These routines are unsupported.
|
||||
**
|
||||
** $Id: experimental.c,v 1.4 2006-05-22 17:48:14 brettw%gmail.com Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include "os.h"
|
||||
|
||||
/*
|
||||
** Set all the parameters in the compiled SQL statement to NULL.
|
||||
*/
|
||||
int sqlite3_clear_bindings(sqlite3_stmt *pStmt){
|
||||
int i;
|
||||
int rc = SQLITE_OK;
|
||||
for(i=1; rc==SQLITE_OK && i<=sqlite3_bind_parameter_count(pStmt); i++){
|
||||
rc = sqlite3_bind_null(pStmt, i);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Sleep for a little while. Return the amount of time slept.
|
||||
*/
|
||||
int sqlite3_sleep(int ms){
|
||||
return sqlite3OsSleep(ms);
|
||||
}
|
|
@ -1,583 +0,0 @@
|
|||
/*
|
||||
** 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.5 2006-05-22 17:48:14 brettw%gmail.com 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 */
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -12,7 +12,7 @@
|
|||
** This header file defines the interface that the SQLite library
|
||||
** presents to client programs.
|
||||
**
|
||||
** @(#) $Id: sqlite3.h,v 1.6 2006/05/22 17:48:14 brettw%gmail.com Exp $
|
||||
** @(#) $Id: sqlite.h.in,v 1.201 2007/03/30 20:43:42 drh Exp $
|
||||
*/
|
||||
#ifndef _SQLITE3_H_
|
||||
#define _SQLITE3_H_
|
||||
|
@ -31,7 +31,7 @@ extern "C" {
|
|||
#ifdef SQLITE_VERSION
|
||||
# undef SQLITE_VERSION
|
||||
#endif
|
||||
#define SQLITE_VERSION "3.3.5"
|
||||
#define SQLITE_VERSION "3.3.17"
|
||||
|
||||
/*
|
||||
** The format of the version string is "X.Y.Z<trailing string>", where
|
||||
|
@ -48,7 +48,7 @@ extern "C" {
|
|||
#ifdef SQLITE_VERSION_NUMBER
|
||||
# undef SQLITE_VERSION_NUMBER
|
||||
#endif
|
||||
#define SQLITE_VERSION_NUMBER 3003005
|
||||
#define SQLITE_VERSION_NUMBER 3003017
|
||||
|
||||
/*
|
||||
** The version string is also compiled into the library so that a program
|
||||
|
@ -125,7 +125,7 @@ typedef int (*sqlite3_callback)(void*,int,char**, char**);
|
|||
** value then the query is aborted, all subsequent SQL statements
|
||||
** are skipped and the sqlite3_exec() function returns the SQLITE_ABORT.
|
||||
**
|
||||
** The 4th parameter is an arbitrary pointer that is passed
|
||||
** The 1st 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
|
||||
|
@ -182,7 +182,7 @@ int sqlite3_exec(
|
|||
#define SQLITE_NOTFOUND 12 /* NOT USED. 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_PROTOCOL 15 /* NOT USED. Database lock protocol error */
|
||||
#define SQLITE_EMPTY 16 /* Database is empty */
|
||||
#define SQLITE_SCHEMA 17 /* The database schema changed */
|
||||
#define SQLITE_TOOBIG 18 /* NOT USED. Too much data for one row */
|
||||
|
@ -198,28 +198,71 @@ int sqlite3_exec(
|
|||
#define SQLITE_DONE 101 /* sqlite3_step() has finished executing */
|
||||
/* end-of-error-codes */
|
||||
|
||||
/*
|
||||
** Using the sqlite3_extended_result_codes() API, you can cause
|
||||
** SQLite to return result codes with additional information in
|
||||
** their upper bits. The lower 8 bits will be the same as the
|
||||
** primary result codes above. But the upper bits might contain
|
||||
** more specific error information.
|
||||
**
|
||||
** To extract the primary result code from an extended result code,
|
||||
** simply mask off the lower 8 bits.
|
||||
**
|
||||
** primary = extended & 0xff;
|
||||
**
|
||||
** New result error codes may be added from time to time. Software
|
||||
** that uses the extended result codes should plan accordingly and be
|
||||
** sure to always handle new unknown codes gracefully.
|
||||
**
|
||||
** The SQLITE_OK result code will never be extended. It will always
|
||||
** be exactly zero.
|
||||
**
|
||||
** The extended result codes always have the primary result code
|
||||
** as a prefix. Primary result codes only contain a single "_"
|
||||
** character. Extended result codes contain two or more "_" characters.
|
||||
*/
|
||||
#define SQLITE_IOERR_READ (SQLITE_IOERR | (1<<8))
|
||||
#define SQLITE_IOERR_SHORT_READ (SQLITE_IOERR | (2<<8))
|
||||
#define SQLITE_IOERR_WRITE (SQLITE_IOERR | (3<<8))
|
||||
#define SQLITE_IOERR_FSYNC (SQLITE_IOERR | (4<<8))
|
||||
#define SQLITE_IOERR_DIR_FSYNC (SQLITE_IOERR | (5<<8))
|
||||
#define SQLITE_IOERR_TRUNCATE (SQLITE_IOERR | (6<<8))
|
||||
#define SQLITE_IOERR_FSTAT (SQLITE_IOERR | (7<<8))
|
||||
#define SQLITE_IOERR_UNLOCK (SQLITE_IOERR | (8<<8))
|
||||
#define SQLITE_IOERR_RDLOCK (SQLITE_IOERR | (9<<8))
|
||||
#define SQLITE_IOERR_DELETE (SQLITE_IOERR | (10<<8))
|
||||
|
||||
/*
|
||||
** Enable or disable the extended result codes.
|
||||
*/
|
||||
int sqlite3_extended_result_codes(sqlite3*, int onoff);
|
||||
|
||||
/*
|
||||
** 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
|
||||
** otherwise the key is generated automatically. 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.
|
||||
*/
|
||||
sqlite_int64 sqlite3_last_insert_rowid(sqlite3*);
|
||||
|
||||
/*
|
||||
** This function returns the number of database rows that were changed
|
||||
** (or inserted or deleted) by the most recent called sqlite3_exec().
|
||||
** (or inserted or deleted) by the most recent SQL statement. Only
|
||||
** changes that are directly specified by the INSERT, UPDATE, or
|
||||
** DELETE statement are counted. Auxiliary changes caused by
|
||||
** triggers are not counted. Within the body of a trigger, however,
|
||||
** the sqlite3_changes() API can be called to find the number of
|
||||
** changes in the most recently completed INSERT, UPDATE, or DELETE
|
||||
** statement within the body of the trigger.
|
||||
**
|
||||
** 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 sqlite3_exec() recursively, then the changes
|
||||
** in the inner, recursive call are counted together with the changes
|
||||
** in the outer call.
|
||||
** If a callback invokes sqlite3_exec() or sqlite3_step() 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
|
||||
|
@ -254,6 +297,9 @@ int sqlite3_total_changes(sqlite3*);
|
|||
** 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.
|
||||
**
|
||||
** It is safe to call this routine from a different thread that the
|
||||
** thread that is currently running the database operation.
|
||||
*/
|
||||
void sqlite3_interrupt(sqlite3*);
|
||||
|
||||
|
@ -264,9 +310,13 @@ void sqlite3_interrupt(sqlite3*);
|
|||
** sqlite3_complete16(), a nul-terminated machine byte order UTF-16 string
|
||||
** is required.
|
||||
**
|
||||
** The algorithm is simple. If the last token other than spaces
|
||||
** and comments is a semicolon, then return true. otherwise return
|
||||
** false.
|
||||
** This routine is useful for command-line input to see of the user has
|
||||
** entered a complete statement of SQL or if the current statement needs
|
||||
** to be continued on the next line. The algorithm is simple. If the
|
||||
** last token other than spaces and comments is a semicolon, then return
|
||||
** true. Actually, the algorithm is a little more complicated than that
|
||||
** in order to deal with triggers, but the basic idea is the same: the
|
||||
** statement is not complete unless it ends in a semicolon.
|
||||
*/
|
||||
int sqlite3_complete(const char *sql);
|
||||
int sqlite3_complete16(const void *sql);
|
||||
|
@ -277,13 +327,30 @@ int sqlite3_complete16(const void *sql);
|
|||
** currently locked by another process or thread. If the busy callback
|
||||
** is NULL, then sqlite3_exec() returns SQLITE_BUSY immediately if
|
||||
** it finds a locked table. If the busy callback is not NULL, then
|
||||
** sqlite3_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
|
||||
** sqlite3_exec() invokes the callback with two arguments. The
|
||||
** first argument to the handler is a copy of the void* pointer which
|
||||
** is the third argument to this routine. The second argument to
|
||||
** the handler is the number of times that the busy handler has
|
||||
** been invoked for this locking event. If the
|
||||
** busy callback returns 0, then sqlite3_exec() immediately returns
|
||||
** SQLITE_BUSY. If the callback returns non-zero, then sqlite3_exec()
|
||||
** tries to open the table again and the cycle repeats.
|
||||
**
|
||||
** The presence of a busy handler does not guarantee that
|
||||
** it will be invoked when there is lock contention.
|
||||
** If SQLite determines that invoking the busy handler could result in
|
||||
** a deadlock, it will return SQLITE_BUSY instead.
|
||||
** Consider a scenario where one process is holding a read lock that
|
||||
** it is trying to promote to a reserved lock and
|
||||
** a second process is holding a reserved lock that it is trying
|
||||
** to promote to an exclusive lock. The first process cannot proceed
|
||||
** because it is blocked by the second and the second process cannot
|
||||
** proceed because it is blocked by the first. If both processes
|
||||
** invoke the busy handlers, neither will make any progress. Therefore,
|
||||
** SQLite returns SQLITE_BUSY for the first process, hoping that this
|
||||
** will induce the first process to release its read lock and allow
|
||||
** the second process to proceed.
|
||||
**
|
||||
** The default busy callback is NULL.
|
||||
**
|
||||
** Sqlite is re-entrant, so the busy handler may start a new query.
|
||||
|
@ -405,9 +472,19 @@ void sqlite3_free_table(char **result);
|
|||
*/
|
||||
char *sqlite3_mprintf(const char*,...);
|
||||
char *sqlite3_vmprintf(const char*, va_list);
|
||||
void sqlite3_free(char *z);
|
||||
char *sqlite3_snprintf(int,char*,const char*, ...);
|
||||
|
||||
/*
|
||||
** SQLite uses its own memory allocator. On many installations, this
|
||||
** memory allocator is identical to the standard malloc()/realloc()/free()
|
||||
** and can be used interchangable. On others, the implementations are
|
||||
** different. For maximum portability, it is best not to mix calls
|
||||
** to the standard malloc/realloc/free with the sqlite versions.
|
||||
*/
|
||||
void *sqlite3_malloc(int);
|
||||
void *sqlite3_realloc(void*, int);
|
||||
void sqlite3_free(void*);
|
||||
|
||||
#ifndef SQLITE_OMIT_AUTHORIZATION
|
||||
/*
|
||||
** This routine registers a callback with the SQLite library. The
|
||||
|
@ -466,7 +543,9 @@ int sqlite3_set_authorizer(
|
|||
#define SQLITE_ALTER_TABLE 26 /* Database Name Table Name */
|
||||
#define SQLITE_REINDEX 27 /* Index Name NULL */
|
||||
#define SQLITE_ANALYZE 28 /* Table Name NULL */
|
||||
|
||||
#define SQLITE_CREATE_VTABLE 29 /* Table Name Module Name */
|
||||
#define SQLITE_DROP_VTABLE 30 /* Table Name Module Name */
|
||||
#define SQLITE_FUNCTION 31 /* Function Name NULL */
|
||||
|
||||
/*
|
||||
** The return value of the authorization function should be one of the
|
||||
|
@ -642,6 +721,31 @@ int sqlite3_prepare16(
|
|||
const void **pzTail /* OUT: Pointer to unused portion of zSql */
|
||||
);
|
||||
|
||||
/*
|
||||
** Newer versions of the prepare API work just like the legacy versions
|
||||
** but with one exception: The a copy of the SQL text is saved in the
|
||||
** sqlite3_stmt structure that is returned. If this copy exists, it
|
||||
** modifieds the behavior of sqlite3_step() slightly. First, sqlite3_step()
|
||||
** will no longer return an SQLITE_SCHEMA error but will instead automatically
|
||||
** rerun the compiler to rebuild the prepared statement. Secondly,
|
||||
** sqlite3_step() now turns a full result code - the result code that
|
||||
** use used to have to call sqlite3_reset() to get.
|
||||
*/
|
||||
int sqlite3_prepare_v2(
|
||||
sqlite3 *db, /* Database handle */
|
||||
const char *zSql, /* SQL statement, UTF-8 encoded */
|
||||
int nBytes, /* Length of zSql in bytes. */
|
||||
sqlite3_stmt **ppStmt, /* OUT: Statement handle */
|
||||
const char **pzTail /* OUT: Pointer to unused portion of zSql */
|
||||
);
|
||||
int sqlite3_prepare16_v2(
|
||||
sqlite3 *db, /* Database handle */
|
||||
const void *zSql, /* SQL statement, UTF-16 encoded */
|
||||
int nBytes, /* Length of zSql in bytes. */
|
||||
sqlite3_stmt **ppStmt, /* OUT: Statement handle */
|
||||
const void **pzTail /* OUT: Pointer to unused portion of zSql */
|
||||
);
|
||||
|
||||
/*
|
||||
** Pointers to the following two opaque structures are used to communicate
|
||||
** with the implementations of user-defined functions.
|
||||
|
@ -651,31 +755,32 @@ typedef struct Mem sqlite3_value;
|
|||
|
||||
/*
|
||||
** In the SQL strings input to sqlite3_prepare() and sqlite3_prepare16(),
|
||||
** one or more literals can be replace by parameters "?" or ":AAA" or
|
||||
** "$VVV" where AAA is an identifer and VVV is a variable name according
|
||||
** to the syntax rules of the TCL programming language.
|
||||
** The value of these parameters (also called "host parameter names") can
|
||||
** be set using the routines listed below.
|
||||
** one or more literals can be replace by parameters "?" or "?NNN" or
|
||||
** ":AAA" or "@AAA" or "$VVV" where NNN is a integer, AAA is an identifer,
|
||||
** and VVV is a variable name according to the syntax rules of the
|
||||
** TCL programming language. The value of these parameters (also called
|
||||
** "host parameter names") can be set using the routines listed below.
|
||||
**
|
||||
** In every case, the first parameter is a pointer to the sqlite3_stmt
|
||||
** structure returned from sqlite3_prepare(). The second parameter is the
|
||||
** index of the parameter. The first parameter as an index of 1. For
|
||||
** named parameters (":AAA" or "$VVV") you can use
|
||||
** In every case, the first argument is a pointer to the sqlite3_stmt
|
||||
** structure returned from sqlite3_prepare(). The second argument is the
|
||||
** index of the host parameter name. The first host parameter as an index
|
||||
** of 1. For named host parameters (":AAA" or "$VVV") you can use
|
||||
** sqlite3_bind_parameter_index() to get the correct index value given
|
||||
** the parameters name. If the same named parameter occurs more than
|
||||
** the parameter name. If the same named parameter occurs more than
|
||||
** once, it is assigned the same index each time.
|
||||
**
|
||||
** The fifth parameter to sqlite3_bind_blob(), sqlite3_bind_text(), and
|
||||
** The fifth argument to sqlite3_bind_blob(), sqlite3_bind_text(), and
|
||||
** sqlite3_bind_text16() is a destructor used to dispose of the BLOB or
|
||||
** text after SQLite has finished with it. If the fifth argument is the
|
||||
** special value SQLITE_STATIC, then the library assumes that the information
|
||||
** is in static, unmanaged space and does not need to be freed. If the
|
||||
** fifth argument has the value SQLITE_TRANSIENT, then SQLite makes its
|
||||
** own private copy of the data.
|
||||
** own private copy of the data before the sqlite3_bind_* routine returns.
|
||||
**
|
||||
** The sqlite3_bind_* routine must be called before sqlite3_step() after
|
||||
** an sqlite3_prepare() or sqlite3_reset(). Unbound parameterss are
|
||||
** interpreted as NULL.
|
||||
** The sqlite3_bind_* routine must be called before sqlite3_step() and after
|
||||
** an sqlite3_prepare() or sqlite3_reset(). Bindings persist across
|
||||
** multiple calls to sqlite3_reset() and sqlite3_step(). Unbound parameters
|
||||
** are interpreted as NULL.
|
||||
*/
|
||||
int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*));
|
||||
int sqlite3_bind_double(sqlite3_stmt*, int, double);
|
||||
|
@ -687,13 +792,13 @@ int sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*)(void*));
|
|||
int sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*);
|
||||
|
||||
/*
|
||||
** Return the number of parameters in a compiled SQL statement. This
|
||||
** Return the number of host parameters in a compiled SQL statement. This
|
||||
** routine was added to support DBD::SQLite.
|
||||
*/
|
||||
int sqlite3_bind_parameter_count(sqlite3_stmt*);
|
||||
|
||||
/*
|
||||
** Return the name of the i-th parameter. Ordinary parameters "?" are
|
||||
** Return the name of the i-th name parameter. Ordinary parameters "?" are
|
||||
** nameless and a NULL is returned. For parameters of the form :AAA or
|
||||
** $VVV the complete text of the parameter name is returned, including
|
||||
** the initial ":" or "$". NULL is returned if the index is out of range.
|
||||
|
@ -729,7 +834,7 @@ const char *sqlite3_column_name(sqlite3_stmt*,int);
|
|||
const void *sqlite3_column_name16(sqlite3_stmt*,int);
|
||||
|
||||
/*
|
||||
** The first parameter to the following calls is a compiled SQL statement.
|
||||
** The first argument to the following calls is a compiled SQL statement.
|
||||
** These functions return information about the Nth column returned by
|
||||
** the statement, where N is the second function argument.
|
||||
**
|
||||
|
@ -926,6 +1031,7 @@ const unsigned char *sqlite3_column_text(sqlite3_stmt*, int iCol);
|
|||
const void *sqlite3_column_text16(sqlite3_stmt*, int iCol);
|
||||
int sqlite3_column_type(sqlite3_stmt*, int iCol);
|
||||
int sqlite3_column_numeric_type(sqlite3_stmt*, int iCol);
|
||||
sqlite3_value *sqlite3_column_value(sqlite3_stmt*, int iCol);
|
||||
|
||||
/*
|
||||
** The sqlite3_finalize() function is called to delete a compiled
|
||||
|
@ -1092,9 +1198,13 @@ void sqlite3_set_auxdata(sqlite3_context*, int, void*, void (*)(void*));
|
|||
** SQLITE_TRANSIENT value means that the content will likely change in
|
||||
** the near future and that SQLite should make its own private copy of
|
||||
** the content before returning.
|
||||
**
|
||||
** The typedef is necessary to work around problems in certain
|
||||
** C++ compilers. See ticket #2191.
|
||||
*/
|
||||
#define SQLITE_STATIC ((void(*)(void *))0)
|
||||
#define SQLITE_TRANSIENT ((void(*)(void *))-1)
|
||||
typedef void (*sqlite3_destructor_type)(void*);
|
||||
#define SQLITE_STATIC ((sqlite3_destructor_type)0)
|
||||
#define SQLITE_TRANSIENT ((sqlite3_destructor_type)-1)
|
||||
|
||||
/*
|
||||
** User-defined functions invoke the following routines in order to
|
||||
|
@ -1468,6 +1578,299 @@ int sqlite3_table_column_metadata(
|
|||
int *pAutoinc /* OUTPUT: True if colums is auto-increment */
|
||||
);
|
||||
|
||||
/*
|
||||
****** EXPERIMENTAL - subject to change without notice **************
|
||||
**
|
||||
** Attempt to load an SQLite extension library contained in the file
|
||||
** zFile. The entry point is zProc. zProc may be 0 in which case the
|
||||
** name of the entry point defaults to "sqlite3_extension_init".
|
||||
**
|
||||
** Return SQLITE_OK on success and SQLITE_ERROR if something goes wrong.
|
||||
**
|
||||
** If an error occurs and pzErrMsg is not 0, then fill *pzErrMsg with
|
||||
** error message text. The calling function should free this memory
|
||||
** by calling sqlite3_free().
|
||||
**
|
||||
** Extension loading must be enabled using sqlite3_enable_load_extension()
|
||||
** prior to calling this API or an error will be returned.
|
||||
**
|
||||
****** EXPERIMENTAL - subject to change without notice **************
|
||||
*/
|
||||
int sqlite3_load_extension(
|
||||
sqlite3 *db, /* Load the extension into this database connection */
|
||||
const char *zFile, /* Name of the shared library containing extension */
|
||||
const char *zProc, /* Entry point. Derived from zFile if 0 */
|
||||
char **pzErrMsg /* Put error message here if not 0 */
|
||||
);
|
||||
|
||||
/*
|
||||
** So as not to open security holes in older applications that are
|
||||
** unprepared to deal with extension load, and as a means of disabling
|
||||
** extension loading while executing user-entered SQL, the following
|
||||
** API is provided to turn the extension loading mechanism on and
|
||||
** off. It is off by default. See ticket #1863.
|
||||
**
|
||||
** Call this routine with onoff==1 to turn extension loading on
|
||||
** and call it with onoff==0 to turn it back off again.
|
||||
*/
|
||||
int sqlite3_enable_load_extension(sqlite3 *db, int onoff);
|
||||
|
||||
/*
|
||||
****** EXPERIMENTAL - subject to change without notice **************
|
||||
**
|
||||
** Register an extension entry point that is automatically invoked
|
||||
** whenever a new database connection is opened.
|
||||
**
|
||||
** This API can be invoked at program startup in order to register
|
||||
** one or more statically linked extensions that will be available
|
||||
** to all new database connections.
|
||||
**
|
||||
** Duplicate extensions are detected so calling this routine multiple
|
||||
** times with the same extension is harmless.
|
||||
**
|
||||
** This routine stores a pointer to the extension in an array
|
||||
** that is obtained from malloc(). If you run a memory leak
|
||||
** checker on your program and it reports a leak because of this
|
||||
** array, then invoke sqlite3_automatic_extension_reset() prior
|
||||
** to shutdown to free the memory.
|
||||
**
|
||||
** Automatic extensions apply across all threads.
|
||||
*/
|
||||
int sqlite3_auto_extension(void *xEntryPoint);
|
||||
|
||||
|
||||
/*
|
||||
****** EXPERIMENTAL - subject to change without notice **************
|
||||
**
|
||||
** Disable all previously registered automatic extensions. This
|
||||
** routine undoes the effect of all prior sqlite3_automatic_extension()
|
||||
** calls.
|
||||
**
|
||||
** This call disabled automatic extensions in all threads.
|
||||
*/
|
||||
void sqlite3_reset_auto_extension(void);
|
||||
|
||||
|
||||
/*
|
||||
****** EXPERIMENTAL - subject to change without notice **************
|
||||
**
|
||||
** The interface to the virtual-table mechanism is currently considered
|
||||
** to be experimental. The interface might change in incompatible ways.
|
||||
** If this is a problem for you, do not use the interface at this time.
|
||||
**
|
||||
** When the virtual-table mechanism stablizes, we will declare the
|
||||
** interface fixed, support it indefinitely, and remove this comment.
|
||||
*/
|
||||
|
||||
/*
|
||||
** Structures used by the virtual table interface
|
||||
*/
|
||||
typedef struct sqlite3_vtab sqlite3_vtab;
|
||||
typedef struct sqlite3_index_info sqlite3_index_info;
|
||||
typedef struct sqlite3_vtab_cursor sqlite3_vtab_cursor;
|
||||
typedef struct sqlite3_module sqlite3_module;
|
||||
|
||||
/*
|
||||
** A module is a class of virtual tables. Each module is defined
|
||||
** by an instance of the following structure. This structure consists
|
||||
** mostly of methods for the module.
|
||||
*/
|
||||
struct sqlite3_module {
|
||||
int iVersion;
|
||||
int (*xCreate)(sqlite3*, void *pAux,
|
||||
int argc, const char *const*argv,
|
||||
sqlite3_vtab **ppVTab, char**);
|
||||
int (*xConnect)(sqlite3*, void *pAux,
|
||||
int argc, const char *const*argv,
|
||||
sqlite3_vtab **ppVTab, char**);
|
||||
int (*xBestIndex)(sqlite3_vtab *pVTab, sqlite3_index_info*);
|
||||
int (*xDisconnect)(sqlite3_vtab *pVTab);
|
||||
int (*xDestroy)(sqlite3_vtab *pVTab);
|
||||
int (*xOpen)(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor);
|
||||
int (*xClose)(sqlite3_vtab_cursor*);
|
||||
int (*xFilter)(sqlite3_vtab_cursor*, int idxNum, const char *idxStr,
|
||||
int argc, sqlite3_value **argv);
|
||||
int (*xNext)(sqlite3_vtab_cursor*);
|
||||
int (*xEof)(sqlite3_vtab_cursor*);
|
||||
int (*xColumn)(sqlite3_vtab_cursor*, sqlite3_context*, int);
|
||||
int (*xRowid)(sqlite3_vtab_cursor*, sqlite_int64 *pRowid);
|
||||
int (*xUpdate)(sqlite3_vtab *, int, sqlite3_value **, sqlite_int64 *);
|
||||
int (*xBegin)(sqlite3_vtab *pVTab);
|
||||
int (*xSync)(sqlite3_vtab *pVTab);
|
||||
int (*xCommit)(sqlite3_vtab *pVTab);
|
||||
int (*xRollback)(sqlite3_vtab *pVTab);
|
||||
int (*xFindFunction)(sqlite3_vtab *pVtab, int nArg, const char *zName,
|
||||
void (**pxFunc)(sqlite3_context*,int,sqlite3_value**),
|
||||
void **ppArg);
|
||||
};
|
||||
|
||||
/*
|
||||
** The sqlite3_index_info structure and its substructures is used to
|
||||
** pass information into and receive the reply from the xBestIndex
|
||||
** method of an sqlite3_module. The fields under **Inputs** are the
|
||||
** inputs to xBestIndex and are read-only. xBestIndex inserts its
|
||||
** results into the **Outputs** fields.
|
||||
**
|
||||
** The aConstraint[] array records WHERE clause constraints of the
|
||||
** form:
|
||||
**
|
||||
** column OP expr
|
||||
**
|
||||
** Where OP is =, <, <=, >, or >=. The particular operator is stored
|
||||
** in aConstraint[].op. The index of the column is stored in
|
||||
** aConstraint[].iColumn. aConstraint[].usable is TRUE if the
|
||||
** expr on the right-hand side can be evaluated (and thus the constraint
|
||||
** is usable) and false if it cannot.
|
||||
**
|
||||
** The optimizer automatically inverts terms of the form "expr OP column"
|
||||
** and makes other simplificatinos to the WHERE clause in an attempt to
|
||||
** get as many WHERE clause terms into the form shown above as possible.
|
||||
** The aConstraint[] array only reports WHERE clause terms in the correct
|
||||
** form that refer to the particular virtual table being queried.
|
||||
**
|
||||
** Information about the ORDER BY clause is stored in aOrderBy[].
|
||||
** Each term of aOrderBy records a column of the ORDER BY clause.
|
||||
**
|
||||
** The xBestIndex method must fill aConstraintUsage[] with information
|
||||
** about what parameters to pass to xFilter. If argvIndex>0 then
|
||||
** the right-hand side of the corresponding aConstraint[] is evaluated
|
||||
** and becomes the argvIndex-th entry in argv. If aConstraintUsage[].omit
|
||||
** is true, then the constraint is assumed to be fully handled by the
|
||||
** virtual table and is not checked again by SQLite.
|
||||
**
|
||||
** The idxNum and idxPtr values are recorded and passed into xFilter.
|
||||
** sqlite3_free() is used to free idxPtr if needToFreeIdxPtr is true.
|
||||
**
|
||||
** The orderByConsumed means that output from xFilter will occur in
|
||||
** the correct order to satisfy the ORDER BY clause so that no separate
|
||||
** sorting step is required.
|
||||
**
|
||||
** The estimatedCost value is an estimate of the cost of doing the
|
||||
** particular lookup. A full scan of a table with N entries should have
|
||||
** a cost of N. A binary search of a table of N entries should have a
|
||||
** cost of approximately log(N).
|
||||
*/
|
||||
struct sqlite3_index_info {
|
||||
/* Inputs */
|
||||
const int nConstraint; /* Number of entries in aConstraint */
|
||||
const struct sqlite3_index_constraint {
|
||||
int iColumn; /* Column on left-hand side of constraint */
|
||||
unsigned char op; /* Constraint operator */
|
||||
unsigned char usable; /* True if this constraint is usable */
|
||||
int iTermOffset; /* Used internally - xBestIndex should ignore */
|
||||
} *const aConstraint; /* Table of WHERE clause constraints */
|
||||
const int nOrderBy; /* Number of terms in the ORDER BY clause */
|
||||
const struct sqlite3_index_orderby {
|
||||
int iColumn; /* Column number */
|
||||
unsigned char desc; /* True for DESC. False for ASC. */
|
||||
} *const aOrderBy; /* The ORDER BY clause */
|
||||
|
||||
/* Outputs */
|
||||
struct sqlite3_index_constraint_usage {
|
||||
int argvIndex; /* if >0, constraint is part of argv to xFilter */
|
||||
unsigned char omit; /* Do not code a test for this constraint */
|
||||
} *const aConstraintUsage;
|
||||
int idxNum; /* Number used to identify the index */
|
||||
char *idxStr; /* String, possibly obtained from sqlite3_malloc */
|
||||
int needToFreeIdxStr; /* Free idxStr using sqlite3_free() if true */
|
||||
int orderByConsumed; /* True if output is already ordered */
|
||||
double estimatedCost; /* Estimated cost of using this index */
|
||||
};
|
||||
#define SQLITE_INDEX_CONSTRAINT_EQ 2
|
||||
#define SQLITE_INDEX_CONSTRAINT_GT 4
|
||||
#define SQLITE_INDEX_CONSTRAINT_LE 8
|
||||
#define SQLITE_INDEX_CONSTRAINT_LT 16
|
||||
#define SQLITE_INDEX_CONSTRAINT_GE 32
|
||||
#define SQLITE_INDEX_CONSTRAINT_MATCH 64
|
||||
|
||||
/*
|
||||
** This routine is used to register a new module name with an SQLite
|
||||
** connection. Module names must be registered before creating new
|
||||
** virtual tables on the module, or before using preexisting virtual
|
||||
** tables of the module.
|
||||
*/
|
||||
int sqlite3_create_module(
|
||||
sqlite3 *db, /* SQLite connection to register module with */
|
||||
const char *zName, /* Name of the module */
|
||||
const sqlite3_module *, /* Methods for the module */
|
||||
void * /* Client data for xCreate/xConnect */
|
||||
);
|
||||
|
||||
/*
|
||||
** Every module implementation uses a subclass of the following structure
|
||||
** to describe a particular instance of the module. Each subclass will
|
||||
** be taylored to the specific needs of the module implementation. The
|
||||
** purpose of this superclass is to define certain fields that are common
|
||||
** to all module implementations.
|
||||
**
|
||||
** Virtual tables methods can set an error message by assigning a
|
||||
** string obtained from sqlite3_mprintf() to zErrMsg. The method should
|
||||
** take care that any prior string is freed by a call to sqlite3_free()
|
||||
** prior to assigning a new string to zErrMsg. After the error message
|
||||
** is delivered up to the client application, the string will be automatically
|
||||
** freed by sqlite3_free() and the zErrMsg field will be zeroed. Note
|
||||
** that sqlite3_mprintf() and sqlite3_free() are used on the zErrMsg field
|
||||
** since virtual tables are commonly implemented in loadable extensions which
|
||||
** do not have access to sqlite3MPrintf() or sqlite3Free().
|
||||
*/
|
||||
struct sqlite3_vtab {
|
||||
const sqlite3_module *pModule; /* The module for this virtual table */
|
||||
int nRef; /* Used internally */
|
||||
char *zErrMsg; /* Error message from sqlite3_mprintf() */
|
||||
/* Virtual table implementations will typically add additional fields */
|
||||
};
|
||||
|
||||
/* Every module implementation uses a subclass of the following structure
|
||||
** to describe cursors that point into the virtual table and are used
|
||||
** to loop through the virtual table. Cursors are created using the
|
||||
** xOpen method of the module. Each module implementation will define
|
||||
** the content of a cursor structure to suit its own needs.
|
||||
**
|
||||
** This superclass exists in order to define fields of the cursor that
|
||||
** are common to all implementations.
|
||||
*/
|
||||
struct sqlite3_vtab_cursor {
|
||||
sqlite3_vtab *pVtab; /* Virtual table of this cursor */
|
||||
/* Virtual table implementations will typically add additional fields */
|
||||
};
|
||||
|
||||
/*
|
||||
** The xCreate and xConnect methods of a module use the following API
|
||||
** to declare the format (the names and datatypes of the columns) of
|
||||
** the virtual tables they implement.
|
||||
*/
|
||||
int sqlite3_declare_vtab(sqlite3*, const char *zCreateTable);
|
||||
|
||||
/*
|
||||
** Virtual tables can provide alternative implementations of functions
|
||||
** using the xFindFunction method. But global versions of those functions
|
||||
** must exist in order to be overloaded.
|
||||
**
|
||||
** This API makes sure a global version of a function with a particular
|
||||
** name and number of parameters exists. If no such function exists
|
||||
** before this API is called, a new function is created. The implementation
|
||||
** of the new function always causes an exception to be thrown. So
|
||||
** the new function is not good for anything by itself. Its only
|
||||
** purpose is to be a place-holder function that can be overloaded
|
||||
** by virtual tables.
|
||||
**
|
||||
** This API should be considered part of the virtual table interface,
|
||||
** which is experimental and subject to change.
|
||||
*/
|
||||
int sqlite3_overload_function(sqlite3*, const char *zFuncName, int nArg);
|
||||
|
||||
/*
|
||||
** The interface to the virtual-table mechanism defined above (back up
|
||||
** to a comment remarkably similar to this one) is currently considered
|
||||
** to be experimental. The interface might change in incompatible ways.
|
||||
** If this is a problem for you, do not use the interface at this time.
|
||||
**
|
||||
** When the virtual-table mechanism stablizes, we will declare the
|
||||
** interface fixed, support it indefinitely, and remove this comment.
|
||||
**
|
||||
****** EXPERIMENTAL - subject to change without notice **************
|
||||
*/
|
||||
|
||||
/*
|
||||
** Undo the hack that converts floating point types to integer for
|
||||
** builds on processors without floating point support.
|
||||
|
@ -1476,19 +1879,6 @@ int sqlite3_table_column_metadata(
|
|||
# undef double
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Preload the databases into the pager cache, up to the maximum size of the
|
||||
** pager cache.
|
||||
**
|
||||
** For a database to be loaded successfully, the pager must be active. That is,
|
||||
** there must be an open statement on that database. See sqlite3pager_loadall
|
||||
**
|
||||
** There might be many databases attached to the given connection. We iterate
|
||||
** them all and try to load them. If none are loadable successfully, we return
|
||||
** an error. Otherwise, we return OK.
|
||||
*/
|
||||
int sqlite3Preload(sqlite3* db);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* End of the 'extern "C"' block */
|
||||
#endif
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
*
|
||||
* Contributor(s):
|
||||
* Brett Wilson <brettw@gmail.com> (original author)
|
||||
* Shawn Wilsher <me@shawnwilsher.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
|
@ -100,6 +101,7 @@ struct IoMethod {
|
|||
int (*xUnlock)(OsFile*, int);
|
||||
int (*xLockState)(OsFile *id);
|
||||
int (*xCheckReservedLock)(OsFile *id);
|
||||
int (*xSectorSize)(OsFile *id);
|
||||
};
|
||||
|
||||
/* FROM os.h
|
||||
|
@ -148,6 +150,10 @@ struct sqlite3OsVtbl {
|
|||
void *(*xRealloc)(void *, int);
|
||||
void (*xFree)(void *);
|
||||
int (*xAllocationSize)(void *);
|
||||
|
||||
void *(*xDlopen)(const char*);
|
||||
void *(*xDlsym)(void*, const char*);
|
||||
int (*xDlclose)(void*);
|
||||
};
|
||||
|
||||
/* FROM os.h
|
||||
|
@ -185,7 +191,10 @@ struct sqlite3OsVtbl {
|
|||
sqlite3OsMalloc,
|
||||
sqlite3OsRealloc,
|
||||
sqlite3OsFree,
|
||||
sqlite3OsAllocationSize
|
||||
sqlite3OsAllocationSize,
|
||||
IF_DLOPEN( sqlite3OsDlopen ),
|
||||
IF_DLOPEN( sqlite3OsDlsym ),
|
||||
IF_DLOPEN( sqlite3OsDlclose ),
|
||||
};
|
||||
#else
|
||||
/*
|
||||
|
|
|
@ -475,8 +475,11 @@ mozStorageConnection::CreateFunction(const char *aFunctionName,
|
|||
nsresult
|
||||
mozStorageConnection::Preload()
|
||||
{
|
||||
/*
|
||||
int srv = sqlite3Preload(mDBConn);
|
||||
return ConvertResultCode(srv);
|
||||
*/
|
||||
return NS_OK; // XXX restore after sqlite upgrade
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Загрузка…
Ссылка в новой задаче