Sqlite: Update library to 3.8.7.

Sqlite: Update project files.
This commit is contained in:
Arkshine 2014-10-24 11:33:23 +02:00
parent dd38ee103b
commit 162171618c
62 changed files with 158727 additions and 65660 deletions

View File

@ -29,57 +29,16 @@ binary.sources += [
'sqlitepp/SqliteResultSet.cpp', 'sqlitepp/SqliteResultSet.cpp',
'sqlitepp/SqliteDatabase.cpp', 'sqlitepp/SqliteDatabase.cpp',
'sqlitepp/SqliteDriver.cpp', 'sqlitepp/SqliteDriver.cpp',
'sqlite-source/alter.c', 'sqlite-source/sqlite3.c',
'sqlite-source/analyze.c',
'sqlite-source/attach.c',
'sqlite-source/auth.c',
'sqlite-source/btree.c',
'sqlite-source/build.c',
'sqlite-source/callback.c',
'sqlite-source/complete.c',
'sqlite-source/date.c',
'sqlite-source/delete.c',
'sqlite-source/expr.c',
'sqlite-source/func.c',
'sqlite-source/hash.c',
'sqlite-source/insert.c',
'sqlite-source/legacy.c',
'sqlite-source/loadext.c',
'sqlite-source/main.c',
'sqlite-source/opcodes.c',
'sqlite-source/os.c',
'sqlite-source/pager.c',
'sqlite-source/parse.c',
'sqlite-source/pragma.c',
'sqlite-source/prepare.c',
'sqlite-source/printf.c',
'sqlite-source/random.c',
'sqlite-source/select.c',
'sqlite-source/table.c',
'sqlite-source/tokenize.c',
'sqlite-source/trigger.c',
'sqlite-source/update.c',
'sqlite-source/utf.c',
'sqlite-source/util.c',
'sqlite-source/vacuum.c',
'sqlite-source/vdbe.c',
'sqlite-source/vdbeapi.c',
'sqlite-source/vdbeaux.c',
'sqlite-source/vdbefifo.c',
'sqlite-source/vdbemem.c',
'sqlite-source/vtab.c',
'sqlite-source/where.c',
] ]
if builder.target_platform == 'windows': if builder.target_platform == 'windows':
binary.sources += [ binary.sources += [
'thread/WinThreads.cpp', 'thread/WinThreads.cpp',
'sqlite-source/os_win.c',
] ]
else: else:
binary.sources += [ binary.sources += [
'thread/PosixThreads.cpp', 'thread/PosixThreads.cpp',
'sqlite-source/os_unix.c',
] ]
if builder.target_platform == 'windows': if builder.target_platform == 'windows':

View File

@ -20,14 +20,7 @@ OBJECTS = basic_sql.cpp handles.cpp module.cpp threading.cpp amxxmodule.cpp oldc
thread/BaseWorker.cpp thread/ThreadWorker.cpp thread/PosixThreads.cpp \ thread/BaseWorker.cpp thread/ThreadWorker.cpp thread/PosixThreads.cpp \
sqlitepp/SqliteQuery.cpp sqlitepp/SqliteResultSet.cpp sqlitepp/SqliteDatabase.cpp \ sqlitepp/SqliteQuery.cpp sqlitepp/SqliteResultSet.cpp sqlitepp/SqliteDatabase.cpp \
sqlitepp/SqliteDriver.cpp sqlitepp/SqliteDriver.cpp
OBJECTS += $(SQL)/alter.c $(SQL)/analyze.c $(SQL)/attach.c $(SQL)/auth.c $(SQL)/btree.c \ OBJECTS += $(SQL)/sqlite3.c
$(SQL)/build.c $(SQL)/callback.c $(SQL)/complete.c $(SQL)/date.c $(SQL)/delete.c \
$(SQL)/expr.c $(SQL)/func.c $(SQL)/hash.c $(SQL)/insert.c $(SQL)/legacy.c \
$(SQL)/loadext.c $(SQL)/main.c $(SQL)/opcodes.c $(SQL)/os.c $(SQL)/os_unix.c \
$(SQL)/pager.c $(SQL)/parse.c $(SQL)/pragma.c $(SQL)/prepare.c $(SQL)/printf.c \
$(SQL)/random.c $(SQL)/select.c $(SQL)/table.c $(SQL)/tokenize.c $(SQL)/trigger.c \
$(SQL)/update.c $(SQL)/utf.c $(SQL)/util.c $(SQL)/vacuum.c $(SQL)/vdbe.c $(SQL)/vdbeapi.c \
$(SQL)/vdbeaux.c $(SQL)/vdbefifo.c $(SQL)/vdbemem.c $(SQL)/vtab.c $(SQL)/where.c
############################################## ##############################################
### CONFIGURE ANY OTHER FLAGS/OPTIONS HERE ### ### CONFIGURE ANY OTHER FLAGS/OPTIONS HERE ###

View File

@ -200,4 +200,152 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets"> <ImportGroup Label="ExtensionTargets">
</ImportGroup> </ImportGroup>
=======
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{4FDFD106-7163-44F0-85C4-9FAFECD14973}</ProjectGuid>
<RootNamespace>sqlite</RootNamespace>
<Keyword>Win32Proj</Keyword>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<_ProjectFileVersion>10.0.40219.1</_ProjectFileVersion>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
<TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(ProjectName)_amxx</TargetName>
<TargetName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(ProjectName)_amxx</TargetName>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<AdditionalOptions>/D "NO_TCL" %(AdditionalOptions)</AdditionalOptions>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\;..\..\..\public;..\..\..\public\sdk; ..\..\..\public\amtl;..\sqlite-source;..\sqlitepp;..\thread;$(METAMOD)\metamod;$(HLSDK)\common;$(HLSDK)\engine;$(HLSDK)\dlls;$(HLSDK)\public;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;sqlite_EXPORTS;SM_DEFAULT_THREADER;HAVE_STDINT_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<StructMemberAlignment>4Bytes</StructMemberAlignment>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
</ClCompile>
<Link>
<IgnoreSpecificDefaultLibraries>%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
<ModuleDefinitionFile>
</ModuleDefinitionFile>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ProgramDatabaseFile>$(OutDir)sqlite.pdb</ProgramDatabaseFile>
<SubSystem>Windows</SubSystem>
<ImportLibrary>$(OutDir)sqlite.lib</ImportLibrary>
<TargetMachine>MachineX86</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<AdditionalOptions>/D "NO_TCL" %(AdditionalOptions)</AdditionalOptions>
<Optimization>MaxSpeed</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<OmitFramePointers>true</OmitFramePointers>
<AdditionalIncludeDirectories>..\;..\..\..\public;..\..\..\public\sdk; ..\..\..\public\amtl;..\sqlite-source;..\sqlitepp;..\thread;$(METAMOD)\metamod;$(HLSDK)\common;$(HLSDK)\engine;$(HLSDK)\dlls;$(HLSDK)\public;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;sqlite_EXPORTS;SM_DEFAULT_THREADER;HAVE_STDINT_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<StructMemberAlignment>4Bytes</StructMemberAlignment>
<FunctionLevelLinking>true</FunctionLevelLinking>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<ImportLibrary>$(OutDir)sqlite.lib</ImportLibrary>
<TargetMachine>MachineX86</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\basic_sql.cpp" />
<ClCompile Include="..\handles.cpp" />
<ClCompile Include="..\module.cpp" />
<ClCompile Include="..\oldcompat_sql.cpp" />
<ClCompile Include="..\threading.cpp" />
<ClCompile Include="..\sqlitepp\SqliteDatabase.cpp" />
<ClCompile Include="..\sqlitepp\SqliteDriver.cpp" />
<ClCompile Include="..\sqlitepp\SqliteQuery.cpp" />
<ClCompile Include="..\sqlitepp\SqliteResultSet.cpp" />
<ClCompile Include="..\thread\BaseWorker.cpp" />
<ClCompile Include="..\thread\ThreadWorker.cpp" />
<ClCompile Include="..\thread\WinThreads.cpp" />
<ClCompile Include="..\..\..\public\sdk\amxxmodule.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\sqlheaders.h" />
<ClInclude Include="..\sqlite_header.h" />
<ClInclude Include="..\threading.h" />
<ClInclude Include="..\sqlitepp\ISQLDriver.h" />
<ClInclude Include="..\sqlitepp\SqliteDatabase.h" />
<ClInclude Include="..\sqlitepp\SqliteDriver.h" />
<ClInclude Include="..\sqlitepp\SqliteHeaders.h" />
<ClInclude Include="..\sqlitepp\SqliteQuery.h" />
<ClInclude Include="..\sqlitepp\SqliteResultSet.h" />
<ClInclude Include="..\thread\BaseWorker.h" />
<ClInclude Include="..\thread\IThreader.h" />
<ClInclude Include="..\thread\PosixThreads.h" />
<ClInclude Include="..\thread\ThreadSupport.h" />
<ClInclude Include="..\thread\ThreadWorker.h" />
<ClInclude Include="..\thread\WinThreads.h" />
<ClInclude Include="..\moduleconfig.h" />
<ClInclude Include="..\..\..\public\sdk\amxxmodule.h" />
</ItemGroup>
<ItemGroup>
<None Include="..\..\..\plugins\include\sqlx.inc" />
<None Include="..\sqlite-source\sqlite3.c" />
<None Include="..\sqlite-source\sqlite3.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project> </Project>

View File

@ -301,4 +301,152 @@
<Filter>Pawn Includes</Filter> <Filter>Pawn Includes</Filter>
</None> </None>
</ItemGroup> </ItemGroup>
=======
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{fee21ba3-ba57-4165-a636-f131192c35ed}</UniqueIdentifier>
<Extensions>cpp;c;cxx;def;odl;idl;hpj;bat;asm</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{75726cf9-410b-4bb0-8258-e54d8a778fea}</UniqueIdentifier>
<Extensions>h;hpp;hxx;hm;inl;inc</Extensions>
</Filter>
<Filter Include="Database">
<UniqueIdentifier>{170198cf-e562-4903-bc68-4c3528e58f5f}</UniqueIdentifier>
</Filter>
<Filter Include="Database\Header Files">
<UniqueIdentifier>{d27ed8de-c2a0-460f-a0f4-a9adcf9e549f}</UniqueIdentifier>
</Filter>
<Filter Include="Database\Source Files">
<UniqueIdentifier>{55a33451-3931-4fac-ba8a-3be3b07d6a34}</UniqueIdentifier>
</Filter>
<Filter Include="Threader">
<UniqueIdentifier>{cf870f84-b709-46d7-a30c-ae8f4c45de23}</UniqueIdentifier>
</Filter>
<Filter Include="Threader\Header Files">
<UniqueIdentifier>{45cbffb2-fb23-4821-b89c-842ec027be01}</UniqueIdentifier>
</Filter>
<Filter Include="Threader\Source Files">
<UniqueIdentifier>{5ef60ee3-dc5b-420f-a8b8-1ef24213fcf7}</UniqueIdentifier>
</Filter>
<Filter Include="SQLite Source">
<UniqueIdentifier>{03fa14bf-6409-4ed7-bb07-da1b356b5076}</UniqueIdentifier>
</Filter>
<Filter Include="Module SDK">
<UniqueIdentifier>{b24e595e-f6a9-4358-bbe3-094ef6383e53}</UniqueIdentifier>
</Filter>
<Filter Include="Module SDK\SDK Base">
<UniqueIdentifier>{c60d3c45-e23b-4c5a-aae2-2c3c5441bac6}</UniqueIdentifier>
</Filter>
<Filter Include="Pawn Includes">
<UniqueIdentifier>{e0a36119-bb5b-4f07-9e0e-80f9aa7a7d21}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\basic_sql.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\handles.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\module.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\oldcompat_sql.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\threading.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\sqlitepp\SqliteDatabase.cpp">
<Filter>Database\Source Files</Filter>
</ClCompile>
<ClCompile Include="..\sqlitepp\SqliteDriver.cpp">
<Filter>Database\Source Files</Filter>
</ClCompile>
<ClCompile Include="..\sqlitepp\SqliteQuery.cpp">
<Filter>Database\Source Files</Filter>
</ClCompile>
<ClCompile Include="..\sqlitepp\SqliteResultSet.cpp">
<Filter>Database\Source Files</Filter>
</ClCompile>
<ClCompile Include="..\thread\BaseWorker.cpp">
<Filter>Threader\Source Files</Filter>
</ClCompile>
<ClCompile Include="..\thread\ThreadWorker.cpp">
<Filter>Threader\Source Files</Filter>
</ClCompile>
<ClCompile Include="..\thread\WinThreads.cpp">
<Filter>Threader\Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\..\public\sdk\amxxmodule.cpp">
<Filter>Module SDK\SDK Base</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\sqlheaders.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\sqlite_header.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\threading.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\sqlitepp\ISQLDriver.h">
<Filter>Database</Filter>
</ClInclude>
<ClInclude Include="..\sqlitepp\SqliteDatabase.h">
<Filter>Database\Header Files</Filter>
</ClInclude>
<ClInclude Include="..\sqlitepp\SqliteDriver.h">
<Filter>Database\Header Files</Filter>
</ClInclude>
<ClInclude Include="..\sqlitepp\SqliteHeaders.h">
<Filter>Database\Header Files</Filter>
</ClInclude>
<ClInclude Include="..\sqlitepp\SqliteQuery.h">
<Filter>Database\Header Files</Filter>
</ClInclude>
<ClInclude Include="..\sqlitepp\SqliteResultSet.h">
<Filter>Database\Header Files</Filter>
</ClInclude>
<ClInclude Include="..\thread\BaseWorker.h">
<Filter>Threader\Header Files</Filter>
</ClInclude>
<ClInclude Include="..\thread\IThreader.h">
<Filter>Threader\Header Files</Filter>
</ClInclude>
<ClInclude Include="..\thread\PosixThreads.h">
<Filter>Threader\Header Files</Filter>
</ClInclude>
<ClInclude Include="..\thread\ThreadSupport.h">
<Filter>Threader\Header Files</Filter>
</ClInclude>
<ClInclude Include="..\thread\ThreadWorker.h">
<Filter>Threader\Header Files</Filter>
</ClInclude>
<ClInclude Include="..\thread\WinThreads.h">
<Filter>Threader\Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\..\public\sdk\amxxmodule.h">
<Filter>Module SDK\SDK Base</Filter>
</ClInclude>
<ClInclude Include="..\moduleconfig.h">
<Filter>Module SDK</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="..\..\..\plugins\include\sqlx.inc">
<Filter>Pawn Includes</Filter>
</None>
<None Include="..\sqlite-source\sqlite3.c">
<Filter>SQLite Source</Filter>
</None>
<None Include="..\sqlite-source\sqlite3.h">
<Filter>SQLite Source</Filter>
</None>
</ItemGroup>
</Project> </Project>

View File

@ -1,575 +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 3426 2007-03-21 20:19:37Z damagedsoul $
*/
#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 third
** 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 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 third 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;
#ifndef SQLITE_OMIT_VIRTUALTABLE
if( IsVirtual(pTab) ){
sqlite3ErrorMsg(pParse, "virtual tables may not be altered");
goto exit_rename_table;
}
#endif
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;
#ifndef SQLITE_OMIT_VIRTUALTABLE
if( IsVirtual(pTab) ){
sqlite3ErrorMsg(pParse, "virtual tables may not be altered");
goto exit_begin_add_column;
}
#endif
/* 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 */

View File

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

View File

@ -1,504 +0,0 @@
/*
** 2003 April 6
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains code used to implement the ATTACH and DETACH commands.
**
** $Id: attach.c 3426 2007-03-21 20:19:37Z damagedsoul $
*/
#include "sqliteInt.h"
/*
** Resolve an expression that was part of an ATTACH or DETACH statement. This
** is slightly different from resolving a normal SQL expression, because simple
** identifiers are treated as strings, not possible column names or aliases.
**
** i.e. if the parser sees:
**
** ATTACH DATABASE abc AS def
**
** it treats the two expressions as literal strings 'abc' and 'def' instead of
** looking for columns of the same name.
**
** This only applies to the root node of pExpr, so the statement:
**
** ATTACH DATABASE abc||def AS 'db2'
**
** will fail because neither abc or def can be resolved.
*/
static int resolveAttachExpr(NameContext *pName, Expr *pExpr)
{
int rc = SQLITE_OK;
if( pExpr ){
if( pExpr->op!=TK_ID ){
rc = sqlite3ExprResolveNames(pName, pExpr);
}else{
pExpr->op = TK_STRING;
}
}
return rc;
}
/*
** An SQL user-function registered to do the work of an ATTACH statement. The
** three arguments to the function come directly from an attach statement:
**
** ATTACH DATABASE x AS y KEY z
**
** SELECT sqlite_attach(x, y, z)
**
** If the optional "KEY z" syntax is omitted, an SQL NULL is passed as the
** third argument.
*/
static void attachFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
int i;
int rc = 0;
sqlite3 *db = sqlite3_user_data(context);
const char *zName;
const char *zFile;
Db *aNew;
char zErr[128];
char *zErrDyn = 0;
zFile = (const char *)sqlite3_value_text(argv[0]);
zName = (const char *)sqlite3_value_text(argv[1]);
if( zFile==0 ) zFile = "";
if( zName==0 ) zName = "";
/* Check for the following errors:
**
** * Too many attached databases,
** * Transaction currently open
** * Specified database name already being used.
*/
if( db->nDb>=MAX_ATTACHED+2 ){
sqlite3_snprintf(
sizeof(zErr), zErr, "too many attached databases - max %d", MAX_ATTACHED
);
goto attach_error;
}
if( !db->autoCommit ){
strcpy(zErr, "cannot ATTACH database within transaction");
goto attach_error;
}
for(i=0; i<db->nDb; i++){
char *z = db->aDb[i].zName;
if( z && zName && sqlite3StrICmp(z, zName)==0 ){
sqlite3_snprintf(sizeof(zErr), zErr, "database %s is already in use", zName);
goto attach_error;
}
}
/* Allocate the new entry in the db->aDb[] array and initialise the schema
** hash tables.
*/
if( db->aDb==db->aDbStatic ){
aNew = sqliteMalloc( sizeof(db->aDb[0])*3 );
if( aNew==0 ){
return;
}
memcpy(aNew, db->aDb, sizeof(db->aDb[0])*2);
}else{
aNew = sqliteRealloc(db->aDb, sizeof(db->aDb[0])*(db->nDb+1) );
if( aNew==0 ){
return;
}
}
db->aDb = aNew;
aNew = &db->aDb[db->nDb++];
memset(aNew, 0, sizeof(*aNew));
/* Open the database file. If the btree is successfully opened, use
** it to obtain the database schema. At this point the schema may
** or may not be initialised.
*/
rc = sqlite3BtreeFactory(db, zFile, 0, MAX_PAGES, &aNew->pBt);
if( rc==SQLITE_OK ){
aNew->pSchema = sqlite3SchemaGet(aNew->pBt);
if( !aNew->pSchema ){
rc = SQLITE_NOMEM;
}else if( aNew->pSchema->file_format && aNew->pSchema->enc!=ENC(db) ){
strcpy(zErr,
"attached databases must use the same text encoding as main database");
goto attach_error;
}
}
aNew->zName = sqliteStrDup(zName);
aNew->safety_level = 3;
#if SQLITE_HAS_CODEC
{
extern int sqlite3CodecAttach(sqlite3*, int, void*, int);
extern void sqlite3CodecGetKey(sqlite3*, int, void**, int*);
int nKey;
char *zKey;
int t = sqlite3_value_type(argv[2]);
switch( t ){
case SQLITE_INTEGER:
case SQLITE_FLOAT:
zErrDyn = sqliteStrDup("Invalid key value");
rc = SQLITE_ERROR;
break;
case SQLITE_TEXT:
case SQLITE_BLOB:
nKey = sqlite3_value_bytes(argv[2]);
zKey = (char *)sqlite3_value_blob(argv[2]);
sqlite3CodecAttach(db, db->nDb-1, zKey, nKey);
break;
case SQLITE_NULL:
/* No key specified. Use the key from the main database */
sqlite3CodecGetKey(db, 0, (void**)&zKey, &nKey);
sqlite3CodecAttach(db, db->nDb-1, zKey, nKey);
break;
}
}
#endif
/* If the file was opened successfully, read the schema for the new database.
** If this fails, or if opening the file failed, then close the file and
** remove the entry from the db->aDb[] array. i.e. put everything back the way
** we found it.
*/
if( rc==SQLITE_OK ){
sqlite3SafetyOn(db);
rc = sqlite3Init(db, &zErrDyn);
sqlite3SafetyOff(db);
}
if( rc ){
int iDb = db->nDb - 1;
assert( iDb>=2 );
if( db->aDb[iDb].pBt ){
sqlite3BtreeClose(db->aDb[iDb].pBt);
db->aDb[iDb].pBt = 0;
db->aDb[iDb].pSchema = 0;
}
sqlite3ResetInternalSchema(db, 0);
db->nDb = iDb;
if( rc==SQLITE_NOMEM ){
if( !sqlite3MallocFailed() ) sqlite3FailedMalloc();
sqlite3_snprintf(sizeof(zErr),zErr, "out of memory");
}else{
sqlite3_snprintf(sizeof(zErr),zErr, "unable to open database: %s", zFile);
}
goto attach_error;
}
return;
attach_error:
/* Return an error if we get here */
if( zErrDyn ){
sqlite3_result_error(context, zErrDyn, -1);
sqliteFree(zErrDyn);
}else{
zErr[sizeof(zErr)-1] = 0;
sqlite3_result_error(context, zErr, -1);
}
}
/*
** An SQL user-function registered to do the work of an DETACH statement. The
** three arguments to the function come directly from a detach statement:
**
** DETACH DATABASE x
**
** SELECT sqlite_detach(x)
*/
static void detachFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
const char *zName = (const char *)sqlite3_value_text(argv[0]);
sqlite3 *db = sqlite3_user_data(context);
int i;
Db *pDb = 0;
char zErr[128];
if( zName==0 ) zName = "";
for(i=0; i<db->nDb; i++){
pDb = &db->aDb[i];
if( pDb->pBt==0 ) continue;
if( sqlite3StrICmp(pDb->zName, zName)==0 ) break;
}
if( i>=db->nDb ){
sqlite3_snprintf(sizeof(zErr),zErr, "no such database: %s", zName);
goto detach_error;
}
if( i<2 ){
sqlite3_snprintf(sizeof(zErr),zErr, "cannot detach database %s", zName);
goto detach_error;
}
if( !db->autoCommit ){
strcpy(zErr, "cannot DETACH database within transaction");
goto detach_error;
}
if( sqlite3BtreeIsInReadTrans(pDb->pBt) ){
sqlite3_snprintf(sizeof(zErr),zErr, "database %s is locked", zName);
goto detach_error;
}
sqlite3BtreeClose(pDb->pBt);
pDb->pBt = 0;
pDb->pSchema = 0;
sqlite3ResetInternalSchema(db, 0);
return;
detach_error:
sqlite3_result_error(context, zErr, -1);
}
/*
** This procedure generates VDBE code for a single invocation of either the
** sqlite_detach() or sqlite_attach() SQL user functions.
*/
static void codeAttach(
Parse *pParse, /* The parser context */
int type, /* Either SQLITE_ATTACH or SQLITE_DETACH */
const char *zFunc, /* Either "sqlite_attach" or "sqlite_detach */
int nFunc, /* Number of args to pass to zFunc */
Expr *pAuthArg, /* Expression to pass to authorization callback */
Expr *pFilename, /* Name of database file */
Expr *pDbname, /* Name of the database to use internally */
Expr *pKey /* Database key for encryption extension */
){
int rc;
NameContext sName;
Vdbe *v;
FuncDef *pFunc;
sqlite3* db = pParse->db;
#ifndef SQLITE_OMIT_AUTHORIZATION
assert( sqlite3MallocFailed() || pAuthArg );
if( pAuthArg ){
char *zAuthArg = sqlite3NameFromToken(&pAuthArg->span);
if( !zAuthArg ){
goto attach_end;
}
rc = sqlite3AuthCheck(pParse, type, zAuthArg, 0, 0);
sqliteFree(zAuthArg);
if(rc!=SQLITE_OK ){
goto attach_end;
}
}
#endif /* SQLITE_OMIT_AUTHORIZATION */
memset(&sName, 0, sizeof(NameContext));
sName.pParse = pParse;
if(
SQLITE_OK!=(rc = resolveAttachExpr(&sName, pFilename)) ||
SQLITE_OK!=(rc = resolveAttachExpr(&sName, pDbname)) ||
SQLITE_OK!=(rc = resolveAttachExpr(&sName, pKey))
){
pParse->nErr++;
goto attach_end;
}
v = sqlite3GetVdbe(pParse);
sqlite3ExprCode(pParse, pFilename);
sqlite3ExprCode(pParse, pDbname);
sqlite3ExprCode(pParse, pKey);
assert( v || sqlite3MallocFailed() );
if( v ){
sqlite3VdbeAddOp(v, OP_Function, 0, nFunc);
pFunc = sqlite3FindFunction(db, zFunc, strlen(zFunc), nFunc, SQLITE_UTF8,0);
sqlite3VdbeChangeP3(v, -1, (char *)pFunc, P3_FUNCDEF);
/* Code an OP_Expire. For an ATTACH statement, set P1 to true (expire this
** statement only). For DETACH, set it to false (expire all existing
** statements).
*/
sqlite3VdbeAddOp(v, OP_Expire, (type==SQLITE_ATTACH), 0);
}
attach_end:
sqlite3ExprDelete(pFilename);
sqlite3ExprDelete(pDbname);
sqlite3ExprDelete(pKey);
}
/*
** Called by the parser to compile a DETACH statement.
**
** DETACH pDbname
*/
void sqlite3Detach(Parse *pParse, Expr *pDbname){
codeAttach(pParse, SQLITE_DETACH, "sqlite_detach", 1, pDbname, 0, 0, pDbname);
}
/*
** Called by the parser to compile an ATTACH statement.
**
** ATTACH p AS pDbname KEY pKey
*/
void sqlite3Attach(Parse *pParse, Expr *p, Expr *pDbname, Expr *pKey){
codeAttach(pParse, SQLITE_ATTACH, "sqlite_attach", 3, p, p, pDbname, pKey);
}
/*
** Register the functions sqlite_attach and sqlite_detach.
*/
void sqlite3AttachFunctions(sqlite3 *db){
static const int enc = SQLITE_UTF8;
sqlite3CreateFunc(db, "sqlite_attach", 3, enc, db, attachFunc, 0, 0);
sqlite3CreateFunc(db, "sqlite_detach", 1, enc, db, detachFunc, 0, 0);
}
/*
** Initialize a DbFixer structure. This routine must be called prior
** to passing the structure to one of the sqliteFixAAAA() routines below.
**
** The return value indicates whether or not fixation is required. TRUE
** means we do need to fix the database references, FALSE means we do not.
*/
int sqlite3FixInit(
DbFixer *pFix, /* The fixer to be initialized */
Parse *pParse, /* Error messages will be written here */
int iDb, /* This is the database that must be used */
const char *zType, /* "view", "trigger", or "index" */
const Token *pName /* Name of the view, trigger, or index */
){
sqlite3 *db;
if( iDb<0 || iDb==1 ) return 0;
db = pParse->db;
assert( db->nDb>iDb );
pFix->pParse = pParse;
pFix->zDb = db->aDb[iDb].zName;
pFix->zType = zType;
pFix->pName = pName;
return 1;
}
/*
** The following set of routines walk through the parse tree and assign
** a specific database to all table references where the database name
** was left unspecified in the original SQL statement. The pFix structure
** must have been initialized by a prior call to sqlite3FixInit().
**
** These routines are used to make sure that an index, trigger, or
** view in one database does not refer to objects in a different database.
** (Exception: indices, triggers, and views in the TEMP database are
** allowed to refer to anything.) If a reference is explicitly made
** to an object in a different database, an error message is added to
** pParse->zErrMsg and these routines return non-zero. If everything
** checks out, these routines return 0.
*/
int sqlite3FixSrcList(
DbFixer *pFix, /* Context of the fixation */
SrcList *pList /* The Source list to check and modify */
){
int i;
const char *zDb;
struct SrcList_item *pItem;
if( pList==0 ) return 0;
zDb = pFix->zDb;
for(i=0, pItem=pList->a; i<pList->nSrc; i++, pItem++){
if( pItem->zDatabase==0 ){
pItem->zDatabase = sqliteStrDup(zDb);
}else if( sqlite3StrICmp(pItem->zDatabase,zDb)!=0 ){
sqlite3ErrorMsg(pFix->pParse,
"%s %T cannot reference objects in database %s",
pFix->zType, pFix->pName, pItem->zDatabase);
return 1;
}
#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER)
if( sqlite3FixSelect(pFix, pItem->pSelect) ) return 1;
if( sqlite3FixExpr(pFix, pItem->pOn) ) return 1;
#endif
}
return 0;
}
#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER)
int sqlite3FixSelect(
DbFixer *pFix, /* Context of the fixation */
Select *pSelect /* The SELECT statement to be fixed to one database */
){
while( pSelect ){
if( sqlite3FixExprList(pFix, pSelect->pEList) ){
return 1;
}
if( sqlite3FixSrcList(pFix, pSelect->pSrc) ){
return 1;
}
if( sqlite3FixExpr(pFix, pSelect->pWhere) ){
return 1;
}
if( sqlite3FixExpr(pFix, pSelect->pHaving) ){
return 1;
}
pSelect = pSelect->pPrior;
}
return 0;
}
int sqlite3FixExpr(
DbFixer *pFix, /* Context of the fixation */
Expr *pExpr /* The expression to be fixed to one database */
){
while( pExpr ){
if( sqlite3FixSelect(pFix, pExpr->pSelect) ){
return 1;
}
if( sqlite3FixExprList(pFix, pExpr->pList) ){
return 1;
}
if( sqlite3FixExpr(pFix, pExpr->pRight) ){
return 1;
}
pExpr = pExpr->pLeft;
}
return 0;
}
int sqlite3FixExprList(
DbFixer *pFix, /* Context of the fixation */
ExprList *pList /* The expression to be fixed to one database */
){
int i;
struct ExprList_item *pItem;
if( pList==0 ) return 0;
for(i=0, pItem=pList->a; i<pList->nExpr; i++, pItem++){
if( sqlite3FixExpr(pFix, pItem->pExpr) ){
return 1;
}
}
return 0;
}
#endif
#ifndef SQLITE_OMIT_TRIGGER
int sqlite3FixTriggerStep(
DbFixer *pFix, /* Context of the fixation */
TriggerStep *pStep /* The trigger step be fixed to one database */
){
while( pStep ){
if( sqlite3FixSelect(pFix, pStep->pSelect) ){
return 1;
}
if( sqlite3FixExpr(pFix, pStep->pWhere) ){
return 1;
}
if( sqlite3FixExprList(pFix, pStep->pExprList) ){
return 1;
}
pStep = pStep->pNext;
}
return 0;
}
#endif

View File

@ -1,234 +0,0 @@
/*
** 2003 January 11
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains code used to implement the sqlite3_set_authorizer()
** API. This facility is an optional feature of the library. Embedded
** systems that do not need this facility may omit it by recompiling
** the library with -DSQLITE_OMIT_AUTHORIZATION=1
**
** $Id: auth.c 3426 2007-03-21 20:19:37Z damagedsoul $
*/
#include "sqliteInt.h"
/*
** All of the code in this file may be omitted by defining a single
** macro.
*/
#ifndef SQLITE_OMIT_AUTHORIZATION
/*
** Set or clear the access authorization function.
**
** The access authorization function is be called during the compilation
** phase to verify that the user has read and/or write access permission on
** various fields of the database. The first argument to the auth function
** is a copy of the 3rd argument to this routine. The second argument
** to the auth function is one of these constants:
**
** SQLITE_CREATE_INDEX
** SQLITE_CREATE_TABLE
** SQLITE_CREATE_TEMP_INDEX
** SQLITE_CREATE_TEMP_TABLE
** SQLITE_CREATE_TEMP_TRIGGER
** SQLITE_CREATE_TEMP_VIEW
** SQLITE_CREATE_TRIGGER
** SQLITE_CREATE_VIEW
** SQLITE_DELETE
** SQLITE_DROP_INDEX
** SQLITE_DROP_TABLE
** SQLITE_DROP_TEMP_INDEX
** SQLITE_DROP_TEMP_TABLE
** SQLITE_DROP_TEMP_TRIGGER
** SQLITE_DROP_TEMP_VIEW
** SQLITE_DROP_TRIGGER
** SQLITE_DROP_VIEW
** SQLITE_INSERT
** SQLITE_PRAGMA
** SQLITE_READ
** SQLITE_SELECT
** SQLITE_TRANSACTION
** SQLITE_UPDATE
**
** The third and fourth arguments to the auth function are the name of
** the table and the column that are being accessed. The auth function
** should return either SQLITE_OK, SQLITE_DENY, or SQLITE_IGNORE. If
** SQLITE_OK is returned, it means that access is allowed. SQLITE_DENY
** means that the SQL statement will never-run - the sqlite3_exec() call
** will return with an error. SQLITE_IGNORE means that the SQL statement
** should run but attempts to read the specified column will return NULL
** and attempts to write the column will be ignored.
**
** Setting the auth function to NULL disables this hook. The default
** setting of the auth function is NULL.
*/
int sqlite3_set_authorizer(
sqlite3 *db,
int (*xAuth)(void*,int,const char*,const char*,const char*,const char*),
void *pArg
){
db->xAuth = xAuth;
db->pAuthArg = pArg;
sqlite3ExpirePreparedStatements(db);
return SQLITE_OK;
}
/*
** Write an error message into pParse->zErrMsg that explains that the
** user-supplied authorization function returned an illegal value.
*/
static void sqliteAuthBadReturnCode(Parse *pParse, int rc){
sqlite3ErrorMsg(pParse, "illegal return value (%d) from the "
"authorization function - should be SQLITE_OK, SQLITE_IGNORE, "
"or SQLITE_DENY", rc);
pParse->rc = SQLITE_ERROR;
}
/*
** The pExpr should be a TK_COLUMN expression. The table referred to
** is in pTabList or else it is the NEW or OLD table of a trigger.
** Check to see if it is OK to read this particular column.
**
** If the auth function returns SQLITE_IGNORE, change the TK_COLUMN
** instruction into a TK_NULL. If the auth function returns SQLITE_DENY,
** then generate an error.
*/
void sqlite3AuthRead(
Parse *pParse, /* The parser context */
Expr *pExpr, /* The expression to check authorization on */
SrcList *pTabList /* All table that pExpr might refer to */
){
sqlite3 *db = pParse->db;
int rc;
Table *pTab; /* The table being read */
const char *zCol; /* Name of the column of the table */
int iSrc; /* Index in pTabList->a[] of table being read */
const char *zDBase; /* Name of database being accessed */
TriggerStack *pStack; /* The stack of current triggers */
int iDb; /* The index of the database the expression refers to */
if( db->xAuth==0 ) return;
if( pExpr->op==TK_AS ) return;
assert( pExpr->op==TK_COLUMN );
iDb = sqlite3SchemaToIndex(pParse->db, pExpr->pSchema);
if( iDb<0 ){
/* An attempt to read a column out of a subquery or other
** temporary table. */
return;
}
for(iSrc=0; pTabList && iSrc<pTabList->nSrc; iSrc++){
if( pExpr->iTable==pTabList->a[iSrc].iCursor ) break;
}
if( iSrc>=0 && pTabList && iSrc<pTabList->nSrc ){
pTab = pTabList->a[iSrc].pTab;
}else if( (pStack = pParse->trigStack)!=0 ){
/* This must be an attempt to read the NEW or OLD pseudo-tables
** of a trigger.
*/
assert( pExpr->iTable==pStack->newIdx || pExpr->iTable==pStack->oldIdx );
pTab = pStack->pTab;
}else{
return;
}
if( pTab==0 ) return;
if( pExpr->iColumn>=0 ){
assert( pExpr->iColumn<pTab->nCol );
zCol = pTab->aCol[pExpr->iColumn].zName;
}else if( pTab->iPKey>=0 ){
assert( pTab->iPKey<pTab->nCol );
zCol = pTab->aCol[pTab->iPKey].zName;
}else{
zCol = "ROWID";
}
assert( iDb>=0 && iDb<db->nDb );
zDBase = db->aDb[iDb].zName;
rc = db->xAuth(db->pAuthArg, SQLITE_READ, pTab->zName, zCol, zDBase,
pParse->zAuthContext);
if( rc==SQLITE_IGNORE ){
pExpr->op = TK_NULL;
}else if( rc==SQLITE_DENY ){
if( db->nDb>2 || iDb!=0 ){
sqlite3ErrorMsg(pParse, "access to %s.%s.%s is prohibited",
zDBase, pTab->zName, zCol);
}else{
sqlite3ErrorMsg(pParse, "access to %s.%s is prohibited",pTab->zName,zCol);
}
pParse->rc = SQLITE_AUTH;
}else if( rc!=SQLITE_OK ){
sqliteAuthBadReturnCode(pParse, rc);
}
}
/*
** Do an authorization check using the code and arguments given. Return
** either SQLITE_OK (zero) or SQLITE_IGNORE or SQLITE_DENY. If SQLITE_DENY
** is returned, then the error count and error message in pParse are
** modified appropriately.
*/
int sqlite3AuthCheck(
Parse *pParse,
int code,
const char *zArg1,
const char *zArg2,
const char *zArg3
){
sqlite3 *db = pParse->db;
int rc;
/* Don't do any authorization checks if the database is initialising
** or if the parser is being invoked from within sqlite3_declare_vtab.
*/
if( db->init.busy || IN_DECLARE_VTAB ){
return SQLITE_OK;
}
if( db->xAuth==0 ){
return SQLITE_OK;
}
rc = db->xAuth(db->pAuthArg, code, zArg1, zArg2, zArg3, pParse->zAuthContext);
if( rc==SQLITE_DENY ){
sqlite3ErrorMsg(pParse, "not authorized");
pParse->rc = SQLITE_AUTH;
}else if( rc!=SQLITE_OK && rc!=SQLITE_IGNORE ){
rc = SQLITE_DENY;
sqliteAuthBadReturnCode(pParse, rc);
}
return rc;
}
/*
** Push an authorization context. After this routine is called, the
** zArg3 argument to authorization callbacks will be zContext until
** popped. Or if pParse==0, this routine is a no-op.
*/
void sqlite3AuthContextPush(
Parse *pParse,
AuthContext *pContext,
const char *zContext
){
pContext->pParse = pParse;
if( pParse ){
pContext->zAuthContext = pParse->zAuthContext;
pParse->zAuthContext = zContext;
}
}
/*
** Pop an authorization context that was previously pushed
** by sqlite3AuthContextPush
*/
void sqlite3AuthContextPop(AuthContext *pContext){
if( pContext->pParse ){
pContext->pParse->zAuthContext = pContext->zAuthContext;
pContext->pParse = 0;
}
}
#endif /* SQLITE_OMIT_AUTHORIZATION */

File diff suppressed because it is too large Load Diff

View File

@ -1,149 +0,0 @@
/*
** 2001 September 15
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
** This header file defines the interface that the sqlite B-Tree file
** subsystem. See comments in the source code for a detailed description
** of what each interface routine does.
**
** @(#) $Id: btree.h 3426 2007-03-21 20:19:37Z damagedsoul $
*/
#ifndef _BTREE_H_
#define _BTREE_H_
/* TODO: This definition is just included so other modules compile. It
** needs to be revisited.
*/
#define SQLITE_N_BTREE_META 10
/*
** If defined as non-zero, auto-vacuum is enabled by default. Otherwise
** it must be turned on for each database using "PRAGMA auto_vacuum = 1".
*/
#ifndef SQLITE_DEFAULT_AUTOVACUUM
#define SQLITE_DEFAULT_AUTOVACUUM 0
#endif
/*
** Forward declarations of structure
*/
typedef struct Btree Btree;
typedef struct BtCursor BtCursor;
typedef struct BtShared BtShared;
int sqlite3BtreeOpen(
const char *zFilename, /* Name of database file to open */
sqlite3 *db, /* Associated database connection */
Btree **, /* Return open Btree* here */
int flags /* Flags */
);
/* The flags parameter to sqlite3BtreeOpen can be the bitwise or of the
** following values.
**
** NOTE: These values must match the corresponding PAGER_ values in
** pager.h.
*/
#define BTREE_OMIT_JOURNAL 1 /* Do not use journal. No argument */
#define BTREE_NO_READLOCK 2 /* Omit readlocks on readonly files */
#define BTREE_MEMORY 4 /* In-memory DB. No argument */
int sqlite3BtreeClose(Btree*);
int sqlite3BtreeSetBusyHandler(Btree*,BusyHandler*);
int sqlite3BtreeSetCacheSize(Btree*,int);
int sqlite3BtreeSetSafetyLevel(Btree*,int,int);
int sqlite3BtreeSyncDisabled(Btree*);
int sqlite3BtreeSetPageSize(Btree*,int,int);
int sqlite3BtreeGetPageSize(Btree*);
int sqlite3BtreeGetReserve(Btree*);
int sqlite3BtreeSetAutoVacuum(Btree *, int);
int sqlite3BtreeGetAutoVacuum(Btree *);
int sqlite3BtreeBeginTrans(Btree*,int);
int sqlite3BtreeCommit(Btree*);
int sqlite3BtreeRollback(Btree*);
int sqlite3BtreeBeginStmt(Btree*);
int sqlite3BtreeCommitStmt(Btree*);
int sqlite3BtreeRollbackStmt(Btree*);
int sqlite3BtreeCreateTable(Btree*, int*, int flags);
int sqlite3BtreeIsInTrans(Btree*);
int sqlite3BtreeIsInStmt(Btree*);
int sqlite3BtreeIsInReadTrans(Btree*);
int sqlite3BtreeSync(Btree*, const char *zMaster);
void *sqlite3BtreeSchema(Btree *, int, void(*)(void *));
int sqlite3BtreeSchemaLocked(Btree *);
int sqlite3BtreeLockTable(Btree *, int, u8);
const char *sqlite3BtreeGetFilename(Btree *);
const char *sqlite3BtreeGetDirname(Btree *);
const char *sqlite3BtreeGetJournalname(Btree *);
int sqlite3BtreeCopyFile(Btree *, Btree *);
/* The flags parameter to sqlite3BtreeCreateTable can be the bitwise OR
** of the following flags:
*/
#define BTREE_INTKEY 1 /* Table has only 64-bit signed integer keys */
#define BTREE_ZERODATA 2 /* Table has keys only - no data */
#define BTREE_LEAFDATA 4 /* Data stored in leaves only. Implies INTKEY */
int sqlite3BtreeDropTable(Btree*, int, int*);
int sqlite3BtreeClearTable(Btree*, int);
int sqlite3BtreeGetMeta(Btree*, int idx, u32 *pValue);
int sqlite3BtreeUpdateMeta(Btree*, int idx, u32 value);
int sqlite3BtreeCursor(
Btree*, /* BTree containing table to open */
int iTable, /* Index of root page */
int wrFlag, /* 1 for writing. 0 for read-only */
int(*)(void*,int,const void*,int,const void*), /* Key comparison function */
void*, /* First argument to compare function */
BtCursor **ppCursor /* Returned cursor */
);
void sqlite3BtreeSetCompare(
BtCursor *,
int(*)(void*,int,const void*,int,const void*),
void*
);
int sqlite3BtreeCloseCursor(BtCursor*);
int sqlite3BtreeMoveto(BtCursor*, const void *pKey, i64 nKey, int *pRes);
int sqlite3BtreeDelete(BtCursor*);
int sqlite3BtreeInsert(BtCursor*, const void *pKey, i64 nKey,
const void *pData, int nData);
int sqlite3BtreeFirst(BtCursor*, int *pRes);
int sqlite3BtreeLast(BtCursor*, int *pRes);
int sqlite3BtreeNext(BtCursor*, int *pRes);
int sqlite3BtreeEof(BtCursor*);
int sqlite3BtreeFlags(BtCursor*);
int sqlite3BtreePrevious(BtCursor*, int *pRes);
int sqlite3BtreeKeySize(BtCursor*, i64 *pSize);
int sqlite3BtreeKey(BtCursor*, u32 offset, u32 amt, void*);
const void *sqlite3BtreeKeyFetch(BtCursor*, int *pAmt);
const void *sqlite3BtreeDataFetch(BtCursor*, int *pAmt);
int sqlite3BtreeDataSize(BtCursor*, u32 *pSize);
int sqlite3BtreeData(BtCursor*, u32 offset, u32 amt, void*);
char *sqlite3BtreeIntegrityCheck(Btree*, int *aRoot, int nRoot, int, int*);
struct Pager *sqlite3BtreePager(Btree*);
#ifdef SQLITE_TEST
int sqlite3BtreeCursorInfo(BtCursor*, int*, int);
void sqlite3BtreeCursorList(Btree*);
#endif
#ifdef SQLITE_DEBUG
int sqlite3BtreePageDump(Btree*, int, int recursive);
#else
#define sqlite3BtreePageDump(X,Y,Z) SQLITE_OK
#endif
#endif /* _BTREE_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -1,373 +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 3426 2007-03-21 20:19:37Z damagedsoul $
*/
#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.
**
** A separate function sqlite3LocateCollSeq() is a wrapper around
** this routine. sqlite3LocateCollSeq() invokes the collation factory
** if necessary and generates an error message if the collating sequence
** cannot be found.
*/
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);
p->enc = SQLITE_UTF8;
}
return p;
}

View File

@ -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 2779 2006-06-04 04:29:46Z damagedsoul $
*/
#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 */

File diff suppressed because it is too large Load Diff

View File

@ -1,467 +0,0 @@
/*
** 2001 September 15
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** in order to generate code for DELETE FROM statements.
**
** $Id: delete.c 3426 2007-03-21 20:19:37Z damagedsoul $
*/
#include "sqliteInt.h"
/*
** Look up every table that is named in pSrc. If any table is not found,
** add an error message to pParse->zErrMsg and return NULL. If all tables
** are found, return a pointer to the last table.
*/
Table *sqlite3SrcListLookup(Parse *pParse, SrcList *pSrc){
Table *pTab = 0;
int i;
struct SrcList_item *pItem;
for(i=0, pItem=pSrc->a; i<pSrc->nSrc; i++, pItem++){
pTab = sqlite3LocateTable(pParse, pItem->zName, pItem->zDatabase);
sqlite3DeleteTable(pParse->db, pItem->pTab);
pItem->pTab = pTab;
if( pTab ){
pTab->nRef++;
}
}
return pTab;
}
/*
** Check to make sure the given table is writable. If it is not
** writable, generate an error message and return 1. If it is
** writable return 0;
*/
int sqlite3IsReadOnly(Parse *pParse, Table *pTab, int viewOk){
if( (pTab->readOnly && (pParse->db->flags & SQLITE_WriteSchema)==0
&& pParse->nested==0)
#ifndef SQLITE_OMIT_VIRTUALTABLE
|| (pTab->pMod && pTab->pMod->pModule->xUpdate==0)
#endif
){
sqlite3ErrorMsg(pParse, "table %s may not be modified", pTab->zName);
return 1;
}
#ifndef SQLITE_OMIT_VIEW
if( !viewOk && pTab->pSelect ){
sqlite3ErrorMsg(pParse,"cannot modify %s because it is a view",pTab->zName);
return 1;
}
#endif
return 0;
}
/*
** Generate code that will open a table for reading.
*/
void sqlite3OpenTable(
Parse *p, /* Generate code into this VDBE */
int iCur, /* The cursor number of the table */
int iDb, /* The database index in sqlite3.aDb[] */
Table *pTab, /* The table to be opened */
int opcode /* OP_OpenRead or OP_OpenWrite */
){
Vdbe *v;
if( IsVirtual(pTab) ) return;
v = sqlite3GetVdbe(p);
assert( opcode==OP_OpenWrite || opcode==OP_OpenRead );
sqlite3TableLock(p, iDb, pTab->tnum, (opcode==OP_OpenWrite), pTab->zName);
sqlite3VdbeAddOp(v, OP_Integer, iDb, 0);
VdbeComment((v, "# %s", pTab->zName));
sqlite3VdbeAddOp(v, opcode, iCur, pTab->tnum);
sqlite3VdbeAddOp(v, OP_SetNumColumns, iCur, pTab->nCol);
}
/*
** Generate code for a DELETE FROM statement.
**
** DELETE FROM table_wxyz WHERE a<5 AND b NOT NULL;
** \________/ \________________/
** pTabList pWhere
*/
void sqlite3DeleteFrom(
Parse *pParse, /* The parser context */
SrcList *pTabList, /* The table from which we should delete things */
Expr *pWhere /* The WHERE clause. May be null */
){
Vdbe *v; /* The virtual database engine */
Table *pTab; /* The table from which records will be deleted */
const char *zDb; /* Name of database holding pTab */
int end, addr = 0; /* A couple addresses of generated code */
int i; /* Loop counter */
WhereInfo *pWInfo; /* Information about the WHERE clause */
Index *pIdx; /* For looping over indices of the table */
int iCur; /* VDBE Cursor number for pTab */
sqlite3 *db; /* Main database structure */
AuthContext sContext; /* Authorization context */
int oldIdx = -1; /* Cursor for the OLD table of AFTER triggers */
NameContext sNC; /* Name context to resolve expressions in */
int iDb; /* Database number */
int memCnt = 0; /* Memory cell used for change counting */
#ifndef SQLITE_OMIT_TRIGGER
int isView; /* True if attempting to delete from a view */
int triggers_exist = 0; /* True if any triggers exist */
#endif
sContext.pParse = 0;
if( pParse->nErr || sqlite3MallocFailed() ){
goto delete_from_cleanup;
}
db = pParse->db;
assert( pTabList->nSrc==1 );
/* Locate the table which we want to delete. This table has to be
** put in an SrcList structure because some of the subroutines we
** will be calling are designed to work with multiple tables and expect
** an SrcList* parameter instead of just a Table* parameter.
*/
pTab = sqlite3SrcListLookup(pParse, pTabList);
if( pTab==0 ) goto delete_from_cleanup;
/* Figure out if we have any triggers and if the table being
** deleted from is a view
*/
#ifndef SQLITE_OMIT_TRIGGER
triggers_exist = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0);
isView = pTab->pSelect!=0;
#else
# define triggers_exist 0
# define isView 0
#endif
#ifdef SQLITE_OMIT_VIEW
# undef isView
# define isView 0
#endif
if( sqlite3IsReadOnly(pParse, pTab, triggers_exist) ){
goto delete_from_cleanup;
}
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
assert( iDb<db->nDb );
zDb = db->aDb[iDb].zName;
if( sqlite3AuthCheck(pParse, SQLITE_DELETE, pTab->zName, 0, zDb) ){
goto delete_from_cleanup;
}
/* If pTab is really a view, make sure it has been initialized.
*/
if( sqlite3ViewGetColumnNames(pParse, pTab) ){
goto delete_from_cleanup;
}
/* Allocate a cursor used to store the old.* data for a trigger.
*/
if( triggers_exist ){
oldIdx = pParse->nTab++;
}
/* Resolve the column names in the WHERE clause.
*/
assert( pTabList->nSrc==1 );
iCur = pTabList->a[0].iCursor = pParse->nTab++;
memset(&sNC, 0, sizeof(sNC));
sNC.pParse = pParse;
sNC.pSrcList = pTabList;
if( sqlite3ExprResolveNames(&sNC, pWhere) ){
goto delete_from_cleanup;
}
/* Start the view context
*/
if( isView ){
sqlite3AuthContextPush(pParse, &sContext, pTab->zName);
}
/* Begin generating code.
*/
v = sqlite3GetVdbe(pParse);
if( v==0 ){
goto delete_from_cleanup;
}
if( pParse->nested==0 ) sqlite3VdbeCountChanges(v);
sqlite3BeginWriteOperation(pParse, triggers_exist, iDb);
/* If we are trying to delete from a view, realize that view into
** a ephemeral table.
*/
if( isView ){
Select *pView = sqlite3SelectDup(pTab->pSelect);
sqlite3Select(pParse, pView, SRT_EphemTab, iCur, 0, 0, 0, 0);
sqlite3SelectDelete(pView);
}
/* Initialize the counter of the number of rows deleted, if
** we are counting rows.
*/
if( db->flags & SQLITE_CountRows ){
memCnt = pParse->nMem++;
sqlite3VdbeAddOp(v, OP_MemInt, 0, memCnt);
}
/* Special case: A DELETE without a WHERE clause deletes everything.
** It is easier just to erase the whole table. Note, however, that
** this means that the row change count will be incorrect.
*/
if( pWhere==0 && !triggers_exist && !IsVirtual(pTab) ){
if( db->flags & SQLITE_CountRows ){
/* If counting rows deleted, just count the total number of
** entries in the table. */
int endOfLoop = sqlite3VdbeMakeLabel(v);
int addr2;
if( !isView ){
sqlite3OpenTable(pParse, iCur, iDb, pTab, OP_OpenRead);
}
sqlite3VdbeAddOp(v, OP_Rewind, iCur, sqlite3VdbeCurrentAddr(v)+2);
addr2 = sqlite3VdbeAddOp(v, OP_MemIncr, 1, memCnt);
sqlite3VdbeAddOp(v, OP_Next, iCur, addr2);
sqlite3VdbeResolveLabel(v, endOfLoop);
sqlite3VdbeAddOp(v, OP_Close, iCur, 0);
}
if( !isView ){
sqlite3VdbeAddOp(v, OP_Clear, pTab->tnum, iDb);
if( !pParse->nested ){
sqlite3VdbeChangeP3(v, -1, pTab->zName, P3_STATIC);
}
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
assert( pIdx->pSchema==pTab->pSchema );
sqlite3VdbeAddOp(v, OP_Clear, pIdx->tnum, iDb);
}
}
}
/* The usual case: There is a WHERE clause so we have to scan through
** the table and pick which records to delete.
*/
else{
/* Begin the database scan
*/
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0);
if( pWInfo==0 ) goto delete_from_cleanup;
/* Remember the rowid of every item to be deleted.
*/
sqlite3VdbeAddOp(v, IsVirtual(pTab) ? OP_VRowid : OP_Rowid, iCur, 0);
sqlite3VdbeAddOp(v, OP_FifoWrite, 0, 0);
if( db->flags & SQLITE_CountRows ){
sqlite3VdbeAddOp(v, OP_MemIncr, 1, memCnt);
}
/* End the database scan loop.
*/
sqlite3WhereEnd(pWInfo);
/* Open the pseudo-table used to store OLD if there are triggers.
*/
if( triggers_exist ){
sqlite3VdbeAddOp(v, OP_OpenPseudo, oldIdx, 0);
sqlite3VdbeAddOp(v, OP_SetNumColumns, oldIdx, pTab->nCol);
}
/* Delete every item whose key was written to the list during the
** database scan. We have to delete items after the scan is complete
** because deleting an item can change the scan order.
*/
end = sqlite3VdbeMakeLabel(v);
/* This is the beginning of the delete loop when there are
** row triggers.
*/
if( triggers_exist ){
addr = sqlite3VdbeAddOp(v, OP_FifoRead, 0, end);
if( !isView ){
sqlite3VdbeAddOp(v, OP_Dup, 0, 0);
sqlite3OpenTable(pParse, iCur, iDb, pTab, OP_OpenRead);
}
sqlite3VdbeAddOp(v, OP_MoveGe, iCur, 0);
sqlite3VdbeAddOp(v, OP_Rowid, iCur, 0);
sqlite3VdbeAddOp(v, OP_RowData, iCur, 0);
sqlite3VdbeAddOp(v, OP_Insert, oldIdx, 0);
if( !isView ){
sqlite3VdbeAddOp(v, OP_Close, iCur, 0);
}
(void)sqlite3CodeRowTrigger(pParse, TK_DELETE, 0, TRIGGER_BEFORE, pTab,
-1, oldIdx, (pParse->trigStack)?pParse->trigStack->orconf:OE_Default,
addr);
}
if( !isView ){
/* Open cursors for the table we are deleting from and all its
** indices. If there are row triggers, this happens inside the
** OP_FifoRead loop because the cursor have to all be closed
** before the trigger fires. If there are no row triggers, the
** cursors are opened only once on the outside the loop.
*/
sqlite3OpenTableAndIndices(pParse, pTab, iCur, OP_OpenWrite);
/* This is the beginning of the delete loop when there are no
** row triggers */
if( !triggers_exist ){
addr = sqlite3VdbeAddOp(v, OP_FifoRead, 0, end);
}
/* Delete the row */
#ifndef SQLITE_OMIT_VIRTUALTABLE
if( IsVirtual(pTab) ){
pParse->pVirtualLock = pTab;
sqlite3VdbeOp3(v, OP_VUpdate, 0, 1, (const char*)pTab->pVtab, P3_VTAB);
}else
#endif
{
sqlite3GenerateRowDelete(db, v, pTab, iCur, pParse->nested==0);
}
}
/* If there are row triggers, close all cursors then invoke
** the AFTER triggers
*/
if( triggers_exist ){
if( !isView ){
for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
sqlite3VdbeAddOp(v, OP_Close, iCur + i, pIdx->tnum);
}
sqlite3VdbeAddOp(v, OP_Close, iCur, 0);
}
(void)sqlite3CodeRowTrigger(pParse, TK_DELETE, 0, TRIGGER_AFTER, pTab, -1,
oldIdx, (pParse->trigStack)?pParse->trigStack->orconf:OE_Default,
addr);
}
/* End of the delete loop */
sqlite3VdbeAddOp(v, OP_Goto, 0, addr);
sqlite3VdbeResolveLabel(v, end);
/* Close the cursors after the loop if there are no row triggers */
if( !triggers_exist && !IsVirtual(pTab) ){
for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
sqlite3VdbeAddOp(v, OP_Close, iCur + i, pIdx->tnum);
}
sqlite3VdbeAddOp(v, OP_Close, iCur, 0);
}
}
/*
** Return the number of rows that were deleted. If this routine is
** generating code because of a call to sqlite3NestedParse(), do not
** invoke the callback function.
*/
if( db->flags & SQLITE_CountRows && pParse->nested==0 && !pParse->trigStack ){
sqlite3VdbeAddOp(v, OP_MemLoad, memCnt, 0);
sqlite3VdbeAddOp(v, OP_Callback, 1, 0);
sqlite3VdbeSetNumCols(v, 1);
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows deleted", P3_STATIC);
}
delete_from_cleanup:
sqlite3AuthContextPop(&sContext);
sqlite3SrcListDelete(pTabList);
sqlite3ExprDelete(pWhere);
return;
}
/*
** This routine generates VDBE code that causes a single row of a
** single table to be deleted.
**
** The VDBE must be in a particular state when this routine is called.
** These are the requirements:
**
** 1. A read/write cursor pointing to pTab, the table containing the row
** to be deleted, must be opened as cursor number "base".
**
** 2. Read/write cursors for all indices of pTab must be open as
** cursor number base+i for the i-th index.
**
** 3. The record number of the row to be deleted must be on the top
** of the stack.
**
** This routine pops the top of the stack to remove the record number
** and then generates code to remove both the table record and all index
** entries that point to that record.
*/
void sqlite3GenerateRowDelete(
sqlite3 *db, /* The database containing the index */
Vdbe *v, /* Generate code into this VDBE */
Table *pTab, /* Table containing the row to be deleted */
int iCur, /* Cursor number for the table */
int count /* Increment the row change counter */
){
int addr;
addr = sqlite3VdbeAddOp(v, OP_NotExists, iCur, 0);
sqlite3GenerateRowIndexDelete(v, pTab, iCur, 0);
sqlite3VdbeAddOp(v, OP_Delete, iCur, (count?OPFLAG_NCHANGE:0));
if( count ){
sqlite3VdbeChangeP3(v, -1, pTab->zName, P3_STATIC);
}
sqlite3VdbeJumpHere(v, addr);
}
/*
** This routine generates VDBE code that causes the deletion of all
** index entries associated with a single row of a single table.
**
** The VDBE must be in a particular state when this routine is called.
** These are the requirements:
**
** 1. A read/write cursor pointing to pTab, the table containing the row
** to be deleted, must be opened as cursor number "iCur".
**
** 2. Read/write cursors for all indices of pTab must be open as
** cursor number iCur+i for the i-th index.
**
** 3. The "iCur" cursor must be pointing to the row that is to be
** deleted.
*/
void sqlite3GenerateRowIndexDelete(
Vdbe *v, /* Generate code into this VDBE */
Table *pTab, /* Table containing the row to be deleted */
int iCur, /* Cursor number for the table */
char *aIdxUsed /* Only delete if aIdxUsed!=0 && aIdxUsed[i]!=0 */
){
int i;
Index *pIdx;
for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
if( aIdxUsed!=0 && aIdxUsed[i-1]==0 ) continue;
sqlite3GenerateIndexKey(v, pIdx, iCur);
sqlite3VdbeAddOp(v, OP_IdxDelete, iCur+i, 0);
}
}
/*
** Generate code that will assemble an index key and put it on the top
** of the tack. The key with be for index pIdx which is an index on pTab.
** iCur is the index of a cursor open on the pTab table and pointing to
** the entry that needs indexing.
*/
void sqlite3GenerateIndexKey(
Vdbe *v, /* Generate code into this VDBE */
Index *pIdx, /* The index for which to generate a key */
int iCur /* Cursor number for the pIdx->pTable table */
){
int j;
Table *pTab = pIdx->pTable;
sqlite3VdbeAddOp(v, OP_Rowid, iCur, 0);
for(j=0; j<pIdx->nColumn; j++){
int idx = pIdx->aiColumn[j];
if( idx==pTab->iPKey ){
sqlite3VdbeAddOp(v, OP_Dup, j, 0);
}else{
sqlite3VdbeAddOp(v, OP_Column, iCur, idx);
sqlite3ColumnDefault(v, pTab, idx);
}
}
sqlite3VdbeAddOp(v, OP_MakeIdxRec, pIdx->nColumn, 0);
sqlite3IndexAffinityStr(v, pIdx);
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,394 +0,0 @@
/*
** 2001 September 22
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
** This is the implementation of generic hash-tables
** used in SQLite.
**
** $Id: hash.c 2779 2006-06-04 04:29:46Z damagedsoul $
*/
#include "sqliteInt.h"
#include <assert.h>
/* Turn bulk memory into a hash table object by initializing the
** fields of the Hash structure.
**
** "pNew" is a pointer to the hash table that is to be initialized.
** keyClass is one of the constants SQLITE_HASH_INT, SQLITE_HASH_POINTER,
** SQLITE_HASH_BINARY, or SQLITE_HASH_STRING. The value of keyClass
** determines what kind of key the hash table will use. "copyKey" is
** true if the hash table should make its own private copy of keys and
** false if it should just use the supplied pointer. CopyKey only makes
** sense for SQLITE_HASH_STRING and SQLITE_HASH_BINARY and is ignored
** for other key classes.
*/
void sqlite3HashInit(Hash *pNew, int keyClass, int copyKey){
assert( pNew!=0 );
assert( keyClass>=SQLITE_HASH_STRING && keyClass<=SQLITE_HASH_BINARY );
pNew->keyClass = keyClass;
#if 0
if( keyClass==SQLITE_HASH_POINTER || keyClass==SQLITE_HASH_INT ) copyKey = 0;
#endif
pNew->copyKey = copyKey;
pNew->first = 0;
pNew->count = 0;
pNew->htsize = 0;
pNew->ht = 0;
pNew->xMalloc = sqlite3MallocX;
pNew->xFree = sqlite3FreeX;
}
/* Remove all entries from a hash table. Reclaim all memory.
** Call this routine to delete a hash table or to reset a hash table
** to the empty state.
*/
void sqlite3HashClear(Hash *pH){
HashElem *elem; /* For looping over all elements of the table */
assert( pH!=0 );
elem = pH->first;
pH->first = 0;
if( pH->ht ) pH->xFree(pH->ht);
pH->ht = 0;
pH->htsize = 0;
while( elem ){
HashElem *next_elem = elem->next;
if( pH->copyKey && elem->pKey ){
pH->xFree(elem->pKey);
}
pH->xFree(elem);
elem = next_elem;
}
pH->count = 0;
}
#if 0 /* NOT USED */
/*
** Hash and comparison functions when the mode is SQLITE_HASH_INT
*/
static int intHash(const void *pKey, int nKey){
return nKey ^ (nKey<<8) ^ (nKey>>8);
}
static int intCompare(const void *pKey1, int n1, const void *pKey2, int n2){
return n2 - n1;
}
#endif
#if 0 /* NOT USED */
/*
** Hash and comparison functions when the mode is SQLITE_HASH_POINTER
*/
static int ptrHash(const void *pKey, int nKey){
uptr x = Addr(pKey);
return x ^ (x<<8) ^ (x>>8);
}
static int ptrCompare(const void *pKey1, int n1, const void *pKey2, int n2){
if( pKey1==pKey2 ) return 0;
if( pKey1<pKey2 ) return -1;
return 1;
}
#endif
/*
** Hash and comparison functions when the mode is SQLITE_HASH_STRING
*/
static int strHash(const void *pKey, int nKey){
const char *z = (const char *)pKey;
int h = 0;
if( nKey<=0 ) nKey = strlen(z);
while( nKey > 0 ){
h = (h<<3) ^ h ^ sqlite3UpperToLower[(unsigned char)*z++];
nKey--;
}
return h & 0x7fffffff;
}
static int strCompare(const void *pKey1, int n1, const void *pKey2, int n2){
if( n1!=n2 ) return 1;
return sqlite3StrNICmp((const char*)pKey1,(const char*)pKey2,n1);
}
/*
** Hash and comparison functions when the mode is SQLITE_HASH_BINARY
*/
static int binHash(const void *pKey, int nKey){
int h = 0;
const char *z = (const char *)pKey;
while( nKey-- > 0 ){
h = (h<<3) ^ h ^ *(z++);
}
return h & 0x7fffffff;
}
static int binCompare(const void *pKey1, int n1, const void *pKey2, int n2){
if( n1!=n2 ) return 1;
return memcmp(pKey1,pKey2,n1);
}
/*
** Return a pointer to the appropriate hash function given the key class.
**
** The C syntax in this function definition may be unfamilar to some
** programmers, so we provide the following additional explanation:
**
** The name of the function is "hashFunction". The function takes a
** single parameter "keyClass". The return value of hashFunction()
** is a pointer to another function. Specifically, the return value
** of hashFunction() is a pointer to a function that takes two parameters
** with types "const void*" and "int" and returns an "int".
*/
static int (*hashFunction(int keyClass))(const void*,int){
#if 0 /* HASH_INT and HASH_POINTER are never used */
switch( keyClass ){
case SQLITE_HASH_INT: return &intHash;
case SQLITE_HASH_POINTER: return &ptrHash;
case SQLITE_HASH_STRING: return &strHash;
case SQLITE_HASH_BINARY: return &binHash;;
default: break;
}
return 0;
#else
if( keyClass==SQLITE_HASH_STRING ){
return &strHash;
}else{
assert( keyClass==SQLITE_HASH_BINARY );
return &binHash;
}
#endif
}
/*
** Return a pointer to the appropriate hash function given the key class.
**
** For help in interpreted the obscure C code in the function definition,
** see the header comment on the previous function.
*/
static int (*compareFunction(int keyClass))(const void*,int,const void*,int){
#if 0 /* HASH_INT and HASH_POINTER are never used */
switch( keyClass ){
case SQLITE_HASH_INT: return &intCompare;
case SQLITE_HASH_POINTER: return &ptrCompare;
case SQLITE_HASH_STRING: return &strCompare;
case SQLITE_HASH_BINARY: return &binCompare;
default: break;
}
return 0;
#else
if( keyClass==SQLITE_HASH_STRING ){
return &strCompare;
}else{
assert( keyClass==SQLITE_HASH_BINARY );
return &binCompare;
}
#endif
}
/* Link an element into the hash table
*/
static void insertElement(
Hash *pH, /* The complete hash table */
struct _ht *pEntry, /* The entry into which pNew is inserted */
HashElem *pNew /* The element to be inserted */
){
HashElem *pHead; /* First element already in pEntry */
pHead = pEntry->chain;
if( pHead ){
pNew->next = pHead;
pNew->prev = pHead->prev;
if( pHead->prev ){ pHead->prev->next = pNew; }
else { pH->first = pNew; }
pHead->prev = pNew;
}else{
pNew->next = pH->first;
if( pH->first ){ pH->first->prev = pNew; }
pNew->prev = 0;
pH->first = pNew;
}
pEntry->count++;
pEntry->chain = pNew;
}
/* Resize the hash table so that it cantains "new_size" buckets.
** "new_size" must be a power of 2. The hash table might fail
** to resize if sqliteMalloc() fails.
*/
static void rehash(Hash *pH, int new_size){
struct _ht *new_ht; /* The new hash table */
HashElem *elem, *next_elem; /* For looping over existing elements */
int (*xHash)(const void*,int); /* The hash function */
assert( (new_size & (new_size-1))==0 );
new_ht = (struct _ht *)pH->xMalloc( new_size*sizeof(struct _ht) );
if( new_ht==0 ) return;
if( pH->ht ) pH->xFree(pH->ht);
pH->ht = new_ht;
pH->htsize = new_size;
xHash = hashFunction(pH->keyClass);
for(elem=pH->first, pH->first=0; elem; elem = next_elem){
int h = (*xHash)(elem->pKey, elem->nKey) & (new_size-1);
next_elem = elem->next;
insertElement(pH, &new_ht[h], elem);
}
}
/* This function (for internal use only) locates an element in an
** hash table that matches the given key. The hash for this key has
** already been computed and is passed as the 4th parameter.
*/
static HashElem *findElementGivenHash(
const Hash *pH, /* The pH to be searched */
const void *pKey, /* The key we are searching for */
int nKey,
int h /* The hash for this key. */
){
HashElem *elem; /* Used to loop thru the element list */
int count; /* Number of elements left to test */
int (*xCompare)(const void*,int,const void*,int); /* comparison function */
if( pH->ht ){
struct _ht *pEntry = &pH->ht[h];
elem = pEntry->chain;
count = pEntry->count;
xCompare = compareFunction(pH->keyClass);
while( count-- && elem ){
if( (*xCompare)(elem->pKey,elem->nKey,pKey,nKey)==0 ){
return elem;
}
elem = elem->next;
}
}
return 0;
}
/* Remove a single entry from the hash table given a pointer to that
** element and a hash on the element's key.
*/
static void removeElementGivenHash(
Hash *pH, /* The pH containing "elem" */
HashElem* elem, /* The element to be removed from the pH */
int h /* Hash value for the element */
){
struct _ht *pEntry;
if( elem->prev ){
elem->prev->next = elem->next;
}else{
pH->first = elem->next;
}
if( elem->next ){
elem->next->prev = elem->prev;
}
pEntry = &pH->ht[h];
if( pEntry->chain==elem ){
pEntry->chain = elem->next;
}
pEntry->count--;
if( pEntry->count<=0 ){
pEntry->chain = 0;
}
if( pH->copyKey && elem->pKey ){
pH->xFree(elem->pKey);
}
pH->xFree( elem );
pH->count--;
if( pH->count<=0 ){
assert( pH->first==0 );
assert( pH->count==0 );
sqlite3HashClear(pH);
}
}
/* Attempt to locate an element of the hash table pH with a key
** that matches pKey,nKey. Return the data for this element if it is
** found, or NULL if there is no match.
*/
void *sqlite3HashFind(const Hash *pH, const void *pKey, int nKey){
int h; /* A hash on key */
HashElem *elem; /* The element that matches key */
int (*xHash)(const void*,int); /* The hash function */
if( pH==0 || pH->ht==0 ) return 0;
xHash = hashFunction(pH->keyClass);
assert( xHash!=0 );
h = (*xHash)(pKey,nKey);
assert( (pH->htsize & (pH->htsize-1))==0 );
elem = findElementGivenHash(pH,pKey,nKey, h & (pH->htsize-1));
return elem ? elem->data : 0;
}
/* Insert an element into the hash table pH. The key is pKey,nKey
** and the data is "data".
**
** If no element exists with a matching key, then a new
** element is created. A copy of the key is made if the copyKey
** flag is set. NULL is returned.
**
** If another element already exists with the same key, then the
** new data replaces the old data and the old data is returned.
** The key is not copied in this instance. If a malloc fails, then
** the new data is returned and the hash table is unchanged.
**
** If the "data" parameter to this function is NULL, then the
** element corresponding to "key" is removed from the hash table.
*/
void *sqlite3HashInsert(Hash *pH, const void *pKey, int nKey, void *data){
int hraw; /* Raw hash value of the key */
int h; /* the hash of the key modulo hash table size */
HashElem *elem; /* Used to loop thru the element list */
HashElem *new_elem; /* New element added to the pH */
int (*xHash)(const void*,int); /* The hash function */
assert( pH!=0 );
xHash = hashFunction(pH->keyClass);
assert( xHash!=0 );
hraw = (*xHash)(pKey, nKey);
assert( (pH->htsize & (pH->htsize-1))==0 );
h = hraw & (pH->htsize-1);
elem = findElementGivenHash(pH,pKey,nKey,h);
if( elem ){
void *old_data = elem->data;
if( data==0 ){
removeElementGivenHash(pH,elem,h);
}else{
elem->data = data;
}
return old_data;
}
if( data==0 ) return 0;
new_elem = (HashElem*)pH->xMalloc( sizeof(HashElem) );
if( new_elem==0 ) return data;
if( pH->copyKey && pKey!=0 ){
new_elem->pKey = pH->xMalloc( nKey );
if( new_elem->pKey==0 ){
pH->xFree(new_elem);
return data;
}
memcpy((void*)new_elem->pKey, pKey, nKey);
}else{
new_elem->pKey = (void*)pKey;
}
new_elem->nKey = nKey;
pH->count++;
if( pH->htsize==0 ){
rehash(pH,8);
if( pH->htsize==0 ){
pH->count = 0;
pH->xFree(new_elem);
return data;
}
}
if( pH->count > pH->htsize ){
rehash(pH,pH->htsize*2);
}
assert( pH->htsize>0 );
assert( (pH->htsize & (pH->htsize-1))==0 );
h = hraw & (pH->htsize-1);
insertElement(pH, &pH->ht[h], new_elem);
new_elem->data = data;
return 0;
}

View File

@ -1,111 +0,0 @@
/*
** 2001 September 22
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
** This is the header file for the generic hash-table implemenation
** used in SQLite.
**
** $Id: hash.h 2779 2006-06-04 04:29:46Z damagedsoul $
*/
#ifndef _SQLITE_HASH_H_
#define _SQLITE_HASH_H_
/* Forward declarations of structures. */
typedef struct Hash Hash;
typedef struct HashElem HashElem;
/* A complete hash table is an instance of the following structure.
** The internals of this structure are intended to be opaque -- client
** code should not attempt to access or modify the fields of this structure
** directly. Change this structure only by using the routines below.
** However, many of the "procedures" and "functions" for modifying and
** accessing this structure are really macros, so we can't really make
** this structure opaque.
*/
struct Hash {
char keyClass; /* SQLITE_HASH_INT, _POINTER, _STRING, _BINARY */
char copyKey; /* True if copy of key made on insert */
int count; /* Number of entries in this table */
HashElem *first; /* The first element of the array */
void *(*xMalloc)(int); /* malloc() function to use */
void (*xFree)(void *); /* free() function to use */
int htsize; /* Number of buckets in the hash table */
struct _ht { /* the hash table */
int count; /* Number of entries with this hash */
HashElem *chain; /* Pointer to first entry with this hash */
} *ht;
};
/* Each element in the hash table is an instance of the following
** structure. All elements are stored on a single doubly-linked list.
**
** Again, this structure is intended to be opaque, but it can't really
** be opaque because it is used by macros.
*/
struct HashElem {
HashElem *next, *prev; /* Next and previous elements in the table */
void *data; /* Data associated with this element */
void *pKey; int nKey; /* Key associated with this element */
};
/*
** There are 4 different modes of operation for a hash table:
**
** SQLITE_HASH_INT nKey is used as the key and pKey is ignored.
**
** SQLITE_HASH_POINTER pKey is used as the key and nKey is ignored.
**
** SQLITE_HASH_STRING pKey points to a string that is nKey bytes long
** (including the null-terminator, if any). Case
** is ignored in comparisons.
**
** SQLITE_HASH_BINARY pKey points to binary data nKey bytes long.
** memcmp() is used to compare keys.
**
** A copy of the key is made for SQLITE_HASH_STRING and SQLITE_HASH_BINARY
** if the copyKey parameter to HashInit is 1.
*/
/* #define SQLITE_HASH_INT 1 // NOT USED */
/* #define SQLITE_HASH_POINTER 2 // NOT USED */
#define SQLITE_HASH_STRING 3
#define SQLITE_HASH_BINARY 4
/*
** Access routines. To delete, insert a NULL pointer.
*/
void sqlite3HashInit(Hash*, int keytype, int copyKey);
void *sqlite3HashInsert(Hash*, const void *pKey, int nKey, void *pData);
void *sqlite3HashFind(const Hash*, const void *pKey, int nKey);
void sqlite3HashClear(Hash*);
/*
** Macros for looping over all elements of a hash table. The idiom is
** like this:
**
** Hash h;
** HashElem *p;
** ...
** for(p=sqliteHashFirst(&h); p; p=sqliteHashNext(p)){
** SomeStructure *pData = sqliteHashData(p);
** // do something with pData
** }
*/
#define sqliteHashFirst(H) ((H)->first)
#define sqliteHashNext(E) ((E)->next)
#define sqliteHashData(E) ((E)->data)
#define sqliteHashKey(E) ((E)->pKey)
#define sqliteHashKeysize(E) ((E)->nKey)
/*
** Number of entries in a hash table
*/
#define sqliteHashCount(H) ((H)->count)
#endif /* _SQLITE_HASH_H_ */

File diff suppressed because it is too large Load Diff

View File

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

View File

@ -1,136 +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.
**
*************************************************************************
** Main file for the SQLite library. The routines in this file
** implement the programmer interface to the library. Routines in
** other files are for internal use by SQLite and should not be
** accessed by users of the library.
**
** $Id: legacy.c 3426 2007-03-21 20:19:37Z damagedsoul $
*/
#include "sqliteInt.h"
#include "os.h"
#include <ctype.h>
/*
** Execute SQL code. Return one of the SQLITE_ success/failure
** codes. Also write an error message into memory obtained from
** malloc() and make *pzErrMsg point to that message.
**
** If the SQL is a query, then for each row in the query result
** the xCallback() function is called. pArg becomes the first
** argument to xCallback(). If xCallback=NULL then no callback
** is invoked, even for queries.
*/
int sqlite3_exec(
sqlite3 *db, /* The database on which the SQL executes */
const char *zSql, /* The SQL to be executed */
sqlite3_callback xCallback, /* Invoke this callback routine */
void *pArg, /* First argument to xCallback() */
char **pzErrMsg /* Write error messages here */
){
int rc = SQLITE_OK;
const char *zLeftover;
sqlite3_stmt *pStmt = 0;
char **azCols = 0;
int nRetry = 0;
int nChange = 0;
int nCallback;
if( zSql==0 ) return SQLITE_OK;
while( (rc==SQLITE_OK || (rc==SQLITE_SCHEMA && (++nRetry)<2)) && zSql[0] ){
int nCol;
char **azVals = 0;
pStmt = 0;
rc = sqlite3_prepare(db, zSql, -1, &pStmt, &zLeftover);
assert( rc==SQLITE_OK || pStmt==0 );
if( rc!=SQLITE_OK ){
continue;
}
if( !pStmt ){
/* this happens for a comment or white-space */
zSql = zLeftover;
continue;
}
db->nChange += nChange;
nCallback = 0;
nCol = sqlite3_column_count(pStmt);
azCols = sqliteMalloc(2*nCol*sizeof(const char *) + 1);
if( azCols==0 ){
goto exec_out;
}
while( 1 ){
int i;
rc = sqlite3_step(pStmt);
/* Invoke the callback function if required */
if( xCallback && (SQLITE_ROW==rc ||
(SQLITE_DONE==rc && !nCallback && db->flags&SQLITE_NullCallback)) ){
if( 0==nCallback ){
for(i=0; i<nCol; i++){
azCols[i] = (char *)sqlite3_column_name(pStmt, i);
}
nCallback++;
}
if( rc==SQLITE_ROW ){
azVals = &azCols[nCol];
for(i=0; i<nCol; i++){
azVals[i] = (char *)sqlite3_column_text(pStmt, i);
}
}
if( xCallback(pArg, nCol, azVals, azCols) ){
rc = SQLITE_ABORT;
goto exec_out;
}
}
if( rc!=SQLITE_ROW ){
rc = sqlite3_finalize(pStmt);
pStmt = 0;
if( db->pVdbe==0 ){
nChange = db->nChange;
}
if( rc!=SQLITE_SCHEMA ){
nRetry = 0;
zSql = zLeftover;
while( isspace((unsigned char)zSql[0]) ) zSql++;
}
break;
}
}
sqliteFree(azCols);
azCols = 0;
}
exec_out:
if( pStmt ) sqlite3_finalize(pStmt);
if( azCols ) sqliteFree(azCols);
rc = sqlite3ApiExit(0, rc);
if( rc!=SQLITE_OK && rc==sqlite3_errcode(db) && pzErrMsg ){
*pzErrMsg = sqlite3_malloc(1+strlen(sqlite3_errmsg(db)));
if( *pzErrMsg ){
strcpy(*pzErrMsg, sqlite3_errmsg(db));
}
}else if( pzErrMsg ){
*pzErrMsg = 0;
}
assert( (rc&db->errMask)==rc );
return rc;
}

View File

@ -1,422 +0,0 @@
/*
** 2006 June 7
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains code used to dynamically load extensions into
** the SQLite library.
*/
#ifndef SQLITE_OMIT_LOAD_EXTENSION
#define SQLITE_CORE 1 /* Disable the API redefinition in sqlite3ext.h */
#include "sqlite3ext.h"
#include "sqliteInt.h"
#include "os.h"
#include <string.h>
#include <ctype.h>
/*
** Some API routines are omitted when various features are
** excluded from a build of SQLite. Substitute a NULL pointer
** for any missing APIs.
*/
#ifndef SQLITE_ENABLE_COLUMN_METADATA
# define sqlite3_column_database_name 0
# define sqlite3_column_database_name16 0
# define sqlite3_column_table_name 0
# define sqlite3_column_table_name16 0
# define sqlite3_column_origin_name 0
# define sqlite3_column_origin_name16 0
# define sqlite3_table_column_metadata 0
#endif
#ifdef SQLITE_OMIT_AUTHORIZATION
# define sqlite3_set_authorizer 0
#endif
#ifdef SQLITE_OMIT_UTF16
# define sqlite3_bind_text16 0
# define sqlite3_collation_needed16 0
# define sqlite3_column_decltype16 0
# define sqlite3_column_name16 0
# define sqlite3_column_text16 0
# define sqlite3_complete16 0
# define sqlite3_create_collation16 0
# define sqlite3_create_function16 0
# define sqlite3_errmsg16 0
# define sqlite3_open16 0
# define sqlite3_prepare16 0
# define sqlite3_result_error16 0
# define sqlite3_result_text16 0
# define sqlite3_result_text16be 0
# define sqlite3_result_text16le 0
# define sqlite3_value_text16 0
# define sqlite3_value_text16be 0
# define sqlite3_value_text16le 0
#endif
#ifdef SQLITE_OMIT_COMPLETE
# define sqlite3_complete 0
# define sqlite3_complete16 0
#endif
#ifdef SQLITE_OMIT_PROGRESS_CALLBACK
# define sqlite3_progress_handler 0
#endif
#ifdef SQLITE_OMIT_VIRTUALTABLE
# define sqlite3_create_module 0
# define sqlite3_declare_vtab 0
#endif
#ifdef SQLITE_OMIT_SHARED_CACHE
# define sqlite3_enable_shared_cache 0
#endif
#ifdef SQLITE_OMIT_TRACE
# define sqlite3_profile 0
# define sqlite3_trace 0
#endif
#ifdef SQLITE_OMIT_GET_TABLE
# define sqlite3_free_table 0
# define sqlite3_get_table 0
#endif
/*
** The following structure contains pointers to all SQLite API routines.
** A pointer to this structure is passed into extensions when they are
** loaded so that the extension can make calls back into the SQLite
** library.
**
** When adding new APIs, add them to the bottom of this structure
** in order to preserve backwards compatibility.
**
** Extensions that use newer APIs should first call the
** sqlite3_libversion_number() to make sure that the API they
** intend to use is supported by the library. Extensions should
** also check to make sure that the pointer to the function is
** not NULL before calling it.
*/
const sqlite3_api_routines sqlite3_apis = {
sqlite3_aggregate_context,
sqlite3_aggregate_count,
sqlite3_bind_blob,
sqlite3_bind_double,
sqlite3_bind_int,
sqlite3_bind_int64,
sqlite3_bind_null,
sqlite3_bind_parameter_count,
sqlite3_bind_parameter_index,
sqlite3_bind_parameter_name,
sqlite3_bind_text,
sqlite3_bind_text16,
sqlite3_bind_value,
sqlite3_busy_handler,
sqlite3_busy_timeout,
sqlite3_changes,
sqlite3_close,
sqlite3_collation_needed,
sqlite3_collation_needed16,
sqlite3_column_blob,
sqlite3_column_bytes,
sqlite3_column_bytes16,
sqlite3_column_count,
sqlite3_column_database_name,
sqlite3_column_database_name16,
sqlite3_column_decltype,
sqlite3_column_decltype16,
sqlite3_column_double,
sqlite3_column_int,
sqlite3_column_int64,
sqlite3_column_name,
sqlite3_column_name16,
sqlite3_column_origin_name,
sqlite3_column_origin_name16,
sqlite3_column_table_name,
sqlite3_column_table_name16,
sqlite3_column_text,
sqlite3_column_text16,
sqlite3_column_type,
sqlite3_column_value,
sqlite3_commit_hook,
sqlite3_complete,
sqlite3_complete16,
sqlite3_create_collation,
sqlite3_create_collation16,
sqlite3_create_function,
sqlite3_create_function16,
sqlite3_create_module,
sqlite3_data_count,
sqlite3_db_handle,
sqlite3_declare_vtab,
sqlite3_enable_shared_cache,
sqlite3_errcode,
sqlite3_errmsg,
sqlite3_errmsg16,
sqlite3_exec,
sqlite3_expired,
sqlite3_finalize,
sqlite3_free,
sqlite3_free_table,
sqlite3_get_autocommit,
sqlite3_get_auxdata,
sqlite3_get_table,
0, /* Was sqlite3_global_recover(), but that function is deprecated */
sqlite3_interrupt,
sqlite3_last_insert_rowid,
sqlite3_libversion,
sqlite3_libversion_number,
sqlite3_malloc,
sqlite3_mprintf,
sqlite3_open,
sqlite3_open16,
sqlite3_prepare,
sqlite3_prepare16,
sqlite3_profile,
sqlite3_progress_handler,
sqlite3_realloc,
sqlite3_reset,
sqlite3_result_blob,
sqlite3_result_double,
sqlite3_result_error,
sqlite3_result_error16,
sqlite3_result_int,
sqlite3_result_int64,
sqlite3_result_null,
sqlite3_result_text,
sqlite3_result_text16,
sqlite3_result_text16be,
sqlite3_result_text16le,
sqlite3_result_value,
sqlite3_rollback_hook,
sqlite3_set_authorizer,
sqlite3_set_auxdata,
sqlite3_snprintf,
sqlite3_step,
sqlite3_table_column_metadata,
sqlite3_thread_cleanup,
sqlite3_total_changes,
sqlite3_trace,
sqlite3_transfer_bindings,
sqlite3_update_hook,
sqlite3_user_data,
sqlite3_value_blob,
sqlite3_value_bytes,
sqlite3_value_bytes16,
sqlite3_value_double,
sqlite3_value_int,
sqlite3_value_int64,
sqlite3_value_numeric_type,
sqlite3_value_text,
sqlite3_value_text16,
sqlite3_value_text16be,
sqlite3_value_text16le,
sqlite3_value_type,
sqlite3_vmprintf,
/*
** The original API set ends here. All extensions can call any
** of the APIs above provided that the pointer is not NULL. But
** before calling APIs that follow, extension should check the
** sqlite3_libversion_number() to make sure they are dealing with
** a library that is new enough to support that API.
*************************************************************************
*/
sqlite3_overload_function,
};
/*
** Attempt to load an SQLite extension library contained in the file
** zFile. The entry point is zProc. zProc may be 0 in which case a
** default entry point name (sqlite3_extension_init) is used. Use
** of the default name is recommended.
**
** 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().
*/
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. Use "sqlite3_extension_init" if 0 */
char **pzErrMsg /* Put error message here if not 0 */
){
void *handle;
int (*xInit)(sqlite3*,char**,const sqlite3_api_routines*);
char *zErrmsg = 0;
void **aHandle;
/* Ticket #1863. To avoid a creating security problems for older
** applications that relink against newer versions of SQLite, the
** ability to run load_extension is turned off by default. One
** must call sqlite3_enable_load_extension() to turn on extension
** loading. Otherwise you get the following error.
*/
if( (db->flags & SQLITE_LoadExtension)==0 ){
if( pzErrMsg ){
*pzErrMsg = sqlite3_mprintf("not authorized");
}
return SQLITE_ERROR;
}
if( zProc==0 ){
zProc = "sqlite3_extension_init";
}
handle = sqlite3OsDlopen(zFile);
if( handle==0 ){
if( pzErrMsg ){
*pzErrMsg = sqlite3_mprintf("unable to open shared library [%s]", zFile);
}
return SQLITE_ERROR;
}
xInit = (int(*)(sqlite3*,char**,const sqlite3_api_routines*))
sqlite3OsDlsym(handle, zProc);
if( xInit==0 ){
if( pzErrMsg ){
*pzErrMsg = sqlite3_mprintf("no entry point [%s] in shared library [%s]",
zProc, zFile);
}
sqlite3OsDlclose(handle);
return SQLITE_ERROR;
}else if( xInit(db, &zErrmsg, &sqlite3_apis) ){
if( pzErrMsg ){
*pzErrMsg = sqlite3_mprintf("error during initialization: %s", zErrmsg);
}
sqlite3_free(zErrmsg);
sqlite3OsDlclose(handle);
return SQLITE_ERROR;
}
/* Append the new shared library handle to the db->aExtension array. */
db->nExtension++;
aHandle = sqliteMalloc(sizeof(handle)*db->nExtension);
if( aHandle==0 ){
return SQLITE_NOMEM;
}
if( db->nExtension>0 ){
memcpy(aHandle, db->aExtension, sizeof(handle)*(db->nExtension-1));
}
sqliteFree(db->aExtension);
db->aExtension = aHandle;
db->aExtension[db->nExtension-1] = handle;
return SQLITE_OK;
}
/*
** Call this routine when the database connection is closing in order
** to clean up loaded extensions
*/
void sqlite3CloseExtensions(sqlite3 *db){
int i;
for(i=0; i<db->nExtension; i++){
sqlite3OsDlclose(db->aExtension[i]);
}
sqliteFree(db->aExtension);
}
/*
** Enable or disable extension loading. Extension loading is disabled by
** default so as not to open security holes in older applications.
*/
int sqlite3_enable_load_extension(sqlite3 *db, int onoff){
if( onoff ){
db->flags |= SQLITE_LoadExtension;
}else{
db->flags &= ~SQLITE_LoadExtension;
}
return SQLITE_OK;
}
/*
** A list of automatically loaded extensions.
**
** This list is shared across threads, so be sure to hold the
** mutex while accessing or changing it.
*/
static int nAutoExtension = 0;
static void **aAutoExtension = 0;
/*
** Register a statically linked extension that is automatically
** loaded by every new database connection.
*/
int sqlite3_auto_extension(void *xInit){
int i;
int rc = SQLITE_OK;
sqlite3OsEnterMutex();
for(i=0; i<nAutoExtension; i++){
if( aAutoExtension[i]==xInit ) break;
}
if( i==nAutoExtension ){
nAutoExtension++;
aAutoExtension = sqlite3Realloc( aAutoExtension,
nAutoExtension*sizeof(aAutoExtension[0]) );
if( aAutoExtension==0 ){
nAutoExtension = 0;
rc = SQLITE_NOMEM;
}else{
aAutoExtension[nAutoExtension-1] = xInit;
}
}
sqlite3OsLeaveMutex();
assert( (rc&0xff)==rc );
return rc;
}
/*
** Reset the automatic extension loading mechanism.
*/
void sqlite3_reset_auto_extension(void){
sqlite3OsEnterMutex();
sqliteFree(aAutoExtension);
aAutoExtension = 0;
nAutoExtension = 0;
sqlite3OsLeaveMutex();
}
/*
** Load all automatic extensions.
*/
int sqlite3AutoLoadExtensions(sqlite3 *db){
int i;
int go = 1;
int rc = SQLITE_OK;
int (*xInit)(sqlite3*,char**,const sqlite3_api_routines*);
if( nAutoExtension==0 ){
/* Common case: early out without every having to acquire a mutex */
return SQLITE_OK;
}
for(i=0; go; i++){
char *zErrmsg = 0;
sqlite3OsEnterMutex();
if( i>=nAutoExtension ){
xInit = 0;
go = 0;
}else{
xInit = (int(*)(sqlite3*,char**,const sqlite3_api_routines*))
aAutoExtension[i];
}
sqlite3OsLeaveMutex();
if( xInit && xInit(db, &zErrmsg, &sqlite3_apis) ){
sqlite3Error(db, SQLITE_ERROR,
"automatic extension loading failed: %s", zErrmsg);
go = 0;
rc = SQLITE_ERROR;
}
}
return rc;
}
#endif /* SQLITE_OMIT_LOAD_EXTENSION */

File diff suppressed because it is too large Load Diff

View File

@ -1,149 +0,0 @@
/* Automatically generated. Do not edit */
/* See the mkopcodec.awk script for details. */
#if !defined(SQLITE_OMIT_EXPLAIN) || !defined(NDEBUG) || defined(VDBE_PROFILE) || defined(SQLITE_DEBUG)
const char *const sqlite3OpcodeNames[] = { "?",
/* 1 */ "MemLoad",
/* 2 */ "VNext",
/* 3 */ "Column",
/* 4 */ "SetCookie",
/* 5 */ "IfMemPos",
/* 6 */ "Sequence",
/* 7 */ "MoveGt",
/* 8 */ "RowKey",
/* 9 */ "OpenWrite",
/* 10 */ "If",
/* 11 */ "Pop",
/* 12 */ "VRowid",
/* 13 */ "CollSeq",
/* 14 */ "OpenRead",
/* 15 */ "Expire",
/* 16 */ "Not",
/* 17 */ "AutoCommit",
/* 18 */ "IntegrityCk",
/* 19 */ "Sort",
/* 20 */ "Function",
/* 21 */ "Noop",
/* 22 */ "Return",
/* 23 */ "NewRowid",
/* 24 */ "IfMemNeg",
/* 25 */ "Variable",
/* 26 */ "String",
/* 27 */ "RealAffinity",
/* 28 */ "ParseSchema",
/* 29 */ "VOpen",
/* 30 */ "Close",
/* 31 */ "CreateIndex",
/* 32 */ "IsUnique",
/* 33 */ "NotFound",
/* 34 */ "Int64",
/* 35 */ "MustBeInt",
/* 36 */ "Halt",
/* 37 */ "Rowid",
/* 38 */ "IdxLT",
/* 39 */ "AddImm",
/* 40 */ "Statement",
/* 41 */ "RowData",
/* 42 */ "MemMax",
/* 43 */ "Push",
/* 44 */ "NotExists",
/* 45 */ "MemIncr",
/* 46 */ "Gosub",
/* 47 */ "Integer",
/* 48 */ "MemInt",
/* 49 */ "Prev",
/* 50 */ "VColumn",
/* 51 */ "CreateTable",
/* 52 */ "Last",
/* 53 */ "IdxRowid",
/* 54 */ "MakeIdxRec",
/* 55 */ "ResetCount",
/* 56 */ "FifoWrite",
/* 57 */ "Callback",
/* 58 */ "ContextPush",
/* 59 */ "DropTrigger",
/* 60 */ "DropIndex",
/* 61 */ "Or",
/* 62 */ "And",
/* 63 */ "IdxGE",
/* 64 */ "IdxDelete",
/* 65 */ "Vacuum",
/* 66 */ "IsNull",
/* 67 */ "NotNull",
/* 68 */ "Ne",
/* 69 */ "Eq",
/* 70 */ "Gt",
/* 71 */ "Le",
/* 72 */ "Lt",
/* 73 */ "Ge",
/* 74 */ "MoveLe",
/* 75 */ "BitAnd",
/* 76 */ "BitOr",
/* 77 */ "ShiftLeft",
/* 78 */ "ShiftRight",
/* 79 */ "Add",
/* 80 */ "Subtract",
/* 81 */ "Multiply",
/* 82 */ "Divide",
/* 83 */ "Remainder",
/* 84 */ "Concat",
/* 85 */ "IfNot",
/* 86 */ "Negative",
/* 87 */ "DropTable",
/* 88 */ "BitNot",
/* 89 */ "String8",
/* 90 */ "MakeRecord",
/* 91 */ "Delete",
/* 92 */ "AggFinal",
/* 93 */ "Dup",
/* 94 */ "Goto",
/* 95 */ "TableLock",
/* 96 */ "FifoRead",
/* 97 */ "Clear",
/* 98 */ "IdxGT",
/* 99 */ "MoveLt",
/* 100 */ "VerifyCookie",
/* 101 */ "AggStep",
/* 102 */ "Pull",
/* 103 */ "SetNumColumns",
/* 104 */ "AbsValue",
/* 105 */ "Transaction",
/* 106 */ "VFilter",
/* 107 */ "VDestroy",
/* 108 */ "ContextPop",
/* 109 */ "Next",
/* 110 */ "IdxInsert",
/* 111 */ "Distinct",
/* 112 */ "Insert",
/* 113 */ "Destroy",
/* 114 */ "ReadCookie",
/* 115 */ "ForceInt",
/* 116 */ "LoadAnalysis",
/* 117 */ "Explain",
/* 118 */ "IfMemZero",
/* 119 */ "OpenPseudo",
/* 120 */ "OpenEphemeral",
/* 121 */ "Null",
/* 122 */ "Blob",
/* 123 */ "MemStore",
/* 124 */ "Rewind",
/* 125 */ "MoveGe",
/* 126 */ "Real",
/* 127 */ "HexBlob",
/* 128 */ "VBegin",
/* 129 */ "VUpdate",
/* 130 */ "VCreate",
/* 131 */ "MemMove",
/* 132 */ "MemNull",
/* 133 */ "Found",
/* 134 */ "NullRow",
/* 135 */ "NotUsed_135",
/* 136 */ "NotUsed_136",
/* 137 */ "NotUsed_137",
/* 138 */ "NotUsed_138",
/* 139 */ "ToText",
/* 140 */ "ToBlob",
/* 141 */ "ToNumeric",
/* 142 */ "ToInt",
/* 143 */ "ToReal",
};
#endif

View File

@ -1,161 +0,0 @@
/* Automatically generated. Do not edit */
/* See the mkopcodeh.awk script for details */
#define OP_MemLoad 1
#define OP_VNext 2
#define OP_HexBlob 127 /* same as TK_BLOB */
#define OP_Column 3
#define OP_SetCookie 4
#define OP_IfMemPos 5
#define OP_Real 126 /* same as TK_FLOAT */
#define OP_Sequence 6
#define OP_MoveGt 7
#define OP_Ge 73 /* same as TK_GE */
#define OP_RowKey 8
#define OP_Eq 69 /* same as TK_EQ */
#define OP_OpenWrite 9
#define OP_NotNull 67 /* same as TK_NOTNULL */
#define OP_If 10
#define OP_ToInt 142 /* same as TK_TO_INT */
#define OP_String8 89 /* same as TK_STRING */
#define OP_Pop 11
#define OP_VRowid 12
#define OP_CollSeq 13
#define OP_OpenRead 14
#define OP_Expire 15
#define OP_AutoCommit 17
#define OP_Gt 70 /* same as TK_GT */
#define OP_IntegrityCk 18
#define OP_Sort 19
#define OP_Function 20
#define OP_And 62 /* same as TK_AND */
#define OP_Subtract 80 /* same as TK_MINUS */
#define OP_Noop 21
#define OP_Return 22
#define OP_Remainder 83 /* same as TK_REM */
#define OP_NewRowid 23
#define OP_Multiply 81 /* same as TK_STAR */
#define OP_IfMemNeg 24
#define OP_Variable 25
#define OP_String 26
#define OP_RealAffinity 27
#define OP_ParseSchema 28
#define OP_VOpen 29
#define OP_Close 30
#define OP_CreateIndex 31
#define OP_IsUnique 32
#define OP_NotFound 33
#define OP_Int64 34
#define OP_MustBeInt 35
#define OP_Halt 36
#define OP_Rowid 37
#define OP_IdxLT 38
#define OP_AddImm 39
#define OP_Statement 40
#define OP_RowData 41
#define OP_MemMax 42
#define OP_Push 43
#define OP_Or 61 /* same as TK_OR */
#define OP_NotExists 44
#define OP_MemIncr 45
#define OP_Gosub 46
#define OP_Divide 82 /* same as TK_SLASH */
#define OP_Integer 47
#define OP_ToNumeric 141 /* same as TK_TO_NUMERIC*/
#define OP_MemInt 48
#define OP_Prev 49
#define OP_Concat 84 /* same as TK_CONCAT */
#define OP_BitAnd 75 /* same as TK_BITAND */
#define OP_VColumn 50
#define OP_CreateTable 51
#define OP_Last 52
#define OP_IsNull 66 /* same as TK_ISNULL */
#define OP_IdxRowid 53
#define OP_MakeIdxRec 54
#define OP_ShiftRight 78 /* same as TK_RSHIFT */
#define OP_ResetCount 55
#define OP_FifoWrite 56
#define OP_Callback 57
#define OP_ContextPush 58
#define OP_DropTrigger 59
#define OP_DropIndex 60
#define OP_IdxGE 63
#define OP_IdxDelete 64
#define OP_Vacuum 65
#define OP_MoveLe 74
#define OP_IfNot 85
#define OP_DropTable 87
#define OP_MakeRecord 90
#define OP_ToBlob 140 /* same as TK_TO_BLOB */
#define OP_Delete 91
#define OP_AggFinal 92
#define OP_ShiftLeft 77 /* same as TK_LSHIFT */
#define OP_Dup 93
#define OP_Goto 94
#define OP_TableLock 95
#define OP_FifoRead 96
#define OP_Clear 97
#define OP_IdxGT 98
#define OP_MoveLt 99
#define OP_Le 71 /* same as TK_LE */
#define OP_VerifyCookie 100
#define OP_AggStep 101
#define OP_Pull 102
#define OP_ToText 139 /* same as TK_TO_TEXT */
#define OP_Not 16 /* same as TK_NOT */
#define OP_ToReal 143 /* same as TK_TO_REAL */
#define OP_SetNumColumns 103
#define OP_AbsValue 104
#define OP_Transaction 105
#define OP_VFilter 106
#define OP_Negative 86 /* same as TK_UMINUS */
#define OP_Ne 68 /* same as TK_NE */
#define OP_VDestroy 107
#define OP_ContextPop 108
#define OP_BitOr 76 /* same as TK_BITOR */
#define OP_Next 109
#define OP_IdxInsert 110
#define OP_Distinct 111
#define OP_Lt 72 /* same as TK_LT */
#define OP_Insert 112
#define OP_Destroy 113
#define OP_ReadCookie 114
#define OP_ForceInt 115
#define OP_LoadAnalysis 116
#define OP_Explain 117
#define OP_IfMemZero 118
#define OP_OpenPseudo 119
#define OP_OpenEphemeral 120
#define OP_Null 121
#define OP_Blob 122
#define OP_Add 79 /* same as TK_PLUS */
#define OP_MemStore 123
#define OP_Rewind 124
#define OP_MoveGe 125
#define OP_VBegin 128
#define OP_VUpdate 129
#define OP_BitNot 88 /* same as TK_BITNOT */
#define OP_VCreate 130
#define OP_MemMove 131
#define OP_MemNull 132
#define OP_Found 133
#define OP_NullRow 134
/* The following opcode values are never used */
#define OP_NotUsed_135 135
#define OP_NotUsed_136 136
#define OP_NotUsed_137 137
#define OP_NotUsed_138 138
/* Opcodes that are guaranteed to never push a value onto the stack
** contain a 1 their corresponding position of the following mask
** set. See the opcodeNoPush() function in vdbeaux.c */
#define NOPUSH_MASK_0 0xeeb4
#define NOPUSH_MASK_1 0x796b
#define NOPUSH_MASK_2 0x7ddb
#define NOPUSH_MASK_3 0xff92
#define NOPUSH_MASK_4 0xffff
#define NOPUSH_MASK_5 0xd9ef
#define NOPUSH_MASK_6 0xfefe
#define NOPUSH_MASK_7 0x39d9
#define NOPUSH_MASK_8 0xf867
#define NOPUSH_MASK_9 0x0000

View File

@ -1,92 +0,0 @@
/*
** 2005 November 29
**
** 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 OS interface code that is common to all
** architectures.
*/
#define _SQLITE_OS_C_ 1
#include "sqliteInt.h"
#include "os.h"
/*
** The following routines are convenience wrappers around methods
** of the OsFile object. This is mostly just syntactic sugar. All
** of this would be completely automatic if SQLite were coded using
** C++ instead of plain old C.
*/
int sqlite3OsClose(OsFile **pId){
OsFile *id;
if( pId!=0 && (id = *pId)!=0 ){
return id->pMethod->xClose(pId);
}else{
return SQLITE_OK;
}
}
int sqlite3OsOpenDirectory(OsFile *id, const char *zName){
return id->pMethod->xOpenDirectory(id, zName);
}
int sqlite3OsRead(OsFile *id, void *pBuf, int amt){
return id->pMethod->xRead(id, pBuf, amt);
}
int sqlite3OsWrite(OsFile *id, const void *pBuf, int amt){
return id->pMethod->xWrite(id, pBuf, amt);
}
int sqlite3OsSeek(OsFile *id, i64 offset){
return id->pMethod->xSeek(id, offset);
}
int sqlite3OsTruncate(OsFile *id, i64 size){
return id->pMethod->xTruncate(id, size);
}
int sqlite3OsSync(OsFile *id, int fullsync){
return id->pMethod->xSync(id, fullsync);
}
void sqlite3OsSetFullSync(OsFile *id, int value){
id->pMethod->xSetFullSync(id, value);
}
#if defined(SQLITE_TEST) || defined(SQLITE_DEBUG)
/* This method is currently only used while interactively debugging the
** pager. More specificly, it can only be used when sqlite3DebugPrintf() is
** included in the build. */
int sqlite3OsFileHandle(OsFile *id){
return id->pMethod->xFileHandle(id);
}
#endif
int sqlite3OsFileSize(OsFile *id, i64 *pSize){
return id->pMethod->xFileSize(id, pSize);
}
int sqlite3OsLock(OsFile *id, int lockType){
return id->pMethod->xLock(id, lockType);
}
int sqlite3OsUnlock(OsFile *id, int lockType){
return id->pMethod->xUnlock(id, lockType);
}
int sqlite3OsLockState(OsFile *id){
return id->pMethod->xLockState(id);
}
int sqlite3OsCheckReservedLock(OsFile *id){
return id->pMethod->xCheckReservedLock(id);
}
#ifdef SQLITE_ENABLE_REDEF_IO
/*
** A function to return a pointer to the virtual function table.
** This routine really does not accomplish very much since the
** virtual function table is a global variable and anybody who
** can call this function can just as easily access the variable
** for themselves. Nevertheless, we include this routine for
** backwards compatibility with an earlier redefinable I/O
** interface design.
*/
struct sqlite3OsVtbl *sqlite3_os_switch(void){
return &sqlite3Os;
}
#endif

View File

@ -1,517 +0,0 @@
/*
** 2001 September 16
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
******************************************************************************
**
** This header file (together with is companion C source-code file
** "os.c") attempt to abstract the underlying operating system so that
** the SQLite library will work on both POSIX and windows systems.
*/
#ifndef _SQLITE_OS_H_
#define _SQLITE_OS_H_
/*
** Figure out if we are dealing with Unix, Windows, or some other
** operating system.
*/
#if !defined(OS_UNIX) && !defined(OS_OTHER)
# define OS_OTHER 0
# ifndef OS_WIN
# if defined(_WIN32) || defined(WIN32) || defined(__CYGWIN__) || defined(__MINGW32__) || defined(__BORLANDC__)
# define OS_WIN 1
# define OS_UNIX 0
# define OS_OS2 0
# elif defined(_EMX_) || defined(_OS2) || defined(OS2) || defined(_OS2_) || defined(__OS2__)
# define OS_WIN 0
# define OS_UNIX 0
# define OS_OS2 1
# else
# define OS_WIN 0
# define OS_UNIX 1
# define OS_OS2 0
# endif
# else
# define OS_UNIX 0
# define OS_OS2 0
# endif
#else
# ifndef OS_WIN
# define OS_WIN 0
# endif
#endif
/*
** Define the maximum size of a temporary filename
*/
#if OS_WIN
# include <windows.h>
# define SQLITE_TEMPNAME_SIZE (MAX_PATH+50)
#elif OS_OS2
# define INCL_DOSDATETIME
# define INCL_DOSFILEMGR
# define INCL_DOSERRORS
# define INCL_DOSMISC
# define INCL_DOSPROCESS
# include <os2.h>
# define SQLITE_TEMPNAME_SIZE (CCHMAXPATHCOMP)
#else
# define SQLITE_TEMPNAME_SIZE 200
#endif
/* If the SET_FULLSYNC macro is not defined above, then make it
** a no-op
*/
#ifndef SET_FULLSYNC
# define SET_FULLSYNC(x,y)
#endif
/*
** Temporary files are named starting with this prefix followed by 16 random
** alphanumeric characters, and no file extension. They are stored in the
** OS's standard temporary file directory, and are deleted prior to exit.
** If sqlite is being embedded in another program, you may wish to change the
** prefix to reflect your program's name, so that if your program exits
** prematurely, old temporary files can be easily identified. This can be done
** using -DTEMP_FILE_PREFIX=myprefix_ on the compiler command line.
**
** 2006-10-31: The default prefix used to be "sqlite_". But then
** Mcafee started using SQLite in their anti-virus product and it
** started putting files with the "sqlite" name in the c:/temp folder.
** This annoyed many windows users. Those users would then do a
** Google search for "sqlite", find the telephone numbers of the
** developers and call to wake them up at night and complain.
** For this reason, the default name prefix is changed to be "sqlite"
** spelled backwards. So the temp files are still identified, but
** anybody smart enough to figure out the code is also likely smart
** enough to know that calling the developer will not help get rid
** of the file.
*/
#ifndef TEMP_FILE_PREFIX
# define TEMP_FILE_PREFIX "etilqs_"
#endif
/*
** Define the interfaces for Unix, Windows, and OS/2.
*/
#if OS_UNIX
#define sqlite3OsOpenReadWrite sqlite3UnixOpenReadWrite
#define sqlite3OsOpenExclusive sqlite3UnixOpenExclusive
#define sqlite3OsOpenReadOnly sqlite3UnixOpenReadOnly
#define sqlite3OsDelete sqlite3UnixDelete
#define sqlite3OsFileExists sqlite3UnixFileExists
#define sqlite3OsFullPathname sqlite3UnixFullPathname
#define sqlite3OsIsDirWritable sqlite3UnixIsDirWritable
#define sqlite3OsSyncDirectory sqlite3UnixSyncDirectory
#define sqlite3OsTempFileName sqlite3UnixTempFileName
#define sqlite3OsRandomSeed sqlite3UnixRandomSeed
#define sqlite3OsSleep sqlite3UnixSleep
#define sqlite3OsCurrentTime sqlite3UnixCurrentTime
#define sqlite3OsEnterMutex sqlite3UnixEnterMutex
#define sqlite3OsLeaveMutex sqlite3UnixLeaveMutex
#define sqlite3OsInMutex sqlite3UnixInMutex
#define sqlite3OsThreadSpecificData sqlite3UnixThreadSpecificData
#define sqlite3OsMalloc sqlite3GenericMalloc
#define sqlite3OsRealloc sqlite3GenericRealloc
#define sqlite3OsFree sqlite3GenericFree
#define sqlite3OsAllocationSize sqlite3GenericAllocationSize
#define sqlite3OsDlopen sqlite3UnixDlopen
#define sqlite3OsDlsym sqlite3UnixDlsym
#define sqlite3OsDlclose sqlite3UnixDlclose
#endif
#if OS_WIN
#define sqlite3OsOpenReadWrite sqlite3WinOpenReadWrite
#define sqlite3OsOpenExclusive sqlite3WinOpenExclusive
#define sqlite3OsOpenReadOnly sqlite3WinOpenReadOnly
#define sqlite3OsDelete sqlite3WinDelete
#define sqlite3OsFileExists sqlite3WinFileExists
#define sqlite3OsFullPathname sqlite3WinFullPathname
#define sqlite3OsIsDirWritable sqlite3WinIsDirWritable
#define sqlite3OsSyncDirectory sqlite3WinSyncDirectory
#define sqlite3OsTempFileName sqlite3WinTempFileName
#define sqlite3OsRandomSeed sqlite3WinRandomSeed
#define sqlite3OsSleep sqlite3WinSleep
#define sqlite3OsCurrentTime sqlite3WinCurrentTime
#define sqlite3OsEnterMutex sqlite3WinEnterMutex
#define sqlite3OsLeaveMutex sqlite3WinLeaveMutex
#define sqlite3OsInMutex sqlite3WinInMutex
#define sqlite3OsThreadSpecificData sqlite3WinThreadSpecificData
#define sqlite3OsMalloc sqlite3GenericMalloc
#define sqlite3OsRealloc sqlite3GenericRealloc
#define sqlite3OsFree sqlite3GenericFree
#define sqlite3OsAllocationSize sqlite3GenericAllocationSize
#define sqlite3OsDlopen sqlite3WinDlopen
#define sqlite3OsDlsym sqlite3WinDlsym
#define sqlite3OsDlclose sqlite3WinDlclose
#endif
#if OS_OS2
#define sqlite3OsOpenReadWrite sqlite3Os2OpenReadWrite
#define sqlite3OsOpenExclusive sqlite3Os2OpenExclusive
#define sqlite3OsOpenReadOnly sqlite3Os2OpenReadOnly
#define sqlite3OsDelete sqlite3Os2Delete
#define sqlite3OsFileExists sqlite3Os2FileExists
#define sqlite3OsFullPathname sqlite3Os2FullPathname
#define sqlite3OsIsDirWritable sqlite3Os2IsDirWritable
#define sqlite3OsSyncDirectory sqlite3Os2SyncDirectory
#define sqlite3OsTempFileName sqlite3Os2TempFileName
#define sqlite3OsRandomSeed sqlite3Os2RandomSeed
#define sqlite3OsSleep sqlite3Os2Sleep
#define sqlite3OsCurrentTime sqlite3Os2CurrentTime
#define sqlite3OsEnterMutex sqlite3Os2EnterMutex
#define sqlite3OsLeaveMutex sqlite3Os2LeaveMutex
#define sqlite3OsInMutex sqlite3Os2InMutex
#define sqlite3OsThreadSpecificData sqlite3Os2ThreadSpecificData
#define sqlite3OsMalloc sqlite3GenericMalloc
#define sqlite3OsRealloc sqlite3GenericRealloc
#define sqlite3OsFree sqlite3GenericFree
#define sqlite3OsAllocationSize sqlite3GenericAllocationSize
#define sqlite3OsDlopen sqlite3Os2Dlopen
#define sqlite3OsDlsym sqlite3Os2Dlsym
#define sqlite3OsDlclose sqlite3Os2Dlclose
#endif
/*
** If using an alternative OS interface, then we must have an "os_other.h"
** header file available for that interface. Presumably the "os_other.h"
** header file contains #defines similar to those above.
*/
#if OS_OTHER
# include "os_other.h"
#endif
/*
** Forward declarations
*/
typedef struct OsFile OsFile;
typedef struct IoMethod IoMethod;
/*
** An instance of the following structure contains pointers to all
** methods on an OsFile object.
*/
struct IoMethod {
int (*xClose)(OsFile**);
int (*xOpenDirectory)(OsFile*, const char*);
int (*xRead)(OsFile*, void*, int amt);
int (*xWrite)(OsFile*, const void*, int amt);
int (*xSeek)(OsFile*, i64 offset);
int (*xTruncate)(OsFile*, i64 size);
int (*xSync)(OsFile*, int);
void (*xSetFullSync)(OsFile *id, int setting);
int (*xFileHandle)(OsFile *id);
int (*xFileSize)(OsFile*, i64 *pSize);
int (*xLock)(OsFile*, int);
int (*xUnlock)(OsFile*, int);
int (*xLockState)(OsFile *id);
int (*xCheckReservedLock)(OsFile *id);
};
/*
** The OsFile object describes an open disk file in an OS-dependent way.
** The version of OsFile defined here is a generic version. Each OS
** implementation defines its own subclass of this structure that contains
** additional information needed to handle file I/O. But the pMethod
** entry (pointing to the virtual function table) always occurs first
** so that we can always find the appropriate methods.
*/
struct OsFile {
IoMethod const *pMethod;
};
/*
** The following values may be passed as the second argument to
** sqlite3OsLock(). The various locks exhibit the following semantics:
**
** SHARED: Any number of processes may hold a SHARED lock simultaneously.
** RESERVED: A single process may hold a RESERVED lock on a file at
** any time. Other processes may hold and obtain new SHARED locks.
** PENDING: A single process may hold a PENDING lock on a file at
** any one time. Existing SHARED locks may persist, but no new
** SHARED locks may be obtained by other processes.
** EXCLUSIVE: An EXCLUSIVE lock precludes all other locks.
**
** PENDING_LOCK may not be passed directly to sqlite3OsLock(). Instead, a
** process that requests an EXCLUSIVE lock may actually obtain a PENDING
** lock. This can be upgraded to an EXCLUSIVE lock by a subsequent call to
** sqlite3OsLock().
*/
#define NO_LOCK 0
#define SHARED_LOCK 1
#define RESERVED_LOCK 2
#define PENDING_LOCK 3
#define EXCLUSIVE_LOCK 4
/*
** File Locking Notes: (Mostly about windows but also some info for Unix)
**
** We cannot use LockFileEx() or UnlockFileEx() on Win95/98/ME because
** those functions are not available. So we use only LockFile() and
** UnlockFile().
**
** LockFile() prevents not just writing but also reading by other processes.
** A SHARED_LOCK is obtained by locking a single randomly-chosen
** byte out of a specific range of bytes. The lock byte is obtained at
** random so two separate readers can probably access the file at the
** same time, unless they are unlucky and choose the same lock byte.
** An EXCLUSIVE_LOCK is obtained by locking all bytes in the range.
** There can only be one writer. A RESERVED_LOCK is obtained by locking
** a single byte of the file that is designated as the reserved lock byte.
** A PENDING_LOCK is obtained by locking a designated byte different from
** the RESERVED_LOCK byte.
**
** On WinNT/2K/XP systems, LockFileEx() and UnlockFileEx() are available,
** which means we can use reader/writer locks. When reader/writer locks
** are used, the lock is placed on the same range of bytes that is used
** for probabilistic locking in Win95/98/ME. Hence, the locking scheme
** will support two or more Win95 readers or two or more WinNT readers.
** But a single Win95 reader will lock out all WinNT readers and a single
** WinNT reader will lock out all other Win95 readers.
**
** The following #defines specify the range of bytes used for locking.
** SHARED_SIZE is the number of bytes available in the pool from which
** a random byte is selected for a shared lock. The pool of bytes for
** shared locks begins at SHARED_FIRST.
**
** These #defines are available in sqlite_aux.h so that adaptors for
** connecting SQLite to other operating systems can use the same byte
** ranges for locking. In particular, the same locking strategy and
** byte ranges are used for Unix. This leaves open the possiblity of having
** clients on win95, winNT, and unix all talking to the same shared file
** and all locking correctly. To do so would require that samba (or whatever
** tool is being used for file sharing) implements locks correctly between
** windows and unix. I'm guessing that isn't likely to happen, but by
** using the same locking range we are at least open to the possibility.
**
** Locking in windows is manditory. For this reason, we cannot store
** actual data in the bytes used for locking. The pager never allocates
** the pages involved in locking therefore. SHARED_SIZE is selected so
** that all locks will fit on a single page even at the minimum page size.
** PENDING_BYTE defines the beginning of the locks. By default PENDING_BYTE
** is set high so that we don't have to allocate an unused page except
** for very large databases. But one should test the page skipping logic
** by setting PENDING_BYTE low and running the entire regression suite.
**
** Changing the value of PENDING_BYTE results in a subtly incompatible
** file format. Depending on how it is changed, you might not notice
** the incompatibility right away, even running a full regression test.
** The default location of PENDING_BYTE is the first byte past the
** 1GB boundary.
**
*/
#ifndef SQLITE_TEST
#define PENDING_BYTE 0x40000000 /* First byte past the 1GB boundary */
#else
extern unsigned int sqlite3_pending_byte;
#define PENDING_BYTE sqlite3_pending_byte
#endif
#define RESERVED_BYTE (PENDING_BYTE+1)
#define SHARED_FIRST (PENDING_BYTE+2)
#define SHARED_SIZE 510
/*
** Prototypes for operating system interface routines.
*/
int sqlite3OsClose(OsFile**);
int sqlite3OsOpenDirectory(OsFile*, const char*);
int sqlite3OsRead(OsFile*, void*, int amt);
int sqlite3OsWrite(OsFile*, const void*, int amt);
int sqlite3OsSeek(OsFile*, i64 offset);
int sqlite3OsTruncate(OsFile*, i64 size);
int sqlite3OsSync(OsFile*, int);
void sqlite3OsSetFullSync(OsFile *id, int setting);
int sqlite3OsFileHandle(OsFile *id);
int sqlite3OsFileSize(OsFile*, i64 *pSize);
int sqlite3OsLock(OsFile*, int);
int sqlite3OsUnlock(OsFile*, int);
int sqlite3OsLockState(OsFile *id);
int sqlite3OsCheckReservedLock(OsFile *id);
int sqlite3OsOpenReadWrite(const char*, OsFile**, int*);
int sqlite3OsOpenExclusive(const char*, OsFile**, int);
int sqlite3OsOpenReadOnly(const char*, OsFile**);
int sqlite3OsDelete(const char*);
int sqlite3OsFileExists(const char*);
char *sqlite3OsFullPathname(const char*);
int sqlite3OsIsDirWritable(char*);
int sqlite3OsSyncDirectory(const char*);
int sqlite3OsTempFileName(char*);
int sqlite3OsRandomSeed(char*);
int sqlite3OsSleep(int ms);
int sqlite3OsCurrentTime(double*);
void sqlite3OsEnterMutex(void);
void sqlite3OsLeaveMutex(void);
int sqlite3OsInMutex(int);
ThreadData *sqlite3OsThreadSpecificData(int);
void *sqlite3OsMalloc(int);
void *sqlite3OsRealloc(void *, int);
void sqlite3OsFree(void *);
int sqlite3OsAllocationSize(void *);
void *sqlite3OsDlopen(const char*);
void *sqlite3OsDlsym(void*, const char*);
int sqlite3OsDlclose(void*);
/*
** If the SQLITE_ENABLE_REDEF_IO macro is defined, then the OS-layer
** interface routines are not called directly but are invoked using
** pointers to functions. This allows the implementation of various
** OS-layer interface routines to be modified at run-time. There are
** obscure but legitimate reasons for wanting to do this. But for
** most users, a direct call to the underlying interface is preferable
** so the the redefinable I/O interface is turned off by default.
*/
#ifdef SQLITE_ENABLE_REDEF_IO
/*
** When redefinable I/O is enabled, a single global instance of the
** following structure holds pointers to the routines that SQLite
** uses to talk with the underlying operating system. Modify this
** structure (before using any SQLite API!) to accomodate perculiar
** operating system interfaces or behaviors.
*/
struct sqlite3OsVtbl {
int (*xOpenReadWrite)(const char*, OsFile**, int*);
int (*xOpenExclusive)(const char*, OsFile**, int);
int (*xOpenReadOnly)(const char*, OsFile**);
int (*xDelete)(const char*);
int (*xFileExists)(const char*);
char *(*xFullPathname)(const char*);
int (*xIsDirWritable)(char*);
int (*xSyncDirectory)(const char*);
int (*xTempFileName)(char*);
int (*xRandomSeed)(char*);
int (*xSleep)(int ms);
int (*xCurrentTime)(double*);
void (*xEnterMutex)(void);
void (*xLeaveMutex)(void);
int (*xInMutex)(int);
ThreadData *(*xThreadSpecificData)(int);
void *(*xMalloc)(int);
void *(*xRealloc)(void *, int);
void (*xFree)(void *);
int (*xAllocationSize)(void *);
void *(*xDlopen)(const char*);
void *(*xDlsym)(void*, const char*);
int (*xDlclose)(void*);
};
/* Macro used to comment out routines that do not exists when there is
** no disk I/O or extension loading
*/
#ifdef SQLITE_OMIT_DISKIO
# define IF_DISKIO(X) 0
#else
# define IF_DISKIO(X) X
#endif
#ifdef SQLITE_OMIT_LOAD_EXTENSION
# define IF_DLOPEN(X) 0
#else
# define IF_DLOPEN(X) X
#endif
#ifdef _SQLITE_OS_C_
/*
** The os.c file implements the global virtual function table.
*/
struct sqlite3OsVtbl sqlite3Os = {
IF_DISKIO( sqlite3OsOpenReadWrite ),
IF_DISKIO( sqlite3OsOpenExclusive ),
IF_DISKIO( sqlite3OsOpenReadOnly ),
IF_DISKIO( sqlite3OsDelete ),
IF_DISKIO( sqlite3OsFileExists ),
IF_DISKIO( sqlite3OsFullPathname ),
IF_DISKIO( sqlite3OsIsDirWritable ),
IF_DISKIO( sqlite3OsSyncDirectory ),
IF_DISKIO( sqlite3OsTempFileName ),
sqlite3OsRandomSeed,
sqlite3OsSleep,
sqlite3OsCurrentTime,
sqlite3OsEnterMutex,
sqlite3OsLeaveMutex,
sqlite3OsInMutex,
sqlite3OsThreadSpecificData,
sqlite3OsMalloc,
sqlite3OsRealloc,
sqlite3OsFree,
sqlite3OsAllocationSize,
IF_DLOPEN( sqlite3OsDlopen ),
IF_DLOPEN( sqlite3OsDlsym ),
IF_DLOPEN( sqlite3OsDlclose ),
};
#else
/*
** Files other than os.c just reference the global virtual function table.
*/
extern struct sqlite3OsVtbl sqlite3Os;
#endif /* _SQLITE_OS_C_ */
/* This additional API routine is available with redefinable I/O */
struct sqlite3OsVtbl *sqlite3_os_switch(void);
/*
** Redefine the OS interface to go through the virtual function table
** rather than calling routines directly.
*/
#undef sqlite3OsOpenReadWrite
#undef sqlite3OsOpenExclusive
#undef sqlite3OsOpenReadOnly
#undef sqlite3OsDelete
#undef sqlite3OsFileExists
#undef sqlite3OsFullPathname
#undef sqlite3OsIsDirWritable
#undef sqlite3OsSyncDirectory
#undef sqlite3OsTempFileName
#undef sqlite3OsRandomSeed
#undef sqlite3OsSleep
#undef sqlite3OsCurrentTime
#undef sqlite3OsEnterMutex
#undef sqlite3OsLeaveMutex
#undef sqlite3OsInMutex
#undef sqlite3OsThreadSpecificData
#undef sqlite3OsMalloc
#undef sqlite3OsRealloc
#undef sqlite3OsFree
#undef sqlite3OsAllocationSize
#define sqlite3OsOpenReadWrite sqlite3Os.xOpenReadWrite
#define sqlite3OsOpenExclusive sqlite3Os.xOpenExclusive
#define sqlite3OsOpenReadOnly sqlite3Os.xOpenReadOnly
#define sqlite3OsDelete sqlite3Os.xDelete
#define sqlite3OsFileExists sqlite3Os.xFileExists
#define sqlite3OsFullPathname sqlite3Os.xFullPathname
#define sqlite3OsIsDirWritable sqlite3Os.xIsDirWritable
#define sqlite3OsSyncDirectory sqlite3Os.xSyncDirectory
#define sqlite3OsTempFileName sqlite3Os.xTempFileName
#define sqlite3OsRandomSeed sqlite3Os.xRandomSeed
#define sqlite3OsSleep sqlite3Os.xSleep
#define sqlite3OsCurrentTime sqlite3Os.xCurrentTime
#define sqlite3OsEnterMutex sqlite3Os.xEnterMutex
#define sqlite3OsLeaveMutex sqlite3Os.xLeaveMutex
#define sqlite3OsInMutex sqlite3Os.xInMutex
#define sqlite3OsThreadSpecificData sqlite3Os.xThreadSpecificData
#define sqlite3OsMalloc sqlite3Os.xMalloc
#define sqlite3OsRealloc sqlite3Os.xRealloc
#define sqlite3OsFree sqlite3Os.xFree
#define sqlite3OsAllocationSize sqlite3Os.xAllocationSize
#endif /* SQLITE_ENABLE_REDEF_IO */
#endif /* _SQLITE_OS_H_ */

View File

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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,123 +0,0 @@
/*
** 2001 September 15
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
** This header file defines the interface that the sqlite page cache
** subsystem. The page cache subsystem reads and writes a file a page
** at a time and provides a journal for rollback.
**
** @(#) $Id: pager.h 3426 2007-03-21 20:19:37Z damagedsoul $
*/
#ifndef _PAGER_H_
#define _PAGER_H_
/*
** The default size of a database page.
*/
#ifndef SQLITE_DEFAULT_PAGE_SIZE
# define SQLITE_DEFAULT_PAGE_SIZE 1024
#endif
/* Maximum page size. The upper bound on this value is 32768. This a limit
** imposed by necessity of storing the value in a 2-byte unsigned integer
** and the fact that the page size must be a power of 2.
**
** This value is used to initialize certain arrays on the stack at
** various places in the code. On embedded machines where stack space
** is limited and the flexibility of having large pages is not needed,
** it makes good sense to reduce the maximum page size to something more
** reasonable, like 1024.
*/
#ifndef SQLITE_MAX_PAGE_SIZE
# define SQLITE_MAX_PAGE_SIZE 32768
#endif
/*
** Maximum number of pages in one database.
*/
#define SQLITE_MAX_PAGE 1073741823
/*
** The type used to represent a page number. The first page in a file
** is called page 1. 0 is used to represent "not a page".
*/
typedef unsigned int Pgno;
/*
** Each open file is managed by a separate instance of the "Pager" structure.
*/
typedef struct Pager Pager;
/*
** Allowed values for the flags parameter to sqlite3pager_open().
**
** NOTE: This values must match the corresponding BTREE_ values in btree.h.
*/
#define PAGER_OMIT_JOURNAL 0x0001 /* Do not use a rollback journal */
#define PAGER_NO_READLOCK 0x0002 /* Omit readlocks on readonly files */
/*
** See source code comments for a detailed description of the following
** routines:
*/
int sqlite3pager_open(Pager **ppPager, const char *zFilename,
int nExtra, int flags);
void sqlite3pager_set_busyhandler(Pager*, BusyHandler *pBusyHandler);
void sqlite3pager_set_destructor(Pager*, void(*)(void*,int));
void sqlite3pager_set_reiniter(Pager*, void(*)(void*,int));
int sqlite3pager_set_pagesize(Pager*, int);
int sqlite3pager_read_fileheader(Pager*, int, unsigned char*);
void sqlite3pager_set_cachesize(Pager*, int);
int sqlite3pager_close(Pager *pPager);
int sqlite3pager_get(Pager *pPager, Pgno pgno, void **ppPage);
void *sqlite3pager_lookup(Pager *pPager, Pgno pgno);
int sqlite3pager_ref(void*);
int sqlite3pager_unref(void*);
Pgno sqlite3pager_pagenumber(void*);
int sqlite3pager_write(void*);
int sqlite3pager_iswriteable(void*);
int sqlite3pager_overwrite(Pager *pPager, Pgno pgno, void*);
int sqlite3pager_pagecount(Pager*);
int sqlite3pager_truncate(Pager*,Pgno);
int sqlite3pager_begin(void*, int exFlag);
int sqlite3pager_commit(Pager*);
int sqlite3pager_sync(Pager*,const char *zMaster, Pgno);
int sqlite3pager_rollback(Pager*);
int sqlite3pager_isreadonly(Pager*);
int sqlite3pager_stmt_begin(Pager*);
int sqlite3pager_stmt_commit(Pager*);
int sqlite3pager_stmt_rollback(Pager*);
void sqlite3pager_dont_rollback(void*);
void sqlite3pager_dont_write(Pager*, Pgno);
int sqlite3pager_refcount(Pager*);
int *sqlite3pager_stats(Pager*);
void sqlite3pager_set_safety_level(Pager*,int,int);
const char *sqlite3pager_filename(Pager*);
const char *sqlite3pager_dirname(Pager*);
const char *sqlite3pager_journalname(Pager*);
int sqlite3pager_nosync(Pager*);
int sqlite3pager_rename(Pager*, const char *zNewName);
void sqlite3pager_set_codec(Pager*,void*(*)(void*,void*,Pgno,int),void*);
int sqlite3pager_movepage(Pager*,void*,Pgno);
int sqlite3pager_reset(Pager*);
int sqlite3pager_release_memory(int);
#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
int sqlite3pager_lockstate(Pager*);
#endif
#ifdef SQLITE_TEST
void sqlite3pager_refdump(Pager*);
int pager3_refinfo_enable;
#endif
#endif /* _PAGER_H_ */

File diff suppressed because it is too large Load Diff

View File

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

File diff suppressed because it is too large Load Diff

View File

@ -1,682 +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 3426 2007-03-21 20:19:37Z damagedsoul $
*/
#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);
}
pData->rc = SQLITE_CORRUPT;
}
/*
** 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. 0 for trigger or view.
** argv[2] = SQL text for the CREATE statement.
**
*/
int sqlite3InitCallback(void *pInit, int argc, char **argv, char **azColName){
InitData *pData = (InitData*)pInit;
sqlite3 *db = pData->db;
int iDb = pData->iDb;
pData->rc = SQLITE_OK;
DbClearProperty(db, iDb, DB_Empty);
if( sqlite3MallocFailed() ){
corruptSchema(pData, 0);
return SQLITE_NOMEM;
}
assert( argc==3 );
if( argv==0 ) return 0; /* Might happen if EMPTY_RESULT_CALLBACKS are on */
if( argv[1]==0 ){
corruptSchema(pData, 0);
return 1;
}
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 ){
pData->rc = rc;
if( rc==SQLITE_NOMEM ){
sqlite3FailedMalloc();
}else if( rc!=SQLITE_INTERRUPT ){
corruptSchema(pData, zErr);
}
sqlite3_free(zErr);
return 1;
}
}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[4];
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;
azArg[3] = 0;
initData.db = db;
initData.iDb = iDb;
initData.pzErrMsg = pzErrMsg;
rc = sqlite3InitCallback(&initData, 3, (char **)azArg, 0);
if( rc ){
sqlite3SafetyOn(db);
return initData.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 2:UTF-16LE 3:UTF-16BE
** 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 FROM '%q'.%s",
db->aDb[iDb].zName, zMasterName);
sqlite3SafetyOff(db);
rc = sqlite3_exec(db, zSql, sqlite3InitCallback, &initData, 0);
if( rc==SQLITE_ABORT ) rc = initData.rc;
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 sqlite3Prepare(
sqlite3 *db, /* Database handle. */
const char *zSql, /* UTF-8 encoded SQL statement. */
int nBytes, /* Length of zSql in bytes. */
int saveSqlFlag, /* True to copy SQL text into the sqlite3_stmt */
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( sqlite3MallocFailed() ){
sParse.rc = SQLITE_NOMEM;
}
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 ){
if( saveSqlFlag ){
sqlite3VdbeSetSql(sParse.pVdbe, zSql, sParse.zTail - zSql);
}
*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();
assert( (rc&db->errMask)==rc );
return rc;
}
/*
** Rerun the compilation of a statement after a schema change.
** Return true if the statement was recompiled successfully.
** Return false if there is an error of some kind.
*/
int sqlite3Reprepare(Vdbe *p){
int rc;
Vdbe *pNew;
const char *zSql;
sqlite3 *db;
zSql = sqlite3VdbeGetSql(p);
if( zSql==0 ){
return 0;
}
db = sqlite3VdbeDb(p);
rc = sqlite3Prepare(db, zSql, -1, 0, (sqlite3_stmt**)&pNew, 0);
if( rc ){
assert( pNew==0 );
return 0;
}else{
assert( pNew!=0 );
}
sqlite3VdbeSwap(pNew, p);
sqlite3_transfer_bindings((sqlite3_stmt*)pNew, (sqlite3_stmt*)p);
sqlite3VdbeResetStepResult(pNew);
sqlite3VdbeFinalize(pNew);
return 1;
}
/*
** Two versions of the official API. Legacy and new use. In the legacy
** version, the original SQL text is not saved in the prepared statement
** and so if a schema change occurs, SQLITE_SCHEMA is returned by
** sqlite3_step(). In the new version, the original SQL text is retained
** and the statement is automatically recompiled if an schema change
** occurs.
*/
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 */
){
return sqlite3Prepare(db,zSql,nBytes,0,ppStmt,pzTail);
}
int sqlite3_prepare_v2(
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 */
){
return sqlite3Prepare(db,zSql,nBytes,1,ppStmt,pzTail);
}
#ifndef SQLITE_OMIT_UTF16
/*
** Compile the UTF-16 encoded SQL statement zSql into a statement handle.
*/
static int sqlite3Prepare16(
sqlite3 *db, /* Database handle. */
const void *zSql, /* UTF-8 encoded SQL statement. */
int nBytes, /* Length of zSql in bytes. */
int saveSqlFlag, /* True to save SQL text into the sqlite3_stmt */
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 = sqlite3Prepare(db, zSql8, -1, saveSqlFlag, 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);
}
/*
** Two versions of the official API. Legacy and new use. In the legacy
** version, the original SQL text is not saved in the prepared statement
** and so if a schema change occurs, SQLITE_SCHEMA is returned by
** sqlite3_step(). In the new version, the original SQL text is retained
** and the statement is automatically recompiled if an schema change
** occurs.
*/
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 */
){
return sqlite3Prepare16(db,zSql,nBytes,0,ppStmt,pzTail);
}
int sqlite3_prepare16_v2(
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 */
){
return sqlite3Prepare16(db,zSql,nBytes,1,ppStmt,pzTail);
}
#endif /* SQLITE_OMIT_UTF16 */

View File

@ -1,863 +0,0 @@
/*
** The "printf" code that follows dates from the 1980's. It is in
** the public domain. The original comments are included here for
** completeness. They are very out-of-date but might be useful as
** an historical reference. Most of the "enhancements" have been backed
** out so that the functionality is now the same as standard printf().
**
**************************************************************************
**
** The following modules is an enhanced replacement for the "printf" subroutines
** found in the standard C library. The following enhancements are
** supported:
**
** + Additional functions. The standard set of "printf" functions
** includes printf, fprintf, sprintf, vprintf, vfprintf, and
** vsprintf. This module adds the following:
**
** * snprintf -- Works like sprintf, but has an extra argument
** which is the size of the buffer written to.
**
** * mprintf -- Similar to sprintf. Writes output to memory
** obtained from malloc.
**
** * xprintf -- Calls a function to dispose of output.
**
** * nprintf -- No output, but returns the number of characters
** that would have been output by printf.
**
** * A v- version (ex: vsnprintf) of every function is also
** supplied.
**
** + A few extensions to the formatting notation are supported:
**
** * The "=" flag (similar to "-") causes the output to be
** be centered in the appropriately sized field.
**
** * The %b field outputs an integer in binary notation.
**
** * The %c field now accepts a precision. The character output
** is repeated by the number of times the precision specifies.
**
** * The %' field works like %c, but takes as its character the
** next character of the format string, instead of the next
** argument. For example, printf("%.78'-") prints 78 minus
** signs, the same as printf("%.78c",'-').
**
** + When compiled using GCC on a SPARC, this version of printf is
** faster than the library printf for SUN OS 4.1.
**
** + All functions are fully reentrant.
**
*/
#include "sqliteInt.h"
/*
** Conversion types fall into various categories as defined by the
** following enumeration.
*/
#define etRADIX 1 /* Integer types. %d, %x, %o, and so forth */
#define etFLOAT 2 /* Floating point. %f */
#define etEXP 3 /* Exponentional notation. %e and %E */
#define etGENERIC 4 /* Floating or exponential, depending on exponent. %g */
#define etSIZE 5 /* Return number of characters processed so far. %n */
#define etSTRING 6 /* Strings. %s */
#define etDYNSTRING 7 /* Dynamically allocated strings. %z */
#define etPERCENT 8 /* Percent symbol. %% */
#define etCHARX 9 /* Characters. %c */
/* The rest are extensions, not normally found in printf() */
#define etCHARLIT 10 /* Literal characters. %' */
#define etSQLESCAPE 11 /* Strings with '\'' doubled. %q */
#define etSQLESCAPE2 12 /* Strings with '\'' doubled and enclosed in '',
NULL pointers replaced by SQL NULL. %Q */
#define etTOKEN 13 /* a pointer to a Token structure */
#define etSRCLIST 14 /* a pointer to a SrcList */
#define etPOINTER 15 /* The %p conversion */
/*
** An "etByte" is an 8-bit unsigned value.
*/
typedef unsigned char etByte;
/*
** Each builtin conversion character (ex: the 'd' in "%d") is described
** by an instance of the following structure
*/
typedef struct et_info { /* Information about each format field */
char fmttype; /* The format field code letter */
etByte base; /* The base for radix conversion */
etByte flags; /* One or more of FLAG_ constants below */
etByte type; /* Conversion paradigm */
etByte charset; /* Offset into aDigits[] of the digits string */
etByte prefix; /* Offset into aPrefix[] of the prefix string */
} et_info;
/*
** Allowed values for et_info.flags
*/
#define FLAG_SIGNED 1 /* True if the value to convert is signed */
#define FLAG_INTERN 2 /* True if for internal use only */
#define FLAG_STRING 4 /* Allow infinity precision */
/*
** The following table is searched linearly, so it is good to put the
** most frequently used conversion types first.
*/
static const char aDigits[] = "0123456789ABCDEF0123456789abcdef";
static const char aPrefix[] = "-x0\000X0";
static const et_info fmtinfo[] = {
{ 'd', 10, 1, etRADIX, 0, 0 },
{ 's', 0, 4, etSTRING, 0, 0 },
{ 'g', 0, 1, etGENERIC, 30, 0 },
{ 'z', 0, 6, etDYNSTRING, 0, 0 },
{ 'q', 0, 4, etSQLESCAPE, 0, 0 },
{ 'Q', 0, 4, etSQLESCAPE2, 0, 0 },
{ 'c', 0, 0, etCHARX, 0, 0 },
{ 'o', 8, 0, etRADIX, 0, 2 },
{ 'u', 10, 0, etRADIX, 0, 0 },
{ 'x', 16, 0, etRADIX, 16, 1 },
{ 'X', 16, 0, etRADIX, 0, 4 },
#ifndef SQLITE_OMIT_FLOATING_POINT
{ 'f', 0, 1, etFLOAT, 0, 0 },
{ 'e', 0, 1, etEXP, 30, 0 },
{ 'E', 0, 1, etEXP, 14, 0 },
{ 'G', 0, 1, etGENERIC, 14, 0 },
#endif
{ 'i', 10, 1, etRADIX, 0, 0 },
{ 'n', 0, 0, etSIZE, 0, 0 },
{ '%', 0, 0, etPERCENT, 0, 0 },
{ 'p', 16, 0, etPOINTER, 0, 1 },
{ 'T', 0, 2, etTOKEN, 0, 0 },
{ 'S', 0, 2, etSRCLIST, 0, 0 },
};
#define etNINFO (sizeof(fmtinfo)/sizeof(fmtinfo[0]))
/*
** If SQLITE_OMIT_FLOATING_POINT is defined, then none of the floating point
** conversions will work.
*/
#ifndef SQLITE_OMIT_FLOATING_POINT
/*
** "*val" is a double such that 0.1 <= *val < 10.0
** Return the ascii code for the leading digit of *val, then
** multiply "*val" by 10.0 to renormalize.
**
** Example:
** input: *val = 3.14159
** output: *val = 1.4159 function return = '3'
**
** The counter *cnt is incremented each time. After counter exceeds
** 16 (the number of significant digits in a 64-bit float) '0' is
** always returned.
*/
static int et_getdigit(LONGDOUBLE_TYPE *val, int *cnt){
int digit;
LONGDOUBLE_TYPE d;
if( (*cnt)++ >= 16 ) return '0';
digit = (int)*val;
d = digit;
digit += '0';
*val = (*val - d)*10.0;
return digit;
}
#endif /* SQLITE_OMIT_FLOATING_POINT */
/*
** On machines with a small stack size, you can redefine the
** SQLITE_PRINT_BUF_SIZE to be less than 350. But beware - for
** smaller values some %f conversions may go into an infinite loop.
*/
#ifndef SQLITE_PRINT_BUF_SIZE
# define SQLITE_PRINT_BUF_SIZE 350
#endif
#define etBUFSIZE SQLITE_PRINT_BUF_SIZE /* Size of the output buffer */
/*
** The root program. All variations call this core.
**
** INPUTS:
** func This is a pointer to a function taking three arguments
** 1. A pointer to anything. Same as the "arg" parameter.
** 2. A pointer to the list of characters to be output
** (Note, this list is NOT null terminated.)
** 3. An integer number of characters to be output.
** (Note: This number might be zero.)
**
** arg This is the pointer to anything which will be passed as the
** first argument to "func". Use it for whatever you like.
**
** fmt This is the format string, as in the usual print.
**
** ap This is a pointer to a list of arguments. Same as in
** vfprint.
**
** OUTPUTS:
** The return value is the total number of characters sent to
** the function "func". Returns -1 on a error.
**
** Note that the order in which automatic variables are declared below
** seems to make a big difference in determining how fast this beast
** will run.
*/
static int vxprintf(
void (*func)(void*,const char*,int), /* Consumer of text */
void *arg, /* First argument to the consumer */
int useExtended, /* Allow extended %-conversions */
const char *fmt, /* Format string */
va_list ap /* arguments */
){
int c; /* Next character in the format string */
char *bufpt; /* Pointer to the conversion buffer */
int precision; /* Precision of the current field */
int length; /* Length of the field */
int idx; /* A general purpose loop counter */
int count; /* Total number of characters output */
int width; /* Width of the current field */
etByte flag_leftjustify; /* True if "-" flag is present */
etByte flag_plussign; /* True if "+" flag is present */
etByte flag_blanksign; /* True if " " flag is present */
etByte flag_alternateform; /* True if "#" flag is present */
etByte flag_altform2; /* True if "!" flag is present */
etByte flag_zeropad; /* True if field width constant starts with zero */
etByte flag_long; /* True if "l" flag is present */
etByte flag_longlong; /* True if the "ll" flag is present */
etByte done; /* Loop termination flag */
sqlite_uint64 longvalue; /* Value for integer types */
LONGDOUBLE_TYPE realvalue; /* Value for real types */
const et_info *infop; /* Pointer to the appropriate info structure */
char buf[etBUFSIZE]; /* Conversion buffer */
char prefix; /* Prefix character. "+" or "-" or " " or '\0'. */
etByte errorflag = 0; /* True if an error is encountered */
etByte xtype; /* Conversion paradigm */
char *zExtra; /* Extra memory used for etTCLESCAPE conversions */
static const char spaces[] =
" ";
#define etSPACESIZE (sizeof(spaces)-1)
#ifndef SQLITE_OMIT_FLOATING_POINT
int exp, e2; /* exponent of real numbers */
double rounder; /* Used for rounding floating point values */
etByte flag_dp; /* True if decimal point should be shown */
etByte flag_rtz; /* True if trailing zeros should be removed */
etByte flag_exp; /* True to force display of the exponent */
int nsd; /* Number of significant digits returned */
#endif
func(arg,"",0);
count = length = 0;
bufpt = 0;
for(; (c=(*fmt))!=0; ++fmt){
if( c!='%' ){
int amt;
bufpt = (char *)fmt;
amt = 1;
while( (c=(*++fmt))!='%' && c!=0 ) amt++;
(*func)(arg,bufpt,amt);
count += amt;
if( c==0 ) break;
}
if( (c=(*++fmt))==0 ){
errorflag = 1;
(*func)(arg,"%",1);
count++;
break;
}
/* Find out what flags are present */
flag_leftjustify = flag_plussign = flag_blanksign =
flag_alternateform = flag_altform2 = flag_zeropad = 0;
done = 0;
do{
switch( c ){
case '-': flag_leftjustify = 1; break;
case '+': flag_plussign = 1; break;
case ' ': flag_blanksign = 1; break;
case '#': flag_alternateform = 1; break;
case '!': flag_altform2 = 1; break;
case '0': flag_zeropad = 1; break;
default: done = 1; break;
}
}while( !done && (c=(*++fmt))!=0 );
/* Get the field width */
width = 0;
if( c=='*' ){
width = va_arg(ap,int);
if( width<0 ){
flag_leftjustify = 1;
width = -width;
}
c = *++fmt;
}else{
while( c>='0' && c<='9' ){
width = width*10 + c - '0';
c = *++fmt;
}
}
if( width > etBUFSIZE-10 ){
width = etBUFSIZE-10;
}
/* Get the precision */
if( c=='.' ){
precision = 0;
c = *++fmt;
if( c=='*' ){
precision = va_arg(ap,int);
if( precision<0 ) precision = -precision;
c = *++fmt;
}else{
while( c>='0' && c<='9' ){
precision = precision*10 + c - '0';
c = *++fmt;
}
}
}else{
precision = -1;
}
/* Get the conversion type modifier */
if( c=='l' ){
flag_long = 1;
c = *++fmt;
if( c=='l' ){
flag_longlong = 1;
c = *++fmt;
}else{
flag_longlong = 0;
}
}else{
flag_long = flag_longlong = 0;
}
/* Fetch the info entry for the field */
infop = 0;
for(idx=0; idx<etNINFO; idx++){
if( c==fmtinfo[idx].fmttype ){
infop = &fmtinfo[idx];
if( useExtended || (infop->flags & FLAG_INTERN)==0 ){
xtype = infop->type;
}else{
return -1;
}
break;
}
}
zExtra = 0;
if( infop==0 ){
return -1;
}
/* Limit the precision to prevent overflowing buf[] during conversion */
if( precision>etBUFSIZE-40 && (infop->flags & FLAG_STRING)==0 ){
precision = etBUFSIZE-40;
}
/*
** At this point, variables are initialized as follows:
**
** flag_alternateform TRUE if a '#' is present.
** flag_altform2 TRUE if a '!' is present.
** flag_plussign TRUE if a '+' is present.
** flag_leftjustify TRUE if a '-' is present or if the
** field width was negative.
** flag_zeropad TRUE if the width began with 0.
** flag_long TRUE if the letter 'l' (ell) prefixed
** the conversion character.
** flag_longlong TRUE if the letter 'll' (ell ell) prefixed
** the conversion character.
** flag_blanksign TRUE if a ' ' is present.
** width The specified field width. This is
** always non-negative. Zero is the default.
** precision The specified precision. The default
** is -1.
** xtype The class of the conversion.
** infop Pointer to the appropriate info struct.
*/
switch( xtype ){
case etPOINTER:
flag_longlong = sizeof(char*)==sizeof(i64);
flag_long = sizeof(char*)==sizeof(long int);
/* Fall through into the next case */
case etRADIX:
if( infop->flags & FLAG_SIGNED ){
i64 v;
if( flag_longlong ) v = va_arg(ap,i64);
else if( flag_long ) v = va_arg(ap,long int);
else v = va_arg(ap,int);
if( v<0 ){
longvalue = -v;
prefix = '-';
}else{
longvalue = v;
if( flag_plussign ) prefix = '+';
else if( flag_blanksign ) prefix = ' ';
else prefix = 0;
}
}else{
if( flag_longlong ) longvalue = va_arg(ap,u64);
else if( flag_long ) longvalue = va_arg(ap,unsigned long int);
else longvalue = va_arg(ap,unsigned int);
prefix = 0;
}
if( longvalue==0 ) flag_alternateform = 0;
if( flag_zeropad && precision<width-(prefix!=0) ){
precision = width-(prefix!=0);
}
bufpt = &buf[etBUFSIZE-1];
{
register const char *cset; /* Use registers for speed */
register int base;
cset = &aDigits[infop->charset];
base = infop->base;
do{ /* Convert to ascii */
*(--bufpt) = cset[longvalue%base];
longvalue = longvalue/base;
}while( longvalue>0 );
}
length = &buf[etBUFSIZE-1]-bufpt;
for(idx=precision-length; idx>0; idx--){
*(--bufpt) = '0'; /* Zero pad */
}
if( prefix ) *(--bufpt) = prefix; /* Add sign */
if( flag_alternateform && infop->prefix ){ /* Add "0" or "0x" */
const char *pre;
char x;
pre = &aPrefix[infop->prefix];
if( *bufpt!=pre[0] ){
for(; (x=(*pre))!=0; pre++) *(--bufpt) = x;
}
}
length = &buf[etBUFSIZE-1]-bufpt;
break;
case etFLOAT:
case etEXP:
case etGENERIC:
realvalue = va_arg(ap,double);
#ifndef SQLITE_OMIT_FLOATING_POINT
if( precision<0 ) precision = 6; /* Set default precision */
if( precision>etBUFSIZE/2-10 ) precision = etBUFSIZE/2-10;
if( realvalue<0.0 ){
realvalue = -realvalue;
prefix = '-';
}else{
if( flag_plussign ) prefix = '+';
else if( flag_blanksign ) prefix = ' ';
else prefix = 0;
}
if( xtype==etGENERIC && precision>0 ) precision--;
#if 0
/* Rounding works like BSD when the constant 0.4999 is used. Wierd! */
for(idx=precision, rounder=0.4999; idx>0; idx--, rounder*=0.1);
#else
/* It makes more sense to use 0.5 */
for(idx=precision, rounder=0.5; idx>0; idx--, rounder*=0.1){}
#endif
if( xtype==etFLOAT ) realvalue += rounder;
/* Normalize realvalue to within 10.0 > realvalue >= 1.0 */
exp = 0;
if( realvalue>0.0 ){
while( realvalue>=1e32 && exp<=350 ){ realvalue *= 1e-32; exp+=32; }
while( realvalue>=1e8 && exp<=350 ){ realvalue *= 1e-8; exp+=8; }
while( realvalue>=10.0 && exp<=350 ){ realvalue *= 0.1; exp++; }
while( realvalue<1e-8 && exp>=-350 ){ realvalue *= 1e8; exp-=8; }
while( realvalue<1.0 && exp>=-350 ){ realvalue *= 10.0; exp--; }
if( exp>350 || exp<-350 ){
bufpt = "NaN";
length = 3;
break;
}
}
bufpt = buf;
/*
** If the field type is etGENERIC, then convert to either etEXP
** or etFLOAT, as appropriate.
*/
flag_exp = xtype==etEXP;
if( xtype!=etFLOAT ){
realvalue += rounder;
if( realvalue>=10.0 ){ realvalue *= 0.1; exp++; }
}
if( xtype==etGENERIC ){
flag_rtz = !flag_alternateform;
if( exp<-4 || exp>precision ){
xtype = etEXP;
}else{
precision = precision - exp;
xtype = etFLOAT;
}
}else{
flag_rtz = 0;
}
if( xtype==etEXP ){
e2 = 0;
}else{
e2 = exp;
}
nsd = 0;
flag_dp = (precision>0) | flag_alternateform | flag_altform2;
/* The sign in front of the number */
if( prefix ){
*(bufpt++) = prefix;
}
/* Digits prior to the decimal point */
if( e2<0 ){
*(bufpt++) = '0';
}else{
for(; e2>=0; e2--){
*(bufpt++) = et_getdigit(&realvalue,&nsd);
}
}
/* The decimal point */
if( flag_dp ){
*(bufpt++) = '.';
}
/* "0" digits after the decimal point but before the first
** significant digit of the number */
for(e2++; e2<0 && precision>0; precision--, e2++){
*(bufpt++) = '0';
}
/* Significant digits after the decimal point */
while( (precision--)>0 ){
*(bufpt++) = et_getdigit(&realvalue,&nsd);
}
/* Remove trailing zeros and the "." if no digits follow the "." */
if( flag_rtz && flag_dp ){
while( bufpt[-1]=='0' ) *(--bufpt) = 0;
assert( bufpt>buf );
if( bufpt[-1]=='.' ){
if( flag_altform2 ){
*(bufpt++) = '0';
}else{
*(--bufpt) = 0;
}
}
}
/* Add the "eNNN" suffix */
if( flag_exp || (xtype==etEXP && exp) ){
*(bufpt++) = aDigits[infop->charset];
if( exp<0 ){
*(bufpt++) = '-'; exp = -exp;
}else{
*(bufpt++) = '+';
}
if( exp>=100 ){
*(bufpt++) = (exp/100)+'0'; /* 100's digit */
exp %= 100;
}
*(bufpt++) = exp/10+'0'; /* 10's digit */
*(bufpt++) = exp%10+'0'; /* 1's digit */
}
*bufpt = 0;
/* The converted number is in buf[] and zero terminated. Output it.
** Note that the number is in the usual order, not reversed as with
** integer conversions. */
length = bufpt-buf;
bufpt = buf;
/* Special case: Add leading zeros if the flag_zeropad flag is
** set and we are not left justified */
if( flag_zeropad && !flag_leftjustify && length < width){
int i;
int nPad = width - length;
for(i=width; i>=nPad; i--){
bufpt[i] = bufpt[i-nPad];
}
i = prefix!=0;
while( nPad-- ) bufpt[i++] = '0';
length = width;
}
#endif
break;
case etSIZE:
*(va_arg(ap,int*)) = count;
length = width = 0;
break;
case etPERCENT:
buf[0] = '%';
bufpt = buf;
length = 1;
break;
case etCHARLIT:
case etCHARX:
c = buf[0] = (xtype==etCHARX ? va_arg(ap,int) : *++fmt);
if( precision>=0 ){
for(idx=1; idx<precision; idx++) buf[idx] = c;
length = precision;
}else{
length =1;
}
bufpt = buf;
break;
case etSTRING:
case etDYNSTRING:
bufpt = va_arg(ap,char*);
if( bufpt==0 ){
bufpt = "";
}else if( xtype==etDYNSTRING ){
zExtra = bufpt;
}
length = strlen(bufpt);
if( precision>=0 && precision<length ) length = precision;
break;
case etSQLESCAPE:
case etSQLESCAPE2: {
int i, j, n, ch, isnull;
int needQuote;
char *escarg = va_arg(ap,char*);
isnull = escarg==0;
if( isnull ) escarg = (xtype==etSQLESCAPE2 ? "NULL" : "(NULL)");
for(i=n=0; (ch=escarg[i])!=0; i++){
if( ch=='\'' ) n++;
}
needQuote = !isnull && xtype==etSQLESCAPE2;
n += i + 1 + needQuote*2;
if( n>etBUFSIZE ){
bufpt = zExtra = sqliteMalloc( n );
if( bufpt==0 ) return -1;
}else{
bufpt = buf;
}
j = 0;
if( needQuote ) bufpt[j++] = '\'';
for(i=0; (ch=escarg[i])!=0; i++){
bufpt[j++] = ch;
if( ch=='\'' ) bufpt[j++] = ch;
}
if( needQuote ) bufpt[j++] = '\'';
bufpt[j] = 0;
length = j;
/* The precision is ignored on %q and %Q */
/* if( precision>=0 && precision<length ) length = precision; */
break;
}
case etTOKEN: {
Token *pToken = va_arg(ap, Token*);
if( pToken && pToken->z ){
(*func)(arg, (char*)pToken->z, pToken->n);
}
length = width = 0;
break;
}
case etSRCLIST: {
SrcList *pSrc = va_arg(ap, SrcList*);
int k = va_arg(ap, int);
struct SrcList_item *pItem = &pSrc->a[k];
assert( k>=0 && k<pSrc->nSrc );
if( pItem->zDatabase && pItem->zDatabase[0] ){
(*func)(arg, pItem->zDatabase, strlen(pItem->zDatabase));
(*func)(arg, ".", 1);
}
(*func)(arg, pItem->zName, strlen(pItem->zName));
length = width = 0;
break;
}
}/* End switch over the format type */
/*
** The text of the conversion is pointed to by "bufpt" and is
** "length" characters long. The field width is "width". Do
** the output.
*/
if( !flag_leftjustify ){
register int nspace;
nspace = width-length;
if( nspace>0 ){
count += nspace;
while( nspace>=etSPACESIZE ){
(*func)(arg,spaces,etSPACESIZE);
nspace -= etSPACESIZE;
}
if( nspace>0 ) (*func)(arg,spaces,nspace);
}
}
if( length>0 ){
(*func)(arg,bufpt,length);
count += length;
}
if( flag_leftjustify ){
register int nspace;
nspace = width-length;
if( nspace>0 ){
count += nspace;
while( nspace>=etSPACESIZE ){
(*func)(arg,spaces,etSPACESIZE);
nspace -= etSPACESIZE;
}
if( nspace>0 ) (*func)(arg,spaces,nspace);
}
}
if( zExtra ){
sqliteFree(zExtra);
}
}/* End for loop over the format string */
return errorflag ? -1 : count;
} /* End of function */
/* This structure is used to store state information about the
** write to memory that is currently in progress.
*/
struct sgMprintf {
char *zBase; /* A base allocation */
char *zText; /* The string collected so far */
int nChar; /* Length of the string so far */
int nTotal; /* Output size if unconstrained */
int nAlloc; /* Amount of space allocated in zText */
void *(*xRealloc)(void*,int); /* Function used to realloc memory */
};
/*
** This function implements the callback from vxprintf.
**
** This routine add nNewChar characters of text in zNewText to
** the sgMprintf structure pointed to by "arg".
*/
static void mout(void *arg, const char *zNewText, int nNewChar){
struct sgMprintf *pM = (struct sgMprintf*)arg;
pM->nTotal += nNewChar;
if( pM->nChar + nNewChar + 1 > pM->nAlloc ){
if( pM->xRealloc==0 ){
nNewChar = pM->nAlloc - pM->nChar - 1;
}else{
pM->nAlloc = pM->nChar + nNewChar*2 + 1;
if( pM->zText==pM->zBase ){
pM->zText = pM->xRealloc(0, pM->nAlloc);
if( pM->zText && pM->nChar ){
memcpy(pM->zText, pM->zBase, pM->nChar);
}
}else{
char *zNew;
zNew = pM->xRealloc(pM->zText, pM->nAlloc);
if( zNew ){
pM->zText = zNew;
}
}
}
}
if( pM->zText ){
if( nNewChar>0 ){
memcpy(&pM->zText[pM->nChar], zNewText, nNewChar);
pM->nChar += nNewChar;
}
pM->zText[pM->nChar] = 0;
}
}
/*
** This routine is a wrapper around xprintf() that invokes mout() as
** the consumer.
*/
static char *base_vprintf(
void *(*xRealloc)(void*,int), /* Routine to realloc memory. May be NULL */
int useInternal, /* Use internal %-conversions if true */
char *zInitBuf, /* Initially write here, before mallocing */
int nInitBuf, /* Size of zInitBuf[] */
const char *zFormat, /* format string */
va_list ap /* arguments */
){
struct sgMprintf sM;
sM.zBase = sM.zText = zInitBuf;
sM.nChar = sM.nTotal = 0;
sM.nAlloc = nInitBuf;
sM.xRealloc = xRealloc;
vxprintf(mout, &sM, useInternal, zFormat, ap);
if( xRealloc ){
if( sM.zText==sM.zBase ){
sM.zText = xRealloc(0, sM.nChar+1);
if( sM.zText ){
memcpy(sM.zText, sM.zBase, sM.nChar+1);
}
}else if( sM.nAlloc>sM.nChar+10 ){
char *zNew = xRealloc(sM.zText, sM.nChar+1);
if( zNew ){
sM.zText = zNew;
}
}
}
return sM.zText;
}
/*
** Realloc that is a real function, not a macro.
*/
static void *printf_realloc(void *old, int size){
return sqliteRealloc(old,size);
}
/*
** Print into memory obtained from sqliteMalloc(). Use the internal
** %-conversion extensions.
*/
char *sqlite3VMPrintf(const char *zFormat, va_list ap){
char zBase[SQLITE_PRINT_BUF_SIZE];
return base_vprintf(printf_realloc, 1, zBase, sizeof(zBase), zFormat, ap);
}
/*
** Print into memory obtained from sqliteMalloc(). Use the internal
** %-conversion extensions.
*/
char *sqlite3MPrintf(const char *zFormat, ...){
va_list ap;
char *z;
char zBase[SQLITE_PRINT_BUF_SIZE];
va_start(ap, zFormat);
z = base_vprintf(printf_realloc, 1, zBase, sizeof(zBase), zFormat, ap);
va_end(ap);
return z;
}
/*
** Print into memory obtained from sqlite3_malloc(). Omit the internal
** %-conversion extensions.
*/
char *sqlite3_vmprintf(const char *zFormat, va_list ap){
char zBase[SQLITE_PRINT_BUF_SIZE];
return base_vprintf(sqlite3_realloc, 0, zBase, sizeof(zBase), zFormat, ap);
}
/*
** Print into memory obtained from sqlite3_malloc()(). Omit the internal
** %-conversion extensions.
*/
char *sqlite3_mprintf(const char *zFormat, ...){
va_list ap;
char *z;
char zBase[SQLITE_PRINT_BUF_SIZE];
va_start(ap, zFormat);
z = base_vprintf(sqlite3_realloc, 0, zBase, sizeof(zBase), zFormat, ap);
va_end(ap);
return z;
}
/*
** sqlite3_snprintf() works like snprintf() except that it ignores the
** current locale settings. This is important for SQLite because we
** are not able to use a "," as the decimal point in place of "." as
** specified by some locales.
*/
char *sqlite3_snprintf(int n, char *zBuf, const char *zFormat, ...){
char *z;
va_list ap;
va_start(ap,zFormat);
z = base_vprintf(0, 0, zBuf, n, zFormat, ap);
va_end(ap);
return z;
}
#if defined(SQLITE_TEST) || defined(SQLITE_DEBUG)
/*
** A version of printf() that understands %lld. Used for debugging.
** The printf() built into some versions of windows does not understand %lld
** and segfaults if you give it a long long int.
*/
void sqlite3DebugPrintf(const char *zFormat, ...){
extern int getpid(void);
va_list ap;
char zBuf[500];
va_start(ap, zFormat);
base_vprintf(0, 0, zBuf, sizeof(zBuf), zFormat, ap);
va_end(ap);
fprintf(stdout,"%s", zBuf);
fflush(stdout);
}
#endif

View File

@ -1,100 +0,0 @@
/*
** 2001 September 15
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains code to implement a pseudo-random number
** generator (PRNG) for SQLite.
**
** Random numbers are used by some of the database backends in order
** to generate random integer keys for tables or random filenames.
**
** $Id: random.c 3426 2007-03-21 20:19:37Z damagedsoul $
*/
#include "sqliteInt.h"
#include "os.h"
/*
** Get a single 8-bit random value from the RC4 PRNG. The Mutex
** must be held while executing this routine.
**
** Why not just use a library random generator like lrand48() for this?
** Because the OP_NewRowid opcode in the VDBE depends on having a very
** good source of random numbers. The lrand48() library function may
** well be good enough. But maybe not. Or maybe lrand48() has some
** subtle problems on some systems that could cause problems. It is hard
** to know. To minimize the risk of problems due to bad lrand48()
** implementations, SQLite uses this random number generator based
** on RC4, which we know works very well.
**
** (Later): Actually, OP_NewRowid does not depend on a good source of
** randomness any more. But we will leave this code in all the same.
*/
static int randomByte(void){
unsigned char t;
/* All threads share a single random number generator.
** This structure is the current state of the generator.
*/
static struct {
unsigned char isInit; /* True if initialized */
unsigned char i, j; /* State variables */
unsigned char s[256]; /* State variables */
} prng;
/* Initialize the state of the random number generator once,
** the first time this routine is called. The seed value does
** not need to contain a lot of randomness since we are not
** trying to do secure encryption or anything like that...
**
** Nothing in this file or anywhere else in SQLite does any kind of
** encryption. The RC4 algorithm is being used as a PRNG (pseudo-random
** number generator) not as an encryption device.
*/
if( !prng.isInit ){
int i;
char k[256];
prng.j = 0;
prng.i = 0;
sqlite3OsRandomSeed(k);
for(i=0; i<256; i++){
prng.s[i] = i;
}
for(i=0; i<256; i++){
prng.j += prng.s[i] + k[i];
t = prng.s[prng.j];
prng.s[prng.j] = prng.s[i];
prng.s[i] = t;
}
prng.isInit = 1;
}
/* Generate and return single random byte
*/
prng.i++;
t = prng.s[prng.i];
prng.j += t;
prng.s[prng.i] = prng.s[prng.j];
prng.s[prng.j] = t;
t += prng.s[prng.i];
return prng.s[t];
}
/*
** Return N random bytes.
*/
void sqlite3Randomness(int N, void *pBuf){
unsigned char *zBuf = pBuf;
sqlite3OsEnterMutex();
while( N-- ){
*(zBuf++) = randomByte();
}
sqlite3OsLeaveMutex();
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,282 +0,0 @@
/*
** 2006 June 7
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
** This header file defines the SQLite interface for use by
** shared libraries that want to be imported as extensions into
** an SQLite instance. Shared libraries that intend to be loaded
** as extensions by SQLite should #include this file instead of
** sqlite3.h.
**
** @(#) $Id: sqlite3ext.h 3426 2007-03-21 20:19:37Z damagedsoul $
*/
#ifndef _SQLITE3EXT_H_
#define _SQLITE3EXT_H_
#include "sqlite3.h"
typedef struct sqlite3_api_routines sqlite3_api_routines;
/*
** The following structure hold pointers to all of the SQLite API
** routines.
*/
struct sqlite3_api_routines {
void * (*aggregate_context)(sqlite3_context*,int nBytes);
int (*aggregate_count)(sqlite3_context*);
int (*bind_blob)(sqlite3_stmt*,int,const void*,int n,void(*)(void*));
int (*bind_double)(sqlite3_stmt*,int,double);
int (*bind_int)(sqlite3_stmt*,int,int);
int (*bind_int64)(sqlite3_stmt*,int,sqlite_int64);
int (*bind_null)(sqlite3_stmt*,int);
int (*bind_parameter_count)(sqlite3_stmt*);
int (*bind_parameter_index)(sqlite3_stmt*,const char*zName);
const char * (*bind_parameter_name)(sqlite3_stmt*,int);
int (*bind_text)(sqlite3_stmt*,int,const char*,int n,void(*)(void*));
int (*bind_text16)(sqlite3_stmt*,int,const void*,int,void(*)(void*));
int (*bind_value)(sqlite3_stmt*,int,const sqlite3_value*);
int (*busy_handler)(sqlite3*,int(*)(void*,int),void*);
int (*busy_timeout)(sqlite3*,int ms);
int (*changes)(sqlite3*);
int (*close)(sqlite3*);
int (*collation_needed)(sqlite3*,void*,void(*)(void*,sqlite3*,int eTextRep,const char*));
int (*collation_needed16)(sqlite3*,void*,void(*)(void*,sqlite3*,int eTextRep,const void*));
const void * (*column_blob)(sqlite3_stmt*,int iCol);
int (*column_bytes)(sqlite3_stmt*,int iCol);
int (*column_bytes16)(sqlite3_stmt*,int iCol);
int (*column_count)(sqlite3_stmt*pStmt);
const char * (*column_database_name)(sqlite3_stmt*,int);
const void * (*column_database_name16)(sqlite3_stmt*,int);
const char * (*column_decltype)(sqlite3_stmt*,int i);
const void * (*column_decltype16)(sqlite3_stmt*,int);
double (*column_double)(sqlite3_stmt*,int iCol);
int (*column_int)(sqlite3_stmt*,int iCol);
sqlite_int64 (*column_int64)(sqlite3_stmt*,int iCol);
const char * (*column_name)(sqlite3_stmt*,int);
const void * (*column_name16)(sqlite3_stmt*,int);
const char * (*column_origin_name)(sqlite3_stmt*,int);
const void * (*column_origin_name16)(sqlite3_stmt*,int);
const char * (*column_table_name)(sqlite3_stmt*,int);
const void * (*column_table_name16)(sqlite3_stmt*,int);
const unsigned char * (*column_text)(sqlite3_stmt*,int iCol);
const void * (*column_text16)(sqlite3_stmt*,int iCol);
int (*column_type)(sqlite3_stmt*,int iCol);
sqlite3_value* (*column_value)(sqlite3_stmt*,int iCol);
void * (*commit_hook)(sqlite3*,int(*)(void*),void*);
int (*complete)(const char*sql);
int (*complete16)(const void*sql);
int (*create_collation)(sqlite3*,const char*,int,void*,int(*)(void*,int,const void*,int,const void*));
int (*create_collation16)(sqlite3*,const char*,int,void*,int(*)(void*,int,const void*,int,const void*));
int (*create_function)(sqlite3*,const char*,int,int,void*,void (*xFunc)(sqlite3_context*,int,sqlite3_value**),void (*xStep)(sqlite3_context*,int,sqlite3_value**),void (*xFinal)(sqlite3_context*));
int (*create_function16)(sqlite3*,const void*,int,int,void*,void (*xFunc)(sqlite3_context*,int,sqlite3_value**),void (*xStep)(sqlite3_context*,int,sqlite3_value**),void (*xFinal)(sqlite3_context*));
int (*create_module)(sqlite3*,const char*,const sqlite3_module*,void*);
int (*data_count)(sqlite3_stmt*pStmt);
sqlite3 * (*db_handle)(sqlite3_stmt*);
int (*declare_vtab)(sqlite3*,const char*);
int (*enable_shared_cache)(int);
int (*errcode)(sqlite3*db);
const char * (*errmsg)(sqlite3*);
const void * (*errmsg16)(sqlite3*);
int (*exec)(sqlite3*,const char*,sqlite3_callback,void*,char**);
int (*expired)(sqlite3_stmt*);
int (*finalize)(sqlite3_stmt*pStmt);
void (*free)(void*);
void (*free_table)(char**result);
int (*get_autocommit)(sqlite3*);
void * (*get_auxdata)(sqlite3_context*,int);
int (*get_table)(sqlite3*,const char*,char***,int*,int*,char**);
int (*global_recover)(void);
void (*interruptx)(sqlite3*);
sqlite_int64 (*last_insert_rowid)(sqlite3*);
const char * (*libversion)(void);
int (*libversion_number)(void);
void *(*malloc)(int);
char * (*mprintf)(const char*,...);
int (*open)(const char*,sqlite3**);
int (*open16)(const void*,sqlite3**);
int (*prepare)(sqlite3*,const char*,int,sqlite3_stmt**,const char**);
int (*prepare16)(sqlite3*,const void*,int,sqlite3_stmt**,const void**);
void * (*profile)(sqlite3*,void(*)(void*,const char*,sqlite_uint64),void*);
void (*progress_handler)(sqlite3*,int,int(*)(void*),void*);
void *(*realloc)(void*,int);
int (*reset)(sqlite3_stmt*pStmt);
void (*result_blob)(sqlite3_context*,const void*,int,void(*)(void*));
void (*result_double)(sqlite3_context*,double);
void (*result_error)(sqlite3_context*,const char*,int);
void (*result_error16)(sqlite3_context*,const void*,int);
void (*result_int)(sqlite3_context*,int);
void (*result_int64)(sqlite3_context*,sqlite_int64);
void (*result_null)(sqlite3_context*);
void (*result_text)(sqlite3_context*,const char*,int,void(*)(void*));
void (*result_text16)(sqlite3_context*,const void*,int,void(*)(void*));
void (*result_text16be)(sqlite3_context*,const void*,int,void(*)(void*));
void (*result_text16le)(sqlite3_context*,const void*,int,void(*)(void*));
void (*result_value)(sqlite3_context*,sqlite3_value*);
void * (*rollback_hook)(sqlite3*,void(*)(void*),void*);
int (*set_authorizer)(sqlite3*,int(*)(void*,int,const char*,const char*,const char*,const char*),void*);
void (*set_auxdata)(sqlite3_context*,int,void*,void (*)(void*));
char * (*snprintf)(int,char*,const char*,...);
int (*step)(sqlite3_stmt*);
int (*table_column_metadata)(sqlite3*,const char*,const char*,const char*,char const**,char const**,int*,int*,int*);
void (*thread_cleanup)(void);
int (*total_changes)(sqlite3*);
void * (*trace)(sqlite3*,void(*xTrace)(void*,const char*),void*);
int (*transfer_bindings)(sqlite3_stmt*,sqlite3_stmt*);
void * (*update_hook)(sqlite3*,void(*)(void*,int ,char const*,char const*,sqlite_int64),void*);
void * (*user_data)(sqlite3_context*);
const void * (*value_blob)(sqlite3_value*);
int (*value_bytes)(sqlite3_value*);
int (*value_bytes16)(sqlite3_value*);
double (*value_double)(sqlite3_value*);
int (*value_int)(sqlite3_value*);
sqlite_int64 (*value_int64)(sqlite3_value*);
int (*value_numeric_type)(sqlite3_value*);
const unsigned char * (*value_text)(sqlite3_value*);
const void * (*value_text16)(sqlite3_value*);
const void * (*value_text16be)(sqlite3_value*);
const void * (*value_text16le)(sqlite3_value*);
int (*value_type)(sqlite3_value*);
char * (*vmprintf)(const char*,va_list);
int (*overload_function)(sqlite3*, const char *zFuncName, int nArg);
};
/*
** The following macros redefine the API routines so that they are
** redirected throught the global sqlite3_api structure.
**
** This header file is also used by the loadext.c source file
** (part of the main SQLite library - not an extension) so that
** it can get access to the sqlite3_api_routines structure
** definition. But the main library does not want to redefine
** the API. So the redefinition macros are only valid if the
** SQLITE_CORE macros is undefined.
*/
#ifndef SQLITE_CORE
#define sqlite3_aggregate_context sqlite3_api->aggregate_context
#define sqlite3_aggregate_count sqlite3_api->aggregate_count
#define sqlite3_bind_blob sqlite3_api->bind_blob
#define sqlite3_bind_double sqlite3_api->bind_double
#define sqlite3_bind_int sqlite3_api->bind_int
#define sqlite3_bind_int64 sqlite3_api->bind_int64
#define sqlite3_bind_null sqlite3_api->bind_null
#define sqlite3_bind_parameter_count sqlite3_api->bind_parameter_count
#define sqlite3_bind_parameter_index sqlite3_api->bind_parameter_index
#define sqlite3_bind_parameter_name sqlite3_api->bind_parameter_name
#define sqlite3_bind_text sqlite3_api->bind_text
#define sqlite3_bind_text16 sqlite3_api->bind_text16
#define sqlite3_bind_value sqlite3_api->bind_value
#define sqlite3_busy_handler sqlite3_api->busy_handler
#define sqlite3_busy_timeout sqlite3_api->busy_timeout
#define sqlite3_changes sqlite3_api->changes
#define sqlite3_close sqlite3_api->close
#define sqlite3_collation_needed sqlite3_api->collation_needed
#define sqlite3_collation_needed16 sqlite3_api->collation_needed16
#define sqlite3_column_blob sqlite3_api->column_blob
#define sqlite3_column_bytes sqlite3_api->column_bytes
#define sqlite3_column_bytes16 sqlite3_api->column_bytes16
#define sqlite3_column_count sqlite3_api->column_count
#define sqlite3_column_database_name sqlite3_api->column_database_name
#define sqlite3_column_database_name16 sqlite3_api->column_database_name16
#define sqlite3_column_decltype sqlite3_api->column_decltype
#define sqlite3_column_decltype16 sqlite3_api->column_decltype16
#define sqlite3_column_double sqlite3_api->column_double
#define sqlite3_column_int sqlite3_api->column_int
#define sqlite3_column_int64 sqlite3_api->column_int64
#define sqlite3_column_name sqlite3_api->column_name
#define sqlite3_column_name16 sqlite3_api->column_name16
#define sqlite3_column_origin_name sqlite3_api->column_origin_name
#define sqlite3_column_origin_name16 sqlite3_api->column_origin_name16
#define sqlite3_column_table_name sqlite3_api->column_table_name
#define sqlite3_column_table_name16 sqlite3_api->column_table_name16
#define sqlite3_column_text sqlite3_api->column_text
#define sqlite3_column_text16 sqlite3_api->column_text16
#define sqlite3_column_type sqlite3_api->column_type
#define sqlite3_column_value sqlite3_api->column_value
#define sqlite3_commit_hook sqlite3_api->commit_hook
#define sqlite3_complete sqlite3_api->complete
#define sqlite3_complete16 sqlite3_api->complete16
#define sqlite3_create_collation sqlite3_api->create_collation
#define sqlite3_create_collation16 sqlite3_api->create_collation16
#define sqlite3_create_function sqlite3_api->create_function
#define sqlite3_create_function16 sqlite3_api->create_function16
#define sqlite3_create_module sqlite3_api->create_module
#define sqlite3_data_count sqlite3_api->data_count
#define sqlite3_db_handle sqlite3_api->db_handle
#define sqlite3_declare_vtab sqlite3_api->declare_vtab
#define sqlite3_enable_shared_cache sqlite3_api->enable_shared_cache
#define sqlite3_errcode sqlite3_api->errcode
#define sqlite3_errmsg sqlite3_api->errmsg
#define sqlite3_errmsg16 sqlite3_api->errmsg16
#define sqlite3_exec sqlite3_api->exec
#define sqlite3_expired sqlite3_api->expired
#define sqlite3_finalize sqlite3_api->finalize
#define sqlite3_free sqlite3_api->free
#define sqlite3_free_table sqlite3_api->free_table
#define sqlite3_get_autocommit sqlite3_api->get_autocommit
#define sqlite3_get_auxdata sqlite3_api->get_auxdata
#define sqlite3_get_table sqlite3_api->get_table
#define sqlite3_global_recover sqlite3_api->global_recover
#define sqlite3_interrupt sqlite3_api->interruptx
#define sqlite3_last_insert_rowid sqlite3_api->last_insert_rowid
#define sqlite3_libversion sqlite3_api->libversion
#define sqlite3_libversion_number sqlite3_api->libversion_number
#define sqlite3_malloc sqlite3_api->malloc
#define sqlite3_mprintf sqlite3_api->mprintf
#define sqlite3_open sqlite3_api->open
#define sqlite3_open16 sqlite3_api->open16
#define sqlite3_prepare sqlite3_api->prepare
#define sqlite3_prepare16 sqlite3_api->prepare16
#define sqlite3_profile sqlite3_api->profile
#define sqlite3_progress_handler sqlite3_api->progress_handler
#define sqlite3_realloc sqlite3_api->realloc
#define sqlite3_reset sqlite3_api->reset
#define sqlite3_result_blob sqlite3_api->result_blob
#define sqlite3_result_double sqlite3_api->result_double
#define sqlite3_result_error sqlite3_api->result_error
#define sqlite3_result_error16 sqlite3_api->result_error16
#define sqlite3_result_int sqlite3_api->result_int
#define sqlite3_result_int64 sqlite3_api->result_int64
#define sqlite3_result_null sqlite3_api->result_null
#define sqlite3_result_text sqlite3_api->result_text
#define sqlite3_result_text16 sqlite3_api->result_text16
#define sqlite3_result_text16be sqlite3_api->result_text16be
#define sqlite3_result_text16le sqlite3_api->result_text16le
#define sqlite3_result_value sqlite3_api->result_value
#define sqlite3_rollback_hook sqlite3_api->rollback_hook
#define sqlite3_set_authorizer sqlite3_api->set_authorizer
#define sqlite3_set_auxdata sqlite3_api->set_auxdata
#define sqlite3_snprintf sqlite3_api->snprintf
#define sqlite3_step sqlite3_api->step
#define sqlite3_table_column_metadata sqlite3_api->table_column_metadata
#define sqlite3_thread_cleanup sqlite3_api->thread_cleanup
#define sqlite3_total_changes sqlite3_api->total_changes
#define sqlite3_trace sqlite3_api->trace
#define sqlite3_transfer_bindings sqlite3_api->transfer_bindings
#define sqlite3_update_hook sqlite3_api->update_hook
#define sqlite3_user_data sqlite3_api->user_data
#define sqlite3_value_blob sqlite3_api->value_blob
#define sqlite3_value_bytes sqlite3_api->value_bytes
#define sqlite3_value_bytes16 sqlite3_api->value_bytes16
#define sqlite3_value_double sqlite3_api->value_double
#define sqlite3_value_int sqlite3_api->value_int
#define sqlite3_value_int64 sqlite3_api->value_int64
#define sqlite3_value_numeric_type sqlite3_api->value_numeric_type
#define sqlite3_value_text sqlite3_api->value_text
#define sqlite3_value_text16 sqlite3_api->value_text16
#define sqlite3_value_text16be sqlite3_api->value_text16be
#define sqlite3_value_text16le sqlite3_api->value_text16le
#define sqlite3_value_type sqlite3_api->value_type
#define sqlite3_vmprintf sqlite3_api->vmprintf
#define sqlite3_overload_function sqlite3_api->overload_function
#endif /* SQLITE_CORE */
#define SQLITE_EXTENSION_INIT1 const sqlite3_api_routines *sqlite3_api;
#define SQLITE_EXTENSION_INIT2(v) sqlite3_api = v;
#endif /* _SQLITE3EXT_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -1,198 +0,0 @@
/*
** 2001 September 15
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains the sqlite3_get_table() and sqlite3_free_table()
** interface routines. These are just wrappers around the main
** interface routine of sqlite3_exec().
**
** These routines are in a separate files so that they will not be linked
** if they are not used.
*/
#include "sqliteInt.h"
#include <stdlib.h>
#include <string.h>
#ifndef SQLITE_OMIT_GET_TABLE
/*
** This structure is used to pass data from sqlite3_get_table() through
** to the callback function is uses to build the result.
*/
typedef struct TabResult {
char **azResult;
char *zErrMsg;
int nResult;
int nAlloc;
int nRow;
int nColumn;
int nData;
int rc;
} TabResult;
/*
** This routine is called once for each row in the result table. Its job
** is to fill in the TabResult structure appropriately, allocating new
** memory as necessary.
*/
static int sqlite3_get_table_cb(void *pArg, int nCol, char **argv, char **colv){
TabResult *p = (TabResult*)pArg;
int need;
int i;
char *z;
/* Make sure there is enough space in p->azResult to hold everything
** we need to remember from this invocation of the callback.
*/
if( p->nRow==0 && argv!=0 ){
need = nCol*2;
}else{
need = nCol;
}
if( p->nData + need >= p->nAlloc ){
char **azNew;
p->nAlloc = p->nAlloc*2 + need + 1;
azNew = sqlite3_realloc( p->azResult, sizeof(char*)*p->nAlloc );
if( azNew==0 ) goto malloc_failed;
p->azResult = azNew;
}
/* If this is the first row, then generate an extra row containing
** the names of all columns.
*/
if( p->nRow==0 ){
p->nColumn = nCol;
for(i=0; i<nCol; i++){
if( colv[i]==0 ){
z = sqlite3_mprintf("");
}else{
z = sqlite3_mprintf("%s", colv[i]);
}
p->azResult[p->nData++] = z;
}
}else if( p->nColumn!=nCol ){
sqlite3SetString(&p->zErrMsg,
"sqlite3_get_table() called with two or more incompatible queries",
(char*)0);
p->rc = SQLITE_ERROR;
return 1;
}
/* Copy over the row data
*/
if( argv!=0 ){
for(i=0; i<nCol; i++){
if( argv[i]==0 ){
z = 0;
}else{
z = sqlite3_malloc( strlen(argv[i])+1 );
if( z==0 ) goto malloc_failed;
strcpy(z, argv[i]);
}
p->azResult[p->nData++] = z;
}
p->nRow++;
}
return 0;
malloc_failed:
p->rc = SQLITE_NOMEM;
return 1;
}
/*
** Query the database. But instead of invoking a callback for each row,
** malloc() for space to hold the result and return the entire results
** at the conclusion of the call.
**
** The result that is written to ***pazResult is held in memory obtained
** from malloc(). But the caller cannot free this memory directly.
** Instead, the entire table should be passed to sqlite3_free_table() when
** the calling procedure is finished using it.
*/
int sqlite3_get_table(
sqlite3 *db, /* The database on which the SQL executes */
const char *zSql, /* The SQL to be executed */
char ***pazResult, /* Write the result table here */
int *pnRow, /* Write the number of rows in the result here */
int *pnColumn, /* Write the number of columns of result here */
char **pzErrMsg /* Write error messages here */
){
int rc;
TabResult res;
if( pazResult==0 ){ return SQLITE_ERROR; }
*pazResult = 0;
if( pnColumn ) *pnColumn = 0;
if( pnRow ) *pnRow = 0;
res.zErrMsg = 0;
res.nResult = 0;
res.nRow = 0;
res.nColumn = 0;
res.nData = 1;
res.nAlloc = 20;
res.rc = SQLITE_OK;
res.azResult = sqlite3_malloc( sizeof(char*)*res.nAlloc );
if( res.azResult==0 ) return SQLITE_NOMEM;
res.azResult[0] = 0;
rc = sqlite3_exec(db, zSql, sqlite3_get_table_cb, &res, pzErrMsg);
if( res.azResult ){
assert( sizeof(res.azResult[0])>= sizeof(res.nData) );
res.azResult[0] = (char*)res.nData;
}
if( (rc&0xff)==SQLITE_ABORT ){
sqlite3_free_table(&res.azResult[1]);
if( res.zErrMsg ){
if( pzErrMsg ){
sqlite3_free(*pzErrMsg);
*pzErrMsg = sqlite3_mprintf("%s",res.zErrMsg);
}
sqliteFree(res.zErrMsg);
}
db->errCode = res.rc;
return res.rc & db->errMask;
}
sqliteFree(res.zErrMsg);
if( rc!=SQLITE_OK ){
sqlite3_free_table(&res.azResult[1]);
return rc & db->errMask;
}
if( res.nAlloc>res.nData ){
char **azNew;
azNew = sqlite3_realloc( res.azResult, sizeof(char*)*(res.nData+1) );
if( azNew==0 ){
sqlite3_free_table(&res.azResult[1]);
return SQLITE_NOMEM;
}
res.nAlloc = res.nData+1;
res.azResult = azNew;
}
*pazResult = &res.azResult[1];
if( pnColumn ) *pnColumn = res.nColumn;
if( pnRow ) *pnRow = res.nRow;
return rc & db->errMask;
}
/*
** This routine frees the space the sqlite3_get_table() malloced.
*/
void sqlite3_free_table(
char **azResult /* Result returned from from sqlite3_get_table() */
){
if( azResult ){
int i, n;
azResult--;
if( azResult==0 ) return;
n = (int)azResult[0];
for(i=1; i<n; i++){ if( azResult[i] ) sqlite3_free(azResult[i]); }
sqlite3_free(azResult);
}
}
#endif /* SQLITE_OMIT_GET_TABLE */

File diff suppressed because it is too large Load Diff

View File

@ -1,507 +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 splits an SQL input string up into
** individual tokens and sends those tokens one-by-one over to the
** parser for analysis.
**
** $Id: tokenize.c 3426 2007-03-21 20:19:37Z damagedsoul $
*/
#include "sqliteInt.h"
#include "os.h"
#include <ctype.h>
#include <stdlib.h>
/*
** The charMap() macro maps alphabetic characters into their
** lower-case ASCII equivalent. On ASCII machines, this is just
** an upper-to-lower case map. On EBCDIC machines we also need
** to adjust the encoding. Only alphabetic characters and underscores
** need to be translated.
*/
#ifdef SQLITE_ASCII
# define charMap(X) sqlite3UpperToLower[(unsigned char)X]
#endif
#ifdef SQLITE_EBCDIC
# define charMap(X) ebcdicToAscii[(unsigned char)X]
const unsigned char ebcdicToAscii[] = {
/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1x */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 2x */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 3x */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 4x */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 5x */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 95, 0, 0, /* 6x */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 7x */
0, 97, 98, 99,100,101,102,103,104,105, 0, 0, 0, 0, 0, 0, /* 8x */
0,106,107,108,109,110,111,112,113,114, 0, 0, 0, 0, 0, 0, /* 9x */
0, 0,115,116,117,118,119,120,121,122, 0, 0, 0, 0, 0, 0, /* Ax */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Bx */
0, 97, 98, 99,100,101,102,103,104,105, 0, 0, 0, 0, 0, 0, /* Cx */
0,106,107,108,109,110,111,112,113,114, 0, 0, 0, 0, 0, 0, /* Dx */
0, 0,115,116,117,118,119,120,121,122, 0, 0, 0, 0, 0, 0, /* Ex */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Fx */
};
#endif
/*
** The sqlite3KeywordCode function looks up an identifier to determine if
** it is a keyword. If it is a keyword, the token code of that keyword is
** returned. If the input is not a keyword, TK_ID is returned.
**
** The implementation of this routine was generated by a program,
** mkkeywordhash.h, located in the tool subdirectory of the distribution.
** The output of the mkkeywordhash.c program is written into a file
** named keywordhash.h and then included into this source file by
** the #include below.
*/
#include "keywordhash.h"
/*
** If X is a character that can be used in an identifier then
** IdChar(X) will be true. Otherwise it is false.
**
** For ASCII, any character with the high-order bit set is
** allowed in an identifier. For 7-bit characters,
** sqlite3IsIdChar[X] must be 1.
**
** For EBCDIC, the rules are more complex but have the same
** end result.
**
** Ticket #1066. the SQL standard does not allow '$' in the
** middle of identfiers. But many SQL implementations do.
** SQLite will allow '$' in identifiers for compatibility.
** But the feature is undocumented.
*/
#ifdef SQLITE_ASCII
const char sqlite3IsIdChar[] = {
/* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */
0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 2x */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 3x */
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 4x */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* 5x */
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 6x */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 7x */
};
#define IdChar(C) (((c=C)&0x80)!=0 || (c>0x1f && sqlite3IsIdChar[c-0x20]))
#endif
#ifdef SQLITE_EBCDIC
const char sqlite3IsIdChar[] = {
/* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */
0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 4x */
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, /* 5x */
0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, /* 6x */
0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, /* 7x */
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, /* 8x */
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, /* 9x */
1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, /* Ax */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Bx */
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, /* Cx */
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, /* Dx */
0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, /* Ex */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, /* Fx */
};
#define IdChar(C) (((c=C)>=0x42 && sqlite3IsIdChar[c-0x40]))
#endif
/*
** Return the length of the token that begins at z[0].
** Store the token type in *tokenType before returning.
*/
static int getToken(const unsigned char *z, int *tokenType){
int i, c;
switch( *z ){
case ' ': case '\t': case '\n': case '\f': case '\r': {
for(i=1; isspace(z[i]); i++){}
*tokenType = TK_SPACE;
return i;
}
case '-': {
if( z[1]=='-' ){
for(i=2; (c=z[i])!=0 && c!='\n'; i++){}
*tokenType = TK_COMMENT;
return i;
}
*tokenType = TK_MINUS;
return 1;
}
case '(': {
*tokenType = TK_LP;
return 1;
}
case ')': {
*tokenType = TK_RP;
return 1;
}
case ';': {
*tokenType = TK_SEMI;
return 1;
}
case '+': {
*tokenType = TK_PLUS;
return 1;
}
case '*': {
*tokenType = TK_STAR;
return 1;
}
case '/': {
if( z[1]!='*' || z[2]==0 ){
*tokenType = TK_SLASH;
return 1;
}
for(i=3, c=z[2]; (c!='*' || z[i]!='/') && (c=z[i])!=0; i++){}
if( c ) i++;
*tokenType = TK_COMMENT;
return i;
}
case '%': {
*tokenType = TK_REM;
return 1;
}
case '=': {
*tokenType = TK_EQ;
return 1 + (z[1]=='=');
}
case '<': {
if( (c=z[1])=='=' ){
*tokenType = TK_LE;
return 2;
}else if( c=='>' ){
*tokenType = TK_NE;
return 2;
}else if( c=='<' ){
*tokenType = TK_LSHIFT;
return 2;
}else{
*tokenType = TK_LT;
return 1;
}
}
case '>': {
if( (c=z[1])=='=' ){
*tokenType = TK_GE;
return 2;
}else if( c=='>' ){
*tokenType = TK_RSHIFT;
return 2;
}else{
*tokenType = TK_GT;
return 1;
}
}
case '!': {
if( z[1]!='=' ){
*tokenType = TK_ILLEGAL;
return 2;
}else{
*tokenType = TK_NE;
return 2;
}
}
case '|': {
if( z[1]!='|' ){
*tokenType = TK_BITOR;
return 1;
}else{
*tokenType = TK_CONCAT;
return 2;
}
}
case ',': {
*tokenType = TK_COMMA;
return 1;
}
case '&': {
*tokenType = TK_BITAND;
return 1;
}
case '~': {
*tokenType = TK_BITNOT;
return 1;
}
case '`':
case '\'':
case '"': {
int delim = z[0];
for(i=1; (c=z[i])!=0; i++){
if( c==delim ){
if( z[i+1]==delim ){
i++;
}else{
break;
}
}
}
if( c ){
*tokenType = TK_STRING;
return i+1;
}else{
*tokenType = TK_ILLEGAL;
return i;
}
}
case '.': {
#ifndef SQLITE_OMIT_FLOATING_POINT
if( !isdigit(z[1]) )
#endif
{
*tokenType = TK_DOT;
return 1;
}
/* If the next character is a digit, this is a floating point
** number that begins with ".". Fall thru into the next case */
}
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9': {
*tokenType = TK_INTEGER;
for(i=0; isdigit(z[i]); i++){}
#ifndef SQLITE_OMIT_FLOATING_POINT
if( z[i]=='.' ){
i++;
while( isdigit(z[i]) ){ i++; }
*tokenType = TK_FLOAT;
}
if( (z[i]=='e' || z[i]=='E') &&
( isdigit(z[i+1])
|| ((z[i+1]=='+' || z[i+1]=='-') && isdigit(z[i+2]))
)
){
i += 2;
while( isdigit(z[i]) ){ i++; }
*tokenType = TK_FLOAT;
}
#endif
while( IdChar(z[i]) ){
*tokenType = TK_ILLEGAL;
i++;
}
return i;
}
case '[': {
for(i=1, c=z[0]; c!=']' && (c=z[i])!=0; i++){}
*tokenType = TK_ID;
return i;
}
case '?': {
*tokenType = TK_VARIABLE;
for(i=1; isdigit(z[i]); i++){}
return i;
}
case '#': {
for(i=1; isdigit(z[i]); i++){}
if( i>1 ){
/* Parameters of the form #NNN (where NNN is a number) are used
** internally by sqlite3NestedParse. */
*tokenType = TK_REGISTER;
return i;
}
/* Fall through into the next case if the '#' is not followed by
** a digit. Try to match #AAAA where AAAA is a parameter name. */
}
#ifndef SQLITE_OMIT_TCL_VARIABLE
case '$':
#endif
case '@': /* For compatibility with MS SQL Server */
case ':': {
int n = 0;
*tokenType = TK_VARIABLE;
for(i=1; (c=z[i])!=0; i++){
if( IdChar(c) ){
n++;
#ifndef SQLITE_OMIT_TCL_VARIABLE
}else if( c=='(' && n>0 ){
do{
i++;
}while( (c=z[i])!=0 && !isspace(c) && c!=')' );
if( c==')' ){
i++;
}else{
*tokenType = TK_ILLEGAL;
}
break;
}else if( c==':' && z[i+1]==':' ){
i++;
#endif
}else{
break;
}
}
if( n==0 ) *tokenType = TK_ILLEGAL;
return i;
}
#ifndef SQLITE_OMIT_BLOB_LITERAL
case 'x': case 'X': {
if( (c=z[1])=='\'' || c=='"' ){
int delim = c;
*tokenType = TK_BLOB;
for(i=2; (c=z[i])!=0; i++){
if( c==delim ){
if( i%2 ) *tokenType = TK_ILLEGAL;
break;
}
if( !isxdigit(c) ){
*tokenType = TK_ILLEGAL;
return i;
}
}
if( c ) i++;
return i;
}
/* Otherwise fall through to the next case */
}
#endif
default: {
if( !IdChar(*z) ){
break;
}
for(i=1; IdChar(z[i]); i++){}
*tokenType = keywordCode((char*)z, i);
return i;
}
}
*tokenType = TK_ILLEGAL;
return 1;
}
int sqlite3GetToken(const unsigned char *z, int *tokenType){
return getToken(z, tokenType);
}
/*
** Run the parser on the given SQL string. The parser structure is
** passed in. An SQLITE_ status code is returned. If an error occurs
** and pzErrMsg!=NULL then an error message might be written into
** memory obtained from malloc() and *pzErrMsg made to point to that
** error message. Or maybe not.
*/
int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){
int nErr = 0;
int i;
void *pEngine;
int tokenType;
int lastTokenParsed = -1;
sqlite3 *db = pParse->db;
extern void *sqlite3ParserAlloc(void*(*)(size_t));
extern void sqlite3ParserFree(void*, void(*)(void*));
extern void sqlite3Parser(void*, int, Token, Parse*);
if( db->activeVdbeCnt==0 ){
db->u1.isInterrupted = 0;
}
pParse->rc = SQLITE_OK;
i = 0;
pEngine = sqlite3ParserAlloc((void*(*)(size_t))sqlite3MallocX);
if( pEngine==0 ){
return SQLITE_NOMEM;
}
assert( pParse->sLastToken.dyn==0 );
assert( pParse->pNewTable==0 );
assert( pParse->pNewTrigger==0 );
assert( pParse->nVar==0 );
assert( pParse->nVarExpr==0 );
assert( pParse->nVarExprAlloc==0 );
assert( pParse->apVarExpr==0 );
pParse->zTail = pParse->zSql = zSql;
while( !sqlite3MallocFailed() && zSql[i]!=0 ){
assert( i>=0 );
pParse->sLastToken.z = (u8*)&zSql[i];
assert( pParse->sLastToken.dyn==0 );
pParse->sLastToken.n = getToken((unsigned char*)&zSql[i],&tokenType);
i += pParse->sLastToken.n;
switch( tokenType ){
case TK_SPACE:
case TK_COMMENT: {
if( db->u1.isInterrupted ){
pParse->rc = SQLITE_INTERRUPT;
sqlite3SetString(pzErrMsg, "interrupt", (char*)0);
goto abort_parse;
}
break;
}
case TK_ILLEGAL: {
if( pzErrMsg ){
sqliteFree(*pzErrMsg);
*pzErrMsg = sqlite3MPrintf("unrecognized token: \"%T\"",
&pParse->sLastToken);
}
nErr++;
goto abort_parse;
}
case TK_SEMI: {
pParse->zTail = &zSql[i];
/* Fall thru into the default case */
}
default: {
sqlite3Parser(pEngine, tokenType, pParse->sLastToken, pParse);
lastTokenParsed = tokenType;
if( pParse->rc!=SQLITE_OK ){
goto abort_parse;
}
break;
}
}
}
abort_parse:
if( zSql[i]==0 && nErr==0 && pParse->rc==SQLITE_OK ){
if( lastTokenParsed!=TK_SEMI ){
sqlite3Parser(pEngine, TK_SEMI, pParse->sLastToken, pParse);
pParse->zTail = &zSql[i];
}
sqlite3Parser(pEngine, 0, pParse->sLastToken, pParse);
}
sqlite3ParserFree(pEngine, sqlite3FreeX);
if( sqlite3MallocFailed() ){
pParse->rc = SQLITE_NOMEM;
}
if( pParse->rc!=SQLITE_OK && pParse->rc!=SQLITE_DONE && pParse->zErrMsg==0 ){
sqlite3SetString(&pParse->zErrMsg, sqlite3ErrStr(pParse->rc), (char*)0);
}
if( pParse->zErrMsg ){
if( pzErrMsg && *pzErrMsg==0 ){
*pzErrMsg = pParse->zErrMsg;
}else{
sqliteFree(pParse->zErrMsg);
}
pParse->zErrMsg = 0;
if( !nErr ) nErr++;
}
if( pParse->pVdbe && pParse->nErr>0 && pParse->nested==0 ){
sqlite3VdbeDelete(pParse->pVdbe);
pParse->pVdbe = 0;
}
#ifndef SQLITE_OMIT_SHARED_CACHE
if( pParse->nested==0 ){
sqliteFree(pParse->aTableLock);
pParse->aTableLock = 0;
pParse->nTableLock = 0;
}
#endif
if( !IN_DECLARE_VTAB ){
/* If the pParse->declareVtab flag is set, do not delete any table
** structure built up in pParse->pNewTable. The calling code (see vtab.c)
** will take responsibility for freeing the Table structure.
*/
sqlite3DeleteTable(pParse->db, pParse->pNewTable);
}
sqlite3DeleteTrigger(pParse->pNewTrigger);
sqliteFree(pParse->apVarExpr);
if( nErr>0 && (pParse->rc==SQLITE_OK || pParse->rc==SQLITE_DONE) ){
pParse->rc = SQLITE_ERROR;
}
return nErr;
}

View File

@ -1,823 +0,0 @@
/*
**
** 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.
**
*************************************************************************
*
*/
#include "sqliteInt.h"
#ifndef SQLITE_OMIT_TRIGGER
/*
** Delete a linked list of TriggerStep structures.
*/
void sqlite3DeleteTriggerStep(TriggerStep *pTriggerStep){
while( pTriggerStep ){
TriggerStep * pTmp = pTriggerStep;
pTriggerStep = pTriggerStep->pNext;
if( pTmp->target.dyn ) sqliteFree((char*)pTmp->target.z);
sqlite3ExprDelete(pTmp->pWhere);
sqlite3ExprListDelete(pTmp->pExprList);
sqlite3SelectDelete(pTmp->pSelect);
sqlite3IdListDelete(pTmp->pIdList);
sqliteFree(pTmp);
}
}
/*
** This is called by the parser when it sees a CREATE TRIGGER statement
** up to the point of the BEGIN before the trigger actions. A Trigger
** structure is generated based on the information available and stored
** in pParse->pNewTrigger. After the trigger actions have been parsed, the
** sqlite3FinishTrigger() function is called to complete the trigger
** construction process.
*/
void sqlite3BeginTrigger(
Parse *pParse, /* The parse context of the CREATE TRIGGER statement */
Token *pName1, /* The name of the trigger */
Token *pName2, /* The name of the trigger */
int tr_tm, /* One of TK_BEFORE, TK_AFTER, TK_INSTEAD */
int op, /* One of TK_INSERT, TK_UPDATE, TK_DELETE */
IdList *pColumns, /* column list if this is an UPDATE OF trigger */
SrcList *pTableName,/* The name of the table/view the trigger applies to */
int foreach, /* One of TK_ROW or TK_STATEMENT */
Expr *pWhen, /* WHEN clause */
int isTemp, /* True if the TEMPORARY keyword is present */
int noErr /* Suppress errors if the trigger already exists */
){
Trigger *pTrigger = 0;
Table *pTab;
char *zName = 0; /* Name of the trigger */
sqlite3 *db = pParse->db;
int iDb; /* The database to store the trigger in */
Token *pName; /* The unqualified db name */
DbFixer sFix;
int iTabDb;
assert( pName1!=0 ); /* pName1->z might be NULL, but not pName1 itself */
assert( pName2!=0 );
if( isTemp ){
/* If TEMP was specified, then the trigger name may not be qualified. */
if( pName2->n>0 ){
sqlite3ErrorMsg(pParse, "temporary trigger may not have qualified name");
goto trigger_cleanup;
}
iDb = 1;
pName = pName1;
}else{
/* Figure out the db that the the trigger will be created in */
iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pName);
if( iDb<0 ){
goto trigger_cleanup;
}
}
/* If the trigger name was unqualified, and the table is a temp table,
** then set iDb to 1 to create the trigger in the temporary database.
** If sqlite3SrcListLookup() returns 0, indicating the table does not
** exist, the error is caught by the block below.
*/
if( !pTableName || sqlite3MallocFailed() ){
goto trigger_cleanup;
}
pTab = sqlite3SrcListLookup(pParse, pTableName);
if( pName2->n==0 && pTab && pTab->pSchema==db->aDb[1].pSchema ){
iDb = 1;
}
/* Ensure the table name matches database name and that the table exists */
if( sqlite3MallocFailed() ) goto trigger_cleanup;
assert( pTableName->nSrc==1 );
if( sqlite3FixInit(&sFix, pParse, iDb, "trigger", pName) &&
sqlite3FixSrcList(&sFix, pTableName) ){
goto trigger_cleanup;
}
pTab = sqlite3SrcListLookup(pParse, pTableName);
if( !pTab ){
/* The table does not exist. */
goto trigger_cleanup;
}
if( IsVirtual(pTab) ){
sqlite3ErrorMsg(pParse, "cannot create triggers on virtual tables");
goto trigger_cleanup;
}
/* Check that the trigger name is not reserved and that no trigger of the
** specified name exists */
zName = sqlite3NameFromToken(pName);
if( !zName || SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){
goto trigger_cleanup;
}
if( sqlite3HashFind(&(db->aDb[iDb].pSchema->trigHash), zName,strlen(zName)) ){
if( !noErr ){
sqlite3ErrorMsg(pParse, "trigger %T already exists", pName);
}
goto trigger_cleanup;
}
/* Do not create a trigger on a system table */
if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0 ){
sqlite3ErrorMsg(pParse, "cannot create trigger on system table");
pParse->nErr++;
goto trigger_cleanup;
}
/* INSTEAD of triggers are only for views and views only support INSTEAD
** of triggers.
*/
if( pTab->pSelect && tr_tm!=TK_INSTEAD ){
sqlite3ErrorMsg(pParse, "cannot create %s trigger on view: %S",
(tr_tm == TK_BEFORE)?"BEFORE":"AFTER", pTableName, 0);
goto trigger_cleanup;
}
if( !pTab->pSelect && tr_tm==TK_INSTEAD ){
sqlite3ErrorMsg(pParse, "cannot create INSTEAD OF"
" trigger on table: %S", pTableName, 0);
goto trigger_cleanup;
}
iTabDb = sqlite3SchemaToIndex(db, pTab->pSchema);
#ifndef SQLITE_OMIT_AUTHORIZATION
{
int code = SQLITE_CREATE_TRIGGER;
const char *zDb = db->aDb[iTabDb].zName;
const char *zDbTrig = isTemp ? db->aDb[1].zName : zDb;
if( iTabDb==1 || isTemp ) code = SQLITE_CREATE_TEMP_TRIGGER;
if( sqlite3AuthCheck(pParse, code, zName, pTab->zName, zDbTrig) ){
goto trigger_cleanup;
}
if( sqlite3AuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(iTabDb),0,zDb)){
goto trigger_cleanup;
}
}
#endif
/* INSTEAD OF triggers can only appear on views and BEFORE triggers
** cannot appear on views. So we might as well translate every
** INSTEAD OF trigger into a BEFORE trigger. It simplifies code
** elsewhere.
*/
if (tr_tm == TK_INSTEAD){
tr_tm = TK_BEFORE;
}
/* Build the Trigger object */
pTrigger = (Trigger*)sqliteMalloc(sizeof(Trigger));
if( pTrigger==0 ) goto trigger_cleanup;
pTrigger->name = zName;
zName = 0;
pTrigger->table = sqliteStrDup(pTableName->a[0].zName);
pTrigger->pSchema = db->aDb[iDb].pSchema;
pTrigger->pTabSchema = pTab->pSchema;
pTrigger->op = op;
pTrigger->tr_tm = tr_tm==TK_BEFORE ? TRIGGER_BEFORE : TRIGGER_AFTER;
pTrigger->pWhen = sqlite3ExprDup(pWhen);
pTrigger->pColumns = sqlite3IdListDup(pColumns);
pTrigger->foreach = foreach;
sqlite3TokenCopy(&pTrigger->nameToken,pName);
assert( pParse->pNewTrigger==0 );
pParse->pNewTrigger = pTrigger;
trigger_cleanup:
sqliteFree(zName);
sqlite3SrcListDelete(pTableName);
sqlite3IdListDelete(pColumns);
sqlite3ExprDelete(pWhen);
if( !pParse->pNewTrigger ){
sqlite3DeleteTrigger(pTrigger);
}else{
assert( pParse->pNewTrigger==pTrigger );
}
}
/*
** This routine is called after all of the trigger actions have been parsed
** in order to complete the process of building the trigger.
*/
void sqlite3FinishTrigger(
Parse *pParse, /* Parser context */
TriggerStep *pStepList, /* The triggered program */
Token *pAll /* Token that describes the complete CREATE TRIGGER */
){
Trigger *pTrig = 0; /* The trigger whose construction is finishing up */
sqlite3 *db = pParse->db; /* The database */
DbFixer sFix;
int iDb; /* Database containing the trigger */
pTrig = pParse->pNewTrigger;
pParse->pNewTrigger = 0;
if( pParse->nErr || !pTrig ) goto triggerfinish_cleanup;
iDb = sqlite3SchemaToIndex(pParse->db, pTrig->pSchema);
pTrig->step_list = pStepList;
while( pStepList ){
pStepList->pTrig = pTrig;
pStepList = pStepList->pNext;
}
if( sqlite3FixInit(&sFix, pParse, iDb, "trigger", &pTrig->nameToken)
&& sqlite3FixTriggerStep(&sFix, pTrig->step_list) ){
goto triggerfinish_cleanup;
}
/* if we are not initializing, and this trigger is not on a TEMP table,
** build the sqlite_master entry
*/
if( !db->init.busy ){
static const VdbeOpList insertTrig[] = {
{ OP_NewRowid, 0, 0, 0 },
{ OP_String8, 0, 0, "trigger" },
{ OP_String8, 0, 0, 0 }, /* 2: trigger name */
{ OP_String8, 0, 0, 0 }, /* 3: table name */
{ OP_Integer, 0, 0, 0 },
{ OP_String8, 0, 0, "CREATE TRIGGER "},
{ OP_String8, 0, 0, 0 }, /* 6: SQL */
{ OP_Concat, 0, 0, 0 },
{ OP_MakeRecord, 5, 0, "aaada" },
{ OP_Insert, 0, 0, 0 },
};
int addr;
Vdbe *v;
/* Make an entry in the sqlite_master table */
v = sqlite3GetVdbe(pParse);
if( v==0 ) goto triggerfinish_cleanup;
sqlite3BeginWriteOperation(pParse, 0, iDb);
sqlite3OpenMasterTable(pParse, iDb);
addr = sqlite3VdbeAddOpList(v, ArraySize(insertTrig), insertTrig);
sqlite3VdbeChangeP3(v, addr+2, pTrig->name, 0);
sqlite3VdbeChangeP3(v, addr+3, pTrig->table, 0);
sqlite3VdbeChangeP3(v, addr+6, (char*)pAll->z, pAll->n);
sqlite3ChangeCookie(db, v, iDb);
sqlite3VdbeAddOp(v, OP_Close, 0, 0);
sqlite3VdbeOp3(v, OP_ParseSchema, iDb, 0,
sqlite3MPrintf("type='trigger' AND name='%q'", pTrig->name), P3_DYNAMIC);
}
if( db->init.busy ){
int n;
Table *pTab;
Trigger *pDel;
pDel = sqlite3HashInsert(&db->aDb[iDb].pSchema->trigHash,
pTrig->name, strlen(pTrig->name), pTrig);
if( pDel ){
assert( sqlite3MallocFailed() && pDel==pTrig );
goto triggerfinish_cleanup;
}
n = strlen(pTrig->table) + 1;
pTab = sqlite3HashFind(&pTrig->pTabSchema->tblHash, pTrig->table, n);
assert( pTab!=0 );
pTrig->pNext = pTab->pTrigger;
pTab->pTrigger = pTrig;
pTrig = 0;
}
triggerfinish_cleanup:
sqlite3DeleteTrigger(pTrig);
assert( !pParse->pNewTrigger );
sqlite3DeleteTriggerStep(pStepList);
}
/*
** Make a copy of all components of the given trigger step. This has
** the effect of copying all Expr.token.z values into memory obtained
** from sqliteMalloc(). As initially created, the Expr.token.z values
** all point to the input string that was fed to the parser. But that
** string is ephemeral - it will go away as soon as the sqlite3_exec()
** call that started the parser exits. This routine makes a persistent
** copy of all the Expr.token.z strings so that the TriggerStep structure
** will be valid even after the sqlite3_exec() call returns.
*/
static void sqlitePersistTriggerStep(TriggerStep *p){
if( p->target.z ){
p->target.z = (u8*)sqliteStrNDup((char*)p->target.z, p->target.n);
p->target.dyn = 1;
}
if( p->pSelect ){
Select *pNew = sqlite3SelectDup(p->pSelect);
sqlite3SelectDelete(p->pSelect);
p->pSelect = pNew;
}
if( p->pWhere ){
Expr *pNew = sqlite3ExprDup(p->pWhere);
sqlite3ExprDelete(p->pWhere);
p->pWhere = pNew;
}
if( p->pExprList ){
ExprList *pNew = sqlite3ExprListDup(p->pExprList);
sqlite3ExprListDelete(p->pExprList);
p->pExprList = pNew;
}
if( p->pIdList ){
IdList *pNew = sqlite3IdListDup(p->pIdList);
sqlite3IdListDelete(p->pIdList);
p->pIdList = pNew;
}
}
/*
** Turn a SELECT statement (that the pSelect parameter points to) into
** a trigger step. Return a pointer to a TriggerStep structure.
**
** The parser calls this routine when it finds a SELECT statement in
** body of a TRIGGER.
*/
TriggerStep *sqlite3TriggerSelectStep(Select *pSelect){
TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep));
if( pTriggerStep==0 ) {
sqlite3SelectDelete(pSelect);
return 0;
}
pTriggerStep->op = TK_SELECT;
pTriggerStep->pSelect = pSelect;
pTriggerStep->orconf = OE_Default;
sqlitePersistTriggerStep(pTriggerStep);
return pTriggerStep;
}
/*
** Build a trigger step out of an INSERT statement. Return a pointer
** to the new trigger step.
**
** The parser calls this routine when it sees an INSERT inside the
** body of a trigger.
*/
TriggerStep *sqlite3TriggerInsertStep(
Token *pTableName, /* Name of the table into which we insert */
IdList *pColumn, /* List of columns in pTableName to insert into */
ExprList *pEList, /* The VALUE clause: a list of values to be inserted */
Select *pSelect, /* A SELECT statement that supplies values */
int orconf /* The conflict algorithm (OE_Abort, OE_Replace, etc.) */
){
TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep));
assert(pEList == 0 || pSelect == 0);
assert(pEList != 0 || pSelect != 0);
if( pTriggerStep ){
pTriggerStep->op = TK_INSERT;
pTriggerStep->pSelect = pSelect;
pTriggerStep->target = *pTableName;
pTriggerStep->pIdList = pColumn;
pTriggerStep->pExprList = pEList;
pTriggerStep->orconf = orconf;
sqlitePersistTriggerStep(pTriggerStep);
}else{
sqlite3IdListDelete(pColumn);
sqlite3ExprListDelete(pEList);
sqlite3SelectDup(pSelect);
}
return pTriggerStep;
}
/*
** Construct a trigger step that implements an UPDATE statement and return
** a pointer to that trigger step. The parser calls this routine when it
** sees an UPDATE statement inside the body of a CREATE TRIGGER.
*/
TriggerStep *sqlite3TriggerUpdateStep(
Token *pTableName, /* Name of the table to be updated */
ExprList *pEList, /* The SET clause: list of column and new values */
Expr *pWhere, /* The WHERE clause */
int orconf /* The conflict algorithm. (OE_Abort, OE_Ignore, etc) */
){
TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep));
if( pTriggerStep==0 ) return 0;
pTriggerStep->op = TK_UPDATE;
pTriggerStep->target = *pTableName;
pTriggerStep->pExprList = pEList;
pTriggerStep->pWhere = pWhere;
pTriggerStep->orconf = orconf;
sqlitePersistTriggerStep(pTriggerStep);
return pTriggerStep;
}
/*
** Construct a trigger step that implements a DELETE statement and return
** a pointer to that trigger step. The parser calls this routine when it
** sees a DELETE statement inside the body of a CREATE TRIGGER.
*/
TriggerStep *sqlite3TriggerDeleteStep(Token *pTableName, Expr *pWhere){
TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep));
if( pTriggerStep==0 ) return 0;
pTriggerStep->op = TK_DELETE;
pTriggerStep->target = *pTableName;
pTriggerStep->pWhere = pWhere;
pTriggerStep->orconf = OE_Default;
sqlitePersistTriggerStep(pTriggerStep);
return pTriggerStep;
}
/*
** Recursively delete a Trigger structure
*/
void sqlite3DeleteTrigger(Trigger *pTrigger){
if( pTrigger==0 ) return;
sqlite3DeleteTriggerStep(pTrigger->step_list);
sqliteFree(pTrigger->name);
sqliteFree(pTrigger->table);
sqlite3ExprDelete(pTrigger->pWhen);
sqlite3IdListDelete(pTrigger->pColumns);
if( pTrigger->nameToken.dyn ) sqliteFree((char*)pTrigger->nameToken.z);
sqliteFree(pTrigger);
}
/*
** This function is called to drop a trigger from the database schema.
**
** This may be called directly from the parser and therefore identifies
** the trigger by name. The sqlite3DropTriggerPtr() routine does the
** same job as this routine except it takes a pointer to the trigger
** instead of the trigger name.
**/
void sqlite3DropTrigger(Parse *pParse, SrcList *pName, int noErr){
Trigger *pTrigger = 0;
int i;
const char *zDb;
const char *zName;
int nName;
sqlite3 *db = pParse->db;
if( sqlite3MallocFailed() ) goto drop_trigger_cleanup;
if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){
goto drop_trigger_cleanup;
}
assert( pName->nSrc==1 );
zDb = pName->a[0].zDatabase;
zName = pName->a[0].zName;
nName = strlen(zName);
for(i=OMIT_TEMPDB; i<db->nDb; i++){
int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */
if( zDb && sqlite3StrICmp(db->aDb[j].zName, zDb) ) continue;
pTrigger = sqlite3HashFind(&(db->aDb[j].pSchema->trigHash), zName, nName);
if( pTrigger ) break;
}
if( !pTrigger ){
if( !noErr ){
sqlite3ErrorMsg(pParse, "no such trigger: %S", pName, 0);
}
goto drop_trigger_cleanup;
}
sqlite3DropTriggerPtr(pParse, pTrigger);
drop_trigger_cleanup:
sqlite3SrcListDelete(pName);
}
/*
** Return a pointer to the Table structure for the table that a trigger
** is set on.
*/
static Table *tableOfTrigger(Trigger *pTrigger){
int n = strlen(pTrigger->table) + 1;
return sqlite3HashFind(&pTrigger->pTabSchema->tblHash, pTrigger->table, n);
}
/*
** Drop a trigger given a pointer to that trigger.
*/
void sqlite3DropTriggerPtr(Parse *pParse, Trigger *pTrigger){
Table *pTable;
Vdbe *v;
sqlite3 *db = pParse->db;
int iDb;
iDb = sqlite3SchemaToIndex(pParse->db, pTrigger->pSchema);
assert( iDb>=0 && iDb<db->nDb );
pTable = tableOfTrigger(pTrigger);
assert( pTable );
assert( pTable->pSchema==pTrigger->pSchema || iDb==1 );
#ifndef SQLITE_OMIT_AUTHORIZATION
{
int code = SQLITE_DROP_TRIGGER;
const char *zDb = db->aDb[iDb].zName;
const char *zTab = SCHEMA_TABLE(iDb);
if( iDb==1 ) code = SQLITE_DROP_TEMP_TRIGGER;
if( sqlite3AuthCheck(pParse, code, pTrigger->name, pTable->zName, zDb) ||
sqlite3AuthCheck(pParse, SQLITE_DELETE, zTab, 0, zDb) ){
return;
}
}
#endif
/* Generate code to destroy the database record of the trigger.
*/
assert( pTable!=0 );
if( (v = sqlite3GetVdbe(pParse))!=0 ){
int base;
static const VdbeOpList dropTrigger[] = {
{ OP_Rewind, 0, ADDR(9), 0},
{ OP_String8, 0, 0, 0}, /* 1 */
{ OP_Column, 0, 1, 0},
{ OP_Ne, 0, ADDR(8), 0},
{ OP_String8, 0, 0, "trigger"},
{ OP_Column, 0, 0, 0},
{ OP_Ne, 0, ADDR(8), 0},
{ OP_Delete, 0, 0, 0},
{ OP_Next, 0, ADDR(1), 0}, /* 8 */
};
sqlite3BeginWriteOperation(pParse, 0, iDb);
sqlite3OpenMasterTable(pParse, iDb);
base = sqlite3VdbeAddOpList(v, ArraySize(dropTrigger), dropTrigger);
sqlite3VdbeChangeP3(v, base+1, pTrigger->name, 0);
sqlite3ChangeCookie(db, v, iDb);
sqlite3VdbeAddOp(v, OP_Close, 0, 0);
sqlite3VdbeOp3(v, OP_DropTrigger, iDb, 0, pTrigger->name, 0);
}
}
/*
** Remove a trigger from the hash tables of the sqlite* pointer.
*/
void sqlite3UnlinkAndDeleteTrigger(sqlite3 *db, int iDb, const char *zName){
Trigger *pTrigger;
int nName = strlen(zName);
pTrigger = sqlite3HashInsert(&(db->aDb[iDb].pSchema->trigHash),
zName, nName, 0);
if( pTrigger ){
Table *pTable = tableOfTrigger(pTrigger);
assert( pTable!=0 );
if( pTable->pTrigger == pTrigger ){
pTable->pTrigger = pTrigger->pNext;
}else{
Trigger *cc = pTable->pTrigger;
while( cc ){
if( cc->pNext == pTrigger ){
cc->pNext = cc->pNext->pNext;
break;
}
cc = cc->pNext;
}
assert(cc);
}
sqlite3DeleteTrigger(pTrigger);
db->flags |= SQLITE_InternChanges;
}
}
/*
** pEList is the SET clause of an UPDATE statement. Each entry
** in pEList is of the format <id>=<expr>. If any of the entries
** in pEList have an <id> which matches an identifier in pIdList,
** then return TRUE. If pIdList==NULL, then it is considered a
** wildcard that matches anything. Likewise if pEList==NULL then
** it matches anything so always return true. Return false only
** if there is no match.
*/
static int checkColumnOverLap(IdList *pIdList, ExprList *pEList){
int e;
if( !pIdList || !pEList ) return 1;
for(e=0; e<pEList->nExpr; e++){
if( sqlite3IdListIndex(pIdList, pEList->a[e].zName)>=0 ) return 1;
}
return 0;
}
/*
** Return a bit vector to indicate what kind of triggers exist for operation
** "op" on table pTab. If pChanges is not NULL then it is a list of columns
** that are being updated. Triggers only match if the ON clause of the
** trigger definition overlaps the set of columns being updated.
**
** The returned bit vector is some combination of TRIGGER_BEFORE and
** TRIGGER_AFTER.
*/
int sqlite3TriggersExist(
Parse *pParse, /* Used to check for recursive triggers */
Table *pTab, /* The table the contains the triggers */
int op, /* one of TK_DELETE, TK_INSERT, TK_UPDATE */
ExprList *pChanges /* Columns that change in an UPDATE statement */
){
Trigger *pTrigger;
int mask = 0;
pTrigger = IsVirtual(pTab) ? 0 : pTab->pTrigger;
while( pTrigger ){
if( pTrigger->op==op && checkColumnOverLap(pTrigger->pColumns, pChanges) ){
mask |= pTrigger->tr_tm;
}
pTrigger = pTrigger->pNext;
}
return mask;
}
/*
** Convert the pStep->target token into a SrcList and return a pointer
** to that SrcList.
**
** This routine adds a specific database name, if needed, to the target when
** forming the SrcList. This prevents a trigger in one database from
** referring to a target in another database. An exception is when the
** trigger is in TEMP in which case it can refer to any other database it
** wants.
*/
static SrcList *targetSrcList(
Parse *pParse, /* The parsing context */
TriggerStep *pStep /* The trigger containing the target token */
){
Token sDb; /* Dummy database name token */
int iDb; /* Index of the database to use */
SrcList *pSrc; /* SrcList to be returned */
iDb = sqlite3SchemaToIndex(pParse->db, pStep->pTrig->pSchema);
if( iDb==0 || iDb>=2 ){
assert( iDb<pParse->db->nDb );
sDb.z = (u8*)pParse->db->aDb[iDb].zName;
sDb.n = strlen((char*)sDb.z);
pSrc = sqlite3SrcListAppend(0, &sDb, &pStep->target);
} else {
pSrc = sqlite3SrcListAppend(0, &pStep->target, 0);
}
return pSrc;
}
/*
** Generate VDBE code for zero or more statements inside the body of a
** trigger.
*/
static int codeTriggerProgram(
Parse *pParse, /* The parser context */
TriggerStep *pStepList, /* List of statements inside the trigger body */
int orconfin /* Conflict algorithm. (OE_Abort, etc) */
){
TriggerStep * pTriggerStep = pStepList;
int orconf;
Vdbe *v = pParse->pVdbe;
assert( pTriggerStep!=0 );
assert( v!=0 );
sqlite3VdbeAddOp(v, OP_ContextPush, 0, 0);
VdbeComment((v, "# begin trigger %s", pStepList->pTrig->name));
while( pTriggerStep ){
orconf = (orconfin == OE_Default)?pTriggerStep->orconf:orconfin;
pParse->trigStack->orconf = orconf;
switch( pTriggerStep->op ){
case TK_SELECT: {
Select *ss = sqlite3SelectDup(pTriggerStep->pSelect);
if( ss ){
sqlite3SelectResolve(pParse, ss, 0);
sqlite3Select(pParse, ss, SRT_Discard, 0, 0, 0, 0, 0);
sqlite3SelectDelete(ss);
}
break;
}
case TK_UPDATE: {
SrcList *pSrc;
pSrc = targetSrcList(pParse, pTriggerStep);
sqlite3VdbeAddOp(v, OP_ResetCount, 0, 0);
sqlite3Update(pParse, pSrc,
sqlite3ExprListDup(pTriggerStep->pExprList),
sqlite3ExprDup(pTriggerStep->pWhere), orconf);
sqlite3VdbeAddOp(v, OP_ResetCount, 1, 0);
break;
}
case TK_INSERT: {
SrcList *pSrc;
pSrc = targetSrcList(pParse, pTriggerStep);
sqlite3VdbeAddOp(v, OP_ResetCount, 0, 0);
sqlite3Insert(pParse, pSrc,
sqlite3ExprListDup(pTriggerStep->pExprList),
sqlite3SelectDup(pTriggerStep->pSelect),
sqlite3IdListDup(pTriggerStep->pIdList), orconf);
sqlite3VdbeAddOp(v, OP_ResetCount, 1, 0);
break;
}
case TK_DELETE: {
SrcList *pSrc;
sqlite3VdbeAddOp(v, OP_ResetCount, 0, 0);
pSrc = targetSrcList(pParse, pTriggerStep);
sqlite3DeleteFrom(pParse, pSrc, sqlite3ExprDup(pTriggerStep->pWhere));
sqlite3VdbeAddOp(v, OP_ResetCount, 1, 0);
break;
}
default:
assert(0);
}
pTriggerStep = pTriggerStep->pNext;
}
sqlite3VdbeAddOp(v, OP_ContextPop, 0, 0);
VdbeComment((v, "# end trigger %s", pStepList->pTrig->name));
return 0;
}
/*
** This is called to code FOR EACH ROW triggers.
**
** When the code that this function generates is executed, the following
** must be true:
**
** 1. No cursors may be open in the main database. (But newIdx and oldIdx
** can be indices of cursors in temporary tables. See below.)
**
** 2. If the triggers being coded are ON INSERT or ON UPDATE triggers, then
** a temporary vdbe cursor (index newIdx) must be open and pointing at
** a row containing values to be substituted for new.* expressions in the
** trigger program(s).
**
** 3. If the triggers being coded are ON DELETE or ON UPDATE triggers, then
** a temporary vdbe cursor (index oldIdx) must be open and pointing at
** a row containing values to be substituted for old.* expressions in the
** trigger program(s).
**
*/
int sqlite3CodeRowTrigger(
Parse *pParse, /* Parse context */
int op, /* One of TK_UPDATE, TK_INSERT, TK_DELETE */
ExprList *pChanges, /* Changes list for any UPDATE OF triggers */
int tr_tm, /* One of TRIGGER_BEFORE, TRIGGER_AFTER */
Table *pTab, /* The table to code triggers from */
int newIdx, /* The indice of the "new" row to access */
int oldIdx, /* The indice of the "old" row to access */
int orconf, /* ON CONFLICT policy */
int ignoreJump /* Instruction to jump to for RAISE(IGNORE) */
){
Trigger *p;
TriggerStack trigStackEntry;
assert(op == TK_UPDATE || op == TK_INSERT || op == TK_DELETE);
assert(tr_tm == TRIGGER_BEFORE || tr_tm == TRIGGER_AFTER );
assert(newIdx != -1 || oldIdx != -1);
for(p=pTab->pTrigger; p; p=p->pNext){
int fire_this = 0;
/* Determine whether we should code this trigger */
if(
p->op==op &&
p->tr_tm==tr_tm &&
(p->pSchema==p->pTabSchema || p->pSchema==pParse->db->aDb[1].pSchema) &&
(op!=TK_UPDATE||!p->pColumns||checkColumnOverLap(p->pColumns,pChanges))
){
TriggerStack *pS; /* Pointer to trigger-stack entry */
for(pS=pParse->trigStack; pS && p!=pS->pTrigger; pS=pS->pNext){}
if( !pS ){
fire_this = 1;
}
#if 0 /* Give no warning for recursive triggers. Just do not do them */
else{
sqlite3ErrorMsg(pParse, "recursive triggers not supported (%s)",
p->name);
return SQLITE_ERROR;
}
#endif
}
if( fire_this ){
int endTrigger;
Expr * whenExpr;
AuthContext sContext;
NameContext sNC;
memset(&sNC, 0, sizeof(sNC));
sNC.pParse = pParse;
/* Push an entry on to the trigger stack */
trigStackEntry.pTrigger = p;
trigStackEntry.newIdx = newIdx;
trigStackEntry.oldIdx = oldIdx;
trigStackEntry.pTab = pTab;
trigStackEntry.pNext = pParse->trigStack;
trigStackEntry.ignoreJump = ignoreJump;
pParse->trigStack = &trigStackEntry;
sqlite3AuthContextPush(pParse, &sContext, p->name);
/* code the WHEN clause */
endTrigger = sqlite3VdbeMakeLabel(pParse->pVdbe);
whenExpr = sqlite3ExprDup(p->pWhen);
if( sqlite3ExprResolveNames(&sNC, whenExpr) ){
pParse->trigStack = trigStackEntry.pNext;
sqlite3ExprDelete(whenExpr);
return 1;
}
sqlite3ExprIfFalse(pParse, whenExpr, endTrigger, 1);
sqlite3ExprDelete(whenExpr);
codeTriggerProgram(pParse, p->step_list, orconf);
/* Pop the entry off the trigger stack */
pParse->trigStack = trigStackEntry.pNext;
sqlite3AuthContextPop(&sContext);
sqlite3VdbeResolveLabel(pParse->pVdbe, endTrigger);
}
}
return 0;
}
#endif /* !defined(SQLITE_OMIT_TRIGGER) */

View File

@ -1,625 +0,0 @@
/*
** 2001 September 15
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle UPDATE statements.
**
** $Id: update.c 3426 2007-03-21 20:19:37Z damagedsoul $
*/
#include "sqliteInt.h"
#ifndef SQLITE_OMIT_VIRTUALTABLE
/* Forward declaration */
static void updateVirtualTable(
Parse *pParse, /* The parsing context */
SrcList *pSrc, /* The virtual table to be modified */
Table *pTab, /* The virtual table */
ExprList *pChanges, /* The columns to change in the UPDATE statement */
Expr *pRowidExpr, /* Expression used to recompute the rowid */
int *aXRef, /* Mapping from columns of pTab to entries in pChanges */
Expr *pWhere /* WHERE clause of the UPDATE statement */
);
#endif /* SQLITE_OMIT_VIRTUALTABLE */
/*
** The most recently coded instruction was an OP_Column to retrieve the
** i-th column of table pTab. This routine sets the P3 parameter of the
** OP_Column to the default value, if any.
**
** The default value of a column is specified by a DEFAULT clause in the
** column definition. This was either supplied by the user when the table
** was created, or added later to the table definition by an ALTER TABLE
** command. If the latter, then the row-records in the table btree on disk
** may not contain a value for the column and the default value, taken
** from the P3 parameter of the OP_Column instruction, is returned instead.
** If the former, then all row-records are guaranteed to include a value
** for the column and the P3 value is not required.
**
** Column definitions created by an ALTER TABLE command may only have
** literal default values specified: a number, null or a string. (If a more
** complicated default expression value was provided, it is evaluated
** when the ALTER TABLE is executed and one of the literal values written
** into the sqlite_master table.)
**
** Therefore, the P3 parameter is only required if the default value for
** the column is a literal number, string or null. The sqlite3ValueFromExpr()
** function is capable of transforming these types of expressions into
** sqlite3_value objects.
*/
void sqlite3ColumnDefault(Vdbe *v, Table *pTab, int i){
if( pTab && !pTab->pSelect ){
sqlite3_value *pValue;
u8 enc = ENC(sqlite3VdbeDb(v));
Column *pCol = &pTab->aCol[i];
sqlite3ValueFromExpr(pCol->pDflt, enc, pCol->affinity, &pValue);
if( pValue ){
sqlite3VdbeChangeP3(v, -1, (const char *)pValue, P3_MEM);
}else{
VdbeComment((v, "# %s.%s", pTab->zName, pCol->zName));
}
}
}
/*
** Process an UPDATE statement.
**
** UPDATE OR IGNORE table_wxyz SET a=b, c=d WHERE e<5 AND f NOT NULL;
** \_______/ \________/ \______/ \________________/
* onError pTabList pChanges pWhere
*/
void sqlite3Update(
Parse *pParse, /* The parser context */
SrcList *pTabList, /* The table in which we should change things */
ExprList *pChanges, /* Things to be changed */
Expr *pWhere, /* The WHERE clause. May be null */
int onError /* How to handle constraint errors */
){
int i, j; /* Loop counters */
Table *pTab; /* The table to be updated */
int addr = 0; /* VDBE instruction address of the start of the loop */
WhereInfo *pWInfo; /* Information about the WHERE clause */
Vdbe *v; /* The virtual database engine */
Index *pIdx; /* For looping over indices */
int nIdx; /* Number of indices that need updating */
int nIdxTotal; /* Total number of indices */
int iCur; /* VDBE Cursor number of pTab */
sqlite3 *db; /* The database structure */
Index **apIdx = 0; /* An array of indices that need updating too */
char *aIdxUsed = 0; /* aIdxUsed[i]==1 if the i-th index is used */
int *aXRef = 0; /* aXRef[i] is the index in pChanges->a[] of the
** an expression for the i-th column of the table.
** aXRef[i]==-1 if the i-th column is not changed. */
int chngRowid; /* True if the record number is being changed */
Expr *pRowidExpr = 0; /* Expression defining the new record number */
int openAll = 0; /* True if all indices need to be opened */
AuthContext sContext; /* The authorization context */
NameContext sNC; /* The name-context to resolve expressions in */
int iDb; /* Database containing the table being updated */
int memCnt = 0; /* Memory cell used for counting rows changed */
#ifndef SQLITE_OMIT_TRIGGER
int isView; /* Trying to update a view */
int triggers_exist = 0; /* True if any row triggers exist */
#endif
int newIdx = -1; /* index of trigger "new" temp table */
int oldIdx = -1; /* index of trigger "old" temp table */
sContext.pParse = 0;
if( pParse->nErr || sqlite3MallocFailed() ){
goto update_cleanup;
}
db = pParse->db;
assert( pTabList->nSrc==1 );
/* Locate the table which we want to update.
*/
pTab = sqlite3SrcListLookup(pParse, pTabList);
if( pTab==0 ) goto update_cleanup;
iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
/* Figure out if we have any triggers and if the table being
** updated is a view
*/
#ifndef SQLITE_OMIT_TRIGGER
triggers_exist = sqlite3TriggersExist(pParse, pTab, TK_UPDATE, pChanges);
isView = pTab->pSelect!=0;
#else
# define triggers_exist 0
# define isView 0
#endif
#ifdef SQLITE_OMIT_VIEW
# undef isView
# define isView 0
#endif
if( sqlite3IsReadOnly(pParse, pTab, triggers_exist) ){
goto update_cleanup;
}
if( sqlite3ViewGetColumnNames(pParse, pTab) ){
goto update_cleanup;
}
aXRef = sqliteMallocRaw( sizeof(int) * pTab->nCol );
if( aXRef==0 ) goto update_cleanup;
for(i=0; i<pTab->nCol; i++) aXRef[i] = -1;
/* If there are FOR EACH ROW triggers, allocate cursors for the
** special OLD and NEW tables
*/
if( triggers_exist ){
newIdx = pParse->nTab++;
oldIdx = pParse->nTab++;
}
/* Allocate a cursors for the main database table and for all indices.
** The index cursors might not be used, but if they are used they
** need to occur right after the database cursor. So go ahead and
** allocate enough space, just in case.
*/
pTabList->a[0].iCursor = iCur = pParse->nTab++;
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
pParse->nTab++;
}
/* Initialize the name-context */
memset(&sNC, 0, sizeof(sNC));
sNC.pParse = pParse;
sNC.pSrcList = pTabList;
/* Resolve the column names in all the expressions of the
** of the UPDATE statement. Also find the column index
** for each column to be updated in the pChanges array. For each
** column to be updated, make sure we have authorization to change
** that column.
*/
chngRowid = 0;
for(i=0; i<pChanges->nExpr; i++){
if( sqlite3ExprResolveNames(&sNC, pChanges->a[i].pExpr) ){
goto update_cleanup;
}
for(j=0; j<pTab->nCol; j++){
if( sqlite3StrICmp(pTab->aCol[j].zName, pChanges->a[i].zName)==0 ){
if( j==pTab->iPKey ){
chngRowid = 1;
pRowidExpr = pChanges->a[i].pExpr;
}
aXRef[j] = i;
break;
}
}
if( j>=pTab->nCol ){
if( sqlite3IsRowid(pChanges->a[i].zName) ){
chngRowid = 1;
pRowidExpr = pChanges->a[i].pExpr;
}else{
sqlite3ErrorMsg(pParse, "no such column: %s", pChanges->a[i].zName);
goto update_cleanup;
}
}
#ifndef SQLITE_OMIT_AUTHORIZATION
{
int rc;
rc = sqlite3AuthCheck(pParse, SQLITE_UPDATE, pTab->zName,
pTab->aCol[j].zName, db->aDb[iDb].zName);
if( rc==SQLITE_DENY ){
goto update_cleanup;
}else if( rc==SQLITE_IGNORE ){
aXRef[j] = -1;
}
}
#endif
}
/* Allocate memory for the array apIdx[] and fill it with pointers to every
** index that needs to be updated. Indices only need updating if their
** key includes one of the columns named in pChanges or if the record
** number of the original table entry is changing.
*/
for(nIdx=nIdxTotal=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdxTotal++){
if( chngRowid ){
i = 0;
}else {
for(i=0; i<pIdx->nColumn; i++){
if( aXRef[pIdx->aiColumn[i]]>=0 ) break;
}
}
if( i<pIdx->nColumn ) nIdx++;
}
if( nIdxTotal>0 ){
apIdx = sqliteMallocRaw( sizeof(Index*) * nIdx + nIdxTotal );
if( apIdx==0 ) goto update_cleanup;
aIdxUsed = (char*)&apIdx[nIdx];
}
for(nIdx=j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
if( chngRowid ){
i = 0;
}else{
for(i=0; i<pIdx->nColumn; i++){
if( aXRef[pIdx->aiColumn[i]]>=0 ) break;
}
}
if( i<pIdx->nColumn ){
apIdx[nIdx++] = pIdx;
aIdxUsed[j] = 1;
}else{
aIdxUsed[j] = 0;
}
}
/* Begin generating code.
*/
v = sqlite3GetVdbe(pParse);
if( v==0 ) goto update_cleanup;
if( pParse->nested==0 ) sqlite3VdbeCountChanges(v);
sqlite3BeginWriteOperation(pParse, 1, iDb);
#ifndef SQLITE_OMIT_VIRTUALTABLE
/* Virtual tables must be handled separately */
if( IsVirtual(pTab) ){
updateVirtualTable(pParse, pTabList, pTab, pChanges, pRowidExpr, aXRef,
pWhere);
pWhere = 0;
pTabList = 0;
goto update_cleanup;
}
#endif
/* Resolve the column names in all the expressions in the
** WHERE clause.
*/
if( sqlite3ExprResolveNames(&sNC, pWhere) ){
goto update_cleanup;
}
/* Start the view context
*/
if( isView ){
sqlite3AuthContextPush(pParse, &sContext, pTab->zName);
}
/* If we are trying to update a view, realize that view into
** a ephemeral table.
*/
if( isView ){
Select *pView;
pView = sqlite3SelectDup(pTab->pSelect);
sqlite3Select(pParse, pView, SRT_EphemTab, iCur, 0, 0, 0, 0);
sqlite3SelectDelete(pView);
}
/* Begin the database scan
*/
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0);
if( pWInfo==0 ) goto update_cleanup;
/* Remember the rowid of every item to be updated.
*/
sqlite3VdbeAddOp(v, IsVirtual(pTab) ? OP_VRowid : OP_Rowid, iCur, 0);
sqlite3VdbeAddOp(v, OP_FifoWrite, 0, 0);
/* End the database scan loop.
*/
sqlite3WhereEnd(pWInfo);
/* Initialize the count of updated rows
*/
if( db->flags & SQLITE_CountRows && !pParse->trigStack ){
memCnt = pParse->nMem++;
sqlite3VdbeAddOp(v, OP_MemInt, 0, memCnt);
}
if( triggers_exist ){
/* Create pseudo-tables for NEW and OLD
*/
sqlite3VdbeAddOp(v, OP_OpenPseudo, oldIdx, 0);
sqlite3VdbeAddOp(v, OP_SetNumColumns, oldIdx, pTab->nCol);
sqlite3VdbeAddOp(v, OP_OpenPseudo, newIdx, 0);
sqlite3VdbeAddOp(v, OP_SetNumColumns, newIdx, pTab->nCol);
/* The top of the update loop for when there are triggers.
*/
addr = sqlite3VdbeAddOp(v, OP_FifoRead, 0, 0);
if( !isView ){
sqlite3VdbeAddOp(v, OP_Dup, 0, 0);
sqlite3VdbeAddOp(v, OP_Dup, 0, 0);
/* Open a cursor and make it point to the record that is
** being updated.
*/
sqlite3OpenTable(pParse, iCur, iDb, pTab, OP_OpenRead);
}
sqlite3VdbeAddOp(v, OP_MoveGe, iCur, 0);
/* Generate the OLD table
*/
sqlite3VdbeAddOp(v, OP_Rowid, iCur, 0);
sqlite3VdbeAddOp(v, OP_RowData, iCur, 0);
sqlite3VdbeAddOp(v, OP_Insert, oldIdx, 0);
/* Generate the NEW table
*/
if( chngRowid ){
sqlite3ExprCodeAndCache(pParse, pRowidExpr);
}else{
sqlite3VdbeAddOp(v, OP_Rowid, iCur, 0);
}
for(i=0; i<pTab->nCol; i++){
if( i==pTab->iPKey ){
sqlite3VdbeAddOp(v, OP_Null, 0, 0);
continue;
}
j = aXRef[i];
if( j<0 ){
sqlite3VdbeAddOp(v, OP_Column, iCur, i);
sqlite3ColumnDefault(v, pTab, i);
}else{
sqlite3ExprCodeAndCache(pParse, pChanges->a[j].pExpr);
}
}
sqlite3VdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0);
if( !isView ){
sqlite3TableAffinityStr(v, pTab);
}
if( pParse->nErr ) goto update_cleanup;
sqlite3VdbeAddOp(v, OP_Insert, newIdx, 0);
if( !isView ){
sqlite3VdbeAddOp(v, OP_Close, iCur, 0);
}
/* Fire the BEFORE and INSTEAD OF triggers
*/
if( sqlite3CodeRowTrigger(pParse, TK_UPDATE, pChanges, TRIGGER_BEFORE, pTab,
newIdx, oldIdx, onError, addr) ){
goto update_cleanup;
}
}
if( !isView && !IsVirtual(pTab) ){
/*
** Open every index that needs updating. Note that if any
** index could potentially invoke a REPLACE conflict resolution
** action, then we need to open all indices because we might need
** to be deleting some records.
*/
sqlite3OpenTable(pParse, iCur, iDb, pTab, OP_OpenWrite);
if( onError==OE_Replace ){
openAll = 1;
}else{
openAll = 0;
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
if( pIdx->onError==OE_Replace ){
openAll = 1;
break;
}
}
}
for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
if( openAll || aIdxUsed[i] ){
KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIdx);
sqlite3VdbeAddOp(v, OP_Integer, iDb, 0);
sqlite3VdbeOp3(v, OP_OpenWrite, iCur+i+1, pIdx->tnum,
(char*)pKey, P3_KEYINFO_HANDOFF);
assert( pParse->nTab>iCur+i+1 );
}
}
/* Loop over every record that needs updating. We have to load
** the old data for each record to be updated because some columns
** might not change and we will need to copy the old value.
** Also, the old data is needed to delete the old index entries.
** So make the cursor point at the old record.
*/
if( !triggers_exist ){
addr = sqlite3VdbeAddOp(v, OP_FifoRead, 0, 0);
sqlite3VdbeAddOp(v, OP_Dup, 0, 0);
}
sqlite3VdbeAddOp(v, OP_NotExists, iCur, addr);
/* If the record number will change, push the record number as it
** will be after the update. (The old record number is currently
** on top of the stack.)
*/
if( chngRowid ){
sqlite3ExprCode(pParse, pRowidExpr);
sqlite3VdbeAddOp(v, OP_MustBeInt, 0, 0);
}
/* Compute new data for this record.
*/
for(i=0; i<pTab->nCol; i++){
if( i==pTab->iPKey ){
sqlite3VdbeAddOp(v, OP_Null, 0, 0);
continue;
}
j = aXRef[i];
if( j<0 ){
sqlite3VdbeAddOp(v, OP_Column, iCur, i);
sqlite3ColumnDefault(v, pTab, i);
}else{
sqlite3ExprCode(pParse, pChanges->a[j].pExpr);
}
}
/* Do constraint checks
*/
sqlite3GenerateConstraintChecks(pParse, pTab, iCur, aIdxUsed, chngRowid, 1,
onError, addr);
/* Delete the old indices for the current record.
*/
sqlite3GenerateRowIndexDelete(v, pTab, iCur, aIdxUsed);
/* If changing the record number, delete the old record.
*/
if( chngRowid ){
sqlite3VdbeAddOp(v, OP_Delete, iCur, 0);
}
/* Create the new index entries and the new record.
*/
sqlite3CompleteInsertion(pParse, pTab, iCur, aIdxUsed, chngRowid, 1, -1);
}
/* Increment the row counter
*/
if( db->flags & SQLITE_CountRows && !pParse->trigStack){
sqlite3VdbeAddOp(v, OP_MemIncr, 1, memCnt);
}
/* If there are triggers, close all the cursors after each iteration
** through the loop. The fire the after triggers.
*/
if( triggers_exist ){
if( !isView ){
for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
if( openAll || aIdxUsed[i] )
sqlite3VdbeAddOp(v, OP_Close, iCur+i+1, 0);
}
sqlite3VdbeAddOp(v, OP_Close, iCur, 0);
}
if( sqlite3CodeRowTrigger(pParse, TK_UPDATE, pChanges, TRIGGER_AFTER, pTab,
newIdx, oldIdx, onError, addr) ){
goto update_cleanup;
}
}
/* Repeat the above with the next record to be updated, until
** all record selected by the WHERE clause have been updated.
*/
sqlite3VdbeAddOp(v, OP_Goto, 0, addr);
sqlite3VdbeJumpHere(v, addr);
/* Close all tables if there were no FOR EACH ROW triggers */
if( !triggers_exist ){
for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
if( openAll || aIdxUsed[i] ){
sqlite3VdbeAddOp(v, OP_Close, iCur+i+1, 0);
}
}
sqlite3VdbeAddOp(v, OP_Close, iCur, 0);
}else{
sqlite3VdbeAddOp(v, OP_Close, newIdx, 0);
sqlite3VdbeAddOp(v, OP_Close, oldIdx, 0);
}
/*
** Return the number of rows that were changed. If this routine is
** generating code because of a call to sqlite3NestedParse(), do not
** invoke the callback function.
*/
if( db->flags & SQLITE_CountRows && !pParse->trigStack && pParse->nested==0 ){
sqlite3VdbeAddOp(v, OP_MemLoad, memCnt, 0);
sqlite3VdbeAddOp(v, OP_Callback, 1, 0);
sqlite3VdbeSetNumCols(v, 1);
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows updated", P3_STATIC);
}
update_cleanup:
sqlite3AuthContextPop(&sContext);
sqliteFree(apIdx);
sqliteFree(aXRef);
sqlite3SrcListDelete(pTabList);
sqlite3ExprListDelete(pChanges);
sqlite3ExprDelete(pWhere);
return;
}
#ifndef SQLITE_OMIT_VIRTUALTABLE
/*
** Generate code for an UPDATE of a virtual table.
**
** The strategy is that we create an ephemerial table that contains
** for each row to be changed:
**
** (A) The original rowid of that row.
** (B) The revised rowid for the row. (note1)
** (C) The content of every column in the row.
**
** Then we loop over this ephemeral table and for each row in
** the ephermeral table call VUpdate.
**
** When finished, drop the ephemeral table.
**
** (note1) Actually, if we know in advance that (A) is always the same
** as (B) we only store (A), then duplicate (A) when pulling
** it out of the ephemeral table before calling VUpdate.
*/
static void updateVirtualTable(
Parse *pParse, /* The parsing context */
SrcList *pSrc, /* The virtual table to be modified */
Table *pTab, /* The virtual table */
ExprList *pChanges, /* The columns to change in the UPDATE statement */
Expr *pRowid, /* Expression used to recompute the rowid */
int *aXRef, /* Mapping from columns of pTab to entries in pChanges */
Expr *pWhere /* WHERE clause of the UPDATE statement */
){
Vdbe *v = pParse->pVdbe; /* Virtual machine under construction */
ExprList *pEList = 0; /* The result set of the SELECT statement */
Select *pSelect = 0; /* The SELECT statement */
Expr *pExpr; /* Temporary expression */
int ephemTab; /* Table holding the result of the SELECT */
int i; /* Loop counter */
int addr; /* Address of top of loop */
/* Construct the SELECT statement that will find the new values for
** all updated rows.
*/
pEList = sqlite3ExprListAppend(0, sqlite3CreateIdExpr("_rowid_"), 0);
if( pRowid ){
pEList = sqlite3ExprListAppend(pEList, sqlite3ExprDup(pRowid), 0);
}
assert( pTab->iPKey<0 );
for(i=0; i<pTab->nCol; i++){
if( aXRef[i]>=0 ){
pExpr = sqlite3ExprDup(pChanges->a[aXRef[i]].pExpr);
}else{
pExpr = sqlite3CreateIdExpr(pTab->aCol[i].zName);
}
pEList = sqlite3ExprListAppend(pEList, pExpr, 0);
}
pSelect = sqlite3SelectNew(pEList, pSrc, pWhere, 0, 0, 0, 0, 0, 0);
/* Create the ephemeral table into which the update results will
** be stored.
*/
assert( v );
ephemTab = pParse->nTab++;
sqlite3VdbeAddOp(v, OP_OpenEphemeral, ephemTab, pTab->nCol+1+(pRowid!=0));
/* fill the ephemeral table
*/
sqlite3Select(pParse, pSelect, SRT_Table, ephemTab, 0, 0, 0, 0);
/*
** Generate code to scan the ephemeral table and call VDelete and
** VInsert
*/
sqlite3VdbeAddOp(v, OP_Rewind, ephemTab, 0);
addr = sqlite3VdbeCurrentAddr(v);
sqlite3VdbeAddOp(v, OP_Column, ephemTab, 0);
if( pRowid ){
sqlite3VdbeAddOp(v, OP_Column, ephemTab, 1);
}else{
sqlite3VdbeAddOp(v, OP_Dup, 0, 0);
}
for(i=0; i<pTab->nCol; i++){
sqlite3VdbeAddOp(v, OP_Column, ephemTab, i+1+(pRowid!=0));
}
pParse->pVirtualLock = pTab;
sqlite3VdbeOp3(v, OP_VUpdate, 0, pTab->nCol+2,
(const char*)pTab->pVtab, P3_VTAB);
sqlite3VdbeAddOp(v, OP_Next, ephemTab, addr);
sqlite3VdbeAddOp(v, OP_Close, ephemTab, 0);
/* Cleanup */
sqlite3SelectDelete(pSelect);
}
#endif /* SQLITE_OMIT_VIRTUALTABLE */

View File

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

File diff suppressed because it is too large Load Diff

View File

@ -1,270 +0,0 @@
/*
** 2003 April 6
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains code used to implement the VACUUM command.
**
** Most of the code in this file may be omitted by defining the
** SQLITE_OMIT_VACUUM macro.
**
** $Id: vacuum.c 3426 2007-03-21 20:19:37Z damagedsoul $
*/
#include "sqliteInt.h"
#include "vdbeInt.h"
#include "os.h"
#ifndef SQLITE_OMIT_VACUUM
/*
** Execute zSql on database db. Return an error code.
*/
static int execSql(sqlite3 *db, const char *zSql){
sqlite3_stmt *pStmt;
if( SQLITE_OK!=sqlite3_prepare(db, zSql, -1, &pStmt, 0) ){
return sqlite3_errcode(db);
}
while( SQLITE_ROW==sqlite3_step(pStmt) ){}
return sqlite3_finalize(pStmt);
}
/*
** Execute zSql on database db. The statement returns exactly
** one column. Execute this as SQL on the same database.
*/
static int execExecSql(sqlite3 *db, const char *zSql){
sqlite3_stmt *pStmt;
int rc;
rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0);
if( rc!=SQLITE_OK ) return rc;
while( SQLITE_ROW==sqlite3_step(pStmt) ){
rc = execSql(db, (char*)sqlite3_column_text(pStmt, 0));
if( rc!=SQLITE_OK ){
sqlite3_finalize(pStmt);
return rc;
}
}
return sqlite3_finalize(pStmt);
}
/*
** The non-standard VACUUM command is used to clean up the database,
** collapse free space, etc. It is modelled after the VACUUM command
** in PostgreSQL.
**
** In version 1.0.x of SQLite, the VACUUM command would call
** gdbm_reorganize() on all the database tables. But beginning
** with 2.0.0, SQLite no longer uses GDBM so this command has
** become a no-op.
*/
void sqlite3Vacuum(Parse *pParse){
Vdbe *v = sqlite3GetVdbe(pParse);
if( v ){
sqlite3VdbeAddOp(v, OP_Vacuum, 0, 0);
}
return;
}
/*
** This routine implements the OP_Vacuum opcode of the VDBE.
*/
int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){
int rc = SQLITE_OK; /* Return code from service routines */
Btree *pMain; /* The database being vacuumed */
Btree *pTemp; /* The temporary database we vacuum into */
char *zSql = 0; /* SQL statements */
int saved_flags; /* Saved value of the db->flags */
Db *pDb = 0; /* Database to detach at end of vacuum */
char zTemp[SQLITE_TEMPNAME_SIZE+20]; /* Name of the TEMP file */
/* Save the current value of the write-schema flag before setting it. */
saved_flags = db->flags;
db->flags |= SQLITE_WriteSchema | SQLITE_IgnoreChecks;
sqlite3OsTempFileName(zTemp);
if( !db->autoCommit ){
sqlite3SetString(pzErrMsg, "cannot VACUUM from within a transaction",
(char*)0);
rc = SQLITE_ERROR;
goto end_of_vacuum;
}
pMain = db->aDb[0].pBt;
/* Attach the temporary database as 'vacuum_db'. The synchronous pragma
** can be set to 'off' for this file, as it is not recovered if a crash
** occurs anyway. The integrity of the database is maintained by a
** (possibly synchronous) transaction opened on the main database before
** sqlite3BtreeCopyFile() is called.
**
** An optimisation would be to use a non-journaled pager.
*/
zSql = sqlite3MPrintf("ATTACH '%q' AS vacuum_db;", zTemp);
if( !zSql ){
rc = SQLITE_NOMEM;
goto end_of_vacuum;
}
rc = execSql(db, zSql);
sqliteFree(zSql);
zSql = 0;
if( rc!=SQLITE_OK ) goto end_of_vacuum;
pDb = &db->aDb[db->nDb-1];
assert( strcmp(db->aDb[db->nDb-1].zName,"vacuum_db")==0 );
pTemp = db->aDb[db->nDb-1].pBt;
sqlite3BtreeSetPageSize(pTemp, sqlite3BtreeGetPageSize(pMain),
sqlite3BtreeGetReserve(pMain));
assert( sqlite3BtreeGetPageSize(pTemp)==sqlite3BtreeGetPageSize(pMain) );
rc = execSql(db, "PRAGMA vacuum_db.synchronous=OFF");
if( rc!=SQLITE_OK ){
goto end_of_vacuum;
}
#ifndef SQLITE_OMIT_AUTOVACUUM
sqlite3BtreeSetAutoVacuum(pTemp, sqlite3BtreeGetAutoVacuum(pMain));
#endif
/* Begin a transaction */
rc = execSql(db, "BEGIN EXCLUSIVE;");
if( rc!=SQLITE_OK ) goto end_of_vacuum;
/* Query the schema of the main database. Create a mirror schema
** in the temporary database.
*/
rc = execExecSql(db,
"SELECT 'CREATE TABLE vacuum_db.' || substr(sql,14,100000000) "
" FROM sqlite_master WHERE type='table' AND name!='sqlite_sequence'"
" AND rootpage>0"
);
if( rc!=SQLITE_OK ) goto end_of_vacuum;
rc = execExecSql(db,
"SELECT 'CREATE INDEX vacuum_db.' || substr(sql,14,100000000)"
" FROM sqlite_master WHERE sql LIKE 'CREATE INDEX %' ");
if( rc!=SQLITE_OK ) goto end_of_vacuum;
rc = execExecSql(db,
"SELECT 'CREATE UNIQUE INDEX vacuum_db.' || substr(sql,21,100000000) "
" FROM sqlite_master WHERE sql LIKE 'CREATE UNIQUE INDEX %'");
if( rc!=SQLITE_OK ) goto end_of_vacuum;
/* Loop through the tables in the main database. For each, do
** an "INSERT INTO vacuum_db.xxx SELECT * FROM xxx;" to copy
** the contents to the temporary database.
*/
rc = execExecSql(db,
"SELECT 'INSERT INTO vacuum_db.' || quote(name) "
"|| ' SELECT * FROM ' || quote(name) || ';'"
"FROM sqlite_master "
"WHERE type = 'table' AND name!='sqlite_sequence' "
" AND rootpage>0"
);
if( rc!=SQLITE_OK ) goto end_of_vacuum;
/* Copy over the sequence table
*/
rc = execExecSql(db,
"SELECT 'DELETE FROM vacuum_db.' || quote(name) || ';' "
"FROM vacuum_db.sqlite_master WHERE name='sqlite_sequence' "
);
if( rc!=SQLITE_OK ) goto end_of_vacuum;
rc = execExecSql(db,
"SELECT 'INSERT INTO vacuum_db.' || quote(name) "
"|| ' SELECT * FROM ' || quote(name) || ';' "
"FROM vacuum_db.sqlite_master WHERE name=='sqlite_sequence';"
);
if( rc!=SQLITE_OK ) goto end_of_vacuum;
/* Copy the triggers, views, and virtual tables from the main database
** over to the temporary database. None of these objects has any
** associated storage, so all we have to do is copy their entries
** from the SQLITE_MASTER table.
*/
rc = execSql(db,
"INSERT INTO vacuum_db.sqlite_master "
" SELECT type, name, tbl_name, rootpage, sql"
" FROM sqlite_master"
" WHERE type='view' OR type='trigger'"
" OR (type='table' AND rootpage=0)"
);
if( rc ) goto end_of_vacuum;
/* At this point, unless the main db was completely empty, there is now a
** transaction open on the vacuum database, but not on the main database.
** Open a btree level transaction on the main database. This allows a
** call to sqlite3BtreeCopyFile(). The main database btree level
** transaction is then committed, so the SQL level never knows it was
** opened for writing. This way, the SQL transaction used to create the
** temporary database never needs to be committed.
*/
if( rc==SQLITE_OK ){
u32 meta;
int i;
/* This array determines which meta meta values are preserved in the
** vacuum. Even entries are the meta value number and odd entries
** are an increment to apply to the meta value after the vacuum.
** The increment is used to increase the schema cookie so that other
** connections to the same database will know to reread the schema.
*/
static const unsigned char aCopy[] = {
1, 1, /* Add one to the old schema cookie */
3, 0, /* Preserve the default page cache size */
5, 0, /* Preserve the default text encoding */
6, 0, /* Preserve the user version */
};
assert( 1==sqlite3BtreeIsInTrans(pTemp) );
assert( 1==sqlite3BtreeIsInTrans(pMain) );
/* Copy Btree meta values */
for(i=0; i<sizeof(aCopy)/sizeof(aCopy[0]); i+=2){
rc = sqlite3BtreeGetMeta(pMain, aCopy[i], &meta);
if( rc!=SQLITE_OK ) goto end_of_vacuum;
rc = sqlite3BtreeUpdateMeta(pTemp, aCopy[i], meta+aCopy[i+1]);
if( rc!=SQLITE_OK ) goto end_of_vacuum;
}
rc = sqlite3BtreeCopyFile(pMain, pTemp);
if( rc!=SQLITE_OK ) goto end_of_vacuum;
rc = sqlite3BtreeCommit(pTemp);
if( rc!=SQLITE_OK ) goto end_of_vacuum;
rc = sqlite3BtreeCommit(pMain);
}
end_of_vacuum:
/* Restore the original value of db->flags */
db->flags = saved_flags;
/* Currently there is an SQL level transaction open on the vacuum
** database. No locks are held on any other files (since the main file
** was committed at the btree level). So it safe to end the transaction
** by manually setting the autoCommit flag to true and detaching the
** vacuum database. The vacuum_db journal file is deleted when the pager
** is closed by the DETACH.
*/
db->autoCommit = 1;
if( pDb ){
sqlite3MallocDisallow();
sqlite3BtreeClose(pDb->pBt);
sqlite3MallocAllow();
pDb->pBt = 0;
pDb->pSchema = 0;
}
sqlite3OsDelete(zTemp);
strcat(zTemp, "-journal");
sqlite3OsDelete(zTemp);
sqliteFree( zSql );
sqlite3ResetInternalSchema(db, 0);
return rc;
}
#endif /* SQLITE_OMIT_VACUUM */

File diff suppressed because it is too large Load Diff

View File

@ -1,150 +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.
**
*************************************************************************
** Header file for the Virtual DataBase Engine (VDBE)
**
** This header defines the interface to the virtual database engine
** or VDBE. The VDBE implements an abstract machine that runs a
** simple program to access and modify the underlying database.
**
** $Id: vdbe.h 3426 2007-03-21 20:19:37Z damagedsoul $
*/
#ifndef _SQLITE_VDBE_H_
#define _SQLITE_VDBE_H_
#include <stdio.h>
/*
** A single VDBE is an opaque structure named "Vdbe". Only routines
** in the source file sqliteVdbe.c are allowed to see the insides
** of this structure.
*/
typedef struct Vdbe Vdbe;
/*
** A single instruction of the virtual machine has an opcode
** and as many as three operands. The instruction is recorded
** as an instance of the following structure:
*/
struct VdbeOp {
u8 opcode; /* What operation to perform */
int p1; /* First operand */
int p2; /* Second parameter (often the jump destination) */
char *p3; /* Third parameter */
int p3type; /* One of the P3_xxx constants defined below */
#ifdef VDBE_PROFILE
int cnt; /* Number of times this instruction was executed */
long long cycles; /* Total time spend executing this instruction */
#endif
};
typedef struct VdbeOp VdbeOp;
/*
** A smaller version of VdbeOp used for the VdbeAddOpList() function because
** it takes up less space.
*/
struct VdbeOpList {
u8 opcode; /* What operation to perform */
signed char p1; /* First operand */
short int p2; /* Second parameter (often the jump destination) */
char *p3; /* Third parameter */
};
typedef struct VdbeOpList VdbeOpList;
/*
** Allowed values of VdbeOp.p3type
*/
#define P3_NOTUSED 0 /* The P3 parameter is not used */
#define P3_DYNAMIC (-1) /* Pointer to a string obtained from sqliteMalloc() */
#define P3_STATIC (-2) /* Pointer to a static string */
#define P3_COLLSEQ (-4) /* P3 is a pointer to a CollSeq structure */
#define P3_FUNCDEF (-5) /* P3 is a pointer to a FuncDef structure */
#define P3_KEYINFO (-6) /* P3 is a pointer to a KeyInfo structure */
#define P3_VDBEFUNC (-7) /* P3 is a pointer to a VdbeFunc structure */
#define P3_MEM (-8) /* P3 is a pointer to a Mem* structure */
#define P3_TRANSIENT (-9) /* P3 is a pointer to a transient string */
#define P3_VTAB (-10) /* P3 is a pointer to an sqlite3_vtab structure */
#define P3_MPRINTF (-11) /* P3 is a string obtained from sqlite3_mprintf() */
/* When adding a P3 argument using P3_KEYINFO, a copy of the KeyInfo structure
** is made. That copy is freed when the Vdbe is finalized. But if the
** argument is P3_KEYINFO_HANDOFF, the passed in pointer is used. It still
** gets freed when the Vdbe is finalized so it still should be obtained
** from a single sqliteMalloc(). But no copy is made and the calling
** function should *not* try to free the KeyInfo.
*/
#define P3_KEYINFO_HANDOFF (-9)
/*
** The Vdbe.aColName array contains 5n Mem structures, where n is the
** number of columns of data returned by the statement.
*/
#define COLNAME_NAME 0
#define COLNAME_DECLTYPE 1
#define COLNAME_DATABASE 2
#define COLNAME_TABLE 3
#define COLNAME_COLUMN 4
#define COLNAME_N 5 /* Number of COLNAME_xxx symbols */
/*
** The following macro converts a relative address in the p2 field
** of a VdbeOp structure into a negative number so that
** sqlite3VdbeAddOpList() knows that the address is relative. Calling
** the macro again restores the address.
*/
#define ADDR(X) (-1-(X))
/*
** The makefile scans the vdbe.c source file and creates the "opcodes.h"
** header file that defines a number for each opcode used by the VDBE.
*/
#include "opcodes.h"
/*
** Prototypes for the VDBE interface. See comments on the implementation
** for a description of what each of these routines does.
*/
Vdbe *sqlite3VdbeCreate(sqlite3*);
void sqlite3VdbeCreateCallback(Vdbe*, int*);
int sqlite3VdbeAddOp(Vdbe*,int,int,int);
int sqlite3VdbeOp3(Vdbe*,int,int,int,const char *zP3,int);
int sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp);
void sqlite3VdbeChangeP1(Vdbe*, int addr, int P1);
void sqlite3VdbeChangeP2(Vdbe*, int addr, int P2);
void sqlite3VdbeJumpHere(Vdbe*, int addr);
void sqlite3VdbeChangeToNoop(Vdbe*, int addr, int N);
void sqlite3VdbeChangeP3(Vdbe*, int addr, const char *zP1, int N);
VdbeOp *sqlite3VdbeGetOp(Vdbe*, int);
int sqlite3VdbeMakeLabel(Vdbe*);
void sqlite3VdbeDelete(Vdbe*);
void sqlite3VdbeMakeReady(Vdbe*,int,int,int,int);
int sqlite3VdbeFinalize(Vdbe*);
void sqlite3VdbeResolveLabel(Vdbe*, int);
int sqlite3VdbeCurrentAddr(Vdbe*);
void sqlite3VdbeTrace(Vdbe*,FILE*);
void sqlite3VdbeResetStepResult(Vdbe*);
int sqlite3VdbeReset(Vdbe*);
int sqliteVdbeSetVariables(Vdbe*,int,const char**);
void sqlite3VdbeSetNumCols(Vdbe*,int);
int sqlite3VdbeSetColName(Vdbe*, int, int, const char *, int);
void sqlite3VdbeCountChanges(Vdbe*);
sqlite3 *sqlite3VdbeDb(Vdbe*);
void sqlite3VdbeSetSql(Vdbe*, const char *z, int n);
const char *sqlite3VdbeGetSql(Vdbe*);
void sqlite3VdbeSwap(Vdbe*,Vdbe*);
#ifndef NDEBUG
void sqlite3VdbeComment(Vdbe*, const char*, ...);
# define VdbeComment(X) sqlite3VdbeComment X
#else
# define VdbeComment(X)
#endif
#endif

View File

@ -1,409 +0,0 @@
/*
** 2003 September 6
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
** This is the header file for information that is private to the
** VDBE. This information used to all be at the top of the single
** source code file "vdbe.c". When that file became too big (over
** 6000 lines long) it was split up into several smaller files and
** this header information was factored out.
*/
#ifndef _VDBEINT_H_
#define _VDBEINT_H_
/*
** intToKey() and keyToInt() used to transform the rowid. But with
** the latest versions of the design they are no-ops.
*/
#define keyToInt(X) (X)
#define intToKey(X) (X)
/*
** The makefile scans the vdbe.c source file and creates the following
** array of string constants which are the names of all VDBE opcodes. This
** array is defined in a separate source code file named opcode.c which is
** automatically generated by the makefile.
*/
extern char *sqlite3OpcodeNames[];
/*
** SQL is translated into a sequence of instructions to be
** executed by a virtual machine. Each instruction is an instance
** of the following structure.
*/
typedef struct VdbeOp Op;
/*
** Boolean values
*/
typedef unsigned char Bool;
/*
** A cursor is a pointer into a single BTree within a database file.
** The cursor can seek to a BTree entry with a particular key, or
** loop over all entries of the Btree. You can also insert new BTree
** entries or retrieve the key or data from the entry that the cursor
** is currently pointing to.
**
** Every cursor that the virtual machine has open is represented by an
** instance of the following structure.
**
** If the Cursor.isTriggerRow flag is set it means that this cursor is
** really a single row that represents the NEW or OLD pseudo-table of
** a row trigger. The data for the row is stored in Cursor.pData and
** the rowid is in Cursor.iKey.
*/
struct Cursor {
BtCursor *pCursor; /* The cursor structure of the backend */
int iDb; /* Index of cursor database in db->aDb[] (or -1) */
i64 lastRowid; /* Last rowid from a Next or NextIdx operation */
i64 nextRowid; /* Next rowid returned by OP_NewRowid */
Bool zeroed; /* True if zeroed out and ready for reuse */
Bool rowidIsValid; /* True if lastRowid is valid */
Bool atFirst; /* True if pointing to first entry */
Bool useRandomRowid; /* Generate new record numbers semi-randomly */
Bool nullRow; /* True if pointing to a row with no data */
Bool nextRowidValid; /* True if the nextRowid field is valid */
Bool pseudoTable; /* This is a NEW or OLD pseudo-tables of a trigger */
Bool deferredMoveto; /* A call to sqlite3BtreeMoveto() is needed */
Bool isTable; /* True if a table requiring integer keys */
Bool isIndex; /* True if an index containing keys only - no data */
u8 bogusIncrKey; /* Something for pIncrKey to point to if pKeyInfo==0 */
i64 movetoTarget; /* Argument to the deferred sqlite3BtreeMoveto() */
Btree *pBt; /* Separate file holding temporary table */
int nData; /* Number of bytes in pData */
char *pData; /* Data for a NEW or OLD pseudo-table */
i64 iKey; /* Key for the NEW or OLD pseudo-table row */
u8 *pIncrKey; /* Pointer to pKeyInfo->incrKey */
KeyInfo *pKeyInfo; /* Info about index keys needed by index cursors */
int nField; /* Number of fields in the header */
i64 seqCount; /* Sequence counter */
sqlite3_vtab_cursor *pVtabCursor; /* The cursor for a virtual table */
const sqlite3_module *pModule; /* Module for cursor pVtabCursor */
/* Cached information about the header for the data record that the
** cursor is currently pointing to. Only valid if cacheValid is true.
** aRow might point to (ephemeral) data for the current row, or it might
** be NULL.
*/
int cacheStatus; /* Cache is valid if this matches Vdbe.cacheCtr */
int payloadSize; /* Total number of bytes in the record */
u32 *aType; /* Type values for all entries in the record */
u32 *aOffset; /* Cached offsets to the start of each columns data */
u8 *aRow; /* Data for the current row, if all on one page */
};
typedef struct Cursor Cursor;
/*
** Number of bytes of string storage space available to each stack
** layer without having to malloc. NBFS is short for Number of Bytes
** For Strings.
*/
#define NBFS 32
/*
** A value for Cursor.cacheValid that means the cache is always invalid.
*/
#define CACHE_STALE 0
/*
** Internally, the vdbe manipulates nearly all SQL values as Mem
** structures. Each Mem struct may cache multiple representations (string,
** integer etc.) of the same value. A value (and therefore Mem structure)
** has the following properties:
**
** Each value has a manifest type. The manifest type of the value stored
** in a Mem struct is returned by the MemType(Mem*) macro. The type is
** one of SQLITE_NULL, SQLITE_INTEGER, SQLITE_REAL, SQLITE_TEXT or
** SQLITE_BLOB.
*/
struct Mem {
i64 i; /* Integer value. Or FuncDef* when flags==MEM_Agg */
double r; /* Real value */
char *z; /* String or BLOB value */
int n; /* Number of characters in string value, including '\0' */
u16 flags; /* Some combination of MEM_Null, MEM_Str, MEM_Dyn, etc. */
u8 type; /* One of MEM_Null, MEM_Str, etc. */
u8 enc; /* TEXT_Utf8, TEXT_Utf16le, or TEXT_Utf16be */
void (*xDel)(void *); /* If not null, call this function to delete Mem.z */
char zShort[NBFS]; /* Space for short strings */
};
typedef struct Mem Mem;
/* One or more of the following flags are set to indicate the validOK
** representations of the value stored in the Mem struct.
**
** If the MEM_Null flag is set, then the value is an SQL NULL value.
** No other flags may be set in this case.
**
** If the MEM_Str flag is set then Mem.z points at a string representation.
** Usually this is encoded in the same unicode encoding as the main
** database (see below for exceptions). If the MEM_Term flag is also
** set, then the string is nul terminated. The MEM_Int and MEM_Real
** flags may coexist with the MEM_Str flag.
**
** Multiple of these values can appear in Mem.flags. But only one
** at a time can appear in Mem.type.
*/
#define MEM_Null 0x0001 /* Value is NULL */
#define MEM_Str 0x0002 /* Value is a string */
#define MEM_Int 0x0004 /* Value is an integer */
#define MEM_Real 0x0008 /* Value is a real number */
#define MEM_Blob 0x0010 /* Value is a BLOB */
/* Whenever Mem contains a valid string or blob representation, one of
** the following flags must be set to determine the memory management
** policy for Mem.z. The MEM_Term flag tells us whether or not the
** string is \000 or \u0000 terminated
*/
#define MEM_Term 0x0020 /* String rep is nul terminated */
#define MEM_Dyn 0x0040 /* Need to call sqliteFree() on Mem.z */
#define MEM_Static 0x0080 /* Mem.z points to a static string */
#define MEM_Ephem 0x0100 /* Mem.z points to an ephemeral string */
#define MEM_Short 0x0200 /* Mem.z points to Mem.zShort */
#define MEM_Agg 0x0400 /* Mem.z points to an agg function context */
/* A VdbeFunc is just a FuncDef (defined in sqliteInt.h) that contains
** additional information about auxiliary information bound to arguments
** of the function. This is used to implement the sqlite3_get_auxdata()
** and sqlite3_set_auxdata() APIs. The "auxdata" is some auxiliary data
** that can be associated with a constant argument to a function. This
** allows functions such as "regexp" to compile their constant regular
** expression argument once and reused the compiled code for multiple
** invocations.
*/
struct VdbeFunc {
FuncDef *pFunc; /* The definition of the function */
int nAux; /* Number of entries allocated for apAux[] */
struct AuxData {
void *pAux; /* Aux data for the i-th argument */
void (*xDelete)(void *); /* Destructor for the aux data */
} apAux[1]; /* One slot for each function argument */
};
typedef struct VdbeFunc VdbeFunc;
/*
** The "context" argument for a installable function. A pointer to an
** instance of this structure is the first argument to the routines used
** implement the SQL functions.
**
** There is a typedef for this structure in sqlite.h. So all routines,
** even the public interface to SQLite, can use a pointer to this structure.
** But this file is the only place where the internal details of this
** structure are known.
**
** This structure is defined inside of vdbeInt.h because it uses substructures
** (Mem) which are only defined there.
*/
struct sqlite3_context {
FuncDef *pFunc; /* Pointer to function information. MUST BE FIRST */
VdbeFunc *pVdbeFunc; /* Auxilary data, if created. */
Mem s; /* The return value is stored here */
Mem *pMem; /* Memory cell used to store aggregate context */
u8 isError; /* Set to true for an error */
CollSeq *pColl; /* Collating sequence */
};
/*
** A Set structure is used for quick testing to see if a value
** is part of a small set. Sets are used to implement code like
** this:
** x.y IN ('hi','hoo','hum')
*/
typedef struct Set Set;
struct Set {
Hash hash; /* A set is just a hash table */
HashElem *prev; /* Previously accessed hash elemen */
};
/*
** A FifoPage structure holds a single page of valves. Pages are arranged
** in a list.
*/
typedef struct FifoPage FifoPage;
struct FifoPage {
int nSlot; /* Number of entries aSlot[] */
int iWrite; /* Push the next value into this entry in aSlot[] */
int iRead; /* Read the next value from this entry in aSlot[] */
FifoPage *pNext; /* Next page in the fifo */
i64 aSlot[1]; /* One or more slots for rowid values */
};
/*
** The Fifo structure is typedef-ed in vdbeInt.h. But the implementation
** of that structure is private to this file.
**
** The Fifo structure describes the entire fifo.
*/
typedef struct Fifo Fifo;
struct Fifo {
int nEntry; /* Total number of entries */
FifoPage *pFirst; /* First page on the list */
FifoPage *pLast; /* Last page on the list */
};
/*
** A Context stores the last insert rowid, the last statement change count,
** and the current statement change count (i.e. changes since last statement).
** The current keylist is also stored in the context.
** Elements of Context structure type make up the ContextStack, which is
** updated by the ContextPush and ContextPop opcodes (used by triggers).
** The context is pushed before executing a trigger a popped when the
** trigger finishes.
*/
typedef struct Context Context;
struct Context {
i64 lastRowid; /* Last insert rowid (sqlite3.lastRowid) */
int nChange; /* Statement changes (Vdbe.nChanges) */
Fifo sFifo; /* Records that will participate in a DELETE or UPDATE */
};
/*
** An instance of the virtual machine. This structure contains the complete
** state of the virtual machine.
**
** The "sqlite3_stmt" structure pointer that is returned by sqlite3_compile()
** is really a pointer to an instance of this structure.
**
** The Vdbe.inVtabMethod variable is set to non-zero for the duration of
** any virtual table method invocations made by the vdbe program. It is
** set to 2 for xDestroy method calls and 1 for all other methods. This
** variable is used for two purposes: to allow xDestroy methods to execute
** "DROP TABLE" statements and to prevent some nasty side effects of
** malloc failure when SQLite is invoked recursively by a virtual table
** method function.
*/
struct Vdbe {
sqlite3 *db; /* The whole database */
Vdbe *pPrev,*pNext; /* Linked list of VDBEs with the same Vdbe.db */
FILE *trace; /* Write an execution trace here, if not NULL */
int nOp; /* Number of instructions in the program */
int nOpAlloc; /* Number of slots allocated for aOp[] */
Op *aOp; /* Space to hold the virtual machine's program */
int nLabel; /* Number of labels used */
int nLabelAlloc; /* Number of slots allocated in aLabel[] */
int *aLabel; /* Space to hold the labels */
Mem *aStack; /* The operand stack, except string values */
Mem *pTos; /* Top entry in the operand stack */
Mem **apArg; /* Arguments to currently executing user function */
Mem *aColName; /* Column names to return */
int nCursor; /* Number of slots in apCsr[] */
Cursor **apCsr; /* One element of this array for each open cursor */
int nVar; /* Number of entries in aVar[] */
Mem *aVar; /* Values for the OP_Variable opcode. */
char **azVar; /* Name of variables */
int okVar; /* True if azVar[] has been initialized */
int magic; /* Magic number for sanity checking */
int nMem; /* Number of memory locations currently allocated */
Mem *aMem; /* The memory locations */
int nCallback; /* Number of callbacks invoked so far */
int cacheCtr; /* Cursor row cache generation counter */
Fifo sFifo; /* A list of ROWIDs */
int contextStackTop; /* Index of top element in the context stack */
int contextStackDepth; /* The size of the "context" stack */
Context *contextStack; /* Stack used by opcodes ContextPush & ContextPop*/
int pc; /* The program counter */
int rc; /* Value to return */
unsigned uniqueCnt; /* Used by OP_MakeRecord when P2!=0 */
int errorAction; /* Recovery action to do in case of an error */
int inTempTrans; /* True if temp database is transactioned */
int returnStack[100]; /* Return address stack for OP_Gosub & OP_Return */
int returnDepth; /* Next unused element in returnStack[] */
int nResColumn; /* Number of columns in one row of the result set */
char **azResColumn; /* Values for one row of result */
int popStack; /* Pop the stack this much on entry to VdbeExec() */
char *zErrMsg; /* Error message written here */
u8 resOnStack; /* True if there are result values on the stack */
u8 explain; /* True if EXPLAIN present on SQL command */
u8 changeCntOn; /* True to update the change-counter */
u8 aborted; /* True if ROLLBACK in another VM causes an abort */
u8 expired; /* True if the VM needs to be recompiled */
u8 minWriteFileFormat; /* Minimum file format for writable database files */
u8 inVtabMethod; /* See comments above */
int nChange; /* Number of db changes made since last reset */
i64 startTime; /* Time when query started - used for profiling */
int nSql; /* Number of bytes in zSql */
char *zSql; /* Text of the SQL statement that generated this */
#ifdef SQLITE_SSE
int fetchId; /* Statement number used by sqlite3_fetch_statement */
int lru; /* Counter used for LRU cache replacement */
#endif
};
/*
** The following are allowed values for Vdbe.magic
*/
#define VDBE_MAGIC_INIT 0x26bceaa5 /* Building a VDBE program */
#define VDBE_MAGIC_RUN 0xbdf20da3 /* VDBE is ready to execute */
#define VDBE_MAGIC_HALT 0x519c2973 /* VDBE has completed execution */
#define VDBE_MAGIC_DEAD 0xb606c3c8 /* The VDBE has been deallocated */
/*
** Function prototypes
*/
void sqlite3VdbeFreeCursor(Vdbe *, Cursor*);
void sqliteVdbePopStack(Vdbe*,int);
int sqlite3VdbeCursorMoveto(Cursor*);
#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE)
void sqlite3VdbePrintOp(FILE*, int, Op*);
#endif
#ifdef SQLITE_DEBUG
void sqlite3VdbePrintSql(Vdbe*);
#endif
int sqlite3VdbeSerialTypeLen(u32);
u32 sqlite3VdbeSerialType(Mem*, int);
int sqlite3VdbeSerialPut(unsigned char*, Mem*, int);
int sqlite3VdbeSerialGet(const unsigned char*, u32, Mem*);
void sqlite3VdbeDeleteAuxData(VdbeFunc*, int);
int sqlite2BtreeKeyCompare(BtCursor *, const void *, int, int, int *);
int sqlite3VdbeIdxKeyCompare(Cursor*, int , const unsigned char*, int*);
int sqlite3VdbeIdxRowid(BtCursor *, i64 *);
int sqlite3MemCompare(const Mem*, const Mem*, const CollSeq*);
int sqlite3VdbeRecordCompare(void*,int,const void*,int, const void*);
int sqlite3VdbeIdxRowidLen(const u8*);
int sqlite3VdbeExec(Vdbe*);
int sqlite3VdbeList(Vdbe*);
int sqlite3VdbeHalt(Vdbe*);
int sqlite3VdbeChangeEncoding(Mem *, int);
int sqlite3VdbeMemCopy(Mem*, const Mem*);
void sqlite3VdbeMemShallowCopy(Mem*, const Mem*, int);
int sqlite3VdbeMemMove(Mem*, Mem*);
int sqlite3VdbeMemNulTerminate(Mem*);
int sqlite3VdbeMemSetStr(Mem*, const char*, int, u8, void(*)(void*));
void sqlite3VdbeMemSetInt64(Mem*, i64);
void sqlite3VdbeMemSetDouble(Mem*, double);
void sqlite3VdbeMemSetNull(Mem*);
int sqlite3VdbeMemMakeWriteable(Mem*);
int sqlite3VdbeMemDynamicify(Mem*);
int sqlite3VdbeMemStringify(Mem*, int);
i64 sqlite3VdbeIntValue(Mem*);
int sqlite3VdbeMemIntegerify(Mem*);
double sqlite3VdbeRealValue(Mem*);
void sqlite3VdbeIntegerAffinity(Mem*);
int sqlite3VdbeMemRealify(Mem*);
int sqlite3VdbeMemNumerify(Mem*);
int sqlite3VdbeMemFromBtree(BtCursor*,int,int,int,Mem*);
void sqlite3VdbeMemRelease(Mem *p);
int sqlite3VdbeMemFinalize(Mem*, FuncDef*);
#ifndef NDEBUG
void sqlite3VdbeMemSanity(Mem*);
int sqlite3VdbeOpcodeNoPush(u8);
#endif
int sqlite3VdbeMemTranslate(Mem*, u8);
void sqlite3VdbeMemPrettyPrint(Mem *pMem, char *zBuf);
int sqlite3VdbeMemHandleBom(Mem *pMem);
void sqlite3VdbeFifoInit(Fifo*);
int sqlite3VdbeFifoPush(Fifo*, i64);
int sqlite3VdbeFifoPop(Fifo*, i64*);
void sqlite3VdbeFifoClear(Fifo*);
#endif /* !defined(_VDBEINT_H_) */

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

@ -1,693 +0,0 @@
/*
** 2006 June 10
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains code used to help implement virtual tables.
**
** $Id: vtab.c 3426 2007-03-21 20:19:37Z damagedsoul $
*/
#ifndef SQLITE_OMIT_VIRTUALTABLE
#include "sqliteInt.h"
/*
** External API function used to create a new virtual-table module.
*/
int sqlite3_create_module(
sqlite3 *db, /* Database in which module is registered */
const char *zName, /* Name assigned to this module */
const sqlite3_module *pModule, /* The definition of the module */
void *pAux /* Context pointer for xCreate/xConnect */
){
int nName = strlen(zName);
Module *pMod = (Module *)sqliteMallocRaw(sizeof(Module) + nName + 1);
if( pMod ){
char *zCopy = (char *)(&pMod[1]);
strcpy(zCopy, zName);
pMod->zName = zCopy;
pMod->pModule = pModule;
pMod->pAux = pAux;
pMod = (Module *)sqlite3HashInsert(&db->aModule, zCopy, nName, (void*)pMod);
sqliteFree(pMod);
sqlite3ResetInternalSchema(db, 0);
}
return sqlite3ApiExit(db, SQLITE_OK);
}
/*
** Lock the virtual table so that it cannot be disconnected.
** Locks nest. Every lock should have a corresponding unlock.
** If an unlock is omitted, resources leaks will occur.
**
** If a disconnect is attempted while a virtual table is locked,
** the disconnect is deferred until all locks have been removed.
*/
void sqlite3VtabLock(sqlite3_vtab *pVtab){
pVtab->nRef++;
}
/*
** Unlock a virtual table. When the last lock is removed,
** disconnect the virtual table.
*/
void sqlite3VtabUnlock(sqlite3_vtab *pVtab){
pVtab->nRef--;
if( pVtab->nRef==0 ){
pVtab->pModule->xDisconnect(pVtab);
}
}
/*
** Clear any and all virtual-table information from the Table record.
** This routine is called, for example, just before deleting the Table
** record.
*/
void sqlite3VtabClear(Table *p){
sqlite3_vtab *pVtab = p->pVtab;
if( pVtab ){
assert( p->pMod && p->pMod->pModule );
sqlite3VtabUnlock(pVtab);
p->pVtab = 0;
}
if( p->azModuleArg ){
int i;
for(i=0; i<p->nModuleArg; i++){
sqliteFree(p->azModuleArg[i]);
}
sqliteFree(p->azModuleArg);
}
}
/*
** Add a new module argument to pTable->azModuleArg[].
** The string is not copied - the pointer is stored. The
** string will be freed automatically when the table is
** deleted.
*/
static void addModuleArgument(Table *pTable, char *zArg){
int i = pTable->nModuleArg++;
int nBytes = sizeof(char *)*(1+pTable->nModuleArg);
char **azModuleArg;
azModuleArg = sqliteRealloc(pTable->azModuleArg, nBytes);
if( azModuleArg==0 ){
int j;
for(j=0; j<i; j++){
sqliteFree(pTable->azModuleArg[j]);
}
sqliteFree(zArg);
sqliteFree(pTable->azModuleArg);
pTable->nModuleArg = 0;
}else{
azModuleArg[i] = zArg;
azModuleArg[i+1] = 0;
}
pTable->azModuleArg = azModuleArg;
}
/*
** The parser calls this routine when it first sees a CREATE VIRTUAL TABLE
** statement. The module name has been parsed, but the optional list
** of parameters that follow the module name are still pending.
*/
void sqlite3VtabBeginParse(
Parse *pParse, /* Parsing context */
Token *pName1, /* Name of new table, or database name */
Token *pName2, /* Name of new table or NULL */
Token *pModuleName /* Name of the module for the virtual table */
){
int iDb; /* The database the table is being created in */
Table *pTable; /* The new virtual table */
sqlite3StartTable(pParse, pName1, pName2, 0, 0, 1, 0);
pTable = pParse->pNewTable;
if( pTable==0 || pParse->nErr ) return;
assert( 0==pTable->pIndex );
iDb = sqlite3SchemaToIndex(pParse->db, pTable->pSchema);
assert( iDb>=0 );
pTable->isVirtual = 1;
pTable->nModuleArg = 0;
addModuleArgument(pTable, sqlite3NameFromToken(pModuleName));
addModuleArgument(pTable, sqlite3StrDup(pParse->db->aDb[iDb].zName));
addModuleArgument(pTable, sqlite3StrDup(pTable->zName));
pParse->sNameToken.n = pModuleName->z + pModuleName->n - pName1->z;
#ifndef SQLITE_OMIT_AUTHORIZATION
/* Creating a virtual table invokes the authorization callback twice.
** The first invocation, to obtain permission to INSERT a row into the
** sqlite_master table, has already been made by sqlite3StartTable().
** The second call, to obtain permission to create the table, is made now.
*/
if( pTable->azModuleArg ){
sqlite3AuthCheck(pParse, SQLITE_CREATE_VTABLE, pTable->zName,
pTable->azModuleArg[0], pParse->db->aDb[iDb].zName);
}
#endif
}
/*
** This routine takes the module argument that has been accumulating
** in pParse->zArg[] and appends it to the list of arguments on the
** virtual table currently under construction in pParse->pTable.
*/
static void addArgumentToVtab(Parse *pParse){
if( pParse->sArg.z && pParse->pNewTable ){
const char *z = (const char*)pParse->sArg.z;
int n = pParse->sArg.n;
addModuleArgument(pParse->pNewTable, sqliteStrNDup(z, n));
}
}
/*
** The parser calls this routine after the CREATE VIRTUAL TABLE statement
** has been completely parsed.
*/
void sqlite3VtabFinishParse(Parse *pParse, Token *pEnd){
Table *pTab; /* The table being constructed */
sqlite3 *db; /* The database connection */
char *zModule; /* The module name of the table: USING modulename */
Module *pMod = 0;
addArgumentToVtab(pParse);
pParse->sArg.z = 0;
/* Lookup the module name. */
pTab = pParse->pNewTable;
if( pTab==0 ) return;
db = pParse->db;
if( pTab->nModuleArg<1 ) return;
zModule = pTab->azModuleArg[0];
pMod = (Module *)sqlite3HashFind(&db->aModule, zModule, strlen(zModule));
pTab->pMod = pMod;
/* If the CREATE VIRTUAL TABLE statement is being entered for the
** first time (in other words if the virtual table is actually being
** created now instead of just being read out of sqlite_master) then
** do additional initialization work and store the statement text
** in the sqlite_master table.
*/
if( !db->init.busy ){
char *zStmt;
char *zWhere;
int iDb;
Vdbe *v;
/* Compute the complete text of the CREATE VIRTUAL TABLE statement */
if( pEnd ){
pParse->sNameToken.n = pEnd->z - pParse->sNameToken.z + pEnd->n;
}
zStmt = sqlite3MPrintf("CREATE VIRTUAL TABLE %T", &pParse->sNameToken);
/* A slot for the record has already been allocated in the
** SQLITE_MASTER table. We just need to update that slot with all
** the information we've collected.
**
** The top of the stack is the rootpage allocated by sqlite3StartTable().
** This value is always 0 and is ignored, a virtual table does not have a
** rootpage. The next entry on the stack is the rowid of the record
** in the sqlite_master table.
*/
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
sqlite3NestedParse(pParse,
"UPDATE %Q.%s "
"SET type='table', name=%Q, tbl_name=%Q, rootpage=0, sql=%Q "
"WHERE rowid=#1",
db->aDb[iDb].zName, SCHEMA_TABLE(iDb),
pTab->zName,
pTab->zName,
zStmt
);
sqliteFree(zStmt);
v = sqlite3GetVdbe(pParse);
sqlite3ChangeCookie(db, v, iDb);
sqlite3VdbeAddOp(v, OP_Expire, 0, 0);
zWhere = sqlite3MPrintf("name='%q'", pTab->zName);
sqlite3VdbeOp3(v, OP_ParseSchema, iDb, 1, zWhere, P3_DYNAMIC);
sqlite3VdbeOp3(v, OP_VCreate, iDb, 0, pTab->zName, strlen(pTab->zName) + 1);
}
/* If we are rereading the sqlite_master table create the in-memory
** record of the table. If the module has already been registered,
** also call the xConnect method here.
*/
else {
Table *pOld;
Schema *pSchema = pTab->pSchema;
const char *zName = pTab->zName;
int nName = strlen(zName) + 1;
pOld = sqlite3HashInsert(&pSchema->tblHash, zName, nName, pTab);
if( pOld ){
assert( pTab==pOld ); /* Malloc must have failed inside HashInsert() */
return;
}
pParse->pNewTable = 0;
}
}
/*
** The parser calls this routine when it sees the first token
** of an argument to the module name in a CREATE VIRTUAL TABLE statement.
*/
void sqlite3VtabArgInit(Parse *pParse){
addArgumentToVtab(pParse);
pParse->sArg.z = 0;
pParse->sArg.n = 0;
}
/*
** The parser calls this routine for each token after the first token
** in an argument to the module name in a CREATE VIRTUAL TABLE statement.
*/
void sqlite3VtabArgExtend(Parse *pParse, Token *p){
Token *pArg = &pParse->sArg;
if( pArg->z==0 ){
pArg->z = p->z;
pArg->n = p->n;
}else{
assert(pArg->z < p->z);
pArg->n = (p->z + p->n - pArg->z);
}
}
/*
** Invoke a virtual table constructor (either xCreate or xConnect). The
** pointer to the function to invoke is passed as the fourth parameter
** to this procedure.
*/
static int vtabCallConstructor(
sqlite3 *db,
Table *pTab,
Module *pMod,
int (*xConstruct)(sqlite3*,void*,int,const char*const*,sqlite3_vtab**,char**),
char **pzErr
){
int rc;
int rc2;
sqlite3_vtab *pVtab;
const char *const*azArg = (const char *const*)pTab->azModuleArg;
int nArg = pTab->nModuleArg;
char *zErr = 0;
char *zModuleName = sqlite3MPrintf("%s", pTab->zName);
assert( !db->pVTab );
assert( xConstruct );
db->pVTab = pTab;
rc = sqlite3SafetyOff(db);
assert( rc==SQLITE_OK );
rc = xConstruct(db, pMod->pAux, nArg, azArg, &pTab->pVtab, &zErr);
rc2 = sqlite3SafetyOn(db);
pVtab = pTab->pVtab;
if( rc==SQLITE_OK && pVtab ){
pVtab->pModule = pMod->pModule;
pVtab->nRef = 1;
}
if( SQLITE_OK!=rc ){
if( zErr==0 ){
*pzErr = sqlite3MPrintf("vtable constructor failed: %s", zModuleName);
}else {
*pzErr = sqlite3MPrintf("%s", zErr);
sqlite3_free(zErr);
}
}else if( db->pVTab ){
const char *zFormat = "vtable constructor did not declare schema: %s";
*pzErr = sqlite3MPrintf(zFormat, pTab->zName);
rc = SQLITE_ERROR;
}
if( rc==SQLITE_OK ){
rc = rc2;
}
db->pVTab = 0;
sqliteFree(zModuleName);
return rc;
}
/*
** This function is invoked by the parser to call the xConnect() method
** of the virtual table pTab. If an error occurs, an error code is returned
** and an error left in pParse.
**
** This call is a no-op if table pTab is not a virtual table.
*/
int sqlite3VtabCallConnect(Parse *pParse, Table *pTab){
Module *pMod;
int rc = SQLITE_OK;
if( !pTab || !pTab->isVirtual || pTab->pVtab ){
return SQLITE_OK;
}
pMod = pTab->pMod;
if( !pMod ){
const char *zModule = pTab->azModuleArg[0];
sqlite3ErrorMsg(pParse, "no such module: %s", zModule);
rc = SQLITE_ERROR;
} else {
char *zErr = 0;
sqlite3 *db = pParse->db;
rc = vtabCallConstructor(db, pTab, pMod, pMod->pModule->xConnect, &zErr);
if( rc!=SQLITE_OK ){
sqlite3ErrorMsg(pParse, "%s", zErr);
}
sqliteFree(zErr);
}
return rc;
}
/*
** Add the virtual table pVtab to the array sqlite3.aVTrans[].
*/
static int addToVTrans(sqlite3 *db, sqlite3_vtab *pVtab){
const int ARRAY_INCR = 5;
/* Grow the sqlite3.aVTrans array if required */
if( (db->nVTrans%ARRAY_INCR)==0 ){
sqlite3_vtab **aVTrans;
int nBytes = sizeof(sqlite3_vtab *) * (db->nVTrans + ARRAY_INCR);
aVTrans = sqliteRealloc((void *)db->aVTrans, nBytes);
if( !aVTrans ){
return SQLITE_NOMEM;
}
memset(&aVTrans[db->nVTrans], 0, sizeof(sqlite3_vtab *)*ARRAY_INCR);
db->aVTrans = aVTrans;
}
/* Add pVtab to the end of sqlite3.aVTrans */
db->aVTrans[db->nVTrans++] = pVtab;
sqlite3VtabLock(pVtab);
return SQLITE_OK;
}
/*
** This function is invoked by the vdbe to call the xCreate method
** of the virtual table named zTab in database iDb.
**
** If an error occurs, *pzErr is set to point an an English language
** description of the error and an SQLITE_XXX error code is returned.
** In this case the caller must call sqliteFree() on *pzErr.
*/
int sqlite3VtabCallCreate(sqlite3 *db, int iDb, const char *zTab, char **pzErr){
int rc = SQLITE_OK;
Table *pTab;
Module *pMod;
const char *zModule;
pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zName);
assert(pTab && pTab->isVirtual && !pTab->pVtab);
pMod = pTab->pMod;
zModule = pTab->azModuleArg[0];
/* If the module has been registered and includes a Create method,
** invoke it now. If the module has not been registered, return an
** error. Otherwise, do nothing.
*/
if( !pMod ){
*pzErr = sqlite3MPrintf("no such module: %s", zModule);
rc = SQLITE_ERROR;
}else{
rc = vtabCallConstructor(db, pTab, pMod, pMod->pModule->xCreate, pzErr);
}
if( rc==SQLITE_OK && pTab->pVtab ){
rc = addToVTrans(db, pTab->pVtab);
}
return rc;
}
/*
** This function is used to set the schema of a virtual table. It is only
** valid to call this function from within the xCreate() or xConnect() of a
** virtual table module.
*/
int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){
Parse sParse;
int rc = SQLITE_OK;
Table *pTab = db->pVTab;
char *zErr = 0;
if( !pTab ){
sqlite3Error(db, SQLITE_MISUSE, 0);
return SQLITE_MISUSE;
}
assert(pTab->isVirtual && pTab->nCol==0 && pTab->aCol==0);
memset(&sParse, 0, sizeof(Parse));
sParse.declareVtab = 1;
sParse.db = db;
if(
SQLITE_OK == sqlite3RunParser(&sParse, zCreateTable, &zErr) &&
sParse.pNewTable &&
!sParse.pNewTable->pSelect &&
!sParse.pNewTable->isVirtual
){
pTab->aCol = sParse.pNewTable->aCol;
pTab->nCol = sParse.pNewTable->nCol;
sParse.pNewTable->nCol = 0;
sParse.pNewTable->aCol = 0;
} else {
sqlite3Error(db, SQLITE_ERROR, zErr);
sqliteFree(zErr);
rc = SQLITE_ERROR;
}
sParse.declareVtab = 0;
sqlite3_finalize((sqlite3_stmt*)sParse.pVdbe);
sqlite3DeleteTable(0, sParse.pNewTable);
sParse.pNewTable = 0;
db->pVTab = 0;
assert( (rc&0xff)==rc );
return rc;
}
/*
** This function is invoked by the vdbe to call the xDestroy method
** of the virtual table named zTab in database iDb. This occurs
** when a DROP TABLE is mentioned.
**
** This call is a no-op if zTab is not a virtual table.
*/
int sqlite3VtabCallDestroy(sqlite3 *db, int iDb, const char *zTab)
{
int rc = SQLITE_OK;
Table *pTab;
pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zName);
assert(pTab);
if( pTab->pVtab ){
int (*xDestroy)(sqlite3_vtab *pVTab) = pTab->pMod->pModule->xDestroy;
rc = sqlite3SafetyOff(db);
assert( rc==SQLITE_OK );
if( xDestroy ){
rc = xDestroy(pTab->pVtab);
}
sqlite3SafetyOn(db);
if( rc==SQLITE_OK ){
pTab->pVtab = 0;
}
}
return rc;
}
/*
** This function invokes either the xRollback or xCommit method
** of each of the virtual tables in the sqlite3.aVTrans array. The method
** called is identified by the second argument, "offset", which is
** the offset of the method to call in the sqlite3_module structure.
**
** The array is cleared after invoking the callbacks.
*/
static void callFinaliser(sqlite3 *db, int offset){
int i;
for(i=0; i<db->nVTrans && db->aVTrans[i]; i++){
sqlite3_vtab *pVtab = db->aVTrans[i];
int (*x)(sqlite3_vtab *);
x = *(int (**)(sqlite3_vtab *))((char *)pVtab->pModule + offset);
if( x ) x(pVtab);
sqlite3VtabUnlock(pVtab);
}
sqliteFree(db->aVTrans);
db->nVTrans = 0;
db->aVTrans = 0;
}
/*
** If argument rc2 is not SQLITE_OK, then return it and do nothing.
** Otherwise, invoke the xSync method of all virtual tables in the
** sqlite3.aVTrans array. Return the error code for the first error
** that occurs, or SQLITE_OK if all xSync operations are successful.
*/
int sqlite3VtabSync(sqlite3 *db, int rc2){
int i;
int rc = SQLITE_OK;
int rcsafety;
sqlite3_vtab **aVTrans = db->aVTrans;
if( rc2!=SQLITE_OK ) return rc2;
rc = sqlite3SafetyOff(db);
db->aVTrans = 0;
for(i=0; rc==SQLITE_OK && i<db->nVTrans && aVTrans[i]; i++){
sqlite3_vtab *pVtab = aVTrans[i];
int (*x)(sqlite3_vtab *);
x = pVtab->pModule->xSync;
if( x ){
rc = x(pVtab);
}
}
db->aVTrans = aVTrans;
rcsafety = sqlite3SafetyOn(db);
if( rc==SQLITE_OK ){
rc = rcsafety;
}
return rc;
}
/*
** Invoke the xRollback method of all virtual tables in the
** sqlite3.aVTrans array. Then clear the array itself.
*/
int sqlite3VtabRollback(sqlite3 *db){
callFinaliser(db, (int)(&((sqlite3_module *)0)->xRollback));
return SQLITE_OK;
}
/*
** Invoke the xCommit method of all virtual tables in the
** sqlite3.aVTrans array. Then clear the array itself.
*/
int sqlite3VtabCommit(sqlite3 *db){
callFinaliser(db, (int)(&((sqlite3_module *)0)->xCommit));
return SQLITE_OK;
}
/*
** If the virtual table pVtab supports the transaction interface
** (xBegin/xRollback/xCommit and optionally xSync) and a transaction is
** not currently open, invoke the xBegin method now.
**
** If the xBegin call is successful, place the sqlite3_vtab pointer
** in the sqlite3.aVTrans array.
*/
int sqlite3VtabBegin(sqlite3 *db, sqlite3_vtab *pVtab){
int rc = SQLITE_OK;
const sqlite3_module *pModule;
/* Special case: If db->aVTrans is NULL and db->nVTrans is greater
** than zero, then this function is being called from within a
** virtual module xSync() callback. It is illegal to write to
** virtual module tables in this case, so return SQLITE_LOCKED.
*/
if( 0==db->aVTrans && db->nVTrans>0 ){
return SQLITE_LOCKED;
}
if( !pVtab ){
return SQLITE_OK;
}
pModule = pVtab->pModule;
if( pModule->xBegin ){
int i;
/* If pVtab is already in the aVTrans array, return early */
for(i=0; (i<db->nVTrans) && 0!=db->aVTrans[i]; i++){
if( db->aVTrans[i]==pVtab ){
return SQLITE_OK;
}
}
/* Invoke the xBegin method */
rc = pModule->xBegin(pVtab);
if( rc!=SQLITE_OK ){
return rc;
}
rc = addToVTrans(db, pVtab);
}
return rc;
}
/*
** The first parameter (pDef) is a function implementation. The
** second parameter (pExpr) is the first argument to this function.
** If pExpr is a column in a virtual table, then let the virtual
** table implementation have an opportunity to overload the function.
**
** This routine is used to allow virtual table implementations to
** overload MATCH, LIKE, GLOB, and REGEXP operators.
**
** Return either the pDef argument (indicating no change) or a
** new FuncDef structure that is marked as ephemeral using the
** SQLITE_FUNC_EPHEM flag.
*/
FuncDef *sqlite3VtabOverloadFunction(
FuncDef *pDef, /* Function to possibly overload */
int nArg, /* Number of arguments to the function */
Expr *pExpr /* First argument to the function */
){
Table *pTab;
sqlite3_vtab *pVtab;
sqlite3_module *pMod;
void (*xFunc)(sqlite3_context*,int,sqlite3_value**);
void *pArg;
FuncDef *pNew;
int rc;
char *zLowerName;
unsigned char *z;
/* Check to see the left operand is a column in a virtual table */
if( pExpr==0 ) return pDef;
if( pExpr->op!=TK_COLUMN ) return pDef;
pTab = pExpr->pTab;
if( pTab==0 ) return pDef;
if( !pTab->isVirtual ) return pDef;
pVtab = pTab->pVtab;
assert( pVtab!=0 );
assert( pVtab->pModule!=0 );
pMod = (sqlite3_module *)pVtab->pModule;
if( pMod->xFindFunction==0 ) return pDef;
/* Call the xFuncFunction method on the virtual table implementation
** to see if the implementation wants to overload this function
*/
zLowerName = sqlite3StrDup(pDef->zName);
for(z=(unsigned char*)zLowerName; *z; z++){
*z = sqlite3UpperToLower[*z];
}
rc = pMod->xFindFunction(pVtab, nArg, zLowerName, &xFunc, &pArg);
sqliteFree(zLowerName);
if( rc==0 ){
return pDef;
}
/* Create a new ephemeral function definition for the overloaded
** function */
pNew = sqliteMalloc( sizeof(*pNew) + strlen(pDef->zName) );
if( pNew==0 ){
return pDef;
}
*pNew = *pDef;
strcpy(pNew->zName, pDef->zName);
pNew->xFunc = xFunc;
pNew->pUserData = pArg;
pNew->flags |= SQLITE_FUNC_EPHEM;
return pNew;
}
#endif /* SQLITE_OMIT_VIRTUALTABLE */

File diff suppressed because it is too large Load Diff